Improve visual appearance of ProcessingOverlay

This commit is contained in:
Dean Herbert 2020-02-20 19:47:50 +09:00
parent 0bbc4abb35
commit 3380dbbd71
5 changed files with 323 additions and 192 deletions

View File

@ -0,0 +1,86 @@
// 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 NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Tests.Visual.UserInterface
{
public class TestSceneProcessingOverlay : OsuTestScene
{
private Drawable dimContent;
private ProcessingOverlay overlay;
[SetUp]
public void SetUp() => Schedule(() =>
{
Children = new[]
{
new Container
{
Size = new Vector2(300),
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Children = new[]
{
new Box
{
Colour = Color4.SlateGray,
RelativeSizeAxes = Axes.Both,
},
dimContent = new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Direction = FillDirection.Vertical,
Spacing = new Vector2(10),
RelativeSizeAxes = Axes.Both,
Size = new Vector2(0.9f),
Children = new Drawable[]
{
new OsuSpriteText { Text = "Sample content" },
new TriangleButton { Text = "can't puush me", Width = 200, },
new TriangleButton { Text = "puush me", Width = 200, Action = () => { } },
}
},
overlay = new ProcessingOverlay(dimContent),
}
},
};
});
[Test]
public void ShowHide()
{
AddAssert("not visible", () => !overlay.IsPresent);
AddStep("show", () => overlay.Show());
AddUntilStep("wait for content dim", () => dimContent.Colour != Color4.White);
AddStep("hide", () => overlay.Hide());
AddUntilStep("wait for content restore", () => dimContent.Colour == Color4.White);
}
[Test]
public void ContentRestoreOnDispose()
{
AddAssert("not visible", () => !overlay.IsPresent);
AddStep("show", () => overlay.Show());
AddUntilStep("wait for content dim", () => dimContent.Colour != Color4.White);
AddStep("hide", () => overlay.Expire());
AddUntilStep("wait for content restore", () => dimContent.Colour == Color4.White);
}
}
}

View File

@ -6,20 +6,27 @@
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Graphics.UserInterface
{
/// <summary>
/// An overlay that will consume all available space and block input when required.
/// An overlay that will show a loading overlay and completely block input to an area.
/// Also optionally dims target elements.
/// Useful for disabling all elements in a form and showing we are waiting on a response, for instance.
/// </summary>
public class ProcessingOverlay : VisibilityContainer
{
private const float transition_duration = 200;
private readonly Drawable dimTarget;
public ProcessingOverlay()
private Container loadingBox;
private const float transition_duration = 600;
public ProcessingOverlay(Drawable dimTarget = null)
{
this.dimTarget = dimTarget;
RelativeSizeAxes = Axes.Both;
}
@ -28,29 +35,54 @@ private void load()
{
InternalChildren = new Drawable[]
{
new Box
loadingBox = new Container
{
Colour = Color4.Black,
RelativeSizeAxes = Axes.Both,
Alpha = 0.9f,
Size = new Vector2(80),
Scale = new Vector2(0.8f),
Masking = true,
CornerRadius = 15,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Children = new Drawable[]
{
new Box
{
Colour = Color4.Black,
RelativeSizeAxes = Axes.Both,
},
new LoadingAnimation { State = { Value = Visibility.Visible } }
}
},
new LoadingAnimation { State = { Value = Visibility.Visible } }
};
}
protected override bool Handle(UIEvent e)
{
return true;
}
protected override bool Handle(UIEvent e) => true;
protected override void PopIn()
{
this.FadeIn(transition_duration * 2, Easing.OutQuint);
this.FadeIn(transition_duration, Easing.OutQuint);
loadingBox.ScaleTo(1, transition_duration, Easing.OutElastic);
dimTarget?.FadeColour(OsuColour.Gray(0.5f), transition_duration, Easing.OutQuint);
}
protected override void PopOut()
{
this.FadeOut(transition_duration, Easing.OutQuint);
loadingBox.ScaleTo(0.8f, transition_duration / 2, Easing.In);
dimTarget?.FadeColour(Color4.White, transition_duration, Easing.OutQuint);
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (State.Value == Visibility.Visible)
{
// ensure we don't leave the targetin a bad state.
dimTarget?.FadeColour(Color4.White, transition_duration);
}
}
}
}

View File

@ -48,9 +48,11 @@ public class ScreenEntry : AccountCreationScreen
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
FillFlowContainer mainContent;
InternalChildren = new Drawable[]
{
new FillFlowContainer
mainContent = new FillFlowContainer
{
RelativeSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
@ -122,7 +124,7 @@ private void load(OsuColour colours)
},
},
},
processingOverlay = new ProcessingOverlay { Alpha = 0 }
processingOverlay = new ProcessingOverlay(mainContent)
};
textboxes = new[] { usernameTextBox, emailTextBox, passwordTextBox };

View File

@ -30,6 +30,8 @@ public class LoungeSubScreen : MultiplayerSubScreen
public LoungeSubScreen()
{
SearchContainer searchContainer;
InternalChildren = new Drawable[]
{
Filter = new FilterControl { Depth = -1 },
@ -49,14 +51,14 @@ public LoungeSubScreen()
RelativeSizeAxes = Axes.Both,
ScrollbarOverlapsContent = false,
Padding = new MarginPadding(10),
Child = new SearchContainer
Child = searchContainer = new SearchContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Child = new RoomsContainer { JoinRequested = joinRequested }
},
},
processingOverlay = new ProcessingOverlay { Alpha = 0 }
processingOverlay = new ProcessingOverlay(searchContainer),
}
},
new RoomInspector

View File

@ -79,226 +79,235 @@ protected class MatchSettings : MultiplayerComposite
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
Container dimContent;
InternalChildren = new Drawable[]
{
new Box
dimContent = new Container
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.FromHex(@"28242d"),
},
new GridContainer
{
RelativeSizeAxes = Axes.Both,
RowDimensions = new[]
Children = new Drawable[]
{
new Dimension(GridSizeMode.Distributed),
new Dimension(GridSizeMode.AutoSize),
},
Content = new[]
{
new Drawable[]
new Box
{
new OsuScrollContainer
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.FromHex(@"28242d"),
},
new GridContainer
{
RelativeSizeAxes = Axes.Both,
RowDimensions = new[]
{
Padding = new MarginPadding
new Dimension(GridSizeMode.Distributed),
new Dimension(GridSizeMode.AutoSize),
},
Content = new[]
{
new Drawable[]
{
Horizontal = OsuScreen.HORIZONTAL_OVERFLOW_PADDING,
Vertical = 10
},
RelativeSizeAxes = Axes.Both,
Children = new[]
{
new Container
new OsuScrollContainer
{
Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING },
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
Padding = new MarginPadding
{
new SectionContainer
Horizontal = OsuScreen.HORIZONTAL_OVERFLOW_PADDING,
Vertical = 10
},
RelativeSizeAxes = Axes.Both,
Children = new[]
{
new Container
{
Padding = new MarginPadding { Right = field_padding / 2 },
Children = new[]
Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING },
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{
new Section("Room name")
new SectionContainer
{
Child = NameField = new SettingsTextBox
Padding = new MarginPadding { Right = field_padding / 2 },
Children = new[]
{
RelativeSizeAxes = Axes.X,
TabbableContentContainer = this,
OnCommit = (sender, text) => apply(),
},
},
new Section("Duration")
{
Child = DurationField = new DurationDropdown
{
RelativeSizeAxes = Axes.X,
Items = new[]
new Section("Room name")
{
TimeSpan.FromMinutes(30),
TimeSpan.FromHours(1),
TimeSpan.FromHours(2),
TimeSpan.FromHours(4),
TimeSpan.FromHours(8),
TimeSpan.FromHours(12),
//TimeSpan.FromHours(16),
TimeSpan.FromHours(24),
TimeSpan.FromDays(3),
TimeSpan.FromDays(7)
}
}
},
new Section("Room visibility")
{
Alpha = disabled_alpha,
Child = AvailabilityPicker = new RoomAvailabilityPicker
{
Enabled = { Value = false }
},
},
new Section("Game type")
{
Alpha = disabled_alpha,
Child = new FillFlowContainer
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Direction = FillDirection.Vertical,
Spacing = new Vector2(7),
Children = new Drawable[]
{
TypePicker = new GameTypePicker
Child = NameField = new SettingsTextBox
{
RelativeSizeAxes = Axes.X,
Enabled = { Value = false }
},
typeLabel = new OsuSpriteText
{
Font = OsuFont.GetFont(size: 14),
Colour = colours.Yellow
TabbableContentContainer = this,
OnCommit = (sender, text) => apply(),
},
},
},
},
new Section("Max participants")
{
Alpha = disabled_alpha,
Child = MaxParticipantsField = new SettingsNumberTextBox
{
RelativeSizeAxes = Axes.X,
TabbableContentContainer = this,
ReadOnly = true,
OnCommit = (sender, text) => apply()
},
},
new Section("Password (optional)")
{
Alpha = disabled_alpha,
Child = new SettingsPasswordTextBox
{
RelativeSizeAxes = Axes.X,
TabbableContentContainer = this,
ReadOnly = true,
OnCommit = (sender, text) => apply()
},
},
},
},
new SectionContainer
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
Padding = new MarginPadding { Left = field_padding / 2 },
Children = new[]
{
new Section("Playlist")
{
Child = new GridContainer
{
RelativeSizeAxes = Axes.X,
Height = 300,
Content = new[]
new Section("Duration")
{
new Drawable[]
Child = DurationField = new DurationDropdown
{
playlist = new DrawableRoomPlaylist(true, true) { RelativeSizeAxes = Axes.Both }
},
new Drawable[]
{
new PurpleTriangleButton
RelativeSizeAxes = Axes.X,
Items = new[]
{
RelativeSizeAxes = Axes.X,
Height = 40,
Text = "Edit playlist",
Action = () => EditPlaylist?.Invoke()
TimeSpan.FromMinutes(30),
TimeSpan.FromHours(1),
TimeSpan.FromHours(2),
TimeSpan.FromHours(4),
TimeSpan.FromHours(8),
TimeSpan.FromHours(12),
//TimeSpan.FromHours(16),
TimeSpan.FromHours(24),
TimeSpan.FromDays(3),
TimeSpan.FromDays(7)
}
}
},
RowDimensions = new[]
new Section("Room visibility")
{
new Dimension(),
new Dimension(GridSizeMode.AutoSize),
}
}
Alpha = disabled_alpha,
Child = AvailabilityPicker = new RoomAvailabilityPicker
{
Enabled = { Value = false }
},
},
new Section("Game type")
{
Alpha = disabled_alpha,
Child = new FillFlowContainer
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Direction = FillDirection.Vertical,
Spacing = new Vector2(7),
Children = new Drawable[]
{
TypePicker = new GameTypePicker
{
RelativeSizeAxes = Axes.X,
Enabled = { Value = false }
},
typeLabel = new OsuSpriteText
{
Font = OsuFont.GetFont(size: 14),
Colour = colours.Yellow
},
},
},
},
new Section("Max participants")
{
Alpha = disabled_alpha,
Child = MaxParticipantsField = new SettingsNumberTextBox
{
RelativeSizeAxes = Axes.X,
TabbableContentContainer = this,
ReadOnly = true,
OnCommit = (sender, text) => apply()
},
},
new Section("Password (optional)")
{
Alpha = disabled_alpha,
Child = new SettingsPasswordTextBox
{
RelativeSizeAxes = Axes.X,
TabbableContentContainer = this,
ReadOnly = true,
OnCommit = (sender, text) => apply()
},
},
},
},
new SectionContainer
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
Padding = new MarginPadding { Left = field_padding / 2 },
Children = new[]
{
new Section("Playlist")
{
Child = new GridContainer
{
RelativeSizeAxes = Axes.X,
Height = 300,
Content = new[]
{
new Drawable[]
{
playlist = new DrawableRoomPlaylist(true, true) { RelativeSizeAxes = Axes.Both }
},
new Drawable[]
{
new PurpleTriangleButton
{
RelativeSizeAxes = Axes.X,
Height = 40,
Text = "Edit playlist",
Action = () => EditPlaylist?.Invoke()
}
}
},
RowDimensions = new[]
{
new Dimension(),
new Dimension(GridSizeMode.AutoSize),
}
}
},
},
},
},
},
}
},
}
},
},
},
new Drawable[]
{
new Container
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Y = 2,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.FromHex(@"28242d").Darken(0.5f).Opacity(1f),
},
new FillFlowContainer
},
new Drawable[]
{
new Container
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Y = 2,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 20),
Margin = new MarginPadding { Vertical = 20 },
Padding = new MarginPadding { Horizontal = OsuScreen.HORIZONTAL_OVERFLOW_PADDING },
Children = new Drawable[]
{
ApplyButton = new CreateRoomButton
new Box
{
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
Size = new Vector2(230, 55),
Enabled = { Value = false },
Action = apply,
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.FromHex(@"28242d").Darken(0.5f).Opacity(1f),
},
ErrorText = new OsuSpriteText
new FillFlowContainer
{
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
Alpha = 0,
Depth = 1,
Colour = colours.RedDark
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 20),
Margin = new MarginPadding { Vertical = 20 },
Padding = new MarginPadding { Horizontal = OsuScreen.HORIZONTAL_OVERFLOW_PADDING },
Children = new Drawable[]
{
ApplyButton = new CreateRoomButton
{
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
Size = new Vector2(230, 55),
Enabled = { Value = false },
Action = apply,
},
ErrorText = new OsuSpriteText
{
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
Alpha = 0,
Depth = 1,
Colour = colours.RedDark
}
}
}
}
}
}
}
}
},
}
},
processingOverlay = new ProcessingOverlay { Alpha = 0 }
processingOverlay = new ProcessingOverlay(dimContent)
};
TypePicker.Current.BindValueChanged(type => typeLabel.Text = type.NewValue?.Name ?? string.Empty, true);