Skip to content

Commit

Permalink
feat: add nested inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
HayesGordon committed Jun 5, 2024
1 parent 6f5b4ab commit db7e9bb
Show file tree
Hide file tree
Showing 13 changed files with 187 additions and 8 deletions.
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ dependencies {
implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1'
implementation 'app.rive:rive-android:9.3.6'
implementation 'app.rive:rive-android:9.4.0'
implementation "androidx.startup:startup-runtime:1.1.1"
implementation 'com.android.volley:volley:1.2.0'
}
24 changes: 24 additions & 0 deletions android/src/main/java/com/rivereactnative/RiveReactNativeView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,30 @@ class RiveReactNativeView(private val context: ThemedReactContext) : FrameLayout
}
}

fun fireStateAtPath(inputName: String, path: String) {
try {
riveAnimationView.fireStateAtPath(inputName, path)
} catch (ex: RiveException) {
handleRiveException(ex)
}
}

fun setBooleanStateAtPath(inputName: String, value: Boolean, path: String) {
try {
riveAnimationView.setBooleanStateAtPath(inputName, value, path)
} catch (ex: RiveException) {
handleRiveException(ex)
}
}

fun setNumberStateAtPath(inputName: String, value: Float, path: String) {
try {
riveAnimationView.setNumberStateAtPath(inputName, value, path)
} catch (ex: RiveException) {
handleRiveException(ex)
}
}

private fun handleRiveException(exception: RiveException) {
if (isUserHandlingErrors) {
val rnRiveError = RNRiveError.mapToRNRiveError(exception)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,35 @@ class RiveReactNativeViewManager : SimpleViewManager<RiveReactNativeView>() {
}
}
}
"fireStateAtPath" -> {
args?.let {
val inputName = it.getString(0)
val path = it.getString(1)
view.run {
fireStateAtPath(inputName, path)
}
}
}
"setBooleanStateAtPath" -> {
args?.let {
val inputName = it.getString(0)
val value = it.getBoolean(1)
val path = it.getString(2)
view.run {
setBooleanStateAtPath(inputName, value, path)
}
}
}
"setNumberStateAtPath" -> {
args?.let {
val inputName = it.getString(0)
val value = it.getDouble(1)
val path = it.getString(2)
view.run {
setNumberStateAtPath(inputName, value.toFloat(), path)
}
}
}

// Touch Events

Expand Down
Binary file not shown.
Binary file added example/ios/Assets/runtime_nested_inputs.riv
Binary file not shown.
6 changes: 6 additions & 0 deletions example/ios/RiveReactNativeExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
E5A17A90299AA0F5008CC433 /* avatars.riv in Resources */ = {isa = PBXBuildFile; fileRef = E5A17A8F299AA0F5008CC433 /* avatars.riv */; };
E5F3FC4029B2661500D6D265 /* switch.riv in Resources */ = {isa = PBXBuildFile; fileRef = E5F3FC3F29B2661500D6D265 /* switch.riv */; };
E5FC4EAA2ABB975100D98158 /* rating.riv in Resources */ = {isa = PBXBuildFile; fileRef = E5FC4EA92ABB975100D98158 /* rating.riv */; };
F8AA4CA42C0F3FDB00C1A5FF /* runtime_nested_inputs.riv in Resources */ = {isa = PBXBuildFile; fileRef = F8AA4CA32C0F3FDB00C1A5FF /* runtime_nested_inputs.riv */; };
F8AA4CA52C0F3FDB00C1A5FF /* runtime_nested_inputs.riv in Resources */ = {isa = PBXBuildFile; fileRef = F8AA4CA32C0F3FDB00C1A5FF /* runtime_nested_inputs.riv */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -101,6 +103,7 @@
E5FC4EA92ABB975100D98158 /* rating.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = rating.riv; sourceTree = "<group>"; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; };
F8AA4CA32C0F3FDB00C1A5FF /* runtime_nested_inputs.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = runtime_nested_inputs.riv; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -255,6 +258,7 @@
E5F3FC3F29B2661500D6D265 /* switch.riv */,
9D879D0C265BF2A400D01424 /* ui_swipe_left_to_delete.riv */,
E5FC4EA92ABB975100D98158 /* rating.riv */,
F8AA4CA32C0F3FDB00C1A5FF /* runtime_nested_inputs.riv */,
E5A17A8F299AA0F5008CC433 /* avatars.riv */,
E59C190F2B07F6FE002F0CBA /* nested_menu.riv */,
E5637D79292BD26D000CBC1E /* skills_listener.riv */,
Expand Down Expand Up @@ -398,6 +402,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F8AA4CA52C0F3FDB00C1A5FF /* runtime_nested_inputs.riv in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -409,6 +414,7 @@
E5FC4EAA2ABB975100D98158 /* rating.riv in Resources */,
042FD22726B81BD1004556A3 /* constrained.riv in Resources */,
9D879D0B26578A5E00D01424 /* artboard_animations.riv in Resources */,
F8AA4CA42C0F3FDB00C1A5FF /* runtime_nested_inputs.riv in Resources */,
E5637D7A292BD27F000CBC1E /* skills_listener.riv in Resources */,
04A886F326A990050078530A /* two_bone_ik.riv in Resources */,
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
Expand Down
53 changes: 47 additions & 6 deletions example/src/NestedInputs.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,60 @@
import * as React from 'react';
import { SafeAreaView, ScrollView, StyleSheet } from 'react-native';
import Rive, { Alignment, Fit } from 'rive-react-native';
import { Button, SafeAreaView, ScrollView, StyleSheet } from 'react-native';
import Rive, { Alignment, RiveRef } from 'rive-react-native';

export default function NestedInputs() {
const riveRef = React.useRef<RiveRef>(null);

return (
<SafeAreaView style={styles.safeAreaViewContainer}>
<ScrollView contentContainerStyle={styles.container}>
<Button
title="Outer Cicle On"
onPress={() => {
riveRef.current?.setInputStateAtPath(
'CircleOuterState',
true,
'CircleOuter' // artboard path to input
);
}}
/>
<Button
title="Outer Cicle Off"
onPress={() => {
riveRef.current?.setInputStateAtPath(
'CircleOuterState',
false,
'CircleOuter' // artboard path to input
);
}}
/>
<Button
title="Inner Cicle On"
onPress={() => {
riveRef.current?.setInputStateAtPath(
'CircleInnerState',
true,
'CircleOuter/CircleInner' // artboard path to input
);
}}
/>
<Button
title="Inner Cicle Off"
onPress={() => {
riveRef.current?.setInputStateAtPath(
'CircleInnerState',
false,
'CircleOuter/CircleInner' // artboard path to input
);
}}
/>
<Rive
fit={Fit.Contain}
ref={riveRef}
alignment={Alignment.Center}
style={styles.animation}
artboardName={'Main Artboard'}
autoplay={true}
stateMachineName="State Machine 1"
resourceName={'nested_menu'}
stateMachineName="MainStateMachine"
resourceName={'runtime_nested_inputs'}
/>
</ScrollView>
</SafeAreaView>
Expand Down
12 changes: 12 additions & 0 deletions ios/RiveReactNativeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,18 @@ class RiveReactNativeView: RCTView, RivePlayerDelegate, RiveStateMachineDelegate
func setBooleanState(stateMachineName: String, inputName: String, value: Bool) {
viewModel?.setInput(inputName, value: value)
}

func fireStateAtPath(inputName: String, path: String) {
viewModel?.triggerInput(inputName, path: path)
}

func setNumberStateAtPath(inputName: String, value: Float, path: String) {
viewModel?.setInput(inputName, value: value, path: path)
}

func setBooleanStateAtPath(inputName: String, value: Bool, path: String) {
viewModel?.setInput(inputName, value: value, path: path)
}

// MARK: - Text Runs
func setTextRunValue(textRunName: String, textRunValue: String) throws {
Expand Down
3 changes: 3 additions & 0 deletions ios/RiveReactNativeViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ @interface RCT_EXTERN_MODULE(RiveReactNativeViewManager, RCTViewManager)
RCT_EXTERN_METHOD(fireState:(nonnull NSNumber *)node stateMachineName:(nonnull NSString)stateMachineName inputName:(nonnull NSString)inputName)
RCT_EXTERN_METHOD(setBooleanState:(nonnull NSNumber *)node stateMachineName:(nonnull NSString)stateMachineName inputName:(nonnull NSString)inputName value:(BOOL)value)
RCT_EXTERN_METHOD(setNumberState:(nonnull NSNumber *)node stateMachineName:(nonnull NSString)stateMachineName inputName:(nonnull NSString)inputName value:(nonnull NSNumber *)value)
RCT_EXTERN_METHOD(fireStateAtPath:(nonnull NSNumber *)node inputName:(nonnull NSString)inputName path:(nonnull NSString)path)
RCT_EXTERN_METHOD(setBooleanStateAtPath:(nonnull NSNumber *)node inputName:(nonnull NSString)inputName value:(BOOL)value path:(nonnull NSString)path)
RCT_EXTERN_METHOD(setNumberStateAtPath:(nonnull NSNumber *)node inputName:(nonnull NSString)inputName value:(nonnull NSNumber *)value path:(nonnull NSString)path)
RCT_EXTERN_METHOD(touchBegan:(nonnull NSNumber *)node x:(nonnull NSNumber*)x y:(nonnull NSNumber*)y)
RCT_EXTERN_METHOD(touchMoved:(nonnull NSNumber *)node x:(nonnull NSNumber*)x y:(nonnull NSNumber*)y)
RCT_EXTERN_METHOD(touchEnded:(nonnull NSNumber *)node x:(nonnull NSNumber*)x y:(nonnull NSNumber*)y)
Expand Down
22 changes: 22 additions & 0 deletions ios/RiveReactNativeViewManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class RiveReactNativeViewManager: RCTViewManager {
component.fireState(stateMachineName: stateMachineName, inputName: inputName)
}
}

@objc func setBooleanState(_ node: NSNumber, stateMachineName: String, inputName: String, value: Bool) {
DispatchQueue.main.async {
let component = self.bridge.uiManager.view(forReactTag: node) as! RiveReactNativeView
Expand All @@ -56,6 +57,27 @@ class RiveReactNativeViewManager: RCTViewManager {
component.setNumberState(stateMachineName: stateMachineName, inputName: inputName, value: Float(truncating: value))
}
}

@objc func fireStateAtPath(_ node: NSNumber, inputName: String, path: String) {
DispatchQueue.main.async {
let component = self.bridge.uiManager.view(forReactTag: node) as! RiveReactNativeView
component.fireStateAtPath(inputName: inputName, path: path)
}
}

@objc func setBooleanStateAtPath(_ node: NSNumber, inputName: String, value: Bool, path: String) {
DispatchQueue.main.async {
let component = self.bridge.uiManager.view(forReactTag: node) as! RiveReactNativeView
component.setBooleanStateAtPath(inputName: inputName, value: value, path: path)
}
}

@objc func setNumberStateAtPath(_ node: NSNumber, inputName: String, value: NSNumber, path: String) {
DispatchQueue.main.async {
let component = self.bridge.uiManager.view(forReactTag: node) as! RiveReactNativeView
component.setNumberStateAtPath(inputName: inputName, value: Float(truncating: value), path: path)
}
}

@objc func touchBegan(_ node: NSNumber, x: NSNumber, y: NSNumber) {
DispatchQueue.main.async {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rive-react-native",
"version": "7.1.1",
"version": "7.2.0",
"description": "Rive React Native",
"main": "lib/commonjs/index",
"module": "lib/module/index",
Expand Down
33 changes: 33 additions & 0 deletions src/Rive.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,35 @@ const RiveContainer = React.forwardRef<RiveRef, Props>(
[]
);

const fireStateAtPath = useCallback<
RiveRef[ViewManagerMethod.fireStateAtPath]
>((inputName, path) => {
UIManager.dispatchViewManagerCommand(
findNodeHandle(riveRef.current),
ViewManagerMethod.fireStateAtPath,
[inputName, path]
);
}, []);

const setInputStateAtPath = useCallback<RiveRef['setInputStateAtPath']>(
(inputName, value, path) => {
if (typeof value === 'boolean') {
UIManager.dispatchViewManagerCommand(
findNodeHandle(riveRef.current),
ViewManagerMethod.setBooleanStateAtPath,
[inputName, value, path]
);
} else if (typeof value === 'number') {
UIManager.dispatchViewManagerCommand(
findNodeHandle(riveRef.current),
ViewManagerMethod.setNumberStateAtPath,
[inputName, value, path]
);
}
},
[]
);

const touchBegan = useCallback<RiveRef[ViewManagerMethod.touchBegan]>(
(x: number, y: number) => {
if (!isNaN(x) && !isNaN(y)) {
Expand Down Expand Up @@ -344,7 +373,9 @@ const RiveContainer = React.forwardRef<RiveRef, Props>(
ref,
() => ({
setInputState,
setInputStateAtPath,
fireState,
fireStateAtPath,
play,
pause,
stop,
Expand All @@ -359,7 +390,9 @@ const RiveContainer = React.forwardRef<RiveRef, Props>(
stop,
reset,
setInputState,
setInputStateAtPath,
fireState,
fireStateAtPath,
touchBegan,
touchEnded,
setTextRunValue,
Expand Down
9 changes: 9 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ export type RiveRef = {
inputName: string,
value: boolean | number
) => void;
fireStateAtPath: (inputName: string, path: string) => void;
setInputStateAtPath: (
inputName: string,
value: boolean | number,
path: string
) => void;
play: (
animationName?: string,
loop?: LoopMode,
Expand All @@ -27,6 +33,9 @@ export enum ViewManagerMethod {
fireState = 'fireState',
setBooleanState = 'setBooleanState',
setNumberState = 'setNumberState',
fireStateAtPath = 'fireStateAtPath',
setBooleanStateAtPath = 'setBooleanStateAtPath',
setNumberStateAtPath = 'setNumberStateAtPath',
touchBegan = 'touchBegan',
touchEnded = 'touchEnded',
setTextRunValue = 'setTextRunValue',
Expand Down

0 comments on commit db7e9bb

Please sign in to comment.