1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-24 12:07:27 +08:00
osu-lazer/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs

179 lines
5.2 KiB
C#
Raw Normal View History

2018-04-13 17:19:50 +08:00
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
2018-10-18 15:36:06 +08:00
using System.Linq;
2018-04-13 17:19:50 +08:00
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
2018-10-18 15:36:06 +08:00
using osu.Framework.Input.Events;
2018-07-21 10:38:28 +08:00
using osu.Framework.Input.States;
2018-04-13 17:19:50 +08:00
using osu.Game.Graphics;
using osu.Game.Rulesets.Edit;
using OpenTK;
2018-10-18 15:36:06 +08:00
using OpenTK.Input;
2018-04-13 17:19:50 +08:00
2018-11-06 17:28:22 +08:00
namespace osu.Game.Screens.Edit.Compose.Components
2018-04-13 17:19:50 +08:00
{
/// <summary>
2018-11-06 16:56:04 +08:00
/// A box which surrounds <see cref="SelectionBlueprint"/>s and provides interactive handles, context menus etc.
2018-04-13 17:19:50 +08:00
/// </summary>
2018-11-06 16:52:47 +08:00
public class SelectionBox : CompositeDrawable
2018-04-13 17:19:50 +08:00
{
public const float BORDER_RADIUS = 2;
2018-11-06 17:06:34 +08:00
private readonly List<SelectionBlueprint> selectedBlueprints;
2018-04-13 17:19:50 +08:00
private Drawable outline;
2018-10-18 15:36:06 +08:00
[Resolved]
private IPlacementHandler placementHandler { get; set; }
2018-11-06 16:52:47 +08:00
public SelectionBox()
2018-04-13 17:19:50 +08:00
{
2018-11-06 17:06:34 +08:00
selectedBlueprints = new List<SelectionBlueprint>();
2018-04-13 17:19:50 +08:00
RelativeSizeAxes = Axes.Both;
AlwaysPresent = true;
Alpha = 0;
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
InternalChild = outline = new Container
{
Masking = true,
BorderThickness = BORDER_RADIUS,
BorderColour = colours.Yellow,
Child = new Box
{
RelativeSizeAxes = Axes.Both,
AlwaysPresent = true,
Alpha = 0
}
};
}
#region User Input Handling
public void HandleDrag(DragEvent dragEvent)
2018-04-13 17:19:50 +08:00
{
// Todo: Various forms of snapping
2018-11-06 17:06:34 +08:00
foreach (var blueprint in selectedBlueprints)
blueprint.AdjustPosition(dragEvent);
2018-04-13 17:19:50 +08:00
}
2018-10-18 15:36:06 +08:00
protected override bool OnKeyDown(KeyDownEvent e)
{
if (e.Repeat)
return base.OnKeyDown(e);
switch (e.Key)
{
case Key.Delete:
2018-11-06 17:06:34 +08:00
foreach (var h in selectedBlueprints.ToList())
2018-10-18 15:36:06 +08:00
placementHandler.Delete(h.HitObject.HitObject);
return true;
}
2018-10-31 11:07:06 +08:00
2018-10-18 15:36:06 +08:00
return base.OnKeyDown(e);
}
2018-04-13 17:19:50 +08:00
#endregion
#region Selection Handling
/// <summary>
2018-11-06 17:06:34 +08:00
/// Bind an action to deselect all selected blueprints.
2018-04-13 17:19:50 +08:00
/// </summary>
public Action DeselectAll { private get; set; }
/// <summary>
2018-11-06 17:06:34 +08:00
/// Handle a blueprint becoming selected.
2018-04-13 17:19:50 +08:00
/// </summary>
2018-11-06 17:06:34 +08:00
/// <param name="blueprint">The blueprint.</param>
public void HandleSelected(SelectionBlueprint blueprint) => selectedBlueprints.Add(blueprint);
2018-04-13 17:19:50 +08:00
/// <summary>
2018-11-06 17:06:34 +08:00
/// Handle a blueprint becoming deselected.
2018-04-13 17:19:50 +08:00
/// </summary>
2018-11-06 17:06:34 +08:00
/// <param name="blueprint">The blueprint.</param>
2018-11-06 16:56:04 +08:00
public void HandleDeselected(SelectionBlueprint blueprint)
2018-04-13 17:19:50 +08:00
{
2018-11-06 17:06:34 +08:00
selectedBlueprints.Remove(blueprint);
2018-04-13 17:19:50 +08:00
2018-11-06 17:06:34 +08:00
// We don't want to update visibility if > 0, since we may be deselecting blueprints during drag-selection
if (selectedBlueprints.Count == 0)
2018-04-13 17:19:50 +08:00
UpdateVisibility();
}
/// <summary>
2018-11-06 17:06:34 +08:00
/// Handle a blueprint requesting selection.
2018-04-13 17:19:50 +08:00
/// </summary>
2018-11-06 17:06:34 +08:00
/// <param name="blueprint">The blueprint.</param>
2018-11-06 16:56:04 +08:00
public void HandleSelectionRequested(SelectionBlueprint blueprint, InputState state)
2018-04-13 17:19:50 +08:00
{
if (state.Keyboard.ControlPressed)
{
2018-11-06 16:56:04 +08:00
if (blueprint.IsSelected)
blueprint.Deselect();
2018-04-13 17:19:50 +08:00
else
2018-11-06 16:56:04 +08:00
blueprint.Select();
2018-04-13 17:19:50 +08:00
}
else
{
2018-11-06 16:56:04 +08:00
if (blueprint.IsSelected)
2018-04-13 17:19:50 +08:00
return;
DeselectAll?.Invoke();
2018-11-06 16:56:04 +08:00
blueprint.Select();
2018-04-13 17:19:50 +08:00
}
UpdateVisibility();
}
#endregion
/// <summary>
2018-11-06 16:52:47 +08:00
/// Updates whether this <see cref="SelectionBox"/> is visible.
2018-04-13 17:19:50 +08:00
/// </summary>
internal void UpdateVisibility()
{
2018-11-06 17:06:34 +08:00
if (selectedBlueprints.Count > 0)
2018-04-13 17:19:50 +08:00
Show();
else
Hide();
}
protected override void Update()
{
base.Update();
2018-11-06 17:06:34 +08:00
if (selectedBlueprints.Count == 0)
2018-04-13 17:19:50 +08:00
return;
// Move the rectangle to cover the hitobjects
var topLeft = new Vector2(float.MaxValue, float.MaxValue);
var bottomRight = new Vector2(float.MinValue, float.MinValue);
bool hasSelection = false;
2018-11-06 17:06:34 +08:00
foreach (var blueprint in selectedBlueprints)
2018-04-13 17:19:50 +08:00
{
2018-11-06 17:06:34 +08:00
topLeft = Vector2.ComponentMin(topLeft, ToLocalSpace(blueprint.SelectionQuad.TopLeft));
bottomRight = Vector2.ComponentMax(bottomRight, ToLocalSpace(blueprint.SelectionQuad.BottomRight));
2018-04-13 17:19:50 +08:00
}
topLeft -= new Vector2(5);
bottomRight += new Vector2(5);
outline.Size = bottomRight - topLeft;
outline.Position = topLeft;
}
}
}