mirror of
https://github.com/ppy/osu.git
synced 2026-05-13 19:54:15 +08:00
Compare commits
2 Commits
d0afc54e57
...
f4c96ecb54
@@ -99,8 +99,35 @@ namespace osu.Game.Tests.Visual.Online
|
||||
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
},
|
||||
TopTags =
|
||||
[
|
||||
new APIBeatmapTag { TagId = 4, VoteCount = 1 },
|
||||
new APIBeatmapTag { TagId = 2, VoteCount = 1 },
|
||||
new APIBeatmapTag { TagId = 23, VoteCount = 5 },
|
||||
],
|
||||
},
|
||||
},
|
||||
RelatedTags =
|
||||
[
|
||||
new APITag
|
||||
{
|
||||
Id = 2,
|
||||
Name = "song representation/simple",
|
||||
Description = "Accessible and straightforward map design."
|
||||
},
|
||||
new APITag
|
||||
{
|
||||
Id = 4,
|
||||
Name = "style/clean",
|
||||
Description = "Visually uncluttered and organised patterns, often involving few overlaps and equal visual spacing between objects."
|
||||
},
|
||||
new APITag
|
||||
{
|
||||
Id = 23,
|
||||
Name = "aim/aim control",
|
||||
Description = "Patterns with velocity or direction changes which strongly go against a player's natural movement pattern."
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -128,6 +128,9 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
[JsonProperty(@"converts")]
|
||||
public APIBeatmap[]? Converts { get; set; }
|
||||
|
||||
[JsonProperty(@"related_tags")]
|
||||
public APITag[]? RelatedTags { get; set; }
|
||||
|
||||
private BeatmapMetadata metadata => new BeatmapMetadata
|
||||
{
|
||||
Title = Title,
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// 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.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
@@ -9,6 +11,7 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays.BeatmapListing;
|
||||
@@ -17,26 +20,22 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
{
|
||||
public partial class Info : Container
|
||||
{
|
||||
private const float metadata_width = 175;
|
||||
private const float metadata_width = 185;
|
||||
private const float spacing = 20;
|
||||
private const float base_height = 220;
|
||||
private const float base_height = 300;
|
||||
|
||||
private readonly Box successRateBackground;
|
||||
private readonly Box background;
|
||||
private readonly SuccessRate successRate;
|
||||
private readonly MetadataSection<string[]?> userTags;
|
||||
|
||||
public readonly Bindable<APIBeatmapSet> BeatmapSet = new Bindable<APIBeatmapSet>();
|
||||
|
||||
public APIBeatmap? BeatmapInfo
|
||||
{
|
||||
get => successRate.Beatmap;
|
||||
set => successRate.Beatmap = value;
|
||||
}
|
||||
public readonly Bindable<APIBeatmap> Beatmap = new Bindable<APIBeatmap>();
|
||||
|
||||
public Info()
|
||||
{
|
||||
SuccessRate successRate;
|
||||
MetadataSectionNominators nominators;
|
||||
MetadataSection source, tags;
|
||||
MetadataSection source, mapperTags;
|
||||
MetadataSectionGenre genre;
|
||||
MetadataSectionLanguage language;
|
||||
OsuSpriteText notRankedPlaceholder;
|
||||
@@ -66,27 +65,30 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
Child = new MetadataSectionDescription(),
|
||||
},
|
||||
},
|
||||
new Container
|
||||
new OsuScrollContainer
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = metadata_width,
|
||||
Padding = new MarginPadding { Horizontal = 10 },
|
||||
Padding = new MarginPadding { Left = 10 },
|
||||
Margin = new MarginPadding { Right = BeatmapSetOverlay.RIGHT_WIDTH + spacing },
|
||||
Masking = true,
|
||||
ScrollbarOverlapsContent = false,
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Full,
|
||||
Padding = new MarginPadding { Right = 5 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
nominators = new MetadataSectionNominators(),
|
||||
source = new MetadataSectionSource(),
|
||||
genre = new MetadataSectionGenre { Width = 0.5f },
|
||||
language = new MetadataSectionLanguage { Width = 0.5f },
|
||||
tags = new MetadataSectionTags(),
|
||||
userTags = new MetadataSectionUserTags(),
|
||||
mapperTags = new MetadataSectionMapperTags(),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -121,18 +123,42 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
},
|
||||
};
|
||||
|
||||
BeatmapSet.ValueChanged += b =>
|
||||
BeatmapSet.BindValueChanged(b =>
|
||||
{
|
||||
nominators.Metadata = (b.NewValue?.CurrentNominations ?? Array.Empty<BeatmapSetOnlineNomination>(), b.NewValue?.RelatedUsers ?? Array.Empty<APIUser>());
|
||||
source.Metadata = b.NewValue?.Source ?? string.Empty;
|
||||
tags.Metadata = b.NewValue?.Tags ?? string.Empty;
|
||||
mapperTags.Metadata = b.NewValue?.Tags ?? string.Empty;
|
||||
updateUserTags();
|
||||
genre.Metadata = b.NewValue?.Genre ?? new BeatmapSetOnlineGenre { Id = (int)SearchGenre.Unspecified };
|
||||
language.Metadata = b.NewValue?.Language ?? new BeatmapSetOnlineLanguage { Id = (int)SearchLanguage.Unspecified };
|
||||
bool setHasLeaderboard = b.NewValue?.Status > 0;
|
||||
successRate.Alpha = setHasLeaderboard ? 1 : 0;
|
||||
notRankedPlaceholder.Alpha = setHasLeaderboard ? 0 : 1;
|
||||
Height = setHasLeaderboard ? 270 : base_height;
|
||||
};
|
||||
});
|
||||
Beatmap.BindValueChanged(b =>
|
||||
{
|
||||
successRate.Beatmap = b.NewValue;
|
||||
updateUserTags();
|
||||
});
|
||||
}
|
||||
|
||||
private void updateUserTags()
|
||||
{
|
||||
if (Beatmap.Value?.TopTags == null || Beatmap.Value.TopTags.Length == 0 || BeatmapSet.Value?.RelatedTags == null)
|
||||
{
|
||||
userTags.Metadata = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var tagsById = BeatmapSet.Value.RelatedTags.ToDictionary(t => t.Id);
|
||||
userTags.Metadata = Beatmap.Value.TopTags
|
||||
.Select(t => (topTag: t, relatedTag: tagsById.GetValueOrDefault(t.TagId)))
|
||||
.Where(t => t.relatedTag != null)
|
||||
// see https://github.com/ppy/osu-web/blob/bb3bd2e7c6f84f26066df5ea20a81c77ec9bb60a/resources/js/beatmapsets-show/controller.ts#L103-L106 for sort criteria
|
||||
.OrderByDescending(t => t.topTag.VoteCount)
|
||||
.ThenBy(t => t.relatedTag!.Name)
|
||||
.Select(t => t.relatedTag!.Name)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
||||
+3
-3
@@ -7,10 +7,10 @@ using osu.Game.Online.Chat;
|
||||
|
||||
namespace osu.Game.Overlays.BeatmapSet
|
||||
{
|
||||
public partial class MetadataSectionTags : MetadataSection
|
||||
public partial class MetadataSectionMapperTags : MetadataSection
|
||||
{
|
||||
public MetadataSectionTags(Action<string>? searchAction = null)
|
||||
: base(MetadataType.Tags, searchAction)
|
||||
public MetadataSectionMapperTags(Action<string>? searchAction = null)
|
||||
: base(MetadataType.MapperTags, searchAction)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
// 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 osu.Game.Graphics.Containers;
|
||||
using osu.Game.Online.Chat;
|
||||
|
||||
namespace osu.Game.Overlays.BeatmapSet
|
||||
{
|
||||
public partial class MetadataSectionUserTags : MetadataSection<string[]?>
|
||||
{
|
||||
private readonly Action<string>? searchAction;
|
||||
|
||||
public MetadataSectionUserTags(Action<string>? searchAction = null)
|
||||
: base(MetadataType.UserTags, null)
|
||||
{
|
||||
this.searchAction = searchAction;
|
||||
}
|
||||
|
||||
protected override void AddMetadata(string[]? tags, LinkFlowContainer loaded)
|
||||
{
|
||||
if (tags == null)
|
||||
return;
|
||||
|
||||
for (int i = 0; i <= tags.Length - 1; i++)
|
||||
{
|
||||
string tag = tags[i];
|
||||
|
||||
if (searchAction != null)
|
||||
loaded.AddLink(tag, () => searchAction(tag));
|
||||
else
|
||||
loaded.AddLink(tag, LinkAction.SearchBeatmapSet, $@"tag=""""{tag}""""");
|
||||
|
||||
if (i != tags.Length - 1)
|
||||
loaded.AddText(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// 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;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
|
||||
@@ -8,8 +9,11 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
{
|
||||
public enum MetadataType
|
||||
{
|
||||
[LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowInfoTags))]
|
||||
Tags,
|
||||
[Description("User Tags")] // TODO: use translated string after osu-resources update
|
||||
UserTags,
|
||||
|
||||
[Description("Mapper Tags")] // TODO: use translated string after osu-resources update
|
||||
MapperTags,
|
||||
|
||||
[LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowInfoSource))]
|
||||
Source,
|
||||
|
||||
@@ -47,7 +47,10 @@ namespace osu.Game.Overlays
|
||||
Spacing = new Vector2(0, 20),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
info = new Info(),
|
||||
info = new Info
|
||||
{
|
||||
Beatmap = { BindTarget = Header.HeaderContent.Picker.Beatmap }
|
||||
},
|
||||
new ScoresContainer
|
||||
{
|
||||
Beatmap = { BindTarget = Header.HeaderContent.Picker.Beatmap }
|
||||
@@ -60,11 +63,7 @@ namespace osu.Game.Overlays
|
||||
info.BeatmapSet.BindTo(beatmapSet);
|
||||
comments.BeatmapSet.BindTo(beatmapSet);
|
||||
|
||||
Header.HeaderContent.Picker.Beatmap.ValueChanged += b =>
|
||||
{
|
||||
info.BeatmapInfo = b.NewValue;
|
||||
ScrollFlow.ScrollToStart();
|
||||
};
|
||||
Header.HeaderContent.Picker.Beatmap.ValueChanged += b => ScrollFlow.ScrollToStart();
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
||||
@@ -133,7 +133,7 @@ namespace osu.Game.Screens.Select
|
||||
{
|
||||
description = new MetadataSectionDescription(query => songSelect?.Search(query)),
|
||||
source = new MetadataSectionSource(query => songSelect?.Search(query)),
|
||||
tags = new MetadataSectionTags(query => songSelect?.Search(query)),
|
||||
tags = new MetadataSectionMapperTags(query => songSelect?.Search(query)),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user