Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c050078
Use more direct way to apply transforms
EVAST9919 Mar 3, 2024
7193ec6
Make use of framework's transform loops
EVAST9919 Mar 3, 2024
f5d24e6
Remove unused transform extensions
EVAST9919 Mar 3, 2024
4a7635e
Fix broken tests
EVAST9919 Mar 3, 2024
8b03acd
Implement StoryboardElementWithDuration
EVAST9919 Mar 5, 2024
1c8ede8
Remove blank lines
EVAST9919 Mar 5, 2024
07392a4
Further simplify transform application
EVAST9919 Mar 5, 2024
585ab59
Apply major refactor to the storyboard commands flow structrure
frenzibyte Mar 6, 2024
9b77d8c
Fix group start/end time not calculating correctly
frenzibyte Mar 7, 2024
6c257e5
Fix `HasCommands` property not set at all
frenzibyte Mar 7, 2024
87b065b
Fix incorrect start time calculations
frenzibyte Mar 7, 2024
3755dd0
Calculate loop delays at point of transform application
frenzibyte Mar 7, 2024
2ca3625
Fix comparison interface not implemented on storyboard command classes
frenzibyte Mar 7, 2024
b450abb
Support applying initial values of storyboard commands
frenzibyte Mar 7, 2024
fa9b2f0
Add generics to `ApplyInitialValue`/`ApplyTransforms` for ability to …
frenzibyte Mar 8, 2024
79da6d8
Fix refactor error on `EndTimeForDisplay`
frenzibyte Mar 8, 2024
8d3e502
Merge branch 'master' into storyboard-loops-v2
frenzibyte Mar 8, 2024
a85be2a
Fix merge conflicts
frenzibyte Mar 8, 2024
c1649b7
Reorder command properties to match general format
frenzibyte Mar 8, 2024
0efa12a
Fix parameter commands applying initial value before start time
frenzibyte Mar 8, 2024
6861d9a
Expose storyboard command lists as read-only and remove unnecessary m…
frenzibyte Mar 8, 2024
1942d46
Remove leftover debugging code
frenzibyte Mar 8, 2024
8c92bb0
Remove unused using directive
frenzibyte Mar 8, 2024
9f71eac
Remove extra end line
frenzibyte Mar 8, 2024
82048df
Add basic test scene for asserting storyboard commands behaviour
frenzibyte Mar 9, 2024
8a1c5a7
Adjust time values
frenzibyte Mar 10, 2024
d039b56
Add test case for running with high number of loops
frenzibyte Mar 10, 2024
99b0610
Add enough test coverage
frenzibyte Mar 10, 2024
895c09d
Merge branch 'master' into storyboard-loops-v2
frenzibyte May 1, 2024
4ffeb5b
Resolve post-merge-conflict issues
frenzibyte May 1, 2024
6d6f165
Make video sprites flippable and vector-scalable to fix type constrai…
frenzibyte May 1, 2024
b1aff91
Use throw helper methods
frenzibyte May 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ public void TestVideo(bool scaleTransformProvided)

if (scaleTransformProvided)
{
sprite.TimelineGroup.Scale.Add(Easing.None, Time.Current, Time.Current + 1000, 1, 2);
sprite.TimelineGroup.Scale.Add(Easing.None, Time.Current + 1000, Time.Current + 2000, 2, 1);
sprite.Commands.AddScale(Easing.None, Time.Current, Time.Current + 1000, 1, 2);
sprite.Commands.AddScale(Easing.None, Time.Current + 1000, Time.Current + 2000, 2, 1);
}

layer.Elements.Clear();
Expand Down Expand Up @@ -211,7 +211,8 @@ private Drawable createSprite(string lookupName, Anchor origin, Vector2 initialP
var layer = storyboard.GetLayer("Background");

var sprite = new StoryboardSprite(lookupName, origin, initialPosition);
sprite.AddLoop(Time.Current, 100).Alpha.Add(Easing.None, 0, 10000, 1, 1);
var loop = sprite.AddLoopingGroup(Time.Current, 100);
loop.AddAlpha(Easing.None, 0, 10000, 1, 1);

layer.Elements.Clear();
layer.Add(sprite);
Expand Down
16 changes: 8 additions & 8 deletions osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void TestStoryboardProducesCorrectStartTimeSimpleAlpha(double firstStoryb

var sprite = new StoryboardSprite("unknown", Anchor.TopLeft, Vector2.Zero);

sprite.TimelineGroup.Alpha.Add(Easing.None, firstStoryboardEvent, firstStoryboardEvent + 500, 0, 1);
sprite.Commands.AddAlpha(Easing.None, firstStoryboardEvent, firstStoryboardEvent + 500, 0, 1);

storyboard.GetLayer("Background").Add(sprite);

Expand All @@ -73,17 +73,17 @@ public void TestStoryboardProducesCorrectStartTimeFadeInAfterOtherEvents(double
var sprite = new StoryboardSprite("unknown", Anchor.TopLeft, Vector2.Zero);

// these should be ignored as we have an alpha visibility blocker proceeding this command.
sprite.TimelineGroup.Scale.Add(Easing.None, loop_start_time, -18000, 0, 1);
var loopGroup = sprite.AddLoop(loop_start_time, 50);
loopGroup.Scale.Add(Easing.None, loop_start_time, -18000, 0, 1);
sprite.Commands.AddScale(Easing.None, loop_start_time, -18000, 0, 1);
var loopGroup = sprite.AddLoopingGroup(loop_start_time, 50);
loopGroup.AddScale(Easing.None, loop_start_time, -18000, 0, 1);

var target = addEventToLoop ? loopGroup : sprite.TimelineGroup;
var target = addEventToLoop ? loopGroup : sprite.Commands;
double loopRelativeOffset = addEventToLoop ? -loop_start_time : 0;
target.Alpha.Add(Easing.None, loopRelativeOffset + firstStoryboardEvent, loopRelativeOffset + firstStoryboardEvent + 500, 0, 1);
target.AddAlpha(Easing.None, loopRelativeOffset + firstStoryboardEvent, loopRelativeOffset + firstStoryboardEvent + 500, 0, 1);

// these should be ignored due to being in the future.
sprite.TimelineGroup.Alpha.Add(Easing.None, 18000, 20000, 0, 1);
loopGroup.Alpha.Add(Easing.None, 38000, 40000, 0, 1);
sprite.Commands.AddAlpha(Easing.None, 18000, 20000, 0, 1);
loopGroup.AddAlpha(Easing.None, 38000, 40000, 0, 1);

storyboard.GetLayer("Background").Add(sprite);

Expand Down
264 changes: 264 additions & 0 deletions osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardCommands.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
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.IO.Stores;
using osu.Framework.Testing;
using osu.Framework.Timing;
using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Mods;
using osu.Game.Storyboards;
using osu.Game.Storyboards.Drawables;
using osu.Game.Tests.Resources;
using osuTK;

namespace osu.Game.Tests.Visual.Gameplay
{
public partial class TestSceneStoryboardCommands : OsuTestScene
{
[Cached(typeof(Storyboard))]
private TestStoryboard storyboard { get; set; } = new TestStoryboard
{
UseSkinSprites = false,
AlwaysProvideTexture = true,
};

private readonly ManualClock manualClock = new ManualClock { Rate = 1, IsRunning = true };
private int clockDirection;

private const string lookup_name = "hitcircleoverlay";
private const double clock_limit = 2500;

protected override Container<Drawable> Content => content;

private Container content = null!;
private SpriteText timelineText = null!;
private Box timelineMarker = null!;

[BackgroundDependencyLoader]
private void load()
{
base.Content.Children = new Drawable[]
{
content = new Container
{
RelativeSizeAxes = Axes.Both,
},
timelineText = new OsuSpriteText
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Margin = new MarginPadding { Bottom = 60 },
},
timelineMarker = new Box
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomCentre,
RelativePositionAxes = Axes.X,
Size = new Vector2(2, 50),
},
};
}

[SetUpSteps]
public void SetUpSteps()
{
AddStep("start clock", () => clockDirection = 1);
AddStep("pause clock", () => clockDirection = 0);
AddStep("set clock = 0", () => manualClock.CurrentTime = 0);
}

[Test]
public void TestNormalCommandPlayback()
{
AddStep("create storyboard", () => Child = createStoryboard(s =>
{
s.Commands.AddY(Easing.OutBounce, 500, 900, 100, 240);
s.Commands.AddY(Easing.OutQuint, 1100, 1500, 240, 100);
}));

assert(0, 100);
assert(500, 100);
assert(1000, 240);
assert(1500, 100);
assert(clock_limit, 100);
assert(1500, 100);
assert(1000, 240);
assert(500, 100);
assert(0, 100);

void assert(double time, double y)
{
AddStep($"set clock = {time}", () => manualClock.CurrentTime = time);
AddAssert($"sprite y = {y} at t = {time}", () => this.ChildrenOfType<DrawableStoryboardSprite>().Single().Y == y);
}
}

[Test]
public void TestLoopingCommandsPlayback()
{
AddStep("create storyboard", () => Child = createStoryboard(s =>
{
var loop = s.AddLoopingGroup(250, 1);
loop.AddY(Easing.OutBounce, 0, 400, 100, 240);
loop.AddY(Easing.OutQuint, 600, 1000, 240, 100);
}));

assert(0, 100);
assert(250, 100);
assert(850, 240);
assert(1250, 100);
assert(1850, 240);
assert(2250, 100);
assert(clock_limit, 100);
assert(2250, 100);
assert(1850, 240);
assert(1250, 100);
assert(850, 240);
assert(250, 100);
assert(0, 100);

void assert(double time, double y)
{
AddStep($"set clock = {time}", () => manualClock.CurrentTime = time);
AddAssert($"sprite y = {y} at t = {time}", () => this.ChildrenOfType<DrawableStoryboardSprite>().Single().Y == y);
}
}

[Test]
public void TestLoopManyTimes()
{
AddStep("create storyboard", () => Child = createStoryboard(s =>
{
var loop = s.AddLoopingGroup(500, 10000);
loop.AddY(Easing.OutBounce, 0, 60, 100, 240);
loop.AddY(Easing.OutQuint, 80, 120, 240, 100);
}));
}

[Test]
public void TestParameterTemporaryEffect()
{
AddStep("create storyboard", () => Child = createStoryboard(s =>
{
s.Commands.AddFlipV(Easing.None, 1000, 1500, true, false);
}));

AddAssert("sprite not flipped at t = 0", () => !this.ChildrenOfType<DrawableStoryboardSprite>().Single().FlipV);

AddStep("set clock = 1250", () => manualClock.CurrentTime = 1250);
AddAssert("sprite flipped at t = 1250", () => this.ChildrenOfType<DrawableStoryboardSprite>().Single().FlipV);

AddStep("set clock = 2000", () => manualClock.CurrentTime = 2000);
AddAssert("sprite not flipped at t = 2000", () => !this.ChildrenOfType<DrawableStoryboardSprite>().Single().FlipV);

AddStep("resume clock", () => clockDirection = 1);
}

[Test]
public void TestParameterPermanentEffect()
{
AddStep("create storyboard", () => Child = createStoryboard(s =>
{
s.Commands.AddFlipV(Easing.None, 1000, 1000, true, true);
}));

AddAssert("sprite flipped at t = 0", () => this.ChildrenOfType<DrawableStoryboardSprite>().Single().FlipV);

AddStep("set clock = 1250", () => manualClock.CurrentTime = 1250);
AddAssert("sprite flipped at t = 1250", () => this.ChildrenOfType<DrawableStoryboardSprite>().Single().FlipV);

AddStep("set clock = 2000", () => manualClock.CurrentTime = 2000);
AddAssert("sprite flipped at t = 2000", () => this.ChildrenOfType<DrawableStoryboardSprite>().Single().FlipV);

AddStep("resume clock", () => clockDirection = 1);
}

protected override void Update()
{
base.Update();

if (manualClock.CurrentTime > clock_limit || manualClock.CurrentTime < 0)
clockDirection = -clockDirection;

manualClock.CurrentTime += Time.Elapsed * clockDirection;
timelineText.Text = $"Time: {manualClock.CurrentTime:0}ms";
timelineMarker.X = (float)(manualClock.CurrentTime / clock_limit);
}

private DrawableStoryboard createStoryboard(Action<StoryboardSprite>? addCommands = null)
{
var layer = storyboard.GetLayer("Background");

var sprite = new StoryboardSprite(lookup_name, Anchor.Centre, new Vector2(320, 240));
sprite.Commands.AddScale(Easing.None, 0, clock_limit, 0.5f, 0.5f);
sprite.Commands.AddAlpha(Easing.None, 0, clock_limit, 1, 1);
addCommands?.Invoke(sprite);

layer.Elements.Clear();
layer.Add(sprite);

return storyboard.CreateDrawable().With(c => c.Clock = new FramedClock(manualClock));
}

private partial class TestStoryboard : Storyboard
{
public override DrawableStoryboard CreateDrawable(IReadOnlyList<Mod>? mods = null)
{
return new TestDrawableStoryboard(this, mods);
}

public bool AlwaysProvideTexture { get; set; }

public override string GetStoragePathFromStoryboardPath(string path) => AlwaysProvideTexture ? path : string.Empty;

private partial class TestDrawableStoryboard : DrawableStoryboard
{
private readonly bool alwaysProvideTexture;

public TestDrawableStoryboard(TestStoryboard storyboard, IReadOnlyList<Mod>? mods)
: base(storyboard, mods)
{
alwaysProvideTexture = storyboard.AlwaysProvideTexture;
}

protected override IResourceStore<byte[]> CreateResourceLookupStore() => alwaysProvideTexture
? new AlwaysReturnsTextureStore()
: new ResourceStore<byte[]>();

internal class AlwaysReturnsTextureStore : IResourceStore<byte[]>
{
private const string test_image = "Resources/Textures/test-image.png";

private readonly DllResourceStore store;

public AlwaysReturnsTextureStore()
{
store = TestResources.GetStore();
}

public void Dispose() => store.Dispose();

public byte[] Get(string name) => store.Get(test_image);

public Task<byte[]> GetAsync(string name, CancellationToken cancellationToken = new CancellationToken()) => store.GetAsync(test_image, cancellationToken);

public Stream GetStream(string name) => store.GetStream(test_image);

public IEnumerable<string> GetAvailableResources() => store.GetAvailableResources();
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ private Storyboard createStoryboard(double startTime)
{
var storyboard = new Storyboard();
var sprite = new StoryboardSprite("unknown", Anchor.TopLeft, Vector2.Zero);
sprite.TimelineGroup.Alpha.Add(Easing.None, startTime, 0, 0, 1);
sprite.Commands.AddAlpha(Easing.None, startTime, 0, 0, 1);
storyboard.GetLayer("Background").Add(sprite);
return storyboard;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ private Storyboard createStoryboard(double duration)
{
var storyboard = new Storyboard();
var sprite = new StoryboardSprite("unknown", Anchor.TopLeft, Vector2.Zero);
sprite.TimelineGroup.Alpha.Add(Easing.None, 0, duration, 1, 0);
sprite.Commands.AddAlpha(Easing.None, 0, duration, 1, 0);
storyboard.GetLayer("Background").Add(sprite);
return storyboard;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ public void TestPlayersLeaveWhileSpectating()
public void TestIntroStoryboardElement() => testLeadIn(b =>
{
var sprite = new StoryboardSprite("unknown", Anchor.TopLeft, Vector2.Zero);
sprite.TimelineGroup.Alpha.Add(Easing.None, -2000, 0, 0, 1);
sprite.Commands.AddAlpha(Easing.None, -2000, 0, 0, 1);
b.Storyboard.GetLayer("Background").Add(sprite);
});

Expand Down
Loading