Merge remote-tracking branch 'upstream/master' into songselect-best-user-score

This commit is contained in:
Dean Herbert
2019-09-19 12:57:30 +09:00
623 changed files with 15821 additions and 5199 deletions

View File

@ -24,8 +24,11 @@ using osu.Game.Screens.Select.Carousel;
namespace osu.Game.Screens.Select
{
public class BeatmapCarousel : OsuScrollContainer
public class BeatmapCarousel : CompositeDrawable
{
private const float bleed_top = FilterControl.HEIGHT;
private const float bleed_bottom = Footer.HEIGHT;
/// <summary>
/// Triggered when the <see cref="BeatmapSets"/> loaded change and are completely loaded.
/// </summary>
@ -58,6 +61,8 @@ namespace osu.Game.Screens.Select
/// </summary>
public bool BeatmapSetsLoaded { get; private set; }
private readonly OsuScrollContainer scroll;
private IEnumerable<CarouselBeatmapSet> beatmapSets => root.Children.OfType<CarouselBeatmapSet>();
public IEnumerable<BeatmapSetInfo> BeatmapSets
@ -81,7 +86,8 @@ namespace osu.Game.Screens.Select
itemsCache.Invalidate();
scrollPositionCache.Invalidate();
Schedule(() =>
// Run on late scheduler want to ensure this runs after all pending UpdateBeatmapSet / RemoveBeatmapSet operations are run.
SchedulerAfterChildren.Add(() =>
{
BeatmapSetsChanged?.Invoke();
BeatmapSetsLoaded = true;
@ -89,8 +95,8 @@ namespace osu.Game.Screens.Select
}
private readonly List<float> yPositions = new List<float>();
private Cached itemsCache = new Cached();
private Cached scrollPositionCache = new Cached();
private readonly Cached itemsCache = new Cached();
private readonly Cached scrollPositionCache = new Cached();
private readonly Container<DrawableCarouselItem> scrollableContent;
@ -106,13 +112,17 @@ namespace osu.Game.Screens.Select
public BeatmapCarousel()
{
root = new CarouselRoot(this);
Child = new OsuContextMenuContainer
InternalChild = new OsuContextMenuContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Child = scrollableContent = new Container<DrawableCarouselItem>
RelativeSizeAxes = Axes.Both,
Child = scroll = new CarouselScrollContainer
{
RelativeSizeAxes = Axes.X,
Masking = false,
RelativeSizeAxes = Axes.Both,
Child = scrollableContent = new Container<DrawableCarouselItem>
{
RelativeSizeAxes = Axes.X,
}
}
};
}
@ -123,25 +133,22 @@ namespace osu.Game.Screens.Select
config.BindWith(OsuSetting.RandomSelectAlgorithm, RandomAlgorithm);
config.BindWith(OsuSetting.SongSelectRightMouseScroll, RightClickScrollingEnabled);
RightClickScrollingEnabled.ValueChanged += enabled => RightMouseScrollbar = enabled.NewValue;
RightClickScrollingEnabled.ValueChanged += enabled => scroll.RightMouseScrollbar = enabled.NewValue;
RightClickScrollingEnabled.TriggerChange();
loadBeatmapSets(beatmaps.GetAllUsableBeatmapSetsEnumerable());
}
public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet)
public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() =>
{
Schedule(() =>
{
var existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.ID == beatmapSet.ID);
var existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.ID == beatmapSet.ID);
if (existingSet == null)
return;
if (existingSet == null)
return;
root.RemoveChild(existingSet);
itemsCache.Invalidate();
});
}
root.RemoveChild(existingSet);
itemsCache.Invalidate();
});
public void UpdateBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() =>
{
@ -338,6 +345,25 @@ namespace osu.Game.Screens.Select
public bool AllowSelection = true;
/// <summary>
/// Half the height of the visible content.
/// <remarks>
/// This is different from the height of <see cref="ScrollContainer{T}.displayableContent"/>, since
/// the beatmap carousel bleeds into the <see cref="FilterControl"/> and the <see cref="Footer"/>
/// </remarks>
/// </summary>
private float visibleHalfHeight => (DrawHeight + bleed_bottom + bleed_top) / 2;
/// <summary>
/// The position of the lower visible bound with respect to the current scroll position.
/// </summary>
private float visibleBottomBound => scroll.Current + DrawHeight + bleed_bottom;
/// <summary>
/// The position of the upper visible bound with respect to the current scroll position.
/// </summary>
private float visibleUpperBound => scroll.Current - bleed_top;
public void FlushPendingFilterOperations()
{
if (PendingFilter?.Completed == false)
@ -414,6 +440,8 @@ namespace osu.Game.Screens.Select
return true;
}
protected override bool ReceivePositionalInputAtSubTree(Vector2 screenSpacePos) => ReceivePositionalInputAt(screenSpacePos);
protected override void Update()
{
base.Update();
@ -424,17 +452,15 @@ namespace osu.Game.Screens.Select
if (!scrollPositionCache.IsValid)
updateScrollPosition();
float drawHeight = DrawHeight;
// Remove all items that should no longer be on-screen
scrollableContent.RemoveAll(p => p.Y < Current - p.DrawHeight || p.Y > Current + drawHeight || !p.IsPresent);
scrollableContent.RemoveAll(p => p.Y < visibleUpperBound - p.DrawHeight || p.Y > visibleBottomBound || !p.IsPresent);
// Find index range of all items that should be on-screen
Trace.Assert(Items.Count == yPositions.Count);
int firstIndex = yPositions.BinarySearch(Current - DrawableCarouselItem.MAX_HEIGHT);
int firstIndex = yPositions.BinarySearch(visibleUpperBound - DrawableCarouselItem.MAX_HEIGHT);
if (firstIndex < 0) firstIndex = ~firstIndex;
int lastIndex = yPositions.BinarySearch(Current + drawHeight);
int lastIndex = yPositions.BinarySearch(visibleBottomBound);
if (lastIndex < 0) lastIndex = ~lastIndex;
int notVisibleCount = 0;
@ -486,9 +512,8 @@ namespace osu.Game.Screens.Select
// Update externally controlled state of currently visible items
// (e.g. x-offset and opacity).
float halfHeight = drawHeight / 2;
foreach (DrawableCarouselItem p in scrollableContent.Children)
updateItem(p, halfHeight);
updateItem(p);
}
protected override void Dispose(bool isDisposing)
@ -542,7 +567,7 @@ namespace osu.Game.Screens.Select
yPositions.Clear();
float currentY = DrawHeight / 2;
float currentY = visibleHalfHeight;
DrawableCarouselBeatmapSet lastSet = null;
scrollTarget = null;
@ -575,7 +600,6 @@ namespace osu.Game.Screens.Select
float? setY = null;
if (!d.IsLoaded || beatmap.Alpha == 0) // can't use IsPresent due to DrawableCarouselItem override.
// ReSharper disable once PossibleNullReferenceException (resharper broken?)
setY = lastSet.Y + lastSet.DrawHeight + 5;
if (d.IsLoaded)
@ -596,7 +620,7 @@ namespace osu.Game.Screens.Select
currentY += d.DrawHeight + 5;
}
currentY += DrawHeight / 2;
currentY += visibleHalfHeight;
scrollableContent.Height = currentY;
if (BeatmapSetsLoaded && (selectedBeatmapSet == null || selectedBeatmap == null || selectedBeatmapSet.State.Value != CarouselItemState.Selected))
@ -610,7 +634,7 @@ namespace osu.Game.Screens.Select
private void updateScrollPosition()
{
if (scrollTarget != null) ScrollTo(scrollTarget.Value);
if (scrollTarget != null) scroll.ScrollTo(scrollTarget.Value);
scrollPositionCache.Validate();
}
@ -637,18 +661,15 @@ namespace osu.Game.Screens.Select
/// the current scroll position.
/// </summary>
/// <param name="p">The item to be updated.</param>
/// <param name="halfHeight">Half the draw height of the carousel container.</param>
private void updateItem(DrawableCarouselItem p, float halfHeight)
private void updateItem(DrawableCarouselItem p)
{
var height = p.IsPresent ? p.DrawHeight : 0;
float itemDrawY = p.Position.Y - Current + height / 2;
float dist = Math.Abs(1f - itemDrawY / halfHeight);
float itemDrawY = p.Position.Y - visibleUpperBound + p.DrawHeight / 2;
float dist = Math.Abs(1f - itemDrawY / visibleHalfHeight);
// Setting the origin position serves as an additive position on top of potential
// local transformation we may want to apply (e.g. when a item gets selected, we
// may want to smoothly transform it leftwards.)
p.OriginPosition = new Vector2(-offsetX(dist, halfHeight), 0);
p.OriginPosition = new Vector2(-offsetX(dist, visibleHalfHeight), 0);
// We are applying a multiplicative alpha (which is internally done by nesting an
// additional container and setting that container's alpha) such that we can
@ -673,5 +694,35 @@ namespace osu.Game.Screens.Select
base.PerformSelection();
}
}
private class CarouselScrollContainer : OsuScrollContainer
{
private bool rightMouseScrollBlocked;
protected override bool OnMouseDown(MouseDownEvent e)
{
if (e.Button == MouseButton.Right)
{
// we need to block right click absolute scrolling when hovering a carousel item so context menus can display.
// this can be reconsidered when we have an alternative to right click scrolling.
if (GetContainingInputManager().HoveredDrawables.OfType<DrawableCarouselItem>().Any())
{
rightMouseScrollBlocked = true;
return false;
}
}
rightMouseScrollBlocked = false;
return base.OnMouseDown(e);
}
protected override bool OnDragStart(DragStartEvent e)
{
if (rightMouseScrollBlocked)
return false;
return base.OnDragStart(e);
}
}
}
}

View File

@ -25,8 +25,8 @@ namespace osu.Game.Screens.Select
set
{
beatmap = value;
Leaderboard.Beatmap = beatmap?.BeatmapInfo;
Details.Beatmap = beatmap?.BeatmapInfo;
Leaderboard.Beatmap = beatmap is DummyWorkingBeatmap ? null : beatmap?.BeatmapInfo;
TopScore.Hide();
}
}

View File

@ -25,22 +25,6 @@ namespace osu.Game.Screens.Select
private Bindable<BeatmapDetailTab> selectedTab;
private void invokeOnFilter()
{
OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value);
}
[BackgroundDependencyLoader]
private void load(OsuColour colour, OsuConfigManager config)
{
modsCheckbox.AccentColour = tabs.AccentColour = colour.YellowLight;
selectedTab = config.GetBindable<BeatmapDetailTab>(OsuSetting.BeatmapDetailTab);
tabs.Current.BindTo(selectedTab);
tabs.Current.TriggerChange();
}
public BeatmapDetailAreaTabControl()
{
Height = HEIGHT;
@ -66,12 +50,31 @@ namespace osu.Game.Screens.Select
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
Text = @"Mods",
Alpha = 0,
},
};
tabs.Current.ValueChanged += _ => invokeOnFilter();
modsCheckbox.Current.ValueChanged += _ => invokeOnFilter();
}
[BackgroundDependencyLoader]
private void load(OsuColour colour, OsuConfigManager config)
{
modsCheckbox.AccentColour = tabs.AccentColour = colour.YellowLight;
selectedTab = config.GetBindable<BeatmapDetailTab>(OsuSetting.BeatmapDetailTab);
tabs.Current.BindTo(selectedTab);
tabs.Current.TriggerChange();
}
private void invokeOnFilter()
{
OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value);
modsCheckbox.FadeTo(tabs.Current.Value == BeatmapDetailTab.Details ? 0 : 1, 200, Easing.OutQuint);
}
}
public enum BeatmapDetailTab

View File

@ -35,7 +35,7 @@ namespace osu.Game.Screens.Select
private readonly MetadataSection description, source, tags;
private readonly Container failRetryContainer;
private readonly FailRetryGraph failRetryGraph;
private readonly DimmedLoadingAnimation loading;
private readonly DimmedLoadingLayer loading;
private IAPIProvider api;
@ -156,10 +156,7 @@ namespace osu.Game.Screens.Select
},
},
},
loading = new DimmedLoadingAnimation
{
RelativeSizeAxes = Axes.Both,
},
loading = new DimmedLoadingLayer(),
};
}
@ -365,35 +362,5 @@ namespace osu.Game.Screens.Select
});
}
}
private class DimmedLoadingAnimation : VisibilityContainer
{
private readonly LoadingAnimation loading;
public DimmedLoadingAnimation()
{
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black.Opacity(0.5f),
},
loading = new LoadingAnimation(),
};
}
protected override void PopIn()
{
this.FadeIn(transition_duration, Easing.OutQuint);
loading.Show();
}
protected override void PopOut()
{
this.FadeOut(transition_duration, Easing.OutQuint);
loading.Hide();
}
}
}
}

View File

@ -141,6 +141,7 @@ namespace osu.Game.Screens.Select
private readonly RulesetInfo ruleset;
public BufferedWedgeInfo(WorkingBeatmap beatmap, RulesetInfo userRuleset)
: base(pixelSnapping: true)
{
this.beatmap = beatmap;
ruleset = userRuleset ?? beatmap.BeatmapInfo.Ruleset;
@ -152,8 +153,9 @@ namespace osu.Game.Screens.Select
var beatmapInfo = beatmap.BeatmapInfo;
var metadata = beatmapInfo.Metadata ?? beatmap.BeatmapSetInfo?.Metadata ?? new BeatmapMetadata();
PixelSnapping = true;
CacheDrawnFrameBuffer = true;
RedrawOnScale = false;
RelativeSizeAxes = Axes.Both;
titleBinding = localisation.GetLocalisedString(new LocalisedString((metadata.TitleUnicode, metadata.Title)));
@ -402,31 +404,35 @@ namespace osu.Game.Screens.Select
}
}
private class DifficultyColourBar : DifficultyColouredContainer
private class DifficultyColourBar : Container
{
private readonly BeatmapInfo beatmap;
public DifficultyColourBar(BeatmapInfo beatmap)
: base(beatmap)
{
this.beatmap = beatmap;
}
[BackgroundDependencyLoader]
private void load()
private void load(OsuColour colours)
{
const float full_opacity_ratio = 0.7f;
var difficultyColour = colours.ForDifficultyRating(beatmap.DifficultyRating);
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = AccentColour,
Colour = difficultyColour,
Width = full_opacity_ratio,
},
new Box
{
RelativeSizeAxes = Axes.Both,
RelativePositionAxes = Axes.Both,
Colour = AccentColour,
Colour = difficultyColour,
Alpha = 0.5f,
X = full_opacity_ratio,
Width = 1 - full_opacity_ratio,

View File

@ -82,7 +82,7 @@ namespace osu.Game.Screens.Select.Carousel
Origin = Anchor.CentreLeft,
Children = new Drawable[]
{
new DifficultyIcon(beatmap)
new DifficultyIcon(beatmap, shouldShowTooltip: false)
{
Scale = new Vector2(1.8f),
},

View File

@ -19,6 +19,7 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays;
using osu.Game.Rulesets;
using osuTK;
using osuTK.Graphics;
@ -95,10 +96,11 @@ namespace osu.Game.Screens.Select.Carousel
TextPadding = new MarginPadding { Horizontal = 8, Vertical = 2 },
Status = beatmapSet.Status
},
new FillFlowContainer<FilterableDifficultyIcon>
new FillFlowContainer<DifficultyIcon>
{
AutoSizeAxes = Axes.Both,
Children = ((CarouselBeatmapSet)Item).Beatmaps.Select(b => new FilterableDifficultyIcon(b)).ToList()
Spacing = new Vector2(3),
ChildrenEnumerable = getDifficultyIcons(),
},
}
}
@ -107,6 +109,17 @@ namespace osu.Game.Screens.Select.Carousel
};
}
private const int maximum_difficulty_icons = 18;
private IEnumerable<DifficultyIcon> getDifficultyIcons()
{
var beatmaps = ((CarouselBeatmapSet)Item).Beatmaps.ToList();
return beatmaps.Count > maximum_difficulty_icons
? (IEnumerable<DifficultyIcon>)beatmaps.GroupBy(b => b.Beatmap.Ruleset).Select(group => new FilterableGroupedDifficultyIcon(group.ToList(), group.Key))
: beatmaps.Select(b => new FilterableDifficultyIcon(b));
}
public MenuItem[] ContextMenuItems
{
get
@ -133,6 +146,7 @@ namespace osu.Game.Screens.Select.Carousel
public PanelBackground(WorkingBeatmap working)
{
CacheDrawnFrameBuffer = true;
RedrawOnScale = false;
Children = new Drawable[]
{
@ -204,5 +218,27 @@ namespace osu.Game.Screens.Select.Carousel
filtered.TriggerChange();
}
}
public class FilterableGroupedDifficultyIcon : GroupedDifficultyIcon
{
private readonly List<CarouselBeatmap> items;
public FilterableGroupedDifficultyIcon(List<CarouselBeatmap> items, RulesetInfo ruleset)
: base(items.Select(i => i.Beatmap).ToList(), ruleset, Color4.White)
{
this.items = items;
foreach (var item in items)
item.Filtered.BindValueChanged(_ => Scheduler.AddOnce(updateFilteredDisplay));
updateFilteredDisplay();
}
private void updateFilteredDisplay()
{
// for now, fade the whole group based on the ratio of hidden items.
this.FadeTo(1 - 0.9f * ((float)items.Count(i => i.Filtered.Value) / items.Count), 100);
}
}
}
}

View File

@ -64,7 +64,7 @@ namespace osu.Game.Screens.Select.Carousel
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
Blending = BlendingMode.Additive,
Blending = BlendingParameters.Additive,
},
}
};

View File

@ -14,7 +14,6 @@ using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Select.Filter;
using Container = osu.Framework.Graphics.Containers.Container;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
using osu.Game.Configuration;
using osu.Game.Rulesets;
@ -22,46 +21,22 @@ namespace osu.Game.Screens.Select
{
public class FilterControl : Container
{
public const float HEIGHT = 100;
public Action<FilterCriteria> FilterChanged;
private readonly OsuTabControl<SortMode> sortTabs;
private readonly TabControl<GroupMode> groupTabs;
private SortMode sort = SortMode.Title;
private Bindable<SortMode> sortMode;
public SortMode Sort
{
get => sort;
set
{
if (sort != value)
{
sort = value;
FilterChanged?.Invoke(CreateCriteria());
}
}
}
private GroupMode group = GroupMode.All;
public GroupMode Group
{
get => group;
set
{
if (group != value)
{
group = value;
FilterChanged?.Invoke(CreateCriteria());
}
}
}
private Bindable<GroupMode> groupMode;
public FilterCriteria CreateCriteria() => new FilterCriteria
{
Group = group,
Sort = sort,
Group = groupMode.Value,
Sort = sortMode.Value,
SearchText = searchTextBox.Text,
AllowConvertedBeatmaps = showConverted.Value,
Ruleset = ruleset.Value
@ -121,7 +96,6 @@ namespace osu.Game.Screens.Select
Height = 24,
Width = 0.5f,
AutoSort = true,
Current = { Value = GroupMode.Title }
},
//spriteText = new OsuSpriteText
//{
@ -140,7 +114,6 @@ namespace osu.Game.Screens.Select
Width = 0.5f,
Height = 24,
AutoSort = true,
Current = { Value = SortMode.Title }
}
}
},
@ -152,8 +125,6 @@ namespace osu.Game.Screens.Select
groupTabs.PinItem(GroupMode.All);
groupTabs.PinItem(GroupMode.RecentlyPlayed);
groupTabs.Current.ValueChanged += group => Group = group.NewValue;
sortTabs.Current.ValueChanged += sort => Sort = sort.NewValue;
}
public void Deactivate()
@ -183,15 +154,20 @@ namespace osu.Game.Screens.Select
showConverted.ValueChanged += _ => updateCriteria();
ruleset.BindTo(parentRuleset);
ruleset.BindValueChanged(_ => updateCriteria(), true);
ruleset.BindValueChanged(_ => updateCriteria());
sortMode = config.GetBindable<SortMode>(OsuSetting.SongSelectSortingMode);
groupMode = config.GetBindable<GroupMode>(OsuSetting.SongSelectGroupingMode);
sortTabs.Current.BindTo(sortMode);
groupTabs.Current.BindTo(groupMode);
groupMode.BindValueChanged(_ => updateCriteria());
sortMode.BindValueChanged(_ => updateCriteria());
updateCriteria();
}
private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria());
protected override bool OnMouseDown(MouseDownEvent e) => true;
protected override bool OnMouseMove(MouseMoveEvent e) => true;
protected override bool OnClick(ClickEvent e) => true;
}
}

View File

@ -94,7 +94,7 @@ namespace osu.Game.Screens.Select
buttons = new FillFlowContainer<FooterButton>
{
Direction = FillDirection.Horizontal,
Spacing = new Vector2(0.2f, 0),
Spacing = new Vector2(-FooterButton.SHEAR_WIDTH, 0),
AutoSizeAxes = Axes.Both,
}
}

View File

@ -17,7 +17,9 @@ namespace osu.Game.Screens.Select
{
public class FooterButton : OsuClickableContainer
{
private static readonly Vector2 shearing = new Vector2(0.15f, 0);
public static readonly float SHEAR_WIDTH = 7.5f;
protected static readonly Vector2 SHEAR = new Vector2(SHEAR_WIDTH / Footer.HEIGHT, 0);
public string Text
{
@ -59,37 +61,35 @@ namespace osu.Game.Screens.Select
private readonly Box box;
private readonly Box light;
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => box.ReceivePositionalInputAt(screenSpacePos);
public FooterButton()
{
AutoSizeAxes = Axes.Both;
Shear = SHEAR;
Children = new Drawable[]
{
TextContainer = new Container
{
Size = new Vector2(100, 50),
Child = SpriteText = new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
},
box = new Box
{
RelativeSizeAxes = Axes.Both,
Shear = shearing,
EdgeSmoothness = new Vector2(2, 0),
Colour = Color4.White,
Alpha = 0,
},
light = new Box
{
Shear = shearing,
Height = 4,
EdgeSmoothness = new Vector2(2, 0),
RelativeSizeAxes = Axes.X,
},
TextContainer = new Container
{
Size = new Vector2(100 - SHEAR_WIDTH, 50),
Shear = -SHEAR,
Child = SpriteText = new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
},
};
}

View File

@ -32,6 +32,7 @@ namespace osu.Game.Screens.Select
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Shear = -SHEAR,
Child = modDisplay = new FooterModDisplay
{
DisplayUnrankedText = false,

View File

@ -88,6 +88,12 @@ namespace osu.Game.Screens.Select.Leaderboards
{
TopScore.Value = null;
if (Beatmap == null)
{
PlaceholderState = PlaceholderState.NoneSelected;
return null;
}
if (Scope == BeatmapLeaderboardScope.Local)
{
var scores = scoreManager
@ -118,7 +124,7 @@ namespace osu.Game.Screens.Select.Leaderboards
return null;
}
if (Beatmap?.OnlineBeatmapID == null || Beatmap?.Status <= BeatmapSetOnlineStatus.Pending)
if (Beatmap.OnlineBeatmapID == null || Beatmap?.Status <= BeatmapSetOnlineStatus.Pending)
{
PlaceholderState = PlaceholderState.Unavailable;
return null;

View File

@ -1,13 +1,22 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.ComponentModel;
namespace osu.Game.Screens.Select.Leaderboards
{
public enum BeatmapLeaderboardScope
{
[Description("Local Ranking")]
Local,
[Description("Country Ranking")]
Country,
[Description("Global Ranking")]
Global,
[Description("Friend Ranking")]
Friend,
}
}

View File

@ -121,7 +121,7 @@ namespace osu.Game.Screens.Select.Options
{
RelativeSizeAxes = Axes.Both,
EdgeSmoothness = new Vector2(1.5f, 0),
Blending = BlendingMode.Additive,
Blending = BlendingParameters.Additive,
Colour = Color4.White,
Alpha = 0,
},

View File

@ -121,7 +121,7 @@ namespace osu.Game.Screens.Select
Size = new Vector2(wedged_container_size.X, 1),
Padding = new MarginPadding
{
Bottom = 50,
Bottom = Footer.HEIGHT,
Top = wedged_container_size.Y + left_area_padding,
Left = left_area_padding,
Right = left_area_padding * 2,
@ -147,20 +147,28 @@ namespace osu.Game.Screens.Select
Width = 0.5f,
Children = new Drawable[]
{
Carousel = new BeatmapCarousel
new Container
{
Masking = false,
RelativeSizeAxes = Axes.Both,
Size = new Vector2(1 - wedged_container_size.X, 1),
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
SelectionChanged = updateSelectedBeatmap,
BeatmapSetsChanged = carouselBeatmapsLoaded,
Padding = new MarginPadding
{
Top = FilterControl.HEIGHT,
Bottom = Footer.HEIGHT
},
Child = Carousel = new BeatmapCarousel
{
RelativeSizeAxes = Axes.Both,
Size = new Vector2(1 - wedged_container_size.X, 1),
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
SelectionChanged = updateSelectedBeatmap,
BeatmapSetsChanged = carouselBeatmapsLoaded,
},
},
FilterControl = new FilterControl
{
RelativeSizeAxes = Axes.X,
Height = 100,
Height = FilterControl.HEIGHT,
FilterChanged = c => Carousel.Filter(c),
Background = { Width = 2 },
Exit = () =>
@ -354,6 +362,7 @@ namespace osu.Game.Screens.Select
return;
beatmapNoDebounce = beatmap;
performUpdateSelected();
}
@ -408,7 +417,11 @@ namespace osu.Game.Screens.Select
{
Logger.Log($"beatmap changed from \"{Beatmap.Value.BeatmapInfo}\" to \"{beatmap}\"");
Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap, Beatmap.Value);
WorkingBeatmap previous = Beatmap.Value;
Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap, previous);
if (this.IsCurrentScreen() && Beatmap.Value?.Track != previous?.Track)
ensurePlayingSelected();
if (beatmap != null)
{
@ -419,8 +432,6 @@ namespace osu.Game.Screens.Select
}
}
if (this.IsCurrentScreen())
ensurePlayingSelected();
UpdateBeatmap(Beatmap.Value);
}
}
@ -581,10 +592,18 @@ namespace osu.Game.Screens.Select
{
Track track = Beatmap.Value.Track;
if ((!track.IsRunning || restart) && music?.IsUserPaused != true)
if (!track.IsRunning || restart)
{
track.RestartPoint = Beatmap.Value.Metadata.PreviewTime;
track.Restart();
if (music != null)
{
// use the global music controller (when available) to cancel a potential local user paused state.
music.SeekTo(track.RestartPoint);
music.Play();
}
else
track.Restart();
}
}