Skip to content

Commit

Permalink
Added in default state machines
Browse files Browse the repository at this point in the history
  • Loading branch information
duncandoit committed Jul 6, 2022
1 parent 4948e74 commit dcc6d8d
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 39 deletions.
10 changes: 6 additions & 4 deletions Example-iOS/Source/Examples/Storyboard/StateMachine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class StateMachineView: UIView {
}

class StateMachineViewController: UIViewController {
// MARK: RiveViewModel
// This view model specifies the exact StateMachine that it wants from the file
var viewModel = RiveViewModel(fileName: "skills", stateMachineName: "Designer's Test")

override public func loadView() {
Expand All @@ -47,16 +49,16 @@ class StateMachineViewController: UIViewController {
viewModel.setView(stateMachineView.riveView)

stateMachineView.beginnerButtonAction = {
try? self.viewModel.setInput("Level", value: 0.0)
self.viewModel.setInput("Level", value: 0.0)
}
stateMachineView.intermediateButtonAction = {
try? self.viewModel.setInput("Level", value: 1.0)
self.viewModel.setInput("Level", value: 1.0)
}
stateMachineView.expertButtonAction = {
try? self.viewModel.setInput("Level", value: 2.0)
self.viewModel.setInput("Level", value: 2.0)
}
stateMachineView.resetButtonAction = {
try? self.viewModel.reset()
self.viewModel.reset()
}
}

Expand Down
7 changes: 6 additions & 1 deletion Example-iOS/Source/Examples/SwiftUI/SwiftCannonGame.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ struct SwiftCannonGame: DismissableView {
var dismiss: () -> Void = {}

var body: some View {
RiveViewModel(fileName: "bullet_man_game", stateMachineName: "State Machine 1").view()
// MARK: RiveViewModel
// This view model controls a file configured with:
// - StateMachine
// - Listeners

RiveViewModel(fileName: "bullet_man_game").view()
}
}
7 changes: 5 additions & 2 deletions Example-iOS/Source/Examples/SwiftUI/SwiftMeshAnimation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@ import SwiftUI
import RiveRuntime

struct SwiftMeshAnimation: DismissableView {
var dismiss: () -> Void = {}

// MARK: RiveViewModel
// This view model specifies the exact StateMachine that it wants from the file
var tapePlayer = RiveViewModel(fileName: "prop_example", stateMachineName: "State Machine 1")
@State var isTapped: Bool = false
var dismiss: () -> Void = {}

var body: some View {
tapePlayer.view()
.aspectRatio(1, contentMode: .fit)
.onTapGesture {
isTapped = !isTapped
try? tapePlayer.setInput("Hover", value: isTapped)
tapePlayer.setInput("Hover", value: isTapped)
}
}
}
12 changes: 8 additions & 4 deletions Example-iOS/Source/Examples/SwiftUI/SwiftStateMachine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ import SwiftUI
import RiveRuntime

struct SwiftStateMachine: DismissableView {
var stateChanger = RiveViewModel(fileName: "skills", stateMachineName: "Designer's Test")
var dismiss: () -> Void = {}

// MARK: RiveViewModel
// This view model specifies the exact StateMachine that it wants from the file

var stateChanger = RiveViewModel(fileName: "skills", stateMachineName: "Designer's Test")

var body: some View {
ScrollView{
VStack {
Expand All @@ -21,13 +25,13 @@ struct SwiftStateMachine: DismissableView {

HStack{
Button("Beginner") {
try? stateChanger.setInput("Level", value: 0.0)
stateChanger.setInput("Level", value: 0.0)
}
Button("Intermediate") {
try? stateChanger.setInput("Level", value: 1.0)
stateChanger.setInput("Level", value: 1.0)
}
Button("Expert") {
try? stateChanger.setInput("Level", value: 2.0)
stateChanger.setInput("Level", value: 2.0)
}
}

Expand Down
18 changes: 12 additions & 6 deletions Example-iOS/Source/Examples/SwiftUI/SwiftTouchEvents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@ import RiveRuntime

struct SwiftTouchEvents: DismissableView {
var dismiss: () -> Void = {}

// MARK: RiveViewModels
// Each of the these view models controls a file configured with:
// - State Machine
// - Listeners

@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 {
Expand Down
39 changes: 26 additions & 13 deletions Source/Components/RiveModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,43 +30,56 @@ open class RiveModel: ObservableObject {

open func setArtboard(_ name: String) throws {
do { artboard = try riveFile.artboard(fromName: name) }
catch { throw RiveModelError.invalidArtboard(name: name) }
catch { throw RiveModelError.invalidArtboard("Name \(name) not found") }
}

open func setArtboard(_ index: Int? = nil) throws {
if let index = index {
do { artboard = try riveFile.artboard(from: index) }
catch { throw RiveModelError.invalidArtboard(index: index) }
catch { throw RiveModelError.invalidArtboard("Index \(index) not found") }
} else {
// This tries to find the 'default' Artboard
do { artboard = try riveFile.artboard() }
catch { throw RiveModelError.invalidArtboard(message: "No Default Artboard") }
catch { throw RiveModelError.invalidArtboard("No Default Artboard") }
}
}

open func setStateMachine(_ name: String) throws {
do { stateMachine = try artboard.stateMachine(fromName: name) }
catch { throw RiveModelError.invalidStateMachine(name: name) }
catch { throw RiveModelError.invalidStateMachine("Name \(name) not found") }
}

open func setStateMachine(_ index: Int? = nil) throws {
// Defaults to 0 as it's assumed to be the first element in the collection
let index = index ?? 0
do { stateMachine = try artboard.stateMachine(from: index) }
catch { throw RiveModelError.invalidStateMachine(index: index) }
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 {
guard animation?.name() != name else { return }
do { animation = try artboard.animation(fromName: name) }
catch { throw RiveModelError.invalidAnimation(name: 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
do { animation = try artboard.animation(from: index) }
catch { throw RiveModelError.invalidAnimation(index: index) }
catch { throw RiveModelError.invalidAnimation("Index \(index) not found") }
}

// MARK: -
Expand All @@ -86,8 +99,8 @@ open class RiveModel: ObservableObject {
}

enum RiveModelError: Error {
case invalidStateMachine(name: String), invalidStateMachine(index: Int)
case invalidAnimation(name: String), invalidAnimation(index: Int)
case invalidArtboard(name: String), invalidArtboard(index: Int), invalidArtboard(message: String)
case invalidStateMachine(_ message: String)
case invalidAnimation(_ message: String)
case invalidArtboard(_ message: String)
}
}
25 changes: 16 additions & 9 deletions Source/Components/RiveViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -226,28 +226,35 @@ 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("Cannot configure nil RiveModel") }

if let name = artboardName {
try riveModel?.setArtboard(name)
try model.setArtboard(name)
} else {
// Keep current Artboard if there is one
if riveModel?.artboard == nil {
if model.artboard == nil {
// Set default Artboard if not
try riveModel?.setArtboard()
try model.setArtboard()
}
}

riveModel?.animation = nil
riveModel?.stateMachine = nil
model.animation = nil
model.stateMachine = nil

if let name = stateMachineName {
try riveModel?.setStateMachine(name)
try model.setStateMachine(name)
}
else if let name = animationName {
try riveModel?.setAnimation(name)
try model.setAnimation(name)
}

// Find defaults
else {
// Set default Animation
try riveModel?.setAnimation()
// Attempts to set a default StateMachine first
if ((try? model.setStateMachine()) == nil) {
// If it fails, attempts a default Animation
try model.setAnimation()
}
}
}

Expand Down
9 changes: 9 additions & 0 deletions Source/Renderer/RiveArtboard.mm
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ - (RiveStateMachineInstance *)stateMachineFromName:(NSString *)name error:(NSErr
return [[RiveStateMachineInstance alloc] initWithStateMachine: machine];
}

- (RiveStateMachineInstance *)defaultStateMachine {
rive::StateMachineInstance *machine = _artboardInstance->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];
}

- (NSArray *)stateMachineNames{
NSMutableArray *stateMachineNames = [NSMutableArray array];
for (NSUInteger i=0; i<[self stateMachineCount]; i++){
Expand Down
1 change: 1 addition & 0 deletions Source/Renderer/include/RiveArtboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ NS_ASSUME_NONNULL_BEGIN
- (NSArray<NSString *> *)stateMachineNames;
- (RiveStateMachineInstance * __nullable)stateMachineFromIndex:(NSInteger)index error:(NSError **)error;
- (RiveStateMachineInstance * __nullable)stateMachineFromName:(NSString *)name error:(NSError **)error;
- (RiveStateMachineInstance * __nullable)defaultStateMachine;

- (void)advanceBy:(double)elapsedSeconds;
- (void)draw:(RiveRenderer *)renderer;
Expand Down

0 comments on commit dcc6d8d

Please sign in to comment.