Skip to content

Commit

Permalink
Delegate for loop event
Browse files Browse the repository at this point in the history
  • Loading branch information
mjohnsullivan committed May 8, 2021
1 parent 587ebde commit 53a8e5c
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 10 deletions.
7 changes: 6 additions & 1 deletion Example-iOS/Source/SwiftUI/RiveSwiftUIView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,20 @@ struct RiveSwiftUIView: View {
@State private var isPlaying: Bool = true
@State private var fit: Fit = Fit.Cover
@State private var alignment: RiveRuntime.Alignment = RiveRuntime.Alignment.Center
@State private var loopCount: Int = 0

var body: some View {
ZStack(alignment: .bottomLeading) {
UIRiveView(
resource: "off_road_car_blog",
fit: $fit,
alignment: $alignment
alignment: $alignment,
loopCount: $loopCount
)
VStack {
Text("Looped \(loopCount) times")
.foregroundColor(.blue)
.padding()
HStack {
Button(action: { alignment = RiveRuntime.Alignment.TopLeft },
label: { Text("Top Left") })
Expand Down
33 changes: 28 additions & 5 deletions Example-iOS/Source/SwiftUI/RiveViewWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ struct UIRiveView: UIViewRepresentable {
let resource: String
@Binding var fit: Fit // Binding<Fit> = Binding.constant(Fit.Contain)
@Binding var alignment: RiveRuntime.Alignment
@Binding var loopCount: Int

// Constructs the view
func makeUIView(context: Context) -> RiveView {
// print("Making Rive View")
let riveView = RiveView(riveFile: getRiveFile(resourceName: resource))
riveView.setFit(fit: Fit.Contain)
riveView.setFit(fit: fit)
riveView.setAlignment(alignment: alignment)

// Set the delegates
riveView.loopDelegate = context.coordinator

return riveView
}

Expand All @@ -22,8 +26,27 @@ struct UIRiveView: UIViewRepresentable {
}

// Constructs a coordinator for managing updating state
// func makeCoordinator() -> Coordinator {
// Coordinator(self, fit: fit)
// }
func makeCoordinator() -> Coordinator {
Coordinator(loopCount: $loopCount)
}

}

// Coordinator between RiveView and UIRiveView
class Coordinator: NSObject, LoopDelegate {
@Binding private var loopCount: Int

init(loopCount: Binding<Int>) {
self._loopCount = loopCount
}

func loop(_ animationName: String, type: Int) {
loopCount += 1
}

// @Binding private var fit: Fit
//
// init(fit: Binding<Fit>) {
// self._fit = fit
// }
}
2 changes: 2 additions & 0 deletions Source/Renderer/Rive.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ typedef NS_ENUM(NSInteger, Alignment) {
- (void)direction:(int)direction;
- (int)loop;
- (void)loop:(int)loopMode;
- (bool)didLoop;
- (NSString *)name;

@end

Expand Down
8 changes: 8 additions & 0 deletions Source/Renderer/Rive.mm
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,14 @@ - (void)loop:(int)loopType {
instance->loopValue(loopType);
}

- (bool)didLoop {
return instance->didLoop();
}

- (NSString *)name {
std::string str = instance->animation()->name();
return [NSString stringWithCString:str.c_str() encoding:[NSString defaultCStringEncoding]];
}
@end

/*
Expand Down
35 changes: 31 additions & 4 deletions Source/Views/RiveView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@

import UIKit

// Delegate for handling loop events
public protocol LoopDelegate: AnyObject {
func loop(_ animationName: String, type: Int)
}

public class RiveView: UIView {

var displayLink: CADisplayLink?
Expand All @@ -27,6 +32,9 @@ public class RiveView: UIView {
var autoPlay: Bool = true
var lastTime: CFTimeInterval = 0

// Delegates
public weak var loopDelegate: LoopDelegate?

public init(riveFile: RiveFile, fit: Fit = Fit.Contain, alignment: Alignment = Alignment.Center) {
super.init(frame: .zero)
self.configure(withRiveFile: riveFile)
Expand All @@ -50,10 +58,19 @@ public class RiveView: UIView {
open func setFit(fit: Fit){
self.fit = fit
}
open func setAlignment(alignment: Alignment){
open func setAlignment(alignment: Alignment) {
self.alignment = alignment
}


@objc func animationWillMoveToBackground() {
print("Triggers when app is moving to background")
}

@objc func animationWillEnterForeground() {
print("Triggers when app is moving to foreground")
}

/*
* Updates the artboard and layout options
*/
Expand All @@ -63,6 +80,12 @@ public class RiveView: UIView {
andAnimation animation: String?=nil,
andAutoPlay autoPlay: Bool=true
) {
// Testing stuff
NotificationCenter.default.addObserver(self, selector: #selector(animationWillEnterForeground),
name: UIApplication.willEnterForegroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(animationWillMoveToBackground),
name: UIApplication.didEnterBackgroundNotification, object: nil)

// Ensure the view's transparent
self.isOpaque = false

Expand Down Expand Up @@ -177,21 +200,25 @@ public class RiveView: UIView {
return
}
animations.forEach{ animation in
if playingAnimations.contains(animation){
if playingAnimations.contains(animation) {
let stillPlaying = animation.advance(by: delta)
animation.apply(to: artboard)
if !stillPlaying {
playingAnimations.remove(animation)
if (animation.loop() == Loop.LoopOneShot.rawValue) {
animations.removeAll(where: {animationInstance in
animations.removeAll(where: { animationInstance in
return animationInstance == animation
})
}
}
// Check if the animation looped and if so, call the delegate
if animation.didLoop() {
loopDelegate?.loop(animation.name(), type: Int(animation.loop()))
}
}
}
stateMachines.forEach{ stateMachine in
if playingStateMachines.contains(stateMachine){
if playingStateMachines.contains(stateMachine) {
let stillPlaying = stateMachine.advance(by: delta)
stateMachine.apply(to: artboard)
if !stillPlaying {
Expand Down

0 comments on commit 53a8e5c

Please sign in to comment.