diff --git a/osu.Android.props b/osu.Android.props
index caaa83bff4..d5390e6a3d 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -52,7 +52,7 @@
-
+
diff --git a/osu.Android/AndroidJoystickSettings.cs b/osu.Android/AndroidJoystickSettings.cs
new file mode 100644
index 0000000000..26e921a426
--- /dev/null
+++ b/osu.Android/AndroidJoystickSettings.cs
@@ -0,0 +1,76 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Framework.Allocation;
+using osu.Framework.Android.Input;
+using osu.Framework.Bindables;
+using osu.Framework.Graphics;
+using osu.Framework.Localisation;
+using osu.Game.Localisation;
+using osu.Game.Overlays.Settings;
+
+namespace osu.Android
+{
+ public class AndroidJoystickSettings : SettingsSubsection
+ {
+ protected override LocalisableString Header => JoystickSettingsStrings.JoystickGamepad;
+
+ private readonly AndroidJoystickHandler joystickHandler;
+
+ private readonly Bindable enabled = new BindableBool(true);
+
+ private SettingsSlider deadzoneSlider = null!;
+
+ private Bindable handlerDeadzone = null!;
+
+ private Bindable localDeadzone = null!;
+
+ public AndroidJoystickSettings(AndroidJoystickHandler joystickHandler)
+ {
+ this.joystickHandler = joystickHandler;
+ }
+
+ [BackgroundDependencyLoader]
+ private void load()
+ {
+ // use local bindable to avoid changing enabled state of game host's bindable.
+ handlerDeadzone = joystickHandler.DeadzoneThreshold.GetBoundCopy();
+ localDeadzone = handlerDeadzone.GetUnboundCopy();
+
+ Children = new Drawable[]
+ {
+ new SettingsCheckbox
+ {
+ LabelText = CommonStrings.Enabled,
+ Current = enabled
+ },
+ deadzoneSlider = new SettingsSlider
+ {
+ LabelText = JoystickSettingsStrings.DeadzoneThreshold,
+ KeyboardStep = 0.01f,
+ DisplayAsPercentage = true,
+ Current = localDeadzone,
+ },
+ };
+ }
+
+ protected override void LoadComplete()
+ {
+ base.LoadComplete();
+
+ enabled.BindTo(joystickHandler.Enabled);
+ enabled.BindValueChanged(e => deadzoneSlider.Current.Disabled = !e.NewValue, true);
+
+ handlerDeadzone.BindValueChanged(val =>
+ {
+ bool disabled = localDeadzone.Disabled;
+
+ localDeadzone.Disabled = false;
+ localDeadzone.Value = val.NewValue;
+ localDeadzone.Disabled = disabled;
+ }, true);
+
+ localDeadzone.BindValueChanged(val => handlerDeadzone.Value = val.NewValue);
+ }
+ }
+}
diff --git a/osu.Android/OsuGameAndroid.cs b/osu.Android/OsuGameAndroid.cs
index 636fc7d2df..062f2ce10c 100644
--- a/osu.Android/OsuGameAndroid.cs
+++ b/osu.Android/OsuGameAndroid.cs
@@ -96,6 +96,9 @@ namespace osu.Android
case AndroidMouseHandler mh:
return new AndroidMouseSettings(mh);
+ case AndroidJoystickHandler jh:
+ return new AndroidJoystickSettings(jh);
+
default:
return base.CreateSettingsSubsectionFor(handler);
}
diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj
index 90b02c527b..004cc8c39c 100644
--- a/osu.Android/osu.Android.csproj
+++ b/osu.Android/osu.Android.csproj
@@ -26,6 +26,7 @@
true
+
diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyFollowCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyFollowCircle.cs
index 324f2525bc..5b7da5a1ba 100644
--- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyFollowCircle.cs
+++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyFollowCircle.cs
@@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
if (ParentObject.Judged)
return;
- double remainingTime = ParentObject.HitStateUpdateTime - Time.Current;
+ double remainingTime = Math.Max(0, ParentObject.HitStateUpdateTime - Time.Current);
// Note that the scale adjust here is 2 instead of DrawableSliderBall.FOLLOW_AREA to match legacy behaviour.
// This means the actual tracking area for gameplay purposes is larger than the sprite (but skins may be accounting for this).
diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs
index be03328caa..6ef87f762c 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs
@@ -274,14 +274,18 @@ namespace osu.Game.Tests.Visual.Online
}
};
+ const int initial_great_count = 2000;
+
+ int greatCount = initial_great_count;
+
foreach (var s in scores.Scores)
{
s.Statistics = new Dictionary
{
- { HitResult.Great, RNG.Next(2000) },
- { HitResult.Ok, RNG.Next(2000) },
- { HitResult.Meh, RNG.Next(2000) },
- { HitResult.Miss, RNG.Next(2000) }
+ { HitResult.Great, greatCount -= 100 },
+ { HitResult.Ok, RNG.Next(100) },
+ { HitResult.Meh, RNG.Next(100) },
+ { HitResult.Miss, initial_great_count - greatCount }
};
}
diff --git a/osu.Game/Database/EFToRealmMigrator.cs b/osu.Game/Database/EFToRealmMigrator.cs
index 3b5424b3fb..294a8cd3ed 100644
--- a/osu.Game/Database/EFToRealmMigrator.cs
+++ b/osu.Game/Database/EFToRealmMigrator.cs
@@ -443,7 +443,6 @@ namespace osu.Game.Database
TotalScore = score.TotalScore,
MaxCombo = score.MaxCombo,
Accuracy = score.Accuracy,
- HasReplay = ((IScoreInfo)score).HasReplay,
Date = score.Date,
PP = score.PP,
Rank = score.Rank,
diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs
index 02b5a51f1f..bebc101b13 100644
--- a/osu.Game/Database/RealmAccess.cs
+++ b/osu.Game/Database/RealmAccess.cs
@@ -59,8 +59,9 @@ namespace osu.Game.Database
/// 13 2022-01-13 Final migration of beatmaps and scores to realm (multiple new storage fields).
/// 14 2022-03-01 Added BeatmapUserSettings to BeatmapInfo.
/// 15 2022-07-13 Added LastPlayed to BeatmapInfo.
+ /// 16 2022-07-15 Removed HasReplay from ScoreInfo.
///
- private const int schema_version = 15;
+ private const int schema_version = 16;
///
/// Lock object which is held during sections, blocking realm retrieval during blocking periods.
diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs
index a6cd9a52c7..966e69938c 100644
--- a/osu.Game/Online/API/Requests/GetScoresRequest.cs
+++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs
@@ -35,7 +35,7 @@ namespace osu.Game.Online.API.Requests
this.mods = mods ?? Array.Empty();
}
- protected override string Target => $@"beatmaps/{beatmapInfo.OnlineID}/scores{createQueryParameters()}";
+ protected override string Target => $@"beatmaps/{beatmapInfo.OnlineID}/solo-scores{createQueryParameters()}";
private string createQueryParameters()
{
diff --git a/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs
index b70da194a5..6c48c7883f 100644
--- a/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs
+++ b/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs
@@ -103,9 +103,6 @@ namespace osu.Game.Online.API.Requests.Responses
var mods = Mods.Select(apiMod => rulesetInstance.CreateModFromAcronym(apiMod.Acronym)).Where(m => m != null).ToArray();
- // all API scores provided by this class are considered to be legacy.
- mods = mods.Append(rulesetInstance.CreateMod()).ToArray();
-
var scoreInfo = ToScoreInfo(mods);
scoreInfo.Ruleset = ruleset;
@@ -132,8 +129,7 @@ namespace osu.Game.Online.API.Requests.Responses
Rank = Rank,
Statistics = Statistics,
Date = EndedAt ?? DateTimeOffset.Now,
- Hash = "online", // TODO: temporary?
- HasReplay = HasReplay,
+ Hash = HasReplay ? "online" : string.Empty, // TODO: temporary?
Mods = mods,
PP = PP,
};
diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs
index 767b8646e3..2ca369d459 100644
--- a/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs
+++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs
@@ -143,7 +143,7 @@ namespace osu.Game.Overlays.BeatmapListing
}
public void Search(string query)
- => searchControl.Query.Value = query;
+ => Schedule(() => searchControl.Query.Value = query);
protected override void LoadComplete()
{
diff --git a/osu.Game/Overlays/BeatmapSet/MetadataSection.cs b/osu.Game/Overlays/BeatmapSet/MetadataSection.cs
index c6bf94f507..317b369d8f 100644
--- a/osu.Game/Overlays/BeatmapSet/MetadataSection.cs
+++ b/osu.Game/Overlays/BeatmapSet/MetadataSection.cs
@@ -3,6 +3,7 @@
#nullable disable
+using System;
using osu.Framework.Extensions;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
@@ -22,11 +23,14 @@ namespace osu.Game.Overlays.BeatmapSet
private readonly MetadataType type;
private TextFlowContainer textFlow;
+ private readonly Action searchAction;
+
private const float transition_duration = 250;
- public MetadataSection(MetadataType type)
+ public MetadataSection(MetadataType type, Action searchAction = null)
{
this.type = type;
+ this.searchAction = searchAction;
Alpha = 0;
@@ -91,7 +95,12 @@ namespace osu.Game.Overlays.BeatmapSet
for (int i = 0; i <= tags.Length - 1; i++)
{
- loaded.AddLink(tags[i], LinkAction.SearchBeatmapSet, tags[i]);
+ string tag = tags[i];
+
+ if (searchAction != null)
+ loaded.AddLink(tag, () => searchAction(tag));
+ else
+ loaded.AddLink(tag, LinkAction.SearchBeatmapSet, tag);
if (i != tags.Length - 1)
loaded.AddText(" ");
@@ -100,7 +109,11 @@ namespace osu.Game.Overlays.BeatmapSet
break;
case MetadataType.Source:
- loaded.AddLink(text, LinkAction.SearchBeatmapSet, text);
+ if (searchAction != null)
+ loaded.AddLink(text, () => searchAction(text));
+ else
+ loaded.AddLink(text, LinkAction.SearchBeatmapSet, text);
+
break;
default:
diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs
index cbe9615380..81ca5f0300 100644
--- a/osu.Game/Scoring/ScoreInfo.cs
+++ b/osu.Game/Scoring/ScoreInfo.cs
@@ -45,7 +45,7 @@ namespace osu.Game.Scoring
public double Accuracy { get; set; }
- public bool HasReplay { get; set; }
+ public bool HasReplay => !string.IsNullOrEmpty(Hash);
public DateTimeOffset Date { get; set; }
diff --git a/osu.Game/Scoring/ScoreRank.cs b/osu.Game/Scoring/ScoreRank.cs
index a4bb99add1..a1916953c4 100644
--- a/osu.Game/Scoring/ScoreRank.cs
+++ b/osu.Game/Scoring/ScoreRank.cs
@@ -11,6 +11,7 @@ namespace osu.Game.Scoring
{
public enum ScoreRank
{
+ // TODO: Localisable?
[Description(@"F")]
F = -1,
diff --git a/osu.Game/Screens/Ranking/ReplayDownloadButton.cs b/osu.Game/Screens/Ranking/ReplayDownloadButton.cs
index 954a5159b9..7081a0156e 100644
--- a/osu.Game/Screens/Ranking/ReplayDownloadButton.cs
+++ b/osu.Game/Screens/Ranking/ReplayDownloadButton.cs
@@ -33,7 +33,7 @@ namespace osu.Game.Screens.Ranking
if (State.Value == DownloadState.LocallyAvailable)
return ReplayAvailability.Local;
- if (!string.IsNullOrEmpty(Score.Value?.Hash))
+ if (Score.Value?.HasReplay == true)
return ReplayAvailability.Online;
return ReplayAvailability.NotAvailable;
diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs
index 2fe62c4a4e..90418efe15 100644
--- a/osu.Game/Screens/Select/BeatmapDetails.cs
+++ b/osu.Game/Screens/Select/BeatmapDetails.cs
@@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-#nullable disable
-
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
@@ -38,15 +36,18 @@ namespace osu.Game.Screens.Select
private readonly LoadingLayer loading;
[Resolved]
- private IAPIProvider api { get; set; }
+ private IAPIProvider api { get; set; } = null!;
- private IBeatmapInfo beatmapInfo;
+ [Resolved]
+ private SongSelect? songSelect { get; set; }
- private APIFailTimes failTimes;
+ private IBeatmapInfo? beatmapInfo;
- private int[] ratings;
+ private APIFailTimes? failTimes;
- public IBeatmapInfo BeatmapInfo
+ private int[]? ratings;
+
+ public IBeatmapInfo? BeatmapInfo
{
get => beatmapInfo;
set
@@ -56,7 +57,7 @@ namespace osu.Game.Screens.Select
beatmapInfo = value;
var onlineInfo = beatmapInfo as IBeatmapOnlineInfo;
- var onlineSetInfo = beatmapInfo.BeatmapSet as IBeatmapSetOnlineInfo;
+ var onlineSetInfo = beatmapInfo?.BeatmapSet as IBeatmapSetOnlineInfo;
failTimes = onlineInfo?.FailTimes;
ratings = onlineSetInfo?.Ratings;
@@ -140,9 +141,9 @@ namespace osu.Game.Screens.Select
LayoutEasing = Easing.OutQuad,
Children = new[]
{
- description = new MetadataSection(MetadataType.Description),
- source = new MetadataSection(MetadataType.Source),
- tags = new MetadataSection(MetadataType.Tags),
+ description = new MetadataSection(MetadataType.Description, searchOnSongSelect),
+ source = new MetadataSection(MetadataType.Source, searchOnSongSelect),
+ tags = new MetadataSection(MetadataType.Tags, searchOnSongSelect),
},
},
},
@@ -175,6 +176,12 @@ namespace osu.Game.Screens.Select
},
loading = new LoadingLayer(true)
};
+
+ void searchOnSongSelect(string text)
+ {
+ if (songSelect != null)
+ songSelect.FilterControl.CurrentTextSearch.Value = text;
+ }
}
private void updateStatistics()
diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs
index a92b631100..e43261f374 100644
--- a/osu.Game/Screens/Select/FilterControl.cs
+++ b/osu.Game/Screens/Select/FilterControl.cs
@@ -31,6 +31,8 @@ namespace osu.Game.Screens.Select
public Action FilterChanged;
+ public Bindable CurrentTextSearch => searchTextBox.Current;
+
private OsuTabControl sortTabs;
private Bindable sortMode;
@@ -63,6 +65,7 @@ namespace osu.Game.Screens.Select
}
private SeekLimitedSearchTextBox searchTextBox;
+
private CollectionFilterDropdown collectionDropdown;
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) =>
diff --git a/osu.Game/Screens/Select/NoResultsPlaceholder.cs b/osu.Game/Screens/Select/NoResultsPlaceholder.cs
index b8b589ff99..f3c3fb4d87 100644
--- a/osu.Game/Screens/Select/NoResultsPlaceholder.cs
+++ b/osu.Game/Screens/Select/NoResultsPlaceholder.cs
@@ -109,7 +109,7 @@ namespace osu.Game.Screens.Select
textFlow.AddParagraph("No beatmaps found!");
textFlow.AddParagraph(string.Empty);
- textFlow.AddParagraph("Consider using the \"");
+ textFlow.AddParagraph("- Consider running the \"");
textFlow.AddLink(FirstRunSetupOverlayStrings.FirstRunSetupTitle, () => firstRunSetupOverlay?.Show());
textFlow.AddText("\" to download or import some beatmaps!");
}
@@ -141,15 +141,14 @@ namespace osu.Game.Screens.Select
textFlow.AddLink(" enabling ", () => config.SetValue(OsuSetting.ShowConvertedBeatmaps, true));
textFlow.AddText("automatic conversion!");
}
-
- if (!string.IsNullOrEmpty(filter?.SearchText))
- {
- textFlow.AddParagraph("- Try ");
- textFlow.AddLink("searching online", LinkAction.SearchBeatmapSet, filter.SearchText);
- textFlow.AddText($" for \"{filter.SearchText}\".");
- }
}
+ if (!string.IsNullOrEmpty(filter?.SearchText))
+ {
+ textFlow.AddParagraph("- Try ");
+ textFlow.AddLink("searching online", LinkAction.SearchBeatmapSet, filter.SearchText);
+ textFlow.AddText($" for \"{filter.SearchText}\".");
+ }
// TODO: add clickable link to reset criteria.
}
}
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 355fd5f458..61fcf2e375 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -36,7 +36,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index fcf71f3ab0..8843b5c831 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -61,7 +61,7 @@
-
+
@@ -84,7 +84,7 @@
-
+