@reactvision/react-viro 2.53.1 → 2.55.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.
Files changed (153) hide show
  1. package/README.md +85 -46
  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/ViroARCamera.tsx +5 -0
  5. package/components/AR/ViroARImageMarker.tsx +5 -0
  6. package/components/AR/ViroARObjectMarker.tsx +5 -0
  7. package/components/AR/ViroARPlane.tsx +5 -0
  8. package/components/AR/ViroARPlaneSelector.tsx +5 -0
  9. package/components/AR/ViroARScene.tsx +5 -0
  10. package/components/AR/ViroARSceneNavigator.tsx +84 -0
  11. package/components/AR/ViroCommonProps.ts +11 -0
  12. package/components/Material/ViroMaterials.ts +51 -0
  13. package/components/Studio/StudioARScene.tsx +368 -0
  14. package/components/Studio/StudioSceneNavigator.tsx +191 -0
  15. package/components/Studio/VRTStudioModule.ts +40 -0
  16. package/components/Studio/domain/animationRegistry.ts +86 -0
  17. package/components/Studio/domain/collisionBindingsRuntime.ts +93 -0
  18. package/components/Studio/domain/collisionPairKey.ts +15 -0
  19. package/components/Studio/domain/dragConfiguration.ts +48 -0
  20. package/components/Studio/domain/materialConfig.ts +276 -0
  21. package/components/Studio/domain/physicsConfig.ts +204 -0
  22. package/components/Studio/domain/sceneNavigationHandler.ts +150 -0
  23. package/components/Studio/domain/studioMaterials.ts +33 -0
  24. package/components/Studio/domain/triggerImageRegistry.ts +64 -0
  25. package/components/Studio/domain/useStudioShaderTimeUniforms.ts +51 -0
  26. package/components/Studio/domain/useStudioShaderViewportUniforms.ts +52 -0
  27. package/components/Studio/domain/viroNodeFactory.tsx +323 -0
  28. package/components/Studio/index.ts +18 -0
  29. package/components/Studio/types.ts +164 -0
  30. package/components/Types/ViroEvents.ts +53 -0
  31. package/components/Utilities/VRModuleOpenXR.ts +50 -0
  32. package/components/Utilities/VRQuestNavigatorBridge.ts +168 -0
  33. package/components/Utilities/ViroPlatform.ts +52 -0
  34. package/components/Utilities/ViroUtils.tsx +48 -0
  35. package/components/Utilities/ViroVersion.ts +1 -1
  36. package/components/Utilities/useAnySourceHover.ts +55 -0
  37. package/components/Utilities/useAnySourcePressed.ts +70 -0
  38. package/components/Viro360Image.tsx +7 -0
  39. package/components/ViroQuestEntryPoint.tsx +79 -0
  40. package/components/ViroVRSceneNavigator.tsx +44 -19
  41. package/components/ViroXRSceneNavigator.tsx +217 -0
  42. package/components/VisionOS/ViroVisionOSModule.ts +93 -0
  43. package/dist/components/AR/ViroARCamera.d.ts +1 -1
  44. package/dist/components/AR/ViroARCamera.js +5 -0
  45. package/dist/components/AR/ViroARImageMarker.d.ts +1 -1
  46. package/dist/components/AR/ViroARImageMarker.js +5 -0
  47. package/dist/components/AR/ViroARObjectMarker.d.ts +1 -1
  48. package/dist/components/AR/ViroARObjectMarker.js +5 -0
  49. package/dist/components/AR/ViroARPlane.d.ts +1 -1
  50. package/dist/components/AR/ViroARPlane.js +5 -0
  51. package/dist/components/AR/ViroARPlaneSelector.d.ts +1 -1
  52. package/dist/components/AR/ViroARPlaneSelector.js +5 -0
  53. package/dist/components/AR/ViroARScene.d.ts +1 -1
  54. package/dist/components/AR/ViroARScene.js +5 -0
  55. package/dist/components/AR/ViroARSceneNavigator.d.ts +36 -0
  56. package/dist/components/AR/ViroARSceneNavigator.js +41 -0
  57. package/dist/components/AR/ViroCommonProps.d.ts +11 -0
  58. package/dist/components/Material/ViroMaterials.d.ts +12 -0
  59. package/dist/components/Material/ViroMaterials.js +25 -0
  60. package/dist/components/ReactVisionClient.d.ts +25 -0
  61. package/dist/components/ReactVisionClient.js +11 -0
  62. package/dist/components/Studio/StudioARScene.d.ts +15 -0
  63. package/dist/components/Studio/StudioARScene.js +299 -0
  64. package/dist/components/Studio/StudioSceneNavigator.d.ts +31 -0
  65. package/dist/components/Studio/StudioSceneNavigator.js +174 -0
  66. package/dist/components/Studio/VRTStudioModule.d.ts +15 -0
  67. package/dist/components/Studio/VRTStudioModule.js +31 -0
  68. package/dist/components/Studio/domain/animationRegistry.d.ts +11 -0
  69. package/dist/components/Studio/domain/animationRegistry.js +67 -0
  70. package/dist/components/Studio/domain/collisionBindingsRuntime.d.ts +21 -0
  71. package/dist/components/Studio/domain/collisionBindingsRuntime.js +54 -0
  72. package/dist/components/Studio/domain/collisionPairKey.d.ts +8 -0
  73. package/dist/components/Studio/domain/collisionPairKey.js +15 -0
  74. package/dist/components/Studio/domain/dragConfiguration.d.ts +20 -0
  75. package/dist/components/Studio/domain/dragConfiguration.js +37 -0
  76. package/dist/components/Studio/domain/materialConfig.d.ts +56 -0
  77. package/dist/components/Studio/domain/materialConfig.js +239 -0
  78. package/dist/components/Studio/domain/physicsConfig.d.ts +69 -0
  79. package/dist/components/Studio/domain/physicsConfig.js +165 -0
  80. package/dist/components/Studio/domain/sceneNavigationHandler.d.ts +12 -0
  81. package/dist/components/Studio/domain/sceneNavigationHandler.js +112 -0
  82. package/dist/components/Studio/domain/studioMaterials.d.ts +6 -0
  83. package/dist/components/Studio/domain/studioMaterials.js +30 -0
  84. package/dist/components/Studio/domain/triggerImageRegistry.d.ts +13 -0
  85. package/dist/components/Studio/domain/triggerImageRegistry.js +47 -0
  86. package/dist/components/Studio/domain/useStudioShaderTimeUniforms.d.ts +6 -0
  87. package/dist/components/Studio/domain/useStudioShaderTimeUniforms.js +48 -0
  88. package/dist/components/Studio/domain/useStudioShaderViewportUniforms.d.ts +6 -0
  89. package/dist/components/Studio/domain/useStudioShaderViewportUniforms.js +48 -0
  90. package/dist/components/Studio/domain/viroNodeFactory.d.ts +28 -0
  91. package/dist/components/Studio/domain/viroNodeFactory.js +193 -0
  92. package/dist/components/Studio/index.d.ts +3 -0
  93. package/dist/components/Studio/index.js +7 -0
  94. package/dist/components/Studio/types.d.ts +149 -0
  95. package/dist/components/Studio/types.js +4 -0
  96. package/dist/components/Types/ViroEvents.d.ts +49 -1
  97. package/dist/components/Types/ViroEvents.js +1 -0
  98. package/dist/components/Utilities/VRModuleOpenXR.d.ts +32 -0
  99. package/dist/components/Utilities/VRModuleOpenXR.js +44 -0
  100. package/dist/components/Utilities/VRQuestNavigatorBridge.d.ts +85 -0
  101. package/dist/components/Utilities/VRQuestNavigatorBridge.js +124 -0
  102. package/dist/components/Utilities/ViroPlatform.d.ts +10 -0
  103. package/dist/components/Utilities/ViroPlatform.js +43 -0
  104. package/dist/components/Utilities/ViroUtils.d.ts +19 -0
  105. package/dist/components/Utilities/ViroUtils.js +34 -0
  106. package/dist/components/Utilities/ViroVersion.d.ts +1 -1
  107. package/dist/components/Utilities/ViroVersion.js +1 -1
  108. package/dist/components/Utilities/useAnySourceHover.d.ts +36 -0
  109. package/dist/components/Utilities/useAnySourceHover.js +48 -0
  110. package/dist/components/Utilities/useAnySourcePressed.d.ts +37 -0
  111. package/dist/components/Utilities/useAnySourcePressed.js +61 -0
  112. package/dist/components/Viro360Image.d.ts +7 -0
  113. package/dist/components/ViroQuestEntryPoint.d.ts +13 -0
  114. package/dist/components/ViroQuestEntryPoint.js +104 -0
  115. package/dist/components/ViroVRSceneNavigator.d.ts +24 -10
  116. package/dist/components/ViroVRSceneNavigator.js +21 -18
  117. package/dist/components/ViroXRSceneNavigator.d.ts +54 -0
  118. package/dist/components/ViroXRSceneNavigator.js +173 -0
  119. package/dist/components/VisionOS/ViroVisionOSModule.d.ts +65 -0
  120. package/dist/components/VisionOS/ViroVisionOSModule.js +91 -0
  121. package/dist/index.d.ts +16 -3
  122. package/dist/index.js +34 -2
  123. package/dist/plugins/withViro.d.ts +28 -1
  124. package/dist/plugins/withViroAndroid.js +312 -7
  125. package/dist/plugins/withViroIos.js +17 -8
  126. package/dist/plugins/withViroVisionOS.d.ts +24 -0
  127. package/dist/plugins/withViroVisionOS.js +265 -0
  128. package/index.ts +66 -0
  129. package/ios/ViroReact.podspec +15 -5
  130. package/ios/dist/ViroRenderer/ViroKit.framework/ARCoreCoreMLSemanticsResources.bundle/Info.plist +0 -0
  131. package/ios/dist/ViroRenderer/ViroKit.framework/ARCoreResources.bundle/Info.plist +0 -0
  132. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROARSession.h +30 -1
  133. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROARSessioniOS.h +16 -0
  134. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROGLTFLoader.h +34 -0
  135. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROInputControllerBase.h +74 -0
  136. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROInputType.h +11 -3
  137. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROMaterial.h +29 -0
  138. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROMorpher.h +4 -0
  139. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROPlatformUtil.h +13 -0
  140. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROPortal.h +17 -0
  141. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VRORenderContext.h +41 -0
  142. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VRORenderer.h +23 -0
  143. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROSemantics.h +14 -0
  144. package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROViewAR.h +11 -0
  145. package/ios/dist/ViroRenderer/ViroKit.framework/Info.plist +0 -0
  146. package/ios/dist/ViroRenderer/ViroKit.framework/Shaders.dat +1 -1
  147. package/ios/dist/ViroRenderer/ViroKit.framework/ViroKit +0 -0
  148. package/ios/dist/ViroRenderer/ViroKit.podspec +5 -0
  149. package/ios/dist/include/VRT360Image.h +1 -0
  150. package/ios/dist/include/VRTARSceneNavigator.h +7 -0
  151. package/ios/dist/include/VRTStudioModule.h +6 -0
  152. package/ios/dist/lib/libViroReact.a +0 -0
  153. package/package.json +8 -8
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.executeFunctionWithRelations = executeFunctionWithRelations;
4
+ exports.executeOnLoadFunction = executeOnLoadFunction;
5
+ const react_native_1 = require("react-native");
6
+ const ViroPlatform_1 = require("../../Utilities/ViroPlatform");
7
+ const VRTStudioModule_1 = require("../VRTStudioModule");
8
+ const ANIMATION_CHAIN_MAX_DEPTH = 10;
9
+ /**
10
+ * Resolves a scene function by ID from a flat list.
11
+ */
12
+ function resolveById(id, fns) {
13
+ return fns.find((f) => f.id === id);
14
+ }
15
+ /**
16
+ * Looks up target_asset_id for an ANIMATION-type scene function.
17
+ * The inline scene_animation only has the animation UUID — we resolve it
18
+ * from the top-level animations array.
19
+ */
20
+ function resolveAnimationTargetAssetId(animationId, animations) {
21
+ return animations.find((a) => a.id === animationId)?.target_asset_id;
22
+ }
23
+ /**
24
+ * Single dispatcher for all scene function types.
25
+ * Used by onClick, onCollision, and on_load_function triggers.
26
+ */
27
+ function executeFunctionWithRelations(fn, sceneNavigator, animations, onAnimationTrigger, depth = 0, onSceneChange) {
28
+ if (depth > ANIMATION_CHAIN_MAX_DEPTH) {
29
+ console.warn(`[Studio] Max animation chain depth (${ANIMATION_CHAIN_MAX_DEPTH}) exceeded for function ${fn.id}.`);
30
+ return;
31
+ }
32
+ if (fn.function_type === "NAVIGATION") {
33
+ const nav = fn.scene_navigation;
34
+ if (!nav?.navigate_to || !sceneNavigator)
35
+ return;
36
+ void navigateToScene(sceneNavigator, nav.navigate_to, animations, onSceneChange);
37
+ }
38
+ else if (fn.function_type === "ALERT") {
39
+ const alrt = fn.scene_alert;
40
+ if (!alrt)
41
+ return;
42
+ if (ViroPlatform_1.isQuest) {
43
+ // Alert.alert shows a 2D panel dialog — invisible in the VR compositor.
44
+ // Log it so it's not silently swallowed; in-scene VR alert UI is a TODO.
45
+ console.warn(`[Studio] Alert (Quest — not shown in VR): "${alrt.alert_title}" — ${alrt.alert_message}`);
46
+ return;
47
+ }
48
+ react_native_1.Alert.alert(alrt.alert_title ?? "Alert", alrt.alert_message ?? "", [
49
+ { text: "OK", style: "default" },
50
+ ]);
51
+ }
52
+ else if (fn.function_type === "ANIMATION") {
53
+ const anim = fn.scene_animation;
54
+ if (!anim || !onAnimationTrigger)
55
+ return;
56
+ const animLookupId = fn.animation ?? anim.id;
57
+ const targetAssetId = resolveAnimationTargetAssetId(animLookupId, animations);
58
+ if (!targetAssetId) {
59
+ console.warn(`[Studio] ANIMATION function ${fn.id}: could not resolve target_asset_id for animation ${anim.id}`);
60
+ return;
61
+ }
62
+ onAnimationTrigger(targetAssetId, anim.animation_key);
63
+ }
64
+ }
65
+ /**
66
+ * Executes the scene's on_load_function if set.
67
+ */
68
+ function executeOnLoadFunction(functionId, functions, sceneNavigator, animations, onAnimationTrigger, onSceneChange) {
69
+ const fn = resolveById(functionId, functions);
70
+ if (!fn) {
71
+ console.warn(`[Studio] on_load_function ${functionId} not found.`);
72
+ return;
73
+ }
74
+ executeFunctionWithRelations(fn, sceneNavigator, animations, onAnimationTrigger, 0, onSceneChange);
75
+ }
76
+ /**
77
+ * Navigates to a new AR scene by fetching its data via rvGetScene and
78
+ * pushing it onto the ViroARSceneNavigator stack.
79
+ *
80
+ * The sceneNavigator object exposes rvGetScene as a method — no separate
81
+ * API client needed here.
82
+ */
83
+ async function navigateToScene(sceneNavigator, targetSceneId, currentAnimations, onSceneChange) {
84
+ if (!sceneNavigator) {
85
+ console.error("[Studio] SceneNavigator not available for navigation");
86
+ react_native_1.Alert.alert("Navigation Error", "Unable to navigate to scene");
87
+ return;
88
+ }
89
+ console.log(`[Studio] Navigating to scene: ${targetSceneId}`);
90
+ try {
91
+ const result = await VRTStudioModule_1.VRTStudioModule.rvGetScene(targetSceneId);
92
+ if (!result?.success) {
93
+ throw new Error(result?.error ?? "rvGetScene failed");
94
+ }
95
+ const sceneData = JSON.parse(result.data);
96
+ // Lazy import to avoid circular dependency
97
+ const { StudioARScene } = require("../StudioARScene");
98
+ sceneNavigator.push({
99
+ scene: StudioARScene,
100
+ passProps: {
101
+ sceneData,
102
+ onSceneChange,
103
+ },
104
+ });
105
+ onSceneChange?.(targetSceneId, sceneData.scene.name ?? targetSceneId);
106
+ console.log(`[Studio] Navigated to scene: ${sceneData.scene.name}`);
107
+ }
108
+ catch (error) {
109
+ console.error("[Studio] Error navigating to scene:", error);
110
+ react_native_1.Alert.alert("Navigation Error", "Failed to load scene");
111
+ }
112
+ }
@@ -0,0 +1,6 @@
1
+ import { StudioAsset } from "../types";
2
+ /**
3
+ * Registers Viro materials for scene assets that have a valid `material_config`.
4
+ * Call synchronously after fetching assets and before rendering AR nodes.
5
+ */
6
+ export declare function registerStudioMaterialsForAssets(assets: StudioAsset[]): void;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerStudioMaterialsForAssets = registerStudioMaterialsForAssets;
4
+ const ViroMaterials_1 = require("../../Material/ViroMaterials");
5
+ const materialConfig_1 = require("./materialConfig");
6
+ /**
7
+ * Registers Viro materials for scene assets that have a valid `material_config`.
8
+ * Call synchronously after fetching assets and before rendering AR nodes.
9
+ */
10
+ function registerStudioMaterialsForAssets(assets) {
11
+ const materials = {};
12
+ for (const asset of assets) {
13
+ if (asset.asset_type_name !== "3D-MODEL")
14
+ continue;
15
+ if (asset.material_config == null)
16
+ continue;
17
+ const config = (0, materialConfig_1.parseMaterialConfig)(asset.material_config);
18
+ if (!config)
19
+ continue;
20
+ materials[(0, materialConfig_1.studioMaterialName)(asset.id)] = (0, materialConfig_1.buildViroMaterialDefinition)(config);
21
+ }
22
+ if (Object.keys(materials).length === 0)
23
+ return;
24
+ try {
25
+ ViroMaterials_1.ViroMaterials.createMaterials(materials);
26
+ }
27
+ catch (err) {
28
+ console.error("[studioMaterials] ViroMaterials.createMaterials failed", err);
29
+ }
30
+ }
@@ -0,0 +1,13 @@
1
+ import { StudioAsset } from "../types";
2
+ /**
3
+ * Registers trigger image targets with ViroReact for image recognition.
4
+ * One target per asset with trigger_image_url.
5
+ * Must be called before rendering ViroARImageMarker components.
6
+ *
7
+ * @returns Map from trigger_image_url → target name for lookup in ViroARImageMarker
8
+ */
9
+ export declare function registerTriggerImageTargets(assets: StudioAsset[]): Map<string, string>;
10
+ /**
11
+ * Cleans up trigger image targets when the scene unmounts.
12
+ */
13
+ export declare function cleanupTriggerImageTargets(targetNames: string[]): void;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerTriggerImageTargets = registerTriggerImageTargets;
4
+ exports.cleanupTriggerImageTargets = cleanupTriggerImageTargets;
5
+ const ViroARTrackingTargets_1 = require("../../AR/ViroARTrackingTargets");
6
+ const DEFAULT_PHYSICAL_WIDTH = 0.2; // meters
7
+ const DEFAULT_ORIENTATION = "Up";
8
+ /**
9
+ * Registers trigger image targets with ViroReact for image recognition.
10
+ * One target per asset with trigger_image_url.
11
+ * Must be called before rendering ViroARImageMarker components.
12
+ *
13
+ * @returns Map from trigger_image_url → target name for lookup in ViroARImageMarker
14
+ */
15
+ function registerTriggerImageTargets(assets) {
16
+ const assetsWithTrigger = assets.filter((a) => !!a.trigger_image_url);
17
+ if (assetsWithTrigger.length === 0) {
18
+ return new Map();
19
+ }
20
+ const urlToTargetName = new Map();
21
+ const targets = {};
22
+ assetsWithTrigger.forEach((asset, index) => {
23
+ const targetName = `studio-trigger-${index}`;
24
+ urlToTargetName.set(asset.trigger_image_url, targetName);
25
+ targets[targetName] = {
26
+ source: { uri: asset.trigger_image_url },
27
+ orientation: asset.trigger_image_orientation ?? DEFAULT_ORIENTATION,
28
+ physicalWidth: asset.trigger_image_physical_width_m ?? DEFAULT_PHYSICAL_WIDTH,
29
+ type: "Image",
30
+ };
31
+ });
32
+ ViroARTrackingTargets_1.ViroARTrackingTargets.createTargets(targets);
33
+ return urlToTargetName;
34
+ }
35
+ /**
36
+ * Cleans up trigger image targets when the scene unmounts.
37
+ */
38
+ function cleanupTriggerImageTargets(targetNames) {
39
+ targetNames.forEach((name) => {
40
+ try {
41
+ ViroARTrackingTargets_1.ViroARTrackingTargets.deleteTarget(name);
42
+ }
43
+ catch (error) {
44
+ console.warn(`[Studio] Failed to delete trigger target "${name}":`, error);
45
+ }
46
+ });
47
+ }
@@ -0,0 +1,6 @@
1
+ import { StudioAsset } from "../types";
2
+ /**
3
+ * Drives the `time` shader uniform for materials that use animated presets.
4
+ * Uses `setInterval(16)` and `Date.now() % 1000000` like working Viro starter kits.
5
+ */
6
+ export declare function useStudioShaderTimeUniforms(assets: StudioAsset[]): void;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useStudioShaderTimeUniforms = useStudioShaderTimeUniforms;
4
+ const react_1 = require("react");
5
+ const ViroMaterials_1 = require("../../Material/ViroMaterials");
6
+ const materialConfig_1 = require("./materialConfig");
7
+ /** ~60fps — matches Viro starter kit / shader docs. */
8
+ const TIME_TICK_MS = 16;
9
+ function computeTimeUniformPayload(assets) {
10
+ const names = [];
11
+ for (const asset of assets) {
12
+ if (asset.asset_type_name !== "3D-MODEL")
13
+ continue;
14
+ if (asset.material_config == null)
15
+ continue;
16
+ const config = (0, materialConfig_1.parseMaterialConfig)(asset.material_config);
17
+ if (!config || !(0, materialConfig_1.materialConfigNeedsTimeUniform)(config))
18
+ continue;
19
+ names.push((0, materialConfig_1.studioMaterialName)(asset.id));
20
+ }
21
+ names.sort();
22
+ return { key: names.join("|"), names };
23
+ }
24
+ /**
25
+ * Drives the `time` shader uniform for materials that use animated presets.
26
+ * Uses `setInterval(16)` and `Date.now() % 1000000` like working Viro starter kits.
27
+ */
28
+ function useStudioShaderTimeUniforms(assets) {
29
+ const payload = (0, react_1.useMemo)(() => computeTimeUniformPayload(assets), [assets]);
30
+ const payloadRef = (0, react_1.useRef)(payload);
31
+ payloadRef.current = payload;
32
+ const applyTimeUniforms = (0, react_1.useCallback)(() => {
33
+ const { names } = payloadRef.current;
34
+ if (names.length === 0)
35
+ return;
36
+ const time = Date.now() % 1_000_000;
37
+ for (const name of names) {
38
+ ViroMaterials_1.ViroMaterials.updateShaderUniform(name, "time", "float", time);
39
+ }
40
+ }, []);
41
+ (0, react_1.useEffect)(() => {
42
+ if (payload.names.length === 0)
43
+ return;
44
+ const id = setInterval(applyTimeUniforms, TIME_TICK_MS);
45
+ applyTimeUniforms();
46
+ return () => clearInterval(id);
47
+ }, [payload.key, applyTimeUniforms]);
48
+ }
@@ -0,0 +1,6 @@
1
+ import { StudioAsset } from "../types";
2
+ /**
3
+ * Pushes _rf_vpw / _rf_vph (physical pixel dimensions) to materials that sample the camera
4
+ * feed via gl_FragCoord. Called on mount and whenever the screen dimensions change.
5
+ */
6
+ export declare function useStudioShaderViewportUniforms(assets: StudioAsset[]): void;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useStudioShaderViewportUniforms = useStudioShaderViewportUniforms;
4
+ const react_1 = require("react");
5
+ const react_native_1 = require("react-native");
6
+ const ViroMaterials_1 = require("../../Material/ViroMaterials");
7
+ const materialConfig_1 = require("./materialConfig");
8
+ function computeViewportPayload(assets) {
9
+ const names = [];
10
+ for (const asset of assets) {
11
+ if (asset.asset_type_name !== "3D-MODEL")
12
+ continue;
13
+ if (asset.material_config == null)
14
+ continue;
15
+ const config = (0, materialConfig_1.parseMaterialConfig)(asset.material_config);
16
+ if (!config || !(0, materialConfig_1.materialConfigNeedsViewportUniforms)(config))
17
+ continue;
18
+ names.push((0, materialConfig_1.studioMaterialName)(asset.id));
19
+ }
20
+ names.sort();
21
+ return { key: names.join("|"), names };
22
+ }
23
+ /**
24
+ * Pushes _rf_vpw / _rf_vph (physical pixel dimensions) to materials that sample the camera
25
+ * feed via gl_FragCoord. Called on mount and whenever the screen dimensions change.
26
+ */
27
+ function useStudioShaderViewportUniforms(assets) {
28
+ const payload = (0, react_1.useMemo)(() => computeViewportPayload(assets), [assets]);
29
+ const pushViewport = (0, react_1.useCallback)(() => {
30
+ if (payload.names.length === 0)
31
+ return;
32
+ const { width, height } = react_native_1.Dimensions.get("screen");
33
+ const pr = react_native_1.PixelRatio.get();
34
+ const pw = width * pr;
35
+ const ph = height * pr;
36
+ for (const name of payload.names) {
37
+ ViroMaterials_1.ViroMaterials.updateShaderUniform(name, "_rf_vpw", "float", pw);
38
+ ViroMaterials_1.ViroMaterials.updateShaderUniform(name, "_rf_vph", "float", ph);
39
+ }
40
+ }, [payload]);
41
+ (0, react_1.useEffect)(() => {
42
+ if (payload.names.length === 0)
43
+ return;
44
+ pushViewport();
45
+ const sub = react_native_1.Dimensions.addEventListener("change", pushViewport);
46
+ return () => sub.remove();
47
+ }, [payload.key, pushViewport]);
48
+ }
@@ -0,0 +1,28 @@
1
+ import * as React from "react";
2
+ import { StudioAnimation, StudioAsset, StudioSceneMeta, ViroAnimationProp } from "../types";
3
+ type SceneNavigator = any;
4
+ export type NodeConfig = {
5
+ position: [number, number, number];
6
+ rotation: [number, number, number];
7
+ scale: [number, number, number];
8
+ dragType?: "FixedDistance" | "FixedDistanceOrigin" | "FixedToWorld" | "FixedToPlane";
9
+ dragPlane?: {
10
+ planePoint: [number, number, number];
11
+ planeNormal: [number, number, number];
12
+ maxDistance: number;
13
+ };
14
+ physicsBody?: Record<string, unknown>;
15
+ viroTag?: string;
16
+ onClick?: () => void;
17
+ animation?: ViroAnimationProp;
18
+ };
19
+ /**
20
+ * Derives the transform config for an asset.
21
+ * Clamps Z to -2 for non-trigger assets to guarantee visibility.
22
+ */
23
+ 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): NodeConfig;
24
+ /**
25
+ * Creates the appropriate Viro component for a StudioAsset.
26
+ */
27
+ 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): React.ReactElement | null;
28
+ export {};
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createNodeConfig = createNodeConfig;
37
+ exports.createNode = createNode;
38
+ const React = __importStar(require("react"));
39
+ const react_native_1 = require("react-native");
40
+ const Viro3DObject_1 = require("../../Viro3DObject");
41
+ const ViroImage_1 = require("../../ViroImage");
42
+ const ViroText_1 = require("../../ViroText");
43
+ const ViroVideo_1 = require("../../ViroVideo");
44
+ const sceneNavigationHandler_1 = require("./sceneNavigationHandler");
45
+ const materialConfig_1 = require("./materialConfig");
46
+ const dragConfiguration_1 = require("./dragConfiguration");
47
+ const physicsConfig_1 = require("./physicsConfig");
48
+ /**
49
+ * Derives the transform config for an asset.
50
+ * Clamps Z to -2 for non-trigger assets to guarantee visibility.
51
+ */
52
+ function createNodeConfig(asset, sceneNavigator, animations, scene, onAnimationTrigger, animationStates, onSceneChange) {
53
+ const hasTriggerImage = !!asset.trigger_image_url;
54
+ let posZ = asset.position_z ?? -2;
55
+ if (!hasTriggerImage && posZ > -0.5) {
56
+ console.warn(`[Studio/NodeFactory] Asset "${asset.name}" Z=${posZ} too close, clamping to -2`);
57
+ posZ = -2;
58
+ }
59
+ const position = [
60
+ asset.position_x ?? 0,
61
+ asset.position_y ?? 0,
62
+ posZ,
63
+ ];
64
+ // Apply trigger image orientation offset to rotation Z
65
+ let rotationZ = asset.rotation_z ?? 0;
66
+ if (hasTriggerImage && asset.trigger_image_orientation) {
67
+ const offsets = {
68
+ Left: -90,
69
+ Right: 90,
70
+ Down: 180,
71
+ Up: 0,
72
+ };
73
+ rotationZ += offsets[asset.trigger_image_orientation] ?? 0;
74
+ }
75
+ const rotation = [
76
+ asset.rotation_x ?? 0,
77
+ asset.rotation_y ?? 0,
78
+ rotationZ,
79
+ ];
80
+ let scaleValue = asset.scale ?? 1;
81
+ if (scaleValue < 0.01)
82
+ scaleValue = 0.1;
83
+ if (scaleValue > 10)
84
+ scaleValue = 2;
85
+ const scale = [scaleValue, scaleValue, scaleValue];
86
+ const dragType = dragConfiguration_1.DragConfiguration.getDragType(asset, scene);
87
+ let dragPlane;
88
+ if (dragType === "FixedToPlane") {
89
+ dragPlane = dragConfiguration_1.DragConfiguration.getDragPlane(scene?.plane_direction ?? "Horizontal", position);
90
+ }
91
+ const parsedPhysics = (0, physicsConfig_1.parsePhysicsBodyConfig)(asset.physics_config);
92
+ const physicsBody = parsedPhysics ? (0, physicsConfig_1.buildViroPhysicsBody)(parsedPhysics) : undefined;
93
+ const viroTag = parsedPhysics ? asset.id : undefined;
94
+ const onClick = createOnClickHandler(asset, sceneNavigator, animations, onAnimationTrigger, onSceneChange);
95
+ const animation = animationStates?.[asset.id];
96
+ return { position, rotation, scale, dragType, dragPlane, physicsBody, viroTag, onClick, animation };
97
+ }
98
+ function createOnClickHandler(asset, sceneNavigator, animations, onAnimationTrigger, onSceneChange) {
99
+ const fn = asset.scene_function;
100
+ if (!fn)
101
+ return undefined;
102
+ if (fn.function_type === "NAVIGATION" && !fn.scene_navigation?.navigate_to) {
103
+ console.warn(`[Studio] Asset "${asset.name}" has NAVIGATION but no target scene`);
104
+ return undefined;
105
+ }
106
+ if (fn.function_type === "ALERT" && !fn.scene_alert) {
107
+ console.warn(`[Studio] Asset "${asset.name}" has ALERT but no alert data`);
108
+ return undefined;
109
+ }
110
+ if (fn.function_type === "ANIMATION" && !fn.scene_animation) {
111
+ console.warn(`[Studio] Asset "${asset.name}" has ANIMATION but no animation data`);
112
+ return undefined;
113
+ }
114
+ return () => (0, sceneNavigationHandler_1.executeFunctionWithRelations)(fn, sceneNavigator, animations, onAnimationTrigger, 0, onSceneChange);
115
+ }
116
+ /** Resolves asset type from asset_type_name. */
117
+ function resolveType(asset) {
118
+ return asset.asset_type_name ?? null;
119
+ }
120
+ /** Infers 3D model format from file extension. */
121
+ function inferModelType(url) {
122
+ const ext = url.toLowerCase().split(".").pop();
123
+ if (ext === "gltf")
124
+ return "GLTF";
125
+ if (ext === "obj")
126
+ return "OBJ";
127
+ if (ext === "vrx")
128
+ return "VRX";
129
+ return "GLB";
130
+ }
131
+ function create3DObject(asset, config, onAssetLoaded, onCollision) {
132
+ if (!asset.file_url) {
133
+ console.warn(`[Studio] 3D model "${asset.name}" has no file_url`);
134
+ return null;
135
+ }
136
+ const modelType = inferModelType(asset.file_url);
137
+ // Android: slightly reduce scale for stability
138
+ const scale = react_native_1.Platform.OS === "android"
139
+ ? [
140
+ config.scale[0] * 0.8,
141
+ config.scale[1] * 0.8,
142
+ config.scale[2] * 0.8,
143
+ ]
144
+ : config.scale;
145
+ const hasMaterialConfig = (0, materialConfig_1.parseMaterialConfig)(asset.material_config) !== null;
146
+ const shaderOverrides = hasMaterialConfig ? [(0, materialConfig_1.studioMaterialName)(asset.id)] : undefined;
147
+ 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)}
148
+ // Viro derives native canDrag from `onDrag != undefined`; without this prop
149
+ // the drag recognizer is never attached, even when dragType is set.
150
+ {...(config.dragType ? { onDrag: () => { } } : {})} {...(shaderOverrides ? { shaderOverrides } : {})} {...(config.physicsBody ? { physicsBody: config.physicsBody, viroTag: config.viroTag } : {})} {...(onCollision ? { onCollision: onCollision } : {})}/>);
151
+ }
152
+ function createImage(asset, config, onAssetLoaded) {
153
+ if (!asset.file_url) {
154
+ console.warn(`[Studio] Image "${asset.name}" has no file_url`);
155
+ return null;
156
+ }
157
+ 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: () => { } } : {})}/>);
158
+ }
159
+ function createText(asset, config) {
160
+ return (<ViroText_1.ViroText key={asset.id} text={asset.name ?? ""} position={config.position} rotation={config.rotation} scale={config.scale} dragType={config.dragType} animation={config.animation} onClick={config.onClick} style={{
161
+ fontFamily: "Arial",
162
+ fontSize: 20,
163
+ color: "#FFFFFF",
164
+ textAlign: "center",
165
+ }} {...(config.dragType ? { onDrag: () => { } } : {})}/>);
166
+ }
167
+ function createVideo(asset, config) {
168
+ if (!asset.file_url) {
169
+ console.warn(`[Studio] Video "${asset.name}" has no file_url`);
170
+ return null;
171
+ }
172
+ 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: () => { } } : {})}/>);
173
+ }
174
+ /**
175
+ * Creates the appropriate Viro component for a StudioAsset.
176
+ */
177
+ function createNode(asset, sceneNavigator, animations, scene, onAnimationTrigger, animationStates, onAssetLoaded, onCollision, onSceneChange) {
178
+ const type = resolveType(asset);
179
+ const config = createNodeConfig(asset, sceneNavigator, animations, scene, onAnimationTrigger, animationStates, onSceneChange);
180
+ switch (type) {
181
+ case "3D-MODEL":
182
+ return create3DObject(asset, config, onAssetLoaded, onCollision);
183
+ case "IMAGE":
184
+ return createImage(asset, config, onAssetLoaded);
185
+ case "TEXT":
186
+ return createText(asset, config);
187
+ case "VIDEO":
188
+ return createVideo(asset, config);
189
+ default:
190
+ console.warn(`[Studio] Unknown asset type "${type}" for "${asset.name}"`);
191
+ return null;
192
+ }
193
+ }
@@ -0,0 +1,3 @@
1
+ export { StudioARScene } from "./StudioARScene";
2
+ export { StudioSceneNavigator } from "./StudioSceneNavigator";
3
+ export type { StudioAnimation, StudioAsset, StudioCollisionBinding, StudioProjectApiResponse, StudioProjectAsset, StudioProjectMeta, StudioProjectOpeningScene, StudioProjectOverview, StudioProjectSceneSummary, StudioSceneCreatedBy, StudioSceneFunction, StudioSceneMeta, StudioSceneResponse, ViroAnimationProp, } from "./types";
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StudioSceneNavigator = exports.StudioARScene = void 0;
4
+ var StudioARScene_1 = require("./StudioARScene");
5
+ Object.defineProperty(exports, "StudioARScene", { enumerable: true, get: function () { return StudioARScene_1.StudioARScene; } });
6
+ var StudioSceneNavigator_1 = require("./StudioSceneNavigator");
7
+ Object.defineProperty(exports, "StudioSceneNavigator", { enumerable: true, get: function () { return StudioSceneNavigator_1.StudioSceneNavigator; } });