diff --git a/osu.Game/Screens/Import/FileImportScreen.cs b/osu.Game/Screens/Import/FileImportScreen.cs new file mode 100644 index 0000000000..669c26101c --- /dev/null +++ b/osu.Game/Screens/Import/FileImportScreen.cs @@ -0,0 +1,318 @@ +using System.IO; +using System.Threading.Tasks; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Platform; +using osu.Framework.Screens; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterfaceV2; +using osuTK; +using osu.Game.Overlays.Settings; +using osu.Game.Configuration; +using osu.Game.Overlays; +using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.Containers; +using osuTK.Graphics; + +namespace osu.Game.Screens.Import +{ + public class FileImportScreen : OsuScreen + { + private Container contentContainer; + private FileSelector fileSelector; + private Container fileSelectContainer; + + public override bool HideOverlaysOnEnter => true; + + private string[] fileExtensions = { ".foo" }; + private string defaultPath; + + private readonly Bindable currentFile = new Bindable(); + private readonly IBindable currentDirectory = new Bindable(); + private readonly Bindable filterType = new Bindable(FileFilterType.All); + private TextFlowContainer currentFileText; + private OsuScrollContainer fileNameScroll; + private readonly OverlayColourProvider overlayColourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); + + [Resolved] + private OsuGameBase gameBase { get; set; } + + [Resolved] + private DialogOverlay dialogOverlay { get; set; } + + [BackgroundDependencyLoader(true)] + private void load(Storage storage) + { + storage.GetStorageForDirectory("imports"); + var originalPath = storage.GetFullPath("imports", true); + + defaultPath = originalPath; + + InternalChild = contentContainer = new Container + { + Masking = true, + CornerRadius = 10, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(0.9f, 0.8f), + Children = new Drawable[] + { + new Box + { + Colour = overlayColourProvider.Background5, + RelativeSizeAxes = Axes.Both, + }, + fileSelectContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Width = 0.65f, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Width = 0.35f, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Masking = true, + CornerRadius = 10, + Children = new Drawable[] + { + new GridContainer + { + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Children = new Drawable[] + { + new Box + { + Colour = overlayColourProvider.Background3, + RelativeSizeAxes = Axes.Both + }, + fileNameScroll = new OsuScrollContainer + { + Masking = false, + RelativeSizeAxes = Axes.Both, + Child = currentFileText = new TextFlowContainer(t => t.Font = OsuFont.Default.With(size: 30)) + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + TextAnchor = Anchor.Centre + }, + }, + } + }, + }, + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new Box + { + Colour = overlayColourProvider.Background4, + RelativeSizeAxes = Axes.Both + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(10), + Children = new Drawable[] + { + new SettingsEnumDropdown + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + LabelText = "File Type", + Current = filterType, + Margin = new MarginPadding { Bottom = 15 } + }, + new GridContainer + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Margin = new MarginPadding { Top = 15 }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize) + }, + Content = new[] + { + new Drawable[] + { + new TriangleButton + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.X, + Height = 50, + Width = 0.9f, + Text = "Refresh", + Action = refresh + }, + new TriangleButton + { + Text = "Import", + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.X, + Height = 50, + Width = 0.9f, + Action = () => + { + var d = currentFile.Value?.FullName; + if (d != null) + startImport(d); + else + currentFileText.FlashColour(Color4.Red, 500); + }, + } + }, + } + }, + } + }, + } + } + } + } + }, + } + } + } + }; + + fileNameScroll.ScrollContent.Anchor = Anchor.Centre; + fileNameScroll.ScrollContent.Origin = Anchor.Centre; + + currentFile.BindValueChanged(updateFileSelectionText, true); + currentDirectory.BindValueChanged(_ => + { + currentFile.Value = null; + }); + + filterType.BindValueChanged(onFilterTypeChanged, true); + } + + private void onFilterTypeChanged(ValueChangedEvent v) + { + switch (v.NewValue) + { + case FileFilterType.Beatmap: + fileExtensions = new string[] { ".osz" }; + break; + + case FileFilterType.Skin: + fileExtensions = new string[] { ".osk" }; + break; + + case FileFilterType.Replay: + fileExtensions = new string[] { ".osr" }; + break; + + default: + case FileFilterType.All: + fileExtensions = new string[] { ".osk", ".osr", ".osz" }; + break; + } + + refresh(); + } + + private void refresh() + { + currentFile.UnbindBindings(); + currentDirectory.UnbindBindings(); + + fileSelector?.Expire(); + + var directory = currentDirectory.Value?.FullName ?? defaultPath; + fileSelector = new FileSelector(initialPath: directory, validFileExtensions: fileExtensions) + { + RelativeSizeAxes = Axes.Both + }; + + currentDirectory.BindTo(fileSelector.CurrentPath); + currentFile.BindTo(fileSelector.CurrentFile); + + fileSelectContainer.Add(fileSelector); + } + + private void updateFileSelectionText(ValueChangedEvent v) + { + currentFileText.Text = v.NewValue?.Name ?? "Select a file"; + } + + public override void OnEntering(IScreen last) + { + base.OnEntering(last); + + contentContainer.FadeOut().Then().ScaleTo(0.8f).RotateTo(-15).MoveToX(300) + .Then() + .ScaleTo(1, 1500, Easing.OutElastic) + .FadeIn(500) + .MoveToX(0, 500, Easing.OutQuint) + .RotateTo(0, 500, Easing.OutQuint); + } + + public override bool OnExiting(IScreen next) + { + contentContainer.ScaleTo(0.8f, 500, Easing.OutExpo).RotateTo(-15, 500, Easing.OutExpo).MoveToX(300, 500, Easing.OutQuint).FadeOut(500); + this.FadeOut(500, Easing.OutExpo); + + return base.OnExiting(next); + } + + private void startImport(string path) + { + if (string.IsNullOrEmpty(path)) + return; + + if (!File.Exists(path)) + { + refresh(); + currentFileText.Text = "File not exist"; + currentFileText.FlashColour(Color4.Red, 500); + return; + } + + string[] paths = { path }; + + Task.Factory.StartNew(() => gameBase.Import(paths), TaskCreationOptions.LongRunning); + } + + public enum FileFilterType + { + Skin, + Beatmap, + Replay, + All + } + } +} diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 4becdd58cd..1e0d27ac6a 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -41,6 +41,7 @@ namespace osu.Game.Screens.Menu public Action OnExit; public Action OnBeatmapListing; public Action OnSolo; + public Action OnImportButton; public Action OnSettings; public Action OnMulti; public Action OnChart; @@ -131,6 +132,7 @@ namespace osu.Game.Screens.Menu buttonsTopLevel.Add(new Button(@"play", @"button-play-select", OsuIcon.Logo, new Color4(102, 68, 204, 255), () => State = ButtonSystemState.Play, WEDGE_WIDTH, Key.P)); buttonsTopLevel.Add(new Button(@"osu!editor", @"button-generic-select", OsuIcon.EditCircle, new Color4(238, 170, 0, 255), () => OnEdit?.Invoke(), 0, Key.E)); buttonsTopLevel.Add(new Button(@"osu!direct", @"button-direct-select", OsuIcon.ChevronDownCircle, new Color4(165, 204, 0, 255), () => OnBeatmapListing?.Invoke(), 0, Key.D)); + buttonsTopLevel.Add(new Button(@"Import File", @"button-generic-select", FontAwesome.Solid.File, new Color4(0, 86, 73, 255), () => OnImportButton?.Invoke())); if (host.CanExit) buttonsTopLevel.Add(new Button(@"exit", string.Empty, OsuIcon.CrossCircle, new Color4(238, 51, 153, 255), () => OnExit?.Invoke(), 0, Key.Q)); diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index c3ecd75963..69e4ea487e 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -19,6 +19,7 @@ using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Edit; using osu.Game.Screens.Multi; using osu.Game.Screens.Select; +using osu.Game.Screens.Import; namespace osu.Game.Screens.Menu { @@ -105,6 +106,7 @@ namespace osu.Game.Screens.Menu }, OnSolo = onSolo, OnMulti = delegate { this.Push(new Multiplayer()); }, + OnImportButton = onImport, OnExit = confirmAndExit, } } @@ -144,7 +146,7 @@ namespace osu.Game.Screens.Menu [Resolved(canBeNull: true)] private OsuGame game { get; set; } - + private void onImport() => this.Push(new FileImportScreen()); private void confirmAndExit() { if (exitConfirmed) return;