mirror of
https://github.com/ppy/osu.git
synced 2025-03-17 22:17:25 +08:00
Merge branch 'master' of https://github.com/ppy/osu into no-long-notes-mod
This commit is contained in:
commit
b13f3df327
@ -794,5 +794,32 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
Assert.That(path.Distance, Is.EqualTo(1));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLegacyDefaultsPreserved()
|
||||
{
|
||||
var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false };
|
||||
|
||||
using (var memoryStream = new MemoryStream())
|
||||
using (var stream = new LineBufferedReader(memoryStream))
|
||||
{
|
||||
var decoded = decoder.Decode(stream);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(decoded.BeatmapInfo.AudioLeadIn, Is.EqualTo(0));
|
||||
Assert.That(decoded.BeatmapInfo.StackLeniency, Is.EqualTo(0.7f));
|
||||
Assert.That(decoded.BeatmapInfo.SpecialStyle, Is.False);
|
||||
Assert.That(decoded.BeatmapInfo.LetterboxInBreaks, Is.False);
|
||||
Assert.That(decoded.BeatmapInfo.WidescreenStoryboard, Is.False);
|
||||
Assert.That(decoded.BeatmapInfo.EpilepsyWarning, Is.False);
|
||||
Assert.That(decoded.BeatmapInfo.SamplesMatchPlaybackRate, Is.False);
|
||||
Assert.That(decoded.BeatmapInfo.Countdown, Is.EqualTo(CountdownType.Normal));
|
||||
Assert.That(decoded.BeatmapInfo.CountdownOffset, Is.EqualTo(0));
|
||||
Assert.That(decoded.BeatmapInfo.Metadata.PreviewTime, Is.EqualTo(-1));
|
||||
Assert.That(decoded.BeatmapInfo.Ruleset.OnlineID, Is.EqualTo(0));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
@ -19,28 +19,35 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
protected override double TimePerAction => 100; // required for the early exit test, since hold-to-confirm delay is 200ms
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
private HoldForMenuButton holdForMenuButton;
|
||||
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
{
|
||||
HoldForMenuButton holdForMenuButton;
|
||||
|
||||
Add(holdForMenuButton = new HoldForMenuButton
|
||||
AddStep("create button", () =>
|
||||
{
|
||||
Origin = Anchor.BottomRight,
|
||||
Anchor = Anchor.BottomRight,
|
||||
Action = () => exitAction = true
|
||||
exitAction = false;
|
||||
|
||||
Child = holdForMenuButton = new HoldForMenuButton
|
||||
{
|
||||
Scale = new Vector2(2),
|
||||
Origin = Anchor.CentreRight,
|
||||
Anchor = Anchor.CentreRight,
|
||||
Action = () => exitAction = true
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
var text = holdForMenuButton.Children.OfType<SpriteText>().First();
|
||||
|
||||
[Test]
|
||||
public void TestMovementAndTrigger()
|
||||
{
|
||||
AddStep("Trigger text fade in", () => InputManager.MoveMouseTo(holdForMenuButton));
|
||||
AddUntilStep("Text visible", () => text.IsPresent && !exitAction);
|
||||
AddUntilStep("Text visible", () => getSpriteText().IsPresent && !exitAction);
|
||||
AddStep("Trigger text fade out", () => InputManager.MoveMouseTo(Vector2.One));
|
||||
AddUntilStep("Text is not visible", () => !text.IsPresent && !exitAction);
|
||||
AddUntilStep("Text is not visible", () => !getSpriteText().IsPresent && !exitAction);
|
||||
|
||||
AddStep("Trigger exit action", () =>
|
||||
{
|
||||
exitAction = false;
|
||||
InputManager.MoveMouseTo(holdForMenuButton);
|
||||
InputManager.PressButton(MouseButton.Left);
|
||||
});
|
||||
@ -50,6 +57,17 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
AddStep("Trigger exit action", () => InputManager.PressButton(MouseButton.Left));
|
||||
AddUntilStep($"{nameof(holdForMenuButton.Action)} was triggered", () => exitAction);
|
||||
AddStep("Release", () => InputManager.ReleaseButton(MouseButton.Left));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFadeOnNoInput()
|
||||
{
|
||||
AddStep("move mouse away", () => InputManager.MoveMouseTo(Vector2.One));
|
||||
AddUntilStep("wait for text fade out", () => !getSpriteText().IsPresent);
|
||||
AddUntilStep("wait for button fade out", () => holdForMenuButton.Alpha < 0.1f);
|
||||
}
|
||||
|
||||
private SpriteText getSpriteText() => holdForMenuButton.Children.OfType<SpriteText>().First();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
@ -10,16 +11,19 @@ using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Overlays.Toolbar;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.OnlinePlay.Lounge;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Screens.Select.Options;
|
||||
using osu.Game.Tests.Beatmaps.IO;
|
||||
using osuTK;
|
||||
@ -96,35 +100,81 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
[Test]
|
||||
public void TestRetryFromResults()
|
||||
{
|
||||
Player player = null;
|
||||
ResultsScreen results = null;
|
||||
var getOriginalPlayer = playToResults();
|
||||
|
||||
IWorkingBeatmap beatmap() => Game.Beatmap.Value;
|
||||
AddStep("attempt to retry", () => ((ResultsScreen)Game.ScreenStack.CurrentScreen).ChildrenOfType<HotkeyRetryOverlay>().First().Action());
|
||||
AddUntilStep("wait for player", () => Game.ScreenStack.CurrentScreen != getOriginalPlayer() && Game.ScreenStack.CurrentScreen is Player);
|
||||
}
|
||||
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
[Test]
|
||||
public void TestDeleteAllScoresAfterPlaying()
|
||||
{
|
||||
playToResults();
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
ScoreInfo score = null;
|
||||
LeaderboardScore scorePanel = null;
|
||||
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
AddStep("get score", () => score = ((ResultsScreen)Game.ScreenStack.CurrentScreen).Score);
|
||||
|
||||
AddStep("set mods", () => Game.SelectedMods.Value = new Mod[] { new OsuModNoFail(), new OsuModDoubleTime { SpeedChange = { Value = 2 } } });
|
||||
AddAssert("ensure score is databased", () => Game.Realm.Run(r => r.Find<ScoreInfo>(score.ID)?.DeletePending == false));
|
||||
|
||||
AddStep("press enter", () => InputManager.Key(Key.Enter));
|
||||
AddStep("press back button", () => Game.ChildrenOfType<BackButton>().First().Action());
|
||||
|
||||
AddUntilStep("wait for player", () =>
|
||||
AddStep("show local scores", () => Game.ChildrenOfType<BeatmapDetailAreaTabControl>().First().Current.Value = new BeatmapDetailAreaLeaderboardTabItem<BeatmapLeaderboardScope>(BeatmapLeaderboardScope.Local));
|
||||
|
||||
AddUntilStep("wait for score displayed", () => (scorePanel = Game.ChildrenOfType<LeaderboardScore>().FirstOrDefault(s => s.Score.Equals(score))) != null);
|
||||
|
||||
AddStep("open options", () => InputManager.Key(Key.F3));
|
||||
|
||||
AddStep("choose clear all scores", () => InputManager.Key(Key.Number4));
|
||||
|
||||
AddStep("confirm deletion", () => InputManager.Key(Key.Number1));
|
||||
|
||||
AddAssert("ensure score is pending deletion", () => Game.Realm.Run(r => r.Find<ScoreInfo>(score.ID)?.DeletePending == true));
|
||||
|
||||
AddUntilStep("wait for score panel removal", () => scorePanel.Parent == null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDeleteScoreAfterPlaying()
|
||||
{
|
||||
playToResults();
|
||||
|
||||
ScoreInfo score = null;
|
||||
LeaderboardScore scorePanel = null;
|
||||
|
||||
AddStep("get score", () => score = ((ResultsScreen)Game.ScreenStack.CurrentScreen).Score);
|
||||
|
||||
AddAssert("ensure score is databased", () => Game.Realm.Run(r => r.Find<ScoreInfo>(score.ID)?.DeletePending == false));
|
||||
|
||||
AddStep("press back button", () => Game.ChildrenOfType<BackButton>().First().Action());
|
||||
|
||||
AddStep("show local scores", () => Game.ChildrenOfType<BeatmapDetailAreaTabControl>().First().Current.Value = new BeatmapDetailAreaLeaderboardTabItem<BeatmapLeaderboardScope>(BeatmapLeaderboardScope.Local));
|
||||
|
||||
AddUntilStep("wait for score displayed", () => (scorePanel = Game.ChildrenOfType<LeaderboardScore>().FirstOrDefault(s => s.Score.Equals(score))) != null);
|
||||
|
||||
AddStep("right click panel", () =>
|
||||
{
|
||||
// dismiss any notifications that may appear (ie. muted notification).
|
||||
clickMouseInCentre();
|
||||
return (player = Game.ScreenStack.CurrentScreen as Player) != null;
|
||||
InputManager.MoveMouseTo(scorePanel);
|
||||
InputManager.Click(MouseButton.Right);
|
||||
});
|
||||
|
||||
AddUntilStep("wait for track playing", () => beatmap().Track.IsRunning);
|
||||
AddStep("seek to near end", () => player.ChildrenOfType<GameplayClockContainer>().First().Seek(beatmap().Beatmap.HitObjects[^1].StartTime - 1000));
|
||||
AddUntilStep("wait for pass", () => (results = Game.ScreenStack.CurrentScreen as ResultsScreen) != null && results.IsLoaded);
|
||||
AddStep("attempt to retry", () => results.ChildrenOfType<HotkeyRetryOverlay>().First().Action());
|
||||
AddUntilStep("wait for player", () => Game.ScreenStack.CurrentScreen != player && Game.ScreenStack.CurrentScreen is Player);
|
||||
AddStep("click delete", () =>
|
||||
{
|
||||
var dropdownItem = Game
|
||||
.ChildrenOfType<PlayBeatmapDetailArea>().First()
|
||||
.ChildrenOfType<OsuContextMenu>().First()
|
||||
.ChildrenOfType<DrawableOsuMenuItem>().First(i => i.Item.Text.ToString() == "Delete");
|
||||
|
||||
InputManager.MoveMouseTo(dropdownItem);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddStep("confirm deletion", () => InputManager.Key(Key.Number1));
|
||||
|
||||
AddAssert("ensure score is pending deletion", () => Game.Realm.Run(r => r.Find<ScoreInfo>(score.ID)?.DeletePending == true));
|
||||
|
||||
AddUntilStep("wait for score panel removal", () => scorePanel.Parent == null);
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
@ -432,6 +482,37 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddStep("test dispose doesn't crash", () => Game.Dispose());
|
||||
}
|
||||
|
||||
private Func<Player> playToResults()
|
||||
{
|
||||
Player player = null;
|
||||
|
||||
IWorkingBeatmap beatmap() => Game.Beatmap.Value;
|
||||
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
AddStep("set mods", () => Game.SelectedMods.Value = new Mod[] { new OsuModNoFail(), new OsuModDoubleTime { SpeedChange = { Value = 2 } } });
|
||||
|
||||
AddStep("press enter", () => InputManager.Key(Key.Enter));
|
||||
|
||||
AddUntilStep("wait for player", () =>
|
||||
{
|
||||
// dismiss any notifications that may appear (ie. muted notification).
|
||||
clickMouseInCentre();
|
||||
return (player = Game.ScreenStack.CurrentScreen as Player) != null;
|
||||
});
|
||||
|
||||
AddUntilStep("wait for track playing", () => beatmap().Track.IsRunning);
|
||||
AddStep("seek to near end", () => player.ChildrenOfType<GameplayClockContainer>().First().Seek(beatmap().Beatmap.HitObjects[^1].StartTime - 1000));
|
||||
AddUntilStep("wait for pass", () => (Game.ScreenStack.CurrentScreen as ResultsScreen)?.IsLoaded == true);
|
||||
return () => player;
|
||||
}
|
||||
|
||||
private void clickMouseInCentre()
|
||||
{
|
||||
InputManager.MoveMouseTo(Game.ScreenSpaceDrawQuad.Centre);
|
||||
|
@ -9,6 +9,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets;
|
||||
@ -40,6 +41,36 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
this.rulesets = rulesets;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestScrollPositionMaintainedOnAdd()
|
||||
{
|
||||
loadBeatmaps(count: 1, randomDifficulties: false);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
AddRepeatStep("Add some sets", () => carousel.UpdateBeatmapSet(TestResources.CreateTestBeatmapSetInfo()), 4);
|
||||
|
||||
checkSelectionIsCentered();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestScrollPositionMaintainedOnDelete()
|
||||
{
|
||||
loadBeatmaps(count: 50, randomDifficulties: false);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
AddRepeatStep("Remove some sets", () =>
|
||||
carousel.RemoveBeatmapSet(carousel.Items.Select(item => item.Item)
|
||||
.OfType<CarouselBeatmapSet>()
|
||||
.OrderBy(item => item.GetHashCode())
|
||||
.First(item => item.State.Value != CarouselItemState.Selected && item.Visible).BeatmapSet), 4);
|
||||
|
||||
checkSelectionIsCentered();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestManyPanels()
|
||||
{
|
||||
@ -813,6 +844,18 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
carousel.Items.Count(s => (diff ? s.Item is CarouselBeatmap : s.Item is CarouselBeatmapSet) && s.Item.Visible) == count);
|
||||
}
|
||||
|
||||
private void checkSelectionIsCentered()
|
||||
{
|
||||
AddAssert("Selected panel is centered", () =>
|
||||
{
|
||||
return Precision.AlmostEquals(
|
||||
carousel.ScreenSpaceDrawQuad.Centre,
|
||||
carousel.Items
|
||||
.First(i => i.Item.State.Value == CarouselItemState.Selected)
|
||||
.ScreenSpaceDrawQuad.Centre, 100);
|
||||
});
|
||||
}
|
||||
|
||||
private void checkNoSelection() => AddAssert("Selection is null", () => currentSelection == null);
|
||||
|
||||
private void nextRandom() =>
|
||||
|
@ -61,18 +61,15 @@ namespace osu.Game.Tournament
|
||||
|
||||
loadingSpinner.Show();
|
||||
|
||||
BracketLoadTask.ContinueWith(t =>
|
||||
BracketLoadTask.ContinueWith(t => Schedule(() =>
|
||||
{
|
||||
if (t.IsFaulted)
|
||||
{
|
||||
Schedule(() =>
|
||||
{
|
||||
loadingSpinner.Hide();
|
||||
loadingSpinner.Expire();
|
||||
loadingSpinner.Hide();
|
||||
loadingSpinner.Expire();
|
||||
|
||||
Logger.Error(t.Exception, "Couldn't load bracket with error");
|
||||
Add(new WarningBox($"Your {BRACKET_FILENAME} file could not be parsed. Please check runtime.log for more details."));
|
||||
});
|
||||
Logger.Error(t.Exception, "Couldn't load bracket with error");
|
||||
Add(new WarningBox($"Your {BRACKET_FILENAME} file could not be parsed. Please check runtime.log for more details."));
|
||||
|
||||
return;
|
||||
}
|
||||
@ -143,7 +140,7 @@ namespace osu.Game.Tournament
|
||||
windowMode.Value = WindowMode.Windowed;
|
||||
}), true);
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,11 +99,11 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
public bool LetterboxInBreaks { get; set; }
|
||||
|
||||
public bool WidescreenStoryboard { get; set; }
|
||||
public bool WidescreenStoryboard { get; set; } = true;
|
||||
|
||||
public bool EpilepsyWarning { get; set; }
|
||||
|
||||
public bool SamplesMatchPlaybackRate { get; set; }
|
||||
public bool SamplesMatchPlaybackRate { get; set; } = true;
|
||||
|
||||
public double DistanceSpacing { get; set; }
|
||||
|
||||
|
@ -90,14 +90,7 @@ namespace osu.Game.Beatmaps
|
||||
{
|
||||
Beatmaps =
|
||||
{
|
||||
new BeatmapInfo
|
||||
{
|
||||
Difficulty = new BeatmapDifficulty(),
|
||||
Ruleset = ruleset,
|
||||
Metadata = metadata,
|
||||
WidescreenStoryboard = true,
|
||||
SamplesMatchPlaybackRate = true,
|
||||
}
|
||||
new BeatmapInfo(ruleset, new BeatmapDifficulty(), metadata)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -39,7 +39,7 @@ namespace osu.Game.Beatmaps
|
||||
/// The time in milliseconds to begin playing the track for preview purposes.
|
||||
/// If -1, the track should begin playing at 40% of its length.
|
||||
/// </summary>
|
||||
public int PreviewTime { get; set; }
|
||||
public int PreviewTime { get; set; } = -1;
|
||||
|
||||
public string AudioFile { get; set; } = string.Empty;
|
||||
public string BackgroundFile { get; set; } = string.Empty;
|
||||
|
@ -56,6 +56,8 @@ namespace osu.Game.Beatmaps.Formats
|
||||
this.beatmap = beatmap;
|
||||
this.beatmap.BeatmapInfo.BeatmapVersion = FormatVersion;
|
||||
|
||||
applyLegacyDefaults(this.beatmap.BeatmapInfo);
|
||||
|
||||
base.ParseStreamInto(stream, beatmap);
|
||||
|
||||
flushPendingPoints();
|
||||
@ -70,6 +72,19 @@ namespace osu.Game.Beatmaps.Formats
|
||||
hitObject.ApplyDefaults(this.beatmap.ControlPointInfo, this.beatmap.Difficulty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Some `BeatmapInfo` members have default values that differ from the default values used by stable.
|
||||
/// In addition, legacy beatmaps will sometimes not contain some configuration keys, in which case
|
||||
/// the legacy default values should be used.
|
||||
/// This method's intention is to restore those legacy defaults.
|
||||
/// See also: https://osu.ppy.sh/wiki/en/Client/File_formats/Osu_%28file_format%29
|
||||
/// </summary>
|
||||
private void applyLegacyDefaults(BeatmapInfo beatmapInfo)
|
||||
{
|
||||
beatmapInfo.WidescreenStoryboard = false;
|
||||
beatmapInfo.SamplesMatchPlaybackRate = false;
|
||||
}
|
||||
|
||||
protected override bool ShouldSkipLine(string line) => base.ShouldSkipLine(line) || line.StartsWith(' ') || line.StartsWith('_');
|
||||
|
||||
protected override void ParseLine(Beatmap beatmap, Section section, string line)
|
||||
|
@ -374,12 +374,12 @@ namespace osu.Game.Database
|
||||
log($"Migrated {written}/{count} scores...");
|
||||
}
|
||||
|
||||
var beatmap = r.All<BeatmapInfo>().First(b => b.Hash == score.BeatmapInfo.Hash);
|
||||
var beatmap = r.All<BeatmapInfo>().FirstOrDefault(b => b.Hash == score.BeatmapInfo.Hash);
|
||||
var ruleset = r.Find<RulesetInfo>(score.Ruleset.ShortName);
|
||||
|
||||
if (ruleset == null)
|
||||
if (beatmap == null || ruleset == null)
|
||||
{
|
||||
log($"Skipping {++missing} scores with missing ruleset");
|
||||
log($"Skipping {++missing} scores with missing ruleset or beatmap");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,10 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Development;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Threading;
|
||||
|
||||
@ -66,6 +68,8 @@ namespace osu.Game.Online
|
||||
|
||||
private void doPoll()
|
||||
{
|
||||
Debug.Assert(ThreadSafety.IsUpdateThread);
|
||||
|
||||
scheduledPoll = null;
|
||||
pollingActive = true;
|
||||
Poll().ContinueWith(_ => pollComplete());
|
||||
@ -96,13 +100,13 @@ namespace osu.Game.Online
|
||||
|
||||
if (!lastTimePolled.HasValue)
|
||||
{
|
||||
doPoll();
|
||||
Scheduler.AddOnce(doPoll);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Time.Current - lastTimePolled.Value > TimeBetweenPolls.Value)
|
||||
{
|
||||
doPoll();
|
||||
Scheduler.AddOnce(doPoll);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -107,6 +107,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
{
|
||||
set
|
||||
{
|
||||
if (score == null && value == null)
|
||||
return;
|
||||
|
||||
if (score?.Equals(value) == true)
|
||||
return;
|
||||
|
||||
|
@ -266,6 +266,15 @@ namespace osu.Game.Scoring
|
||||
});
|
||||
}
|
||||
|
||||
public void Delete(BeatmapInfo beatmap, bool silent = false)
|
||||
{
|
||||
realm.Run(r =>
|
||||
{
|
||||
var beatmapScores = r.Find<BeatmapInfo>(beatmap.ID).Scores.ToList();
|
||||
scoreModelManager.Delete(beatmapScores, silent);
|
||||
});
|
||||
}
|
||||
|
||||
public void Delete(List<ScoreInfo> items, bool silent = false)
|
||||
{
|
||||
scoreModelManager.Delete(items, silent);
|
||||
|
@ -82,6 +82,11 @@ namespace osu.Game.Screens.Edit.Compose
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
// May be null in the case of a ruleset that doesn't have editor support, see CreateMainContent().
|
||||
if (composer == null)
|
||||
return;
|
||||
|
||||
EditorBeatmap.SelectedHitObjects.BindCollectionChanged((_, __) => updateClipboardActionAvailability());
|
||||
clipboard.BindValueChanged(_ => updateClipboardActionAvailability());
|
||||
composer.OnLoadComplete += _ => updateClipboardActionAvailability();
|
||||
|
@ -28,6 +28,8 @@ using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Screens.Edit.Components;
|
||||
using osu.Game.Screens.Edit.Components.Menus;
|
||||
@ -61,7 +63,16 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
public override bool? AllowTrackAdjustments => false;
|
||||
|
||||
protected bool HasUnsavedChanges => lastSavedHash != changeHandler.CurrentStateHash;
|
||||
protected bool HasUnsavedChanges
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!canSave)
|
||||
return false;
|
||||
|
||||
return lastSavedHash != changeHandler?.CurrentStateHash;
|
||||
}
|
||||
}
|
||||
|
||||
[Resolved]
|
||||
private BeatmapManager beatmapManager { get; set; }
|
||||
@ -72,10 +83,15 @@ namespace osu.Game.Screens.Edit
|
||||
[Resolved(canBeNull: true)]
|
||||
private DialogOverlay dialogOverlay { get; set; }
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
private NotificationOverlay notifications { get; set; }
|
||||
|
||||
public IBindable<bool> SamplePlaybackDisabled => samplePlaybackDisabled;
|
||||
|
||||
private readonly Bindable<bool> samplePlaybackDisabled = new Bindable<bool>();
|
||||
|
||||
private bool canSave;
|
||||
|
||||
private bool exitConfirmed;
|
||||
|
||||
private string lastSavedHash;
|
||||
@ -92,6 +108,8 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
private IBeatmap playableBeatmap;
|
||||
private EditorBeatmap editorBeatmap;
|
||||
|
||||
[CanBeNull] // Should be non-null once it can support custom rulesets.
|
||||
private EditorChangeHandler changeHandler;
|
||||
|
||||
private EditorMenuBar menuBar;
|
||||
@ -172,8 +190,14 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
AddInternal(editorBeatmap = new EditorBeatmap(playableBeatmap, loadableBeatmap.GetSkin(), loadableBeatmap.BeatmapInfo));
|
||||
dependencies.CacheAs(editorBeatmap);
|
||||
changeHandler = new EditorChangeHandler(editorBeatmap);
|
||||
dependencies.CacheAs<IEditorChangeHandler>(changeHandler);
|
||||
|
||||
canSave = editorBeatmap.BeatmapInfo.Ruleset.CreateInstance() is ILegacyRuleset;
|
||||
|
||||
if (canSave)
|
||||
{
|
||||
changeHandler = new EditorChangeHandler(editorBeatmap);
|
||||
dependencies.CacheAs<IEditorChangeHandler>(changeHandler);
|
||||
}
|
||||
|
||||
beatDivisor.Value = editorBeatmap.BeatmapInfo.BeatDivisor;
|
||||
beatDivisor.BindValueChanged(divisor => editorBeatmap.BeatmapInfo.BeatDivisor = divisor.NewValue);
|
||||
@ -311,8 +335,8 @@ namespace osu.Game.Screens.Edit
|
||||
}
|
||||
});
|
||||
|
||||
changeHandler.CanUndo.BindValueChanged(v => undoMenuItem.Action.Disabled = !v.NewValue, true);
|
||||
changeHandler.CanRedo.BindValueChanged(v => redoMenuItem.Action.Disabled = !v.NewValue, true);
|
||||
changeHandler?.CanUndo.BindValueChanged(v => undoMenuItem.Action.Disabled = !v.NewValue, true);
|
||||
changeHandler?.CanRedo.BindValueChanged(v => redoMenuItem.Action.Disabled = !v.NewValue, true);
|
||||
|
||||
menuBar.Mode.ValueChanged += onModeChanged;
|
||||
}
|
||||
@ -353,6 +377,12 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
protected void Save()
|
||||
{
|
||||
if (!canSave)
|
||||
{
|
||||
notifications?.Post(new SimpleErrorNotification { Text = "Saving is not supported for this ruleset yet, sorry!" });
|
||||
return;
|
||||
}
|
||||
|
||||
// no longer new after first user-triggered save.
|
||||
isNewBeatmap = false;
|
||||
|
||||
@ -648,9 +678,9 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
#endregion
|
||||
|
||||
protected void Undo() => changeHandler.RestoreState(-1);
|
||||
protected void Undo() => changeHandler?.RestoreState(-1);
|
||||
|
||||
protected void Redo() => changeHandler.RestoreState(1);
|
||||
protected void Redo() => changeHandler?.RestoreState(1);
|
||||
|
||||
private void resetTrack(bool seekToStart = false)
|
||||
{
|
||||
@ -761,7 +791,7 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
private void updateLastSavedHash()
|
||||
{
|
||||
lastSavedHash = changeHandler.CurrentStateHash;
|
||||
lastSavedHash = changeHandler?.CurrentStateHash;
|
||||
}
|
||||
|
||||
private List<MenuItem> createFileMenuItems()
|
||||
|
@ -33,7 +33,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
});
|
||||
}
|
||||
|
||||
private GetRoomsRequest pollReq;
|
||||
private GetRoomsRequest lastPollRequest;
|
||||
|
||||
protected override Task Poll()
|
||||
{
|
||||
@ -45,10 +45,11 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
|
||||
pollReq?.Cancel();
|
||||
pollReq = new GetRoomsRequest(Filter.Value.Status, Filter.Value.Category);
|
||||
lastPollRequest?.Cancel();
|
||||
|
||||
pollReq.Success += result =>
|
||||
var req = new GetRoomsRequest(Filter.Value.Status, Filter.Value.Category);
|
||||
|
||||
req.Success += result =>
|
||||
{
|
||||
foreach (var existing in RoomManager.Rooms.ToArray())
|
||||
{
|
||||
@ -66,10 +67,11 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
tcs.SetResult(true);
|
||||
};
|
||||
|
||||
pollReq.Failure += _ => tcs.SetResult(false);
|
||||
req.Failure += _ => tcs.SetResult(false);
|
||||
|
||||
API.Queue(pollReq);
|
||||
API.Queue(req);
|
||||
|
||||
lastPollRequest = req;
|
||||
return tcs.Task;
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
private GetRoomRequest pollReq;
|
||||
private GetRoomRequest lastPollRequest;
|
||||
|
||||
protected override Task Poll()
|
||||
{
|
||||
@ -30,19 +30,22 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
|
||||
pollReq?.Cancel();
|
||||
pollReq = new GetRoomRequest(room.RoomID.Value.Value);
|
||||
lastPollRequest?.Cancel();
|
||||
|
||||
pollReq.Success += result =>
|
||||
var req = new GetRoomRequest(room.RoomID.Value.Value);
|
||||
|
||||
req.Success += result =>
|
||||
{
|
||||
result.RemoveExpiredPlaylistItems();
|
||||
RoomManager.AddOrUpdateRoom(result);
|
||||
tcs.SetResult(true);
|
||||
};
|
||||
|
||||
pollReq.Failure += _ => tcs.SetResult(false);
|
||||
req.Failure += _ => tcs.SetResult(false);
|
||||
|
||||
API.Queue(pollReq);
|
||||
API.Queue(req);
|
||||
|
||||
lastPollRequest = req;
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ namespace osu.Game.Screens.Play.HUD
|
||||
base.LoadComplete();
|
||||
}
|
||||
|
||||
private float positionalAdjust;
|
||||
private float positionalAdjust = 1; // Start at 1 to handle the case where a user never send positional input.
|
||||
|
||||
protected override bool OnMouseMove(MouseMoveEvent e)
|
||||
{
|
||||
|
@ -286,6 +286,9 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
root.RemoveChild(existingSet);
|
||||
itemsCache.Invalidate();
|
||||
|
||||
if (!Scroll.UserScrolling)
|
||||
ScrollToSelected(true);
|
||||
});
|
||||
|
||||
public void UpdateBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() =>
|
||||
@ -311,13 +314,10 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
itemsCache.Invalidate();
|
||||
|
||||
Schedule(() =>
|
||||
{
|
||||
if (!Scroll.UserScrolling)
|
||||
ScrollToSelected(true);
|
||||
if (!Scroll.UserScrolling)
|
||||
ScrollToSelected(true);
|
||||
|
||||
BeatmapSetsChanged?.Invoke();
|
||||
});
|
||||
BeatmapSetsChanged?.Invoke();
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
|
@ -28,7 +28,7 @@ namespace osu.Game.Screens.Select
|
||||
Text = @"Yes. Please.",
|
||||
Action = () =>
|
||||
{
|
||||
Task.Run(() => scoreManager.Delete(s => !s.DeletePending && s.BeatmapInfo.ID == beatmapInfo.ID))
|
||||
Task.Run(() => scoreManager.Delete(beatmapInfo))
|
||||
.ContinueWith(_ => onCompletion);
|
||||
}
|
||||
},
|
||||
|
@ -38,6 +38,14 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
get => beatmapInfo;
|
||||
set
|
||||
{
|
||||
if (beatmapInfo == null && value == null)
|
||||
{
|
||||
// always null scores to ensure a correct initial display.
|
||||
// see weird `scoresLoadedOnce` logic in base implementation.
|
||||
Scores = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (beatmapInfo?.Equals(value) == true)
|
||||
return;
|
||||
|
||||
|
@ -14,6 +14,7 @@ using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Overlays;
|
||||
@ -111,6 +112,8 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
public new ScreenStack ScreenStack => base.ScreenStack;
|
||||
|
||||
public RealmAccess Realm => Dependencies.Get<RealmAccess>();
|
||||
|
||||
public new BackButton BackButton => base.BackButton;
|
||||
|
||||
public new BeatmapManager BeatmapManager => base.BeatmapManager;
|
||||
@ -158,6 +161,14 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
Dependencies.Get<SessionStatics>().SetValue(Static.MutedAudioNotificationShownOnce, true);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
// when running in visual tests and the window loses focus, we generally don't want the game to pause.
|
||||
((Bindable<bool>)IsActive).Value = true;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestLoader : Loader
|
||||
|
Loading…
x
Reference in New Issue
Block a user