diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformRuleset.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformRuleset.cs
index 00754c6346..1e88f87f09 100644
--- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformRuleset.cs
+++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformRuleset.cs
@@ -77,5 +77,8 @@ namespace osu.Game.Rulesets.EmptyFreeform
};
}
}
+
+ // Leave this line intact. It will bake the correct version into the ruleset on each build/release.
+ public override string RulesetAPIVersionSupported => CURRENT_RULESET_API_VERSION;
}
}
diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonRuleset.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonRuleset.cs
index 0522840e9e..2f6ba0dda6 100644
--- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonRuleset.cs
+++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonRuleset.cs
@@ -49,5 +49,8 @@ namespace osu.Game.Rulesets.Pippidon
};
public override Drawable CreateIcon() => new PippidonRulesetIcon(this);
+
+ // Leave this line intact. It will bake the correct version into the ruleset on each build/release.
+ public override string RulesetAPIVersionSupported => CURRENT_RULESET_API_VERSION;
}
}
diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingRuleset.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingRuleset.cs
index c8f0c07724..a32586c414 100644
--- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingRuleset.cs
+++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingRuleset.cs
@@ -54,5 +54,8 @@ namespace osu.Game.Rulesets.EmptyScrolling
Text = ShortName[0].ToString(),
Font = OsuFont.Default.With(size: 18),
};
+
+ // Leave this line intact. It will bake the correct version into the ruleset on each build/release.
+ public override string RulesetAPIVersionSupported => CURRENT_RULESET_API_VERSION;
}
}
diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonRuleset.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonRuleset.cs
index 89246373ee..bde530feb8 100644
--- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonRuleset.cs
+++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonRuleset.cs
@@ -46,5 +46,8 @@ namespace osu.Game.Rulesets.Pippidon
};
public override Drawable CreateIcon() => new PippidonRulesetIcon(this);
+
+ // Leave this line intact. It will bake the correct version into the ruleset on each build/release.
+ public override string RulesetAPIVersionSupported => CURRENT_RULESET_API_VERSION;
}
}
diff --git a/osu.Android.props b/osu.Android.props
index 17a6178641..2c186a52dd 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -51,8 +51,8 @@
-
-
+
+
diff --git a/osu.Desktop/Security/ElevatedPrivilegesChecker.cs b/osu.Desktop/Security/ElevatedPrivilegesChecker.cs
index 9959b24b35..cc4337fb02 100644
--- a/osu.Desktop/Security/ElevatedPrivilegesChecker.cs
+++ b/osu.Desktop/Security/ElevatedPrivilegesChecker.cs
@@ -76,7 +76,7 @@ namespace osu.Desktop.Security
private void load(OsuColour colours)
{
Icon = FontAwesome.Solid.ShieldAlt;
- IconBackground.Colour = colours.YellowDark;
+ IconContent.Colour = colours.YellowDark;
}
}
}
diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs
index d53db6c516..84bac9da7c 100644
--- a/osu.Desktop/Updater/SquirrelUpdateManager.cs
+++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs
@@ -5,29 +5,24 @@ using System;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using osu.Framework.Allocation;
-using osu.Framework.Graphics;
-using osu.Framework.Graphics.Colour;
-using osu.Framework.Graphics.Shapes;
-using osu.Framework.Graphics.Sprites;
using osu.Framework.Logging;
using osu.Game;
-using osu.Game.Graphics;
using osu.Game.Overlays;
using osu.Game.Overlays.Notifications;
-using osuTK;
-using osuTK.Graphics;
using Squirrel;
using Squirrel.SimpleSplat;
+using LogLevel = Squirrel.SimpleSplat.LogLevel;
+using UpdateManager = osu.Game.Updater.UpdateManager;
namespace osu.Desktop.Updater
{
[SupportedOSPlatform("windows")]
- public class SquirrelUpdateManager : osu.Game.Updater.UpdateManager
+ public class SquirrelUpdateManager : UpdateManager
{
- private UpdateManager? updateManager;
+ private Squirrel.UpdateManager? updateManager;
private INotificationOverlay notificationOverlay = null!;
- public Task PrepareUpdateAsync() => UpdateManager.RestartAppWhenExited();
+ public Task PrepareUpdateAsync() => Squirrel.UpdateManager.RestartAppWhenExited();
private static readonly Logger logger = Logger.GetLogger("updater");
@@ -38,6 +33,9 @@ namespace osu.Desktop.Updater
private readonly SquirrelLogger squirrelLogger = new SquirrelLogger();
+ [Resolved]
+ private OsuGameBase game { get; set; } = null!;
+
[BackgroundDependencyLoader]
private void load(INotificationOverlay notifications)
{
@@ -66,7 +64,14 @@ namespace osu.Desktop.Updater
if (updatePending)
{
// the user may have dismissed the completion notice, so show it again.
- notificationOverlay.Post(new UpdateCompleteNotification(this));
+ notificationOverlay.Post(new UpdateApplicationCompleteNotification
+ {
+ Activated = () =>
+ {
+ restartToApplyUpdate();
+ return true;
+ },
+ });
return true;
}
@@ -78,19 +83,21 @@ namespace osu.Desktop.Updater
if (notification == null)
{
- notification = new UpdateProgressNotification(this) { State = ProgressNotificationState.Active };
+ notification = new UpdateProgressNotification
+ {
+ CompletionClickAction = restartToApplyUpdate,
+ };
+
Schedule(() => notificationOverlay.Post(notification));
}
- notification.Progress = 0;
- notification.Text = @"Downloading update...";
+ notification.StartDownload();
try
{
await updateManager.DownloadReleases(info.ReleasesToApply, p => notification.Progress = p / 100f).ConfigureAwait(false);
- notification.Progress = 0;
- notification.Text = @"Installing update...";
+ notification.StartInstall();
await updateManager.ApplyReleases(info, p => notification.Progress = p / 100f).ConfigureAwait(false);
@@ -110,9 +117,7 @@ namespace osu.Desktop.Updater
else
{
// In the case of an error, a separate notification will be displayed.
- notification.State = ProgressNotificationState.Cancelled;
- notification.Close();
-
+ notification.FailDownload();
Logger.Error(e, @"update failed!");
}
}
@@ -134,84 +139,24 @@ namespace osu.Desktop.Updater
return true;
}
+ private bool restartToApplyUpdate()
+ {
+ PrepareUpdateAsync()
+ .ContinueWith(_ => Schedule(() => game.AttemptExit()));
+ return true;
+ }
+
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
updateManager?.Dispose();
}
- private class UpdateCompleteNotification : ProgressCompletionNotification
- {
- [Resolved]
- private OsuGame game { get; set; } = null!;
-
- public UpdateCompleteNotification(SquirrelUpdateManager updateManager)
- {
- Text = @"Update ready to install. Click to restart!";
-
- Activated = () =>
- {
- updateManager.PrepareUpdateAsync()
- .ContinueWith(_ => updateManager.Schedule(() => game.AttemptExit()));
- return true;
- };
- }
- }
-
- private class UpdateProgressNotification : ProgressNotification
- {
- private readonly SquirrelUpdateManager updateManager;
-
- public UpdateProgressNotification(SquirrelUpdateManager updateManager)
- {
- this.updateManager = updateManager;
- }
-
- protected override Notification CreateCompletionNotification()
- {
- return new UpdateCompleteNotification(updateManager);
- }
-
- [BackgroundDependencyLoader]
- private void load(OsuColour colours)
- {
- IconContent.AddRange(new Drawable[]
- {
- new Box
- {
- RelativeSizeAxes = Axes.Both,
- Colour = ColourInfo.GradientVertical(colours.YellowDark, colours.Yellow)
- },
- new SpriteIcon
- {
- Anchor = Anchor.Centre,
- Origin = Anchor.Centre,
- Icon = FontAwesome.Solid.Upload,
- Colour = Color4.White,
- Size = new Vector2(20),
- }
- });
- }
-
- public override void Close()
- {
- // cancelling updates is not currently supported by the underlying updater.
- // only allow dismissing for now.
-
- switch (State)
- {
- case ProgressNotificationState.Cancelled:
- base.Close();
- break;
- }
- }
- }
-
private class SquirrelLogger : ILogger, IDisposable
{
- public Squirrel.SimpleSplat.LogLevel Level { get; set; } = Squirrel.SimpleSplat.LogLevel.Info;
+ public LogLevel Level { get; set; } = LogLevel.Info;
- public void Write(string message, Squirrel.SimpleSplat.LogLevel logLevel)
+ public void Write(string message, LogLevel logLevel)
{
if (logLevel < Level)
return;
diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/CatchSelectionBlueprintTestScene.cs b/osu.Game.Rulesets.Catch.Tests/Editor/CatchSelectionBlueprintTestScene.cs
index ea17fa400c..60fb31d1e0 100644
--- a/osu.Game.Rulesets.Catch.Tests/Editor/CatchSelectionBlueprintTestScene.cs
+++ b/osu.Game.Rulesets.Catch.Tests/Editor/CatchSelectionBlueprintTestScene.cs
@@ -70,10 +70,17 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor
[Cached]
private readonly BindableBeatDivisor beatDivisor;
+ protected override Container Content { get; } = new Container { RelativeSizeAxes = Axes.Both };
+
public EditorBeatmapDependencyContainer(IBeatmap beatmap, BindableBeatDivisor beatDivisor)
{
- editorClock = new EditorClock(beatmap, beatDivisor);
this.beatDivisor = beatDivisor;
+
+ InternalChildren = new Drawable[]
+ {
+ editorClock = new EditorClock(beatmap, beatDivisor),
+ Content,
+ };
}
}
}
diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchTouchInput.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchTouchInput.cs
new file mode 100644
index 0000000000..cbf6e8f202
--- /dev/null
+++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchTouchInput.cs
@@ -0,0 +1,43 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using NUnit.Framework;
+using osu.Framework.Graphics;
+using osu.Framework.Testing;
+using osu.Game.Rulesets.Catch.UI;
+using osu.Game.Tests.Visual;
+
+namespace osu.Game.Rulesets.Catch.Tests
+{
+ [TestFixture]
+ public class TestSceneCatchTouchInput : OsuTestScene
+ {
+ private CatchTouchInputMapper catchTouchInputMapper = null!;
+
+ [SetUpSteps]
+ public void SetUpSteps()
+ {
+ AddStep("create input overlay", () =>
+ {
+ Child = new CatchInputManager(new CatchRuleset().RulesetInfo)
+ {
+ RelativeSizeAxes = Axes.Both,
+ Children = new Drawable[]
+ {
+ catchTouchInputMapper = new CatchTouchInputMapper
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre
+ }
+ }
+ };
+ });
+ }
+
+ [Test]
+ public void TestBasic()
+ {
+ AddStep("show overlay", () => catchTouchInputMapper.Show());
+ }
+ }
+}
diff --git a/osu.Game.Rulesets.Catch/CatchInputManager.cs b/osu.Game.Rulesets.Catch/CatchInputManager.cs
index 86f35c8cee..5b62154a34 100644
--- a/osu.Game.Rulesets.Catch/CatchInputManager.cs
+++ b/osu.Game.Rulesets.Catch/CatchInputManager.cs
@@ -4,11 +4,13 @@
#nullable disable
using System.ComponentModel;
+using osu.Framework.Allocation;
using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Catch
{
+ [Cached]
public class CatchInputManager : RulesetInputManager
{
public CatchInputManager(RulesetInfo ruleset)
diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs
index ed151855b1..321399c597 100644
--- a/osu.Game.Rulesets.Catch/CatchRuleset.cs
+++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs
@@ -3,30 +3,30 @@
#nullable disable
-using osu.Game.Beatmaps;
-using osu.Game.Graphics;
-using osu.Game.Rulesets.Catch.Mods;
-using osu.Game.Rulesets.Catch.UI;
-using osu.Game.Rulesets.Mods;
-using osu.Game.Rulesets.UI;
+using System;
using System.Collections.Generic;
+using osu.Framework.Extensions.EnumExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Bindings;
-using osu.Game.Rulesets.Catch.Replays;
-using osu.Game.Rulesets.Replays.Types;
+using osu.Framework.Localisation;
+using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Legacy;
+using osu.Game.Graphics;
using osu.Game.Rulesets.Catch.Beatmaps;
using osu.Game.Rulesets.Catch.Difficulty;
-using osu.Game.Rulesets.Catch.Scoring;
-using osu.Game.Rulesets.Difficulty;
-using osu.Game.Rulesets.Scoring;
-using System;
-using osu.Framework.Extensions.EnumExtensions;
-using osu.Framework.Localisation;
using osu.Game.Rulesets.Catch.Edit;
+using osu.Game.Rulesets.Catch.Mods;
+using osu.Game.Rulesets.Catch.Replays;
+using osu.Game.Rulesets.Catch.Scoring;
using osu.Game.Rulesets.Catch.Skinning.Legacy;
+using osu.Game.Rulesets.Catch.UI;
+using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Edit;
+using osu.Game.Rulesets.Mods;
+using osu.Game.Rulesets.Replays.Types;
+using osu.Game.Rulesets.Scoring;
+using osu.Game.Rulesets.UI;
using osu.Game.Skinning;
namespace osu.Game.Rulesets.Catch
@@ -43,6 +43,8 @@ namespace osu.Game.Rulesets.Catch
public const string SHORT_NAME = "fruits";
+ public override string RulesetAPIVersionSupported => CURRENT_RULESET_API_VERSION;
+
public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[]
{
new KeyBinding(InputKey.Z, CatchAction.MoveLeft),
diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs
index 44d14ec330..8473eda663 100644
--- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs
+++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs
@@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components
public void UpdateFrom(ScrollingHitObjectContainer hitObjectContainer, JuiceStream hitObject)
{
while (path.Vertices.Count < InternalChildren.Count)
- RemoveInternal(InternalChildren[^1]);
+ RemoveInternal(InternalChildren[^1], true);
while (InternalChildren.Count < path.Vertices.Count)
AddInternal(new VertexPiece());
diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/NestedOutlineContainer.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/NestedOutlineContainer.cs
index 431ba331ac..a6f1732bc1 100644
--- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/NestedOutlineContainer.cs
+++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/NestedOutlineContainer.cs
@@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components
.Where(h => !(h is TinyDroplet)));
while (nestedHitObjects.Count < InternalChildren.Count)
- RemoveInternal(InternalChildren[^1]);
+ RemoveInternal(InternalChildren[^1], true);
while (InternalChildren.Count < nestedHitObjects.Count)
AddInternal(new FruitOutline());
diff --git a/osu.Game.Rulesets.Catch/UI/CatchTouchInputMapper.cs b/osu.Game.Rulesets.Catch/UI/CatchTouchInputMapper.cs
new file mode 100644
index 0000000000..e6736d6c93
--- /dev/null
+++ b/osu.Game.Rulesets.Catch/UI/CatchTouchInputMapper.cs
@@ -0,0 +1,277 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Collections.Generic;
+using System.Linq;
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
+using osu.Framework.Input.Bindings;
+using osu.Framework.Input.Events;
+using osu.Game.Graphics;
+using osuTK;
+using osuTK.Input;
+
+namespace osu.Game.Rulesets.Catch.UI
+{
+ public class CatchTouchInputMapper : VisibilityContainer
+ {
+ public override bool PropagatePositionalInputSubTree => true;
+ public override bool PropagateNonPositionalInputSubTree => true;
+
+ private readonly Dictionary