diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardEncoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardEncoderTest.cs index ad6d0fb7c3..1b340ddd24 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardEncoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardEncoderTest.cs @@ -30,6 +30,23 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.That(decodedAfterEncode.Beatmap.BeatmapInfo.Metadata.BackgroundFile, Is.EqualTo("bg.jpg")); } + [Test] + public void TestBackgroundOffset() + { + var initial = createComponents(); + initial.Beatmap.BeatmapInfo.Metadata.BackgroundFile = "bg_offset.jpg"; + initial.Storyboard.BackgroundOffset = new Vector2(0, 45); + + var encoded = encode(initial); + var decodedAfterEncode = decode(encoded); + + Assert.Multiple(() => + { + Assert.That(decodedAfterEncode.Beatmap.BeatmapInfo.Metadata.BackgroundFile, Is.EqualTo("bg_offset.jpg")); + Assert.That(decodedAfterEncode.Storyboard.BackgroundOffset, Is.EqualTo(new Vector2(0, 45))); + }); + } + [Test] public void TestVideos() { diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index eb1dacb447..563ef78362 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -120,6 +120,20 @@ namespace osu.Game.Beatmaps.Formats switch (type) { + case LegacyEventType.Background: + { + // the actual filename is handled in `LegacyBeatmapDecoder`. + // this only handles the background offset, because it does not logically belong in `Beatmap` or related classes. + if (split.Length > 4) + { + float x = Parsing.ParseFloat(split[3]); + float y = Parsing.ParseFloat(split[4]); + storyboard.BackgroundOffset = new Vector2(x, y); + } + + break; + } + case LegacyEventType.Video: { int offset = Parsing.ParseInt(split[1]); diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardEncoder.cs index 7238f2e7af..09148899e7 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardEncoder.cs @@ -54,10 +54,9 @@ namespace osu.Game.Beatmaps.Formats if (target == StoryboardElementSource.Beatmap) { // https://github.com/peppy/osu-stable-reference/blob/c34a74fb61c17c5667486a12548485d1f03baa2e/osu!/GameplayElements/HitObjectManager_LoadSave.cs#L1499 - // TODO: handle nonzero background offset (https://github.com/ppy/osu/issues/14238) writer.WriteLine(string.Format(CultureInfo.InvariantCulture, @"{0},{1},""{2}"",{3},{4}", - (int)LegacyEventType.Background, 0, storyboard.BeatmapInfo.Metadata.BackgroundFile, 0, 0)); + (int)LegacyEventType.Background, 0, storyboard.BeatmapInfo.Metadata.BackgroundFile, storyboard.BackgroundOffset.X, storyboard.BackgroundOffset.Y)); } // https://github.com/peppy/osu-stable-reference/blob/c34a74fb61c17c5667486a12548485d1f03baa2e/osu!/GameplayElements/HitObjectManager_LoadSave.cs#L1496 diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 4dc96c84a4..d3c10aa162 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -9,6 +9,7 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; using osu.Game.Storyboards.Drawables; using osu.Game.Utils; +using osuTK; namespace osu.Game.Storyboards { @@ -98,6 +99,12 @@ namespace osu.Game.Storyboards } } + /// + /// Offset to be applied to the beatmap background. + /// TODO: Unused yet. See https://github.com/ppy/osu/issues/14238. + /// + public Vector2 BackgroundOffset { get; set; } = Vector2.Zero; + public virtual DrawableStoryboard CreateDrawable(IReadOnlyList? mods = null) => new DrawableStoryboard(this, mods);