1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 07:32:55 +08:00

Merge pull request #539 from DrabWeb/beatmap-detail-tabs

Beatmap detail area
This commit is contained in:
Dan Balasescu 2017-03-23 17:20:47 +09:00 committed by GitHub
commit 50543a164c
10 changed files with 370 additions and 22 deletions

@ -1 +1 @@
Subproject commit 06e426da039f7bb54aedf5d82c21b8d858a0310e
Subproject commit 34c9f17a6ac6fa5e9fd5569f9e119331316c1313

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 OpenTK;
using osu.Framework.Graphics;
using osu.Framework.Screens.Testing;
using osu.Game.Screens.Select;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseBeatmapDetailArea : TestCase
{
public override string Description => @"Beatmap details in song select";
public override void Reset()
{
base.Reset();
Add(new BeatmapDetailArea
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(550f, 450f),
});
}
}
}

View File

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

View File

@ -28,6 +28,8 @@ namespace osu.Game.Graphics.UserInterface
public OsuTabControl()
{
TabContainer.Spacing = new Vector2(10f, 0f);
if (!typeof(T).IsEnum)
throw new InvalidOperationException("OsuTabControl only supports enums as the generic type argument");
@ -142,7 +144,7 @@ namespace osu.Game.Graphics.UserInterface
{
text = new OsuSpriteText
{
Margin = new MarginPadding(5),
Margin = new MarginPadding { Top = 5, Bottom = 5 },
Origin = Anchor.BottomLeft,
Anchor = Anchor.BottomLeft,
TextSize = 14,

View File

@ -0,0 +1,140 @@
// 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.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transforms;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input;
using osu.Game.Graphics.Sprites;
namespace osu.Game.Graphics.UserInterface
{
/// <summary>
/// A checkbox styled to be placed in line with an <see cref="OsuTabControl{T}"/>
/// </summary>
public class OsuTabControlCheckBox : CheckBox
{
private readonly Box box;
private readonly SpriteText text;
private readonly TextAwesome icon;
public event EventHandler<CheckBoxState> Action;
private Color4? accentColour;
public Color4 AccentColour
{
get { return accentColour.GetValueOrDefault(); }
set
{
accentColour = value;
if (State != CheckBoxState.Checked)
{
text.Colour = AccentColour;
icon.Colour = AccentColour;
}
}
}
public string Text
{
get { return text.Text; }
set { text.Text = value; }
}
protected override void OnChecked()
{
fadeIn();
icon.Icon = FontAwesome.fa_check_circle_o;
Action?.Invoke(this, State);
}
protected override void OnUnchecked()
{
fadeOut();
icon.Icon = FontAwesome.fa_circle_o;
Action?.Invoke(this, State);
}
private const float transition_length = 500;
private void fadeIn()
{
box.FadeIn(transition_length, EasingTypes.OutQuint);
text.FadeColour(Color4.White, transition_length, EasingTypes.OutQuint);
}
private void fadeOut()
{
box.FadeOut(transition_length, EasingTypes.OutQuint);
text.FadeColour(AccentColour, transition_length, EasingTypes.OutQuint);
}
protected override bool OnHover(InputState state)
{
fadeIn();
return base.OnHover(state);
}
protected override void OnHoverLost(InputState state)
{
if (State == CheckBoxState.Unchecked)
fadeOut();
base.OnHoverLost(state);
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
if (accentColour == null)
AccentColour = colours.Blue;
}
public OsuTabControlCheckBox()
{
AutoSizeAxes = Axes.Both;
Children = new Drawable[]
{
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Margin = new MarginPadding { Top = 5, Bottom = 5, },
Spacing = new Vector2(5f, 0f),
Direction = FillDirection.Horizontal,
Children = new Drawable[]
{
text = new OsuSpriteText
{
TextSize = 14,
Font = @"Exo2.0-Bold",
},
icon = new TextAwesome
{
TextSize = 14,
Icon = FontAwesome.fa_circle_o,
Shadow = true,
},
},
},
box = new Box
{
RelativeSizeAxes = Axes.X,
Height = 1,
Alpha = 0,
Colour = Color4.White,
Origin = Anchor.BottomLeft,
Anchor = Anchor.BottomLeft,
}
};
}
}
}

View File

@ -0,0 +1,111 @@
// 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.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Game.Beatmaps;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Screens.Select.Leaderboards;
namespace osu.Game.Screens.Select
{
public class BeatmapDetailArea : Container
{
private readonly Container content;
protected override Container<Drawable> Content => content;
public readonly Container Details; //todo: replace with a real details view when added
public readonly Leaderboard Leaderboard;
private APIAccess api;
private WorkingBeatmap beatmap;
public WorkingBeatmap Beatmap
{
get
{
return beatmap;
}
set
{
beatmap = value;
if (IsLoaded) Schedule(updateScores);
}
}
public BeatmapDetailArea()
{
AddInternal(new Drawable[]
{
new BeatmapDetailAreaTabControl
{
RelativeSizeAxes = Axes.X,
OnFilter = (tab, mods) =>
{
switch (tab)
{
case BeatmapDetailTab.Details:
Details.Show();
Leaderboard.Hide();
break;
default:
Details.Hide();
Leaderboard.Show();
break;
}
//for now let's always update scores.
updateScores();
},
},
content = new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT },
},
});
Add(new Drawable[]
{
Details = new Container
{
RelativeSizeAxes = Axes.Both,
},
Leaderboard = new Leaderboard
{
RelativeSizeAxes = Axes.Both,
}
});
}
protected override void LoadComplete()
{
base.LoadComplete();
updateScores();
}
[BackgroundDependencyLoader(permitNulls: true)]
private void load(APIAccess api)
{
this.api = api;
}
private GetScoresRequest getScoresRequest;
private void updateScores()
{
if (!IsLoaded) return;
Leaderboard.Scores = null;
getScoresRequest?.Cancel();
if (api == null || beatmap?.BeatmapInfo == null || !Leaderboard.IsPresent) return;
getScoresRequest = new GetScoresRequest(beatmap.BeatmapInfo);
getScoresRequest.Success += r => Leaderboard.Scores = r.Scores;
api.Queue(getScoresRequest);
}
}
}

View File

@ -0,0 +1,79 @@
// 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.Graphics;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
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.UserInterface;
namespace osu.Game.Screens.Select
{
public class BeatmapDetailAreaTabControl : Container
{
public static readonly float HEIGHT = 24;
private readonly OsuTabControlCheckBox modsCheckbox;
private readonly OsuTabControl<BeatmapDetailTab> tabs;
public Action<BeatmapDetailTab, bool> OnFilter; //passed the selected tab and if mods is checked
private void invokeOnFilter()
{
OnFilter?.Invoke(tabs.SelectedItem, modsCheckbox.State == CheckBoxState.Checked);
}
[BackgroundDependencyLoader]
private void load(OsuColour colour)
{
modsCheckbox.AccentColour = tabs.AccentColour = colour.YellowLight;
}
public BeatmapDetailAreaTabControl()
{
Height = HEIGHT;
Children = new Drawable[]
{
new Box
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.X,
Height = 1,
Colour = Color4.White.Opacity(0.2f),
},
tabs = new OsuTabControl<BeatmapDetailTab>
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.Both,
},
modsCheckbox = new OsuTabControlCheckBox
{
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
Text = @"Mods",
},
};
tabs.ItemChanged += (sender, e) => invokeOnFilter();
modsCheckbox.Action += (sender, e) => invokeOnFilter();
tabs.SelectedItem = BeatmapDetailTab.Global;
}
}
public enum BeatmapDetailTab
{
Details,
Local,
Country,
Global,
Friends
}
}

View File

@ -74,7 +74,7 @@ namespace osu.Game.Screens.Select.Leaderboards
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(0f, 5f),
Padding = new MarginPadding(5),
Padding = new MarginPadding { Top = 10, Bottom = 5 },
},
},
},

View File

@ -8,11 +8,9 @@ using osu.Framework.Graphics.Primitives;
using osu.Framework.Screens;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Online.API.Requests;
using osu.Game.Overlays.Mods;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Play;
using osu.Game.Screens.Select.Leaderboards;
namespace osu.Game.Screens.Select
{
@ -20,7 +18,7 @@ namespace osu.Game.Screens.Select
{
private OsuScreen player;
private readonly ModSelectOverlay modSelect;
private readonly Leaderboard leaderboard;
private readonly BeatmapDetailArea beatmapDetails;
public PlaySongSelect()
{
@ -32,9 +30,10 @@ namespace osu.Game.Screens.Select
Margin = new MarginPadding { Bottom = 50 }
});
LeftContent.Add(leaderboard = new Leaderboard
LeftContent.Add(beatmapDetails = new BeatmapDetailArea
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Top = 10, Right = 5 },
});
}
@ -52,29 +51,15 @@ namespace osu.Game.Screens.Select
}, Key.Number3);
}
private GetScoresRequest getScoresRequest;
protected override void OnBeatmapChanged(WorkingBeatmap beatmap)
{
beatmap?.Mods.BindTo(modSelect.SelectedMods);
updateLeaderboard(beatmap);
beatmapDetails.Beatmap = beatmap;
base.OnBeatmapChanged(beatmap);
}
private void updateLeaderboard(WorkingBeatmap beatmap)
{
leaderboard.Scores = null;
getScoresRequest?.Cancel();
if (beatmap?.BeatmapInfo == null) return;
getScoresRequest = new GetScoresRequest(beatmap.BeatmapInfo);
getScoresRequest.Success += r => leaderboard.Scores = r.Scores;
Game.API.Queue(getScoresRequest);
}
protected override void OnResuming(Screen last)
{
player = null;

View File

@ -363,6 +363,9 @@
<Compile Include="Users\Avatar.cs" />
<Compile Include="Screens\Select\Leaderboards\DrawableRank.cs" />
<Compile Include="Graphics\UserInterface\OsuTabControl.cs" />
<Compile Include="Screens\Select\BeatmapDetailArea.cs" />
<Compile Include="Graphics\UserInterface\OsuTabControlCheckBox.cs" />
<Compile Include="Screens\Select\BeatmapDetailAreaTabControl.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\osu-framework\osu.Framework\osu.Framework.csproj">