@sceneview-sdk/react-native 4.26.0 → 4.28.0

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.
@@ -18,6 +18,48 @@ struct RNModelData: Identifiable, Equatable {
18
18
  }
19
19
  }
20
20
 
21
+ // MARK: - Tap payload
22
+
23
+ /// Builds the JS `onTap` payload — the iOS counterpart of Android's single
24
+ /// `TapEvent.getEventData()`.
25
+ ///
26
+ /// Both iOS views go through here so `nodeName` is written on *every* dispatch
27
+ /// path, never merely on the ones that happen to have a name: a missed tap
28
+ /// reports `NSNull()`, which crosses the bridge as the same JS `null` Android
29
+ /// emits via `putNull`. That is what lets the public `TapEvent.nodeName` be
30
+ /// typed `string | null` instead of `string | null | undefined` — a consumer
31
+ /// writes one `nodeName == null` guard.
32
+ ///
33
+ /// This iOS `ARSceneView` can only resolve a surface point, never an entity, so
34
+ /// it always passes `nil`. That is a platform limitation, not the contract:
35
+ /// Android's AR view hit-tests the scene and does name the tapped model. Naming
36
+ /// it here needs an entity hit-test hook on `SceneViewSwift.ARSceneView`, which
37
+ /// does not exist yet (#2051).
38
+ ///
39
+ /// Keeping this a single function (rather than a comment asking each call site
40
+ /// to remember the key) is the guard: a new tap source cannot omit `nodeName`
41
+ /// without skipping the only payload builder in the bridge.
42
+ func rnTapPayload(worldPosition: SIMD3<Float>, nodeName: String?) -> [String: Any] {
43
+ // Seeded with the null sentinel, then overwritten — so the key exists
44
+ // before any branch runs and no path can drop it.
45
+ var payload: [String: Any] = [
46
+ "x": worldPosition.x,
47
+ "y": worldPosition.y,
48
+ "z": worldPosition.z,
49
+ "nodeName": NSNull(),
50
+ ]
51
+ // An empty name is "no model", not a model called "". Android already
52
+ // collapses it (`SceneViewManager.nodeName()` ends in
53
+ // `takeIf { it.isNotEmpty() }`); collapsing it here rather than at the call
54
+ // sites is what keeps the two platforms on ONE sentinel, for the same
55
+ // reason the key is seeded above — a future tap source cannot reintroduce
56
+ // the empty string without going around the only payload builder.
57
+ if let nodeName, !nodeName.isEmpty {
58
+ payload["nodeName"] = nodeName
59
+ }
60
+ return payload
61
+ }
62
+
21
63
  // MARK: - SceneView (3D)
22
64
 
23
65
  /// RCTViewManager subclass that bridges React Native's `<RNSceneView>`
@@ -34,35 +76,43 @@ class RNSceneViewManager: RCTViewManager {
34
76
  }
35
77
  }
36
78
 
37
- /// Maps the wire string sent from JS to a `CameraControlMode` (v4.3.0).
38
- /// Unknown values fall back to `.orbit`.
39
- func rnCameraControlMode(_ raw: String?) -> CameraControlMode {
40
- switch raw {
41
- case "pan": return .pan
42
- case "firstPerson": return .firstPerson
43
- default: return .orbit
44
- }
45
- }
46
-
47
- /// Observable state model shared between React props and SwiftUI view.
79
+ /// State model backing the React props.
80
+ ///
81
+ /// Still an `ObservableObject` for shape consistency with `RNARSceneState`, which
82
+ /// genuinely drives SwiftUI; nothing observes this one since the 3D scene moved
83
+ /// onto `SceneViewerHostView`.
48
84
  @MainActor
49
85
  class RNSceneState: ObservableObject {
50
86
  @Published var models: [RNModelData] = []
51
87
  @Published var environmentPath: String?
88
+
89
+ /// Accepted, stored, and deliberately not applied — as before this bridge
90
+ /// moved onto the shared host.
91
+ ///
92
+ /// `cameraControlMode` supersedes it and the two would contradict each other
93
+ /// (which wins for `cameraOrbit: false, cameraControlMode: "orbit"`?). Wiring
94
+ /// it up here would be a behaviour change dressed as a refactor, so it stays
95
+ /// inert; the TypeScript surface deprecates it.
52
96
  @Published var cameraOrbit: Bool = true
53
- @Published var cameraControlMode: CameraControlMode = .orbit
54
- @Published var autoCenterContent: Bool = true
55
97
 
56
- /// Invoked from the SwiftUI content's `onEntityTapped` modifier so the
57
- /// wrapper can forward the tap to React Native's `onTap` prop (issue #2053).
58
- /// Not `@Published` — it is plumbing, not rendered state.
59
- var onTap: ((Entity) -> Void)?
98
+ /// Wire name as it arrives from JS: `"orbit"`, `"pan"` or `"firstPerson"`.
99
+ /// `SceneViewerConfiguration` normalises an unrecognised value to `"orbit"`,
100
+ /// which is what the local mapping this replaces did.
101
+ @Published var cameraControlMode: String = "orbit"
102
+
103
+ @Published var autoCenterContent: Bool = true
60
104
  }
61
105
 
62
- /// UIView wrapper that hosts a SwiftUI `SceneView` via UIHostingController.
106
+ /// UIView wrapper hosting the shared `SceneViewerHostView`.
107
+ ///
108
+ /// This class owns the React prop bag; the scene itself — hosting SwiftUI in
109
+ /// UIKit, loading models, reconciling them — belongs to `SceneViewerHostView`
110
+ /// and is shared with the Flutter plugin and `sceneview-compose`. The AR wrapper
111
+ /// below keeps its own SwiftUI content: `ARSceneView` is anchor-driven and
112
+ /// shares nothing with the 3D viewer.
63
113
  class RNSceneViewWrapper: UIView {
64
114
 
65
- private var hostingController: UIHostingController<RNSceneViewContent>?
115
+ private let hostView = SceneViewerHostView()
66
116
  private let sceneState = RNSceneState()
67
117
 
68
118
  /// Event callback for tap events.
@@ -70,16 +120,21 @@ class RNSceneViewWrapper: UIView {
70
120
  didSet {
71
121
  let block = onTap
72
122
  Task { @MainActor in
73
- sceneState.onTap = { entity in
123
+ // `onTapEntity` rather than the host's flattened `onTap`: this
124
+ // prop reports the tapped *model* — its own origin and its file
125
+ // base name — where the flattened callback carries the hit's
126
+ // bounds centre and no name at all.
127
+ //
128
+ // The model root is what the host resolves, so a tap inside a
129
+ // USDZ that names its meshes reports the model, not `skin0`.
130
+ hostView.onTapEntity = { _, modelRoot in
74
131
  // Mirrors the Android `TapEvent` payload: world-space
75
- // coordinates of the tapped entity + its node name.
76
- let p = entity.position(relativeTo: nil)
77
- block?([
78
- "x": p.x,
79
- "y": p.y,
80
- "z": p.z,
81
- "nodeName": entity.name,
82
- ])
132
+ // coordinates of the tapped model (`node.worldPosition`
133
+ // there) + its node name, `null` when nothing was hit.
134
+ block?(rnTapPayload(
135
+ worldPosition: modelRoot?.position(relativeTo: nil) ?? .zero,
136
+ nodeName: modelRoot.map { ($0.name as NSString).deletingPathExtension }
137
+ ))
83
138
  }
84
139
  }
85
140
  }
@@ -96,12 +151,55 @@ class RNSceneViewWrapper: UIView {
96
151
  }
97
152
 
98
153
  private func setupView() {
99
- let content = RNSceneViewContent(state: sceneState)
100
- let hosting = UIHostingController(rootView: content)
101
- hosting.view.frame = bounds
102
- hosting.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
103
- addSubview(hosting.view)
104
- hostingController = hosting
154
+ hostView.frame = bounds
155
+ hostView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
156
+ addSubview(hostView)
157
+ }
158
+
159
+ /// Pushes the current props into the host view.
160
+ ///
161
+ /// Called after every prop change. `applyConfiguration` compares field by
162
+ /// field and touches only what changed, so re-sending everything on each
163
+ /// prop update costs nothing.
164
+ @MainActor
165
+ private func applyState() {
166
+ let configuration = SceneViewerConfiguration()
167
+
168
+ configuration.models = sceneState.models.map { data in
169
+ let model = SceneViewerModel()
170
+ model.assetPath = data.path
171
+ // The per-entry id minted when the prop was decoded. A new
172
+ // `modelNodes` value mints new ids, which is what gives this prop
173
+ // its replace-the-whole-list semantics.
174
+ model.identity = data.id.uuidString
175
+ model.setScale(data.scale.x, data.scale.y, data.scale.z)
176
+ model.setPosition(data.position.x, data.position.y, data.position.z)
177
+ model.animationName = data.animation
178
+ // No named animation means play them all, which is this bridge's
179
+ // behaviour and not the Flutter one's.
180
+ model.autoPlayAllAnimations = true
181
+ // The file's name — with its extension, which the tap report
182
+ // strips. This is the only entity the bridge names, and the host
183
+ // resolves a tap to exactly it, so it is what JS receives as
184
+ // `nodeName`. Matches Android's `ModelNodeData.nodeName()`.
185
+ model.nodeName = sceneViewerModelFileName(data.path)
186
+ return model
187
+ }
188
+
189
+ configuration.cameraControlMode = sceneState.cameraControlMode
190
+ configuration.autoCenterContent = sceneState.autoCenterContent
191
+ // This bridge exposes no camera prop, so it authors no pose: without
192
+ // this, every prop change would re-assert the configuration's default
193
+ // pose and snap the camera back out of the auto-centre framing and away
194
+ // from wherever the user had orbited to.
195
+ configuration.cameraPoseAuthored = false
196
+
197
+ if let path = sceneState.environmentPath, !path.isEmpty {
198
+ configuration.environmentKind = "hdr"
199
+ configuration.environmentHdrPath = path
200
+ }
201
+
202
+ hostView.applyConfiguration(configuration)
105
203
  }
106
204
 
107
205
  // MARK: - React props
@@ -110,6 +208,7 @@ class RNSceneViewWrapper: UIView {
110
208
  didSet {
111
209
  Task { @MainActor in
112
210
  sceneState.environmentPath = environment
211
+ applyState()
113
212
  }
114
213
  }
115
214
  }
@@ -136,10 +235,12 @@ class RNSceneViewWrapper: UIView {
136
235
  let animation = dict["animation"] as? String
137
236
  return RNModelData(path: src, scale: scale, position: position, animation: animation)
138
237
  } ?? []
238
+ applyState()
139
239
  }
140
240
  }
141
241
  }
142
242
 
243
+ /// **Deprecated.** Superseded by `cameraControlMode`; see `RNSceneState.cameraOrbit`.
143
244
  @objc var cameraOrbit: Bool = true {
144
245
  didSet {
145
246
  Task { @MainActor in
@@ -151,9 +252,10 @@ class RNSceneViewWrapper: UIView {
151
252
  /// Camera interaction mode (v4.3.0, issue #1053).
152
253
  @objc var cameraControlMode: String? {
153
254
  didSet {
154
- let mode = rnCameraControlMode(cameraControlMode)
255
+ let raw = cameraControlMode
155
256
  Task { @MainActor in
156
- sceneState.cameraControlMode = mode
257
+ sceneState.cameraControlMode = raw ?? "orbit"
258
+ applyState()
157
259
  }
158
260
  }
159
261
  }
@@ -163,78 +265,7 @@ class RNSceneViewWrapper: UIView {
163
265
  didSet {
164
266
  Task { @MainActor in
165
267
  sceneState.autoCenterContent = autoCenterContent
166
- }
167
- }
168
- }
169
- }
170
-
171
- /// SwiftUI content view rendering `SceneViewSwift.SceneView` (issue #2067).
172
- ///
173
- /// `SceneViewSwift` loads models **asynchronously** (`ModelNode.load(_:)` is
174
- /// `async throws`) — there is no synchronous `ModelNode(String)` initialiser,
175
- /// and the `@NodeBuilder` content builder composes static `EntityProvider`
176
- /// values, not a SwiftUI `ForEach`. So the bridge loads each `RNModelData`
177
- /// off the main actor's `Task`, wraps the resulting `ModelEntity`s in a
178
- /// stable holder entity, and feeds that holder to `SceneView`'s **imperative**
179
- /// `init(_ content: (Entity) -> Void)`.
180
- ///
181
- /// `SceneView`'s content closure runs once when the underlying `RealityView`
182
- /// is created, so the holder entity is built up front and re-populated in a
183
- /// `.task(id:)` whenever the JS `modelNodes` prop changes — RealityKit picks
184
- /// up the new children on its next render frame without recreating the view.
185
- struct RNSceneViewContent: View {
186
- @ObservedObject var state: RNSceneState
187
-
188
- /// Stable parent entity handed to `SceneView`. Its children are the
189
- /// loaded model entities; rebuilt by `loadModels()` on every prop change.
190
- @State private var modelRoot = Entity()
191
-
192
- var body: some View {
193
- SceneView { root in
194
- root.addChild(modelRoot)
195
- }
196
- .cameraControls(state.cameraControlMode)
197
- .autoCenterContent(state.autoCenterContent)
198
- // Forward entity taps to React Native's `onTap` prop (issue #2053).
199
- .onEntityTapped { entity in
200
- state.onTap?(entity)
201
- }
202
- // Reload whenever the JS `modelNodes` prop changes. Keyed on the
203
- // model identities so an unrelated re-render does not re-download.
204
- .task(id: state.models.map(\.id)) {
205
- await loadModels()
206
- }
207
- }
208
-
209
- /// Loads every model in `state.models` and replaces `modelRoot`'s
210
- /// children with the freshly loaded entities. `ModelNode.load(_:)` is
211
- /// `@MainActor`-isolated, so this runs on the main actor as required by
212
- /// RealityKit. A failed load is skipped (the others still render).
213
- @MainActor
214
- private func loadModels() async {
215
- // Clear previous content before reloading.
216
- for child in modelRoot.children {
217
- child.removeFromParent()
218
- }
219
- for model in state.models {
220
- do {
221
- let node = try await ModelNode.load(model.path)
222
- // `.task(id:)` cancels this task when the `modelNodes` prop
223
- // changes mid-load. A cancelled task still resumes past the
224
- // `await`, so bail out before mutating the scene — otherwise a
225
- // superseded load leaks a stale model into `modelRoot`.
226
- guard !Task.isCancelled else { return }
227
- node.position(model.position)
228
- node.scale(model.scale)
229
- if let animation = model.animation {
230
- node.playAnimation(named: animation)
231
- } else if node.animationCount > 0 {
232
- node.playAllAnimations()
233
- }
234
- modelRoot.addChild(node.entity)
235
- } catch {
236
- // A single bad path must not break the whole scene.
237
- print("[RNSceneView] Failed to load model '\(model.path)': \(error)")
268
+ applyState()
238
269
  }
239
270
  }
240
271
  }
@@ -284,12 +315,14 @@ class RNARSceneViewWrapper: UIView {
284
315
  sceneState.onTap = { worldPosition in
285
316
  // Mirrors the Android `TapEvent` payload. `ARSceneView`'s
286
317
  // `onTapOnPlane` reports the tapped surface point, not a
287
- // node, so `nodeName` is left absent.
288
- block?([
289
- "x": worldPosition.x,
290
- "y": worldPosition.y,
291
- "z": worldPosition.z,
292
- ])
318
+ // node, so `nodeName` is always `null` here — the same JS
319
+ // `null` Android emits via `putNull` and the 3D view emits
320
+ // for a tap that hit no model. It used to omit the key,
321
+ // which made JS see `undefined` on this one view.
322
+ //
323
+ // Android's AR view names the tapped model instead; this
324
+ // side cannot until #2051 adds an entity hit-test hook.
325
+ block?(rnTapPayload(worldPosition: worldPosition, nodeName: nil))
293
326
  }
294
327
  }
295
328
  }
@@ -7,6 +7,13 @@ exports.SceneView = exports.ARSceneView = exports.ARRecorder = void 0;
7
7
  var _react = _interopRequireDefault(require("react"));
8
8
  var _reactNative = require("react-native");
9
9
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
+ // `tsconfig.json` sets `"jsx": "react"` — the CLASSIC runtime — so every JSX
11
+ // element below compiles to `React.createElement(...)` (verified in the
12
+ // published `lib/commonjs/index.js`). Biome's `useImportType` only sees the
13
+ // `React.FC` type annotations, not the JSX lowering, so it offers a "safe fix"
14
+ // that would erase this import and break the shipped bundle at runtime.
15
+ // biome-ignore lint/style/useImportType: React is a VALUE import — see above.
16
+
10
17
  // ---------------------------------------------------------------------------
11
18
  // Node type interfaces
12
19
  // ---------------------------------------------------------------------------
@@ -55,9 +62,9 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
55
62
  // Native components (only available on Android and iOS)
56
63
  // ---------------------------------------------------------------------------
57
64
 
58
- const isNativeAvailable = _reactNative.Platform.OS === 'android' || _reactNative.Platform.OS === 'ios';
59
- const NativeSceneView = isNativeAvailable ? (0, _reactNative.requireNativeComponent)('RNSceneView') : null;
60
- const NativeARSceneView = isNativeAvailable ? (0, _reactNative.requireNativeComponent)('RNARSceneView') : null;
65
+ const isNativeAvailable = _reactNative.Platform.OS === "android" || _reactNative.Platform.OS === "ios";
66
+ const NativeSceneView = isNativeAvailable ? (0, _reactNative.requireNativeComponent)("RNSceneView") : null;
67
+ const NativeARSceneView = isNativeAvailable ? (0, _reactNative.requireNativeComponent)("RNARSceneView") : null;
61
68
 
62
69
  // ---------------------------------------------------------------------------
63
70
  // Fallback for unsupported platforms
@@ -73,12 +80,12 @@ const UnsupportedView = ({
73
80
  const fallbackStyles = _reactNative.StyleSheet.create({
74
81
  container: {
75
82
  flex: 1,
76
- justifyContent: 'center',
77
- alignItems: 'center',
78
- backgroundColor: '#1a1a2e'
83
+ justifyContent: "center",
84
+ alignItems: "center",
85
+ backgroundColor: "#1a1a2e"
79
86
  },
80
87
  text: {
81
- color: '#aaa',
88
+ color: "#aaa",
82
89
  fontSize: 16
83
90
  }
84
91
  });
@@ -158,10 +165,10 @@ const NativeARRecorder = _reactNative.NativeModules.RNARRecorder;
158
165
  class ARRecorder {
159
166
  /** `true` when {@link ARRecorder} is supported on the current platform. */
160
167
  static get isSupported() {
161
- return _reactNative.Platform.OS === 'ios' && NativeARRecorder != null;
168
+ return _reactNative.Platform.OS === "ios" && NativeARRecorder != null;
162
169
  }
163
170
  rejectUnsupported() {
164
- return Promise.reject(new Error('ARRecorder is currently only supported on iOS. Android AR session ' + 'recording is tracked in issue #1051.'));
171
+ return Promise.reject(new Error("ARRecorder is currently only supported on iOS. Android AR session " + "recording is tracked in issue #1051."));
165
172
  }
166
173
 
167
174
  /** Starts an AR session recording. */
@@ -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","NativeARRecorder","NativeModules","RNARRecorder","ARRecorder","isSupported","rejectUnsupported","Promise","reject","Error","start","stop","outputPath","saveToPhotoLibrary","movPath"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","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","NativeARRecorder","NativeModules","RNARRecorder","ARRecorder","isSupported","rejectUnsupported","Promise","reject","Error","start","stop","outputPath","saveToPhotoLibrary","movPath"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,5 +1,11 @@
1
- import React from 'react';
2
- import { requireNativeComponent, NativeModules, Platform, View, Text, StyleSheet } from 'react-native';
1
+ // `tsconfig.json` sets `"jsx": "react"` — the CLASSIC runtime — so every JSX
2
+ // element below compiles to `React.createElement(...)` (verified in the
3
+ // published `lib/commonjs/index.js`). Biome's `useImportType` only sees the
4
+ // `React.FC` type annotations, not the JSX lowering, so it offers a "safe fix"
5
+ // that would erase this import and break the shipped bundle at runtime.
6
+ // biome-ignore lint/style/useImportType: React is a VALUE import — see above.
7
+ import React from "react";
8
+ import { NativeModules, Platform, requireNativeComponent, StyleSheet, Text, View } from "react-native";
3
9
 
4
10
  // ---------------------------------------------------------------------------
5
11
  // Node type interfaces
@@ -49,9 +55,9 @@ import { requireNativeComponent, NativeModules, Platform, View, Text, StyleSheet
49
55
  // Native components (only available on Android and iOS)
50
56
  // ---------------------------------------------------------------------------
51
57
 
52
- const isNativeAvailable = Platform.OS === 'android' || Platform.OS === 'ios';
53
- const NativeSceneView = isNativeAvailable ? requireNativeComponent('RNSceneView') : null;
54
- const NativeARSceneView = isNativeAvailable ? requireNativeComponent('RNARSceneView') : null;
58
+ const isNativeAvailable = Platform.OS === "android" || Platform.OS === "ios";
59
+ const NativeSceneView = isNativeAvailable ? requireNativeComponent("RNSceneView") : null;
60
+ const NativeARSceneView = isNativeAvailable ? requireNativeComponent("RNARSceneView") : null;
55
61
 
56
62
  // ---------------------------------------------------------------------------
57
63
  // Fallback for unsupported platforms
@@ -67,12 +73,12 @@ const UnsupportedView = ({
67
73
  const fallbackStyles = StyleSheet.create({
68
74
  container: {
69
75
  flex: 1,
70
- justifyContent: 'center',
71
- alignItems: 'center',
72
- backgroundColor: '#1a1a2e'
76
+ justifyContent: "center",
77
+ alignItems: "center",
78
+ backgroundColor: "#1a1a2e"
73
79
  },
74
80
  text: {
75
- color: '#aaa',
81
+ color: "#aaa",
76
82
  fontSize: 16
77
83
  }
78
84
  });
@@ -151,10 +157,10 @@ const NativeARRecorder = NativeModules.RNARRecorder;
151
157
  export class ARRecorder {
152
158
  /** `true` when {@link ARRecorder} is supported on the current platform. */
153
159
  static get isSupported() {
154
- return Platform.OS === 'ios' && NativeARRecorder != null;
160
+ return Platform.OS === "ios" && NativeARRecorder != null;
155
161
  }
156
162
  rejectUnsupported() {
157
- return Promise.reject(new Error('ARRecorder is currently only supported on iOS. Android AR session ' + 'recording is tracked in issue #1051.'));
163
+ return Promise.reject(new Error("ARRecorder is currently only supported on iOS. Android AR session " + "recording is tracked in issue #1051."));
158
164
  }
159
165
 
160
166
  /** Starts an AR session recording. */
@@ -1 +1 @@
1
- {"version":3,"names":["React","requireNativeComponent","NativeModules","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","NativeARRecorder","RNARRecorder","ARRecorder","isSupported","rejectUnsupported","Promise","reject","Error","start","stop","outputPath","saveToPhotoLibrary","movPath"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["React","NativeModules","Platform","requireNativeComponent","StyleSheet","Text","View","isNativeAvailable","OS","NativeSceneView","NativeARSceneView","UnsupportedView","name","createElement","style","fallbackStyles","container","text","create","flex","justifyContent","alignItems","backgroundColor","color","fontSize","SceneView","props","ARSceneView","NativeARRecorder","RNARRecorder","ARRecorder","isSupported","rejectUnsupported","Promise","reject","Error","start","stop","outputPath","saveToPhotoLibrary","movPath"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,5 +1,5 @@
1
- import React from 'react';
2
- import { type ViewStyle, type NativeSyntheticEvent } from 'react-native';
1
+ import React from "react";
2
+ import { type NativeSyntheticEvent, type ViewStyle } from "react-native";
3
3
  /** A 3D model loaded from a .glb / .gltf file. */
4
4
  export interface ModelNode {
5
5
  /** Asset path or URL to the glTF/GLB model. */
@@ -26,7 +26,7 @@ export interface ModelNode {
26
26
  * cross-platform bridge-parity umbrella (#909). Use `modelNodes` on iOS.
27
27
  */
28
28
  export interface GeometryNode {
29
- type: 'box' | 'cube' | 'sphere' | 'cylinder' | 'plane';
29
+ type: "box" | "cube" | "sphere" | "cylinder" | "plane";
30
30
  size?: [number, number, number];
31
31
  position?: [number, number, number];
32
32
  rotation?: [number, number, number];
@@ -52,7 +52,7 @@ export interface GeometryNode {
52
52
  * cross-platform bridge-parity umbrella (#909).
53
53
  */
54
54
  export interface LightNode {
55
- type: 'directional' | 'point' | 'spot';
55
+ type: "directional" | "point" | "spot";
56
56
  intensity?: number;
57
57
  color?: string;
58
58
  position?: [number, number, number];
@@ -63,12 +63,28 @@ export interface TapEvent {
63
63
  x: number;
64
64
  y: number;
65
65
  z: number;
66
- /** Name of the tapped node, if any. */
67
- nodeName?: string;
66
+ /**
67
+ * Name of the tapped model: its file's base name without extension
68
+ * (`models/robot.glb` → `robot`). Never an asset-internal mesh name — a tap
69
+ * inside a model always reports the model.
70
+ *
71
+ * **Measured on Android and iOS** (#3086) — the iOS run named the
72
+ * tapped model on every dispatch; see {@link SceneViewProps.onTap | `onTap`}.
73
+ *
74
+ * `null` — never `undefined` — when the tap hit no model: an untitled
75
+ * geometry node or nothing at all on Android, a plane or a miss in Android
76
+ * AR, and *every* `ARSceneView` tap on iOS, where `SceneViewSwift`'s
77
+ * `ARSceneView` exposes no entity hit-test hook and so can only resolve the
78
+ * surface point (#2051).
79
+ *
80
+ * Every native dispatch path writes the key, so `nodeName == null` is the one
81
+ * guard that covers both views on both platforms.
82
+ */
83
+ nodeName: string | null;
68
84
  }
69
85
  export interface PlaneDetectedEvent {
70
86
  id: string;
71
- type: 'horizontal' | 'vertical';
87
+ type: "horizontal" | "vertical";
72
88
  center: [number, number, number];
73
89
  extent: [number, number];
74
90
  }
@@ -81,7 +97,7 @@ export interface PlaneDetectedEvent {
81
97
  * back to orbit (the per-mode switch is an iOS-first v4.3.0 addition —
82
98
  * the Android side is tracked in issue #1051).
83
99
  */
84
- export type CameraControlMode = 'orbit' | 'pan' | 'firstPerson';
100
+ export type CameraControlMode = "orbit" | "pan" | "firstPerson";
85
101
  export interface SceneViewProps {
86
102
  style?: ViewStyle;
87
103
  /** HDR environment asset path (e.g. "environments/studio.hdr"). */
@@ -100,7 +116,17 @@ export interface SceneViewProps {
100
116
  * **iOS:** acknowledged but not yet rendered — see {@link LightNode}.
101
117
  */
102
118
  lightNodes?: LightNode[];
103
- /** Enable default orbit camera controls. Default: true. */
119
+ /**
120
+ * Enable default orbit camera controls. Default: `true`.
121
+ *
122
+ * @deprecated Superseded by {@link SceneViewProps.cameraControlMode}, and
123
+ * **inert on iOS**: the two would contradict each other — nothing can say
124
+ * which wins for `cameraOrbit: false, cameraControlMode: 'orbit'` — so the
125
+ * iOS bridge deliberately reads only `cameraControlMode`. Still honoured on
126
+ * Android. There is currently no way to freeze the camera from this bridge
127
+ * on iOS; `SceneViewSwift` has `cameraGesturesEnabled` but it is not exposed
128
+ * here yet.
129
+ */
104
130
  cameraOrbit?: boolean;
105
131
  /**
106
132
  * Camera interaction mode (v4.3.0). Default: `'orbit'`.
@@ -118,9 +144,39 @@ export interface SceneViewProps {
118
144
  /**
119
145
  * Called when the user taps inside the scene.
120
146
  *
121
- * The event payload carries the world-space tap coordinates. On Android the
122
- * tapped node's `nodeName` is included when the tap hits a node; on iOS AR
123
- * the tap reports the surface point only, so `nodeName` is absent there.
147
+ * Dispatched on **Android and iOS**. The iOS half was measured on an iPhone
148
+ * 17 Pro Max simulator — 5 taps on a rendering model, 5 dispatches, the
149
+ * model's name every time
150
+ * ({@link https://github.com/sceneview/sceneview/issues/3086 | #3086}).
151
+ * The sibling Flutter bridge still never fires its 3D `onTap` on iOS
152
+ * ({@link https://github.com/sceneview/sceneview/issues/3045 | #3045}); the
153
+ * same run showed that is Flutter's platform-view touch delivery, not this
154
+ * shared RealityKit path, so it does not apply here.
155
+ *
156
+ * The event payload carries the world-space position of the tapped model and
157
+ * its `nodeName` (the model file's base name without extension). A tap that
158
+ * hits no model reports `nodeName: null` — with
159
+ * the tapped node's real world position on Android when it landed on an
160
+ * (unnamed) geometry node, and `0, 0, 0` when it hit nothing at all. That
161
+ * `0, 0, 0` miss is **in practice Android-only**: iOS resolves the tap
162
+ * through RealityKit's entity-targeted gesture, which fires only on a hit,
163
+ * so a tap on empty space dispatches no `onTap` event at all — count taps
164
+ * and you will see fewer events on iOS, not a `0, 0, 0` one. (iOS emits
165
+ * `0, 0, 0` only if a hit entity resolves outside every loaded model, which
166
+ * the content root's contents make unreachable today.)
167
+ *
168
+ * On {@link ARSceneViewProps | `ARSceneView`} *what a hit reports* differs by
169
+ * platform:
170
+ * - **Android**: the AR view hit-tests the scene, so a tap on a model reports
171
+ * that model's file base name exactly as `SceneView` does; a tap on a plane
172
+ * or on nothing reports `null`.
173
+ * - **iOS**: always `null` — `SceneViewSwift.ARSceneView` exposes no entity
174
+ * hit-test hook, so the AR tap can only resolve the surface point. Tracked
175
+ * under {@link https://github.com/sceneview/sceneview/issues/2051 | #2051}.
176
+ *
177
+ * The *key* is written on every dispatch path of both views on both
178
+ * platforms, so one `nodeName == null` check remains the correct "the tap hit
179
+ * no model" test everywhere; it is never omitted and never `undefined`.
124
180
  */
125
181
  onTap?: (event: NativeSyntheticEvent<TapEvent>) => void;
126
182
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAIL,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;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;IACvD,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAMD,MAAM,WAAW,QAAQ;IACvB,0CAA0C;IAC1C,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,YAAY,GAAG,UAAU,CAAC;IAChC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1B;AAMD;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,KAAK,GAAG,aAAa,CAAC;AAEhE,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB;;;;OAIG;IACH,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B;;;;OAIG;IACH,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IAEzB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IAEtC;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;CACzD;AAED,MAAM,WAAW,gBAAiB,SAAQ,cAAc;IACtD,6CAA6C;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,kBAAkB,CAAC,KAAK,IAAI,CAAC;CAC7E;AA2CD;;;;;;;;;GASG;AACH,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAK9C,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAKlD,CAAC;AAgBF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,UAAU;IACrB,2EAA2E;IAC3E,MAAM,KAAK,WAAW,IAAI,OAAO,CAEhC;IAED,OAAO,CAAC,iBAAiB;IASzB,sCAAsC;IACtC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtB;;;;;;OAMG;IACH,IAAI,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO1C,wEAAwE;IACxE,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAMnD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"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"}