1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-21 23:51:01 +08:00

Compare commits

...

39 Commits

17 changed files with 200 additions and 53 deletions
+1 -1
View File
@@ -42,7 +42,7 @@ body:
- type: input
attributes:
label: Version
description: The version you encountered this bug on. This is shown at the bottom of the main menu and also at the end of the settings screen.
description: The version you encountered this bug on. This is shown at the end of the settings overlay.
validations:
required: true
- type: markdown
@@ -19,6 +19,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
{
public partial class ArgonJudgementPiece : JudgementPiece, IAnimatableJudgement
{
private const float judgement_y_position = 160;
private RingExplosion? ringExplosion;
[Resolved]
@@ -30,7 +32,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
AutoSizeAxes = Axes.Both;
Origin = Anchor.Centre;
Y = 160;
Y = judgement_y_position;
}
[BackgroundDependencyLoader]
@@ -76,7 +78,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
this.ScaleTo(1.6f);
this.ScaleTo(1, 100, Easing.In);
this.MoveTo(Vector2.Zero);
this.MoveToY(judgement_y_position);
this.MoveToOffset(new Vector2(0, 100), 800, Easing.InQuint);
this.RotateTo(0);
@@ -25,6 +25,7 @@ using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.Taiko;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Compose.Components.Timeline;
using osu.Game.Screens.Edit.Setup;
using osu.Game.Storyboards;
using osu.Game.Tests.Resources;
@@ -94,8 +95,11 @@ namespace osu.Game.Tests.Visual.Editing
[Test]
public void TestAddAudioTrack()
{
AddAssert("track is virtual", () => Beatmap.Value.Track is TrackVirtual);
AddStep("enter compose mode", () => InputManager.Key(Key.F1));
AddUntilStep("wait for timeline load", () => Editor.ChildrenOfType<Timeline>().FirstOrDefault()?.IsLoaded == true);
AddStep("enter setup mode", () => InputManager.Key(Key.F4));
AddAssert("track is virtual", () => Beatmap.Value.Track is TrackVirtual);
AddAssert("switch track to real track", () =>
{
var setup = Editor.ChildrenOfType<SetupScreen>().First();
@@ -3,33 +3,40 @@
using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Screens.Menu;
using osuTK.Input;
namespace osu.Game.Tests.Visual.Menus
{
public partial class TestSceneMainMenu : OsuGameTestScene
{
private SystemTitle systemTitle => Game.ChildrenOfType<SystemTitle>().Single();
[Test]
public void TestSystemTitle()
{
AddStep("set system title", () => Game.ChildrenOfType<SystemTitle>().Single().Current.Value = new APISystemTitle
AddStep("set system title", () => systemTitle.Current.Value = new APISystemTitle
{
Image = @"https://assets.ppy.sh/main-menu/project-loved-2@2x.png",
Url = @"https://osu.ppy.sh/home/news/2023-12-21-project-loved-december-2023",
});
AddStep("set another title", () => Game.ChildrenOfType<SystemTitle>().Single().Current.Value = new APISystemTitle
AddAssert("system title not visible", () => systemTitle.State.Value, () => Is.EqualTo(Visibility.Hidden));
AddStep("enter menu", () => InputManager.Key(Key.Enter));
AddUntilStep("system title visible", () => systemTitle.State.Value, () => Is.EqualTo(Visibility.Visible));
AddStep("set another title", () => systemTitle.Current.Value = new APISystemTitle
{
Image = @"https://assets.ppy.sh/main-menu/wf2023-vote@2x.png",
Url = @"https://osu.ppy.sh/community/contests/189",
});
AddStep("set title with nonexistent image", () => Game.ChildrenOfType<SystemTitle>().Single().Current.Value = new APISystemTitle
AddStep("set title with nonexistent image", () => systemTitle.Current.Value = new APISystemTitle
{
Image = @"https://test.invalid/@2x", // .invalid TLD reserved by https://datatracker.ietf.org/doc/html/rfc2606#section-2
Url = @"https://osu.ppy.sh/community/contests/189",
});
AddStep("unset system title", () => Game.ChildrenOfType<SystemTitle>().Single().Current.Value = null);
AddStep("unset system title", () => systemTitle.Current.Value = null);
}
}
}
@@ -3,7 +3,7 @@
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Utils;
@@ -25,9 +25,15 @@ namespace osu.Game.Tests.Visual.Settings
private Container content = null!;
protected override Container Content => content;
private OsuConfigManager localConfig = null!;
private AudioOffsetAdjustControl adjustControl = null!;
[BackgroundDependencyLoader]
private void load()
{
localConfig = new OsuConfigManager(LocalStorage);
Dependencies.CacheAs(localConfig);
base.Content.AddRange(new Drawable[]
{
tracker,
@@ -41,17 +47,21 @@ namespace osu.Game.Tests.Visual.Settings
});
}
[Test]
public void TestBehaviour()
[SetUp]
public void SetUp() => Schedule(() =>
{
AddStep("create control", () => Child = new AudioOffsetAdjustControl
Child = adjustControl = new AudioOffsetAdjustControl
{
Current = new BindableDouble
{
MinValue = -500,
MaxValue = 500
}
});
Current = localConfig.GetBindable<double>(OsuSetting.AudioOffset),
};
localConfig.SetValue(OsuSetting.AudioOffset, 0.0);
tracker.ClearHistory();
});
[Test]
public void TestDisplay()
{
AddStep("set new score", () => statics.SetValue(Static.LastLocalUserScore, new ScoreInfo
{
HitEvents = TestSceneHitEventTimingDistributionGraph.CreateDistributedHitEvents(RNG.NextDouble(-100, 100)),
@@ -59,5 +69,63 @@ namespace osu.Game.Tests.Visual.Settings
}));
AddStep("clear history", () => tracker.ClearHistory());
}
[Test]
public void TestBehaviour()
{
AddStep("set score with -20ms", () => setScore(-20));
AddAssert("suggested global offset is 20ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(20));
AddStep("clear history", () => tracker.ClearHistory());
AddStep("set score with 40ms", () => setScore(40));
AddAssert("suggested global offset is -40ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(-40));
AddStep("clear history", () => tracker.ClearHistory());
}
[Test]
public void TestNonZeroGlobalOffset()
{
AddStep("set global offset to -20ms", () => localConfig.SetValue(OsuSetting.AudioOffset, -20.0));
AddStep("set score with -20ms", () => setScore(-20));
AddAssert("suggested global offset is 0ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(0));
AddStep("clear history", () => tracker.ClearHistory());
AddStep("set global offset to 20ms", () => localConfig.SetValue(OsuSetting.AudioOffset, 20.0));
AddStep("set score with 40ms", () => setScore(40));
AddAssert("suggested global offset is -20ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(-20));
AddStep("clear history", () => tracker.ClearHistory());
}
[Test]
public void TestMultiplePlays()
{
AddStep("set score with -20ms", () => setScore(-20));
AddStep("set score with -10ms", () => setScore(-10));
AddAssert("suggested global offset is 15ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(15));
AddStep("clear history", () => tracker.ClearHistory());
AddStep("set score with -20ms", () => setScore(-20));
AddStep("set global offset to 30ms", () => localConfig.SetValue(OsuSetting.AudioOffset, 30.0));
AddStep("set score with 10ms", () => setScore(10));
AddAssert("suggested global offset is 20ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(20));
AddStep("clear history", () => tracker.ClearHistory());
}
private void setScore(double averageHitError)
{
statics.SetValue(Static.LastLocalUserScore, new ScoreInfo
{
HitEvents = TestSceneHitEventTimingDistributionGraph.CreateDistributedHitEvents(averageHitError),
BeatmapInfo = Beatmap.Value.BeatmapInfo,
});
}
protected override void Dispose(bool isDisposing)
{
if (localConfig.IsNotNull())
localConfig.Dispose();
base.Dispose(isDisposing);
}
}
}
@@ -17,11 +17,14 @@ namespace osu.Game.Configuration
[Cached]
public partial class SessionAverageHitErrorTracker : Component
{
public IBindableList<double> AverageHitErrorHistory => averageHitErrorHistory;
private readonly BindableList<double> averageHitErrorHistory = new BindableList<double>();
public IBindableList<DataPoint> AverageHitErrorHistory => averageHitErrorHistory;
private readonly BindableList<DataPoint> averageHitErrorHistory = new BindableList<DataPoint>();
private readonly Bindable<ScoreInfo?> latestScore = new Bindable<ScoreInfo?>();
[Resolved]
private OsuConfigManager configManager { get; set; } = null!;
[BackgroundDependencyLoader]
private void load(SessionStatics statics)
{
@@ -46,9 +49,25 @@ namespace osu.Game.Configuration
// keep a sane maximum number of entries.
if (averageHitErrorHistory.Count >= 50)
averageHitErrorHistory.RemoveAt(0);
averageHitErrorHistory.Add(averageError);
double globalOffset = configManager.Get<double>(OsuSetting.AudioOffset);
averageHitErrorHistory.Add(new DataPoint(averageError, globalOffset));
}
public void ClearHistory() => averageHitErrorHistory.Clear();
public readonly struct DataPoint
{
public double AverageHitError { get; }
public double GlobalAudioOffset { get; }
public double SuggestedGlobalAudioOffset => GlobalAudioOffset - AverageHitError;
public DataPoint(double averageHitError, double globalOffset)
{
AverageHitError = averageHitError;
GlobalAudioOffset = globalOffset;
}
}
}
}
@@ -363,6 +363,7 @@ namespace osu.Game.Graphics.UserInterface
base.LoadComplete();
SearchBar.State.ValueChanged += _ => updateColour();
Enabled.BindValueChanged(_ => updateColour());
updateColour();
}
@@ -383,6 +384,9 @@ namespace osu.Game.Graphics.UserInterface
var hoveredColour = colourProvider?.Light4 ?? colours.PinkDarker;
var unhoveredColour = colourProvider?.Background5 ?? Color4.Black.Opacity(0.5f);
Colour = Color4.White;
Alpha = Enabled.Value ? 1 : 0.3f;
if (SearchBar.State.Value == Visibility.Visible)
{
Icon.Colour = hovered ? hoveredColour.Lighten(0.5f) : Colour4.White;
+1 -1
View File
@@ -994,7 +994,7 @@ namespace osu.Game
Margin = new MarginPadding(5),
}, topMostOverlayContent.Add);
if (!args?.Any(a => a == @"--no-version-overlay") ?? true)
if (!IsDeployedBuild)
{
dependencies.Cache(versionManager = new VersionManager { Depth = int.MinValue });
loadComponentSingleFile(versionManager, ScreenContainer.Add);
@@ -145,7 +145,7 @@ namespace osu.Game.Overlays.Profile.Header
bool anyInfoAdded = false;
anyInfoAdded |= tryAddInfo(FontAwesome.Solid.MapMarker, user.Location);
anyInfoAdded |= tryAddInfo(OsuIcon.Heart, user.Interests);
anyInfoAdded |= tryAddInfo(FontAwesome.Solid.Heart, user.Interests);
anyInfoAdded |= tryAddInfo(FontAwesome.Solid.Suitcase, user.Occupation);
if (anyInfoAdded)
@@ -24,6 +24,8 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
{
public partial class AudioOffsetAdjustControl : SettingsItem<double>
{
public IBindable<double?> SuggestedOffset => ((AudioOffsetPreview)Control).SuggestedOffset;
[BackgroundDependencyLoader]
private void load()
{
@@ -42,9 +44,9 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
private readonly BindableNumberWithCurrent<double> current = new BindableNumberWithCurrent<double>();
private readonly IBindableList<double> averageHitErrorHistory = new BindableList<double>();
private readonly IBindableList<SessionAverageHitErrorTracker.DataPoint> averageHitErrorHistory = new BindableList<SessionAverageHitErrorTracker.DataPoint>();
private readonly Bindable<double?> suggestedOffset = new Bindable<double?>();
public readonly Bindable<double?> SuggestedOffset = new Bindable<double?>();
private Container<Box> notchContainer = null!;
private TextFlowContainer hintText = null!;
@@ -90,8 +92,8 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
Text = "Apply suggested offset",
Action = () =>
{
if (suggestedOffset.Value.HasValue)
current.Value = suggestedOffset.Value.Value;
if (SuggestedOffset.Value.HasValue)
current.Value = SuggestedOffset.Value.Value;
hitErrorTracker.ClearHistory();
}
}
@@ -104,7 +106,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
base.LoadComplete();
averageHitErrorHistory.BindCollectionChanged(updateDisplay, true);
suggestedOffset.BindValueChanged(_ => updateHintText(), true);
SuggestedOffset.BindValueChanged(_ => updateHintText(), true);
}
private void updateDisplay(object? _, NotifyCollectionChangedEventArgs e)
@@ -112,7 +114,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (double average in e.NewItems!)
foreach (SessionAverageHitErrorTracker.DataPoint dataPoint in e.NewItems!)
{
notchContainer.ForEach(n => n.Alpha *= 0.95f);
notchContainer.Add(new Box
@@ -122,16 +124,16 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
RelativePositionAxes = Axes.X,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
X = getXPositionForAverage(average)
X = getXPositionForOffset(dataPoint.SuggestedGlobalAudioOffset)
});
}
break;
case NotifyCollectionChangedAction.Remove:
foreach (double average in e.OldItems!)
foreach (SessionAverageHitErrorTracker.DataPoint dataPoint in e.OldItems!)
{
var notch = notchContainer.FirstOrDefault(n => n.X == getXPositionForAverage(average));
var notch = notchContainer.FirstOrDefault(n => n.X == getXPositionForOffset(dataPoint.SuggestedGlobalAudioOffset));
Debug.Assert(notch != null);
notchContainer.Remove(notch, true);
}
@@ -143,17 +145,17 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
break;
}
suggestedOffset.Value = averageHitErrorHistory.Any() ? -averageHitErrorHistory.Average() : null;
SuggestedOffset.Value = averageHitErrorHistory.Any() ? averageHitErrorHistory.Average(dataPoint => dataPoint.SuggestedGlobalAudioOffset) : null;
}
private float getXPositionForAverage(double average) => (float)(Math.Clamp(-average, current.MinValue, current.MaxValue) / (2 * current.MaxValue));
private float getXPositionForOffset(double offset) => (float)(Math.Clamp(offset, current.MinValue, current.MaxValue) / (2 * current.MaxValue));
private void updateHintText()
{
hintText.Text = suggestedOffset.Value == null
hintText.Text = SuggestedOffset.Value == null
? @"Play a few beatmaps to receive a suggested offset!"
: $@"Based on the last {averageHitErrorHistory.Count} play(s), the suggested offset is {suggestedOffset.Value:N0} ms.";
applySuggestion.Enabled.Value = suggestedOffset.Value != null;
: $@"Based on the last {averageHitErrorHistory.Count} play(s), the suggested offset is {SuggestedOffset.Value:N0} ms.";
applySuggestion.Enabled.Value = SuggestedOffset.Value != null;
}
}
}
@@ -40,8 +40,6 @@ namespace osu.Game.Overlays.Toolbar
[BackgroundDependencyLoader]
private void load(OsuColour colours, IAPIProvider api, LoginOverlay? login)
{
BackgroundContent.Add(new OpaqueBackground { Depth = 1 });
Flow.Add(new Container
{
Masking = true,
+1 -1
View File
@@ -195,7 +195,7 @@ namespace osu.Game.Rulesets.Mods
/// <summary>
/// Whether all settings in this mod are set to their default state.
/// </summary>
protected virtual bool UsesDefaultConfiguration => SettingsBindables.All(s => s.IsDefault);
public virtual bool UsesDefaultConfiguration => SettingsBindables.All(s => s.IsDefault);
/// <summary>
/// Creates a copy of this <see cref="Mod"/> initialised to a default state.
@@ -144,13 +144,26 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
track.BindValueChanged(_ =>
{
waveform.Waveform = beatmap.Value.Waveform;
waveform.RelativePositionAxes = Axes.X;
waveform.X = -(float)(Editor.WAVEFORM_VISUAL_OFFSET / beatmap.Value.Track.Length);
Scheduler.AddOnce(applyVisualOffset, beatmap);
}, true);
Zoom = (float)(defaultTimelineZoom * editorBeatmap.BeatmapInfo.TimelineZoom);
}
private void applyVisualOffset(IBindable<WorkingBeatmap> beatmap)
{
waveform.RelativePositionAxes = Axes.X;
if (beatmap.Value.Track.Length > 0)
waveform.X = -(float)(Editor.WAVEFORM_VISUAL_OFFSET / beatmap.Value.Track.Length);
else
{
// sometimes this can be the case immediately after a track switch.
// reschedule with the hope that the track length eventually populates.
Scheduler.AddOnce(applyVisualOffset, beatmap);
}
}
protected override void LoadComplete()
{
base.LoadComplete();
+4 -1
View File
@@ -94,6 +94,7 @@ namespace osu.Game.Screens.Menu
private ParallaxContainer buttonsContainer;
private SongTicker songTicker;
private Container logoTarget;
private SystemTitle systemTitle;
private MenuTip menuTip;
private FillFlowContainer bottomElementsFlow;
private SupporterDisplay supporterDisplay;
@@ -173,7 +174,7 @@ namespace osu.Game.Screens.Menu
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
},
new SystemTitle
systemTitle = new SystemTitle
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
@@ -196,10 +197,12 @@ namespace osu.Game.Screens.Menu
case ButtonSystemState.Initial:
case ButtonSystemState.Exit:
ApplyToBackground(b => b.FadeColour(Color4.White, 500, Easing.OutSine));
systemTitle.State.Value = Visibility.Hidden;
break;
default:
ApplyToBackground(b => b.FadeColour(OsuColour.Gray(0.8f), 500, Easing.OutSine));
systemTitle.State.Value = Visibility.Visible;
break;
}
};
+11 -6
View File
@@ -31,6 +31,9 @@ namespace osu.Game.Screens.Menu
/// </summary>
public partial class MainMenuButton : BeatSyncedContainer, IStateful<ButtonState>
{
public const float BOUNCE_COMPRESSION = 0.9f;
public const float HOVER_SCALE = 1.2f;
public const float BOUNCE_ROTATION = 8;
public event Action<ButtonState>? StateChanged;
public readonly Key[] TriggerKeys;
@@ -125,8 +128,9 @@ namespace osu.Game.Screens.Menu
Shadow = true,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(30),
Size = new Vector2(32),
Position = new Vector2(0, 0),
Margin = new MarginPadding { Top = -4 },
Icon = symbol
},
new OsuSpriteText
@@ -136,6 +140,7 @@ namespace osu.Game.Screens.Menu
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Position = new Vector2(0, 35),
Margin = new MarginPadding { Left = -3 },
Text = text
}
}
@@ -153,14 +158,14 @@ namespace osu.Game.Screens.Menu
double duration = timingPoint.BeatLength / 2;
icon.RotateTo(rightward ? 10 : -10, duration * 2, Easing.InOutSine);
icon.RotateTo(rightward ? BOUNCE_ROTATION : -BOUNCE_ROTATION, duration * 2, Easing.InOutSine);
icon.Animate(
i => i.MoveToY(-10, duration, Easing.Out),
i => i.ScaleTo(1, duration, Easing.Out)
i => i.ScaleTo(HOVER_SCALE, duration, Easing.Out)
).Then(
i => i.MoveToY(0, duration, Easing.In),
i => i.ScaleTo(new Vector2(1, 0.9f), duration, Easing.In)
i => i.ScaleTo(new Vector2(HOVER_SCALE, HOVER_SCALE * BOUNCE_COMPRESSION), duration, Easing.In)
);
rightward = !rightward;
@@ -177,8 +182,8 @@ namespace osu.Game.Screens.Menu
double duration = TimeUntilNextBeat;
icon.ClearTransforms();
icon.RotateTo(rightward ? -10 : 10, duration, Easing.InOutSine);
icon.ScaleTo(new Vector2(1, 0.9f), duration, Easing.Out);
icon.RotateTo(rightward ? -BOUNCE_ROTATION : BOUNCE_ROTATION, duration, Easing.InOutSine);
icon.ScaleTo(new Vector2(HOVER_SCALE, HOVER_SCALE * BOUNCE_COMPRESSION), duration, Easing.Out);
return true;
}
+15 -3
View File
@@ -94,14 +94,14 @@ namespace osu.Game.Screens.Menu
{
string[] tips =
{
"You can press Ctrl-T anywhere in the game to toggle the toolbar!",
"You can press Ctrl-O anywhere in the game to access options!",
"Press Ctrl-T anywhere in the game to toggle the toolbar!",
"Press Ctrl-O anywhere in the game to access options!",
"All settings are dynamic and take effect in real-time. Try changing the skin while watching autoplay!",
"New features are coming online every update. Make sure to stay up-to-date!",
"If you find the UI too large or small, try adjusting UI scale in settings!",
"Try adjusting the \"Screen Scaling\" mode to change your gameplay or UI area, even in fullscreen!",
"What used to be \"osu!direct\" is available to all users just like on the website. You can access it anywhere using Ctrl-B!",
"Seeking in replays is available by dragging on the difficulty bar at the bottom of the screen!",
"Seeking in replays is available by dragging on the progress bar at the bottom of the screen or by using the left and right arrow keys!",
"Multithreading support means that even with low \"FPS\" your input and judgements will be accurate!",
"Try scrolling right in mod select to find a bunch of new fun mods!",
"Most of the web content (profiles, rankings, etc.) are available natively in-game from the icons on the toolbar!",
@@ -110,6 +110,18 @@ namespace osu.Game.Screens.Menu
"Check out the \"playlists\" system, which lets users create their own custom and permanent leaderboards!",
"Toggle advanced frame / thread statistics with Ctrl-F11!",
"Take a look under the hood at performance counters and enable verbose performance logging with Ctrl-F2!",
"You can pause during a replay by pressing Space!",
"Most of the hotkeys in the game are configurable and can be changed to anything you want. Check the bindings panel under input settings!",
"When your gameplay HUD is hidden, you can press and hold Ctrl to view it temporarily!",
"Your gameplay HUD can be customized by using the skin layout editor. Open it at any time via Ctrl-Shift-S!",
"Drag and drop any image into the skin editor to load it in quickly!",
"You can create mod presets to make toggling your favorite mod combinations easier!",
"Many mods have customisation settings that drastically change how they function. Click the Mod Customisation button in mod select to view settings!",
"Press Ctrl-Shift-R to switch to a random skin!",
"Press Ctrl-Shift-F to toggle the FPS Counter. But make sure not to pay too much attention to it!",
"While watching a replay, press Ctrl-H to toggle replay settings!",
"You can easily copy the mods from scores on a leaderboard by right-clicking on them!",
"Ctrl-Enter at song select will start a beatmap in autoplay mode!"
};
return tips[RNG.Next(0, tips.Length)];
+11 -1
View File
@@ -18,10 +18,12 @@ using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Screens.Menu
{
public partial class SystemTitle : CompositeDrawable
public partial class SystemTitle : VisibilityContainer
{
internal Bindable<APISystemTitle?> Current { get; } = new Bindable<APISystemTitle?>();
private const float transition_duration = 500;
private Container content = null!;
private CancellationTokenSource? cancellationTokenSource;
private SystemTitleImage? currentImage;
@@ -32,9 +34,13 @@ namespace osu.Game.Screens.Menu
private void load(OsuGame? game)
{
AutoSizeAxes = Axes.Both;
AutoSizeDuration = transition_duration;
AutoSizeEasing = Easing.OutQuint;
InternalChild = content = new OsuClickableContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.Both,
Action = () =>
{
@@ -51,6 +57,10 @@ namespace osu.Game.Screens.Menu
};
}
protected override void PopIn() => content.FadeInFromZero(transition_duration, Easing.OutQuint);
protected override void PopOut() => content.FadeOut(transition_duration, Easing.OutQuint);
protected override bool OnHover(HoverEvent e)
{
content.ScaleTo(1.05f, 2000, Easing.OutQuint);