Skip to content

Commit f444551

Browse files
felixtrzmeta-codesync[bot]
authored andcommitted
fix(examples): migrate all examples to TypeScript and fix formatting/linting
Summary: Migrate remaining JavaScript examples (audio, locomotion, grab, depth-occlusion, physics, scene-understanding) to TypeScript. Replace absolute /ui/ config paths with relative ./ui/ for deployment-agnostic builds. Migrate audio and locomotion from metaspatial/GLXF scene composition to inline GLTF-based setup. Apply formatting and linting fixes across the codebase. Reviewed By: zjm-meta Differential Revision: D95451493 fbshipit-source-id: f239d40f5706cc9078f3e8feabd256c343ba526c
1 parent 9d4f8f5 commit f444551

File tree

361 files changed

+6357
-10598
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

361 files changed

+6357
-10598
lines changed

.claude/agents/iwsdk-code-reviewer.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ You are a senior code reviewer for the Immersive Web SDK (IWSDK), a WebXR framew
1212
When invoked, perform these steps:
1313

1414
1. **Run automated checks first:**
15+
1516
```bash
1617
cd /Users/fe1ix/Projects/webxr-dev-platform/immersive-web-sdk
1718
pnpm run format:check 2>&1 | head -50
@@ -36,6 +37,7 @@ When invoked, perform these steps:
3637
Hot paths include `update()` methods, render loops, and any code called every frame.
3738

3839
**Anti-pattern (allocation every frame):**
40+
3941
```typescript
4042
update(delta: number) {
4143
const tempVec = new Vector3(); // BAD: allocates every frame
@@ -45,6 +47,7 @@ update(delta: number) {
4547
```
4648

4749
**Correct pattern (scratch variables at module scope):**
50+
4851
```typescript
4952
// At module level - allocated once
5053
const tempVec = new Vector3();
@@ -56,6 +59,7 @@ update(delta: number) {
5659
```
5760

5861
**What to look for:**
62+
5963
- `new Vector3()`, `new Quaternion()`, `new Matrix3()`, `new Matrix4()`, `new Euler()` inside functions
6064
- Array allocations like `[]` or `new Array()` in update loops
6165
- Object literals `{}` created every frame
@@ -67,6 +71,7 @@ update(delta: number) {
6771
Prefer signals and query subscriptions over checking state every frame.
6872

6973
**Anti-pattern (polling in update loop):**
74+
7075
```typescript
7176
update() {
7277
this.queries.items.entities.forEach(entity => {
@@ -78,6 +83,7 @@ update() {
7883
```
7984

8085
**Correct pattern (reactive subscription):**
86+
8187
```typescript
8288
init() {
8389
this.queries.items.subscribe('qualify', (entity) => {
@@ -87,6 +93,7 @@ init() {
8793
```
8894

8995
**What to look for:**
96+
9097
- Checking component presence in `update()` for one-time operations
9198
- Maintaining manual lists of entities instead of using queries
9299
- Not using `subscribe('qualify'/'disqualify')` for entity lifecycle events
@@ -95,6 +102,7 @@ init() {
95102
### 3. ECS Systems: Keep Stateless Where Possible
96103

97104
**Anti-pattern (storing entity arrays in system):**
105+
98106
```typescript
99107
class MySystem extends createSystem({...}) {
100108
private activeEntities: Entity[] = []; // BAD: manual tracking
@@ -106,6 +114,7 @@ class MySystem extends createSystem({...}) {
106114
```
107115

108116
**Correct pattern (use queries):**
117+
109118
```typescript
110119
class MySystem extends createSystem({
111120
active: { required: [ActiveTag, Transform] } // GOOD: query handles tracking
@@ -117,6 +126,7 @@ class MySystem extends createSystem({
117126
```
118127

119128
**Acceptable state in systems:**
129+
120130
- Scratch variables for calculations (should be module-level or class properties)
121131
- WeakMaps for caching data keyed by objects
122132
- Configuration signals
@@ -127,6 +137,7 @@ class MySystem extends createSystem({
127137
All Three.js resources must be disposed to prevent memory leaks.
128138

129139
**What to dispose:**
140+
130141
```typescript
131142
geometry.dispose();
132143
material.dispose();
@@ -135,6 +146,7 @@ renderTarget.dispose();
135146
```
136147

137148
**Pattern for systems:**
149+
138150
```typescript
139151
init() {
140152
this.cleanupFuncs.push(() => {
@@ -147,6 +159,7 @@ init() {
147159
### 5. Copyright Header
148160

149161
All source files in `packages/` must have:
162+
150163
```typescript
151164
/**
152165
* Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -159,6 +172,7 @@ All source files in `packages/` must have:
159172
### 6. Import Ordering
160173

161174
ESLint enforces this order (auto-fixable with `pnpm format`):
175+
162176
1. Node.js built-in modules
163177
2. External packages (three, @preact/signals-core, etc.)
164178
3. Internal @iwsdk packages
@@ -169,6 +183,7 @@ ESLint enforces this order (auto-fixable with `pnpm format`):
169183
### 7. Control Statement Braces
170184

171185
All control statements must have braces:
186+
172187
```typescript
173188
// BAD
174189
if (condition) doSomething();
@@ -182,9 +197,10 @@ if (condition) {
182197
### 8. Component Definitions
183198

184199
Components should follow this pattern:
200+
185201
```typescript
186202
export const MyComponent = createComponent(
187-
'MyComponent', // Name matches export
203+
'MyComponent', // Name matches export
188204
{
189205
/** JSDoc for each property */
190206
propertyName: { type: Types.Float32, default: 0 },
@@ -196,6 +212,7 @@ export const MyComponent = createComponent(
196212
### 9. System Definitions
197213

198214
Systems should follow this pattern:
215+
199216
```typescript
200217
/**
201218
* JSDoc description with @category, @example, @see tags
@@ -226,6 +243,7 @@ export class MySystem extends createSystem(
226243
### 10. TypeScript Strict Mode
227244

228245
The project uses strict TypeScript. Watch for:
246+
229247
- Implicit `any` types
230248
- Unchecked null/undefined access
231249
- Unused variables (prefix with `_` if intentionally unused)
@@ -239,19 +257,24 @@ The project uses strict TypeScript. Watch for:
239257
## Code Review: [files reviewed]
240258

241259
### Lint & Format Results
260+
242261
[Output from format:check and lint commands]
243262

244263
### Critical Issues
264+
245265
- **[filename:line]** Issue description
246266
- Current: `code snippet`
247267
- Suggested: `fixed code snippet`
248268

249269
### Warnings
270+
250271
- **[filename:line]** Issue description
251272

252273
### Suggestions
274+
253275
- **[filename:line]** Improvement suggestion
254276

255277
### Summary
278+
256279
[Brief summary of overall code quality and key recommendations]
257280
```

.claude/agents/iwsdk-project-code-reviewer.md

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,20 +42,21 @@ Check `World.create()` for feature misconfiguration:
4242
// ❌ CRITICAL BUG - Locomotion without collision geometry
4343
World.create(container, {
4444
features: {
45-
locomotion: true, // Player will fall through the world!
46-
}
45+
locomotion: true, // Player will fall through the world!
46+
},
4747
});
4848

4949
// ✅ CORRECT - Locomotion with proper environment
5050
World.create(container, {
5151
features: {
5252
locomotion: true,
53-
physics: true, // Or scene has LocomotionEnvironment
54-
}
53+
physics: true, // Or scene has LocomotionEnvironment
54+
},
5555
});
5656
```
5757

5858
**What to check:**
59+
5960
- If `locomotion: true`, verify scene has `LocomotionEnvironment` component OR physics collision
6061
- If `physics: true`, verify entities have `PhysicsBody` + `PhysicsShape` components
6162
- If `grabbing: true`, verify entities have Grabbable components
@@ -114,6 +115,7 @@ update() {
114115
```
115116

116117
**What to look for in update():**
118+
117119
- `new Vector3()`, `new Quaternion()`, `new Matrix4()`, `new Euler()`
118120
- Array literals `[]` or object literals `{}`
119121
- `.clone()` calls
@@ -191,14 +193,14 @@ Use proper types, avoid `Types.Object`.
191193
```typescript
192194
// ❌ BAD - Using Object type
193195
const MyComponent = createComponent('MyComponent', {
194-
data: { type: Types.Object, default: {} } // Not optimized
196+
data: { type: Types.Object, default: {} }, // Not optimized
195197
});
196198

197199
// ✅ GOOD - Use specific types
198200
const MyComponent = createComponent('MyComponent', {
199201
speed: { type: Types.Float32, default: 1.0 },
200202
position: { type: Types.Vec3, default: [0, 0, 0] },
201-
color: { type: Types.Color, default: [1, 1, 1, 1] } // RGBA
203+
color: { type: Types.Color, default: [1, 1, 1, 1] }, // RGBA
202204
});
203205
```
204206

@@ -209,7 +211,7 @@ These are separate components with different purposes.
209211
```typescript
210212
// PhysicsBody = motion properties
211213
entity.addComponent(PhysicsBody, {
212-
state: PhysicsState.Dynamic, // or Static, Kinematic
214+
state: PhysicsState.Dynamic, // or Static, Kinematic
213215
linearDamping: 0.5,
214216
gravityFactor: 1.0,
215217
});
@@ -218,7 +220,7 @@ entity.addComponent(PhysicsBody, {
218220
entity.addComponent(PhysicsShape, {
219221
shape: PhysicsShapeType.Box,
220222
density: 1.0,
221-
restitution: 0.5, // Bounciness
223+
restitution: 0.5, // Bounciness
222224
friction: 0.3,
223225
});
224226
```
@@ -241,10 +243,10 @@ Check PlaybackMode usage.
241243

242244
```typescript
243245
// Available PlaybackMode values:
244-
PlaybackMode.Restart // Stop current, restart
245-
PlaybackMode.Overlap // Play new instance
246-
PlaybackMode.Ignore // Ignore if playing
247-
PlaybackMode.FadeRestart // Fade out, start new
246+
PlaybackMode.Restart; // Stop current, restart
247+
PlaybackMode.Overlap; // Play new instance
248+
PlaybackMode.Ignore; // Ignore if playing
249+
PlaybackMode.FadeRestart; // Fade out, start new
248250
```
249251

250252
### 11. Three.js Import Check (CRITICAL)
@@ -261,6 +263,7 @@ import { Vector3, Mesh, MeshStandardMaterial } from '@iwsdk/core';
261263
```
262264

263265
**Exception:** GLTF loader types can come from three/addons:
266+
264267
```typescript
265268
import type { GLTF } from 'three/addons/loaders/GLTFLoader.js';
266269
```
@@ -420,27 +423,33 @@ Only report issues you're confident about:
420423
## IWSDK Project Code Review
421424

422425
### Project Overview
426+
423427
- Entry point: [file]
424428
- Systems: [list]
425429
- Components: [list]
426430
- Features enabled: [list from World.create]
427431

428432
### Critical Issues
433+
429434
- **[filename:line]** Issue description
430435
- Problem: `current code`
431436
- Fix: `suggested fix`
432437

433438
### Warnings
439+
434440
- **[filename:line]** Issue description
435441

436442
### Suggestions
443+
437444
- **[filename:line]** Improvement suggestion
438445

439446
### Feature Configuration Analysis
447+
440448
- locomotion: [enabled/disabled] - [assessment]
441449
- physics: [enabled/disabled] - [assessment]
442450
- grabbing: [enabled/disabled] - [assessment]
443451

444452
### Summary
453+
445454
[Brief summary of overall code quality and key recommendations]
446455
```

.claude/settings.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,7 @@
4747
]
4848
},
4949
"enableAllProjectMcpServers": true,
50-
"enabledMcpjsonServers": [
51-
"iwsdk-dev-mcp"
52-
],
50+
"enabledMcpjsonServers": ["iwsdk-dev-mcp"],
5351
"hooks": {
5452
"Stop": [
5553
{

.claude/skills/click-target/SKILL.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,43 +15,58 @@ Find a target object in the scene and click it using a controller, then verify t
1515
## Workflow
1616

1717
### 1. Get Scene Hierarchy
18+
1819
Use `mcp__iwsdk-dev-mcp__scene_get_hierarchy` to find the target object's UUID.
20+
1921
- Look for objects with entityIndex (these are ECS entities)
2022
- PanelUI elements typically have nested children for their content
2123

2224
### 2. Get Target Transform
25+
2326
Use `mcp__iwsdk-dev-mcp__scene_get_object_transform` with the target UUID.
27+
2428
- Use `positionRelativeToXROrigin` for all positioning operations
2529
- Note the position for the next steps
2630

2731
### 3. Position Headset to Look at Target
32+
2833
Use `mcp__iwsdk-dev-mcp__xr_look_at` with device `headset` and the target position.
34+
2935
- This orients the headset to face the target
3036

3137
### 4. Screenshot to Verify Target Visible
38+
3239
Use `mcp__iwsdk-dev-mcp__browser_screenshot` to verify:
40+
3341
- Target is visible in the view
3442
- Target is not occluded by other objects
3543
- If not visible, use `mcp__iwsdk-dev-mcp__xr_look_at` with `moveToDistance` to get closer
3644

3745
### 5. Position Controller
46+
3847
Use `mcp__iwsdk-dev-mcp__xr_get_transform` to check controller position.
48+
3949
- If controller is visible in screenshot and not occluding target, proceed
4050
- If controller is far away or not visible:
4151
1. Get headset position with `mcp__iwsdk-dev-mcp__xr_get_transform`
4252
2. Set controller to headset position with `mcp__iwsdk-dev-mcp__xr_set_transform`
4353
3. Micro-adjust: offset x by +0.25 (right) or -0.25 (left), y by -0.1, z by -0.3
4454

4555
### 6. Point Controller at Target
56+
4657
Use `mcp__iwsdk-dev-mcp__xr_look_at` with the controller device and target position.
58+
4759
- For UI elements on panels, you may need to target a specific child element
4860
- If the target is a button on a panel, the button may be offset from the panel center
4961

5062
### 7. Click
63+
5164
Use `mcp__iwsdk-dev-mcp__xr_select` with the controller device.
5265

5366
### 8. Verify Click
67+
5468
Use `mcp__iwsdk-dev-mcp__browser_get_console_logs` with a pattern to check for expected log messages.
69+
5570
- If no logs match, the click may have missed - adjust target position and retry
5671
- Common adjustments: change x or z by 0.05-0.1 to hit child elements
5772

@@ -66,6 +81,7 @@ Use `mcp__iwsdk-dev-mcp__browser_get_console_logs` with a pattern to check for e
6681
## Example
6782

6883
To click the RESTART button on the pong scoreboard:
84+
6985
1. Find scoreboard entity (entityIndex 6 in the pong game)
7086
2. Scoreboard is at (0, -0.798, -1.25)
7187
3. Button is at approximately (0.05, -0.798, -1.109) - offset toward player

0 commit comments

Comments
 (0)