@reactvision/react-viro 2.54.0 → 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.
- package/README.md +85 -46
- package/android/react_viro/react_viro-release.aar +0 -0
- package/android/viro_renderer/viro_renderer-release.aar +0 -0
- package/components/AR/ViroARCamera.tsx +5 -0
- package/components/AR/ViroARImageMarker.tsx +5 -0
- package/components/AR/ViroARObjectMarker.tsx +5 -0
- package/components/AR/ViroARPlane.tsx +5 -0
- package/components/AR/ViroARPlaneSelector.tsx +5 -0
- package/components/AR/ViroARScene.tsx +5 -0
- package/components/AR/ViroARSceneNavigator.tsx +54 -0
- package/components/Studio/StudioARScene.tsx +368 -0
- package/components/Studio/StudioSceneNavigator.tsx +191 -0
- package/components/Studio/VRTStudioModule.ts +40 -0
- package/components/Studio/domain/animationRegistry.ts +86 -0
- package/components/Studio/domain/collisionBindingsRuntime.ts +93 -0
- package/components/Studio/domain/collisionPairKey.ts +15 -0
- package/components/Studio/domain/dragConfiguration.ts +48 -0
- package/components/Studio/domain/materialConfig.ts +276 -0
- package/components/Studio/domain/physicsConfig.ts +204 -0
- package/components/Studio/domain/sceneNavigationHandler.ts +150 -0
- package/components/Studio/domain/studioMaterials.ts +33 -0
- package/components/Studio/domain/triggerImageRegistry.ts +64 -0
- package/components/Studio/domain/useStudioShaderTimeUniforms.ts +51 -0
- package/components/Studio/domain/useStudioShaderViewportUniforms.ts +52 -0
- package/components/Studio/domain/viroNodeFactory.tsx +323 -0
- package/components/Studio/index.ts +18 -0
- package/components/Studio/types.ts +164 -0
- package/components/Types/ViroEvents.ts +53 -0
- package/components/Utilities/VRModuleOpenXR.ts +50 -0
- package/components/Utilities/VRQuestNavigatorBridge.ts +168 -0
- package/components/Utilities/ViroPlatform.ts +52 -0
- package/components/Utilities/ViroVersion.ts +1 -1
- package/components/Utilities/useAnySourceHover.ts +55 -0
- package/components/Utilities/useAnySourcePressed.ts +70 -0
- package/components/ViroQuestEntryPoint.tsx +79 -0
- package/components/ViroVRSceneNavigator.tsx +44 -19
- package/components/ViroXRSceneNavigator.tsx +217 -0
- package/components/VisionOS/ViroVisionOSModule.ts +93 -0
- package/dist/components/AR/ViroARCamera.d.ts +1 -1
- package/dist/components/AR/ViroARCamera.js +5 -0
- package/dist/components/AR/ViroARImageMarker.d.ts +1 -1
- package/dist/components/AR/ViroARImageMarker.js +5 -0
- package/dist/components/AR/ViroARObjectMarker.d.ts +1 -1
- package/dist/components/AR/ViroARObjectMarker.js +5 -0
- package/dist/components/AR/ViroARPlane.d.ts +1 -1
- package/dist/components/AR/ViroARPlane.js +5 -0
- package/dist/components/AR/ViroARPlaneSelector.d.ts +1 -1
- package/dist/components/AR/ViroARPlaneSelector.js +5 -0
- package/dist/components/AR/ViroARScene.d.ts +1 -1
- package/dist/components/AR/ViroARScene.js +5 -0
- package/dist/components/AR/ViroARSceneNavigator.d.ts +13 -0
- package/dist/components/AR/ViroARSceneNavigator.js +36 -0
- package/dist/components/Studio/StudioARScene.d.ts +15 -0
- package/dist/components/Studio/StudioARScene.js +299 -0
- package/dist/components/Studio/StudioSceneNavigator.d.ts +31 -0
- package/dist/components/Studio/StudioSceneNavigator.js +174 -0
- package/dist/components/Studio/VRTStudioModule.d.ts +15 -0
- package/dist/components/Studio/VRTStudioModule.js +31 -0
- package/dist/components/Studio/domain/animationRegistry.d.ts +11 -0
- package/dist/components/Studio/domain/animationRegistry.js +67 -0
- package/dist/components/Studio/domain/collisionBindingsRuntime.d.ts +21 -0
- package/dist/components/Studio/domain/collisionBindingsRuntime.js +54 -0
- package/dist/components/Studio/domain/collisionPairKey.d.ts +8 -0
- package/dist/components/Studio/domain/collisionPairKey.js +15 -0
- package/dist/components/Studio/domain/dragConfiguration.d.ts +20 -0
- package/dist/components/Studio/domain/dragConfiguration.js +37 -0
- package/dist/components/Studio/domain/materialConfig.d.ts +56 -0
- package/dist/components/Studio/domain/materialConfig.js +239 -0
- package/dist/components/Studio/domain/physicsConfig.d.ts +69 -0
- package/dist/components/Studio/domain/physicsConfig.js +165 -0
- package/dist/components/Studio/domain/sceneNavigationHandler.d.ts +12 -0
- package/dist/components/Studio/domain/sceneNavigationHandler.js +112 -0
- package/dist/components/Studio/domain/studioMaterials.d.ts +6 -0
- package/dist/components/Studio/domain/studioMaterials.js +30 -0
- package/dist/components/Studio/domain/triggerImageRegistry.d.ts +13 -0
- package/dist/components/Studio/domain/triggerImageRegistry.js +47 -0
- package/dist/components/Studio/domain/useStudioShaderTimeUniforms.d.ts +6 -0
- package/dist/components/Studio/domain/useStudioShaderTimeUniforms.js +48 -0
- package/dist/components/Studio/domain/useStudioShaderViewportUniforms.d.ts +6 -0
- package/dist/components/Studio/domain/useStudioShaderViewportUniforms.js +48 -0
- package/dist/components/Studio/domain/viroNodeFactory.d.ts +28 -0
- package/dist/components/Studio/domain/viroNodeFactory.js +193 -0
- package/dist/components/Studio/index.d.ts +3 -0
- package/dist/components/Studio/index.js +7 -0
- package/dist/components/Studio/types.d.ts +149 -0
- package/dist/components/Studio/types.js +4 -0
- package/dist/components/Types/ViroEvents.d.ts +49 -1
- package/dist/components/Types/ViroEvents.js +1 -0
- package/dist/components/Utilities/VRModuleOpenXR.d.ts +32 -0
- package/dist/components/Utilities/VRModuleOpenXR.js +44 -0
- package/dist/components/Utilities/VRQuestNavigatorBridge.d.ts +85 -0
- package/dist/components/Utilities/VRQuestNavigatorBridge.js +124 -0
- package/dist/components/Utilities/ViroPlatform.d.ts +10 -0
- package/dist/components/Utilities/ViroPlatform.js +43 -0
- package/dist/components/Utilities/ViroVersion.d.ts +1 -1
- package/dist/components/Utilities/ViroVersion.js +1 -1
- package/dist/components/Utilities/useAnySourceHover.d.ts +36 -0
- package/dist/components/Utilities/useAnySourceHover.js +48 -0
- package/dist/components/Utilities/useAnySourcePressed.d.ts +37 -0
- package/dist/components/Utilities/useAnySourcePressed.js +61 -0
- package/dist/components/ViroQuestEntryPoint.d.ts +13 -0
- package/dist/components/ViroQuestEntryPoint.js +104 -0
- package/dist/components/ViroVRSceneNavigator.d.ts +24 -10
- package/dist/components/ViroVRSceneNavigator.js +21 -18
- package/dist/components/ViroXRSceneNavigator.d.ts +54 -0
- package/dist/components/ViroXRSceneNavigator.js +173 -0
- package/dist/components/VisionOS/ViroVisionOSModule.d.ts +65 -0
- package/dist/components/VisionOS/ViroVisionOSModule.js +91 -0
- package/dist/index.d.ts +15 -2
- package/dist/index.js +32 -2
- package/dist/plugins/withViro.d.ts +17 -1
- package/dist/plugins/withViroAndroid.js +312 -7
- package/dist/plugins/withViroIos.js +5 -0
- package/dist/plugins/withViroVisionOS.d.ts +24 -0
- package/dist/plugins/withViroVisionOS.js +265 -0
- package/index.ts +58 -0
- package/ios/ViroReact.podspec +13 -4
- package/ios/dist/ViroRenderer/ViroKit.framework/ARCoreCoreMLSemanticsResources.bundle/Info.plist +0 -0
- package/ios/dist/ViroRenderer/ViroKit.framework/ARCoreResources.bundle/Info.plist +0 -0
- package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROARSession.h +10 -0
- package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROARSessioniOS.h +4 -0
- package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROInputControllerBase.h +74 -0
- package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROInputType.h +11 -3
- package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROPlatformUtil.h +13 -0
- package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VRORenderer.h +8 -0
- package/ios/dist/ViroRenderer/ViroKit.framework/Info.plist +0 -0
- package/ios/dist/ViroRenderer/ViroKit.framework/Shaders.dat +1 -1
- package/ios/dist/ViroRenderer/ViroKit.framework/ViroKit +0 -0
- package/ios/dist/ViroRenderer/ViroKit.podspec +5 -0
- package/ios/dist/include/VRTARSceneNavigator.h +3 -0
- package/ios/dist/include/VRTStudioModule.h +6 -0
- package/ios/dist/lib/libViroReact.a +0 -0
- package/package.json +1 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VRModuleOpenXR = void 0;
|
|
4
|
+
exports.exitVRScene = exitVRScene;
|
|
5
|
+
exports.useVRViewTag = useVRViewTag;
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
const react_native_1 = require("react-native");
|
|
8
|
+
const VRQuestNavigatorBridge_1 = require("./VRQuestNavigatorBridge");
|
|
9
|
+
/**
|
|
10
|
+
* Finishes VRActivity and returns the user to the panel (MainActivity).
|
|
11
|
+
* Safe to call on any platform — no-op when VRLauncher is unavailable.
|
|
12
|
+
*/
|
|
13
|
+
function exitVRScene() {
|
|
14
|
+
VRQuestNavigatorBridge_1.VRQuestNavigatorBridge.setVRActive(false);
|
|
15
|
+
react_native_1.NativeModules.VRLauncher
|
|
16
|
+
?.exitVRScene?.();
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Typed reference to the VRModuleOpenXR native module.
|
|
20
|
+
* undefined when not running on Meta Quest (no-op calls are safe via optional chaining).
|
|
21
|
+
*/
|
|
22
|
+
exports.VRModuleOpenXR = react_native_1.NativeModules.VRModuleOpenXR ?? undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Returns the live viewTag of the ViroVRSceneNavigator running in VRActivity,
|
|
25
|
+
* kept in sync via VRQuestNavigatorBridge. null until ViroQuestEntryPoint has
|
|
26
|
+
* mounted and published the tag.
|
|
27
|
+
*
|
|
28
|
+
* Use this inside VR scenes when you need to call VRModuleOpenXR methods:
|
|
29
|
+
*
|
|
30
|
+
* ```tsx
|
|
31
|
+
* function MyVRScene() {
|
|
32
|
+
* const viewTag = useVRViewTag();
|
|
33
|
+
* const recenter = () => {
|
|
34
|
+
* if (viewTag != null) VRModuleOpenXR?.recenterTracking?.(viewTag);
|
|
35
|
+
* };
|
|
36
|
+
* return <ViroScene>...</ViroScene>;
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
function useVRViewTag() {
|
|
41
|
+
const [tag, setTag] = (0, react_1.useState)(() => VRQuestNavigatorBridge_1.VRQuestNavigatorBridge.getViewTag());
|
|
42
|
+
(0, react_1.useEffect)(() => VRQuestNavigatorBridge_1.VRQuestNavigatorBridge.onViewTag(setTag), []);
|
|
43
|
+
return tag;
|
|
44
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VRQuestNavigatorBridge
|
|
3
|
+
*
|
|
4
|
+
* Carries VR "intents" and navigator operations from panel-Activity component
|
|
5
|
+
* trees to VRActivity. Both activities run in the same process and share the
|
|
6
|
+
* same Hermes JS engine, so a module-level store is sufficient — no native
|
|
7
|
+
* round-trip needed.
|
|
8
|
+
*
|
|
9
|
+
* Flow:
|
|
10
|
+
* Panel (MainActivity)
|
|
11
|
+
* ViroXRSceneNavigator mounts
|
|
12
|
+
* → setIntent(scene, config) — stores intent, notifies ViroQuestEntryPoint
|
|
13
|
+
* → launchVRScene() — OS switches to VRActivity
|
|
14
|
+
* → ref.push(StudioScene) — dispatchOp() queues the op
|
|
15
|
+
*
|
|
16
|
+
* VRActivity mounts VRQuestScene → ViroQuestEntryPoint
|
|
17
|
+
* → onIntent cb fires — reads intentKey + initialScene + rendererConfig
|
|
18
|
+
* → renders ViroVRSceneNavigator key={intentKey} (fresh mount per intent)
|
|
19
|
+
* → ViroQuestEntryPoint captures viewTag → setViewTag()
|
|
20
|
+
* → subscribeOps() drains queued ops — push(StudioScene) arrives
|
|
21
|
+
*
|
|
22
|
+
* Each call to setIntent() generates a new intentKey. ViroQuestEntryPoint
|
|
23
|
+
* uses key={intentKey} on ViroVRSceneNavigator, guaranteeing a clean navigator
|
|
24
|
+
* stack whenever a different panel screen activates VR.
|
|
25
|
+
*/
|
|
26
|
+
export type VRNavigatorOp = {
|
|
27
|
+
type: "push";
|
|
28
|
+
scene: any;
|
|
29
|
+
} | {
|
|
30
|
+
type: "pop";
|
|
31
|
+
} | {
|
|
32
|
+
type: "popN";
|
|
33
|
+
n: number;
|
|
34
|
+
} | {
|
|
35
|
+
type: "replace";
|
|
36
|
+
scene: any;
|
|
37
|
+
} | {
|
|
38
|
+
type: "jump";
|
|
39
|
+
scene: any;
|
|
40
|
+
};
|
|
41
|
+
/** Renderer flags forwarded from ViroXRSceneNavigator to ViroVRSceneNavigator. */
|
|
42
|
+
export type VRQuestRendererConfig = {
|
|
43
|
+
hdrEnabled?: boolean;
|
|
44
|
+
pbrEnabled?: boolean;
|
|
45
|
+
bloomEnabled?: boolean;
|
|
46
|
+
shadowsEnabled?: boolean;
|
|
47
|
+
multisamplingEnabled?: boolean;
|
|
48
|
+
vrModeEnabled?: boolean;
|
|
49
|
+
passthroughEnabled?: boolean;
|
|
50
|
+
handTrackingEnabled?: boolean;
|
|
51
|
+
debug?: boolean;
|
|
52
|
+
onExitViro?: () => void;
|
|
53
|
+
};
|
|
54
|
+
export type VRQuestIntent = {
|
|
55
|
+
intentKey: string;
|
|
56
|
+
initialScene: any;
|
|
57
|
+
rendererConfig?: VRQuestRendererConfig;
|
|
58
|
+
};
|
|
59
|
+
export declare const VRQuestNavigatorBridge: {
|
|
60
|
+
/**
|
|
61
|
+
* Record the scene and renderer config that VRActivity should use, and
|
|
62
|
+
* return a unique intent key. Call launchVRScene() after this.
|
|
63
|
+
*/
|
|
64
|
+
setIntent(initialScene: any, rendererConfig?: VRQuestRendererConfig): string;
|
|
65
|
+
/** Current intent (may be null if VR has never been launched). */
|
|
66
|
+
getIntent(): VRQuestIntent | null;
|
|
67
|
+
/**
|
|
68
|
+
* Subscribe to intent changes. Fires immediately with the current intent if
|
|
69
|
+
* one exists so that ViroQuestEntryPoint can render even if it mounts after
|
|
70
|
+
* setIntent() was called.
|
|
71
|
+
*/
|
|
72
|
+
onIntent(cb: (intent: VRQuestIntent) => void): () => void;
|
|
73
|
+
dispatchOp(op: VRNavigatorOp): void;
|
|
74
|
+
subscribeOps(cb: (op: VRNavigatorOp) => void): () => void;
|
|
75
|
+
setVRActive(active: boolean): void;
|
|
76
|
+
isVRActive(): boolean;
|
|
77
|
+
setViewTag(tag: number | null): void;
|
|
78
|
+
getViewTag(): number | null;
|
|
79
|
+
/**
|
|
80
|
+
* Subscribe to viewTag changes. Fires immediately with the current value.
|
|
81
|
+
* Use this inside VR scenes that need VRModuleOpenXR (recenterTracking,
|
|
82
|
+
* setPassthroughEnabled) without a direct ref to ViroVRSceneNavigator.
|
|
83
|
+
*/
|
|
84
|
+
onViewTag(cb: (tag: number | null) => void): () => void;
|
|
85
|
+
};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* VRQuestNavigatorBridge
|
|
4
|
+
*
|
|
5
|
+
* Carries VR "intents" and navigator operations from panel-Activity component
|
|
6
|
+
* trees to VRActivity. Both activities run in the same process and share the
|
|
7
|
+
* same Hermes JS engine, so a module-level store is sufficient — no native
|
|
8
|
+
* round-trip needed.
|
|
9
|
+
*
|
|
10
|
+
* Flow:
|
|
11
|
+
* Panel (MainActivity)
|
|
12
|
+
* ViroXRSceneNavigator mounts
|
|
13
|
+
* → setIntent(scene, config) — stores intent, notifies ViroQuestEntryPoint
|
|
14
|
+
* → launchVRScene() — OS switches to VRActivity
|
|
15
|
+
* → ref.push(StudioScene) — dispatchOp() queues the op
|
|
16
|
+
*
|
|
17
|
+
* VRActivity mounts VRQuestScene → ViroQuestEntryPoint
|
|
18
|
+
* → onIntent cb fires — reads intentKey + initialScene + rendererConfig
|
|
19
|
+
* → renders ViroVRSceneNavigator key={intentKey} (fresh mount per intent)
|
|
20
|
+
* → ViroQuestEntryPoint captures viewTag → setViewTag()
|
|
21
|
+
* → subscribeOps() drains queued ops — push(StudioScene) arrives
|
|
22
|
+
*
|
|
23
|
+
* Each call to setIntent() generates a new intentKey. ViroQuestEntryPoint
|
|
24
|
+
* uses key={intentKey} on ViroVRSceneNavigator, guaranteeing a clean navigator
|
|
25
|
+
* stack whenever a different panel screen activates VR.
|
|
26
|
+
*/
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.VRQuestNavigatorBridge = void 0;
|
|
29
|
+
// ── Intent store ────────────────────────────────────────────────────────────
|
|
30
|
+
let _intent = null;
|
|
31
|
+
const _intentListeners = new Set();
|
|
32
|
+
// ── Op queue ─────────────────────────────────────────────────────────────────
|
|
33
|
+
const _opListeners = new Set();
|
|
34
|
+
const _opQueue = [];
|
|
35
|
+
let _opCounter = 0;
|
|
36
|
+
// ── VR active flag ────────────────────────────────────────────────────────────
|
|
37
|
+
// True while VRActivity is running. Set to true just before launchVRScene(),
|
|
38
|
+
// set to false by exitVRScene(). The AppState-based relaunch in
|
|
39
|
+
// ViroXRSceneNavigator checks this so it only fires for system-level
|
|
40
|
+
// backgrounding (Quest menu / home), not for explicit exits.
|
|
41
|
+
let _vrActive = false;
|
|
42
|
+
// ── ViewTag store ─────────────────────────────────────────────────────────────
|
|
43
|
+
// ViroQuestEntryPoint populates this after ViroVRSceneNavigator mounts.
|
|
44
|
+
// Panel-side code (e.g. VRModuleOpenXR.recenterTracking) reads it to target
|
|
45
|
+
// the live native view without needing a direct ref to ViroVRSceneNavigator.
|
|
46
|
+
let _viewTag = null;
|
|
47
|
+
const _viewTagListeners = new Set();
|
|
48
|
+
exports.VRQuestNavigatorBridge = {
|
|
49
|
+
// ── Called by ViroXRSceneNavigator when mounting on Quest ──────────────────
|
|
50
|
+
/**
|
|
51
|
+
* Record the scene and renderer config that VRActivity should use, and
|
|
52
|
+
* return a unique intent key. Call launchVRScene() after this.
|
|
53
|
+
*/
|
|
54
|
+
setIntent(initialScene, rendererConfig) {
|
|
55
|
+
const intentKey = `vr-${Date.now()}-${++_opCounter}`;
|
|
56
|
+
_intent = { intentKey, initialScene, rendererConfig };
|
|
57
|
+
// Clear any stale ops from the previous intent.
|
|
58
|
+
_opQueue.length = 0;
|
|
59
|
+
_intentListeners.forEach((l) => l(_intent));
|
|
60
|
+
return intentKey;
|
|
61
|
+
},
|
|
62
|
+
/** Current intent (may be null if VR has never been launched). */
|
|
63
|
+
getIntent() {
|
|
64
|
+
return _intent;
|
|
65
|
+
},
|
|
66
|
+
/**
|
|
67
|
+
* Subscribe to intent changes. Fires immediately with the current intent if
|
|
68
|
+
* one exists so that ViroQuestEntryPoint can render even if it mounts after
|
|
69
|
+
* setIntent() was called.
|
|
70
|
+
*/
|
|
71
|
+
onIntent(cb) {
|
|
72
|
+
_intentListeners.add(cb);
|
|
73
|
+
if (_intent)
|
|
74
|
+
cb(_intent);
|
|
75
|
+
return () => {
|
|
76
|
+
_intentListeners.delete(cb);
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
// ── Called by ViroXRSceneNavigator ref (push / pop / etc.) ────────────────
|
|
80
|
+
dispatchOp(op) {
|
|
81
|
+
if (_opListeners.size > 0) {
|
|
82
|
+
_opListeners.forEach((l) => l(op));
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
_opQueue.push(op);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
// ── Called by ViroQuestEntryPoint after ViroVRSceneNavigator mounts ────────
|
|
89
|
+
subscribeOps(cb) {
|
|
90
|
+
_opListeners.add(cb);
|
|
91
|
+
const pending = _opQueue.splice(0);
|
|
92
|
+
pending.forEach((op) => cb(op));
|
|
93
|
+
return () => {
|
|
94
|
+
_opListeners.delete(cb);
|
|
95
|
+
};
|
|
96
|
+
},
|
|
97
|
+
// ── VR active flag ────────────────────────────────────────────────────────
|
|
98
|
+
setVRActive(active) {
|
|
99
|
+
_vrActive = active;
|
|
100
|
+
},
|
|
101
|
+
isVRActive() {
|
|
102
|
+
return _vrActive;
|
|
103
|
+
},
|
|
104
|
+
// ── ViewTag — native node handle of the live ViroVRSceneNavigator ──────────
|
|
105
|
+
setViewTag(tag) {
|
|
106
|
+
_viewTag = tag;
|
|
107
|
+
_viewTagListeners.forEach((l) => l(tag));
|
|
108
|
+
},
|
|
109
|
+
getViewTag() {
|
|
110
|
+
return _viewTag;
|
|
111
|
+
},
|
|
112
|
+
/**
|
|
113
|
+
* Subscribe to viewTag changes. Fires immediately with the current value.
|
|
114
|
+
* Use this inside VR scenes that need VRModuleOpenXR (recenterTracking,
|
|
115
|
+
* setPassthroughEnabled) without a direct ref to ViroVRSceneNavigator.
|
|
116
|
+
*/
|
|
117
|
+
onViewTag(cb) {
|
|
118
|
+
_viewTagListeners.add(cb);
|
|
119
|
+
cb(_viewTag);
|
|
120
|
+
return () => {
|
|
121
|
+
_viewTagListeners.delete(cb);
|
|
122
|
+
};
|
|
123
|
+
},
|
|
124
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const isQuest: boolean;
|
|
2
|
+
/**
|
|
3
|
+
* True when this app build includes the OpenXR VR native module (i.e. the
|
|
4
|
+
* Quest variant of react-viro is registered in `MainApplication`). Does NOT
|
|
5
|
+
* imply the current device is a Quest — for that, use `isQuest`.
|
|
6
|
+
*
|
|
7
|
+
* Useful when you need to decide whether `ViroVRSceneNavigator` *could* render
|
|
8
|
+
* if you forced VR mode (e.g., for in-app build diagnostics).
|
|
9
|
+
*/
|
|
10
|
+
export declare const hasOpenXRSupport: boolean;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hasOpenXRSupport = exports.isQuest = void 0;
|
|
4
|
+
const react_native_1 = require("react-native");
|
|
5
|
+
/**
|
|
6
|
+
* True only on actual Meta Quest hardware (Quest 1/2/Pro/3/3S).
|
|
7
|
+
*
|
|
8
|
+
* Detection is based on `Platform.constants` (Android `Build.MANUFACTURER`,
|
|
9
|
+
* `BRAND`, `MODEL`) — NOT on the presence of `NativeModules.VRModuleOpenXR`.
|
|
10
|
+
* The OpenXR module ships with any app built against the Quest variant of
|
|
11
|
+
* react-viro and is therefore present on regular Android phones too when the
|
|
12
|
+
* same APK targets both phone and Quest. Branding strings are the
|
|
13
|
+
* authoritative signal for "is the user wearing a Quest right now".
|
|
14
|
+
*
|
|
15
|
+
* Quest 1/2/Pro: Manufacturer="Oculus", Brand="oculus"
|
|
16
|
+
* Quest 3/3S: Manufacturer="Meta", Brand="meta"
|
|
17
|
+
*/
|
|
18
|
+
function detectQuest() {
|
|
19
|
+
if (react_native_1.Platform.OS !== "android")
|
|
20
|
+
return false;
|
|
21
|
+
const c = (react_native_1.Platform.constants ?? {});
|
|
22
|
+
const manufacturer = (c.Manufacturer ?? "").toLowerCase();
|
|
23
|
+
const brand = (c.Brand ?? "").toLowerCase();
|
|
24
|
+
const model = (c.Model ?? "").toLowerCase();
|
|
25
|
+
if (manufacturer === "oculus" ||
|
|
26
|
+
manufacturer === "meta" ||
|
|
27
|
+
brand === "oculus" ||
|
|
28
|
+
brand === "meta") {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
// Defensive: future hardware shipping under new manufacturer strings.
|
|
32
|
+
return /\bquest\b/.test(model);
|
|
33
|
+
}
|
|
34
|
+
exports.isQuest = detectQuest();
|
|
35
|
+
/**
|
|
36
|
+
* True when this app build includes the OpenXR VR native module (i.e. the
|
|
37
|
+
* Quest variant of react-viro is registered in `MainApplication`). Does NOT
|
|
38
|
+
* imply the current device is a Quest — for that, use `isQuest`.
|
|
39
|
+
*
|
|
40
|
+
* Useful when you need to decide whether `ViroVRSceneNavigator` *could* render
|
|
41
|
+
* if you forced VR mode (e.g., for in-app build diagnostics).
|
|
42
|
+
*/
|
|
43
|
+
exports.hasOpenXRSupport = react_native_1.NativeModules.VRModuleOpenXR !== undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VIRO_VERSION = "2.
|
|
1
|
+
export declare const VIRO_VERSION = "2.55.0";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Viro3DPoint } from "../Types/ViroUtils";
|
|
2
|
+
/**
|
|
3
|
+
* Aggregate `onHover` state across all input sources.
|
|
4
|
+
*
|
|
5
|
+
* On Quest (and any other backend that supports multiple simultaneous
|
|
6
|
+
* pointers — e.g. left + right controllers, or controller + tracked hand),
|
|
7
|
+
* Viro fires the node's `onHover` callback **per source**. A second pointer
|
|
8
|
+
* sweeping over an already-hovered node would otherwise produce spurious
|
|
9
|
+
* enter/exit toggles in JS even though the visual hover should remain "on".
|
|
10
|
+
*
|
|
11
|
+
* This hook tracks each source ID independently and exposes a single
|
|
12
|
+
* aggregated boolean — `true` whenever **any** source is hovering the node.
|
|
13
|
+
* Apps that don't care about per-source distinction (the common case for
|
|
14
|
+
* UI buttons) can just consume the boolean.
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* ```tsx
|
|
18
|
+
* function MyButton() {
|
|
19
|
+
* const [hovered, onHover] = useAnySourceHover();
|
|
20
|
+
* return (
|
|
21
|
+
* <ViroNode onHover={onHover}>
|
|
22
|
+
* <ViroQuad materials={[hovered ? "btnHover" : "btnIdle"]} ... />
|
|
23
|
+
* </ViroNode>
|
|
24
|
+
* );
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* The handler signature matches Viro's `onHover` prop directly — pass it as
|
|
29
|
+
* `onHover={onHover}` with no wrapper. Internally the hook deduplicates per
|
|
30
|
+
* source so a sequence of `(true, …, src=A)` events from the same source
|
|
31
|
+
* produces at most one re-render.
|
|
32
|
+
*/
|
|
33
|
+
export declare function useAnySourceHover(): readonly [
|
|
34
|
+
boolean,
|
|
35
|
+
(isHovering: boolean, position: Viro3DPoint, source: unknown) => void
|
|
36
|
+
];
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useAnySourceHover = useAnySourceHover;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
/**
|
|
6
|
+
* Aggregate `onHover` state across all input sources.
|
|
7
|
+
*
|
|
8
|
+
* On Quest (and any other backend that supports multiple simultaneous
|
|
9
|
+
* pointers — e.g. left + right controllers, or controller + tracked hand),
|
|
10
|
+
* Viro fires the node's `onHover` callback **per source**. A second pointer
|
|
11
|
+
* sweeping over an already-hovered node would otherwise produce spurious
|
|
12
|
+
* enter/exit toggles in JS even though the visual hover should remain "on".
|
|
13
|
+
*
|
|
14
|
+
* This hook tracks each source ID independently and exposes a single
|
|
15
|
+
* aggregated boolean — `true` whenever **any** source is hovering the node.
|
|
16
|
+
* Apps that don't care about per-source distinction (the common case for
|
|
17
|
+
* UI buttons) can just consume the boolean.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* ```tsx
|
|
21
|
+
* function MyButton() {
|
|
22
|
+
* const [hovered, onHover] = useAnySourceHover();
|
|
23
|
+
* return (
|
|
24
|
+
* <ViroNode onHover={onHover}>
|
|
25
|
+
* <ViroQuad materials={[hovered ? "btnHover" : "btnIdle"]} ... />
|
|
26
|
+
* </ViroNode>
|
|
27
|
+
* );
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* The handler signature matches Viro's `onHover` prop directly — pass it as
|
|
32
|
+
* `onHover={onHover}` with no wrapper. Internally the hook deduplicates per
|
|
33
|
+
* source so a sequence of `(true, …, src=A)` events from the same source
|
|
34
|
+
* produces at most one re-render.
|
|
35
|
+
*/
|
|
36
|
+
function useAnySourceHover() {
|
|
37
|
+
const sourcesRef = (0, react_1.useRef)({});
|
|
38
|
+
const [hovered, setHovered] = (0, react_1.useState)(false);
|
|
39
|
+
const onHover = (0, react_1.useCallback)((isHovering, _position, source) => {
|
|
40
|
+
const key = String(source ?? "default");
|
|
41
|
+
if (sourcesRef.current[key] === isHovering)
|
|
42
|
+
return;
|
|
43
|
+
sourcesRef.current[key] = isHovering;
|
|
44
|
+
const any = Object.values(sourcesRef.current).some(Boolean);
|
|
45
|
+
setHovered(any);
|
|
46
|
+
}, []);
|
|
47
|
+
return [hovered, onHover];
|
|
48
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ViroClickState } from "../Types/ViroEvents";
|
|
2
|
+
import type { Viro3DPoint } from "../Types/ViroUtils";
|
|
3
|
+
/**
|
|
4
|
+
* Aggregate `onClickState` "is being pressed" state across all input sources.
|
|
5
|
+
*
|
|
6
|
+
* Mirror of `useAnySourceHover` for clicks. Tracks per-source `CLICK_DOWN` /
|
|
7
|
+
* `CLICK_UP` events from any input source (right + left controllers / hands)
|
|
8
|
+
* and returns a single aggregated boolean — `true` whenever **any** source
|
|
9
|
+
* is currently holding the trigger / pinch on this node.
|
|
10
|
+
*
|
|
11
|
+
* The fully-completed `CLICKED` event is intentionally ignored here: it is
|
|
12
|
+
* informational ("a complete click happened") and shouldn't toggle the
|
|
13
|
+
* held-state. Apps that need the click event itself can use the regular
|
|
14
|
+
* `onClick` prop — those callbacks already pass the `source`.
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* ```tsx
|
|
18
|
+
* function MyButton() {
|
|
19
|
+
* const [pressed, onClickState] = useAnySourcePressed();
|
|
20
|
+
* return (
|
|
21
|
+
* <ViroNode onClickState={onClickState} onClick={...}>
|
|
22
|
+
* <ViroQuad
|
|
23
|
+
* scale={pressed ? [0.95, 0.95, 0.95] : [1, 1, 1]}
|
|
24
|
+
* materials={[pressed ? "btnPressed" : "btnIdle"]}
|
|
25
|
+
* />
|
|
26
|
+
* </ViroNode>
|
|
27
|
+
* );
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* Internally deduplicates per source so a sequence of `(CLICK_DOWN, src=A)`
|
|
32
|
+
* events from the same source produces at most one re-render.
|
|
33
|
+
*/
|
|
34
|
+
export declare function useAnySourcePressed(): readonly [
|
|
35
|
+
boolean,
|
|
36
|
+
(clickState: ViroClickState, position: Viro3DPoint, source: unknown) => void
|
|
37
|
+
];
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useAnySourcePressed = useAnySourcePressed;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const ViroEvents_1 = require("../Types/ViroEvents");
|
|
6
|
+
/**
|
|
7
|
+
* Aggregate `onClickState` "is being pressed" state across all input sources.
|
|
8
|
+
*
|
|
9
|
+
* Mirror of `useAnySourceHover` for clicks. Tracks per-source `CLICK_DOWN` /
|
|
10
|
+
* `CLICK_UP` events from any input source (right + left controllers / hands)
|
|
11
|
+
* and returns a single aggregated boolean — `true` whenever **any** source
|
|
12
|
+
* is currently holding the trigger / pinch on this node.
|
|
13
|
+
*
|
|
14
|
+
* The fully-completed `CLICKED` event is intentionally ignored here: it is
|
|
15
|
+
* informational ("a complete click happened") and shouldn't toggle the
|
|
16
|
+
* held-state. Apps that need the click event itself can use the regular
|
|
17
|
+
* `onClick` prop — those callbacks already pass the `source`.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* ```tsx
|
|
21
|
+
* function MyButton() {
|
|
22
|
+
* const [pressed, onClickState] = useAnySourcePressed();
|
|
23
|
+
* return (
|
|
24
|
+
* <ViroNode onClickState={onClickState} onClick={...}>
|
|
25
|
+
* <ViroQuad
|
|
26
|
+
* scale={pressed ? [0.95, 0.95, 0.95] : [1, 1, 1]}
|
|
27
|
+
* materials={[pressed ? "btnPressed" : "btnIdle"]}
|
|
28
|
+
* />
|
|
29
|
+
* </ViroNode>
|
|
30
|
+
* );
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* Internally deduplicates per source so a sequence of `(CLICK_DOWN, src=A)`
|
|
35
|
+
* events from the same source produces at most one re-render.
|
|
36
|
+
*/
|
|
37
|
+
function useAnySourcePressed() {
|
|
38
|
+
const sourcesRef = (0, react_1.useRef)({});
|
|
39
|
+
const [pressed, setPressed] = (0, react_1.useState)(false);
|
|
40
|
+
const onClickState = (0, react_1.useCallback)((clickState, _position, source) => {
|
|
41
|
+
let next;
|
|
42
|
+
if (clickState === ViroEvents_1.ViroClickStateTypes.CLICK_DOWN) {
|
|
43
|
+
next = true;
|
|
44
|
+
}
|
|
45
|
+
else if (clickState === ViroEvents_1.ViroClickStateTypes.CLICK_UP) {
|
|
46
|
+
next = false;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
// CLICKED is fired between DOWN and UP for completed clicks —
|
|
50
|
+
// doesn't change held state, ignore.
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const key = String(source ?? "default");
|
|
54
|
+
if (sourcesRef.current[key] === next)
|
|
55
|
+
return;
|
|
56
|
+
sourcesRef.current[key] = next;
|
|
57
|
+
const any = Object.values(sourcesRef.current).some(Boolean);
|
|
58
|
+
setPressed(any);
|
|
59
|
+
}, []);
|
|
60
|
+
return [pressed, onClickState];
|
|
61
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Drop-in root component for VRActivity on Meta Quest.
|
|
4
|
+
*
|
|
5
|
+
* The library auto-registers this as 'VRQuestScene' when imported, so most
|
|
6
|
+
* apps need no manual setup. ViroXRSceneNavigator (panel side) calls
|
|
7
|
+
* setIntent() with the initial scene and renderer config before launching
|
|
8
|
+
* VRActivity. This component reads that intent, mounts ViroVRSceneNavigator
|
|
9
|
+
* with key={intentKey} (fresh stack per intent), and populates the bridge
|
|
10
|
+
* viewTag so VRModuleOpenXR ops (recenterTracking, setPassthroughEnabled)
|
|
11
|
+
* work without a direct ref to ViroVRSceneNavigator.
|
|
12
|
+
*/
|
|
13
|
+
export declare function ViroQuestEntryPoint(): React.JSX.Element | null;
|
|
@@ -0,0 +1,104 @@
|
|
|
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.ViroQuestEntryPoint = ViroQuestEntryPoint;
|
|
37
|
+
const React = __importStar(require("react"));
|
|
38
|
+
const react_native_1 = require("react-native");
|
|
39
|
+
const VRQuestNavigatorBridge_1 = require("./Utilities/VRQuestNavigatorBridge");
|
|
40
|
+
const VRModuleOpenXR_1 = require("./Utilities/VRModuleOpenXR");
|
|
41
|
+
const ViroVRSceneNavigator_1 = require("./ViroVRSceneNavigator");
|
|
42
|
+
/**
|
|
43
|
+
* Drop-in root component for VRActivity on Meta Quest.
|
|
44
|
+
*
|
|
45
|
+
* The library auto-registers this as 'VRQuestScene' when imported, so most
|
|
46
|
+
* apps need no manual setup. ViroXRSceneNavigator (panel side) calls
|
|
47
|
+
* setIntent() with the initial scene and renderer config before launching
|
|
48
|
+
* VRActivity. This component reads that intent, mounts ViroVRSceneNavigator
|
|
49
|
+
* with key={intentKey} (fresh stack per intent), and populates the bridge
|
|
50
|
+
* viewTag so VRModuleOpenXR ops (recenterTracking, setPassthroughEnabled)
|
|
51
|
+
* work without a direct ref to ViroVRSceneNavigator.
|
|
52
|
+
*/
|
|
53
|
+
function ViroQuestEntryPoint() {
|
|
54
|
+
const [intent, setIntent] = React.useState(() => VRQuestNavigatorBridge_1.VRQuestNavigatorBridge.getIntent());
|
|
55
|
+
const navRef = React.useRef(null);
|
|
56
|
+
React.useEffect(() => VRQuestNavigatorBridge_1.VRQuestNavigatorBridge.onIntent(setIntent), []);
|
|
57
|
+
// Wire hardware back button to exit VR. Apps that need custom back behaviour
|
|
58
|
+
// can call AppRegistry.registerComponent('VRQuestScene', ...) to override.
|
|
59
|
+
React.useEffect(() => {
|
|
60
|
+
const sub = react_native_1.BackHandler.addEventListener("hardwareBackPress", () => {
|
|
61
|
+
(0, VRModuleOpenXR_1.exitVRScene)();
|
|
62
|
+
return true;
|
|
63
|
+
});
|
|
64
|
+
return () => sub.remove();
|
|
65
|
+
}, []);
|
|
66
|
+
// Forward bridge ops (push/pop/etc.) to the live navigator.
|
|
67
|
+
React.useEffect(() => {
|
|
68
|
+
if (!intent)
|
|
69
|
+
return;
|
|
70
|
+
return VRQuestNavigatorBridge_1.VRQuestNavigatorBridge.subscribeOps((op) => {
|
|
71
|
+
const nav = navRef.current;
|
|
72
|
+
if (!nav)
|
|
73
|
+
return;
|
|
74
|
+
if (op.type === "push")
|
|
75
|
+
nav.push(op.scene);
|
|
76
|
+
else if (op.type === "pop")
|
|
77
|
+
nav.pop();
|
|
78
|
+
else if (op.type === "popN")
|
|
79
|
+
nav.popN(op.n);
|
|
80
|
+
else if (op.type === "replace")
|
|
81
|
+
nav.replace(op.scene);
|
|
82
|
+
else if (op.type === "jump")
|
|
83
|
+
nav.jump(op.scene);
|
|
84
|
+
});
|
|
85
|
+
}, [intent?.intentKey]);
|
|
86
|
+
// Publish the native view tag so VRModuleOpenXR callers can target this view.
|
|
87
|
+
React.useEffect(() => {
|
|
88
|
+
if (!intent)
|
|
89
|
+
return;
|
|
90
|
+
const t = setTimeout(() => {
|
|
91
|
+
const tag = (0, react_native_1.findNodeHandle)(navRef.current);
|
|
92
|
+
if (tag != null)
|
|
93
|
+
VRQuestNavigatorBridge_1.VRQuestNavigatorBridge.setViewTag(tag);
|
|
94
|
+
}, 100);
|
|
95
|
+
return () => {
|
|
96
|
+
clearTimeout(t);
|
|
97
|
+
VRQuestNavigatorBridge_1.VRQuestNavigatorBridge.setViewTag(null);
|
|
98
|
+
};
|
|
99
|
+
}, [intent?.intentKey]);
|
|
100
|
+
if (!intent)
|
|
101
|
+
return null;
|
|
102
|
+
const { initialScene, rendererConfig } = intent;
|
|
103
|
+
return (<ViroVRSceneNavigator_1.ViroVRSceneNavigator ref={navRef} key={intent.intentKey} initialScene={initialScene} {...rendererConfig} style={react_native_1.StyleSheet.absoluteFill}/>);
|
|
104
|
+
}
|