Added osu!direct header and filter control

This commit is contained in:
DrabWeb 2017-05-17 05:58:34 -03:00
parent c78f4cc7ab
commit 9ba356f2c6
12 changed files with 601 additions and 7 deletions

View File

@ -0,0 +1,27 @@
// 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.Testing;
using osu.Game.Graphics;
using osu.Game.Overlays;
using osu.Game.Overlays.Dialog;
namespace osu.Desktop.VisualTests.Tests
{
public class TestCaseDirect : TestCase
{
public override string Description => @"osu!direct overlay";
private DirectOverlay direct;
public override void Reset()
{
base.Reset();
Add(direct = new DirectOverlay());
AddStep(@"Toggle", direct.ToggleVisibility);
}
}
}

View File

@ -220,6 +220,7 @@
<Compile Include="Tests\TestCaseLeaderboard.cs" />
<Compile Include="Beatmaps\TestWorkingBeatmap.cs" />
<Compile Include="Tests\TestCaseBeatmapDetailArea.cs" />
<Compile Include="Tests\TestCaseDirect.cs" />
</ItemGroup>
<ItemGroup />
<ItemGroup />

View File

@ -113,7 +113,7 @@ private void load(OsuColour colours)
}
}
protected class OsuDropdownHeader : DropdownHeader
public class OsuDropdownHeader : DropdownHeader
{
private readonly SpriteText label;
protected override string Label

View File

@ -0,0 +1,32 @@
// 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 System.ComponentModel;
using System.Reflection;
using System.Collections.Generic;
namespace osu.Game.Graphics.UserInterface
{
public class OsuEnumDropdown<T> : OsuDropdown<T>
{
public OsuEnumDropdown()
{
if (!typeof(T).IsEnum)
throw new InvalidOperationException("SettingsDropdown only supports enums as the generic type argument");
List<KeyValuePair<string, T>> items = new List<KeyValuePair<string, T>>();
foreach(var val in (T[])Enum.GetValues(typeof(T)))
{
var field = typeof(T).GetField(Enum.GetName(typeof(T), val));
items.Add(
new KeyValuePair<string, T>(
field.GetCustomAttribute<DescriptionAttribute>()?.Description ?? Enum.GetName(typeof(T), val),
val
)
);
}
Items = items;
}
}
}

View File

@ -57,9 +57,9 @@ public Color4 AccentColour
}
}
private class OsuTabItem : TabItem<T>
public class OsuTabItem : TabItem<T>
{
private readonly SpriteText text;
protected readonly SpriteText Text;
private readonly Box box;
private Color4? accentColour;
@ -70,7 +70,7 @@ public Color4 AccentColour
{
accentColour = value;
if (!Active)
text.Colour = value;
Text.Colour = value;
}
}
@ -94,13 +94,13 @@ public override bool Active
private void fadeActive()
{
box.FadeIn(transition_length, EasingTypes.OutQuint);
text.FadeColour(Color4.White, transition_length, EasingTypes.OutQuint);
Text.FadeColour(Color4.White, transition_length, EasingTypes.OutQuint);
}
private void fadeInactive()
{
box.FadeOut(transition_length, EasingTypes.OutQuint);
text.FadeColour(AccentColour, transition_length, EasingTypes.OutQuint);
Text.FadeColour(AccentColour, transition_length, EasingTypes.OutQuint);
}
protected override bool OnHover(InputState state)
@ -130,7 +130,7 @@ public OsuTabItem(T value) : base(value)
Children = new Drawable[]
{
text = new OsuSpriteText
Text = new OsuSpriteText
{
Margin = new MarginPadding { Top = 5, Bottom = 5 },
Origin = Anchor.BottomLeft,

View File

@ -41,6 +41,8 @@ public class OsuGame : OsuGameBase
private DialogOverlay dialogOverlay;
private DirectOverlay direct;
private Intro intro
{
get
@ -70,6 +72,8 @@ public OsuGame(string[] args = null)
public void ToggleSettings() => settings.ToggleVisibility();
public void ToggleDirect() => direct.ToggleVisibility();
[BackgroundDependencyLoader]
private void load()
{
@ -160,6 +164,7 @@ protected override void LoadComplete()
});
//overlay elements
LoadComponentAsync(direct = new DirectOverlay { Depth = -1 }, overlayContent.Add);
LoadComponentAsync(chat = new ChatOverlay { Depth = -1 }, mainContent.Add);
LoadComponentAsync(settings = new SettingsOverlay { Depth = -1 }, overlayContent.Add);
LoadComponentAsync(musicController = new MusicController
@ -249,6 +254,9 @@ private bool globalHotkeyPressed(InputState state, KeyDownEventArgs args)
case Key.O:
settings.ToggleVisibility();
return true;
case Key.D:
direct.ToggleVisibility();
return true;
}
}

View File

@ -0,0 +1,188 @@
// 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.ComponentModel;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using Container = osu.Framework.Graphics.Containers.Container;
namespace osu.Game.Overlays.Direct
{
public class FilterControl : Container
{
private readonly Box tabStrip;
private readonly FillFlowContainer<ModeToggleButton> modeButtons;
private readonly OsuDropdown<RankStatus> rankStatusDropdown;
public readonly SearchTextBox Search;
public enum RankStatus
{
Any,
[Description("Ranked & Approved")]
RankedApproved,
Approved,
Loved,
Favourites,
[Description("Mod Requests")]
ModRequests,
Pending,
Graveyard,
[Description("My Maps")]
MyMaps,
}
protected override bool InternalContains(Vector2 screenSpacePos) => true;
public FilterControl()
{
RelativeSizeAxes = Axes.X;
//AutoSizeAxes = Axes.Y;
Height = 127;
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.FromHex(@"384552"),
},
tabStrip = new Box
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Position = new Vector2(0f, 1f),
RelativeSizeAxes = Axes.X,
Height = 1,
},
new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Padding = new MarginPadding { Left = DirectOverlay.WIDTH_PADDING, Right = DirectOverlay.WIDTH_PADDING, Top = 10 },
Spacing = new Vector2(0f, 10f),
Children = new Drawable[]
{
Search = new DirectSearchTextBox
{
RelativeSizeAxes = Axes.X,
},
modeButtons = new FillFlowContainer<ModeToggleButton>
{
AutoSizeAxes = Axes.Both,
Spacing = new Vector2(10f, 0f),
},
new SortTabControl
{
RelativeSizeAxes = Axes.X,
},
},
},
rankStatusDropdown = new SlimEnumDropdown<RankStatus>
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
RelativeSizeAxes = Axes.None,
Margin = new MarginPadding { Top = 93, Bottom = 5, Right = DirectOverlay.WIDTH_PADDING }, //todo: sort of hacky positioning
Width = 160f,
},
};
rankStatusDropdown.Current.Value = RankStatus.RankedApproved;
}
[BackgroundDependencyLoader(true)]
private void load(OsuGame game, RulesetDatabase rulesets, OsuColour colours)
{
tabStrip.Colour = colours.Yellow;
rankStatusDropdown.AccentColour = colours.BlueDark;
foreach (var r in rulesets.AllRulesets)
{
modeButtons.Add(new ModeToggleButton(game?.Ruleset ?? new Bindable<RulesetInfo>(), r));
}
}
private class DirectSearchTextBox : SearchTextBox
{
protected override Color4 BackgroundUnfocused => OsuColour.FromHex(@"222222");
protected override Color4 BackgroundFocused => OsuColour.FromHex(@"222222");
}
private class ModeToggleButton : ClickableContainer
{
private TextAwesome icon;
private RulesetInfo ruleset;
public RulesetInfo Ruleset
{
get { return ruleset; }
set
{
ruleset = value;
icon.Icon = Ruleset.CreateInstance().Icon;
}
}
private Bindable<RulesetInfo> bindable;
void Bindable_ValueChanged(RulesetInfo obj)
{
icon.FadeTo((Ruleset == obj) ? 1f : 0.5f, 100);
}
public ModeToggleButton(Bindable<RulesetInfo> bindable, RulesetInfo ruleset)
{
this.bindable = bindable;
AutoSizeAxes = Axes.Both;
Children = new[]
{
icon = new TextAwesome
{
Origin = Anchor.TopLeft,
Anchor = Anchor.TopLeft,
TextSize = 32,
}
};
Ruleset = ruleset;
bindable.ValueChanged += Bindable_ValueChanged;
Bindable_ValueChanged(null);
Action = () => bindable.Value = Ruleset;
}
protected override void Dispose(bool isDisposing)
{
if (bindable != null)
bindable.ValueChanged -= Bindable_ValueChanged;
base.Dispose(isDisposing);
}
}
private class SlimEnumDropdown<T> : OsuEnumDropdown<T>
{
protected override DropdownHeader CreateHeader() => new SlimDropdownHeader { AccentColour = AccentColour };
private class SlimDropdownHeader : OsuDropdownHeader
{
public SlimDropdownHeader()
{
Height = 25;
Icon.TextSize = 16;
Foreground.Padding = new MarginPadding { Top = 4, Bottom = 4, Left = 8, Right = 4, };
}
}
}
}
}

View File

@ -0,0 +1,123 @@
// 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 System.ComponentModel;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using Container = osu.Framework.Graphics.Containers.Container;
namespace osu.Game.Overlays.Direct
{
public class Header : Container
{
private readonly Box tabStrip;
private readonly DirectTabControl tabs;
public Action<DirectTab> OnSelectTab;
public Header()
{
Height = 90;
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.FromHex(@"252f3a"),
},
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = DirectOverlay.WIDTH_PADDING, Right = DirectOverlay.WIDTH_PADDING },
Children = new Drawable[]
{
new FillFlowContainer
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.BottomLeft,
Position = new Vector2(-35f, 5f),
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(10f, 0f),
Children = new Drawable[]
{
new TextAwesome
{
TextSize = 25,
Icon = FontAwesome.fa_osu_chevron_down_o,
},
new OsuSpriteText
{
TextSize = 25,
Text = @"osu!direct",
},
},
},
tabStrip = new Box
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Width = 282, //todo: make this actually match the tab control's width instead of hardcoding
Height = 1,
},
tabs = new DirectTabControl
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.X,
},
},
},
};
tabs.Current.ValueChanged += (newValue) => OnSelectTab?.Invoke(newValue);
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
tabStrip.Colour = colours.Green;
}
private class DirectTabControl : OsuTabControl<DirectTab>
{
protected override TabItem<DirectTab> CreateTabItem(DirectTab value) => new DirectTabItem(value);
public DirectTabControl()
{
Height = 25;
AccentColour = Color4.White;
}
private class DirectTabItem : OsuTabControl<DirectTab>.OsuTabItem
{
public DirectTabItem(DirectTab value) : base(value)
{
Text.TextSize = 15;
}
}
}
}
public enum DirectTab
{
Search,
[Description("Newest Maps")]
New,
[Description("Top Rated")]
Top,
[Description("Most Played")]
MostP
}
}

View File

@ -0,0 +1,117 @@
// 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 OpenTK;
using OpenTK.Graphics;
using osu.Framework.Allocation;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
namespace osu.Game.Overlays.Direct
{
public class SortTabControl : OsuTabControl<SortCriteria>
{
protected override TabItem<SortCriteria> CreateTabItem(SortCriteria value) => new SortTabItem(value);
public SortTabControl()
{
Height = 30;
}
private class SortTabItem : TabItem<SortCriteria>
{
private readonly float transition_duration = 100;
private Box box;
public override bool Active
{
get { return base.Active; }
set
{
if (Active == value) return;
if (value)
slideActive();
else
slideInactive();
base.Active = value;
}
}
public SortTabItem(SortCriteria value) : base(value)
{
AutoSizeAxes = Axes.X;
RelativeSizeAxes = Axes.Y;
Children = new Drawable[]
{
new OsuSpriteText
{
Margin = new MarginPadding { Top = 8, Bottom = 8 },
Origin = Anchor.BottomLeft,
Anchor = Anchor.BottomLeft,
Text = (value as Enum)?.GetDescription() ?? value.ToString(),
TextSize = 14,
Font = @"Exo2.0-Bold",
},
box = new Box
{
RelativeSizeAxes = Axes.X,
Height = 5,
Scale = new Vector2(1f, 0f),
Colour = Color4.White,
Origin = Anchor.BottomLeft,
Anchor = Anchor.BottomLeft,
},
};
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
box.Colour = colours.Yellow;
}
protected override bool OnHover(InputState state)
{
if (!Active)
slideActive();
return true;
}
protected override void OnHoverLost(InputState state)
{
if (!Active)
slideInactive();
}
private void slideActive()
{
box.ScaleTo(new Vector2(1f), transition_duration);
}
private void slideInactive()
{
box.ScaleTo(new Vector2(1f, 0f), transition_duration);
}
}
}
public enum SortCriteria
{
Title,
Artist,
Creator,
Difficulty,
Ranked,
Rating,
}
}

View File

@ -0,0 +1,89 @@
// 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.Graphics.Sprites;
using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds;
using osu.Game.Overlays.Direct;
namespace osu.Game.Overlays
{
public class DirectOverlay : WaveOverlayContainer
{
public static readonly int WIDTH_PADDING = 80;
private readonly Box background;
private readonly FilterControl filter;
public DirectOverlay()
{
RelativeSizeAxes = Axes.Both;
// osu!direct colours are not part of the standard palette
FirstWaveColour = OsuColour.FromHex(@"19b0e2");
SecondWaveColour = OsuColour.FromHex(@"2280a2");
ThirdWaveColour = OsuColour.FromHex(@"005774");
FourthWaveColour = OsuColour.FromHex(@"003a4e");
Children = new Drawable[]
{
background = new Box
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.FromHex(@"485e74"),
},
new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
Children = new[]
{
new Triangles
{
RelativeSizeAxes = Axes.Both,
TriangleScale = 5,
ColourLight = OsuColour.FromHex(@"465b71"),
ColourDark = OsuColour.FromHex(@"3f5265"),
},
},
},
new FillFlowContainer
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Children = new Drawable[]
{
new Header
{
RelativeSizeAxes = Axes.X,
},
filter = new FilterControl
{
RelativeSizeAxes = Axes.X,
},
},
},
};
filter.Search.Exit = Hide;
}
protected override void PopIn()
{
base.PopIn();
filter.Search.HoldFocus = true;
Schedule(() => filter.Search.TriggerFocus());
}
protected override void PopOut()
{
base.PopOut();
filter.Search.HoldFocus = false;
}
}
}

View File

@ -85,6 +85,7 @@ private void load(OsuGame game, OsuConfigManager config, BeatmapDatabase beatmap
}
buttons.OnSettings = game.ToggleSettings;
buttons.OnDirect = game.ToggleDirect;
preloadSongSelect();
}

View File

@ -428,6 +428,11 @@
<Compile Include="Overlays\Music\PlaylistOverlay.cs" />
<Compile Include="Rulesets\Replays\IAutoGenerator.cs" />
<Compile Include="Rulesets\Replays\AutoGenerator.cs" />
<Compile Include="Overlays\DirectOverlay.cs" />
<Compile Include="Overlays\Direct\FilterControl.cs" />
<Compile Include="Overlays\Direct\Header.cs" />
<Compile Include="Overlays\Direct\SortTabControl.cs" />
<Compile Include="Graphics\UserInterface\OsuEnumDropdown.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\osu-framework\osu.Framework\osu.Framework.csproj">
@ -450,6 +455,9 @@
<ItemGroup />
<ItemGroup />
<ItemGroup />
<ItemGroup>
<Folder Include="Overlays\Direct\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.