diff --git a/.rive_head b/.rive_head index ca0ca4d5..ceeb57a8 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -a55f1ffb6cabe9b918fa0b8fd1ad11b4d656ae1c +8db7cac50c53ab10838da0cd80c869917c51c72a diff --git a/.rive_renderer b/.rive_renderer index 46dfb49c..92f627c1 100644 --- a/.rive_renderer +++ b/.rive_renderer @@ -1 +1 @@ -b615413345a91dbfc1ada8b7c3a91c941d25ca16 +988aea8692eb53d1e38579a7c3b75dc6c72e9cab diff --git a/RiveRuntime.xcodeproj/project.pbxproj b/RiveRuntime.xcodeproj/project.pbxproj index 958de410..396c8730 100644 --- a/RiveRuntime.xcodeproj/project.pbxproj +++ b/RiveRuntime.xcodeproj/project.pbxproj @@ -57,6 +57,7 @@ 04BE5430264D1F4100427B39 /* LayerState.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BE542F264D1F4100427B39 /* LayerState.h */; settings = {ATTRIBUTES = (Public, ); }; }; 04BE5434264D267900427B39 /* LayerState.mm in Sources */ = {isa = PBXBuildFile; fileRef = 04BE5431264D243D00427B39 /* LayerState.mm */; }; 04BE5436264D2A7500427B39 /* RivePrivateHeaders.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BE5435264D2A7500427B39 /* RivePrivateHeaders.h */; }; + 04E222402BE3C85100D82668 /* ball_test.riv in Resources */ = {isa = PBXBuildFile; fileRef = 04E2223F2BE3C85100D82668 /* ball_test.riv */; }; 04ED72F1299C114000E8DE53 /* RiveViewModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04ED72F0299C114000E8DE53 /* RiveViewModelTest.swift */; }; 04ED72F3299C115100E8DE53 /* empty_animation_state.riv in Resources */ = {isa = PBXBuildFile; fileRef = 04ED72F2299C115100E8DE53 /* empty_animation_state.riv */; }; 2A7079352726277C00C035A1 /* rive_renderer_view.hh in Headers */ = {isa = PBXBuildFile; fileRef = 2A7079342726277C00C035A1 /* rive_renderer_view.hh */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -157,6 +158,7 @@ 04BE542F264D1F4100427B39 /* LayerState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LayerState.h; sourceTree = ""; }; 04BE5431264D243D00427B39 /* LayerState.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = LayerState.mm; sourceTree = ""; }; 04BE5435264D2A7500427B39 /* RivePrivateHeaders.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RivePrivateHeaders.h; sourceTree = ""; }; + 04E2223F2BE3C85100D82668 /* ball_test.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = ball_test.riv; sourceTree = ""; }; 04ED72F0299C114000E8DE53 /* RiveViewModelTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RiveViewModelTest.swift; sourceTree = ""; }; 04ED72F2299C115100E8DE53 /* empty_animation_state.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = empty_animation_state.riv; sourceTree = ""; }; 2A7079342726277C00C035A1 /* rive_renderer_view.hh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = rive_renderer_view.hh; sourceTree = ""; }; @@ -252,6 +254,7 @@ isa = PBXGroup; children = ( 0424A8752BD59435000A9A1C /* img_test.riv */, + 04E2223F2BE3C85100D82668 /* ball_test.riv */, 0424A8732BD592F2000A9A1C /* audio_test.riv */, 041265272B0CC387009400EC /* hosted_assets.riv */, 041265292B0CCB8E009400EC /* embedded_assets.riv */, @@ -525,6 +528,7 @@ 04BE540D2649403600427B39 /* junk.riv in Resources */, 04BE54092649403600427B39 /* state_machine_configurations.riv in Resources */, 04BE54072649403600427B39 /* what_a_state.riv in Resources */, + 04E222402BE3C85100D82668 /* ball_test.riv in Resources */, 0424A8762BD59435000A9A1C /* img_test.riv in Resources */, 04BE541A264A823000427B39 /* animationconfigurations.riv in Resources */, 04BE540E2649403600427B39 /* multiple_state_machines.riv in Resources */, diff --git a/Tests/Assets/ball_test.riv b/Tests/Assets/ball_test.riv new file mode 100644 index 00000000..e0e618da Binary files /dev/null and b/Tests/Assets/ball_test.riv differ diff --git a/Tests/RiveDelegatesTest.swift b/Tests/RiveDelegatesTest.swift index 1bfc43ab..135c44cc 100644 --- a/Tests/RiveDelegatesTest.swift +++ b/Tests/RiveDelegatesTest.swift @@ -271,6 +271,50 @@ class DelegatesTest: XCTestCase { XCTAssertTrue((delegate.events.last as? RiveOpenUrlEvent)?.url != nil) } + func testNestedStateMachineLooping() throws { + // this test tests advancing a state machine with a one shot animation that ends after 1 second + // but the artboard has a nested artboard that is playing a looping animation via its state machine. + let delegate = DrDelegate() + let file = try RiveFile(testfileName: "ball_test") + let model = RiveModel(riveFile: file) + let viewModel = RiveViewModel(model, stateMachineName: "State Machine 1", autoPlay: true) + let view = viewModel.createRiveView() + + view.playerDelegate = delegate + view.stateMachineDelegate = delegate + XCTAssertEqual(true, viewModel.isPlaying) + view.advance(delta:0.1) + XCTAssertEqual(true, viewModel.isPlaying) + view.advance(delta:1.0) + XCTAssertEqual(true, viewModel.isPlaying) + view.advance(delta:0.1) + XCTAssertEqual(true, viewModel.isPlaying) + } + + func testNestedStateMachineOneShot() throws { + // this test tests advancing a state machine with a one shot animation that ends after 1 second + // but the artboard has a nested artboard that is playing a one shot animation via its state machine. + let delegate = DrDelegate() + let file = try RiveFile(testfileName: "ball_test") + let model = RiveModel(riveFile: file) + let viewModel = RiveViewModel( + model, + stateMachineName: "State Machine 1", + autoPlay: true, + artboardName: "Artboard 2" + ) + let view = viewModel.createRiveView() + + view.playerDelegate = delegate + view.stateMachineDelegate = delegate + XCTAssertEqual(true, viewModel.isPlaying) + view.advance(delta:0.1) + XCTAssertEqual(true, viewModel.isPlaying) + view.advance(delta:1.0) + XCTAssertEqual(false, viewModel.isPlaying) + } + + func testStateMachineLayerStates() throws { let delegate = DrDelegate() let file = try RiveFile(testfileName: "what_a_state") @@ -326,8 +370,12 @@ class DelegatesTest: XCTestCase { XCTAssertEqual(0, delegate.stateMachineStates.count) XCTAssertEqual(true, viewModel.isPlaying) - // animation came to an end inside this time period, this still means no state change + // state machine advance ends, but + // artboard advanced in this period, so we "keepGoing" view.advance(delta:0.4) + XCTAssertEqual(true, viewModel.isPlaying) + // animation is done + view.advance(delta:0.1) XCTAssertEqual(false, viewModel.isPlaying) XCTAssertEqual(0, delegate.stateMachineStates.count) diff --git a/submodules/rive-cpp b/submodules/rive-cpp index 331c05ab..efe03821 160000 --- a/submodules/rive-cpp +++ b/submodules/rive-cpp @@ -1 +1 @@ -Subproject commit 331c05ab77d786db6f9d969bee0928dc17952a2b +Subproject commit efe038211e583aba2ab03cec538eae40b448ef45