@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 +25 -9
- package/android/src/main/java/io/github/sceneview/reactnative/ARSceneViewManager.kt +170 -3
- package/android/src/main/java/io/github/sceneview/reactnative/SceneViewManager.kt +285 -5
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/index.d.ts +9 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.tsx +9 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# react-native
|
|
1
|
+
# @sceneview-sdk/react-native
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@sceneview-sdk/react-native)
|
|
4
4
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
5
5
|
[](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: `
|
|
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
|
|
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
|
|
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 ->
|
|
118
|
-
| (Filament, SceneView SDK
|
|
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
|
|
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
|
-
* `
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
-
* `
|
|
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
|
-
|
|
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
|
-
|
|
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;;
|
|
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":[]}
|
package/lib/module/index.js.map
CHANGED
|
@@ -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;;
|
|
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":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,oBAAoB,EAI1B,MAAM,cAAc,CAAC;AAMtB,kDAAkD;AAClD,MAAM,WAAW,SAAS;IACxB,+CAA+C;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,iEAAiE;AACjE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;
|
|
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
|
+
"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. */
|