@babylonjs/react-native 0.4.0-alpha.8 → 0.64.0-alpha.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/BabylonModule.d.ts +2 -0
  2. package/{BabylonModule.ts → BabylonModule.js} +9 -12
  3. package/BabylonModule.js.map +1 -0
  4. package/EngineHook.d.ts +2 -0
  5. package/EngineHook.js +178 -0
  6. package/EngineHook.js.map +1 -0
  7. package/EngineView.d.ts +13 -0
  8. package/EngineView.js +94 -0
  9. package/EngineView.js.map +1 -0
  10. package/FontFace.d.ts +12 -0
  11. package/FontFace.js +35 -0
  12. package/FontFace.js.map +1 -0
  13. package/NativeCapture.d.ts +14 -0
  14. package/NativeCapture.js +14 -0
  15. package/NativeCapture.js.map +1 -0
  16. package/NativeEngineHook.d.ts +4 -0
  17. package/NativeEngineHook.js +43 -0
  18. package/NativeEngineHook.js.map +1 -0
  19. package/NativeEngineView.d.ts +10 -0
  20. package/NativeEngineView.js +3 -0
  21. package/NativeEngineView.js.map +1 -0
  22. package/README.md +8 -8
  23. package/ReactNativeEngine.d.ts +7 -0
  24. package/ReactNativeEngine.js +33 -0
  25. package/ReactNativeEngine.js.map +1 -0
  26. package/VersionValidation.d.ts +1 -0
  27. package/{VersionValidation.ts → VersionValidation.js} +3 -3
  28. package/VersionValidation.js.map +1 -0
  29. package/android/build.gradle +13 -1
  30. package/android/include/IXrContextARCore.h +10 -0
  31. package/android/src/main/java/com/babylonreactnative/BabylonModule.java +6 -4
  32. package/android/src/main/java/com/babylonreactnative/BabylonNativeInterop.java +20 -6
  33. package/android/src/main/java/com/babylonreactnative/EngineView.java +151 -8
  34. package/android/src/main/java/com/babylonreactnative/EngineViewManager.java +8 -0
  35. package/android/src/main/jniLibs/arm64-v8a/libBabylonNative.so +0 -0
  36. package/android/src/main/jniLibs/arm64-v8a/libturbomodulejsijni.so +0 -0
  37. package/android/src/main/jniLibs/armeabi-v7a/libBabylonNative.so +0 -0
  38. package/android/src/main/jniLibs/armeabi-v7a/libturbomodulejsijni.so +0 -0
  39. package/android/src/main/jniLibs/x86/libBabylonNative.so +0 -0
  40. package/android/src/main/jniLibs/x86/libturbomodulejsijni.so +0 -0
  41. package/{index.ts → index.d.ts} +1 -0
  42. package/index.js +5 -0
  43. package/index.js.map +1 -0
  44. package/ios/BabylonModule.mm +7 -0
  45. package/ios/BabylonNativeInterop.h +4 -0
  46. package/ios/BabylonNativeInterop.mm +37 -14
  47. package/ios/EngineViewManager.mm +41 -3
  48. package/ios/ReactNativeBabylon.xcodeproj/project.pbxproj +7532 -9825
  49. package/ios/include/IXrContextARKit.h +10 -0
  50. package/ios/libs/libBabylonNative.a +0 -0
  51. package/ios/libs/libCanvas.a +0 -0
  52. package/ios/libs/libGenericCodeGen.a +0 -0
  53. package/ios/libs/libGraphics.a +0 -0
  54. package/ios/libs/libJsRuntime.a +0 -0
  55. package/ios/libs/libMachineIndependent.a +0 -0
  56. package/ios/libs/libNativeCapture.a +0 -0
  57. package/ios/libs/libNativeEngine.a +0 -0
  58. package/ios/libs/libNativeInput.a +0 -0
  59. package/ios/libs/libNativeOptimizations.a +0 -0
  60. package/ios/libs/libNativeTracing.a +0 -0
  61. package/ios/libs/libNativeXr.a +0 -0
  62. package/ios/libs/libOGLCompiler.a +0 -0
  63. package/ios/libs/libOSDependent.a +0 -0
  64. package/ios/libs/libSPIRV.a +0 -0
  65. package/ios/libs/libUrlLib.a +0 -0
  66. package/ios/libs/libWindow.a +0 -0
  67. package/ios/libs/libXMLHttpRequest.a +0 -0
  68. package/ios/libs/libastc-codec.a +0 -0
  69. package/ios/libs/libastc.a +0 -0
  70. package/ios/libs/libbgfx.a +0 -0
  71. package/ios/libs/libbimg.a +0 -0
  72. package/ios/libs/libbx.a +0 -0
  73. package/ios/libs/libglslang.a +0 -0
  74. package/ios/libs/libnapi.a +0 -0
  75. package/ios/libs/libspirv-cross-core.a +0 -0
  76. package/ios/libs/libspirv-cross-glsl.a +0 -0
  77. package/ios/libs/libspirv-cross-msl.a +0 -0
  78. package/ios/libs/libtinyexr.a +0 -0
  79. package/ios/libs/libxr.a +0 -0
  80. package/package.json +53 -52
  81. package/shared/BabylonNative.h +30 -3
  82. package/shared/XrAnchorHelper.h +229 -0
  83. package/shared/XrContextHelper.h +179 -0
  84. package/EngineHook.ts +0 -103
  85. package/EngineView.tsx +0 -156
  86. package/NativeCapture.ts +0 -30
  87. package/ReactNativeEngine.ts +0 -69
  88. package/ios/libs/libspirv-cross-hlsl.a +0 -0
@@ -19,6 +19,10 @@ def safeExtGet(prop, fallback) {
19
19
  rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
20
20
  }
21
21
 
22
+ def reactProperties = new Properties()
23
+ file("$projectDir/../../../react-native/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) }
24
+ def REACT_VERSION = reactProperties.getProperty("VERSION_NAME").split("\\.")[1].toInteger()
25
+
22
26
  apply plugin: 'com.android.library'
23
27
  apply plugin: 'maven'
24
28
 
@@ -59,6 +63,14 @@ android {
59
63
  }
60
64
  }
61
65
 
66
+ // The full/real version of libturbomodulejsijni.so will be built and included in apps using React Native 0.64 or newer,
67
+ // so exclude Babylon React Native's minimal version of these libs in this case.
68
+ if (REACT_VERSION >= 64) {
69
+ android.packagingOptions.excludes += 'lib/armeabi-v7a/libturbomodulejsijni.so'
70
+ android.packagingOptions.excludes += 'lib/arm64-v8a/libturbomodulejsijni.so'
71
+ android.packagingOptions.excludes += 'lib/x86/libturbomodulejsijni.so'
72
+ }
73
+
62
74
  repositories {
63
75
  // ref: https://www.baeldung.com/maven-local-repository
64
76
  mavenLocal()
@@ -77,7 +89,7 @@ repositories {
77
89
  dependencies {
78
90
  //noinspection GradleDynamicVersion
79
91
  implementation 'com.facebook.react:react-native:+' // From node_modules
80
- implementation 'com.google.ar:core:1.14.0'
92
+ implementation 'com.google.ar:core:1.22.0'
81
93
  }
82
94
 
83
95
  def configureReactNativePom(def pom) {
@@ -0,0 +1,10 @@
1
+ #pragma once
2
+
3
+ #include <arcore_c_api.h>
4
+
5
+ typedef struct IXrContextARCore
6
+ {
7
+ virtual bool IsInitialized() const = 0;
8
+ virtual ArSession* XrSession() const = 0;
9
+ virtual ArFrame* XrFrame() const = 0;
10
+ } IXrContextARCore;
@@ -27,9 +27,11 @@ public final class BabylonModule extends ReactContextBaseJavaModule {
27
27
  });
28
28
  }
29
29
 
30
- // NOTE: This happens during dev mode reload, when the JS engine is being shutdown and restarted.
31
- @Override
32
- public void onCatalystInstanceDestroy() {
33
- this.getReactApplicationContext().runOnJSQueueThread(BabylonNativeInterop::deinitialize);
30
+ @ReactMethod
31
+ public void resetView(Promise promise) {
32
+ this.getReactApplicationContext().runOnUiQueueThread(() -> {
33
+ BabylonNativeInterop.resetView();
34
+ promise.resolve(null);
35
+ });
34
36
  }
35
37
  }
@@ -19,11 +19,14 @@ public final class BabylonNativeInterop {
19
19
  }
20
20
 
21
21
  public static native void initialize(Context context, long jsiRuntimeRef, CallInvokerHolder jsCallInvokerHolder);
22
- public static native void deinitialize();
23
22
  public static native void setCurrentActivity(Activity activity);
24
23
  public static native void pause();
25
24
  public static native void resume();
26
25
  public static native void updateView(Surface surface);
26
+ public static native void renderView();
27
+ public static native void resetView();
28
+ public static native void updateXRView(Surface surface);
29
+ public static native boolean isXRActive();
27
30
  public static native void setTouchButtonState(int pointerId, boolean isDown, int x, int y);
28
31
  public static native void setTouchPosition(int pointerId, int x, int y);
29
32
  }
@@ -54,7 +57,6 @@ public final class BabylonNativeInterop {
54
57
 
55
58
  @Override
56
59
  public void onHostDestroy() {
57
- BabylonNative.deinitialize();
58
60
  }
59
61
  };
60
62
 
@@ -79,14 +81,26 @@ public final class BabylonNativeInterop {
79
81
  reactContext.addActivityEventListener(BabylonNativeInterop.activityEventListener);
80
82
  }
81
83
 
82
- public static void deinitialize() {
83
- BabylonNative.deinitialize();
84
- }
85
-
86
84
  public static void updateView(Surface surface) {
87
85
  BabylonNative.updateView(surface);
88
86
  }
89
87
 
88
+ public static void renderView() {
89
+ BabylonNative.renderView();
90
+ }
91
+
92
+ public static void resetView() {
93
+ BabylonNative.resetView();
94
+ }
95
+
96
+ public static void updateXRView(Surface surface) {
97
+ BabylonNative.updateXRView(surface);
98
+ }
99
+
100
+ public static boolean isXRActive() {
101
+ return BabylonNative.isXRActive();
102
+ }
103
+
90
104
  public static void reportMotionEvent(MotionEvent motionEvent) {
91
105
  int maskedAction = motionEvent.getActionMasked();
92
106
  boolean isPointerDown = maskedAction == MotionEvent.ACTION_DOWN || maskedAction == MotionEvent.ACTION_POINTER_DOWN;
@@ -2,15 +2,21 @@ package com.babylonreactnative;
2
2
 
3
3
  import android.annotation.TargetApi;
4
4
  import android.graphics.Bitmap;
5
+ import android.graphics.SurfaceTexture;
5
6
  import android.os.Build;
6
7
  import android.os.Handler;
7
8
  import android.os.HandlerThread;
8
9
  import android.util.Base64;
9
10
  import android.view.MotionEvent;
10
11
  import android.view.PixelCopy;
12
+ import android.view.Surface;
11
13
  import android.view.SurfaceHolder;
12
14
  import android.view.SurfaceView;
15
+ import android.view.TextureView;
13
16
  import android.view.View;
17
+ import android.widget.FrameLayout;
18
+
19
+ import androidx.annotation.NonNull;
14
20
 
15
21
  import com.facebook.react.bridge.ReactContext;
16
22
  import com.facebook.react.uimanager.UIManagerModule;
@@ -18,19 +24,83 @@ import com.facebook.react.uimanager.events.EventDispatcher;
18
24
 
19
25
  import java.io.ByteArrayOutputStream;
20
26
 
21
- public final class EngineView extends SurfaceView implements SurfaceHolder.Callback, View.OnTouchListener {
27
+ public final class EngineView extends FrameLayout implements SurfaceHolder.Callback, TextureView.SurfaceTextureListener, View.OnTouchListener {
28
+ private static final FrameLayout.LayoutParams childViewLayoutParams = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
29
+ private TextureView transparentTextureView;
30
+ private Surface transparentSurface = null;
31
+ private SurfaceView opaqueSurfaceView = null;
32
+ private SurfaceView xrSurfaceView;
22
33
  private final EventDispatcher reactEventDispatcher;
34
+ private Runnable renderRunnable;
23
35
 
24
36
  public EngineView(ReactContext reactContext) {
25
37
  super(reactContext);
26
- this.getHolder().addCallback(this);
38
+
39
+ this.setIsTransparent(false);
40
+
41
+ this.xrSurfaceView = new SurfaceView(reactContext);
42
+ this.xrSurfaceView.setLayoutParams(childViewLayoutParams);
43
+ this.xrSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
44
+ @Override
45
+ public void surfaceCreated(SurfaceHolder holder) {
46
+ // surfaceChanged is also called when the surface is created, so just do all the handling there
47
+ }
48
+
49
+ @Override
50
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
51
+ BabylonNativeInterop.updateXRView(holder.getSurface());
52
+ }
53
+
54
+ @Override
55
+ public void surfaceDestroyed(SurfaceHolder holder) {
56
+ BabylonNativeInterop.updateXRView(null);
57
+ }
58
+ });
59
+ this.xrSurfaceView.setVisibility(View.INVISIBLE);
60
+ this.addView(this.xrSurfaceView);
61
+
27
62
  this.setOnTouchListener(this);
63
+
28
64
  this.reactEventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
29
65
  }
30
66
 
67
+ // ------------------------------------
68
+ // TextureView related
69
+
70
+ public void setIsTransparent(Boolean isTransparent) {
71
+ if (isTransparent) {
72
+ if (this.opaqueSurfaceView != null) {
73
+ this.opaqueSurfaceView.setVisibility(View.GONE);
74
+ this.opaqueSurfaceView = null;
75
+ }
76
+ if (this.transparentTextureView == null) {
77
+ this.transparentTextureView = new TextureView(this.getContext());
78
+ this.transparentTextureView.setLayoutParams(EngineView.childViewLayoutParams);
79
+ this.transparentTextureView.setSurfaceTextureListener(this);
80
+ this.transparentTextureView.setOpaque(false);
81
+ this.addView(this.transparentTextureView);
82
+ }
83
+ } else {
84
+ if (this.transparentTextureView != null) {
85
+ this.transparentTextureView.setVisibility(View.GONE);
86
+ this.transparentTextureView = null;
87
+ }
88
+ if (this.opaqueSurfaceView == null) {
89
+ this.opaqueSurfaceView = new SurfaceView(this.getContext());
90
+ this.opaqueSurfaceView.setLayoutParams(EngineView.childViewLayoutParams);
91
+ this.opaqueSurfaceView.getHolder().addCallback(this);
92
+ this.addView(this.opaqueSurfaceView);
93
+ }
94
+ }
95
+ // xr view needs to be on top of views that might be created after it.
96
+ if (this.xrSurfaceView != null) {
97
+ this.xrSurfaceView.bringToFront();
98
+ }
99
+ }
100
+
31
101
  @Override
32
102
  public void surfaceCreated(SurfaceHolder surfaceHolder) {
33
- // surfaceChanged is also called when the surface is created, so just do all the handling there
103
+ this.startRenderLoop();
34
104
  }
35
105
 
36
106
  @Override
@@ -40,8 +110,47 @@ public final class EngineView extends SurfaceView implements SurfaceHolder.Callb
40
110
 
41
111
  @Override
42
112
  public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
113
+ this.removeCallbacks(this.renderRunnable);
114
+ this.renderRunnable = null;
115
+ }
116
+
117
+ @Override
118
+ public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surfaceTexture, int i, int i1) {
119
+ this.startRenderLoop();
120
+ this.acquireNewTransparentSurface(surfaceTexture);
121
+ BabylonNativeInterop.updateView(this.transparentSurface);
43
122
  }
44
123
 
124
+ @Override
125
+ public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surfaceTexture, int i, int i1) {
126
+ this.acquireNewTransparentSurface(surfaceTexture);
127
+ BabylonNativeInterop.updateView(this.transparentSurface);
128
+ }
129
+
130
+ @Override
131
+ public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surfaceTexture) {
132
+ this.stopRenderLoop();
133
+ this.transparentSurface.release();
134
+ this.transparentSurface = null;
135
+ return false;
136
+ }
137
+
138
+ @Override
139
+ public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surfaceTexture) {
140
+ this.acquireNewTransparentSurface(surfaceTexture);
141
+ BabylonNativeInterop.updateView(this.transparentSurface);
142
+ }
143
+
144
+ private void acquireNewTransparentSurface(@NonNull SurfaceTexture surfaceTexture) {
145
+ if (this.transparentSurface != null) {
146
+ this.transparentSurface.release();
147
+ }
148
+ this.transparentSurface = new Surface(surfaceTexture);
149
+ }
150
+
151
+ // ------------------------------------
152
+ // Common
153
+
45
154
  @Override
46
155
  public boolean onTouch(View view, MotionEvent motionEvent) {
47
156
  BabylonNativeInterop.reportMotionEvent(motionEvent);
@@ -67,21 +176,55 @@ public final class EngineView extends SurfaceView implements SurfaceHolder.Callb
67
176
  helperThread.start();
68
177
  final Handler helperThreadHandler = new Handler(helperThread.getLooper());
69
178
 
70
- // Request the pixel copy.
71
- PixelCopy.request(this, bitmap, (copyResult) -> {
179
+ Surface sourceSurface = this.transparentSurface;
180
+ if (BabylonNativeInterop.isXRActive()) {
181
+ sourceSurface = this.xrSurfaceView.getHolder().getSurface();
182
+ } else if (this.opaqueSurfaceView != null) {
183
+ sourceSurface = this.opaqueSurfaceView.getHolder().getSurface();
184
+ }
185
+ PixelCopy.request(sourceSurface, bitmap, getOnPixelCopyFinishedListener(bitmap, helperThread), helperThreadHandler);
186
+ }
187
+
188
+ // ---------------------------------------------------------------------------------------------
189
+ // Returns the listener for the PixelCopy.request function call
190
+ @NonNull
191
+ private PixelCopy.OnPixelCopyFinishedListener getOnPixelCopyFinishedListener(Bitmap bitmap, HandlerThread helperThread) {
192
+ return (copyResult) -> {
72
193
  // If the pixel copy was a success then convert the image to a base 64 encoded jpeg and fire the event.
73
194
  String encoded = "";
74
195
  if (copyResult == PixelCopy.SUCCESS) {
75
196
  ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
76
- bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayStream);
197
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 80, byteArrayStream);
77
198
  byte[] byteArray = byteArrayStream.toByteArray();
78
199
  bitmap.recycle();
79
200
  encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
80
201
  }
81
-
82
202
  SnapshotDataReturnedEvent snapshotEvent = new SnapshotDataReturnedEvent(this.getId(), encoded);
83
203
  reactEventDispatcher.dispatchEvent(snapshotEvent);
84
204
  helperThread.quitSafely();
85
- }, helperThreadHandler);
205
+ };
206
+ }
207
+
208
+ private void startRenderLoop() {
209
+ if(this.renderRunnable == null){
210
+ this.renderRunnable = new Runnable() {
211
+ @Override
212
+ public void run() {
213
+ if (BabylonNativeInterop.isXRActive()) {
214
+ EngineView.this.xrSurfaceView.setVisibility(View.VISIBLE);
215
+ } else {
216
+ EngineView.this.xrSurfaceView.setVisibility(View.INVISIBLE);
217
+ }
218
+ BabylonNativeInterop.renderView();
219
+ EngineView.this.postOnAnimation(this);
220
+ }
221
+ };
222
+ this.postOnAnimation(this.renderRunnable);
223
+ }
224
+ }
225
+
226
+ private void stopRenderLoop() {
227
+ this.removeCallbacks(this.renderRunnable);
228
+ this.renderRunnable = null;
86
229
  }
87
230
  }
@@ -1,5 +1,7 @@
1
1
  package com.babylonreactnative;
2
2
 
3
+ import android.widget.FrameLayout;
4
+
3
5
  import androidx.annotation.NonNull;
4
6
  import androidx.annotation.Nullable;
5
7
 
@@ -7,6 +9,7 @@ import com.facebook.react.bridge.ReadableArray;
7
9
  import com.facebook.react.common.MapBuilder;
8
10
  import com.facebook.react.uimanager.SimpleViewManager;
9
11
  import com.facebook.react.uimanager.ThemedReactContext;
12
+ import com.facebook.react.uimanager.annotations.ReactProp;
10
13
 
11
14
  import java.util.Map;
12
15
 
@@ -20,6 +23,11 @@ public final class EngineViewManager extends SimpleViewManager<EngineView> {
20
23
  return "EngineView";
21
24
  }
22
25
 
26
+ @ReactProp(name = "isTransparent")
27
+ public void setIsTransparent(EngineView view, Boolean isTransparent) {
28
+ view.setIsTransparent(isTransparent);
29
+ }
30
+
23
31
  @NonNull
24
32
  @Override
25
33
  protected EngineView createViewInstance(@NonNull ThemedReactContext reactContext) {
@@ -1,3 +1,4 @@
1
1
  export * from './EngineView';
2
2
  export * from './EngineHook';
3
3
  export * from './NativeCapture';
4
+ export * from './FontFace';
package/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from './EngineView';
2
+ export * from './EngineHook';
3
+ export * from './NativeCapture';
4
+ export * from './FontFace';
5
+ //# sourceMappingURL=index.js.map
package/index.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../Modules/@babylonjs/react-native/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC"}
@@ -25,4 +25,11 @@ RCT_EXPORT_METHOD(initialize:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseR
25
25
  });
26
26
  }
27
27
 
28
+ RCT_EXPORT_METHOD(resetView:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
29
+ dispatch_async(dispatch_get_main_queue(), ^{
30
+ [BabylonNativeInterop resetView];
31
+ resolve([NSNull null]);
32
+ });
33
+ }
34
+
28
35
  @end
@@ -6,5 +6,9 @@
6
6
  @interface BabylonNativeInterop : NSObject
7
7
  + (void)initialize:(RCTBridge*)bridge;
8
8
  + (void)updateView:(MTKView*)mtkView;
9
+ + (void)renderView;
10
+ + (void)resetView;
11
+ + (void)updateXRView:(MTKView*)mtkView;
12
+ + (bool)isXRActive;
9
13
  + (void)reportTouchEvent:(MTKView*)mtkView touches:(NSSet<UITouch*>*)touches event:(UIEvent*)event;
10
14
  @end
@@ -24,7 +24,7 @@ namespace {
24
24
 
25
25
  @implementation BabylonNativeInterop
26
26
 
27
- static NSMutableArray* activeTouches;
27
+ static NSMutableArray* activeTouches = [NSMutableArray new];
28
28
 
29
29
  + (void)initialize:(RCTBridge*)bridge {
30
30
  auto jsCallInvoker{ bridge.jsCallInvoker };
@@ -36,7 +36,7 @@ static NSMutableArray* activeTouches;
36
36
  });
37
37
  } };
38
38
 
39
- Babylon::Initialize(*GetJSIRuntime(bridge), std::move(jsDispatcher));
39
+ BabylonNative::Initialize(*GetJSIRuntime(bridge), std::move(jsDispatcher));
40
40
 
41
41
  [[NSNotificationCenter defaultCenter] removeObserver:self
42
42
  name:RCTBridgeWillInvalidateModulesNotification
@@ -51,49 +51,72 @@ static NSMutableArray* activeTouches;
51
51
  // NOTE: This happens during dev mode reload, when the JS engine is being shutdown and restarted.
52
52
  + (void)onBridgeWillInvalidate:(NSNotification*)notification
53
53
  {
54
- Babylon::Deinitialize();
54
+ BabylonNative::Deinitialize();
55
55
  }
56
56
 
57
57
  + (void)updateView:(MTKView*)mtkView {
58
- const int width = static_cast<int>(mtkView.bounds.size.width * UIScreen.mainScreen.scale);
59
- const int height = static_cast<int>(mtkView.bounds.size.height * UIScreen.mainScreen.scale);
58
+ const CGFloat scale = mtkView.contentScaleFactor;
59
+ const int width = static_cast<int>(mtkView.bounds.size.width * scale);
60
+ const int height = static_cast<int>(mtkView.bounds.size.height * scale);
60
61
  if (width != 0 && height != 0) {
61
- Babylon::UpdateView((__bridge void*)mtkView, width, height);
62
+ BabylonNative::UpdateView(mtkView, width, height);
62
63
  }
63
64
  }
64
65
 
66
+ + (void)renderView {
67
+ BabylonNative::RenderView();
68
+ }
69
+
70
+ + (void)resetView {
71
+ BabylonNative::ResetView();
72
+ }
73
+
74
+ + (void)updateXRView:(MTKView*)mtkView {
75
+ BabylonNative::UpdateXRView(mtkView);
76
+ }
77
+
78
+ + (bool)isXRActive {
79
+ return BabylonNative::IsXRActive();
80
+ }
81
+
65
82
  + (void)reportTouchEvent:(MTKView*)mtkView touches:(NSSet<UITouch*>*)touches event:(UIEvent*)event {
66
83
  for (UITouch* touch in touches) {
67
84
  if (touch.view == mtkView) {
68
- const CGFloat scale = UIScreen.mainScreen.scale;
85
+ const CGFloat scale = mtkView.contentScaleFactor;
69
86
  const CGPoint pointerPosition = [touch locationInView:mtkView];
70
87
  const uint32_t x = static_cast<uint32_t>(pointerPosition.x * scale);
71
88
  const uint32_t y = static_cast<uint32_t>(pointerPosition.y * scale);
72
89
 
73
90
  switch (touch.phase) {
74
91
  case UITouchPhaseBegan: {
92
+ // The activeTouches array only grows, it does not shrink (to keep indices constant since they are used as pointer ids),
93
+ // so look for an unused (null) array element and reuse it if found. Otherwise, add a new entry to the array.
75
94
  NSUInteger pointerId = [activeTouches indexOfObject:[NSNull null]];
76
- if (pointerId == NSNotFound) {
95
+ if (pointerId != NSNotFound) {
96
+ [activeTouches replaceObjectAtIndex:pointerId withObject:touch];
97
+ } else {
77
98
  pointerId = [activeTouches count];
78
99
  [activeTouches addObject:touch];
79
- } else {
80
- [activeTouches replaceObjectAtIndex:pointerId withObject:touch];
81
100
  }
82
- Babylon::SetTouchButtonState(static_cast<uint32_t>(pointerId), true, x, y);
101
+ BabylonNative::SetTouchButtonState(static_cast<uint32_t>(pointerId), true, x, y);
83
102
  break;
84
103
  }
85
104
 
86
105
  case UITouchPhaseMoved: {
87
106
  NSUInteger pointerId = [activeTouches indexOfObject:touch];
88
- Babylon::SetTouchPosition(static_cast<uint32_t>(pointerId), x, y);
107
+ if (pointerId != NSNotFound) {
108
+ BabylonNative::SetTouchPosition(static_cast<uint32_t>(pointerId), x, y);
109
+ }
89
110
  break;
90
111
  }
91
112
 
92
113
  case UITouchPhaseEnded:
93
114
  case UITouchPhaseCancelled: {
94
115
  NSUInteger pointerId = [activeTouches indexOfObject:touch];
95
- [activeTouches replaceObjectAtIndex:pointerId withObject:[NSNull null]];
96
- Babylon::SetTouchButtonState(static_cast<uint32_t>(pointerId), false, x, y);
116
+ if (pointerId != NSNotFound) {
117
+ [activeTouches replaceObjectAtIndex:pointerId withObject:[NSNull null]];
118
+ BabylonNative::SetTouchButtonState(static_cast<uint32_t>(pointerId), false, x, y);
119
+ }
97
120
  break;
98
121
  }
99
122
 
@@ -11,17 +11,19 @@
11
11
  @interface EngineView : MTKView
12
12
 
13
13
  @property (nonatomic, copy) RCTDirectEventBlock onSnapshotDataReturned;
14
+ @property (nonatomic, assign) BOOL isTransparent;
15
+
14
16
 
15
17
  @end
16
18
 
17
19
  @implementation EngineView {
18
- RCTBridge* bridge;
20
+ const RCTBridge* bridge;
21
+ MTKView* xrView;
19
22
  }
20
23
 
21
24
  - (instancetype)init:(RCTBridge*)_bridge {
22
25
  if (self = [super initWithFrame:CGRectZero device:MTLCreateSystemDefaultDevice()]) {
23
26
  bridge = _bridge;
24
-
25
27
  super.translatesAutoresizingMaskIntoConstraints = false;
26
28
  super.colorPixelFormat = MTLPixelFormatBGRA8Unorm_sRGB;
27
29
  super.depthStencilPixelFormat = MTLPixelFormatDepth32Float;
@@ -29,6 +31,16 @@
29
31
  return self;
30
32
  }
31
33
 
34
+ - (void)setIsTransparentFlag:(NSNumber*)isTransparentFlag {
35
+ BOOL isTransparent = [isTransparentFlag intValue] == 1;
36
+ if(isTransparent){
37
+ [self setOpaque:NO];
38
+ } else {
39
+ [self setOpaque:YES];
40
+ }
41
+ self.isTransparent = isTransparent;
42
+ }
43
+
32
44
  - (void)setBounds:(CGRect)bounds {
33
45
  [super setBounds:bounds];
34
46
  [BabylonNativeInterop updateView:self];
@@ -50,6 +62,28 @@
50
62
  [BabylonNativeInterop reportTouchEvent:self touches:touches event:event];
51
63
  }
52
64
 
65
+ - (void)drawRect:(CGRect)rect {
66
+ if ([BabylonNativeInterop isXRActive]) {
67
+ if (!xrView) {
68
+ xrView = [[MTKView alloc] initWithFrame:self.bounds device:self.device];
69
+ xrView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
70
+ xrView.userInteractionEnabled = false;
71
+ [self addSubview:xrView];
72
+ [BabylonNativeInterop updateXRView:xrView];
73
+ }
74
+ } else if (xrView) {
75
+ [BabylonNativeInterop updateXRView:nil];
76
+ [xrView removeFromSuperview];
77
+ xrView = nil;
78
+ }
79
+
80
+ [BabylonNativeInterop renderView];
81
+ }
82
+
83
+ -(void)dealloc {
84
+ [BabylonNativeInterop updateXRView:nil];
85
+ }
86
+
53
87
  - (void)takeSnapshot {
54
88
  // We must take the screenshot on the main thread otherwise we might fail to get a valid handle on the view's image.
55
89
  dispatch_async(dispatch_get_main_queue(), ^{
@@ -62,7 +96,7 @@
62
96
  // Grab the image from the graphics context, and convert into a base64 encoded JPG.
63
97
  UIImage* capturedImage = UIGraphicsGetImageFromCurrentImageContext();
64
98
  UIGraphicsEndImageContext();
65
- NSData* jpgData = UIImageJPEGRepresentation(capturedImage, 1.0f);
99
+ NSData* jpgData = UIImageJPEGRepresentation(capturedImage, .8f);
66
100
  NSString* encodedData = [jpgData base64EncodedStringWithOptions:0];
67
101
 
68
102
  // Fire the onSnapshotDataReturned event if hooked up.
@@ -80,6 +114,10 @@
80
114
 
81
115
  @implementation EngineViewManager
82
116
 
117
+ RCT_CUSTOM_VIEW_PROPERTY(isTransparent, NSNumber*, EngineView){
118
+ [view setIsTransparentFlag:json];
119
+ }
120
+
83
121
  RCT_EXPORT_MODULE(EngineViewManager)
84
122
 
85
123
  RCT_EXPORT_VIEW_PROPERTY(onSnapshotDataReturned, RCTDirectEventBlock)