private void load(AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores, CollectionManager collections, ManageCollectionsDialog manageCollectionsDialog, DifficultyRecommender recommender) { // initial value transfer is required for FilterControl (it uses our re-cached bindables in its async load for the initial filter). transferRulesetValue(); LoadComponentAsync(Carousel = new BeatmapCarousel { AllowSelection = false, // delay any selection until our bindables are ready to make a good choice. Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, RelativeSizeAxes = Axes.Both, BleedTop = FilterControl.HEIGHT, BleedBottom = Footer.HEIGHT, SelectionChanged = updateSelectedBeatmap, BeatmapSetsChanged = carouselBeatmapsLoaded, GetRecommendedBeatmap = s => recommender?.GetRecommendedBeatmap(s), }, c => carouselContainer.Child = c); AddRangeInternal(new Drawable[] { new ResetScrollContainer(() => Carousel.ScrollToSelected()) { RelativeSizeAxes = Axes.Y, Width = 250, }, new VerticalMaskingContainer { Children = new Drawable[] { new GridContainer // used for max width implementation { RelativeSizeAxes = Axes.Both, ColumnDimensions = new[] { new Dimension(), new Dimension(GridSizeMode.Relative, 0.5f, maxSize: 850), }, Content = new[] { new Drawable[] { new ParallaxContainer { ParallaxAmount = 0.005f, RelativeSizeAxes = Axes.Both, Child = new WedgeBackground { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Right = -150 }, }, }, carouselContainer = new Container { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = FilterControl.HEIGHT, Bottom = Footer.HEIGHT }, Child = new LoadingSpinner(true) { State = { Value = Visibility.Visible } } } }, } }, FilterControl = new FilterControl { RelativeSizeAxes = Axes.X, Height = FilterControl.HEIGHT, FilterChanged = ApplyFilterToCarousel, }, new GridContainer // used for max width implementation { RelativeSizeAxes = Axes.Both, ColumnDimensions = new[] { new Dimension(GridSizeMode.Relative, 0.5f, maxSize: 650), }, Content = new[] { new Drawable[] { new Container { Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, RelativeSizeAxes = Axes.Both, Children = new Drawable[] { beatmapInfoWedge = new BeatmapInfoWedge { Height = WEDGE_HEIGHT, RelativeSizeAxes = Axes.X, Margin = new MarginPadding { Top = left_area_padding, Right = left_area_padding, }, }, new Container { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Bottom = Footer.HEIGHT, Top = WEDGE_HEIGHT + left_area_padding, Left = left_area_padding, Right = left_area_padding * 2, }, Child = BeatmapDetails = CreateBeatmapDetailArea().With(d => { d.RelativeSizeAxes = Axes.Both; d.Padding = new MarginPadding { Top = 10, Right = 5 }; }) }, } }, }, } } } }, }); if (ShowFooter) { AddRangeInternal(new Drawable[] { new GridContainer // used for max height implementation { RelativeSizeAxes = Axes.Both, RowDimensions = new[] { new Dimension(), new Dimension(GridSizeMode.Relative, 1f, maxSize: ModSelectOverlay.HEIGHT + Footer.HEIGHT), }, Content = new[] { null, new Drawable[] { FooterPanels = new Container { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Bottom = Footer.HEIGHT }, Children = new Drawable[] { BeatmapOptions = new BeatmapOptionsOverlay(), ModSelect = CreateModSelectOverlay() } } } } }, Footer = new Footer() }); } if (Footer != null) { foreach (var(button, overlay) in CreateFooterButtons()) { Footer.AddButton(button, overlay); } BeatmapOptions.AddButton(@"Manage", @"collections", FontAwesome.Solid.Book, colours.Green, () => manageCollectionsDialog?.Show()); BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo)); BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.Regular.TimesCircle, colours.Purple, null); BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.Solid.Eraser, colours.Purple, () => clearScores(Beatmap.Value.BeatmapInfo)); } dialogOverlay = dialog; sampleChangeDifficulty = audio.Samples.Get(@"SongSelect/select-difficulty"); sampleChangeBeatmap = audio.Samples.Get(@"SongSelect/select-expand"); SampleConfirm = audio.Samples.Get(@"SongSelect/confirm-selection"); if (dialogOverlay != null) { Schedule(() => { // if we have no beatmaps but osu-stable is found, let's prompt the user to import. if (!beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.Minimal).Any() && beatmaps.StableInstallationAvailable) { dialogOverlay.Push(new ImportFromStablePopup(() => { Task.Run(beatmaps.ImportFromStableAsync) .ContinueWith(_ => { Task.Run(scores.ImportFromStableAsync); Task.Run(collections.ImportFromStableAsync); }, TaskContinuationOptions.OnlyOnRanToCompletion); Task.Run(skins.ImportFromStableAsync); })); } }); } }
private void load(AudioManager audio, IDialogOverlay dialog, OsuColour colours, ManageCollectionsDialog manageCollectionsDialog, DifficultyRecommender recommender) { // initial value transfer is required for FilterControl (it uses our re-cached bindables in its async load for the initial filter). transferRulesetValue(); LoadComponentAsync(Carousel = new BeatmapCarousel { AllowSelection = false, // delay any selection until our bindables are ready to make a good choice. Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, RelativeSizeAxes = Axes.Both, BleedTop = FilterControl.HEIGHT, BleedBottom = Footer.HEIGHT, SelectionChanged = updateSelectedBeatmap, BeatmapSetsChanged = carouselBeatmapsLoaded, GetRecommendedBeatmap = s => recommender?.GetRecommendedBeatmap(s), }, c => carouselContainer.Child = c); AddRangeInternal(new Drawable[] { new ResetScrollContainer(() => Carousel.ScrollToSelected()) { RelativeSizeAxes = Axes.Y, Width = 250, }, new VerticalMaskingContainer { Children = new Drawable[] { new GridContainer // used for max width implementation { RelativeSizeAxes = Axes.Both, ColumnDimensions = new[] { new Dimension(), new Dimension(GridSizeMode.Relative, 0.5f, maxSize: 850), }, Content = new[] { new Drawable[] { new ParallaxContainer { ParallaxAmount = 0.005f, RelativeSizeAxes = Axes.Both, Child = new WedgeBackground { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Right = -150 }, }, }, carouselContainer = new Container { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = FilterControl.HEIGHT, Bottom = Footer.HEIGHT }, Child = new LoadingSpinner(true) { State = { Value = Visibility.Visible } } } }, } }, FilterControl = new FilterControl { RelativeSizeAxes = Axes.X, Height = FilterControl.HEIGHT, FilterChanged = ApplyFilterToCarousel, }, new GridContainer // used for max width implementation { RelativeSizeAxes = Axes.Both, ColumnDimensions = new[] { new Dimension(GridSizeMode.Relative, 0.5f, maxSize: 650), }, Content = new[] { new Drawable[] { LeftArea = new Container { Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = left_area_padding }, Children = new Drawable[] { beatmapInfoWedge = new BeatmapInfoWedge { Height = WEDGE_HEIGHT, RelativeSizeAxes = Axes.X, Margin = new MarginPadding { Right = left_area_padding, Left = -BeatmapInfoWedge.BORDER_THICKNESS, // Hide the left border }, }, new Container { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Bottom = Footer.HEIGHT, Top = WEDGE_HEIGHT, Left = left_area_padding, Right = left_area_padding * 2, }, Child = BeatmapDetails = CreateBeatmapDetailArea().With(d => { d.RelativeSizeAxes = Axes.Both; d.Padding = new MarginPadding { Top = 10, Right = 5 }; }) }, } }, }, } } } }, new SkinnableTargetContainer(SkinnableTarget.SongSelect) { RelativeSizeAxes = Axes.Both, }, }); if (ShowFooter) { AddRangeInternal(new Drawable[] { FooterPanels = new Container { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Bottom = Footer.HEIGHT }, Children = new Drawable[] { BeatmapOptions = new BeatmapOptionsOverlay(), } }, Footer = new Footer(), }); } // preload the mod select overlay for later use in `LoadComplete()`. // therein it will be registered at the `OsuGame` level to properly function as a blocking overlay. LoadComponent(ModSelect = CreateModSelectOverlay()); if (Footer != null) { foreach (var(button, overlay) in CreateFooterButtons()) { Footer.AddButton(button, overlay); } BeatmapOptions.AddButton(@"Manage", @"collections", FontAwesome.Solid.Book, colours.Green, () => manageCollectionsDialog?.Show()); BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo)); BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.Regular.TimesCircle, colours.Purple, null); BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.Solid.Eraser, colours.Purple, () => clearScores(Beatmap.Value.BeatmapInfo)); } dialogOverlay = dialog; sampleChangeDifficulty = audio.Samples.Get(@"SongSelect/select-difficulty"); sampleChangeBeatmap = audio.Samples.Get(@"SongSelect/select-expand"); SampleConfirm = audio.Samples.Get(@"SongSelect/confirm-selection"); if (dialogOverlay != null) { Schedule(() => { // if we have no beatmaps, let's prompt the user to import from over a stable install if he has one. if (beatmaps.QueryBeatmapSet(s => !s.Protected && !s.DeletePending) == null && DisplayStableImportPrompt) { dialogOverlay.Push(new ImportFromStablePopup(() => { Task.Run(() => legacyImportManager.ImportFromStableAsync(StableContent.All)); })); } }); } }