2022-04-28 15:09:00 +08:00
#nullable enable
2022-04-27 17:57:20 +08:00
// 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.
2022-04-28 17:57:32 +08:00
using System ;
2022-04-27 17:57:20 +08:00
using System.ComponentModel ;
2022-04-27 18:41:13 +08:00
using System.Linq ;
2022-04-27 17:57:20 +08:00
using osu.Framework.Allocation ;
using osu.Framework.Graphics ;
2022-04-28 17:57:32 +08:00
using osu.Game.Beatmaps ;
2022-04-27 17:57:20 +08:00
using osu.Game.Beatmaps.Drawables ;
2022-04-28 15:09:00 +08:00
using osu.Game.Database ;
2022-04-27 17:57:20 +08:00
using osu.Game.Graphics ;
using osu.Game.Graphics.Containers ;
using osu.Game.Graphics.UserInterface ;
2022-04-27 19:19:11 +08:00
using osu.Game.Graphics.UserInterfaceV2 ;
2022-04-28 15:09:00 +08:00
using osu.Game.Localisation ;
2022-04-27 18:41:13 +08:00
using osu.Game.Online ;
2022-04-27 19:19:11 +08:00
using osuTK ;
2022-04-28 17:57:32 +08:00
using Realms ;
using Container = osu . Framework . Graphics . Containers . Container ;
2022-04-27 17:57:20 +08:00
namespace osu.Game.Overlays.FirstRunSetup
{
2022-04-28 15:09:00 +08:00
[Description("Obtaining Beatmaps")]
public class ScreenBeatmaps : FirstRunSetupScreen
2022-04-27 17:57:20 +08:00
{
2022-04-28 16:11:29 +08:00
private ProgressRoundedButton downloadBundledButton = null ! ;
private ProgressRoundedButton importBeatmapsButton = null ! ;
private ProgressRoundedButton downloadTutorialButton = null ! ;
2022-04-27 17:57:20 +08:00
2022-04-28 17:57:32 +08:00
private OsuTextFlowContainer currentlyLoadedBeatmaps = null ! ;
2022-04-28 16:11:29 +08:00
private BundledBeatmapDownloader ? tutorialDownloader ;
private BundledBeatmapDownloader ? bundledDownloader ;
2022-04-27 19:19:11 +08:00
2022-04-28 16:11:29 +08:00
[Resolved]
private OsuColour colours { get ; set ; } = null ! ;
2022-04-27 18:41:13 +08:00
2022-04-28 17:57:32 +08:00
[Resolved]
private RealmAccess realmAccess { get ; set ; } = null ! ;
private IDisposable ? beatmapSubscription ;
2022-04-28 15:09:00 +08:00
[BackgroundDependencyLoader(permitNulls: true)]
2022-04-28 17:57:32 +08:00
private void load ( LegacyImportManager ? legacyImportManager )
2022-04-27 17:57:20 +08:00
{
2022-04-28 15:09:00 +08:00
Vector2 buttonSize = new Vector2 ( 500 , 60 ) ;
2022-04-27 19:19:11 +08:00
2022-04-27 17:57:20 +08:00
Content . Children = new Drawable [ ]
{
new OsuTextFlowContainer ( cp = > cp . Font = OsuFont . Default . With ( size : 20 ) )
{
2022-04-28 17:57:32 +08:00
Colour = OverlayColourProvider . Content1 ,
2022-04-27 19:19:11 +08:00
Text =
2022-04-28 15:36:25 +08:00
"\"Beatmaps\" are what we call playable levels. osu! doesn't come with any beatmaps pre-loaded. This step will help you get started on your beatmap collection." ,
2022-04-28 15:09:00 +08:00
RelativeSizeAxes = Axes . X ,
AutoSizeAxes = Axes . Y
} ,
2022-04-28 17:57:32 +08:00
new Container
{
RelativeSizeAxes = Axes . X ,
Height = 30 ,
Children = new Drawable [ ]
{
currentlyLoadedBeatmaps = new OsuTextFlowContainer ( cp = > cp . Font = OsuFont . Default . With ( size : 24 , weight : FontWeight . SemiBold ) )
{
Colour = OverlayColourProvider . Content2 ,
TextAnchor = Anchor . Centre ,
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
AutoSizeAxes = Axes . Both ,
} ,
}
} ,
2022-04-28 15:09:00 +08:00
new OsuTextFlowContainer ( cp = > cp . Font = OsuFont . Default . With ( size : 20 ) )
{
2022-04-28 17:57:32 +08:00
Colour = OverlayColourProvider . Content1 ,
2022-04-28 15:09:00 +08:00
Text =
"If you are a new player, we recommend playing through the tutorial to get accustomed to the gameplay." ,
2022-04-27 17:57:20 +08:00
RelativeSizeAxes = Axes . X ,
AutoSizeAxes = Axes . Y
} ,
2022-04-28 16:11:29 +08:00
downloadTutorialButton = new ProgressRoundedButton
2022-04-27 19:19:11 +08:00
{
Size = buttonSize ,
Anchor = Anchor . TopCentre ,
Origin = Anchor . TopCentre ,
BackgroundColour = colours . Pink3 ,
2022-04-28 15:36:25 +08:00
Text = "Get the osu! tutorial" ,
2022-04-27 19:19:11 +08:00
Action = downloadTutorial
} ,
2022-04-28 15:09:00 +08:00
new OsuTextFlowContainer ( cp = > cp . Font = OsuFont . Default . With ( size : 20 ) )
{
2022-04-28 17:57:32 +08:00
Colour = OverlayColourProvider . Content1 ,
2022-04-28 15:09:00 +08:00
Text = "To get you started, we have some recommended beatmaps." ,
RelativeSizeAxes = Axes . X ,
AutoSizeAxes = Axes . Y
} ,
2022-04-28 16:11:29 +08:00
downloadBundledButton = new ProgressRoundedButton
2022-04-27 17:57:20 +08:00
{
2022-04-27 19:19:11 +08:00
Size = buttonSize ,
2022-04-27 17:57:20 +08:00
Anchor = Anchor . TopCentre ,
Origin = Anchor . TopCentre ,
2022-04-27 19:19:11 +08:00
BackgroundColour = colours . Blue3 ,
2022-04-28 15:36:25 +08:00
Text = "Get recommended beatmaps" ,
2022-04-27 19:19:11 +08:00
Action = downloadBundled
2022-04-27 18:41:13 +08:00
} ,
2022-04-28 15:09:00 +08:00
new OsuTextFlowContainer ( cp = > cp . Font = OsuFont . Default . With ( size : 20 ) )
{
2022-04-28 17:57:32 +08:00
Colour = OverlayColourProvider . Content1 ,
2022-04-28 15:09:00 +08:00
Text = "If you have an existing osu! install, you can also choose to import your existing beatmap collection." ,
RelativeSizeAxes = Axes . X ,
AutoSizeAxes = Axes . Y
} ,
2022-04-28 16:11:29 +08:00
importBeatmapsButton = new ProgressRoundedButton
2022-04-28 15:09:00 +08:00
{
Size = buttonSize ,
Anchor = Anchor . TopCentre ,
Origin = Anchor . TopCentre ,
BackgroundColour = colours . Blue3 ,
Text = MaintenanceSettingsStrings . ImportBeatmapsFromStable ,
Action = ( ) = >
{
importBeatmapsButton . Enabled . Value = false ;
2022-04-28 16:11:29 +08:00
legacyImportManager ? . ImportFromStableAsync ( StableContent . Beatmaps ) . ContinueWith ( t = > Schedule ( ( ) = >
{
2022-04-28 17:17:29 +08:00
if ( t . IsCompletedSuccessfully )
importBeatmapsButton . Complete ( ) ;
else
importBeatmapsButton . Enabled . Value = true ;
2022-04-28 16:11:29 +08:00
} ) ) ;
2022-04-28 15:09:00 +08:00
}
} ,
new OsuTextFlowContainer ( cp = > cp . Font = OsuFont . Default . With ( size : 20 ) )
{
2022-04-28 17:57:32 +08:00
Colour = OverlayColourProvider . Content1 ,
2022-04-28 15:09:00 +08:00
Text = "You can also obtain more beatmaps from the main menu \"browse\" button at any time." ,
RelativeSizeAxes = Axes . X ,
AutoSizeAxes = Axes . Y
} ,
2022-04-27 17:57:20 +08:00
} ;
}
2022-04-28 17:57:32 +08:00
protected override void LoadComplete ( )
{
base . LoadComplete ( ) ;
beatmapSubscription = realmAccess . RegisterForNotifications ( r = > r . All < BeatmapSetInfo > ( ) . Where ( s = > ! s . DeletePending & & ! s . Protected ) , beatmapsChanged ) ;
}
protected override void Dispose ( bool isDisposing )
{
base . Dispose ( isDisposing ) ;
beatmapSubscription ? . Dispose ( ) ;
}
private void beatmapsChanged ( IRealmCollection < BeatmapSetInfo > sender , ChangeSet ? changes , Exception error )
{
currentlyLoadedBeatmaps . Text = $"You currently have {sender.Count} beatmap(s) loaded!" ;
if ( changes ! = null & & ( changes . DeletedIndices . Any ( ) | | changes . InsertedIndices . Any ( ) ) )
{
currentlyLoadedBeatmaps . FadeColour ( colours . YellowLight ) . FadeColour ( OverlayColourProvider . Content2 ) ;
currentlyLoadedBeatmaps . ScaleTo ( 1.1f ) . ScaleTo ( 1 , 1000 , Easing . OutQuint ) ;
}
}
2022-04-27 19:19:11 +08:00
private void downloadTutorial ( )
2022-04-27 17:57:20 +08:00
{
2022-04-28 16:11:29 +08:00
if ( tutorialDownloader ! = null )
return ;
2022-04-27 19:19:11 +08:00
tutorialDownloader = new BundledBeatmapDownloader ( true ) ;
AddInternal ( tutorialDownloader ) ;
var downloadTracker = tutorialDownloader . DownloadTrackers . First ( ) ;
2022-04-27 18:41:13 +08:00
2022-04-27 19:19:11 +08:00
downloadTracker . Progress . BindValueChanged ( progress = >
{
2022-04-28 17:26:29 +08:00
downloadTutorialButton . SetProgress ( progress . NewValue , false ) ;
2022-04-27 19:19:11 +08:00
if ( progress . NewValue = = 1 )
2022-04-28 16:11:29 +08:00
downloadTutorialButton . Complete ( ) ;
2022-04-27 19:19:11 +08:00
} , true ) ;
2022-04-27 18:41:13 +08:00
}
2022-04-27 19:19:11 +08:00
private void downloadBundled ( )
2022-04-27 18:41:13 +08:00
{
2022-04-28 16:11:29 +08:00
if ( bundledDownloader ! = null )
return ;
2022-04-27 19:19:11 +08:00
bundledDownloader = new BundledBeatmapDownloader ( false ) ;
AddInternal ( bundledDownloader ) ;
foreach ( var tracker in bundledDownloader . DownloadTrackers )
tracker . State . BindValueChanged ( _ = > updateProgress ( ) , true ) ;
void updateProgress ( )
{
double progress = ( double ) bundledDownloader . DownloadTrackers . Count ( t = > t . State . Value = = DownloadState . LocallyAvailable ) / bundledDownloader . DownloadTrackers . Count ( ) ;
if ( progress = = 1 )
2022-04-28 16:11:29 +08:00
downloadBundledButton . Complete ( ) ;
2022-04-28 17:26:29 +08:00
else
downloadBundledButton . SetProgress ( progress , true ) ;
2022-04-28 16:11:29 +08:00
}
}
private class ProgressRoundedButton : RoundedButton
{
[Resolved]
private OsuColour colours { get ; set ; } = null ! ;
private ProgressBar progressBar = null ! ;
protected override void LoadComplete ( )
{
base . LoadComplete ( ) ;
Add ( progressBar = new ProgressBar ( false )
{
RelativeSizeAxes = Axes . Both ,
Blending = BlendingParameters . Additive ,
FillColour = BackgroundColour ,
Alpha = 0.5f ,
Depth = float . MinValue
} ) ;
}
public void Complete ( )
{
Enabled . Value = false ;
Background . FadeColour ( colours . Green , 500 , Easing . OutQuint ) ;
progressBar . FillColour = colours . Green ;
2022-04-28 17:26:29 +08:00
this . TransformBindableTo ( progressBar . Current , 1 , 500 , Easing . OutQuint ) ;
}
public void SetProgress ( double progress , bool animated )
{
if ( ! Enabled . Value )
return ;
this . TransformBindableTo ( progressBar . Current , progress , animated ? 500 : 0 , Easing . OutQuint ) ;
2022-04-27 19:19:11 +08:00
}
2022-04-27 17:57:20 +08:00
}
}
}