diff --git a/docs/docs/guides/GETTING_STARTED.mdx b/docs/docs/guides/GETTING_STARTED.mdx index 201951c0..6e5509da 100644 --- a/docs/docs/guides/GETTING_STARTED.mdx +++ b/docs/docs/guides/GETTING_STARTED.mdx @@ -12,9 +12,27 @@ import TabItem from '@theme/TabItem' 1. Install [react-native-filament](https://www.npmjs.com/package/react-native-filament): -```sh -npm i react-native-filament -``` += 0.75.x', value: 'RN075'}, + {label: 'React Native < 0.75.x', value: 'RN074'} + ]}> + + We highly recommend that you use react-native >= v0.75.x, as it has a lot of improvements and fixes. You'll get the fastest performance as react-native-filament uses [react-native-nitro-modules](https://nitro.margelo.com/docs/for-users): + + ```sh + npm i react-native-nitro-modules + npm i react-native-filament + ``` + + + ```sh + npm i react-native-filament@^1.0.0 + ``` + + 2. `react-native-filament` depends on [`react-native-worklets-core`](https://github.com/margelo/react-native-worklets-core): @@ -65,7 +83,7 @@ For react-native-worklets-core its necessary to add a plugin to your `babel.conf - You should already use the reaniamted babel pluginVersions, make sure to add the `processNestedWorklets` option to it: + You should already use the reanimated babel pluginVersions, make sure to add the `processNestedWorklets` option to it: ```js module.exports = { diff --git a/package/android/CMakeLists.txt b/package/android/CMakeLists.txt index c65328cf..5de45291 100644 --- a/package/android/CMakeLists.txt +++ b/package/android/CMakeLists.txt @@ -23,6 +23,7 @@ endif() find_package(ReactAndroid REQUIRED CONFIG) find_package(fbjni REQUIRED CONFIG) find_library(LOG_LIB log) +find_package(react-native-nitro-modules REQUIRED) # <-- Used to create all HybridObjects and use the Nitro core library # Add react-native-filament sources add_library( @@ -38,13 +39,11 @@ add_library( ../cpp/RNFChoreographer.cpp ../cpp/RNFChoreographerWrapper.cpp ../cpp/RNFListener.cpp - ../cpp/jsi/RNFHybridObject.cpp ../cpp/jsi/RNFPromise.cpp ../cpp/jsi/RNFPromiseFactory.cpp ../cpp/jsi/RNFRuntimeCache.cpp ../cpp/jsi/RNFWorkletRuntimeRegistry.cpp ../cpp/threading/RNFDispatcher.cpp - ../cpp/test/RNFTestHybridObject.cpp # Filament Core ../cpp/core/RNFEngineImpl.cpp @@ -124,6 +123,7 @@ target_link_libraries( fbjni::fbjni # <-- fbjni GLESv3 # <-- OpenGL (Core) EGL # <-- OpenGL (EGL) + react-native-nitro-modules::NitroModules # <-- NitroModules Core :) ) # Link with RNWC: diff --git a/package/cpp/RNFChoreographer.cpp b/package/cpp/RNFChoreographer.cpp index 21b2b351..307aa8e5 100644 --- a/package/cpp/RNFChoreographer.cpp +++ b/package/cpp/RNFChoreographer.cpp @@ -4,6 +4,7 @@ #include "RNFChoreographer.h" #include "RNFListenerManager.h" +#include "RNFLogger.h" namespace margelo { diff --git a/package/cpp/RNFChoreographer.h b/package/cpp/RNFChoreographer.h index 83813d0d..a6c3fe77 100644 --- a/package/cpp/RNFChoreographer.h +++ b/package/cpp/RNFChoreographer.h @@ -6,6 +6,7 @@ #include "RNFListener.h" #include "RNFListenerManager.h" +#include "RNFLogger.h" #include namespace margelo { diff --git a/package/cpp/RNFChoreographerWrapper.cpp b/package/cpp/RNFChoreographerWrapper.cpp index b8f93746..20831d55 100644 --- a/package/cpp/RNFChoreographerWrapper.cpp +++ b/package/cpp/RNFChoreographerWrapper.cpp @@ -13,10 +13,14 @@ ChoreographerWrapper::~ChoreographerWrapper() { } void ChoreographerWrapper::loadHybridMethods() { - registerHybridMethod("start", &ChoreographerWrapper::start, this); - registerHybridMethod("stop", &ChoreographerWrapper::stop, this); - registerHybridMethod("addFrameCallbackListener", &ChoreographerWrapper::addFrameCallbackListener, this); - registerHybridMethod("release", &ChoreographerWrapper::release, this, true); + PointerHolder::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("start", &ChoreographerWrapper::start); + proto.registerHybridMethod("stop", &ChoreographerWrapper::stop); + proto.registerHybridMethod("addFrameCallbackListener", &ChoreographerWrapper::addFrameCallbackListener); + // TODO: overwrite mechanism doens't exist yet i believe + proto.registerHybridMethod("release", &ChoreographerWrapper::release); + }); } void ChoreographerWrapper::start() { @@ -85,11 +89,12 @@ void ChoreographerWrapper::release() { PointerHolder::release(); } -void ChoreographerWrapper::onRuntimeDestroyed(jsi::Runtime*) { - std::unique_lock lock(_mutex); - Logger::log(TAG, "Runtime destroyed..."); - stopAndRemoveListeners(); -} +// TODO: nitro is this still needed? I don't think so +// void ChoreographerWrapper::onRuntimeDestroyed(jsi::Runtime*) { +// std::unique_lock lock(_mutex); +// Logger::log(TAG, "Runtime destroyed..."); +// stopAndRemoveListeners(); +//} std::shared_ptr ChoreographerWrapper::getChoreographer() { if (getIsValid()) { diff --git a/package/cpp/RNFChoreographerWrapper.h b/package/cpp/RNFChoreographerWrapper.h index cb7d862e..8a7ca013 100644 --- a/package/cpp/RNFChoreographerWrapper.h +++ b/package/cpp/RNFChoreographerWrapper.h @@ -6,14 +6,13 @@ #include "RNFChoreographer.h" #include "jsi/RNFPointerHolder.h" -#include "jsi/RNFRuntimeCache.h" namespace margelo { using FrameInfo = std::unordered_map; using RenderCallback = std::function; -class ChoreographerWrapper : public PointerHolder, public RuntimeLifecycleListener { +class ChoreographerWrapper : public PointerHolder { public: explicit ChoreographerWrapper(std::shared_ptr choreographer) : PointerHolder(TAG, choreographer) {} ~ChoreographerWrapper() override; @@ -32,7 +31,6 @@ class ChoreographerWrapper : public PointerHolder, public Runtime private: // Internal void stopAndRemoveListeners(); - void onRuntimeDestroyed(jsi::Runtime*) override; FrameInfo createFrameInfo(double timestamp); private: diff --git a/package/cpp/RNFFilamentBuffer.h b/package/cpp/RNFFilamentBuffer.h index 3fc1a4b5..e0584415 100644 --- a/package/cpp/RNFFilamentBuffer.h +++ b/package/cpp/RNFFilamentBuffer.h @@ -8,7 +8,9 @@ namespace margelo { class FilamentBuffer : public PointerHolder { public: explicit FilamentBuffer(std::shared_ptr buffer) : PointerHolder("FilamentBuffer", buffer) {} - void loadHybridMethods() override {} + void loadHybridMethods() override { + PointerHolder::loadHybridMethods(); + } std::shared_ptr getBuffer() { return pointee(); diff --git a/package/cpp/RNFFilamentProxy.cpp b/package/cpp/RNFFilamentProxy.cpp index c881994d..f5409be4 100644 --- a/package/cpp/RNFFilamentProxy.cpp +++ b/package/cpp/RNFFilamentProxy.cpp @@ -8,8 +8,6 @@ #include "RNFReferences.h" #include "core/RNFEngineBackendEnum.h" #include "core/RNFEngineConfigHelper.h" -#include "jsi/RNFPromise.h" -#include "threading/RNFDispatcher.h" #include #include @@ -21,18 +19,20 @@ namespace margelo { using namespace facebook; void FilamentProxy::loadHybridMethods() { - registerHybridMethod("loadAsset", &FilamentProxy::loadAssetAsync, this); - registerHybridMethod("findFilamentView", &FilamentProxy::findFilamentViewAsync, this); - registerHybridMethod("createTestObject", &FilamentProxy::createTestObject, this); - registerHybridMethod("createEngine", &FilamentProxy::createEngine, this); - registerHybridMethod("createBullet", &FilamentProxy::createBullet, this); - registerHybridMethod("createChoreographer", &FilamentProxy::createChoreographerWrapper, this); - registerHybridMethod("createRecorder", &FilamentProxy::createRecorder, this); - registerHybridMethod("getCurrentDispatcher", &FilamentProxy::getCurrentDispatcher, this); - registerHybridGetter("hasWorklets", &FilamentProxy::getHasWorklets, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("loadAsset", &FilamentProxy::loadAssetAsync); + proto.registerHybridMethod("findFilamentView", &FilamentProxy::findFilamentViewAsync); + proto.registerHybridMethod("createEngine", &FilamentProxy::createEngine); + proto.registerHybridMethod("createBullet", &FilamentProxy::createBullet); + proto.registerRawHybridMethod("createChoreographer", 0, &FilamentProxy::createChoreographerWrapper); + proto.registerHybridMethod("createRecorder", &FilamentProxy::createRecorder); + proto.registerRawHybridMethod("getCurrentDispatcher", 0, &FilamentProxy::getCurrentDispatcher); + proto.registerHybridGetter("hasWorklets", &FilamentProxy::getHasWorklets); #if HAS_WORKLETS - registerHybridMethod("createWorkletContext", &FilamentProxy::createWorkletContext, this); + proto.registerHybridMethod("createWorkletContext", &FilamentProxy::createWorkletContext); #endif + }); } bool FilamentProxy::getHasWorklets() { @@ -55,7 +55,7 @@ std::shared_ptr FilamentProxy::createWorkletContex Logger::log(TAG, "Successfully created WorkletContext! Installing global Dispatcher..."); workletContext->invokeOnWorkletThread([=](RNWorklet::JsiWorkletContext*, jsi::Runtime& runtime) { - Dispatcher::installRuntimeGlobalDispatcher(runtime, renderThreadDispatcher); + nitro::Dispatcher::installRuntimeGlobalDispatcher(runtime, renderThreadDispatcher); Logger::log(TAG, "Successfully installed global Dispatcher in WorkletContext!"); }); @@ -63,8 +63,17 @@ std::shared_ptr FilamentProxy::createWorkletContex } #endif +// TODO: nitro is this still needed?! jsi::Value FilamentProxy::getCurrentDispatcher(jsi::Runtime& runtime, const jsi::Value&, const jsi::Value*, size_t) { - return Dispatcher::getRuntimeGlobalDispatcherHolder(runtime); +#ifdef NITRO_DEBUG + if (!runtime.global().hasProperty(runtime, "__nitroDispatcher")) [[unlikely]] { + throw std::runtime_error("Failed to get current Dispatcher - the global Dispatcher " + "holder (global.__nitroDispatcher) " + "does not exist! Was Dispatcher::installDispatcherIntoRuntime() called " + "for this jsi::Runtime?"); + } +#endif + return runtime.global().getProperty(runtime, "__nitroDispatcher"); } std::future> FilamentProxy::loadAssetAsync(const std::string& path) { @@ -95,16 +104,11 @@ std::future> FilamentProxy::findFilamentViewAsync( }); } -std::shared_ptr FilamentProxy::createTestObject() { - Logger::log(TAG, "Creating TestObject..."); - return std::make_shared(); -} - std::shared_ptr FilamentProxy::createEngine(std::optional backend, std::optional> arguments) { Logger::log(TAG, "Creating Engine..."); - std::shared_ptr renderThread = getRenderThreadDispatcher(); + std::shared_ptr renderThread = getRenderThreadDispatcher(); Engine::Config config = EngineConfigHelper::makeConfigFromUserParams(arguments); Engine::Backend backendEnum = Engine::Backend::DEFAULT; @@ -145,19 +149,9 @@ jsi::Value FilamentProxy::createChoreographerWrapper(jsi::Runtime& runtime, cons Logger::log(TAG, "Creating Choreographer..."); std::shared_ptr choreographer = createChoreographer(); - ChoreographerWrapper* choreographerWrapperPtr = new ChoreographerWrapper(choreographer); - - RuntimeLifecycleMonitor::addListener(runtime, choreographerWrapperPtr); - - // Wrap the ChoreographerWrapper in a shared_ptr with a custom deleter that removes the listener from the RuntimeLifecycleMonitor: - std::shared_ptr choreographerWrapper = - std::shared_ptr(choreographerWrapperPtr, [&runtime](ChoreographerWrapper* ptr) { - // Remove the ChoreographerWrapper from the RuntimeLifecycleMonitor when it gets destroyed. - RuntimeLifecycleMonitor::removeListener(runtime, ptr); - delete ptr; - }); + std::shared_ptr choreographerWrapper = std::make_shared(choreographer); - return JSIConverter>::toJSI(runtime, choreographerWrapper); + return nitro::JSIConverter>::toJSI(runtime, choreographerWrapper); } } // namespace margelo diff --git a/package/cpp/RNFFilamentProxy.h b/package/cpp/RNFFilamentProxy.h index 6cf84b00..ee95b6a3 100644 --- a/package/cpp/RNFFilamentProxy.h +++ b/package/cpp/RNFFilamentProxy.h @@ -4,6 +4,13 @@ #pragma once +#if __has_include() +#include +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + #include #include @@ -17,9 +24,6 @@ #include "RNFFilamentView.h" #include "bullet/RNFBulletWrapper.h" #include "core/RNFEngineWrapper.h" -#include "jsi/RNFHybridObject.h" -#include "test/RNFTestHybridObject.h" -#include "threading/RNFDispatcher.h" #include @@ -37,7 +41,7 @@ namespace margelo { using namespace facebook; -class FilamentProxy : public HybridObject { +class FilamentProxy : public nitro::HybridObject { public: explicit FilamentProxy() : HybridObject(TAG) {} @@ -51,22 +55,22 @@ class FilamentProxy : public HybridObject { /** * Get the Dispatcher for the main react JS thread. */ - virtual std::shared_ptr getJSDispatcher() = 0; + virtual std::shared_ptr getJSDispatcher() = 0; /** * Get the Dispatcher that is responsible for rendering to Filament. * This is guaranteed to only use a single Thread, as opposed to a Thread-pool. */ - virtual std::shared_ptr getRenderThreadDispatcher() = 0; + virtual std::shared_ptr getRenderThreadDispatcher() = 0; /** * Get the Dispatcher for the platform-default UI Thread. * This is guaranteed to only use a single Thread, as opposed to a Thread-pool. */ - virtual std::shared_ptr getUIDispatcher() = 0; + virtual std::shared_ptr getUIDispatcher() = 0; /** * Get a Dispatcher that uses a Thread-pool for background operations such as File I/O. * This Dispatcher may use multiple Threads to run code. */ - virtual std::shared_ptr getBackgroundDispatcher() = 0; + virtual std::shared_ptr getBackgroundDispatcher() = 0; /** * Get the refresh rate of the display in Hz. * Needed for correct frame pacing and dynamic resolution calculations. @@ -79,9 +83,6 @@ class FilamentProxy : public HybridObject { jsi::Value getCurrentDispatcher(jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* args, size_t count); - // For testing - std::shared_ptr createTestObject(); - // Public API std::future> loadAssetAsync(const std::string& path); std::future> findFilamentViewAsync(int id); diff --git a/package/cpp/RNFFilamentRecorder.cpp b/package/cpp/RNFFilamentRecorder.cpp index fb191e38..dba866e5 100644 --- a/package/cpp/RNFFilamentRecorder.cpp +++ b/package/cpp/RNFFilamentRecorder.cpp @@ -3,13 +3,15 @@ // #include "RNFFilamentRecorder.h" +#include "RNFLogger.h" #include namespace margelo { using namespace facebook; -FilamentRecorder::FilamentRecorder(std::shared_ptr renderThreadDispatcher, int width, int height, int fps, double bitRate) +FilamentRecorder::FilamentRecorder(std::shared_ptr renderThreadDispatcher, int width, int height, int fps, + double bitRate) : HybridObject("FilamentRecorder"), _renderThreadDispatcher(renderThreadDispatcher), _width(width), _height(height), _fps(fps), _bitRate(bitRate), _listenerManager(ListenerManager::create()) { Logger::log(TAG, "Creating %zu x %zu @ %zu FPS (%f bps) FilamentRecorder...", width, height, fps, bitRate); @@ -20,19 +22,23 @@ FilamentRecorder::~FilamentRecorder() { } void FilamentRecorder::loadHybridMethods() { - registerHybridGetter("width", &FilamentRecorder::getWidth, this); - registerHybridGetter("height", &FilamentRecorder::getHeight, this); - registerHybridGetter("fps", &FilamentRecorder::getFps, this); - registerHybridGetter("bitRate", &FilamentRecorder::getBitRate, this); - registerHybridGetter("outputFile", &FilamentRecorder::getOutputFile, this); - registerHybridGetter("isRecording", &FilamentRecorder::getIsRecording, this); - registerHybridMethod("startRecording", &FilamentRecorder::startRecording, this); - registerHybridMethod("stopRecording", &FilamentRecorder::stopRecording, this); - registerHybridMethod("renderFrame", &FilamentRecorder::renderFrame, this); - registerHybridMethod("addOnReadyForMoreDataListener", &FilamentRecorder::addOnReadyForMoreDataListener, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridGetter("width", &FilamentRecorder::getWidth); + proto.registerHybridGetter("height", &FilamentRecorder::getHeight); + proto.registerHybridGetter("fps", &FilamentRecorder::getFps); + proto.registerHybridGetter("bitRate", &FilamentRecorder::getBitRate); + proto.registerHybridGetter("outputFile", &FilamentRecorder::getOutputFile); + proto.registerHybridGetter("isRecording", &FilamentRecorder::getIsRecording); + proto.registerHybridMethod("startRecording", &FilamentRecorder::startRecording); + proto.registerHybridMethod("stopRecording", &FilamentRecorder::stopRecording); + proto.registerHybridMethod("renderFrame", &FilamentRecorder::renderFrame); + // TODO: nitro + // proto.registerHybridMethod("addOnReadyForMoreDataListener", &FilamentRecorder::addOnReadyForMoreDataListener); + }); } -std::shared_ptr FilamentRecorder::addOnReadyForMoreDataListener(ReadyForMoreDataCallback callback) { +std::shared_ptr FilamentRecorder::addOnReadyForMoreDataListener(const ReadyForMoreDataCallback& callback) { return _listenerManager->add(callback); } diff --git a/package/cpp/RNFFilamentRecorder.h b/package/cpp/RNFFilamentRecorder.h index fd5e1762..acbfe1a8 100644 --- a/package/cpp/RNFFilamentRecorder.h +++ b/package/cpp/RNFFilamentRecorder.h @@ -11,19 +11,23 @@ #include "RNFListener.h" #include "RNFListenerManager.h" -#include "jsi/RNFHybridObject.h" -#include "threading/RNFDispatcher.h" +#if __has_include() +#include +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif namespace margelo { using namespace facebook; -class FilamentRecorder : public HybridObject { +class FilamentRecorder : public nitro::HybridObject { public: using ReadyForMoreDataCallback = std::function; public: - explicit FilamentRecorder(std::shared_ptr renderThreadDispatcher, int width, int height, int fps, double bitRate); + explicit FilamentRecorder(std::shared_ptr renderThreadDispatcher, int width, int height, int fps, double bitRate); ~FilamentRecorder(); public: @@ -40,7 +44,7 @@ class FilamentRecorder : public HybridObject { return _bitRate; } - std::shared_ptr addOnReadyForMoreDataListener(ReadyForMoreDataCallback callback); + std::shared_ptr addOnReadyForMoreDataListener(const ReadyForMoreDataCallback& callback); /** * Notify all JS listeners that the Recorder is ready for more data - this will probably cause rendering to happen. * This needs to be called from the renderer Thread! @@ -77,7 +81,7 @@ class FilamentRecorder : public HybridObject { static constexpr auto TAG = "FilamentRecorder"; protected: - std::shared_ptr _renderThreadDispatcher; + std::shared_ptr _renderThreadDispatcher; int _width; int _height; int _fps; diff --git a/package/cpp/RNFFilamentView.cpp b/package/cpp/RNFFilamentView.cpp index a7951712..6e7a703b 100644 --- a/package/cpp/RNFFilamentView.cpp +++ b/package/cpp/RNFFilamentView.cpp @@ -15,8 +15,11 @@ FilamentView::~FilamentView() { } void FilamentView::loadHybridMethods() { - registerHybridMethod("getSurfaceProvider", &FilamentView::getSurfaceProvider, this); - registerHybridMethod("setChoreographer", &FilamentView::setChoreographer, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("getSurfaceProvider", &FilamentView::getSurfaceProvider); + proto.registerHybridMethod("setChoreographer", &FilamentView::setChoreographer); + }); } void FilamentView::setChoreographer(std::optional> choreographerWrapperOrNull) { diff --git a/package/cpp/RNFFilamentView.h b/package/cpp/RNFFilamentView.h index e0b6e51d..c000a6d4 100644 --- a/package/cpp/RNFFilamentView.h +++ b/package/cpp/RNFFilamentView.h @@ -8,7 +8,11 @@ #include "RNFChoreographerWrapper.h" #include "RNFSurfaceProvider.h" -#include "jsi/RNFHybridObject.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif #include #include @@ -16,7 +20,7 @@ namespace margelo { using namespace facebook; -class FilamentView : public HybridObject { +class FilamentView : public nitro::HybridObject { public: explicit FilamentView() : HybridObject("FilamentView") {} ~FilamentView() override; diff --git a/package/cpp/RNFListener.cpp b/package/cpp/RNFListener.cpp index 880fca2f..4bbdb834 100644 --- a/package/cpp/RNFListener.cpp +++ b/package/cpp/RNFListener.cpp @@ -17,7 +17,8 @@ Listener::~Listener() { } void Listener::loadHybridMethods() { - registerHybridMethod("remove", &Listener::remove, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { proto.registerHybridMethod("remove", &Listener::remove); }); } void Listener::remove() { diff --git a/package/cpp/RNFListener.h b/package/cpp/RNFListener.h index ea3e1aa9..880eccd7 100644 --- a/package/cpp/RNFListener.h +++ b/package/cpp/RNFListener.h @@ -4,13 +4,17 @@ #pragma once -#include "jsi/RNFHybridObject.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif #include #include namespace margelo { -class Listener : public HybridObject { +class Listener : public nitro::HybridObject { public: using ListenerRemover = std::function; diff --git a/package/cpp/RNFSurface.cpp b/package/cpp/RNFSurface.cpp index f3c4c2d6..13dd153a 100644 --- a/package/cpp/RNFSurface.cpp +++ b/package/cpp/RNFSurface.cpp @@ -6,8 +6,11 @@ namespace margelo { void Surface::loadHybridMethods() { - registerHybridGetter("width", &Surface::getWidth, this); - registerHybridGetter("height", &Surface::getHeight, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridGetter("width", &Surface::getWidth); + proto.registerHybridGetter("height", &Surface::getHeight); + }); } } // namespace margelo diff --git a/package/cpp/RNFSurface.h b/package/cpp/RNFSurface.h index 3e04f2e2..c4c40044 100644 --- a/package/cpp/RNFSurface.h +++ b/package/cpp/RNFSurface.h @@ -4,13 +4,17 @@ #pragma once -#include "jsi/RNFHybridObject.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif #include #include namespace margelo { -class Surface : public HybridObject { +class Surface : public nitro::HybridObject { public: explicit Surface() : HybridObject("Surface") {} diff --git a/package/cpp/RNFSurfaceProvider.cpp b/package/cpp/RNFSurfaceProvider.cpp index 095b7923..1520c607 100644 --- a/package/cpp/RNFSurfaceProvider.cpp +++ b/package/cpp/RNFSurfaceProvider.cpp @@ -8,9 +8,12 @@ namespace margelo { void SurfaceProvider::loadHybridMethods() { - registerHybridMethod("getSurface", &SurfaceProvider::getSurface, this); - registerHybridMethod("addOnSurfaceCreatedListener", &SurfaceProvider::addOnSurfaceCreatedListener, this); - registerHybridMethod("addOnSurfaceDestroyedListener", &SurfaceProvider::addOnSurfaceDestroyedListener, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("getSurface", &SurfaceProvider::getSurface); + proto.registerHybridMethod("addOnSurfaceCreatedListener", &SurfaceProvider::addOnSurfaceCreatedListener); + proto.registerHybridMethod("addOnSurfaceDestroyedListener", &SurfaceProvider::addOnSurfaceDestroyedListener); + }); } std::shared_ptr SurfaceProvider::addOnSurfaceChangedListener(SurfaceProvider::Callbacks&& callbacks) { @@ -20,7 +23,7 @@ std::shared_ptr SurfaceProvider::addOnSurfaceChangedListener(SurfacePr } std::shared_ptr SurfaceProvider::addOnSurfaceCreatedListener(SurfaceProvider::TOnCreate callback, - std::shared_ptr dispatcher) { + std::shared_ptr dispatcher) { Logger::log(TAG, "Adding \"surface created\" listener"); std::unique_lock lock(_mutex); @@ -36,7 +39,7 @@ std::shared_ptr SurfaceProvider::addOnSurfaceCreatedListener(SurfacePr }); } std::shared_ptr SurfaceProvider::addOnSurfaceDestroyedListener(SurfaceProvider::TOnDestroy callback, - std::shared_ptr dispatcher) { + std::shared_ptr dispatcher) { Logger::log(TAG, "Adding \"surface destroyed\" listener"); std::unique_lock lock(_mutex); diff --git a/package/cpp/RNFSurfaceProvider.h b/package/cpp/RNFSurfaceProvider.h index 9b5c1c93..2e5cae56 100644 --- a/package/cpp/RNFSurfaceProvider.h +++ b/package/cpp/RNFSurfaceProvider.h @@ -4,10 +4,16 @@ #pragma once +#if __has_include() +#include +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + #include "RNFListener.h" #include "RNFListenerManager.h" #include "RNFSurface.h" -#include "jsi/RNFHybridObject.h" #include #include #include @@ -15,7 +21,7 @@ namespace margelo { -class SurfaceProvider : public HybridObject { +class SurfaceProvider : public nitro::HybridObject { public: using TOnCreate = std::function surface)>; using TOnResize = std::function surface, int width, int height)>; @@ -32,8 +38,8 @@ class SurfaceProvider : public HybridObject { public: std::shared_ptr addOnSurfaceChangedListener(Callbacks&& callbacks); - std::shared_ptr addOnSurfaceCreatedListener(TOnCreate callback, std::shared_ptr dispatcher); - std::shared_ptr addOnSurfaceDestroyedListener(TOnDestroy callback, std::shared_ptr dispatcher); + std::shared_ptr addOnSurfaceCreatedListener(TOnCreate callback, std::shared_ptr dispatcher); + std::shared_ptr addOnSurfaceDestroyedListener(TOnDestroy callback, std::shared_ptr dispatcher); virtual std::shared_ptr getSurfaceOrNull() = 0; std::optional> getSurface(); diff --git a/package/cpp/bullet/RNFBulletWrapper.cpp b/package/cpp/bullet/RNFBulletWrapper.cpp index 3019be49..57b9d312 100644 --- a/package/cpp/bullet/RNFBulletWrapper.cpp +++ b/package/cpp/bullet/RNFBulletWrapper.cpp @@ -7,15 +7,18 @@ namespace margelo { void BulletWrapper::loadHybridMethods() { - registerHybridMethod("createDiscreteDynamicWorld", &BulletWrapper::createDiscreteDynamicWorld, this); - registerHybridMethod("createRigidBody", &BulletWrapper::createRigidBody, this); - registerHybridMethod("createBoxShape", &BulletWrapper::createBoxShape, this); - registerHybridMethod("createCylinderShape", &BulletWrapper::createCylinderShape, this); - registerHybridMethod("createCylinderShapeX", &BulletWrapper::createCylinderShapeX, this); - registerHybridMethod("createCylinderShapeZ", &BulletWrapper::createCylinderShapeZ, this); - registerHybridMethod("createStaticPlaneShape", &BulletWrapper::createStaticPlaneShape, this); - registerHybridMethod("createRigidBodyFromTransform", &BulletWrapper::createRigidBodyFromTransform, this); - registerHybridMethod("createSphereShape", &BulletWrapper::createSphereShape, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("createDiscreteDynamicWorld", &BulletWrapper::createDiscreteDynamicWorld); + proto.registerHybridMethod("createRigidBody", &BulletWrapper::createRigidBody); + proto.registerHybridMethod("createBoxShape", &BulletWrapper::createBoxShape); + proto.registerHybridMethod("createCylinderShape", &BulletWrapper::createCylinderShape); + proto.registerHybridMethod("createCylinderShapeX", &BulletWrapper::createCylinderShapeX); + proto.registerHybridMethod("createCylinderShapeZ", &BulletWrapper::createCylinderShapeZ); + proto.registerHybridMethod("createStaticPlaneShape", &BulletWrapper::createStaticPlaneShape); + proto.registerHybridMethod("createRigidBodyFromTransform", &BulletWrapper::createRigidBodyFromTransform); + proto.registerHybridMethod("createSphereShape", &BulletWrapper::createSphereShape); + }); } std::shared_ptr BulletWrapper::createDiscreteDynamicWorld(double gravityX, double gravityY, double gravityZ) { @@ -23,8 +26,8 @@ std::shared_ptr BulletWrapper::createDiscreteDynami } std::shared_ptr BulletWrapper::createRigidBody(double mass, double x, double y, double z, - std::shared_ptr shape, std::string id, - std::optional collisionCallback) { + const std::shared_ptr& shape, std::string id, + const std::optional& collisionCallback) { // Don't pass the shape wrapper, but the shape itself const auto& shapePtr = shape->getShape(); if (shapePtr == nullptr) { @@ -34,9 +37,10 @@ std::shared_ptr BulletWrapper::createRigidBody(double mass, do return RigidBodyWrapper::create(mass, x, y, z, shapePtr, id, collisionCallback); } -std::shared_ptr BulletWrapper::createRigidBodyFromTransform(double mass, std::shared_ptr entityTransform, - std::shared_ptr shape, std::string id, - std::optional collisionCallback) { +std::shared_ptr BulletWrapper::createRigidBodyFromTransform(double mass, + const std::shared_ptr& entityTransform, + const std::shared_ptr& shape, std::string id, + const std::optional& collisionCallback) { const auto& shapePtr = shape->getShape(); if (shapePtr == nullptr) { throw std::runtime_error("Shape is null"); diff --git a/package/cpp/bullet/RNFBulletWrapper.h b/package/cpp/bullet/RNFBulletWrapper.h index 2992e828..a9a40483 100644 --- a/package/cpp/bullet/RNFBulletWrapper.h +++ b/package/cpp/bullet/RNFBulletWrapper.h @@ -12,23 +12,27 @@ #include "RNFRigidBodyWrapper.h" #include "RNFSphereShapeWrapper.h" #include "RNFStaticPlaneShapeWrapper.h" -#include "jsi/RNFHybridObject.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif namespace margelo { // Main Wrapper for all Bullet Physics related APIs -class BulletWrapper : public HybridObject { +class BulletWrapper : public nitro::HybridObject { public: explicit BulletWrapper() : HybridObject("BulletWrapper") {} void loadHybridMethods() override; private: std::shared_ptr createDiscreteDynamicWorld(double gravityX, double gravityY, double gravityZ); - std::shared_ptr createRigidBody(double mass, double x, double y, double z, std::shared_ptr shape, - std::string id, std::optional collisionCallback); - std::shared_ptr createRigidBodyFromTransform(double mass, std::shared_ptr entityTransform, - std::shared_ptr shape, std::string id, - std::optional collisionCallback); + std::shared_ptr createRigidBody(double mass, double x, double y, double z, const std::shared_ptr& shape, + std::string id, const std::optional& collisionCallback); + std::shared_ptr createRigidBodyFromTransform(double mass, const std::shared_ptr& entityTransform, + const std::shared_ptr& shape, std::string id, + const std::optional& collisionCallback); std::shared_ptr createBoxShape(double x, double y, double z); std::shared_ptr createCylinderShape(double x, double y, double z); std::shared_ptr createCylinderShapeX(double x, double y, double z); diff --git a/package/cpp/bullet/RNFDiscreteDynamicWorldWrapper.cpp b/package/cpp/bullet/RNFDiscreteDynamicWorldWrapper.cpp index ca827806..1f9d9309 100644 --- a/package/cpp/bullet/RNFDiscreteDynamicWorldWrapper.cpp +++ b/package/cpp/bullet/RNFDiscreteDynamicWorldWrapper.cpp @@ -19,9 +19,12 @@ DiscreteDynamicWorldWrapper::DiscreteDynamicWorldWrapper(double gravityX, double } void DiscreteDynamicWorldWrapper::loadHybridMethods() { - registerHybridMethod("addRigidBody", &DiscreteDynamicWorldWrapper::addRigidBody, this); - registerHybridMethod("removeRigidBody", &DiscreteDynamicWorldWrapper::removeRigidBody, this); - registerHybridMethod("stepSimulation", &DiscreteDynamicWorldWrapper::stepSimulation, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("addRigidBody", &DiscreteDynamicWorldWrapper::addRigidBody); + proto.registerHybridMethod("removeRigidBody", &DiscreteDynamicWorldWrapper::removeRigidBody); + proto.registerHybridMethod("stepSimulation", &DiscreteDynamicWorldWrapper::stepSimulation); + }); } void DiscreteDynamicWorldWrapper::addRigidBody(std::shared_ptr rigidBody) { diff --git a/package/cpp/bullet/RNFDiscreteDynamicWorldWrapper.h b/package/cpp/bullet/RNFDiscreteDynamicWorldWrapper.h index 72412afc..50712b8a 100644 --- a/package/cpp/bullet/RNFDiscreteDynamicWorldWrapper.h +++ b/package/cpp/bullet/RNFDiscreteDynamicWorldWrapper.h @@ -5,14 +5,18 @@ #pragma once #include "RNFRigidBodyWrapper.h" -#include "jsi/RNFHybridObject.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif #include #include namespace margelo { -class DiscreteDynamicWorldWrapper : public HybridObject { +class DiscreteDynamicWorldWrapper : public nitro::HybridObject { public: explicit DiscreteDynamicWorldWrapper(double gravityX, double gravityY, double gravityZ); diff --git a/package/cpp/bullet/RNFRigidBodyWrapper.cpp b/package/cpp/bullet/RNFRigidBodyWrapper.cpp index dcc84351..46418f7f 100644 --- a/package/cpp/bullet/RNFRigidBodyWrapper.cpp +++ b/package/cpp/bullet/RNFRigidBodyWrapper.cpp @@ -70,14 +70,17 @@ std::shared_ptr RigidBodyWrapper::create(double mass, std::sha } void RigidBodyWrapper::loadHybridMethods() { - registerHybridMethod("setDamping", &RigidBodyWrapper::setDamping, this); - registerHybridSetter("friction", &RigidBodyWrapper::setFriction, this); - registerHybridGetter("friction", &RigidBodyWrapper::getFriction, this); - registerHybridSetter("activationState", &RigidBodyWrapper::setActivationState, this); - registerHybridGetter("activationState", &RigidBodyWrapper::getActivationState, this); - registerHybridGetter("id", &RigidBodyWrapper::getId, this); - registerHybridSetter("id", &RigidBodyWrapper::setId, this); - registerHybridMethod("setCollisionCallback", &RigidBodyWrapper::setCollisionCallback, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("setDamping", &RigidBodyWrapper::setDamping); + proto.registerHybridSetter("friction", &RigidBodyWrapper::setFriction); + proto.registerHybridGetter("friction", &RigidBodyWrapper::getFriction); + proto.registerHybridSetter("activationState", &RigidBodyWrapper::setActivationState); + proto.registerHybridGetter("activationState", &RigidBodyWrapper::getActivationState); + proto.registerHybridGetter("id", &RigidBodyWrapper::getId); + proto.registerHybridSetter("id", &RigidBodyWrapper::setId); + proto.registerHybridMethod("setCollisionCallback", &RigidBodyWrapper::setCollisionCallback); + }); } void RigidBodyWrapper::setDamping(double linearDamping, double angularDamping) { diff --git a/package/cpp/bullet/RNFRigidBodyWrapper.h b/package/cpp/bullet/RNFRigidBodyWrapper.h index a01161d1..46dd12db 100644 --- a/package/cpp/bullet/RNFRigidBodyWrapper.h +++ b/package/cpp/bullet/RNFRigidBodyWrapper.h @@ -7,7 +7,11 @@ #include "RNFActivationStateEnum.h" #include "core/RNFFilamentAssetWrapper.h" #include "core/math/RNFTMat44Wrapper.h" -#include "jsi/RNFHybridObject.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif #include @@ -19,9 +23,9 @@ class RigidBodyWrapper; * first arg: "this" rigid body * second arg: the rigid body "this" is colliding with */ -using CollisionCallback = std::function&, const std::shared_ptr)>; +using CollisionCallback = std::function&, const std::shared_ptr&)>; -class RigidBodyWrapper : public HybridObject { +class RigidBodyWrapper : public nitro::HybridObject { public: explicit RigidBodyWrapper(double mass, std::shared_ptr shape, std::unique_ptr motionState, std::string id, std::optional collisionCallback); diff --git a/package/cpp/bullet/RNFShapeWrapper.cpp b/package/cpp/bullet/RNFShapeWrapper.cpp index 574ca226..1d854e47 100644 --- a/package/cpp/bullet/RNFShapeWrapper.cpp +++ b/package/cpp/bullet/RNFShapeWrapper.cpp @@ -7,10 +7,13 @@ namespace margelo { void margelo::ShapeWrapper::loadHybridMethods() { - registerHybridGetter("localScaling", &ShapeWrapper::getLocalScaling, this); - registerHybridSetter("localScaling", &ShapeWrapper::setLocalScaling, this); - registerHybridGetter("margin", &ShapeWrapper::getMargin, this); - registerHybridSetter("margin", &ShapeWrapper::setMargin, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridGetter("localScaling", &ShapeWrapper::getLocalScaling); + proto.registerHybridSetter("localScaling", &ShapeWrapper::setLocalScaling); + proto.registerHybridGetter("margin", &ShapeWrapper::getMargin); + proto.registerHybridSetter("margin", &ShapeWrapper::setMargin); + }); } std::vector ShapeWrapper::getLocalScaling() { diff --git a/package/cpp/bullet/RNFShapeWrapper.h b/package/cpp/bullet/RNFShapeWrapper.h index d1677e56..93e94a82 100644 --- a/package/cpp/bullet/RNFShapeWrapper.h +++ b/package/cpp/bullet/RNFShapeWrapper.h @@ -4,7 +4,11 @@ #pragma once -#include "jsi/RNFHybridObject.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif #include namespace margelo { @@ -13,7 +17,7 @@ namespace margelo { * Base class for all bullet collision shapes. * Every new collision shape we want to support in the API should be derived from this class. */ -class ShapeWrapper : public HybridObject { +class ShapeWrapper : public nitro::HybridObject { public: explicit ShapeWrapper(const char* name, std::shared_ptr shape) : HybridObject(name), _shape(shape) {}; diff --git a/package/cpp/core/RNFAABBWrapper.cpp b/package/cpp/core/RNFAABBWrapper.cpp index 3768120e..0159fc1d 100644 --- a/package/cpp/core/RNFAABBWrapper.cpp +++ b/package/cpp/core/RNFAABBWrapper.cpp @@ -6,10 +6,13 @@ namespace margelo { void AABBWrapper::loadHybridMethods() { - registerHybridGetter("center", &AABBWrapper::getCenter, this); - registerHybridGetter("halfExtent", &AABBWrapper::getHalfExtent, this); - registerHybridGetter("min", &AABBWrapper::getMin, this); - registerHybridGetter("max", &AABBWrapper::getMax, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridGetter("center", &AABBWrapper::getCenter); + proto.registerHybridGetter("halfExtent", &AABBWrapper::getHalfExtent); + proto.registerHybridGetter("min", &AABBWrapper::getMin); + proto.registerHybridGetter("max", &AABBWrapper::getMax); + }); } std::vector AABBWrapper::getCenter() { @@ -31,4 +34,4 @@ std::vector AABBWrapper::getMax() { math::float3 max = _aabb.max; return {max.x, max.y, max.z}; } -} // namespace margelo \ No newline at end of file +} // namespace margelo diff --git a/package/cpp/core/RNFAABBWrapper.h b/package/cpp/core/RNFAABBWrapper.h index 0c3fc8a7..bbff6e58 100644 --- a/package/cpp/core/RNFAABBWrapper.h +++ b/package/cpp/core/RNFAABBWrapper.h @@ -5,13 +5,17 @@ #pragma once #include -#include +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif namespace margelo { using namespace filament; -class AABBWrapper : public HybridObject { +class AABBWrapper : public nitro::HybridObject { public: explicit AABBWrapper(const Aabb& aabb) : HybridObject("AABBWrapper"), _aabb(aabb) {} void loadHybridMethods() override; diff --git a/package/cpp/core/RNFAmbientOcclusionOptionsWrapper.h b/package/cpp/core/RNFAmbientOcclusionOptionsWrapper.h index 2cc83612..d76f6705 100644 --- a/package/cpp/core/RNFAmbientOcclusionOptionsWrapper.h +++ b/package/cpp/core/RNFAmbientOcclusionOptionsWrapper.h @@ -5,44 +5,51 @@ #pragma once #include "RNFQualityLevel.h" -#include "jsi/RNFHybridObject.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif #include namespace margelo { using namespace filament; -class AmbientOcclusionOptionsWrapper : public HybridObject, public AmbientOcclusionOptions { +class AmbientOcclusionOptionsWrapper : public nitro::HybridObject, public AmbientOcclusionOptions { public: explicit AmbientOcclusionOptionsWrapper() : HybridObject("AmbientOcclusionOptionsWrapper") {} explicit AmbientOcclusionOptionsWrapper(const AmbientOcclusionOptions& options) : HybridObject("AmbientOcclusionOptionsWrapper"), AmbientOcclusionOptions(options) {} void loadHybridMethods() override { - registerHybridGetter("radius", &AmbientOcclusionOptionsWrapper::getRadius, this); - registerHybridSetter("radius", &AmbientOcclusionOptionsWrapper::setRadius, this); - registerHybridGetter("power", &AmbientOcclusionOptionsWrapper::getPower, this); - registerHybridSetter("power", &AmbientOcclusionOptionsWrapper::setPower, this); - registerHybridGetter("bias", &AmbientOcclusionOptionsWrapper::getBias, this); - registerHybridSetter("bias", &AmbientOcclusionOptionsWrapper::setBias, this); - registerHybridGetter("resolution", &AmbientOcclusionOptionsWrapper::getResolution, this); - registerHybridSetter("resolution", &AmbientOcclusionOptionsWrapper::setResolution, this); - registerHybridGetter("intensity", &AmbientOcclusionOptionsWrapper::getIntensity, this); - registerHybridSetter("intensity", &AmbientOcclusionOptionsWrapper::setIntensity, this); - registerHybridGetter("bilateralThreshold", &AmbientOcclusionOptionsWrapper::getBilateralThreshold, this); - registerHybridSetter("bilateralThreshold", &AmbientOcclusionOptionsWrapper::setBilateralThreshold, this); - registerHybridGetter("quality", &AmbientOcclusionOptionsWrapper::getQuality, this); - registerHybridSetter("quality", &AmbientOcclusionOptionsWrapper::setQuality, this); - registerHybridGetter("lowPassFilter", &AmbientOcclusionOptionsWrapper::getLowPassFilter, this); - registerHybridSetter("lowPassFilter", &AmbientOcclusionOptionsWrapper::setLowPassFilter, this); - registerHybridGetter("upsampling", &AmbientOcclusionOptionsWrapper::getUpsampling, this); - registerHybridSetter("upsampling", &AmbientOcclusionOptionsWrapper::setUpsampling, this); - registerHybridGetter("enabled", &AmbientOcclusionOptionsWrapper::getEnabled, this); - registerHybridSetter("enabled", &AmbientOcclusionOptionsWrapper::setEnabled, this); - registerHybridGetter("bentNormals", &AmbientOcclusionOptionsWrapper::getBentNormals, this); - registerHybridSetter("bentNormals", &AmbientOcclusionOptionsWrapper::setBentNormals, this); - registerHybridGetter("minHorizonAngleRad", &AmbientOcclusionOptionsWrapper::getMinHorizonAngleRad, this); - registerHybridSetter("minHorizonAngleRad", &AmbientOcclusionOptionsWrapper::setMinHorizonAngleRad, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridGetter("radius", &AmbientOcclusionOptionsWrapper::getRadius); + proto.registerHybridSetter("radius", &AmbientOcclusionOptionsWrapper::setRadius); + proto.registerHybridGetter("power", &AmbientOcclusionOptionsWrapper::getPower); + proto.registerHybridSetter("power", &AmbientOcclusionOptionsWrapper::setPower); + proto.registerHybridGetter("bias", &AmbientOcclusionOptionsWrapper::getBias); + proto.registerHybridSetter("bias", &AmbientOcclusionOptionsWrapper::setBias); + proto.registerHybridGetter("resolution", &AmbientOcclusionOptionsWrapper::getResolution); + proto.registerHybridSetter("resolution", &AmbientOcclusionOptionsWrapper::setResolution); + proto.registerHybridGetter("intensity", &AmbientOcclusionOptionsWrapper::getIntensity); + proto.registerHybridSetter("intensity", &AmbientOcclusionOptionsWrapper::setIntensity); + proto.registerHybridGetter("bilateralThreshold", &AmbientOcclusionOptionsWrapper::getBilateralThreshold); + proto.registerHybridSetter("bilateralThreshold", &AmbientOcclusionOptionsWrapper::setBilateralThreshold); + proto.registerHybridGetter("quality", &AmbientOcclusionOptionsWrapper::getQuality); + proto.registerHybridSetter("quality", &AmbientOcclusionOptionsWrapper::setQuality); + proto.registerHybridGetter("lowPassFilter", &AmbientOcclusionOptionsWrapper::getLowPassFilter); + proto.registerHybridSetter("lowPassFilter", &AmbientOcclusionOptionsWrapper::setLowPassFilter); + proto.registerHybridGetter("upsampling", &AmbientOcclusionOptionsWrapper::getUpsampling); + proto.registerHybridSetter("upsampling", &AmbientOcclusionOptionsWrapper::setUpsampling); + proto.registerHybridGetter("enabled", &AmbientOcclusionOptionsWrapper::getEnabled); + proto.registerHybridSetter("enabled", &AmbientOcclusionOptionsWrapper::setEnabled); + proto.registerHybridGetter("bentNormals", &AmbientOcclusionOptionsWrapper::getBentNormals); + proto.registerHybridSetter("bentNormals", &AmbientOcclusionOptionsWrapper::setBentNormals); + proto.registerHybridGetter("minHorizonAngleRad", &AmbientOcclusionOptionsWrapper::getMinHorizonAngleRad); + proto.registerHybridSetter("minHorizonAngleRad", &AmbientOcclusionOptionsWrapper::setMinHorizonAngleRad); + }); } private: diff --git a/package/cpp/core/RNFAnimatorWrapper.cpp b/package/cpp/core/RNFAnimatorWrapper.cpp index 82f971bb..7ffd4a69 100644 --- a/package/cpp/core/RNFAnimatorWrapper.cpp +++ b/package/cpp/core/RNFAnimatorWrapper.cpp @@ -9,15 +9,18 @@ namespace margelo { void AnimatorWrapper::loadHybridMethods() { - registerHybridMethod("applyAnimation", &AnimatorWrapper::applyAnimation, this); - registerHybridMethod("updateBoneMatrices", &AnimatorWrapper::updateBoneMatrices, this); - registerHybridMethod("applyCrossFade", &AnimatorWrapper::applyCrossFade, this); - registerHybridMethod("resetBoneMatrices", &AnimatorWrapper::resetBoneMatrices, this); - registerHybridMethod("getAnimationCount", &AnimatorWrapper::getAnimationCount, this); - registerHybridMethod("getAnimationDuration", &AnimatorWrapper::getAnimationDuration, this); - registerHybridMethod("getAnimationName", &AnimatorWrapper::getAnimationName, this); - registerHybridMethod("addToSyncList", &AnimatorWrapper::addToSyncList, this); - registerHybridMethod("removeFromSyncList", &AnimatorWrapper::removeFromSyncList, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("applyAnimation", &AnimatorWrapper::applyAnimation); + proto.registerHybridMethod("updateBoneMatrices", &AnimatorWrapper::updateBoneMatrices); + proto.registerHybridMethod("applyCrossFade", &AnimatorWrapper::applyCrossFade); + proto.registerHybridMethod("resetBoneMatrices", &AnimatorWrapper::resetBoneMatrices); + proto.registerHybridMethod("getAnimationCount", &AnimatorWrapper::getAnimationCount); + proto.registerHybridMethod("getAnimationDuration", &AnimatorWrapper::getAnimationDuration); + proto.registerHybridMethod("getAnimationName", &AnimatorWrapper::getAnimationName); + proto.registerHybridMethod("addToSyncList", &AnimatorWrapper::addToSyncList); + proto.registerHybridMethod("removeFromSyncList", &AnimatorWrapper::removeFromSyncList); + }); } inline void assertAnimationIndexSmallerThan(int animationIndex, int max) { diff --git a/package/cpp/core/RNFAnimatorWrapper.h b/package/cpp/core/RNFAnimatorWrapper.h index db040e4b..82f3ba24 100644 --- a/package/cpp/core/RNFAnimatorWrapper.h +++ b/package/cpp/core/RNFAnimatorWrapper.h @@ -6,7 +6,11 @@ #include "RNFFilamentAssetWrapper.h" #include "RNFFilamentInstanceWrapper.h" -#include "jsi/RNFHybridObject.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif #include #include @@ -17,7 +21,7 @@ namespace margelo { using namespace filament::gltfio; using EntityNameMap = std::map; -class AnimatorWrapper : public HybridObject { +class AnimatorWrapper : public nitro::HybridObject { public: explicit AnimatorWrapper(Animator* animator, FilamentInstance* instance, std::shared_ptr nameComponentManager) : HybridObject("AnimatorWrapper"), _animator(animator), _instance(instance), _nameComponentManager(nameComponentManager), diff --git a/package/cpp/core/RNFBoxWrapper.cpp b/package/cpp/core/RNFBoxWrapper.cpp index eb1c4167..b004cc0a 100644 --- a/package/cpp/core/RNFBoxWrapper.cpp +++ b/package/cpp/core/RNFBoxWrapper.cpp @@ -6,10 +6,13 @@ namespace margelo { void BoxWrapper::loadHybridMethods() { - registerHybridGetter("center", &BoxWrapper::getCenter, this); - registerHybridGetter("halfExtent", &BoxWrapper::getHalfExtent, this); - registerHybridGetter("min", &BoxWrapper::getMin, this); - registerHybridGetter("max", &BoxWrapper::getMax, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridGetter("center", &BoxWrapper::getCenter); + proto.registerHybridGetter("halfExtent", &BoxWrapper::getHalfExtent); + proto.registerHybridGetter("min", &BoxWrapper::getMin); + proto.registerHybridGetter("max", &BoxWrapper::getMax); + }); } std::vector BoxWrapper::getCenter() { diff --git a/package/cpp/core/RNFBoxWrapper.h b/package/cpp/core/RNFBoxWrapper.h index e3c138e2..3945f1d6 100644 --- a/package/cpp/core/RNFBoxWrapper.h +++ b/package/cpp/core/RNFBoxWrapper.h @@ -5,13 +5,17 @@ #pragma once #include -#include +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif namespace margelo { using namespace filament; -class BoxWrapper : public HybridObject { +class BoxWrapper : public nitro::HybridObject { public: explicit BoxWrapper(const Box& box) : HybridObject("BoxWrapper"), _box(box) {} void loadHybridMethods() override; diff --git a/package/cpp/core/RNFCameraWrapper.cpp b/package/cpp/core/RNFCameraWrapper.cpp index 4706a445..9e926ca2 100644 --- a/package/cpp/core/RNFCameraWrapper.cpp +++ b/package/cpp/core/RNFCameraWrapper.cpp @@ -2,10 +2,13 @@ #include "RNFCameraFovEnum.h" void margelo::CameraWrapper::loadHybridMethods() { - registerHybridMethod("lookAtCameraManipulator", &CameraWrapper::lookAtCameraManipulator, this); - registerHybridMethod("lookAt", &CameraWrapper::lookAt, this); - registerHybridMethod("setLensProjection", &CameraWrapper::setLensProjection, this); - registerHybridMethod("setProjection", &CameraWrapper::setProjection, this); + PointerHolder::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("lookAtCameraManipulator", &CameraWrapper::lookAtCameraManipulator); + proto.registerHybridMethod("lookAt", &CameraWrapper::lookAt); + proto.registerHybridMethod("setLensProjection", &CameraWrapper::setLensProjection); + proto.registerHybridMethod("setProjection", &CameraWrapper::setProjection); + }); } void margelo::CameraWrapper::lookAtCameraManipulator(std::shared_ptr cameraManipulator) { diff --git a/package/cpp/core/RNFDynamicResolutionOptions.h b/package/cpp/core/RNFDynamicResolutionOptions.h index b01b2c8f..62ac9451 100644 --- a/package/cpp/core/RNFDynamicResolutionOptions.h +++ b/package/cpp/core/RNFDynamicResolutionOptions.h @@ -5,32 +5,39 @@ #pragma once #include "RNFQualityLevel.h" -#include "jsi/RNFHybridObject.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif #include namespace margelo { using namespace filament; -class DynamicResolutionOptionsWrapper : public HybridObject, public DynamicResolutionOptions { +class DynamicResolutionOptionsWrapper : public nitro::HybridObject, public DynamicResolutionOptions { public: explicit DynamicResolutionOptionsWrapper() : HybridObject("DynamicResolutionOptions") {} explicit DynamicResolutionOptionsWrapper(const DynamicResolutionOptions& options) : HybridObject("DynamicResolutionOptions"), DynamicResolutionOptions(options) {} void loadHybridMethods() { - registerHybridGetter("minScale", &DynamicResolutionOptionsWrapper::getMinScale, this); - registerHybridSetter("minScale", &DynamicResolutionOptionsWrapper::setMinScale, this); - registerHybridGetter("maxScale", &DynamicResolutionOptionsWrapper::getMaxScale, this); - registerHybridSetter("maxScale", &DynamicResolutionOptionsWrapper::setMaxScale, this); - registerHybridGetter("sharpness", &DynamicResolutionOptionsWrapper::getSharpness, this); - registerHybridSetter("sharpness", &DynamicResolutionOptionsWrapper::setSharpness, this); - registerHybridGetter("enabled", &DynamicResolutionOptionsWrapper::getEnabled, this); - registerHybridSetter("enabled", &DynamicResolutionOptionsWrapper::setEnabled, this); - registerHybridGetter("homogeneousScaling", &DynamicResolutionOptionsWrapper::getHomogeneousScaling, this); - registerHybridSetter("homogeneousScaling", &DynamicResolutionOptionsWrapper::setHomogeneousScaling, this); - registerHybridGetter("quality", &DynamicResolutionOptionsWrapper::getQuality, this); - registerHybridSetter("quality", &DynamicResolutionOptionsWrapper::setQuality, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridGetter("minScale", &DynamicResolutionOptionsWrapper::getMinScale); + proto.registerHybridSetter("minScale", &DynamicResolutionOptionsWrapper::setMinScale); + proto.registerHybridGetter("maxScale", &DynamicResolutionOptionsWrapper::getMaxScale); + proto.registerHybridSetter("maxScale", &DynamicResolutionOptionsWrapper::setMaxScale); + proto.registerHybridGetter("sharpness", &DynamicResolutionOptionsWrapper::getSharpness); + proto.registerHybridSetter("sharpness", &DynamicResolutionOptionsWrapper::setSharpness); + proto.registerHybridGetter("enabled", &DynamicResolutionOptionsWrapper::getEnabled); + proto.registerHybridSetter("enabled", &DynamicResolutionOptionsWrapper::setEnabled); + proto.registerHybridGetter("homogeneousScaling", &DynamicResolutionOptionsWrapper::getHomogeneousScaling); + proto.registerHybridSetter("homogeneousScaling", &DynamicResolutionOptionsWrapper::setHomogeneousScaling); + proto.registerHybridGetter("quality", &DynamicResolutionOptionsWrapper::getQuality); + proto.registerHybridSetter("quality", &DynamicResolutionOptionsWrapper::setQuality); + }); } private: diff --git a/package/cpp/core/RNFEngineImpl.cpp b/package/cpp/core/RNFEngineImpl.cpp index b82b0ac5..75ab67d1 100644 --- a/package/cpp/core/RNFEngineImpl.cpp +++ b/package/cpp/core/RNFEngineImpl.cpp @@ -33,7 +33,7 @@ namespace margelo { -EngineImpl::EngineImpl(std::shared_ptr rendererDispatcher, std::shared_ptr engine, float displayRefreshRate, +EngineImpl::EngineImpl(std::shared_ptr rendererDispatcher, std::shared_ptr engine, float displayRefreshRate, float densityPixelRatio) : _engine(engine), _rendererDispatcher(rendererDispatcher), _densityPixelRatio(densityPixelRatio) { diff --git a/package/cpp/core/RNFEngineImpl.h b/package/cpp/core/RNFEngineImpl.h index 4a42677a..5b08aa1e 100644 --- a/package/cpp/core/RNFEngineImpl.h +++ b/package/cpp/core/RNFEngineImpl.h @@ -4,6 +4,12 @@ #pragma once +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + #include "jsi/RNFPointerHolder.h" #include "RNFChoreographer.h" @@ -20,7 +26,6 @@ #include "bullet/RNFRigidBodyWrapper.h" #include "core/utils/RNFEntityWrapper.h" #include "core/utils/RNFManipulatorWrapper.h" -#include "threading/RNFDispatcher.h" #include #include @@ -45,7 +50,7 @@ using ManipulatorBuilder = Manipulator::Builder; // If you add a new method that you want to expose to JS, you need to add it to the EngineWrapper as well. class EngineImpl : public std::enable_shared_from_this { public: - explicit EngineImpl(std::shared_ptr rendererDispatcher, std::shared_ptr engine, float displayRefreshRate, + explicit EngineImpl(std::shared_ptr rendererDispatcher, std::shared_ptr engine, float displayRefreshRate, float densityPixelRatio); // First a surface provider must be set, then once we have a surface a swapchain can be created and finally the swapchain can be set @@ -63,8 +68,7 @@ class EngineImpl : public std::enable_shared_from_this { std::shared_ptr createNameComponentManager(); std::shared_ptr createMaterial(std::shared_ptr materialBuffer); void createAndSetSkybox(std::string hexColor, std::optional showSun, std::optional envIntensity); - void createAndSetSkybox(std::shared_ptr textureBuffer, std::optional showSun, - std::optional envIntensity); + void createAndSetSkybox(std::shared_ptr textureBuffer, std::optional showSun, std::optional envIntensity); void clearSkybox(); void setAutomaticInstancingEnabled(bool enabled); @@ -73,7 +77,7 @@ class EngineImpl : public std::enable_shared_from_this { private: std::mutex _mutex; std::shared_ptr _engine; - std::shared_ptr _rendererDispatcher; + std::shared_ptr _rendererDispatcher; std::shared_ptr _surfaceProvider; std::shared_ptr _surfaceListener; std::shared_ptr _materialProvider; diff --git a/package/cpp/core/RNFEngineWrapper.cpp b/package/cpp/core/RNFEngineWrapper.cpp index 5960f930..7c9073b4 100644 --- a/package/cpp/core/RNFEngineWrapper.cpp +++ b/package/cpp/core/RNFEngineWrapper.cpp @@ -32,28 +32,31 @@ namespace margelo { void EngineWrapper::loadHybridMethods() { - registerHybridMethod("setSurfaceProvider", &EngineWrapper::setSurfaceProvider, this); - registerHybridMethod("createSwapChainForSurface", &EngineWrapper::createSwapChainForSurface, this); - registerHybridMethod("createSwapChainForRecorder", &EngineWrapper::createSwapChainForRecorder, this); - registerHybridMethod("setSwapChain", &EngineWrapper::setSwapChain, this); - registerHybridMethod("setIndirectLight", &EngineWrapper::setIndirectLight, this); - registerHybridMethod("loadAsset", &EngineWrapper::loadAsset, this); - registerHybridMethod("loadInstancedAsset", &EngineWrapper::loadInstancedAsset, this); - registerHybridMethod("getScene", &EngineWrapper::getScene, this); - registerHybridMethod("getView", &EngineWrapper::getView, this); - registerHybridMethod("getCamera", &EngineWrapper::getCamera, this); - registerHybridMethod("createOrbitCameraManipulator", &EngineWrapper::createOrbitCameraManipulator, this); - registerHybridMethod("createTransformManager", &EngineWrapper::createTransformManager, this); - registerHybridMethod("createRenderableManager", &EngineWrapper::createRenderableManager, this); - registerHybridMethod("createMaterial", &EngineWrapper::createMaterial, this); - registerHybridMethod("createLightManager", &EngineWrapper::createLightManager, this); - registerHybridMethod("createRenderer", &EngineWrapper::createRenderer, this); - registerHybridMethod("createNameComponentManager", &EngineWrapper::createNameComponentManager, this); - registerHybridMethod("createAndSetSkyboxByColor", &EngineWrapper::createAndSetSkyboxByColor, this); - registerHybridMethod("createAndSetSkyboxByTexture", &EngineWrapper::createAndSetSkyboxByTexture, this); - registerHybridMethod("clearSkybox", &EngineWrapper::clearSkybox, this); - registerHybridMethod("setAutomaticInstancingEnabled", &EngineWrapper::setAutomaticInstancingEnabled, this); - registerHybridMethod("flushAndWait", &EngineWrapper::flushAndWait, this); + PointerHolder::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("setSurfaceProvider", &EngineWrapper::setSurfaceProvider); + proto.registerHybridMethod("createSwapChainForSurface", &EngineWrapper::createSwapChainForSurface); + proto.registerHybridMethod("createSwapChainForRecorder", &EngineWrapper::createSwapChainForRecorder); + proto.registerHybridMethod("setSwapChain", &EngineWrapper::setSwapChain); + proto.registerHybridMethod("setIndirectLight", &EngineWrapper::setIndirectLight); + proto.registerHybridMethod("loadAsset", &EngineWrapper::loadAsset); + proto.registerHybridMethod("loadInstancedAsset", &EngineWrapper::loadInstancedAsset); + proto.registerHybridMethod("getScene", &EngineWrapper::getScene); + proto.registerHybridMethod("getView", &EngineWrapper::getView); + proto.registerHybridMethod("getCamera", &EngineWrapper::getCamera); + proto.registerHybridMethod("createOrbitCameraManipulator", &EngineWrapper::createOrbitCameraManipulator); + proto.registerHybridMethod("createTransformManager", &EngineWrapper::createTransformManager); + proto.registerHybridMethod("createRenderableManager", &EngineWrapper::createRenderableManager); + proto.registerHybridMethod("createMaterial", &EngineWrapper::createMaterial); + proto.registerHybridMethod("createLightManager", &EngineWrapper::createLightManager); + proto.registerHybridMethod("createRenderer", &EngineWrapper::createRenderer); + proto.registerHybridMethod("createNameComponentManager", &EngineWrapper::createNameComponentManager); + proto.registerHybridMethod("createAndSetSkyboxByColor", &EngineWrapper::createAndSetSkyboxByColor); + proto.registerHybridMethod("createAndSetSkyboxByTexture", &EngineWrapper::createAndSetSkyboxByTexture); + proto.registerHybridMethod("clearSkybox", &EngineWrapper::clearSkybox); + proto.registerHybridMethod("setAutomaticInstancingEnabled", &EngineWrapper::setAutomaticInstancingEnabled); + proto.registerHybridMethod("flushAndWait", &EngineWrapper::flushAndWait); + }); } void EngineWrapper::setSurfaceProvider(std::shared_ptr surfaceProvider) { pointee()->setSurfaceProvider(surfaceProvider); diff --git a/package/cpp/core/RNFEngineWrapper.h b/package/cpp/core/RNFEngineWrapper.h index a3302a11..4e359e3f 100644 --- a/package/cpp/core/RNFEngineWrapper.h +++ b/package/cpp/core/RNFEngineWrapper.h @@ -39,7 +39,6 @@ #include "RNFSwapChainWrapper.h" #include "RNFTransformManagerWrapper.h" #include "RNFViewWrapper.h" -#include "threading/RNFDispatcher.h" #include #include #include diff --git a/package/cpp/core/RNFFilamentAssetWrapper.cpp b/package/cpp/core/RNFFilamentAssetWrapper.cpp index 0bb472e2..30735f34 100644 --- a/package/cpp/core/RNFFilamentAssetWrapper.cpp +++ b/package/cpp/core/RNFFilamentAssetWrapper.cpp @@ -11,17 +11,20 @@ namespace margelo { using namespace utils; void FilamentAssetWrapper::loadHybridMethods() { - registerHybridMethod("getRoot", &FilamentAssetWrapper::getRoot, this); - registerHybridMethod("releaseSourceData", &FilamentAssetWrapper::releaseSourceData, this); - registerHybridMethod("createAnimator", &FilamentAssetWrapper::createAnimator, this); - registerHybridGetter("entityCount", &FilamentAssetWrapper::getEntityCount, this); - registerHybridMethod("getEntities", &FilamentAssetWrapper::getEntities, this); - registerHybridGetter("renderableEntityCount", &FilamentAssetWrapper::getRenderableEntityCount, this); - registerHybridMethod("getRenderableEntities", &FilamentAssetWrapper::getRenderableEntities, this); - registerHybridMethod("getBoundingBox", &FilamentAssetWrapper::getBoundingBox, this); - registerHybridMethod("getFirstEntityByName", &FilamentAssetWrapper::getFirstEntityByName, this); - registerHybridMethod("getInstance", &FilamentAssetWrapper::getInstance, this); - registerHybridMethod("getAssetInstances", &FilamentAssetWrapper::getAssetInstances, this); + PointerHolder::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("getRoot", &FilamentAssetWrapper::getRoot); + proto.registerHybridMethod("releaseSourceData", &FilamentAssetWrapper::releaseSourceData); + proto.registerHybridMethod("createAnimator", &FilamentAssetWrapper::createAnimator); + proto.registerHybridGetter("entityCount", &FilamentAssetWrapper::getEntityCount); + proto.registerHybridMethod("getEntities", &FilamentAssetWrapper::getEntities); + proto.registerHybridGetter("renderableEntityCount", &FilamentAssetWrapper::getRenderableEntityCount); + proto.registerHybridMethod("getRenderableEntities", &FilamentAssetWrapper::getRenderableEntities); + proto.registerHybridMethod("getBoundingBox", &FilamentAssetWrapper::getBoundingBox); + proto.registerHybridMethod("getFirstEntityByName", &FilamentAssetWrapper::getFirstEntityByName); + proto.registerHybridMethod("getInstance", &FilamentAssetWrapper::getInstance); + proto.registerHybridMethod("getAssetInstances", &FilamentAssetWrapper::getAssetInstances); + }); } std::shared_ptr FilamentAssetWrapper::getRoot() { diff --git a/package/cpp/core/RNFFilamentInstanceWrapper.cpp b/package/cpp/core/RNFFilamentInstanceWrapper.cpp index 0c8b5354..3530fe8f 100644 --- a/package/cpp/core/RNFFilamentInstanceWrapper.cpp +++ b/package/cpp/core/RNFFilamentInstanceWrapper.cpp @@ -10,11 +10,14 @@ namespace margelo { void FilamentInstanceWrapper::loadHybridMethods() { - registerHybridGetter("entityCount", &FilamentInstanceWrapper::getEntityCount, this); - registerHybridMethod("getEntities", &FilamentInstanceWrapper::getEntities, this); - registerHybridMethod("getRoot", &FilamentInstanceWrapper::getRoot, this); - registerHybridMethod("createAnimator", &FilamentInstanceWrapper::createAnimator, this); - registerHybridMethod("getBoundingBox", &FilamentInstanceWrapper::getBoundingBox, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridGetter("entityCount", &FilamentInstanceWrapper::getEntityCount); + proto.registerHybridMethod("getEntities", &FilamentInstanceWrapper::getEntities); + proto.registerHybridMethod("getRoot", &FilamentInstanceWrapper::getRoot); + proto.registerHybridMethod("createAnimator", &FilamentInstanceWrapper::createAnimator); + proto.registerHybridMethod("getBoundingBox", &FilamentInstanceWrapper::getBoundingBox); + }); } int FilamentInstanceWrapper::getEntityCount() { diff --git a/package/cpp/core/RNFFilamentInstanceWrapper.h b/package/cpp/core/RNFFilamentInstanceWrapper.h index 51a0b13c..aef397c5 100644 --- a/package/cpp/core/RNFFilamentInstanceWrapper.h +++ b/package/cpp/core/RNFFilamentInstanceWrapper.h @@ -6,7 +6,11 @@ #include "RNFAABBWrapper.h" #include "RNFNameComponentManagerWrapper.h" -#include "jsi/RNFHybridObject.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif #include "utils/RNFEntityWrapper.h" #include @@ -18,7 +22,7 @@ using namespace gltfio; class AnimatorWrapper; -class FilamentInstanceWrapper : public HybridObject { +class FilamentInstanceWrapper : public nitro::HybridObject { public: explicit FilamentInstanceWrapper(FilamentInstance* instance) : HybridObject("FilamentInstanceWrapper"), _instance(instance) {} diff --git a/package/cpp/core/RNFLightManagerWrapper.cpp b/package/cpp/core/RNFLightManagerWrapper.cpp index 353f9b5c..21db0fd5 100644 --- a/package/cpp/core/RNFLightManagerWrapper.cpp +++ b/package/cpp/core/RNFLightManagerWrapper.cpp @@ -13,20 +13,23 @@ namespace margelo { void LightManagerWrapper::loadHybridMethods() { - registerHybridMethod("createLightEntity", &LightManagerWrapper::createLightEntity, this); - registerHybridMethod("destroy", &LightManagerWrapper::destroy, this); - registerHybridMethod("setPosition", &LightManagerWrapper::setPosition, this); - registerHybridMethod("getPosition", &LightManagerWrapper::getPosition, this); - registerHybridMethod("setDirection", &LightManagerWrapper::setDirection, this); - registerHybridMethod("getDirection", &LightManagerWrapper::getDirection, this); - registerHybridMethod("setColor", &LightManagerWrapper::setColor, this); - registerHybridMethod("getColor", &LightManagerWrapper::getColor, this); - registerHybridMethod("setIntensity", &LightManagerWrapper::setIntensity, this); - registerHybridMethod("getIntensity", &LightManagerWrapper::getIntensity, this); - registerHybridMethod("setFalloff", &LightManagerWrapper::setFalloff, this); - registerHybridMethod("getFalloff", &LightManagerWrapper::getFalloff, this); - registerHybridMethod("setSpotLightCone", &LightManagerWrapper::setSpotLightCone, this); - registerHybridMethod("getSpotLightCone", &LightManagerWrapper::getSpotLightCone, this); + PointerHolder::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("createLightEntity", &LightManagerWrapper::createLightEntity); + proto.registerHybridMethod("destroy", &LightManagerWrapper::destroy); + proto.registerHybridMethod("setPosition", &LightManagerWrapper::setPosition); + proto.registerHybridMethod("getPosition", &LightManagerWrapper::getPosition); + proto.registerHybridMethod("setDirection", &LightManagerWrapper::setDirection); + proto.registerHybridMethod("getDirection", &LightManagerWrapper::getDirection); + proto.registerHybridMethod("setColor", &LightManagerWrapper::setColor); + proto.registerHybridMethod("getColor", &LightManagerWrapper::getColor); + proto.registerHybridMethod("setIntensity", &LightManagerWrapper::setIntensity); + proto.registerHybridMethod("getIntensity", &LightManagerWrapper::getIntensity); + proto.registerHybridMethod("setFalloff", &LightManagerWrapper::setFalloff); + proto.registerHybridMethod("getFalloff", &LightManagerWrapper::getFalloff); + proto.registerHybridMethod("setSpotLightCone", &LightManagerWrapper::setSpotLightCone); + proto.registerHybridMethod("getSpotLightCone", &LightManagerWrapper::getSpotLightCone); + }); } std::shared_ptr LightManagerWrapper::createLightEntity(const std::string& lightTypeStr, std::optional colorKelvin, @@ -171,4 +174,4 @@ std::vector LightManagerWrapper::getSpotLightCone(std::shared_ptr(innerCone), static_cast(outerCone)}; } -} // namespace margelo \ No newline at end of file +} // namespace margelo diff --git a/package/cpp/core/RNFMaterialImpl.h b/package/cpp/core/RNFMaterialImpl.h index 6ec64035..d89fc868 100644 --- a/package/cpp/core/RNFMaterialImpl.h +++ b/package/cpp/core/RNFMaterialImpl.h @@ -5,7 +5,11 @@ #pragma once #include "RNFMaterialInstanceWrapper.h" -#include "jsi/RNFHybridObject.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif #include diff --git a/package/cpp/core/RNFMaterialInstanceWrapper.cpp b/package/cpp/core/RNFMaterialInstanceWrapper.cpp index a08977c2..055a5e21 100644 --- a/package/cpp/core/RNFMaterialInstanceWrapper.cpp +++ b/package/cpp/core/RNFMaterialInstanceWrapper.cpp @@ -10,20 +10,23 @@ namespace margelo { void MaterialInstanceWrapper::loadHybridMethods() { - registerHybridMethod("setCullingMode", &MaterialInstanceWrapper::setCullingMode, this); - registerHybridMethod("setTransparencyMode", &MaterialInstanceWrapper::setTransparencyMode, this); - registerHybridMethod("changeAlpha", &MaterialInstanceWrapper::changeAlpha, this); - registerHybridMethod("setFloatParameter", &MaterialInstanceWrapper::setFloatParameter, this); - registerHybridMethod("setIntParameter", &MaterialInstanceWrapper::setIntParameter, this); - registerHybridMethod("setFloat3Parameter", &MaterialInstanceWrapper::setFloat3Parameter, this); - registerHybridMethod("setFloat4Parameter", &MaterialInstanceWrapper::setFloat4Parameter, this); - registerHybridMethod("setMat3fParameter", &MaterialInstanceWrapper::setMat3fParameter, this); - registerHybridMethod("getFloatParameter", &MaterialInstanceWrapper::getFloatParameter, this); - registerHybridMethod("getIntParameter", &MaterialInstanceWrapper::getIntParameter, this); - registerHybridMethod("getFloat3Parameter", &MaterialInstanceWrapper::getFloat3Parameter, this); - registerHybridMethod("getFloat4Parameter", &MaterialInstanceWrapper::getFloat4Parameter, this); - registerHybridMethod("getMat3fParameter", &MaterialInstanceWrapper::getMat3fParameter, this); - registerHybridGetter("getName", &MaterialInstanceWrapper::getName, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("setCullingMode", &MaterialInstanceWrapper::setCullingMode); + proto.registerHybridMethod("setTransparencyMode", &MaterialInstanceWrapper::setTransparencyMode); + proto.registerHybridMethod("changeAlpha", &MaterialInstanceWrapper::changeAlpha); + proto.registerHybridMethod("setFloatParameter", &MaterialInstanceWrapper::setFloatParameter); + proto.registerHybridMethod("setIntParameter", &MaterialInstanceWrapper::setIntParameter); + proto.registerHybridMethod("setFloat3Parameter", &MaterialInstanceWrapper::setFloat3Parameter); + proto.registerHybridMethod("setFloat4Parameter", &MaterialInstanceWrapper::setFloat4Parameter); + proto.registerHybridMethod("setMat3fParameter", &MaterialInstanceWrapper::setMat3fParameter); + proto.registerHybridMethod("getFloatParameter", &MaterialInstanceWrapper::getFloatParameter); + proto.registerHybridMethod("getIntParameter", &MaterialInstanceWrapper::getIntParameter); + proto.registerHybridMethod("getFloat3Parameter", &MaterialInstanceWrapper::getFloat3Parameter); + proto.registerHybridMethod("getFloat4Parameter", &MaterialInstanceWrapper::getFloat4Parameter); + proto.registerHybridMethod("getMat3fParameter", &MaterialInstanceWrapper::getMat3fParameter); + proto.registerHybridGetter("getName", &MaterialInstanceWrapper::getName); + }); } void MaterialInstanceWrapper::setCullingMode(std::string mode) { diff --git a/package/cpp/core/RNFMaterialInstanceWrapper.h b/package/cpp/core/RNFMaterialInstanceWrapper.h index 7e18c0aa..80531d14 100644 --- a/package/cpp/core/RNFMaterialInstanceWrapper.h +++ b/package/cpp/core/RNFMaterialInstanceWrapper.h @@ -6,13 +6,17 @@ #include -#include "jsi/RNFHybridObject.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif namespace margelo { using namespace filament; -class MaterialInstanceWrapper : public HybridObject { +class MaterialInstanceWrapper : public nitro::HybridObject { public: explicit MaterialInstanceWrapper(MaterialInstance* materialInstance) diff --git a/package/cpp/core/RNFMaterialWrapper.cpp b/package/cpp/core/RNFMaterialWrapper.cpp index e63ec894..09d59b05 100644 --- a/package/cpp/core/RNFMaterialWrapper.cpp +++ b/package/cpp/core/RNFMaterialWrapper.cpp @@ -9,14 +9,17 @@ namespace margelo { void MaterialWrapper::loadHybridMethods() { - registerHybridMethod("createInstance", &MaterialWrapper::createInstance, this); - registerHybridMethod("setDefaultFloatParameter", &MaterialWrapper::setDefaultFloatParameter, this); - registerHybridMethod("setDefaultTextureParameter", &MaterialWrapper::setDefaultTextureParameter, this); - registerHybridMethod("getDefaultInstance", &MaterialWrapper::getDefaultInstance, this); - registerHybridMethod("setDefaultMat3fParameter", &MaterialWrapper::setDefaultMat3fParameter, this); - registerHybridMethod("setDefaultFloat3Parameter", &MaterialWrapper::setDefaultFloat3Parameter, this); - registerHybridMethod("setDefaultFloat4Parameter", &MaterialWrapper::setDefaultFloat4Parameter, this); - registerHybridMethod("setDefaultIntParameter", &MaterialWrapper::setDefaultIntParameter, this); + PointerHolder::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("createInstance", &MaterialWrapper::createInstance); + proto.registerHybridMethod("setDefaultFloatParameter", &MaterialWrapper::setDefaultFloatParameter); + proto.registerHybridMethod("setDefaultTextureParameter", &MaterialWrapper::setDefaultTextureParameter); + proto.registerHybridMethod("getDefaultInstance", &MaterialWrapper::getDefaultInstance); + proto.registerHybridMethod("setDefaultMat3fParameter", &MaterialWrapper::setDefaultMat3fParameter); + proto.registerHybridMethod("setDefaultFloat3Parameter", &MaterialWrapper::setDefaultFloat3Parameter); + proto.registerHybridMethod("setDefaultFloat4Parameter", &MaterialWrapper::setDefaultFloat4Parameter); + proto.registerHybridMethod("setDefaultIntParameter", &MaterialWrapper::setDefaultIntParameter); + }); } std::shared_ptr MaterialWrapper::createInstance() { return pointee()->createInstance(); @@ -62,4 +65,4 @@ void MaterialWrapper::setDefaultMat3fParameter(std::string name, std::vectorgetName(); } -} // namespace margelo \ No newline at end of file +} // namespace margelo diff --git a/package/cpp/core/RNFNameComponentManagerWrapper.cpp b/package/cpp/core/RNFNameComponentManagerWrapper.cpp index e638cedb..99162ba5 100644 --- a/package/cpp/core/RNFNameComponentManagerWrapper.cpp +++ b/package/cpp/core/RNFNameComponentManagerWrapper.cpp @@ -5,29 +5,30 @@ namespace margelo { - void NameComponentManagerWrapper::loadHybridMethods() { - registerHybridMethod("getEntityName", &NameComponentManagerWrapper::getEntityName, this); - } +void NameComponentManagerWrapper::loadHybridMethods() { + PointerHolder::loadHybridMethods(); + registerHybrids( + this, [](nitro::Prototype& proto) { proto.registerHybridMethod("getEntityName", &NameComponentManagerWrapper::getEntityName); }); +} - // TODO: This code is similar to EntityNameMap AnimatorWrapper::createEntityNameMap, consider refactoring - std::optional - NameComponentManagerWrapper::getEntityName(std::shared_ptr entityWrapper) { - if (!entityWrapper) { - throw std::invalid_argument("EntityWrapper is null"); - } +// TODO: This code is similar to EntityNameMap AnimatorWrapper::createEntityNameMap, consider refactoring +std::optional NameComponentManagerWrapper::getEntityName(std::shared_ptr entityWrapper) { + if (!entityWrapper) { + throw std::invalid_argument("EntityWrapper is null"); + } - Entity entity = entityWrapper->getEntity(); - bool hasEntity = pointee()->hasComponent(entity); - if (!hasEntity) { - Logger::log(TAG, "Entity wasn't found in NameComponentManager"); - return std::nullopt; - } + Entity entity = entityWrapper->getEntity(); + bool hasEntity = pointee()->hasComponent(entity); + if (!hasEntity) { + Logger::log(TAG, "Entity wasn't found in NameComponentManager"); + return std::nullopt; + } - NameComponentManager::Instance instance = pointee()->getInstance(entity); - if (!instance || !instance.isValid()) { - Logger::log(TAG, "Instance wasn't found in NameComponentManager"); - return std::nullopt; - } - return pointee()->getName(instance); - } -} \ No newline at end of file + NameComponentManager::Instance instance = pointee()->getInstance(entity); + if (!instance || !instance.isValid()) { + Logger::log(TAG, "Instance wasn't found in NameComponentManager"); + return std::nullopt; + } + return pointee()->getName(instance); +} +} // namespace margelo diff --git a/package/cpp/core/RNFNameComponentManagerWrapper.h b/package/cpp/core/RNFNameComponentManagerWrapper.h index cd12747b..1cb8ecf5 100644 --- a/package/cpp/core/RNFNameComponentManagerWrapper.h +++ b/package/cpp/core/RNFNameComponentManagerWrapper.h @@ -4,8 +4,8 @@ #pragma once -#include "jsi/RNFPointerHolder.h" #include "core/utils/RNFEntityWrapper.h" +#include "jsi/RNFPointerHolder.h" #include namespace margelo { @@ -27,7 +27,7 @@ class NameComponentManagerWrapper : public PointerHolder { static auto constexpr TAG = "NameComponentManagerWrapper"; private: // Exposed JS method - std::optional getEntityName(std::shared_ptr entityWrapper); + std::optional getEntityName(std::shared_ptr entityWrapper); }; } // namespace margelo diff --git a/package/cpp/core/RNFRenderableManagerImpl.h b/package/cpp/core/RNFRenderableManagerImpl.h index c503e499..55419956 100644 --- a/package/cpp/core/RNFRenderableManagerImpl.h +++ b/package/cpp/core/RNFRenderableManagerImpl.h @@ -4,6 +4,12 @@ #pragma once +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + #include "RNFFilamentAssetWrapper.h" #include "RNFFilamentBuffer.h" #include "RNFMaterialInstanceWrapper.h" @@ -28,7 +34,7 @@ struct DebugVertex { class RenderableManagerImpl { public: - explicit RenderableManagerImpl(std::shared_ptr engine, std::shared_ptr rendererDispatcher) + explicit RenderableManagerImpl(std::shared_ptr engine, std::shared_ptr rendererDispatcher) : _engine(engine), _rendererDispatcher(rendererDispatcher) { _textureProvider = std::shared_ptr(filament::gltfio::createStbProvider(_engine.get())); } @@ -86,7 +92,7 @@ class RenderableManagerImpl { private: std::shared_ptr _engine; - std::shared_ptr _rendererDispatcher; + std::shared_ptr _rendererDispatcher; std::shared_ptr _textureProvider; // Keep a list of all material instances the RenderableManager creates, so we can clean them up when the RenderableManager is std::vector> _materialInstances; diff --git a/package/cpp/core/RNFRenderableManagerWrapper.cpp b/package/cpp/core/RNFRenderableManagerWrapper.cpp index 8a7cc7ca..2df0cd9b 100644 --- a/package/cpp/core/RNFRenderableManagerWrapper.cpp +++ b/package/cpp/core/RNFRenderableManagerWrapper.cpp @@ -10,19 +10,22 @@ namespace margelo { void RenderableManagerWrapper::loadHybridMethods() { - registerHybridMethod("getPrimitiveCount", &RenderableManagerWrapper::getPrimitiveCount, this); - registerHybridMethod("getMaterialInstanceAt", &RenderableManagerWrapper::getMaterialInstanceAt, this); - registerHybridMethod("setMaterialInstanceAt", &RenderableManagerWrapper::setMaterialInstanceAt, this); - registerHybridMethod("setAssetEntitiesOpacity", &RenderableManagerWrapper::setAssetEntitiesOpacity, this); - registerHybridMethod("setInstanceEntitiesOpacity", &RenderableManagerWrapper::setInstanceWrapperEntitiesOpacity, this); - registerHybridMethod("changeMaterialTextureMap", &RenderableManagerWrapper::changeMaterialTextureMap, this); - registerHybridMethod("setCastShadow", &RenderableManagerWrapper::setCastShadow, this); - registerHybridMethod("setReceiveShadow", &RenderableManagerWrapper::setReceiveShadow, this); - registerHybridMethod("createPlane", &RenderableManagerWrapper::createPlane, this); - registerHybridMethod("createImageBackgroundShape", &RenderableManagerWrapper::createImageBackgroundShape, this); - registerHybridMethod("scaleBoundingBox", &RenderableManagerWrapper::scaleBoundingBox, this); - registerHybridMethod("createDebugCubeWireframe", &RenderableManagerWrapper::createDebugCubeWireframe, this); - registerHybridMethod("getAxisAlignedBoundingBox", &RenderableManagerWrapper::getAxisAlignedBoundingBox, this); + PointerHolder::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("getPrimitiveCount", &RenderableManagerWrapper::getPrimitiveCount); + proto.registerHybridMethod("getMaterialInstanceAt", &RenderableManagerWrapper::getMaterialInstanceAt); + proto.registerHybridMethod("setMaterialInstanceAt", &RenderableManagerWrapper::setMaterialInstanceAt); + proto.registerHybridMethod("setAssetEntitiesOpacity", &RenderableManagerWrapper::setAssetEntitiesOpacity); + proto.registerHybridMethod("setInstanceEntitiesOpacity", &RenderableManagerWrapper::setInstanceWrapperEntitiesOpacity); + proto.registerHybridMethod("changeMaterialTextureMap", &RenderableManagerWrapper::changeMaterialTextureMap); + proto.registerHybridMethod("setCastShadow", &RenderableManagerWrapper::setCastShadow); + proto.registerHybridMethod("setReceiveShadow", &RenderableManagerWrapper::setReceiveShadow); + proto.registerHybridMethod("createPlane", &RenderableManagerWrapper::createPlane); + proto.registerHybridMethod("createImageBackgroundShape", &RenderableManagerWrapper::createImageBackgroundShape); + proto.registerHybridMethod("scaleBoundingBox", &RenderableManagerWrapper::scaleBoundingBox); + proto.registerHybridMethod("createDebugCubeWireframe", &RenderableManagerWrapper::createDebugCubeWireframe); + proto.registerHybridMethod("getAxisAlignedBoundingBox", &RenderableManagerWrapper::getAxisAlignedBoundingBox); + }); } int RenderableManagerWrapper::getPrimitiveCount(std::shared_ptr entity) { return pointee()->getPrimitiveCount(entity); @@ -90,4 +93,4 @@ std::shared_ptr RenderableManagerWrapper::getAxisAlignedBoundingBox( return std::make_shared(box); } -} // namespace margelo \ No newline at end of file +} // namespace margelo diff --git a/package/cpp/core/RNFRendererWrapper.cpp b/package/cpp/core/RNFRendererWrapper.cpp index 32c5ab12..dd329746 100644 --- a/package/cpp/core/RNFRendererWrapper.cpp +++ b/package/cpp/core/RNFRendererWrapper.cpp @@ -6,12 +6,15 @@ namespace margelo { void RendererWrapper::loadHybridMethods() { - registerHybridMethod("setFrameRateOptions", &RendererWrapper::setFrameRateOptions, this); - registerHybridMethod("setClearContent", &RendererWrapper::setClearContent, this); - registerHybridMethod("setPresentationTime", &RendererWrapper::setPresentationTime, this); - registerHybridMethod("beginFrame", &RendererWrapper::beginFrame, this); - registerHybridMethod("render", &RendererWrapper::render, this); - registerHybridMethod("endFrame", &RendererWrapper::endFrame, this); + PointerHolder::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("setFrameRateOptions", &RendererWrapper::setFrameRateOptions); + proto.registerHybridMethod("setClearContent", &RendererWrapper::setClearContent); + proto.registerHybridMethod("setPresentationTime", &RendererWrapper::setPresentationTime); + proto.registerHybridMethod("beginFrame", &RendererWrapper::beginFrame); + proto.registerHybridMethod("render", &RendererWrapper::render); + proto.registerHybridMethod("endFrame", &RendererWrapper::endFrame); + }); } void RendererWrapper::setFrameRateOptions(std::unordered_map options) { diff --git a/package/cpp/core/RNFSceneWrapper.cpp b/package/cpp/core/RNFSceneWrapper.cpp index 86b249e4..44380674 100644 --- a/package/cpp/core/RNFSceneWrapper.cpp +++ b/package/cpp/core/RNFSceneWrapper.cpp @@ -5,13 +5,16 @@ namespace margelo { void margelo::SceneWrapper::loadHybridMethods() { - registerHybridMethod("addEntity", &SceneWrapper::addEntity, this); - registerHybridMethod("addEntities", &SceneWrapper::addEntities, this); - registerHybridMethod("removeEntity", &SceneWrapper::removeEntity, this); - registerHybridMethod("removeEntities", &SceneWrapper::removeEntities, this); - registerHybridMethod("addAssetEntities", &SceneWrapper::addAssetEntities, this); - registerHybridMethod("removeAssetEntities", &SceneWrapper::removeAssetEntities, this); - registerHybridGetter("entityCount", &SceneWrapper::getEntityCount, this); + PointerHolder::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("addEntity", &SceneWrapper::addEntity); + proto.registerHybridMethod("addEntities", &SceneWrapper::addEntities); + proto.registerHybridMethod("removeEntity", &SceneWrapper::removeEntity); + proto.registerHybridMethod("removeEntities", &SceneWrapper::removeEntities); + proto.registerHybridMethod("addAssetEntities", &SceneWrapper::addAssetEntities); + proto.registerHybridMethod("removeAssetEntities", &SceneWrapper::removeAssetEntities); + proto.registerHybridGetter("entityCount", &SceneWrapper::getEntityCount); + }); } void margelo::SceneWrapper::addEntity(std::shared_ptr entity) { diff --git a/package/cpp/core/RNFSwapChainWrapper.h b/package/cpp/core/RNFSwapChainWrapper.h index 5ac4cb51..16e28073 100644 --- a/package/cpp/core/RNFSwapChainWrapper.h +++ b/package/cpp/core/RNFSwapChainWrapper.h @@ -11,7 +11,9 @@ class SwapChainWrapper : public PointerHolder { public: explicit SwapChainWrapper(std::shared_ptr swapChain) : PointerHolder("SwapChainWrapper", swapChain) {} - void loadHybridMethods() override {} + void loadHybridMethods() override { + PointerHolder::loadHybridMethods(); + } std::shared_ptr getSwapChain() { return pointee(); diff --git a/package/cpp/core/RNFTransformManagerWrapper.cpp b/package/cpp/core/RNFTransformManagerWrapper.cpp index 803a76a1..9670620d 100644 --- a/package/cpp/core/RNFTransformManagerWrapper.cpp +++ b/package/cpp/core/RNFTransformManagerWrapper.cpp @@ -7,17 +7,20 @@ namespace margelo { void TransformManagerWrapper::loadHybridMethods() { - registerHybridMethod("getTransform", &TransformManagerWrapper::getTransform, this); - registerHybridMethod("getWorldTransform", &TransformManagerWrapper::getWorldTransform, this); - registerHybridMethod("openLocalTransformTransaction", &TransformManagerWrapper::openLocalTransformTransaction, this); - registerHybridMethod("commitLocalTransformTransaction", &TransformManagerWrapper::commitLocalTransformTransaction, this); - registerHybridMethod("setTransform", &TransformManagerWrapper::setTransform, this); - registerHybridMethod("createIdentityMatrix", &TransformManagerWrapper::createIdentityMatrix, this); - registerHybridMethod("setEntityPosition", &TransformManagerWrapper::setEntityPosition, this); - registerHybridMethod("setEntityRotation", &TransformManagerWrapper::setEntityRotation, this); - registerHybridMethod("setEntityScale", &TransformManagerWrapper::setEntityScale, this); - registerHybridMethod("updateTransformByRigidBody", &TransformManagerWrapper::updateTransformByRigidBody, this); - registerHybridMethod("transformToUnitCube", &TransformManagerWrapper::transformToUnitCube, this); + PointerHolder::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("getTransform", &TransformManagerWrapper::getTransform); + proto.registerHybridMethod("getWorldTransform", &TransformManagerWrapper::getWorldTransform); + proto.registerHybridMethod("openLocalTransformTransaction", &TransformManagerWrapper::openLocalTransformTransaction); + proto.registerHybridMethod("commitLocalTransformTransaction", &TransformManagerWrapper::commitLocalTransformTransaction); + proto.registerHybridMethod("setTransform", &TransformManagerWrapper::setTransform); + proto.registerHybridMethod("createIdentityMatrix", &TransformManagerWrapper::createIdentityMatrix); + proto.registerHybridMethod("setEntityPosition", &TransformManagerWrapper::setEntityPosition); + proto.registerHybridMethod("setEntityRotation", &TransformManagerWrapper::setEntityRotation); + proto.registerHybridMethod("setEntityScale", &TransformManagerWrapper::setEntityScale); + proto.registerHybridMethod("updateTransformByRigidBody", &TransformManagerWrapper::updateTransformByRigidBody); + proto.registerHybridMethod("transformToUnitCube", &TransformManagerWrapper::transformToUnitCube); + }); } std::shared_ptr TransformManagerWrapper::getTransform(std::shared_ptr entityWrapper) { Entity entity = getEntity(entityWrapper); @@ -81,4 +84,4 @@ Entity TransformManagerWrapper::getEntity(std::shared_ptr entityW return entityWrapper->getEntity(); } -} // namespace margelo \ No newline at end of file +} // namespace margelo diff --git a/package/cpp/core/RNFViewWrapper.cpp b/package/cpp/core/RNFViewWrapper.cpp index c49131ed..a8b3926c 100644 --- a/package/cpp/core/RNFViewWrapper.cpp +++ b/package/cpp/core/RNFViewWrapper.cpp @@ -3,27 +3,30 @@ namespace margelo { void ViewWrapper::loadHybridMethods() { - registerHybridMethod("getAspectRatio", &ViewWrapper::getAspectRatio, this); - registerHybridMethod("createAmbientOcclusionOptions", &ViewWrapper::createAmbientOcclusionOptions, this); - registerHybridMethod("setAmbientOcclusionOptions", &ViewWrapper::setAmbientOcclusionOptions, this); - registerHybridMethod("getAmbientOcclusionOptions", &ViewWrapper::getAmbientOcclusionOptions, this); - registerHybridMethod("createDynamicResolutionOptions", &ViewWrapper::createDynamicResolutionOptions, this); - registerHybridMethod("setDynamicResolutionOptions", &ViewWrapper::setDynamicResolutionOptions, this); - registerHybridMethod("getDynamicResolutionOptions", &ViewWrapper::getDynamicResolutionOptions, this); - registerHybridSetter("temporalAntiAliasingOptions", &ViewWrapper::setTemporalAntiAliasingOptions, this); - registerHybridGetter("screenSpaceRefraction", &ViewWrapper::isScreenSpaceRefractionEnabled, this); - registerHybridSetter("screenSpaceRefraction", &ViewWrapper::setScreenSpaceRefractionEnabled, this); - registerHybridGetter("postProcessing", &ViewWrapper::isPostProcessingEnabled, this); - registerHybridSetter("postProcessing", &ViewWrapper::setPostProcessingEnabled, this); - registerHybridGetter("shadowing", &ViewWrapper::isShadowingEnabled, this); - registerHybridSetter("shadowing", &ViewWrapper::setShadowingEnabled, this); - registerHybridGetter("dithering", &ViewWrapper::getDithering, this); - registerHybridSetter("dithering", &ViewWrapper::setDithering, this); - registerHybridGetter("antiAliasing", &ViewWrapper::getAntiAliasing, this); - registerHybridSetter("antiAliasing", &ViewWrapper::setAntiAliasing, this); - registerHybridMethod("projectWorldToScreen", &ViewWrapper::projectWorldToScreen, this); - registerHybridMethod("pickEntity", &ViewWrapper::pickEntity, this); - registerHybridMethod("getViewport", &ViewWrapper::getViewport, this); + PointerHolder::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("getAspectRatio", &ViewWrapper::getAspectRatio); + proto.registerHybridMethod("createAmbientOcclusionOptions", &ViewWrapper::createAmbientOcclusionOptions); + proto.registerHybridMethod("setAmbientOcclusionOptions", &ViewWrapper::setAmbientOcclusionOptions); + proto.registerHybridMethod("getAmbientOcclusionOptions", &ViewWrapper::getAmbientOcclusionOptions); + proto.registerHybridMethod("createDynamicResolutionOptions", &ViewWrapper::createDynamicResolutionOptions); + proto.registerHybridMethod("setDynamicResolutionOptions", &ViewWrapper::setDynamicResolutionOptions); + proto.registerHybridMethod("getDynamicResolutionOptions", &ViewWrapper::getDynamicResolutionOptions); + proto.registerHybridSetter("temporalAntiAliasingOptions", &ViewWrapper::setTemporalAntiAliasingOptions); + proto.registerHybridGetter("screenSpaceRefraction", &ViewWrapper::isScreenSpaceRefractionEnabled); + proto.registerHybridSetter("screenSpaceRefraction", &ViewWrapper::setScreenSpaceRefractionEnabled); + proto.registerHybridGetter("postProcessing", &ViewWrapper::isPostProcessingEnabled); + proto.registerHybridSetter("postProcessing", &ViewWrapper::setPostProcessingEnabled); + proto.registerHybridGetter("shadowing", &ViewWrapper::isShadowingEnabled); + proto.registerHybridSetter("shadowing", &ViewWrapper::setShadowingEnabled); + proto.registerHybridGetter("dithering", &ViewWrapper::getDithering); + proto.registerHybridSetter("dithering", &ViewWrapper::setDithering); + proto.registerHybridGetter("antiAliasing", &ViewWrapper::getAntiAliasing); + proto.registerHybridSetter("antiAliasing", &ViewWrapper::setAntiAliasing); + proto.registerHybridMethod("projectWorldToScreen", &ViewWrapper::projectWorldToScreen); + proto.registerHybridMethod("pickEntity", &ViewWrapper::pickEntity); + proto.registerHybridMethod("getViewport", &ViewWrapper::getViewport); + }); } double ViewWrapper::getAspectRatio() { diff --git a/package/cpp/core/math/RNFTMat44Wrapper.cpp b/package/cpp/core/math/RNFTMat44Wrapper.cpp index 1c74606d..0f6ad1ff 100644 --- a/package/cpp/core/math/RNFTMat44Wrapper.cpp +++ b/package/cpp/core/math/RNFTMat44Wrapper.cpp @@ -5,12 +5,15 @@ namespace margelo { void margelo::TMat44Wrapper::loadHybridMethods() { - registerHybridGetter("data", &TMat44Wrapper::getMatrixData, this); - registerHybridMethod("scaling", &TMat44Wrapper::scaling, this); - registerHybridMethod("translate", &TMat44Wrapper::translate, this); - registerHybridMethod("rotate", &TMat44Wrapper::rotate, this); - registerHybridGetter("scale", &TMat44Wrapper::getScale, this); - registerHybridGetter("translation", &TMat44Wrapper::getTranslation, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridGetter("data", &TMat44Wrapper::getMatrixData); + proto.registerHybridMethod("scaling", &TMat44Wrapper::scaling); + proto.registerHybridMethod("translate", &TMat44Wrapper::translate); + proto.registerHybridMethod("rotate", &TMat44Wrapper::rotate); + proto.registerHybridGetter("scale", &TMat44Wrapper::getScale); + proto.registerHybridGetter("translation", &TMat44Wrapper::getTranslation); + }); } std::vector TMat44Wrapper::getMatrixData() { diff --git a/package/cpp/core/math/RNFTMat44Wrapper.h b/package/cpp/core/math/RNFTMat44Wrapper.h index 55584b63..68dee8fd 100644 --- a/package/cpp/core/math/RNFTMat44Wrapper.h +++ b/package/cpp/core/math/RNFTMat44Wrapper.h @@ -4,13 +4,17 @@ #pragma once -#include "jsi/RNFHybridObject.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif #include namespace margelo { using namespace filament; -class TMat44Wrapper : public HybridObject { +class TMat44Wrapper : public nitro::HybridObject { public: explicit TMat44Wrapper(math::mat4f matrix) : HybridObject("TMat44Wrapper"), _matrix(matrix) {} diff --git a/package/cpp/core/utils/RNFEntityWrapper.cpp b/package/cpp/core/utils/RNFEntityWrapper.cpp index ca096d47..d0a81fbe 100644 --- a/package/cpp/core/utils/RNFEntityWrapper.cpp +++ b/package/cpp/core/utils/RNFEntityWrapper.cpp @@ -1,7 +1,8 @@ #include "RNFEntityWrapper.h" void margelo::EntityWrapper::loadHybridMethods() { - registerHybridGetter("id", &EntityWrapper::getId, this); + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { proto.registerHybridGetter("id", &EntityWrapper::getId); }); } int margelo::EntityWrapper::getId() { diff --git a/package/cpp/core/utils/RNFEntityWrapper.h b/package/cpp/core/utils/RNFEntityWrapper.h index a5743dc9..e7d31500 100644 --- a/package/cpp/core/utils/RNFEntityWrapper.h +++ b/package/cpp/core/utils/RNFEntityWrapper.h @@ -1,6 +1,10 @@ #pragma once -#include "jsi/RNFHybridObject.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif #include #include @@ -11,7 +15,7 @@ namespace margelo { using namespace utils; using namespace filament; -class EntityWrapper : public HybridObject { +class EntityWrapper : public nitro::HybridObject { public: explicit EntityWrapper(Entity entity) : HybridObject("EntityWrapper"), _entity(entity) {} explicit EntityWrapper(const VertexEntity& vertexEntity) diff --git a/package/cpp/core/utils/RNFManipulatorWrapper.cpp b/package/cpp/core/utils/RNFManipulatorWrapper.cpp index 71008769..2b5fbbab 100644 --- a/package/cpp/core/utils/RNFManipulatorWrapper.cpp +++ b/package/cpp/core/utils/RNFManipulatorWrapper.cpp @@ -2,12 +2,15 @@ namespace margelo { void ManipulatorWrapper::loadHybridMethods() { - registerHybridMethod("grabBegin", &ManipulatorWrapper::grabBegin, this); - registerHybridMethod("grabUpdate", &ManipulatorWrapper::grabUpdate, this); - registerHybridMethod("grabEnd", &ManipulatorWrapper::grabEnd, this); - registerHybridMethod("scroll", &ManipulatorWrapper::scroll, this); - registerHybridMethod("update", &ManipulatorWrapper::update, this); - registerHybridMethod("getLookAt", &ManipulatorWrapper::getLookAt, this); + PointerHolder::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("grabBegin", &ManipulatorWrapper::grabBegin); + proto.registerHybridMethod("grabUpdate", &ManipulatorWrapper::grabUpdate); + proto.registerHybridMethod("grabEnd", &ManipulatorWrapper::grabEnd); + proto.registerHybridMethod("scroll", &ManipulatorWrapper::scroll); + proto.registerHybridMethod("update", &ManipulatorWrapper::update); + proto.registerHybridMethod("getLookAt", &ManipulatorWrapper::getLookAt); + }); } void ManipulatorWrapper::grabBegin(float x, float y, bool strafe) { diff --git a/package/cpp/jsi/RNFHybridObject.cpp b/package/cpp/jsi/RNFHybridObject.cpp deleted file mode 100644 index f96ef34b..00000000 --- a/package/cpp/jsi/RNFHybridObject.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// -// Created by Marc Rousavy on 21.02.24. -// - -#include "RNFHybridObject.h" -#include "RNFJSIConverter.h" -#include "RNFLogger.h" - -namespace margelo { - -#if DEBUG && RNF_ENABLE_LOGS -static std::unordered_map _instanceIds; -static std::mutex _mutex; - -static int getId(const char* name) { - std::unique_lock lock(_mutex); - if (_instanceIds.find(name) == _instanceIds.end()) { - _instanceIds.insert({name, 1}); - } - auto iterator = _instanceIds.find(name); - return iterator->second++; -} -#endif - -HybridObject::HybridObject(const char* name) : _name(name) { -#if DEBUG && RNF_ENABLE_LOGS - _instanceId = getId(name); - Logger::log(TAG, "(MEMORY) Creating %s (#%i)... ✅", _name, _instanceId); -#endif -} - -HybridObject::~HybridObject() { -#if DEBUG && RNF_ENABLE_LOGS - Logger::log(TAG, "(MEMORY) Deleting %s (#%i)... ❌", _name, _instanceId); -#endif - _functionCache.clear(); -} - -std::string HybridObject::toString(jsi::Runtime& runtime) { - std::string result = std::string(_name) + " { "; - std::vector props = getPropertyNames(runtime); - for (size_t i = 0; i < props.size(); i++) { - auto suffix = i < props.size() - 1 ? ", " : " "; - result += "\"" + props[i].utf8(runtime) + "\"" + suffix; - } - return result + "}"; -} - -std::vector HybridObject::getPropertyNames(facebook::jsi::Runtime& runtime) { - std::unique_lock lock(_mutex); - ensureInitialized(runtime); - - std::vector result; - size_t totalSize = _methods.size() + _getters.size() + _setters.size(); - result.reserve(totalSize); - - for (const auto& item : _methods) { - result.push_back(jsi::PropNameID::forUtf8(runtime, item.first)); - } - for (const auto& item : _getters) { - result.push_back(jsi::PropNameID::forUtf8(runtime, item.first)); - } - for (const auto& item : _setters) { - result.push_back(jsi::PropNameID::forUtf8(runtime, item.first)); - } - return result; -} - -jsi::Value HybridObject::get(facebook::jsi::Runtime& runtime, const facebook::jsi::PropNameID& propName) { - std::unique_lock lock(_mutex); - ensureInitialized(runtime); - - std::string name = propName.utf8(runtime); - auto& functionCache = _functionCache[&runtime]; - - if (_getters.count(name) > 0) { - // it's a property getter - return _getters[name](runtime, jsi::Value::undefined(), nullptr, 0); - } - - if (functionCache.count(name) > 0) { - [[likely]]; - // cache hit - return jsi::Value(runtime, *functionCache[name]); - } - - if (_methods.count(name) > 0) { - // cache miss - create jsi::Function and cache it. - HybridFunction& hybridFunction = _methods.at(name); - jsi::Function function = jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, name), - hybridFunction.parameterCount, hybridFunction.function); - - functionCache[name] = JSIHelper::createSharedJsiFunction(runtime, std::move(function)); - return jsi::Value(runtime, *functionCache[name]); - } - - if (name == "toString") { - return jsi::Function::createFromHostFunction( - runtime, jsi::PropNameID::forUtf8(runtime, "toString"), 0, - [=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* args, size_t count) -> jsi::Value { - std::string stringRepresentation = this->toString(runtime); - return jsi::String::createFromUtf8(runtime, stringRepresentation); - }); - } - - return jsi::HostObject::get(runtime, propName); -} - -void HybridObject::set(facebook::jsi::Runtime& runtime, const facebook::jsi::PropNameID& propName, const facebook::jsi::Value& value) { - std::unique_lock lock(_mutex); - ensureInitialized(runtime); - - std::string name = propName.utf8(runtime); - - if (_setters.count(name) > 0) { - // Call setter - _setters[name](runtime, jsi::Value::undefined(), &value, 1); - return; - } - - HostObject::set(runtime, propName, value); -} - -void HybridObject::ensureInitialized(facebook::jsi::Runtime& runtime) { - if (!_didLoadMethods) { - [[unlikely]]; - _creationRuntime = &runtime; - // lazy-load all exposed methods - loadHybridMethods(); - _didLoadMethods = true; - } -} - -bool HybridObject::isRuntimeAlive() { - if (_creationRuntime == nullptr) { - [[unlikely]]; - return false; - } - return RNFWorkletRuntimeRegistry::isRuntimeAlive(_creationRuntime); -} - -} // namespace margelo diff --git a/package/cpp/jsi/RNFHybridObject.h b/package/cpp/jsi/RNFHybridObject.h deleted file mode 100644 index ef6d81b0..00000000 --- a/package/cpp/jsi/RNFHybridObject.h +++ /dev/null @@ -1,157 +0,0 @@ -// -// Created by Marc Rousavy on 21.02.24. -// - -#pragma once - -#include "RNFJSIConverter.h" -#include "RNFLogger.h" -#include "jsi/RNFWorkletRuntimeRegistry.h" -#include -#include -#include -#include -#include -#include - -namespace margelo { - -using namespace facebook; - -class HybridObject : public jsi::HostObject, public std::enable_shared_from_this { -public: - struct HybridFunction { - jsi::HostFunctionType function; - size_t parameterCount; - }; - -public: - explicit HybridObject(const char* name); - ~HybridObject(); - - void set(jsi::Runtime&, const jsi::PropNameID& name, const jsi::Value& value) override; - jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& propName) override; - std::vector getPropertyNames(jsi::Runtime& runtime) override; - - /** - * Get the `std::shared_ptr` instance of this HybridObject. - * The HybridObject must be managed inside a `shared_ptr` already, otherwise this will fail. - */ - template std::shared_ptr shared() { - return std::static_pointer_cast(shared_from_this()); - } - - /** - * Loads all native methods of this `HybridObject` to be exposed to JavaScript. - * Example: - * - * ```cpp - * int User::getAge() { - * return 23; - * } - * - * void User::loadHybridMethods() { - * registerHybridMethod("getAge", &User::getAge, this); - * } - * ``` - */ - virtual void loadHybridMethods() = 0; - - /** - * Get a string representation of this HostObject, useful for logging or debugging. - */ - virtual std::string toString(jsi::Runtime& runtime); - -private: - static constexpr auto TAG = "HybridObject"; - const char* _name = TAG; - int _instanceId = 1; - bool _didLoadMethods = false; - std::mutex _mutex; - std::unordered_map _methods; - std::unordered_map _getters; - std::unordered_map _setters; - std::unordered_map>> _functionCache; - // Store a pointer to the runtime. Needed for checking if the runtime is still active, see WorkletRuntimeRegistry. - jsi::Runtime* _creationRuntime = nullptr; - -private: - inline void ensureInitialized(facebook::jsi::Runtime& runtime); - -private: - template - static inline jsi::Value callMethod(Derived* obj, ReturnType (Derived::*method)(Args...), jsi::Runtime& runtime, const jsi::Value* args, - std::index_sequence) { - if constexpr (std::is_same_v) { - // It's a void method. - (obj->*method)(JSIConverter>::fromJSI(runtime, args[Is])...); - return jsi::Value::undefined(); - } else { - // It's returning some C++ type, we need to convert that to a JSI value now. - ReturnType result = (obj->*method)(JSIConverter>::fromJSI(runtime, args[Is])...); - return JSIConverter>::toJSI(runtime, std::move(result)); - } - } - - template - static jsi::HostFunctionType createHybridMethod(ReturnType (Derived::*method)(Args...), Derived* derivedInstance) { - - return [derivedInstance, method](jsi::Runtime& runtime, const jsi::Value& thisVal, const jsi::Value* args, size_t count) -> jsi::Value { - if constexpr (std::is_same_v) { - // If the return type is a jsi::Value, we assume the user wants full JSI code control. - // The signature must be identical to jsi::HostFunction (jsi::Runtime&, jsi::Value& this, ...) - return (derivedInstance->*method)(runtime, thisVal, args, count); - } else { - // Call the actual method with JSI values as arguments and return a JSI value again. - // Internally, this method converts the JSI values to C++ values. - return callMethod(derivedInstance, method, runtime, args, std::index_sequence_for{}); - } - }; - } - -protected: - template - void registerHybridMethod(std::string name, ReturnType (Derived::*method)(Args...), Derived* derivedInstance, bool override = false) { - if (!override && (_getters.count(name) > 0 || _setters.count(name) > 0)) { - [[unlikely]]; - throw std::runtime_error("Cannot add Hybrid Method \"" + name + "\" - a property with that name already exists!"); - } - if (!override && (_methods.count(name) > 0)) { - throw std::runtime_error("Cannot add Hybrid Method \"" + name + "\" - a method with that name already exists!"); - } - - _methods[name] = HybridFunction{.function = createHybridMethod(method, derivedInstance), .parameterCount = sizeof...(Args)}; - } - - template - void registerHybridGetter(std::string name, ReturnType (Derived::*method)(), Derived* derivedInstance) { - if (_getters.count(name) > 0) { - [[unlikely]]; - throw std::runtime_error("Cannot add Hybrid Property Getter \"" + name + "\" - a getter with that name already exists!"); - } - if (_methods.count(name) > 0) { - [[unlikely]]; - throw std::runtime_error("Cannot add Hybrid Property Getter \"" + name + "\" - a method with that name already exists!"); - } - - _getters[name] = createHybridMethod(method, derivedInstance); - } - - template - void registerHybridSetter(std::string name, void (Derived::*method)(ValueType), Derived* derivedInstance) { - if (_setters.count(name) > 0) { - [[unlikely]]; - throw std::runtime_error("Cannot add Hybrid Property Setter \"" + name + "\" - a setter with that name already exists!"); - } - if (_methods.count(name) > 0) { - [[unlikely]]; - throw std::runtime_error("Cannot add Hybrid Property Setter \"" + name + "\" - a method with that name already exists!"); - } - - _setters[name] = createHybridMethod(method, derivedInstance); - } - - bool isRuntimeAlive(); -}; - -} // namespace margelo diff --git a/package/cpp/jsi/RNFJSIConverter.h b/package/cpp/jsi/RNFJSIConverter.h deleted file mode 100644 index 686003f0..00000000 --- a/package/cpp/jsi/RNFJSIConverter.h +++ /dev/null @@ -1,418 +0,0 @@ -// -// Created by Marc Rousavy on 21.02.24. -// - -#pragma once - -#include "RNFEnumMapper.h" -#include "RNFHybridObject.h" -#include "RNFJSIHelper.h" -#include "RNFPromise.h" -#include "RNFPromiseFactory.h" -#include "RNFWorkletRuntimeRegistry.h" -#include "threading/RNFDispatcher.h" -#include -#include -#include -#include -#include -#include - -#if __has_include() -#include -#endif - -namespace margelo { - -using namespace facebook; - -// Unknown type (error) -template struct JSIConverter { - static ArgType fromJSI(jsi::Runtime&, const jsi::Value&) { - static_assert(always_false::value, "This type is not supported by the JSIConverter!"); - return ArgType(); - } - static jsi::Value toJSI(jsi::Runtime&, ArgType) { - static_assert(always_false::value, "This type is not supported by the JSIConverter!"); - return jsi::Value::undefined(); - } - -private: - template struct always_false : std::false_type {}; -}; - -// int <> number -template <> struct JSIConverter { - static int fromJSI(jsi::Runtime&, const jsi::Value& arg) { - return static_cast(arg.asNumber()); - } - static jsi::Value toJSI(jsi::Runtime&, int arg) { - return jsi::Value(arg); - } -}; - -// double <> number -template <> struct JSIConverter { - static double fromJSI(jsi::Runtime&, const jsi::Value& arg) { - return arg.asNumber(); - } - static jsi::Value toJSI(jsi::Runtime&, double arg) { - return jsi::Value(arg); - } -}; - -// float <> number -template <> struct JSIConverter { - static float fromJSI(jsi::Runtime&, const jsi::Value& arg) { - return static_cast(arg.asNumber()); - } - static jsi::Value toJSI(jsi::Runtime&, float arg) { - return jsi::Value(static_cast(arg)); - } -}; - -// int64_t <> BigInt -template <> struct JSIConverter { - static double fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - return arg.asBigInt(runtime).asInt64(runtime); - } - static jsi::Value toJSI(jsi::Runtime& runtime, int64_t arg) { - return jsi::BigInt::fromInt64(runtime, arg); - } -}; - -// uint64_t <> BigInt -template <> struct JSIConverter { - static double fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - return arg.asBigInt(runtime).asUint64(runtime); - } - static jsi::Value toJSI(jsi::Runtime& runtime, uint64_t arg) { - return jsi::BigInt::fromUint64(runtime, arg); - } -}; - -// bool <> boolean -template <> struct JSIConverter { - static bool fromJSI(jsi::Runtime&, const jsi::Value& arg) { - return arg.asBool(); - } - static jsi::Value toJSI(jsi::Runtime&, bool arg) { - return jsi::Value(arg); - } -}; - -// std::string <> string -template <> struct JSIConverter { - static std::string fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - return arg.asString(runtime).utf8(runtime); - } - static jsi::Value toJSI(jsi::Runtime& runtime, const std::string& arg) { - return jsi::String::createFromUtf8(runtime, arg); - } -}; - -// std::optional <> T | undefined -template struct JSIConverter> { - static std::optional fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - if (arg.isUndefined() || arg.isNull()) { - return std::nullopt; - } else { - return JSIConverter::fromJSI(runtime, std::move(arg)); - } - } - static jsi::Value toJSI(jsi::Runtime& runtime, const std::optional& arg) { - if (arg == std::nullopt) { - return jsi::Value::undefined(); - } else { - return JSIConverter::toJSI(runtime, arg.value()); - } - } -}; - -// Enum <> Union -template struct JSIConverter::value>> { - static TEnum fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - std::string string = arg.asString(runtime).utf8(runtime); - TEnum outEnum; - EnumMapper::convertJSUnionToEnum(string, &outEnum); - return outEnum; - } - static jsi::Value toJSI(jsi::Runtime& runtime, const TEnum& arg) { - std::string outUnion; - EnumMapper::convertEnumToJSUnion(arg, &outUnion); - return jsi::String::createFromUtf8(runtime, outUnion); - } -}; - -// std::future <> Promise -template struct JSIConverter> { - static std::future fromJSI(jsi::Runtime&, const jsi::Value&) { - throw std::runtime_error("Promise cannot be converted to a native type - it needs to be awaited first!"); - } - static jsi::Value toJSI(jsi::Runtime& runtime, std::future&& arg) { - auto sharedFuture = std::make_shared>(std::move(arg)); - return PromiseFactory::createPromise(runtime, [sharedFuture = std::move(sharedFuture)](jsi::Runtime& runtime, - std::shared_ptr promise, - std::shared_ptr dispatcher) { - // Spawn new async thread to wait for the result - std::thread waiterThread([promise, &runtime, dispatcher, sharedFuture = std::move(sharedFuture)]() { - // wait until the future completes. we are running on a background task here. - sharedFuture->wait(); - - // the async function completed successfully, resolve the promise on JS Thread - dispatcher->runAsync([&runtime, promise, sharedFuture]() mutable { - try { - if constexpr (std::is_same_v) { - // it's returning void, just return undefined to JS - sharedFuture->get(); - promise->resolve(jsi::Value::undefined()); - } else { - // it's returning a custom type, convert it to a jsi::Value - TResult result = sharedFuture->get(); - jsi::Value jsResult = JSIConverter::toJSI(runtime, result); - promise->resolve(std::move(jsResult)); - } - } catch (const std::exception& exception) { - // the async function threw an error, reject the promise on JS Thread - std::string what = exception.what(); - promise->reject(what); - } catch (...) { - // the async function threw a non-std error, try getting it -#if __has_include() - std::string name = __cxxabiv1::__cxa_current_exception_type()->name(); -#else - std::string name = ""; -#endif - promise->reject("Unknown non-std exception: " + name); - } - - // This lambda owns the promise shared pointer, and we need to call its - // destructor on the correct thread here - otherwise it might be called - // from the waiterThread. - promise = nullptr; - }); - }); - waiterThread.detach(); - }); - } -}; - -// [](Args...) -> T {} <> (Args...) => T -template struct JSIConverter> { - static std::function fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - jsi::Function function = arg.asObject(runtime).asFunction(runtime); - - std::shared_ptr sharedFunction = JSIHelper::createSharedJsiFunction(runtime, std::move(function)); - return [&runtime, sharedFunction](Args... args) -> ReturnType { - jsi::Value result = sharedFunction->call(runtime, JSIConverter>::toJSI(runtime, args)...); - if constexpr (std::is_same_v) { - // it is a void function (returns undefined) - return; - } else { - // it returns a custom type, parse it from the JSI value. - return JSIConverter::fromJSI(runtime, std::move(result)); - } - }; - } - - template - static jsi::Value callHybridFunction(const std::function& function, jsi::Runtime& runtime, const jsi::Value* args, - std::index_sequence) { - if constexpr (std::is_same_v) { - // it is a void function (will return undefined in JS) - function(JSIConverter>::fromJSI(runtime, args[Is])...); - return jsi::Value::undefined(); - } else { - // it is a custom type, parse it to a JS value - ReturnType result = function(JSIConverter>::fromJSI(runtime, args[Is])...); - return JSIConverter::toJSI(runtime, result); - } - } - static jsi::Value toJSI(jsi::Runtime& runtime, const std::function& function) { - jsi::HostFunctionType jsFunction = [function = std::move(function)](jsi::Runtime& runtime, const jsi::Value& thisValue, - const jsi::Value* args, size_t count) -> jsi::Value { - if (count != sizeof...(Args)) { - [[unlikely]]; - throw jsi::JSError(runtime, "Function expected " + std::to_string(sizeof...(Args)) + " arguments, but received " + - std::to_string(count) + "!"); - } - return callHybridFunction(function, runtime, args, std::index_sequence_for{}); - }; - return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "hostFunction"), sizeof...(Args), jsFunction); - } -}; - -// std::vector <> T[] -template struct JSIConverter> { - static std::vector fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - jsi::Array array = arg.asObject(runtime).asArray(runtime); - size_t length = array.size(runtime); - - std::vector vector; - vector.reserve(length); - for (size_t i = 0; i < length; ++i) { - jsi::Value elementValue = array.getValueAtIndex(runtime, i); - vector.emplace_back(JSIConverter::fromJSI(runtime, elementValue)); - } - return vector; - } - static jsi::Value toJSI(jsi::Runtime& runtime, const std::vector& vector) { - jsi::Array array(runtime, vector.size()); - for (size_t i = 0; i < vector.size(); i++) { - jsi::Value value = JSIConverter::toJSI(runtime, vector[i]); - array.setValueAtIndex(runtime, i, std::move(value)); - } - return array; - } -}; - -// std::unordered_map <> Record -template struct JSIConverter> { - static std::unordered_map fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - jsi::Object object = arg.asObject(runtime); - jsi::Array propertyNames = object.getPropertyNames(runtime); - size_t length = propertyNames.size(runtime); - - std::unordered_map map; - map.reserve(length); - for (size_t i = 0; i < length; ++i) { - std::string key = propertyNames.getValueAtIndex(runtime, i).asString(runtime).utf8(runtime); - jsi::Value value = object.getProperty(runtime, key.c_str()); - map.emplace(key, JSIConverter::fromJSI(runtime, value)); - } - return map; - } - static jsi::Value toJSI(jsi::Runtime& runtime, const std::unordered_map& map) { - jsi::Object object(runtime); - for (const auto& pair : map) { - jsi::Value value = JSIConverter::toJSI(runtime, pair.second); - jsi::String key = jsi::String::createFromUtf8(runtime, pair.first); - object.setProperty(runtime, key, std::move(value)); - } - return object; - } -}; - -// HybridObject <> {} -template struct is_shared_ptr_to_host_object : std::false_type {}; - -template struct is_shared_ptr_to_host_object> : std::is_base_of {}; - -template struct JSIConverter::value>> { - using TPointee = typename T::element_type; - -#if DEBUG - inline static std::string getFriendlyTypename() { - std::string name = std::string(typeid(TPointee).name()); -#if __has_include() - int status = 0; - char* demangled_name = abi::__cxa_demangle(name.c_str(), NULL, NULL, &status); - if (status == 0) { - name = demangled_name; - std::free(demangled_name); - } -#endif - return name; - } - - inline static std::string invalidTypeErrorMessage(const std::string& typeDescription, const std::string& reason) { - return "Cannot convert \"" + typeDescription + "\" to HostObject<" + getFriendlyTypename() + ">! " + reason; - } -#endif - - static T fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { -#if DEBUG - if (arg.isUndefined()) { - [[unlikely]]; - throw jsi::JSError(runtime, invalidTypeErrorMessage("undefined", "It is undefined!")); - } - if (!arg.isObject()) { - [[unlikely]]; - std::string stringRepresentation = arg.toString(runtime).utf8(runtime); - throw jsi::JSError(runtime, invalidTypeErrorMessage(stringRepresentation, "It is not an object!")); - } -#endif - jsi::Object object = arg.getObject(runtime); -#if DEBUG - if (!object.isHostObject(runtime)) { - [[unlikely]]; - std::string stringRepresentation = arg.toString(runtime).utf8(runtime); - throw jsi::JSError(runtime, invalidTypeErrorMessage(stringRepresentation, "It is a different HostObject!")); - } -#endif - return object.getHostObject(runtime); - } - static jsi::Value toJSI(jsi::Runtime& runtime, const T& arg) { -#if DEBUG - if (arg == nullptr) { - [[unlikely]]; - throw jsi::JSError(runtime, "Cannot convert nullptr to HostObject<" + getFriendlyTypename() + ">!"); - } -#endif - return jsi::Object::createFromHostObject(runtime, arg); - } -}; - -// NativeState <> {} -template struct is_shared_ptr_to_native_state : std::false_type {}; - -template struct is_shared_ptr_to_native_state> : std::is_base_of {}; - -template struct JSIConverter::value>> { - using TPointee = typename T::element_type; - -#if DEBUG - inline static std::string getFriendlyTypename() { - std::string name = std::string(typeid(TPointee).name()); -#if __has_include() - int status = 0; - char* demangled_name = abi::__cxa_demangle(name.c_str(), NULL, NULL, &status); - if (status == 0) { - name = demangled_name; - std::free(demangled_name); - } -#endif - return name; - } - - inline static std::string invalidTypeErrorMessage(const std::string& typeDescription, const std::string& reason) { - return "Cannot convert \"" + typeDescription + "\" to NativeState<" + getFriendlyTypename() + ">! " + reason; - } -#endif - - static T fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { -#if DEBUG - if (arg.isUndefined()) { - [[unlikely]]; - throw jsi::JSError(runtime, invalidTypeErrorMessage("undefined", "It is undefined!")); - } - if (!arg.isObject()) { - [[unlikely]]; - std::string stringRepresentation = arg.toString(runtime).utf8(runtime); - throw jsi::JSError(runtime, invalidTypeErrorMessage(stringRepresentation, "It is not an object!")); - } -#endif - jsi::Object object = arg.getObject(runtime); -#if DEBUG - if (!object.hasNativeState(runtime)) { - [[unlikely]]; - std::string stringRepresentation = arg.toString(runtime).utf8(runtime); - throw jsi::JSError(runtime, invalidTypeErrorMessage(stringRepresentation, "It is a different NativeState!")); - } -#endif - return object.getNativeState(runtime); - } - static jsi::Value toJSI(jsi::Runtime& runtime, const T& arg) { -#if DEBUG - if (arg == nullptr) { - [[unlikely]]; - throw jsi::JSError(runtime, "Cannot convert nullptr to HostObject<" + getFriendlyTypename() + ">!"); - } -#endif - jsi::Object object(runtime); - object.setNativeState(runtime, arg); - return object; - } -}; - -} // namespace margelo diff --git a/package/cpp/jsi/RNFJSIHelper.h b/package/cpp/jsi/RNFJSIHelper.h deleted file mode 100644 index 2b68fae2..00000000 --- a/package/cpp/jsi/RNFJSIHelper.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// Created by Hanno Gödecke on 15.05.24. -// - -#pragma once - -#include "RNFWorkletRuntimeRegistry.h" -#include -#include - -namespace margelo { - -using namespace facebook; - -class JSIHelper { -public: - /** - * Takes a jsi::Function and wraps it in a shared_ptr so its shareable. - * Every jsi::Function you intend to share or hold should be wrapped using this function. - */ - static std::shared_ptr createSharedJsiFunction(jsi::Runtime& runtime, jsi::Function&& function) { - std::shared_ptr sharedFunction(new jsi::Function(std::move(function)), [&runtime](jsi::Function* ptr) { - if (RNFWorkletRuntimeRegistry::isRuntimeAlive(&runtime)) { - // Only delete the jsi::Function when the runtime it created is still alive. - // Otherwise leak memory. We do this on purpose, as sometimes we would keep - // references to JSI objects past the lifetime of its runtime (e.g., - // shared values references from the RN VM holds reference to JSI objects - // on the UI runtime). When the runtime is terminated, the orphaned JSI - // objects would crash the app when their destructors are called, because - // they call into a memory that's managed by the terminated runtime. We - // accept the tradeoff of leaking memory here, as it has a limited impact. - // This scenario can only occur when the React instance is torn down which - // happens in development mode during app reloads, or in production when - // the app is being shut down gracefully by the system. An alternative - // solution would require us to keep track of all JSI values that are in - // use which would require additional data structure and compute spent on - // bookkeeping that only for the sake of destroying the values in time - // before the runtime is terminated. Note that the underlying memory that - // jsi::Value refers to is managed by the VM and gets freed along with the - // runtime. - delete ptr; - } - }); - - return sharedFunction; - } -}; -} // namespace margelo diff --git a/package/cpp/jsi/RNFPointerHolder.h b/package/cpp/jsi/RNFPointerHolder.h index ce67fc00..6c70e4aa 100644 --- a/package/cpp/jsi/RNFPointerHolder.h +++ b/package/cpp/jsi/RNFPointerHolder.h @@ -4,7 +4,11 @@ #pragma once -#include "RNFHybridObject.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif #include "RNFLogger.h" #include #include @@ -13,7 +17,7 @@ namespace margelo { using namespace facebook; -template class PointerHolder : public HybridObject { +template class PointerHolder : public nitro::HybridObject { protected: // no default constructor PointerHolder() = delete; @@ -23,11 +27,7 @@ template class PointerHolder : public HybridObject { * @param name The name of the implementing class, for example "ViewWrapper". * @param pointer The pointer this class will hold. It might be released from JS at any point via `release()`. */ - PointerHolder(const char* name, std::shared_ptr pointer) : HybridObject(name), _name(name), _pointer(pointer) { - // eagerly initialize the release() method instead of putting it in `loadHybridMethods` - registerHybridMethod("release", &PointerHolder::release, this); - registerHybridGetter("isValid", &PointerHolder::getIsValid, this); - } + PointerHolder(const char* name, std::shared_ptr pointer) : HybridObject(name), _name(name), _pointer(pointer) {} /** * Create a new instance of a pointer holder which holds a shared_ptr of the given value. @@ -46,6 +46,14 @@ template class PointerHolder : public HybridObject { } } + void loadHybridMethods() override { + HybridObject::loadHybridMethods(); + registerHybrids(this, [](nitro::Prototype& proto) { + proto.registerHybridMethod("release", &PointerHolder::release); + proto.registerHybridGetter("isValid", &PointerHolder::getIsValid); + }); + } + protected: /** * Manually release this reference to the pointer. diff --git a/package/cpp/jsi/RNFPromise.cpp b/package/cpp/jsi/RNFPromise.cpp deleted file mode 100644 index 5a88bbc1..00000000 --- a/package/cpp/jsi/RNFPromise.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "RNFPromise.h" -#include -#include -#include -#include - -namespace margelo { - -using namespace facebook; - -Promise::Promise(jsi::Runtime& runtime, jsi::Function&& resolver, jsi::Function&& rejecter) - : runtime(runtime), _resolver(std::move(resolver)), _rejecter(std::move(rejecter)) {} - -jsi::Value Promise::createPromise(jsi::Runtime& runtime, RunPromise run) { - // Get Promise ctor from global - auto promiseCtor = runtime.global().getPropertyAsFunction(runtime, "Promise"); - - auto promiseCallback = jsi::Function::createFromHostFunction( - runtime, jsi::PropNameID::forUtf8(runtime, "PromiseCallback"), 2, - [=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Value { - // Call function - auto resolver = arguments[0].asObject(runtime).asFunction(runtime); - auto rejecter = arguments[1].asObject(runtime).asFunction(runtime); - auto promise = std::make_shared(runtime, std::move(resolver), std::move(rejecter)); - run(runtime, promise); - - return jsi::Value::undefined(); - }); - - return promiseCtor.callAsConstructor(runtime, promiseCallback); -} - -void Promise::resolve(jsi::Value&& result) { - _resolver.call(runtime, std::move(result)); -} - -void Promise::reject(std::string message) { - jsi::JSError error(runtime, message); - _rejecter.call(runtime, error.value()); -} - -} // namespace margelo diff --git a/package/cpp/jsi/RNFPromise.h b/package/cpp/jsi/RNFPromise.h deleted file mode 100644 index 4a02bb8a..00000000 --- a/package/cpp/jsi/RNFPromise.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace margelo { - -using namespace facebook; - -class Promise { -public: - Promise(jsi::Runtime& runtime, jsi::Function&& resolver, jsi::Function&& rejecter); - - void resolve(jsi::Value&& result); - void reject(std::string error); - -public: - jsi::Runtime& runtime; - -private: - jsi::Function _resolver; - jsi::Function _rejecter; - -public: - using RunPromise = std::function promise)>; - /** - Create a new Promise and runs the given `run` function. - */ - static jsi::Value createPromise(jsi::Runtime& runtime, RunPromise run); -}; - -} // namespace margelo diff --git a/package/cpp/jsi/RNFPromiseFactory.cpp b/package/cpp/jsi/RNFPromiseFactory.cpp deleted file mode 100644 index 31b05a49..00000000 --- a/package/cpp/jsi/RNFPromiseFactory.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// -// PromiseFactory.cpp -// react-native-filament -// -// Created by Marc Rousavy on 11.03.24. -// - -#include "RNFPromiseFactory.h" -#include "RNFLogger.h" -#include "threading/RNFDispatcher.h" - -namespace margelo { - -jsi::Value PromiseFactory::createPromise(jsi::Runtime& runtime, RunPromise&& run) { - std::shared_ptr dispatcher = Dispatcher::getRuntimeGlobalDispatcher(runtime); - - return Promise::createPromise(runtime, [dispatcher, run = std::move(run)](jsi::Runtime& runtime, std::shared_ptr promise) { - run(runtime, promise, dispatcher); - }); -} - -} // namespace margelo diff --git a/package/cpp/jsi/RNFPromiseFactory.h b/package/cpp/jsi/RNFPromiseFactory.h deleted file mode 100644 index 2127d538..00000000 --- a/package/cpp/jsi/RNFPromiseFactory.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// PromiseFactory.hpp -// react-native-filament -// -// Created by Marc Rousavy on 11.03.24. -// - -#pragma once - -#include "RNFPromise.h" -#include "threading/RNFDispatcher.h" -#include -#include - -namespace margelo { - -class PromiseFactory { -public: - using RunPromise = std::function promise, std::shared_ptr dispatcher)>; - - /** - Create a new promise and run the given function. - The caller needs to ensure that the Promise is resolved eventually (on the JS thread with the CallInvoker). - */ - static jsi::Value createPromise(jsi::Runtime& runtime, RunPromise&& run); - -private: - static constexpr auto TAG = "PromiseFactory"; - -private: - PromiseFactory() = delete; -}; - -} // namespace margelo diff --git a/package/cpp/jsi/RNFRuntimeCache.cpp b/package/cpp/jsi/RNFRuntimeCache.cpp deleted file mode 100644 index f51a2821..00000000 --- a/package/cpp/jsi/RNFRuntimeCache.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include - -#include "RNFRuntimeCache.h" - -namespace margelo { - -static std::unordered_map> listeners; - -struct RuntimeLifecycleMonitorObject : public jsi::HostObject { - jsi::Runtime* _rt; - explicit RuntimeLifecycleMonitorObject(jsi::Runtime* rt) : _rt(rt) {} - ~RuntimeLifecycleMonitorObject() { - auto listenersSet = listeners.find(_rt); - if (listenersSet != listeners.end()) { - for (auto listener : listenersSet->second) { - listener->onRuntimeDestroyed(_rt); - } - listeners.erase(listenersSet); - } - } -}; - -void RuntimeLifecycleMonitor::addListener(jsi::Runtime& rt, RuntimeLifecycleListener* listener) { - auto listenersSet = listeners.find(&rt); - if (listenersSet == listeners.end()) { - // We install a global host object in the provided runtime, this way we can - // use that host object destructor to get notified when the runtime is being - // terminated. We use a unique name for the object as it gets saved with the - // runtime's global object. - rt.global().setProperty(rt, "__rnfl_rt_lifecycle_monitor", - jsi::Object::createFromHostObject(rt, std::make_shared(&rt))); - std::unordered_set newSet; - newSet.insert(listener); - listeners.emplace(&rt, std::move(newSet)); - } else { - listenersSet->second.insert(listener); - } -} - -void RuntimeLifecycleMonitor::removeListener(jsi::Runtime& rt, RuntimeLifecycleListener* listener) { - auto listenersSet = listeners.find(&rt); - if (listenersSet == listeners.end()) { - // nothing to do here - } else { - listenersSet->second.erase(listener); - } -} - -} // namespace margelo diff --git a/package/cpp/jsi/RNFRuntimeCache.h b/package/cpp/jsi/RNFRuntimeCache.h deleted file mode 100644 index 0a92c4ac..00000000 --- a/package/cpp/jsi/RNFRuntimeCache.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include - -namespace margelo { - -namespace jsi = facebook::jsi; - -/** - * Listener interface that allows for getting notified when a jsi::Runtime - * instance is destroyed. - */ -struct RuntimeLifecycleListener { - virtual ~RuntimeLifecycleListener() {} - virtual void onRuntimeDestroyed(jsi::Runtime*) = 0; -}; - -/** - * This class provides an API via static methods for registering and - * unregistering runtime lifecycle listeners. The listeners can be used to - * cleanup any data that references a given jsi::Runtime instance before it gets - * destroyed. - */ -struct RuntimeLifecycleMonitor { - static void addListener(jsi::Runtime& rt, RuntimeLifecycleListener* listener); - static void removeListener(jsi::Runtime& rt, RuntimeLifecycleListener* listener); -}; - -/** - * Provides a way to keep data specific to a jsi::Runtime instance that gets - * cleaned up when that runtime is destroyed. This is necessary because JSI does - * not allow for its associated objects to be retained past the runtime - * lifetime. If an object (e.g. jsi::Values or jsi::Function instances) is kept - * after the runtime is torn down, its destructor (once it is destroyed - * eventually) will result in a crash (JSI objects keep a pointer to memory - * managed by the runtime, accessing that portion of the memory after runtime is - * deleted is the root cause of that crash). - */ -template class RuntimeAwareCache : public RuntimeLifecycleListener { - -public: - void onRuntimeDestroyed(jsi::Runtime* rt) override { - // A runtime has been destroyed, so destroy the related cache. - _runtimeCaches.erase(rt); - } - - ~RuntimeAwareCache() { - for (auto& cache : _runtimeCaches) { - // remove all `onRuntimeDestroyed` listeners. - RuntimeLifecycleMonitor::removeListener(*cache.first, this); - } - } - - T& get(jsi::Runtime& rt) { - if (_runtimeCaches.count(&rt) == 0) { - // This is the first time this Runtime has been accessed. - // We set up a `onRuntimeDestroyed` listener for it and - // initialize the cache map. - RuntimeLifecycleMonitor::addListener(rt, this); - - T cache; - _runtimeCaches.emplace(&rt, std::move(cache)); - } - return _runtimeCaches.at(&rt); - } - -private: - std::unordered_map _runtimeCaches; -}; - -} // namespace margelo diff --git a/package/cpp/jsi/RNFWorkletRuntimeCollector.h b/package/cpp/jsi/RNFWorkletRuntimeCollector.h deleted file mode 100644 index d0b822ec..00000000 --- a/package/cpp/jsi/RNFWorkletRuntimeCollector.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "RNFWorkletRuntimeRegistry.h" - -#include - -#include - -namespace margelo { - -// From: -// https://github.com/software-mansion/react-native-reanimated/blob/6cb1a66f1a68cac8079de2b6b305d22359847e51/Common/cpp/ReanimatedRuntime/WorkletRuntimeCollector.h -class WorkletRuntimeCollector : public jsi::HostObject { - // When worklet runtime is created, we inject an instance of this class as a - // `jsi::HostObject` into the global object. When worklet runtime is - // terminated, the object is garbage-collected, which runs the C++ destructor. - // In the destructor, we unregister the worklet runtime from the registry. - -public: - explicit WorkletRuntimeCollector(jsi::Runtime& runtime) : _runtime(runtime) { - Logger::log("WorkletRuntimeCollector", "Registering WorkletRuntime %p", &runtime); - RNFWorkletRuntimeRegistry::registerRuntime(_runtime); - } - - ~WorkletRuntimeCollector() { - Logger::log("WorkletRuntimeCollector", "Unregistering WorkletRuntime %p", &_runtime); - RNFWorkletRuntimeRegistry::unregisterRuntime(_runtime); - } - - static void install(jsi::Runtime& rt) { - auto collector = std::make_shared(rt); - auto object = jsi::Object::createFromHostObject(rt, collector); - rt.global().setProperty(rt, "__workletRuntimeCollector", object); - } - -private: - jsi::Runtime& _runtime; -}; - -} // namespace margelo diff --git a/package/cpp/jsi/RNFWorkletRuntimeRegistry.cpp b/package/cpp/jsi/RNFWorkletRuntimeRegistry.cpp deleted file mode 100644 index c5ca9f44..00000000 --- a/package/cpp/jsi/RNFWorkletRuntimeRegistry.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "RNFWorkletRuntimeRegistry.h" - -namespace margelo { - -std::set RNFWorkletRuntimeRegistry::registry_{}; -std::mutex RNFWorkletRuntimeRegistry::mutex_{}; - -} // namespace margelo diff --git a/package/cpp/jsi/RNFWorkletRuntimeRegistry.h b/package/cpp/jsi/RNFWorkletRuntimeRegistry.h deleted file mode 100644 index cb3b88ce..00000000 --- a/package/cpp/jsi/RNFWorkletRuntimeRegistry.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include - -#include -#include - -using namespace facebook; - -namespace margelo { - -// From: -// https://github.com/software-mansion/react-native-reanimated/blob/6cb1a66f1a68cac8079de2b6b305d22359847e51/Common/cpp/ReanimatedRuntime/WorkletRuntimeRegistry.h -class RNFWorkletRuntimeRegistry { -private: - static std::set registry_; - static std::mutex mutex_; // Protects `registry_`. - - RNFWorkletRuntimeRegistry() {} // private ctor - - static void registerRuntime(jsi::Runtime& runtime) { - std::lock_guard lock(mutex_); - registry_.insert(&runtime); - } - - static void unregisterRuntime(jsi::Runtime& runtime) { - std::lock_guard lock(mutex_); - registry_.erase(&runtime); - } - - friend class WorkletRuntimeCollector; - -public: - static bool isRuntimeAlive(jsi::Runtime* runtime) { - assert(runtime != nullptr); - std::lock_guard lock(mutex_); - return registry_.find(runtime) != registry_.end(); - } -}; - -} // namespace margelo diff --git a/package/cpp/test/RNFTestEnum.h b/package/cpp/test/RNFTestEnum.h deleted file mode 100644 index bf43e2c9..00000000 --- a/package/cpp/test/RNFTestEnum.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Created by Marc Rousavy on 22.02.24. -// - -#pragma once - -#include "jsi/RNFEnumMapper.h" - -namespace margelo { - -enum class TestEnum : uint8_t { FIRST, SECOND, THIRD }; - -namespace EnumMapper { - static void convertJSUnionToEnum(const std::string& inUnion, TestEnum* outEnum) { - if (inUnion == "first") - *outEnum = TestEnum::FIRST; - else if (inUnion == "second") - *outEnum = TestEnum::SECOND; - else if (inUnion == "third") - *outEnum = TestEnum::THIRD; - else - throw invalidUnion(inUnion); - } - static void convertEnumToJSUnion(TestEnum inEnum, std::string* outUnion) { - switch (inEnum) { - case TestEnum::FIRST: - *outUnion = "first"; - break; - case TestEnum::SECOND: - *outUnion = "second"; - break; - case TestEnum::THIRD: - *outUnion = "third"; - break; - default: - throw invalidEnum(inEnum); - } - } -} // namespace EnumMapper -} // namespace margelo \ No newline at end of file diff --git a/package/cpp/test/RNFTestHybridObject.cpp b/package/cpp/test/RNFTestHybridObject.cpp deleted file mode 100644 index 19076e0b..00000000 --- a/package/cpp/test/RNFTestHybridObject.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// -// Created by Marc Rousavy on 20.02.24. -// -#include "RNFTestHybridObject.h" - -namespace margelo { - -void TestHybridObject::loadHybridMethods() { - // this.int get & set - registerHybridGetter("int", &TestHybridObject::getInt, this); - registerHybridSetter("int", &TestHybridObject::setInt, this); - // this.string get & set - registerHybridGetter("string", &TestHybridObject::getString, this); - registerHybridSetter("string", &TestHybridObject::setString, this); - // this.nullableString get & set - registerHybridGetter("nullableString", &TestHybridObject::getNullableString, this); - registerHybridSetter("nullableString", &TestHybridObject::setNullableString, this); - // this.enum - registerHybridGetter("enum", &TestHybridObject::getEnum, this); - registerHybridSetter("enum", &TestHybridObject::setEnum, this); - // methods - registerHybridMethod("multipleArguments", &TestHybridObject::multipleArguments, this); - // callbacks - registerHybridMethod("getIntGetter", &TestHybridObject::getIntGetter, this); - registerHybridMethod("sayHelloCallback", &TestHybridObject::sayHelloCallback, this); - // custom types - registerHybridMethod("createNewHybridObject", &TestHybridObject::createNewHybridObject, this); - // Promises - registerHybridMethod("calculateFibonacci", &TestHybridObject::calculateFibonacci, this); - registerHybridMethod("calculateFibonacciAsync", &TestHybridObject::calculateFibonacciAsync, this); -} - -} // namespace margelo diff --git a/package/cpp/test/RNFTestHybridObject.h b/package/cpp/test/RNFTestHybridObject.h deleted file mode 100644 index d3fa91d9..00000000 --- a/package/cpp/test/RNFTestHybridObject.h +++ /dev/null @@ -1,93 +0,0 @@ -// -// Created by Marc Rousavy on 22.02.24. -// - -#pragma once - -#include "RNFTestEnum.h" -#include "jsi/RNFHybridObject.h" -#include -#include -#include - -namespace margelo { - -class TestHybridObject : public HybridObject { -public: - explicit TestHybridObject() : HybridObject("TestHybridObject") {} - -public: - int getInt() { - return _int; - } - void setInt(int newValue) { - _int = newValue; - } - std::string getString() { - return _string; - } - void setString(const std::string& newValue) { - _string = newValue; - } - void setEnum(TestEnum testEnum) { - _enum = testEnum; - } - TestEnum getEnum() { - return _enum; - } - std::optional getNullableString() { - return _nullableString; - } - void setNullableString(std::optional string) { - _nullableString = string; - } - - std::unordered_map multipleArguments(int first, bool second, std::string third) { - return std::unordered_map{{"first", 5312}, {"second", 532233}, {"third", 2786}}; - } - - std::function getIntGetter() { - return [this]() -> int { return this->_int; }; - } - void sayHelloCallback(std::function callback) { - callback("Test Hybrid"); - } - std::shared_ptr createNewHybridObject() { - return std::make_shared(); - } - - uint64_t calculateFibonacci(int count) { - if (count < 0) - throw std::invalid_argument("Cannot calculate fibonacci for " + std::to_string(count) + " - it needs to be at least 0!"); - if (count == 0) - return 0; - if (count == 1) - return 1; - if (count >= 94) - throw std::invalid_argument("Cannot calculate fibonacci for " + std::to_string(count) + - " - it needs to be 94 at max, the number will overflow!"); - - uint64_t prev = 0; - uint64_t current = 1; - for (unsigned int i = 2; i <= count; ++i) { - uint64_t next = prev + current; - prev = current; - current = next; - } - return current; - } - - std::future calculateFibonacciAsync(int count) { - return std::async(std::launch::async, [count, this]() { return this->calculateFibonacci(count); }); - } - -private: - int _int; - std::string _string; - TestEnum _enum; - std::optional _nullableString; - - void loadHybridMethods() override; -}; - -} // namespace margelo diff --git a/package/cpp/threading/RNFCallInvokerDispatcher.h b/package/cpp/threading/RNFCallInvokerDispatcher.h deleted file mode 100644 index e9a4fb1e..00000000 --- a/package/cpp/threading/RNFCallInvokerDispatcher.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Created by Marc Rousavy on 27.03.24. -// - -#pragma once - -#include "RNFDispatcher.h" -#include - -namespace margelo { - -using namespace facebook; - -/** - * A Dispatcher that uses react::CallInvoker for it's implementation - */ -class CallInvokerDispatcher : public Dispatcher { -public: - explicit CallInvokerDispatcher(std::shared_ptr callInvoker) : _callInvoker(callInvoker) {} - - void runAsync(std::function&& function) override { - _callInvoker->invokeAsync(std::move(function)); - } - - void runSync(std::function&& function) override { - _callInvoker->invokeSync(std::move(function)); - } - -private: - std::shared_ptr _callInvoker; -}; - -} // namespace margelo \ No newline at end of file diff --git a/package/cpp/threading/RNFDispatcher.cpp b/package/cpp/threading/RNFDispatcher.cpp deleted file mode 100644 index 41e3c80d..00000000 --- a/package/cpp/threading/RNFDispatcher.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "RNFDispatcher.h" -#include "RNFLogger.h" -#include "jsi/RNFWorkletRuntimeCollector.h" - -namespace margelo { - -using namespace facebook; - -static constexpr auto GLOBAL_DISPATCHER_HOLDER_NAME = "__globalDispatcher"; - -void Dispatcher::installRuntimeGlobalDispatcher(jsi::Runtime& runtime, std::shared_ptr dispatcher) { - Logger::log(TAG, "Installing global Dispatcher Holder..."); - - // Track the runtime's lifetime - WorkletRuntimeCollector::install(runtime); - - jsi::Object dispatcherHolder(runtime); - dispatcherHolder.setNativeState(runtime, dispatcher); - runtime.global().setProperty(runtime, GLOBAL_DISPATCHER_HOLDER_NAME, dispatcherHolder); -} - -std::shared_ptr Dispatcher::getRuntimeGlobalDispatcher(jsi::Runtime& runtime) { - jsi::Value dispatcherHolderValue = getRuntimeGlobalDispatcherHolder(runtime); - jsi::Object dispatcherHolder = dispatcherHolderValue.asObject(runtime); - return dispatcherHolder.getNativeState(runtime); -} - -jsi::Value Dispatcher::getRuntimeGlobalDispatcherHolder(jsi::Runtime& runtime) { -#if DEBUG - if (!runtime.global().hasProperty(runtime, GLOBAL_DISPATCHER_HOLDER_NAME)) { - throw jsi::JSError(runtime, "Failed to get current Dispatcher - the global Dispatcher " - "holder (global." + - std::string(GLOBAL_DISPATCHER_HOLDER_NAME) + - ") " - "does not exist! Was Dispatcher::installDispatcherIntoRuntime() called " - "for this jsi::Runtime?"); - } -#endif - return runtime.global().getProperty(runtime, GLOBAL_DISPATCHER_HOLDER_NAME); -} - -} // namespace margelo diff --git a/package/cpp/threading/RNFDispatcher.h b/package/cpp/threading/RNFDispatcher.h deleted file mode 100644 index d5b51b12..00000000 --- a/package/cpp/threading/RNFDispatcher.h +++ /dev/null @@ -1,76 +0,0 @@ -// -// Created by Marc Rousavy on 12.03.24. -// - -#pragma once - -#include -#include -#include -#include - -namespace margelo { - -using namespace facebook; - -class Dispatcher : public jsi::NativeState { -public: - /** - Installs the Dispatcher into the given Runtime. - It can be accessed using `getRuntimeGlobalDispatcher` later. - */ - static void installRuntimeGlobalDispatcher(jsi::Runtime& runtime, std::shared_ptr dispatcher); - /** - Gets the global Dispatcher in the given Runtime, or throws an error if not found. - */ - static std::shared_ptr getRuntimeGlobalDispatcher(jsi::Runtime& runtime); - static jsi::Value getRuntimeGlobalDispatcherHolder(jsi::Runtime& runtime); - -public: - /** - * Run the given void function synchronously on the Thread this Dispatcher is managing. - */ - virtual void runSync(std::function&& function) = 0; - - /** - * Run the given void function asynchronously on the Thread this Dispatcher is managing. - */ - virtual void runAsync(std::function&& function) = 0; - - /** - * Run the given function asynchronously on the Thread this Dispatcher is managing, - * and return a future that will hold the result of the function. - */ - template std::future runAsyncAwaitable(std::function&& function) { - // 1. Create Promise that can be shared between this and dispatcher thread - auto promise = std::make_shared>(); - std::future future = promise->get_future(); - - runAsync([function = std::move(function), promise]() { - try { - if constexpr (std::is_void()) { - // 4. Call the actual function on the new Thread - function(); - // 5.a. Resolve the Promise if we succeeded - promise->set_value(); - } else { - // 4. Call the actual function on the new Thread - T result = function(); - // 5.a. Resolve the Promise if we succeeded - promise->set_value(std::move(result)); - } - } catch (...) { - // 5.b. Reject the Promise if the call failed - promise->set_exception(std::current_exception()); - } - }); - - // 3. Return an open future that gets resolved later by the dispatcher Thread - return future; - } - -private: - static constexpr auto TAG = "Dispatcher"; -}; - -} // namespace margelo diff --git a/package/example/AppExampleFabric/ios/Podfile.lock b/package/example/AppExampleFabric/ios/Podfile.lock index b3797564..66c1576e 100644 --- a/package/example/AppExampleFabric/ios/Podfile.lock +++ b/package/example/AppExampleFabric/ios/Podfile.lock @@ -2074,79 +2074,79 @@ PODS: - Yoga (0.0.0) DEPENDENCIES: - - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - - fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`) - - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - - NitroModules (from `../node_modules/react-native-nitro-modules`) - - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - - RCT-Folly/Fabric (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - - RCTDeprecation (from `../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) - - RCTRequired (from `../node_modules/react-native/Libraries/Required`) - - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) - - React (from `../node_modules/react-native/`) - - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) - - React-Core (from `../node_modules/react-native/`) - - React-Core/RCTWebSocket (from `../node_modules/react-native/`) - - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) - - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) - - React-debug (from `../node_modules/react-native/ReactCommon/react/debug`) - - React-defaultsnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/defaults`) - - React-domnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/dom`) - - React-Fabric (from `../node_modules/react-native/ReactCommon`) - - React-FabricComponents (from `../node_modules/react-native/ReactCommon`) - - React-FabricImage (from `../node_modules/react-native/ReactCommon`) - - React-featureflags (from `../node_modules/react-native/ReactCommon/react/featureflags`) - - React-featureflagsnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/featureflags`) - - React-graphics (from `../node_modules/react-native/ReactCommon/react/renderer/graphics`) - - React-hermes (from `../node_modules/react-native/ReactCommon/hermes`) - - React-idlecallbacksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks`) - - React-ImageManager (from `../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios`) - - React-jserrorhandler (from `../node_modules/react-native/ReactCommon/jserrorhandler`) - - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`) - - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) - - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector-modern`) - - React-jsitracing (from `../node_modules/react-native/ReactCommon/hermes/executor/`) - - React-logger (from `../node_modules/react-native/ReactCommon/logger`) - - React-Mapbuffer (from `../node_modules/react-native/ReactCommon`) - - React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`) + - boost (from `../../../node_modules/react-native/third-party-podspecs/boost.podspec`) + - DoubleConversion (from `../../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) + - FBLazyVector (from `../../../node_modules/react-native/Libraries/FBLazyVector`) + - fmt (from `../../../node_modules/react-native/third-party-podspecs/fmt.podspec`) + - glog (from `../../../node_modules/react-native/third-party-podspecs/glog.podspec`) + - hermes-engine (from `../../../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) + - NitroModules (from `../../../node_modules/react-native-nitro-modules`) + - RCT-Folly (from `../../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) + - RCT-Folly/Fabric (from `../../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) + - RCTDeprecation (from `../../../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) + - RCTRequired (from `../../../node_modules/react-native/Libraries/Required`) + - RCTTypeSafety (from `../../../node_modules/react-native/Libraries/TypeSafety`) + - React (from `../../../node_modules/react-native/`) + - React-callinvoker (from `../../../node_modules/react-native/ReactCommon/callinvoker`) + - React-Core (from `../../../node_modules/react-native/`) + - React-Core/RCTWebSocket (from `../../../node_modules/react-native/`) + - React-CoreModules (from `../../../node_modules/react-native/React/CoreModules`) + - React-cxxreact (from `../../../node_modules/react-native/ReactCommon/cxxreact`) + - React-debug (from `../../../node_modules/react-native/ReactCommon/react/debug`) + - React-defaultsnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/defaults`) + - React-domnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/dom`) + - React-Fabric (from `../../../node_modules/react-native/ReactCommon`) + - React-FabricComponents (from `../../../node_modules/react-native/ReactCommon`) + - React-FabricImage (from `../../../node_modules/react-native/ReactCommon`) + - React-featureflags (from `../../../node_modules/react-native/ReactCommon/react/featureflags`) + - React-featureflagsnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/featureflags`) + - React-graphics (from `../../../node_modules/react-native/ReactCommon/react/renderer/graphics`) + - React-hermes (from `../../../node_modules/react-native/ReactCommon/hermes`) + - React-idlecallbacksnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks`) + - React-ImageManager (from `../../../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios`) + - React-jserrorhandler (from `../../../node_modules/react-native/ReactCommon/jserrorhandler`) + - React-jsi (from `../../../node_modules/react-native/ReactCommon/jsi`) + - React-jsiexecutor (from `../../../node_modules/react-native/ReactCommon/jsiexecutor`) + - React-jsinspector (from `../../../node_modules/react-native/ReactCommon/jsinspector-modern`) + - React-jsitracing (from `../../../node_modules/react-native/ReactCommon/hermes/executor/`) + - React-logger (from `../../../node_modules/react-native/ReactCommon/logger`) + - React-Mapbuffer (from `../../../node_modules/react-native/ReactCommon`) + - React-microtasksnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`) - react-native-filament (from `../../..`) - - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) - - react-native-video (from `../node_modules/react-native-video`) - - react-native-worklets-core (from `../node_modules/react-native-worklets-core`) - - React-nativeconfig (from `../node_modules/react-native/ReactCommon`) - - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) - - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) - - React-performancetimeline (from `../node_modules/react-native/ReactCommon/react/performance/timeline`) - - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) - - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) - - React-RCTAppDelegate (from `../node_modules/react-native/Libraries/AppDelegate`) - - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`) - - React-RCTFabric (from `../node_modules/react-native/React`) - - React-RCTImage (from `../node_modules/react-native/Libraries/Image`) - - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`) - - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`) - - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) - - React-RCTText (from `../node_modules/react-native/Libraries/Text`) - - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) - - React-rendererconsistency (from `../node_modules/react-native/ReactCommon/react/renderer/consistency`) - - React-rendererdebug (from `../node_modules/react-native/ReactCommon/react/renderer/debug`) - - React-rncore (from `../node_modules/react-native/ReactCommon`) - - React-RuntimeApple (from `../node_modules/react-native/ReactCommon/react/runtime/platform/ios`) - - React-RuntimeCore (from `../node_modules/react-native/ReactCommon/react/runtime`) - - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) - - React-RuntimeHermes (from `../node_modules/react-native/ReactCommon/react/runtime`) - - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) - - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) + - react-native-safe-area-context (from `../../../node_modules/react-native-safe-area-context`) + - react-native-video (from `../../../node_modules/react-native-video`) + - react-native-worklets-core (from `../../../node_modules/react-native-worklets-core`) + - React-nativeconfig (from `../../../node_modules/react-native/ReactCommon`) + - React-NativeModulesApple (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) + - React-perflogger (from `../../../node_modules/react-native/ReactCommon/reactperflogger`) + - React-performancetimeline (from `../../../node_modules/react-native/ReactCommon/react/performance/timeline`) + - React-RCTActionSheet (from `../../../node_modules/react-native/Libraries/ActionSheetIOS`) + - React-RCTAnimation (from `../../../node_modules/react-native/Libraries/NativeAnimation`) + - React-RCTAppDelegate (from `../../../node_modules/react-native/Libraries/AppDelegate`) + - React-RCTBlob (from `../../../node_modules/react-native/Libraries/Blob`) + - React-RCTFabric (from `../../../node_modules/react-native/React`) + - React-RCTImage (from `../../../node_modules/react-native/Libraries/Image`) + - React-RCTLinking (from `../../../node_modules/react-native/Libraries/LinkingIOS`) + - React-RCTNetwork (from `../../../node_modules/react-native/Libraries/Network`) + - React-RCTSettings (from `../../../node_modules/react-native/Libraries/Settings`) + - React-RCTText (from `../../../node_modules/react-native/Libraries/Text`) + - React-RCTVibration (from `../../../node_modules/react-native/Libraries/Vibration`) + - React-rendererconsistency (from `../../../node_modules/react-native/ReactCommon/react/renderer/consistency`) + - React-rendererdebug (from `../../../node_modules/react-native/ReactCommon/react/renderer/debug`) + - React-rncore (from `../../../node_modules/react-native/ReactCommon`) + - React-RuntimeApple (from `../../../node_modules/react-native/ReactCommon/react/runtime/platform/ios`) + - React-RuntimeCore (from `../../../node_modules/react-native/ReactCommon/react/runtime`) + - React-runtimeexecutor (from `../../../node_modules/react-native/ReactCommon/runtimeexecutor`) + - React-RuntimeHermes (from `../../../node_modules/react-native/ReactCommon/react/runtime`) + - React-runtimescheduler (from `../../../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) + - React-utils (from `../../../node_modules/react-native/ReactCommon/react/utils`) - ReactCodegen (from `build/generated/ios`) - - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - ReactCommon/turbomodule/core (from `../../../node_modules/react-native/ReactCommon`) - rn-fetch-blob (from `../../../node_modules/rn-fetch-blob`) - - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - - RNReanimated (from `../node_modules/react-native-reanimated`) - - RNScreens (from `../node_modules/react-native-screens`) - - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) + - RNGestureHandler (from `../../../node_modules/react-native-gesture-handler`) + - RNReanimated (from `../../../node_modules/react-native-reanimated`) + - RNScreens (from `../../../node_modules/react-native-screens`) + - Yoga (from `../../../node_modules/react-native/ReactCommon/yoga`) SPEC REPOS: trunk: @@ -2154,148 +2154,148 @@ SPEC REPOS: EXTERNAL SOURCES: boost: - :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" + :podspec: "../../../node_modules/react-native/third-party-podspecs/boost.podspec" DoubleConversion: - :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" + :podspec: "../../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" FBLazyVector: - :path: "../node_modules/react-native/Libraries/FBLazyVector" + :path: "../../../node_modules/react-native/Libraries/FBLazyVector" fmt: - :podspec: "../node_modules/react-native/third-party-podspecs/fmt.podspec" + :podspec: "../../../node_modules/react-native/third-party-podspecs/fmt.podspec" glog: - :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" + :podspec: "../../../node_modules/react-native/third-party-podspecs/glog.podspec" hermes-engine: - :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" + :podspec: "../../../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" :tag: hermes-2024-08-15-RNv0.75.1-4b3bf912cc0f705b51b71ce1a5b8bd79b93a451b NitroModules: - :path: "../node_modules/react-native-nitro-modules" + :path: "../../../node_modules/react-native-nitro-modules" RCT-Folly: - :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" + :podspec: "../../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" RCTDeprecation: - :path: "../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation" + :path: "../../../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation" RCTRequired: - :path: "../node_modules/react-native/Libraries/Required" + :path: "../../../node_modules/react-native/Libraries/Required" RCTTypeSafety: - :path: "../node_modules/react-native/Libraries/TypeSafety" + :path: "../../../node_modules/react-native/Libraries/TypeSafety" React: - :path: "../node_modules/react-native/" + :path: "../../../node_modules/react-native/" React-callinvoker: - :path: "../node_modules/react-native/ReactCommon/callinvoker" + :path: "../../../node_modules/react-native/ReactCommon/callinvoker" React-Core: - :path: "../node_modules/react-native/" + :path: "../../../node_modules/react-native/" React-CoreModules: - :path: "../node_modules/react-native/React/CoreModules" + :path: "../../../node_modules/react-native/React/CoreModules" React-cxxreact: - :path: "../node_modules/react-native/ReactCommon/cxxreact" + :path: "../../../node_modules/react-native/ReactCommon/cxxreact" React-debug: - :path: "../node_modules/react-native/ReactCommon/react/debug" + :path: "../../../node_modules/react-native/ReactCommon/react/debug" React-defaultsnativemodule: - :path: "../node_modules/react-native/ReactCommon/react/nativemodule/defaults" + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/defaults" React-domnativemodule: - :path: "../node_modules/react-native/ReactCommon/react/nativemodule/dom" + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/dom" React-Fabric: - :path: "../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" React-FabricComponents: - :path: "../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" React-FabricImage: - :path: "../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" React-featureflags: - :path: "../node_modules/react-native/ReactCommon/react/featureflags" + :path: "../../../node_modules/react-native/ReactCommon/react/featureflags" React-featureflagsnativemodule: - :path: "../node_modules/react-native/ReactCommon/react/nativemodule/featureflags" + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/featureflags" React-graphics: - :path: "../node_modules/react-native/ReactCommon/react/renderer/graphics" + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/graphics" React-hermes: - :path: "../node_modules/react-native/ReactCommon/hermes" + :path: "../../../node_modules/react-native/ReactCommon/hermes" React-idlecallbacksnativemodule: - :path: "../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks" + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks" React-ImageManager: - :path: "../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios" + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios" React-jserrorhandler: - :path: "../node_modules/react-native/ReactCommon/jserrorhandler" + :path: "../../../node_modules/react-native/ReactCommon/jserrorhandler" React-jsi: - :path: "../node_modules/react-native/ReactCommon/jsi" + :path: "../../../node_modules/react-native/ReactCommon/jsi" React-jsiexecutor: - :path: "../node_modules/react-native/ReactCommon/jsiexecutor" + :path: "../../../node_modules/react-native/ReactCommon/jsiexecutor" React-jsinspector: - :path: "../node_modules/react-native/ReactCommon/jsinspector-modern" + :path: "../../../node_modules/react-native/ReactCommon/jsinspector-modern" React-jsitracing: - :path: "../node_modules/react-native/ReactCommon/hermes/executor/" + :path: "../../../node_modules/react-native/ReactCommon/hermes/executor/" React-logger: - :path: "../node_modules/react-native/ReactCommon/logger" + :path: "../../../node_modules/react-native/ReactCommon/logger" React-Mapbuffer: - :path: "../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" React-microtasksnativemodule: - :path: "../node_modules/react-native/ReactCommon/react/nativemodule/microtasks" + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/microtasks" react-native-filament: :path: "../../.." react-native-safe-area-context: - :path: "../node_modules/react-native-safe-area-context" + :path: "../../../node_modules/react-native-safe-area-context" react-native-video: - :path: "../node_modules/react-native-video" + :path: "../../../node_modules/react-native-video" react-native-worklets-core: - :path: "../node_modules/react-native-worklets-core" + :path: "../../../node_modules/react-native-worklets-core" React-nativeconfig: - :path: "../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" React-NativeModulesApple: - :path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" React-perflogger: - :path: "../node_modules/react-native/ReactCommon/reactperflogger" + :path: "../../../node_modules/react-native/ReactCommon/reactperflogger" React-performancetimeline: - :path: "../node_modules/react-native/ReactCommon/react/performance/timeline" + :path: "../../../node_modules/react-native/ReactCommon/react/performance/timeline" React-RCTActionSheet: - :path: "../node_modules/react-native/Libraries/ActionSheetIOS" + :path: "../../../node_modules/react-native/Libraries/ActionSheetIOS" React-RCTAnimation: - :path: "../node_modules/react-native/Libraries/NativeAnimation" + :path: "../../../node_modules/react-native/Libraries/NativeAnimation" React-RCTAppDelegate: - :path: "../node_modules/react-native/Libraries/AppDelegate" + :path: "../../../node_modules/react-native/Libraries/AppDelegate" React-RCTBlob: - :path: "../node_modules/react-native/Libraries/Blob" + :path: "../../../node_modules/react-native/Libraries/Blob" React-RCTFabric: - :path: "../node_modules/react-native/React" + :path: "../../../node_modules/react-native/React" React-RCTImage: - :path: "../node_modules/react-native/Libraries/Image" + :path: "../../../node_modules/react-native/Libraries/Image" React-RCTLinking: - :path: "../node_modules/react-native/Libraries/LinkingIOS" + :path: "../../../node_modules/react-native/Libraries/LinkingIOS" React-RCTNetwork: - :path: "../node_modules/react-native/Libraries/Network" + :path: "../../../node_modules/react-native/Libraries/Network" React-RCTSettings: - :path: "../node_modules/react-native/Libraries/Settings" + :path: "../../../node_modules/react-native/Libraries/Settings" React-RCTText: - :path: "../node_modules/react-native/Libraries/Text" + :path: "../../../node_modules/react-native/Libraries/Text" React-RCTVibration: - :path: "../node_modules/react-native/Libraries/Vibration" + :path: "../../../node_modules/react-native/Libraries/Vibration" React-rendererconsistency: - :path: "../node_modules/react-native/ReactCommon/react/renderer/consistency" + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/consistency" React-rendererdebug: - :path: "../node_modules/react-native/ReactCommon/react/renderer/debug" + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/debug" React-rncore: - :path: "../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" React-RuntimeApple: - :path: "../node_modules/react-native/ReactCommon/react/runtime/platform/ios" + :path: "../../../node_modules/react-native/ReactCommon/react/runtime/platform/ios" React-RuntimeCore: - :path: "../node_modules/react-native/ReactCommon/react/runtime" + :path: "../../../node_modules/react-native/ReactCommon/react/runtime" React-runtimeexecutor: - :path: "../node_modules/react-native/ReactCommon/runtimeexecutor" + :path: "../../../node_modules/react-native/ReactCommon/runtimeexecutor" React-RuntimeHermes: - :path: "../node_modules/react-native/ReactCommon/react/runtime" + :path: "../../../node_modules/react-native/ReactCommon/react/runtime" React-runtimescheduler: - :path: "../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler" + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler" React-utils: - :path: "../node_modules/react-native/ReactCommon/react/utils" + :path: "../../../node_modules/react-native/ReactCommon/react/utils" ReactCodegen: :path: build/generated/ios ReactCommon: - :path: "../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" rn-fetch-blob: :path: "../../../node_modules/rn-fetch-blob" RNGestureHandler: - :path: "../node_modules/react-native-gesture-handler" + :path: "../../../node_modules/react-native-gesture-handler" RNReanimated: - :path: "../node_modules/react-native-reanimated" + :path: "../../../node_modules/react-native-reanimated" RNScreens: - :path: "../node_modules/react-native-screens" + :path: "../../../node_modules/react-native-screens" Yoga: - :path: "../node_modules/react-native/ReactCommon/yoga" + :path: "../../../node_modules/react-native/ReactCommon/yoga" SPEC CHECKSUMS: boost: 4cb898d0bf20404aab1850c656dcea009429d6c1 @@ -2362,11 +2362,11 @@ SPEC CHECKSUMS: React-RuntimeHermes: c6b0afdf1f493621214eeb6517fb859ce7b21b81 React-runtimescheduler: 84f0d876d254bce6917a277b3930eb9bc29df6c7 React-utils: cbe8b8b3d7b2ac282e018e46f0e7b25cdc87c5a0 - ReactCodegen: 4bcb34e6b5ebf6eef5cee34f55aa39991ea1c1f1 + ReactCodegen: 3982de3211b80e119d9daa9cd6af090d75cb8e90 ReactCommon: 6a952e50c2a4b694731d7682aaa6c79bc156e4ad rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba RNGestureHandler: c374c750a0a9bacd95f5c740d146ab9428549d6b - RNReanimated: e94c6ad6b7a23ff641da13ada7d405c65f2c45f1 + RNReanimated: b3d406ee69af6972be20715d972b45d713aad400 RNScreens: de6e57426ba0e6cbc3fb5b4f496e7f08cb2773c2 SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d Yoga: aa3df615739504eebb91925fc9c58b4922ea9a08 diff --git a/package/example/AppExampleFabric/ios/RNFFabric.xcodeproj/project.pbxproj b/package/example/AppExampleFabric/ios/RNFFabric.xcodeproj/project.pbxproj index a4a2484c..7cb6e5d0 100644 --- a/package/example/AppExampleFabric/ios/RNFFabric.xcodeproj/project.pbxproj +++ b/package/example/AppExampleFabric/ios/RNFFabric.xcodeproj/project.pbxproj @@ -603,7 +603,7 @@ "$(inherited)", " ", ); - REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; + REACT_NATIVE_PATH = "${PODS_ROOT}/../../../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; USE_HERMES = true; @@ -680,7 +680,7 @@ "$(inherited)", " ", ); - REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; + REACT_NATIVE_PATH = "${PODS_ROOT}/../../../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; VALIDATE_PRODUCT = YES; diff --git a/package/example/Shared/babel.config.js b/package/example/Shared/babel.config.js index 1b9a6fb6..7db9ee35 100644 --- a/package/example/Shared/babel.config.js +++ b/package/example/Shared/babel.config.js @@ -3,7 +3,6 @@ const pak = require('../../package.json') const aliasMap = { [pak.name]: path.join(__dirname, '..', '..', pak.source), - [pak.name + '-test']: path.join(__dirname, '..', '..', pak.test), '~/assets': path.join(__dirname, 'assets'), } diff --git a/package/example/Shared/index.js b/package/example/Shared/index.js index c91a5d7b..df16acfe 100644 --- a/package/example/Shared/index.js +++ b/package/example/Shared/index.js @@ -24,10 +24,6 @@ setLogger({ error: prefixLog(console.error), }) -// Run filament tests -import { runTests } from 'react-native-filament-test' -runTests() - AppRegistry.registerComponent(appName, () => () => ( diff --git a/package/example/Shared/src/CameraPan.tsx b/package/example/Shared/src/CameraPan.tsx index a589dac4..15169f9a 100644 --- a/package/example/Shared/src/CameraPan.tsx +++ b/package/example/Shared/src/CameraPan.tsx @@ -18,15 +18,15 @@ function Scene() { const panGesture = Gesture.Pan() .onBegin((event) => { const yCorrected = viewHeight - event.translationY - cameraManipulator?.grabBegin(event.translationX, yCorrected, false) // false means rotation instead of translation + cameraManipulator?.unbox().grabBegin(event.translationX, yCorrected, false) // false means rotation instead of translation }) .onUpdate((event) => { const yCorrected = viewHeight - event.translationY - cameraManipulator?.grabUpdate(event.translationX, yCorrected) + cameraManipulator?.unbox().grabUpdate(event.translationX, yCorrected) }) .maxPointers(1) .onEnd(() => { - cameraManipulator?.grabEnd() + cameraManipulator?.unbox().grabEnd() }) // Scale gesture @@ -38,7 +38,7 @@ function Scene() { }) .onUpdate(({ scale, focalX, focalY }) => { const delta = scale - previousScale.value - cameraManipulator?.scroll(focalX, focalY, -delta * scaleMultiplier) + cameraManipulator?.unbox().scroll(focalX, focalY, -delta * scaleMultiplier) previousScale.value = scale }) const combinedGesture = Gesture.Race(pinchGesture, panGesture) diff --git a/package/example/Shared/tsconfig.json b/package/example/Shared/tsconfig.json index 70f291bb..d32c70fd 100644 --- a/package/example/Shared/tsconfig.json +++ b/package/example/Shared/tsconfig.json @@ -3,7 +3,6 @@ "compilerOptions": { "paths": { "react-native-filament": ["../../src/index"], - "react-native-filament-test": ["../../src/test/RunTests"], "~/assets/*": ["./assets/*"] } }, diff --git a/package/ios/src/RNFAppleDispatcher.h b/package/ios/src/RNFAppleDispatcher.h index 5d4ba918..b78aad8f 100644 --- a/package/ios/src/RNFAppleDispatcher.h +++ b/package/ios/src/RNFAppleDispatcher.h @@ -7,7 +7,12 @@ #pragma once -#include "threading/RNFDispatcher.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + #include namespace margelo { @@ -15,7 +20,7 @@ namespace margelo { /** A [Dispatcher] implementation that uses iOS dispatch_queues to schedule calls. */ -class AppleDispatcher : public Dispatcher { +class AppleDispatcher : public nitro::Dispatcher { public: explicit AppleDispatcher(dispatch_queue_t dispatchQueue) : _dispatchQueue(dispatchQueue) {} diff --git a/package/ios/src/RNFAppleFilamentProxy.h b/package/ios/src/RNFAppleFilamentProxy.h index 3509742b..66007a6b 100644 --- a/package/ios/src/RNFAppleFilamentProxy.h +++ b/package/ios/src/RNFAppleFilamentProxy.h @@ -8,11 +8,16 @@ #pragma once +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + #include "RNFFilamentBuffer.h" #include "RNFFilamentProxy.h" #include "RNFFilamentRecorder.h" #include "RNFFilamentView.h" -#include "threading/RNFDispatcher.h" #include #include @@ -25,7 +30,7 @@ namespace margelo { class AppleFilamentProxy : public FilamentProxy { public: #ifdef RCT_NEW_ARCH_ENABLED - explicit AppleFilamentProxy(jsi::Runtime* runtime, std::shared_ptr jsDispatcher, + explicit AppleFilamentProxy(jsi::Runtime* runtime, std::shared_ptr jsDispatcher, __weak RCTSurfacePresenter* surfacePresenter); #else explicit AppleFilamentProxy(jsi::Runtime* runtime, std::shared_ptr jsDispatcher); @@ -36,10 +41,10 @@ class AppleFilamentProxy : public FilamentProxy { std::shared_ptr findFilamentView(int modelId) override; std::shared_ptr createChoreographer() override; std::shared_ptr createRecorder(int width, int height, int fps, double bitRate) override; - std::shared_ptr getJSDispatcher() override; - std::shared_ptr getRenderThreadDispatcher() override; - std::shared_ptr getUIDispatcher() override; - std::shared_ptr getBackgroundDispatcher() override; + std::shared_ptr getJSDispatcher() override; + std::shared_ptr getRenderThreadDispatcher() override; + std::shared_ptr getUIDispatcher() override; + std::shared_ptr getBackgroundDispatcher() override; float getDisplayRefreshRate() override; float getDensityPixelRatio() override; @@ -48,10 +53,10 @@ class AppleFilamentProxy : public FilamentProxy { private: // The runtime the proxy has been installed on jsi::Runtime* _runtime; - std::shared_ptr _jsDispatcher; - std::shared_ptr _renderThreadDispatcher; - std::shared_ptr _uiDispatcher; - std::shared_ptr _backgroundDispatcher; + std::shared_ptr _jsDispatcher; + std::shared_ptr _renderThreadDispatcher; + std::shared_ptr _uiDispatcher; + std::shared_ptr _backgroundDispatcher; #ifdef RCT_NEW_ARCH_ENABLED __weak RCTSurfacePresenter* _surfacePresenter; #endif diff --git a/package/ios/src/RNFAppleFilamentProxy.mm b/package/ios/src/RNFAppleFilamentProxy.mm index 7923259e..0253c24c 100644 --- a/package/ios/src/RNFAppleFilamentProxy.mm +++ b/package/ios/src/RNFAppleFilamentProxy.mm @@ -28,7 +28,7 @@ namespace margelo { #ifdef RCT_NEW_ARCH_ENABLED -AppleFilamentProxy::AppleFilamentProxy(jsi::Runtime* runtime, std::shared_ptr jsDispatcher, +AppleFilamentProxy::AppleFilamentProxy(jsi::Runtime* runtime, std::shared_ptr jsDispatcher, __weak RCTSurfacePresenter* surfacePresenter) : _runtime(runtime), _jsDispatcher(jsDispatcher), _surfacePresenter(surfacePresenter) {} #else @@ -88,11 +88,11 @@ return std::make_shared(managedBuffer); } -std::shared_ptr AppleFilamentProxy::getJSDispatcher() { +std::shared_ptr AppleFilamentProxy::getJSDispatcher() { return _jsDispatcher; } -std::shared_ptr AppleFilamentProxy::getRenderThreadDispatcher() { +std::shared_ptr AppleFilamentProxy::getRenderThreadDispatcher() { if (_renderThreadDispatcher == nullptr) { // Filament has a strong requirement that you can only render from one single Thread. // iOS dispatch_queues may use multiple Threads, so we need to use NSThreadDispatcher instead of @@ -102,14 +102,14 @@ return _renderThreadDispatcher; } -std::shared_ptr AppleFilamentProxy::getUIDispatcher() { +std::shared_ptr AppleFilamentProxy::getUIDispatcher() { if (_uiDispatcher == nullptr) { _uiDispatcher = std::make_shared(dispatch_get_main_queue()); } return _uiDispatcher; } -std::shared_ptr AppleFilamentProxy::getBackgroundDispatcher() { +std::shared_ptr AppleFilamentProxy::getBackgroundDispatcher() { if (_backgroundDispatcher == nullptr) { dispatch_queue_attr_t qos = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_USER_INITIATED, -1); dispatch_queue_t queue = dispatch_queue_create("filament.background.queue", qos); diff --git a/package/ios/src/RNFAppleFilamentRecorder.h b/package/ios/src/RNFAppleFilamentRecorder.h index a40b9521..8bf366f8 100644 --- a/package/ios/src/RNFAppleFilamentRecorder.h +++ b/package/ios/src/RNFAppleFilamentRecorder.h @@ -17,7 +17,7 @@ namespace margelo { class AppleFilamentRecorder : public FilamentRecorder { public: - explicit AppleFilamentRecorder(std::shared_ptr renderThreadDispatcher, int width, int height, int fps, double bitRate); + explicit AppleFilamentRecorder(std::shared_ptr renderThreadDispatcher, int width, int height, int fps, double bitRate); void* getNativeWindow() override; std::string getOutputFile() override; diff --git a/package/ios/src/RNFAppleFilamentRecorder.mm b/package/ios/src/RNFAppleFilamentRecorder.mm index 1543a68c..65378520 100644 --- a/package/ios/src/RNFAppleFilamentRecorder.mm +++ b/package/ios/src/RNFAppleFilamentRecorder.mm @@ -6,6 +6,7 @@ // #include "RNFAppleFilamentRecorder.h" +#include "RNFLogger.h" #include #include #include @@ -16,7 +17,7 @@ static int kCVPixelBufferLock_Write = 0; -AppleFilamentRecorder::AppleFilamentRecorder(std::shared_ptr renderThreadDispatcher, int width, int height, int fps, +AppleFilamentRecorder::AppleFilamentRecorder(std::shared_ptr renderThreadDispatcher, int width, int height, int fps, double bitRate) : FilamentRecorder(renderThreadDispatcher, width, height, fps, bitRate) { dispatch_queue_attr_t qos = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, -1); diff --git a/package/ios/src/RNFFilamentInstaller.mm b/package/ios/src/RNFFilamentInstaller.mm index af9f5482..3021ca75 100644 --- a/package/ios/src/RNFFilamentInstaller.mm +++ b/package/ios/src/RNFFilamentInstaller.mm @@ -7,16 +7,12 @@ #import "RNFFilamentInstaller.h" #import "RNFAppleFilamentProxy.h" -#import "RNFPromiseFactory.h" #import #import #import #import -#import "threading/RNFCallInvokerDispatcher.h" -#import "threading/RNFDispatcher.h" - using namespace facebook; using namespace margelo; @@ -45,9 +41,7 @@ + (BOOL)installToBridge:(jsi::Runtime*)runtime return NO; } - // global.__globalDispatcher - std::shared_ptr jsDispatcher = std::make_shared(callInvoker); - Dispatcher::installRuntimeGlobalDispatcher(*runtime, jsDispatcher); + std::shared_ptr jsDispatcher = nitro::Dispatcher::getRuntimeGlobalDispatcher(*runtime); // global.FilamentProxy #ifdef RCT_NEW_ARCH_ENABLED @@ -55,7 +49,7 @@ + (BOOL)installToBridge:(jsi::Runtime*)runtime #else auto filamentProxy = std::make_shared(runtime, jsDispatcher); #endif - runtime->global().setProperty(*runtime, "FilamentProxy", jsi::Object::createFromHostObject(*runtime, filamentProxy)); + runtime->global().setProperty(*runtime, "FilamentProxy", filamentProxy->toObject(*runtime)); return YES; } diff --git a/package/ios/src/RNFNSThreadDispatcher.h b/package/ios/src/RNFNSThreadDispatcher.h index 2e1e9f51..55881140 100644 --- a/package/ios/src/RNFNSThreadDispatcher.h +++ b/package/ios/src/RNFNSThreadDispatcher.h @@ -7,7 +7,12 @@ #pragma once -#include "threading/RNFDispatcher.h" +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + #include #include @@ -16,7 +21,7 @@ namespace margelo { /** A [Dispatcher] implementation that uses an Objective-C NSThread. */ -class NSThreadDispatcher : public Dispatcher { +class NSThreadDispatcher : public nitro::Dispatcher { public: explicit NSThreadDispatcher(const std::string& name); diff --git a/package/package.json b/package/package.json index 5eb4a982..ec85742a 100644 --- a/package/package.json +++ b/package/package.json @@ -87,11 +87,12 @@ "@types/react": "18.3.11", "eslint": "^8.51.0", "eslint-config-prettier": "^9.0.0", - "eslint-plugin-prettier": "^5.0.1", + "eslint-plugin-prettier": "^5.2.1", "prettier": "^3.0.3", "react": "18.3.1", "react-native": "0.75.4", "react-native-builder-bob": "^0.20.0", + "react-native-nitro-modules": "^0.11.0", "react-native-worklets-core": "^2.0.0-beta.4", "release-it": "^15.0.0", "typescript": "^5.2.2" @@ -102,6 +103,7 @@ "peerDependencies": { "react": "*", "react-native": "*", + "react-native-nitro-modules": ">=0.11.0", "react-native-worklets-core": ">=1.3.2" }, "release-it": { diff --git a/package/src/hooks/internal/useApplyTransformations.tsx b/package/src/hooks/internal/useApplyTransformations.tsx index 8fea8701..7e39fd65 100644 --- a/package/src/hooks/internal/useApplyTransformations.tsx +++ b/package/src/hooks/internal/useApplyTransformations.tsx @@ -1,26 +1,28 @@ -import { useEffect, useRef } from 'react' +import { useEffect, useMemo, useRef } from 'react' import { TransformationProps } from '../../types/TransformProps' import { useFilamentContext } from '../useFilamentContext' import { AABB, Entity, Float3 } from '../../types' import { areFloat3Equal, isWorkletSharedValue } from '../../utilities/helper' import { useWorkletEffect } from '../useWorkletEffect' +import { BoxedHybridObject } from 'react-native-nitro-modules/lib/BoxedHybridObject' type Params = { // If null it will not take the entity from the context, as it indicates that it will be provided through the param - to?: Entity | null + to?: BoxedHybridObject | null transformProps?: TransformationProps // If transformToUnitCube is true, the aabb is required - aabb?: AABB + aabb?: BoxedHybridObject } /** * Takes the next entity from the context and applies all transformations from the next * transformation context to it */ -export function useApplyTransformations({ to: entity, transformProps, aabb }: Params) { +export function useApplyTransformations({ to: boxedEntity, transformProps, aabb: boxedAABB }: Params) { const { translate: position, scale, rotate, transformToUnitCube, multiplyWithCurrentTransform = true } = transformProps ?? {} const { transformManager } = useFilamentContext() + const unboxedTransformManagerJS = useMemo(() => transformManager.unbox(), [transformManager]) // TODO: multiplying current transformations is a bit problematic with react. // E.g. in strict mode or concurrent rendering our effects can be called multiple times. // Running an effect multiple times with transformation multiplication can lead to unexpected results. @@ -29,33 +31,36 @@ export function useApplyTransformations({ to: entity, transformProps, aabb }: Pa const prevPosition = useRef(null) useEffect(() => { - if (entity == null) return + if (boxedEntity == null) return + const entity = boxedEntity.unbox() + const aabb = boxedAABB?.unbox() if (transformToUnitCube && aabb != null) { - transformManager.transformToUnitCube(entity, aabb) + unboxedTransformManagerJS.transformToUnitCube(entity, aabb) + console.log('converted to unit cube :)') } if (Array.isArray(scale) && (prevScale.current == null || !areFloat3Equal(scale, prevScale.current))) { - transformManager.setEntityScale(entity, scale, multiplyWithCurrentTransform) + unboxedTransformManagerJS.setEntityScale(entity, scale, multiplyWithCurrentTransform) prevScale.current = scale } if (Array.isArray(rotate) && (prevRotate.current == null || !areFloat3Equal(rotate, prevRotate.current))) { const [x, y, z] = rotate - transformManager.setEntityRotation(entity, x, [1, 0, 0], multiplyWithCurrentTransform) + unboxedTransformManagerJS.setEntityRotation(entity, x, [1, 0, 0], multiplyWithCurrentTransform) // Rotation across axis is one operation so we need to always multiply the remaining rotations: - transformManager.setEntityRotation(entity, y, [0, 1, 0], true) - transformManager.setEntityRotation(entity, z, [0, 0, 1], true) + unboxedTransformManagerJS.setEntityRotation(entity, y, [0, 1, 0], true) + unboxedTransformManagerJS.setEntityRotation(entity, z, [0, 0, 1], true) prevRotate.current = rotate } if (Array.isArray(position) && (prevPosition.current == null || !areFloat3Equal(position, prevPosition.current))) { - transformManager.setEntityPosition(entity, position, multiplyWithCurrentTransform) + unboxedTransformManagerJS.setEntityPosition(entity, position, multiplyWithCurrentTransform) prevPosition.current = position } }, [ - aabb, - entity, + boxedAABB, + boxedEntity, multiplyWithCurrentTransform, position, prevPosition, @@ -63,28 +68,31 @@ export function useApplyTransformations({ to: entity, transformProps, aabb }: Pa prevScale, rotate, scale, - transformManager, + unboxedTransformManagerJS, transformToUnitCube, ]) + console.log(transformProps) + // Effects for when a transform option is a shared value (SRT) useEffect(() => { - if (entity == null) return + if (boxedEntity == null) return if (scale == null || Array.isArray(scale)) return const unsubscribeScale = scale.addListener(() => { - transformManager.setEntityScale(entity, scale.value, multiplyWithCurrentTransform) + 'worklet' + transformManager.unbox().setEntityScale(boxedEntity.unbox(), scale.value, multiplyWithCurrentTransform) }) return () => { unsubscribeScale() } - }, [entity, multiplyWithCurrentTransform, scale, transformManager]) + }, [boxedEntity, multiplyWithCurrentTransform, scale, transformManager]) useWorkletEffect(() => { 'worklet' - if (entity == null) return + if (boxedEntity == null) return if (rotate == null || !isWorkletSharedValue(rotate)) { return @@ -92,11 +100,13 @@ export function useApplyTransformations({ to: entity, transformProps, aabb }: Pa const unsubscribeRotate = rotate.addListener(() => { 'worklet' + const entity = boxedEntity.unbox() const [x, y, z] = rotate.value - transformManager.setEntityRotation(entity, x, [1, 0, 0], multiplyWithCurrentTransform) + const unboxedTransformManager = transformManager.unbox() + unboxedTransformManager.setEntityRotation(entity, x, [1, 0, 0], multiplyWithCurrentTransform) // Rotation across axis is one operation so we need to always multiply the remaining rotations: - transformManager.setEntityRotation(entity, y, [0, 1, 0], true) - transformManager.setEntityRotation(entity, z, [0, 0, 1], true) + unboxedTransformManager.setEntityRotation(entity, y, [0, 1, 0], true) + unboxedTransformManager.setEntityRotation(entity, z, [0, 0, 1], true) }) return () => { @@ -106,16 +116,17 @@ export function useApplyTransformations({ to: entity, transformProps, aabb }: Pa }) useEffect(() => { - if (entity == null) return + if (boxedEntity == null) return if (position == null || Array.isArray(position)) return const unsubscribePosition = position.addListener(() => { - transformManager.setEntityPosition(entity, position.value, multiplyWithCurrentTransform) + 'worklet' + transformManager.unbox().setEntityPosition(boxedEntity.unbox(), position.value, multiplyWithCurrentTransform) }) return () => { unsubscribePosition() } - }, [entity, multiplyWithCurrentTransform, position, transformManager]) + }, [boxedEntity, multiplyWithCurrentTransform, position, transformManager]) } diff --git a/package/src/hooks/useAnimator.ts b/package/src/hooks/useAnimator.ts index 0d34b2d5..f55572e6 100644 --- a/package/src/hooks/useAnimator.ts +++ b/package/src/hooks/useAnimator.ts @@ -21,10 +21,10 @@ export function useAnimator(modelOrAsset?: FilamentAsset | FilamentInstance | Fi if (isFilamentModel(modelOrAsset)) { if (modelOrAsset.state === 'loading') return undefined const { asset } = modelOrAsset - return asset.createAnimator(nameComponentManager) + return asset.unbox().createAnimator(nameComponentManager.unbox()) } - return modelOrAsset.createAnimator(nameComponentManager) + return modelOrAsset.createAnimator(nameComponentManager.unbox()) }, [modelOrAsset, nameComponentManager]) return animator } diff --git a/package/src/hooks/useCameraManipulator.ts b/package/src/hooks/useCameraManipulator.ts index caaa658f..cce545d5 100644 --- a/package/src/hooks/useCameraManipulator.ts +++ b/package/src/hooks/useCameraManipulator.ts @@ -1,6 +1,7 @@ import { useFilamentContext } from './useFilamentContext' import { Float3, OrbitCameraManipulatorConfig } from '../types' import { useDisposableResource } from './useDisposableResource' +import { NitroModules } from 'react-native-nitro-modules' const cameraPosition: Float3 = [0, 0, 8] const cameraTarget: Float3 = [0, 0, 0] @@ -41,7 +42,10 @@ export function useCameraManipulator({ localConfig.orbitSpeed = [orbitSpeedX, orbitSpeedY] } - return Promise.resolve(engine.createOrbitCameraManipulator(localConfig)) + const unboxedEngine = engine.unbox() + const newCameraManipulator = unboxedEngine.createOrbitCameraManipulator(localConfig) + const boxedCameraManipulator = NitroModules.box(newCameraManipulator) + return Promise.resolve(boxedCameraManipulator) }, [ engine, orbitHomePositionX, diff --git a/package/src/hooks/useConfigureAssetShadow.ts b/package/src/hooks/useConfigureAssetShadow.ts index c171b03d..b72f4939 100644 --- a/package/src/hooks/useConfigureAssetShadow.ts +++ b/package/src/hooks/useConfigureAssetShadow.ts @@ -1,10 +1,11 @@ import { useEffect, useMemo, useRef } from 'react' import { FilamentAsset, RenderableManager } from '../types' import { useFilamentContext } from './useFilamentContext' +import { BoxedHybridObject } from 'react-native-nitro-modules/lib/BoxedHybridObject' export type UseAssetShadowProps = { - renderableManager: RenderableManager - asset?: FilamentAsset + renderableManager: BoxedHybridObject + asset?: BoxedHybridObject /** * @default false */ @@ -19,7 +20,7 @@ export type UseAssetShadowProps = { export function useConfigureAssetShadow({ renderableManager, asset, receiveShadow, castShadow }: UseAssetShadowProps) { const { workletContext } = useFilamentContext() - const renderableEntities = useMemo(() => asset?.getRenderableEntities(), [asset]) + const renderableEntities = useMemo(() => (asset == null ? undefined : asset.unbox().getRenderableEntities()), [asset]) const prevCastShadowRef = useRef() useEffect(() => { if (renderableEntities == null || castShadow == null || prevCastShadowRef.current === castShadow) { @@ -30,8 +31,9 @@ export function useConfigureAssetShadow({ renderableManager, asset, receiveShado workletContext.runAsync(() => { 'worklet' + const unboxedRenderableManager = renderableManager.unbox() renderableEntities.forEach((entity) => { - renderableManager.setCastShadow(entity, castShadow) + unboxedRenderableManager.setCastShadow(entity, castShadow) }) }) }, [castShadow, renderableManager, renderableEntities, workletContext]) @@ -46,8 +48,9 @@ export function useConfigureAssetShadow({ renderableManager, asset, receiveShado workletContext.runAsync(() => { 'worklet' + const unboxedRenderableManager = renderableManager.unbox() renderableEntities.forEach((entity) => { - renderableManager.setReceiveShadow(entity, receiveShadow) + unboxedRenderableManager.setReceiveShadow(entity, receiveShadow) }) }) }, [receiveShadow, renderableEntities, renderableManager, workletContext]) diff --git a/package/src/hooks/useDisposableResource.ts b/package/src/hooks/useDisposableResource.ts index aaa02efa..045b1f6a 100644 --- a/package/src/hooks/useDisposableResource.ts +++ b/package/src/hooks/useDisposableResource.ts @@ -1,11 +1,14 @@ import { DependencyList, useEffect, useState } from 'react' import { withCleanupScope } from '../utilities/withCleanupScope' import { PointerHolder } from '../types/PointerHolder' - -type ReleasingResource = Pick +import { BoxedHybridObject } from 'react-native-nitro-modules/lib/BoxedHybridObject' const emptyStaticArray: DependencyList = [] +function isBoxed(obj: any): obj is BoxedHybridObject { + return obj.unbox != null +} + /** * Any resource that is a {@link PointerHolder} and can be released, should be loaded * using this hook. It takes care of properly releasing the resource when the component @@ -14,7 +17,7 @@ const emptyStaticArray: DependencyList = [] * multiple times. Also loading the resource can be async and this hooks handles all these * cases properly. */ -export const useDisposableResource = ( +export const useDisposableResource = >( initialize: () => Promise | undefined, deps?: DependencyList ): T | undefined => { @@ -32,7 +35,12 @@ export const useDisposableResource = ( currentAsset = a } else { // this useEffect has been unmounted already, drop the asset - a.release() + if (isBoxed(a)) { + const unboxed = a.unbox() + unboxed.release() + } else { + a.release() + } } }) // TODO: catch is broken @@ -43,7 +51,13 @@ export const useDisposableResource = ( setResource(undefined) isValid = false withCleanupScope(() => { - currentAsset?.release() + if (currentAsset == null) return + if (isBoxed(currentAsset)) { + const unboxed = currentAsset.unbox() + unboxed.release() + } else { + currentAsset.release() + } })() } // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/package/src/hooks/useEngine.ts b/package/src/hooks/useEngine.ts index 8d9ede6c..fdd1d2f5 100644 --- a/package/src/hooks/useEngine.ts +++ b/package/src/hooks/useEngine.ts @@ -1,7 +1,8 @@ import type { Engine, EngineBackend, EngineConfig } from '../types' -import { FilamentProxy } from '../native/FilamentProxy' +import { FilamentProxyBoxed, NitroBoxed } from '../native/FilamentProxy' import { IWorkletContext, useWorklet } from 'react-native-worklets-core' import { useDisposableResource } from './useDisposableResource' +import { BoxedHybridObject } from 'react-native-nitro-modules/lib/BoxedHybridObject' export interface EngineProps { /** @@ -18,11 +19,16 @@ export interface EngineProps { context: IWorkletContext } -export function useEngine({ backend, config, context }: EngineProps): Engine | undefined { +export function useEngine({ backend, config, context }: EngineProps): BoxedHybridObject | undefined { // Important: create the engine on the worklet thread, so its owned by the worklet thread const createEngine = useWorklet(context, () => { 'worklet' - return FilamentProxy.createEngine(backend ?? undefined, config ?? undefined) + + const filamentProxy = FilamentProxyBoxed.unbox() + const engine = filamentProxy.createEngine(backend ?? undefined, config ?? undefined) + const nitro = NitroBoxed.unbox() + const boxedEngine = nitro.box(engine) + return boxedEngine }) const engine = useDisposableResource(createEngine) diff --git a/package/src/hooks/useFilamentContext.ts b/package/src/hooks/useFilamentContext.ts index 12dace35..a23b3c99 100644 --- a/package/src/hooks/useFilamentContext.ts +++ b/package/src/hooks/useFilamentContext.ts @@ -12,17 +12,18 @@ import { View, } from '../types' import { IWorkletContext } from 'react-native-worklets-core' +import { BoxedHybridObject } from 'react-native-nitro-modules/lib/BoxedHybridObject' export type FilamentContextType = { - engine: Engine - transformManager: TransformManager - renderableManager: RenderableManager - scene: Scene - lightManager: LightManager - view: View - camera: RNFCamera - renderer: Renderer - nameComponentManager: NameComponentManager + engine: BoxedHybridObject + transformManager: BoxedHybridObject + renderableManager: BoxedHybridObject + scene: BoxedHybridObject + lightManager: BoxedHybridObject + view: BoxedHybridObject + camera: BoxedHybridObject + renderer: BoxedHybridObject + nameComponentManager: BoxedHybridObject workletContext: IWorkletContext /** @@ -30,7 +31,7 @@ export type FilamentContextType = { * @private * @internal */ - choreographer: Choreographer + choreographer: BoxedHybridObject } export const FilamentContext = React.createContext(undefined) diff --git a/package/src/hooks/useLightEntity.ts b/package/src/hooks/useLightEntity.ts index 11220100..1eccf3b8 100644 --- a/package/src/hooks/useLightEntity.ts +++ b/package/src/hooks/useLightEntity.ts @@ -63,6 +63,7 @@ export function useLightEntity(lightManager: LightManager, config: UseLightEntit if (intensity == null) return if (typeof intensity === 'number') return + // TODO: nitro this needs to be boxed i assume const setIntensity = lightManager.setIntensity return intensity.addListener( diff --git a/package/src/hooks/useModel.ts b/package/src/hooks/useModel.ts index c9244554..0d7b5f8c 100644 --- a/package/src/hooks/useModel.ts +++ b/package/src/hooks/useModel.ts @@ -6,6 +6,9 @@ import usePrevious from './usePrevious' import { useWorkletEffect } from './useWorkletEffect' import { AABB, Entity } from '../types' import { useMemo } from 'react' +import { NitroBoxed } from '../native/FilamentProxy' +import { BoxedHybridObject } from 'react-native-nitro-modules/lib/BoxedHybridObject' +import { NitroModules } from 'react-native-nitro-modules' export interface UseModelConfigParams { /** @@ -33,12 +36,12 @@ export interface UseModelConfigParams { export type FilamentModel = | { state: 'loaded' - asset: FilamentAsset - boundingBox: AABB + asset: BoxedHybridObject + boundingBox: BoxedHybridObject /** * The root entity of the model. */ - rootEntity: Entity + rootEntity: BoxedHybridObject } | { state: 'loading' @@ -60,11 +63,12 @@ export type FilamentModel = export function useModel(source: BufferSource, props?: UseModelConfigParams): FilamentModel { const { shouldReleaseSourceData = true, addToScene = true, instanceCount } = props ?? {} const { engine, scene, workletContext } = useFilamentContext() - const assetBuffer = useBuffer({ source: source, releaseOnUnmount: false }) + const rawAssetBuffer = useBuffer({ source: source, releaseOnUnmount: false }) + const boxedAssetBuffer = rawAssetBuffer == null ? undefined : NitroModules.box(rawAssetBuffer) // Note: the native cleanup of the asset will remove it automatically from the scene const asset = useDisposableResource(() => { - if (assetBuffer == null) return + if (boxedAssetBuffer == null) return if (instanceCount === 0) { throw new Error('instanceCount must be greater than 0') } @@ -73,18 +77,22 @@ export function useModel(source: BufferSource, props?: UseModelConfigParams): Fi 'worklet' let loadedAsset: FilamentAsset + const unboxedEngine = engine.unbox() + const assetBuffer = boxedAssetBuffer.unbox() if (instanceCount == null || instanceCount === 1) { - loadedAsset = engine.loadAsset(assetBuffer) + loadedAsset = unboxedEngine.loadAsset(assetBuffer) } else { - loadedAsset = engine.loadInstancedAsset(assetBuffer, instanceCount) + loadedAsset = unboxedEngine.loadInstancedAsset(assetBuffer, instanceCount) } // After loading the asset we can release the buffer assetBuffer.release() - return loadedAsset + const nitro = NitroBoxed.unbox() + const boxedAsset = nitro.box(loadedAsset) + return boxedAsset }) - }, [assetBuffer, workletContext, engine, instanceCount]) + }, [boxedAssetBuffer, instanceCount, workletContext, engine]) useWorkletEffect(() => { 'worklet' @@ -93,7 +101,7 @@ export function useModel(source: BufferSource, props?: UseModelConfigParams): Fi } // releases CPU memory for bindings - asset.releaseSourceData() + asset.unbox().releaseSourceData() }) // Add or remove from the scene: @@ -102,27 +110,35 @@ export function useModel(source: BufferSource, props?: UseModelConfigParams): Fi 'worklet' if (asset == null) return + const unboxedScene = scene.unbox() + const unboxedAsset = asset.unbox() if (addToScene) { - scene.addAssetEntities(asset) + unboxedScene.addAssetEntities(unboxedAsset) } else if (!addToScene && previousAddToScene) { // Only remove when it was previously added (ie. the user set addToScene: false) - scene.removeAssetEntities(asset) + unboxedScene.removeAssetEntities(unboxedAsset) } }) const boundingBox = useMemo(() => { if (asset == null) return undefined - return asset.getBoundingBox() + return NitroModules.box(asset.unbox().getBoundingBox()) }, [asset]) const rootEntity = useMemo(() => { if (asset == null) { return null } - return asset.getRoot() + return NitroModules.box(asset.unbox().getRoot()) }, [asset]) - if (assetBuffer == null || asset == null || boundingBox == null || rootEntity == null) { + if (rawAssetBuffer == null || asset == null || boundingBox == null || rootEntity == null) { + console.log({ + rawAssetBuffer, + asset, + boundingBox, + rootEntity, + }) return { state: 'loading', } diff --git a/package/src/hooks/useSkybox.ts b/package/src/hooks/useSkybox.ts index d5bc9d15..8dd9decd 100644 --- a/package/src/hooks/useSkybox.ts +++ b/package/src/hooks/useSkybox.ts @@ -33,14 +33,16 @@ export function useSkybox(options?: SkyboxOptions | null) { useWorkletEffect(() => { 'worklet' + const unboxedEngine = engine.unbox() + if (!hasOptions) { - engine.clearSkybox() + unboxedEngine.clearSkybox() return } if (texture) { - engine.createAndSetSkyboxByTexture(texture, showSun, envIntensity) + unboxedEngine.createAndSetSkyboxByTexture(texture, showSun, envIntensity) } else if (color) { - engine.createAndSetSkyboxByColor(color, showSun, envIntensity) + unboxedEngine.createAndSetSkyboxByColor(color, showSun, envIntensity) } }) } diff --git a/package/src/index.tsx b/package/src/index.tsx index 3474bca8..573326ea 100644 --- a/package/src/index.tsx +++ b/package/src/index.tsx @@ -1,3 +1,6 @@ +import { isRuntimeAlive } from 'react-native-nitro-modules' // TODO: nitro this should be accessed through a proxy if a user doesn't have this installed +isRuntimeAlive() // This is a "dummy" call to init react-native-nitro-modules + export * from './types' // hooks diff --git a/package/src/native/FilamentProxy.ts b/package/src/native/FilamentProxy.ts index f05162a8..d91db0e4 100644 --- a/package/src/native/FilamentProxy.ts +++ b/package/src/native/FilamentProxy.ts @@ -9,6 +9,7 @@ import { Choreographer } from '../types/Choreographer' import { Dispatcher } from './Dispatcher' import { FilamentModule } from './FilamentModule' import { Worklets } from 'react-native-worklets-core' +import { HybridObject, NitroModules } from 'react-native-nitro-modules' interface TestHybridObject { int: number @@ -24,7 +25,7 @@ interface TestHybridObject { enum: 'first' | 'second' | 'third' } -export interface TFilamentProxy { +export interface TFilamentProxy extends HybridObject<{ ios: 'c++'; android: 'c++' }> { /** * Asynchronously loads the the given asset into a ByteBuffer. * @param path A web URL (http:// or https://), local file (file://) or resource ID. (Only resource ID supported for now) @@ -119,6 +120,8 @@ if (!proxy.hasWorklets) { } export const FilamentProxy = proxy +export const FilamentProxyBoxed = NitroModules.box(proxy) +export const NitroBoxed = NitroModules.box(NitroModules) // We must make sure that the Worklets API (module) is initialized (as its possible a lazy-loaded CxxTurboModule), // to initialize we must only call any property of the module: diff --git a/package/src/native/FilamentViewTypes.ts b/package/src/native/FilamentViewTypes.ts index 1c0d0d66..4a6a1ea4 100644 --- a/package/src/native/FilamentViewTypes.ts +++ b/package/src/native/FilamentViewTypes.ts @@ -1,3 +1,4 @@ +import { HybridObject } from 'react-native-nitro-modules' import { Choreographer } from '../types' import { Listener } from '../types/Listener' import { Dispatcher } from './Dispatcher' @@ -7,7 +8,7 @@ export interface Surface { readonly height: number } -export interface SurfaceProvider { +export interface SurfaceProvider extends HybridObject<{ android: 'c++'; ios: 'c++' }> { /** * @private */ diff --git a/package/src/react/BackgroundImage.tsx b/package/src/react/BackgroundImage.tsx index e76001cb..ea28528b 100644 --- a/package/src/react/BackgroundImage.tsx +++ b/package/src/react/BackgroundImage.tsx @@ -24,14 +24,14 @@ export function BackgroundImage({ source, materialSource, resizeMode = 'contain' 'worklet' if (imageMaterialBuffer == null || imageBuffer == null) return undefined - const newMaterial = engine.createMaterial(imageMaterialBuffer) - const textureInfo = newMaterial.setDefaultTextureParameter(renderableManager, 'image', imageBuffer, 'sRGB') + const newMaterial = engine.unbox().createMaterial(imageMaterialBuffer) + const textureInfo = newMaterial.setDefaultTextureParameter(renderableManager.unbox(), 'image', imageBuffer, 'sRGB') newMaterial.setDefaultIntParameter('showImage', 1) // Transform calculation const srcWidth = textureInfo.width const srcHeight = textureInfo.height - const viewport = view.getViewport() + const viewport = view.unbox().getViewport() const dstWidth = viewport.width const dstHeight = viewport.height @@ -94,6 +94,7 @@ export function BackgroundImage({ source, materialSource, resizeMode = 'contain' newMaterial.setDefaultMat3fParameter('transform', transform) newMaterial.setDefaultFloat3Parameter('backgroundColor', [0.0, 0.0, 0.0]) + // TODO: nitro needs to be boxed return newMaterial }), [engine, imageMaterialBuffer, imageBuffer] @@ -105,9 +106,9 @@ export function BackgroundImage({ source, materialSource, resizeMode = 'contain' if (material == null) return - return renderableManager.createImageBackgroundShape(material) + return renderableManager.unbox().createImageBackgroundShape(material) }, [material, renderableManager]) - useEntityInScene(scene, entity) + useEntityInScene(scene.unbox(), entity) return null } diff --git a/package/src/react/Camera.tsx b/package/src/react/Camera.tsx index cea9e35c..35896448 100644 --- a/package/src/react/Camera.tsx +++ b/package/src/react/Camera.tsx @@ -2,6 +2,7 @@ import { useSharedValue } from 'react-native-worklets-core' import { CameraManipulator, Float3 } from '../types' import { useFilamentContext } from '../hooks/useFilamentContext' import { RenderCallbackContext } from './RenderCallbackContext' +import { BoxedHybridObject } from 'react-native-nitro-modules/lib/BoxedHybridObject' export type CameraProps = { /** @@ -45,7 +46,7 @@ export type CameraProps = { * The camera can optionally be owned by a {@linkcode CameraManipulator}. * In this case the manipulators state will be used to update the camera. */ - cameraManipulator?: CameraManipulator + cameraManipulator?: BoxedHybridObject } // Sensible defaults: @@ -83,18 +84,20 @@ export function Camera({ cameraManipulator, ...cameraConfig }: CameraProps) { RenderCallbackContext.useRenderCallback(() => { 'worklet' - const aspectRatio = view.getAspectRatio() + const unboxedCamera = camera.unbox() + const aspectRatio = view.unbox().getAspectRatio() if (prevAspectRatio.value !== aspectRatio) { prevAspectRatio.value = aspectRatio // Setup camera lens: - camera.setLensProjection(focalLengthInMillimeters, aspect ?? aspectRatio, near, far) + unboxedCamera.setLensProjection(focalLengthInMillimeters, aspect ?? aspectRatio, near, far) console.log('Setting up camera lens with aspect ratio:', aspectRatio) } if (cameraManipulator != null) { - camera.lookAtCameraManipulator(cameraManipulator) + const unboxedCameraManipulator = cameraManipulator.unbox() + unboxedCamera.lookAtCameraManipulator(unboxedCameraManipulator) } else { - camera.lookAt( + unboxedCamera.lookAt( [cameraPositionX, cameraPositionY, cameraPositionZ], [cameraTargetX, cameraTargetY, cameraTargetZ], [cameraUpX, cameraUpY, cameraUpZ] diff --git a/package/src/react/Configurator.tsx b/package/src/react/Configurator.tsx index b1d5c02c..ef18b58d 100644 --- a/package/src/react/Configurator.tsx +++ b/package/src/react/Configurator.tsx @@ -1,4 +1,4 @@ -import { PropsWithChildren, useEffect } from 'react' +import { PropsWithChildren, useEffect, useMemo } from 'react' import { AmbientOcclusionOptions, DynamicResolutionOptions, @@ -48,23 +48,25 @@ export function Configurator({ rendererProps, viewProps, children }: Configurato shadowing, temporalAntiAliasingOptions, } = viewProps + + const unboxedViewJS = useMemo(() => view.unbox(), [view]) useEffect(() => { if (ambientOcclusionOptions != null) { - const options = makeAmbientOcclusionHostObject(view, ambientOcclusionOptions) - view.setAmbientOcclusionOptions(options) + const options = makeAmbientOcclusionHostObject(unboxedViewJS, ambientOcclusionOptions) + unboxedViewJS.setAmbientOcclusionOptions(options) } if (dynamicResolutionOptions != null) { - const options = makeDynamicResolutionHostObject(view, dynamicResolutionOptions) - view.setDynamicResolutionOptions(options) + const options = makeDynamicResolutionHostObject(unboxedViewJS, dynamicResolutionOptions) + unboxedViewJS.setDynamicResolutionOptions(options) } - if (antiAliasing != null) view.antiAliasing = antiAliasing - if (dithering != null) view.dithering = dithering - if (postProcessing != null) view.postProcessing = postProcessing - if (screenSpaceRefraction != null) view.screenSpaceRefraction = screenSpaceRefraction - if (shadowing != null) view.shadowing = shadowing - if (temporalAntiAliasingOptions != null) view.temporalAntiAliasingOptions = optionsToJSI(temporalAntiAliasingOptions) + if (antiAliasing != null) unboxedViewJS.antiAliasing = antiAliasing + if (dithering != null) unboxedViewJS.dithering = dithering + if (postProcessing != null) unboxedViewJS.postProcessing = postProcessing + if (screenSpaceRefraction != null) unboxedViewJS.screenSpaceRefraction = screenSpaceRefraction + if (shadowing != null) unboxedViewJS.shadowing = shadowing + if (temporalAntiAliasingOptions != null) unboxedViewJS.temporalAntiAliasingOptions = optionsToJSI(temporalAntiAliasingOptions) }, [ - view, + unboxedViewJS, ambientOcclusionOptions, antiAliasing, dithering, @@ -79,7 +81,7 @@ export function Configurator({ rendererProps, viewProps, children }: Configurato const { frameRateOptions } = rendererProps ?? {} useEffect(() => { if (frameRateOptions != null) { - renderer.setFrameRateOptions(frameRateOptions) + renderer.unbox().setFrameRateOptions(frameRateOptions) } }, [renderer, frameRateOptions]) diff --git a/package/src/react/DebugBox.tsx b/package/src/react/DebugBox.tsx index 571c0fd6..67672b19 100644 --- a/package/src/react/DebugBox.tsx +++ b/package/src/react/DebugBox.tsx @@ -5,6 +5,7 @@ import { TransformationProps } from '../types/TransformProps' import { useApplyTransformations } from '../hooks/internal/useApplyTransformations' import { ParentInstancesContext } from './ParentInstancesContext' import { useEntityInScene } from '../hooks/useEntityInScene' +import { NitroModules } from 'react-native-nitro-modules' export type DebugBoxProps = TransformationProps & { halfExtent?: Float3 @@ -25,12 +26,14 @@ export function DebugBox({ halfExtent: halfExtentProp, ...transformProps }: Debu if (halfExtent == null) return null // TODO: other colors are only supported by importing a material - i think it should be possible to create a material on the fly - return renderableManager.createDebugCubeWireframe(halfExtent, undefined, undefined) + const entity = renderableManager.unbox().createDebugCubeWireframe(halfExtent, undefined, undefined) + const boxedEntity = NitroModules.box(entity) + return boxedEntity }, [halfExtent, renderableManager]) useApplyTransformations({ to: boxEntity, transformProps }) - useEntityInScene(scene, boxEntity ?? undefined) + useEntityInScene(scene.unbox(), boxEntity?.unbox()) return null } diff --git a/package/src/react/EntitySelector.tsx b/package/src/react/EntitySelector.tsx index 7b1a2458..dd360059 100644 --- a/package/src/react/EntitySelector.tsx +++ b/package/src/react/EntitySelector.tsx @@ -6,6 +6,8 @@ import React from 'react' import { useApplyTransformations } from '../hooks/internal/useApplyTransformations' import { FilamentBuffer } from '../native/FilamentBuffer' import { useWorkletEffect } from '../hooks/useWorkletEffect' +import { BoxedHybridObject } from 'react-native-nitro-modules/lib/BoxedHybridObject' +import { NitroModules } from 'react-native-nitro-modules' export type SelectorProps = | { @@ -42,7 +44,7 @@ export function EntitySelector(props: EntitySelectorProps) { if (byName != null) { // TODO: can be optimized by using it from asset, or https://github.com/google/filament/discussions/7980 - return entities.find((e) => nameComponentManager.getEntityName(e) === byName) + return entities.find((e) => nameComponentManager.unbox().getEntityName(e) === byName) } else if (byIndex != null) { if (byIndex >= entities.length) { throw new Error(': byIndex is out of bounds. Instance only has ' + entities.length + ' entities') @@ -66,11 +68,12 @@ export function EntitySelector(props: EntitySelectorProps) { throw new Error(`: Could not find entity by ${byName != null ? 'name' : 'index'} "${byName ?? byIndex}"`) } - return + const boxedEntity = NitroModules.box(entity) + return } type ImplProps = { - entity: Entity + entity: BoxedHybridObject } & ModifierProps /** @@ -84,7 +87,7 @@ function EntitySelectorImpl(props: ImplProps) { } type TextureModifierProps = TextureMap & { - entity: Entity + entity: BoxedHybridObject } /** @@ -95,7 +98,7 @@ function TextureModifier({ entity, textureSource, materialName, textureFlags = ' useWorkletEffect(() => { 'worklet' - renderableManager.changeMaterialTextureMap(entity, materialName, textureSource, textureFlags) + renderableManager.unbox().changeMaterialTextureMap(entity.unbox(), materialName, textureSource, textureFlags) }) return null diff --git a/package/src/react/EnvironmentalLight.tsx b/package/src/react/EnvironmentalLight.tsx index 57d5f399..29377c7f 100644 --- a/package/src/react/EnvironmentalLight.tsx +++ b/package/src/react/EnvironmentalLight.tsx @@ -1,3 +1,4 @@ +import { NitroModules } from 'react-native-nitro-modules' import { BufferSource, useBuffer } from '../hooks/useBuffer' import { useFilamentContext } from '../hooks/useFilamentContext' import { useWorkletEffect } from '../hooks/useWorkletEffect' @@ -24,13 +25,15 @@ export type EnvironmentalLightProps = { */ export function EnvironmentalLight({ source, intensity = 25_000, irradianceBands }: EnvironmentalLightProps) { const { engine } = useFilamentContext() - const lightBuffer = useBuffer({ source: source, releaseOnUnmount: false }) + const rawLightBuffer = useBuffer({ source: source, releaseOnUnmount: false }) + const lightBufferBoxed = rawLightBuffer == null ? undefined : NitroModules.box(rawLightBuffer) useWorkletEffect(() => { 'worklet' - if (lightBuffer == null) return - engine.setIndirectLight(lightBuffer, intensity, irradianceBands) + if (lightBufferBoxed == null) return + const lightBuffer = lightBufferBoxed.unbox() + engine.unbox().setIndirectLight(lightBuffer, intensity, irradianceBands) lightBuffer.release() }) diff --git a/package/src/react/FilamentScene.tsx b/package/src/react/FilamentScene.tsx index 8fd8c9d4..9c62a143 100644 --- a/package/src/react/FilamentScene.tsx +++ b/package/src/react/FilamentScene.tsx @@ -1,5 +1,5 @@ import { PropsWithChildren, useMemo } from 'react' -import { FilamentProxy, FilamentWorkletContext } from '../native/FilamentProxy' +import { FilamentProxyBoxed, FilamentWorkletContext, NitroBoxed } from '../native/FilamentProxy' import { EngineProps, useEngine } from '../hooks/useEngine' import { useDisposableResource } from '../hooks/useDisposableResource' import { useWorklet } from 'react-native-worklets-core' @@ -7,6 +7,7 @@ import React from 'react' import { Configurator, RendererConfigProps, ViewConfigProps } from './Configurator' import { FilamentContext, FilamentContextType } from '../hooks/useFilamentContext' import { RenderCallbackContext } from './RenderCallbackContext' +import { NitroModules } from 'react-native-nitro-modules' export type FilamentProviderProps = PropsWithChildren< Omit & @@ -50,20 +51,47 @@ export function FilamentScene({ children, fallback, config, backend, frameRateOp const engine = useEngine({ config, backend, context: FilamentWorkletContext }) // Create all Filament APIs using the engine - const transformManager = useDisposableResource(() => Promise.resolve(engine?.createTransformManager()), [engine]) - const renderableManager = useDisposableResource(() => Promise.resolve(engine?.createRenderableManager()), [engine]) - const scene = useDisposableResource(() => Promise.resolve(engine?.getScene()), [engine]) - const lightManager = useDisposableResource(() => Promise.resolve(engine?.createLightManager()), [engine]) - const view = useDisposableResource(() => Promise.resolve(engine?.getView()), [engine]) - const camera = useDisposableResource(() => Promise.resolve(engine?.getCamera()), [engine]) - const renderer = useDisposableResource(() => Promise.resolve(engine?.createRenderer()), [engine]) - const nameComponentManager = useDisposableResource(() => Promise.resolve(engine?.createNameComponentManager()), [engine]) + const transformManager = useDisposableResource( + () => Promise.resolve(engine == null ? undefined : NitroModules.box(engine.unbox().createTransformManager())), + [engine] + ) + const renderableManager = useDisposableResource( + () => Promise.resolve(engine == null ? undefined : NitroModules.box(engine.unbox().createRenderableManager())), + [engine] + ) + const scene = useDisposableResource( + () => Promise.resolve(engine == null ? undefined : NitroModules.box(engine.unbox().getScene())), + [engine] + ) + const lightManager = useDisposableResource( + () => Promise.resolve(engine == null ? undefined : NitroModules.box(engine.unbox().createLightManager())), + [engine] + ) + const view = useDisposableResource( + () => Promise.resolve(engine == null ? undefined : NitroModules.box(engine.unbox().getView())), + [engine] + ) + const camera = useDisposableResource( + () => Promise.resolve(engine == null ? undefined : NitroModules.box(engine.unbox().getCamera())), + [engine] + ) + const renderer = useDisposableResource( + () => Promise.resolve(engine == null ? undefined : NitroModules.box(engine.unbox().createRenderer())), + [engine] + ) + const nameComponentManager = useDisposableResource( + () => Promise.resolve(engine == null ? undefined : NitroModules.box(engine?.unbox().createNameComponentManager())), + [engine] + ) // Create a choreographer for this context tree const choreographer = useDisposableResource( useWorklet(FilamentWorkletContext, () => { 'worklet' - return FilamentProxy.createChoreographer() + const filamentProxy = FilamentProxyBoxed.unbox() + const newChoreographer = filamentProxy.createChoreographer() + const nitro = NitroBoxed.unbox() + return nitro.box(newChoreographer) }) ) diff --git a/package/src/react/FilamentView.tsx b/package/src/react/FilamentView.tsx index 84afe747..d2a85ad4 100644 --- a/package/src/react/FilamentView.tsx +++ b/package/src/react/FilamentView.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { FilamentProxy } from '../native/FilamentProxy' +import { FilamentProxy, NitroBoxed } from '../native/FilamentProxy' import FilamentNativeView, { type FilamentViewNativeType, type NativeProps } from '../native/specs/FilamentViewNativeComponent' import { reportWorkletError, wrapWithErrorHandler } from '../ErrorUtils' import { FilamentContext } from '../hooks/useFilamentContext' @@ -10,6 +10,7 @@ import { findNodeHandle, GestureResponderEvent } from 'react-native' import { Worklets } from 'react-native-worklets-core' import { getLogger } from '../utilities/logger/Logger' import { getTouchHandlers } from './TouchHandlerContext' +import { NitroModules } from 'react-native-nitro-modules' const Logger = getLogger() @@ -69,7 +70,7 @@ export class FilamentView extends React.PureComponent { private updateTransparentRendering = (enable: boolean) => { const { renderer } = this.getContext() - renderer.setClearContent(enable) + renderer.unbox().setClearContent(enable) } private latestToken = 0 @@ -83,17 +84,20 @@ export class FilamentView extends React.PureComponent { // Adding a new render callback listener is an async operation Logger.debug('Setting render callback') - const listener = await workletContext.runAsync( + const boxedSwapChain = NitroModules.box(swapChain) + const boxedListener = await workletContext.runAsync( wrapWithErrorHandler(() => { 'worklet' // We need to create the function we pass to addFrameCallbackListener on the worklet thread, so that the // underlying JSI function is owned by that thread. Only then can we call it on the worklet thread when // the choreographer is calling its listeners. - return choreographer.addFrameCallbackListener((frameInfo) => { + const unboxedChoreographer = choreographer.unbox() + const listener = unboxedChoreographer.addFrameCallbackListener((frameInfo) => { 'worklet' - if (!swapChain.isValid) { + const unboxedSwapChain = boxedSwapChain.unbox() + if (!unboxedSwapChain.isValid) { // TODO: Supposedly fixed in https://github.com/margelo/react-native-filament/pull/210, remove this once proven reportWorkletError( new Error( @@ -106,16 +110,22 @@ export class FilamentView extends React.PureComponent { try { callback(frameInfo) - if (renderer.beginFrame(swapChain, frameInfo.timestamp)) { - renderer.render(view) - renderer.endFrame() + const unboxedRenderer = renderer.unbox() + if (unboxedRenderer.beginFrame(unboxedSwapChain, frameInfo.timestamp)) { + unboxedRenderer.render(view.unbox()) + unboxedRenderer.endFrame() } } catch (error) { reportWorkletError(error) } }) + + const nitro = NitroBoxed.unbox() + const newBoxedListener = nitro.box(listener) + return newBoxedListener }) ) + const listener = boxedListener.unbox() // It can happen that after the listener was set the surface got destroyed already: if (!this.isComponentMounted || !this.isSurfaceAlive.value) { @@ -136,7 +146,7 @@ export class FilamentView extends React.PureComponent { // Calling this here ensures that only after the latest successful call for attaching a listener, the choreographer is started. Logger.debug('Starting choreographer') - choreographer.start() + choreographer.unbox().start() } private getContext = () => { @@ -172,7 +182,7 @@ export class FilamentView extends React.PureComponent { cleanupResources() { Logger.debug('Cleaning up resources') const { choreographer } = this.getContext() - choreographer.stop() + choreographer.unbox().stop() this.renderCallbackListener?.remove() this.isSurfaceAlive.value = false @@ -208,7 +218,7 @@ export class FilamentView extends React.PureComponent { Logger.debug('Found FilamentView!') // Link the view with the choreographer. // When the view gets destroyed, the choreographer will be stopped. - this.view.setChoreographer(context.choreographer) + this.view.setChoreographer(context.choreographer.unbox()) if (this.ref.current == null) { throw new Error('Ref is not set!') @@ -224,7 +234,7 @@ export class FilamentView extends React.PureComponent { }, filamentDispatcher) // Link the surface with the engine: Logger.debug('Setting surface provider') - context.engine.setSurfaceProvider(surfaceProvider) + context.engine.unbox().setSurfaceProvider(surfaceProvider) // Its possible that the surface is already created, then our callback wouldn't be called // (we still keep the callback as on android a surface can be destroyed and recreated, while the view stays alive) if (surfaceProvider.getSurface() != null) { @@ -242,6 +252,7 @@ export class FilamentView extends React.PureComponent { // Create a swap chain … const enableTransparentRendering = this.props.enableTransparentRendering ?? true Logger.debug('Creating swap chain') + const boxedSurfaceProvider = NitroModules.box(surfaceProvider) const swapChain = await workletContext.runAsync(() => { 'worklet' @@ -250,8 +261,13 @@ export class FilamentView extends React.PureComponent { } try { - return engine.createSwapChainForSurface(surfaceProvider, enableTransparentRendering) + const unboxedSurfaceProvider = boxedSurfaceProvider.unbox() + const unboxedEngine = engine.unbox() + const newSwapChain = unboxedEngine.createSwapChainForSurface(unboxedSurfaceProvider, enableTransparentRendering) + const nitro = NitroBoxed.unbox() + return nitro.box(newSwapChain) } catch (error) { + console.log('Error while creating swap chain:', error) // Report this error as none-fatal. We only throw in createSwapChainForSurface if the surface is already released. // There is the chance of a race condition where the surface is destroyed but our JS onDestroy listener hasn't been called yet. reportWorkletError(error, false) @@ -264,11 +280,11 @@ export class FilamentView extends React.PureComponent { Logger.info('🚧 Swap chain is null, surface was already destroyed while we tried to create a swapchain from it.') return } - this.swapChain = swapChain + this.swapChain = swapChain.unbox() // Apply the swapchain to the engine … - Logger.debug('Setting swap chain') - engine.setSwapChain(this.swapChain) + Logger.debug('Setting swap chain', this.swapChain) + engine.unbox().setSwapChain(this.swapChain) // Set the render callback in the choreographer: const { renderCallback } = this.props @@ -291,7 +307,7 @@ export class FilamentView extends React.PureComponent { public pause = (): void => { Logger.info('Pausing rendering') const { choreographer } = this.getContext() - choreographer.stop() + choreographer.unbox().stop() } /** @@ -301,7 +317,7 @@ export class FilamentView extends React.PureComponent { public resume = (): void => { Logger.info('Resuming rendering') const { choreographer } = this.getContext() - choreographer.start() + choreographer.unbox().start() } private onTouchStart = (event: GestureResponderEvent) => { diff --git a/package/src/react/Light.tsx b/package/src/react/Light.tsx index bab18886..5981872d 100644 --- a/package/src/react/Light.tsx +++ b/package/src/react/Light.tsx @@ -7,8 +7,8 @@ export type LightProps = UseLightEntityProps export function Light(config: LightProps) { const { lightManager, scene } = useFilamentContext() - const lightEntity = useLightEntity(lightManager, config) - useEntityInScene(scene, lightEntity) + const lightEntity = useLightEntity(lightManager.unbox(), config) + useEntityInScene(scene.unbox(), lightEntity) return null } diff --git a/package/src/react/Model.tsx b/package/src/react/Model.tsx index d89414ca..6ea9f7fa 100644 --- a/package/src/react/Model.tsx +++ b/package/src/react/Model.tsx @@ -47,6 +47,7 @@ export function Model({ source, ...restProps }: ModelProps) { const [_transformProps, modelProps] = extractTransformationProps(restProps) const model = useModel(source, modelProps) + console.log('model', model) return } @@ -73,7 +74,7 @@ export function ModelRenderer({ model, onPress, children, ...restProps }: ModelR const renderableEntities = useMemo(() => { // The entities are only needed for touch events, so only load them if a touch handler is provided if (asset == null || onPress == null) return [] - return asset.getRenderableEntities() + return asset.unbox().getRenderableEntities() }, [asset, onPress]) const { view, renderableManager } = useFilamentContext() @@ -82,7 +83,7 @@ export function ModelRenderer({ model, onPress, children, ...restProps }: ModelR if (renderableEntities == null || onPress == null) return const { locationX, locationY } = event.nativeEvent - const entity = await view.pickEntity(locationX, locationY) + const entity = await view.unbox().pickEntity(locationX, locationY) Logger.debug('Picked entity', entity, 'at', locationX, locationY) if (entity == null) { Logger.debug('No entity was picked') @@ -120,7 +121,7 @@ export function ModelRenderer({ model, onPress, children, ...restProps }: ModelR if (asset === undefined) { return null } - return asset.getAssetInstances() + return asset.unbox().getAssetInstances() }, [asset]) useConfigureAssetShadow({ diff --git a/package/src/react/ModelInstance.tsx b/package/src/react/ModelInstance.tsx index 93fe2de0..2a5ec8b3 100644 --- a/package/src/react/ModelInstance.tsx +++ b/package/src/react/ModelInstance.tsx @@ -4,6 +4,7 @@ import { FilamentInstance } from '../types' import { ParentInstancesContext, useParentInstancesContext } from './ParentInstancesContext' import { TransformationProps } from '../types/TransformProps' import { useApplyTransformations } from '../hooks/internal/useApplyTransformations' +import { NitroModules } from 'react-native-nitro-modules' export type ModelInstanceProps = PropsWithChildren< TransformationProps & { @@ -43,10 +44,10 @@ type Props = PropsWithChildren< function ModelInstanceImpl({ instance, children, ...transformProps }: Props) { const rootEntity = useMemo(() => { - return instance.getRoot() + return NitroModules.box(instance.getRoot()) }, [instance]) const boundingBox = useMemo(() => { - return instance.getBoundingBox() + return NitroModules.box(instance.getBoundingBox()) }, [instance]) const instances = useMemo(() => [instance], [instance]) diff --git a/package/src/test/RunTests.ts b/package/src/test/RunTests.ts deleted file mode 100644 index 967cd93d..00000000 --- a/package/src/test/RunTests.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { testHybridObject } from './TestHybridObject' - -async function wrapTest(name: string, func: () => void | Promise): Promise { - console.log(`-------- BEGIN TEST: ${name}`) - try { - await func() - console.log(`-------- END TEST: ${name}`) - } catch (e) { - console.error(`-------- ERROR IN TEST ${name}:`, e) - } -} - -// TODO: Write proper tests for that that actually run on a device/simulator. -// I want to make sure Hybrid Objects and Choreographers all work fine and test those in the CI. -export function runTests() { - const TEST_HYBRID_OBJECTS = true - if (__DEV__ && TEST_HYBRID_OBJECTS) { - const run = async () => { - await wrapTest('HybridObject', testHybridObject) - } - run() - } -} diff --git a/package/src/test/TestHybridObject.ts b/package/src/test/TestHybridObject.ts deleted file mode 100644 index c753b5da..00000000 --- a/package/src/test/TestHybridObject.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { FilamentProxy } from '../native/FilamentProxy' - -const FIBONACCI_LIMIT = 70 - -export async function testHybridObject(): Promise { - // 1. Creation - console.log('Creating HybridObject...') - const hybridObject = FilamentProxy.createTestObject() - console.log('Created HybridObject!') - - // 2. Logging the entire thing as JSON - console.log(hybridObject) - - // 3. Int Getter & Setter - console.log(`Int: ${hybridObject.int}`) - hybridObject.int = 6723 - console.log(`New Int: ${hybridObject.int}`) - - // 4. Enum Getter & Setter - console.log(`Enum: ${hybridObject.enum}`) - hybridObject.enum = 'second' - console.log(`New Enum: ${hybridObject.enum}`) - - // 5. String Getter & Setter - console.log(`String: ${hybridObject.string}`) - hybridObject.string = 'new string value!' - console.log(`New String: ${hybridObject.string}`) - - // 6. Nullable String Getter & Setter - console.log(`Nullable String: ${hybridObject.nullableString}`) - hybridObject.nullableString = 'now its not null!' - console.log(`New Nullable String: ${hybridObject.nullableString}`) - - // 7. Testing multiple arguments and maps - const result = hybridObject.multipleArguments(5, true, 'hahah!') - console.log(`multipleArguments() -> ${JSON.stringify(result)}`) - - // 8. Testing callbacks - hybridObject.sayHelloCallback(() => 'hello from JS!') - const getter = hybridObject.getIntGetter() - console.log(`Int getter: ${getter()}`) - - // 9. Create a new one - const newObject = hybridObject.createNewHybridObject() - console.log(`Created new hybrid object!`, newObject) - - // 10. Test Promises - console.log(`Calculating Fibonacci up to number ${FIBONACCI_LIMIT}...`) - const start = performance.now() - const fibonacci = await hybridObject.calculateFibonacciAsync(FIBONACCI_LIMIT) - const end = performance.now() - console.log(`Calculated Fibonacci for ${FIBONACCI_LIMIT} = ${fibonacci} (took ${(end - start).toFixed(0)}ms)`) -} - -// @ts-expect-error -// eslint-disable-next-line @typescript-eslint/no-unused-vars -function fib(count: number): BigInt { - let prev = 0n - let current = 1n - for (let i = 2; i <= count; ++i) { - let next = prev + current - prev = current - current = next - } - return current -} diff --git a/package/src/types/Boxes.ts b/package/src/types/Boxes.ts index bb8d96e0..2c5431d0 100644 --- a/package/src/types/Boxes.ts +++ b/package/src/types/Boxes.ts @@ -1,6 +1,7 @@ +import { HybridObject } from 'react-native-nitro-modules' import { Float3 } from './Math' -export interface BaseBox { +export interface BaseBox extends HybridObject<{ android: 'c++'; ios: 'c++' }> { /** * The center of the box. */ diff --git a/package/src/types/Entity.ts b/package/src/types/Entity.ts index cd93f2b6..ddb49e04 100644 --- a/package/src/types/Entity.ts +++ b/package/src/types/Entity.ts @@ -1,8 +1,10 @@ +import { HybridObject } from 'react-native-nitro-modules' + /** * Everything inside the scene is an entity. * Entities are managed by the EntityManager. */ -export interface Entity { +export interface Entity extends HybridObject<{ ios: 'c++'; android: 'c++' }> { id: number } diff --git a/package/src/types/Listener.ts b/package/src/types/Listener.ts index 739e1292..b11b9980 100644 --- a/package/src/types/Listener.ts +++ b/package/src/types/Listener.ts @@ -1,3 +1,5 @@ -export interface Listener { +import { HybridObject } from 'react-native-nitro-modules' + +export interface Listener extends HybridObject<{ ios: 'c++'; android: 'c++' }> { remove(): void } diff --git a/package/src/types/PointerHolder.ts b/package/src/types/PointerHolder.ts index 8d86df9e..ce65136e 100644 --- a/package/src/types/PointerHolder.ts +++ b/package/src/types/PointerHolder.ts @@ -1,3 +1,5 @@ +import { HybridObject } from 'react-native-nitro-modules' + /** * Represents a holder of any native pointer. * @@ -6,7 +8,7 @@ * * Instances of {@linkcode PointerHolder} are always backed by a `jsi::HostObject`. */ -export interface PointerHolder { +export interface PointerHolder extends HybridObject<{ ios: 'c++'; android: 'c++' }> { /** * Manually release this reference to the native pointer. * This will ensure that JS will no longer hold a strong reference, diff --git a/package/src/utilities/getAssetFromModel.ts b/package/src/utilities/getAssetFromModel.ts index d23bda9b..37c20533 100644 --- a/package/src/utilities/getAssetFromModel.ts +++ b/package/src/utilities/getAssetFromModel.ts @@ -1,9 +1,10 @@ +import { BoxedHybridObject } from 'react-native-nitro-modules/lib/BoxedHybridObject' import { FilamentModel } from '../hooks/useModel' import { FilamentAsset } from '../types' /** * Helper function to unwrap model.asset from a filament model. */ -export function getAssetFromModel(model: FilamentModel): FilamentAsset | undefined { +export function getAssetFromModel(model: FilamentModel): BoxedHybridObject | undefined { return model.state === 'loaded' ? model.asset : undefined } diff --git a/package/yarn.lock b/package/yarn.lock index a6dcb4e7..ebf9a403 100644 --- a/package/yarn.lock +++ b/package/yarn.lock @@ -6679,12 +6679,12 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-prettier@npm:^5.0.1": - version: 5.1.3 - resolution: "eslint-plugin-prettier@npm:5.1.3" +"eslint-plugin-prettier@npm:^5.2.1": + version: 5.2.1 + resolution: "eslint-plugin-prettier@npm:5.2.1" dependencies: prettier-linter-helpers: ^1.0.0 - synckit: ^0.8.6 + synckit: ^0.9.1 peerDependencies: "@types/eslint": ">=8.0.0" eslint: ">=8.0.0" @@ -6695,7 +6695,7 @@ __metadata: optional: true eslint-config-prettier: optional: true - checksum: eb2a7d46a1887e1b93788ee8f8eb81e0b6b2a6f5a66a62bc6f375b033fc4e7ca16448da99380be800042786e76cf5c0df9c87a51a2c9b960ed47acbd7c0b9381 + checksum: 812f4d1596dcd3a55963212dfbd818a4b38f880741aac75f6869aa740dc5d934060674d3b85d10ff9fec424defa61967dbdef26b8a893a92c9b51880264ed0d9 languageName: node linkType: hard @@ -11112,17 +11112,19 @@ __metadata: "@types/react": 18.3.11 eslint: ^8.51.0 eslint-config-prettier: ^9.0.0 - eslint-plugin-prettier: ^5.0.1 + eslint-plugin-prettier: ^5.2.1 prettier: ^3.0.3 react: 18.3.1 react-native: 0.75.4 react-native-builder-bob: ^0.20.0 + react-native-nitro-modules: ^0.11.0 react-native-worklets-core: ^2.0.0-beta.4 release-it: ^15.0.0 typescript: ^5.2.2 peerDependencies: react: "*" react-native: "*" + react-native-nitro-modules: ">=0.11.0" react-native-worklets-core: ">=1.3.2" languageName: unknown linkType: soft @@ -12581,13 +12583,13 @@ __metadata: languageName: node linkType: hard -"synckit@npm:^0.8.6": - version: 0.8.8 - resolution: "synckit@npm:0.8.8" +"synckit@npm:^0.9.1": + version: 0.9.2 + resolution: "synckit@npm:0.9.2" dependencies: "@pkgr/core": ^0.1.0 tslib: ^2.6.2 - checksum: 9ed5d33abb785f5f24e2531efd53b2782ca77abf7912f734d170134552b99001915531be5a50297aa45c5701b5c9041e8762e6cd7a38e41e2461c1e7fccdedf8 + checksum: 3a30e828efbdcf3b50fccab4da6e90ea7ca24d8c5c2ad3ffe98e07d7c492df121e0f75227c6e510f96f976aae76f1fa4710cb7b1d69db881caf66ef9de89360e languageName: node linkType: hard @@ -12742,13 +12744,20 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.1, tslib@npm:^2.1.0, tslib@npm:^2.6.2": +"tslib@npm:^2.0.1, tslib@npm:^2.1.0": version: 2.6.2 resolution: "tslib@npm:2.6.2" checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad languageName: node linkType: hard +"tslib@npm:^2.6.2": + version: 2.7.0 + resolution: "tslib@npm:2.7.0" + checksum: 1606d5c89f88d466889def78653f3aab0f88692e80bb2066d090ca6112ae250ec1cfa9dbfaab0d17b60da15a4186e8ec4d893801c67896b277c17374e36e1d28 + languageName: node + linkType: hard + "tsutils@npm:^3.21.0": version: 3.21.0 resolution: "tsutils@npm:3.21.0"