From 171125803812bc31af05b8e6bb4a9eb162a1c619 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Mon, 12 Jun 2017 12:56:07 +0300 Subject: [PATCH] Context Menu --- .../Tests/TestCaseContextMenu.cs | 126 ++++++++++++++++++ .../osu.Desktop.VisualTests.csproj | 1 + .../Cursor/OsuContextMenuContainer.cs | 18 +++ osu.Game/Graphics/OsuColour.cs | 2 + .../Graphics/UserInterface/ContextMenuType.cs | 12 ++ .../Graphics/UserInterface/OsuContextMenu.cs | 45 +++++++ .../UserInterface/OsuContextMenuItem.cs | 114 ++++++++++++++++ osu.Game/OsuGameBase.cs | 1 + osu.Game/osu.Game.csproj | 10 +- 9 files changed, 326 insertions(+), 3 deletions(-) create mode 100644 osu.Desktop.VisualTests/Tests/TestCaseContextMenu.cs create mode 100644 osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs create mode 100644 osu.Game/Graphics/UserInterface/ContextMenuType.cs create mode 100644 osu.Game/Graphics/UserInterface/OsuContextMenu.cs create mode 100644 osu.Game/Graphics/UserInterface/OsuContextMenuItem.cs diff --git a/osu.Desktop.VisualTests/Tests/TestCaseContextMenu.cs b/osu.Desktop.VisualTests/Tests/TestCaseContextMenu.cs new file mode 100644 index 0000000000..ac7fe4b403 --- /dev/null +++ b/osu.Desktop.VisualTests/Tests/TestCaseContextMenu.cs @@ -0,0 +1,126 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Transforms; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Testing; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Desktop.VisualTests.Tests +{ + internal class TestCaseContextMenu : TestCase + { + public override string Description => @"Menu visible on right click"; + + private const int start_time = 0; + private const int duration = 1000; + + private MyContextMenuContainer container; + + public override void Reset() + { + base.Reset(); + + Add(container = new MyContextMenuContainer + { + Size = new Vector2(200), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + new Framework.Graphics.Sprites.Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Green, + } + } + }); + + Add(new AnotherContextMenuContainer + { + Size = new Vector2(200), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Red, + } + } + }); + + container.Transforms.Add(new TransformPosition + { + StartValue = Vector2.Zero, + EndValue = new Vector2(0, 100), + StartTime = start_time, + EndTime = start_time + duration, + LoopCount = -1, + LoopDelay = duration * 3 + }); + container.Transforms.Add(new TransformPosition + { + StartValue = new Vector2(0, 100), + EndValue = new Vector2(100, 100), + StartTime = start_time + duration, + EndTime = start_time + duration * 2, + LoopCount = -1, + LoopDelay = duration * 3 + }); + container.Transforms.Add(new TransformPosition + { + StartValue = new Vector2(100, 100), + EndValue = new Vector2(100, 0), + StartTime = start_time + duration * 2, + EndTime = start_time + duration * 3, + LoopCount = -1, + LoopDelay = duration * 3 + }); + container.Transforms.Add(new TransformPosition + { + StartValue = new Vector2(100, 0), + EndValue = Vector2.Zero, + StartTime = start_time + duration * 3, + EndTime = start_time + duration * 4, + LoopCount = -1, + LoopDelay = duration * 3 + }); + } + + private class MyContextMenuContainer : Container, IHasContextMenu + { + public ContextMenuItem[] ContextMenuItems => new[] + { + new OsuContextMenuItem(@"Some option"), + new OsuContextMenuItem(@"Highlighted option", ContextMenuType.Highlighted), + new OsuContextMenuItem(@"Another option"), + new OsuContextMenuItem(@"Choose me please"), + new OsuContextMenuItem(@"And me too"), + new OsuContextMenuItem(@"Trying to fill"), + new OsuContextMenuItem(@"Destructive option", ContextMenuType.Destructive), + }; + } + + private class AnotherContextMenuContainer : Container, IHasContextMenu + { + public ContextMenuItem[] ContextMenuItems => new[] + { + new OsuContextMenuItem(@"Simple option"), + new OsuContextMenuItem(@"Simple very very long option"), + new OsuContextMenuItem(@"Change width", ContextMenuType.Highlighted) { Action = () => ResizeWidthTo(Width * 2, 100, EasingTypes.OutQuint) }, + new OsuContextMenuItem(@"Change height", ContextMenuType.Highlighted) { Action = () => ResizeHeightTo(Height * 2, 100, EasingTypes.OutQuint) }, + new OsuContextMenuItem(@"Change width back", ContextMenuType.Destructive) { Action = () => ResizeWidthTo(Width / 2, 100, EasingTypes.OutQuint) }, + new OsuContextMenuItem(@"Change height back", ContextMenuType.Destructive) { Action = () => ResizeHeightTo(Height / 2, 100, EasingTypes.OutQuint) }, + }; + } + } +} diff --git a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj index d1d0cc1c1a..c32d38482a 100644 --- a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj +++ b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj @@ -187,6 +187,7 @@ + diff --git a/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs b/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs new file mode 100644 index 0000000000..2cc6c3a46a --- /dev/null +++ b/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Graphics.Cursor +{ + public class OsuContextMenuContainer : ContextMenuContainer + { + protected override ContextMenu CreateContextMenu() => new OsuContextMenu(); + + public OsuContextMenuContainer(CursorContainer cursor) : base(cursor) + { + } + } +} \ No newline at end of file diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 3d83668d07..d2f4d4768c 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -87,5 +87,7 @@ namespace osu.Game.Graphics public readonly Color4 RedDarker = FromHex(@"870000"); public readonly Color4 ChatBlue = FromHex(@"17292e"); + + public readonly Color4 ContextMenuGray = FromHex(@"223034"); } } diff --git a/osu.Game/Graphics/UserInterface/ContextMenuType.cs b/osu.Game/Graphics/UserInterface/ContextMenuType.cs new file mode 100644 index 0000000000..11086f13b8 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ContextMenuType.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Graphics +{ + public enum ContextMenuType + { + Standard, + Highlighted, + Destructive, + } +} \ No newline at end of file diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs new file mode 100644 index 0000000000..684bc840ec --- /dev/null +++ b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs @@ -0,0 +1,45 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; + +namespace osu.Game.Graphics.UserInterface +{ + public class OsuContextMenu : ContextMenu + where TItem : ContextMenuItem + { + protected override Menu CreateMenu() => new CustomMenu(); + + public class CustomMenu : Menu + { + private const int fade_duration = 250; + + public CustomMenu() + { + CornerRadius = 5; + ItemsContainer.Padding = new MarginPadding { Vertical = OsuContextMenuItem.MARGIN_VERTICAL }; + Masking = true; + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(0.25f), + Radius = 4, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Background.Colour = colours.ContextMenuGray; + } + + protected override void AnimateOpen() => FadeIn(fade_duration, EasingTypes.OutQuint); + protected override void AnimateClose() => FadeOut(fade_duration, EasingTypes.OutQuint); + } + } +} \ No newline at end of file diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenuItem.cs b/osu.Game/Graphics/UserInterface/OsuContextMenuItem.cs new file mode 100644 index 0000000000..a9b4975552 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/OsuContextMenuItem.cs @@ -0,0 +1,114 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Graphics.UserInterface +{ + public class OsuContextMenuItem : ContextMenuItem + { + private const int transition_length = 200; + private const int margin_horizontal = 17; + public const int MARGIN_VERTICAL = 4; + private const int text_size = 17; + + private OsuSpriteText text; + private OsuSpriteText textBold; + + private SampleChannel sampleClick; + private SampleChannel sampleHover; + + private ContextMenuType type; + + protected override Container CreateTextContainer(string title) => new Container + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Children = new Drawable[] + { + text = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + TextSize = text_size, + Text = title, + Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, + }, + textBold = new OsuSpriteText + { + AlwaysPresent = true, + Alpha = 0, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + TextSize = text_size, + Text = title, + Font = @"Exo2.0-Bold", + Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, + } + } + }; + + public OsuContextMenuItem(string title, ContextMenuType type = ContextMenuType.Standard) : base(title) + { + this.type = type; + } + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sampleHover = audio.Sample.Get(@"Menu/menuclick"); + sampleClick = audio.Sample.Get(@"Menu/menuback"); + + BackgroundColour = Color4.Transparent; + BackgroundColourHover = OsuColour.FromHex(@"172023"); + + updateTextColour(); + } + + private void updateTextColour() + { + switch (type) + { + case ContextMenuType.Standard: + textBold.Colour = text.Colour = Color4.White; + break; + case ContextMenuType.Destructive: + textBold.Colour = text.Colour = Color4.Red; + break; + case ContextMenuType.Highlighted: + textBold.Colour = text.Colour = OsuColour.FromHex(@"ffcc22"); + break; + } + } + + protected override bool OnHover(InputState state) + { + sampleHover.Play(); + textBold.FadeIn(transition_length, EasingTypes.OutQuint); + text.FadeOut(transition_length, EasingTypes.OutQuint); + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + textBold.FadeOut(transition_length, EasingTypes.OutQuint); + text.FadeIn(transition_length, EasingTypes.OutQuint); + base.OnHoverLost(state); + } + + protected override bool OnClick(InputState state) + { + sampleClick.Play(); + return base.OnClick(state); + } + } +} \ No newline at end of file diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index b228b6485a..306cdaddf0 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -158,6 +158,7 @@ namespace osu.Game Children = new Drawable[] { Cursor = new MenuCursor(), + new OsuContextMenuContainer(Cursor) { Depth = -2 }, new OsuTooltipContainer(Cursor) { Depth = -1 }, } }, diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a299ea3cb2..fd7bbe058f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -43,8 +43,8 @@ $(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1341\lib\net45\OpenTK.dll - $(SolutionDir)\packages\sharpcompress.0.15.2\lib\net45\SharpCompress.dll - $(SolutionDir)\packages\SharpCompress.0.15.2\lib\net45\SharpCompress.dll + $(SolutionDir)\packages\sharpcompress.0.15.2\lib\net45\SharpCompress.dll + $(SolutionDir)\packages\SharpCompress.0.15.2\lib\net45\SharpCompress.dll $(SolutionDir)\packages\SQLite.Net.Core-PCL.3.1.1\lib\portable-win8+net45+wp8+wpa81+MonoAndroid1+MonoTouch1\SQLite.Net.dll @@ -75,8 +75,12 @@ + + + + @@ -505,4 +509,4 @@ --> - + \ No newline at end of file