Skip to content

Commit 41cddfb

Browse files
committed
Add xr-active-switch.ts
1 parent 615fa1b commit 41cddfb

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ export * from './vrm.js';
2424
export * from './wasd-controls.js';
2525
export * from './input-profile.js';
2626
export * from './orbital-camera.js';
27+
export * from './xr-active-switch.js';
2728

2829
export * from '@wonderlandengine/spatial-audio';

xr-active-switch.ts

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import {Component, Object3D} from '@wonderlandengine/api';
2+
import {property} from '@wonderlandengine/api/decorators.js';
3+
4+
export enum SCOPE {
5+
ThisObject = 'this object',
6+
Children = 'children only',
7+
ThisObjectAndChildren = 'this object & children',
8+
}
9+
10+
export enum ACTION {
11+
None = 'none',
12+
Activate = 'activate',
13+
Deactivate = 'deactivate',
14+
Toggle = 'toggle',
15+
}
16+
17+
/**
18+
* XR Active Switch Component for controlling component activation states
19+
* based on XR session status.
20+
*
21+
* This component allows toggling, activating, deactivating, or keeping the
22+
* current state of components when entering or exiting XR sessions.
23+
*
24+
* The scope of affected components can be limited to the current object,
25+
* its children, or both.
26+
*
27+
* Use this component to manage visibility, interactivity, or other properties
28+
* that depend on XR session states.
29+
*
30+
*/
31+
export class XrActiveSwitch extends Component {
32+
static TypeName = 'xr-active-switch';
33+
34+
/** Action to perform when XR session starts */
35+
@property.enum(Object.values(ACTION))
36+
ifInXR!: number;
37+
38+
/** Action to perform when XR session ends */
39+
@property.enum(Object.values(ACTION))
40+
ifNotInXR!: number;
41+
42+
/** Scope of elements to affect */
43+
@property.enum(Object.values(SCOPE))
44+
scope!: number;
45+
46+
private components: Component[] = [];
47+
48+
start() {
49+
// Initial state setup
50+
this.applyAction(this.engine.xr?.session ? this.ifInXR : this.ifNotInXR);
51+
52+
// Bind event handlers
53+
this.engine.onXRSessionStart.add(this.onSessionStart);
54+
this.engine.onXRSessionEnd.add(this.onSessionEnd);
55+
}
56+
57+
onActivate() {
58+
this.engine.onXRSessionStart.add(this.onSessionStart);
59+
this.engine.onXRSessionEnd.add(this.onSessionEnd);
60+
}
61+
62+
onDeactivate() {
63+
this.engine.onXRSessionStart.remove(this.onSessionStart);
64+
this.engine.onXRSessionEnd.remove(this.onSessionEnd);
65+
}
66+
67+
private collectComponents() {
68+
const mode = Object.values(SCOPE)[this.scope];
69+
70+
// Handle current object
71+
if (mode === SCOPE.ThisObject || mode === SCOPE.ThisObjectAndChildren) {
72+
this.object
73+
.getComponents()
74+
.filter((c) => c.type !== XrActiveSwitch.TypeName)
75+
.forEach((c) => this.components.push(c));
76+
}
77+
78+
// Handle children
79+
if (mode === SCOPE.Children || mode === SCOPE.ThisObjectAndChildren) {
80+
this.processChildren(this.object);
81+
}
82+
}
83+
84+
private processChildren(obj: Object3D) {
85+
for (const child of obj.children) {
86+
child
87+
.getComponents()
88+
.filter((c) => c.type !== XrActiveSwitch.TypeName)
89+
.forEach((c) => this.components.push(c));
90+
this.processChildren(child); // Recurse through all descendants
91+
}
92+
}
93+
94+
private applyAction(action_index: number) {
95+
const action = Object.values(ACTION)[action_index];
96+
this.components = [];
97+
this.collectComponents();
98+
for (const comp of this.components) {
99+
if (action === ACTION.Activate) {
100+
comp.active = true;
101+
} else if (action === ACTION.Deactivate) {
102+
comp.active = false;
103+
} else if (action === ACTION.Toggle) {
104+
comp.active = !comp.active;
105+
}
106+
}
107+
}
108+
109+
private onSessionStart = () => {
110+
this.applyAction(this.ifInXR);
111+
};
112+
113+
private onSessionEnd = () => {
114+
this.applyAction(this.ifNotInXR);
115+
};
116+
}

0 commit comments

Comments
 (0)