From 06e5ef88c041c6298e3b2d1e8d64c5f28171d2ac Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 11 Jul 2023 02:30:16 +0200 Subject: [PATCH 001/118] legacy export broken --- osu.Game/Beatmaps/BeatmapManager.cs | 53 ++++++++++++++++++++ osu.Game/Beatmaps/BeatmapSetInfo.cs | 13 +++++ osu.Game/Database/ModelManager.cs | 2 + osu.Game/Localisation/EditorStrings.cs | 5 ++ osu.Game/Rulesets/Objects/BezierConverter.cs | 7 +++ osu.Game/Screens/Edit/Editor.cs | 7 +++ 6 files changed, 87 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 305dc01844..7d8c47ea5a 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -18,12 +18,15 @@ using osu.Framework.Platform; using osu.Game.Beatmaps.Formats; using osu.Game.Database; using osu.Game.Extensions; +using osu.Game.IO; using osu.Game.IO.Archives; using osu.Game.Models; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Skinning; using osu.Game.Utils; @@ -400,6 +403,56 @@ namespace osu.Game.Beatmaps public Task Export(BeatmapSetInfo beatmap) => beatmapExporter.ExportAsync(beatmap.ToLive(Realm)); + /// + /// Creates a copy of the and converts all beatmaps to legacy format, then exports it as a legacy package. + /// + /// + /// + public Task ExportLegacy(BeatmapSetInfo beatmap) + { + var copy = beatmap.Clone(); // does the detach from realm + + // convert all beatmaps to legacy format + foreach (var beatmapInfo in copy.Beatmaps) + { + // Convert beatmap + var file = beatmapInfo.File; + + if (file == null) + continue; + + using var oldStream = new LineBufferedReader(ReadFile(file)); + var beatmapContent = new LegacyBeatmapDecoder().Decode(oldStream); + + foreach (var controlPoint in beatmapContent.ControlPointInfo.AllControlPoints) + controlPoint.Time = Math.Floor(controlPoint.Time); + + foreach (var hitObject in beatmapContent.HitObjects) + { + hitObject.StartTime = Math.Floor(hitObject.StartTime); + + if (hitObject is IHasPath hasPath && BezierConverter.CountSegments(hasPath.Path.ControlPoints) > 1) + { + var newControlPoints = BezierConverter.ConvertToModernBezier(hasPath.Path.ControlPoints); + hasPath.Path.ControlPoints.Clear(); + hasPath.Path.ControlPoints.AddRange(newControlPoints); + } + } + + using var newStream = new MemoryStream(); + using var sw = new StreamWriter(newStream, Encoding.UTF8, 1024, true); + new LegacyBeatmapEncoder(beatmapContent, null).Encode(sw); + newStream.Seek(0, SeekOrigin.Begin); + + beatmapInfo.MD5Hash = newStream.ComputeMD5Hash(); + beatmapInfo.Hash = newStream.ComputeSHA2Hash(); + + AddFile(copy, newStream, file.Filename); + } + + return beatmapExporter.ExportAsync(new RealmLiveUnmanaged(copy)); + } + private void updateHashAndMarkDirty(BeatmapSetInfo setInfo) { setInfo.Hash = beatmapImporter.ComputeHash(setInfo); diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 59e413d935..923c498df8 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -90,6 +90,19 @@ namespace osu.Game.Beatmaps return ID == other.ID; } + public BeatmapSetInfo Clone() + { + var clone = (BeatmapSetInfo)this.Detach().MemberwiseClone(); + + for (int i = 0; i < clone.Beatmaps.Count; i++) + clone.Beatmaps[i] = clone.Beatmaps[i].Clone(); + + for (int i = 0; i < clone.Files.Count; i++) + clone.Files[i] = new RealmNamedFileUsage(clone.Files[i].File, clone.Files[i].Filename); + + return clone; + } + public override string ToString() => Metadata.GetDisplayString(); public bool Equals(IBeatmapSetInfo? other) => other is BeatmapSetInfo b && Equals(b); diff --git a/osu.Game/Database/ModelManager.cs b/osu.Game/Database/ModelManager.cs index 7d1dc5239a..8dafe0874c 100644 --- a/osu.Game/Database/ModelManager.cs +++ b/osu.Game/Database/ModelManager.cs @@ -33,6 +33,8 @@ namespace osu.Game.Database Realm = realm; } + public Stream ReadFile(RealmNamedFileUsage file) => realmFileStore.Storage.GetStream(file.File.GetStoragePath()); + public void DeleteFile(TModel item, RealmNamedFileUsage file) => performFileOperation(item, managed => DeleteFile(managed, managed.Files.First(f => f.Filename == file.Filename), managed.Realm)); diff --git a/osu.Game/Localisation/EditorStrings.cs b/osu.Game/Localisation/EditorStrings.cs index 20258b9c35..f1f650cf66 100644 --- a/osu.Game/Localisation/EditorStrings.cs +++ b/osu.Game/Localisation/EditorStrings.cs @@ -39,6 +39,11 @@ namespace osu.Game.Localisation /// public static LocalisableString ExportPackage => new TranslatableString(getKey(@"export_package"), @"Export package"); + /// + /// "Export legacy package" + /// + public static LocalisableString ExportLegacyPackage => new TranslatableString(getKey(@"export_legacy_package"), @"Export legacy package"); + /// /// "Create new difficulty" /// diff --git a/osu.Game/Rulesets/Objects/BezierConverter.cs b/osu.Game/Rulesets/Objects/BezierConverter.cs index ebee36a7db..0c878fa1fd 100644 --- a/osu.Game/Rulesets/Objects/BezierConverter.cs +++ b/osu.Game/Rulesets/Objects/BezierConverter.cs @@ -39,6 +39,13 @@ namespace osu.Game.Rulesets.Objects new[] { new Vector2d(1, 0), new Vector2d(1, 1.2447058f), new Vector2d(-0.8526471f, 2.118367f), new Vector2d(-2.6211002f, 7.854936e-06f), new Vector2d(-0.8526448f, -2.118357f), new Vector2d(1, -1.2447058f), new Vector2d(1, 0) }) }; + /// + /// Counts the number of segments in a slider path. + /// + /// The control points of the path. + /// The number of segments in a slider path. + public static int CountSegments(IList controlPoints) => controlPoints.Where((t, i) => t.Type != null && i < controlPoints.Count - 1).Count(); + /// /// Converts a slider path to bezier control point positions compatible with the legacy osu! client. /// diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index b8fa7f6579..bc5df37570 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -966,6 +966,7 @@ namespace osu.Game.Screens.Edit { new EditorMenuItem(WebCommonStrings.ButtonsSave, MenuItemType.Standard, () => Save()), new EditorMenuItem(EditorStrings.ExportPackage, MenuItemType.Standard, exportBeatmap) { Action = { Disabled = !RuntimeInfo.IsDesktop } }, + new EditorMenuItem(EditorStrings.ExportLegacyPackage, MenuItemType.Standard, exportLegacyBeatmap) { Action = { Disabled = !RuntimeInfo.IsDesktop } }, new EditorMenuItemSpacer(), createDifficultyCreationMenu(), createDifficultySwitchMenu(), @@ -981,6 +982,12 @@ namespace osu.Game.Screens.Edit beatmapManager.Export(Beatmap.Value.BeatmapSetInfo); } + private void exportLegacyBeatmap() + { + Save(); + beatmapManager.ExportLegacy(Beatmap.Value.BeatmapSetInfo); + } + /// /// Beatmaps of the currently edited set, grouped by ruleset and ordered by difficulty. /// From 2db25722cbf29eb7d93e59df5d3e6b414e4d2dd4 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 11 Jul 2023 20:18:54 +0200 Subject: [PATCH 002/118] It works now --- osu.Game/Beatmaps/BeatmapManager.cs | 89 +++++++++++++++++++---------- osu.Game/Beatmaps/BeatmapSetInfo.cs | 13 ----- osu.Game/Database/ModelManager.cs | 10 ++-- 3 files changed, 62 insertions(+), 50 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 7d8c47ea5a..7c21b87a97 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -29,6 +29,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Skinning; using osu.Game.Utils; +using osuTK; namespace osu.Game.Beatmaps { @@ -406,51 +407,77 @@ namespace osu.Game.Beatmaps /// /// Creates a copy of the and converts all beatmaps to legacy format, then exports it as a legacy package. /// - /// + /// /// - public Task ExportLegacy(BeatmapSetInfo beatmap) + public Task ExportLegacy(BeatmapSetInfo beatmapSetInfo) { - var copy = beatmap.Clone(); // does the detach from realm + // Create a clone of the original beatmap set which we will convert to legacy format and then export + var clone = new BeatmapSetInfo(beatmapSetInfo.Beatmaps.Select(b => b.Clone())); + clone.Files.AddRange(beatmapSetInfo.Files.Select(f => new RealmNamedFileUsage(f.File, f.Filename))); - // convert all beatmaps to legacy format - foreach (var beatmapInfo in copy.Beatmaps) + // convert all beatmaps in the cloned beatmap set to legacy format + foreach (var beatmapInfo in clone.Beatmaps) { - // Convert beatmap - var file = beatmapInfo.File; + beatmapInfo.BeatmapSet = clone; + beatmapInfo.ID = Guid.NewGuid(); + var file = beatmapInfo.File; if (file == null) continue; - using var oldStream = new LineBufferedReader(ReadFile(file)); - var beatmapContent = new LegacyBeatmapDecoder().Decode(oldStream); - - foreach (var controlPoint in beatmapContent.ControlPointInfo.AllControlPoints) - controlPoint.Time = Math.Floor(controlPoint.Time); - - foreach (var hitObject in beatmapContent.HitObjects) + var beatmapContent = new LegacyBeatmapDecoder().Decode(new LineBufferedReader(RealmFileStore.Storage.GetStream(file.File.GetStoragePath()))); + var beatmapSkin = new LegacySkin(new SkinInfo(), null!) { - hitObject.StartTime = Math.Floor(hitObject.StartTime); + Configuration = new LegacySkinDecoder().Decode(new LineBufferedReader(RealmFileStore.Storage.GetStream(file.File.GetStoragePath()))) + }; - if (hitObject is IHasPath hasPath && BezierConverter.CountSegments(hasPath.Path.ControlPoints) > 1) - { - var newControlPoints = BezierConverter.ConvertToModernBezier(hasPath.Path.ControlPoints); - hasPath.Path.ControlPoints.Clear(); - hasPath.Path.ControlPoints.AddRange(newControlPoints); - } - } + Realm.Realm.Write(realm => + { + using var stream = new MemoryStream(); + convertAndEncodeLegacyBeatmap(beatmapContent, beatmapSkin, stream); - using var newStream = new MemoryStream(); - using var sw = new StreamWriter(newStream, Encoding.UTF8, 1024, true); - new LegacyBeatmapEncoder(beatmapContent, null).Encode(sw); - newStream.Seek(0, SeekOrigin.Begin); + beatmapInfo.MD5Hash = stream.ComputeMD5Hash(); + beatmapInfo.Hash = stream.ComputeSHA2Hash(); - beatmapInfo.MD5Hash = newStream.ComputeMD5Hash(); - beatmapInfo.Hash = newStream.ComputeSHA2Hash(); - - AddFile(copy, newStream, file.Filename); + file.File = RealmFileStore.Add(stream, realm).Detach(); + }); } - return beatmapExporter.ExportAsync(new RealmLiveUnmanaged(copy)); + return beatmapExporter.ExportAsync(new RealmLiveUnmanaged(clone)); + } + + private void convertAndEncodeLegacyBeatmap(IBeatmap beatmapContent, ISkin beatmapSkin, Stream stream) + { + // Convert beatmap elements to be compatible with legacy format + // So we truncate time and position values to integers, and convert paths with multiple segments to bezier curves + foreach (var controlPoint in beatmapContent.ControlPointInfo.AllControlPoints) + controlPoint.Time = Math.Floor(controlPoint.Time); + + foreach (var hitObject in beatmapContent.HitObjects) + { + hitObject.StartTime = Math.Floor(hitObject.StartTime); + + if (hitObject is not IHasPath hasPath || BezierConverter.CountSegments(hasPath.Path.ControlPoints) <= 1) continue; + + var newControlPoints = BezierConverter.ConvertToModernBezier(hasPath.Path.ControlPoints); + + // Truncate control points to integer positions + foreach (var pathControlPoint in newControlPoints) + { + pathControlPoint.Position = new Vector2( + (float)Math.Floor(pathControlPoint.Position.X), + (float)Math.Floor(pathControlPoint.Position.Y)); + } + + hasPath.Path.ControlPoints.Clear(); + hasPath.Path.ControlPoints.AddRange(newControlPoints); + } + + // Encode to legacy format + using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) + new LegacyBeatmapEncoder(beatmapContent, beatmapSkin).Encode(sw); + + stream.Seek(0, SeekOrigin.Begin); } private void updateHashAndMarkDirty(BeatmapSetInfo setInfo) diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 923c498df8..59e413d935 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -90,19 +90,6 @@ namespace osu.Game.Beatmaps return ID == other.ID; } - public BeatmapSetInfo Clone() - { - var clone = (BeatmapSetInfo)this.Detach().MemberwiseClone(); - - for (int i = 0; i < clone.Beatmaps.Count; i++) - clone.Beatmaps[i] = clone.Beatmaps[i].Clone(); - - for (int i = 0; i < clone.Files.Count; i++) - clone.Files[i] = new RealmNamedFileUsage(clone.Files[i].File, clone.Files[i].Filename); - - return clone; - } - public override string ToString() => Metadata.GetDisplayString(); public bool Equals(IBeatmapSetInfo? other) => other is BeatmapSetInfo b && Equals(b); diff --git a/osu.Game/Database/ModelManager.cs b/osu.Game/Database/ModelManager.cs index 8dafe0874c..172a2df5a3 100644 --- a/osu.Game/Database/ModelManager.cs +++ b/osu.Game/Database/ModelManager.cs @@ -25,16 +25,14 @@ namespace osu.Game.Database protected RealmAccess Realm { get; } - private readonly RealmFileStore realmFileStore; + protected readonly RealmFileStore RealmFileStore; public ModelManager(Storage storage, RealmAccess realm) { - realmFileStore = new RealmFileStore(realm, storage); + RealmFileStore = new RealmFileStore(realm, storage); Realm = realm; } - public Stream ReadFile(RealmNamedFileUsage file) => realmFileStore.Storage.GetStream(file.File.GetStoragePath()); - public void DeleteFile(TModel item, RealmNamedFileUsage file) => performFileOperation(item, managed => DeleteFile(managed, managed.Files.First(f => f.Filename == file.Filename), managed.Realm)); @@ -79,7 +77,7 @@ namespace osu.Game.Database /// public void ReplaceFile(RealmNamedFileUsage file, Stream contents, Realm realm) { - file.File = realmFileStore.Add(contents, realm); + file.File = RealmFileStore.Add(contents, realm); } /// @@ -95,7 +93,7 @@ namespace osu.Game.Database return; } - var file = realmFileStore.Add(contents, realm); + var file = RealmFileStore.Add(contents, realm); var namedUsage = new RealmNamedFileUsage(file, filename); item.Files.Add(namedUsage); From b577b6b6ae9ce8e4b047cfed8ba0820c04546db7 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 11 Jul 2023 21:04:09 +0200 Subject: [PATCH 003/118] Export legacy converted beatmaps as .osz and non-converted beatmaps as .osz2 --- osu.Game/Beatmaps/BeatmapImporter.cs | 4 ++-- osu.Game/Beatmaps/BeatmapManager.cs | 13 ++++++++++--- osu.Game/Database/BeatmapExporter.cs | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 osu.Game/Database/BeatmapExporter.cs diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index 7d367ef77d..a2d74d089f 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -29,7 +29,7 @@ namespace osu.Game.Beatmaps /// public class BeatmapImporter : RealmArchiveModelImporter { - public override IEnumerable HandledExtensions => new[] { ".osz" }; + public override IEnumerable HandledExtensions => new[] { ".osz", ".osz2" }; protected override string[] HashableFileTypes => new[] { ".osu" }; @@ -145,7 +145,7 @@ namespace osu.Game.Beatmaps } } - protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path).ToLowerInvariant() == ".osz"; + protected override bool ShouldDeleteArchive(string path) => HandledExtensions.Contains(Path.GetExtension(path).ToLowerInvariant()); protected override void Populate(BeatmapSetInfo beatmapSet, ArchiveReader? archive, Realm realm, CancellationToken cancellationToken = default) { diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 7c21b87a97..ded26f79cd 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -44,7 +44,9 @@ namespace osu.Game.Beatmaps private readonly WorkingBeatmapCache workingBeatmapCache; - private readonly LegacyBeatmapExporter beatmapExporter; + private readonly BeatmapExporter beatmapExporter; + + private readonly LegacyBeatmapExporter legacyBeatmapExporter; public ProcessBeatmapDelegate? ProcessBeatmap { private get; set; } @@ -81,7 +83,12 @@ namespace osu.Game.Beatmaps workingBeatmapCache = CreateWorkingBeatmapCache(audioManager, gameResources, userResources, defaultBeatmap, host); - beatmapExporter = new LegacyBeatmapExporter(storage) + beatmapExporter = new BeatmapExporter(storage) + { + PostNotification = obj => PostNotification?.Invoke(obj) + }; + + legacyBeatmapExporter = new LegacyBeatmapExporter(storage) { PostNotification = obj => PostNotification?.Invoke(obj) }; @@ -443,7 +450,7 @@ namespace osu.Game.Beatmaps }); } - return beatmapExporter.ExportAsync(new RealmLiveUnmanaged(clone)); + return legacyBeatmapExporter.ExportAsync(new RealmLiveUnmanaged(clone)); } private void convertAndEncodeLegacyBeatmap(IBeatmap beatmapContent, ISkin beatmapSkin, Stream stream) diff --git a/osu.Game/Database/BeatmapExporter.cs b/osu.Game/Database/BeatmapExporter.cs new file mode 100644 index 0000000000..b3a85dd5d9 --- /dev/null +++ b/osu.Game/Database/BeatmapExporter.cs @@ -0,0 +1,18 @@ +// 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.Platform; +using osu.Game.Beatmaps; + +namespace osu.Game.Database +{ + public class BeatmapExporter : LegacyArchiveExporter + { + public BeatmapExporter(Storage storage) + : base(storage) + { + } + + protected override string FileExtension => @".osz2"; + } +} From 465cc759f02c84c6c3ae720d715623ac2b7596d6 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Wed, 12 Jul 2023 14:49:49 +0200 Subject: [PATCH 004/118] Add xmldoc to clarify the purpose of BeatmapExporter --- osu.Game/Database/BeatmapExporter.cs | 4 ++++ osu.Game/Database/LegacyBeatmapExporter.cs | 3 +++ 2 files changed, 7 insertions(+) diff --git a/osu.Game/Database/BeatmapExporter.cs b/osu.Game/Database/BeatmapExporter.cs index b3a85dd5d9..9377065973 100644 --- a/osu.Game/Database/BeatmapExporter.cs +++ b/osu.Game/Database/BeatmapExporter.cs @@ -6,6 +6,10 @@ using osu.Game.Beatmaps; namespace osu.Game.Database { + /// + /// Exporter for beatmap archives. + /// This is not for legacy purposes and works for lazer only. + /// public class BeatmapExporter : LegacyArchiveExporter { public BeatmapExporter(Storage storage) diff --git a/osu.Game/Database/LegacyBeatmapExporter.cs b/osu.Game/Database/LegacyBeatmapExporter.cs index 4ee8c0636e..62096f862a 100644 --- a/osu.Game/Database/LegacyBeatmapExporter.cs +++ b/osu.Game/Database/LegacyBeatmapExporter.cs @@ -6,6 +6,9 @@ using osu.Game.Beatmaps; namespace osu.Game.Database { + /// + /// Exporter for osu!stable legacy beatmap archives. + /// public class LegacyBeatmapExporter : LegacyArchiveExporter { public LegacyBeatmapExporter(Storage storage) From 3052c317e10c801e79a45542bcc247ee59379ce5 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Wed, 12 Jul 2023 15:04:06 +0200 Subject: [PATCH 005/118] change .osz2 to .olz (osu lazer zip) --- osu.Game/Beatmaps/BeatmapImporter.cs | 2 +- osu.Game/Database/BeatmapExporter.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index a2d74d089f..e500f87984 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -29,7 +29,7 @@ namespace osu.Game.Beatmaps /// public class BeatmapImporter : RealmArchiveModelImporter { - public override IEnumerable HandledExtensions => new[] { ".osz", ".osz2" }; + public override IEnumerable HandledExtensions => new[] { ".osz", ".olz" }; protected override string[] HashableFileTypes => new[] { ".osu" }; diff --git a/osu.Game/Database/BeatmapExporter.cs b/osu.Game/Database/BeatmapExporter.cs index 9377065973..f37c57dea5 100644 --- a/osu.Game/Database/BeatmapExporter.cs +++ b/osu.Game/Database/BeatmapExporter.cs @@ -17,6 +17,6 @@ namespace osu.Game.Database { } - protected override string FileExtension => @".osz2"; + protected override string FileExtension => @".olz"; } } From 8ca801a2240b6749c35dc98a33f73ba229d080fe Mon Sep 17 00:00:00 2001 From: OliBomby Date: Wed, 12 Jul 2023 15:18:16 +0200 Subject: [PATCH 006/118] dispose the streams --- osu.Game/Beatmaps/BeatmapManager.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index ded26f79cd..248e97d6ee 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -432,10 +432,15 @@ namespace osu.Game.Beatmaps if (file == null) continue; - var beatmapContent = new LegacyBeatmapDecoder().Decode(new LineBufferedReader(RealmFileStore.Storage.GetStream(file.File.GetStoragePath()))); + using var contentStream = RealmFileStore.Storage.GetStream(file.File.GetStoragePath()); + using var contentStreamReader = new LineBufferedReader(contentStream); + var beatmapContent = new LegacyBeatmapDecoder().Decode(contentStreamReader); + + using var skinStream = RealmFileStore.Storage.GetStream(file.File.GetStoragePath()); + using var skinStreamReader = new LineBufferedReader(contentStream); var beatmapSkin = new LegacySkin(new SkinInfo(), null!) { - Configuration = new LegacySkinDecoder().Decode(new LineBufferedReader(RealmFileStore.Storage.GetStream(file.File.GetStoragePath()))) + Configuration = new LegacySkinDecoder().Decode(skinStreamReader) }; Realm.Realm.Write(realm => From 1d837a8725308a7f6e83ced3713a8796ad464930 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Thu, 13 Jul 2023 00:20:01 +0200 Subject: [PATCH 007/118] Move all conversion code to LegacyBeatmapExporter --- osu.Game/Beatmaps/BeatmapManager.cs | 85 +--------------------- osu.Game/Database/LegacyArchiveExporter.cs | 4 +- osu.Game/Database/LegacyBeatmapExporter.cs | 70 ++++++++++++++++++ osu.Game/Database/ModelManager.cs | 8 +- 4 files changed, 78 insertions(+), 89 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 248e97d6ee..ffdff13845 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -18,18 +18,14 @@ using osu.Framework.Platform; using osu.Game.Beatmaps.Formats; using osu.Game.Database; using osu.Game.Extensions; -using osu.Game.IO; using osu.Game.IO.Archives; using osu.Game.Models; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Skinning; using osu.Game.Utils; -using osuTK; namespace osu.Game.Beatmaps { @@ -411,86 +407,7 @@ namespace osu.Game.Beatmaps public Task Export(BeatmapSetInfo beatmap) => beatmapExporter.ExportAsync(beatmap.ToLive(Realm)); - /// - /// Creates a copy of the and converts all beatmaps to legacy format, then exports it as a legacy package. - /// - /// - /// - public Task ExportLegacy(BeatmapSetInfo beatmapSetInfo) - { - // Create a clone of the original beatmap set which we will convert to legacy format and then export - var clone = new BeatmapSetInfo(beatmapSetInfo.Beatmaps.Select(b => b.Clone())); - clone.Files.AddRange(beatmapSetInfo.Files.Select(f => new RealmNamedFileUsage(f.File, f.Filename))); - - // convert all beatmaps in the cloned beatmap set to legacy format - foreach (var beatmapInfo in clone.Beatmaps) - { - beatmapInfo.BeatmapSet = clone; - beatmapInfo.ID = Guid.NewGuid(); - - var file = beatmapInfo.File; - if (file == null) - continue; - - using var contentStream = RealmFileStore.Storage.GetStream(file.File.GetStoragePath()); - using var contentStreamReader = new LineBufferedReader(contentStream); - var beatmapContent = new LegacyBeatmapDecoder().Decode(contentStreamReader); - - using var skinStream = RealmFileStore.Storage.GetStream(file.File.GetStoragePath()); - using var skinStreamReader = new LineBufferedReader(contentStream); - var beatmapSkin = new LegacySkin(new SkinInfo(), null!) - { - Configuration = new LegacySkinDecoder().Decode(skinStreamReader) - }; - - Realm.Realm.Write(realm => - { - using var stream = new MemoryStream(); - convertAndEncodeLegacyBeatmap(beatmapContent, beatmapSkin, stream); - - beatmapInfo.MD5Hash = stream.ComputeMD5Hash(); - beatmapInfo.Hash = stream.ComputeSHA2Hash(); - - file.File = RealmFileStore.Add(stream, realm).Detach(); - }); - } - - return legacyBeatmapExporter.ExportAsync(new RealmLiveUnmanaged(clone)); - } - - private void convertAndEncodeLegacyBeatmap(IBeatmap beatmapContent, ISkin beatmapSkin, Stream stream) - { - // Convert beatmap elements to be compatible with legacy format - // So we truncate time and position values to integers, and convert paths with multiple segments to bezier curves - foreach (var controlPoint in beatmapContent.ControlPointInfo.AllControlPoints) - controlPoint.Time = Math.Floor(controlPoint.Time); - - foreach (var hitObject in beatmapContent.HitObjects) - { - hitObject.StartTime = Math.Floor(hitObject.StartTime); - - if (hitObject is not IHasPath hasPath || BezierConverter.CountSegments(hasPath.Path.ControlPoints) <= 1) continue; - - var newControlPoints = BezierConverter.ConvertToModernBezier(hasPath.Path.ControlPoints); - - // Truncate control points to integer positions - foreach (var pathControlPoint in newControlPoints) - { - pathControlPoint.Position = new Vector2( - (float)Math.Floor(pathControlPoint.Position.X), - (float)Math.Floor(pathControlPoint.Position.Y)); - } - - hasPath.Path.ControlPoints.Clear(); - hasPath.Path.ControlPoints.AddRange(newControlPoints); - } - - // Encode to legacy format - using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) - new LegacyBeatmapEncoder(beatmapContent, beatmapSkin).Encode(sw); - - stream.Seek(0, SeekOrigin.Begin); - } + public Task ExportLegacy(BeatmapSetInfo beatmap) => legacyBeatmapExporter.ExportAsync(beatmap.ToLive(Realm)); private void updateHashAndMarkDirty(BeatmapSetInfo setInfo) { diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index 7689ffc13d..9805207591 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -39,7 +39,7 @@ namespace osu.Game.Database { cancellationToken.ThrowIfCancellationRequested(); - using (var stream = UserFileStorage.GetStream(file.File.GetStoragePath())) + using (var stream = GetFileContents(model, file)) { if (stream == null) { @@ -65,5 +65,7 @@ namespace osu.Game.Database } } } + + protected virtual Stream? GetFileContents(TModel model, INamedFileUsage file) => UserFileStorage.GetStream(file.File.GetStoragePath()); } } diff --git a/osu.Game/Database/LegacyBeatmapExporter.cs b/osu.Game/Database/LegacyBeatmapExporter.cs index 62096f862a..42d8a72073 100644 --- a/osu.Game/Database/LegacyBeatmapExporter.cs +++ b/osu.Game/Database/LegacyBeatmapExporter.cs @@ -1,13 +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; +using System.IO; +using System.Linq; +using System.Text; using osu.Framework.Platform; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Formats; +using osu.Game.Extensions; +using osu.Game.IO; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Skinning; +using osuTK; namespace osu.Game.Database { /// /// Exporter for osu!stable legacy beatmap archives. + /// Converts all beatmaps in the set to legacy format and exports it as a legacy package. /// public class LegacyBeatmapExporter : LegacyArchiveExporter { @@ -16,6 +28,64 @@ namespace osu.Game.Database { } + protected override Stream? GetFileContents(BeatmapSetInfo model, INamedFileUsage file) + { + bool isBeatmap = model.Beatmaps.Any(o => o.Hash == file.File.Hash); + + if (!isBeatmap) + return base.GetFileContents(model, file); + + // Read the beatmap contents and skin + using var contentStream = UserFileStorage.GetStream(file.File.GetStoragePath()); + + if (contentStream == null) + return null; + + using var contentStreamReader = new LineBufferedReader(contentStream); + var beatmapContent = new LegacyBeatmapDecoder().Decode(contentStreamReader); + + using var skinStream = UserFileStorage.GetStream(file.File.GetStoragePath()); + using var skinStreamReader = new LineBufferedReader(contentStream); + var beatmapSkin = new LegacySkin(new SkinInfo(), null!) + { + Configuration = new LegacySkinDecoder().Decode(skinStreamReader) + }; + + // Convert beatmap elements to be compatible with legacy format + // So we truncate time and position values to integers, and convert paths with multiple segments to bezier curves + foreach (var controlPoint in beatmapContent.ControlPointInfo.AllControlPoints) + controlPoint.Time = Math.Floor(controlPoint.Time); + + foreach (var hitObject in beatmapContent.HitObjects) + { + hitObject.StartTime = Math.Floor(hitObject.StartTime); + + if (hitObject is not IHasPath hasPath || BezierConverter.CountSegments(hasPath.Path.ControlPoints) <= 1) continue; + + var newControlPoints = BezierConverter.ConvertToModernBezier(hasPath.Path.ControlPoints); + + // Truncate control points to integer positions + foreach (var pathControlPoint in newControlPoints) + { + pathControlPoint.Position = new Vector2( + (float)Math.Floor(pathControlPoint.Position.X), + (float)Math.Floor(pathControlPoint.Position.Y)); + } + + hasPath.Path.ControlPoints.Clear(); + hasPath.Path.ControlPoints.AddRange(newControlPoints); + } + + // Encode to legacy format + var stream = new MemoryStream(); + using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) + new LegacyBeatmapEncoder(beatmapContent, beatmapSkin).Encode(sw); + + stream.Seek(0, SeekOrigin.Begin); + + return stream; + } + protected override string FileExtension => @".osz"; } } diff --git a/osu.Game/Database/ModelManager.cs b/osu.Game/Database/ModelManager.cs index 172a2df5a3..7d1dc5239a 100644 --- a/osu.Game/Database/ModelManager.cs +++ b/osu.Game/Database/ModelManager.cs @@ -25,11 +25,11 @@ namespace osu.Game.Database protected RealmAccess Realm { get; } - protected readonly RealmFileStore RealmFileStore; + private readonly RealmFileStore realmFileStore; public ModelManager(Storage storage, RealmAccess realm) { - RealmFileStore = new RealmFileStore(realm, storage); + realmFileStore = new RealmFileStore(realm, storage); Realm = realm; } @@ -77,7 +77,7 @@ namespace osu.Game.Database /// public void ReplaceFile(RealmNamedFileUsage file, Stream contents, Realm realm) { - file.File = RealmFileStore.Add(contents, realm); + file.File = realmFileStore.Add(contents, realm); } /// @@ -93,7 +93,7 @@ namespace osu.Game.Database return; } - var file = RealmFileStore.Add(contents, realm); + var file = realmFileStore.Add(contents, realm); var namedUsage = new RealmNamedFileUsage(file, filename); item.Files.Add(namedUsage); From dd8774a64006792556b357d78756438324a34b37 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jul 2023 13:21:28 +0900 Subject: [PATCH 008/118] Vertically centre the editor osu! playfield --- osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index aac5f6ffb1..8d93613156 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -65,8 +65,8 @@ namespace osu.Game.Rulesets.Osu.Edit PlayfieldContentContainer.Padding = new MarginPadding { Vertical = 10, - Left = TOOLBOX_CONTRACTED_SIZE_LEFT + 10, - Right = TOOLBOX_CONTRACTED_SIZE_RIGHT + 10, + // Intentionally use the left toolbox size for both sides to vertically centre the playfield. + Horizontal = TOOLBOX_CONTRACTED_SIZE_LEFT + 10, }; LayerBelowRuleset.AddRange(new Drawable[] From 56acc9e3dde3f161c79f7fafc312d9800e0fc420 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jul 2023 14:02:48 +0900 Subject: [PATCH 009/118] Change `BeatDivisorControl` to retrive bindable divisor via DI --- .../Visual/Editing/TestSceneBeatDivisorControl.cs | 9 +++++++-- .../Visual/Editing/TestSceneTimelineTickDisplay.cs | 2 +- .../Edit/Compose/Components/BeatDivisorControl.cs | 8 ++------ osu.Game/Screens/Edit/EditorScreenWithTimeline.cs | 10 ++-------- 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs index 88b959a2a0..f2b3351533 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs @@ -22,7 +22,6 @@ namespace osu.Game.Tests.Visual.Editing public partial class TestSceneBeatDivisorControl : OsuManualInputManagerTestScene { private BeatDivisorControl beatDivisorControl = null!; - private BindableBeatDivisor bindableBeatDivisor = null!; private SliderBar tickSliderBar => beatDivisorControl.ChildrenOfType>().Single(); private Triangle tickMarkerHead => tickSliderBar.ChildrenOfType().Single(); @@ -30,13 +29,19 @@ namespace osu.Game.Tests.Visual.Editing [Cached] private readonly OverlayColourProvider overlayColour = new OverlayColourProvider(OverlayColourScheme.Aquamarine); + [Cached] + private readonly BindableBeatDivisor bindableBeatDivisor = new BindableBeatDivisor(16); + [SetUp] public void SetUp() => Schedule(() => { + bindableBeatDivisor.ValidDivisors.SetDefault(); + bindableBeatDivisor.SetDefault(); + Child = new PopoverContainer { RelativeSizeAxes = Axes.Both, - Child = beatDivisorControl = new BeatDivisorControl(bindableBeatDivisor = new BindableBeatDivisor(16)) + Child = beatDivisorControl = new BeatDivisorControl { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineTickDisplay.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineTickDisplay.cs index 1376ba23fb..18bd6d840a 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineTickDisplay.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineTickDisplay.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.Editing { BeatDivisor.Value = 4; - Add(new BeatDivisorControl(BeatDivisor) + Add(new BeatDivisorControl { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index f7159f8670..59b0bd1785 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -33,12 +33,8 @@ namespace osu.Game.Screens.Edit.Compose.Components { private int? lastCustomDivisor; - private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); - - public BeatDivisorControl(BindableBeatDivisor beatDivisor) - { - this.beatDivisor.BindTo(beatDivisor); - } + [Resolved] + private BindableBeatDivisor beatDivisor { get; set; } = null!; [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index b8cbff047e..0c5f28c2d6 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -3,7 +3,6 @@ #nullable disable -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -19,8 +18,6 @@ namespace osu.Game.Screens.Edit { private const float padding = 10; - private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); - private Container timelineContainer; protected EditorScreenWithTimeline(EditorScreenMode type) @@ -33,11 +30,8 @@ namespace osu.Game.Screens.Edit private LoadingSpinner spinner; [BackgroundDependencyLoader(true)] - private void load(OverlayColourProvider colourProvider, [CanBeNull] BindableBeatDivisor beatDivisor) + private void load(OverlayColourProvider colourProvider) { - if (beatDivisor != null) - this.beatDivisor.BindTo(beatDivisor); - Child = new GridContainer { RelativeSizeAxes = Axes.Both, @@ -82,7 +76,7 @@ namespace osu.Game.Screens.Edit AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Right = 5 }, }, - new BeatDivisorControl(this.beatDivisor) { RelativeSizeAxes = Axes.Both } + new BeatDivisorControl { RelativeSizeAxes = Axes.Both } }, }, RowDimensions = new[] From ebaf63b7644425dd06f9e1ba00e8159070813ccf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jul 2023 14:04:12 +0900 Subject: [PATCH 010/118] Apply NRT to timeline related classes --- .../Edit/Compose/Components/Timeline/TimelineArea.cs | 8 +++----- osu.Game/Screens/Edit/EditorScreenWithTimeline.cs | 12 +++++------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index 0b83258f8b..02c773fd4b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.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 osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -18,16 +16,16 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { public partial class TimelineArea : CompositeDrawable { - public Timeline Timeline; + public Timeline Timeline = null!; private readonly Drawable userContent; - public TimelineArea(Drawable content = null) + public TimelineArea(Drawable? content = null) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - userContent = content ?? Drawable.Empty(); + userContent = content ?? Empty(); } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index 0c5f28c2d6..bd57ea42f0 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.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 osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -18,17 +16,17 @@ namespace osu.Game.Screens.Edit { private const float padding = 10; - private Container timelineContainer; + private Container timelineContainer = null!; + + private Container mainContent = null!; + + private LoadingSpinner spinner = null!; protected EditorScreenWithTimeline(EditorScreenMode type) : base(type) { } - private Container mainContent; - - private LoadingSpinner spinner; - [BackgroundDependencyLoader(true)] private void load(OverlayColourProvider colourProvider) { From 5b2e70426488a295df83f83345326d7181b83568 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jul 2023 14:19:04 +0900 Subject: [PATCH 011/118] Move beat divisor control inside of `TimelineArea` and adjust metrics to match design --- .../Components/Timeline/TimelineArea.cs | 44 +++++++++---------- .../Screens/Edit/EditorScreenWithTimeline.cs | 5 ++- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index 02c773fd4b..3969a002db 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -48,14 +48,24 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + }, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Absolute, 140), + new Dimension(), + new Dimension(GridSizeMode.Absolute, 30), + new Dimension(GridSizeMode.Absolute, 110), + }, Content = new[] { new Drawable[] { new Container { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Both, Name = @"Toggle controls", Children = new Drawable[] { @@ -92,31 +102,31 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } } }, + Timeline = new Timeline(userContent), new Container { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Both, Name = @"Zoom controls", + Padding = new MarginPadding { Right = 5 }, Children = new Drawable[] { new Box { RelativeSizeAxes = Axes.Both, - Colour = colourProvider.Background3, + Colour = colourProvider.Background2, }, new Container { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Both, Masking = true, Children = new[] { new TimelineButton { - RelativeSizeAxes = Axes.Y, - Height = 0.5f, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(1, 0.5f), Icon = FontAwesome.Solid.SearchPlus, Action = () => Timeline.AdjustZoomRelatively(1) }, @@ -124,8 +134,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.Y, - Height = 0.5f, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(1, 0.5f), Icon = FontAwesome.Solid.SearchMinus, Action = () => Timeline.AdjustZoomRelatively(-1) }, @@ -133,19 +143,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } } }, - Timeline = new Timeline(userContent), + new BeatDivisorControl { RelativeSizeAxes = Axes.Both } }, }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - }, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - } } }; diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index bd57ea42f0..a2367dd66c 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; -using osu.Game.Screens.Edit.Compose.Components; using osu.Game.Screens.Edit.Compose.Components.Timeline; namespace osu.Game.Screens.Edit @@ -30,6 +29,9 @@ namespace osu.Game.Screens.Edit [BackgroundDependencyLoader(true)] private void load(OverlayColourProvider colourProvider) { + // Grid with only two rows. + // First is the timeline area, which should be allowed to expand as required. + // Second is the main editor content, including the playfield and side toolbars (but not the bottom). Child = new GridContainer { RelativeSizeAxes = Axes.Both, @@ -74,7 +76,6 @@ namespace osu.Game.Screens.Edit AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Right = 5 }, }, - new BeatDivisorControl { RelativeSizeAxes = Axes.Both } }, }, RowDimensions = new[] From 1dc293ed619adc285ac5554b4ea6a65e04049f77 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jul 2023 14:24:53 +0900 Subject: [PATCH 012/118] Allow specifying a custom width for nubs in `OsuCheckbox`es --- osu.Game/Graphics/UserInterface/Nub.cs | 6 +++--- osu.Game/Graphics/UserInterface/OsuCheckbox.cs | 8 ++++---- osu.Game/Graphics/UserInterface/RoundedSliderBar.cs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs index 28a2eb40c3..4b953718bc 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/Nub.cs @@ -20,16 +20,16 @@ namespace osu.Game.Graphics.UserInterface { public const float HEIGHT = 15; - public const float EXPANDED_SIZE = 50; + public const float DEFAULT_EXPANDED_SIZE = 50; private const float border_width = 3; private readonly Box fill; private readonly Container main; - public Nub() + public Nub(float expandedSize = DEFAULT_EXPANDED_SIZE) { - Size = new Vector2(EXPANDED_SIZE, HEIGHT); + Size = new Vector2(expandedSize, HEIGHT); InternalChildren = new[] { diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index 160105af1a..b7b405a7e8 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -47,7 +47,7 @@ namespace osu.Game.Graphics.UserInterface private Sample sampleChecked; private Sample sampleUnchecked; - public OsuCheckbox(bool nubOnRight = true) + public OsuCheckbox(bool nubOnRight = true, float nubSize = Nub.DEFAULT_EXPANDED_SIZE) { AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; @@ -61,7 +61,7 @@ namespace osu.Game.Graphics.UserInterface AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, }, - Nub = new Nub(), + Nub = new Nub(nubSize), new HoverSounds() }; @@ -70,14 +70,14 @@ namespace osu.Game.Graphics.UserInterface Nub.Anchor = Anchor.CentreRight; Nub.Origin = Anchor.CentreRight; Nub.Margin = new MarginPadding { Right = nub_padding }; - LabelTextFlowContainer.Padding = new MarginPadding { Right = Nub.EXPANDED_SIZE + nub_padding * 2 }; + LabelTextFlowContainer.Padding = new MarginPadding { Right = Nub.DEFAULT_EXPANDED_SIZE + nub_padding * 2 }; } else { Nub.Anchor = Anchor.CentreLeft; Nub.Origin = Anchor.CentreLeft; Nub.Margin = new MarginPadding { Left = nub_padding }; - LabelTextFlowContainer.Padding = new MarginPadding { Left = Nub.EXPANDED_SIZE + nub_padding * 2 }; + LabelTextFlowContainer.Padding = new MarginPadding { Left = Nub.DEFAULT_EXPANDED_SIZE + nub_padding * 2 }; } Nub.Current.BindTo(Current); diff --git a/osu.Game/Graphics/UserInterface/RoundedSliderBar.cs b/osu.Game/Graphics/UserInterface/RoundedSliderBar.cs index a666b83c05..56af23ff10 100644 --- a/osu.Game/Graphics/UserInterface/RoundedSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/RoundedSliderBar.cs @@ -51,7 +51,7 @@ namespace osu.Game.Graphics.UserInterface public RoundedSliderBar() { Height = Nub.HEIGHT; - RangePadding = Nub.EXPANDED_SIZE / 2; + RangePadding = Nub.DEFAULT_EXPANDED_SIZE / 2; Children = new Drawable[] { new Container From 01750dd0914e13b6ce4ee1dda8c878639b7d9972 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jul 2023 14:24:40 +0900 Subject: [PATCH 013/118] Update metrics of checkboxes and backgrounds to match design better --- .../Components/Timeline/TimelineArea.cs | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index 3969a002db..70322bd3e0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -39,11 +39,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline InternalChildren = new Drawable[] { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colourProvider.Background5 - }, new GridContainer { RelativeSizeAxes = Axes.X, @@ -76,24 +71,23 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline }, new FillFlowContainer { - AutoSizeAxes = Axes.Y, - Width = 160, + RelativeSizeAxes = Axes.Both, Padding = new MarginPadding(10), Direction = FillDirection.Vertical, Spacing = new Vector2(0, 4), Children = new[] { - waveformCheckbox = new OsuCheckbox + waveformCheckbox = new OsuCheckbox(nubSize: 30f) { LabelText = EditorStrings.TimelineWaveform, Current = { Value = true }, }, - ticksCheckbox = new OsuCheckbox + ticksCheckbox = new OsuCheckbox(nubSize: 30f) { LabelText = EditorStrings.TimelineTicks, Current = { Value = true }, }, - controlPointsCheckbox = new OsuCheckbox + controlPointsCheckbox = new OsuCheckbox(nubSize: 30f) { LabelText = BeatmapsetsStrings.ShowStatsBpm, Current = { Value = true }, @@ -102,7 +96,21 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } } }, - Timeline = new Timeline(userContent), + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Depth = float.MaxValue, + Colour = colourProvider.Background5 + }, + Timeline = new Timeline(userContent), + } + }, new Container { RelativeSizeAxes = Axes.Both, From 6b222cfafdedf6bb7299e189f30b533aa83b659f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jul 2023 14:29:13 +0900 Subject: [PATCH 014/118] Fix slight misalignment so timeline is now completely centered --- osu.Game/Screens/Edit/EditorScreenWithTimeline.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index a2367dd66c..104d9dd58f 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -13,7 +13,7 @@ namespace osu.Game.Screens.Edit { public abstract partial class EditorScreenWithTimeline : EditorScreen { - private const float padding = 10; + private const float padding = 15; private Container timelineContainer = null!; @@ -74,7 +74,6 @@ namespace osu.Game.Screens.Edit { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Right = 5 }, }, }, }, From 00e9746174b842bcec7cb6ea2c08bd2e55932580 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jul 2023 15:17:24 +0900 Subject: [PATCH 015/118] Implement longer design for timing point piece --- .../Timeline/TimelineControlPointGroup.cs | 2 +- .../Components/Timeline/TopPointPiece.cs | 64 ++++++++++++++----- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointGroup.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointGroup.cs index fc3ef92bf5..c1b6069523 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointGroup.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointGroup.cs @@ -22,7 +22,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline RelativeSizeAxes = Axes.Y; AutoSizeAxes = Axes.X; - Origin = Anchor.TopCentre; + Origin = Anchor.TopLeft; X = (float)group.Time; } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TopPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TopPointPiece.cs index 69fb001a66..243cdc6ddd 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TopPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TopPointPiece.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 osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -10,24 +8,25 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { public partial class TopPointPiece : CompositeDrawable { - private readonly ControlPoint point; + protected readonly ControlPoint Point; - protected OsuSpriteText Label { get; private set; } + protected OsuSpriteText Label { get; private set; } = null!; + + private const float width = 80; public TopPointPiece(ControlPoint point) { - this.point = point; - AutoSizeAxes = Axes.X; + Point = point; + Width = width; Height = 16; - Margin = new MarginPadding(4); - - Masking = true; - CornerRadius = Height / 2; + Margin = new MarginPadding { Vertical = 4 }; Origin = Anchor.TopCentre; Anchor = Anchor.TopCentre; @@ -36,17 +35,52 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline [BackgroundDependencyLoader] private void load(OsuColour colours) { + const float corner_radius = 4; + const float arrow_extension = 3; + const float triangle_portion = 15; + InternalChildren = new Drawable[] { - new Box + // This is a triangle, trust me. + // Doing it this way looks okay. Doing it using Triangle primitive is basically impossible. + new Container { - Colour = point.GetRepresentingColour(colours), - RelativeSizeAxes = Axes.Both, + Colour = Point.GetRepresentingColour(colours), + X = -corner_radius, + Size = new Vector2(triangle_portion * arrow_extension, Height), + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Masking = true, + CornerRadius = Height, + CornerExponent = 1.4f, + Children = new Drawable[] + { + new Box + { + Colour = Color4.White, + RelativeSizeAxes = Axes.Both, + }, + } + }, + new Container + { + RelativeSizeAxes = Axes.Y, + Width = width - triangle_portion, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Colour = Point.GetRepresentingColour(colours), + Masking = true, + CornerRadius = corner_radius, + Child = new Box + { + Colour = Color4.White, + RelativeSizeAxes = Axes.Both, + }, }, Label = new OsuSpriteText { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, Padding = new MarginPadding(3), Font = OsuFont.Default.With(size: 14, weight: FontWeight.SemiBold), Colour = colours.B5, From 57abb15724e537bee9a97ffdbd810b632b675671 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jul 2023 15:58:53 +0900 Subject: [PATCH 016/118] Update design of timeline centre marker and adjust surrounding paddings --- .../Components/Timeline/CentreMarker.cs | 20 +++++++------------ .../Components/Timeline/TimelineArea.cs | 20 +++++++++++++------ .../Screens/Edit/EditorScreenWithTimeline.cs | 4 ++-- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs index aee3cffbfd..74786cc0c9 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs @@ -12,17 +12,17 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { public partial class CentreMarker : CompositeDrawable { - private const float triangle_width = 15; - private const float triangle_height = 10; - private const float bar_width = 2; + private const float triangle_width = 8; + + private const float bar_width = 1.6f; public CentreMarker() { RelativeSizeAxes = Axes.Y; Size = new Vector2(triangle_width, 1); - Anchor = Anchor.Centre; - Origin = Anchor.Centre; + Anchor = Anchor.TopCentre; + Origin = Anchor.TopCentre; InternalChildren = new Drawable[] { @@ -37,22 +37,16 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { Anchor = Anchor.TopCentre, Origin = Anchor.BottomCentre, - Size = new Vector2(triangle_width, triangle_height), + Size = new Vector2(triangle_width, triangle_width * 0.8f), Scale = new Vector2(1, -1) }, - new Triangle - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Size = new Vector2(triangle_width, triangle_height), - } }; } [BackgroundDependencyLoader] private void load(OsuColour colours) { - Colour = colours.RedDark; + Colour = colours.Red1; } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index 70322bd3e0..fb7ce8e423 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; using osu.Game.Overlays; @@ -29,10 +30,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) + private void load(OverlayColourProvider colourProvider, OsuColour colours) { - Masking = true; - OsuCheckbox waveformCheckbox; OsuCheckbox controlPointsCheckbox; OsuCheckbox ticksCheckbox; @@ -51,7 +50,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { new Dimension(GridSizeMode.Absolute, 140), new Dimension(), - new Dimension(GridSizeMode.Absolute, 30), + new Dimension(GridSizeMode.Absolute, 35), new Dimension(GridSizeMode.Absolute, 110), }, Content = new[] @@ -102,6 +101,16 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline AutoSizeAxes = Axes.Y, Children = new Drawable[] { + // the out-of-bounds portion of the centre marker. + new Box + { + Width = 24, + Height = EditorScreenWithTimeline.PADDING, + Depth = float.MaxValue, + Colour = colours.Red1, + Anchor = Anchor.TopCentre, + Origin = Anchor.BottomCentre, + }, new Box { RelativeSizeAxes = Axes.Both, @@ -115,7 +124,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { RelativeSizeAxes = Axes.Both, Name = @"Zoom controls", - Padding = new MarginPadding { Right = 5 }, + Padding = new MarginPadding { Right = 10 }, Children = new Drawable[] { new Box @@ -128,7 +137,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, RelativeSizeAxes = Axes.Both, - Masking = true, Children = new[] { new TimelineButton diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index 104d9dd58f..ea2790b50a 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -13,7 +13,7 @@ namespace osu.Game.Screens.Edit { public abstract partial class EditorScreenWithTimeline : EditorScreen { - private const float padding = 15; + public const float PADDING = 10; private Container timelineContainer = null!; @@ -61,7 +61,7 @@ namespace osu.Game.Screens.Edit Name = "Timeline content", RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Horizontal = padding, Top = padding }, + Padding = new MarginPadding { Horizontal = PADDING, Top = PADDING }, Child = new GridContainer { RelativeSizeAxes = Axes.X, From e6b8cd0c06abce3e02806c570b4316a484c2d817 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jul 2023 16:55:12 +0900 Subject: [PATCH 017/118] Add editor header --- .../Edit/Components/Menus/EditorMenuBar.cs | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs index a911b4e1d8..fa4e52d6a6 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs @@ -3,6 +3,9 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics; @@ -14,19 +17,56 @@ namespace osu.Game.Screens.Edit.Components.Menus { public partial class EditorMenuBar : OsuMenu { + private const float heading_area = 114; + public EditorMenuBar() : base(Direction.Horizontal, true) { RelativeSizeAxes = Axes.X; MaskingContainer.CornerRadius = 0; - ItemsContainer.Padding = new MarginPadding { Left = 100 }; + ItemsContainer.Padding = new MarginPadding { Left = heading_area }; } [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) + private void load(OverlayColourProvider colourProvider, TextureStore textures) { BackgroundColour = colourProvider.Background3; + + TextFlowContainer text; + + AddRangeInternal(new[] + { + new Container + { + RelativeSizeAxes = Axes.Y, + Width = heading_area, + Padding = new MarginPadding(8), + Children = new Drawable[] + { + new Sprite + { + Size = new Vector2(26), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Texture = textures.Get("Icons/Hexacons/editor"), + }, + text = new TextFlowContainer + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + } + } + }, + }); + + text.AddText("osu!", t => t.Font = OsuFont.TorusAlternate); + text.AddText("editor", t => + { + t.Font = OsuFont.TorusAlternate; + t.Colour = colourProvider.Highlight1; + }); } protected override Framework.Graphics.UserInterface.Menu CreateSubMenu() => new SubMenu(); From fe70f2492538533148fd3ee28a2749901736bf43 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jul 2023 17:00:42 +0900 Subject: [PATCH 018/118] Update design of summary timeline current time marker --- .../Timelines/Summary/Parts/MarkerPart.cs | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs index d42c02e03d..ff707407dd 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -73,6 +73,8 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { public MarkerVisualisation() { + const float box_height = 4; + Anchor = Anchor.CentreLeft; Origin = Anchor.Centre; RelativePositionAxes = Axes.X; @@ -80,32 +82,46 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts AutoSizeAxes = Axes.X; InternalChildren = new Drawable[] { + new Box + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Size = new Vector2(14, box_height), + }, new Triangle { Anchor = Anchor.TopCentre, Origin = Anchor.BottomCentre, Scale = new Vector2(1, -1), Size = new Vector2(10, 5), + Y = box_height, }, new Triangle { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, - Size = new Vector2(10, 5) + Size = new Vector2(10, 5), + Y = -box_height, + }, + new Box + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Size = new Vector2(14, box_height), }, new Box { Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Y, - Width = 2, + Width = 1.4f, EdgeSmoothness = new Vector2(1, 0) } }; } [BackgroundDependencyLoader] - private void load(OsuColour colours) => Colour = colours.Red; + private void load(OsuColour colours) => Colour = colours.Red1; } } } From 3888471148e0db66654e7ce4b34886671abe2828 Mon Sep 17 00:00:00 2001 From: NiceAesth Date: Sun, 16 Jul 2023 23:03:21 +0300 Subject: [PATCH 019/118] Add break length and bounds checks --- .../Editing/Checks/CheckBreaksTest.cs | 10 +++ osu.Game/Rulesets/Edit/BeatmapVerifier.cs | 3 + osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs | 84 +++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 osu.Game.Tests/Editing/Checks/CheckBreaksTest.cs create mode 100644 osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs diff --git a/osu.Game.Tests/Editing/Checks/CheckBreaksTest.cs b/osu.Game.Tests/Editing/Checks/CheckBreaksTest.cs new file mode 100644 index 0000000000..664f72c5f8 --- /dev/null +++ b/osu.Game.Tests/Editing/Checks/CheckBreaksTest.cs @@ -0,0 +1,10 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Tests.Editing.Checks +{ + public class CheckBreaksTest + { + + } +} diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index 3988f29e13..4bcf74db45 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -38,6 +38,9 @@ namespace osu.Game.Rulesets.Edit // Timing new CheckPreviewTime(), + + // Events + new CheckBreaks() }; public IEnumerable Run(BeatmapVerifierContext context) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs b/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs new file mode 100644 index 0000000000..12dc5554f4 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs @@ -0,0 +1,84 @@ +// 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 osu.Game.Beatmaps.Timing; +using osu.Game.Rulesets.Edit.Checks.Components; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Edit.Checks +{ + public class CheckBreaks : ICheck + { + // Breaks may be off by 1 ms. + private const int leniency_threshold = 1; + private const double min_start_threshold = 200; + + // Break end time depends on the upcoming object's pre-empt time. + // As things stand, "pre-empt time" is only defined for osu! standard + // This is a generic value representing AR=10 + // Relevant: https://github.com/ppy/osu/issues/14330#issuecomment-1002158551 + private const double min_end_threshold = 450; + public CheckMetadata Metadata => new CheckMetadata(CheckCategory.Events, "Breaks not achievable using the editor"); + + public IEnumerable PossibleTemplates => new IssueTemplate[] + { + new IssueTemplateEarlyStart(this), + new IssueTemplateLateEnd(this), + new IssueTemplateTooShort(this) + }; + + public IEnumerable Run(BeatmapVerifierContext context) + { + foreach (var breakPeriod in context.Beatmap.Breaks) + { + if (breakPeriod.Duration < BreakPeriod.MIN_BREAK_DURATION) + yield return new IssueTemplateTooShort(this).Create(breakPeriod.StartTime); + } + + foreach (var hitObject in context.Beatmap.HitObjects) + { + foreach (var breakPeriod in context.Beatmap.Breaks) + { + double diffStart = breakPeriod.StartTime - hitObject.GetEndTime(); + double diffEnd = hitObject.StartTime - breakPeriod.EndTime; + + if (diffStart < min_start_threshold - leniency_threshold && diffStart > 0) + yield return new IssueTemplateEarlyStart(this).Create(breakPeriod.StartTime, min_start_threshold - diffStart); + else if (diffEnd < min_end_threshold - leniency_threshold && diffEnd > 0) + yield return new IssueTemplateLateEnd(this).Create(breakPeriod.StartTime, min_end_threshold - diffEnd); + } + } + } + + public class IssueTemplateEarlyStart : IssueTemplate + { + public IssueTemplateEarlyStart(ICheck check) + : base(check, IssueType.Problem, "Break starts {0} ms early.") + { + } + + public Issue Create(double startTime, double diff) => new Issue(startTime, this, (int)diff); + } + + public class IssueTemplateLateEnd : IssueTemplate + { + public IssueTemplateLateEnd(ICheck check) + : base(check, IssueType.Problem, "Break ends {0} ms late.") + { + } + + public Issue Create(double startTime, double diff) => new Issue(startTime, this, (int)diff); + } + + public class IssueTemplateTooShort : IssueTemplate + { + public IssueTemplateTooShort(ICheck check) + : base(check, IssueType.Warning, "Break is non-functional due to being less than 650ms.") + { + } + + public Issue Create(double startTime) => new Issue(startTime, this); + } + } +} From b3974b34e7cd519d6576b0f01c8788976789f35c Mon Sep 17 00:00:00 2001 From: NiceAesth Date: Sun, 16 Jul 2023 23:03:30 +0300 Subject: [PATCH 020/118] Test break checks --- .../Editing/Checks/CheckBreaksTest.cs | 105 +++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Editing/Checks/CheckBreaksTest.cs b/osu.Game.Tests/Editing/Checks/CheckBreaksTest.cs index 664f72c5f8..39e414827a 100644 --- a/osu.Game.Tests/Editing/Checks/CheckBreaksTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckBreaksTest.cs @@ -1,10 +1,113 @@ // 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 NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Timing; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Checks; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Tests.Beatmaps; + namespace osu.Game.Tests.Editing.Checks { public class CheckBreaksTest { - + private CheckBreaks check = null!; + + [SetUp] + public void Setup() + { + check = new CheckBreaks(); + } + + [Test] + public void TestBreakTooShort() + { + var beatmap = new Beatmap + { + Breaks = new List + { + new BreakPeriod(0, 649) + } + }; + var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckBreaks.IssueTemplateTooShort); + } + + [Test] + public void TestBreakStartsEarly() + { + var beatmap = new Beatmap + { + HitObjects = + { + new HitCircle { StartTime = 0 }, + new HitCircle { StartTime = 1_200 } + }, + Breaks = new List + { + new BreakPeriod(100, 751) + } + }; + var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckBreaks.IssueTemplateEarlyStart); + } + + [Test] + public void TestBreakEndsLate() + { + var beatmap = new Beatmap + { + HitObjects = + { + new HitCircle { StartTime = 0 }, + new HitCircle { StartTime = 1_298 } + }, + Breaks = new List + { + new BreakPeriod(200, 850) + } + }; + var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckBreaks.IssueTemplateLateEnd); + } + + [Test] + public void TestBreaksCorrect() + { + var beatmap = new Beatmap + { + HitObjects = + { + new HitCircle { StartTime = 0 }, + new HitCircle { StartTime = 1_300 } + }, + Breaks = new List + { + new BreakPeriod(200, 850) + } + }; + var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + + var issues = check.Run(context).ToList(); + + Assert.That(issues, Is.Empty); + } } } From ff529d9df7d66dc3191c6f75b3691df451c7aeb9 Mon Sep 17 00:00:00 2001 From: NiceAesth Date: Mon, 17 Jul 2023 20:48:53 +0300 Subject: [PATCH 021/118] Rename variables, fix check message formatting --- osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs b/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs index 12dc5554f4..54dfb557fe 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Edit.Checks { // Breaks may be off by 1 ms. private const int leniency_threshold = 1; - private const double min_start_threshold = 200; + private const double minimum_gap_before_break = 200; // Break end time depends on the upcoming object's pre-empt time. // As things stand, "pre-empt time" is only defined for osu! standard @@ -40,13 +40,13 @@ namespace osu.Game.Rulesets.Edit.Checks { foreach (var breakPeriod in context.Beatmap.Breaks) { - double diffStart = breakPeriod.StartTime - hitObject.GetEndTime(); - double diffEnd = hitObject.StartTime - breakPeriod.EndTime; + double gapBeforeBreak = breakPeriod.StartTime - hitObject.GetEndTime(); + double gapAfterBreak = hitObject.StartTime - breakPeriod.EndTime; - if (diffStart < min_start_threshold - leniency_threshold && diffStart > 0) - yield return new IssueTemplateEarlyStart(this).Create(breakPeriod.StartTime, min_start_threshold - diffStart); - else if (diffEnd < min_end_threshold - leniency_threshold && diffEnd > 0) - yield return new IssueTemplateLateEnd(this).Create(breakPeriod.StartTime, min_end_threshold - diffEnd); + if (gapBeforeBreak < minimum_gap_before_break - leniency_threshold && gapBeforeBreak > 0) + yield return new IssueTemplateEarlyStart(this).Create(breakPeriod.StartTime, minimum_gap_before_break - gapBeforeBreak); + else if (gapAfterBreak < min_end_threshold - leniency_threshold && gapAfterBreak > 0) + yield return new IssueTemplateLateEnd(this).Create(breakPeriod.StartTime, min_end_threshold - gapAfterBreak); } } } @@ -74,11 +74,11 @@ namespace osu.Game.Rulesets.Edit.Checks public class IssueTemplateTooShort : IssueTemplate { public IssueTemplateTooShort(ICheck check) - : base(check, IssueType.Warning, "Break is non-functional due to being less than 650ms.") + : base(check, IssueType.Warning, "Break is non-functional due to being less than {0} ms.") { } - public Issue Create(double startTime) => new Issue(startTime, this); + public Issue Create(double startTime) => new Issue(startTime, this, BreakPeriod.MIN_BREAK_DURATION); } } } From c02684d985e426b8dab1bf175204026cff2845e3 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 18 Jul 2023 12:18:43 +0200 Subject: [PATCH 022/118] truncate hit object end time --- osu.Game/Database/LegacyBeatmapExporter.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Database/LegacyBeatmapExporter.cs b/osu.Game/Database/LegacyBeatmapExporter.cs index 42d8a72073..3b2282c234 100644 --- a/osu.Game/Database/LegacyBeatmapExporter.cs +++ b/osu.Game/Database/LegacyBeatmapExporter.cs @@ -60,6 +60,9 @@ namespace osu.Game.Database { hitObject.StartTime = Math.Floor(hitObject.StartTime); + if (hitObject is IHasDuration hasDuration && hitObject is not IHasPath) + hasDuration.Duration = Math.Floor(hasDuration.Duration); + if (hitObject is not IHasPath hasPath || BezierConverter.CountSegments(hasPath.Path.ControlPoints) <= 1) continue; var newControlPoints = BezierConverter.ConvertToModernBezier(hasPath.Path.ControlPoints); From bcdf5310390021d2b5b4996c6d88293846a12004 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 18 Jul 2023 12:28:35 +0200 Subject: [PATCH 023/118] truncate end time before start time --- osu.Game/Database/LegacyBeatmapExporter.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/LegacyBeatmapExporter.cs b/osu.Game/Database/LegacyBeatmapExporter.cs index 3b2282c234..983d25a25a 100644 --- a/osu.Game/Database/LegacyBeatmapExporter.cs +++ b/osu.Game/Database/LegacyBeatmapExporter.cs @@ -58,10 +58,11 @@ namespace osu.Game.Database foreach (var hitObject in beatmapContent.HitObjects) { - hitObject.StartTime = Math.Floor(hitObject.StartTime); - + // Truncate end time before truncating start time because end time is dependent on start time if (hitObject is IHasDuration hasDuration && hitObject is not IHasPath) - hasDuration.Duration = Math.Floor(hasDuration.Duration); + hasDuration.Duration = Math.Floor(hasDuration.EndTime) - Math.Floor(hitObject.StartTime); + + hitObject.StartTime = Math.Floor(hitObject.StartTime); if (hitObject is not IHasPath hasPath || BezierConverter.CountSegments(hasPath.Path.ControlPoints) <= 1) continue; From 395dd23966d0ae3fb15b13b8e0b8c6628e1a310b Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 18 Jul 2023 12:37:37 +0200 Subject: [PATCH 024/118] Put 'Export package' and 'Export legacy package' in one nested menu --- osu.Game/Localisation/EditorStrings.cs | 9 +++++++-- osu.Game/Screens/Edit/Editor.cs | 14 ++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/osu.Game/Localisation/EditorStrings.cs b/osu.Game/Localisation/EditorStrings.cs index 70392d5c83..07b4dddc05 100644 --- a/osu.Game/Localisation/EditorStrings.cs +++ b/osu.Game/Localisation/EditorStrings.cs @@ -40,9 +40,14 @@ namespace osu.Game.Localisation public static LocalisableString ExportPackage => new TranslatableString(getKey(@"export_package"), @"Export package"); /// - /// "Export legacy package" + /// "Legacy format (.osz)" /// - public static LocalisableString ExportLegacyPackage => new TranslatableString(getKey(@"export_legacy_package"), @"Export legacy package"); + public static LocalisableString ExportLegacyFormat => new TranslatableString(getKey(@"export_legacy_format"), @"Legacy format (.osz)"); + + /// + /// "New format (.olz)" + /// + public static LocalisableString ExportNewFormat => new TranslatableString(getKey(@"export_new_format"), @"New format (.olz)"); /// /// "Create new difficulty" diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index a48c57f991..16cd7768fa 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -998,8 +998,7 @@ namespace osu.Game.Screens.Edit private List createFileMenuItems() => new List { new EditorMenuItem(WebCommonStrings.ButtonsSave, MenuItemType.Standard, () => Save()), - new EditorMenuItem(EditorStrings.ExportPackage, MenuItemType.Standard, exportBeatmap) { Action = { Disabled = !RuntimeInfo.IsDesktop } }, - new EditorMenuItem(EditorStrings.ExportLegacyPackage, MenuItemType.Standard, exportLegacyBeatmap) { Action = { Disabled = !RuntimeInfo.IsDesktop } }, + createExportPackageMenu(), new EditorMenuItemSpacer(), createDifficultyCreationMenu(), createDifficultySwitchMenu(), @@ -1009,6 +1008,17 @@ namespace osu.Game.Screens.Edit new EditorMenuItem(CommonStrings.Exit, MenuItemType.Standard, this.Exit) }; + private EditorMenuItem createExportPackageMenu() + { + var exportItems = new List + { + new EditorMenuItem(EditorStrings.ExportNewFormat, MenuItemType.Standard, exportBeatmap) { Action = { Disabled = !RuntimeInfo.IsDesktop } }, + new EditorMenuItem(EditorStrings.ExportLegacyFormat, MenuItemType.Standard, exportLegacyBeatmap) { Action = { Disabled = !RuntimeInfo.IsDesktop } }, + }; + + return new EditorMenuItem(EditorStrings.ExportPackage) { Items = exportItems }; + } + private void exportBeatmap() { Save(); From 63dd8bd991835344cbbf3e0c88b8f4b749ea1029 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 18 Jul 2023 12:40:48 +0200 Subject: [PATCH 025/118] use base.GetFileContents to get file stream --- osu.Game/Database/LegacyBeatmapExporter.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/LegacyBeatmapExporter.cs b/osu.Game/Database/LegacyBeatmapExporter.cs index 983d25a25a..b90ea73244 100644 --- a/osu.Game/Database/LegacyBeatmapExporter.cs +++ b/osu.Game/Database/LegacyBeatmapExporter.cs @@ -8,7 +8,6 @@ using System.Text; using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; -using osu.Game.Extensions; using osu.Game.IO; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -36,7 +35,7 @@ namespace osu.Game.Database return base.GetFileContents(model, file); // Read the beatmap contents and skin - using var contentStream = UserFileStorage.GetStream(file.File.GetStoragePath()); + using var contentStream = base.GetFileContents(model, file); if (contentStream == null) return null; @@ -44,7 +43,7 @@ namespace osu.Game.Database using var contentStreamReader = new LineBufferedReader(contentStream); var beatmapContent = new LegacyBeatmapDecoder().Decode(contentStreamReader); - using var skinStream = UserFileStorage.GetStream(file.File.GetStoragePath()); + using var skinStream = base.GetFileContents(model, file); using var skinStreamReader = new LineBufferedReader(contentStream); var beatmapSkin = new LegacySkin(new SkinInfo(), null!) { From e7a9175aeae253a515c8a8ab0d40985853de28ec Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 18 Jul 2023 13:08:05 +0200 Subject: [PATCH 026/118] fix skin using wrong stream --- osu.Game/Database/LegacyBeatmapExporter.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyBeatmapExporter.cs b/osu.Game/Database/LegacyBeatmapExporter.cs index b90ea73244..e054652efa 100644 --- a/osu.Game/Database/LegacyBeatmapExporter.cs +++ b/osu.Game/Database/LegacyBeatmapExporter.cs @@ -44,7 +44,11 @@ namespace osu.Game.Database var beatmapContent = new LegacyBeatmapDecoder().Decode(contentStreamReader); using var skinStream = base.GetFileContents(model, file); - using var skinStreamReader = new LineBufferedReader(contentStream); + + if (skinStream == null) + return null; + + using var skinStreamReader = new LineBufferedReader(skinStream); var beatmapSkin = new LegacySkin(new SkinInfo(), null!) { Configuration = new LegacySkinDecoder().Decode(skinStreamReader) From b9a66ad7b346aa26d49a875a522deb8932b8dca9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 19 Jul 2023 14:58:45 +0900 Subject: [PATCH 027/118] Add test coverage of incorrect selection behaviour --- .../Editor/TestSceneOsuComposerSelection.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuComposerSelection.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuComposerSelection.cs index 8641663ce8..623cefff6b 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuComposerSelection.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuComposerSelection.cs @@ -25,6 +25,35 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor { protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false); + [Test] + public void TestSelectAfterFadedOut() + { + var slider = new Slider + { + StartTime = 0, + Position = new Vector2(100, 100), + Path = new SliderPath + { + ControlPoints = + { + new PathControlPoint(), + new PathControlPoint(new Vector2(100)) + } + } + }; + AddStep("add slider", () => EditorBeatmap.Add(slider)); + + moveMouseToObject(() => slider); + + AddStep("seek after end", () => EditorClock.Seek(750)); + AddStep("left click", () => InputManager.Click(MouseButton.Left)); + AddAssert("slider not selected", () => EditorBeatmap.SelectedHitObjects.Count == 0); + + AddStep("seek to visible", () => EditorClock.Seek(650)); + AddStep("left click", () => InputManager.Click(MouseButton.Left)); + AddUntilStep("slider selected", () => EditorBeatmap.SelectedHitObjects.Single() == slider); + } + [Test] public void TestContextMenuShownCorrectlyForSelectedSlider() { From 4a6a5b174a3255b8479edb2ab4683fd779040925 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 19 Jul 2023 14:52:31 +0900 Subject: [PATCH 028/118] Fix editor blueprints being selectable for too long when hit markers are enabled Addresses https://github.com/ppy/osu/discussions/24163. --- .../Edit/Blueprints/OsuSelectionBlueprint.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs index bdd19f9106..178b809d8b 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs @@ -22,7 +22,16 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints protected override bool AlwaysShowWhenSelected => true; protected override bool ShouldBeAlive => base.ShouldBeAlive - || (DrawableObject is not DrawableSpinner && ShowHitMarkers.Value && editorClock.CurrentTime >= Item.StartTime && editorClock.CurrentTime - Item.GetEndTime() < HitCircleOverlapMarker.FADE_OUT_EXTENSION); + || (DrawableObject is not DrawableSpinner && ShowHitMarkers.Value && editorClock.CurrentTime >= Item.StartTime + && editorClock.CurrentTime - Item.GetEndTime() < HitCircleOverlapMarker.FADE_OUT_EXTENSION); + + public override bool HandlePositionalInput => + // Bypass fade out extension from hit markers for input handling purposes. + // This is to match stable, where even when the afterimage hit markers are still visible, objects are not selectable. + // + // Note that we are intentionally overriding HandlePositionalInput here and not ReceivePositionalInputAt + // as individual blueprint implementations override that. + base.ShouldBeAlive; protected OsuSelectionBlueprint(T hitObject) : base(hitObject) From 871056790b4bfb56fb5d5fad4e3e224673b53987 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 19 Jul 2023 15:01:20 +0900 Subject: [PATCH 029/118] Mark editor tile as non-localisable --- osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs index fa4e52d6a6..e958849bb0 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs @@ -61,8 +61,8 @@ namespace osu.Game.Screens.Edit.Components.Menus }, }); - text.AddText("osu!", t => t.Font = OsuFont.TorusAlternate); - text.AddText("editor", t => + text.AddText(@"osu!", t => t.Font = OsuFont.TorusAlternate); + text.AddText(@"editor", t => { t.Font = OsuFont.TorusAlternate; t.Colour = colourProvider.Highlight1; From 55a41b0887ff6e7d78502f40dc61204eda4c0306 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 19 Jul 2023 15:13:20 +0900 Subject: [PATCH 030/118] Fix overlap between header text and menu items --- osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs index e958849bb0..b9385ff0c3 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs @@ -25,7 +25,10 @@ namespace osu.Game.Screens.Edit.Components.Menus RelativeSizeAxes = Axes.X; MaskingContainer.CornerRadius = 0; - ItemsContainer.Padding = new MarginPadding { Left = heading_area }; + ItemsContainer.Padding = new MarginPadding(); + + ContentContainer.Margin = new MarginPadding { Left = heading_area }; + ContentContainer.Masking = true; } [BackgroundDependencyLoader] From e283845b7144d1e16039841af85f3441a3be2a26 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 19 Jul 2023 17:45:07 +0900 Subject: [PATCH 031/118] Adjust legacy skin elements to better align with skinning expectations --- osu.Game/Skinning/LegacyAccuracyCounter.cs | 4 ++-- osu.Game/Skinning/LegacyScoreCounter.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Skinning/LegacyAccuracyCounter.cs b/osu.Game/Skinning/LegacyAccuracyCounter.cs index c99cdba91c..326257c25f 100644 --- a/osu.Game/Skinning/LegacyAccuracyCounter.cs +++ b/osu.Game/Skinning/LegacyAccuracyCounter.cs @@ -17,8 +17,8 @@ namespace osu.Game.Skinning Anchor = Anchor.TopRight; Origin = Anchor.TopRight; - Scale = new Vector2(0.6f); - Margin = new MarginPadding(10); + Scale = new Vector2(0.6f * 0.96f); + Margin = new MarginPadding { Vertical = 9, Horizontal = 17 }; } protected sealed override OsuSpriteText CreateSpriteText() => new LegacySpriteText(LegacyFont.Score) diff --git a/osu.Game/Skinning/LegacyScoreCounter.cs b/osu.Game/Skinning/LegacyScoreCounter.cs index d8ee6b21de..d238369be1 100644 --- a/osu.Game/Skinning/LegacyScoreCounter.cs +++ b/osu.Game/Skinning/LegacyScoreCounter.cs @@ -21,7 +21,7 @@ namespace osu.Game.Skinning Origin = Anchor.TopRight; Scale = new Vector2(0.96f); - Margin = new MarginPadding(10); + Margin = new MarginPadding { Horizontal = 10 }; } protected sealed override OsuSpriteText CreateSpriteText() => new LegacySpriteText(LegacyFont.Score) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 79f13686e8..00c18bef3d 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -368,7 +368,7 @@ namespace osu.Game.Skinning { songProgress.Anchor = Anchor.TopRight; songProgress.Origin = Anchor.CentreRight; - songProgress.X = -accuracy.ScreenSpaceDeltaToParentSpace(accuracy.ScreenSpaceDrawQuad.Size).X - 10; + songProgress.X = -accuracy.ScreenSpaceDeltaToParentSpace(accuracy.ScreenSpaceDrawQuad.Size).X - 20; songProgress.Y = container.ToLocalSpace(accuracy.ScreenSpaceDrawQuad.TopLeft).Y + (accuracy.ScreenSpaceDeltaToParentSpace(accuracy.ScreenSpaceDrawQuad.Size).Y / 2); } From 61ff3d08d45f2667215c46d1412cd9d3f02e3d5a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 19 Jul 2023 17:48:19 +0900 Subject: [PATCH 032/118] Change depth of `LegacySongProgress` to allow "skinning" via health bar background --- osu.Game/Skinning/LegacySkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 00c18bef3d..b72a757e6c 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -397,8 +397,8 @@ namespace osu.Game.Skinning new LegacyComboCounter(), new LegacyScoreCounter(), new LegacyAccuracyCounter(), - new LegacyHealthDisplay(), new LegacySongProgress(), + new LegacyHealthDisplay(), new BarHitErrorMeter(), new DefaultKeyCounterDisplay() } From fa29c25097a178ad04a08c5c8ab26a3c918e847e Mon Sep 17 00:00:00 2001 From: NiceAesth Date: Thu, 20 Jul 2023 00:32:35 +0300 Subject: [PATCH 033/118] Change check to use binary search --- osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs | 57 ++++++++++++++++---- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs b/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs index 54dfb557fe..44d2c18dad 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs @@ -34,23 +34,62 @@ namespace osu.Game.Rulesets.Edit.Checks { if (breakPeriod.Duration < BreakPeriod.MIN_BREAK_DURATION) yield return new IssueTemplateTooShort(this).Create(breakPeriod.StartTime); - } - foreach (var hitObject in context.Beatmap.HitObjects) - { - foreach (var breakPeriod in context.Beatmap.Breaks) + var previousObject = getPreviousObject(breakPeriod.StartTime, context.Beatmap.HitObjects); + var nextObject = getNextObject(breakPeriod.EndTime, context.Beatmap.HitObjects); + + if (previousObject != null) { - double gapBeforeBreak = breakPeriod.StartTime - hitObject.GetEndTime(); - double gapAfterBreak = hitObject.StartTime - breakPeriod.EndTime; - - if (gapBeforeBreak < minimum_gap_before_break - leniency_threshold && gapBeforeBreak > 0) + double gapBeforeBreak = breakPeriod.StartTime - previousObject.GetEndTime(); + if (gapBeforeBreak < minimum_gap_before_break - leniency_threshold) yield return new IssueTemplateEarlyStart(this).Create(breakPeriod.StartTime, minimum_gap_before_break - gapBeforeBreak); - else if (gapAfterBreak < min_end_threshold - leniency_threshold && gapAfterBreak > 0) + } + + if (nextObject != null) + { + double gapAfterBreak = nextObject.StartTime - breakPeriod.EndTime; + if (gapAfterBreak < min_end_threshold - leniency_threshold) yield return new IssueTemplateLateEnd(this).Create(breakPeriod.StartTime, min_end_threshold - gapAfterBreak); } } } + private HitObject? getPreviousObject(double time, IReadOnlyList hitObjects) + { + int left = 0; + int right = hitObjects.Count - 1; + + while (left <= right) + { + int mid = left + (right - left) / 2; + + if (hitObjects[mid].GetEndTime() < time) + left = mid + 1; + else + right = mid - 1; + } + + return right >= 0 ? hitObjects[right] : null; + } + + private HitObject? getNextObject(double time, IReadOnlyList hitObjects) + { + int left = 0; + int right = hitObjects.Count - 1; + + while (left <= right) + { + int mid = left + (right - left) / 2; + + if (hitObjects[mid].StartTime <= time) + left = mid + 1; + else + right = mid - 1; + } + + return left < hitObjects.Count ? hitObjects[left] : null; + } + public class IssueTemplateEarlyStart : IssueTemplate { public IssueTemplateEarlyStart(ICheck check) From ce78bb549f2e5d9c09bf91402f55a7d26555f191 Mon Sep 17 00:00:00 2001 From: NiceAesth Date: Thu, 20 Jul 2023 00:32:54 +0300 Subject: [PATCH 034/118] Add test for multiple too early objects in break --- .../Editing/Checks/CheckBreaksTest.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/osu.Game.Tests/Editing/Checks/CheckBreaksTest.cs b/osu.Game.Tests/Editing/Checks/CheckBreaksTest.cs index 39e414827a..aaa536f9b9 100644 --- a/osu.Game.Tests/Editing/Checks/CheckBreaksTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckBreaksTest.cs @@ -88,6 +88,30 @@ namespace osu.Game.Tests.Editing.Checks Assert.That(issues.Single().Template is CheckBreaks.IssueTemplateLateEnd); } + [Test] + public void TestBreakMultipleObjectsEarly() + { + var beatmap = new Beatmap + { + HitObjects = + { + new HitCircle { StartTime = 0 }, + new HitCircle { StartTime = 1_297 }, + new HitCircle { StartTime = 1_298 } + }, + Breaks = new List + { + new BreakPeriod(200, 850) + } + }; + var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckBreaks.IssueTemplateLateEnd); + } + [Test] public void TestBreaksCorrect() { From 970ea50269f8b248b69aa458a4baa0aa41e7e45b Mon Sep 17 00:00:00 2001 From: chayleaf Date: Thu, 20 Jul 2023 20:53:27 +0700 Subject: [PATCH 035/118] fix alive hitobjects blocking hits in taiko with hd --- .../Mods/TestSceneTaikoModHidden.cs | 55 +++++++++++++++++-- .../Mods/TaikoModHidden.cs | 6 ++ 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModHidden.cs b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModHidden.cs index edc53429b1..6e6be26e43 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModHidden.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModHidden.cs @@ -1,24 +1,71 @@ // 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 System.Linq; using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Taiko.Mods; +using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Tests.Mods { public partial class TestSceneTaikoModHidden : TaikoModTestScene { + private Func checkAllMaxResultJudgements(int count) => () + => Player.ScoreProcessor.JudgedHits >= count + && Player.Results.All(result => result.Type == result.Judgement.MaxResult); + [Test] public void TestDefaultBeatmapTest() => CreateModTest(new ModTestData { Mod = new TaikoModHidden(), Autoplay = true, - PassCondition = checkSomeAutoplayHits + PassCondition = checkAllMaxResultJudgements(4), }); - private bool checkSomeAutoplayHits() - => Player.ScoreProcessor.JudgedHits >= 4 - && Player.Results.All(result => result.Type == result.Judgement.MaxResult); + [Test] + public void TestHitTwoNotesWithinShortPeriod() + { + const double hit_time = 1; + + var beatmap = new Beatmap + { + HitObjects = new List + { + new Hit + { + Type = HitType.Rim, + StartTime = hit_time, + }, + new Hit + { + Type = HitType.Centre, + StartTime = hit_time * 2, + }, + }, + BeatmapInfo = + { + Difficulty = new BeatmapDifficulty + { + SliderTickRate = 4, + OverallDifficulty = 0, + }, + Ruleset = new TaikoRuleset().RulesetInfo + }, + }; + + beatmap.ControlPointInfo.Add(0, new EffectControlPoint { ScrollSpeed = 0.1f }); + + CreateModTest(new ModTestData + { + Mod = new TaikoModHidden(), + Autoplay = true, + PassCondition = checkAllMaxResultJudgements(2), + Beatmap = beatmap, + }); + } } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs index 2c3b4a8d18..ad17955f75 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs @@ -57,6 +57,12 @@ namespace osu.Game.Rulesets.Taiko.Mods { hitObject.FadeOut(duration); + // Keep updating the object even after it stopped being visible. + // This is required because of the custom logic in DrawableHit's Update method. + // Specifically, pressHandledThisFrame wasn't reset, which caused further hits + // within the object's lifetime to be rejected. + hitObject.AlwaysPresent = true; + // DrawableHitObject sets LifetimeEnd to LatestTransformEndTime if it isn't manually changed. // in order for the object to not be killed before its actual end time (as the latest transform ends earlier), set lifetime end explicitly. hitObject.LifetimeEnd = state == ArmedState.Idle || !hitObject.AllJudged From a16d7e6cc5b70251b0df7beac54dbd6b077eb950 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Jul 2023 18:34:08 +0900 Subject: [PATCH 036/118] Add more padding around editor screen content --- .../Screens/Editors/TournamentEditorScreen.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs index 0fb6c1367b..8d221b1818 100644 --- a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.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.Collections.Specialized; using System.Diagnostics; using System.Linq; @@ -27,17 +25,18 @@ namespace osu.Game.Tournament.Screens.Editors { protected abstract BindableList Storage { get; } - private FillFlowContainer flow; + private FillFlowContainer flow = null!; - [Resolved(canBeNull: true)] - private TournamentSceneManager sceneManager { get; set; } + [Resolved] + private TournamentSceneManager? sceneManager { get; set; } - protected ControlPanel ControlPanel; + protected ControlPanel ControlPanel = null!; - private readonly TournamentScreen parentScreen; - private BackButton backButton; + private readonly TournamentScreen? parentScreen; - protected TournamentEditorScreen(TournamentScreen parentScreen = null) + private BackButton backButton = null!; + + protected TournamentEditorScreen(TournamentScreen? parentScreen = null) { this.parentScreen = parentScreen; } @@ -63,6 +62,7 @@ namespace osu.Game.Tournament.Screens.Editors RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Spacing = new Vector2(20), + Padding = new MarginPadding(20), }, }, ControlPanel = new ControlPanel From 0284fa1fc187ae9e5bc47d066258eec941170f61 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Jul 2023 19:02:36 +0900 Subject: [PATCH 037/118] Tidy up `TeamEditorScreen` --- .../Screens/Editors/TeamEditorScreen.cs | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index 93fbfba0e3..6684ccd24b 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -15,6 +15,10 @@ using osu.Game.Online.API; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; +using osu.Game.Tournament.Screens.Drawings.Components; +using osu.Game.Tournament.Screens.Gameplay.Components; +using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Screens.TeamIntro; using osu.Game.Users; using osuTK; @@ -59,8 +63,6 @@ namespace osu.Game.Tournament.Screens.Editors { public TournamentTeam Model { get; } - private readonly Container drawableContainer; - [Resolved] private TournamentSceneManager? sceneManager { get; set; } @@ -74,6 +76,9 @@ namespace osu.Game.Tournament.Screens.Editors Masking = true; CornerRadius = 10; + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + PlayerEditor playerEditor = new PlayerEditor(Model) { Width = 0.95f @@ -86,10 +91,9 @@ namespace osu.Game.Tournament.Screens.Editors Colour = OsuColour.Gray(0.1f), RelativeSizeAxes = Axes.Both, }, - drawableContainer = new Container + new GroupTeam(team) { - Size = new Vector2(100, 50), - Margin = new MarginPadding(10), + Margin = new MarginPadding(32), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, }, @@ -134,14 +138,14 @@ namespace osu.Game.Tournament.Screens.Editors }, new SettingsButton { - Width = 0.11f, + Width = 0.2f, Margin = new MarginPadding(10), Text = "Add player", Action = () => playerEditor.CreateNew() }, new DangerousSettingsButton { - Width = 0.11f, + Width = 0.2f, Text = "Delete Team", Margin = new MarginPadding(10), Action = () => @@ -164,16 +168,6 @@ namespace osu.Game.Tournament.Screens.Editors } }, }; - - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - Model.FlagName.BindValueChanged(updateDrawable, true); - } - - private void updateDrawable(ValueChangedEvent flag) - { - drawableContainer.Child = new DrawableTeamFlag(Model); } public partial class PlayerEditor : CompositeDrawable @@ -216,7 +210,7 @@ namespace osu.Game.Tournament.Screens.Editors private readonly Bindable playerId = new Bindable(); - private readonly Container drawableContainer; + private readonly Container userPanelContainer; public PlayerRow(TournamentTeam team, TournamentUser user) { @@ -228,7 +222,7 @@ namespace osu.Game.Tournament.Screens.Editors AutoSizeAxes = Axes.Y; Masking = true; - CornerRadius = 5; + CornerRadius = 10; InternalChildren = new Drawable[] { @@ -240,10 +234,11 @@ namespace osu.Game.Tournament.Screens.Editors new FillFlowContainer { Margin = new MarginPadding(5), - Padding = new MarginPadding { Right = 160 }, + Padding = new MarginPadding { Right = 60 }, Spacing = new Vector2(5), Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Children = new Drawable[] { new SettingsNumberBox @@ -253,9 +248,10 @@ namespace osu.Game.Tournament.Screens.Editors Width = 200, Current = playerId, }, - drawableContainer = new Container + userPanelContainer = new Container { - Size = new Vector2(100, 70), + Width = 500, + RelativeSizeAxes = Axes.Y, }, } }, @@ -298,7 +294,11 @@ namespace osu.Game.Tournament.Screens.Editors private void updatePanel() => Scheduler.AddOnce(() => { - drawableContainer.Child = new UserGridPanel(user.ToAPIUser()) { Width = 300 }; + userPanelContainer.Child = new UserListPanel(user.ToAPIUser()) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; }); } } From b712b195399485038a950f79deda980088e4dc9e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Jul 2023 19:08:09 +0900 Subject: [PATCH 038/118] Update all tournament buttons to use new design --- .../Screens/Editors/TeamEditorScreen.cs | 4 ---- .../Screens/Editors/TournamentEditorScreen.cs | 6 +++--- osu.Game.Tournament/TournamentSceneManager.cs | 3 +-- osu.Game.Tournament/TourneyButton.cs | 11 +++++++---- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index 6684ccd24b..a8afcece37 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -13,12 +13,8 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Online.API; using osu.Game.Overlays.Settings; -using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Drawings.Components; -using osu.Game.Tournament.Screens.Gameplay.Components; -using osu.Game.Tournament.Screens.Ladder.Components; -using osu.Game.Tournament.Screens.TeamIntro; using osu.Game.Users; using osuTK; diff --git a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs index 8d221b1818..8a90777300 100644 --- a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs @@ -13,7 +13,6 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; using osuTK; @@ -42,7 +41,7 @@ namespace osu.Game.Tournament.Screens.Editors } [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colours) { AddRangeInternal(new Drawable[] { @@ -75,9 +74,10 @@ namespace osu.Game.Tournament.Screens.Editors Text = "Add new", Action = () => Storage.Add(new TModel()) }, - new DangerousSettingsButton + new TourneyButton { RelativeSizeAxes = Axes.X, + BackgroundColour = colours.Pink3, Text = "Clear all", Action = Storage.Clear }, diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index abfe69b97b..216743e4a2 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -252,14 +252,13 @@ namespace osu.Game.Tournament if (shortcutKey != null) { - Add(new Container + Add(new CircularContainer { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Size = new Vector2(24), Margin = new MarginPadding(5), Masking = true, - CornerRadius = 4, Alpha = 0.5f, Blending = BlendingParameters.Additive, Children = new Drawable[] diff --git a/osu.Game.Tournament/TourneyButton.cs b/osu.Game.Tournament/TourneyButton.cs index 67426c1d58..b874c5c37c 100644 --- a/osu.Game.Tournament/TourneyButton.cs +++ b/osu.Game.Tournament/TourneyButton.cs @@ -1,18 +1,21 @@ // 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.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Settings; namespace osu.Game.Tournament { - public partial class TourneyButton : OsuButton + public partial class TourneyButton : SettingsButton { public new Box Background => base.Background; - public TourneyButton() - : base(null) + [BackgroundDependencyLoader] + private void load() { + Padding = new MarginPadding(); } } } From 427045fdaf6aee48a40229ffc814b1c3785e4897 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Jul 2023 19:28:43 +0900 Subject: [PATCH 039/118] Further layout improvements to `TeamEditorScreen` --- .../Screens/Editors/TeamEditorScreen.cs | 70 ++++++++++--------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index a8afcece37..161ba71f7a 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; -using osu.Game.Online.API; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Drawings.Components; @@ -75,10 +74,7 @@ namespace osu.Game.Tournament.Screens.Editors RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - PlayerEditor playerEditor = new PlayerEditor(Model) - { - Width = 0.95f - }; + PlayerEditor playerEditor = new PlayerEditor(Model); InternalChildren = new Drawable[] { @@ -89,14 +85,15 @@ namespace osu.Game.Tournament.Screens.Editors }, new GroupTeam(team) { - Margin = new MarginPadding(32), + Margin = new MarginPadding(16), + Scale = new Vector2(2), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, }, new FillFlowContainer { - Margin = new MarginPadding(5), Spacing = new Vector2(5), + Padding = new MarginPadding(10), Direction = FillDirection.Full, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -133,25 +130,6 @@ namespace osu.Game.Tournament.Screens.Editors Current = Model.LastYearPlacing }, new SettingsButton - { - Width = 0.2f, - Margin = new MarginPadding(10), - Text = "Add player", - Action = () => playerEditor.CreateNew() - }, - new DangerousSettingsButton - { - Width = 0.2f, - Text = "Delete Team", - Margin = new MarginPadding(10), - Action = () => - { - Expire(); - ladderInfo.Teams.Remove(Model); - }, - }, - playerEditor, - new SettingsButton { Width = 0.2f, Margin = new MarginPadding(10), @@ -161,6 +139,32 @@ namespace osu.Game.Tournament.Screens.Editors sceneManager?.SetScreen(new SeedingEditorScreen(team, parent)); } }, + playerEditor, + new SettingsButton + { + Text = "Add player", + Action = () => playerEditor.CreateNew() + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new DangerousSettingsButton + { + Width = 0.2f, + Text = "Delete Team", + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Action = () => + { + Expire(); + ladderInfo.Teams.Remove(Model); + }, + }, + } + }, } }, }; @@ -183,6 +187,8 @@ namespace osu.Game.Tournament.Screens.Editors RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, + Padding = new MarginPadding(5), + Spacing = new Vector2(5), ChildrenEnumerable = team.Players.Select(p => new PlayerRow(team, p)) }; } @@ -198,9 +204,6 @@ namespace osu.Game.Tournament.Screens.Editors { private readonly TournamentUser user; - [Resolved] - protected IAPIProvider API { get; private set; } = null!; - [Resolved] private TournamentGameBase game { get; set; } = null!; @@ -212,8 +215,6 @@ namespace osu.Game.Tournament.Screens.Editors { this.user = user; - Margin = new MarginPadding(10); - RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -246,7 +247,7 @@ namespace osu.Game.Tournament.Screens.Editors }, userPanelContainer = new Container { - Width = 500, + Width = 400, RelativeSizeAxes = Axes.Y, }, } @@ -292,8 +293,9 @@ namespace osu.Game.Tournament.Screens.Editors { userPanelContainer.Child = new UserListPanel(user.ToAPIUser()) { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Scale = new Vector2(1.7f), }; }); } From cfc4575490c17bb2cad7c971021953082770e2aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Jul 2023 19:51:52 +0900 Subject: [PATCH 040/118] Fix save changes button gone somewhere else --- osu.Game.Tournament/SaveChangesOverlay.cs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tournament/SaveChangesOverlay.cs b/osu.Game.Tournament/SaveChangesOverlay.cs index 6db8605808..7838d4ba48 100644 --- a/osu.Game.Tournament/SaveChangesOverlay.cs +++ b/osu.Game.Tournament/SaveChangesOverlay.cs @@ -25,12 +25,11 @@ namespace osu.Game.Tournament { RelativeSizeAxes = Axes.Both; - InternalChild = new Container + InternalChild = new CircularContainer { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, - Position = new Vector2(5), - CornerRadius = 10, + Position = new Vector2(-5), Masking = true, AutoSizeAxes = Axes.Both, Children = new Drawable[] @@ -43,18 +42,10 @@ namespace osu.Game.Tournament saveChangesButton = new TourneyButton { Text = "Save Changes", + RelativeSizeAxes = Axes.None, Width = 140, Height = 50, - Padding = new MarginPadding - { - Top = 10, - Left = 10, - }, - Margin = new MarginPadding - { - Right = 10, - Bottom = 10, - }, + Margin = new MarginPadding(10), Action = saveChanges, // Enabled = { Value = false }, }, From f9742c3c34afcb5239092e51a2bdab1ef4590d9d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Jul 2023 19:56:32 +0900 Subject: [PATCH 041/118] Increase button size of setup screen buttons --- .../Screens/Setup/ActionableInfo.cs | 19 ++++++++++--------- .../Screens/Setup/TournamentSwitcher.cs | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tournament/Screens/Setup/ActionableInfo.cs b/osu.Game.Tournament/Screens/Setup/ActionableInfo.cs index e3fe2170ba..62f945e50d 100644 --- a/osu.Game.Tournament/Screens/Setup/ActionableInfo.cs +++ b/osu.Game.Tournament/Screens/Setup/ActionableInfo.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; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -15,7 +13,15 @@ namespace osu.Game.Tournament.Screens.Setup { internal partial class ActionableInfo : LabelledDrawable { - protected OsuButton Button; + public const float BUTTON_SIZE = 120; + + public Action? Action; + + protected FillFlowContainer FlowContainer = null!; + + protected OsuButton Button = null!; + + private TournamentSpriteText valueText = null!; public ActionableInfo() : base(true) @@ -37,11 +43,6 @@ namespace osu.Game.Tournament.Screens.Setup set => valueText.Colour = value ? Color4.Red : Color4.White; } - public Action Action; - - private TournamentSpriteText valueText; - protected FillFlowContainer FlowContainer; - protected override Drawable CreateComponent() => new Container { AutoSizeAxes = Axes.Y, @@ -63,7 +64,7 @@ namespace osu.Game.Tournament.Screens.Setup { Button = new RoundedButton { - Size = new Vector2(100, 40), + Size = new Vector2(BUTTON_SIZE, 40), Action = () => Action?.Invoke() } } diff --git a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs index 01d86274d7..2d57757ad9 100644 --- a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs +++ b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tournament.Screens.Setup FlowContainer.Insert(-1, folderButton = new RoundedButton { Text = "Open folder", - Width = 100 + Width = BUTTON_SIZE }); FlowContainer.Insert(-2, dropdown = new OsuDropdown From f0cec046199c77b0768698ce8b8b3c0f54ad9fde Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Jul 2023 03:47:32 +0900 Subject: [PATCH 042/118] Fix nullability warning --- osu.Game.Tournament/Screens/Setup/SetupScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Screens/Setup/SetupScreen.cs b/osu.Game.Tournament/Screens/Setup/SetupScreen.cs index ceddd4d1a1..ff1d32516a 100644 --- a/osu.Game.Tournament/Screens/Setup/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/Setup/SetupScreen.cs @@ -106,8 +106,8 @@ namespace osu.Game.Tournament.Screens.Setup loginOverlay.State.Value = Visibility.Visible; }, - Value = api?.LocalUser.Value.Username, - Failing = api?.IsLoggedIn != true, + Value = api.LocalUser.Value.Username, + Failing = api.IsLoggedIn != true, Description = "In order to access the API and display metadata, signing in is required." }, new LabelledDropdown From 2833497e5b0b1eaeb5bdbab7a500881fe9554908 Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Sun, 16 Jul 2023 22:35:20 +0100 Subject: [PATCH 043/118] add dialogoverlay to tournament client, confirmation dialog for resetting bracket teams --- .../Screens/BracketResetTeamsDialog.cs | 34 +++++++++++++++++++ .../Screens/Editors/LadderEditorScreen.cs | 10 ++++-- .../Screens/Ladder/LadderScreen.cs | 2 ++ osu.Game.Tournament/TournamentGame.cs | 15 +++++++- 4 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 osu.Game.Tournament/Screens/BracketResetTeamsDialog.cs diff --git a/osu.Game.Tournament/Screens/BracketResetTeamsDialog.cs b/osu.Game.Tournament/Screens/BracketResetTeamsDialog.cs new file mode 100644 index 0000000000..d3197bd1e6 --- /dev/null +++ b/osu.Game.Tournament/Screens/BracketResetTeamsDialog.cs @@ -0,0 +1,34 @@ +// 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.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Overlays.Dialog; +using osu.Game.Tournament.Screens.Ladder.Components; + +namespace osu.Game.Tournament.Screens +{ + public partial class BracketResetTeamsDialog : DangerousActionDialog + { + private readonly Container matchesContainer; + + public BracketResetTeamsDialog(Container matchesContainer) + { + this.matchesContainer = matchesContainer; + BodyText = @""; + HeaderText = @"Confirm reset teams?"; + Icon = FontAwesome.Solid.Undo; + } + + [BackgroundDependencyLoader] + private void load() + { + DangerousAction = () => + { + foreach (var p in matchesContainer) + p.Match.Reset(); + }; + } + } +} diff --git a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs index e698e6e5b3..52d073068b 100644 --- a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs @@ -6,6 +6,7 @@ using System; using System.Drawing; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,8 +14,10 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Input.States; +using osu.Framework.Logging; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; +using osu.Game.Overlays; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Ladder; using osu.Game.Tournament.Screens.Ladder.Components; @@ -31,6 +34,10 @@ namespace osu.Game.Tournament.Screens.Editors private WarningBox rightClickMessage; + [Resolved] + [CanBeNull] + private IDialogOverlay dialogOverlay { get; set; } + protected override bool DrawLoserPaths => true; [BackgroundDependencyLoader] @@ -73,8 +80,7 @@ namespace osu.Game.Tournament.Screens.Editors }), new OsuMenuItem("Reset teams", MenuItemType.Destructive, () => { - foreach (var p in MatchesContainer) - p.Match.Reset(); + dialogOverlay?.Push(new BracketResetTeamsDialog(MatchesContainer)); }) }; } diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index a74c9a9429..fa0ac644b9 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -6,12 +6,14 @@ using System.Collections.Specialized; using System.Diagnostics; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Caching; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Lines; +using osu.Game.Overlays; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Editors; diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index beef1e197d..601ee259af 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -11,12 +11,14 @@ using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; using osu.Framework.Input.Handlers.Mouse; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Graphics; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; using osu.Game.Tournament.Models; using osuTK.Graphics; @@ -39,6 +41,13 @@ namespace osu.Game.Tournament private Bindable windowMode; private LoadingSpinner loadingSpinner; + private readonly DialogOverlay dialogOverlay = new DialogOverlay(); + private DependencyContainer dependencies; + private Container topMostOverlayContent; + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => + dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + [BackgroundDependencyLoader] private void load(FrameworkConfigManager frameworkConfig, GameHost host) { @@ -52,6 +61,8 @@ namespace osu.Game.Tournament Margin = new MarginPadding(40), }); + dependencies.CacheAs(dialogOverlay); + // in order to have the OS mouse cursor visible, relative mode needs to be disabled. // can potentially be removed when https://github.com/ppy/osu-framework/issues/4309 is resolved. var mouseHandler = host.AvailableInputHandlers.OfType().FirstOrDefault(); @@ -90,12 +101,14 @@ namespace osu.Game.Tournament { RelativeSizeAxes = Axes.Both, Child = new TournamentSceneManager() - } + }, + topMostOverlayContent = new Container { RelativeSizeAxes = Axes.Both } }, drawables => { loadingSpinner.Hide(); loadingSpinner.Expire(); + topMostOverlayContent.Add(dialogOverlay); AddRange(drawables); windowSize.BindValueChanged(size => ScheduleAfterChildren(() => From e7795296e2e77d5b91d37251e4b0bdccba2ce1e9 Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Sun, 16 Jul 2023 22:44:41 +0100 Subject: [PATCH 044/118] refactor LadderResetTeamsDialog.cs --- .../Screens/Editors/LadderEditorScreen.cs | 3 +-- .../Components/LadderResetTeamsDialog.cs} | 17 +++-------------- .../Screens/Ladder/LadderScreen.cs | 2 -- 3 files changed, 4 insertions(+), 18 deletions(-) rename osu.Game.Tournament/Screens/{BracketResetTeamsDialog.cs => Ladder/Components/LadderResetTeamsDialog.cs} (50%) diff --git a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs index 52d073068b..2cd5dfb513 100644 --- a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs @@ -14,7 +14,6 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Input.States; -using osu.Framework.Logging; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Overlays; @@ -80,7 +79,7 @@ namespace osu.Game.Tournament.Screens.Editors }), new OsuMenuItem("Reset teams", MenuItemType.Destructive, () => { - dialogOverlay?.Push(new BracketResetTeamsDialog(MatchesContainer)); + dialogOverlay?.Push(new LadderResetTeamsDialog(MatchesContainer)); }) }; } diff --git a/osu.Game.Tournament/Screens/BracketResetTeamsDialog.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderResetTeamsDialog.cs similarity index 50% rename from osu.Game.Tournament/Screens/BracketResetTeamsDialog.cs rename to osu.Game.Tournament/Screens/Ladder/Components/LadderResetTeamsDialog.cs index d3197bd1e6..0ecaab9af0 100644 --- a/osu.Game.Tournament/Screens/BracketResetTeamsDialog.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderResetTeamsDialog.cs @@ -1,29 +1,18 @@ // 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.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; -using osu.Game.Tournament.Screens.Ladder.Components; -namespace osu.Game.Tournament.Screens +namespace osu.Game.Tournament.Screens.Ladder.Components { - public partial class BracketResetTeamsDialog : DangerousActionDialog + public partial class LadderResetTeamsDialog : DangerousActionDialog { - private readonly Container matchesContainer; - - public BracketResetTeamsDialog(Container matchesContainer) + public LadderResetTeamsDialog(Container matchesContainer) { - this.matchesContainer = matchesContainer; - BodyText = @""; HeaderText = @"Confirm reset teams?"; Icon = FontAwesome.Solid.Undo; - } - - [BackgroundDependencyLoader] - private void load() - { DangerousAction = () => { foreach (var p in matchesContainer) diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index fa0ac644b9..a74c9a9429 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -6,14 +6,12 @@ using System.Collections.Specialized; using System.Diagnostics; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Caching; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Lines; -using osu.Game.Overlays; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Editors; From 35103946999865a37408e38c1e4663eecc67f07a Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Mon, 17 Jul 2023 07:59:15 +0100 Subject: [PATCH 045/118] add ladder editor reset teams confirmation dialog test --- .../Screens/TestSceneLadderEditorScreen.cs | 87 +++++++++++++++++-- .../TournamentTestScene.cs | 8 +- 2 files changed, 89 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs index 839730f3ca..825a976309 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs @@ -1,22 +1,99 @@ // 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; +#nullable disable + +using System.Linq; +using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Graphics.Cursor; using osu.Game.Tournament.Screens.Editors; +using osu.Framework.Testing; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Dialog; +using osu.Game.Tournament.Screens.Ladder.Components; +using osuTK; +using osuTK.Input; namespace osu.Game.Tournament.Tests.Screens { public partial class TestSceneLadderEditorScreen : TournamentTestScene { - [BackgroundDependencyLoader] - private void load() + private LadderEditorScreen ladderEditorScreen; + private OsuContextMenuContainer osuContextMenuContainer; + + [SetUp] + public void Setup() => Schedule(() => { - Add(new OsuContextMenuContainer + Add(osuContextMenuContainer = new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, - Child = new LadderEditorScreen() + Child = ladderEditorScreen = new LadderEditorScreen() + }); + }); + + [Test] + public void TestResetBracketTeams() + { + AddStep("pull up context menu", () => + { + InputManager.MoveMouseTo(ladderEditorScreen); + InputManager.Click(MouseButton.Right); + }); + + AddStep("click Reset teams button", () => + { + InputManager.MoveMouseTo(osuContextMenuContainer.ChildrenOfType().Last(p => + ((OsuMenuItem)p.Item).Type == MenuItemType.Destructive), new Vector2(5, 0)); + InputManager.Click(MouseButton.Left); + }); + + AddAssert("dialog displayed", () => dialogOverlay.CurrentDialog is LadderResetTeamsDialog); + + AddStep("click confirmation", () => + { + InputManager.MoveMouseTo(dialogOverlay.CurrentDialog.ChildrenOfType().First()); + InputManager.PressButton(MouseButton.Left); + }); + + AddUntilStep("dialog dismissed", () => dialogOverlay.CurrentDialog is not LadderResetTeamsDialog); + + AddStep("release mouse button", () => InputManager.ReleaseButton(MouseButton.Left)); + + AddAssert("assert ladder teams reset", () => + { + return Ladder.Matches.All(m => m.Team1.Value == null && m.Team2.Value == null); + }); + } + + [Test] + public void TestResetBracketTeamsCancelled() + { + AddStep("pull up context menu", () => + { + InputManager.MoveMouseTo(ladderEditorScreen); + InputManager.Click(MouseButton.Right); + }); + + AddStep("click Reset teams button", () => + { + InputManager.MoveMouseTo(osuContextMenuContainer.ChildrenOfType().Last(p => + ((OsuMenuItem)p.Item).Type == MenuItemType.Destructive), new Vector2(5, 0)); + InputManager.Click(MouseButton.Left); + }); + + AddAssert("dialog displayed", () => dialogOverlay.CurrentDialog is LadderResetTeamsDialog); + AddStep("click cancel", () => + { + InputManager.MoveMouseTo(dialogOverlay.CurrentDialog.ChildrenOfType().Last()); + InputManager.Click(MouseButton.Left); + }); + + AddUntilStep("dialog dismissed", () => dialogOverlay.CurrentDialog is not LadderResetTeamsDialog); + + AddAssert("assert ladder teams unchanged", () => + { + return !Ladder.Matches.Any(m => m.Team1.Value == null && m.Team2.Value == null); }); } } diff --git a/osu.Game.Tournament.Tests/TournamentTestScene.cs b/osu.Game.Tournament.Tests/TournamentTestScene.cs index cab78422a2..2c59b28a7c 100644 --- a/osu.Game.Tournament.Tests/TournamentTestScene.cs +++ b/osu.Game.Tournament.Tests/TournamentTestScene.cs @@ -10,6 +10,7 @@ using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Beatmaps; +using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Tests.Visual; using osu.Game.Tournament.IO; @@ -18,9 +19,10 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Tests { - public abstract partial class TournamentTestScene : OsuTestScene + public abstract partial class TournamentTestScene : OsuManualInputManagerTestScene { private TournamentMatch match; + protected DialogOverlay dialogOverlay; [Cached] protected LadderInfo Ladder { get; private set; } = new LadderInfo(); @@ -45,6 +47,10 @@ namespace osu.Game.Tournament.Tests Ruleset.BindTo(Ladder.Ruleset); Dependencies.CacheAs(new StableInfo(storage)); + + Add(dialogOverlay = new DialogOverlay { Depth = -1 }); + + Dependencies.CacheAs(dialogOverlay); } [SetUpSteps] From 8cd81681b2ca823b7562e3d95e1f9171587410d7 Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Mon, 17 Jul 2023 08:11:28 +0100 Subject: [PATCH 046/118] reorder LadderEditorScreen tests --- .../Screens/TestSceneLadderEditorScreen.cs | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs index 825a976309..1bcf6334ec 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs @@ -32,6 +32,37 @@ namespace osu.Game.Tournament.Tests.Screens }); }); + [Test] + public void TestResetBracketTeamsCancelled() + { + AddStep("pull up context menu", () => + { + InputManager.MoveMouseTo(ladderEditorScreen); + InputManager.Click(MouseButton.Right); + }); + + AddStep("click Reset teams button", () => + { + InputManager.MoveMouseTo(osuContextMenuContainer.ChildrenOfType().Last(p => + ((OsuMenuItem)p.Item).Type == MenuItemType.Destructive), new Vector2(5, 0)); + InputManager.Click(MouseButton.Left); + }); + + AddAssert("dialog displayed", () => dialogOverlay.CurrentDialog is LadderResetTeamsDialog); + AddStep("click cancel", () => + { + InputManager.MoveMouseTo(dialogOverlay.CurrentDialog.ChildrenOfType().Last()); + InputManager.Click(MouseButton.Left); + }); + + AddUntilStep("dialog dismissed", () => dialogOverlay.CurrentDialog is not LadderResetTeamsDialog); + + AddAssert("assert ladder teams unchanged", () => + { + return !Ladder.Matches.Any(m => m.Team1.Value == null && m.Team2.Value == null); + }); + } + [Test] public void TestResetBracketTeams() { @@ -65,36 +96,5 @@ namespace osu.Game.Tournament.Tests.Screens return Ladder.Matches.All(m => m.Team1.Value == null && m.Team2.Value == null); }); } - - [Test] - public void TestResetBracketTeamsCancelled() - { - AddStep("pull up context menu", () => - { - InputManager.MoveMouseTo(ladderEditorScreen); - InputManager.Click(MouseButton.Right); - }); - - AddStep("click Reset teams button", () => - { - InputManager.MoveMouseTo(osuContextMenuContainer.ChildrenOfType().Last(p => - ((OsuMenuItem)p.Item).Type == MenuItemType.Destructive), new Vector2(5, 0)); - InputManager.Click(MouseButton.Left); - }); - - AddAssert("dialog displayed", () => dialogOverlay.CurrentDialog is LadderResetTeamsDialog); - AddStep("click cancel", () => - { - InputManager.MoveMouseTo(dialogOverlay.CurrentDialog.ChildrenOfType().Last()); - InputManager.Click(MouseButton.Left); - }); - - AddUntilStep("dialog dismissed", () => dialogOverlay.CurrentDialog is not LadderResetTeamsDialog); - - AddAssert("assert ladder teams unchanged", () => - { - return !Ladder.Matches.Any(m => m.Team1.Value == null && m.Team2.Value == null); - }); - } } } From 41638ff4b7a89064d9521c14d7f30335176ac31c Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Tue, 18 Jul 2023 23:44:53 +0100 Subject: [PATCH 047/118] move LadderResetTeamsDialog.cs into editor screens components --- .../Screens/TestSceneLadderEditorScreen.cs | 2 +- .../{Ladder => Editors}/Components/LadderResetTeamsDialog.cs | 3 ++- osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) rename osu.Game.Tournament/Screens/{Ladder => Editors}/Components/LadderResetTeamsDialog.cs (86%) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs index 1bcf6334ec..f41289a28f 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs @@ -11,7 +11,7 @@ using osu.Game.Tournament.Screens.Editors; using osu.Framework.Testing; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Dialog; -using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Screens.Editors.Components; using osuTK; using osuTK.Input; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderResetTeamsDialog.cs b/osu.Game.Tournament/Screens/Editors/Components/LadderResetTeamsDialog.cs similarity index 86% rename from osu.Game.Tournament/Screens/Ladder/Components/LadderResetTeamsDialog.cs rename to osu.Game.Tournament/Screens/Editors/Components/LadderResetTeamsDialog.cs index 0ecaab9af0..5fd5ae365e 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderResetTeamsDialog.cs +++ b/osu.Game.Tournament/Screens/Editors/Components/LadderResetTeamsDialog.cs @@ -4,8 +4,9 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; +using osu.Game.Tournament.Screens.Ladder.Components; -namespace osu.Game.Tournament.Screens.Ladder.Components +namespace osu.Game.Tournament.Screens.Editors.Components { public partial class LadderResetTeamsDialog : DangerousActionDialog { diff --git a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs index 2cd5dfb513..86805b767f 100644 --- a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs @@ -18,6 +18,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Overlays; using osu.Game.Tournament.Models; +using osu.Game.Tournament.Screens.Editors.Components; using osu.Game.Tournament.Screens.Ladder; using osu.Game.Tournament.Screens.Ladder.Components; using osuTK; From e3a7b6969af55dfc05568bb492bb16941161102e Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Wed, 19 Jul 2023 00:24:34 +0100 Subject: [PATCH 048/118] add confirmation dialog for Clear All button in TournamentEditorScreen --- .../Screens/TestSceneRoundEditorScreen.cs | 4 +- .../Screens/TestSceneSeedingEditorScreen.cs | 3 +- .../Screens/TestSceneTeamEditorScreen.cs | 4 +- .../Components/TournamentClearAllDialog.cs | 46 +++++++++++++++++++ .../Screens/Editors/RoundEditorScreen.cs | 36 +++++++++++++++ .../Screens/Editors/TournamentEditorScreen.cs | 12 ++++- 6 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs index 2e7bf364f7..2b67193249 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs @@ -1,13 +1,15 @@ // 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.Game.Tournament.Screens.Editors; namespace osu.Game.Tournament.Tests.Screens { public partial class TestSceneRoundEditorScreen : TournamentTestScene { - public TestSceneRoundEditorScreen() + [BackgroundDependencyLoader] + private void load() { Add(new RoundEditorScreen { diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs index 0d06b0352f..797b7cfd69 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs @@ -12,7 +12,8 @@ namespace osu.Game.Tournament.Tests.Screens [Cached] private readonly LadderInfo ladder = new LadderInfo(); - public TestSceneSeedingEditorScreen() + [BackgroundDependencyLoader] + private void load() { var match = CreateSampleMatch(); diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs index 7b371ed78b..e22967eda2 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs @@ -1,13 +1,15 @@ // 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.Game.Tournament.Screens.Editors; namespace osu.Game.Tournament.Tests.Screens { public partial class TestSceneTeamEditorScreen : TournamentTestScene { - public TestSceneTeamEditorScreen() + [BackgroundDependencyLoader] + private void load() { Add(new TeamEditorScreen { diff --git a/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs b/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs new file mode 100644 index 0000000000..d1d6c65982 --- /dev/null +++ b/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs @@ -0,0 +1,46 @@ +// 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; +using osu.Framework.Graphics.Sprites; +using osu.Game.Overlays.Dialog; + +namespace osu.Game.Tournament.Screens.Editors.Components +{ + public partial class TournamentClearAllDialog : DangerousActionDialog + + { + public TournamentClearAllDialog(IList storage) + { + HeaderText = @"Confirm clear all?"; + Icon = FontAwesome.Solid.Trash; + DangerousAction = storage.Clear; + } + + // // 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.Graphics.Containers; + // using osu.Framework.Graphics.Sprites; + // using osu.Game.Overlays.Dialog; + // using osu.Game.Tournament.Screens.Ladder.Components; + // + // namespace osu.Game.Tournament.Screens.Editors.Components + // { + // public partial class LadderResetTeamsDialog : DangerousActionDialog + // { + // public LadderResetTeamsDialog(Container matchesContainer) + // { + // HeaderText = @"Confirm reset teams?"; + // Icon = FontAwesome.Solid.Undo; + // DangerousAction = () => + // { + // foreach (var p in matchesContainer) + // p.Match.Reset(); + // }; + // } + // } + // } + + } +} diff --git a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index 4a3b5c0846..846e84ebda 100644 --- a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -7,13 +7,17 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Logging; +using osu.Framework.Testing; using osu.Game.Graphics; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; +using osu.Game.Tournament.Screens.Editors.Components; using osuTK; namespace osu.Game.Tournament.Screens.Editors @@ -21,6 +25,38 @@ namespace osu.Game.Tournament.Screens.Editors public partial class RoundEditorScreen : TournamentEditorScreen { protected override BindableList Storage => LadderInfo.Rounds; + // + // [Resolved] + // private IDialogOverlay? dialogOverlay { get; set; } + // + // [BackgroundDependencyLoader] + // private void load() + // { + // // ControlPanel.Add(new TourneyButton + // // { + // // RelativeSizeAxes = Axes.X, + // // Text = "aaaaaa", + // // Action = () => + // // { + // // Logger.Log("asdaf", LoggingTarget.Runtime, LogLevel.Important); + // // } + // // }); + // // Logger.Log($"Current action is {.Action}", LoggingTarget.Runtime, LogLevel.Important); + // + // dialogOverlay?.Push(new TournamentClearAllDialog(Storage)); + // + // var clearAllButton = ControlPanel.ChildrenOfType().FirstOrDefault(); + // + // if (clearAllButton != null) + // { + // clearAllButton.Action = () => + // { + // Logger.Log("doing the thing!", LoggingTarget.Runtime, LogLevel.Important); + // Logger.Log($"currently, dialogOverlay is {dialogOverlay}", LoggingTarget.Runtime, LogLevel.Important); + // dialogOverlay?.Push(new TournamentClearAllDialog(Storage)); + // }; + // } + // } public partial class RoundRow : CompositeDrawable, IModelBacked { diff --git a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs index 0fb6c1367b..a6b2a9b1ab 100644 --- a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs @@ -6,6 +6,7 @@ using System.Collections.Specialized; using System.Diagnostics; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; @@ -15,8 +16,10 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Overlays; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; +using osu.Game.Tournament.Screens.Editors.Components; using osuTK; namespace osu.Game.Tournament.Screens.Editors @@ -27,6 +30,10 @@ namespace osu.Game.Tournament.Screens.Editors { protected abstract BindableList Storage { get; } + [Resolved] + [CanBeNull] + private IDialogOverlay dialogOverlay { get; set; } + private FillFlowContainer flow; [Resolved(canBeNull: true)] @@ -79,7 +86,10 @@ namespace osu.Game.Tournament.Screens.Editors { RelativeSizeAxes = Axes.X, Text = "Clear all", - Action = Storage.Clear + Action = () => + { + dialogOverlay?.Push(new TournamentClearAllDialog(Storage)); + } }, } } From e67253ed1e6b70dd2c6a6e89dd60c5f8df97270d Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Wed, 19 Jul 2023 00:25:07 +0100 Subject: [PATCH 049/118] remove unused code --- .../Components/TournamentClearAllDialog.cs | 26 -------------- .../Screens/Editors/RoundEditorScreen.cs | 36 ------------------- 2 files changed, 62 deletions(-) diff --git a/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs b/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs index d1d6c65982..06b1071ce9 100644 --- a/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs +++ b/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs @@ -16,31 +16,5 @@ namespace osu.Game.Tournament.Screens.Editors.Components Icon = FontAwesome.Solid.Trash; DangerousAction = storage.Clear; } - - // // 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.Graphics.Containers; - // using osu.Framework.Graphics.Sprites; - // using osu.Game.Overlays.Dialog; - // using osu.Game.Tournament.Screens.Ladder.Components; - // - // namespace osu.Game.Tournament.Screens.Editors.Components - // { - // public partial class LadderResetTeamsDialog : DangerousActionDialog - // { - // public LadderResetTeamsDialog(Container matchesContainer) - // { - // HeaderText = @"Confirm reset teams?"; - // Icon = FontAwesome.Solid.Undo; - // DangerousAction = () => - // { - // foreach (var p in matchesContainer) - // p.Match.Reset(); - // }; - // } - // } - // } - } } diff --git a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index 846e84ebda..4a3b5c0846 100644 --- a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -7,17 +7,13 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Logging; -using osu.Framework.Testing; using osu.Game.Graphics; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Overlays; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; -using osu.Game.Tournament.Screens.Editors.Components; using osuTK; namespace osu.Game.Tournament.Screens.Editors @@ -25,38 +21,6 @@ namespace osu.Game.Tournament.Screens.Editors public partial class RoundEditorScreen : TournamentEditorScreen { protected override BindableList Storage => LadderInfo.Rounds; - // - // [Resolved] - // private IDialogOverlay? dialogOverlay { get; set; } - // - // [BackgroundDependencyLoader] - // private void load() - // { - // // ControlPanel.Add(new TourneyButton - // // { - // // RelativeSizeAxes = Axes.X, - // // Text = "aaaaaa", - // // Action = () => - // // { - // // Logger.Log("asdaf", LoggingTarget.Runtime, LogLevel.Important); - // // } - // // }); - // // Logger.Log($"Current action is {.Action}", LoggingTarget.Runtime, LogLevel.Important); - // - // dialogOverlay?.Push(new TournamentClearAllDialog(Storage)); - // - // var clearAllButton = ControlPanel.ChildrenOfType().FirstOrDefault(); - // - // if (clearAllButton != null) - // { - // clearAllButton.Action = () => - // { - // Logger.Log("doing the thing!", LoggingTarget.Runtime, LogLevel.Important); - // Logger.Log($"currently, dialogOverlay is {dialogOverlay}", LoggingTarget.Runtime, LogLevel.Important); - // dialogOverlay?.Push(new TournamentClearAllDialog(Storage)); - // }; - // } - // } public partial class RoundRow : CompositeDrawable, IModelBacked { From 68495c937d975ff23052bb1c029a08ace9537847 Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Wed, 19 Jul 2023 01:59:40 +0100 Subject: [PATCH 050/118] fix ResetBracketTeams tests also fixes formatting and var naming issues --- .../Screens/TestSceneLadderEditorScreen.cs | 32 ++++++++++--------- .../TournamentTestScene.cs | 6 ++-- .../Components/TournamentClearAllDialog.cs | 1 - 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs index f41289a28f..bbf4da803e 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs @@ -3,9 +3,13 @@ #nullable disable +using System; using System.Linq; +using Newtonsoft.Json; using NUnit.Framework; +using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Logging; using osu.Game.Graphics.Cursor; using osu.Game.Tournament.Screens.Editors; using osu.Framework.Testing; @@ -35,12 +39,16 @@ namespace osu.Game.Tournament.Tests.Screens [Test] public void TestResetBracketTeamsCancelled() { + Bindable matchBeforeReset = new Bindable(); + AddStep("save current match state", () => + { + matchBeforeReset.Value = JsonConvert.SerializeObject(Ladder.CurrentMatch.Value); + }); AddStep("pull up context menu", () => { InputManager.MoveMouseTo(ladderEditorScreen); InputManager.Click(MouseButton.Right); }); - AddStep("click Reset teams button", () => { InputManager.MoveMouseTo(osuContextMenuContainer.ChildrenOfType().Last(p => @@ -48,19 +56,16 @@ namespace osu.Game.Tournament.Tests.Screens InputManager.Click(MouseButton.Left); }); - AddAssert("dialog displayed", () => dialogOverlay.CurrentDialog is LadderResetTeamsDialog); + AddAssert("dialog displayed", () => DialogOverlay.CurrentDialog is LadderResetTeamsDialog); AddStep("click cancel", () => { - InputManager.MoveMouseTo(dialogOverlay.CurrentDialog.ChildrenOfType().Last()); + InputManager.MoveMouseTo(DialogOverlay.CurrentDialog.ChildrenOfType().Last()); InputManager.Click(MouseButton.Left); }); - AddUntilStep("dialog dismissed", () => dialogOverlay.CurrentDialog is not LadderResetTeamsDialog); + AddUntilStep("dialog dismissed", () => DialogOverlay.CurrentDialog is not LadderResetTeamsDialog); - AddAssert("assert ladder teams unchanged", () => - { - return !Ladder.Matches.Any(m => m.Team1.Value == null && m.Team2.Value == null); - }); + AddAssert("assert ladder teams unchanged", () => string.Equals(matchBeforeReset.Value, JsonConvert.SerializeObject(Ladder.CurrentMatch.Value), StringComparison.Ordinal)); } [Test] @@ -79,22 +84,19 @@ namespace osu.Game.Tournament.Tests.Screens InputManager.Click(MouseButton.Left); }); - AddAssert("dialog displayed", () => dialogOverlay.CurrentDialog is LadderResetTeamsDialog); + AddAssert("dialog displayed", () => DialogOverlay.CurrentDialog is LadderResetTeamsDialog); AddStep("click confirmation", () => { - InputManager.MoveMouseTo(dialogOverlay.CurrentDialog.ChildrenOfType().First()); + InputManager.MoveMouseTo(DialogOverlay.CurrentDialog.ChildrenOfType().First()); InputManager.PressButton(MouseButton.Left); }); - AddUntilStep("dialog dismissed", () => dialogOverlay.CurrentDialog is not LadderResetTeamsDialog); + AddUntilStep("dialog dismissed", () => DialogOverlay.CurrentDialog is not LadderResetTeamsDialog); AddStep("release mouse button", () => InputManager.ReleaseButton(MouseButton.Left)); - AddAssert("assert ladder teams reset", () => - { - return Ladder.Matches.All(m => m.Team1.Value == null && m.Team2.Value == null); - }); + AddAssert("assert ladder teams reset", () => Ladder.CurrentMatch.Value.Team1.Value == null && Ladder.CurrentMatch.Value.Team2.Value == null); } } } diff --git a/osu.Game.Tournament.Tests/TournamentTestScene.cs b/osu.Game.Tournament.Tests/TournamentTestScene.cs index 2c59b28a7c..740145074e 100644 --- a/osu.Game.Tournament.Tests/TournamentTestScene.cs +++ b/osu.Game.Tournament.Tests/TournamentTestScene.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tournament.Tests public abstract partial class TournamentTestScene : OsuManualInputManagerTestScene { private TournamentMatch match; - protected DialogOverlay dialogOverlay; + protected DialogOverlay DialogOverlay; [Cached] protected LadderInfo Ladder { get; private set; } = new LadderInfo(); @@ -48,9 +48,9 @@ namespace osu.Game.Tournament.Tests Ruleset.BindTo(Ladder.Ruleset); Dependencies.CacheAs(new StableInfo(storage)); - Add(dialogOverlay = new DialogOverlay { Depth = -1 }); + Add(DialogOverlay = new DialogOverlay { Depth = -1 }); - Dependencies.CacheAs(dialogOverlay); + Dependencies.CacheAs(DialogOverlay); } [SetUpSteps] diff --git a/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs b/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs index 06b1071ce9..036a81dc62 100644 --- a/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs +++ b/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs @@ -8,7 +8,6 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Tournament.Screens.Editors.Components { public partial class TournamentClearAllDialog : DangerousActionDialog - { public TournamentClearAllDialog(IList storage) { From fa480cc27bbcdf67a5ce4da55c4bd45bc63ed20d Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Thu, 20 Jul 2023 22:33:43 +0100 Subject: [PATCH 051/118] remove #nullable disable, pass action instead of container to DangerousActionDialog --- .../Screens/TestSceneLadderEditorScreen.cs | 8 +++----- .../Editors/Components/LadderResetTeamsDialog.cs | 13 ++++--------- .../Editors/Components/TournamentClearAllDialog.cs | 2 +- .../Screens/Editors/LadderEditorScreen.cs | 8 ++++++-- .../Screens/Editors/TournamentEditorScreen.cs | 2 +- 5 files changed, 15 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs index bbf4da803e..c383e93e7f 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs @@ -1,15 +1,12 @@ // 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; using System.Linq; using Newtonsoft.Json; using NUnit.Framework; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Logging; using osu.Game.Graphics.Cursor; using osu.Game.Tournament.Screens.Editors; using osu.Framework.Testing; @@ -23,12 +20,13 @@ namespace osu.Game.Tournament.Tests.Screens { public partial class TestSceneLadderEditorScreen : TournamentTestScene { - private LadderEditorScreen ladderEditorScreen; - private OsuContextMenuContainer osuContextMenuContainer; + private LadderEditorScreen ladderEditorScreen = null!; + private OsuContextMenuContainer? osuContextMenuContainer; [SetUp] public void Setup() => Schedule(() => { + ladderEditorScreen = new LadderEditorScreen(); Add(osuContextMenuContainer = new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game.Tournament/Screens/Editors/Components/LadderResetTeamsDialog.cs b/osu.Game.Tournament/Screens/Editors/Components/LadderResetTeamsDialog.cs index 5fd5ae365e..8ed1b381f6 100644 --- a/osu.Game.Tournament/Screens/Editors/Components/LadderResetTeamsDialog.cs +++ b/osu.Game.Tournament/Screens/Editors/Components/LadderResetTeamsDialog.cs @@ -1,24 +1,19 @@ // 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.Graphics.Containers; +using System; using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; -using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament.Screens.Editors.Components { public partial class LadderResetTeamsDialog : DangerousActionDialog { - public LadderResetTeamsDialog(Container matchesContainer) + public LadderResetTeamsDialog(Action action) { - HeaderText = @"Confirm reset teams?"; + HeaderText = @"Reset teams?"; Icon = FontAwesome.Solid.Undo; - DangerousAction = () => - { - foreach (var p in matchesContainer) - p.Match.Reset(); - }; + DangerousAction = action; } } } diff --git a/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs b/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs index 036a81dc62..050549fe76 100644 --- a/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs +++ b/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs @@ -11,7 +11,7 @@ namespace osu.Game.Tournament.Screens.Editors.Components { public TournamentClearAllDialog(IList storage) { - HeaderText = @"Confirm clear all?"; + HeaderText = @"Clear all?"; Icon = FontAwesome.Solid.Trash; DangerousAction = storage.Clear; } diff --git a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs index 86805b767f..32685ace36 100644 --- a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs @@ -34,7 +34,7 @@ namespace osu.Game.Tournament.Screens.Editors private WarningBox rightClickMessage; - [Resolved] + [Resolved(canBeNull: true)] [CanBeNull] private IDialogOverlay dialogOverlay { get; set; } @@ -80,7 +80,11 @@ namespace osu.Game.Tournament.Screens.Editors }), new OsuMenuItem("Reset teams", MenuItemType.Destructive, () => { - dialogOverlay?.Push(new LadderResetTeamsDialog(MatchesContainer)); + dialogOverlay?.Push(new LadderResetTeamsDialog(() => + { + foreach (var p in MatchesContainer) + p.Match.Reset(); + })); }) }; } diff --git a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs index a6b2a9b1ab..cd6127f1ce 100644 --- a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs @@ -30,7 +30,7 @@ namespace osu.Game.Tournament.Screens.Editors { protected abstract BindableList Storage { get; } - [Resolved] + [Resolved(canBeNull: true)] [CanBeNull] private IDialogOverlay dialogOverlay { get; set; } From 3c05246baf536249507f6fad924d9b6de4150398 Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Thu, 20 Jul 2023 22:47:29 +0100 Subject: [PATCH 052/118] fix weird handling of dialogOverlay in tourney client --- osu.Game.Tournament/TournamentGame.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index 601ee259af..97292c09aa 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -43,7 +43,6 @@ namespace osu.Game.Tournament private readonly DialogOverlay dialogOverlay = new DialogOverlay(); private DependencyContainer dependencies; - private Container topMostOverlayContent; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); @@ -102,13 +101,11 @@ namespace osu.Game.Tournament RelativeSizeAxes = Axes.Both, Child = new TournamentSceneManager() }, - topMostOverlayContent = new Container { RelativeSizeAxes = Axes.Both } + new Container { RelativeSizeAxes = Axes.Both, Child = dialogOverlay } }, drawables => { loadingSpinner.Hide(); loadingSpinner.Expire(); - - topMostOverlayContent.Add(dialogOverlay); AddRange(drawables); windowSize.BindValueChanged(size => ScheduleAfterChildren(() => From 2825671e28c7dad949a4f95c234e929617f71968 Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Thu, 20 Jul 2023 23:01:14 +0100 Subject: [PATCH 053/118] pass action instead of storage to TournamentClearAllDialog --- .../Screens/Editors/Components/TournamentClearAllDialog.cs | 6 +++--- .../Screens/Editors/TournamentEditorScreen.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs b/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs index 050549fe76..1dc7c8231d 100644 --- a/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs +++ b/osu.Game.Tournament/Screens/Editors/Components/TournamentClearAllDialog.cs @@ -1,7 +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.Collections; +using System; using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; @@ -9,11 +9,11 @@ namespace osu.Game.Tournament.Screens.Editors.Components { public partial class TournamentClearAllDialog : DangerousActionDialog { - public TournamentClearAllDialog(IList storage) + public TournamentClearAllDialog(Action action) { HeaderText = @"Clear all?"; Icon = FontAwesome.Solid.Trash; - DangerousAction = storage.Clear; + DangerousAction = action; } } } diff --git a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs index cd6127f1ce..bc0d25a238 100644 --- a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs @@ -88,7 +88,7 @@ namespace osu.Game.Tournament.Screens.Editors Text = "Clear all", Action = () => { - dialogOverlay?.Push(new TournamentClearAllDialog(Storage)); + dialogOverlay?.Push(new TournamentClearAllDialog(() => Storage.Clear())); } }, } From bf9c25f429130942be2b69627da3c7afb803bbc8 Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Thu, 20 Jul 2023 23:28:31 +0100 Subject: [PATCH 054/118] add confirmation dialog to delete team/round buttons in tourney editor screens --- .../RoundEditorDeleteRoundDialog.cs | 19 +++++++++++++++++ .../Components/TeamEditorDeleteTeamDialog.cs | 21 +++++++++++++++++++ .../Screens/Editors/RoundEditorScreen.cs | 17 ++++++++++----- .../Screens/Editors/TeamEditorScreen.cs | 20 +++++++++++++----- 4 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 osu.Game.Tournament/Screens/Editors/Components/RoundEditorDeleteRoundDialog.cs create mode 100644 osu.Game.Tournament/Screens/Editors/Components/TeamEditorDeleteTeamDialog.cs diff --git a/osu.Game.Tournament/Screens/Editors/Components/RoundEditorDeleteRoundDialog.cs b/osu.Game.Tournament/Screens/Editors/Components/RoundEditorDeleteRoundDialog.cs new file mode 100644 index 0000000000..629cd4e135 --- /dev/null +++ b/osu.Game.Tournament/Screens/Editors/Components/RoundEditorDeleteRoundDialog.cs @@ -0,0 +1,19 @@ +// 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 osu.Framework.Graphics.Sprites; +using osu.Game.Overlays.Dialog; + +namespace osu.Game.Tournament.Screens.Editors.Components +{ + public partial class RoundEditorDeleteRoundDialog : DangerousActionDialog + { + public RoundEditorDeleteRoundDialog(string roundName, Action action) + { + HeaderText = roundName.Length > 0 ? $@"Delete round ""{roundName}""?" : @"Delete unnamed round?"; + Icon = FontAwesome.Solid.Trash; + DangerousAction = action; + } + } +} diff --git a/osu.Game.Tournament/Screens/Editors/Components/TeamEditorDeleteTeamDialog.cs b/osu.Game.Tournament/Screens/Editors/Components/TeamEditorDeleteTeamDialog.cs new file mode 100644 index 0000000000..f91b58e185 --- /dev/null +++ b/osu.Game.Tournament/Screens/Editors/Components/TeamEditorDeleteTeamDialog.cs @@ -0,0 +1,21 @@ +// 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 osu.Framework.Graphics.Sprites; +using osu.Game.Overlays.Dialog; + +namespace osu.Game.Tournament.Screens.Editors.Components +{ + public partial class TeamEditorDeleteTeamDialog : DangerousActionDialog + { + public TeamEditorDeleteTeamDialog(string fullTeamName, string acronym, Action action) + { + HeaderText = fullTeamName.Length > 0 ? $@"Delete team ""{fullTeamName}""?" : + acronym.Length > 0 ? $@"Delete team ""{acronym}""?" : + @"Delete unnamed team?"; + Icon = FontAwesome.Solid.Trash; + DangerousAction = action; + } + } +} diff --git a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index 4a3b5c0846..712a724d4d 100644 --- a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -11,9 +11,11 @@ using osu.Game.Graphics; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; +using osu.Game.Tournament.Screens.Editors.Components; using osuTK; namespace osu.Game.Tournament.Screens.Editors @@ -29,6 +31,9 @@ namespace osu.Game.Tournament.Screens.Editors [Resolved] private LadderInfo ladderInfo { get; set; } = null!; + [Resolved(canBeNull: true)] + private IDialogOverlay? dialogOverlay { get; set; } + public RoundRow(TournamentRound round) { Model = round; @@ -99,11 +104,13 @@ namespace osu.Game.Tournament.Screens.Editors RelativeSizeAxes = Axes.None, Width = 150, Text = "Delete Round", - Action = () => - { - Expire(); - ladderInfo.Rounds.Remove(Model); - }, + Action = () => dialogOverlay?.Push( + new RoundEditorDeleteRoundDialog( + Model.Name.Value, () => + { + Expire(); + ladderInfo.Rounds.Remove(Model); + })) } }; diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index 93fbfba0e3..584e947b1f 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -12,9 +12,11 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Online.API; +using osu.Game.Overlays; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; +using osu.Game.Tournament.Screens.Editors.Components; using osu.Game.Users; using osuTK; @@ -64,6 +66,9 @@ namespace osu.Game.Tournament.Screens.Editors [Resolved] private TournamentSceneManager? sceneManager { get; set; } + [Resolved(canBeNull: true)] + private IDialogOverlay? dialogOverlay { get; set; } + [Resolved] private LadderInfo ladderInfo { get; set; } = null!; @@ -144,11 +149,16 @@ namespace osu.Game.Tournament.Screens.Editors Width = 0.11f, Text = "Delete Team", Margin = new MarginPadding(10), - Action = () => - { - Expire(); - ladderInfo.Teams.Remove(Model); - }, + Action = () => dialogOverlay?.Push( + new TeamEditorDeleteTeamDialog(Model.FullName.Value, + Model.Acronym.Value, + () => + { + Expire(); + ladderInfo.Teams.Remove(Model); + } + ) + ) }, playerEditor, new SettingsButton From 870f3e324a6e7737ae9240a1bd5cecdca4424bf5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Jul 2023 14:26:23 +0900 Subject: [PATCH 055/118] Adjust "test" button to better align with rest of interface --- osu.Game/Screens/Edit/BottomBar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/BottomBar.cs b/osu.Game/Screens/Edit/BottomBar.cs index b8fed4b935..9a32d5d968 100644 --- a/osu.Game/Screens/Edit/BottomBar.cs +++ b/osu.Game/Screens/Edit/BottomBar.cs @@ -57,7 +57,7 @@ namespace osu.Game.Screens.Edit new Dimension(GridSizeMode.Absolute, 170), new Dimension(), new Dimension(GridSizeMode.Absolute, 220), - new Dimension(GridSizeMode.Absolute, 120), + new Dimension(GridSizeMode.Absolute, 140), }, Content = new[] { From f489dbd7a9c1a3baea4063cc79e2cc6fc7edc0db Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Jul 2023 14:39:15 +0900 Subject: [PATCH 056/118] Reduce width of right toolbar ever so slightly (and use more shared constants) --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 2 +- osu.Game/Screens/Edit/BottomBar.cs | 4 ++-- .../Edit/Compose/Components/Timeline/TimelineArea.cs | 9 ++++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 6fcb8f62ee..d379242e3b 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -472,7 +472,7 @@ namespace osu.Game.Rulesets.Edit public abstract partial class HitObjectComposer : CompositeDrawable, IPositionSnapProvider { public const float TOOLBOX_CONTRACTED_SIZE_LEFT = 60; - public const float TOOLBOX_CONTRACTED_SIZE_RIGHT = 130; + public const float TOOLBOX_CONTRACTED_SIZE_RIGHT = 120; public readonly Ruleset Ruleset; diff --git a/osu.Game/Screens/Edit/BottomBar.cs b/osu.Game/Screens/Edit/BottomBar.cs index 9a32d5d968..aa3c4ba0d0 100644 --- a/osu.Game/Screens/Edit/BottomBar.cs +++ b/osu.Game/Screens/Edit/BottomBar.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Overlays; +using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit.Components; using osu.Game.Screens.Edit.Components.Timelines.Summary; using osuTK; @@ -57,7 +58,7 @@ namespace osu.Game.Screens.Edit new Dimension(GridSizeMode.Absolute, 170), new Dimension(), new Dimension(GridSizeMode.Absolute, 220), - new Dimension(GridSizeMode.Absolute, 140), + new Dimension(GridSizeMode.Absolute, HitObjectComposer.TOOLBOX_CONTRACTED_SIZE_RIGHT), }, Content = new[] { @@ -69,7 +70,6 @@ namespace osu.Game.Screens.Edit TestGameplayButton = new TestGameplayButton { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = 10 }, Size = new Vector2(1), Action = editor.TestGameplay, } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index fb7ce8e423..88c5d0104b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -11,6 +11,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; using osu.Game.Overlays; using osu.Game.Resources.Localisation.Web; +using osu.Game.Rulesets.Edit; using osuTK; namespace osu.Game.Screens.Edit.Compose.Components.Timeline @@ -36,6 +37,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline OsuCheckbox controlPointsCheckbox; OsuCheckbox ticksCheckbox; + const float padding = 10; + InternalChildren = new Drawable[] { new GridContainer @@ -51,7 +54,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline new Dimension(GridSizeMode.Absolute, 140), new Dimension(), new Dimension(GridSizeMode.Absolute, 35), - new Dimension(GridSizeMode.Absolute, 110), + new Dimension(GridSizeMode.Absolute, HitObjectComposer.TOOLBOX_CONTRACTED_SIZE_RIGHT - padding * 2), }, Content = new[] { @@ -71,7 +74,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline new FillFlowContainer { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding(10), + Padding = new MarginPadding(padding), Direction = FillDirection.Vertical, Spacing = new Vector2(0, 4), Children = new[] @@ -124,7 +127,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { RelativeSizeAxes = Axes.Both, Name = @"Zoom controls", - Padding = new MarginPadding { Right = 10 }, + Padding = new MarginPadding { Right = padding }, Children = new Drawable[] { new Box From b58354ac641cf92d9f80b83279054852f4bb4a38 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Jul 2023 15:20:19 +0900 Subject: [PATCH 057/118] Fix playfield getting cut off (again) at tall aspect ratios --- .../Edit/OsuHitObjectComposer.cs | 7 +------ osu.Game/Rulesets/Edit/HitObjectComposer.cs | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 8d93613156..0b80750a02 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -62,12 +62,7 @@ namespace osu.Game.Rulesets.Osu.Edit private void load() { // Give a bit of breathing room around the playfield content. - PlayfieldContentContainer.Padding = new MarginPadding - { - Vertical = 10, - // Intentionally use the left toolbox size for both sides to vertically centre the playfield. - Horizontal = TOOLBOX_CONTRACTED_SIZE_LEFT + 10, - }; + PlayfieldContentContainer.Padding = new MarginPadding(10); LayerBelowRuleset.AddRange(new Drawable[] { diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index d379242e3b..bad7c55883 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -117,13 +117,10 @@ namespace osu.Game.Rulesets.Edit { PlayfieldContentContainer = new Container { - Name = "Content", - Padding = new MarginPadding - { - Left = TOOLBOX_CONTRACTED_SIZE_LEFT, - Right = TOOLBOX_CONTRACTED_SIZE_RIGHT, - }, - RelativeSizeAxes = Axes.Both, + Name = "Playfield content", + RelativeSizeAxes = Axes.Y, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Children = new Drawable[] { // layers below playfield @@ -240,6 +237,14 @@ namespace osu.Game.Rulesets.Edit }); } + protected override void Update() + { + base.Update(); + + // Ensure that the playfield is always centered but also doesn't get cut off by toolboxes. + PlayfieldContentContainer.Width = Math.Max(1024, DrawWidth) - TOOLBOX_CONTRACTED_SIZE_RIGHT * 2; + } + public override Playfield Playfield => drawableRulesetWrapper.Playfield; public override IEnumerable HitObjects => drawableRulesetWrapper.Playfield.AllHitObjects; From cdcb10e0e7d278749ad2d97e326326ed94cf11a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Jul 2023 15:26:41 +0900 Subject: [PATCH 058/118] Fix timeline centre point being ever-so-slight off --- .../Screens/Edit/Compose/Components/Timeline/TimelineArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index 88c5d0104b..b973ac3731 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -51,7 +51,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline }, ColumnDimensions = new[] { - new Dimension(GridSizeMode.Absolute, 140), + new Dimension(GridSizeMode.Absolute, 135), new Dimension(), new Dimension(GridSizeMode.Absolute, 35), new Dimension(GridSizeMode.Absolute, HitObjectComposer.TOOLBOX_CONTRACTED_SIZE_RIGHT - padding * 2), From 82a5ba66e1f25049702e8ed2470fa29af7622d06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Jul 2023 15:27:42 +0900 Subject: [PATCH 059/118] Align mode switcher with rest of interface --- osu.Game/Screens/Edit/Editor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 41c11ce5c1..951c73b169 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -359,7 +359,7 @@ namespace osu.Game.Screens.Edit { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, - X = -15, + X = -10, Current = Mode, }, }, From ac4ad1e78ce7ed33398b0b9e4cbdb24487b19800 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Jul 2023 15:35:03 +0900 Subject: [PATCH 060/118] Change tournament tests to use development folder Unsure there was a reason for this not to be the case (looks to have been an oversight). --- osu.Game.Tournament.Tests/TournamentTestRunner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament.Tests/TournamentTestRunner.cs b/osu.Game.Tournament.Tests/TournamentTestRunner.cs index f6aef53514..5f642b14f5 100644 --- a/osu.Game.Tournament.Tests/TournamentTestRunner.cs +++ b/osu.Game.Tournament.Tests/TournamentTestRunner.cs @@ -12,7 +12,7 @@ namespace osu.Game.Tournament.Tests [STAThread] public static int Main(string[] args) { - using (DesktopGameHost host = Host.GetSuitableDesktopHost(@"osu", new HostOptions { BindIPC = true })) + using (DesktopGameHost host = Host.GetSuitableDesktopHost(@"osu-development", new HostOptions { BindIPC = true })) { host.Run(new TournamentTestBrowser()); return 0; From 741c3b8d212e1a0df93675de3ef913735142890e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Jul 2023 15:39:40 +0900 Subject: [PATCH 061/118] Reduce spacing in settings items --- osu.Game/Overlays/Settings/SettingsItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 9085b6c911..9c6bb5ae60 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -196,7 +196,7 @@ namespace osu.Game.Overlays.Settings { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Spacing = new Vector2(0, 10), + Spacing = new Vector2(0, 5), Child = Control = CreateControl(), } } From b5c3231feb95c93d3ced0be400ceccdb98e103b6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Jul 2023 15:43:48 +0900 Subject: [PATCH 062/118] Fix `SettingsNumberBox` having additional margin --- osu.Game/Overlays/Settings/SettingsNumberBox.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/SettingsNumberBox.cs b/osu.Game/Overlays/Settings/SettingsNumberBox.cs index 7912890528..a0f85eda31 100644 --- a/osu.Game/Overlays/Settings/SettingsNumberBox.cs +++ b/osu.Game/Overlays/Settings/SettingsNumberBox.cs @@ -36,7 +36,6 @@ namespace osu.Game.Overlays.Settings { numberBox = new OutlinedNumberBox { - Margin = new MarginPadding { Top = 5 }, RelativeSizeAxes = Axes.X, CommitOnFocusLost = true } From cfcfe202217011a1d8b7dab4f0f0e71572e10762 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Jul 2023 15:46:14 +0900 Subject: [PATCH 063/118] Reduce scale and better align user panel --- osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index 161ba71f7a..f8d839d2fc 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -293,9 +293,9 @@ namespace osu.Game.Tournament.Screens.Editors { userPanelContainer.Child = new UserListPanel(user.ToAPIUser()) { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Scale = new Vector2(1.7f), + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Scale = new Vector2(1f), }; }); } From d23c73a2f1ed9eb1d4f143671956819981fb6c70 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Jul 2023 17:25:38 +0900 Subject: [PATCH 064/118] Adjust with better numbers based off 1920x1080 resolution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Skinning/LegacySkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index b72a757e6c..7a8c490e4d 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -368,7 +368,7 @@ namespace osu.Game.Skinning { songProgress.Anchor = Anchor.TopRight; songProgress.Origin = Anchor.CentreRight; - songProgress.X = -accuracy.ScreenSpaceDeltaToParentSpace(accuracy.ScreenSpaceDrawQuad.Size).X - 20; + songProgress.X = -accuracy.ScreenSpaceDeltaToParentSpace(accuracy.ScreenSpaceDrawQuad.Size).X - 18; songProgress.Y = container.ToLocalSpace(accuracy.ScreenSpaceDrawQuad.TopLeft).Y + (accuracy.ScreenSpaceDeltaToParentSpace(accuracy.ScreenSpaceDrawQuad.Size).Y / 2); } From fd2bdc10c7d1106e01552f48018f9e80622c6e76 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Jul 2023 18:52:19 +0900 Subject: [PATCH 065/118] Fix "key count" setting showing as "circle size" in osu!mania editor Closes https://github.com/ppy/osu/issues/12904. --- .../Edit/Setup/ManiaDifficultySection.cs | 19 ++++++++++ osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 + osu.Game/Rulesets/Ruleset.cs | 5 +++ .../Screens/Edit/Setup/DifficultySection.cs | 38 +++++++++---------- osu.Game/Screens/Edit/Setup/SetupScreen.cs | 6 ++- 5 files changed, 49 insertions(+), 21 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs diff --git a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs new file mode 100644 index 0000000000..82ec66a28a --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs @@ -0,0 +1,19 @@ +// 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.Game.Resources.Localisation.Web; +using osu.Game.Screens.Edit.Setup; + +namespace osu.Game.Rulesets.Mania.Edit.Setup +{ + public partial class ManiaDifficultySection : DifficultySection + { + [BackgroundDependencyLoader] + private void load() + { + CircleSizeSlider.Label = BeatmapsetsStrings.ShowStatsCsMania; + CircleSizeSlider.Description = "The number of columns in the beatmap"; + } + } +} diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 802399e247..4507015169 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -425,6 +425,8 @@ namespace osu.Game.Rulesets.Mania } public override RulesetSetupSection CreateEditorSetupSection() => new ManiaSetupSection(); + + public override DifficultySection CreateEditorDifficultySection() => new ManiaDifficultySection(); } public enum PlayfieldType diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index cd432e050b..be0d757e06 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -384,5 +384,10 @@ namespace osu.Game.Rulesets /// Can be overridden to add a ruleset-specific section to the editor beatmap setup screen. /// public virtual RulesetSetupSection? CreateEditorSetupSection() => null; + + /// + /// Can be overridden to alter the difficulty section to the editor beatmap setup screen. + /// + public virtual DifficultySection? CreateEditorDifficultySection() => null; } } diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs index 4c062b0cb7..3954271290 100644 --- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs @@ -13,14 +13,14 @@ using osu.Game.Localisation; namespace osu.Game.Screens.Edit.Setup { - internal partial class DifficultySection : SetupSection + public partial class DifficultySection : SetupSection { - private LabelledSliderBar circleSizeSlider = null!; - private LabelledSliderBar healthDrainSlider = null!; - private LabelledSliderBar approachRateSlider = null!; - private LabelledSliderBar overallDifficultySlider = null!; - private LabelledSliderBar baseVelocitySlider = null!; - private LabelledSliderBar tickRateSlider = null!; + protected LabelledSliderBar CircleSizeSlider = null!; + protected LabelledSliderBar HealthDrainSlider = null!; + protected LabelledSliderBar ApproachRateSlider = null!; + protected LabelledSliderBar OverallDifficultySlider = null!; + protected LabelledSliderBar BaseVelocitySlider = null!; + protected LabelledSliderBar TickRateSlider = null!; public override LocalisableString Title => EditorSetupStrings.DifficultyHeader; @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Edit.Setup { Children = new Drawable[] { - circleSizeSlider = new LabelledSliderBar + CircleSizeSlider = new LabelledSliderBar { Label = BeatmapsetsStrings.ShowStatsCs, FixedLabelWidth = LABEL_WIDTH, @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Edit.Setup Precision = 0.1f, } }, - healthDrainSlider = new LabelledSliderBar + HealthDrainSlider = new LabelledSliderBar { Label = BeatmapsetsStrings.ShowStatsDrain, FixedLabelWidth = LABEL_WIDTH, @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Edit.Setup Precision = 0.1f, } }, - approachRateSlider = new LabelledSliderBar + ApproachRateSlider = new LabelledSliderBar { Label = BeatmapsetsStrings.ShowStatsAr, FixedLabelWidth = LABEL_WIDTH, @@ -68,7 +68,7 @@ namespace osu.Game.Screens.Edit.Setup Precision = 0.1f, } }, - overallDifficultySlider = new LabelledSliderBar + OverallDifficultySlider = new LabelledSliderBar { Label = BeatmapsetsStrings.ShowStatsAccuracy, FixedLabelWidth = LABEL_WIDTH, @@ -81,7 +81,7 @@ namespace osu.Game.Screens.Edit.Setup Precision = 0.1f, } }, - baseVelocitySlider = new LabelledSliderBar + BaseVelocitySlider = new LabelledSliderBar { Label = EditorSetupStrings.BaseVelocity, FixedLabelWidth = LABEL_WIDTH, @@ -94,7 +94,7 @@ namespace osu.Game.Screens.Edit.Setup Precision = 0.01f, } }, - tickRateSlider = new LabelledSliderBar + TickRateSlider = new LabelledSliderBar { Label = EditorSetupStrings.TickRate, FixedLabelWidth = LABEL_WIDTH, @@ -120,12 +120,12 @@ namespace osu.Game.Screens.Edit.Setup { // for now, update these on commit rather than making BeatmapMetadata bindables. // after switching database engines we can reconsider if switching to bindables is a good direction. - Beatmap.Difficulty.CircleSize = circleSizeSlider.Current.Value; - Beatmap.Difficulty.DrainRate = healthDrainSlider.Current.Value; - Beatmap.Difficulty.ApproachRate = approachRateSlider.Current.Value; - Beatmap.Difficulty.OverallDifficulty = overallDifficultySlider.Current.Value; - Beatmap.Difficulty.SliderMultiplier = baseVelocitySlider.Current.Value; - Beatmap.Difficulty.SliderTickRate = tickRateSlider.Current.Value; + Beatmap.Difficulty.CircleSize = CircleSizeSlider.Current.Value; + Beatmap.Difficulty.DrainRate = HealthDrainSlider.Current.Value; + Beatmap.Difficulty.ApproachRate = ApproachRateSlider.Current.Value; + Beatmap.Difficulty.OverallDifficulty = OverallDifficultySlider.Current.Value; + Beatmap.Difficulty.SliderMultiplier = BaseVelocitySlider.Current.Value; + Beatmap.Difficulty.SliderTickRate = TickRateSlider.Current.Value; Beatmap.UpdateAllHitObjects(); Beatmap.SaveState(); diff --git a/osu.Game/Screens/Edit/Setup/SetupScreen.cs b/osu.Game/Screens/Edit/Setup/SetupScreen.cs index ab4299a2f0..266ea1f929 100644 --- a/osu.Game/Screens/Edit/Setup/SetupScreen.cs +++ b/osu.Game/Screens/Edit/Setup/SetupScreen.cs @@ -26,16 +26,18 @@ namespace osu.Game.Screens.Edit.Setup [BackgroundDependencyLoader] private void load(EditorBeatmap beatmap, OverlayColourProvider colourProvider) { + var ruleset = beatmap.BeatmapInfo.Ruleset.CreateInstance(); + var sectionsEnumerable = new List { new ResourcesSection(), new MetadataSection(), - new DifficultySection(), + ruleset.CreateEditorDifficultySection() ?? new DifficultySection(), new ColoursSection(), new DesignSection(), }; - var rulesetSpecificSection = beatmap.BeatmapInfo.Ruleset.CreateInstance().CreateEditorSetupSection(); + var rulesetSpecificSection = ruleset.CreateEditorSetupSection(); if (rulesetSpecificSection != null) sectionsEnumerable.Add(rulesetSpecificSection); From 2ef843261ba3a9176394c86bfe50f12d84ca4320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 21 Jul 2023 19:08:40 +0200 Subject: [PATCH 066/118] Adjust failing test after metrics changes --- .../Visual/Editing/TestSceneHitObjectComposer.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs index 9bdb9a513c..a38c481003 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs @@ -117,9 +117,9 @@ namespace osu.Game.Tests.Visual.Editing AddStep("move mouse to overlapping toggle button", () => { var playfield = hitObjectComposer.Playfield.ScreenSpaceDrawQuad; - var button = toolboxContainer.ChildrenOfType().First(b => playfield.Contains(b.ScreenSpaceDrawQuad.Centre)); + var button = toolboxContainer.ChildrenOfType().First(b => playfield.Contains(getOverlapPoint(b))); - InputManager.MoveMouseTo(button); + InputManager.MoveMouseTo(getOverlapPoint(button)); }); AddAssert("no circles placed", () => editorBeatmap.HitObjects.Count == 0); @@ -127,6 +127,12 @@ namespace osu.Game.Tests.Visual.Editing AddStep("attempt place circle", () => InputManager.Click(MouseButton.Left)); AddAssert("no circles placed", () => editorBeatmap.HitObjects.Count == 0); + + Vector2 getOverlapPoint(DrawableTernaryButton ternaryButton) + { + var quad = ternaryButton.ScreenSpaceDrawQuad; + return quad.TopLeft + new Vector2(quad.Width * 9 / 10, quad.Height / 2); + } } [Test] From 7ace50f442c460845c3d1b8c736bc6160678c34d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 21 Jul 2023 21:17:14 +0200 Subject: [PATCH 067/118] Touch up dialogs a bit --- ...itorDeleteRoundDialog.cs => DeleteRoundDialog.cs} | 7 ++++--- ...EditorDeleteTeamDialog.cs => DeleteTeamDialog.cs} | 9 +++++---- .../Screens/Editors/RoundEditorScreen.cs | 12 +++++------- .../Screens/Editors/TeamEditorScreen.cs | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) rename osu.Game.Tournament/Screens/Editors/Components/{RoundEditorDeleteRoundDialog.cs => DeleteRoundDialog.cs} (58%) rename osu.Game.Tournament/Screens/Editors/Components/{TeamEditorDeleteTeamDialog.cs => DeleteTeamDialog.cs} (55%) diff --git a/osu.Game.Tournament/Screens/Editors/Components/RoundEditorDeleteRoundDialog.cs b/osu.Game.Tournament/Screens/Editors/Components/DeleteRoundDialog.cs similarity index 58% rename from osu.Game.Tournament/Screens/Editors/Components/RoundEditorDeleteRoundDialog.cs rename to osu.Game.Tournament/Screens/Editors/Components/DeleteRoundDialog.cs index 629cd4e135..769412bf94 100644 --- a/osu.Game.Tournament/Screens/Editors/Components/RoundEditorDeleteRoundDialog.cs +++ b/osu.Game.Tournament/Screens/Editors/Components/DeleteRoundDialog.cs @@ -4,14 +4,15 @@ using System; using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; +using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens.Editors.Components { - public partial class RoundEditorDeleteRoundDialog : DangerousActionDialog + public partial class DeleteRoundDialog : DangerousActionDialog { - public RoundEditorDeleteRoundDialog(string roundName, Action action) + public DeleteRoundDialog(TournamentRound round, Action action) { - HeaderText = roundName.Length > 0 ? $@"Delete round ""{roundName}""?" : @"Delete unnamed round?"; + HeaderText = round.Name.Value.Length > 0 ? $@"Delete round ""{round.Name.Value}""?" : @"Delete unnamed round?"; Icon = FontAwesome.Solid.Trash; DangerousAction = action; } diff --git a/osu.Game.Tournament/Screens/Editors/Components/TeamEditorDeleteTeamDialog.cs b/osu.Game.Tournament/Screens/Editors/Components/DeleteTeamDialog.cs similarity index 55% rename from osu.Game.Tournament/Screens/Editors/Components/TeamEditorDeleteTeamDialog.cs rename to osu.Game.Tournament/Screens/Editors/Components/DeleteTeamDialog.cs index f91b58e185..65fb47cf94 100644 --- a/osu.Game.Tournament/Screens/Editors/Components/TeamEditorDeleteTeamDialog.cs +++ b/osu.Game.Tournament/Screens/Editors/Components/DeleteTeamDialog.cs @@ -4,15 +4,16 @@ using System; using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; +using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens.Editors.Components { - public partial class TeamEditorDeleteTeamDialog : DangerousActionDialog + public partial class DeleteTeamDialog : DangerousActionDialog { - public TeamEditorDeleteTeamDialog(string fullTeamName, string acronym, Action action) + public DeleteTeamDialog(TournamentTeam team, Action action) { - HeaderText = fullTeamName.Length > 0 ? $@"Delete team ""{fullTeamName}""?" : - acronym.Length > 0 ? $@"Delete team ""{acronym}""?" : + HeaderText = team.FullName.Value.Length > 0 ? $@"Delete team ""{team.FullName.Value}""?" : + team.Acronym.Value.Length > 0 ? $@"Delete team ""{team.Acronym.Value}""?" : @"Delete unnamed team?"; Icon = FontAwesome.Solid.Trash; DangerousAction = action; diff --git a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index 712a724d4d..6c1e7d9200 100644 --- a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -104,13 +104,11 @@ namespace osu.Game.Tournament.Screens.Editors RelativeSizeAxes = Axes.None, Width = 150, Text = "Delete Round", - Action = () => dialogOverlay?.Push( - new RoundEditorDeleteRoundDialog( - Model.Name.Value, () => - { - Expire(); - ladderInfo.Rounds.Remove(Model); - })) + Action = () => dialogOverlay?.Push(new DeleteRoundDialog(Model, () => + { + Expire(); + ladderInfo.Rounds.Remove(Model); + })) } }; diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index aa55c75483..29616292ee 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -162,7 +162,7 @@ namespace osu.Game.Tournament.Screens.Editors Text = "Delete Team", Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - Action = () => dialogOverlay?.Push(new TeamEditorDeleteTeamDialog(Model.FullName.Value, Model.Acronym.Value, () => + Action = () => dialogOverlay?.Push(new DeleteTeamDialog(Model, () => { Expire(); ladderInfo.Teams.Remove(Model); From d055d16ba78f24854bb3722f2d101106b29f0520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 21 Jul 2023 21:18:49 +0200 Subject: [PATCH 068/118] Remove superfluous `CanBeNull` dependency specs As stated before, not required in NRT-annotated files if auto-properties are already marked nullable. --- osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs | 2 +- osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs | 2 +- osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index 6c1e7d9200..ff6657324d 100644 --- a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -31,7 +31,7 @@ namespace osu.Game.Tournament.Screens.Editors [Resolved] private LadderInfo ladderInfo { get; set; } = null!; - [Resolved(canBeNull: true)] + [Resolved] private IDialogOverlay? dialogOverlay { get; set; } public RoundRow(TournamentRound round) diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index 29616292ee..241692d515 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -63,7 +63,7 @@ namespace osu.Game.Tournament.Screens.Editors [Resolved] private TournamentSceneManager? sceneManager { get; set; } - [Resolved(canBeNull: true)] + [Resolved] private IDialogOverlay? dialogOverlay { get; set; } [Resolved] diff --git a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs index aa9f83ba21..9dd028fa79 100644 --- a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs @@ -26,7 +26,7 @@ namespace osu.Game.Tournament.Screens.Editors { protected abstract BindableList Storage { get; } - [Resolved(canBeNull: true)] + [Resolved] private IDialogOverlay? dialogOverlay { get; set; } private FillFlowContainer flow = null!; From 92c40c9cedd506e369f5059819c35e19aac5b144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 21 Jul 2023 21:20:22 +0200 Subject: [PATCH 069/118] Remove superfluous container --- osu.Game.Tournament/TournamentGame.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index 97292c09aa..39d19261e6 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -11,7 +11,6 @@ using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Containers; using osu.Framework.Input.Handlers.Mouse; using osu.Framework.Logging; using osu.Framework.Platform; @@ -101,7 +100,7 @@ namespace osu.Game.Tournament RelativeSizeAxes = Axes.Both, Child = new TournamentSceneManager() }, - new Container { RelativeSizeAxes = Axes.Both, Child = dialogOverlay } + dialogOverlay }, drawables => { loadingSpinner.Hide(); From e0fe5c77d56722ef93afbcab6f2769dc9841e835 Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Sat, 22 Jul 2023 09:44:02 +0100 Subject: [PATCH 070/118] add reload tournaments list button to tourney setup screen --- .../Screens/Setup/TournamentSwitcher.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs index 2d57757ad9..0852161db8 100644 --- a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs +++ b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs @@ -15,6 +15,7 @@ namespace osu.Game.Tournament.Screens.Setup { private OsuDropdown dropdown; private OsuButton folderButton; + private OsuButton reloadTournamentsButton; [Resolved] private TournamentGameBase game { get; set; } @@ -28,6 +29,9 @@ namespace osu.Game.Tournament.Screens.Setup dropdown.Items = storage.ListTournaments(); dropdown.Current.BindValueChanged(v => Button.Enabled.Value = v.NewValue != startupTournament, true); + reloadTournamentsButton.Enabled.Value = true; + reloadTournamentsButton.Action = () => dropdown.Items = storage.ListTournaments(); + Action = () => { game.RestartAppWhenExited(); @@ -48,7 +52,13 @@ namespace osu.Game.Tournament.Screens.Setup Width = BUTTON_SIZE }); - FlowContainer.Insert(-2, dropdown = new OsuDropdown + FlowContainer.Insert(-2, reloadTournamentsButton = new RoundedButton + { + Text = "Reload list", + Width = BUTTON_SIZE + }); + + FlowContainer.Insert(-3, dropdown = new OsuDropdown { Width = 510 }); From ef74084a2ed11ef9bb1b0e393b2bc646532739e1 Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Sat, 22 Jul 2023 09:59:00 +0100 Subject: [PATCH 071/118] make list of tournaments in SetupScreen dropdown alphabetically sorted --- osu.Game.Tournament/IO/TournamentStorage.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/IO/TournamentStorage.cs b/osu.Game.Tournament/IO/TournamentStorage.cs index e59f90a45e..7c5f3e44a7 100644 --- a/osu.Game.Tournament/IO/TournamentStorage.cs +++ b/osu.Game.Tournament/IO/TournamentStorage.cs @@ -1,7 +1,9 @@ // 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 System.Linq; using osu.Framework.Bindables; using osu.Framework.Logging; using osu.Framework.Platform; @@ -43,6 +45,6 @@ namespace osu.Game.Tournament.IO Logger.Log("Changing tournament storage: " + GetFullPath(string.Empty)); } - public IEnumerable ListTournaments() => AllTournaments.GetDirectories(string.Empty); + public IEnumerable ListTournaments() => AllTournaments.GetDirectories(string.Empty).OrderBy(directory => directory, StringComparer.CurrentCultureIgnoreCase); } } From 101f3eca2546d60e02a3b7ab22382045f4234869 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Jul 2023 21:01:32 +0900 Subject: [PATCH 072/118] Rename button slightly --- osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs index 0852161db8..bf3e410aca 100644 --- a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs +++ b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs @@ -54,7 +54,7 @@ namespace osu.Game.Tournament.Screens.Setup FlowContainer.Insert(-2, reloadTournamentsButton = new RoundedButton { - Text = "Reload list", + Text = "Refresh", Width = BUTTON_SIZE }); From a59876ce13b4c16c374eb2b1b151d0ec54ae4e7f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Jul 2023 21:03:13 +0900 Subject: [PATCH 073/118] Remove unnecessary enable call --- osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs index bf3e410aca..ae49ccb63b 100644 --- a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs +++ b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs @@ -29,7 +29,6 @@ namespace osu.Game.Tournament.Screens.Setup dropdown.Items = storage.ListTournaments(); dropdown.Current.BindValueChanged(v => Button.Enabled.Value = v.NewValue != startupTournament, true); - reloadTournamentsButton.Enabled.Value = true; reloadTournamentsButton.Action = () => dropdown.Items = storage.ListTournaments(); Action = () => From f985bdc10f5e5f26f3fb3011030d99cae6fb1926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 22 Jul 2023 15:55:20 +0200 Subject: [PATCH 074/118] Make difficulty sliders `private set` --- osu.Game/Screens/Edit/Setup/DifficultySection.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs index 3954271290..1915b0cfd1 100644 --- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs @@ -15,12 +15,12 @@ namespace osu.Game.Screens.Edit.Setup { public partial class DifficultySection : SetupSection { - protected LabelledSliderBar CircleSizeSlider = null!; - protected LabelledSliderBar HealthDrainSlider = null!; - protected LabelledSliderBar ApproachRateSlider = null!; - protected LabelledSliderBar OverallDifficultySlider = null!; - protected LabelledSliderBar BaseVelocitySlider = null!; - protected LabelledSliderBar TickRateSlider = null!; + protected LabelledSliderBar CircleSizeSlider { get; private set; } = null!; + protected LabelledSliderBar HealthDrainSlider { get; private set; } = null!; + protected LabelledSliderBar ApproachRateSlider { get; private set; } = null!; + protected LabelledSliderBar OverallDifficultySlider { get; private set; } = null!; + protected LabelledSliderBar BaseVelocitySlider { get; private set; } = null!; + protected LabelledSliderBar TickRateSlider { get; private set; } = null!; public override LocalisableString Title => EditorSetupStrings.DifficultyHeader; From 157aec5144e5030486193821f18335cc329c3637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 22 Jul 2023 16:10:58 +0200 Subject: [PATCH 075/118] Fix mania key count slider still using circle size precision --- osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs index 82ec66a28a..4f983debea 100644 --- a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs +++ b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Resources.Localisation.Web; using osu.Game.Screens.Edit.Setup; @@ -14,6 +15,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Setup { CircleSizeSlider.Label = BeatmapsetsStrings.ShowStatsCsMania; CircleSizeSlider.Description = "The number of columns in the beatmap"; + if (CircleSizeSlider.Current is BindableNumber circleSizeFloat) + circleSizeFloat.Precision = 1; } } } From 699b66be4228d220325e63c9361fdef34141a7f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 22 Jul 2023 17:12:21 +0200 Subject: [PATCH 076/118] Do not reimplement binary sort manually --- osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs | 55 +++++--------------- 1 file changed, 13 insertions(+), 42 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs b/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs index 44d2c18dad..94369443c2 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; using osu.Game.Beatmaps.Timing; using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Objects; @@ -30,66 +31,36 @@ namespace osu.Game.Rulesets.Edit.Checks public IEnumerable Run(BeatmapVerifierContext context) { + var startTimes = context.Beatmap.HitObjects.Select(ho => ho.StartTime).OrderBy(x => x).ToList(); + var endTimes = context.Beatmap.HitObjects.Select(ho => ho.GetEndTime()).OrderBy(x => x).ToList(); + foreach (var breakPeriod in context.Beatmap.Breaks) { if (breakPeriod.Duration < BreakPeriod.MIN_BREAK_DURATION) yield return new IssueTemplateTooShort(this).Create(breakPeriod.StartTime); - var previousObject = getPreviousObject(breakPeriod.StartTime, context.Beatmap.HitObjects); - var nextObject = getNextObject(breakPeriod.EndTime, context.Beatmap.HitObjects); + int previousObjectEndTimeIndex = endTimes.BinarySearch(breakPeriod.StartTime); + if (previousObjectEndTimeIndex < 0) previousObjectEndTimeIndex = ~previousObjectEndTimeIndex - 1; - if (previousObject != null) + if (previousObjectEndTimeIndex >= 0) { - double gapBeforeBreak = breakPeriod.StartTime - previousObject.GetEndTime(); + double gapBeforeBreak = breakPeriod.StartTime - endTimes[previousObjectEndTimeIndex]; if (gapBeforeBreak < minimum_gap_before_break - leniency_threshold) yield return new IssueTemplateEarlyStart(this).Create(breakPeriod.StartTime, minimum_gap_before_break - gapBeforeBreak); } - if (nextObject != null) + int nextObjectStartTimeIndex = startTimes.BinarySearch(breakPeriod.EndTime); + if (nextObjectStartTimeIndex < 0) nextObjectStartTimeIndex = ~nextObjectStartTimeIndex; + + if (nextObjectStartTimeIndex < startTimes.Count) { - double gapAfterBreak = nextObject.StartTime - breakPeriod.EndTime; + double gapAfterBreak = startTimes[nextObjectStartTimeIndex] - breakPeriod.EndTime; if (gapAfterBreak < min_end_threshold - leniency_threshold) yield return new IssueTemplateLateEnd(this).Create(breakPeriod.StartTime, min_end_threshold - gapAfterBreak); } } } - private HitObject? getPreviousObject(double time, IReadOnlyList hitObjects) - { - int left = 0; - int right = hitObjects.Count - 1; - - while (left <= right) - { - int mid = left + (right - left) / 2; - - if (hitObjects[mid].GetEndTime() < time) - left = mid + 1; - else - right = mid - 1; - } - - return right >= 0 ? hitObjects[right] : null; - } - - private HitObject? getNextObject(double time, IReadOnlyList hitObjects) - { - int left = 0; - int right = hitObjects.Count - 1; - - while (left <= right) - { - int mid = left + (right - left) / 2; - - if (hitObjects[mid].StartTime <= time) - left = mid + 1; - else - right = mid - 1; - } - - return left < hitObjects.Count ? hitObjects[left] : null; - } - public class IssueTemplateEarlyStart : IssueTemplate { public IssueTemplateEarlyStart(ICheck check) From 2df6e91176a91b391f14461ff8f01396f1ba0725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 22 Jul 2023 17:12:35 +0200 Subject: [PATCH 077/118] Add extra test coverage for breaks before first/after last object --- .../Editing/Checks/CheckBreaksTest.cs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/osu.Game.Tests/Editing/Checks/CheckBreaksTest.cs b/osu.Game.Tests/Editing/Checks/CheckBreaksTest.cs index aaa536f9b9..28556566ba 100644 --- a/osu.Game.Tests/Editing/Checks/CheckBreaksTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckBreaksTest.cs @@ -88,6 +88,52 @@ namespace osu.Game.Tests.Editing.Checks Assert.That(issues.Single().Template is CheckBreaks.IssueTemplateLateEnd); } + [Test] + public void TestBreakAfterLastObjectStartsEarly() + { + var beatmap = new Beatmap + { + HitObjects = + { + new HitCircle { StartTime = 0 }, + new HitCircle { StartTime = 1200 } + }, + Breaks = new List + { + new BreakPeriod(1398, 2300) + } + }; + var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckBreaks.IssueTemplateEarlyStart); + } + + [Test] + public void TestBreakBeforeFirstObjectEndsLate() + { + var beatmap = new Beatmap + { + HitObjects = + { + new HitCircle { StartTime = 1100 }, + new HitCircle { StartTime = 1500 } + }, + Breaks = new List + { + new BreakPeriod(0, 652) + } + }; + var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckBreaks.IssueTemplateLateEnd); + } + [Test] public void TestBreakMultipleObjectsEarly() { From 647f2b67153f1ee0bb172c390421eb34eaa64607 Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Sat, 22 Jul 2023 23:08:20 +0100 Subject: [PATCH 078/118] fix auto advance screens sometimes not working --- osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs | 6 ++++++ osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index f2a2e97bcc..a921a29abd 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -232,6 +232,12 @@ namespace osu.Game.Tournament.Screens.Gameplay } } + public override void Hide() + { + scheduledOperation?.Cancel(); + base.Hide(); + } + private partial class ChromaArea : CompositeDrawable { [Resolved] diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index cb6c5902ec..f0e65e3158 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -222,6 +222,12 @@ namespace osu.Game.Tournament.Screens.MapPool } } + public override void Hide() + { + scheduledChange?.Cancel(); + base.Hide(); + } + protected override void CurrentMatchChanged(ValueChangedEvent match) { base.CurrentMatchChanged(match); From d11e56b8bb6ade5c4f6e47de5fa288a909f6bc66 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Jul 2023 14:03:35 +0900 Subject: [PATCH 079/118] Add common `Export` string and use in editor --- osu.Game/Localisation/CommonStrings.cs | 5 +++++ osu.Game/Localisation/EditorStrings.cs | 5 ----- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 2 +- osu.Game/Screens/Edit/Editor.cs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Localisation/CommonStrings.cs b/osu.Game/Localisation/CommonStrings.cs index c9223db246..480d68619d 100644 --- a/osu.Game/Localisation/CommonStrings.cs +++ b/osu.Game/Localisation/CommonStrings.cs @@ -39,6 +39,11 @@ namespace osu.Game.Localisation /// public static LocalisableString Default => new TranslatableString(getKey(@"default"), @"Default"); + /// + /// "Export" + /// + public static LocalisableString Export => new TranslatableString(getKey(@"export"), @"Export"); + /// /// "Width" /// diff --git a/osu.Game/Localisation/EditorStrings.cs b/osu.Game/Localisation/EditorStrings.cs index 07b4dddc05..7ff4d9a7ca 100644 --- a/osu.Game/Localisation/EditorStrings.cs +++ b/osu.Game/Localisation/EditorStrings.cs @@ -34,11 +34,6 @@ namespace osu.Game.Localisation /// public static LocalisableString SetPreviewPointToCurrent => new TranslatableString(getKey(@"set_preview_point_to_current"), @"Set preview point to current time"); - /// - /// "Export package" - /// - public static LocalisableString ExportPackage => new TranslatableString(getKey(@"export_package"), @"Export package"); - /// /// "Legacy format (.osz)" /// diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index e4ea277756..229cfd2aa6 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -425,7 +425,7 @@ namespace osu.Game.Online.Leaderboards if (Score.Files.Count > 0) { - items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => scoreManager.Export(Score))); + items.Add(new OsuMenuItem(Localisation.CommonStrings.Export, MenuItemType.Standard, () => scoreManager.Export(Score))); items.Add(new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new LocalScoreDeleteDialog(Score)))); } diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 16cd7768fa..0ec6abbc63 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -1016,7 +1016,7 @@ namespace osu.Game.Screens.Edit new EditorMenuItem(EditorStrings.ExportLegacyFormat, MenuItemType.Standard, exportLegacyBeatmap) { Action = { Disabled = !RuntimeInfo.IsDesktop } }, }; - return new EditorMenuItem(EditorStrings.ExportPackage) { Items = exportItems }; + return new EditorMenuItem(CommonStrings.Export) { Items = exportItems }; } private void exportBeatmap() From 20359c90bc589b149dc7f827c253b6e28539115a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Jul 2023 14:05:44 +0900 Subject: [PATCH 080/118] Adjust localisations slightly --- osu.Game/Localisation/EditorStrings.cs | 8 ++++---- osu.Game/Screens/Edit/Editor.cs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Localisation/EditorStrings.cs b/osu.Game/Localisation/EditorStrings.cs index 7ff4d9a7ca..93e52746c5 100644 --- a/osu.Game/Localisation/EditorStrings.cs +++ b/osu.Game/Localisation/EditorStrings.cs @@ -35,14 +35,14 @@ namespace osu.Game.Localisation public static LocalisableString SetPreviewPointToCurrent => new TranslatableString(getKey(@"set_preview_point_to_current"), @"Set preview point to current time"); /// - /// "Legacy format (.osz)" + /// "For editing (.olz)" /// - public static LocalisableString ExportLegacyFormat => new TranslatableString(getKey(@"export_legacy_format"), @"Legacy format (.osz)"); + public static LocalisableString ExportForEditing => new TranslatableString(getKey(@"export_for_editing"), @"For editing (.olz)"); /// - /// "New format (.olz)" + /// "For compatibility (.osz)" /// - public static LocalisableString ExportNewFormat => new TranslatableString(getKey(@"export_new_format"), @"New format (.olz)"); + public static LocalisableString ExportForCompatibility => new TranslatableString(getKey(@"export_for_compatibility"), @"For compatibility (.osz)"); /// /// "Create new difficulty" diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 0ec6abbc63..6558554b01 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -998,7 +998,7 @@ namespace osu.Game.Screens.Edit private List createFileMenuItems() => new List { new EditorMenuItem(WebCommonStrings.ButtonsSave, MenuItemType.Standard, () => Save()), - createExportPackageMenu(), + createExportMenu(), new EditorMenuItemSpacer(), createDifficultyCreationMenu(), createDifficultySwitchMenu(), @@ -1008,12 +1008,12 @@ namespace osu.Game.Screens.Edit new EditorMenuItem(CommonStrings.Exit, MenuItemType.Standard, this.Exit) }; - private EditorMenuItem createExportPackageMenu() + private EditorMenuItem createExportMenu() { var exportItems = new List { - new EditorMenuItem(EditorStrings.ExportNewFormat, MenuItemType.Standard, exportBeatmap) { Action = { Disabled = !RuntimeInfo.IsDesktop } }, - new EditorMenuItem(EditorStrings.ExportLegacyFormat, MenuItemType.Standard, exportLegacyBeatmap) { Action = { Disabled = !RuntimeInfo.IsDesktop } }, + new EditorMenuItem(EditorStrings.ExportForEditing, MenuItemType.Standard, exportBeatmap) { Action = { Disabled = !RuntimeInfo.IsDesktop } }, + new EditorMenuItem(EditorStrings.ExportForCompatibility, MenuItemType.Standard, exportLegacyBeatmap) { Action = { Disabled = !RuntimeInfo.IsDesktop } }, }; return new EditorMenuItem(CommonStrings.Export) { Items = exportItems }; From fb34ee94c2f451c4fa5ffe4749f970da75d4154a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Jul 2023 14:07:31 +0900 Subject: [PATCH 081/118] Move export/save options to bottom of menu --- osu.Game/Screens/Edit/Editor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 6558554b01..672551e088 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -997,14 +997,14 @@ namespace osu.Game.Screens.Edit private List createFileMenuItems() => new List { - new EditorMenuItem(WebCommonStrings.ButtonsSave, MenuItemType.Standard, () => Save()), - createExportMenu(), - new EditorMenuItemSpacer(), createDifficultyCreationMenu(), createDifficultySwitchMenu(), new EditorMenuItemSpacer(), new EditorMenuItem(EditorStrings.DeleteDifficulty, MenuItemType.Standard, deleteDifficulty) { Action = { Disabled = Beatmap.Value.BeatmapSetInfo.Beatmaps.Count < 2 } }, new EditorMenuItemSpacer(), + new EditorMenuItem(WebCommonStrings.ButtonsSave, MenuItemType.Standard, () => Save()), + createExportMenu(), + new EditorMenuItemSpacer(), new EditorMenuItem(CommonStrings.Exit, MenuItemType.Standard, this.Exit) }; From 4ea8495c610cd91d66f0afce8cf00edd74d95ad1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Jul 2023 14:12:37 +0900 Subject: [PATCH 082/118] Adjust metrics of editor menu spacers (and make visible) --- .../Screens/Edit/Components/Menus/EditorMenuBar.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs index b9385ff0c3..fb0ae2df73 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.UserInterface; @@ -200,7 +201,17 @@ namespace osu.Game.Screens.Edit.Components.Menus public DrawableSpacer(MenuItem item) : base(item) { - Scale = new Vector2(1, 0.3f); + Scale = new Vector2(1, 0.6f); + + AddInternal(new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Colour = BackgroundColourHover, + RelativeSizeAxes = Axes.X, + Height = 2f, + Width = 0.8f, + }); } protected override bool OnHover(HoverEvent e) => true; From 1a76f6441a67a2d189d2ea3898f83d9a596964e4 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 23 Jul 2023 15:32:12 +0900 Subject: [PATCH 083/118] add MatchScoreDiffCounter Intuitively show the score difference between the two teams --- .../Components/TournamentMatchScoreDisplay.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs index bd1f3a2dd0..bc7886eb7e 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs @@ -28,6 +28,8 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components private readonly MatchScoreCounter score1Text; private readonly MatchScoreCounter score2Text; + private readonly MatchScoreDiffCounter scoreDiffText; + private readonly Drawable score1Bar; private readonly Drawable score2Bar; @@ -88,6 +90,11 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre }, + scoreDiffText = new MatchScoreDiffCounter + { + Anchor = Anchor.TopCentre, + Alpha = 0 + } }; } @@ -119,6 +126,16 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components losingBar.ResizeWidthTo(0, 400, Easing.OutQuint); winningBar.ResizeWidthTo(Math.Min(0.4f, MathF.Pow(diff / 1500000f, 0.5f) / 2), 400, Easing.OutQuint); + + if (diff == 0) + { + scoreDiffText.Hide(); + return; + } + + scoreDiffText.Show(); + scoreDiffText.Current.Value = -diff; + scoreDiffText.Origin = score1.Value > score2.Value ? Anchor.TopLeft : Anchor.TopRight; } protected override void UpdateAfterChildren() @@ -154,5 +171,19 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components ? OsuFont.Torus.With(weight: FontWeight.Bold, size: 50, fixedWidth: true) : OsuFont.Torus.With(weight: FontWeight.Regular, size: 40, fixedWidth: true); } + + private partial class MatchScoreDiffCounter : CommaSeparatedScoreCounter + { + public MatchScoreDiffCounter() + { + Margin = new MarginPadding { Top = bar_height / 4, Horizontal = 10 }; + } + + protected override OsuSpriteText CreateSpriteText() => base.CreateSpriteText().With(s => + { + s.Spacing = new Vector2(-1); + s.Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: bar_height, fixedWidth: true); + }); + } } } From 3b47949ace8a36cea6ca364334421fc810b7ac60 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Jul 2023 17:04:57 +0900 Subject: [PATCH 084/118] Avoid transform overhead on every frame --- .../Gameplay/Components/TournamentMatchScoreDisplay.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs index bc7886eb7e..e8a5396a37 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs @@ -127,13 +127,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components losingBar.ResizeWidthTo(0, 400, Easing.OutQuint); winningBar.ResizeWidthTo(Math.Min(0.4f, MathF.Pow(diff / 1500000f, 0.5f) / 2), 400, Easing.OutQuint); - if (diff == 0) - { - scoreDiffText.Hide(); - return; - } - - scoreDiffText.Show(); + scoreDiffText.Alpha = diff != 0 ? 1 : 0; scoreDiffText.Current.Value = -diff; scoreDiffText.Origin = score1.Value > score2.Value ? Anchor.TopLeft : Anchor.TopRight; } From 7e4e96a4a95dbdbb59effd21b55f9e36310283ed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Jul 2023 17:05:04 +0900 Subject: [PATCH 085/118] Adjust spacing and clean up code --- .../Components/TournamentMatchScoreDisplay.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs index e8a5396a37..838e5fa071 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs @@ -93,6 +93,11 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components scoreDiffText = new MatchScoreDiffCounter { Anchor = Anchor.TopCentre, + Margin = new MarginPadding + { + Top = bar_height / 4, + Horizontal = 8 + }, Alpha = 0 } }; @@ -168,14 +173,9 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components private partial class MatchScoreDiffCounter : CommaSeparatedScoreCounter { - public MatchScoreDiffCounter() - { - Margin = new MarginPadding { Top = bar_height / 4, Horizontal = 10 }; - } - protected override OsuSpriteText CreateSpriteText() => base.CreateSpriteText().With(s => { - s.Spacing = new Vector2(-1); + s.Spacing = new Vector2(-2); s.Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: bar_height, fixedWidth: true); }); } From 3049d159d8bca2340ca89853ced370abf3919678 Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Sun, 23 Jul 2023 10:39:47 +0100 Subject: [PATCH 086/118] avoid potentially cancelling `contract` when switching away from GameplayScreen --- .../Screens/Gameplay/GameplayScreen.cs | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index a921a29abd..7a54c6fe90 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -3,6 +3,7 @@ #nullable disable +using System.Diagnostics.Contracts; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -159,6 +160,25 @@ namespace osu.Game.Tournament.Screens.Gameplay private TourneyState lastState; private MatchHeader header; + private void contract() + { + SongBar.Expanded = false; + scoreDisplay.FadeOut(100); + using (chat?.BeginDelayedSequence(500)) + chat?.Expand(); + } + + private void expand() + { + chat?.Contract(); + + using (BeginDelayedSequence(300)) + { + scoreDisplay.FadeIn(100); + SongBar.Expanded = true; + } + } + private void stateChanged(ValueChangedEvent state) { try @@ -175,25 +195,6 @@ namespace osu.Game.Tournament.Screens.Gameplay scheduledOperation?.Cancel(); - void expand() - { - chat?.Contract(); - - using (BeginDelayedSequence(300)) - { - scoreDisplay.FadeIn(100); - SongBar.Expanded = true; - } - } - - void contract() - { - SongBar.Expanded = false; - scoreDisplay.FadeOut(100); - using (chat?.BeginDelayedSequence(500)) - chat?.Expand(); - } - switch (state.NewValue) { case TourneyState.Idle: @@ -234,7 +235,14 @@ namespace osu.Game.Tournament.Screens.Gameplay public override void Hide() { - scheduledOperation?.Cancel(); + if (scheduledOperation != null) + { + scheduledOperation.Cancel(); + + if (State.Value == TourneyState.Ranking) + contract(); + } + base.Hide(); } From 5a568eacb637d78eac4b11405a5e6a94bb735d45 Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Sun, 23 Jul 2023 10:44:00 +0100 Subject: [PATCH 087/118] remove unused `using` directive --- osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 7a54c6fe90..73193e6dbd 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -3,7 +3,6 @@ #nullable disable -using System.Diagnostics.Contracts; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; From 7813a3162b7a0d678d3ee5184fd3522a952ad6c7 Mon Sep 17 00:00:00 2001 From: Dao Heng Liu Date: Sun, 23 Jul 2023 12:01:58 +0100 Subject: [PATCH 088/118] run stateChanged upon unhiding of GameplayScreen --- .../Screens/Gameplay/GameplayScreen.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 73193e6dbd..ae05517385 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -234,17 +234,17 @@ namespace osu.Game.Tournament.Screens.Gameplay public override void Hide() { - if (scheduledOperation != null) - { - scheduledOperation.Cancel(); - - if (State.Value == TourneyState.Ranking) - contract(); - } + scheduledOperation?.Cancel(); base.Hide(); } + public override void Show() + { + stateChanged(new ValueChangedEvent(TourneyState.Idle, State.Value)); + base.Show(); + } + private partial class ChromaArea : CompositeDrawable { [Resolved] From a7f08358660f684a74764c34f28b027f2c132c33 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 23 Jul 2023 20:24:12 +0300 Subject: [PATCH 089/118] Enable AOT compilation on iOS release builds --- osu.iOS.props | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.iOS.props b/osu.iOS.props index 272e17a288..40873a1c6b 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -2,13 +2,20 @@ iPhone Developer true - - true $(NoWarn);MT7091 + + + true + + + + false + -all + ios-arm64 From 97075b0726f82cec03e4bb5a533e9e6d11bc8c1b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 23 Jul 2023 20:31:26 +0300 Subject: [PATCH 090/118] Fix iOS visual tests having unusual bundle identifiers --- osu.Game.Rulesets.Catch.Tests.iOS/Info.plist | 4 ++-- osu.Game.Rulesets.Mania.Tests.iOS/Info.plist | 4 ++-- osu.Game.Rulesets.Osu.Tests.iOS/Info.plist | 4 ++-- osu.Game.Rulesets.Taiko.Tests.iOS/Info.plist | 4 ++-- osu.Game.Tests.iOS/Info.plist | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/Info.plist b/osu.Game.Rulesets.Catch.Tests.iOS/Info.plist index 5ace6c07f5..f87043e1d1 100644 --- a/osu.Game.Rulesets.Catch.Tests.iOS/Info.plist +++ b/osu.Game.Rulesets.Catch.Tests.iOS/Info.plist @@ -5,7 +5,7 @@ CFBundleName osu.Game.Rulesets.Catch.Tests.iOS CFBundleIdentifier - ppy.osu-Game-Rulesets-Catch-Tests-iOS + sh.ppy.catch-ruleset-tests CFBundleShortVersionString 1.0 CFBundleVersion @@ -42,4 +42,4 @@ CADisableMinimumFrameDurationOnPhone - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/Info.plist b/osu.Game.Rulesets.Mania.Tests.iOS/Info.plist index ff5dde856e..740036309f 100644 --- a/osu.Game.Rulesets.Mania.Tests.iOS/Info.plist +++ b/osu.Game.Rulesets.Mania.Tests.iOS/Info.plist @@ -5,7 +5,7 @@ CFBundleName osu.Game.Rulesets.Mania.Tests.iOS CFBundleIdentifier - ppy.osu-Game-Rulesets-Mania-Tests-iOS + sh.ppy.mania-ruleset-tests CFBundleShortVersionString 1.0 CFBundleVersion @@ -42,4 +42,4 @@ CADisableMinimumFrameDurationOnPhone - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/Info.plist b/osu.Game.Rulesets.Osu.Tests.iOS/Info.plist index 1e33f2ff16..7f489874e7 100644 --- a/osu.Game.Rulesets.Osu.Tests.iOS/Info.plist +++ b/osu.Game.Rulesets.Osu.Tests.iOS/Info.plist @@ -5,7 +5,7 @@ CFBundleName osu.Game.Rulesets.Osu.Tests.iOS CFBundleIdentifier - ppy.osu-Game-Rulesets-Osu-Tests-iOS + sh.ppy.osu-ruleset-tests CFBundleShortVersionString 1.0 CFBundleVersion @@ -42,4 +42,4 @@ CADisableMinimumFrameDurationOnPhone - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/Info.plist b/osu.Game.Rulesets.Taiko.Tests.iOS/Info.plist index 76cb3c0db0..162ee75c22 100644 --- a/osu.Game.Rulesets.Taiko.Tests.iOS/Info.plist +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/Info.plist @@ -5,7 +5,7 @@ CFBundleName osu.Game.Rulesets.Taiko.Tests.iOS CFBundleIdentifier - ppy.osu-Game-Rulesets-Taiko-Tests-iOS + sh.ppy.taiko-ruleset-tests CFBundleShortVersionString 1.0 CFBundleVersion @@ -42,4 +42,4 @@ CADisableMinimumFrameDurationOnPhone - + \ No newline at end of file diff --git a/osu.Game.Tests.iOS/Info.plist b/osu.Game.Tests.iOS/Info.plist index ac661f6263..d2d0583e46 100644 --- a/osu.Game.Tests.iOS/Info.plist +++ b/osu.Game.Tests.iOS/Info.plist @@ -5,7 +5,7 @@ CFBundleName osu.Game.Tests.iOS CFBundleIdentifier - ppy.osu-Game-Tests-iOS + sh.ppy.osu-tests CFBundleShortVersionString 1.0 CFBundleVersion @@ -42,4 +42,4 @@ CADisableMinimumFrameDurationOnPhone - + \ No newline at end of file From bf89fbcd817aab251797b40d8a4942103c360109 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 24 Jul 2023 16:38:37 +0900 Subject: [PATCH 091/118] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index ed97f609cc..7f15d9fafd 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ true - +