diff --git a/Example-iOS/Assets/hero_editor.riv b/Example-iOS/Assets/hero_editor.riv new file mode 100644 index 00000000..9b859599 Binary files /dev/null and b/Example-iOS/Assets/hero_editor.riv differ diff --git a/Example-iOS/RiveExample.xcodeproj/project.pbxproj b/Example-iOS/RiveExample.xcodeproj/project.pbxproj index 3fee2b5e..002dca62 100644 --- a/Example-iOS/RiveExample.xcodeproj/project.pbxproj +++ b/Example-iOS/RiveExample.xcodeproj/project.pbxproj @@ -51,6 +51,7 @@ C3357CA1280F42EC00F03B6F /* ExamplesMaster.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3357CA0280F42EC00F03B6F /* ExamplesMaster.swift */; }; C3460A002800A6CE002DBCB7 /* bird.riv in Resources */ = {isa = PBXBuildFile; fileRef = C34609FD2800A6CE002DBCB7 /* bird.riv */; }; C3468E6227FDCBC6008652FD /* SimpleSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3468E6127FDCBC6008652FD /* SimpleSlider.swift */; }; + C3745FCE282AE2320087F4AF /* hero_editor.riv in Resources */ = {isa = PBXBuildFile; fileRef = C3745FCB282AE2320087F4AF /* hero_editor.riv */; }; C3D187F3280751A8008B739A /* RiveProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3D187F2280751A8008B739A /* RiveProgressBar.swift */; }; C3D187F728075B6C008B739A /* riveslider.riv in Resources */ = {isa = PBXBuildFile; fileRef = C3D187F628075B6C008B739A /* riveslider.riv */; }; C3D187F9280770EA008B739A /* truck.riv in Resources */ = {isa = PBXBuildFile; fileRef = C3D187F8280770EA008B739A /* truck.riv */; }; @@ -151,6 +152,7 @@ C3357CA0280F42EC00F03B6F /* ExamplesMaster.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExamplesMaster.swift; sourceTree = ""; }; C34609FD2800A6CE002DBCB7 /* bird.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = bird.riv; sourceTree = ""; }; C3468E6127FDCBC6008652FD /* SimpleSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleSlider.swift; sourceTree = ""; }; + C3745FCB282AE2320087F4AF /* hero_editor.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = hero_editor.riv; sourceTree = ""; }; C3D187F2280751A8008B739A /* RiveProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RiveProgressBar.swift; sourceTree = ""; }; C3D187F628075B6C008B739A /* riveslider.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = riveslider.riv; sourceTree = ""; }; C3D187F8280770EA008B739A /* truck.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = truck.riv; sourceTree = ""; }; @@ -245,6 +247,7 @@ C9696B0E24FC6FD10041502A /* Assets */ = { isa = PBXGroup; children = ( + C3745FCB282AE2320087F4AF /* hero_editor.riv */, C3ECAC30281840EF00A81123 /* watch_v1.riv */, C3ECAC29281837B300A81123 /* leg_day_events_example.riv */, C3ECAC28281837B300A81123 /* play_button_event_example.riv */, @@ -463,6 +466,7 @@ C3ECAC2D281837B300A81123 /* switch_event_example.riv in Resources */, 0480028B2729AA4400F7132B /* clean_icon_set.riv in Resources */, 04F1C80B26A8442300CEE6BE /* two_bone_ik.riv in Resources */, + C3745FCE282AE2320087F4AF /* hero_editor.riv in Resources */, C3D187F9280770EA008B739A /* truck.riv in Resources */, C9C73EA124FC471E00EF9516 /* Preview Assets.xcassets in Resources */, 042C88DD2644447500E7DBB2 /* ui_swipe_left_to_delete.riv in Resources */, diff --git a/Example-iOS/Source/Examples/SwiftUI/SwiftTouchEvents.swift b/Example-iOS/Source/Examples/SwiftUI/SwiftTouchEvents.swift index 21c4043c..e0328b9a 100644 --- a/Example-iOS/Source/Examples/SwiftUI/SwiftTouchEvents.swift +++ b/Example-iOS/Source/Examples/SwiftUI/SwiftTouchEvents.swift @@ -15,14 +15,18 @@ struct SwiftTouchEvents: DismissableView { var body: some View { ScrollView { VStack { - RiveViewModel(fileName: "play_button_event_example", stateMachineName: "State Machine") + RiveViewModel(fileName: "hero_editor", stateMachineName: "Jellyfish") .view() .aspectRatio(1, contentMode: .fit) + RiveViewModel(fileName: "play_button_event_example", stateMachineName: "State Machine") + .view() + .aspectRatio(1, contentMode: .fit) + RiveViewModel(fileName: "switch_event_example", stateMachineName: "Main State Machine") .view() .aspectRatio(1, contentMode: .fit) - + RiveViewModel(fileName: "magic_8-ball_v2", stateMachineName: "Main State Machine") .view() .aspectRatio(1, contentMode: .fit) diff --git a/Source/Components/RiveView.swift b/Source/Components/RiveView.swift index f20f1fdc..ec0b9e90 100644 --- a/Source/Components/RiveView.swift +++ b/Source/Components/RiveView.swift @@ -120,6 +120,32 @@ open class RiveView: RiveRendererView { private var lastTime: CFTimeInterval = 0 private var displayLinkProxy: CADisplayLinkProxy? + private var fpsLabel: UILabel? = nil + private var fpsFormatter: NumberFormatter? = nil + public var showFPS: Bool = false { + didSet { + if showFPS { + fpsLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 75, height: 30)) + addSubview(fpsLabel!) + fpsLabel!.backgroundColor = .darkGray + fpsLabel!.textColor = .white + fpsLabel!.textAlignment = .center + fpsLabel!.alpha = 0.75 + fpsLabel!.clipsToBounds = true + fpsLabel!.layer.cornerRadius = 10 + fpsLabel!.text = "..." + + fpsFormatter = NumberFormatter() + fpsFormatter!.minimumFractionDigits = 2 + fpsFormatter!.maximumFractionDigits = 2 + fpsFormatter!.roundingMode = .down + } else { + fpsLabel?.removeFromSuperview() + fpsLabel = nil + fpsFormatter = nil + } + } + } // Delegates public weak var playerDelegate: RivePlayerDelegate? @@ -158,13 +184,11 @@ open class RiveView: RiveRendererView { stateChangeDelegate: RStateDelegate? = nil ) throws { super.init(frame: .zero) - self.fit = fit - self.alignment = alignment - self.playerDelegate = playerDelegate - self.inputsDelegate = inputsDelegate - self.stateChangeDelegate = stateChangeDelegate - - try configure(riveFile, artboardName: artboardName, animationName: animationName, stateMachineName: stateMachineName, autoPlay: autoplay) + try sharedInit( + riveFile, artboardName: artboardName, animationName: animationName, stateMachineName: stateMachineName, + fit: fit, alignment: alignment, autoplay: autoplay, + playerDelegate: playerDelegate, inputsDelegate: inputsDelegate, stateChangeDelegate: stateChangeDelegate + ) } /// Constructor with a .riv file name. @@ -192,14 +216,11 @@ open class RiveView: RiveRendererView { stateChangeDelegate: RStateDelegate? = nil ) throws { super.init(frame: .zero) - let riveFile = try RiveFile(name: fileName) - self.fit = fit - self.alignment = alignment - self.playerDelegate = playerDelegate - self.inputsDelegate = inputsDelegate - self.stateChangeDelegate = stateChangeDelegate - - try configure(riveFile, artboardName: artboardName, animationName: animationName, stateMachineName: stateMachineName, autoPlay: autoplay) + try sharedInit( + try RiveFile(name: fileName), artboardName: artboardName, animationName: animationName, stateMachineName: stateMachineName, + fit: fit, alignment: alignment, autoplay: autoplay, + playerDelegate: playerDelegate, inputsDelegate: inputsDelegate, stateChangeDelegate: stateChangeDelegate + ) } /// Constructor with a resource file. @@ -227,7 +248,25 @@ open class RiveView: RiveRendererView { stateChangeDelegate: RStateDelegate? = nil ) throws { super.init(frame: .zero) - let riveFile = RiveFile(httpUrl: webURL, with:self)! + try sharedInit( + RiveFile(httpUrl: webURL, with:self)!, artboardName: artboardName, animationName: animationName, stateMachineName: stateMachineName, + fit: fit, alignment: alignment, autoplay: autoplay, + playerDelegate: playerDelegate, inputsDelegate: inputsDelegate, stateChangeDelegate: stateChangeDelegate + ) + } + + private func sharedInit( + _ riveFile: RiveFile, + artboardName: String?, + animationName: String?, + stateMachineName: String?, + fit: Fit, + alignment: Alignment, + autoplay: Bool, + playerDelegate: RivePlayerDelegate?, + inputsDelegate: RInputDelegate?, + stateChangeDelegate: RStateDelegate? + ) throws { self.fit = fit self.alignment = alignment self.playerDelegate = playerDelegate @@ -339,6 +378,8 @@ extension RiveView { } else { advance(delta: 0) } + + showFPS = true } /// Stop playback, clear any created animation or state machine instances. @@ -464,6 +505,7 @@ extension RiveView { displayLinkProxy?.invalidate() displayLinkProxy = nil lastTime = 0 + fpsLabel?.text = "Stopped" } @@ -493,6 +535,11 @@ extension RiveView { // Calculate the time elapsed between ticks let elapsedTime = timestamp - lastTime lastTime = timestamp + + if elapsedTime != 0 { + fpsLabel?.text = fpsFormatter!.string(from: NSNumber(value: 1 / elapsedTime))! + "fps" + } + advance(delta: elapsedTime) if !isPlaying { stopTimer()