diff --git a/osu.Android.props b/osu.Android.props
index b24493665e..0dd3c98116 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -63,6 +63,6 @@
-
+
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs
index 97c7c9cec5..6bc19ee3b5 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs
@@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System;
using System.Collections.Generic;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Lines;
@@ -75,22 +76,22 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
protected SliderBody()
{
- InternalChild = path = new SliderPath();
+ RecyclePath();
}
///
/// Initialises a new , releasing all resources retained by the old one.
///
- public void RecyclePath()
+ public virtual void RecyclePath()
{
InternalChild = path = new SliderPath
{
- Position = path.Position,
- PathRadius = path.PathRadius,
- AccentColour = path.AccentColour,
- BorderColour = path.BorderColour,
- BorderSize = path.BorderSize,
- Vertices = path.Vertices
+ Position = path?.Position ?? Vector2.Zero,
+ PathRadius = path?.PathRadius ?? 10,
+ AccentColour = path?.AccentColour ?? Color4.White,
+ BorderColour = path?.BorderColour ?? Color4.White,
+ BorderSize = path?.BorderSize ?? DEFAULT_BORDER_SIZE,
+ Vertices = path?.Vertices ?? Array.Empty()
};
}
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs
index 73b184bffe..a3d3893c8b 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
+using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Types;
using osuTK;
@@ -78,9 +79,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
slider.Path.GetPathToProgress(CurrentCurve, 0, 1);
SetVertices(CurrentCurve);
- // The body is sized to the full path size to avoid excessive autosize computations
+ // Force the body to be the final path size to avoid excessive autosize computations
+ Path.AutoSizeAxes = Axes.Both;
Size = Path.Size;
+ updatePathSize();
+
snakedPosition = Path.PositionInBoundingBox(Vector2.Zero);
snakedPathOffset = Path.PositionInBoundingBox(Path.Vertices[0]);
@@ -93,6 +97,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
setRange(lastSnakedStart, lastSnakedEnd);
}
+ public override void RecyclePath()
+ {
+ base.RecyclePath();
+ updatePathSize();
+ }
+
+ private void updatePathSize()
+ {
+ // Force the path to its final size to avoid excessive framebuffer resizes
+ Path.AutoSizeAxes = Axes.None;
+ Path.Size = Size;
+ }
+
private void setRange(double p0, double p1)
{
if (p0 > p1)
diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs
index 65efcaa949..166ba5111c 100644
--- a/osu.Game/Beatmaps/BeatmapManager.cs
+++ b/osu.Game/Beatmaps/BeatmapManager.cs
@@ -386,7 +386,7 @@ namespace osu.Game.Beatmaps
beatmap.OnlineBeatmapID = res.OnlineBeatmapID;
};
- req.Failure += e => { LogForModel(set, $"Online retrieval failed for {beatmap}", e); };
+ req.Failure += e => { LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})"); };
// intentionally blocking to limit web request concurrency
req.Perform(api);
diff --git a/osu.Game/Graphics/UserInterface/LineGraph.cs b/osu.Game/Graphics/UserInterface/LineGraph.cs
index 757a9a349c..714e953816 100644
--- a/osu.Game/Graphics/UserInterface/LineGraph.cs
+++ b/osu.Game/Graphics/UserInterface/LineGraph.cs
@@ -76,7 +76,12 @@ namespace osu.Game.Graphics.UserInterface
{
Masking = true,
RelativeSizeAxes = Axes.Both,
- Child = path = new SmoothPath { RelativeSizeAxes = Axes.Both, PathRadius = 1 }
+ Child = path = new SmoothPath
+ {
+ AutoSizeAxes = Axes.None,
+ RelativeSizeAxes = Axes.Both,
+ PathRadius = 1
+ }
});
}
diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs
index 8134cfb42d..d158186899 100644
--- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs
+++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs
@@ -64,7 +64,7 @@ namespace osu.Game.Graphics.UserInterface
Direction = FillDirection.Horizontal,
Children = new Drawable[]
{
- text = new OsuSpriteText { Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold) },
+ text = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) },
icon = new SpriteIcon
{
Size = new Vector2(14),
@@ -84,7 +84,11 @@ namespace osu.Game.Graphics.UserInterface
}
};
- Current.ValueChanged += selected => { icon.Icon = selected.NewValue ? FontAwesome.Regular.CheckCircle : FontAwesome.Regular.Circle; };
+ Current.ValueChanged += selected =>
+ {
+ icon.Icon = selected.NewValue ? FontAwesome.Regular.CheckCircle : FontAwesome.Regular.Circle;
+ text.Font = text.Font.With(weight: selected.NewValue ? FontWeight.Bold : FontWeight.Medium);
+ };
}
[BackgroundDependencyLoader]
diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs
index 41b67f343a..ceaf0c3d5e 100644
--- a/osu.Game/OsuGame.cs
+++ b/osu.Game/OsuGame.cs
@@ -589,7 +589,7 @@ namespace osu.Game
{
int recentLogCount = 0;
- const double debounce = 5000;
+ const double debounce = 60000;
Logger.NewEntry += entry =>
{
diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs
index 7f820e4ff7..2a3dd55c71 100644
--- a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs
+++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs
@@ -16,6 +16,7 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Online.Chat;
using osuTK;
using osuTK.Graphics;
+using osuTK.Input;
namespace osu.Game.Overlays.Chat.Tabs
{
@@ -138,6 +139,19 @@ namespace osu.Game.Overlays.Chat.Tabs
updateState();
}
+ protected override bool OnMouseUp(MouseUpEvent e)
+ {
+ switch (e.Button)
+ {
+ case MouseButton.Middle:
+ CloseButton.Click();
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs
index 005cdd36d7..f96c176104 100644
--- a/osu.Game/Screens/Play/BreakOverlay.cs
+++ b/osu.Game/Screens/Play/BreakOverlay.cs
@@ -21,11 +21,11 @@ namespace osu.Game.Screens.Play
private const float remaining_time_container_max_size = 0.3f;
private const int vertical_margin = 25;
- private List breaks;
-
private readonly Container fadeContainer;
- public List Breaks
+ private IReadOnlyList breaks;
+
+ public IReadOnlyList Breaks
{
get => breaks;
set
diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs
index 16354534f4..5069096a44 100644
--- a/osu.Game/Screens/Select/BeatmapCarousel.cs
+++ b/osu.Game/Screens/Select/BeatmapCarousel.cs
@@ -81,7 +81,8 @@ namespace osu.Game.Screens.Select
itemsCache.Invalidate();
scrollPositionCache.Invalidate();
- Schedule(() =>
+ // Run on late scheduler want to ensure this runs after all pending UpdateBeatmapSet / RemoveBeatmapSet operations are run.
+ SchedulerAfterChildren.Add(() =>
{
BeatmapSetsChanged?.Invoke();
BeatmapSetsLoaded = true;
@@ -129,19 +130,16 @@ namespace osu.Game.Screens.Select
loadBeatmapSets(beatmaps.GetAllUsableBeatmapSetsEnumerable());
}
- public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet)
+ public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() =>
{
- Schedule(() =>
- {
- var existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.ID == beatmapSet.ID);
+ var existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.ID == beatmapSet.ID);
- if (existingSet == null)
- return;
+ if (existingSet == null)
+ return;
- root.RemoveChild(existingSet);
- itemsCache.Invalidate();
- });
- }
+ root.RemoveChild(existingSet);
+ itemsCache.Invalidate();
+ });
public void UpdateBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() =>
{
diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs
index f66cd2b29a..7f82d3cc12 100644
--- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs
+++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs
@@ -25,22 +25,6 @@ namespace osu.Game.Screens.Select
private Bindable selectedTab;
- private void invokeOnFilter()
- {
- OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value);
- }
-
- [BackgroundDependencyLoader]
- private void load(OsuColour colour, OsuConfigManager config)
- {
- modsCheckbox.AccentColour = tabs.AccentColour = colour.YellowLight;
-
- selectedTab = config.GetBindable(OsuSetting.BeatmapDetailTab);
-
- tabs.Current.BindTo(selectedTab);
- tabs.Current.TriggerChange();
- }
-
public BeatmapDetailAreaTabControl()
{
Height = HEIGHT;
@@ -66,12 +50,31 @@ namespace osu.Game.Screens.Select
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
Text = @"Mods",
+ Alpha = 0,
},
};
tabs.Current.ValueChanged += _ => invokeOnFilter();
modsCheckbox.Current.ValueChanged += _ => invokeOnFilter();
}
+
+ [BackgroundDependencyLoader]
+ private void load(OsuColour colour, OsuConfigManager config)
+ {
+ modsCheckbox.AccentColour = tabs.AccentColour = colour.YellowLight;
+
+ selectedTab = config.GetBindable(OsuSetting.BeatmapDetailTab);
+
+ tabs.Current.BindTo(selectedTab);
+ tabs.Current.TriggerChange();
+ }
+
+ private void invokeOnFilter()
+ {
+ OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value);
+
+ modsCheckbox.FadeTo(tabs.Current.Value == BeatmapDetailTab.Details ? 0 : 1, 200, Easing.OutQuint);
+ }
}
public enum BeatmapDetailTab
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index c05cc6f9dd..9f405d1099 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -15,7 +15,7 @@
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index 3b18039600..4e8ce18c6f 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -105,8 +105,8 @@
-
-
+
+
diff --git a/osu.iOS/AppDelegate.cs b/osu.iOS/AppDelegate.cs
index 058e246ed8..9ef21e014c 100644
--- a/osu.iOS/AppDelegate.cs
+++ b/osu.iOS/AppDelegate.cs
@@ -1,15 +1,25 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System.Threading.Tasks;
using Foundation;
using osu.Framework.iOS;
using osu.Game;
+using UIKit;
namespace osu.iOS
{
[Register("AppDelegate")]
public class AppDelegate : GameAppDelegate
{
- protected override Framework.Game CreateGame() => new OsuGameIOS();
+ private OsuGameIOS game;
+
+ protected override Framework.Game CreateGame() => game = new OsuGameIOS();
+
+ public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
+ {
+ Task.Run(() => game.Import(url.Path));
+ return true;
+ }
}
}
diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist
index d7992353cf..0775d1522d 100644
--- a/osu.iOS/Info.plist
+++ b/osu.iOS/Info.plist
@@ -40,5 +40,70 @@
XSAppIconAssets
Assets.xcassets/AppIcon.appiconset
+ UTExportedTypeDeclarations
+
+
+ UTTypeConformsTo
+
+
+
+ UTTypeIdentifier
+ sh.ppy.osu.items
+ UTTypeTagSpecification
+
+
+
+ UTTypeConformsTo
+
+ sh.ppy.osu.items
+
+ UTTypeIdentifier
+ sh.ppy.osu.osr
+ UTTypeTagSpecification
+
+ public.filename-extension
+ osr
+
+
+
+ UTTypeConformsTo
+
+ sh.ppy.osu.items
+
+ UTTypeIdentifier
+ sh.ppy.osu.osk
+ UTTypeTagSpecification
+
+ public.filename-extension
+ osk
+
+
+
+ UTTypeConformsTo
+
+ sh.ppy.osu.items
+
+ UTTypeIdentifier
+ sh.ppy.osu.osz
+ UTTypeTagSpecification
+
+ public.filename-extension
+ osz
+
+
+
+ CFBundleDocumentTypes
+
+
+ LSHandlerRank
+ Owner
+ CFBundleTypeName
+ Supported osu! files
+ LSItemContentTypes
+
+ sh.ppy.osu.items
+
+
+