@sceneview-sdk/react-native 3.6.1 → 4.1.1

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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # react-native-sceneview
1
+ # @sceneview-sdk/react-native
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/react-native-sceneview.svg)](https://www.npmjs.com/package/react-native-sceneview)
3
+ [![npm version](https://img.shields.io/npm/v/@sceneview-sdk/react-native.svg)](https://www.npmjs.com/package/@sceneview-sdk/react-native)
4
4
  [![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
5
5
  [![GitHub](https://img.shields.io/badge/GitHub-sceneview%2Fsceneview-black)](https://github.com/sceneview/sceneview)
6
6
 
@@ -19,8 +19,24 @@ React Native bindings for [SceneView](https://sceneview.github.io) — 3D and AR
19
19
 
20
20
  ## Installation
21
21
 
22
+ > **Status note (May 2026):** the npm registry currently has
23
+ > `@sceneview-sdk/react-native@3.6.1` as `latest`. The 4.0.x line of this
24
+ > bridge — including the type-safe `unlit` prop and the v4 SceneView
25
+ > bindings — has not yet been published to npm. Tracked in
26
+ > [#924](https://github.com/sceneview/sceneview/issues/924) and
27
+ > [#962](https://github.com/sceneview/sceneview/issues/962) (publish-rn
28
+ > GitHub Actions job lands automatically on the next `v4.0.x` tag).
29
+ > To pin against the latest source today, prefer the GitHub-package
30
+ > snippet at the bottom of this section.
31
+
32
+ ```sh
33
+ npm install @sceneview-sdk/react-native
34
+ ```
35
+
36
+ …or to ride main directly until the 4.0.x publish lands:
37
+
22
38
  ```sh
23
- npm install react-native-sceneview
39
+ npm install github:sceneview/sceneview#v4.0.9 --save # path includes react-native/react-native-sceneview/
24
40
  ```
25
41
 
26
42
  ### iOS
@@ -31,7 +47,7 @@ cd ios && pod install
31
47
 
32
48
  Requires iOS 17+ and Xcode 15+. The host app must also add `SceneViewSwift` via Swift Package Manager:
33
49
  - URL: `https://github.com/sceneview/SceneViewSwift`
34
- - Version: `3.6.0`
50
+ - Version: `4.0.0`
35
51
 
36
52
  ### Android
37
53
 
@@ -51,7 +67,7 @@ android {
51
67
  ### 3D Scene
52
68
 
53
69
  ```tsx
54
- import { SceneView } from 'react-native-sceneview';
70
+ import { SceneView } from '@sceneview-sdk/react-native';
55
71
 
56
72
  <SceneView
57
73
  style={{ flex: 1 }}
@@ -64,7 +80,7 @@ import { SceneView } from 'react-native-sceneview';
64
80
  ### AR Scene
65
81
 
66
82
  ```tsx
67
- import { ARSceneView } from 'react-native-sceneview';
83
+ import { ARSceneView } from '@sceneview-sdk/react-native';
68
84
 
69
85
  <ARSceneView
70
86
  style={{ flex: 1 }}
@@ -114,11 +130,11 @@ React Native JS
114
130
  v
115
131
  requireNativeComponent('RNSceneView' / 'RNARSceneView')
116
132
  |
117
- +---> Android: ViewManager -> ComposeView -> Scene { } / ARScene { }
118
- | (Filament, SceneView SDK 3.6.0)
133
+ +---> Android: ViewManager -> ComposeView -> SceneView { } / ARSceneView { }
134
+ | (Filament, SceneView SDK 4.0.0)
119
135
  |
120
136
  +---> iOS: RCTViewManager -> UIHostingController -> SceneView / ARSceneView
121
- (RealityKit, SceneViewSwift 3.6.0)
137
+ (RealityKit, SceneViewSwift 4.0.0)
122
138
  ```
123
139
 
124
140
  Props are mapped from the React Native bridge to native view parameters on each platform.
@@ -2,15 +2,22 @@ package io.github.sceneview.reactnative
2
2
 
3
3
  import android.widget.FrameLayout
4
4
  import androidx.compose.foundation.layout.fillMaxSize
5
+ import androidx.compose.runtime.DisposableEffect
5
6
  import androidx.compose.runtime.mutableStateListOf
6
7
  import androidx.compose.runtime.mutableStateOf
8
+ import androidx.compose.runtime.remember
7
9
  import androidx.compose.ui.Modifier
8
10
  import androidx.compose.ui.platform.ComposeView
9
11
  import com.facebook.react.bridge.ReadableArray
12
+ import com.facebook.react.bridge.ReadableType
10
13
  import com.facebook.react.uimanager.SimpleViewManager
11
14
  import com.facebook.react.uimanager.ThemedReactContext
12
15
  import com.facebook.react.uimanager.annotations.ReactProp
16
+ import com.google.android.filament.LightManager
17
+ import io.github.sceneview.SurfaceType
18
+ import io.github.sceneview.math.Size
13
19
  import io.github.sceneview.rememberEngine
20
+ import io.github.sceneview.rememberMaterialLoader
14
21
  import io.github.sceneview.rememberModelInstance
15
22
  import io.github.sceneview.rememberModelLoader
16
23
 
@@ -19,6 +26,8 @@ import io.github.sceneview.rememberModelLoader
19
26
  */
20
27
  class ARSceneViewState {
21
28
  val modelPaths = mutableStateListOf<ModelNodeData>()
29
+ val geometryNodes = mutableStateListOf<GeometryNodeData>()
30
+ val lightNodes = mutableStateListOf<LightNodeData>()
22
31
  val planeDetection = mutableStateOf(true)
23
32
  val depthOcclusion = mutableStateOf(false)
24
33
  val instantPlacement = mutableStateOf(false)
@@ -26,7 +35,7 @@ class ARSceneViewState {
26
35
 
27
36
  /**
28
37
  * ViewManager that bridges React Native's `<RNARSceneView>` to the Jetpack Compose
29
- * `ARScene { }` composable from `io.github.sceneview.ar`.
38
+ * `ARSceneView { }` composable from `io.github.sceneview.ar`.
30
39
  *
31
40
  * State is stored per-instance via [FrameLayout.getTag] to support multiple
32
41
  * `<RNARSceneView>` components on the same screen.
@@ -48,11 +57,14 @@ class ARSceneViewManager : SimpleViewManager<FrameLayout>() {
48
57
  setContent {
49
58
  val engine = rememberEngine()
50
59
  val modelLoader = rememberModelLoader(engine)
60
+ val materialLoader = rememberMaterialLoader(engine)
51
61
 
52
- io.github.sceneview.ar.ARScene(
62
+ io.github.sceneview.ar.ARSceneView(
53
63
  modifier = Modifier.fillMaxSize(),
64
+ surfaceType = SurfaceType.TextureSurface,
54
65
  engine = engine,
55
66
  modelLoader = modelLoader,
67
+ materialLoader = materialLoader,
56
68
  planeRenderer = state.planeDetection.value,
57
69
  ) {
58
70
  state.modelPaths.forEach { model ->
@@ -62,9 +74,89 @@ class ARSceneViewManager : SimpleViewManager<FrameLayout>() {
62
74
  modelInstance = it,
63
75
  scaleToUnits = model.scale,
64
76
  autoAnimate = model.animate,
77
+ position = model.position,
78
+ rotation = model.rotation,
65
79
  )
66
80
  }
67
81
  }
82
+
83
+ state.geometryNodes.forEach { geom ->
84
+ val colorInt = geom.color?.let {
85
+ runCatching { android.graphics.Color.parseColor(it) }.getOrNull()
86
+ }
87
+ // Cache material instance per (color, unlit) to avoid leaking on recomposition.
88
+ // Use varargs `keys` to skip the per-recomposition Pair allocation.
89
+ val mat = colorInt?.let { c ->
90
+ val instance = remember(c, geom.unlit) {
91
+ if (geom.unlit) materialLoader.createUnlitColorInstance(c)
92
+ else materialLoader.createColorInstance(c)
93
+ }
94
+ DisposableEffect(c, geom.unlit) {
95
+ onDispose {
96
+ materialLoader.destroyMaterialInstance(instance)
97
+ }
98
+ }
99
+ instance
100
+ }
101
+ when (geom.type) {
102
+ "cube", "box" -> CubeNode(
103
+ size = geom.size?.let { Size(it[0], it[1], it[2]) }
104
+ ?: Size(1f, 1f, 1f),
105
+ materialInstance = mat,
106
+ position = geom.position,
107
+ rotation = geom.rotation,
108
+ scale = geom.scale,
109
+ )
110
+ "sphere" -> SphereNode(
111
+ radius = geom.size?.let { it[0] / 2f } ?: 0.5f,
112
+ materialInstance = mat,
113
+ position = geom.position,
114
+ rotation = geom.rotation,
115
+ scale = geom.scale,
116
+ )
117
+ "cylinder" -> CylinderNode(
118
+ radius = geom.size?.let { it[0] / 2f } ?: 0.5f,
119
+ height = geom.size?.let { it[1] } ?: 1f,
120
+ materialInstance = mat,
121
+ position = geom.position,
122
+ rotation = geom.rotation,
123
+ scale = geom.scale,
124
+ )
125
+ "plane" -> PlaneNode(
126
+ size = geom.size?.let { Size(it[0], it[1]) }
127
+ ?: Size(1f, 1f),
128
+ materialInstance = mat,
129
+ position = geom.position,
130
+ rotation = geom.rotation,
131
+ scale = geom.scale,
132
+ )
133
+ }
134
+ }
135
+
136
+ state.lightNodes.forEach { light ->
137
+ val lightType = when (light.type) {
138
+ "directional" -> LightManager.Type.DIRECTIONAL
139
+ "point" -> LightManager.Type.POINT
140
+ "spot" -> LightManager.Type.SPOT
141
+ else -> LightManager.Type.DIRECTIONAL
142
+ }
143
+ LightNode(
144
+ type = lightType,
145
+ intensity = light.intensity,
146
+ direction = light.direction,
147
+ position = light.position,
148
+ apply = {
149
+ light.color?.let { hex ->
150
+ val c = runCatching { android.graphics.Color.parseColor(hex) }.getOrNull() ?: return@let
151
+ color(
152
+ android.graphics.Color.red(c) / 255f,
153
+ android.graphics.Color.green(c) / 255f,
154
+ android.graphics.Color.blue(c) / 255f,
155
+ )
156
+ }
157
+ },
158
+ )
159
+ }
68
160
  }
69
161
  }
70
162
  }
@@ -72,6 +164,12 @@ class ARSceneViewManager : SimpleViewManager<FrameLayout>() {
72
164
  return container
73
165
  }
74
166
 
167
+ override fun onDropViewInstance(view: FrameLayout) {
168
+ // Remove the ComposeView so its Composition is disposed, releasing Filament resources.
169
+ view.removeAllViews()
170
+ super.onDropViewInstance(view)
171
+ }
172
+
75
173
  @ReactProp(name = "environment")
76
174
  fun setEnvironment(view: FrameLayout, environment: String?) {
77
175
  // AR scenes use camera feed as background; environment HDR
@@ -103,7 +201,76 @@ class ARSceneViewManager : SimpleViewManager<FrameLayout>() {
103
201
  } else {
104
202
  true
105
203
  }
106
- state.modelPaths.add(ModelNodeData(src = src, scale = scale, animate = animate))
204
+ val position = readPosition(map, "position")
205
+ val rotation = readRotation(map, "rotation")
206
+ state.modelPaths.add(
207
+ ModelNodeData(
208
+ src = src,
209
+ scale = scale,
210
+ animate = animate,
211
+ position = position,
212
+ rotation = rotation,
213
+ )
214
+ )
215
+ }
216
+ }
217
+ }
218
+
219
+ @ReactProp(name = "geometryNodes")
220
+ fun setGeometryNodes(view: FrameLayout, nodes: ReadableArray?) {
221
+ val state = getState(view)
222
+ state.geometryNodes.clear()
223
+ nodes?.let { array ->
224
+ for (i in 0 until array.size()) {
225
+ val map = array.getMap(i) ?: continue
226
+ val type = map.getString("type") ?: continue
227
+ val size = readFloatArray3(map, "size")
228
+ val position = readPosition(map, "position")
229
+ val rotation = readRotation(map, "rotation")
230
+ val scale = readScale(map, "scale")
231
+ val color = if (map.hasKey("color")) map.getString("color") else null
232
+ // Type-safe `unlit` parsing — guards against JS sending `"true"` or `1`.
233
+ val unlit = map.hasKey("unlit") &&
234
+ map.getType("unlit") == ReadableType.Boolean &&
235
+ map.getBoolean("unlit")
236
+ state.geometryNodes.add(
237
+ GeometryNodeData(
238
+ type = type,
239
+ size = size,
240
+ position = position,
241
+ rotation = rotation,
242
+ scale = scale,
243
+ color = color,
244
+ unlit = unlit,
245
+ )
246
+ )
247
+ }
248
+ }
249
+ }
250
+
251
+ @ReactProp(name = "lightNodes")
252
+ fun setLightNodes(view: FrameLayout, nodes: ReadableArray?) {
253
+ val state = getState(view)
254
+ state.lightNodes.clear()
255
+ nodes?.let { array ->
256
+ for (i in 0 until array.size()) {
257
+ val map = array.getMap(i) ?: continue
258
+ val type = map.getString("type") ?: continue
259
+ val intensity = if (map.hasKey("intensity")) {
260
+ map.getDouble("intensity").toFloat()
261
+ } else null
262
+ val color = if (map.hasKey("color")) map.getString("color") else null
263
+ val position = readPosition(map, "position")
264
+ val direction = readDirection(map, "direction")
265
+ state.lightNodes.add(
266
+ LightNodeData(
267
+ type = type,
268
+ intensity = intensity,
269
+ color = color,
270
+ position = position,
271
+ direction = direction,
272
+ )
273
+ )
107
274
  }
108
275
  }
109
276
  }
@@ -2,20 +2,30 @@ package io.github.sceneview.reactnative
2
2
 
3
3
  import android.widget.FrameLayout
4
4
  import androidx.compose.foundation.layout.fillMaxSize
5
+ import androidx.compose.runtime.DisposableEffect
5
6
  import androidx.compose.runtime.mutableStateListOf
6
7
  import androidx.compose.runtime.mutableStateOf
8
+ import androidx.compose.runtime.remember
7
9
  import androidx.compose.ui.Modifier
8
10
  import androidx.compose.ui.platform.ComposeView
9
11
  import com.facebook.react.bridge.ReadableArray
12
+ import com.facebook.react.bridge.ReadableType
10
13
  import com.facebook.react.uimanager.SimpleViewManager
11
14
  import com.facebook.react.uimanager.ThemedReactContext
12
15
  import com.facebook.react.uimanager.annotations.ReactProp
13
- import io.github.sceneview.Scene
16
+ import com.google.android.filament.LightManager
17
+ import io.github.sceneview.SceneView
18
+ import io.github.sceneview.SurfaceType
19
+ import io.github.sceneview.math.Direction
14
20
  import io.github.sceneview.math.Position
21
+ import io.github.sceneview.math.Rotation
22
+ import io.github.sceneview.math.Scale
23
+ import io.github.sceneview.math.Size
15
24
  import io.github.sceneview.rememberCameraNode
16
25
  import io.github.sceneview.rememberEngine
17
26
  import io.github.sceneview.rememberEnvironment
18
27
  import io.github.sceneview.rememberEnvironmentLoader
28
+ import io.github.sceneview.rememberMaterialLoader
19
29
  import io.github.sceneview.rememberModelInstance
20
30
  import io.github.sceneview.rememberModelLoader
21
31
 
@@ -25,13 +35,15 @@ import io.github.sceneview.rememberModelLoader
25
35
  */
26
36
  class SceneViewState {
27
37
  val modelPaths = mutableStateListOf<ModelNodeData>()
38
+ val geometryNodes = mutableStateListOf<GeometryNodeData>()
39
+ val lightNodes = mutableStateListOf<LightNodeData>()
28
40
  val environmentPath = mutableStateOf<String?>(null)
29
41
  val orbitEnabled = mutableStateOf(true)
30
42
  }
31
43
 
32
44
  /**
33
45
  * ViewManager that bridges React Native's `<RNSceneView>` to the Jetpack Compose
34
- * `Scene { }` composable from `io.github.sceneview`.
46
+ * `SceneView { }` composable from `io.github.sceneview`.
35
47
  *
36
48
  * State is stored per-instance via [FrameLayout.getTag] to support multiple
37
49
  * `<RNSceneView>` components on the same screen.
@@ -53,6 +65,7 @@ class SceneViewManager : SimpleViewManager<FrameLayout>() {
53
65
  setContent {
54
66
  val engine = rememberEngine()
55
67
  val modelLoader = rememberModelLoader(engine)
68
+ val materialLoader = rememberMaterialLoader(engine)
56
69
  val environmentLoader = rememberEnvironmentLoader(engine)
57
70
 
58
71
  val cameraNode = rememberCameraNode(engine) {
@@ -66,10 +79,12 @@ class SceneViewManager : SimpleViewManager<FrameLayout>() {
66
79
  }
67
80
  }
68
81
 
69
- Scene(
82
+ SceneView(
70
83
  modifier = Modifier.fillMaxSize(),
84
+ surfaceType = SurfaceType.TextureSurface,
71
85
  engine = engine,
72
86
  modelLoader = modelLoader,
87
+ materialLoader = materialLoader,
73
88
  cameraNode = cameraNode,
74
89
  environment = environment ?: rememberEnvironment(environmentLoader),
75
90
  ) {
@@ -80,9 +95,92 @@ class SceneViewManager : SimpleViewManager<FrameLayout>() {
80
95
  modelInstance = it,
81
96
  scaleToUnits = model.scale,
82
97
  autoAnimate = model.animate,
98
+ position = model.position,
99
+ rotation = model.rotation,
83
100
  )
84
101
  }
85
102
  }
103
+
104
+ state.geometryNodes.forEach { geom ->
105
+ val colorInt = geom.color?.let {
106
+ runCatching { android.graphics.Color.parseColor(it) }.getOrNull()
107
+ }
108
+ // Cache material instance per (color, unlit) to avoid leaking on recomposition.
109
+ // The unlit flag is part of the cache key — switching from lit ↔ unlit
110
+ // returns a fresh instance because the underlying .filamat is different.
111
+ // Use varargs `keys` (Compose handles Boolean autobox internally without
112
+ // a per-recomposition Pair allocation).
113
+ val mat = colorInt?.let { c ->
114
+ val instance = remember(c, geom.unlit) {
115
+ if (geom.unlit) materialLoader.createUnlitColorInstance(c)
116
+ else materialLoader.createColorInstance(c)
117
+ }
118
+ DisposableEffect(c, geom.unlit) {
119
+ onDispose {
120
+ materialLoader.destroyMaterialInstance(instance)
121
+ }
122
+ }
123
+ instance
124
+ }
125
+ when (geom.type) {
126
+ "cube", "box" -> CubeNode(
127
+ size = geom.size?.let { Size(it[0], it[1], it[2]) }
128
+ ?: Size(1f, 1f, 1f),
129
+ materialInstance = mat,
130
+ position = geom.position,
131
+ rotation = geom.rotation,
132
+ scale = geom.scale,
133
+ )
134
+ "sphere" -> SphereNode(
135
+ radius = geom.size?.let { it[0] / 2f } ?: 0.5f,
136
+ materialInstance = mat,
137
+ position = geom.position,
138
+ rotation = geom.rotation,
139
+ scale = geom.scale,
140
+ )
141
+ "cylinder" -> CylinderNode(
142
+ radius = geom.size?.let { it[0] / 2f } ?: 0.5f,
143
+ height = geom.size?.let { it[1] } ?: 1f,
144
+ materialInstance = mat,
145
+ position = geom.position,
146
+ rotation = geom.rotation,
147
+ scale = geom.scale,
148
+ )
149
+ "plane" -> PlaneNode(
150
+ size = geom.size?.let { Size(it[0], it[1]) }
151
+ ?: Size(1f, 1f),
152
+ materialInstance = mat,
153
+ position = geom.position,
154
+ rotation = geom.rotation,
155
+ scale = geom.scale,
156
+ )
157
+ }
158
+ }
159
+
160
+ state.lightNodes.forEach { light ->
161
+ val lightType = when (light.type) {
162
+ "directional" -> LightManager.Type.DIRECTIONAL
163
+ "point" -> LightManager.Type.POINT
164
+ "spot" -> LightManager.Type.SPOT
165
+ else -> LightManager.Type.DIRECTIONAL
166
+ }
167
+ LightNode(
168
+ type = lightType,
169
+ intensity = light.intensity,
170
+ direction = light.direction,
171
+ position = light.position,
172
+ apply = {
173
+ light.color?.let { hex ->
174
+ val c = runCatching { android.graphics.Color.parseColor(hex) }.getOrNull() ?: return@let
175
+ color(
176
+ android.graphics.Color.red(c) / 255f,
177
+ android.graphics.Color.green(c) / 255f,
178
+ android.graphics.Color.blue(c) / 255f,
179
+ )
180
+ }
181
+ },
182
+ )
183
+ }
86
184
  }
87
185
  }
88
186
  }
@@ -90,6 +188,12 @@ class SceneViewManager : SimpleViewManager<FrameLayout>() {
90
188
  return container
91
189
  }
92
190
 
191
+ override fun onDropViewInstance(view: FrameLayout) {
192
+ // Remove the ComposeView so its Composition is disposed, releasing Filament resources.
193
+ view.removeAllViews()
194
+ super.onDropViewInstance(view)
195
+ }
196
+
93
197
  @ReactProp(name = "environment")
94
198
  fun setEnvironment(view: FrameLayout, environment: String?) {
95
199
  getState(view).environmentPath.value = environment
@@ -119,7 +223,78 @@ class SceneViewManager : SimpleViewManager<FrameLayout>() {
119
223
  } else {
120
224
  true
121
225
  }
122
- state.modelPaths.add(ModelNodeData(src = src, scale = scale, animate = animate))
226
+ val position = readPosition(map, "position")
227
+ val rotation = readRotation(map, "rotation")
228
+ state.modelPaths.add(
229
+ ModelNodeData(
230
+ src = src,
231
+ scale = scale,
232
+ animate = animate,
233
+ position = position,
234
+ rotation = rotation,
235
+ )
236
+ )
237
+ }
238
+ }
239
+ }
240
+
241
+ @ReactProp(name = "geometryNodes")
242
+ fun setGeometryNodes(view: FrameLayout, nodes: ReadableArray?) {
243
+ val state = getState(view)
244
+ state.geometryNodes.clear()
245
+ nodes?.let { array ->
246
+ for (i in 0 until array.size()) {
247
+ val map = array.getMap(i) ?: continue
248
+ val type = map.getString("type") ?: continue
249
+ val size = readFloatArray3(map, "size")
250
+ val position = readPosition(map, "position")
251
+ val rotation = readRotation(map, "rotation")
252
+ val scale = readScale(map, "scale")
253
+ val color = if (map.hasKey("color")) map.getString("color") else null
254
+ // `getBoolean` throws on type-mismatch; guard against JS sending
255
+ // `unlit: "true"` (string) or `unlit: 1` (number) which would crash
256
+ // the property setter and leave the view in a partial state.
257
+ val unlit = map.hasKey("unlit") &&
258
+ map.getType("unlit") == ReadableType.Boolean &&
259
+ map.getBoolean("unlit")
260
+ state.geometryNodes.add(
261
+ GeometryNodeData(
262
+ type = type,
263
+ size = size,
264
+ position = position,
265
+ rotation = rotation,
266
+ scale = scale,
267
+ color = color,
268
+ unlit = unlit,
269
+ )
270
+ )
271
+ }
272
+ }
273
+ }
274
+
275
+ @ReactProp(name = "lightNodes")
276
+ fun setLightNodes(view: FrameLayout, nodes: ReadableArray?) {
277
+ val state = getState(view)
278
+ state.lightNodes.clear()
279
+ nodes?.let { array ->
280
+ for (i in 0 until array.size()) {
281
+ val map = array.getMap(i) ?: continue
282
+ val type = map.getString("type") ?: continue
283
+ val intensity = if (map.hasKey("intensity")) {
284
+ map.getDouble("intensity").toFloat()
285
+ } else null
286
+ val color = if (map.hasKey("color")) map.getString("color") else null
287
+ val position = readPosition(map, "position")
288
+ val direction = readDirection(map, "direction")
289
+ state.lightNodes.add(
290
+ LightNodeData(
291
+ type = type,
292
+ intensity = intensity,
293
+ color = color,
294
+ position = position,
295
+ direction = direction,
296
+ )
297
+ )
123
298
  }
124
299
  }
125
300
  }
@@ -133,5 +308,110 @@ class SceneViewManager : SimpleViewManager<FrameLayout>() {
133
308
  data class ModelNodeData(
134
309
  val src: String,
135
310
  val scale: Float = 1.0f,
136
- val animate: Boolean = true
311
+ val animate: Boolean = true,
312
+ val position: Position = Position(x = 0f),
313
+ val rotation: Rotation = Rotation(x = 0f),
314
+ )
315
+
316
+ data class GeometryNodeData(
317
+ val type: String,
318
+ val size: FloatArray? = null,
319
+ val position: Position = Position(x = 0f),
320
+ val rotation: Rotation = Rotation(x = 0f),
321
+ val scale: Scale = Scale(1f),
322
+ val color: String? = null,
323
+ /**
324
+ * When `true` the node's material ignores all scene lighting (no PBR shading,
325
+ * no IBL, no shadows) and renders the flat [color] straight to the framebuffer.
326
+ * Use for HUD overlays, gizmos, axes, lines, AR face/body meshes — anywhere
327
+ * lighting would fight the use case. Defaults to `false` (lit PBR).
328
+ */
329
+ val unlit: Boolean = false,
137
330
  )
331
+
332
+ data class LightNodeData(
333
+ val type: String,
334
+ val intensity: Float? = null,
335
+ val color: String? = null,
336
+ val position: Position = Position(x = 0f),
337
+ val direction: Direction? = null,
338
+ )
339
+
340
+ // ---------------------------------------------------------------------------
341
+ // Helpers for reading ReadableMap arrays into SceneView math types
342
+ // ---------------------------------------------------------------------------
343
+
344
+ internal fun readFloatArray3(
345
+ map: com.facebook.react.bridge.ReadableMap,
346
+ key: String
347
+ ): FloatArray? {
348
+ if (!map.hasKey(key)) return null
349
+ val arr = map.getArray(key) ?: return null
350
+ if (arr.size() < 3) return null
351
+ return floatArrayOf(
352
+ arr.getDouble(0).toFloat(),
353
+ arr.getDouble(1).toFloat(),
354
+ arr.getDouble(2).toFloat(),
355
+ )
356
+ }
357
+
358
+ internal fun readPosition(
359
+ map: com.facebook.react.bridge.ReadableMap,
360
+ key: String
361
+ ): Position {
362
+ if (!map.hasKey(key)) return Position(x = 0f)
363
+ val arr = map.getArray(key) ?: return Position(x = 0f)
364
+ if (arr.size() < 3) return Position(x = 0f)
365
+ return Position(
366
+ x = arr.getDouble(0).toFloat(),
367
+ y = arr.getDouble(1).toFloat(),
368
+ z = arr.getDouble(2).toFloat(),
369
+ )
370
+ }
371
+
372
+ internal fun readRotation(
373
+ map: com.facebook.react.bridge.ReadableMap,
374
+ key: String
375
+ ): Rotation {
376
+ if (!map.hasKey(key)) return Rotation(x = 0f)
377
+ val arr = map.getArray(key) ?: return Rotation(x = 0f)
378
+ if (arr.size() < 3) return Rotation(x = 0f)
379
+ return Rotation(
380
+ x = arr.getDouble(0).toFloat(),
381
+ y = arr.getDouble(1).toFloat(),
382
+ z = arr.getDouble(2).toFloat(),
383
+ )
384
+ }
385
+
386
+ internal fun readScale(
387
+ map: com.facebook.react.bridge.ReadableMap,
388
+ key: String
389
+ ): Scale {
390
+ if (!map.hasKey(key)) return Scale(1f)
391
+ return try {
392
+ val v = map.getDouble(key).toFloat()
393
+ Scale(v)
394
+ } catch (_: Exception) {
395
+ val arr = map.getArray(key) ?: return Scale(1f)
396
+ if (arr.size() < 3) return Scale(1f)
397
+ Scale(
398
+ x = arr.getDouble(0).toFloat(),
399
+ y = arr.getDouble(1).toFloat(),
400
+ z = arr.getDouble(2).toFloat(),
401
+ )
402
+ }
403
+ }
404
+
405
+ internal fun readDirection(
406
+ map: com.facebook.react.bridge.ReadableMap,
407
+ key: String
408
+ ): Direction? {
409
+ if (!map.hasKey(key)) return null
410
+ val arr = map.getArray(key) ?: return null
411
+ if (arr.size() < 3) return null
412
+ return Direction(
413
+ x = arr.getDouble(0).toFloat(),
414
+ y = arr.getDouble(1).toFloat(),
415
+ z = arr.getDouble(2).toFloat(),
416
+ )
417
+ }
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireDefault","require","_reactNative","e","__esModule","default","isNativeAvailable","Platform","OS","NativeSceneView","requireNativeComponent","NativeARSceneView","UnsupportedView","name","createElement","View","style","fallbackStyles","container","Text","text","StyleSheet","create","flex","justifyContent","alignItems","backgroundColor","color","fontSize","SceneView","props","exports","ARSceneView"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AAQsB,SAAAD,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAEtB;AACA;AACA;;AAEA;;AAiBA;;AAWA;;AASA;AACA;AACA;;AAkBA;AACA;AACA;;AAoCA;AACA;AACA;;AAEA,MAAMG,iBAAiB,GAAGC,qBAAQ,CAACC,EAAE,KAAK,SAAS,IAAID,qBAAQ,CAACC,EAAE,KAAK,KAAK;AAE5E,MAAMC,eAAe,GAAGH,iBAAiB,GACrC,IAAAI,mCAAsB,EAAiB,aAAa,CAAC,GACrD,IAAI;AAER,MAAMC,iBAAiB,GAAGL,iBAAiB,GACvC,IAAAI,mCAAsB,EAAmB,eAAe,CAAC,GACzD,IAAI;;AAER;AACA;AACA;;AAEA,MAAME,eAA2C,GAAGA,CAAC;EAAEC;AAAK,CAAC,kBAC3Dd,MAAA,CAAAM,OAAA,CAAAS,aAAA,CAACZ,YAAA,CAAAa,IAAI;EAACC,KAAK,EAAEC,cAAc,CAACC;AAAU,gBACpCnB,MAAA,CAAAM,OAAA,CAAAS,aAAA,CAACZ,YAAA,CAAAiB,IAAI;EAACH,KAAK,EAAEC,cAAc,CAACG;AAAK,GAAEP,IAAI,EAAC,oCAAwC,CAC5E,CACP;AAED,MAAMI,cAAc,GAAGI,uBAAU,CAACC,MAAM,CAAC;EACvCJ,SAAS,EAAE;IACTK,IAAI,EAAE,CAAC;IACPC,cAAc,EAAE,QAAQ;IACxBC,UAAU,EAAE,QAAQ;IACpBC,eAAe,EAAE;EACnB,CAAC;EACDN,IAAI,EAAE;IACJO,KAAK,EAAE,MAAM;IACbC,QAAQ,EAAE;EACZ;AACF,CAAC,CAAC;;AAEF;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMC,SAAmC,GAAIC,KAAK,IAAK;EAC5D,IAAI,CAACrB,eAAe,EAAE;IACpB,oBAAOV,MAAA,CAAAM,OAAA,CAAAS,aAAA,CAACF,eAAe;MAACC,IAAI,EAAC;IAAW,CAAE,CAAC;EAC7C;EACA,oBAAOd,MAAA,CAAAM,OAAA,CAAAS,aAAA,CAACL,eAAe,EAAKqB,KAAQ,CAAC;AACvC,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AATAC,OAAA,CAAAF,SAAA,GAAAA,SAAA;AAUO,MAAMG,WAAuC,GAAIF,KAAK,IAAK;EAChE,IAAI,CAACnB,iBAAiB,EAAE;IACtB,oBAAOZ,MAAA,CAAAM,OAAA,CAAAS,aAAA,CAACF,eAAe;MAACC,IAAI,EAAC;IAAa,CAAE,CAAC;EAC/C;EACA,oBAAOd,MAAA,CAAAM,OAAA,CAAAS,aAAA,CAACH,iBAAiB,EAAKmB,KAAQ,CAAC;AACzC,CAAC;AAACC,OAAA,CAAAC,WAAA,GAAAA,WAAA","ignoreList":[]}
1
+ {"version":3,"names":["_react","_interopRequireDefault","require","_reactNative","e","__esModule","default","isNativeAvailable","Platform","OS","NativeSceneView","requireNativeComponent","NativeARSceneView","UnsupportedView","name","createElement","View","style","fallbackStyles","container","Text","text","StyleSheet","create","flex","justifyContent","alignItems","backgroundColor","color","fontSize","SceneView","props","exports","ARSceneView"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AAQsB,SAAAD,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAEtB;AACA;AACA;;AAEA;;AAiBA;;AAmBA;;AASA;AACA;AACA;;AAkBA;AACA;AACA;;AAoCA;AACA;AACA;;AAEA,MAAMG,iBAAiB,GAAGC,qBAAQ,CAACC,EAAE,KAAK,SAAS,IAAID,qBAAQ,CAACC,EAAE,KAAK,KAAK;AAE5E,MAAMC,eAAe,GAAGH,iBAAiB,GACrC,IAAAI,mCAAsB,EAAiB,aAAa,CAAC,GACrD,IAAI;AAER,MAAMC,iBAAiB,GAAGL,iBAAiB,GACvC,IAAAI,mCAAsB,EAAmB,eAAe,CAAC,GACzD,IAAI;;AAER;AACA;AACA;;AAEA,MAAME,eAA2C,GAAGA,CAAC;EAAEC;AAAK,CAAC,kBAC3Dd,MAAA,CAAAM,OAAA,CAAAS,aAAA,CAACZ,YAAA,CAAAa,IAAI;EAACC,KAAK,EAAEC,cAAc,CAACC;AAAU,gBACpCnB,MAAA,CAAAM,OAAA,CAAAS,aAAA,CAACZ,YAAA,CAAAiB,IAAI;EAACH,KAAK,EAAEC,cAAc,CAACG;AAAK,GAAEP,IAAI,EAAC,oCAAwC,CAC5E,CACP;AAED,MAAMI,cAAc,GAAGI,uBAAU,CAACC,MAAM,CAAC;EACvCJ,SAAS,EAAE;IACTK,IAAI,EAAE,CAAC;IACPC,cAAc,EAAE,QAAQ;IACxBC,UAAU,EAAE,QAAQ;IACpBC,eAAe,EAAE;EACnB,CAAC;EACDN,IAAI,EAAE;IACJO,KAAK,EAAE,MAAM;IACbC,QAAQ,EAAE;EACZ;AACF,CAAC,CAAC;;AAEF;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMC,SAAmC,GAAIC,KAAK,IAAK;EAC5D,IAAI,CAACrB,eAAe,EAAE;IACpB,oBAAOV,MAAA,CAAAM,OAAA,CAAAS,aAAA,CAACF,eAAe;MAACC,IAAI,EAAC;IAAW,CAAE,CAAC;EAC7C;EACA,oBAAOd,MAAA,CAAAM,OAAA,CAAAS,aAAA,CAACL,eAAe,EAAKqB,KAAQ,CAAC;AACvC,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AATAC,OAAA,CAAAF,SAAA,GAAAA,SAAA;AAUO,MAAMG,WAAuC,GAAIF,KAAK,IAAK;EAChE,IAAI,CAACnB,iBAAiB,EAAE;IACtB,oBAAOZ,MAAA,CAAAM,OAAA,CAAAS,aAAA,CAACF,eAAe;MAACC,IAAI,EAAC;IAAa,CAAE,CAAC;EAC/C;EACA,oBAAOd,MAAA,CAAAM,OAAA,CAAAS,aAAA,CAACH,iBAAiB,EAAKmB,KAAQ,CAAC;AACzC,CAAC;AAACC,OAAA,CAAAC,WAAA,GAAAA,WAAA","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":["React","requireNativeComponent","Platform","View","Text","StyleSheet","isNativeAvailable","OS","NativeSceneView","NativeARSceneView","UnsupportedView","name","createElement","style","fallbackStyles","container","text","create","flex","justifyContent","alignItems","backgroundColor","color","fontSize","SceneView","props","ARSceneView"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SACEC,sBAAsB,EACtBC,QAAQ,EAGRC,IAAI,EACJC,IAAI,EACJC,UAAU,QACL,cAAc;;AAErB;AACA;AACA;;AAEA;;AAiBA;;AAWA;;AASA;AACA;AACA;;AAkBA;AACA;AACA;;AAoCA;AACA;AACA;;AAEA,MAAMC,iBAAiB,GAAGJ,QAAQ,CAACK,EAAE,KAAK,SAAS,IAAIL,QAAQ,CAACK,EAAE,KAAK,KAAK;AAE5E,MAAMC,eAAe,GAAGF,iBAAiB,GACrCL,sBAAsB,CAAiB,aAAa,CAAC,GACrD,IAAI;AAER,MAAMQ,iBAAiB,GAAGH,iBAAiB,GACvCL,sBAAsB,CAAmB,eAAe,CAAC,GACzD,IAAI;;AAER;AACA;AACA;;AAEA,MAAMS,eAA2C,GAAGA,CAAC;EAAEC;AAAK,CAAC,kBAC3DX,KAAA,CAAAY,aAAA,CAACT,IAAI;EAACU,KAAK,EAAEC,cAAc,CAACC;AAAU,gBACpCf,KAAA,CAAAY,aAAA,CAACR,IAAI;EAACS,KAAK,EAAEC,cAAc,CAACE;AAAK,GAAEL,IAAI,EAAC,oCAAwC,CAC5E,CACP;AAED,MAAMG,cAAc,GAAGT,UAAU,CAACY,MAAM,CAAC;EACvCF,SAAS,EAAE;IACTG,IAAI,EAAE,CAAC;IACPC,cAAc,EAAE,QAAQ;IACxBC,UAAU,EAAE,QAAQ;IACpBC,eAAe,EAAE;EACnB,CAAC;EACDL,IAAI,EAAE;IACJM,KAAK,EAAE,MAAM;IACbC,QAAQ,EAAE;EACZ;AACF,CAAC,CAAC;;AAEF;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,SAAmC,GAAIC,KAAK,IAAK;EAC5D,IAAI,CAACjB,eAAe,EAAE;IACpB,oBAAOR,KAAA,CAAAY,aAAA,CAACF,eAAe;MAACC,IAAI,EAAC;IAAW,CAAE,CAAC;EAC7C;EACA,oBAAOX,KAAA,CAAAY,aAAA,CAACJ,eAAe,EAAKiB,KAAQ,CAAC;AACvC,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,WAAuC,GAAID,KAAK,IAAK;EAChE,IAAI,CAAChB,iBAAiB,EAAE;IACtB,oBAAOT,KAAA,CAAAY,aAAA,CAACF,eAAe;MAACC,IAAI,EAAC;IAAa,CAAE,CAAC;EAC/C;EACA,oBAAOX,KAAA,CAAAY,aAAA,CAACH,iBAAiB,EAAKgB,KAAQ,CAAC;AACzC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["React","requireNativeComponent","Platform","View","Text","StyleSheet","isNativeAvailable","OS","NativeSceneView","NativeARSceneView","UnsupportedView","name","createElement","style","fallbackStyles","container","text","create","flex","justifyContent","alignItems","backgroundColor","color","fontSize","SceneView","props","ARSceneView"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SACEC,sBAAsB,EACtBC,QAAQ,EAGRC,IAAI,EACJC,IAAI,EACJC,UAAU,QACL,cAAc;;AAErB;AACA;AACA;;AAEA;;AAiBA;;AAmBA;;AASA;AACA;AACA;;AAkBA;AACA;AACA;;AAoCA;AACA;AACA;;AAEA,MAAMC,iBAAiB,GAAGJ,QAAQ,CAACK,EAAE,KAAK,SAAS,IAAIL,QAAQ,CAACK,EAAE,KAAK,KAAK;AAE5E,MAAMC,eAAe,GAAGF,iBAAiB,GACrCL,sBAAsB,CAAiB,aAAa,CAAC,GACrD,IAAI;AAER,MAAMQ,iBAAiB,GAAGH,iBAAiB,GACvCL,sBAAsB,CAAmB,eAAe,CAAC,GACzD,IAAI;;AAER;AACA;AACA;;AAEA,MAAMS,eAA2C,GAAGA,CAAC;EAAEC;AAAK,CAAC,kBAC3DX,KAAA,CAAAY,aAAA,CAACT,IAAI;EAACU,KAAK,EAAEC,cAAc,CAACC;AAAU,gBACpCf,KAAA,CAAAY,aAAA,CAACR,IAAI;EAACS,KAAK,EAAEC,cAAc,CAACE;AAAK,GAAEL,IAAI,EAAC,oCAAwC,CAC5E,CACP;AAED,MAAMG,cAAc,GAAGT,UAAU,CAACY,MAAM,CAAC;EACvCF,SAAS,EAAE;IACTG,IAAI,EAAE,CAAC;IACPC,cAAc,EAAE,QAAQ;IACxBC,UAAU,EAAE,QAAQ;IACpBC,eAAe,EAAE;EACnB,CAAC;EACDL,IAAI,EAAE;IACJM,KAAK,EAAE,MAAM;IACbC,QAAQ,EAAE;EACZ;AACF,CAAC,CAAC;;AAEF;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,SAAmC,GAAIC,KAAK,IAAK;EAC5D,IAAI,CAACjB,eAAe,EAAE;IACpB,oBAAOR,KAAA,CAAAY,aAAA,CAACF,eAAe;MAACC,IAAI,EAAC;IAAW,CAAE,CAAC;EAC7C;EACA,oBAAOX,KAAA,CAAAY,aAAA,CAACJ,eAAe,EAAKiB,KAAQ,CAAC;AACvC,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,WAAuC,GAAID,KAAK,IAAK;EAChE,IAAI,CAAChB,iBAAiB,EAAE;IACtB,oBAAOT,KAAA,CAAAY,aAAA,CAACF,eAAe;MAACC,IAAI,EAAC;IAAa,CAAE,CAAC;EAC/C;EACA,oBAAOX,KAAA,CAAAY,aAAA,CAACH,iBAAiB,EAAKgB,KAAQ,CAAC;AACzC,CAAC","ignoreList":[]}
@@ -18,13 +18,21 @@ export interface ModelNode {
18
18
  }
19
19
  /** A procedural geometry node (box, sphere, cylinder, plane). */
20
20
  export interface GeometryNode {
21
- type: 'box' | 'sphere' | 'cylinder' | 'plane';
21
+ type: 'box' | 'cube' | 'sphere' | 'cylinder' | 'plane';
22
22
  size?: [number, number, number];
23
23
  position?: [number, number, number];
24
24
  rotation?: [number, number, number];
25
25
  scale?: number | [number, number, number];
26
26
  /** Hex color string, e.g. "#FF5500". */
27
27
  color?: string;
28
+ /**
29
+ * When `true` the material ignores all scene lighting (no PBR shading,
30
+ * no IBL, no shadows) and renders the flat [color] straight to the
31
+ * framebuffer. Use for HUD overlays, gizmos, axes, lines, or AR face/body
32
+ * meshes — anywhere lighting would fight the use case. Defaults to `false`
33
+ * (lit PBR).
34
+ */
35
+ unlit?: boolean;
28
36
  }
29
37
  /** A light source in the scene. */
30
38
  export interface LightNode {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sceneview-sdk/react-native",
3
- "version": "3.6.1",
3
+ "version": "4.1.1",
4
4
  "description": "React Native bindings for SceneView — 3D and AR scenes powered by Filament (Android) and RealityKit (iOS)",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
package/src/index.tsx CHANGED
@@ -32,13 +32,21 @@ export interface ModelNode {
32
32
 
33
33
  /** A procedural geometry node (box, sphere, cylinder, plane). */
34
34
  export interface GeometryNode {
35
- type: 'box' | 'sphere' | 'cylinder' | 'plane';
35
+ type: 'box' | 'cube' | 'sphere' | 'cylinder' | 'plane';
36
36
  size?: [number, number, number];
37
37
  position?: [number, number, number];
38
38
  rotation?: [number, number, number];
39
39
  scale?: number | [number, number, number];
40
40
  /** Hex color string, e.g. "#FF5500". */
41
41
  color?: string;
42
+ /**
43
+ * When `true` the material ignores all scene lighting (no PBR shading,
44
+ * no IBL, no shadows) and renders the flat [color] straight to the
45
+ * framebuffer. Use for HUD overlays, gizmos, axes, lines, or AR face/body
46
+ * meshes — anywhere lighting would fight the use case. Defaults to `false`
47
+ * (lit PBR).
48
+ */
49
+ unlit?: boolean;
42
50
  }
43
51
 
44
52
  /** A light source in the scene. */