diff --git a/Apps/BRNPlayground/android/gradle.properties b/Apps/BRNPlayground/android/gradle.properties index c65407b6c..35d9292e6 100644 --- a/Apps/BRNPlayground/android/gradle.properties +++ b/Apps/BRNPlayground/android/gradle.properties @@ -40,7 +40,8 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 # to write custom TurboModules/Fabric components OR use libraries that # are providing them. # Note that this is incompatible with web debugging. -#newArchEnabled=true +newArchEnabled=false +hermesEnabled=true # Uncomment the line below if building react-native from source #ANDROID_NDK_VERSION=26.1.10909125 diff --git a/Apps/BRNPlayground/android/gradle/wrapper/gradle-wrapper.properties b/Apps/BRNPlayground/android/gradle/wrapper/gradle-wrapper.properties index 1af9e0930..250caf51e 100644 --- a/Apps/BRNPlayground/android/gradle/wrapper/gradle-wrapper.properties +++ b/Apps/BRNPlayground/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ +#Mon Sep 23 14:46:34 CEST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/Apps/BRNPlayground/ios/Podfile b/Apps/BRNPlayground/ios/Podfile index 81d178afd..a6794291d 100644 --- a/Apps/BRNPlayground/ios/Podfile +++ b/Apps/BRNPlayground/ios/Podfile @@ -4,8 +4,6 @@ require_relative '../node_modules/react-native-permissions/scripts/setup' workspace 'BRNPlayground.xcworkspace' options = { - :bridgeless_enabled => true, - :fabric_enabled => true, :hermes_enabled => true, } diff --git a/Modules/@babylonjs/react-native-iosandroid/android/build.gradle b/Modules/@babylonjs/react-native-iosandroid/android/build.gradle index 5fb2e30df..c24e9a24d 100644 --- a/Modules/@babylonjs/react-native-iosandroid/android/build.gradle +++ b/Modules/@babylonjs/react-native-iosandroid/android/build.gradle @@ -20,8 +20,16 @@ def safeExtGet(prop, fallback) { rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback } +def isNewArchitectureEnabled() { + return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true" +} + apply plugin: 'com.android.library' +if (isNewArchitectureEnabled()) { + apply plugin: 'com.facebook.react' +} + def rootBuildDir = "${rootProject.rootDir}/../../../../Build/Android" def extractedLibDir = "${rootBuildDir}/lib" @@ -77,6 +85,8 @@ android { defaultConfig { minSdkVersion safeExtGet('minSdkVersion', DEFAULT_MIN_SDK_VERSION) targetSdkVersion safeExtGet('targetSdkVersion', DEFAULT_TARGET_SDK_VERSION) + buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() + versionCode 1 versionName "1.0" externalNativeBuild { @@ -140,6 +150,19 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + sourceSets { + main { + if (isNewArchitectureEnabled()) { + java.srcDirs += [ + "src/fabric/java", + "generated/jni", + "generated/java", + ] + } else { + java.srcDirs += ["src/paper/java"] + } + } + } } repositories { @@ -157,6 +180,14 @@ dependencies { extractLibs 'com.facebook.fbjni:fbjni:0.3.0', 'com.google.ar:core:1.22.0' } +if (isNewArchitectureEnabled()) { + react { + jsRootDir = file("../../react-native/spec") + libraryName = "BabylonModuleSpec" + codegenJavaPackageName = "com.babylonreactnative" + } +} + def configureReactNativePom(def pom) { def packageJson = new groovy.json.JsonSlurper().parseText(file('../package.json').text) diff --git a/Modules/@babylonjs/react-native-iosandroid/android/src/fabric/java/com/babylonreactnative/BabylonModule.java b/Modules/@babylonjs/react-native-iosandroid/android/src/fabric/java/com/babylonreactnative/BabylonModule.java new file mode 100644 index 000000000..622cfcb6b --- /dev/null +++ b/Modules/@babylonjs/react-native-iosandroid/android/src/fabric/java/com/babylonreactnative/BabylonModule.java @@ -0,0 +1,38 @@ +package com.babylonreactnative; + +import androidx.annotation.NonNull; + +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.module.annotations.ReactModule; + +@ReactModule(name = BabylonModule.NAME) +public final class BabylonModule extends NativeBabylonModuleSpec { + static final String NAME = "EngineViewNativeComponent"; + + BabylonModule(ReactApplicationContext reactContext) { + super(reactContext); + } + + @NonNull + @Override + public String getName() { + return BabylonModule.NAME; + } + + @Override + public void initialize(Promise promise) { +// this.getReactApplicationContext().runOnJSQueueThread(() -> { +// BabylonNativeInterop.initialize(this.getReactApplicationContext()); +// promise.resolve(null); +// }); + } + + @Override + public void resetView(Promise promise) { +// this.getReactApplicationContext().runOnUiQueueThread(() -> { +// BabylonNativeInterop.resetView(); +// promise.resolve(null); +// }); + } +} diff --git a/Modules/@babylonjs/react-native-iosandroid/android/src/fabric/java/com/babylonreactnative/EngineViewManager.java b/Modules/@babylonjs/react-native-iosandroid/android/src/fabric/java/com/babylonreactnative/EngineViewManager.java new file mode 100644 index 000000000..754e7c2ff --- /dev/null +++ b/Modules/@babylonjs/react-native-iosandroid/android/src/fabric/java/com/babylonreactnative/EngineViewManager.java @@ -0,0 +1,68 @@ +package com.babylonreactnative; + +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.module.annotations.ReactModule; +import com.facebook.react.uimanager.SimpleViewManager; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewManagerDelegate; +import com.facebook.react.viewmanagers.EngineViewNativeComponentManagerDelegate; +import com.facebook.react.viewmanagers.EngineViewNativeComponentManagerInterface; + +@ReactModule(name = EngineViewManager.NAME) +public final class EngineViewManager extends SimpleViewManager implements EngineViewNativeComponentManagerInterface { + private final ViewManagerDelegate mDelegate; + + static final String NAME = "EngineViewNativeComponent"; + @NonNull + @Override + public String getName() { + return EngineViewManager.NAME; + } + + public EngineViewManager() { + mDelegate = new EngineViewNativeComponentManagerDelegate<>(this); + } + + @Nullable + @Override + protected ViewManagerDelegate getDelegate() { + return mDelegate; + } + + @NonNull + @Override + protected EngineView createViewInstance(@NonNull ThemedReactContext reactContext) { + return new EngineView(reactContext); + } + +// @Override +// public void onDropViewInstance(@NonNull EngineView view) { +// super.onDropViewInstance(view); +// // TODO: Native view specific cleanup +// } + + @Override + public void setIsTransparent(EngineView view, boolean value) { + view.setIsTransparent(value); + } + + @Override + public void setAntiAliasing(EngineView view, int value) { + view.setAntiAliasing(value); + } + + @Override + public void setAndroidView(EngineView view, @Nullable String value) { + view.setAndroidView(value); + } + + @Override + public void takeSnapshot(EngineView view) { + view.takeSnapshot(); + } +} diff --git a/Modules/@babylonjs/react-native-iosandroid/android/src/main/java/com/babylonreactnative/BabylonNativeInterop.java b/Modules/@babylonjs/react-native-iosandroid/android/src/main/java/com/babylonreactnative/BabylonNativeInterop.java index 5e5dddcf1..90db5ccf7 100644 --- a/Modules/@babylonjs/react-native-iosandroid/android/src/main/java/com/babylonreactnative/BabylonNativeInterop.java +++ b/Modules/@babylonjs/react-native-iosandroid/android/src/main/java/com/babylonreactnative/BabylonNativeInterop.java @@ -9,6 +9,7 @@ import com.facebook.react.bridge.ActivityEventListener; import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactContext; +import com.facebook.react.bridge.RuntimeExecutor; import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder; public final class BabylonNativeInterop { diff --git a/Modules/@babylonjs/react-native-iosandroid/android/src/main/java/com/babylonreactnative/BabylonPackage.java b/Modules/@babylonjs/react-native-iosandroid/android/src/main/java/com/babylonreactnative/BabylonPackage.java index d5d533949..2c3d93cee 100644 --- a/Modules/@babylonjs/react-native-iosandroid/android/src/main/java/com/babylonreactnative/BabylonPackage.java +++ b/Modules/@babylonjs/react-native-iosandroid/android/src/main/java/com/babylonreactnative/BabylonPackage.java @@ -1,19 +1,30 @@ package com.babylonreactnative; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import com.facebook.react.BaseReactPackage; import com.facebook.react.ReactPackage; +import com.facebook.react.TurboReactPackage; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.module.model.ReactModuleInfo; +import com.facebook.react.module.model.ReactModuleInfoProvider; import com.facebook.react.uimanager.ViewManager; public class BabylonPackage implements ReactPackage { + @NonNull @Override public List createNativeModules(ReactApplicationContext reactContext) { return Arrays.asList(new BabylonModule(reactContext)); } + @NonNull @Override public List createViewManagers(ReactApplicationContext reactContext) { return Arrays.asList(new EngineViewManager()); diff --git a/Modules/@babylonjs/react-native-iosandroid/android/src/main/java/com/babylonreactnative/BabylonModule.java b/Modules/@babylonjs/react-native-iosandroid/android/src/paper/java/com/babylonreactnative/BabylonModule.java similarity index 100% rename from Modules/@babylonjs/react-native-iosandroid/android/src/main/java/com/babylonreactnative/BabylonModule.java rename to Modules/@babylonjs/react-native-iosandroid/android/src/paper/java/com/babylonreactnative/BabylonModule.java diff --git a/Modules/@babylonjs/react-native-iosandroid/android/src/main/java/com/babylonreactnative/EngineViewManager.java b/Modules/@babylonjs/react-native-iosandroid/android/src/paper/java/com/babylonreactnative/EngineViewManager.java similarity index 98% rename from Modules/@babylonjs/react-native-iosandroid/android/src/main/java/com/babylonreactnative/EngineViewManager.java rename to Modules/@babylonjs/react-native-iosandroid/android/src/paper/java/com/babylonreactnative/EngineViewManager.java index 15af178af..96bb70245 100644 --- a/Modules/@babylonjs/react-native-iosandroid/android/src/main/java/com/babylonreactnative/EngineViewManager.java +++ b/Modules/@babylonjs/react-native-iosandroid/android/src/paper/java/com/babylonreactnative/EngineViewManager.java @@ -20,7 +20,7 @@ public final class EngineViewManager extends SimpleViewManager { @NonNull @Override public String getName() { - return "EngineView"; + return "EngineViewNativeComponent"; } @ReactProp(name = "isTransparent") diff --git a/Modules/@babylonjs/react-native/EngineView.tsx b/Modules/@babylonjs/react-native/EngineView.tsx index 15956f4b3..b0c8820a7 100644 --- a/Modules/@babylonjs/react-native/EngineView.tsx +++ b/Modules/@babylonjs/react-native/EngineView.tsx @@ -1,15 +1,14 @@ import React, { Component, FunctionComponent, SyntheticEvent, useCallback, useEffect, useState, useRef, useMemo } from 'react'; -import { ViewProps, View, Text, findNodeHandle, UIManager } from 'react-native'; +import { View, Text, findNodeHandle, UIManager } from 'react-native'; import { Camera, SceneInstrumentation } from '@babylonjs/core'; import { ReactNativeEngine } from './ReactNativeEngine'; import { useModuleInitializer, useRenderLoop } from './NativeEngineHook'; import { NativeEngineViewProps, NativeEngineView } from './NativeEngineView'; -export interface EngineViewProps extends ViewProps { +export interface EngineViewProps extends NativeEngineViewProps { camera?: Camera; displayFrameRate?: boolean; isTransparent?: boolean; - androidView?: "TextureView" | "SurfaceView" | "SurfaceViewZTopMost" | "SurfaceViewZMediaOverlay"; antiAliasing?: 0 | 1 | 2 | 4 | 8 | 16; onInitialized?: (view: EngineViewCallbacks) => void; } diff --git a/Modules/@babylonjs/react-native/NativeEngineView.tsx b/Modules/@babylonjs/react-native/NativeEngineView.tsx index e2efb9c85..e7816f3f7 100644 --- a/Modules/@babylonjs/react-native/NativeEngineView.tsx +++ b/Modules/@babylonjs/react-native/NativeEngineView.tsx @@ -1,3 +1,4 @@ -import EngineView from './spec/EngineViewNativeComponent' +import EngineView, {NativeProps} from './spec/EngineViewNativeComponent' export { EngineView as NativeEngineView }; +export type { NativeProps as NativeEngineViewProps }; diff --git a/Modules/@babylonjs/react-native/spec/EngineViewNativeComponent.ts b/Modules/@babylonjs/react-native/spec/EngineViewNativeComponent.ts index 471a32a3f..491ba0ecf 100644 --- a/Modules/@babylonjs/react-native/spec/EngineViewNativeComponent.ts +++ b/Modules/@babylonjs/react-native/spec/EngineViewNativeComponent.ts @@ -12,6 +12,8 @@ export interface NativeProps extends ViewProps { isTransparent?: WithDefault; antiAliasing?: Int32; onSnapshotDataReturned?: DirectEventHandler; + // Android only + androidView?: string; } type EngineViewViewType = HostComponent; diff --git a/Modules/@babylonjs/react-native/spec/NativeBabylonModule.ts b/Modules/@babylonjs/react-native/spec/NativeBabylonModule.ts index 14fd906af..17b51b4fc 100644 --- a/Modules/@babylonjs/react-native/spec/NativeBabylonModule.ts +++ b/Modules/@babylonjs/react-native/spec/NativeBabylonModule.ts @@ -6,4 +6,4 @@ export interface Spec extends TurboModule { resetView(): Promise; } -export default TurboModuleRegistry.get("BabylonModule"); +export default TurboModuleRegistry.getEnforcing("BabylonModule");