1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 16:12:57 +08:00

Initial right click context menu implementation

This commit is contained in:
smoogipoo 2019-11-07 22:51:49 +09:00
parent 92d8526370
commit abb3a6ca5b
3 changed files with 162 additions and 70 deletions

View File

@ -17,6 +17,7 @@ using osu.Game.Rulesets.Edit.Tools;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osuTK;
using osuTK.Input;
namespace osu.Game.Screens.Edit.Compose.Components
{
@ -95,12 +96,18 @@ namespace osu.Game.Screens.Edit.Compose.Components
protected override bool OnMouseDown(MouseDownEvent e)
{
if (e.Button == MouseButton.Right)
return false;
beginClickSelection(e);
return true;
}
protected override bool OnClick(ClickEvent e)
{
if (e.Button == MouseButton.Right)
return false;
// Deselection should only occur if no selected blueprints are hovered
// A special case for when a blueprint was selected via this click is added since OnClick() may occur outside the hitobject and should not trigger deselection
if (endClickSelection() || selectionHandler.SelectedBlueprints.Any(b => b.IsHovered))
@ -112,6 +119,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
protected override bool OnDoubleClick(DoubleClickEvent e)
{
if (e.Button == MouseButton.Right)
return false;
SelectionBlueprint clickedBlueprint = selectionHandler.SelectedBlueprints.FirstOrDefault(b => b.IsHovered);
if (clickedBlueprint == null)
@ -123,6 +133,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
protected override bool OnMouseUp(MouseUpEvent e)
{
if (e.Button == MouseButton.Right)
return false;
// Special case for when a drag happened instead of a click
Schedule(() => endClickSelection());
return true;
@ -141,6 +154,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
protected override bool OnDragStart(DragStartEvent e)
{
if (e.Button == MouseButton.Right)
return false;
if (!beginSelectionMovement())
{
dragBox.UpdateDrag(e);
@ -152,6 +168,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
protected override bool OnDrag(DragEvent e)
{
if (e.Button == MouseButton.Right)
return false;
if (!moveCurrentSelection(e))
dragBox.UpdateDrag(e);
@ -160,6 +179,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
protected override bool OnDragEnd(DragEndEvent e)
{
if (e.Button == MouseButton.Right)
return false;
if (!finishSelectionMovement())
{
dragBox.FadeOut(250, Easing.OutQuint);

View File

@ -7,11 +7,16 @@ using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Framework.Input.States;
using osu.Game.Audio;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
@ -22,7 +27,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// <summary>
/// A component which outlines <see cref="DrawableHitObject"/>s and handles movement of selections.
/// </summary>
public class SelectionHandler : CompositeDrawable, IKeyBindingHandler<PlatformAction>
public class SelectionHandler : CompositeDrawable, IKeyBindingHandler<PlatformAction>, IHasContextMenu
{
public const float BORDER_RADIUS = 2;
@ -142,6 +147,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
#endregion
#region Outline Display
/// <summary>
/// Updates whether this <see cref="SelectionHandler"/> is visible.
/// </summary>
@ -176,5 +183,63 @@ namespace osu.Game.Screens.Edit.Compose.Components
outline.Size = bottomRight - topLeft;
outline.Position = topLeft;
}
#endregion
#region Context Menu
public virtual MenuItem[] ContextMenuItems
{
get
{
if (!SelectedBlueprints.Any())
return Array.Empty<MenuItem>();
return new MenuItem[]
{
new OsuMenuItem("hit sound")
{
Items = new[]
{
createHitSampleMenuItem(HitSampleInfo.HIT_WHISTLE),
createHitSampleMenuItem(HitSampleInfo.HIT_CLAP),
createHitSampleMenuItem(HitSampleInfo.HIT_FINISH)
}
}
};
}
}
private MenuItem createHitSampleMenuItem(string sampleName)
{
return new ToggleMenuItem(sampleName, MenuItemType.Standard, setHitSampleState)
{
State = { Value = getHitSampleState() }
};
void setHitSampleState(bool enabled)
{
if (enabled)
{
foreach (var h in SelectedHitObjects)
{
// Make sure there isn't already an existing sample
if (h.Samples.Any(s => s.Name == sampleName))
continue;
h.Samples.Add(new HitSampleInfo { Name = sampleName });
}
}
else
{
foreach (var h in SelectedHitObjects)
h.Samples.RemoveAll(s => s.Name == sampleName);
}
}
bool getHitSampleState() => SelectedHitObjects.All(h => h.Samples.Any(s => s.Name == sampleName));
}
#endregion
}
}

View File

@ -24,6 +24,7 @@ using osuTK.Input;
using System.Collections.Generic;
using osu.Framework;
using osu.Framework.Input.Bindings;
using osu.Game.Graphics.Cursor;
using osu.Game.Input.Bindings;
using osu.Game.Screens.Edit.Compose;
using osu.Game.Screens.Edit.Setup;
@ -85,87 +86,91 @@ namespace osu.Game.Screens.Edit
fileMenuItems.Add(new EditorMenuItem("Exit", MenuItemType.Standard, this.Exit));
InternalChildren = new[]
InternalChild = new OsuContextMenuContainer
{
new Container
RelativeSizeAxes = Axes.Both,
Children = new[]
{
Name = "Screen container",
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Top = 40, Bottom = 60 },
Child = screenContainer = new Container
new Container
{
Name = "Screen container",
RelativeSizeAxes = Axes.Both,
Masking = true
}
},
new Container
{
Name = "Top bar",
RelativeSizeAxes = Axes.X,
Height = 40,
Child = menuBar = new EditorMenuBar
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
RelativeSizeAxes = Axes.Both,
Items = new[]
{
new MenuItem("File")
{
Items = fileMenuItems
}
}
}
},
new Container
{
Name = "Bottom bar",
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.X,
Height = 60,
Children = new Drawable[]
{
bottomBackground = new Box { RelativeSizeAxes = Axes.Both },
new Container
Padding = new MarginPadding { Top = 40, Bottom = 60 },
Child = screenContainer = new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Vertical = 5, Horizontal = 10 },
Child = new GridContainer
Masking = true
}
},
new Container
{
Name = "Top bar",
RelativeSizeAxes = Axes.X,
Height = 40,
Child = menuBar = new EditorMenuBar
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
RelativeSizeAxes = Axes.Both,
Items = new[]
{
new MenuItem("File")
{
Items = fileMenuItems
}
}
}
},
new Container
{
Name = "Bottom bar",
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.X,
Height = 60,
Children = new Drawable[]
{
bottomBackground = new Box { RelativeSizeAxes = Axes.Both },
new Container
{
RelativeSizeAxes = Axes.Both,
ColumnDimensions = new[]
Padding = new MarginPadding { Vertical = 5, Horizontal = 10 },
Child = new GridContainer
{
new Dimension(GridSizeMode.Absolute, 220),
new Dimension(),
new Dimension(GridSizeMode.Absolute, 220)
},
Content = new[]
{
new Drawable[]
RelativeSizeAxes = Axes.Both,
ColumnDimensions = new[]
{
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Right = 10 },
Child = new TimeInfoContainer { RelativeSizeAxes = Axes.Both },
},
new SummaryTimeline
{
RelativeSizeAxes = Axes.Both,
},
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = 10 },
Child = new PlaybackControl { RelativeSizeAxes = Axes.Both },
}
new Dimension(GridSizeMode.Absolute, 220),
new Dimension(),
new Dimension(GridSizeMode.Absolute, 220)
},
}
},
Content = new[]
{
new Drawable[]
{
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Right = 10 },
Child = new TimeInfoContainer { RelativeSizeAxes = Axes.Both },
},
new SummaryTimeline
{
RelativeSizeAxes = Axes.Both,
},
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = 10 },
Child = new PlaybackControl { RelativeSizeAxes = Axes.Both },
}
},
}
},
}
}
}
},
},
}
};
menuBar.Mode.ValueChanged += onModeChanged;