@reactvision/react-viro 2.57.2 → 2.57.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +8 -0
  2. package/android/react_viro/react_viro-release.aar +0 -0
  3. package/android/viro_renderer/viro_renderer-release.aar +0 -0
  4. package/components/AR/ViroARSceneNavigator.tsx +11 -3
  5. package/components/Studio/StudioARScene.tsx +153 -4
  6. package/components/Studio/StudioSceneErrorBoundary.tsx +48 -0
  7. package/components/Studio/StudioSceneNavigator.tsx +186 -41
  8. package/components/Studio/VRTStudioModule.ts +26 -0
  9. package/components/Studio/domain/dragConfiguration.ts +6 -4
  10. package/components/Studio/domain/materialConfig.ts +75 -42
  11. package/components/Studio/domain/physicsConfig.ts +75 -32
  12. package/components/Studio/domain/viroNodeFactory.tsx +53 -14
  13. package/components/Studio/index.ts +4 -0
  14. package/components/Studio/types.ts +3 -8
  15. package/components/Utilities/ViroVersion.ts +1 -1
  16. package/components/ViroXRSceneNavigator.tsx +2 -0
  17. package/dist/components/AR/ViroARSceneNavigator.d.ts +11 -3
  18. package/dist/components/Studio/StudioARScene.d.ts +6 -0
  19. package/dist/components/Studio/StudioARScene.js +101 -6
  20. package/dist/components/Studio/StudioSceneErrorBoundary.d.ts +28 -0
  21. package/dist/components/Studio/StudioSceneErrorBoundary.js +31 -0
  22. package/dist/components/Studio/StudioSceneNavigator.d.ts +28 -3
  23. package/dist/components/Studio/StudioSceneNavigator.js +84 -20
  24. package/dist/components/Studio/VRTStudioModule.d.ts +17 -0
  25. package/dist/components/Studio/VRTStudioModule.js +14 -0
  26. package/dist/components/Studio/domain/dragConfiguration.d.ts +5 -3
  27. package/dist/components/Studio/domain/dragConfiguration.js +5 -3
  28. package/dist/components/Studio/domain/materialConfig.d.ts +0 -1
  29. package/dist/components/Studio/domain/materialConfig.js +12 -5
  30. package/dist/components/Studio/domain/physicsConfig.d.ts +0 -1
  31. package/dist/components/Studio/domain/physicsConfig.js +18 -6
  32. package/dist/components/Studio/domain/viroNodeFactory.d.ts +2 -2
  33. package/dist/components/Studio/domain/viroNodeFactory.js +31 -18
  34. package/dist/components/Studio/index.d.ts +1 -0
  35. package/dist/components/Studio/types.d.ts +1 -0
  36. package/dist/components/Utilities/ViroVersion.d.ts +1 -1
  37. package/dist/components/Utilities/ViroVersion.js +1 -1
  38. package/dist/components/ViroXRSceneNavigator.d.ts +2 -0
  39. package/dist/index.d.ts +1 -1
  40. package/index.ts +2 -0
  41. package/ios/dist/ViroRenderer/ViroKit.framework/ARCoreCoreMLSemanticsResources.bundle/Info.plist +0 -0
  42. package/ios/dist/ViroRenderer/ViroKit.framework/ARCoreResources.bundle/Info.plist +0 -0
  43. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROARFrameiOS.h +8 -0
  44. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROARSessioniOS.h +14 -3
  45. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROFrontCameraProvider.h +34 -0
  46. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROViewAR.h +3 -1
  47. package/ios/dist/ViroRenderer/ViroKit.framework/Shaders.dat +1 -1
  48. package/ios/dist/ViroRenderer/ViroKit.framework/ViroKit +0 -0
  49. package/ios/dist/include/RVStudioWatermarkState.h +25 -0
  50. package/ios/dist/lib/libViroReact.a +0 -0
  51. package/package.json +11 -11
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  /**
3
3
  * Studio material_config parsing and Viro material definition building.
4
- * Ported from studio-go/domain/materialConfig.ts — no zod dependency.
5
4
  */
6
5
  Object.defineProperty(exports, "__esModule", { value: true });
7
6
  exports.materialConfigNeedsTimeUniform = materialConfigNeedsTimeUniform;
@@ -69,7 +68,8 @@ function injectMissingGlslDeclarations(uniforms, body) {
69
68
  result;
70
69
  }
71
70
  if (RF_VIEWPORT_RE.test(body) && !/\b_rf_vpw\b/.test(result)) {
72
- result = "uniform highp float _rf_vpw;\nuniform highp float _rf_vph;\n" + result;
71
+ result =
72
+ "uniform highp float _rf_vpw;\nuniform highp float _rf_vph;\n" + result;
73
73
  }
74
74
  return result;
75
75
  }
@@ -80,9 +80,14 @@ function injectMissingGlslDeclarations(uniforms, body) {
80
80
  */
81
81
  function mergeMaterialUniformsForViro(config) {
82
82
  const list = config.materialUniforms
83
- ? config.materialUniforms.map((u) => ({ name: u.name, type: u.type, value: u.value }))
83
+ ? config.materialUniforms.map((u) => ({
84
+ name: u.name,
85
+ type: u.type,
86
+ value: u.value,
87
+ }))
84
88
  : [];
85
- if (materialConfigNeedsTimeUniform(config) && !list.some((u) => u.name === "time")) {
89
+ if (materialConfigNeedsTimeUniform(config) &&
90
+ !list.some((u) => u.name === "time")) {
86
91
  list.push({ name: "time", type: "float", value: 0 });
87
92
  }
88
93
  if (materialConfigNeedsViewportUniforms(config)) {
@@ -184,7 +189,9 @@ function parseMaterialConfig(raw) {
184
189
  if (typeof v === "string" || v === null)
185
190
  config[key] = v;
186
191
  }
187
- if (r.shaderModifiers && typeof r.shaderModifiers === "object" && !Array.isArray(r.shaderModifiers)) {
192
+ if (r.shaderModifiers &&
193
+ typeof r.shaderModifiers === "object" &&
194
+ !Array.isArray(r.shaderModifiers)) {
188
195
  config.shaderModifiers = r.shaderModifiers;
189
196
  }
190
197
  if (Array.isArray(r.materialUniforms)) {
@@ -1,6 +1,5 @@
1
1
  /**
2
2
  * Studio physics_config and physics_world_config parsing and Viro prop building.
3
- * Ported from studio-go/domain/physicsConfig.ts — no zod dependency.
4
3
  */
5
4
  type Vec3 = [number, number, number];
6
5
  type ForceEntry = {
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  /**
3
3
  * Studio physics_config and physics_world_config parsing and Viro prop building.
4
- * Ported from studio-go/domain/physicsConfig.ts — no zod dependency.
5
4
  */
6
5
  Object.defineProperty(exports, "__esModule", { value: true });
7
6
  exports.parsePhysicsWorldConfig = parsePhysicsWorldConfig;
@@ -11,7 +10,7 @@ exports.buildViroPhysicsBody = buildViroPhysicsBody;
11
10
  exports.shouldUseKinematicPhysicsDrag = shouldUseKinematicPhysicsDrag;
12
11
  // ─── Helpers ──────────────────────────────────────────────────────────────────
13
12
  function isVec3(v) {
14
- return Array.isArray(v) && v.length === 3 && v.every((n) => typeof n === "number");
13
+ return (Array.isArray(v) && v.length === 3 && v.every((n) => typeof n === "number"));
15
14
  }
16
15
  function parseShape(raw) {
17
16
  if (!raw || typeof raw !== "object" || Array.isArray(raw))
@@ -28,7 +27,9 @@ function parseShape(raw) {
28
27
  if (!c || typeof c !== "object")
29
28
  return false;
30
29
  const ch = c;
31
- return (ch.type === "Box" || ch.type === "Sphere") && Array.isArray(ch.params) && isVec3(ch.position);
30
+ return ((ch.type === "Box" || ch.type === "Sphere") &&
31
+ Array.isArray(ch.params) &&
32
+ isVec3(ch.position));
32
33
  });
33
34
  if (children.length > 0)
34
35
  return { type: "Compound", children };
@@ -44,7 +45,11 @@ function mapShapeToViro(shape) {
44
45
  type: "Compound",
45
46
  params: [],
46
47
  children: shape.children.map((c) => {
47
- const base = { type: c.type, params: [...c.params], position: [...c.position] };
48
+ const base = {
49
+ type: c.type,
50
+ params: [...c.params],
51
+ position: [...c.position],
52
+ };
48
53
  if (c.rotation)
49
54
  base.rotation = [...c.rotation];
50
55
  return base;
@@ -134,11 +139,18 @@ function buildViroPhysicsWorld(config) {
134
139
  }
135
140
  /** Maps validated Studio physics_config to Viro `physicsBody` prop. */
136
141
  function buildViroPhysicsBody(config, options) {
137
- const kinematicDrag = options?.kinematicDragOverride === true && config.type === "Dynamic" && config.enabled;
142
+ const kinematicDrag = options?.kinematicDragOverride === true &&
143
+ config.type === "Dynamic" &&
144
+ config.enabled;
138
145
  const type = kinematicDrag ? "Kinematic" : config.type;
139
146
  const mass = kinematicDrag ? 0 : config.mass;
140
147
  const shape = mapShapeToViro(config.shape ?? { type: "Box", params: [1, 1, 1] });
141
- const body = { type, mass, shape, enabled: config.enabled };
148
+ const body = {
149
+ type,
150
+ mass,
151
+ shape,
152
+ enabled: config.enabled,
153
+ };
142
154
  if (config.restitution !== undefined)
143
155
  body.restitution = config.restitution;
144
156
  if (config.friction !== undefined)
@@ -18,6 +18,6 @@ export type NodeConfig = {
18
18
  animation?: ViroAnimationProp;
19
19
  };
20
20
  /** Clamps Z to -2 for non-trigger assets to guarantee visibility. */
21
- export declare function createNodeConfig(asset: StudioAsset, sceneNavigator: SceneNavigator | undefined, animations: StudioAnimation[], scene: StudioSceneMeta | null, onAnimationTrigger?: (targetAssetId: string, animKey: string) => void, animationStates?: Record<string, ViroAnimationProp>, onSceneChange?: (sceneId: string, sceneName: string) => void, runtimeCtx?: SequenceRuntimeContext): NodeConfig;
22
- export declare function createNode(asset: StudioAsset, sceneNavigator: SceneNavigator | undefined, animations: StudioAnimation[], scene: StudioSceneMeta | null, onAnimationTrigger?: (targetAssetId: string, animKey: string) => void, animationStates?: Record<string, ViroAnimationProp>, onAssetLoaded?: (id: string) => void, onCollision?: (viroTag: string, collidedPoint: [number, number, number], collidedNormal: [number, number, number]) => void, onSceneChange?: (sceneId: string, sceneName: string) => void, runtimeCtx?: SequenceRuntimeContext): React.ReactElement | null;
21
+ export declare function createNodeConfig(asset: StudioAsset, sceneNavigator: SceneNavigator | undefined, animations: StudioAnimation[], scene: StudioSceneMeta | null, onAnimationTrigger?: (targetAssetId: string, animKey: string) => void, animationStates?: Record<string, ViroAnimationProp>, isDragActive?: (assetId: string) => boolean, onSceneChange?: (sceneId: string, sceneName: string) => void, runtimeCtx?: SequenceRuntimeContext): NodeConfig;
22
+ export declare function createNode(asset: StudioAsset, sceneNavigator: SceneNavigator | undefined, animations: StudioAnimation[], scene: StudioSceneMeta | null, onAnimationTrigger?: (targetAssetId: string, animKey: string) => void, animationStates?: Record<string, ViroAnimationProp>, onAssetLoaded?: (id: string) => void, onCollision?: (viroTag: string, collidedPoint: [number, number, number], collidedNormal: [number, number, number]) => void, isDragActive?: (assetId: string) => boolean, notifyPhysicsDrag?: (assetId: string) => void, onSceneChange?: (sceneId: string, sceneName: string) => void, runtimeCtx?: SequenceRuntimeContext): React.ReactElement | null;
23
23
  export {};
@@ -47,7 +47,7 @@ const materialConfig_1 = require("./materialConfig");
47
47
  const dragConfiguration_1 = require("./dragConfiguration");
48
48
  const physicsConfig_1 = require("./physicsConfig");
49
49
  /** Clamps Z to -2 for non-trigger assets to guarantee visibility. */
50
- function createNodeConfig(asset, sceneNavigator, animations, scene, onAnimationTrigger, animationStates, onSceneChange, runtimeCtx) {
50
+ function createNodeConfig(asset, sceneNavigator, animations, scene, onAnimationTrigger, animationStates, isDragActive, onSceneChange, runtimeCtx) {
51
51
  const hasTriggerImage = !!asset.trigger_image_url;
52
52
  let posZ = asset.position_z ?? -2;
53
53
  if (!hasTriggerImage && posZ > -0.5) {
@@ -87,8 +87,11 @@ function createNodeConfig(asset, sceneNavigator, animations, scene, onAnimationT
87
87
  dragPlane = dragConfiguration_1.DragConfiguration.getDragPlane(scene?.plane_direction ?? "Horizontal", position);
88
88
  }
89
89
  const parsedPhysics = (0, physicsConfig_1.parsePhysicsBodyConfig)(asset.physics_config);
90
+ const dragActive = isDragActive?.(asset.id) ?? false;
90
91
  const physicsBody = parsedPhysics
91
- ? (0, physicsConfig_1.buildViroPhysicsBody)(parsedPhysics)
92
+ ? (0, physicsConfig_1.buildViroPhysicsBody)(parsedPhysics, {
93
+ kinematicDragOverride: dragActive && (0, physicsConfig_1.shouldUseKinematicPhysicsDrag)(asset, parsedPhysics),
94
+ })
92
95
  : undefined;
93
96
  const viroTag = parsedPhysics ? asset.id : undefined;
94
97
  const onClick = createOnClickHandler(asset, sceneNavigator, animations, onAnimationTrigger, onSceneChange, runtimeCtx);
@@ -136,7 +139,7 @@ function inferModelType(url) {
136
139
  return "VRX";
137
140
  return "GLB";
138
141
  }
139
- function create3DObject(asset, config, onAssetLoaded, onCollision) {
142
+ function create3DObject(asset, config, onAssetLoaded, notifyPhysicsDrag, onCollision) {
140
143
  if (!asset.file_url) {
141
144
  console.warn(`[Studio] 3D model "${asset.name}" has no file_url`);
142
145
  return null;
@@ -157,16 +160,20 @@ function create3DObject(asset, config, onAssetLoaded, onCollision) {
157
160
  return (<Viro3DObject_1.Viro3DObject key={asset.id} source={{ uri: asset.file_url }} position={config.position} rotation={config.rotation} scale={scale} type={modelType} dragType={config.dragType} dragPlane={config.dragPlane} animation={config.animation} onClick={config.onClick} renderingOrder={react_native_1.Platform.OS === "android" ? 1 : 0} onLoadEnd={() => onAssetLoaded?.(asset.id)} onError={(e) => console.error(`[Studio] 3D model "${asset.name}" error:`, e)}
158
161
  // Viro derives native canDrag from `onDrag != undefined`; without this prop
159
162
  // the drag recognizer is never attached, even when dragType is set.
160
- {...(config.dragType ? { onDrag: () => { } } : {})} {...(shaderOverrides ? { shaderOverrides } : {})} {...(config.physicsBody
163
+ {...(config.dragType
164
+ ? { onDrag: () => notifyPhysicsDrag?.(asset.id) }
165
+ : {})} {...(shaderOverrides ? { shaderOverrides } : {})} {...(config.physicsBody
161
166
  ? { physicsBody: config.physicsBody, viroTag: config.viroTag }
162
167
  : {})} {...(onCollision ? { onCollision: onCollision } : {})}/>);
163
168
  }
164
- function createImage(asset, config, onAssetLoaded) {
169
+ function createImage(asset, config, onAssetLoaded, notifyPhysicsDrag) {
165
170
  if (!asset.file_url) {
166
171
  console.warn(`[Studio] Image "${asset.name}" has no file_url`);
167
172
  return null;
168
173
  }
169
- return (<ViroImage_1.ViroImage key={asset.id} source={{ uri: asset.file_url }} position={config.position} rotation={config.rotation} scale={config.scale} dragType={config.dragType} animation={config.animation} onClick={config.onClick} onLoadEnd={() => onAssetLoaded?.(asset.id)} onError={(e) => console.error(`[Studio] Image "${asset.name}" error:`, e)} {...(config.dragType ? { onDrag: () => { } } : {})}/>);
174
+ return (<ViroImage_1.ViroImage key={asset.id} source={{ uri: asset.file_url }} position={config.position} rotation={config.rotation} scale={config.scale} dragType={config.dragType} animation={config.animation} onClick={config.onClick} onLoadEnd={() => onAssetLoaded?.(asset.id)} onError={(e) => console.error(`[Studio] Image "${asset.name}" error:`, e)} {...(config.dragType
175
+ ? { onDrag: () => notifyPhysicsDrag?.(asset.id) }
176
+ : {})}/>);
170
177
  }
171
178
  /**
172
179
  * TEXT node whose content is a {{variable}} template (the asset name). It
@@ -174,7 +181,7 @@ function createImage(asset, config, onAssetLoaded) {
174
181
  * subscribes when the template actually has placeholders). Resolution is
175
182
  * fail-soft: unknown names stay literal.
176
183
  */
177
- const VariableText = ({ asset, config, store, visible }) => {
184
+ const VariableText = ({ asset, config, store, notifyPhysicsDrag, visible }) => {
178
185
  const template = asset.name ?? "";
179
186
  const compute = () => store
180
187
  ? (0, apiRequestHelpers_1.interpolateDisplayTemplate)(template, (n) => store.get(n))
@@ -193,7 +200,9 @@ const VariableText = ({ asset, config, store, visible }) => {
193
200
  fontSize: 20,
194
201
  color: "#FFFFFF",
195
202
  textAlign: "center",
196
- }} {...(config.dragType ? { onDrag: () => { } } : {})}/>);
203
+ }} {...(config.dragType
204
+ ? { onDrag: () => notifyPhysicsDrag?.(asset.id) }
205
+ : {})}/>);
197
206
  };
198
207
  /**
199
208
  * Wraps a created node and drives its `visible` prop from the per-scene
@@ -211,32 +220,36 @@ const VisibleNode = ({ assetId, store, children }) => {
211
220
  }, [store, assetId]);
212
221
  return React.cloneElement(children, { visible });
213
222
  };
214
- function createText(asset, config, store) {
215
- return (<VariableText key={asset.id} asset={asset} config={config} store={store}/>);
223
+ function createText(asset, config, notifyPhysicsDrag, store) {
224
+ return (<VariableText key={asset.id} asset={asset} config={config} store={store} notifyPhysicsDrag={notifyPhysicsDrag}/>);
216
225
  }
217
- function createVideo(asset, config) {
226
+ function createVideo(asset, config, notifyPhysicsDrag) {
218
227
  if (!asset.file_url) {
219
228
  console.warn(`[Studio] Video "${asset.name}" has no file_url`);
220
229
  return null;
221
230
  }
222
- return (<ViroVideo_1.ViroVideo key={asset.id} source={{ uri: asset.file_url }} position={config.position} rotation={config.rotation} scale={config.scale} dragType={config.dragType} animation={config.animation} onClick={config.onClick} loop={true} muted={false} onError={(e) => console.error(`[Studio] Video "${asset.name}" error:`, e)} {...(config.dragType ? { onDrag: () => { } } : {})}/>);
231
+ return (<ViroVideo_1.ViroVideo key={asset.id} source={{ uri: asset.file_url }} position={config.position} rotation={config.rotation} scale={config.scale} dragType={config.dragType} animation={config.animation} onClick={config.onClick} loop={true} muted={false} onError={(e) => console.error(`[Studio] Video "${asset.name}" error:`, e)} {...(config.dragType
232
+ ? { onDrag: () => notifyPhysicsDrag?.(asset.id) }
233
+ : {})}/>);
223
234
  }
224
- function createNode(asset, sceneNavigator, animations, scene, onAnimationTrigger, animationStates, onAssetLoaded, onCollision, onSceneChange, runtimeCtx) {
235
+ function createNode(asset, sceneNavigator, animations, scene, onAnimationTrigger, animationStates, onAssetLoaded, onCollision, isDragActive, notifyPhysicsDrag, onSceneChange, runtimeCtx) {
225
236
  const type = resolveType(asset);
226
- const config = createNodeConfig(asset, sceneNavigator, animations, scene, onAnimationTrigger, animationStates, onSceneChange, runtimeCtx);
237
+ const config = createNodeConfig(asset, sceneNavigator, animations, scene, onAnimationTrigger, animationStates, isDragActive, onSceneChange, runtimeCtx);
227
238
  let node;
228
239
  switch (type) {
229
240
  case "3D-MODEL":
230
- node = create3DObject(asset, config, onAssetLoaded, onCollision);
241
+ // NOTE: notifyPhysicsDrag and onCollision are distinct wirings — keep both;
242
+ // a drag-only merge here once silently killed collisions.
243
+ node = create3DObject(asset, config, onAssetLoaded, notifyPhysicsDrag, onCollision);
231
244
  break;
232
245
  case "IMAGE":
233
- node = createImage(asset, config, onAssetLoaded);
246
+ node = createImage(asset, config, onAssetLoaded, notifyPhysicsDrag);
234
247
  break;
235
248
  case "TEXT":
236
- node = createText(asset, config, runtimeCtx?.variableStore);
249
+ node = createText(asset, config, notifyPhysicsDrag, runtimeCtx?.variableStore);
237
250
  break;
238
251
  case "VIDEO":
239
- node = createVideo(asset, config);
252
+ node = createVideo(asset, config, notifyPhysicsDrag);
240
253
  break;
241
254
  default:
242
255
  console.warn(`[Studio] Unknown asset type "${type}" for "${asset.name}"`);
@@ -1,3 +1,4 @@
1
1
  export { StudioARScene } from "./StudioARScene";
2
2
  export { StudioSceneNavigator } from "./StudioSceneNavigator";
3
+ export type { StudioSceneNavigatorHandle, StudioSceneNavigatorProps, } from "./StudioSceneNavigator";
3
4
  export type { StudioAnimation, StudioAsset, StudioCollisionBinding, StudioProjectApiResponse, StudioProjectAsset, StudioProjectMeta, StudioProjectOpeningScene, StudioProjectOverview, StudioProjectSceneSummary, StudioSceneCreatedBy, StudioSceneFunction, StudioSceneMeta, StudioSceneResponse, StudioSceneVariable, ViroAnimationProp, } from "./types";
@@ -282,6 +282,7 @@ export interface StudioSceneResponse {
282
282
  functions: StudioSceneFunction[];
283
283
  /** Absent in responses from backends predating the Variables feature. */
284
284
  variables?: StudioSceneVariable[];
285
+ is_free_tier?: boolean;
285
286
  meta: {
286
287
  request_id: string;
287
288
  };
@@ -1 +1 @@
1
- export declare const VIRO_VERSION = "2.57.2";
1
+ export declare const VIRO_VERSION = "2.57.4";
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VIRO_VERSION = void 0;
4
- exports.VIRO_VERSION = "2.57.2";
4
+ exports.VIRO_VERSION = "2.57.4";
@@ -47,6 +47,8 @@ export declare const ViroXRSceneNavigator: React.ForwardRefExoticComponent<ViewP
47
47
  autofocus?: boolean;
48
48
  videoQuality?: "High" | "Low";
49
49
  numberOfTrackedImages?: number;
50
+ /** AR depth/people occlusion. Flows via ...rest to ViroARSceneNavigator. */
51
+ occlusionMode?: "peopleOnly" | "depthBased";
50
52
  vrModeEnabled?: boolean;
51
53
  passthroughEnabled?: boolean;
52
54
  handTrackingEnabled?: boolean;
package/dist/index.d.ts CHANGED
@@ -81,4 +81,4 @@ import { StreamingAudioManager } from "./components/Utilities/StreamingAudioMana
81
81
  export { ViroARImageMarker, ViroARObjectMarker, ViroARTrackingTargets, ViroARPlane, ViroARPlaneSelector, ViroARScene, ViroARSceneNavigator, ViroBox, ViroButton, ViroCamera, ViroController, ViroVirtualJoystick, ViroVirtualButton, ViroGameLoop, ViroGameLoopUtils, useGameLoop, useLateUpdate, useFixedUpdate, ViroDirectionalLight, ViroFlexView, ViroGeometry, ViroLightingEnvironment, ViroImage, ViroMaterials, ViroARCamera, ViroMaterialVideo, ViroCameraTexture, ViroObjectDetector, ViroNode, ViroOmniLight, ViroOrbitCamera, ViroParticleEmitter, ViroPolygon, ViroPolyline, ViroPortal, ViroPortalScene, ViroQuad, ViroScene, ViroSurface, ViroSceneNavigator, ViroSkyBox, ViroAnimations, Viro3DObject, Viro360Image, Viro360Video, ViroAnimatedImage, ViroAmbientLight, ViroAnimatedComponent, ViroSound, ViroSoundField, ViroSpatialSound, ViroSphere, ViroSpinner, ViroSpotLight, ViroText, ViroVideo, ViroVRSceneNavigator, ViroXRSceneNavigator, ViroQuestEntryPoint, VRQuestNavigatorBridge, VRModuleOpenXR, useVRViewTag, exitVRScene, setPassthroughStyle, Viro3DSceneNavigator, StreamingAudioManager, hasOpenXRSupport, isQuest, useAnySourceHover, useAnySourcePressed, ViroARTrackingReasonConstants, ViroRecordingErrorConstants, ViroTrackingStateConstants, polarToCartesian, polarToCartesianActual, isARSupportedOnDevice, requestRequiredPermissions, checkPermissions, latLngToMercator, gpsToArWorld, ViroARSupportResponse, ViroPermissionsResult, ViroPermission, ViroHoverEvent, ViroClickEvent, ViroClickStateEvent, ViroClickStateTypes, ViroTouchEvent, ViroScrollEvent, ViroSwipeEvent, ViroFuseEvent, ViroPinchEvent, ViroPinchStateTypes, ViroRotateEvent, ViroRotateStateTypes, ViroDragEvent, ViroPlatformEvent, ViroCollisionEvent, ViroPlatformInfo, ViroCameraTransformEvent, ViroPlatformUpdateEvent, ViroCameraTransform, ViroExitViroEvent, ViroErrorEvent, ViroAnimationStartEvent, ViroAnimationFinishEvent, ViroLoadStartEvent, ViroLoadEndEvent, ViroLoadErrorEvent, ViroVideoBufferStartEvent, ViroVideoBufferEndEvent, ViroVideoUpdateTimeEvent, ViroVideoErrorEvent, ViroVideoFinishEvent, ViroAnimatedComponentStartEvent, ViroAnimatedComponentFinishEvent, ViroARAnchorRemovedEvent, ViroARAnchorUpdatedEvent, ViroARAnchorFoundEvent, ViroAnchor, ViroAnchorFoundMap, ViroAnchorUpdatedMap, ViroPlaneUpdatedMap, ViroPlaneUpdatedEvent, ViroARPlaneSizes, ViroCameraARHitTestEvent, ViroCameraARHitTest, ViroARHitTestResult, ViroARPointCloudUpdateEvent, ViroARPointCloud, ViroTrackingUpdatedEvent, ViroTrackingState, ViroTrackingReason, ViroAmbientLightUpdateEvent, ViroAmbientLightInfo, ViroWorldOrigin, ViroNativeTransformUpdateEvent, ViroControllerStatusEvent, ViroControllerStatus, ViroPortalEnterEvent, ViroPortalExitEvent, ViroSoundFinishEvent, ViroTextStyle, ViroStyle, ViroMaterial, ViroShaderModifiers, ViroShaderUniform, ViroShaderModifier, VIRO_VERSION, ViroProvider, ViroCloudAnchorState, ViroCloudAnchorProvider, ViroCloudAnchor, ViroHostCloudAnchorResult, ViroResolveCloudAnchorResult, ViroCloudAnchorStateChangeEvent, ViroGeospatialAnchorProvider, ViroEarthTrackingState, ViroVPSAvailability, ViroGeospatialAnchorType, ViroQuaternion, ViroGeospatialPose, ViroGeospatialAnchor, ViroGeospatialSupportResult, ViroEarthTrackingStateResult, ViroGeospatialPoseResult, ViroVPSAvailabilityResult, ViroCreateGeospatialAnchorResult, ViroMonocularDepthSupportResult, ViroMonocularDepthModelAvailableResult, ViroMonocularDepthPreferenceResult, ViroJoint, ViroHandJoints, ViroHandPinchEvent, ViroHandUpdateEvent, StudioSceneNavigator, StudioARScene, ViroVisionOSModule, isVisionOS, enterImmersiveSpace, exitImmersiveSpace, };
82
82
  export type { VRModuleOpenXRType, ViroPassthroughStyle };
83
83
  export type { ImmersiveSpaceStyle } from "./components/VisionOS/ViroVisionOSModule";
84
- export type { StudioSceneResponse, StudioAsset, StudioAnimation, StudioCollisionBinding, StudioSceneFunction, StudioSceneMeta, StudioProjectMeta, } from "./components/Studio";
84
+ export type { StudioSceneResponse, StudioAsset, StudioAnimation, StudioCollisionBinding, StudioSceneFunction, StudioSceneMeta, StudioProjectMeta, StudioSceneNavigatorHandle, StudioSceneNavigatorProps, } from "./components/Studio";
package/index.ts CHANGED
@@ -403,4 +403,6 @@ export type {
403
403
  StudioSceneFunction,
404
404
  StudioSceneMeta,
405
405
  StudioProjectMeta,
406
+ StudioSceneNavigatorHandle,
407
+ StudioSceneNavigatorProps,
406
408
  } from "./components/Studio";
@@ -144,6 +144,14 @@ private:
144
144
  */
145
145
  float sampleDepthTextureAtUV(std::shared_ptr<VROTexture> texture, float u, float v) const;
146
146
 
147
+ /*
148
+ Sample the LiDAR depth confidence at normalized UV coordinates (0-1 range).
149
+ Reads ARKit's ARDepthData.confidenceMap (ARConfidenceLevel: 0=low, 1=medium, 2=high)
150
+ and normalizes to [0,1] (low=0.0, medium=0.5, high=1.0). Returns -1.0 when confidence
151
+ is unavailable (no LiDAR / no confidence map).
152
+ */
153
+ float sampleConfidenceAtUV(float u, float v) const;
154
+
147
155
  /*
148
156
  Unproject a camera-image-space point (normalized [0,1] in ARKit's landscape image
149
157
  space, the same space used for [ARFrame hitTest:]) at a given metric depth (meters
@@ -126,8 +126,19 @@ public:
126
126
  void setPreferMonocularDepth(bool prefer);
127
127
  bool isPreferMonocularDepth() const;
128
128
 
129
- // Use the front (TrueDepth) camera via ARFaceTrackingConfiguration.
130
- // When true, world tracking, planes, and LiDAR are unavailable.
129
+ // Front-camera AR is supplied by an optional external module so that ViroKit
130
+ // itself never references the ARKit face-tracking / TrueDepth API. Apps that
131
+ // need it install @reactvision/react-viro-face-tracking, which registers a
132
+ // provider here. The provider returns a ready-to-run front-camera
133
+ // ARConfiguration (or nil if the device is unsupported). When no provider is
134
+ // registered, setFrontCameraEnabled(true) has no effect and AR falls through
135
+ // to world tracking.
136
+ typedef ARConfiguration * _Nullable (^VROARFrontCameraConfigProvider)(void);
137
+ static void setFrontCameraConfigProvider(VROARFrontCameraConfigProvider provider);
138
+
139
+ // Enable/disable front-camera AR. Requires a registered config provider
140
+ // (see setFrontCameraConfigProvider); otherwise it is a no-op. When active,
141
+ // world tracking, planes, and LiDAR are unavailable.
131
142
  void setFrontCameraEnabled(bool enabled);
132
143
  bool isFrontCameraEnabled() const { return _frontCameraEnabled; }
133
144
 
@@ -371,7 +382,7 @@ private:
371
382
  std::shared_ptr<VROMonocularDepthEstimator> _monocularDepthEstimator;
372
383
  bool _monocularDepthEnabled;
373
384
  bool _preferMonocularDepth; // When true, use monocular even on LiDAR devices
374
- bool _frontCameraEnabled; // When true, use ARFaceTrackingConfiguration (front camera)
385
+ bool _frontCameraEnabled; // When true and a config provider is registered, use front-camera AR
375
386
  bool _monocularDepthLoading;
376
387
  float _monocularDepthScale; // Multiplied into depth values (1.0 = no change)
377
388
  int _monocularDepthTargetFPS; // 0 = use estimator default
@@ -0,0 +1,34 @@
1
+ //
2
+ // VROFrontCameraProvider.h
3
+ // ViroKit
4
+ //
5
+ // Copyright © 2026 ReactVision. All rights reserved.
6
+ //
7
+
8
+ #import <Foundation/Foundation.h>
9
+ #import <ARKit/ARKit.h>
10
+
11
+ NS_ASSUME_NONNULL_BEGIN
12
+
13
+ /**
14
+ * VROFrontCameraProvider — Objective-C registration host for front-camera AR.
15
+ *
16
+ * ViroKit itself does NOT reference the ARKit face-tracking / TrueDepth API. An
17
+ * optional external module (@reactvision/react-viro-face-tracking) supplies a
18
+ * front-camera ARConfiguration by calling +registerConfigProvider:. That module
19
+ * discovers this class at runtime via NSClassFromString, so ViroKit carries no
20
+ * build- or link-time dependency on it (mirrors how react-viro-onnx registers
21
+ * against VRTObjectDetectorView).
22
+ *
23
+ * The registered block returns a ready-to-run front-camera ARConfiguration, or
24
+ * nil if the device does not support it. It is stored process-wide and consulted
25
+ * by VROARSessioniOS whenever front-camera AR is requested.
26
+ */
27
+ @interface VROFrontCameraProvider : NSObject
28
+
29
+ /** Register the front-camera config provider used by VROARSessioniOS (idempotent). */
30
+ + (void)registerConfigProvider:(ARConfiguration * _Nullable (^)(void))provider;
31
+
32
+ @end
33
+
34
+ NS_ASSUME_NONNULL_END
@@ -194,7 +194,9 @@ enum class VROCameraPosition;
194
194
  // Target inference rate for monocular depth. Thermal state overrides downward automatically.
195
195
  - (void)setMonocularDepthTargetFPS:(int)fps;
196
196
 
197
- // Switch to ARFaceTrackingConfiguration (front TrueDepth camera) when YES.
197
+ // Switch to front-camera AR when YES. Requires the optional face-tracking
198
+ // module to be installed (see VROARSessioniOS::setFrontCameraConfigProvider);
199
+ // otherwise this has no effect.
198
200
  - (void)setFrontCameraEnabled:(BOOL)enabled;
199
201
 
200
202
  @end
@@ -1,5 +1,5 @@
1
1
  dependencies: \
2
2
  /Users/dorantes/Documents/ViroWorkspace/virocore/ViroRenderer/Shaders.metal \
3
- /private/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.6.109.0.hR8Z6P/Metal.xctoolchain/usr/metal/32023/lib/clang/32023.883/include/metal/module.modulemap \
3
+ /private/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.6.109.0.qEW6mp/Metal.xctoolchain/usr/metal/32023/lib/clang/32023.883/include/metal/module.modulemap \
4
4
  /Users/dorantes/Documents/ViroWorkspace/virocore/ViroRenderer/VROSharedStructures.h \
5
5
  /Users/dorantes/Documents/ViroWorkspace/virocore/ViroRenderer/VRODefines.h
@@ -0,0 +1,25 @@
1
+ //
2
+ // RVStudioWatermarkState.h
3
+ // ViroReact
4
+ //
5
+
6
+ #import <Foundation/Foundation.h>
7
+
8
+ // Process-wide source of truth for the Free-tier "Powered by ReactVision
9
+ // Studio" watermark. Written only from the native rvGetScene response, never
10
+ // from JS, so a consumer cannot strip the watermark by editing JS.
11
+
12
+ /// Posted on the main queue whenever `freeTier` changes.
13
+ extern NSString *const RVStudioWatermarkDidChangeNotification;
14
+
15
+ @interface RVStudioWatermarkState : NSObject
16
+
17
+ @property (atomic, assign, readonly) BOOL freeTier;
18
+
19
+ + (instancetype)sharedState;
20
+
21
+ /// Parses an rvGetScene resolve payload ({ success, data }) and updates
22
+ /// `freeTier` from its `is_free_tier` field.
23
+ - (void)updateFromSceneResponse:(NSDictionary *)response;
24
+
25
+ @end
Binary file
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "main": "dist/index.js",
4
4
  "module": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
- "version": "2.57.2",
6
+ "version": "2.57.4",
7
7
  "license": "MIT",
8
8
  "publishConfig": {
9
9
  "registry": "https://registry.npmjs.org/"
@@ -27,12 +27,12 @@
27
27
  "prepare": "npm run build"
28
28
  },
29
29
  "peerDependencies": {
30
- "expo": ">=55.0.0 <57.0.0",
30
+ "expo": ">=55.0.0 <58.0.0",
31
31
  "react": ">=18.0.0",
32
- "react-native": ">=0.83.0 <0.86.0"
32
+ "react-native": ">=0.83.0 <0.87.0"
33
33
  },
34
34
  "engines": {
35
- "react-native": ">=0.83.0 <0.86.0"
35
+ "react-native": ">=0.83.0 <0.87.0"
36
36
  },
37
37
  "peerDependenciesMeta": {
38
38
  "expo": {
@@ -61,23 +61,23 @@
61
61
  "@babel/core": "^7.25.2",
62
62
  "@babel/preset-env": "^7.25.3",
63
63
  "@babel/preset-typescript": "^7.26.0",
64
- "@expo/config-plugins": "~56.0.8",
64
+ "@expo/config-plugins": "~57.0.0",
65
65
  "@jest/globals": "^29.7.0",
66
66
  "@react-native-community/cli": "^20.1.3",
67
67
  "@react-native-community/cli-platform-android": "^20.1.3",
68
68
  "@react-native-community/cli-platform-ios": "^20.1.3",
69
- "@react-native/babel-preset": "^0.85.3",
70
- "@react-native/eslint-config": "^0.85.3",
71
- "@react-native/metro-config": "^0.85.3",
72
- "@react-native/typescript-config": "^0.85.3",
69
+ "@react-native/babel-preset": "^0.86.0",
70
+ "@react-native/eslint-config": "^0.86.0",
71
+ "@react-native/metro-config": "^0.86.0",
72
+ "@react-native/typescript-config": "^0.86.0",
73
73
  "@types/babel__core": "^7.20.5",
74
74
  "@types/node": "^22.13.1",
75
75
  "@types/react": "~19.2.17",
76
76
  "babel-jest": "^29.7.0",
77
- "expo": "~56.0.9",
77
+ "expo": "~57.0.0",
78
78
  "jest": "^29.7.0",
79
79
  "react": "~19.2.3",
80
- "react-native": "~0.85.3",
80
+ "react-native": "~0.86.0",
81
81
  "release-it": "^17.1.1",
82
82
  "ts-node": "^10.9.2",
83
83
  "typescript": "^5.3.0"