Skip to content

Commit 172864c

Browse files
committed
i can see a frame before crashing due to RNW issues
1 parent 9b8c825 commit 172864c

21 files changed

+219
-128
lines changed

bun.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/Shared/src/App.tsx

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { StyleSheet, Pressable, Text, View, ScrollView } from 'react-native'
33
import { NavigationContainer, useNavigation } from '@react-navigation/native'
44
import { createNativeStackNavigator } from '@react-navigation/native-stack'
55
import { GestureHandlerRootView } from 'react-native-gesture-handler'
6+
import {SafeAreaView} from 'react-native-safe-area-context'
67

78
import { AnimationTransitions } from './AnimationTransitions'
89
import { AnimationTransitionsRecording } from './AnimationTransitionsRecording'
@@ -50,6 +51,7 @@ function NavigationItem(props: { name: string; route: string }) {
5051

5152
function HomeScreen() {
5253
return (
54+
<SafeAreaView style={{ flex: 1 }}>
5355
<ScrollView style={{ flex: 1 }}>
5456
<NavigationItem name="▶️ Animation Transitions" route="AnimationTransitions" />
5557
<NavigationItem name="📸 Camera Pan" route="CameraPan" />
@@ -69,6 +71,7 @@ function HomeScreen() {
6971
<NavigationItem name="☁️ Skybox" route="SkyboxExample" />
7072
<NavigationItem name="🔄 MorphTargets" route="MorphTargets" />
7173
</ScrollView>
74+
</SafeAreaView>
7275
)
7376
}
7477

@@ -88,30 +91,30 @@ function App() {
8891
<NavigationContainer>
8992
<Stack.Navigator>
9093
<Stack.Screen name="Home" component={HomeScreen} />
91-
<Stack.Screen
94+
{/* <Stack.Screen
9295
name="AnimationTransitions"
9396
component={AnimationTransitions}
9497
options={{
9598
headerShown: false,
9699
}}
97-
/>
98-
<Stack.Screen name="CameraPan" component={CameraPan} />
99-
<Stack.Screen name="AnimationTransitionsRecording" component={AnimationTransitionsRecording} />
100-
<Stack.Screen name="ImageExample" component={ImageExample} />
101-
<Stack.Screen name="LoadFromFile" component={LoadFromFile} />
102-
<Stack.Screen name="NoneTransparent" component={NoneTransparent} />
100+
/> */}
101+
{/* <Stack.Screen name="CameraPan" component={CameraPan} /> */}
102+
{/* <Stack.Screen name="AnimationTransitionsRecording" component={AnimationTransitionsRecording} /> */}
103+
{/* <Stack.Screen name="ImageExample" component={ImageExample} /> */}
104+
{/* <Stack.Screen name="LoadFromFile" component={LoadFromFile} /> */}
105+
{/* <Stack.Screen name="NoneTransparent" component={NoneTransparent} /> */}
103106
<Stack.Screen name="MultipleInstances" component={MultipleInstances} />
104-
<Stack.Screen name="AnimatedRotate" component={AnimatedRotate} />
105-
<Stack.Screen name="AnimatedRotateSharedValues" component={AnimatedRotateSharedValues} />
106-
<Stack.Screen name="ReanimatedRotation" component={ReanimatedRotation} />
107-
<Stack.Screen name="PhysicsCoin" component={PhysicsCoin} />
108-
<Stack.Screen name="FadeOut" component={FadeOut} />
109-
<Stack.Screen name="CastShadow" component={CastShadow} />
110-
<Stack.Screen name="ScaleEffect" component={ScaleEffect} />
111-
<Stack.Screen name="ChangeMaterials" component={ChangeMaterials} />
107+
{/* <Stack.Screen name="AnimatedRotate" component={AnimatedRotate} /> */}
108+
{/* <Stack.Screen name="AnimatedRotateSharedValues" component={AnimatedRotateSharedValues} /> */}
109+
{/* <Stack.Screen name="ReanimatedRotation" component={ReanimatedRotation} /> */}
110+
{/* <Stack.Screen name="PhysicsCoin" component={PhysicsCoin} /> */}
111+
{/* <Stack.Screen name="FadeOut" component={FadeOut} /> */}
112+
{/* <Stack.Screen name="CastShadow" component={CastShadow} /> */}
113+
{/* <Stack.Screen name="ScaleEffect" component={ScaleEffect} /> */}
114+
{/* <Stack.Screen name="ChangeMaterials" component={ChangeMaterials} /> */}
112115
<Stack.Screen name="Test" component={TestScreen} />
113116
<Stack.Screen name="SkyboxExample" component={SkyboxExample} />
114-
<Stack.Screen name="MorphTargets" component={MorphTargets} />
117+
{/* <Stack.Screen name="MorphTargets" component={MorphTargets} /> */}
115118
</Stack.Navigator>
116119
</NavigationContainer>
117120
</GestureHandlerRootView>

package/android/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ add_library(
3838
../cpp/RNFChoreographer.cpp
3939
../cpp/RNFChoreographerWrapper.cpp
4040
../cpp/RNFListener.cpp
41+
../cpp/jsi/RNFBoxedHybridObject.cpp
4142
../cpp/jsi/RNFHybridObject.cpp
4243
../cpp/jsi/RNFPromise.cpp
4344
../cpp/jsi/RNFPromiseFactory.cpp

package/cpp/RNFFilamentProxy.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@ void FilamentProxy::loadHybridMethods() {
3333
registerHybridGetter("hasWorklets", &FilamentProxy::getHasWorklets, this);
3434
#if HAS_WORKLETS
3535
registerHybridMethod("createWorkletContext", &FilamentProxy::createWorkletContext, this);
36+
// Newly added APIs:
3637
registerHybridMethod("createWorkletAsyncQueue", &FilamentProxy::createWorkletAsyncQueue, this);
3738
registerHybridMethod("installDispatcher", &FilamentProxy::installDispatcher, this);
39+
registerHybridMethod("box", &FilamentProxy::box, this);
3840
#endif
3941
}
4042

@@ -68,20 +70,26 @@ std::shared_ptr<RNWorklet::JsiWorkletContext> FilamentProxy::createWorkletContex
6870
std::shared_ptr<worklets::AsyncQueue> FilamentProxy::createWorkletAsyncQueue() {
6971
Logger::log(TAG, "Creating Worklet AsyncQueue...");
7072
auto renderThreadDispatcher = getRenderThreadDispatcher();
71-
auto runOnWorklet = [=](std::function<void()>&& function) { renderThreadDispatcher->runAsync(std::move(function)); };
73+
// auto runOnWorklet = [=](std::function<void()>&& function) { renderThreadDispatcher->runAsync(std::move(function)); };
7274
// TODO: i am pretty sure i should hold this dispatcher somewhere? or will the JS engine keep it alive as its NativeState?
7375
auto asyncQueue = std::make_shared<RNFAsyncQueueImpl>(renderThreadDispatcher);
7476

7577
return asyncQueue;
7678
}
7779

80+
7881
jsi::Value FilamentProxy::installDispatcher(jsi::Runtime& runtime, const jsi::Value&, const jsi::Value*, size_t) {
7982
auto renderThreadDispatcher = getRenderThreadDispatcher(); // todo: return dispatcher, and pass it here is cleaner i guess
83+
// Note: one thing that is odd, is that this is called with the correct runtime, but on the "wrong" thread.
84+
// this will still be called from the JS thread, but the runtime is the worklet runtime.
8085
Dispatcher::installRuntimeGlobalDispatcher(runtime, renderThreadDispatcher);
81-
Logger::log(TAG, "Successfully installed renderThreadDispatcher into rnw runtime 🎉");
8286
return jsi::Value::undefined();
8387
}
8488

89+
std::shared_ptr<RNFBoxedHybridObject> FilamentProxy::box(const std::shared_ptr<HybridObject>& hybridObject) {
90+
return std::make_shared<RNFBoxedHybridObject>(hybridObject);
91+
}
92+
8593
#endif
8694

8795
jsi::Value FilamentProxy::getCurrentDispatcher(jsi::Runtime& runtime, const jsi::Value&, const jsi::Value*, size_t) {

package/cpp/RNFFilamentProxy.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "bullet/RNFBulletWrapper.h"
1919
#include "core/RNFEngineWrapper.h"
2020
#include "jsi/RNFHybridObject.h"
21+
#include "jsi/RNFBoxedHybridObject.h"
2122
#include "test/RNFTestHybridObject.h"
2223
#include "threading/RNFDispatcher.h"
2324
#include "threading/RNFAsyncQueueImpl.h"
@@ -105,6 +106,8 @@ class FilamentProxy : public HybridObject {
105106

106107
std::shared_ptr<worklets::AsyncQueue> createWorkletAsyncQueue();
107108
jsi::Value installDispatcher(jsi::Runtime& runtime, const jsi::Value&, const jsi::Value*, size_t);
109+
std::shared_ptr<RNFBoxedHybridObject> box(const std::shared_ptr<HybridObject>& hybridObject);
110+
// jsi::Value box(jsi::Runtime& runtime, const jsi::Value&, const jsi::Value*, size_t);
108111
#endif
109112

110113
public:
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//
2+
// BoxedHybridObject.cpp
3+
// NitroModules
4+
//
5+
// Created by Marc Rousavy on 17.09.24.
6+
//
7+
8+
#include "RNFBoxedHybridObject.h"
9+
10+
namespace margelo {
11+
12+
std::vector<jsi::PropNameID> RNFBoxedHybridObject::getPropertyNames(facebook::jsi::Runtime& runtime) {
13+
return jsi::PropNameID::names(runtime, "unbox");
14+
}
15+
16+
jsi::Value RNFBoxedHybridObject::get(jsi::Runtime& runtime, const jsi::PropNameID& propName) {
17+
std::string name = propName.utf8(runtime);
18+
19+
if (name == "unbox") {
20+
return jsi::Function::createFromHostFunction(
21+
runtime, jsi::PropNameID::forUtf8(runtime, "unbox"), 0,
22+
[hybridObject = _hybridObject](jsi::Runtime& runtime, const jsi::Value&, const jsi::Value*, size_t) -> jsi::Value {
23+
return JSIConverter<std::shared_ptr<HybridObject>>::toJSI(runtime, hybridObject);
24+
// return jsi::Object::createFromHostObject(runtime, hybridObject);
25+
});
26+
}
27+
28+
return jsi::Value::undefined();
29+
}
30+
31+
} // namespace margelo::nitro
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//
2+
// Created by Hanno Gödecke on 11.01.26.
3+
// From https://github.com/mrousavy/nitro/blob/afa41bae947ecf738c33569ead42eaf0825cc6d5/packages/react-native-nitro-modules/cpp/core/BoxedHybridObject.hpp
4+
// TODO: should be removable once migrated to nitro modules + RNW supporting nitro HybridObjects
5+
//
6+
7+
#pragma once
8+
9+
#include "RNFHybridObject.h"
10+
#include <jsi/jsi.h>
11+
#include <memory>
12+
13+
namespace margelo {
14+
15+
using namespace facebook;
16+
17+
/**
18+
* Represents a `HybridObject` that has been boxed into a `jsi::HostObject`.
19+
*
20+
* While `HybridObject`s are runtime agnostic, some threading/worklet libraries do not support copying over objects
21+
* with `jsi::NativeState` and a prototype chain (which is what a `HybridObject` is), so Nitro offers support for
22+
* boxing those `HybridObject`s into a type that those libraries support - which is a `jsi::HostObject`.
23+
*
24+
* Simply call `unbox()` on this `jsi::HostObject` from the new Runtime/context to get the `HybridObject` again.
25+
*/
26+
class RNFBoxedHybridObject final : public jsi::HostObject {
27+
public:
28+
explicit RNFBoxedHybridObject(const std::shared_ptr<HybridObject>& hybridObject) : _hybridObject(hybridObject) {}
29+
30+
public:
31+
jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& propName) override;
32+
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime& runtime) override;
33+
34+
private:
35+
std::shared_ptr<HybridObject> _hybridObject;
36+
};
37+
38+
} // namespace margelo::nitro
39+

package/cpp/threading/RNFDispatcher.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ using namespace facebook;
99
static constexpr auto GLOBAL_DISPATCHER_HOLDER_NAME = "__globalDispatcher";
1010

1111
void Dispatcher::installRuntimeGlobalDispatcher(jsi::Runtime& runtime, std::shared_ptr<Dispatcher> dispatcher) {
12-
Logger::log(TAG, "Installing global Dispatcher Holder...");
12+
Logger::log(TAG, "Installing global Dispatcher Holder on runtime ptr: " + std::to_string(reinterpret_cast<uintptr_t>(&runtime)) + " desc: " + runtime.description());
1313

1414
// TODO: we should be able to remove this here, as we now use react-native-worklets
1515
// Track the runtime's lifetime

package/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@
103103
"react": "*",
104104
"react-native": "*",
105105
"react-native-worklets-core": ">=1.3.2",
106-
"react-native-worklets": "*"
106+
"react-native-worklets": "*",
107+
"react-native-reanimated": ">=4.0.0"
107108
},
108109
"release-it": {
109110
"git": {

package/src/hooks/internal/useApplyTransformations.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useFilamentContext } from '../useFilamentContext'
44
import { AABB, Entity, Float3 } from '../../types'
55
import { areFloat3Equal, isWorkletSharedValue } from '../../utilities/helper'
66
import { useWorkletEffect } from '../useWorkletEffect'
7-
import { ISharedValue, Worklets } from 'react-native-worklets-core'
7+
import { makeMutable, type SharedValue } from 'react-native-reanimated'
88

99
type Params = {
1010
// If null it will not take the entity from the context, as it indicates that it will be provided through the param
@@ -76,9 +76,9 @@ export function useApplyTransformations({ to: entity, transformProps, aabb }: Pa
7676
transformToUnitCube,
7777
])
7878

79-
const prevScaleShared = useRef(isWorkletSharedValue(scale) ? Worklets.createSharedValue<Float3 | null>(null) : null)
80-
const prevRotateShared = useRef(isWorkletSharedValue(rotate) ? Worklets.createSharedValue<Float3 | null>(null) : null)
81-
const prevPositionShared = useRef(isWorkletSharedValue(position) ? Worklets.createSharedValue<Float3 | null>(null) : null)
79+
const prevScaleShared = useRef(isWorkletSharedValue(scale) ? makeMutable<Float3 | null>(null) : null)
80+
const prevRotateShared = useRef(isWorkletSharedValue(rotate) ? makeMutable<Float3 | null>(null) : null)
81+
const prevPositionShared = useRef(isWorkletSharedValue(position) ? makeMutable<Float3 | null>(null) : null)
8282

8383
// Effects for when a transform option is a shared value (SRT)
8484
useWorkletEffect(() => {
@@ -91,7 +91,7 @@ export function useApplyTransformations({ to: entity, transformProps, aabb }: Pa
9191
// Generic handler for worklet transform values
9292
const createTransformHandler = (
9393
value: any,
94-
prevValueShared: ISharedValue<Float3 | null> | null,
94+
prevValueShared: SharedValue<Float3 | null> | null,
9595
updater: (newValue: Float3) => void
9696
) => {
9797
'worklet'

0 commit comments

Comments
 (0)