mirror of
https://github.com/osukey/osukey.git
synced 2025-08-03 14:46:38 +09:00
Merge remote-tracking branch 'origin/master' into star-filtering
# Conflicts: # osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs # osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs # osu.Game/Screens/Select/FilterControl.cs # osu.Game/Screens/Select/FilterCriteria.cs
This commit is contained in:
@ -1,7 +1,8 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Screens.Select.Filter;
|
||||
@ -24,13 +25,37 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
{
|
||||
base.Filter(criteria);
|
||||
|
||||
bool match = criteria.Ruleset == null || Beatmap.RulesetID == criteria.Ruleset.ID || Beatmap.RulesetID == 0 && criteria.Ruleset.ID > 0 && criteria.AllowConvertedBeatmaps;
|
||||
bool match =
|
||||
criteria.Ruleset == null ||
|
||||
Beatmap.RulesetID == criteria.Ruleset.ID ||
|
||||
(Beatmap.RulesetID == 0 && criteria.Ruleset.ID > 0 && criteria.AllowConvertedBeatmaps);
|
||||
|
||||
match &= !criteria.StarDifficulty.HasFilter || criteria.StarDifficulty.IsInRange(Beatmap.StarDifficulty);
|
||||
match &= !criteria.ApproachRate.HasFilter || criteria.ApproachRate.IsInRange(Beatmap.BaseDifficulty.ApproachRate);
|
||||
match &= !criteria.DrainRate.HasFilter || criteria.DrainRate.IsInRange(Beatmap.BaseDifficulty.DrainRate);
|
||||
match &= !criteria.CircleSize.HasFilter || criteria.CircleSize.IsInRange(Beatmap.BaseDifficulty.CircleSize);
|
||||
match &= !criteria.Length.HasFilter || criteria.Length.IsInRange(Beatmap.Length);
|
||||
match &= !criteria.BPM.HasFilter || criteria.BPM.IsInRange(Beatmap.BPM);
|
||||
|
||||
match &= !criteria.BeatDivisor.HasFilter || criteria.BeatDivisor.IsInRange(Beatmap.BeatDivisor);
|
||||
match &= !criteria.OnlineStatus.HasFilter || criteria.OnlineStatus.IsInRange(Beatmap.Status);
|
||||
|
||||
match &= !criteria.Creator.HasFilter || criteria.Creator.Matches(Beatmap.Metadata.AuthorString);
|
||||
match &= !criteria.Artist.HasFilter || criteria.Artist.Matches(Beatmap.Metadata.Artist) ||
|
||||
criteria.Artist.Matches(Beatmap.Metadata.ArtistUnicode);
|
||||
|
||||
match &= Beatmap.StarDifficulty >= criteria.DisplayStarsMinimum && Beatmap.StarDifficulty <= criteria.DisplayStarsMaximum;
|
||||
|
||||
if (!string.IsNullOrEmpty(criteria.SearchText))
|
||||
match &=
|
||||
Beatmap.Metadata.SearchableTerms.Any(term => term.IndexOf(criteria.SearchText, StringComparison.InvariantCultureIgnoreCase) >= 0) ||
|
||||
Beatmap.Version.IndexOf(criteria.SearchText, StringComparison.InvariantCultureIgnoreCase) >= 0;
|
||||
if (match)
|
||||
{
|
||||
var terms = new List<string>();
|
||||
|
||||
terms.AddRange(Beatmap.Metadata.SearchableTerms);
|
||||
terms.Add(Beatmap.Version);
|
||||
|
||||
foreach (var criteriaTerm in criteria.SearchTerms)
|
||||
match &= terms.Any(term => term.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0);
|
||||
}
|
||||
|
||||
Filtered.Value = !match;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
// 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;
|
||||
using System.Collections.Generic;
|
||||
@ -37,20 +37,49 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
{
|
||||
default:
|
||||
case SortMode.Artist:
|
||||
return string.Compare(BeatmapSet.Metadata.Artist, otherSet.BeatmapSet.Metadata.Artist, StringComparison.InvariantCultureIgnoreCase);
|
||||
return string.Compare(BeatmapSet.Metadata.Artist, otherSet.BeatmapSet.Metadata.Artist, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
case SortMode.Title:
|
||||
return string.Compare(BeatmapSet.Metadata.Title, otherSet.BeatmapSet.Metadata.Title, StringComparison.InvariantCultureIgnoreCase);
|
||||
return string.Compare(BeatmapSet.Metadata.Title, otherSet.BeatmapSet.Metadata.Title, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
case SortMode.Author:
|
||||
return string.Compare(BeatmapSet.Metadata.Author.Username, otherSet.BeatmapSet.Metadata.Author.Username, StringComparison.InvariantCultureIgnoreCase);
|
||||
return string.Compare(BeatmapSet.Metadata.Author.Username, otherSet.BeatmapSet.Metadata.Author.Username, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
case SortMode.DateAdded:
|
||||
return otherSet.BeatmapSet.DateAdded.CompareTo(BeatmapSet.DateAdded);
|
||||
|
||||
case SortMode.BPM:
|
||||
return compareUsingAggregateMax(otherSet, b => b.BPM);
|
||||
|
||||
case SortMode.Length:
|
||||
return compareUsingAggregateMax(otherSet, b => b.Length);
|
||||
|
||||
case SortMode.Difficulty:
|
||||
return BeatmapSet.MaxStarDifficulty.CompareTo(otherSet.BeatmapSet.MaxStarDifficulty);
|
||||
return compareUsingAggregateMax(otherSet, b => b.StarDifficulty);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// All beatmaps which are not filtered and valid for display.
|
||||
/// </summary>
|
||||
protected IEnumerable<BeatmapInfo> ValidBeatmaps => Beatmaps.Where(b => !b.Filtered.Value).Select(b => b.Beatmap);
|
||||
|
||||
private int compareUsingAggregateMax(CarouselBeatmapSet other, Func<BeatmapInfo, double> func)
|
||||
{
|
||||
var ourBeatmaps = ValidBeatmaps.Any();
|
||||
var otherBeatmaps = other.ValidBeatmaps.Any();
|
||||
|
||||
if (!ourBeatmaps && !otherBeatmaps) return 0;
|
||||
if (!ourBeatmaps) return -1;
|
||||
if (!otherBeatmaps) return 1;
|
||||
|
||||
return ValidBeatmaps.Max(func).CompareTo(other.ValidBeatmaps.Max(func));
|
||||
}
|
||||
|
||||
public override void Filter(FilterCriteria criteria)
|
||||
{
|
||||
base.Filter(criteria);
|
||||
Filtered.Value = InternalChildren.All(i => i.Filtered);
|
||||
Filtered.Value = InternalChildren.All(i => i.Filtered.Value);
|
||||
}
|
||||
|
||||
public override string ToString() => BeatmapSet.ToString();
|
||||
|
@ -1,7 +1,8 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace osu.Game.Screens.Select.Carousel
|
||||
{
|
||||
@ -49,7 +50,7 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
|
||||
public virtual void AddChild(CarouselItem i)
|
||||
{
|
||||
i.State.ValueChanged += v => ChildItemStateChanged(i, v);
|
||||
i.State.ValueChanged += state => ChildItemStateChanged(i, state.NewValue);
|
||||
i.ChildID = ++currentChildID;
|
||||
InternalChildren.Add(i);
|
||||
}
|
||||
@ -58,18 +59,19 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
{
|
||||
if (items != null) InternalChildren = items;
|
||||
|
||||
State.ValueChanged += v =>
|
||||
State.ValueChanged += state =>
|
||||
{
|
||||
switch (v)
|
||||
switch (state.NewValue)
|
||||
{
|
||||
case CarouselItemState.Collapsed:
|
||||
case CarouselItemState.NotSelected:
|
||||
InternalChildren.ForEach(c => c.State.Value = CarouselItemState.Collapsed);
|
||||
break;
|
||||
|
||||
case CarouselItemState.Selected:
|
||||
InternalChildren.ForEach(c =>
|
||||
{
|
||||
if (c.State == CarouselItemState.Collapsed) c.State.Value = CarouselItemState.NotSelected;
|
||||
if (c.State.Value == CarouselItemState.Collapsed) c.State.Value = CarouselItemState.NotSelected;
|
||||
});
|
||||
break;
|
||||
}
|
||||
@ -80,12 +82,10 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
{
|
||||
base.Filter(criteria);
|
||||
|
||||
var children = new List<CarouselItem>(InternalChildren);
|
||||
|
||||
children.Sort((x, y) => x.CompareTo(criteria, y));
|
||||
children.ForEach(c => c.Filter(criteria));
|
||||
|
||||
InternalChildren = children;
|
||||
InternalChildren.ForEach(c => c.Filter(criteria));
|
||||
// IEnumerable<T>.OrderBy() is used instead of List<T>.Sort() to ensure sorting stability
|
||||
var criteriaComparer = Comparer<CarouselItem>.Create((x, y) => x.CompareTo(criteria, y));
|
||||
InternalChildren = InternalChildren.OrderBy(c => c, criteriaComparer).ToList();
|
||||
}
|
||||
|
||||
protected virtual void ChildItemStateChanged(CarouselItem item, CarouselItemState value)
|
||||
@ -96,6 +96,7 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
foreach (var b in InternalChildren)
|
||||
{
|
||||
if (item == b) continue;
|
||||
|
||||
b.State.Value = CarouselItemState.NotSelected;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
// 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;
|
||||
using System.Linq;
|
||||
@ -13,9 +13,9 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
{
|
||||
public CarouselGroupEagerSelect()
|
||||
{
|
||||
State.ValueChanged += v =>
|
||||
State.ValueChanged += state =>
|
||||
{
|
||||
if (v == CarouselItemState.Selected)
|
||||
if (state.NewValue == CarouselItemState.Selected)
|
||||
attemptSelection();
|
||||
};
|
||||
}
|
||||
@ -69,6 +69,7 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
case CarouselItemState.Selected:
|
||||
updateSelected(item);
|
||||
break;
|
||||
|
||||
case CarouselItemState.NotSelected:
|
||||
case CarouselItemState.Collapsed:
|
||||
attemptSelection();
|
||||
@ -81,10 +82,10 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
if (filteringChildren) return;
|
||||
|
||||
// we only perform eager selection if we are a currently selected group.
|
||||
if (State != CarouselItemState.Selected) return;
|
||||
if (State.Value != CarouselItemState.Selected) return;
|
||||
|
||||
// we only perform eager selection if none of our children are in a selected state already.
|
||||
if (Children.Any(i => i.State == CarouselItemState.Selected)) return;
|
||||
if (Children.Any(i => i.State.Value == CarouselItemState.Selected)) return;
|
||||
|
||||
PerformSelection();
|
||||
}
|
||||
@ -92,8 +93,8 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
protected virtual void PerformSelection()
|
||||
{
|
||||
CarouselItem nextToSelect =
|
||||
Children.Skip(lastSelectedIndex).FirstOrDefault(i => !i.Filtered) ??
|
||||
Children.Reverse().Skip(InternalChildren.Count - lastSelectedIndex).FirstOrDefault(i => !i.Filtered);
|
||||
Children.Skip(lastSelectedIndex).FirstOrDefault(i => !i.Filtered.Value) ??
|
||||
Children.Reverse().Skip(InternalChildren.Count - lastSelectedIndex).FirstOrDefault(i => !i.Filtered.Value);
|
||||
|
||||
if (nextToSelect != null)
|
||||
nextToSelect.State.Value = CarouselItemState.Selected;
|
||||
|
@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Bindables;
|
||||
|
||||
namespace osu.Game.Screens.Select.Carousel
|
||||
{
|
||||
@ -16,7 +16,7 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
/// <summary>
|
||||
/// This item is not in a hidden state.
|
||||
/// </summary>
|
||||
public bool Visible => State.Value != CarouselItemState.Collapsed && !Filtered;
|
||||
public bool Visible => State.Value != CarouselItemState.Collapsed && !Filtered.Value;
|
||||
|
||||
public virtual List<DrawableCarouselItem> Drawables
|
||||
{
|
||||
@ -31,15 +31,13 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
}
|
||||
}
|
||||
|
||||
private int creationOrder;
|
||||
|
||||
protected CarouselItem()
|
||||
{
|
||||
DrawableRepresentation = new Lazy<DrawableCarouselItem>(CreateDrawableRepresentation);
|
||||
|
||||
Filtered.ValueChanged += v =>
|
||||
Filtered.ValueChanged += filtered =>
|
||||
{
|
||||
if (v && State == CarouselItemState.Selected)
|
||||
if (filtered.NewValue && State.Value == CarouselItemState.Selected)
|
||||
State.Value = CarouselItemState.NotSelected;
|
||||
};
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
@ -38,7 +39,8 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
|
||||
private BeatmapSetOverlay beatmapOverlay;
|
||||
|
||||
public DrawableCarouselBeatmap(CarouselBeatmap panel) : base(panel)
|
||||
public DrawableCarouselBeatmap(CarouselBeatmap panel)
|
||||
: base(panel)
|
||||
{
|
||||
beatmap = panel.Beatmap;
|
||||
Height *= 0.60f;
|
||||
@ -80,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),
|
||||
},
|
||||
@ -100,25 +102,21 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Font = @"Exo2.0-Medium",
|
||||
Text = beatmap.Version,
|
||||
TextSize = 20,
|
||||
Font = OsuFont.GetFont(size: 20),
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Font = @"Exo2.0-Medium",
|
||||
Text = "mapped by",
|
||||
TextSize = 16,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Font = @"Exo2.0-MediumItalic",
|
||||
Text = $"{(beatmap.Metadata ?? beatmap.BeatmapSet.Metadata).Author.Username}",
|
||||
TextSize = 16,
|
||||
Font = OsuFont.GetFont(italics: true),
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft
|
||||
},
|
||||
@ -157,7 +155,7 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
if (Item.State == CarouselItemState.Selected)
|
||||
if (Item.State.Value == CarouselItemState.Selected)
|
||||
startRequested?.Invoke(beatmap);
|
||||
|
||||
return base.OnClick(e);
|
||||
@ -171,15 +169,22 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
base.ApplyState();
|
||||
}
|
||||
|
||||
public MenuItem[] ContextMenuItems => new MenuItem[]
|
||||
public MenuItem[] ContextMenuItems
|
||||
{
|
||||
new OsuMenuItem("Play", MenuItemType.Highlighted, () => startRequested?.Invoke(beatmap)),
|
||||
new OsuMenuItem("Edit", MenuItemType.Standard, () => editRequested?.Invoke(beatmap)),
|
||||
new OsuMenuItem("Hide", MenuItemType.Destructive, () => hideRequested?.Invoke(beatmap)),
|
||||
new OsuMenuItem("Details", MenuItemType.Standard, () =>
|
||||
get
|
||||
{
|
||||
if (beatmap.OnlineBeatmapID.HasValue) beatmapOverlay?.FetchAndShowBeatmap(beatmap.OnlineBeatmapID.Value);
|
||||
}),
|
||||
};
|
||||
List<MenuItem> items = new List<MenuItem>
|
||||
{
|
||||
new OsuMenuItem("Play", MenuItemType.Highlighted, () => startRequested?.Invoke(beatmap)),
|
||||
new OsuMenuItem("Edit", MenuItemType.Standard, () => editRequested?.Invoke(beatmap)),
|
||||
new OsuMenuItem("Hide", MenuItemType.Destructive, () => hideRequested?.Invoke(beatmap)),
|
||||
};
|
||||
|
||||
if (beatmap.OnlineBeatmapID.HasValue)
|
||||
items.Add(new OsuMenuItem("Details", MenuItemType.Standard, () => beatmapOverlay?.FetchAndShowBeatmap(beatmap.OnlineBeatmapID.Value)));
|
||||
|
||||
return items.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@ -15,9 +15,11 @@ using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
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;
|
||||
|
||||
@ -48,10 +50,15 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new DelayedLoadUnloadWrapper(() =>
|
||||
new PanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault()))
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
OnLoadComplete = d => d.FadeInFromZero(1000, Easing.OutQuint),
|
||||
var background = new PanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault()))
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
};
|
||||
|
||||
background.OnLoadComplete += d => d.FadeInFromZero(1000, Easing.OutQuint);
|
||||
|
||||
return background;
|
||||
}, 300, 5000
|
||||
),
|
||||
new FillFlowContainer
|
||||
@ -63,16 +70,14 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Font = @"Exo2.0-BoldItalic",
|
||||
Text = new LocalisedString((beatmapSet.Metadata.TitleUnicode, beatmapSet.Metadata.Title)),
|
||||
TextSize = 22,
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 22, italics: true),
|
||||
Shadow = true,
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Font = @"Exo2.0-SemiBoldItalic",
|
||||
Text = new LocalisedString((beatmapSet.Metadata.ArtistUnicode, beatmapSet.Metadata.Artist)),
|
||||
TextSize = 17,
|
||||
Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 17, italics: true),
|
||||
Shadow = true,
|
||||
},
|
||||
new FillFlowContainer
|
||||
@ -91,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(),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -103,13 +109,24 @@ 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
|
||||
{
|
||||
List<MenuItem> items = new List<MenuItem>();
|
||||
|
||||
if (Item.State == CarouselItemState.NotSelected)
|
||||
if (Item.State.Value == CarouselItemState.NotSelected)
|
||||
items.Add(new OsuMenuItem("Expand", MenuItemType.Highlighted, () => Item.State.Value = CarouselItemState.Selected));
|
||||
|
||||
if (beatmapSet.OnlineBeatmapSetID != null)
|
||||
@ -129,6 +146,7 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
public PanelBackground(WorkingBeatmap working)
|
||||
{
|
||||
CacheDrawnFrameBuffer = true;
|
||||
RedrawOnScale = false;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
@ -139,10 +157,10 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
Origin = Anchor.Centre,
|
||||
FillMode = FillMode.Fill,
|
||||
},
|
||||
new FillFlowContainer
|
||||
// Todo: This should be a fill flow, but has invalidation issues (see https://github.com/ppy/osu-framework/issues/223)
|
||||
new Container
|
||||
{
|
||||
Depth = -1,
|
||||
Direction = FillDirection.Horizontal,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
// This makes the gradient not be perfectly horizontal, but diagonal at a ~40° angle
|
||||
Shear = new Vector2(0.8f, 0),
|
||||
@ -153,6 +171,7 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RelativePositionAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
Width = 0.4f,
|
||||
},
|
||||
@ -160,20 +179,26 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RelativePositionAxes = Axes.Both,
|
||||
Colour = ColourInfo.GradientHorizontal(Color4.Black, new Color4(0f, 0f, 0f, 0.9f)),
|
||||
Width = 0.05f,
|
||||
X = 0.4f,
|
||||
},
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RelativePositionAxes = Axes.Both,
|
||||
Colour = ColourInfo.GradientHorizontal(new Color4(0f, 0f, 0f, 0.9f), new Color4(0f, 0f, 0f, 0.1f)),
|
||||
Width = 0.2f,
|
||||
X = 0.45f,
|
||||
},
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RelativePositionAxes = Axes.Both,
|
||||
Colour = ColourInfo.GradientHorizontal(new Color4(0f, 0f, 0f, 0.1f), new Color4(0, 0, 0, 0)),
|
||||
Width = 0.05f,
|
||||
X = 0.65f,
|
||||
},
|
||||
}
|
||||
},
|
||||
@ -189,9 +214,31 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
: base(item.Beatmap)
|
||||
{
|
||||
filtered.BindTo(item.Filtered);
|
||||
filtered.ValueChanged += v => Schedule(() => this.FadeTo(v ? 0.1f : 1, 100));
|
||||
filtered.ValueChanged += isFiltered => Schedule(() => this.FadeTo(isFiltered.NewValue ? 0.1f : 1, 100));
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
// 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 osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
@ -7,9 +7,10 @@ using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Graphics;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
@ -63,12 +64,12 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
Blending = BlendingMode.Additive,
|
||||
Blending = BlendingParameters.Additive,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
sampleHover = audio.Sample.Get($@"SongSelect/song-ping-variation-{RNG.Next(1, 5)}");
|
||||
sampleHover = audio.Samples.Get($@"SongSelect/song-ping-variation-{RNG.Next(1, 5)}");
|
||||
hoverLayer.Colour = colours.Blue.Opacity(0.1f);
|
||||
}
|
||||
|
||||
@ -106,6 +107,7 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
case CarouselItemState.NotSelected:
|
||||
Deselected();
|
||||
break;
|
||||
|
||||
case CarouselItemState.Selected:
|
||||
Selected();
|
||||
break;
|
||||
|
Reference in New Issue
Block a user