react-three-game 0.0.60 → 0.0.61

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 (58) hide show
  1. package/package.json +9 -3
  2. package/.gitattributes +0 -2
  3. package/.github/copilot-instructions.md +0 -83
  4. package/.github/workflows/nextjs.yml +0 -99
  5. package/.gitmodules +0 -3
  6. package/assets/architecture.png +0 -0
  7. package/assets/editor.gif +0 -0
  8. package/assets/favicon.ico +0 -0
  9. package/assets/react-three-game-logo.png +0 -0
  10. package/dist/tools/dragdrop/page.d.ts +0 -1
  11. package/dist/tools/dragdrop/page.js +0 -11
  12. package/dist/tools/prefabeditor/EntityEvents.d.ts +0 -54
  13. package/dist/tools/prefabeditor/EntityEvents.js +0 -85
  14. package/dist/tools/prefabeditor/page.d.ts +0 -1
  15. package/dist/tools/prefabeditor/page.js +0 -5
  16. package/react-three-game-skill/.gitattributes +0 -2
  17. package/react-three-game-skill/README.md +0 -7
  18. package/react-three-game-skill/react-three-game/SKILL.md +0 -514
  19. package/react-three-game-skill/react-three-game/rules/ADVANCED_PHYSICS.md +0 -472
  20. package/react-three-game-skill/react-three-game/rules/LIGHTING.md +0 -6
  21. package/src/helpers/SoundManager.ts +0 -130
  22. package/src/helpers/index.ts +0 -91
  23. package/src/index.ts +0 -59
  24. package/src/shared/ContactShadow.tsx +0 -74
  25. package/src/shared/GameCanvas.tsx +0 -52
  26. package/src/tools/assetviewer/page.tsx +0 -425
  27. package/src/tools/dragdrop/DragDropLoader.tsx +0 -159
  28. package/src/tools/dragdrop/index.ts +0 -4
  29. package/src/tools/dragdrop/modelLoader.ts +0 -204
  30. package/src/tools/dragdrop/page.tsx +0 -45
  31. package/src/tools/prefabeditor/Dropdown.tsx +0 -112
  32. package/src/tools/prefabeditor/EditorContext.tsx +0 -25
  33. package/src/tools/prefabeditor/EditorTree.tsx +0 -452
  34. package/src/tools/prefabeditor/EditorTreeMenus.tsx +0 -307
  35. package/src/tools/prefabeditor/EditorUI.tsx +0 -204
  36. package/src/tools/prefabeditor/EventSystem.tsx +0 -36
  37. package/src/tools/prefabeditor/GameEvents.ts +0 -191
  38. package/src/tools/prefabeditor/InstanceProvider.tsx +0 -466
  39. package/src/tools/prefabeditor/PrefabEditor.tsx +0 -256
  40. package/src/tools/prefabeditor/PrefabRoot.tsx +0 -767
  41. package/src/tools/prefabeditor/components/AmbientLightComponent.tsx +0 -34
  42. package/src/tools/prefabeditor/components/CameraComponent.tsx +0 -117
  43. package/src/tools/prefabeditor/components/ComponentRegistry.ts +0 -40
  44. package/src/tools/prefabeditor/components/DirectionalLightComponent.tsx +0 -210
  45. package/src/tools/prefabeditor/components/EnvironmentComponent.tsx +0 -47
  46. package/src/tools/prefabeditor/components/GeometryComponent.tsx +0 -133
  47. package/src/tools/prefabeditor/components/Input.tsx +0 -820
  48. package/src/tools/prefabeditor/components/MaterialComponent.tsx +0 -431
  49. package/src/tools/prefabeditor/components/ModelComponent.tsx +0 -176
  50. package/src/tools/prefabeditor/components/PhysicsComponent.tsx +0 -188
  51. package/src/tools/prefabeditor/components/SpotLightComponent.tsx +0 -109
  52. package/src/tools/prefabeditor/components/TextComponent.tsx +0 -137
  53. package/src/tools/prefabeditor/components/TransformComponent.tsx +0 -173
  54. package/src/tools/prefabeditor/components/index.ts +0 -26
  55. package/src/tools/prefabeditor/page.tsx +0 -10
  56. package/src/tools/prefabeditor/styles.ts +0 -235
  57. package/src/tools/prefabeditor/types.ts +0 -20
  58. package/src/tools/prefabeditor/utils.ts +0 -312
@@ -1,514 +0,0 @@
1
- ---
2
- name: react-three-game
3
- description: react-three-game, a JSON-first 3D game engine built on React Three Fiber, WebGPU, and Rapier Physics.
4
- ---
5
-
6
- # react-three-game
7
-
8
- Instructions for the agent to follow when this skill is activated.
9
-
10
- ## When to use
11
-
12
- generate 3D scenes, games and physics simulations in React.
13
-
14
- ## Agent Workflow: JSON → GLB
15
-
16
- Agents can programmatically generate 3D assets:
17
-
18
- 1. Create a JSON prefab following the GameObject schema
19
- 2. Load it in `PrefabEditor` to render the Three.js scene
20
- 3. Export the scene to GLB format using `exportGLB` or `exportGLBData`
21
-
22
- ```tsx
23
- import { useRef, useEffect } from 'react';
24
- import { PrefabEditor, exportGLBData } from 'react-three-game';
25
- import type { PrefabEditorRef } from 'react-three-game'
26
-
27
- const jsonPrefab = {
28
- root: {
29
- id: "scene",
30
- children: [
31
- {
32
- id: "cube",
33
- components: {
34
- transform: { type: "Transform", properties: { position: [0, 0, 0] } },
35
- geometry: { type: "Geometry", properties: { geometryType: "box", args: [1, 1, 1] } },
36
- material: { type: "Material", properties: { color: "#ff0000" } }
37
- }
38
- }
39
- ]
40
- }
41
- };
42
-
43
- function AgentExporter() {
44
- const editorRef = useRef<PrefabEditorRef>(null);
45
-
46
- useEffect(() => {
47
- const timer = setTimeout(async () => {
48
- const sceneRoot = editorRef.current?.rootRef.current?.root;
49
- if (!sceneRoot) return;
50
-
51
- const glbData = await exportGLBData(sceneRoot);
52
- // glbData is an ArrayBuffer ready for upload/storage
53
- }, 1000); // Wait for scene to render
54
-
55
- return () => clearTimeout(timer);
56
- }, []);
57
-
58
- return <PrefabEditor ref={editorRef} initialPrefab={jsonPrefab} />;
59
- }
60
- ```
61
-
62
- ## Core Concepts
63
-
64
- ### Asset Paths and Public Directory
65
-
66
- **All asset paths are relative to `/public`** and omit the `/public` prefix:
67
-
68
- ```json
69
- {
70
- "texture": "/textures/floor.png",
71
- "model": "/models/car.glb",
72
- "font": "/fonts/font.ttf"
73
- }
74
- ```
75
-
76
- Path `"/any/path/file.ext"` refers to `/public/any/path/file.ext`.
77
- ### GameObject Structure
78
-
79
- Every game object follows this schema:
80
-
81
- ```typescript
82
- interface GameObject {
83
- id: string;
84
- name?: string;
85
- disabled?: boolean;
86
- components?: Record<string, { type: string; properties: any }>;
87
- children?: GameObject[];
88
- }
89
- ```
90
-
91
- `disabled` is the canonical visibility toggle. Transforms are local to the parent node.
92
-
93
- ### Prefab JSON Format
94
-
95
- Scenes are defined as JSON prefabs with a root node containing children:
96
-
97
- ```json
98
- {
99
- "root": {
100
- "id": "scene",
101
- "children": [
102
- {
103
- "id": "my-object",
104
- "components": {
105
- "transform": { "type": "Transform", "properties": { "position": [0, 0, 0] } },
106
- "geometry": { "type": "Geometry", "properties": { "geometryType": "box" } },
107
- "material": { "type": "Material", "properties": { "color": "#ff0000" } }
108
- }
109
- }
110
- ]
111
- }
112
- }
113
- ```
114
-
115
- ## Built-in Components
116
-
117
- | Component | Type | Key Properties |
118
- |-----------|------|----------------|
119
- | Transform | `Transform` | `position: [x,y,z]`, `rotation: [x,y,z]` (radians), `scale: [x,y,z]` |
120
- | Geometry | `Geometry` | `geometryType`: box/sphere/plane/cylinder, `args`: dimension array |
121
- | Material | `Material` | `color`, `texture?`, `metalness?`, `roughness?`, `repeat?`, `repeatCount?` |
122
- | Physics | `Physics` | `type`: dynamic/fixed/kinematicPosition/kinematicVelocity, `mass?`, `restitution?`, `friction?`, `linearDamping?`, `angularDamping?`, `gravityScale?`, `sensor?`, `activeCollisionTypes?: 'all'` (enable kinematic/fixed collision detection), plus any Rapier RigidBody props - [See advanced physics guide](./rules/ADVANCED_PHYSICS.md) |
123
- | Model | `Model` | `filename` (GLB/FBX path), `instanced?` for GPU batching |
124
- | SpotLight | `SpotLight` | `color`, `intensity`, `angle`, `penumbra`, `distance?`, `castShadow?` |
125
- | DirectionalLight | `DirectionalLight` | `color`, `intensity`, `castShadow?`, `targetOffset?: [x,y,z]` |
126
- | AmbientLight | `AmbientLight` | `color`, `intensity` |
127
- | Environment | `Environment` | `intensity`, `resolution` |
128
- | Camera | `Camera` | `fov`, `near`, `far`, `zoom` |
129
- | Text | `Text` | `text`, `font`, `size`, `depth`, `width`, `align`, `color` |
130
-
131
- ### Text Component
132
-
133
- Requires `hb.wasm` and a font file (TTF/WOFF) in `/public/fonts/`:
134
- - hb.wasm: https://github.com/prnthh/react-three-game/raw/refs/heads/main/docs/public/fonts/hb.wasm
135
- - Sample font: https://github.com/prnthh/react-three-game/raw/refs/heads/main/docs/public/fonts/NotoSans-Regular.ttf
136
-
137
- Font property: `"font": "/fonts/NotoSans-Regular.ttf"`
138
-
139
- ### Geometry Args by Type
140
-
141
- | geometryType | args array |
142
- |--------------|------------|
143
- | `box` | `[width, height, depth]` |
144
- | `sphere` | `[radius, widthSegments, heightSegments]` |
145
- | `plane` | `[width, height]` |
146
- | `cylinder` | `[radiusTop, radiusBottom, height, radialSegments]` |
147
-
148
- ### Material Textures
149
-
150
- ```json
151
- {
152
- "material": {
153
- "type": "Material",
154
- "properties": {
155
- "color": "white",
156
- "texture": "/textures/floor.png",
157
- "repeat": true,
158
- "repeatCount": [4, 4]
159
- }
160
- }
161
- }
162
- ```
163
-
164
- ### Rotations
165
-
166
- Use radians: `1.57` = 90°, `3.14` = 180°, `-1.57` = -90°
167
-
168
- ## Common Patterns
169
-
170
- ### Usage Modes
171
-
172
- **PrefabRoot**: Pure renderer for embedding prefab data in standard R3F applications. Render it inside a regular `@react-three/fiber` `Canvas`. `GameCanvas` provides the WebGPU canvas setup. Add a `Physics` wrapper to enable physics. Use this to integrate prefabs into larger R3F scenes.
173
-
174
- ```jsx
175
- import { Canvas } from '@react-three/fiber';
176
- import { Physics } from '@react-three/rapier';
177
- import { PrefabRoot } from 'react-three-game';
178
-
179
- <Canvas>
180
- <Physics>
181
- <PrefabRoot data={prefabData} />
182
- <CustomComponent />
183
- </Physics>
184
- </Canvas>
185
- ```
186
-
187
- `GameCanvas` provides the library's WebGPU canvas setup.
188
-
189
- **PrefabEditor**: Managed scene with editor UI and play/pause controls for physics. Full authoring tool for level design and prototyping. Includes canvas, physics, transform gizmos, and inspector. Physics only runs in play mode. Can pass R3F components as children. Editor actions live under `Menu > File`, and exports under `Menu > Export`.
190
-
191
- ```jsx
192
- import { PrefabEditor } from 'react-three-game';
193
-
194
- <PrefabEditor initialPrefab={prefabData}>
195
- <CustomComponent />
196
- </PrefabEditor>
197
- ```
198
-
199
- ### Tree Utilities
200
-
201
- ```typescript
202
- import { findNode, updateNode, updateNodeById, deleteNode, cloneNode, exportGLBData } from 'react-three-game';
203
-
204
- const node = findNode(root, nodeId);
205
- const updated = updateNode(root, nodeId, n => ({ ...n, disabled: true })); // or updateNodeById (identical)
206
- const afterDelete = deleteNode(root, nodeId);
207
- const cloned = cloneNode(node);
208
- const glbData = await exportGLBData(sceneRoot);
209
- ```
210
-
211
- ## Hybrid JSON + R3F Children Pattern
212
-
213
- **Prefabs define static scene structure, R3F children add dynamic behavior**:
214
-
215
- ```tsx
216
- import { useRef } from 'react';
217
- import { useFrame } from '@react-three/fiber';
218
- import { PrefabEditor, findNode } from 'react-three-game';
219
- import type { PrefabEditorRef } from 'react-three-game';
220
-
221
- function DynamicLight() {
222
- const lightRef = useRef<THREE.SpotLight>(null!);
223
-
224
- useFrame(({ clock }) => {
225
- lightRef.current.intensity = 100 + Math.sin(clock.elapsedTime) * 50;
226
- });
227
-
228
- return <spotLight ref={lightRef} position={[10, 15, 10]} angle={0.5} />;
229
- }
230
-
231
- <PrefabEditor initialPrefab={staticScenePrefab}>
232
- <DynamicLight />
233
- <CustomController />
234
- </PrefabEditor>
235
- ```
236
-
237
- **Use cases**: Player controllers, AI behaviors, procedural animation, real-time effects.
238
-
239
- ## World Scene Pattern
240
-
241
- The current world demo combines prefab-authored level geometry with runtime React behavior:
242
-
243
- - Static level layout, props, and collision live in prefab JSON.
244
- - `Environment` can wrap sky geometry or lighting content for a full scene backdrop.
245
- - `Camera` can live in the prefab so view-only scenes and editor scenes share the same authored viewpoint.
246
- - Runtime logic can use `useFrame` plus `updateNodeById` to animate prefab entities without abandoning the JSON scene model.
247
-
248
- ```json
249
- {
250
- "id": "environment",
251
- "components": {
252
- "environment": {
253
- "type": "Environment",
254
- "properties": { "intensity": 1, "resolution": 256 }
255
- }
256
- },
257
- "children": [
258
- {
259
- "id": "sky",
260
- "components": {
261
- "geometry": { "type": "Geometry", "properties": { "geometryType": "sphere", "args": [100, 32, 16] } },
262
- "material": { "type": "Material", "properties": { "texture": "/textures/skybox/skybox1.jpg", "side": "BackSide", "materialType": "basic" } }
263
- }
264
- }
265
- ]
266
- }
267
- ```
268
-
269
- ## Quick Reference Examples
270
-
271
- ```json
272
- // Static geometry with physics (floor, wall, platform, ramp)
273
- { "id": "floor", "components": {
274
- "transform": { "type": "Transform", "properties": { "position": [0, -0.5, 0] } },
275
- "geometry": { "type": "Geometry", "properties": { "geometryType": "box", "args": [40, 1, 40] } },
276
- "material": { "type": "Material", "properties": { "texture": "/textures/floor.png", "repeat": true, "repeatCount": [20, 20] } },
277
- "physics": { "type": "Physics", "properties": { "type": "fixed" } }
278
- }}
279
-
280
- // Lighting
281
- { "id": "spot", "components": {
282
- "transform": { "type": "Transform", "properties": { "position": [10, 15, 10] } },
283
- "spotlight": { "type": "SpotLight", "properties": { "intensity": 200, "angle": 0.8, "castShadow": true } }
284
- }}
285
-
286
- // 3D Text
287
- { "id": "title", "components": {
288
- "transform": { "type": "Transform", "properties": { "position": [0, 3, 0] } },
289
- "text": { "type": "Text", "properties": { "text": "Welcome", "font": "/fonts/font.ttf", "size": 1, "depth": 0.1 } }
290
- }}
291
-
292
- // GLB Model
293
- { "id": "tree", "components": {
294
- "transform": { "type": "Transform", "properties": { "position": [0, 0, 0], "scale": [1.5, 1.5, 1.5] } },
295
- "model": { "type": "Model", "properties": { "filename": "/models/tree.glb" } }
296
- }}
297
- ```
298
-
299
- ## Editor
300
-
301
- ### Basic Usage
302
-
303
- ```jsx
304
- import { PrefabEditor } from 'react-three-game';
305
-
306
- <PrefabEditor initialPrefab={sceneData} onPrefabChange={setSceneData} />
307
- ```
308
-
309
- Keyboard shortcuts: **T** (Translate), **R** (Rotate), **S** (Scale)
310
-
311
- ### Camera Control
312
-
313
- By default, `PrefabEditor` uses an orbit camera. **Override it by adding a custom camera with `makeDefault`**:
314
-
315
- ```tsx
316
- import { PerspectiveCamera } from '@react-three/drei';
317
- import { PrefabEditor } from 'react-three-game';
318
-
319
- <PrefabEditor initialPrefab={prefab}>
320
- <PerspectiveCamera makeDefault position={[0, 5, 10]} fov={75} />
321
- </PrefabEditor>
322
- ```
323
-
324
- Any R3F camera component works: `PerspectiveCamera`, `OrthographicCamera`, or custom camera controllers.
325
-
326
- ### Programmatic Updates
327
-
328
- ```jsx
329
- import { useRef } from 'react';
330
- import { PrefabEditor, updateNodeById } from 'react-three-game';
331
- import type { PrefabEditorRef } from 'react-three-game';
332
-
333
- function Scene() {
334
- const editorRef = useRef<PrefabEditorRef>(null);
335
-
336
- const moveBall = () => {
337
- const prefab = editorRef.current!.prefab;
338
- const newRoot = updateNodeById(prefab.root, "ball", node => ({
339
- ...node,
340
- components: {
341
- ...node.components,
342
- transform: {
343
- ...node.components!.transform!,
344
- properties: { ...node.components!.transform!.properties, position: [5, 0, 0] }
345
- }
346
- }
347
- }));
348
- editorRef.current!.setPrefab({ ...prefab, root: newRoot });
349
- };
350
-
351
- return <PrefabEditor ref={editorRef} initialPrefab={sceneData} />;
352
- }
353
- ```
354
-
355
- **PrefabEditorRef**: `prefab`, `setPrefab()`, `screenshot()`, `exportGLB()`, `rootRef`
356
-
357
- ### GLB Export
358
-
359
- ```tsx
360
- import { exportGLBData } from 'react-three-game';
361
-
362
- const glbData = await exportGLBData(editorRef.current!.rootRef.current!.root);
363
- ```
364
-
365
- ### Runtime Animation
366
-
367
- ```tsx
368
- import { useRef } from "react";
369
- import { useFrame } from "@react-three/fiber";
370
- import { PrefabEditor, updateNodeById } from "react-three-game";
371
-
372
- function Animator({ editorRef }) {
373
- useFrame(() => {
374
- const prefab = editorRef.current!.prefab;
375
- const newRoot = updateNodeById(prefab.root, "ball", node => ({
376
- ...node,
377
- components: {
378
- ...node.components,
379
- transform: {
380
- ...node.components!.transform!,
381
- properties: { ...node.components!.transform!.properties, position: [x, y, z] }
382
- }
383
- }
384
- }));
385
- editorRef.current!.setPrefab({ ...prefab, root: newRoot });
386
- });
387
- return null;
388
- }
389
-
390
- function Scene() {
391
- const editorRef = useRef(null);
392
- return (
393
- <PrefabEditor ref={editorRef} initialPrefab={data}>
394
- <Animator editorRef={editorRef} />
395
- </PrefabEditor>
396
- );
397
- }
398
- ```
399
-
400
- ### Custom Component
401
-
402
- ```tsx
403
- import { Component, registerComponent, FieldRenderer } from 'react-three-game';
404
-
405
- const MyComponent: Component = {
406
- name: 'MyComponent',
407
- Editor: ({ component, onUpdate }) => (
408
- <FieldRenderer fields={[{ name: 'speed', type: 'number', step: 0.1 }]} values={component.properties} onChange={onUpdate} />
409
- ),
410
- View: ({ properties, children }) => <group>{children}</group>,
411
- defaultProperties: { speed: 1 }
412
- };
413
-
414
- registerComponent(MyComponent);
415
- ```
416
-
417
- Use the component in prefab JSON by adding a component entry whose `type` matches the registered component name:
418
-
419
- ```json
420
- {
421
- "components": {
422
- "mycomponent": {
423
- "type": "MyComponent",
424
- "properties": {
425
- "speed": 1
426
- }
427
- }
428
- }
429
- }
430
- ```
431
-
432
- Rules:
433
- - Call `registerComponent(MyComponent)` before rendering `<PrefabEditor>` or `<PrefabRoot>` with prefab data that uses it.
434
- - `type` must match the registered component name exactly (`name: 'MyComponent'` -> `"type": "MyComponent"`).
435
- - Use `View` to render visible content, wrap `children`, or add runtime behavior with hooks like `useFrame`.
436
-
437
- **Field types**: `vector3`, `number`, `string`, `color`, `boolean`, `select`, `custom`
438
-
439
- ## Game Events
440
-
441
- A general-purpose event system for game-wide communication. Handles physics events, gameplay events, and any custom events.
442
-
443
- ### Core API
444
-
445
- ```tsx
446
- import { gameEvents, useGameEvent } from 'react-three-game';
447
-
448
- // Emit events
449
- gameEvents.emit('player:death', { playerId: 'p1', cause: 'lava' });
450
- gameEvents.emit('score:change', { delta: 100, total: 500 });
451
-
452
- // Subscribe (React hook - auto cleanup on unmount)
453
- useGameEvent('player:death', (payload) => {
454
- showGameOver(payload.cause);
455
- }, []);
456
-
457
- // Subscribe (manual - returns unsubscribe function)
458
- const unsub = gameEvents.on('score:change', (payload) => {
459
- updateUI(payload.total);
460
- });
461
- unsub(); // cleanup
462
- ```
463
-
464
- ### Built-in Physics Events
465
-
466
- Physics components automatically emit these events:
467
-
468
- | Event | When | Payload |
469
- |-------|------|---------|
470
- | `sensor:enter` | Something enters a sensor collider | `{ sourceEntityId, targetEntityId, targetRigidBody }` |
471
- | `sensor:exit` | Something exits a sensor collider | `{ sourceEntityId, targetEntityId, targetRigidBody }` |
472
- | `collision:enter` | A collision starts | `{ sourceEntityId, targetEntityId, targetRigidBody }` |
473
- | `collision:exit` | A collision ends | `{ sourceEntityId, targetEntityId, targetRigidBody }` |
474
-
475
- **Collision filtering**: By default, kinematic/fixed bodies don't detect each other. For kinematic sensors or projectiles to detect walls/floors, add `"activeCollisionTypes": "all"` to the Physics properties.
476
-
477
- See [Advanced Physics](./rules/ADVANCED_PHYSICS.md) for sensor setup and collision handling patterns.
478
-
479
- ### TypeScript: Typed Custom Events
480
-
481
- Extend `GameEventMap` for type-safe custom events:
482
-
483
- ```typescript
484
- declare module 'react-three-game' {
485
- interface GameEventMap {
486
- 'player:death': { playerId: string; cause: string };
487
- 'score:change': { delta: number; total: number };
488
- 'level:complete': { levelId: number; time: number };
489
- }
490
- }
491
- ```
492
-
493
- ### Common Patterns
494
-
495
- ```tsx
496
- // Gameplay controller
497
- function GameController() {
498
- const [score, setScore] = useState(0);
499
-
500
- useGameEvent('score:change', ({ total }) => setScore(total), []);
501
- useGameEvent('player:death', () => setGameOver(true), []);
502
-
503
- return <ScoreUI score={score} />;
504
- }
505
-
506
- // Pickup system
507
- useGameEvent('sensor:enter', (payload) => {
508
- if (payload.sourceEntityId.startsWith('coin-')) {
509
- gameEvents.emit('score:change', { delta: 10, total: score + 10 });
510
- removeEntity(payload.sourceEntityId);
511
- }
512
- }, [score]);
513
- ```
514
-