1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-18 23:57:22 +08:00

Merge pull request #12283 from bdach/setup-screen-design-refresh

Refresh setup screen appearance to be closer to design
This commit is contained in:
Dean Herbert 2021-04-06 18:33:34 +09:00 committed by GitHub
commit d4c55070e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 353 additions and 164 deletions

View File

@ -5,8 +5,8 @@ using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Localisation;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterfaceV2;
namespace osu.Game.Screens.Edit.Setup
@ -18,15 +18,13 @@ namespace osu.Game.Screens.Edit.Setup
private LabelledSliderBar<float> approachRateSlider;
private LabelledSliderBar<float> overallDifficultySlider;
public override LocalisableString Title => "Difficulty";
[BackgroundDependencyLoader]
private void load()
{
Children = new Drawable[]
{
new OsuSpriteText
{
Text = "Difficulty settings"
},
circleSizeSlider = new LabelledSliderBar<float>
{
Label = "Object Size",

View File

@ -2,12 +2,16 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Events;
using osu.Game.Database;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
using osu.Game.Graphics.UserInterfaceV2;
@ -17,27 +21,27 @@ namespace osu.Game.Screens.Edit.Setup
/// <summary>
/// A labelled textbox which reveals an inline file chooser when clicked.
/// </summary>
internal class FileChooserLabelledTextBox : LabelledTextBox
internal class FileChooserLabelledTextBox : LabelledTextBox, ICanAcceptFiles
{
private readonly string[] handledExtensions;
public IEnumerable<string> HandledExtensions => handledExtensions;
/// <summary>
/// The target container to display the file chooser in.
/// </summary>
public Container Target;
private readonly IBindable<FileInfo> currentFile = new Bindable<FileInfo>();
private readonly Bindable<FileInfo> currentFile = new Bindable<FileInfo>();
[Resolved]
private OsuGameBase game { get; set; }
[Resolved]
private SectionsContainer<SetupSection> sectionsContainer { get; set; }
public FileChooserLabelledTextBox()
public FileChooserLabelledTextBox(params string[] handledExtensions)
{
currentFile.BindValueChanged(onFileSelected);
}
private void onFileSelected(ValueChangedEvent<FileInfo> file)
{
if (file.NewValue == null)
return;
Target.Clear();
Current.Value = file.NewValue.FullName;
this.handledExtensions = handledExtensions;
}
protected override OsuTextBox CreateTextBox() =>
@ -54,7 +58,7 @@ namespace osu.Game.Screens.Edit.Setup
{
FileSelector fileSelector;
Target.Child = fileSelector = new FileSelector(currentFile.Value?.DirectoryName, ResourcesSection.AudioExtensions)
Target.Child = fileSelector = new FileSelector(currentFile.Value?.DirectoryName, handledExtensions)
{
RelativeSizeAxes = Axes.X,
Height = 400,
@ -64,6 +68,37 @@ namespace osu.Game.Screens.Edit.Setup
sectionsContainer.ScrollTo(fileSelector);
}
protected override void LoadComplete()
{
base.LoadComplete();
game.RegisterImportHandler(this);
currentFile.BindValueChanged(onFileSelected);
}
private void onFileSelected(ValueChangedEvent<FileInfo> file)
{
if (file.NewValue == null)
return;
Target.Clear();
Current.Value = file.NewValue.FullName;
}
Task ICanAcceptFiles.Import(params string[] paths)
{
Schedule(() => currentFile.Value = new FileInfo(paths.First()));
return Task.CompletedTask;
}
Task ICanAcceptFiles.Import(params ImportTask[] tasks) => throw new NotImplementedException();
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
game.UnregisterImportHandler(this);
}
internal class FileChooserOsuTextBox : OsuTextBox
{
public Action OnFocused;

View File

@ -5,7 +5,7 @@ using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Graphics.UserInterfaceV2;
namespace osu.Game.Screens.Edit.Setup
@ -17,15 +17,13 @@ namespace osu.Game.Screens.Edit.Setup
private LabelledTextBox creatorTextBox;
private LabelledTextBox difficultyTextBox;
public override LocalisableString Title => "Metadata";
[BackgroundDependencyLoader]
private void load()
{
Children = new Drawable[]
{
new OsuSpriteText
{
Text = "Beatmap metadata"
},
artistTextBox = new LabelledTextBox
{
Label = "Artist",

View File

@ -1,40 +1,25 @@
// 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.IO;
using System.Linq;
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.Localisation;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Overlays;
namespace osu.Game.Screens.Edit.Setup
{
internal class ResourcesSection : SetupSection, ICanAcceptFiles
internal class ResourcesSection : SetupSection
{
private LabelledTextBox audioTrackTextBox;
private Container backgroundSpriteContainer;
private LabelledTextBox backgroundTextBox;
public IEnumerable<string> HandledExtensions => ImageExtensions.Concat(AudioExtensions);
public static string[] ImageExtensions { get; } = { ".jpg", ".jpeg", ".png" };
public static string[] AudioExtensions { get; } = { ".mp3", ".ogg" };
[Resolved]
private OsuGameBase game { get; set; }
public override LocalisableString Title => "Resources";
[Resolved]
private MusicController music { get; set; }
@ -48,70 +33,66 @@ namespace osu.Game.Screens.Edit.Setup
[Resolved(canBeNull: true)]
private Editor editor { get; set; }
[Resolved]
private SetupScreenHeader header { get; set; }
[BackgroundDependencyLoader]
private void load()
{
Container audioTrackFileChooserContainer = new Container
Container audioTrackFileChooserContainer = createFileChooserContainer();
Container backgroundFileChooserContainer = createFileChooserContainer();
Children = new Drawable[]
{
new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
backgroundTextBox = new FileChooserLabelledTextBox(".jpg", ".jpeg", ".png")
{
Label = "Background",
PlaceholderText = "Click to select a background image",
Current = { Value = working.Value.Metadata.BackgroundFile },
Target = backgroundFileChooserContainer,
TabbableContentContainer = this
},
backgroundFileChooserContainer,
}
},
new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
audioTrackTextBox = new FileChooserLabelledTextBox(".mp3", ".ogg")
{
Label = "Audio Track",
PlaceholderText = "Click to select a track",
Current = { Value = working.Value.Metadata.AudioFile },
Target = audioTrackFileChooserContainer,
TabbableContentContainer = this
},
audioTrackFileChooserContainer,
}
}
};
backgroundTextBox.Current.BindValueChanged(backgroundChanged);
audioTrackTextBox.Current.BindValueChanged(audioTrackChanged);
}
private static Container createFileChooserContainer() =>
new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
};
Children = new Drawable[]
{
backgroundSpriteContainer = new Container
{
RelativeSizeAxes = Axes.X,
Height = 250,
Masking = true,
CornerRadius = 10,
},
new OsuSpriteText
{
Text = "Resources"
},
audioTrackTextBox = new FileChooserLabelledTextBox
{
Label = "Audio Track",
PlaceholderText = "Click to select a track",
Current = { Value = working.Value.Metadata.AudioFile },
Target = audioTrackFileChooserContainer,
TabbableContentContainer = this
},
audioTrackFileChooserContainer,
};
updateBackgroundSprite();
audioTrackTextBox.Current.BindValueChanged(audioTrackChanged);
}
Task ICanAcceptFiles.Import(params string[] paths)
{
Schedule(() =>
{
var firstFile = new FileInfo(paths.First());
if (ImageExtensions.Contains(firstFile.Extension))
{
ChangeBackgroundImage(firstFile.FullName);
}
else if (AudioExtensions.Contains(firstFile.Extension))
{
audioTrackTextBox.Text = firstFile.FullName;
}
});
return Task.CompletedTask;
}
Task ICanAcceptFiles.Import(params ImportTask[] tasks) => throw new NotImplementedException();
protected override void LoadComplete()
{
base.LoadComplete();
game.RegisterImportHandler(this);
}
public bool ChangeBackgroundImage(string path)
{
var info = new FileInfo(path);
@ -134,17 +115,11 @@ namespace osu.Game.Screens.Edit.Setup
}
working.Value.Metadata.BackgroundFile = info.Name;
updateBackgroundSprite();
header.Background.UpdateBackground();
return true;
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
game?.UnregisterImportHandler(this);
}
public bool ChangeAudioTrack(string path)
{
var info = new FileInfo(path);
@ -174,45 +149,16 @@ namespace osu.Game.Screens.Edit.Setup
return true;
}
private void backgroundChanged(ValueChangedEvent<string> filePath)
{
if (!ChangeBackgroundImage(filePath.NewValue))
backgroundTextBox.Current.Value = filePath.OldValue;
}
private void audioTrackChanged(ValueChangedEvent<string> filePath)
{
if (!ChangeAudioTrack(filePath.NewValue))
audioTrackTextBox.Current.Value = filePath.OldValue;
}
private void updateBackgroundSprite()
{
LoadComponentAsync(new BeatmapBackgroundSprite(working.Value)
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
FillMode = FillMode.Fill,
}, background =>
{
if (background.Texture != null)
backgroundSpriteContainer.Child = background;
else
{
backgroundSpriteContainer.Children = new Drawable[]
{
new Box
{
Colour = Colours.GreySeafoamDarker,
RelativeSizeAxes = Axes.Both,
},
new OsuTextFlowContainer(t => t.Font = OsuFont.Default.With(size: 24))
{
Text = "Drag image here to set beatmap background!",
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.X,
}
};
}
background.FadeInFromZero(500);
});
}
}
}

View File

@ -13,16 +13,24 @@ namespace osu.Game.Screens.Edit.Setup
{
public class SetupScreen : EditorScreen
{
public const int HORIZONTAL_PADDING = 100;
[Resolved]
private OsuColour colours { get; set; }
[Cached]
protected readonly OverlayColourProvider ColourProvider;
[Cached]
private SectionsContainer<SetupSection> sections = new SectionsContainer<SetupSection>();
[Cached]
private SetupScreenHeader header = new SetupScreenHeader();
public SetupScreen()
: base(EditorScreenMode.SongSetup)
{
ColourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
ColourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
}
[BackgroundDependencyLoader]
@ -41,12 +49,12 @@ namespace osu.Game.Screens.Edit.Setup
{
new Box
{
Colour = colours.GreySeafoamDark,
Colour = ColourProvider.Dark4,
RelativeSizeAxes = Axes.Both,
},
new SectionsContainer<SetupSection>
sections = new SectionsContainer<SetupSection>
{
FixedHeader = new SetupScreenHeader(),
FixedHeader = header,
RelativeSizeAxes = Axes.Both,
Children = new SetupSection[]
{
@ -60,19 +68,4 @@ namespace osu.Game.Screens.Edit.Setup
};
}
}
internal class SetupScreenHeader : OverlayHeader
{
protected override OverlayTitle CreateTitle() => new SetupScreenTitle();
private class SetupScreenTitle : OverlayTitle
{
public SetupScreenTitle()
{
Title = "beatmap setup";
Description = "change general settings of your beatmap";
IconTexture = "Icons/Hexacons/social";
}
}
}
}

View File

@ -0,0 +1,120 @@
// 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 osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.Containers;
using osu.Game.Overlays;
using osuTK.Graphics;
namespace osu.Game.Screens.Edit.Setup
{
internal class SetupScreenHeader : OverlayHeader
{
public SetupScreenHeaderBackground Background { get; private set; }
[Resolved]
private SectionsContainer<SetupSection> sections { get; set; }
private SetupScreenTabControl tabControl;
protected override OverlayTitle CreateTitle() => new SetupScreenTitle();
protected override Drawable CreateContent() => new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
// reverse flow is used to ensure that the tab control's expandable bars extend over the background chooser.
Child = new ReverseChildIDFillFlowContainer<Drawable>
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
tabControl = new SetupScreenTabControl
{
RelativeSizeAxes = Axes.X,
Height = 30
},
Background = new SetupScreenHeaderBackground
{
RelativeSizeAxes = Axes.X,
Height = 120
}
}
}
};
[BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider)
{
tabControl.AccentColour = colourProvider.Highlight1;
tabControl.BackgroundColour = colourProvider.Dark5;
foreach (var section in sections)
tabControl.AddItem(section);
}
protected override void LoadComplete()
{
base.LoadComplete();
sections.SelectedSection.BindValueChanged(section => tabControl.Current.Value = section.NewValue);
tabControl.Current.BindValueChanged(section =>
{
if (section.NewValue != sections.SelectedSection.Value)
sections.ScrollTo(section.NewValue);
});
}
private class SetupScreenTitle : OverlayTitle
{
public SetupScreenTitle()
{
Title = "beatmap setup";
Description = "change general settings of your beatmap";
IconTexture = "Icons/Hexacons/social";
}
}
internal class SetupScreenTabControl : OverlayTabControl<SetupSection>
{
private readonly Box background;
public Color4 BackgroundColour
{
get => background.Colour;
set => background.Colour = value;
}
public SetupScreenTabControl()
{
TabContainer.Margin = new MarginPadding { Horizontal = SetupScreen.HORIZONTAL_PADDING };
AddInternal(background = new Box
{
RelativeSizeAxes = Axes.Both,
Depth = 1
});
}
protected override TabItem<SetupSection> CreateTabItem(SetupSection value) => new SetupScreenTabItem(value)
{
AccentColour = AccentColour
};
private class SetupScreenTabItem : OverlayTabItem
{
public SetupScreenTabItem(SetupSection value)
: base(value)
{
Text.Text = value.Title;
}
}
}
}
}

View File

@ -0,0 +1,76 @@
// 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 osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
namespace osu.Game.Screens.Edit.Setup
{
public class SetupScreenHeaderBackground : CompositeDrawable
{
[Resolved]
private OsuColour colours { get; set; }
[Resolved]
private IBindable<WorkingBeatmap> working { get; set; }
private readonly Container content;
public SetupScreenHeaderBackground()
{
InternalChild = content = new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true
};
}
[BackgroundDependencyLoader]
private void load()
{
UpdateBackground();
}
public void UpdateBackground()
{
LoadComponentAsync(new BeatmapBackgroundSprite(working.Value)
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
FillMode = FillMode.Fill,
}, background =>
{
if (background.Texture != null)
content.Child = background;
else
{
content.Children = new Drawable[]
{
new Box
{
Colour = colours.GreySeafoamDarker,
RelativeSizeAxes = Axes.Both,
},
new OsuTextFlowContainer(t => t.Font = OsuFont.Default.With(size: 24))
{
Text = "Drag image here to set beatmap background!",
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.Both
}
};
}
background.FadeInFromZero(500);
});
}
}
}

View File

@ -4,12 +4,14 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Localisation;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osuTK;
namespace osu.Game.Screens.Edit.Setup
{
internal class SetupSection : Container
internal abstract class SetupSection : Container
{
private readonly FillFlowContainer flow;
@ -21,19 +23,40 @@ namespace osu.Game.Screens.Edit.Setup
protected override Container<Drawable> Content => flow;
public SetupSection()
public abstract LocalisableString Title { get; }
protected SetupSection()
{
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
Padding = new MarginPadding(10);
Padding = new MarginPadding
{
Vertical = 10,
Horizontal = SetupScreen.HORIZONTAL_PADDING
};
InternalChild = flow = new FillFlowContainer
InternalChild = new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(20),
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
new OsuSpriteText
{
Font = OsuFont.GetFont(weight: FontWeight.Bold),
Text = Title
},
flow = new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(20),
Direction = FillDirection.Vertical,
}
}
};
}
}