mirror of
https://github.com/SK-la/Ez2Lazer.git
synced 2026-03-13 11:20:28 +00:00
330 lines
12 KiB
C#
330 lines
12 KiB
C#
// 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.Diagnostics;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using osu.Framework.Allocation;
|
|
using osu.Framework.Bindables;
|
|
using osu.Framework.Extensions.LocalisationExtensions;
|
|
using osu.Framework.Graphics;
|
|
using osu.Framework.Graphics.Containers;
|
|
using osu.Framework.Graphics.Shapes;
|
|
using osu.Framework.Graphics.Sprites;
|
|
using osu.Framework.Graphics.UserInterface;
|
|
using osu.Framework.Localisation;
|
|
using osu.Framework.Threading;
|
|
using osu.Game.Beatmaps;
|
|
using osu.Game.Beatmaps.Drawables;
|
|
using osu.Game.Collections;
|
|
using osu.Game.Database;
|
|
using osu.Game.Graphics;
|
|
using osu.Game.Graphics.Carousel;
|
|
using osu.Game.Graphics.Sprites;
|
|
using osu.Game.Graphics.UserInterface;
|
|
using osu.Game.Localisation;
|
|
using osu.Game.Online.API;
|
|
using osu.Game.Overlays;
|
|
using osu.Game.Rulesets;
|
|
using osuTK;
|
|
using osuTK.Graphics;
|
|
using WebCommonStrings = osu.Game.Resources.Localisation.Web.CommonStrings;
|
|
|
|
namespace osu.Game.Screens.SelectV2
|
|
{
|
|
public partial class PanelBeatmapSet : Panel
|
|
{
|
|
public const float HEIGHT = CarouselItem.DEFAULT_HEIGHT * 1.6f;
|
|
|
|
public Bindable<HashSet<BeatmapInfo>?> VisibleBeatmaps { get; } = new Bindable<HashSet<BeatmapInfo>?>();
|
|
|
|
private Box chevronBackground = null!;
|
|
private PanelSetBackground setBackground = null!;
|
|
private ScheduledDelegate? scheduledBackgroundRetrieval;
|
|
|
|
private OsuSpriteText titleText = null!;
|
|
private OsuSpriteText artistText = null!;
|
|
private Drawable chevronIcon = null!;
|
|
private PanelUpdateBeatmapButton updateButton = null!;
|
|
private BeatmapSetOnlineStatusPill statusPill = null!;
|
|
private SpreadDisplay spreadDisplay = null!;
|
|
|
|
[Resolved]
|
|
private OverlayColourProvider colourProvider { get; set; } = null!;
|
|
|
|
[Resolved]
|
|
private BeatmapSetOverlay? beatmapOverlay { get; set; }
|
|
|
|
[Resolved]
|
|
private BeatmapManager beatmaps { get; set; } = null!;
|
|
|
|
[Resolved]
|
|
private ISongSelect? songSelect { get; set; }
|
|
|
|
[Resolved]
|
|
private OsuGame? game { get; set; }
|
|
|
|
[Resolved]
|
|
private IAPIProvider api { get; set; } = null!;
|
|
|
|
[Resolved]
|
|
private IBindable<RulesetInfo> ruleset { get; set; } = null!;
|
|
|
|
private GroupedBeatmapSet groupedBeatmapSet
|
|
{
|
|
get
|
|
{
|
|
Debug.Assert(Item != null);
|
|
return (GroupedBeatmapSet)Item!.Model;
|
|
}
|
|
}
|
|
|
|
public PanelBeatmapSet()
|
|
{
|
|
PanelXOffset = 20f;
|
|
}
|
|
|
|
[BackgroundDependencyLoader]
|
|
private void load()
|
|
{
|
|
Height = HEIGHT;
|
|
|
|
Icon = chevronIcon = new Container
|
|
{
|
|
Size = new Vector2(0, 22),
|
|
Child = new SpriteIcon
|
|
{
|
|
Anchor = Anchor.Centre,
|
|
Origin = Anchor.Centre,
|
|
Icon = FontAwesome.Solid.ChevronRight,
|
|
Size = new Vector2(8),
|
|
X = 1f,
|
|
Colour = colourProvider.Background5,
|
|
},
|
|
};
|
|
|
|
Background = chevronBackground = new Box
|
|
{
|
|
RelativeSizeAxes = Axes.Both,
|
|
Colour = Color4.White,
|
|
Alpha = 0f,
|
|
};
|
|
|
|
Content.Children = new Drawable[]
|
|
{
|
|
setBackground = new PanelSetBackground(),
|
|
new FillFlowContainer
|
|
{
|
|
AutoSizeAxes = Axes.Both,
|
|
Direction = FillDirection.Vertical,
|
|
Anchor = Anchor.CentreLeft,
|
|
Origin = Anchor.CentreLeft,
|
|
Padding = new MarginPadding { Top = 7.5f, Left = 15, Bottom = 13 },
|
|
Children = new Drawable[]
|
|
{
|
|
titleText = new OsuSpriteText
|
|
{
|
|
Font = OsuFont.Style.Heading1.With(typeface: Typeface.TorusAlternate),
|
|
},
|
|
artistText = new OsuSpriteText
|
|
{
|
|
Font = OsuFont.Style.Body.With(weight: FontWeight.SemiBold),
|
|
},
|
|
new FillFlowContainer
|
|
{
|
|
Direction = FillDirection.Horizontal,
|
|
AutoSizeAxes = Axes.Both,
|
|
Margin = new MarginPadding { Top = 4f },
|
|
Children = new Drawable[]
|
|
{
|
|
statusPill = new BeatmapSetOnlineStatusPill
|
|
{
|
|
Origin = Anchor.CentreLeft,
|
|
Anchor = Anchor.CentreLeft,
|
|
TextSize = OsuFont.Style.Caption2.Size,
|
|
Margin = new MarginPadding { Right = 5f },
|
|
Animated = false,
|
|
},
|
|
updateButton = new PanelUpdateBeatmapButton
|
|
{
|
|
Anchor = Anchor.CentreLeft,
|
|
Origin = Anchor.CentreLeft,
|
|
Margin = new MarginPadding { Right = 5f, Top = -2f },
|
|
},
|
|
spreadDisplay = new SpreadDisplay
|
|
{
|
|
Origin = Anchor.CentreLeft,
|
|
Anchor = Anchor.CentreLeft,
|
|
Expanded = { BindTarget = Expanded },
|
|
VisibleBeatmaps = { BindTarget = VisibleBeatmaps },
|
|
},
|
|
},
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
protected override void LoadComplete()
|
|
{
|
|
base.LoadComplete();
|
|
|
|
Expanded.BindValueChanged(_ => onExpanded(), true);
|
|
KeyboardSelected.BindValueChanged(k => KeyboardSelected.Value = k.NewValue, true);
|
|
}
|
|
|
|
private void onExpanded()
|
|
{
|
|
if (Expanded.Value)
|
|
{
|
|
chevronBackground.FadeIn(DURATION / 2, Easing.OutQuint);
|
|
chevronIcon.ResizeWidthTo(18, DURATION * 1.5f, Easing.OutElasticQuarter);
|
|
chevronIcon.FadeTo(1f, DURATION, Easing.OutQuint);
|
|
}
|
|
else
|
|
{
|
|
chevronBackground.FadeOut(DURATION, Easing.OutQuint);
|
|
chevronIcon.ResizeWidthTo(0f, DURATION, Easing.OutQuint);
|
|
chevronIcon.FadeTo(0f, DURATION, Easing.OutQuint);
|
|
}
|
|
}
|
|
|
|
protected override void PrepareForUse()
|
|
{
|
|
base.PrepareForUse();
|
|
|
|
var beatmapSet = groupedBeatmapSet.BeatmapSet;
|
|
|
|
// Choice of background image matches BSS implementation (always uses the lowest `beatmap_id` from the set).
|
|
scheduledBackgroundRetrieval = Scheduler.AddDelayed(s => setBackground.Beatmap = beatmaps.GetWorkingBeatmap(s.Beatmaps.MinBy(b => b.OnlineID)), beatmapSet, 50);
|
|
|
|
titleText.Text = new RomanisableString(beatmapSet.Metadata.TitleUnicode, beatmapSet.Metadata.Title);
|
|
artistText.Text = new RomanisableString(beatmapSet.Metadata.ArtistUnicode, beatmapSet.Metadata.Artist);
|
|
updateButton.BeatmapSet = beatmapSet;
|
|
statusPill.Status = beatmapSet.Status;
|
|
spreadDisplay.BeatmapSet.Value = beatmapSet;
|
|
}
|
|
|
|
protected override void FreeAfterUse()
|
|
{
|
|
base.FreeAfterUse();
|
|
|
|
scheduledBackgroundRetrieval?.Cancel();
|
|
scheduledBackgroundRetrieval = null;
|
|
setBackground.Beatmap = null;
|
|
updateButton.BeatmapSet = null;
|
|
spreadDisplay.BeatmapSet.Value = null;
|
|
}
|
|
|
|
[Resolved]
|
|
private RealmAccess realm { get; set; } = null!;
|
|
|
|
[Resolved]
|
|
private ManageCollectionsDialog? manageCollectionsDialog { get; set; }
|
|
|
|
public override MenuItem[] ContextMenuItems
|
|
{
|
|
get
|
|
{
|
|
if (Item == null)
|
|
return Array.Empty<MenuItem>();
|
|
|
|
var beatmapSet = groupedBeatmapSet.BeatmapSet;
|
|
|
|
List<MenuItem> items = new List<MenuItem>();
|
|
|
|
if (Expanded.Value)
|
|
{
|
|
if (songSelect is SoloSongSelect soloSongSelect)
|
|
{
|
|
// Assume the current set has one of its beatmaps selected since it is expanded.
|
|
items.Add(new OsuMenuItem(ButtonSystemStrings.Edit.ToSentence(), MenuItemType.Standard, () => soloSongSelect.Edit(soloSongSelect.Beatmap.Value.BeatmapInfo))
|
|
{
|
|
Icon = FontAwesome.Solid.PencilAlt
|
|
});
|
|
items.Add(new OsuMenuItemSpacer());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
items.Add(new OsuMenuItem(WebCommonStrings.ButtonsExpand.ToSentence(), MenuItemType.Highlighted, () => TriggerClick()));
|
|
items.Add(new OsuMenuItemSpacer());
|
|
}
|
|
|
|
if (beatmapSet.OnlineID > 0)
|
|
{
|
|
items.Add(new OsuMenuItem(CommonStrings.Details, MenuItemType.Standard, () => beatmapOverlay?.FetchAndShowBeatmapSet(beatmapSet.OnlineID)));
|
|
|
|
if (beatmapSet.GetOnlineURL(api, ruleset.Value) is string url)
|
|
items.Add(new OsuMenuItem(CommonStrings.CopyLink, MenuItemType.Standard, () => game?.CopyToClipboard(url)));
|
|
|
|
items.Add(new OsuMenuItemSpacer());
|
|
}
|
|
|
|
var collectionItems = realm.Realm.All<BeatmapCollection>()
|
|
.OrderBy(c => c.Name)
|
|
.AsEnumerable()
|
|
.Select(createCollectionMenuItem)
|
|
.ToList();
|
|
|
|
if (manageCollectionsDialog != null)
|
|
collectionItems.Add(new OsuMenuItem(CommonStrings.Manage, MenuItemType.Standard, manageCollectionsDialog.Show));
|
|
|
|
items.Add(new OsuMenuItem(CommonStrings.Collections) { Items = collectionItems });
|
|
|
|
if (beatmapSet.Beatmaps.Any(b => b.Hidden))
|
|
items.Add(new OsuMenuItem(SongSelectStrings.RestoreAllHidden, MenuItemType.Standard, () => songSelect?.RestoreAllHidden(beatmapSet)));
|
|
|
|
items.Add(new OsuMenuItem(CommonStrings.DeleteWithConfirmation, MenuItemType.Destructive, () => songSelect?.Delete(beatmapSet)));
|
|
return items.ToArray();
|
|
}
|
|
}
|
|
|
|
private MenuItem createCollectionMenuItem(BeatmapCollection collection)
|
|
{
|
|
var beatmapSet = groupedBeatmapSet.BeatmapSet;
|
|
|
|
TernaryState state;
|
|
|
|
int countExisting = beatmapSet.Beatmaps.Count(b => collection.BeatmapMD5Hashes.Contains(b.MD5Hash));
|
|
|
|
if (countExisting == beatmapSet.Beatmaps.Count)
|
|
state = TernaryState.True;
|
|
else if (countExisting > 0)
|
|
state = TernaryState.Indeterminate;
|
|
else
|
|
state = TernaryState.False;
|
|
|
|
var liveCollection = collection.ToLive(realm);
|
|
|
|
return new TernaryStateToggleMenuItem(collection.Name, MenuItemType.Standard, s =>
|
|
{
|
|
Task.Run(() => liveCollection.PerformWrite(c =>
|
|
{
|
|
foreach (var b in beatmapSet.Beatmaps)
|
|
{
|
|
switch (s)
|
|
{
|
|
case TernaryState.True:
|
|
if (c.BeatmapMD5Hashes.Contains(b.MD5Hash))
|
|
continue;
|
|
|
|
c.BeatmapMD5Hashes.Add(b.MD5Hash);
|
|
break;
|
|
|
|
case TernaryState.False:
|
|
c.BeatmapMD5Hashes.Remove(b.MD5Hash);
|
|
break;
|
|
}
|
|
}
|
|
}));
|
|
})
|
|
{
|
|
State = { Value = state }
|
|
};
|
|
}
|
|
}
|
|
}
|