-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: Add Rive Event bindings to iOS runtime
Adds event bindings for iOS/macOS **Caveat:** tl;dr We may have to explicitly make app owners open URLs for `OpenUrlEvent`, rather than doing it implicitly Recently, there was a [request for a specific change](#267) to mark `RiveRuntime` package as using application-extension-safe in terms of API usge. This allows RiveRuntime to be used in places other than apps in the Apple ecosystem, which they needed, so that Apple doesn't flag their apps negatively in App Store submissions. Because we mark this setting in build settings for our package, this means we can't use a specific API to access `UIApplication`, which is needed to open URLs from our side (i.e. `UIApplication.shared.open(url)`), thus not allowing us to _directly_ open URLs on `OpenUrlEvent`. Couldn't find a way around this unfortunately, so the onus on opening the URL will be on the consumer when they listen for this event. Diffs= b47ff1523 feature: Add Rive Event bindings to iOS runtime (#5899) Co-authored-by: Zachary Plata <[email protected]>
- Loading branch information
Showing
16 changed files
with
373 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
0dcbdade49885fcae4de304972ae37f6283f19d1 | ||
b47ff1523153056a3359ad9b65d7dbef212bbd17 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
d7323869190ee9b8819c1ad6824888456d47b9b3 | ||
54501530ad9f358b743da5599145c708b04bfcc3 |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// | ||
// SwiftEvents.swift | ||
// RiveExample | ||
// | ||
// Created by Zach Plata on 8/28/23. | ||
// Copyright © 2023 Rive. All rights reserved. | ||
// | ||
|
||
import SwiftUI | ||
import RiveRuntime | ||
|
||
struct SwiftEvents: DismissableView { | ||
var dismiss: () -> Void = {} | ||
@StateObject private var rvm = RiveEventsVMExample() | ||
|
||
var body: some View { | ||
VStack { | ||
rvm.view() | ||
Text("Event Message") | ||
.font(.headline) | ||
.padding(.bottom, 10) | ||
Text(rvm.eventText) | ||
.padding() | ||
.background(rvm.eventText.isEmpty ? Color.clear : Color.black) | ||
.foregroundColor(.white) | ||
.cornerRadius(10) | ||
} | ||
} | ||
} | ||
|
||
class RiveEventsVMExample: RiveViewModel { | ||
@Published var eventText = "" | ||
|
||
init() { | ||
super.init(fileName: "rating_animation") | ||
} | ||
|
||
func view() -> some View { | ||
return super.view().frame(width: 400, height: 400, alignment: .center) | ||
} | ||
|
||
@objc func onRiveEventReceived(onRiveEvent riveEvent: RiveEvent) { | ||
debugPrint("Event Name: \(riveEvent.name())") | ||
debugPrint("Event Type: \(riveEvent.type())") | ||
if let openUrlEvent = riveEvent as? RiveOpenUrlEvent { | ||
debugPrint("Open URL Event Properties: \(openUrlEvent.properties())") | ||
if let url = URL(string: openUrlEvent.url()) { | ||
#if os(iOS) | ||
UIApplication.shared.open(url) | ||
#else | ||
NSWorkspace.shared.open(url) | ||
#endif | ||
} | ||
} else if let generalEvent = riveEvent as? RiveGeneralEvent { | ||
let genEventProperties = generalEvent.properties(); | ||
debugPrint("General Event Properites: \(genEventProperties)") | ||
if let msg = genEventProperties["message"] { | ||
eventText = msg as! String | ||
} | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
// | ||
// RiveEvent.m | ||
// RiveRuntime | ||
// | ||
// Created by Zach Plata on 8/23/23. | ||
// Copyright © 2023 Rive. All rights reserved. | ||
// | ||
|
||
#import <Rive.h> | ||
#import <RivePrivateHeaders.h> | ||
|
||
|
||
/* | ||
* RiveEvent | ||
*/ | ||
@implementation RiveEvent | ||
{ | ||
const rive::Event* instance; | ||
float secondsDelay; | ||
} | ||
|
||
- (const rive::Event*)getInstance | ||
{ | ||
return instance; | ||
} | ||
|
||
- (instancetype)initWithRiveEvent:(const rive::Event*)riveEvent | ||
delay:(float)delay | ||
{ | ||
if (self = [super init]) | ||
{ | ||
secondsDelay = delay; | ||
instance = riveEvent; | ||
return self; | ||
} | ||
else | ||
{ | ||
return nil; | ||
} | ||
} | ||
|
||
- (NSString*)name | ||
{ | ||
std::string str = ((const rive::Event*)instance)->name(); | ||
return [NSString stringWithCString:str.c_str() encoding:[NSString defaultCStringEncoding]]; | ||
} | ||
|
||
- (NSInteger)type | ||
{ | ||
return ((rive::Event*)[self getInstance])->coreType(); | ||
} | ||
|
||
- (float)delay | ||
{ | ||
return secondsDelay; | ||
} | ||
|
||
- (NSDictionary<NSString*, id>*)properties | ||
{ | ||
bool hasCustomProperties = false; | ||
NSMutableDictionary<NSString *, id>* customProperties = [NSMutableDictionary dictionary]; | ||
for (auto child : ((const rive::Event*)instance)->children()) | ||
{ | ||
if (child->is<rive::CustomProperty>()) | ||
{ | ||
std::string eventName = child->name(); | ||
if (!eventName.empty()) | ||
{ | ||
NSString* convertedName = [NSString stringWithCString:eventName.c_str() encoding:[NSString defaultCStringEncoding]]; | ||
switch (child->coreType()) | ||
{ | ||
case rive::CustomPropertyBoolean::typeKey: { | ||
bool customBoolValue = child->as<rive::CustomPropertyBoolean>()->propertyValue(); | ||
customProperties[convertedName] = @(customBoolValue); | ||
break; | ||
} | ||
case rive::CustomPropertyString::typeKey: { | ||
std::string customStringValue = child->as<rive::CustomPropertyString>()->propertyValue(); | ||
NSString* convertedStringValue = [NSString stringWithCString:customStringValue.c_str() encoding:[NSString defaultCStringEncoding]]; | ||
customProperties[convertedName] = convertedStringValue; | ||
break; | ||
} | ||
case rive::CustomPropertyNumber::typeKey: { | ||
float customNumValue = child->as<rive::CustomPropertyNumber>()->propertyValue(); | ||
customProperties[convertedName] = @(customNumValue); | ||
break; | ||
} | ||
} | ||
hasCustomProperties = true; | ||
} | ||
} | ||
} | ||
if (hasCustomProperties) { | ||
return customProperties; | ||
} | ||
return nil; | ||
} | ||
@end | ||
|
||
/* | ||
* RiveGeneralEvent | ||
*/ | ||
@implementation RiveGeneralEvent | ||
@end | ||
|
||
/* | ||
* RiveOpenUrlEvent | ||
*/ | ||
@implementation RiveOpenUrlEvent | ||
- (NSString*)url | ||
{ | ||
std::string str = ((const rive::OpenUrlEvent*)[self getInstance])->url(); | ||
return [NSString stringWithCString:str.c_str() encoding:[NSString defaultCStringEncoding]]; | ||
} | ||
|
||
- (NSString*)target | ||
{ | ||
uint32_t targetValue = ((const rive::OpenUrlEvent*)[self getInstance])->targetValue(); | ||
std::string targetString; | ||
switch (targetValue) | ||
{ | ||
case 0: | ||
targetString = "_blank"; | ||
break; | ||
case 1: | ||
targetString = "_parent"; | ||
break; | ||
case 2: | ||
targetString = "_self"; | ||
break; | ||
case 3: | ||
targetString = "_top"; | ||
break; | ||
} | ||
return [NSString stringWithCString:targetString.c_str() encoding:[NSString defaultCStringEncoding]]; | ||
} | ||
@end |
Oops, something went wrong.