diff --git a/Gemfile.lock b/Gemfile.lock
index 17c0db12e7..f7c19064b4 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -6,7 +6,7 @@ GEM
public_suffix (>= 2.0.2, < 4.0)
atomos (0.1.3)
babosa (1.0.2)
- claide (1.0.2)
+ claide (1.0.3)
colored (1.2)
colored2 (3.1.2)
commander-fastlane (4.4.6)
@@ -14,11 +14,11 @@ GEM
declarative (0.0.10)
declarative-option (0.1.0)
digest-crc (0.4.1)
- domain_name (0.5.20180417)
+ domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
- dotenv (2.7.1)
+ dotenv (2.7.5)
emoji_regex (1.0.1)
- excon (0.62.0)
+ excon (0.66.0)
faraday (0.15.4)
multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.6)
@@ -27,7 +27,7 @@ GEM
faraday_middleware (0.13.1)
faraday (>= 0.7.4, < 1.0)
fastimage (2.1.5)
- fastlane (2.117.0)
+ fastlane (2.129.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.3, < 3.0.0)
babosa (>= 1.0.2, < 2.0.0)
@@ -46,8 +46,8 @@ GEM
google-cloud-storage (>= 1.15.0, < 2.0.0)
highline (>= 1.7.2, < 2.0.0)
json (< 3.0.0)
- mini_magick (~> 4.5.1)
- multi_json
+ jwt (~> 2.1.0)
+ mini_magick (>= 4.9.4, < 5.0.0)
multi_xml (~> 0.5)
multipart-post (~> 2.0.0)
plist (>= 3.1.0, < 4.0.0)
@@ -56,15 +56,15 @@ GEM
security (= 0.1.3)
simctl (~> 1.6.3)
slack-notifier (>= 2.0.0, < 3.0.0)
- terminal-notifier (>= 1.6.2, < 2.0.0)
+ terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
- xcodeproj (>= 1.6.0, < 2.0.0)
+ xcodeproj (>= 1.8.1, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
- fastlane-plugin-clean_testflight_testers (0.2.0)
+ fastlane-plugin-clean_testflight_testers (0.3.0)
fastlane-plugin-souyuz (0.8.1)
souyuz (>= 0.8.1)
fastlane-plugin-xamarin (0.6.3)
@@ -79,7 +79,7 @@ GEM
signet (~> 0.9)
google-cloud-core (1.3.0)
google-cloud-env (~> 1.0)
- google-cloud-env (1.0.5)
+ google-cloud-env (1.2.0)
faraday (~> 0.11)
google-cloud-storage (1.16.0)
digest-crc (~> 0.4)
@@ -102,17 +102,17 @@ GEM
memoist (0.16.0)
mime-types (3.2.2)
mime-types-data (~> 3.2015)
- mime-types-data (3.2018.0812)
- mini_magick (4.5.1)
+ mime-types-data (3.2019.0331)
+ mini_magick (4.9.5)
mini_portile2 (2.4.0)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
nanaimo (0.2.6)
naturally (2.2.0)
- nokogiri (1.10.1)
+ nokogiri (1.10.4)
mini_portile2 (~> 2.4.0)
- os (1.0.0)
+ os (1.0.1)
plist (3.5.0)
public_suffix (2.0.5)
representable (3.0.4)
@@ -121,7 +121,7 @@ GEM
uber (< 0.2.0)
retriable (3.1.2)
rouge (2.0.7)
- rubyzip (1.2.2)
+ rubyzip (1.2.3)
security (0.1.3)
signet (0.11.0)
addressable (~> 2.3)
@@ -136,20 +136,20 @@ GEM
fastlane (>= 2.29.0)
highline (~> 1.7)
nokogiri (~> 1.7)
- terminal-notifier (1.8.0)
+ terminal-notifier (2.0.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
- tty-cursor (0.6.1)
- tty-screen (0.6.5)
- tty-spinner (0.9.0)
- tty-cursor (~> 0.6.0)
+ tty-cursor (0.7.0)
+ tty-screen (0.7.0)
+ tty-spinner (0.9.1)
+ tty-cursor (~> 0.7)
uber (0.1.0)
unf (0.1.4)
unf_ext
- unf_ext (0.0.7.5)
- unicode-display_width (1.4.1)
+ unf_ext (0.0.7.6)
+ unicode-display_width (1.6.0)
word_wrap (1.0.0)
- xcodeproj (1.8.1)
+ xcodeproj (1.12.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index 48c16caf0f..0b60e28b0f 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -1,22 +1,6 @@
update_fastlane
-default_platform(:ios)
-
platform :ios do
- lane :testflight_prune_dry do
- clean_testflight_testers(days_of_inactivity:45, dry_run: true)
- end
-
- # Specify a custom number for what's "inactive"
- lane :testflight_prune do
- clean_testflight_testers(days_of_inactivity: 45) # 120 days, so about 4 months
- end
-
- lane :update_version do |options|
- options[:plist_path] = '../osu.iOS/Info.plist'
- app_version(options)
- end
-
desc 'Deploy to testflight'
lane :beta do |options|
update_version(options)
@@ -62,4 +46,17 @@ platform :ios do
match(options)
end
+
+ lane :update_version do |options|
+ options[:plist_path] = '../osu.iOS/Info.plist'
+ app_version(options)
+ end
+
+ lane :testflight_prune_dry do
+ clean_testflight_testers(days_of_inactivity:45, dry_run: true)
+ end
+
+ lane :testflight_prune do
+ clean_testflight_testers(days_of_inactivity: 45)
+ end
end
diff --git a/fastlane/README.md b/fastlane/README.md
index 53bbc62cae..fbccf1c8c0 100644
--- a/fastlane/README.md
+++ b/fastlane/README.md
@@ -16,21 +16,6 @@ or alternatively using `brew cask install fastlane`
# Available Actions
## iOS
-### ios testflight_prune_dry
-```
-fastlane ios testflight_prune_dry
-```
-
-### ios testflight_prune
-```
-fastlane ios testflight_prune
-```
-
-### ios update_version
-```
-fastlane ios update_version
-```
-
### ios beta
```
fastlane ios beta
@@ -46,6 +31,21 @@ Compile the project
fastlane ios provision
```
Install provisioning profiles using match
+### ios update_version
+```
+fastlane ios update_version
+```
+
+### ios testflight_prune_dry
+```
+fastlane ios testflight_prune_dry
+```
+
+### ios testflight_prune
+```
+fastlane ios testflight_prune
+```
+
----
diff --git a/osu.Android.props b/osu.Android.props
index 7bc60ef884..bb283dc0c5 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -61,6 +61,6 @@
-
+
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs
index d42b61ea55..0c5ead10cf 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs
@@ -17,6 +17,8 @@ namespace osu.Game.Tests.Visual.Gameplay
{
private bool exitAction;
+ protected override double TimePerAction => 100; // required for the early exit test, since hold-to-confirm delay is 200ms
+
[BackgroundDependencyLoader]
private void load()
{
diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs
index 7e6cf1285e..f787754aa4 100644
--- a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs
+++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using osu.Framework.Graphics;
using osu.Game.Graphics;
+using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Screens.Menu;
@@ -12,7 +13,13 @@ namespace osu.Game.Tests.Visual.UserInterface
{
public class TestSceneHoldToConfirmOverlay : OsuTestScene
{
- public override IReadOnlyList RequiredTypes => new[] { typeof(ExitConfirmOverlay) };
+ protected override double TimePerAction => 100; // required for the early exit test, since hold-to-confirm delay is 200ms
+
+ public override IReadOnlyList RequiredTypes => new[]
+ {
+ typeof(ExitConfirmOverlay),
+ typeof(HoldToConfirmContainer),
+ };
public TestSceneHoldToConfirmOverlay()
{
diff --git a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs
index cda5e150de..773265d19b 100644
--- a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs
+++ b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs
@@ -12,9 +12,11 @@ namespace osu.Game.Graphics.Containers
{
public Action Action;
- private const int activate_delay = 400;
+ private const int default_activation_delay = 200;
private const int fadeout_delay = 200;
+ private readonly double activationDelay;
+
private bool fired;
private bool confirming;
@@ -25,13 +27,22 @@ namespace osu.Game.Graphics.Containers
public Bindable Progress = new BindableDouble();
+ ///
+ /// Create a new instance.
+ ///
+ /// The time requried before an action is confirmed.
+ protected HoldToConfirmContainer(double activationDelay = default_activation_delay)
+ {
+ this.activationDelay = activationDelay;
+ }
+
protected void BeginConfirm()
{
if (confirming || (!AllowMultipleFires && fired)) return;
confirming = true;
- this.TransformBindableTo(Progress, 1, activate_delay * (1 - Progress.Value), Easing.Out).OnComplete(_ => Confirm());
+ this.TransformBindableTo(Progress, 1, activationDelay * (1 - Progress.Value), Easing.Out).OnComplete(_ => Confirm());
}
protected virtual void Confirm()
diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs
index 47324ee646..6593531099 100644
--- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs
+++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs
@@ -72,17 +72,11 @@ namespace osu.Game.Graphics.UserInterface
Current.DisabledChanged += disabled => labelText.Alpha = Nub.Alpha = disabled ? 0.3f : 1;
}
- protected override void LoadComplete()
+ [BackgroundDependencyLoader]
+ private void load(AudioManager audio)
{
- base.LoadComplete();
-
- Current.ValueChanged += enabled =>
- {
- if (enabled.NewValue)
- sampleChecked?.Play();
- else
- sampleUnchecked?.Play();
- };
+ sampleChecked = audio.Samples.Get(@"UI/check-on");
+ sampleUnchecked = audio.Samples.Get(@"UI/check-off");
}
protected override bool OnHover(HoverEvent e)
@@ -99,11 +93,13 @@ namespace osu.Game.Graphics.UserInterface
base.OnHoverLost(e);
}
- [BackgroundDependencyLoader]
- private void load(AudioManager audio)
+ protected override void OnUserChange(bool value)
{
- sampleChecked = audio.Samples.Get(@"UI/check-on");
- sampleUnchecked = audio.Samples.Get(@"UI/check-off");
+ base.OnUserChange(value);
+ if (value)
+ sampleChecked?.Play();
+ else
+ sampleUnchecked?.Play();
}
}
}
diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs
index e7f7c2f490..158641d816 100644
--- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs
+++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs
@@ -140,6 +140,9 @@ namespace osu.Game.Overlays.Profile.Header
{
if (string.IsNullOrEmpty(content)) return;
+ // newlines could be contained in API returned user content.
+ content = content.Replace("\n", " ");
+
bottomLinkContainer.AddIcon(icon, text =>
{
text.Font = text.Font.With(size: 10);
diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs
index 9cb9d48de7..de760eedfd 100644
--- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs
+++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs
@@ -196,17 +196,30 @@ namespace osu.Game.Overlays.Profile.Header.Components
}
}
- public string TooltipText => Statistics.Value?.Ranks.Global == null ? "" : $"#{ranks[dayIndex].Value:#,##0}|{ranked_days - ranks[dayIndex].Key + 1}";
+ public object TooltipContent
+ {
+ get
+ {
+ if (Statistics.Value?.Ranks.Global == null)
+ return null;
+
+ var days = ranked_days - ranks[dayIndex].Key + 1;
+
+ return new TooltipDisplayContent
+ {
+ Rank = $"#{ranks[dayIndex].Value:#,##0}",
+ Time = days == 0 ? "now" : $"{days} days ago"
+ };
+ }
+ }
public ITooltip GetCustomTooltip() => new RankGraphTooltip();
- public class RankGraphTooltip : VisibilityContainer, ITooltip
+ private class RankGraphTooltip : VisibilityContainer, ITooltip
{
private readonly OsuSpriteText globalRankingText, timeText;
private readonly Box background;
- public string TooltipText { get; set; }
-
public RankGraphTooltip()
{
AutoSizeAxes = Axes.Both;
@@ -260,11 +273,14 @@ namespace osu.Game.Overlays.Profile.Header.Components
background.Colour = colours.GreySeafoamDark;
}
- public void Refresh()
+ public bool SetContent(object content)
{
- var info = TooltipText.Split('|');
- globalRankingText.Text = info[0];
- timeText.Text = info[1] == "0" ? "now" : $"{info[1]} days ago";
+ if (!(content is TooltipDisplayContent info))
+ return false;
+
+ globalRankingText.Text = info.Rank;
+ timeText.Text = info.Time;
+ return true;
}
private bool instantMove = true;
@@ -280,9 +296,24 @@ namespace osu.Game.Overlays.Profile.Header.Components
this.MoveTo(pos, 200, Easing.OutQuint);
}
+ public void Refresh()
+ {
+ }
+
+ public string TooltipText
+ {
+ set => throw new InvalidOperationException();
+ }
+
protected override void PopIn() => this.FadeIn(200, Easing.OutQuint);
protected override void PopOut() => this.FadeOut(200, Easing.OutQuint);
}
+
+ private class TooltipDisplayContent
+ {
+ public string Rank;
+ public string Time;
+ }
}
}
diff --git a/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs b/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs
index 2200caeb20..e85ebb5f3a 100644
--- a/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs
+++ b/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs
@@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System.Linq;
+using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
@@ -57,7 +58,12 @@ namespace osu.Game.Rulesets.Edit
this.drawableRuleset = drawableRuleset;
InternalChild = drawableRuleset;
+ }
+ [BackgroundDependencyLoader]
+ private void load()
+ {
+ drawableRuleset.FrameStablePlayback = false;
Playfield.DisplayJudgements.Value = false;
}
diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs
index ac81fdc719..eb14bd1f24 100644
--- a/osu.Game/Rulesets/UI/DrawableRuleset.cs
+++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs
@@ -62,6 +62,15 @@ namespace osu.Game.Rulesets.UI
public override GameplayClock FrameStableClock => frameStabilityContainer.GameplayClock;
+ ///
+ /// Whether to enable frame-stable playback.
+ ///
+ internal bool FrameStablePlayback
+ {
+ get => frameStabilityContainer.FrameStablePlayback;
+ set => frameStabilityContainer.FrameStablePlayback = value;
+ }
+
///
/// Invoked when a has been applied by a .
///
diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs
index 1cc56fff8b..05d3c02381 100644
--- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs
+++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs
@@ -24,6 +24,11 @@ namespace osu.Game.Rulesets.UI
///
public int MaxCatchUpFrames { get; set; } = 5;
+ ///
+ /// Whether to enable frame-stable playback.
+ ///
+ internal bool FrameStablePlayback = true;
+
[Cached]
public GameplayClock GameplayClock { get; }
@@ -113,7 +118,13 @@ namespace osu.Game.Rulesets.UI
try
{
- if (firstConsumption)
+ if (!FrameStablePlayback)
+ {
+ manualClock.CurrentTime = newProposedTime;
+ requireMoreUpdateLoops = false;
+ return;
+ }
+ else if (firstConsumption)
{
// On the first update, frame-stability seeking would result in unexpected/unwanted behaviour.
// Instead we perform an initial seek to the proposed time.
diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs
index 7366fa8c17..23c581c6f9 100644
--- a/osu.Game/Screens/Select/BeatmapCarousel.cs
+++ b/osu.Game/Screens/Select/BeatmapCarousel.cs
@@ -24,7 +24,7 @@ using osu.Game.Screens.Select.Carousel;
namespace osu.Game.Screens.Select
{
- public class BeatmapCarousel : OsuScrollContainer
+ public class BeatmapCarousel : CompositeDrawable
{
private const float bleed_top = FilterControl.HEIGHT;
private const float bleed_bottom = Footer.HEIGHT;
@@ -61,6 +61,8 @@ namespace osu.Game.Screens.Select
///
public bool BeatmapSetsLoaded { get; private set; }
+ private readonly OsuScrollContainer scroll;
+
private IEnumerable beatmapSets => root.Children.OfType();
public IEnumerable BeatmapSets
@@ -110,13 +112,17 @@ namespace osu.Game.Screens.Select
public BeatmapCarousel()
{
root = new CarouselRoot(this);
- Child = new OsuContextMenuContainer
+ InternalChild = new OsuContextMenuContainer
{
- RelativeSizeAxes = Axes.X,
- AutoSizeAxes = Axes.Y,
- Child = scrollableContent = new Container
+ RelativeSizeAxes = Axes.Both,
+ Child = scroll = new CarouselScrollContainer
{
- RelativeSizeAxes = Axes.X,
+ Masking = false,
+ RelativeSizeAxes = Axes.Both,
+ Child = scrollableContent = new Container
+ {
+ RelativeSizeAxes = Axes.X,
+ }
}
};
}
@@ -127,7 +133,7 @@ namespace osu.Game.Screens.Select
config.BindWith(OsuSetting.RandomSelectAlgorithm, RandomAlgorithm);
config.BindWith(OsuSetting.SongSelectRightMouseScroll, RightClickScrollingEnabled);
- RightClickScrollingEnabled.ValueChanged += enabled => RightMouseScrollbar = enabled.NewValue;
+ RightClickScrollingEnabled.ValueChanged += enabled => scroll.RightMouseScrollbar = enabled.NewValue;
RightClickScrollingEnabled.TriggerChange();
loadBeatmapSets(beatmaps.GetAllUsableBeatmapSetsEnumerable());
@@ -351,12 +357,12 @@ namespace osu.Game.Screens.Select
///
/// The position of the lower visible bound with respect to the current scroll position.
///
- private float visibleBottomBound => Current + DrawHeight + bleed_bottom;
+ private float visibleBottomBound => scroll.Current + DrawHeight + bleed_bottom;
///
/// The position of the upper visible bound with respect to the current scroll position.
///
- private float visibleUpperBound => Current - bleed_top;
+ private float visibleUpperBound => scroll.Current - bleed_top;
public void FlushPendingFilterOperations()
{
@@ -628,7 +634,7 @@ namespace osu.Game.Screens.Select
private void updateScrollPosition()
{
- if (scrollTarget != null) ScrollTo(scrollTarget.Value);
+ if (scrollTarget != null) scroll.ScrollTo(scrollTarget.Value);
scrollPositionCache.Validate();
}
@@ -688,5 +694,35 @@ namespace osu.Game.Screens.Select
base.PerformSelection();
}
}
+
+ private class CarouselScrollContainer : OsuScrollContainer
+ {
+ private bool rightMouseScrollBlocked;
+
+ protected override bool OnMouseDown(MouseDownEvent e)
+ {
+ if (e.Button == MouseButton.Right)
+ {
+ // we need to block right click absolute scrolling when hovering a carousel item so context menus can display.
+ // this can be reconsidered when we have an alternative to right click scrolling.
+ if (GetContainingInputManager().HoveredDrawables.OfType().Any())
+ {
+ rightMouseScrollBlocked = true;
+ return false;
+ }
+ }
+
+ rightMouseScrollBlocked = false;
+ return base.OnMouseDown(e);
+ }
+
+ protected override bool OnDragStart(DragStartEvent e)
+ {
+ if (rightMouseScrollBlocked)
+ return false;
+
+ return base.OnDragStart(e);
+ }
+ }
}
}
diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs
index 7dd934f91a..8340814db9 100644
--- a/osu.Game/Screens/Select/SongSelect.cs
+++ b/osu.Game/Screens/Select/SongSelect.cs
@@ -157,7 +157,6 @@ namespace osu.Game.Screens.Select
},
Child = Carousel = new BeatmapCarousel
{
- Masking = false,
RelativeSizeAxes = Axes.Both,
Size = new Vector2(1 - wedged_container_size.X, 1),
Anchor = Anchor.CentreRight,
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index f5e4d4b1fb..758c4dda4c 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 63fa354418..d6ad35b663 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -118,8 +118,8 @@
-
-
+
+