mirror of
https://github.com/ppy/osu.git
synced 2025-02-06 22:33:13 +08:00
Merge branch 'master' into editor-beat-snap-adjust-scroll
This commit is contained in:
commit
1f90be3fea
@ -10,7 +10,7 @@
|
|||||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2024.1220.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2024.1224.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Fody does not handle Android build well, and warns when unchanged.
|
<!-- Fody does not handle Android build well, and warns when unchanged.
|
||||||
|
15
osu.Game.Rulesets.Catch.Tests.iOS/AppDelegate.cs
Normal file
15
osu.Game.Rulesets.Catch.Tests.iOS/AppDelegate.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// 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 Foundation;
|
||||||
|
using osu.Framework.iOS;
|
||||||
|
using osu.Game.Tests;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Tests.iOS
|
||||||
|
{
|
||||||
|
[Register("AppDelegate")]
|
||||||
|
public class AppDelegate : GameApplicationDelegate
|
||||||
|
{
|
||||||
|
protected override Framework.Game CreateGame() => new OsuTestBrowser();
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,15 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Framework.iOS;
|
using UIKit;
|
||||||
using osu.Game.Tests;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Tests.iOS
|
namespace osu.Game.Rulesets.Catch.Tests.iOS
|
||||||
{
|
{
|
||||||
public static class Application
|
public static class Program
|
||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
GameApplication.Main(new OsuTestBrowser());
|
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
15
osu.Game.Rulesets.Mania.Tests.iOS/AppDelegate.cs
Normal file
15
osu.Game.Rulesets.Mania.Tests.iOS/AppDelegate.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// 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 Foundation;
|
||||||
|
using osu.Framework.iOS;
|
||||||
|
using osu.Game.Tests;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests.iOS
|
||||||
|
{
|
||||||
|
[Register("AppDelegate")]
|
||||||
|
public class AppDelegate : GameApplicationDelegate
|
||||||
|
{
|
||||||
|
protected override Framework.Game CreateGame() => new OsuTestBrowser();
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,15 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Framework.iOS;
|
using UIKit;
|
||||||
using osu.Game.Tests;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Tests.iOS
|
namespace osu.Game.Rulesets.Mania.Tests.iOS
|
||||||
{
|
{
|
||||||
public static class Application
|
public static class Program
|
||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
GameApplication.Main(new OsuTestBrowser());
|
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
15
osu.Game.Rulesets.Osu.Tests.iOS/AppDelegate.cs
Normal file
15
osu.Game.Rulesets.Osu.Tests.iOS/AppDelegate.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// 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 Foundation;
|
||||||
|
using osu.Framework.iOS;
|
||||||
|
using osu.Game.Tests;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Tests.iOS
|
||||||
|
{
|
||||||
|
[Register("AppDelegate")]
|
||||||
|
public class AppDelegate : GameApplicationDelegate
|
||||||
|
{
|
||||||
|
protected override Framework.Game CreateGame() => new OsuTestBrowser();
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,15 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Framework.iOS;
|
using UIKit;
|
||||||
using osu.Game.Tests;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Tests.iOS
|
namespace osu.Game.Rulesets.Osu.Tests.iOS
|
||||||
{
|
{
|
||||||
public static class Application
|
public static class Program
|
||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
GameApplication.Main(new OsuTestBrowser());
|
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
15
osu.Game.Rulesets.Taiko.Tests.iOS/AppDelegate.cs
Normal file
15
osu.Game.Rulesets.Taiko.Tests.iOS/AppDelegate.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// 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 Foundation;
|
||||||
|
using osu.Framework.iOS;
|
||||||
|
using osu.Game.Tests;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Taiko.Tests.iOS
|
||||||
|
{
|
||||||
|
[Register("AppDelegate")]
|
||||||
|
public class AppDelegate : GameApplicationDelegate
|
||||||
|
{
|
||||||
|
protected override Framework.Game CreateGame() => new OsuTestBrowser();
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,15 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Framework.iOS;
|
using UIKit;
|
||||||
using osu.Game.Tests;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Tests.iOS
|
namespace osu.Game.Rulesets.Taiko.Tests.iOS
|
||||||
{
|
{
|
||||||
public static class Application
|
public static class Program
|
||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
GameApplication.Main(new OsuTestBrowser());
|
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
14
osu.Game.Tests.iOS/AppDelegate.cs
Normal file
14
osu.Game.Tests.iOS/AppDelegate.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// 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 Foundation;
|
||||||
|
using osu.Framework.iOS;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.iOS
|
||||||
|
{
|
||||||
|
[Register("AppDelegate")]
|
||||||
|
public class AppDelegate : GameApplicationDelegate
|
||||||
|
{
|
||||||
|
protected override Framework.Game CreateGame() => new OsuTestBrowser();
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,15 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Framework.iOS;
|
using UIKit;
|
||||||
|
|
||||||
namespace osu.Game.Tests.iOS
|
namespace osu.Game.Tests.iOS
|
||||||
{
|
{
|
||||||
public static class Application
|
public static class Program
|
||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
GameApplication.Main(new OsuTestBrowser());
|
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
BIN
osu.Game.Tests/Resources/Archives/modified-default-20241207.osk
Normal file
BIN
osu.Game.Tests/Resources/Archives/modified-default-20241207.osk
Normal file
Binary file not shown.
@ -68,7 +68,9 @@ namespace osu.Game.Tests.Skins
|
|||||||
// Covers legacy rank display
|
// Covers legacy rank display
|
||||||
"Archives/modified-classic-20230809.osk",
|
"Archives/modified-classic-20230809.osk",
|
||||||
// Covers legacy key counter
|
// Covers legacy key counter
|
||||||
"Archives/modified-classic-20240724.osk"
|
"Archives/modified-classic-20240724.osk",
|
||||||
|
// Covers skinnable mod display
|
||||||
|
"Archives/modified-default-20241207.osk",
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -12,6 +12,7 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Cursor;
|
using osu.Game.Graphics.Cursor;
|
||||||
@ -19,6 +20,7 @@ using osu.Game.Rulesets;
|
|||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
using osu.Game.Storyboards;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Input;
|
using osuTK.Input;
|
||||||
|
|
||||||
@ -28,6 +30,12 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
protected new PausePlayer Player => (PausePlayer)base.Player;
|
protected new PausePlayer Player => (PausePlayer)base.Player;
|
||||||
|
|
||||||
|
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
|
||||||
|
{
|
||||||
|
beatmap.AudioLeadIn = 4000;
|
||||||
|
return base.CreateWorkingBeatmap(beatmap, storyboard);
|
||||||
|
}
|
||||||
|
|
||||||
private readonly Container content;
|
private readonly Container content;
|
||||||
|
|
||||||
protected override Container<Drawable> Content => content;
|
protected override Container<Drawable> Content => content;
|
||||||
@ -200,8 +208,10 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
[Ignore("Fails on github runners if they happen to skip too far forward in time.")]
|
||||||
public void TestUserPauseDuringCooldownTooSoon()
|
public void TestUserPauseDuringCooldownTooSoon()
|
||||||
{
|
{
|
||||||
|
AddStep("seek to gameplay", () => Player.GameplayClockContainer.Seek(0));
|
||||||
AddStep("move cursor outside", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopLeft - new Vector2(10)));
|
AddStep("move cursor outside", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopLeft - new Vector2(10)));
|
||||||
|
|
||||||
pauseAndConfirm();
|
pauseAndConfirm();
|
||||||
@ -213,9 +223,23 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
confirmNotExited();
|
confirmNotExited();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestUserPauseDuringIntroSkipsCooldown()
|
||||||
|
{
|
||||||
|
AddStep("seek before gameplay", () => Player.GameplayClockContainer.Seek(-5000));
|
||||||
|
AddStep("move cursor outside", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopLeft - new Vector2(10)));
|
||||||
|
|
||||||
|
pauseAndConfirm();
|
||||||
|
|
||||||
|
resume();
|
||||||
|
pauseViaBackAction();
|
||||||
|
confirmPaused();
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestQuickExitDuringCooldownTooSoon()
|
public void TestQuickExitDuringCooldownTooSoon()
|
||||||
{
|
{
|
||||||
|
AddStep("seek to gameplay", () => Player.GameplayClockContainer.Seek(0));
|
||||||
AddStep("move cursor outside", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopLeft - new Vector2(10)));
|
AddStep("move cursor outside", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopLeft - new Vector2(10)));
|
||||||
|
|
||||||
pauseAndConfirm();
|
pauseAndConfirm();
|
||||||
|
16
osu.Game.Tests/Visual/Menus/TestSceneIntroChristmas.cs
Normal file
16
osu.Game.Tests/Visual/Menus/TestSceneIntroChristmas.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// 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.Game.Screens.Menu;
|
||||||
|
using osu.Game.Seasonal;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Menus
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public partial class TestSceneIntroChristmas : IntroTestScene
|
||||||
|
{
|
||||||
|
protected override bool IntroReliesOnTrack => true;
|
||||||
|
protected override IntroScreen CreateScreen() => new IntroChristmas();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Seasonal;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Menus
|
||||||
|
{
|
||||||
|
public partial class TestSceneMainMenuSeasonalLighting : OsuTestScene
|
||||||
|
{
|
||||||
|
[Resolved]
|
||||||
|
private BeatmapManager beatmaps { get; set; } = null!;
|
||||||
|
|
||||||
|
[SetUpSteps]
|
||||||
|
public void SetUpSteps()
|
||||||
|
{
|
||||||
|
AddStep("prepare beatmap", () =>
|
||||||
|
{
|
||||||
|
var setInfo = beatmaps.QueryBeatmapSet(b => b.Protected && b.Hash == IntroChristmas.CHRISTMAS_BEATMAP_SET_HASH);
|
||||||
|
|
||||||
|
if (setInfo != null)
|
||||||
|
Beatmap.Value = beatmaps.GetWorkingBeatmap(setInfo.Value.Beatmaps.First());
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("create lighting", () => Child = new MainMenuSeasonalLighting());
|
||||||
|
|
||||||
|
AddStep("restart beatmap", () =>
|
||||||
|
{
|
||||||
|
Beatmap.Value.Track.Start();
|
||||||
|
Beatmap.Value.Track.Seek(4000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBasic()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,20 +4,52 @@
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Screens.Menu;
|
using osu.Game.Screens.Menu;
|
||||||
|
using osu.Game.Seasonal;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.UserInterface
|
namespace osu.Game.Tests.Visual.UserInterface
|
||||||
{
|
{
|
||||||
public partial class TestSceneOsuLogo : OsuTestScene
|
public partial class TestSceneOsuLogo : OsuTestScene
|
||||||
{
|
{
|
||||||
|
private OsuLogo? logo;
|
||||||
|
|
||||||
|
private float scale = 1;
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
AddSliderStep("scale", 0.1, 2, 1, scale =>
|
||||||
|
{
|
||||||
|
if (logo != null)
|
||||||
|
Child.Scale = new Vector2(this.scale = (float)scale);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestBasic()
|
public void TestBasic()
|
||||||
{
|
{
|
||||||
AddStep("Add logo", () =>
|
AddStep("Add logo", () =>
|
||||||
{
|
{
|
||||||
Child = new OsuLogo
|
Child = logo = new OsuLogo
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
|
Scale = new Vector2(scale),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestChristmas()
|
||||||
|
{
|
||||||
|
AddStep("Add logo", () =>
|
||||||
|
{
|
||||||
|
Child = logo = new OsuLogoChristmas
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Scale = new Vector2(scale),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ namespace osu.Game.Configuration
|
|||||||
SetDefault(OsuSetting.ChatDisplayHeight, ChatOverlay.DEFAULT_HEIGHT, 0.2f, 1f, 0.01f);
|
SetDefault(OsuSetting.ChatDisplayHeight, ChatOverlay.DEFAULT_HEIGHT, 0.2f, 1f, 0.01f);
|
||||||
|
|
||||||
SetDefault(OsuSetting.BeatmapListingCardSize, BeatmapCardSize.Normal);
|
SetDefault(OsuSetting.BeatmapListingCardSize, BeatmapCardSize.Normal);
|
||||||
|
SetDefault(OsuSetting.BeatmapListingFeaturedArtistFilter, true);
|
||||||
|
|
||||||
SetDefault(OsuSetting.ProfileCoverExpanded, true);
|
SetDefault(OsuSetting.ProfileCoverExpanded, true);
|
||||||
|
|
||||||
@ -450,5 +451,6 @@ namespace osu.Game.Configuration
|
|||||||
EditorAdjustExistingObjectsOnTimingChanges,
|
EditorAdjustExistingObjectsOnTimingChanges,
|
||||||
AlwaysRequireHoldingForPause,
|
AlwaysRequireHoldingForPause,
|
||||||
MultiplayerShowInProgressFilter,
|
MultiplayerShowInProgressFilter,
|
||||||
|
BeatmapListingFeaturedArtistFilter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,11 @@ This includes content that may not be correctly licensed for osu! usage. Browse
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static LocalisableString UserContentConfirmButtonText => new TranslatableString(getKey(@"understood"), @"I understand");
|
public static LocalisableString UserContentConfirmButtonText => new TranslatableString(getKey(@"understood"), @"I understand");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Featured Artists are music artists who have collaborated with osu! to make a selection of their tracks available for use in beatmaps. For some osu! releases, we showcase only featured artist beatmaps to better support the surrounding ecosystem."
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString FeaturedArtistsTooltip => new TranslatableString(getKey(@"featured_artists_disabled_tooltip"), @"Featured Artists are music artists who have collaborated with osu! to make a selection of their tracks available for use in beatmaps. For some osu! releases, we showcase only featured artist beatmaps to better support the surrounding ecosystem.");
|
||||||
|
|
||||||
private static string getKey(string key) => $@"{prefix}:{key}";
|
private static string getKey(string key) => $@"{prefix}:{key}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,6 +119,11 @@ namespace osu.Game.Localisation
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static LocalisableString AutoplayBeatmapShortcut => new TranslatableString(getKey(@"autoplay_beatmap_shortcut"), @"Ctrl-Enter at song select will start a beatmap in autoplay mode!");
|
public static LocalisableString AutoplayBeatmapShortcut => new TranslatableString(getKey(@"autoplay_beatmap_shortcut"), @"Ctrl-Enter at song select will start a beatmap in autoplay mode!");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ""Lazer" is not an English word. The correct spelling for the bright light is "laser"."
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString LazerIsNotAWord => new TranslatableString(getKey(@"lazer_is_not_a_word"), @"""Lazer"" is not an English word. The correct spelling for the bright light is ""laser"".");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// "Multithreading support means that even with low "FPS" your input and judgements will be accurate!"
|
/// "Multithreading support means that even with low "FPS" your input and judgements will be accurate!"
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
// 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.Localisation;
|
||||||
|
|
||||||
|
namespace osu.Game.Localisation.SkinComponents
|
||||||
|
{
|
||||||
|
public static class SkinnableModDisplayStrings
|
||||||
|
{
|
||||||
|
private const string prefix = @"osu.Game.Resources.Localisation.SkinnableModDisplay";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Show extended information"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString ShowExtendedInformation => new TranslatableString(getKey(@"show_extended_information"), @"Show extended information");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Whether to show extended information for each mod."
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString ShowExtendedInformationDescription => new TranslatableString(getKey(@"whether_to_show_extended_information"), @"Whether to show extended information for each mod.");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Expansion mode"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString ExpansionMode => new TranslatableString(getKey(@"expansion_mode"), @"Expansion mode");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "How the mod display expands when interacted with."
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString ExpansionModeDescription => new TranslatableString(getKey(@"how_the_mod_display_expands"), @"How the mod display expands when interacted with.");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Expand on hover"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString ExpandOnHover => new TranslatableString(getKey(@"expand_on_hover"), @"Expand on hover");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Always contracted"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString AlwaysContracted => new TranslatableString(getKey(@"always_contracted"), @"Always contracted");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Always expanded"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString AlwaysExpanded => new TranslatableString(getKey(@"always_expanded"), @"Always expanded");
|
||||||
|
|
||||||
|
private static string getKey(string key) => $@"{prefix}:{key}";
|
||||||
|
}
|
||||||
|
}
|
@ -54,16 +54,6 @@ namespace osu.Game.Localisation
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static LocalisableString BeatmapHitsounds => new TranslatableString(getKey(@"beatmap_hitsounds"), @"Beatmap hitsounds");
|
public static LocalisableString BeatmapHitsounds => new TranslatableString(getKey(@"beatmap_hitsounds"), @"Beatmap hitsounds");
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// "Export selected skin"
|
|
||||||
/// </summary>
|
|
||||||
public static LocalisableString ExportSkinButton => new TranslatableString(getKey(@"export_skin_button"), @"Export selected skin");
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// "Delete selected skin"
|
|
||||||
/// </summary>
|
|
||||||
public static LocalisableString DeleteSkinButton => new TranslatableString(getKey(@"delete_skin_button"), @"Delete selected skin");
|
|
||||||
|
|
||||||
private static string getKey(string key) => $"{prefix}:{key}";
|
private static string getKey(string key) => $"{prefix}:{key}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,7 @@ using osu.Game.Screens.OnlinePlay.Multiplayer;
|
|||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Screens.Ranking;
|
using osu.Game.Screens.Ranking;
|
||||||
using osu.Game.Screens.Select;
|
using osu.Game.Screens.Select;
|
||||||
|
using osu.Game.Seasonal;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Updater;
|
using osu.Game.Updater;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
@ -220,6 +221,11 @@ namespace osu.Game
|
|||||||
|
|
||||||
private readonly List<OverlayContainer> visibleBlockingOverlays = new List<OverlayContainer>();
|
private readonly List<OverlayContainer> visibleBlockingOverlays = new List<OverlayContainer>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the game should be limited to only display officially licensed content.
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool HideUnlicensedContent => false;
|
||||||
|
|
||||||
public OsuGame(string[] args = null)
|
public OsuGame(string[] args = null)
|
||||||
{
|
{
|
||||||
this.args = args;
|
this.args = args;
|
||||||
@ -361,7 +367,10 @@ namespace osu.Game
|
|||||||
{
|
{
|
||||||
SentryLogger.AttachUser(API.LocalUser);
|
SentryLogger.AttachUser(API.LocalUser);
|
||||||
|
|
||||||
dependencies.Cache(osuLogo = new OsuLogo { Alpha = 0 });
|
if (SeasonalUIConfig.ENABLED)
|
||||||
|
dependencies.CacheAs(osuLogo = new OsuLogoChristmas { Alpha = 0 });
|
||||||
|
else
|
||||||
|
dependencies.CacheAs(osuLogo = new OsuLogo { Alpha = 0 });
|
||||||
|
|
||||||
// bind config int to database RulesetInfo
|
// bind config int to database RulesetInfo
|
||||||
configRuleset = LocalConfig.GetBindable<string>(OsuSetting.Ruleset);
|
configRuleset = LocalConfig.GetBindable<string>(OsuSetting.Ruleset);
|
||||||
|
@ -5,6 +5,7 @@ using System;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
|
using osu.Framework.Graphics.Cursor;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
@ -113,7 +114,7 @@ namespace osu.Game.Overlays.BeatmapListing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private partial class FeaturedArtistsTabItem : MultipleSelectionFilterTabItem
|
private partial class FeaturedArtistsTabItem : MultipleSelectionFilterTabItem, IHasTooltip
|
||||||
{
|
{
|
||||||
private Bindable<bool> disclaimerShown = null!;
|
private Bindable<bool> disclaimerShown = null!;
|
||||||
|
|
||||||
@ -125,17 +126,36 @@ namespace osu.Game.Overlays.BeatmapListing
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private OsuColour colours { get; set; } = null!;
|
private OsuColour colours { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuConfigManager config { get; set; } = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private SessionStatics sessionStatics { get; set; } = null!;
|
private SessionStatics sessionStatics { get; set; } = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private IDialogOverlay? dialogOverlay { get; set; }
|
private IDialogOverlay? dialogOverlay { get; set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuGame? game { get; set; }
|
||||||
|
|
||||||
|
public LocalisableString TooltipText => BeatmapOverlayStrings.FeaturedArtistsTooltip;
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
|
config.BindWith(OsuSetting.BeatmapListingFeaturedArtistFilter, Active);
|
||||||
disclaimerShown = sessionStatics.GetBindable<bool>(Static.FeaturedArtistDisclaimerShownOnce);
|
disclaimerShown = sessionStatics.GetBindable<bool>(Static.FeaturedArtistDisclaimerShownOnce);
|
||||||
|
|
||||||
|
// no need to show the disclaimer if the user already had it toggled off in config.
|
||||||
|
if (!Active.Value)
|
||||||
|
disclaimerShown.Value = true;
|
||||||
|
|
||||||
|
if (game?.HideUnlicensedContent == true)
|
||||||
|
{
|
||||||
|
Enabled.Value = false;
|
||||||
|
Active.Disabled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Color4 ColourNormal => colours.Orange1;
|
protected override Color4 ColourNormal => colours.Orange1;
|
||||||
@ -143,6 +163,9 @@ namespace osu.Game.Overlays.BeatmapListing
|
|||||||
|
|
||||||
protected override bool OnClick(ClickEvent e)
|
protected override bool OnClick(ClickEvent e)
|
||||||
{
|
{
|
||||||
|
if (!Enabled.Value)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (!disclaimerShown.Value && dialogOverlay != null)
|
if (!disclaimerShown.Value && dialogOverlay != null)
|
||||||
{
|
{
|
||||||
dialogOverlay.Push(new FeaturedArtistConfirmDialog(() =>
|
dialogOverlay.Push(new FeaturedArtistConfirmDialog(() =>
|
||||||
|
@ -73,7 +73,10 @@ namespace osu.Game.Overlays.BeatmapListing
|
|||||||
private void currentChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
private void currentChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
foreach (var c in Children)
|
foreach (var c in Children)
|
||||||
c.Active.Value = Current.Contains(c.Value);
|
{
|
||||||
|
if (!c.Active.Disabled)
|
||||||
|
c.Active.Value = Current.Contains(c.Value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -100,7 +103,7 @@ namespace osu.Game.Overlays.BeatmapListing
|
|||||||
|
|
||||||
protected partial class MultipleSelectionFilterTabItem : FilterTabItem<T>
|
protected partial class MultipleSelectionFilterTabItem : FilterTabItem<T>
|
||||||
{
|
{
|
||||||
private Drawable activeContent = null!;
|
private Container activeContent = null!;
|
||||||
private Circle background = null!;
|
private Circle background = null!;
|
||||||
|
|
||||||
public MultipleSelectionFilterTabItem(T value)
|
public MultipleSelectionFilterTabItem(T value)
|
||||||
@ -160,7 +163,9 @@ namespace osu.Game.Overlays.BeatmapListing
|
|||||||
{
|
{
|
||||||
Color4 colour = Active.Value ? ColourActive : ColourNormal;
|
Color4 colour = Active.Value ? ColourActive : ColourNormal;
|
||||||
|
|
||||||
if (IsHovered)
|
if (!Enabled.Value)
|
||||||
|
colour = colour.Darken(1f);
|
||||||
|
else if (IsHovered)
|
||||||
colour = Active.Value ? colour.Darken(0.2f) : colour.Lighten(0.2f);
|
colour = Active.Value ? colour.Darken(0.2f) : colour.Lighten(0.2f);
|
||||||
|
|
||||||
if (Active.Value)
|
if (Active.Value)
|
||||||
|
@ -57,7 +57,9 @@ namespace osu.Game.Overlays.BeatmapListing
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
|
Enabled.BindValueChanged(_ => UpdateState());
|
||||||
UpdateState();
|
UpdateState();
|
||||||
|
|
||||||
FinishTransforms(true);
|
FinishTransforms(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,17 +9,23 @@ using System.Linq;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Cursor;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Graphics.UserInterfaceV2;
|
||||||
using osu.Game.Localisation;
|
using osu.Game.Localisation;
|
||||||
using osu.Game.Overlays.SkinEditor;
|
using osu.Game.Overlays.SkinEditor;
|
||||||
using osu.Game.Screens.Select;
|
using osu.Game.Screens.Select;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
using Realms;
|
using Realms;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Settings.Sections
|
namespace osu.Game.Overlays.Settings.Sections
|
||||||
@ -64,13 +70,26 @@ namespace osu.Game.Overlays.Settings.Sections
|
|||||||
Current = skins.CurrentSkinInfo,
|
Current = skins.CurrentSkinInfo,
|
||||||
Keywords = new[] { @"skins" },
|
Keywords = new[] { @"skins" },
|
||||||
},
|
},
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Spacing = new Vector2(5, 0),
|
||||||
|
Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS, Right = SettingsPanel.CONTENT_MARGINS },
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
// This is all super-temporary until we move skin settings to their own panel / overlay.
|
||||||
|
new RenameSkinButton { Padding = new MarginPadding(), RelativeSizeAxes = Axes.None, Width = 120 },
|
||||||
|
new ExportSkinButton { Padding = new MarginPadding(), RelativeSizeAxes = Axes.None, Width = 120 },
|
||||||
|
new DeleteSkinButton { Padding = new MarginPadding(), RelativeSizeAxes = Axes.None, Width = 110 },
|
||||||
|
}
|
||||||
|
},
|
||||||
new SettingsButton
|
new SettingsButton
|
||||||
{
|
{
|
||||||
Text = SkinSettingsStrings.SkinLayoutEditor,
|
Text = SkinSettingsStrings.SkinLayoutEditor,
|
||||||
Action = () => skinEditor?.ToggleVisibility(),
|
Action = () => skinEditor?.ToggleVisibility(),
|
||||||
},
|
},
|
||||||
new ExportSkinButton(),
|
|
||||||
new DeleteSkinButton(),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,6 +155,34 @@ namespace osu.Game.Overlays.Settings.Sections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public partial class RenameSkinButton : SettingsButton, IHasPopover
|
||||||
|
{
|
||||||
|
[Resolved]
|
||||||
|
private SkinManager skins { get; set; }
|
||||||
|
|
||||||
|
private Bindable<Skin> currentSkin;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
Text = "Rename";
|
||||||
|
Action = this.ShowPopover;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
currentSkin = skins.CurrentSkin.GetBoundCopy();
|
||||||
|
currentSkin.BindValueChanged(skin => Enabled.Value = skin.NewValue.SkinInfo.PerformRead(s => !s.Protected), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Popover GetPopover()
|
||||||
|
{
|
||||||
|
return new RenameSkinPopover();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public partial class ExportSkinButton : SettingsButton
|
public partial class ExportSkinButton : SettingsButton
|
||||||
{
|
{
|
||||||
[Resolved]
|
[Resolved]
|
||||||
@ -146,7 +193,7 @@ namespace osu.Game.Overlays.Settings.Sections
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
Text = SkinSettingsStrings.ExportSkinButton;
|
Text = "Export";
|
||||||
Action = export;
|
Action = export;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +231,7 @@ namespace osu.Game.Overlays.Settings.Sections
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
Text = SkinSettingsStrings.DeleteSkinButton;
|
Text = "Delete";
|
||||||
Action = delete;
|
Action = delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,5 +248,63 @@ namespace osu.Game.Overlays.Settings.Sections
|
|||||||
dialogOverlay?.Push(new SkinDeleteDialog(currentSkin.Value));
|
dialogOverlay?.Push(new SkinDeleteDialog(currentSkin.Value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public partial class RenameSkinPopover : OsuPopover
|
||||||
|
{
|
||||||
|
[Resolved]
|
||||||
|
private SkinManager skins { get; set; }
|
||||||
|
|
||||||
|
private readonly FocusedTextBox textBox;
|
||||||
|
|
||||||
|
public RenameSkinPopover()
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both;
|
||||||
|
Origin = Anchor.TopCentre;
|
||||||
|
|
||||||
|
RoundedButton renameButton;
|
||||||
|
|
||||||
|
Child = new FillFlowContainer
|
||||||
|
{
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Width = 250,
|
||||||
|
Spacing = new Vector2(10f),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
textBox = new FocusedTextBox
|
||||||
|
{
|
||||||
|
PlaceholderText = @"Skin name",
|
||||||
|
FontSize = OsuFont.DEFAULT_FONT_SIZE,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
SelectAllOnFocus = true,
|
||||||
|
},
|
||||||
|
renameButton = new RoundedButton
|
||||||
|
{
|
||||||
|
Height = 40,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
MatchingFilter = true,
|
||||||
|
Text = "Save",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
renameButton.Action += rename;
|
||||||
|
textBox.OnCommit += (_, _) => rename();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PopIn()
|
||||||
|
{
|
||||||
|
textBox.Text = skins.CurrentSkinInfo.Value.Value.Name;
|
||||||
|
textBox.TakeFocus();
|
||||||
|
|
||||||
|
base.PopIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rename() => skins.CurrentSkinInfo.Value.PerformWrite(skin =>
|
||||||
|
{
|
||||||
|
skin.Name = textBox.Text;
|
||||||
|
PopOut();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,13 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
|
|||||||
},
|
},
|
||||||
new SettingsCheckbox
|
new SettingsCheckbox
|
||||||
{
|
{
|
||||||
|
Keywords = new[] { "intro", "welcome" },
|
||||||
LabelText = UserInterfaceStrings.InterfaceVoices,
|
LabelText = UserInterfaceStrings.InterfaceVoices,
|
||||||
Current = config.GetBindable<bool>(OsuSetting.MenuVoice)
|
Current = config.GetBindable<bool>(OsuSetting.MenuVoice)
|
||||||
},
|
},
|
||||||
new SettingsCheckbox
|
new SettingsCheckbox
|
||||||
{
|
{
|
||||||
|
Keywords = new[] { "intro", "welcome" },
|
||||||
LabelText = UserInterfaceStrings.OsuMusicTheme,
|
LabelText = UserInterfaceStrings.OsuMusicTheme,
|
||||||
Current = config.GetBindable<bool>(OsuSetting.MenuMusic)
|
Current = config.GetBindable<bool>(OsuSetting.MenuMusic)
|
||||||
},
|
},
|
||||||
|
@ -39,7 +39,18 @@ namespace osu.Game.Rulesets.UI
|
|||||||
private IMod mod;
|
private IMod mod;
|
||||||
|
|
||||||
private readonly bool showTooltip;
|
private readonly bool showTooltip;
|
||||||
private readonly bool showExtendedInformation;
|
|
||||||
|
private bool showExtendedInformation;
|
||||||
|
|
||||||
|
public bool ShowExtendedInformation
|
||||||
|
{
|
||||||
|
get => showExtendedInformation;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
showExtendedInformation = value;
|
||||||
|
updateExtendedInformation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public IMod Mod
|
public IMod Mod
|
||||||
{
|
{
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Development;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shaders;
|
using osu.Framework.Graphics.Shaders;
|
||||||
@ -15,6 +16,7 @@ using osu.Framework.Screens;
|
|||||||
using osu.Framework.Threading;
|
using osu.Framework.Threading;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Seasonal;
|
||||||
using IntroSequence = osu.Game.Configuration.IntroSequence;
|
using IntroSequence = osu.Game.Configuration.IntroSequence;
|
||||||
|
|
||||||
namespace osu.Game.Screens
|
namespace osu.Game.Screens
|
||||||
@ -37,6 +39,11 @@ namespace osu.Game.Screens
|
|||||||
|
|
||||||
private IntroScreen getIntroSequence()
|
private IntroScreen getIntroSequence()
|
||||||
{
|
{
|
||||||
|
// Headless tests run too fast to load non-circles intros correctly.
|
||||||
|
// They will hit the "audio can't play" notification and cause random test failures.
|
||||||
|
if (SeasonalUIConfig.ENABLED && !DebugUtils.IsNUnitRunning)
|
||||||
|
return new IntroChristmas(createMainMenu);
|
||||||
|
|
||||||
if (introSequence == IntroSequence.Random)
|
if (introSequence == IntroSequence.Random)
|
||||||
introSequence = (IntroSequence)RNG.Next(0, (int)IntroSequence.Random);
|
introSequence = (IntroSequence)RNG.Next(0, (int)IntroSequence.Random);
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
Text = NotificationsStrings.AudioPlaybackIssue
|
Text = NotificationsStrings.AudioPlaybackIssue
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, 5000);
|
}, 8000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnResuming(ScreenTransitionEvent e)
|
public override void OnResuming(ScreenTransitionEvent e)
|
||||||
|
@ -36,6 +36,7 @@ using osu.Game.Screens.OnlinePlay.DailyChallenge;
|
|||||||
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||||
using osu.Game.Screens.OnlinePlay.Playlists;
|
using osu.Game.Screens.OnlinePlay.Playlists;
|
||||||
using osu.Game.Screens.Select;
|
using osu.Game.Screens.Select;
|
||||||
|
using osu.Game.Seasonal;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -125,6 +126,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
|
|
||||||
AddRangeInternal(new[]
|
AddRangeInternal(new[]
|
||||||
{
|
{
|
||||||
|
SeasonalUIConfig.ENABLED ? new MainMenuSeasonalLighting() : Empty(),
|
||||||
new GlobalScrollAdjustsVolume(),
|
new GlobalScrollAdjustsVolume(),
|
||||||
buttonsContainer = new ParallaxContainer
|
buttonsContainer = new ParallaxContainer
|
||||||
{
|
{
|
||||||
@ -161,14 +163,15 @@ namespace osu.Game.Screens.Menu
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
logoTarget = new Container { RelativeSizeAxes = Axes.Both, },
|
logoTarget = new Container { RelativeSizeAxes = Axes.Both, },
|
||||||
sideFlashes = new MenuSideFlashes(),
|
sideFlashes = SeasonalUIConfig.ENABLED ? new SeasonalMenuSideFlashes() : new MenuSideFlashes(),
|
||||||
songTicker = new SongTicker
|
songTicker = new SongTicker
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopRight,
|
Anchor = Anchor.TopRight,
|
||||||
Origin = Anchor.TopRight,
|
Origin = Anchor.TopRight,
|
||||||
Margin = new MarginPadding { Right = 15, Top = 5 }
|
Margin = new MarginPadding { Right = 15, Top = 5 }
|
||||||
},
|
},
|
||||||
new KiaiMenuFountains(),
|
// For now, this is too much alongside the seasonal lighting.
|
||||||
|
SeasonalUIConfig.ENABLED ? Empty() : new KiaiMenuFountains(),
|
||||||
bottomElementsFlow = new FillFlowContainer
|
bottomElementsFlow = new FillFlowContainer
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using osuTK.Graphics;
|
|
||||||
using osu.Game.Skinning;
|
|
||||||
using osu.Game.Online.API;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Menu
|
namespace osu.Game.Screens.Menu
|
||||||
{
|
{
|
||||||
internal partial class MenuLogoVisualisation : LogoVisualisation
|
public partial class MenuLogoVisualisation : LogoVisualisation
|
||||||
{
|
{
|
||||||
private IBindable<APIUser> user;
|
private IBindable<APIUser> user = null!;
|
||||||
private Bindable<Skin> skin;
|
private Bindable<Skin> skin = null!;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(IAPIProvider api, SkinManager skinManager)
|
private void load(IAPIProvider api, SkinManager skinManager)
|
||||||
@ -23,11 +21,11 @@ namespace osu.Game.Screens.Menu
|
|||||||
user = api.LocalUser.GetBoundCopy();
|
user = api.LocalUser.GetBoundCopy();
|
||||||
skin = skinManager.CurrentSkin.GetBoundCopy();
|
skin = skinManager.CurrentSkin.GetBoundCopy();
|
||||||
|
|
||||||
user.ValueChanged += _ => updateColour();
|
user.ValueChanged += _ => UpdateColour();
|
||||||
skin.BindValueChanged(_ => updateColour(), true);
|
skin.BindValueChanged(_ => UpdateColour(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateColour()
|
protected virtual void UpdateColour()
|
||||||
{
|
{
|
||||||
if (user.Value?.IsSupporter ?? false)
|
if (user.Value?.IsSupporter ?? false)
|
||||||
Colour = skin.Value.GetConfig<GlobalSkinColours, Color4>(GlobalSkinColours.MenuGlow)?.Value ?? Color4.White;
|
Colour = skin.Value.GetConfig<GlobalSkinColours, Color4>(GlobalSkinColours.MenuGlow)?.Value ?? Color4.White;
|
||||||
|
@ -3,8 +3,10 @@
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
using osuTK.Graphics;
|
using System;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Audio.Track;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Colour;
|
using osu.Framework.Graphics.Colour;
|
||||||
@ -13,17 +15,19 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Skinning;
|
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using System;
|
|
||||||
using osu.Framework.Audio.Track;
|
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Menu
|
namespace osu.Game.Screens.Menu
|
||||||
{
|
{
|
||||||
public partial class MenuSideFlashes : BeatSyncedContainer
|
public partial class MenuSideFlashes : BeatSyncedContainer
|
||||||
{
|
{
|
||||||
|
protected virtual bool RefreshColoursEveryFlash => false;
|
||||||
|
|
||||||
|
protected virtual float Intensity => 2;
|
||||||
|
|
||||||
private readonly IBindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
private readonly IBindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||||
|
|
||||||
private Box leftBox;
|
private Box leftBox;
|
||||||
@ -67,7 +71,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Y,
|
||||||
Width = box_width * 2,
|
Width = box_width * Intensity,
|
||||||
Height = 1.5f,
|
Height = 1.5f,
|
||||||
// align off-screen to make sure our edges don't become visible during parallax.
|
// align off-screen to make sure our edges don't become visible during parallax.
|
||||||
X = -box_width,
|
X = -box_width,
|
||||||
@ -79,7 +83,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
Anchor = Anchor.CentreRight,
|
Anchor = Anchor.CentreRight,
|
||||||
Origin = Anchor.CentreRight,
|
Origin = Anchor.CentreRight,
|
||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Y,
|
||||||
Width = box_width * 2,
|
Width = box_width * Intensity,
|
||||||
Height = 1.5f,
|
Height = 1.5f,
|
||||||
X = box_width,
|
X = box_width,
|
||||||
Alpha = 0,
|
Alpha = 0,
|
||||||
@ -87,8 +91,11 @@ namespace osu.Game.Screens.Menu
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
user.ValueChanged += _ => updateColour();
|
if (!RefreshColoursEveryFlash)
|
||||||
skin.BindValueChanged(_ => updateColour(), true);
|
{
|
||||||
|
user.ValueChanged += _ => updateColour();
|
||||||
|
skin.BindValueChanged(_ => updateColour(), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes)
|
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes)
|
||||||
@ -104,18 +111,28 @@ namespace osu.Game.Screens.Menu
|
|||||||
|
|
||||||
private void flash(Drawable d, double beatLength, bool kiai, ChannelAmplitudes amplitudes)
|
private void flash(Drawable d, double beatLength, bool kiai, ChannelAmplitudes amplitudes)
|
||||||
{
|
{
|
||||||
d.FadeTo(Math.Max(0, ((ReferenceEquals(d, leftBox) ? amplitudes.LeftChannel : amplitudes.RightChannel) - amplitude_dead_zone) / (kiai ? kiai_multiplier : alpha_multiplier)), box_fade_in_time)
|
if (RefreshColoursEveryFlash)
|
||||||
|
updateColour();
|
||||||
|
|
||||||
|
d.FadeTo(Math.Clamp(0.1f + ((ReferenceEquals(d, leftBox) ? amplitudes.LeftChannel : amplitudes.RightChannel) - amplitude_dead_zone) / (kiai ? kiai_multiplier : alpha_multiplier), 0.1f, 1),
|
||||||
|
box_fade_in_time)
|
||||||
.Then()
|
.Then()
|
||||||
.FadeOut(beatLength, Easing.In);
|
.FadeOut(beatLength, Easing.In);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateColour()
|
protected virtual Color4 GetBaseColour()
|
||||||
{
|
{
|
||||||
Color4 baseColour = colours.Blue;
|
Color4 baseColour = colours.Blue;
|
||||||
|
|
||||||
if (user.Value?.IsSupporter ?? false)
|
if (user.Value?.IsSupporter ?? false)
|
||||||
baseColour = skin.Value.GetConfig<GlobalSkinColours, Color4>(GlobalSkinColours.MenuGlow)?.Value ?? baseColour;
|
baseColour = skin.Value.GetConfig<GlobalSkinColours, Color4>(GlobalSkinColours.MenuGlow)?.Value ?? baseColour;
|
||||||
|
|
||||||
|
return baseColour;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateColour()
|
||||||
|
{
|
||||||
|
var baseColour = GetBaseColour();
|
||||||
// linear colour looks better in this case, so let's use it for now.
|
// linear colour looks better in this case, so let's use it for now.
|
||||||
Color4 gradientDark = baseColour.Opacity(0).ToLinear();
|
Color4 gradientDark = baseColour.Opacity(0).ToLinear();
|
||||||
Color4 gradientLight = baseColour.Opacity(0.6f).ToLinear();
|
Color4 gradientLight = baseColour.Opacity(0.6f).ToLinear();
|
||||||
|
@ -122,7 +122,8 @@ namespace osu.Game.Screens.Menu
|
|||||||
MenuTipStrings.RandomSkinShortcut,
|
MenuTipStrings.RandomSkinShortcut,
|
||||||
MenuTipStrings.ToggleReplaySettingsShortcut,
|
MenuTipStrings.ToggleReplaySettingsShortcut,
|
||||||
MenuTipStrings.CopyModsFromScore,
|
MenuTipStrings.CopyModsFromScore,
|
||||||
MenuTipStrings.AutoplayBeatmapShortcut
|
MenuTipStrings.AutoplayBeatmapShortcut,
|
||||||
|
MenuTipStrings.LazerIsNotAWord
|
||||||
};
|
};
|
||||||
|
|
||||||
return tips[RNG.Next(0, tips.Length)];
|
return tips[RNG.Next(0, tips.Length)];
|
||||||
|
@ -53,8 +53,12 @@ namespace osu.Game.Screens.Menu
|
|||||||
private Sample sampleClick;
|
private Sample sampleClick;
|
||||||
private SampleChannel sampleClickChannel;
|
private SampleChannel sampleClickChannel;
|
||||||
|
|
||||||
private Sample sampleBeat;
|
protected virtual MenuLogoVisualisation CreateMenuLogoVisualisation() => new MenuLogoVisualisation();
|
||||||
private Sample sampleDownbeat;
|
|
||||||
|
protected virtual double BeatSampleVariance => 0.1;
|
||||||
|
|
||||||
|
protected Sample SampleBeat;
|
||||||
|
protected Sample SampleDownbeat;
|
||||||
|
|
||||||
private readonly Container colourAndTriangles;
|
private readonly Container colourAndTriangles;
|
||||||
private readonly TrianglesV2 triangles;
|
private readonly TrianglesV2 triangles;
|
||||||
@ -151,15 +155,15 @@ namespace osu.Game.Screens.Menu
|
|||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
visualizer = new MenuLogoVisualisation
|
visualizer = CreateMenuLogoVisualisation().With(v =>
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
v.RelativeSizeAxes = Axes.Both;
|
||||||
Origin = Anchor.Centre,
|
v.Origin = Anchor.Centre;
|
||||||
Anchor = Anchor.Centre,
|
v.Anchor = Anchor.Centre;
|
||||||
Alpha = visualizer_default_alpha,
|
v.Alpha = visualizer_default_alpha;
|
||||||
Size = SCALE_ADJUST
|
v.Size = SCALE_ADJUST;
|
||||||
},
|
}),
|
||||||
new Container
|
LogoElements = new Container
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
@ -243,6 +247,8 @@ namespace osu.Game.Screens.Menu
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Container LogoElements { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Schedule a new external animation. Handled queueing and finishing previous animations in a sane way.
|
/// Schedule a new external animation. Handled queueing and finishing previous animations in a sane way.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -271,8 +277,9 @@ namespace osu.Game.Screens.Menu
|
|||||||
private void load(TextureStore textures, AudioManager audio)
|
private void load(TextureStore textures, AudioManager audio)
|
||||||
{
|
{
|
||||||
sampleClick = audio.Samples.Get(@"Menu/osu-logo-select");
|
sampleClick = audio.Samples.Get(@"Menu/osu-logo-select");
|
||||||
sampleBeat = audio.Samples.Get(@"Menu/osu-logo-heartbeat");
|
|
||||||
sampleDownbeat = audio.Samples.Get(@"Menu/osu-logo-downbeat");
|
SampleBeat = audio.Samples.Get(@"Menu/osu-logo-heartbeat");
|
||||||
|
SampleDownbeat = audio.Samples.Get(@"Menu/osu-logo-downbeat");
|
||||||
|
|
||||||
logo.Texture = textures.Get(@"Menu/logo");
|
logo.Texture = textures.Get(@"Menu/logo");
|
||||||
ripple.Texture = textures.Get(@"Menu/logo");
|
ripple.Texture = textures.Get(@"Menu/logo");
|
||||||
@ -298,12 +305,13 @@ namespace osu.Game.Screens.Menu
|
|||||||
{
|
{
|
||||||
if (beatIndex % timingPoint.TimeSignature.Numerator == 0)
|
if (beatIndex % timingPoint.TimeSignature.Numerator == 0)
|
||||||
{
|
{
|
||||||
sampleDownbeat?.Play();
|
SampleDownbeat?.Play();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var channel = sampleBeat.GetChannel();
|
var channel = SampleBeat.GetChannel();
|
||||||
channel.Frequency.Value = 0.95 + RNG.NextDouble(0.1);
|
|
||||||
|
channel.Frequency.Value = 1 - BeatSampleVariance / 2 + RNG.NextDouble(BeatSampleVariance);
|
||||||
channel.Play();
|
channel.Play();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -8,7 +8,9 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.UserInterface;
|
using osu.Framework.Graphics.UserInterface;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Localisation.SkinComponents;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -20,9 +22,24 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class ModDisplay : CompositeDrawable, IHasCurrentValue<IReadOnlyList<Mod>>
|
public partial class ModDisplay : CompositeDrawable, IHasCurrentValue<IReadOnlyList<Mod>>
|
||||||
{
|
{
|
||||||
private const int fade_duration = 1000;
|
public const float MOD_ICON_SCALE = 0.6f;
|
||||||
|
|
||||||
public ExpansionMode ExpansionMode = ExpansionMode.ExpandOnHover;
|
private ExpansionMode expansionMode = ExpansionMode.ExpandOnHover;
|
||||||
|
|
||||||
|
public ExpansionMode ExpansionMode
|
||||||
|
{
|
||||||
|
get => expansionMode;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (expansionMode == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
expansionMode = value;
|
||||||
|
|
||||||
|
if (IsLoaded)
|
||||||
|
updateExpansionMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private readonly BindableWithCurrent<IReadOnlyList<Mod>> current = new BindableWithCurrent<IReadOnlyList<Mod>>(Array.Empty<Mod>());
|
private readonly BindableWithCurrent<IReadOnlyList<Mod>> current = new BindableWithCurrent<IReadOnlyList<Mod>>(Array.Empty<Mod>());
|
||||||
|
|
||||||
@ -37,7 +54,19 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly bool showExtendedInformation;
|
private bool showExtendedInformation;
|
||||||
|
|
||||||
|
public bool ShowExtendedInformation
|
||||||
|
{
|
||||||
|
get => showExtendedInformation;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
showExtendedInformation = value;
|
||||||
|
foreach (var icon in iconsContainer)
|
||||||
|
icon.ShowExtendedInformation = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private readonly FillFlowContainer<ModIcon> iconsContainer;
|
private readonly FillFlowContainer<ModIcon> iconsContainer;
|
||||||
|
|
||||||
public ModDisplay(bool showExtendedInformation = true)
|
public ModDisplay(bool showExtendedInformation = true)
|
||||||
@ -58,11 +87,7 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
Current.BindValueChanged(updateDisplay, true);
|
Current.BindValueChanged(updateDisplay, true);
|
||||||
|
updateExpansionMode(0);
|
||||||
iconsContainer.FadeInFromZero(fade_duration, Easing.OutQuint);
|
|
||||||
|
|
||||||
if (ExpansionMode == ExpansionMode.AlwaysExpanded || ExpansionMode == ExpansionMode.AlwaysContracted)
|
|
||||||
FinishTransforms(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateDisplay(ValueChangedEvent<IReadOnlyList<Mod>> mods)
|
private void updateDisplay(ValueChangedEvent<IReadOnlyList<Mod>> mods)
|
||||||
@ -70,29 +95,40 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
iconsContainer.Clear();
|
iconsContainer.Clear();
|
||||||
|
|
||||||
foreach (Mod mod in mods.NewValue.AsOrdered())
|
foreach (Mod mod in mods.NewValue.AsOrdered())
|
||||||
iconsContainer.Add(new ModIcon(mod, showExtendedInformation: showExtendedInformation) { Scale = new Vector2(0.6f) });
|
iconsContainer.Add(new ModIcon(mod, showExtendedInformation: showExtendedInformation) { Scale = new Vector2(MOD_ICON_SCALE) });
|
||||||
|
|
||||||
appearTransform();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appearTransform()
|
private void updateExpansionMode(double duration = 500)
|
||||||
{
|
{
|
||||||
expand();
|
switch (expansionMode)
|
||||||
|
{
|
||||||
|
case ExpansionMode.AlwaysExpanded:
|
||||||
|
expand(duration);
|
||||||
|
break;
|
||||||
|
|
||||||
using (iconsContainer.BeginDelayedSequence(1200))
|
case ExpansionMode.AlwaysContracted:
|
||||||
contract();
|
contract(duration);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ExpansionMode.ExpandOnHover:
|
||||||
|
if (IsHovered)
|
||||||
|
expand(duration);
|
||||||
|
else
|
||||||
|
contract(duration);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expand()
|
private void expand(double duration = 500)
|
||||||
{
|
{
|
||||||
if (ExpansionMode != ExpansionMode.AlwaysContracted)
|
if (ExpansionMode != ExpansionMode.AlwaysContracted)
|
||||||
iconsContainer.TransformSpacingTo(new Vector2(5, 0), 500, Easing.OutQuint);
|
iconsContainer.TransformSpacingTo(new Vector2(5, 0), duration, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void contract()
|
private void contract(double duration = 500)
|
||||||
{
|
{
|
||||||
if (ExpansionMode != ExpansionMode.AlwaysExpanded)
|
if (ExpansionMode != ExpansionMode.AlwaysExpanded)
|
||||||
iconsContainer.TransformSpacingTo(new Vector2(-25, 0), 500, Easing.OutQuint);
|
iconsContainer.TransformSpacingTo(new Vector2(-25, 0), duration, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
protected override bool OnHover(HoverEvent e)
|
||||||
@ -113,16 +149,19 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="ModDisplay"/> will expand only when hovered.
|
/// The <see cref="ModDisplay"/> will expand only when hovered.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[LocalisableDescription(typeof(SkinnableModDisplayStrings), nameof(SkinnableModDisplayStrings.ExpandOnHover))]
|
||||||
ExpandOnHover,
|
ExpandOnHover,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="ModDisplay"/> will always be expanded.
|
/// The <see cref="ModDisplay"/> will always be expanded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[LocalisableDescription(typeof(SkinnableModDisplayStrings), nameof(SkinnableModDisplayStrings.AlwaysExpanded))]
|
||||||
AlwaysExpanded,
|
AlwaysExpanded,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="ModDisplay"/> will always be contracted.
|
/// The <see cref="ModDisplay"/> will always be contracted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
AlwaysContracted
|
[LocalisableDescription(typeof(SkinnableModDisplayStrings), nameof(SkinnableModDisplayStrings.AlwaysContracted))]
|
||||||
|
AlwaysContracted,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
59
osu.Game/Screens/Play/HUD/SkinnableModDisplay.cs
Normal file
59
osu.Game/Screens/Play/HUD/SkinnableModDisplay.cs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// 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.Collections.Generic;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Localisation.SkinComponents;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.UI;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Play.HUD
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Displays a single-line horizontal auto-sized flow of mods. For cases where wrapping is required, use <see cref="ModFlowDisplay"/> instead.
|
||||||
|
/// </summary>
|
||||||
|
public partial class SkinnableModDisplay : CompositeDrawable, ISerialisableDrawable
|
||||||
|
{
|
||||||
|
private ModDisplay modDisplay = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private Bindable<IReadOnlyList<Mod>> mods { get; set; } = null!;
|
||||||
|
|
||||||
|
[SettingSource(typeof(SkinnableModDisplayStrings), nameof(SkinnableModDisplayStrings.ShowExtendedInformation), nameof(SkinnableModDisplayStrings.ShowExtendedInformationDescription))]
|
||||||
|
public Bindable<bool> ShowExtendedInformation { get; } = new Bindable<bool>(true);
|
||||||
|
|
||||||
|
[SettingSource(typeof(SkinnableModDisplayStrings), nameof(SkinnableModDisplayStrings.ExpansionMode), nameof(SkinnableModDisplayStrings.ExpansionModeDescription))]
|
||||||
|
public Bindable<ExpansionMode> ExpansionModeSetting { get; } = new Bindable<ExpansionMode>();
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
// Provide a minimum autosize.
|
||||||
|
new Container { Size = ModIcon.MOD_ICON_SIZE * ModDisplay.MOD_ICON_SCALE },
|
||||||
|
modDisplay = new ModDisplay(),
|
||||||
|
};
|
||||||
|
|
||||||
|
modDisplay.Current = mods;
|
||||||
|
AutoSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
ShowExtendedInformation.BindValueChanged(_ => modDisplay.ShowExtendedInformation = ShowExtendedInformation.Value, true);
|
||||||
|
ExpansionModeSetting.BindValueChanged(_ => modDisplay.ExpansionMode = ExpansionModeSetting.Value, true);
|
||||||
|
|
||||||
|
FinishTransforms(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UsesFixedAnchor { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -85,7 +85,6 @@ namespace osu.Game.Screens.Play
|
|||||||
private readonly BindableBool replayLoaded = new BindableBool();
|
private readonly BindableBool replayLoaded = new BindableBool();
|
||||||
|
|
||||||
private static bool hasShownNotificationOnce;
|
private static bool hasShownNotificationOnce;
|
||||||
|
|
||||||
private readonly FillFlowContainer bottomRightElements;
|
private readonly FillFlowContainer bottomRightElements;
|
||||||
|
|
||||||
internal readonly FillFlowContainer TopRightElements;
|
internal readonly FillFlowContainer TopRightElements;
|
||||||
@ -238,7 +237,7 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
if (e.NewValue)
|
if (e.NewValue)
|
||||||
{
|
{
|
||||||
ModDisplay.FadeIn(200);
|
ModDisplay.FadeIn(1000, FADE_EASING);
|
||||||
InputCountController.Margin = new MarginPadding(10) { Bottom = 30 };
|
InputCountController.Margin = new MarginPadding(10) { Bottom = 30 };
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -249,6 +248,9 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
updateVisibility();
|
updateVisibility();
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
|
ModDisplay.ExpansionMode = ExpansionMode.AlwaysExpanded;
|
||||||
|
Scheduler.AddDelayed(() => ModDisplay.ExpansionMode = ExpansionMode.ExpandOnHover, 1200);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
|
@ -1021,7 +1021,7 @@ namespace osu.Game.Screens.Play
|
|||||||
private double? lastPauseActionTime;
|
private double? lastPauseActionTime;
|
||||||
|
|
||||||
protected bool PauseCooldownActive =>
|
protected bool PauseCooldownActive =>
|
||||||
lastPauseActionTime.HasValue && GameplayClockContainer.CurrentTime < lastPauseActionTime + PauseCooldownDuration;
|
PlayingState.Value == LocalUserPlayingState.Playing && lastPauseActionTime.HasValue && GameplayClockContainer.CurrentTime < lastPauseActionTime + PauseCooldownDuration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A set of conditionals which defines whether the current game state and configuration allows for
|
/// A set of conditionals which defines whether the current game state and configuration allows for
|
||||||
|
332
osu.Game/Seasonal/IntroChristmas.cs
Normal file
332
osu.Game/Seasonal/IntroChristmas.cs
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
// 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 osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Audio.Track;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osu.Framework.Screens;
|
||||||
|
using osu.Framework.Timing;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Screens.Menu;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Seasonal
|
||||||
|
{
|
||||||
|
public partial class IntroChristmas : IntroScreen
|
||||||
|
{
|
||||||
|
// nekodex - circle the halls
|
||||||
|
public const string CHRISTMAS_BEATMAP_SET_HASH = "7e26183e72a496f672c3a21292e6b469fdecd084d31c259ea10a31df5b46cd77";
|
||||||
|
|
||||||
|
protected override string BeatmapHash => CHRISTMAS_BEATMAP_SET_HASH;
|
||||||
|
|
||||||
|
protected override string BeatmapFile => "christmas2024.osz";
|
||||||
|
|
||||||
|
private const double beat_length = 60000 / 172.0;
|
||||||
|
private const double offset = 5924;
|
||||||
|
|
||||||
|
protected override string SeeyaSampleName => "Intro/Welcome/seeya";
|
||||||
|
|
||||||
|
private TrianglesIntroSequence intro = null!;
|
||||||
|
|
||||||
|
public IntroChristmas(Func<MainMenu>? createNextScreen = null)
|
||||||
|
: base(createNextScreen)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LogoArriving(OsuLogo logo, bool resuming)
|
||||||
|
{
|
||||||
|
base.LogoArriving(logo, resuming);
|
||||||
|
|
||||||
|
if (!resuming)
|
||||||
|
{
|
||||||
|
PrepareMenuLoad();
|
||||||
|
|
||||||
|
var decouplingClock = new DecouplingFramedClock(UsingThemedIntro ? Track : null);
|
||||||
|
|
||||||
|
LoadComponentAsync(intro = new TrianglesIntroSequence(logo, () => FadeInBackground())
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Clock = new InterpolatingFramedClock(decouplingClock),
|
||||||
|
LoadMenu = LoadMenu
|
||||||
|
}, _ =>
|
||||||
|
{
|
||||||
|
AddInternal(intro);
|
||||||
|
|
||||||
|
// There is a chance that the intro timed out before being displayed, and this scheduled callback could
|
||||||
|
// happen during the outro rather than intro.
|
||||||
|
// In such a scenario, we don't want to play the intro sample, nor attempt to start the intro track
|
||||||
|
// (that may have already been since disposed by MusicController).
|
||||||
|
if (DidLoadMenu)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If the user has requested no theme, fallback to the same intro voice and delay as IntroCircles.
|
||||||
|
// The triangles intro voice and theme are combined which makes it impossible to use.
|
||||||
|
StartTrack();
|
||||||
|
|
||||||
|
// no-op for the case of themed intro, no harm in calling for both scenarios as a safety measure.
|
||||||
|
decouplingClock.Start();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnSuspending(ScreenTransitionEvent e)
|
||||||
|
{
|
||||||
|
base.OnSuspending(e);
|
||||||
|
|
||||||
|
// important as there is a clock attached to a track which will likely be disposed before returning to this screen.
|
||||||
|
intro.Expire();
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial class TrianglesIntroSequence : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly OsuLogo logo;
|
||||||
|
private readonly Action showBackgroundAction;
|
||||||
|
private OsuSpriteText welcomeText = null!;
|
||||||
|
|
||||||
|
private Container logoContainerSecondary = null!;
|
||||||
|
private LazerLogo lazerLogo = null!;
|
||||||
|
|
||||||
|
private Drawable triangles = null!;
|
||||||
|
|
||||||
|
public Action LoadMenu = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuGameBase game { get; set; } = null!;
|
||||||
|
|
||||||
|
public TrianglesIntroSequence(OsuLogo logo, Action showBackgroundAction)
|
||||||
|
{
|
||||||
|
this.logo = logo;
|
||||||
|
this.showBackgroundAction = showBackgroundAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
InternalChildren = new[]
|
||||||
|
{
|
||||||
|
welcomeText = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Padding = new MarginPadding { Bottom = 10 },
|
||||||
|
Font = OsuFont.GetFont(weight: FontWeight.Light, size: 42),
|
||||||
|
Alpha = 1,
|
||||||
|
Spacing = new Vector2(5),
|
||||||
|
},
|
||||||
|
logoContainerSecondary = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Child = lazerLogo = new LazerLogo
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre
|
||||||
|
}
|
||||||
|
},
|
||||||
|
triangles = new CircularContainer
|
||||||
|
{
|
||||||
|
Alpha = 0,
|
||||||
|
Masking = true,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Size = new Vector2(960),
|
||||||
|
Child = new GlitchingTriangles
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getTimeForBeat(int beat) => offset + beat_length * beat;
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
lazerLogo.Hide();
|
||||||
|
|
||||||
|
using (BeginAbsoluteSequence(0))
|
||||||
|
{
|
||||||
|
using (BeginDelayedSequence(getTimeForBeat(-16)))
|
||||||
|
welcomeText.FadeIn().OnComplete(t => t.Text = "welcome to osu!");
|
||||||
|
|
||||||
|
using (BeginDelayedSequence(getTimeForBeat(-15)))
|
||||||
|
welcomeText.FadeIn().OnComplete(t => t.Text = "");
|
||||||
|
|
||||||
|
using (BeginDelayedSequence(getTimeForBeat(-14)))
|
||||||
|
welcomeText.FadeIn().OnComplete(t => t.Text = "welcome to osu!");
|
||||||
|
|
||||||
|
using (BeginDelayedSequence(getTimeForBeat(-13)))
|
||||||
|
welcomeText.FadeIn().OnComplete(t => t.Text = "");
|
||||||
|
|
||||||
|
using (BeginDelayedSequence(getTimeForBeat(-12)))
|
||||||
|
welcomeText.FadeIn().OnComplete(t => t.Text = "merry christmas!");
|
||||||
|
|
||||||
|
using (BeginDelayedSequence(getTimeForBeat(-11)))
|
||||||
|
welcomeText.FadeIn().OnComplete(t => t.Text = "");
|
||||||
|
|
||||||
|
using (BeginDelayedSequence(getTimeForBeat(-10)))
|
||||||
|
welcomeText.FadeIn().OnComplete(t => t.Text = "merry osumas!");
|
||||||
|
|
||||||
|
using (BeginDelayedSequence(getTimeForBeat(-9)))
|
||||||
|
{
|
||||||
|
welcomeText.FadeIn().OnComplete(t => t.Text = "");
|
||||||
|
}
|
||||||
|
|
||||||
|
lazerLogo.Scale = new Vector2(0.2f);
|
||||||
|
triangles.Scale = new Vector2(0.2f);
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
using (BeginDelayedSequence(getTimeForBeat(-8 + i)))
|
||||||
|
{
|
||||||
|
triangles.FadeIn();
|
||||||
|
|
||||||
|
lazerLogo.ScaleTo(new Vector2(0.2f + (i + 1) / 8f * 0.3f), beat_length * 1, Easing.OutQuint);
|
||||||
|
triangles.ScaleTo(new Vector2(0.2f + (i + 1) / 8f * 0.3f), beat_length * 1, Easing.OutQuint);
|
||||||
|
lazerLogo.FadeTo((i + 1) * 0.06f);
|
||||||
|
lazerLogo.TransformTo(nameof(LazerLogo.Progress), (i + 1) / 10f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GameWideFlash flash = new GameWideFlash();
|
||||||
|
|
||||||
|
using (BeginDelayedSequence(getTimeForBeat(-2)))
|
||||||
|
{
|
||||||
|
lazerLogo.FadeIn().OnComplete(_ => game.Add(flash));
|
||||||
|
}
|
||||||
|
|
||||||
|
flash.FadeInCompleted = () =>
|
||||||
|
{
|
||||||
|
logoContainerSecondary.Remove(lazerLogo, true);
|
||||||
|
triangles.FadeOut();
|
||||||
|
logo.FadeIn();
|
||||||
|
showBackgroundAction();
|
||||||
|
LoadMenu();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial class GameWideFlash : Box
|
||||||
|
{
|
||||||
|
public Action? FadeInCompleted;
|
||||||
|
|
||||||
|
public GameWideFlash()
|
||||||
|
{
|
||||||
|
Colour = Color4.White;
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
Blending = BlendingParameters.Additive;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
Alpha = 0;
|
||||||
|
|
||||||
|
this.FadeTo(0.5f, beat_length * 2, Easing.In)
|
||||||
|
.OnComplete(_ => FadeInCompleted?.Invoke());
|
||||||
|
|
||||||
|
this.Delay(beat_length * 2)
|
||||||
|
.Then()
|
||||||
|
.FadeOutFromOne(3000, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial class LazerLogo : CompositeDrawable
|
||||||
|
{
|
||||||
|
private LogoAnimation highlight = null!;
|
||||||
|
private LogoAnimation background = null!;
|
||||||
|
|
||||||
|
public float Progress
|
||||||
|
{
|
||||||
|
get => background.AnimationProgress;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
background.AnimationProgress = value;
|
||||||
|
highlight.AnimationProgress = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LazerLogo()
|
||||||
|
{
|
||||||
|
Size = new Vector2(960);
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(LargeTextureStore textures)
|
||||||
|
{
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
highlight = new LogoAnimation
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Texture = textures.Get(@"Intro/Triangles/logo-highlight"),
|
||||||
|
Colour = Color4.White,
|
||||||
|
},
|
||||||
|
background = new LogoAnimation
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Texture = textures.Get(@"Intro/Triangles/logo-background"),
|
||||||
|
Colour = OsuColour.Gray(0.6f),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial class GlitchingTriangles : BeatSyncedContainer
|
||||||
|
{
|
||||||
|
private int beatsHandled;
|
||||||
|
|
||||||
|
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes)
|
||||||
|
{
|
||||||
|
base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes);
|
||||||
|
|
||||||
|
Divisor = beatsHandled < 4 ? 1 : 4;
|
||||||
|
|
||||||
|
for (int i = 0; i < (beatsHandled + 1); i++)
|
||||||
|
{
|
||||||
|
float angle = (float)(RNG.NextDouble() * 2 * Math.PI);
|
||||||
|
float randomRadius = (float)(Math.Sqrt(RNG.NextDouble()));
|
||||||
|
|
||||||
|
float x = 0.5f + 0.5f * randomRadius * (float)Math.Cos(angle);
|
||||||
|
float y = 0.5f + 0.5f * randomRadius * (float)Math.Sin(angle);
|
||||||
|
|
||||||
|
Color4 christmasColour = RNG.NextBool() ? SeasonalUIConfig.PRIMARY_COLOUR_1 : SeasonalUIConfig.PRIMARY_COLOUR_2;
|
||||||
|
|
||||||
|
Drawable triangle = new Triangle
|
||||||
|
{
|
||||||
|
Size = new Vector2(RNG.NextSingle() + 1.2f) * 80,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativePositionAxes = Axes.Both,
|
||||||
|
Position = new Vector2(x, y),
|
||||||
|
Colour = christmasColour
|
||||||
|
};
|
||||||
|
|
||||||
|
if (beatsHandled >= 10)
|
||||||
|
triangle.Blending = BlendingParameters.Additive;
|
||||||
|
|
||||||
|
AddInternal(triangle);
|
||||||
|
triangle
|
||||||
|
.ScaleTo(0.9f)
|
||||||
|
.ScaleTo(1, beat_length / 2, Easing.Out);
|
||||||
|
triangle.FadeInFromZero(100, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
|
||||||
|
beatsHandled += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
206
osu.Game/Seasonal/MainMenuSeasonalLighting.cs
Normal file
206
osu.Game/Seasonal/MainMenuSeasonalLighting.cs
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Effects;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Timing;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Audio;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Seasonal
|
||||||
|
{
|
||||||
|
public partial class MainMenuSeasonalLighting : CompositeDrawable
|
||||||
|
{
|
||||||
|
private IBindable<WorkingBeatmap> working = null!;
|
||||||
|
|
||||||
|
private InterpolatingFramedClock? beatmapClock;
|
||||||
|
|
||||||
|
private List<HitObject> hitObjects = null!;
|
||||||
|
|
||||||
|
private RulesetInfo? osuRuleset;
|
||||||
|
|
||||||
|
private int? lastObjectIndex;
|
||||||
|
|
||||||
|
public MainMenuSeasonalLighting()
|
||||||
|
{
|
||||||
|
// match beatmap playfield
|
||||||
|
RelativeChildSize = new Vector2(512, 384);
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(IBindable<WorkingBeatmap> working, RulesetStore rulesets)
|
||||||
|
{
|
||||||
|
// operate in osu! ruleset to keep things simple for now.
|
||||||
|
osuRuleset = rulesets.GetRuleset(0);
|
||||||
|
|
||||||
|
this.working = working.GetBoundCopy();
|
||||||
|
this.working.BindValueChanged(_ => Scheduler.AddOnce(updateBeatmap), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateBeatmap()
|
||||||
|
{
|
||||||
|
lastObjectIndex = null;
|
||||||
|
|
||||||
|
if (osuRuleset == null)
|
||||||
|
{
|
||||||
|
beatmapClock = new InterpolatingFramedClock(Clock);
|
||||||
|
hitObjects = new List<HitObject>();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intentionally maintain separately so the lighting is not in audio clock space (it shouldn't rewind etc.)
|
||||||
|
beatmapClock = new InterpolatingFramedClock(new FramedClock(working.Value.Track));
|
||||||
|
|
||||||
|
hitObjects = working.Value
|
||||||
|
.GetPlayableBeatmap(osuRuleset)
|
||||||
|
.HitObjects
|
||||||
|
.SelectMany(h => h.NestedHitObjects.Prepend(h))
|
||||||
|
.OrderBy(h => h.StartTime)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
if (osuRuleset == null || beatmapClock == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Height = DrawWidth / 16 * 10;
|
||||||
|
|
||||||
|
beatmapClock.ProcessFrame();
|
||||||
|
|
||||||
|
// intentionally slightly early since we are doing fades on the lighting.
|
||||||
|
double time = beatmapClock.CurrentTime + 50;
|
||||||
|
|
||||||
|
// handle seeks or OOB by skipping to current.
|
||||||
|
if (lastObjectIndex == null || lastObjectIndex >= hitObjects.Count || (lastObjectIndex >= 0 && hitObjects[lastObjectIndex.Value].StartTime > time)
|
||||||
|
|| Math.Abs(beatmapClock.ElapsedFrameTime) > 500)
|
||||||
|
lastObjectIndex = hitObjects.Count(h => h.StartTime < time) - 1;
|
||||||
|
|
||||||
|
while (lastObjectIndex < hitObjects.Count - 1)
|
||||||
|
{
|
||||||
|
var h = hitObjects[lastObjectIndex.Value + 1];
|
||||||
|
|
||||||
|
if (h.StartTime > time)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Don't add lighting if the game is running too slow.
|
||||||
|
if (Clock.ElapsedFrameTime < 20)
|
||||||
|
addLight(h);
|
||||||
|
|
||||||
|
lastObjectIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addLight(HitObject h)
|
||||||
|
{
|
||||||
|
var light = new Light
|
||||||
|
{
|
||||||
|
RelativePositionAxes = Axes.Both,
|
||||||
|
Position = ((IHasPosition)h).Position
|
||||||
|
};
|
||||||
|
|
||||||
|
AddInternal(light);
|
||||||
|
|
||||||
|
if (h.GetType().Name.Contains("Tick"))
|
||||||
|
{
|
||||||
|
light.Colour = SeasonalUIConfig.AMBIENT_COLOUR_1;
|
||||||
|
light.Scale = new Vector2(0.5f);
|
||||||
|
light
|
||||||
|
.FadeInFromZero(250)
|
||||||
|
.Then()
|
||||||
|
.FadeOutFromOne(1000, Easing.Out);
|
||||||
|
|
||||||
|
light.MoveToOffset(new Vector2(RNG.Next(-20, 20), RNG.Next(-20, 20)), 1400, Easing.Out);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// default are green
|
||||||
|
Color4 col = SeasonalUIConfig.PRIMARY_COLOUR_2;
|
||||||
|
|
||||||
|
// whistles are red
|
||||||
|
if (h.Samples.Any(s => s.Name == HitSampleInfo.HIT_WHISTLE))
|
||||||
|
col = SeasonalUIConfig.PRIMARY_COLOUR_1;
|
||||||
|
// clap is third ambient (yellow) colour
|
||||||
|
else if (h.Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP))
|
||||||
|
col = SeasonalUIConfig.AMBIENT_COLOUR_1;
|
||||||
|
|
||||||
|
light.Colour = col;
|
||||||
|
|
||||||
|
// finish results in larger lighting
|
||||||
|
if (h.Samples.Any(s => s.Name == HitSampleInfo.HIT_FINISH))
|
||||||
|
light.Scale = new Vector2(3);
|
||||||
|
|
||||||
|
light
|
||||||
|
.FadeInFromZero(150)
|
||||||
|
.Then()
|
||||||
|
.FadeOutFromOne(1000, Easing.In);
|
||||||
|
}
|
||||||
|
|
||||||
|
light.Expire();
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial class Light : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly Circle circle;
|
||||||
|
|
||||||
|
public new Color4 Colour
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
circle.Colour = value.Darken(0.8f);
|
||||||
|
circle.EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = value,
|
||||||
|
Radius = 80,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Light()
|
||||||
|
{
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
circle = new Circle
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Size = new Vector2(12),
|
||||||
|
Colour = SeasonalUIConfig.AMBIENT_COLOUR_1,
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = SeasonalUIConfig.AMBIENT_COLOUR_2,
|
||||||
|
Radius = 80,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
Alpha = 0.5f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
76
osu.Game/Seasonal/OsuLogoChristmas.cs
Normal file
76
osu.Game/Seasonal/OsuLogoChristmas.cs
Normal 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.Audio;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osu.Game.Screens.Menu;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Seasonal
|
||||||
|
{
|
||||||
|
public partial class OsuLogoChristmas : OsuLogo
|
||||||
|
{
|
||||||
|
protected override double BeatSampleVariance => 0.02;
|
||||||
|
|
||||||
|
private Sprite? hat;
|
||||||
|
|
||||||
|
private bool hasHat;
|
||||||
|
|
||||||
|
protected override MenuLogoVisualisation CreateMenuLogoVisualisation() => new SeasonalMenuLogoVisualisation();
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(TextureStore textures, AudioManager audio)
|
||||||
|
{
|
||||||
|
LogoElements.Add(hat = new Sprite
|
||||||
|
{
|
||||||
|
BypassAutoSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0,
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
Scale = new Vector2(-1, 1),
|
||||||
|
Texture = textures.Get(@"Menu/hat"),
|
||||||
|
});
|
||||||
|
|
||||||
|
// override base samples with our preferred ones.
|
||||||
|
SampleDownbeat = SampleBeat = audio.Samples.Get(@"Menu/osu-logo-heartbeat-bell");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
updateHat();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateHat()
|
||||||
|
{
|
||||||
|
if (hat == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool shouldHat = DrawWidth * Scale.X < 400;
|
||||||
|
|
||||||
|
if (shouldHat != hasHat)
|
||||||
|
{
|
||||||
|
hasHat = shouldHat;
|
||||||
|
|
||||||
|
if (hasHat)
|
||||||
|
{
|
||||||
|
hat.Delay(400)
|
||||||
|
.Then()
|
||||||
|
.MoveTo(new Vector2(120, 160))
|
||||||
|
.RotateTo(0)
|
||||||
|
.RotateTo(-20, 500, Easing.OutQuint)
|
||||||
|
.FadeIn(250, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hat.Delay(100)
|
||||||
|
.Then()
|
||||||
|
.MoveToOffset(new Vector2(0, -5), 500, Easing.OutQuint)
|
||||||
|
.FadeOut(500, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
osu.Game/Seasonal/SeasonalMenuLogoVisualisation.cs
Normal file
12
osu.Game/Seasonal/SeasonalMenuLogoVisualisation.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 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.Game.Screens.Menu;
|
||||||
|
|
||||||
|
namespace osu.Game.Seasonal
|
||||||
|
{
|
||||||
|
internal partial class SeasonalMenuLogoVisualisation : MenuLogoVisualisation
|
||||||
|
{
|
||||||
|
protected override void UpdateColour() => Colour = SeasonalUIConfig.AMBIENT_COLOUR_1;
|
||||||
|
}
|
||||||
|
}
|
18
osu.Game/Seasonal/SeasonalMenuSideFlashes.cs
Normal file
18
osu.Game/Seasonal/SeasonalMenuSideFlashes.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// 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.Utils;
|
||||||
|
using osu.Game.Screens.Menu;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Seasonal
|
||||||
|
{
|
||||||
|
public partial class SeasonalMenuSideFlashes : MenuSideFlashes
|
||||||
|
{
|
||||||
|
protected override bool RefreshColoursEveryFlash => true;
|
||||||
|
|
||||||
|
protected override float Intensity => 4;
|
||||||
|
|
||||||
|
protected override Color4 GetBaseColour() => RNG.NextBool() ? SeasonalUIConfig.PRIMARY_COLOUR_1 : SeasonalUIConfig.PRIMARY_COLOUR_2;
|
||||||
|
}
|
||||||
|
}
|
24
osu.Game/Seasonal/SeasonalUIConfig.cs
Normal file
24
osu.Game/Seasonal/SeasonalUIConfig.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// 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.Extensions.Color4Extensions;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Seasonal
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// General configuration setting for seasonal event adjustments to the game.
|
||||||
|
/// </summary>
|
||||||
|
public static class SeasonalUIConfig
|
||||||
|
{
|
||||||
|
public static readonly bool ENABLED = false;
|
||||||
|
|
||||||
|
public static readonly Color4 PRIMARY_COLOUR_1 = Color4Extensions.FromHex(@"D32F2F");
|
||||||
|
|
||||||
|
public static readonly Color4 PRIMARY_COLOUR_2 = Color4Extensions.FromHex(@"388E3C");
|
||||||
|
|
||||||
|
public static readonly Color4 AMBIENT_COLOUR_1 = Color4Extensions.FromHex(@"FFFFCC");
|
||||||
|
|
||||||
|
public static readonly Color4 AMBIENT_COLOUR_2 = Color4Extensions.FromHex(@"FFE4B5");
|
||||||
|
}
|
||||||
|
}
|
@ -35,8 +35,8 @@
|
|||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Realm" Version="11.5.0" />
|
<PackageReference Include="Realm" Version="11.5.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2024.1220.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2024.1224.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2024.1219.1" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2024.1224.0" />
|
||||||
<PackageReference Include="Sentry" Version="4.13.0" />
|
<PackageReference Include="Sentry" Version="4.13.0" />
|
||||||
<!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. -->
|
<!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. -->
|
||||||
<PackageReference Include="SharpCompress" Version="0.38.0" />
|
<PackageReference Include="SharpCompress" Version="0.38.0" />
|
||||||
|
@ -17,6 +17,6 @@
|
|||||||
<MtouchInterpreter>-all</MtouchInterpreter>
|
<MtouchInterpreter>-all</MtouchInterpreter>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2024.1220.0" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2024.1224.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
14
osu.iOS/AppDelegate.cs
Normal file
14
osu.iOS/AppDelegate.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// 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 Foundation;
|
||||||
|
using osu.Framework.iOS;
|
||||||
|
|
||||||
|
namespace osu.iOS
|
||||||
|
{
|
||||||
|
[Register("AppDelegate")]
|
||||||
|
public class AppDelegate : GameApplicationDelegate
|
||||||
|
{
|
||||||
|
protected override Framework.Game CreateGame() => new OsuGameIOS();
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,8 @@ namespace osu.iOS
|
|||||||
{
|
{
|
||||||
public override Version AssemblyVersion => new Version(NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString());
|
public override Version AssemblyVersion => new Version(NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString());
|
||||||
|
|
||||||
|
public override bool HideUnlicensedContent => true;
|
||||||
|
|
||||||
protected override UpdateManager CreateUpdateManager() => new MobileUpdateNotifier();
|
protected override UpdateManager CreateUpdateManager() => new MobileUpdateNotifier();
|
||||||
|
|
||||||
protected override BatteryInfo CreateBatteryInfo() => new IOSBatteryInfo();
|
protected override BatteryInfo CreateBatteryInfo() => new IOSBatteryInfo();
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Framework.iOS;
|
using UIKit;
|
||||||
|
|
||||||
namespace osu.iOS
|
namespace osu.iOS
|
||||||
{
|
{
|
||||||
public static class Application
|
public static class Program
|
||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
GameApplication.Main(new OsuGameIOS());
|
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user