RiveScene no longer maintains an instance of rive::Scene

This commit is contained in:
Zachary Duncan
2022-07-11 12:05:24 -04:00
parent 7d8a981652
commit a601491473
11 changed files with 96 additions and 71 deletions

View File

@@ -17,7 +17,7 @@ struct SwiftLayout: DismissableView {
var body: some View {
VStack {
RiveViewModel(fileName: "off_road_car_blog", fit: fit, alignment: alignment).view()
RiveViewModel(fileName: "truck_v7", fit: fit, alignment: alignment).view()
}
HStack {
Text("Fit")

View File

@@ -12,12 +12,12 @@ import RiveRuntime
struct SwiftTouchEvents: DismissableView {
var dismiss: () -> Void = {}
@StateObject var clock = ClockViewModel()
@StateObject var jelly = RiveViewModel(fileName: "hero_editor", stateMachineName: "Jellyfish")
@StateObject var playButton = RiveViewModel(fileName: "play_button_event_example", stateMachineName: "State Machine")
@StateObject var lighthouse = RiveViewModel(fileName: "switch_event_example", stateMachineName: "Main State Machine")
@StateObject var eightball = RiveViewModel(fileName: "magic_8-ball_v2", stateMachineName: "Main State Machine")
@StateObject var bearGuy = RiveViewModel(fileName: "leg_day_events_example", stateMachineName: "Don't Skip Leg Day")
@StateObject var toggle = RiveViewModel(fileName: "light_switch", stateMachineName: "Switch")
@StateObject var jelly = RiveViewModel(fileName: "hero_editor")
@StateObject var playButton = RiveViewModel(fileName: "play_button_event_example")
@StateObject var lighthouse = RiveViewModel(fileName: "switch_event_example")
@StateObject var eightball = RiveViewModel(fileName: "magic_8-ball_v2")
@StateObject var bearGuy = RiveViewModel(fileName: "leg_day_events_example")
@StateObject var toggle = RiveViewModel(fileName: "light_switch")
var body: some View {
ScrollView {

View File

@@ -153,8 +153,8 @@
isa = PBXGroup;
children = (
046FB7E7264EAA5F000129B1 /* RiveFile.h */,
C39E7647285AE42500D30612 /* RiveScene.hpp */,
046FB7EC264EAA60000129B1 /* RiveArtboard.h */,
C39E7647285AE42500D30612 /* RiveScene.hpp */,
046FB7E1264EAA5E000129B1 /* RiveLinearAnimationInstance.h */,
046FB7F0264EAA60000129B1 /* RiveStateMachineInstance.h */,
046FB7EB264EAA60000129B1 /* RiveSMIInput.h */,
@@ -210,8 +210,8 @@
children = (
046FB801264EB632000129B1 /* include */,
046FB7EF264EAA60000129B1 /* RiveFile.mm */,
C39E764A285AE51900D30612 /* RiveScene.mm */,
046FB7E2264EAA5E000129B1 /* RiveArtboard.mm */,
C39E764A285AE51900D30612 /* RiveScene.mm */,
046FB7E4264EAA5F000129B1 /* RiveLinearAnimationInstance.mm */,
046FB7E8264EAA5F000129B1 /* RiveStateMachineInstance.mm */,
046FB7E5264EAA5F000129B1 /* RiveSMIInput.mm */,

View File

@@ -11,17 +11,9 @@ import Foundation
open class RiveModel: ObservableObject {
internal private(set) var riveFile: RiveFile
public private(set) var artboard: RiveArtboard!
public internal(set) var scene: RiveScene!
public internal(set) var stateMachine: RiveStateMachineInstance? {
didSet {
scene = stateMachine ?? scene
}
}
public internal(set) var animation: RiveLinearAnimationInstance? {
didSet {
scene = animation ?? scene
}
}
public internal(set) var stateMachine: RiveStateMachineInstance?
public internal(set) var animation: RiveLinearAnimationInstance?
public weak var scene: RiveScene? { stateMachine ?? animation }
public init(riveFile: RiveFile) {
self.riveFile = riveFile
@@ -38,49 +30,68 @@ open class RiveModel: ObservableObject {
// MARK: - Setters
open func setArtboard(_ name: String) throws {
artboard = try riveFile.artboard(fromName: name)
do { artboard = try riveFile.artboard(fromName: name) }
catch { throw RiveModelError.invalidArtboard("Name \(name) not found") }
}
open func setArtboard(_ index: Int? = nil) throws {
if let index = index {
artboard = try riveFile.artboard(from: index)
}
else {
// Tries to find the 'default' Artboard
artboard = try riveFile.defaultArtboard()
}
}
open func setStateMachine(_ name: String) throws {
stateMachine = try artboard.stateMachine(fromName: name)
}
open func setStateMachine(_ index: Int? = nil) throws {
if let index = index {
stateMachine = try artboard.stateMachine(from: index)
do { artboard = try riveFile.artboard(from: index) }
catch { throw RiveModelError.invalidArtboard("Index \(index) not found") }
} else {
// Tries to find the 'default' StateMachine
stateMachine = try artboard.defaultStateMachine()
// This tries to find the 'default' Artboard
do { artboard = try riveFile.defaultArtboard() }
catch { throw RiveModelError.invalidArtboard("No Default Artboard") }
}
}
open func setDefaultScene() throws {
let newScene = try artboard.defaultScene()
if newScene is RiveStateMachineInstance {
stateMachine = newScene as? RiveStateMachineInstance
} else {
animation = newScene as? RiveLinearAnimationInstance
let scene = try artboard.defaultScene()
if scene is RiveStateMachineInstance {
stateMachine = scene as? RiveStateMachineInstance
}
else {
animation = scene as? RiveLinearAnimationInstance
}
}
open func setStateMachine(_ name: String) throws {
do { stateMachine = try artboard.stateMachine(fromName: name) }
catch { throw RiveModelError.invalidStateMachine("Name \(name) not found") }
}
open func setStateMachine(_ index: Int? = nil) throws {
do {
// Set by index
if let index = index {
stateMachine = try artboard.stateMachine(from: index)
}
// Set from Artboard's default StateMachine configured in editor
else if let defaultStateMachine = artboard.defaultStateMachine() {
stateMachine = defaultStateMachine
}
// Set by index 0 as a fallback
else {
stateMachine = try artboard.stateMachine(from: 0)
}
}
catch { throw RiveModelError.invalidStateMachine("Index \(index ?? 0) not found") }
}
open func setAnimation(_ name: String) throws {
animation = try artboard.animation(fromName: name)
guard animation?.name() != name else { return }
do { animation = try artboard.animation(fromName: name) }
catch { throw RiveModelError.invalidAnimation("Name \(name) not found") }
}
open func setAnimation(_ index: Int? = nil) throws {
// Defaults to 0 as it's assumed to be the first element in the collection
let index = index ?? 0
animation = try artboard.animation(from: index)
do { animation = try artboard.animation(from: index) }
catch { throw RiveModelError.invalidAnimation("Index \(index) not found") }
}
// MARK: -
@@ -98,4 +109,10 @@ open class RiveModel: ObservableObject {
return art + "]"
}
}
enum RiveModelError: Error {
case invalidStateMachine(_ message: String)
case invalidAnimation(_ message: String)
case invalidArtboard(_ message: String)
}
}

View File

@@ -226,7 +226,7 @@ open class RiveViewModel: NSObject, ObservableObject, RiveFileDelegate, RiveStat
/// Instantiates elements in the model needed to play in a `RiveView`
private func configureModel(artboardName: String? = nil, stateMachineName: String? = nil, animationName: String? = nil) throws {
guard let model = riveModel else { fatalError("Attempting to configure nil RiveModel") }
guard let model = riveModel else { fatalError("Cannot configure nil RiveModel") }
if let name = artboardName {
try model.setArtboard(name)
@@ -238,7 +238,6 @@ open class RiveViewModel: NSObject, ObservableObject, RiveFileDelegate, RiveStat
}
}
model.scene = nil
model.animation = nil
model.stateMachine = nil
@@ -249,7 +248,6 @@ open class RiveViewModel: NSObject, ObservableObject, RiveFileDelegate, RiveStat
try model.setAnimation(name)
}
else {
// Set either a default Animation or default StateMachine
try model.setDefaultScene()
}
}

View File

@@ -24,11 +24,22 @@
- (RiveScene *)defaultScene:(NSError **)error {
auto scene = _instance->defaultScene();
if (scene == nullptr) {
*error = [NSError errorWithDomain:RiveErrorDomain code:RiveNoStateMachineFound userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"No default Scene found."], @"name": @"NoSceneFound"}];
return nil;
}
return [[RiveScene alloc] initWithScene:scene.release()];
// TODO: Fix this disgusting hack
// -1 is a magic number that scene gives for
// the duration when it represents a state machine
if (scene->durationSeconds() == -1) {
rive::StateMachineInstance *machineInstance = (rive::StateMachineInstance *)scene.release();
return [[RiveStateMachineInstance alloc] initWithStateMachine:machineInstance];
} else {
rive::LinearAnimationInstance *animInstance = (rive::LinearAnimationInstance *)scene.release();
return [[RiveLinearAnimationInstance alloc] initWithAnimation:animInstance];
}
}
- (NSInteger)animationCount {
@@ -66,10 +77,9 @@
return _instance->stateMachineCount();
}
- (RiveStateMachineInstance *)defaultStateMachine:(NSError **)error {
- (RiveStateMachineInstance *)defaultStateMachine {
rive::StateMachineInstance *machine = _instance->defaultStateMachine().release();
if (machine == nullptr) {
*error = [NSError errorWithDomain:RiveErrorDomain code:RiveNoStateMachineFound userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"No default State Machine found."], @"name": @"NoStateMachineFound"}];
return nil;
}
return [[RiveStateMachineInstance alloc] initWithStateMachine:machine];

View File

@@ -25,6 +25,10 @@
}
}
- (rive::Scene *)instance {
return instance;
}
- (float)time {
return instance->time();
}

View File

@@ -9,39 +9,31 @@
#import <Rive.h>
#import <RivePrivateHeaders.h>
@implementation RiveScene {
rive::Scene *instance;
}
@implementation RiveScene
- (instancetype)initWithScene:(rive::Scene *)scene {
if (self = [super init]) {
instance = scene;
return self;
} else {
return nil;
}
/// StateMachine and Animation instance classes must override this
- (rive::Scene *)instance {
[NSException raise:@"NotImplemented" format:@"Scene implementation must be overriden"];
return nil;
}
- (NSString *)name {
std::string str = instance->name();
std::string str = [self instance]->name();
return [NSString stringWithCString:str.c_str() encoding:[NSString defaultCStringEncoding]];
}
- (CGRect)bounds {
rive::AABB aabb = instance->bounds();
rive::AABB aabb = [self instance]->bounds();
return CGRectMake(aabb.minX, aabb.minY, aabb.width(), aabb.height());
}
- (bool)advanceBy:(double)elapsedSeconds {
return instance->advanceAndApply(elapsedSeconds);
return [self instance]->advanceAndApply(elapsedSeconds);
}
- (void)draw:(rive::Renderer *)renderer {
instance->draw(renderer);
}
- (void)dealloc {
delete instance;
[self instance]->draw(renderer);
}
@end

View File

@@ -34,6 +34,10 @@
}
}
- (rive::Scene *)instance {
return instance;
}
- (RiveSMIBool *)getBool:(NSString *)name {
// Create a unique dictionary name for numbers;
// this lets us use one dictionary for the three different types

View File

@@ -32,7 +32,7 @@ NS_ASSUME_NONNULL_BEGIN
- (NSInteger)stateMachineCount;
- (NSArray<NSString *> *)stateMachineNames;
- (RiveStateMachineInstance * __nullable)defaultStateMachine:(NSError **)error;
- (RiveStateMachineInstance * __nullable)defaultStateMachine;
- (RiveStateMachineInstance * __nullable)stateMachineFromIndex:(NSInteger)index error:(NSError **)error;
- (RiveStateMachineInstance * __nullable)stateMachineFromName:(NSString *)name error:(NSError **)error;

View File

@@ -31,7 +31,7 @@
* RiveScene interface
*/
@interface RiveScene ()
- (instancetype)initWithScene:(rive::Scene *)scene;
- (rive::Scene *)instance;
- (void)draw:(rive::Renderer *)renderer;
@end