mirror of
https://github.com/osukey/osukey.git
synced 2025-08-07 00:23:59 +09:00
Refactor into separate files + add xmldocs + rename some methods
This commit is contained in:
47
osu.Game/Rulesets/Edit/Layers/Selection/CentreMarker.cs
Normal file
47
osu.Game/Rulesets/Edit/Layers/Selection/CentreMarker.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the centre of a <see cref="MarkerContainer"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class CentreMarker : CompositeDrawable
|
||||||
|
{
|
||||||
|
private const float marker_size = 10;
|
||||||
|
private const float line_width = 2;
|
||||||
|
|
||||||
|
public CentreMarker()
|
||||||
|
{
|
||||||
|
Size = new Vector2(marker_size);
|
||||||
|
|
||||||
|
InternalChildren = new[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = line_width
|
||||||
|
},
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Width = line_width
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
Colour = colours.Yellow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
170
osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs
Normal file
170
osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Primitives;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A box that represents a drag selection.
|
||||||
|
/// </summary>
|
||||||
|
public class DragSelector : CompositeDrawable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="DrawableHitObject"/>s that can be selected through a drag-selection.
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerable<DrawableHitObject> CapturableObjects;
|
||||||
|
|
||||||
|
private readonly Container borderMask;
|
||||||
|
private readonly Drawable background;
|
||||||
|
private readonly MarkerContainer markers;
|
||||||
|
|
||||||
|
private Color4 captureFinishedColour;
|
||||||
|
|
||||||
|
private readonly Vector2 startPos;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="DragSelector"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="startPos">The point at which the drag was initiated, in the parent's coordinates.</param>
|
||||||
|
public DragSelector(Vector2 startPos)
|
||||||
|
{
|
||||||
|
this.startPos = startPos;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding(-1),
|
||||||
|
Child = borderMask = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
BorderColour = Color4.White,
|
||||||
|
BorderThickness = 2,
|
||||||
|
MaskingSmoothness = 1,
|
||||||
|
Child = background = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0.1f,
|
||||||
|
AlwaysPresent = true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
markers = new MarkerContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0,
|
||||||
|
GetDragRectangle = () => dragRectangle,
|
||||||
|
UpdateDragRectangle = r =>
|
||||||
|
{
|
||||||
|
updateDragRectangle(r);
|
||||||
|
BeginCapture();
|
||||||
|
},
|
||||||
|
FinishCapture = FinishCapture
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
captureFinishedColour = colours.Yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The secondary corner of the drag selection box. A rectangle will be fit between the starting position and this value.
|
||||||
|
/// </summary>
|
||||||
|
public Vector2 DragEndPosition { set => updateDragRectangle(RectangleF.FromLTRB(startPos.X, startPos.Y, value.X, value.Y)); }
|
||||||
|
|
||||||
|
private RectangleF dragRectangle;
|
||||||
|
private void updateDragRectangle(RectangleF rectangle)
|
||||||
|
{
|
||||||
|
dragRectangle = rectangle;
|
||||||
|
|
||||||
|
Position = new Vector2(
|
||||||
|
Math.Min(rectangle.Left, rectangle.Right),
|
||||||
|
Math.Min(rectangle.Top, rectangle.Bottom));
|
||||||
|
|
||||||
|
Size = new Vector2(
|
||||||
|
Math.Max(rectangle.Left, rectangle.Right) - Position.X,
|
||||||
|
Math.Max(rectangle.Top, rectangle.Bottom) - Position.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly List<DrawableHitObject> capturedHitObjects = new List<DrawableHitObject>();
|
||||||
|
public IReadOnlyList<DrawableHitObject> CapturedHitObjects => capturedHitObjects;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processes hitobjects to determine which ones are captured by the drag selection.
|
||||||
|
/// Captured hitobjects will be enclosed by the drag selection upon <see cref="FinishCapture"/>.
|
||||||
|
/// </summary>
|
||||||
|
public void BeginCapture()
|
||||||
|
{
|
||||||
|
capturedHitObjects.Clear();
|
||||||
|
|
||||||
|
foreach (var obj in CapturableObjects)
|
||||||
|
{
|
||||||
|
if (!obj.IsAlive || !obj.IsPresent)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var objectPosition = obj.ToScreenSpace(obj.SelectionPoint);
|
||||||
|
if (ScreenSpaceDrawQuad.Contains(objectPosition))
|
||||||
|
capturedHitObjects.Add(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Encloses hitobjects captured through <see cref="BeginCapture"/> in the drag selection box.
|
||||||
|
/// </summary>
|
||||||
|
public void FinishCapture()
|
||||||
|
{
|
||||||
|
if (CapturedHitObjects.Count == 0)
|
||||||
|
{
|
||||||
|
Hide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the rectangle to cover the hitobjects
|
||||||
|
var topLeft = new Vector2(float.MaxValue, float.MaxValue);
|
||||||
|
var bottomRight = new Vector2(float.MinValue, float.MinValue);
|
||||||
|
|
||||||
|
foreach (var obj in capturedHitObjects)
|
||||||
|
{
|
||||||
|
topLeft = Vector2.ComponentMin(topLeft, Parent.ToLocalSpace(obj.SelectionQuad.TopLeft));
|
||||||
|
bottomRight = Vector2.ComponentMax(bottomRight, Parent.ToLocalSpace(obj.SelectionQuad.BottomRight));
|
||||||
|
}
|
||||||
|
|
||||||
|
topLeft -= new Vector2(5);
|
||||||
|
bottomRight += new Vector2(5);
|
||||||
|
|
||||||
|
this.MoveTo(topLeft, 200, Easing.OutQuint)
|
||||||
|
.ResizeTo(bottomRight - topLeft, 200, Easing.OutQuint);
|
||||||
|
|
||||||
|
dragRectangle = RectangleF.FromLTRB(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y);
|
||||||
|
|
||||||
|
borderMask.BorderThickness = 3;
|
||||||
|
borderMask.FadeColour(captureFinishedColour, 200);
|
||||||
|
|
||||||
|
// Transform into markers to let the user modify the drag selection further.
|
||||||
|
background.Delay(50).FadeOut(200);
|
||||||
|
markers.FadeIn(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool isActive = true;
|
||||||
|
public override bool HandleInput => isActive;
|
||||||
|
|
||||||
|
public override void Hide()
|
||||||
|
{
|
||||||
|
isActive = false;
|
||||||
|
this.FadeOut(400, Easing.OutQuint).Expire();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
102
osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs
Normal file
102
osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
using System;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Primitives;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Input;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a marker visible on the border of a <see cref="MarkerContainer"/> which exposes
|
||||||
|
/// properties that are used to resize a <see cref="DragSelector"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class Marker : CompositeDrawable
|
||||||
|
{
|
||||||
|
private const float marker_size = 10;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when this <see cref="Marker"/> requires the current drag rectangle.
|
||||||
|
/// </summary>
|
||||||
|
public Func<RectangleF> GetDragRectangle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when this <see cref="Marker"/> wants to update the drag rectangle.
|
||||||
|
/// </summary>
|
||||||
|
public Action<RectangleF> UpdateDragRectangle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when this <see cref="Marker"/> has finished updates to the drag rectangle.
|
||||||
|
/// </summary>
|
||||||
|
public Action FinishCapture;
|
||||||
|
|
||||||
|
private Color4 normalColour;
|
||||||
|
private Color4 hoverColour;
|
||||||
|
|
||||||
|
public Marker()
|
||||||
|
{
|
||||||
|
Size = new Vector2(marker_size);
|
||||||
|
|
||||||
|
InternalChild = new CircularContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
Child = new Box { RelativeSizeAxes = Axes.Both }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
Colour = normalColour = colours.Yellow;
|
||||||
|
hoverColour = colours.YellowDarker;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnDragStart(InputState state) => true;
|
||||||
|
|
||||||
|
protected override bool OnDrag(InputState state)
|
||||||
|
{
|
||||||
|
var currentRectangle = GetDragRectangle();
|
||||||
|
|
||||||
|
float left = currentRectangle.Left;
|
||||||
|
float right = currentRectangle.Right;
|
||||||
|
float top = currentRectangle.Top;
|
||||||
|
float bottom = currentRectangle.Bottom;
|
||||||
|
|
||||||
|
// Apply modifications to the capture rectangle
|
||||||
|
if ((Anchor & Anchor.y0) > 0)
|
||||||
|
top += state.Mouse.Delta.Y;
|
||||||
|
else if ((Anchor & Anchor.y2) > 0)
|
||||||
|
bottom += state.Mouse.Delta.Y;
|
||||||
|
|
||||||
|
if ((Anchor & Anchor.x0) > 0)
|
||||||
|
left += state.Mouse.Delta.X;
|
||||||
|
else if ((Anchor & Anchor.x2) > 0)
|
||||||
|
right += state.Mouse.Delta.X;
|
||||||
|
|
||||||
|
UpdateDragRectangle(RectangleF.FromLTRB(left, top, right, bottom));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnDragEnd(InputState state)
|
||||||
|
{
|
||||||
|
FinishCapture();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnHover(InputState state)
|
||||||
|
{
|
||||||
|
this.FadeColour(hoverColour, 100);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHoverLost(InputState state)
|
||||||
|
{
|
||||||
|
this.FadeColour(normalColour, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
89
osu.Game/Rulesets/Edit/Layers/Selection/MarkerContainer.cs
Normal file
89
osu.Game/Rulesets/Edit/Layers/Selection/MarkerContainer.cs
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Primitives;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A <see cref="CompositeDrawable"/> that has <see cref="Marker"/>s around its border.
|
||||||
|
/// </summary>
|
||||||
|
public class MarkerContainer : CompositeDrawable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when a <see cref="Marker"/> requires the current drag rectangle.
|
||||||
|
/// </summary>
|
||||||
|
public Func<RectangleF> GetDragRectangle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when a <see cref="Marker"/> wants to update the drag rectangle.
|
||||||
|
/// </summary>
|
||||||
|
public Action<RectangleF> UpdateDragRectangle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when a <see cref="Marker"/> has finished updates to the drag rectangle.
|
||||||
|
/// </summary>
|
||||||
|
public Action FinishCapture;
|
||||||
|
|
||||||
|
public MarkerContainer()
|
||||||
|
{
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Marker
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopLeft,
|
||||||
|
Origin = Anchor.Centre
|
||||||
|
},
|
||||||
|
new Marker
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.Centre
|
||||||
|
},
|
||||||
|
new Marker
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Origin = Anchor.Centre
|
||||||
|
},
|
||||||
|
new Marker
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.Centre
|
||||||
|
},
|
||||||
|
new Marker
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.Centre
|
||||||
|
},
|
||||||
|
new Marker
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreRight,
|
||||||
|
Origin = Anchor.Centre
|
||||||
|
},
|
||||||
|
new Marker
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomRight,
|
||||||
|
Origin = Anchor.Centre
|
||||||
|
},
|
||||||
|
new Marker
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomCentre,
|
||||||
|
Origin = Anchor.Centre
|
||||||
|
},
|
||||||
|
new CentreMarker
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
InternalChildren.OfType<Marker>().ForEach(m =>
|
||||||
|
{
|
||||||
|
m.GetDragRectangle = () => GetDragRectangle();
|
||||||
|
m.UpdateDragRectangle = r => UpdateDragRectangle(r);
|
||||||
|
m.FinishCapture = () => FinishCapture();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
55
osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs
Normal file
55
osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Input;
|
||||||
|
using osu.Game.Rulesets.UI;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||||
|
{
|
||||||
|
public class SelectionLayer : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly Playfield playfield;
|
||||||
|
|
||||||
|
public SelectionLayer(Playfield playfield)
|
||||||
|
{
|
||||||
|
this.playfield = playfield;
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DragSelector selector;
|
||||||
|
|
||||||
|
protected override bool OnDragStart(InputState state)
|
||||||
|
{
|
||||||
|
// Hide the previous drag box - we won't be working with it any longer
|
||||||
|
selector?.Hide();
|
||||||
|
AddInternal(selector = new DragSelector(ToLocalSpace(state.Mouse.NativeState.Position))
|
||||||
|
{
|
||||||
|
CapturableObjects = playfield.HitObjects.Objects
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnDrag(InputState state)
|
||||||
|
{
|
||||||
|
selector.DragEndPosition = ToLocalSpace(state.Mouse.NativeState.Position);
|
||||||
|
selector.BeginCapture();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnDragEnd(InputState state)
|
||||||
|
{
|
||||||
|
selector.FinishCapture();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnClick(InputState state)
|
||||||
|
{
|
||||||
|
selector?.Hide();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,378 +0,0 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Primitives;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Framework.Input;
|
|
||||||
using OpenTK;
|
|
||||||
using OpenTK.Graphics;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
|
||||||
using osu.Game.Rulesets.UI;
|
|
||||||
using System.Linq;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Edit
|
|
||||||
{
|
|
||||||
public class SelectionLayer : CompositeDrawable
|
|
||||||
{
|
|
||||||
private readonly Playfield playfield;
|
|
||||||
|
|
||||||
public SelectionLayer(Playfield playfield)
|
|
||||||
{
|
|
||||||
this.playfield = playfield;
|
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
|
||||||
}
|
|
||||||
|
|
||||||
private DragContainer dragBox;
|
|
||||||
|
|
||||||
protected override bool OnDragStart(InputState state)
|
|
||||||
{
|
|
||||||
dragBox?.Hide();
|
|
||||||
AddInternal(dragBox = new DragContainer(ToLocalSpace(state.Mouse.NativeState.Position))
|
|
||||||
{
|
|
||||||
CapturableObjects = playfield.HitObjects.Objects
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnDrag(InputState state)
|
|
||||||
{
|
|
||||||
dragBox.Track(ToLocalSpace(state.Mouse.NativeState.Position));
|
|
||||||
dragBox.UpdateCapture();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnDragEnd(InputState state)
|
|
||||||
{
|
|
||||||
if (dragBox.CapturedHitObjects.Count == 0)
|
|
||||||
dragBox.Hide();
|
|
||||||
else
|
|
||||||
dragBox.FinishCapture();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnClick(InputState state)
|
|
||||||
{
|
|
||||||
dragBox?.Hide();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DragContainer : CompositeDrawable
|
|
||||||
{
|
|
||||||
public IEnumerable<DrawableHitObject> CapturableObjects;
|
|
||||||
|
|
||||||
private readonly Container borderMask;
|
|
||||||
private readonly Drawable background;
|
|
||||||
private readonly MarkerContainer markers;
|
|
||||||
|
|
||||||
private Color4 captureFinishedColour;
|
|
||||||
|
|
||||||
private readonly Vector2 startPos;
|
|
||||||
|
|
||||||
public DragContainer(Vector2 startPos)
|
|
||||||
{
|
|
||||||
this.startPos = startPos;
|
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
|
||||||
{
|
|
||||||
new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Padding = new MarginPadding(-1),
|
|
||||||
Child = borderMask = new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Masking = true,
|
|
||||||
BorderColour = Color4.White,
|
|
||||||
BorderThickness = 2,
|
|
||||||
MaskingSmoothness = 1,
|
|
||||||
Child = background = new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Alpha = 0.1f,
|
|
||||||
AlwaysPresent = true
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
markers = new MarkerContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Alpha = 0,
|
|
||||||
GetCaptureRectangle = () => trackingRectangle,
|
|
||||||
UpdateCapture = r =>
|
|
||||||
{
|
|
||||||
trackRectangle(r);
|
|
||||||
UpdateCapture();
|
|
||||||
},
|
|
||||||
FinishCapture = FinishCapture
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
captureFinishedColour = colours.Yellow;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Track(Vector2 position) => trackRectangle(RectangleF.FromLTRB(startPos.X, startPos.Y, position.X, position.Y));
|
|
||||||
|
|
||||||
private RectangleF trackingRectangle;
|
|
||||||
private void trackRectangle(RectangleF rectangle)
|
|
||||||
{
|
|
||||||
trackingRectangle = rectangle;
|
|
||||||
|
|
||||||
Position = new Vector2(
|
|
||||||
Math.Min(rectangle.Left, rectangle.Right),
|
|
||||||
Math.Min(rectangle.Top, rectangle.Bottom));
|
|
||||||
|
|
||||||
Size = new Vector2(
|
|
||||||
Math.Max(rectangle.Left, rectangle.Right) - Position.X,
|
|
||||||
Math.Max(rectangle.Top, rectangle.Bottom) - Position.Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<DrawableHitObject> capturedHitObjects = new List<DrawableHitObject>();
|
|
||||||
public IReadOnlyList<DrawableHitObject> CapturedHitObjects => capturedHitObjects;
|
|
||||||
|
|
||||||
public void UpdateCapture()
|
|
||||||
{
|
|
||||||
capturedHitObjects.Clear();
|
|
||||||
|
|
||||||
foreach (var obj in CapturableObjects)
|
|
||||||
{
|
|
||||||
if (!obj.IsAlive || !obj.IsPresent)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var objectPosition = obj.ToScreenSpace(obj.SelectionPoint);
|
|
||||||
if (ScreenSpaceDrawQuad.Contains(objectPosition))
|
|
||||||
capturedHitObjects.Add(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void FinishCapture()
|
|
||||||
{
|
|
||||||
if (CapturedHitObjects.Count == 0)
|
|
||||||
{
|
|
||||||
Hide();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move the rectangle to cover the hitobjects
|
|
||||||
var topLeft = new Vector2(float.MaxValue, float.MaxValue);
|
|
||||||
var bottomRight = new Vector2(float.MinValue, float.MinValue);
|
|
||||||
|
|
||||||
foreach (var obj in capturedHitObjects)
|
|
||||||
{
|
|
||||||
topLeft = Vector2.ComponentMin(topLeft, Parent.ToLocalSpace(obj.SelectionQuad.TopLeft));
|
|
||||||
bottomRight = Vector2.ComponentMax(bottomRight, Parent.ToLocalSpace(obj.SelectionQuad.BottomRight));
|
|
||||||
}
|
|
||||||
|
|
||||||
topLeft -= new Vector2(5);
|
|
||||||
bottomRight += new Vector2(5);
|
|
||||||
|
|
||||||
this.MoveTo(topLeft, 200, Easing.OutQuint)
|
|
||||||
.ResizeTo(bottomRight - topLeft, 200, Easing.OutQuint);
|
|
||||||
|
|
||||||
trackingRectangle = RectangleF.FromLTRB(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y);
|
|
||||||
|
|
||||||
borderMask.BorderThickness = 3;
|
|
||||||
borderMask.FadeColour(captureFinishedColour, 200);
|
|
||||||
|
|
||||||
background.Delay(50).FadeOut(200);
|
|
||||||
markers.FadeIn(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool isActive = true;
|
|
||||||
public override bool HandleInput => isActive;
|
|
||||||
|
|
||||||
public override void Hide()
|
|
||||||
{
|
|
||||||
isActive = false;
|
|
||||||
this.FadeOut(400, Easing.OutQuint).Expire();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MarkerContainer : CompositeDrawable
|
|
||||||
{
|
|
||||||
public Func<RectangleF> GetCaptureRectangle;
|
|
||||||
public Action<RectangleF> UpdateCapture;
|
|
||||||
public Action FinishCapture;
|
|
||||||
|
|
||||||
public MarkerContainer()
|
|
||||||
{
|
|
||||||
InternalChildren = new Drawable[]
|
|
||||||
{
|
|
||||||
new Marker
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopLeft,
|
|
||||||
Origin = Anchor.Centre
|
|
||||||
},
|
|
||||||
new Marker
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.Centre
|
|
||||||
},
|
|
||||||
new Marker
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopRight,
|
|
||||||
Origin = Anchor.Centre
|
|
||||||
},
|
|
||||||
new Marker
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
Origin = Anchor.Centre
|
|
||||||
},
|
|
||||||
new Marker
|
|
||||||
{
|
|
||||||
Anchor = Anchor.BottomLeft,
|
|
||||||
Origin = Anchor.Centre
|
|
||||||
},
|
|
||||||
new Marker
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreRight,
|
|
||||||
Origin = Anchor.Centre
|
|
||||||
},
|
|
||||||
new Marker
|
|
||||||
{
|
|
||||||
Anchor = Anchor.BottomRight,
|
|
||||||
Origin = Anchor.Centre
|
|
||||||
},
|
|
||||||
new Marker
|
|
||||||
{
|
|
||||||
Anchor = Anchor.BottomCentre,
|
|
||||||
Origin = Anchor.Centre
|
|
||||||
},
|
|
||||||
new CentreMarker
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
InternalChildren.OfType<Marker>().ForEach(m =>
|
|
||||||
{
|
|
||||||
m.GetCaptureRectangle = () => GetCaptureRectangle();
|
|
||||||
m.UpdateCapture = r => UpdateCapture(r);
|
|
||||||
m.FinishCapture = () => FinishCapture();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Marker : CompositeDrawable
|
|
||||||
{
|
|
||||||
private const float marker_size = 10;
|
|
||||||
|
|
||||||
public Func<RectangleF> GetCaptureRectangle;
|
|
||||||
public Action<RectangleF> UpdateCapture;
|
|
||||||
public Action FinishCapture;
|
|
||||||
|
|
||||||
private Color4 normalColour;
|
|
||||||
private Color4 hoverColour;
|
|
||||||
|
|
||||||
public Marker()
|
|
||||||
{
|
|
||||||
Size = new Vector2(marker_size);
|
|
||||||
|
|
||||||
InternalChild = new CircularContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Masking = true,
|
|
||||||
Child = new Box { RelativeSizeAxes = Axes.Both }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
Colour = normalColour = colours.Yellow;
|
|
||||||
hoverColour = colours.YellowDarker;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnDragStart(InputState state) => true;
|
|
||||||
|
|
||||||
protected override bool OnDrag(InputState state)
|
|
||||||
{
|
|
||||||
var currentRectangle = GetCaptureRectangle();
|
|
||||||
|
|
||||||
float left = currentRectangle.Left;
|
|
||||||
float right = currentRectangle.Right;
|
|
||||||
float top = currentRectangle.Top;
|
|
||||||
float bottom = currentRectangle.Bottom;
|
|
||||||
|
|
||||||
// Apply modifications to the capture rectangle
|
|
||||||
if ((Anchor & Anchor.y0) > 0)
|
|
||||||
top += state.Mouse.Delta.Y;
|
|
||||||
else if ((Anchor & Anchor.y2) > 0)
|
|
||||||
bottom += state.Mouse.Delta.Y;
|
|
||||||
|
|
||||||
if ((Anchor & Anchor.x0) > 0)
|
|
||||||
left += state.Mouse.Delta.X;
|
|
||||||
else if ((Anchor & Anchor.x2) > 0)
|
|
||||||
right += state.Mouse.Delta.X;
|
|
||||||
|
|
||||||
UpdateCapture(RectangleF.FromLTRB(left, top, right, bottom));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnDragEnd(InputState state)
|
|
||||||
{
|
|
||||||
FinishCapture();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnHover(InputState state)
|
|
||||||
{
|
|
||||||
this.FadeColour(hoverColour, 100);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnHoverLost(InputState state)
|
|
||||||
{
|
|
||||||
this.FadeColour(normalColour, 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CentreMarker : CompositeDrawable
|
|
||||||
{
|
|
||||||
private const float marker_size = 10;
|
|
||||||
private const float line_width = 2;
|
|
||||||
|
|
||||||
public CentreMarker()
|
|
||||||
{
|
|
||||||
Size = new Vector2(marker_size);
|
|
||||||
|
|
||||||
InternalChildren = new[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Height = line_width
|
|
||||||
},
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
RelativeSizeAxes = Axes.Y,
|
|
||||||
Width = line_width
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
Colour = colours.Yellow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -310,6 +310,11 @@
|
|||||||
<Compile Include="Overlays\Profile\Sections\Ranks\DrawableTotalScore.cs" />
|
<Compile Include="Overlays\Profile\Sections\Ranks\DrawableTotalScore.cs" />
|
||||||
<Compile Include="Overlays\Profile\Sections\Ranks\ScoreModsContainer.cs" />
|
<Compile Include="Overlays\Profile\Sections\Ranks\ScoreModsContainer.cs" />
|
||||||
<Compile Include="Overlays\Settings\SettingsButton.cs" />
|
<Compile Include="Overlays\Settings\SettingsButton.cs" />
|
||||||
|
<Compile Include="Rulesets\Edit\Layers\Selection\CentreMarker.cs" />
|
||||||
|
<Compile Include="Rulesets\Edit\Layers\Selection\DragSelector.cs" />
|
||||||
|
<Compile Include="Rulesets\Edit\Layers\Selection\Marker.cs" />
|
||||||
|
<Compile Include="Rulesets\Edit\Layers\Selection\MarkerContainer.cs" />
|
||||||
|
<Compile Include="Rulesets\Edit\Layers\Selection\SelectionLayer.cs" />
|
||||||
<Compile Include="Screens\Edit\Components\BottomBarContainer.cs" />
|
<Compile Include="Screens\Edit\Components\BottomBarContainer.cs" />
|
||||||
<Compile Include="Screens\Edit\Components\PlaybackControl.cs" />
|
<Compile Include="Screens\Edit\Components\PlaybackControl.cs" />
|
||||||
<Compile Include="Screens\Edit\Components\TimeInfoContainer.cs" />
|
<Compile Include="Screens\Edit\Components\TimeInfoContainer.cs" />
|
||||||
@ -573,7 +578,6 @@
|
|||||||
<Compile Include="Rulesets\Edit\Tools\HitObjectCompositionTool.cs" />
|
<Compile Include="Rulesets\Edit\Tools\HitObjectCompositionTool.cs" />
|
||||||
<Compile Include="Rulesets\Edit\Tools\ICompositionTool.cs" />
|
<Compile Include="Rulesets\Edit\Tools\ICompositionTool.cs" />
|
||||||
<Compile Include="Rulesets\Edit\HitObjectComposer.cs" />
|
<Compile Include="Rulesets\Edit\HitObjectComposer.cs" />
|
||||||
<Compile Include="Rulesets\Edit\SelectionLayer.cs" />
|
|
||||||
<Compile Include="Rulesets\Edit\ToolboxGroup.cs" />
|
<Compile Include="Rulesets\Edit\ToolboxGroup.cs" />
|
||||||
<Compile Include="Rulesets\Judgements\DrawableJudgement.cs" />
|
<Compile Include="Rulesets\Judgements\DrawableJudgement.cs" />
|
||||||
<Compile Include="Rulesets\Judgements\Judgement.cs" />
|
<Compile Include="Rulesets\Judgements\Judgement.cs" />
|
||||||
|
Reference in New Issue
Block a user