react-three-game 0.0.18 → 0.0.19

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.
@@ -1,207 +1,78 @@
1
1
  # react-three-game - AI Coding Agent Instructions
2
2
 
3
- ## Project Mission
4
- The **first 3D game engine designed for AI-native development**. Everything is JSON-serializable prefabs that AI agents can generate, modify, and compose without writing imperative code. Think Unity's component system meets React's declarative paradigm.
3
+ ## Project Overview
4
+ AI-native 3D game engine where **scenes are JSON prefabs**. Unity-like GameObject+Component architecture built on React Three Fiber + WebGPU.
5
5
 
6
- ## Why This Exists (Critical Context)
7
- Traditional 3D engines (Unity, Unreal, Three.js) require imperative code that's hard for AI to generate reliably. We solve this by making **everything pure data structures**:
8
- - Entire scenes are JSON objects
9
- - Components are registered modules with Editor + View separation
10
- - ✅ Visual prefab editor exports versionable JSON
11
- - ✅ No manual scene graph manipulation required
6
+ ## Monorepo Structure
7
+ - **`/src`** Library source, builds to `/dist`, published as `react-three-game`
8
+ - **`/docs`** Next.js 16 site, imports library via `"react-three-game": "file:.."`
9
+ - **`npm run dev`** Runs `tsc --watch` + Next.js concurrently (hot reload works)
12
10
 
13
- ## Architecture
14
-
15
- ### Dual-Structure Monorepo
16
- - **`/src`**: Library source (TypeScript) → builds to `/dist` → published as `react-three-game` npm package
17
- - **`/docs`**: Next.js 16 documentation site that imports library via `"react-three-game": "file:.."` in package.json
18
- - Development command: `npm run dev` (runs `tsc --watch` + Next.js dev server concurrently via `concurrently`)
19
- - **Hot reload works**: Changes to `/src` trigger rebuild → docs site sees updates
20
-
21
- ### Component-Based Prefab System
22
- The core innovation is a **GameObject + Component** architecture similar to Unity/Unreal:
23
-
24
- ```typescript
25
- // Prefab JSON structure (see src/tools/prefabeditor/samples/*.json)
26
- {
27
- "id": "prefab-1",
28
- "root": {
29
- "id": "root",
30
- "enabled": true,
31
- "visible": true,
32
- "components": {
33
- "transform": { type: "Transform", properties: { position: [0,0,0], rotation: [0,0,0], scale: [1,1,1] } },
34
- "geometry": { type: "Geometry", properties: { geometryType: "box", args: [1,1,1] } },
35
- "material": { type: "Material", properties: { color: "#ffffff" } },
36
- "physics": { type: "Physics", properties: { type: "dynamic" } }
37
- },
38
- "children": [ /* recursive GameObject[] */ ]
39
- }
40
- }
41
- ```
42
-
43
- **AI agents can generate this entire structure from natural language prompts.**
44
-
45
- ### Component Registry Pattern (`src/tools/prefabeditor/components/`)
46
- Every component implements:
11
+ ## Prefab JSON Schema
47
12
  ```typescript
48
- interface Component {
49
- name: string;
50
- Editor: FC<{ component: any; onUpdate: (newComp: any) => void }>; // Inspector UI
51
- View?: FC<any>; // Three.js runtime renderer
52
- defaultProperties: any;
13
+ // See docs/app/samples/*.json for examples
14
+ interface Prefab { id?: string; name?: string; root: GameObject; }
15
+ interface GameObject {
16
+ id: string; // Use crypto.randomUUID() for new nodes
17
+ disabled?: boolean;
18
+ hidden?: boolean;
19
+ components?: Record<string, { type: string; properties: any }>;
20
+ children?: GameObject[];
53
21
  }
54
22
  ```
23
+ **Transforms are LOCAL** (parent-relative). Rotations in radians. Colors as CSS strings.
55
24
 
56
- Register in `components/index.ts` to make available in editor. Examples:
57
- - **TransformComponent**: Position/rotation/scale (no View - handled by group wrapper)
58
- - **PhysicsComponent**: Wraps children in `<RigidBody>` from @react-three/rapier (only in play mode)
59
- - **MaterialComponent**: Renders as `<meshStandardNodeMaterial>` with texture support
60
- - **ModelComponent**: Loads GLB/FBX via `modelLoader.ts`, supports instancing
61
-
62
- ### World Matrix Math (CRITICAL)
63
- `PrefabRoot.tsx` maintains **parent-relative transforms** but uses **world matrices** for TransformControls:
64
- - Each `GameObjectRenderer` computes `worldMatrix = parentMatrix * localMatrix`
65
- - On transform drag: extract world matrix → compute parent inverse → derive new local transform
66
- - Helper: `computeParentWorldMatrix(root, targetId)` traverses tree to get parent's world matrix
67
- - **Never directly set world transforms in prefab JSON** - always store local transforms
68
-
69
- ### Instancing System (`InstanceProvider.tsx`)
70
- Optimizes rendering of repeated models:
71
- 1. `GameInstanceProvider` flattens all model meshes into `flatMeshes` map
72
- 2. `GameInstance` component registers instance data (position/rotation/scale)
73
- 3. Provider renders once per unique mesh using `<Merged>` from drei + `<InstancedRigidBodies>`
74
- 4. Toggled by `model.properties.instanced = true` in prefab JSON
75
- 5. Physics instances use world-space transforms (not local)
76
-
77
- ## Key Files & Patterns
78
-
79
- ### `src/index.ts` - Library Exports
80
- Main entry point for published package. When adding new features, export them here:
81
- ```typescript
82
- export { default as GameCanvas } from './shared/GameCanvas';
83
- export { default as PrefabEditor } from './tools/prefabeditor/PrefabEditor';
84
- export { default as PrefabRoot } from './tools/prefabeditor/PrefabRoot';
85
- export { DragDropLoader } from './tools/dragdrop/DragDropLoader';
86
- // Add new exports as features are developed
87
- ```
88
-
89
- ### `PrefabEditor.tsx` - Main Editor Wrapper
90
- - Manages edit/play mode toggle (pauses Rapier physics in edit mode)
91
- - Handles JSON import/export via file input
92
- - Renders `<EditorUI>` (inspector + tree) and `<PrefabRoot>` (scene renderer)
93
-
94
- ### `PrefabRoot.tsx` - Recursive Scene Renderer
95
- Three rendering paths:
96
- 1. **Instanced nodes**: Short-circuit to `<GameInstance>` (world-space, terminal node)
97
- 2. **Model nodes**: Render as `<primitive object={clonedModel}>` with material override
98
- 3. **Geometry nodes**: Render as `<mesh>` with geometry + material components
99
- - Always wrap in physics if component exists (except edit mode)
100
- - Children always use relative transforms in `<group>`
101
-
102
- ### `EditorUI.tsx` + `EditorTree.tsx`
103
- - Tree view: Drag-to-reorder via pointer events (updates parent's children array)
104
- - Inspector: Dynamically renders component editors from registry
105
- - Transform modes: T/R/S keyboard shortcuts handled in PrefabEditor
106
-
107
- ### `GameCanvas.tsx` - WebGPU Renderer Wrapper
108
- Uses Three.js WebGPU renderer (not WebGL):
109
- ```tsx
110
- <Canvas gl={async ({ canvas }) => {
111
- const renderer = new WebGPURenderer({ canvas, shadowMap: true });
112
- await renderer.init(); // MUST await initialization
113
- return renderer;
114
- }}>
115
- ```
116
- **Material nodes**: Use `MeshStandardNodeMaterial` not `MeshStandardMaterial` (extends for node materials)
117
-
118
- ## Development Workflows
119
-
120
- ### Adding New Components
121
- 1. Create `src/tools/prefabeditor/components/MyComponent.tsx`:
25
+ ## Component System (`src/tools/prefabeditor/components/`)
26
+ Every component has `Editor` (inspector UI) + optional `View` (Three.js render):
122
27
  ```typescript
123
28
  const MyComponent: Component = {
124
- name: 'MyComponent',
125
- Editor: ({ component, onUpdate }) => { /* Inspector UI */ },
126
- View: ({ properties, children }) => { /* Three.js render */ },
127
- defaultProperties: { /* defaults */ }
29
+ name: 'MyComponent', // TitleCase for registry, lowercase key in JSON
30
+ Editor: ({ component, onUpdate }) => <input onChange={e => onUpdate({ value: e.target.value })} />,
31
+ View: ({ properties, children }) => <group>{children}</group>, // Wrapper components accept children
32
+ defaultProperties: { value: 0 }
128
33
  };
129
- export default MyComponent;
130
34
  ```
131
- 2. Export in `components/index.ts`
132
- 3. Auto-registers via `components.forEach(registerComponent)` in PrefabRoot
35
+ **To add a component:** Create file → export from `components/index.ts` → auto-registered in `PrefabRoot.tsx`.
133
36
 
134
- ### Testing in Docs Site
135
- 1. Export new component from `src/index.ts`
136
- 2. Run `npm run dev` (rebuilds library on save)
137
- 3. Use in `docs/app/demo/page.tsx` or create new demo page
37
+ ## Key Files
38
+ | File | Purpose |
39
+ |------|---------|
40
+ | `src/index.ts` | All public exports - add new features here |
41
+ | `src/tools/prefabeditor/PrefabRoot.tsx` | Recursive scene renderer, world matrix math |
42
+ | `src/tools/prefabeditor/PrefabEditor.tsx` | Edit/play mode, physics pause, JSON import/export |
43
+ | `src/tools/prefabeditor/utils.ts` | Tree helpers: `findNode`, `updateNode`, `deleteNode`, `cloneNode` |
44
+ | `src/shared/GameCanvas.tsx` | WebGPU renderer setup (use `MeshStandardNodeMaterial`) |
138
45
 
139
- ### Model Loading
140
- - Supports GLB/GLTF (with Draco compression) and FBX
141
- - Models auto-load when `model.properties.filename` detected in prefab tree
142
- - Uses singleton loaders (don't recreate GLTFLoader instances)
143
- - Draco decoder from CDN: `https://www.gstatic.com/draco/v1/decoders/`
46
+ ## Critical Patterns
144
47
 
145
- ## Common Patterns
146
-
147
- ### Update Prefab Node
48
+ ### Tree Manipulation (Immutable)
148
49
  ```typescript
149
- function updatePrefabNode(root: GameObject, id: string, update: (node: GameObject) => GameObject): GameObject {
150
- if (root.id === id) return update(root);
151
- if (root.children) {
152
- return { ...root, children: root.children.map(child => updatePrefabNode(child, id, update)) };
153
- }
154
- return root;
155
- }
50
+ import { updateNode, findNode, deleteNode } from 'react-three-game';
51
+ const newRoot = updateNode(root, nodeId, node => ({ ...node, components: { ...node.components, physics: {...} } }));
156
52
  ```
157
53
 
158
- ### Three Object References
159
- - `objectRefs.current[gameObjectId]` stores Three.Object3D for each node
160
- - `registerRef(id, obj)` callback passed down hierarchy
161
- - Used by TransformControls to manipulate objects directly
162
-
163
- ### Edit vs Play Mode
164
- - Edit mode: `<MapControls>`, `<TransformControls>`, physics paused
165
- - Play mode: Physics active, no editor UI
166
- - Components check `editMode` prop to conditionally wrap (e.g., PhysicsComponent only wraps in play)
54
+ ### WebGPU Materials
55
+ Use node materials only: `MeshStandardNodeMaterial`, `MeshBasicNodeMaterial` (not `MeshStandardMaterial`).
167
56
 
168
- ## Publishing
169
- ```bash
170
- npm run build # tsc → dist/
171
- npm publish --access public
172
- ```
57
+ ### Physics Wrapping
58
+ `PhysicsComponent.View` wraps children in `<RigidBody>` only when `editMode=false`. Edit mode pauses physics.
173
59
 
174
- ## Conventions
175
- - **IDs**: Use UUIDs for GameObjects (important for tree operations)
176
- - **Transforms**: Always `[x, y, z]` number arrays, rotations in radians
177
- - **Colors**: Accept CSS strings (hex codes or named colors) → convert to THREE.Color
178
- - **Texture paths**: Relative to public root (e.g., `/textures/grid.png`)
179
- - **Component keys**: Lowercase in prefab JSON (`"transform"`, `"physics"`) but TitleCase for registry (`"Transform"`, `"Physics"`)
60
+ ### Model Instancing
61
+ Set `model.properties.instanced = true` uses `InstanceProvider.tsx` for batched rendering with physics.
180
62
 
181
- ## Tech Stack
182
- - **React 19** + **TypeScript 5**
183
- - **@react-three/fiber** (React renderer for Three.js)
184
- - **@react-three/drei** (helpers: MapControls, TransformControls, Merged)
185
- - **@react-three/rapier** (physics via Rapier WASM)
186
- - **Three.js WebGPU** (cutting edge renderer, not WebGL)
187
- - **Next.js 16** (docs site only)
188
- - **Tailwind 4** (docs site styling)
63
+ ## Built-in Components
64
+ `Transform`, `Geometry` (box/sphere/plane), `Material` (color/texture), `Physics` (dynamic/fixed), `Model` (GLB/FBX), `SpotLight`, `DirectionalLight`
189
65
 
190
- ## Design Principles
191
- 1. **AI-first**: Prefabs are JSON LLMs can generate complete scenes
192
- 2. **Zero boilerplate**: No manual Three.js object creation in user code
193
- 3. **Component composition**: Mix physics + rendering + behavior via declarative components
194
- 4. **Visual editing**: Prefab editor generates JSON that can be version controlled
195
- 5. **Instancing by default**: Optimize repeated geometry automatically
66
+ ## Custom Components (User-space)
67
+ See `docs/app/demo/editor/RotatorComponent.tsx` for runtime behavior example using `useFrame`. Register with `registerComponent()` before rendering `<PrefabEditor>`.
196
68
 
197
- ## Coming Soon (Migration in Progress)
198
- These features exist in another repo and are being migrated:
199
- - **Input system**: Keyboard, gamepad, and touchscreen controls
200
- - **Multiplayer primitives**: WebRTC-based state synchronization (Trystero)
201
- - **Controller patterns**: First-person and third-person camera controllers
202
- - **Touch UI**: Virtual joystick and button components for mobile
69
+ ## Development Workflow
70
+ 1. **Edit library**: Modify `/src`, auto-rebuilds via `tsc --watch`
71
+ 2. **Test in docs**: Changes reflect at `http://localhost:3000`
72
+ 3. **Add sample prefabs**: `docs/app/samples/*.json`
73
+ 4. **Release**: `npm run release` (builds + publishes)
203
74
 
204
- When implementing these, maintain the same philosophy:
205
- - Controllers should work with prefab-based scenes
206
- - Input should be declarative (hook-based, not imperative event listeners)
207
- - Multiplayer state sync should serialize naturally with JSON prefabs
75
+ ## Conventions
76
+ - Component keys: lowercase in JSON (`"transform"`), TitleCase in registry (`"Transform"`)
77
+ - Asset paths: Relative to `/public` (e.g., `models/cars/taxi/model.glb`)
78
+ - All Three.js renders must be inside `<GameCanvas>` (WebGPU init required)
package/README.md CHANGED
@@ -1,279 +1,134 @@
1
1
  # react-three-game
2
2
 
3
- Component-based 3D game engine where everything is JSON. Built on React Three Fiber + WebGPU.
3
+ JSON-first 3D game engine. React Three Fiber + WebGPU + Rapier Physics.
4
4
 
5
5
  ```bash
6
- npm i react-three-game @react-three/fiber three
6
+ npm i react-three-game @react-three/fiber @react-three/rapier three
7
7
  ```
8
8
 
9
- [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
10
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.0-blue.svg)](https://www.typescriptlang.org/)
11
- [![React](https://img.shields.io/badge/React-19-blue.svg)](https://react.dev/)
12
-
13
9
  ![Prefab Editor](assets/editor.gif)
14
10
 
15
- ## Core Principle
16
-
17
- Scenes are JSON prefabs. Components are registered modules. Hierarchy is declarative.
11
+ ## Usage
18
12
 
19
13
  ```jsx
20
- <PrefabRoot data={{
14
+ import { Physics } from '@react-three/rapier';
15
+ import { GameCanvas, PrefabRoot } from 'react-three-game';
16
+
17
+ <GameCanvas>
18
+ <Physics>
19
+ <PrefabRoot data={{
21
20
  root: {
22
- id: "cube",
23
- components: {
24
- transform: { type: "Transform", properties: { position: [0, 1, 0] } },
25
- geometry: { type: "Geometry", properties: { geometryType: "box" } },
26
- material: { type: "Material", properties: { color: "green" } },
21
+ id: "scene",
22
+ children: [
23
+ {
24
+ id: "ground",
25
+ components: {
26
+ transform: { type: "Transform", properties: { position: [0, 0, 0], rotation: [-1.57, 0, 0] } },
27
+ geometry: { type: "Geometry", properties: { geometryType: "plane", args: [50, 50] } },
28
+ material: { type: "Material", properties: { color: "#3a3" } },
29
+ physics: { type: "Physics", properties: { type: "fixed" } }
30
+ }
31
+ },
32
+ {
33
+ id: "ball",
34
+ components: {
35
+ transform: { type: "Transform", properties: { position: [0, 5, 0] } },
36
+ geometry: { type: "Geometry", properties: { geometryType: "sphere" } },
37
+ material: { type: "Material", properties: { color: "#f66" } },
27
38
  physics: { type: "Physics", properties: { type: "dynamic" } }
39
+ }
28
40
  }
41
+ ]
29
42
  }
30
- }} />
31
- ```
32
-
33
- ## Quick Start
34
-
35
- ```bash
36
- npm install react-three-game @react-three/fiber @react-three/rapier three
37
- ```
38
-
39
- ```jsx
40
- import { Physics } from '@react-three/rapier';
41
- import { GameCanvas, PrefabRoot } from 'react-three-game';
42
-
43
- export default function App() {
44
- return (
45
- <GameCanvas>
46
- <Physics>
47
- <ambientLight intensity={0.8} />
48
- <PrefabRoot
49
- data={{
50
- id: "scene",
51
- name: "scene",
52
- root: {
53
- id: "root",
54
- children: [
55
- {
56
- id: "ground",
57
- components: {
58
- transform: { type: "Transform", properties: { position: [0, 0, 0], rotation: [-1.57, 0, 0] } },
59
- geometry: { type: "Geometry", properties: { geometryType: "plane", args: [50, 50] } },
60
- material: { type: "Material", properties: { color: "green" } },
61
- physics: { type: "Physics", properties: { type: "fixed" } }
62
- }
63
- },
64
- {
65
- id: "player",
66
- components: {
67
- transform: { type: "Transform", properties: { position: [0, 2, 0] } },
68
- geometry: { type: "Geometry", properties: { geometryType: "sphere" } },
69
- material: { type: "Material", properties: { color: "#ff6b6b" } },
70
- physics: { type: "Physics", properties: { type: "dynamic" } }
71
- }
72
- }
73
- ]
74
- }
75
- }}
76
- />
77
- </Physics>
78
- </GameCanvas>
79
- );
80
- }
43
+ }} />
44
+ </Physics>
45
+ </GameCanvas>
81
46
  ```
82
47
 
83
- ## GameObject Structure
48
+ ## GameObject Schema
84
49
 
85
50
  ```typescript
86
51
  interface GameObject {
87
52
  id: string;
88
53
  disabled?: boolean;
89
54
  hidden?: boolean;
90
- components: {
91
- transform?: TransformComponent;
92
- geometry?: GeometryComponent;
93
- material?: MaterialComponent;
94
- physics?: PhysicsComponent;
95
- model?: ModelComponent;
96
- };
55
+ components?: Record<string, { type: string; properties: any }>;
97
56
  children?: GameObject[];
98
57
  }
99
58
  ```
100
59
 
101
- ## Custom Components
102
-
103
- Extend the engine by registering your own components. Components have two parts:
104
- - **Editor**: UI for inspector panel (edit mode)
105
- - **View**: Three.js runtime renderer (play mode)
106
-
107
- ### Component Interface
108
-
109
- ```typescript
110
- import { Component } from 'react-three-game';
60
+ ## Built-in Components
111
61
 
112
- interface Component {
113
- name: string;
114
- Editor: FC<{ component: any; onUpdate: (newComp: any) => void }>;
115
- View?: FC<{ properties: any; children?: React.ReactNode }>;
116
- defaultProperties: any;
117
- }
118
- ```
62
+ | Component | Key Properties |
63
+ |-----------|----------------|
64
+ | Transform | `position`, `rotation`, `scale` all `[x,y,z]` arrays, rotation in radians |
65
+ | Geometry | `geometryType`: box/sphere/plane/cylinder, `args`: dimension array |
66
+ | Material | `color`, `texture?`, `metalness?`, `roughness?` |
67
+ | Physics | `type`: dynamic/fixed |
68
+ | Model | `filename` (GLB/FBX path), `instanced?` for GPU batching |
69
+ | SpotLight | `color`, `intensity`, `angle`, `penumbra` |
119
70
 
120
- ### Example: Rotator Component
71
+ ## Custom Components
121
72
 
122
73
  ```tsx
123
74
  import { Component, registerComponent } from 'react-three-game';
124
75
  import { useFrame } from '@react-three/fiber';
125
- import { useRef } from 'react';
126
76
 
127
- const RotatorComponent: Component = {
77
+ const Rotator: Component = {
128
78
  name: 'Rotator',
129
-
130
79
  Editor: ({ component, onUpdate }) => (
131
- <div>
132
- <label>Speed</label>
133
- <input
134
- type="number"
135
- value={component.properties.speed ?? 1.0}
136
- onChange={e => onUpdate({ ...component.properties, speed: parseFloat(e.target.value) })}
137
- />
138
- <label>Axis</label>
139
- <select
140
- value={component.properties.axis ?? 'y'}
141
- onChange={e => onUpdate({ ...component.properties, axis: e.target.value })}
142
- >
143
- <option value="x">X</option>
144
- <option value="y">Y</option>
145
- <option value="z">Z</option>
146
- </select>
147
- </div>
80
+ <input type="number" value={component.properties.speed}
81
+ onChange={e => onUpdate({ speed: +e.target.value })} />
148
82
  ),
149
-
150
83
  View: ({ properties, children }) => {
151
- const ref = useRef();
152
- const speed = properties.speed ?? 1.0;
153
- const axis = properties.axis ?? 'y';
154
-
155
- useFrame((state, delta) => {
156
- if (ref.current) {
157
- ref.current.rotation[axis] += delta * speed;
158
- }
159
- });
160
-
84
+ const ref = useRef<Group>(null);
85
+ useFrame((_, dt) => { ref.current!.rotation.y += dt * properties.speed });
161
86
  return <group ref={ref}>{children}</group>;
162
87
  },
163
-
164
- defaultProperties: { speed: 1.0, axis: 'y' }
88
+ defaultProperties: { speed: 1 }
165
89
  };
166
90
 
167
- // Register before using PrefabEditor
168
- registerComponent(RotatorComponent);
169
- ```
170
-
171
- ### Usage in Prefab JSON
172
-
173
- ```json
174
- {
175
- "id": "spinning-cube",
176
- "components": {
177
- "transform": { "type": "Transform", "properties": { "position": [0, 1, 0] } },
178
- "geometry": { "type": "Geometry", "properties": { "geometryType": "box" } },
179
- "material": { "type": "Material", "properties": { "color": "#ff6b6b" } },
180
- "rotator": { "type": "Rotator", "properties": { "speed": 2.0, "axis": "y" } }
181
- }
182
- }
91
+ registerComponent(Rotator); // before rendering PrefabEditor
183
92
  ```
184
93
 
185
- ### Wrapper vs Leaf Components
186
-
187
- **Wrapper components** (accept `children`) wrap the rendered content:
188
- - Use for behaviors that need to manipulate the scene graph (animations, controllers)
189
- - Example: Rotator wraps mesh to apply rotation
190
-
191
- **Leaf components** (no `children`) render as siblings:
192
- - Use for standalone effects (lights, particles, audio sources)
193
- - Example: SpotLight renders a `<spotLight>` element
194
-
195
- The engine automatically detects component type by checking if `View` accepts `children` prop.
196
-
197
- ## Built-in Components
198
-
199
- | Component | Properties |
200
- |-----------|-----------|
201
- | **Transform** | `position: [x,y,z]`, `rotation: [x,y,z]`, `scale: [x,y,z]` |
202
- | **Geometry** | `geometryType: "box"\|"sphere"\|"plane"\|"cylinder"`, `args: number[]` |
203
- | **Material** | `color: string`, `texture?: string`, `metalness?: number`, `roughness?: number` |
204
- | **Physics** | `type: "dynamic"\|"fixed"` |
205
- | **Model** | `filename: string`, `instanced?: boolean` |
206
- | **SpotLight** | `color: string`, `intensity: number`, `angle: number`, `penumbra: number` |
94
+ **Wrapper** components accept `children` (animations, controllers). **Leaf** components don't (lights, particles).
207
95
 
208
- ## Prefab Editor
96
+ ## Visual Editor
209
97
 
210
98
  ```jsx
211
99
  import { PrefabEditor } from 'react-three-game';
212
-
213
- export default function EditorPage() {
214
- return <PrefabEditor />;
215
- }
100
+ <PrefabEditor initialPrefab={sceneData} onPrefabChange={setSceneData} />
216
101
  ```
217
102
 
218
- Transform gizmos (T/R/S keys), drag-to-reorder tree, import/export JSON, edit/play toggle.
219
-
220
- ## Implementation Details
103
+ Keys: **T**ranslate / **R**otate / **S**cale. Drag tree nodes to reparent. Import/export JSON.
221
104
 
222
- ### Transform Hierarchy
223
- - Local transforms stored in JSON (relative to parent)
224
- - World transforms computed at runtime via matrix multiplication
225
- - TransformControls extract world matrix → compute parent inverse → derive new local transform
105
+ ## Internals
226
106
 
227
- ### GPU Instancing
228
- Enable with `model.properties.instanced = true` for optimized repeated geometry. Uses drei's `<Merged>` + `<InstancedRigidBodies>`.
107
+ - **Transforms**: Local in JSON, world computed via matrix multiplication
108
+ - **Instancing**: `model.properties.instanced = true` `<Merged>` + `<InstancedRigidBodies>`
109
+ - **Models**: GLB/GLTF (Draco) and FBX auto-load from `filename`
229
110
 
230
- ### Model Loading
231
- Supports GLB/GLTF (with Draco compression) and FBX. Models auto-load when `model.properties.filename` is detected.
111
+ ## Tree Utilities
232
112
 
233
- ## Patterns
234
-
235
- ### Load External Prefabs
236
- ```jsx
237
- import levelData from './prefabs/arena.json';
238
- <PrefabRoot data={levelData} />
239
- ```
240
-
241
- ### Update Prefab Nodes
242
113
  ```typescript
243
- function updatePrefabNode(root: GameObject, id: string, update: (node: GameObject) => GameObject): GameObject {
244
- if (root.id === id) return update(root);
245
- if (root.children) {
246
- return { ...root, children: root.children.map(child => updatePrefabNode(child, id, update)) };
247
- }
248
- return root;
249
- }
114
+ import { findNode, updateNode, deleteNode, cloneNode } from 'react-three-game';
115
+
116
+ const updated = updateNode(root, nodeId, n => ({ ...n, disabled: true }));
250
117
  ```
251
118
 
252
119
  ## Development
253
120
 
254
121
  ```bash
255
- git clone https://github.com/prnthh/react-three-game.git
256
- cd react-three-game
257
- npm install
258
- npm run dev # tsc --watch + Next.js docs
259
- npm run build # TypeScript → /dist
260
- npm publish # publish to npm
122
+ npm run dev # tsc --watch + docs site (localhost:3000)
123
+ npm run build # → /dist
124
+ npm run release # build + publish
261
125
  ```
262
126
 
263
- Project structure:
264
127
  ```
265
- /src → library source
266
- /shared GameCanvas
267
- /tools
268
- /prefabeditor → editor + PrefabRoot
269
- /docs → Next.js site
270
- /app → demo pages
128
+ /src → library (published)
129
+ /docs Next.js demo site
271
130
  ```
272
131
 
273
- ## Tech Stack
274
-
275
- React 19 • Three.js r181 • TypeScript 5 • WebGPU • Rapier Physics
276
-
277
- ## License
132
+ ---
278
133
 
279
- MIT © [prnth](https://github.com/prnthh)
134
+ React 19 · Three.js WebGPU · TypeScript 5 · Rapier WASM · MIT License
package/dist/index.d.ts CHANGED
@@ -5,5 +5,7 @@ export { DragDropLoader } from './tools/dragdrop/DragDropLoader';
5
5
  export { TextureListViewer, ModelListViewer, SoundListViewer, SharedCanvas, } from './tools/assetviewer/page';
6
6
  export { registerComponent } from './tools/prefabeditor/components/ComponentRegistry';
7
7
  export type { Component } from './tools/prefabeditor/components/ComponentRegistry';
8
+ export * as editorStyles from './tools/prefabeditor/styles';
9
+ export * from './tools/prefabeditor/utils';
8
10
  export * from './helpers';
9
- export type { Prefab, GameObject } from './tools/prefabeditor/types';
11
+ export type { Prefab, GameObject, ComponentData } from './tools/prefabeditor/types';
package/dist/index.js CHANGED
@@ -6,5 +6,8 @@ export { DragDropLoader } from './tools/dragdrop/DragDropLoader';
6
6
  export { TextureListViewer, ModelListViewer, SoundListViewer, SharedCanvas, } from './tools/assetviewer/page';
7
7
  // Component Registry
8
8
  export { registerComponent } from './tools/prefabeditor/components/ComponentRegistry';
9
+ // Editor Styles & Utils
10
+ export * as editorStyles from './tools/prefabeditor/styles';
11
+ export * from './tools/prefabeditor/utils';
9
12
  // Helpers
10
13
  export * from './helpers';
@@ -1,10 +1,8 @@
1
1
  import { Dispatch, SetStateAction } from 'react';
2
2
  import { Prefab } from "./types";
3
- interface EditorTreeProps {
3
+ export default function EditorTree({ prefabData, setPrefabData, selectedId, setSelectedId }: {
4
4
  prefabData?: Prefab;
5
5
  setPrefabData?: Dispatch<SetStateAction<Prefab>>;
6
6
  selectedId: string | null;
7
7
  setSelectedId: Dispatch<SetStateAction<string | null>>;
8
- }
9
- export default function EditorTree({ prefabData, setPrefabData, selectedId, setSelectedId }: EditorTreeProps): import("react/jsx-runtime").JSX.Element | null;
10
- export {};
8
+ }): import("react/jsx-runtime").JSX.Element | null;