-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hacked in play/pause to SwiftUI #28
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,123 @@ | ||
import SwiftUI | ||
import Combine | ||
import RiveRuntime | ||
|
||
typealias LoopAction = ((String, Int) -> Void)? | ||
/// Controller manages the state of the Rive animation | ||
class RiveController: ObservableObject { | ||
@Published var fit: Fit | ||
@Published var alignment: RiveRuntime.Alignment | ||
@Published var playback = Playback.play | ||
|
||
init( | ||
fit: Fit = Fit.Contain, | ||
alignment: RiveRuntime.Alignment = RiveRuntime.Alignment.Center, | ||
autoplay: Bool = false | ||
) { | ||
self.fit = fit | ||
self.alignment = alignment | ||
self.playback = autoplay ? Playback.play : Playback.stop | ||
} | ||
|
||
/// Play animations | ||
func play() { | ||
self.playback = Playback.play | ||
} | ||
|
||
/// Pause all animations and state machines | ||
func pause() { | ||
self.playback = Playback.pause | ||
} | ||
} | ||
|
||
|
||
struct UIRiveView: UIViewRepresentable { | ||
|
||
// MARK: - Properties | ||
|
||
let resource: String | ||
var fit: Fit = Fit.Contain | ||
var alignment: RiveRuntime.Alignment = RiveRuntime.Alignment.Center | ||
@ObservedObject var controller: RiveController | ||
|
||
// Delegate handlers for loop and play events | ||
var loopAction: LoopAction = nil | ||
var playAction: PlaybackAction = nil | ||
var pauseAction: PlaybackAction = nil | ||
|
||
// Constructs the view | ||
// MARK: - UIViewRepresentable | ||
|
||
/// Constructs the view | ||
func makeUIView(context: Context) -> RiveView { | ||
let riveView = RiveView(riveFile: getRiveFile(resourceName: resource)) | ||
riveView.setFit(fit: fit) | ||
riveView.setAlignment(alignment: alignment) | ||
let riveView = RiveView( | ||
riveFile: getRiveFile(resourceName: resource), | ||
fit: controller.fit, | ||
alignment: controller.alignment, | ||
autoplay: controller.playback == Playback.play, | ||
loopDelegate: context.coordinator, | ||
playDelegate: context.coordinator, | ||
pauseDelegate: context.coordinator | ||
) | ||
|
||
// Set the delegates | ||
riveView.loopDelegate = context.coordinator | ||
// Try out target-action? | ||
|
||
return riveView | ||
} | ||
|
||
// Called when a bound variable changes state | ||
func updateUIView(_ uiView: RiveView, context: Context) { | ||
print("updateUI") | ||
uiView.setFit(fit: fit) | ||
uiView.setAlignment(alignment: alignment) | ||
/// Called when the view model changes | ||
func updateUIView(_ uiView: RiveView, context: UIViewRepresentableContext<UIRiveView>) { | ||
uiView.fit = controller.fit | ||
uiView.alignment = controller.alignment | ||
uiView.playback = controller.playback | ||
} | ||
|
||
// Constructs a coordinator for managing updating state | ||
func makeCoordinator() -> Coordinator { | ||
// Coordinator(loopCount: $loopCount) | ||
Coordinator(loopAction: loopAction) | ||
Coordinator(controller: controller, loopAction: loopAction, playAction: playAction, pauseAction: pauseAction) | ||
} | ||
|
||
} | ||
|
||
// Coordinator between RiveView and UIRiveView | ||
class Coordinator: NSObject, LoopDelegate { | ||
private var loopAction: LoopAction | ||
extension UIRiveView { | ||
|
||
init(loopAction: LoopAction) { | ||
self.loopAction = loopAction | ||
} | ||
// MARK: - Coordinator | ||
|
||
func loop(_ animationName: String, type: Int) { | ||
loopAction?(animationName, type) | ||
// Coordinator between RiveView and UIRiveView | ||
class Coordinator: NSObject, LoopDelegate, PlayDelegate, PauseDelegate { | ||
|
||
private var controller: RiveController | ||
private var loopAction: LoopAction | ||
private var playAction: PlaybackAction | ||
private var pauseAction: PlaybackAction | ||
var subscribers: [AnyCancellable] = [] | ||
|
||
init(controller: RiveController, loopAction: LoopAction, playAction: PlaybackAction, pauseAction: PlaybackAction) { | ||
self.loopAction = loopAction | ||
self.playAction = playAction | ||
self.pauseAction = pauseAction | ||
self.controller = controller | ||
|
||
// This stuff is all experimental and may get removed | ||
let fitSubscription = controller.$fit.receive(on: RunLoop.main).sink(receiveValue: fitDidChange) | ||
subscribers.append(fitSubscription) | ||
} | ||
|
||
// @Binding private var loopCount: Int | ||
// | ||
// init(loopCount: Binding<Int>) { | ||
// self._loopCount = loopCount | ||
// } | ||
// | ||
// func loop(_ animationName: String, type: Int) { | ||
// loopCount += 1 | ||
// } | ||
|
||
// Cancel subscribers when Coordinator is deinitialized | ||
deinit { | ||
subscribers.forEach { $0.cancel() } | ||
} | ||
|
||
var fitDidChange: (Fit) -> Void = { fit in | ||
print("Fit changed to \(fit)") | ||
} | ||
|
||
func loop(_ animationName: String, type: Int) { | ||
loopAction?(animationName, type) | ||
} | ||
|
||
func play(_ animationName: String) { | ||
playAction?(animationName) | ||
} | ||
|
||
func pause(_ animationName: String) { | ||
pauseAction?(animationName) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -81,6 +81,7 @@ typedef NS_ENUM(NSInteger, Alignment) { | |
- (const RiveSMIBool *)getBool:(NSString*)name; | ||
- (const RiveSMITrigger *)getTrigger:(NSString*)name; | ||
- (const RiveSMINumber *)getNumber:(NSString*)name; | ||
- (NSString* )name; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. :o does the instance even have a name? |
||
|
||
@end | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,7 +32,7 @@ - (instancetype)initWithStateMachine:(const rive::StateMachine *)stateMachine; | |
* RiveStateMachine interface | ||
*/ | ||
@interface RiveStateMachine () | ||
- (instancetype)initWithStateMachine:(const rive::StateMachine *)riveStateMachine; | ||
- (instancetype)initWithStateMachine:(const rive::StateMachine *)stateMachine; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ohh :P yeah there's a question of names like this :P should we prefix everything with rive, or leave that as implied... |
||
@end | ||
|
||
/* | ||
|
@@ -449,9 +449,9 @@ @implementation RiveStateMachine { | |
} | ||
|
||
// Creates a new RiveStateMachine from a cpp StateMachine | ||
- (instancetype)initWithStateMachine:(const rive::StateMachine *)riveStateMachine { | ||
- (instancetype)initWithStateMachine:(const rive::StateMachine *)stateMachine { | ||
if (self = [super init]) { | ||
stateMachine = riveStateMachine; | ||
self->stateMachine = stateMachine; | ||
return self; | ||
} else { | ||
return nil; | ||
|
@@ -485,24 +485,26 @@ - (RiveStateMachineInstance *)instance { | |
* RiveStateMachineInstance | ||
*/ | ||
@implementation RiveStateMachineInstance { | ||
const rive::StateMachine *stateMachine; | ||
rive::StateMachineInstance *instance; | ||
} | ||
|
||
// Creates a new RiveStateMachineInstance from a cpp StateMachine | ||
- (instancetype)initWithStateMachine:(const rive::StateMachine *)stateMachine { | ||
if (self = [super init]) { | ||
self->stateMachine = stateMachine; | ||
instance = new rive::StateMachineInstance(stateMachine); | ||
return self; | ||
} else { | ||
return nil; | ||
} | ||
} | ||
|
||
-(void) applyTo:(RiveArtboard*) artboard { | ||
- (void) applyTo:(RiveArtboard*)artboard { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what formatter do you use? my xcode doesnt do shit for formatting, is there something we can use here? |
||
instance->apply(artboard.artboard); | ||
} | ||
|
||
-(bool) advanceBy:(double)elapsedSeconds { | ||
- (bool) advanceBy:(double)elapsedSeconds { | ||
return instance->advance(elapsedSeconds); | ||
} | ||
|
||
|
@@ -541,6 +543,11 @@ - (RiveSMINumber *)getNumber:(NSString *) name { | |
} | ||
} | ||
|
||
- (NSString *)name { | ||
std::string str = stateMachine->name(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh! |
||
return [NSString stringWithCString:str.c_str() encoding:[NSString defaultCStringEncoding]]; | ||
} | ||
|
||
@end | ||
|
||
/* | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
love it