react-three-game 0.0.67 → 0.0.69
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 +109 -304
- package/dist/index.d.ts +15 -8
- package/dist/index.js +11 -8
- package/dist/shared/GameCanvas.d.ts +1 -2
- package/dist/tools/prefabeditor/EditorContext.d.ts +2 -2
- package/dist/tools/prefabeditor/EditorTree.d.ts +6 -6
- package/dist/tools/prefabeditor/EditorTree.js +92 -142
- package/dist/tools/prefabeditor/EditorTreeMenus.d.ts +4 -11
- package/dist/tools/prefabeditor/EditorTreeMenus.js +16 -25
- package/dist/tools/prefabeditor/EditorUI.d.ts +5 -5
- package/dist/tools/prefabeditor/EditorUI.js +14 -11
- package/dist/tools/prefabeditor/GameEvents.d.ts +0 -30
- package/dist/tools/prefabeditor/GameEvents.js +0 -7
- package/dist/tools/prefabeditor/PrefabEditor.d.ts +12 -13
- package/dist/tools/prefabeditor/PrefabEditor.js +168 -138
- package/dist/tools/prefabeditor/PrefabRoot.d.ts +8 -5
- package/dist/tools/prefabeditor/PrefabRoot.js +141 -123
- package/dist/tools/prefabeditor/components/AmbientLightComponent.js +3 -3
- package/dist/tools/prefabeditor/components/CameraComponent.js +2 -2
- package/dist/tools/prefabeditor/components/DirectionalLightComponent.js +2 -2
- package/dist/tools/prefabeditor/components/ModelComponent.js +0 -1
- package/dist/tools/prefabeditor/components/SpotLightComponent.js +2 -2
- package/dist/tools/prefabeditor/components/TextComponent.js +2 -3
- package/dist/tools/prefabeditor/components/TransformComponent.js +9 -14
- package/dist/tools/prefabeditor/prefabStore.d.ts +42 -0
- package/dist/tools/prefabeditor/prefabStore.js +347 -0
- package/dist/tools/prefabeditor/sceneApi.d.ts +44 -0
- package/dist/tools/prefabeditor/sceneApi.js +161 -0
- package/dist/tools/prefabeditor/styles.d.ts +2 -1
- package/dist/tools/prefabeditor/styles.js +2 -12
- package/dist/tools/prefabeditor/utils.d.ts +15 -36
- package/dist/tools/prefabeditor/utils.js +36 -162
- package/package.json +4 -3
- package/dist/tools/prefabeditor/EventSystem.d.ts +0 -7
- package/dist/tools/prefabeditor/EventSystem.js +0 -23
package/README.md
CHANGED
|
@@ -1,197 +1,118 @@
|
|
|
1
1
|
# react-three-game
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+

|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
npm i react-three-game @react-three/drei @react-three/fiber @react-three/rapier three
|
|
7
|
-
```
|
|
5
|
+
JSON-first 3D game engine for React Three Fiber.
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-

|
|
7
|
+
Built on top of [three.js](https://github.com/mrdoob/three.js), [@react-three/fiber](https://github.com/pmndrs/react-three-fiber), and [@react-three/rapier](https://github.com/pmndrs/react-three-rapier).
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
* **🧱 Prefabs** - Save scenes as serializable JSON and load them on their own or inside other scenes.
|
|
10
|
+
* **🎬 Scene Editor** - Edit prefabs visually with hierarchy, inspector, transform gizmos, and play mode.
|
|
11
|
+
* **⚛️ Physics** - Author rigid bodies directly in prefab data and run them through Rapier.
|
|
12
|
+
* **🧩 Components** - Build scenes from reusable `GameObject` + component composition.
|
|
13
|
+
* **🔧 Runtime Scene API** - Mutate the live world through `Scene`, `Entity`, and `EntityComponent` handles.
|
|
14
|
+
* **⚡ R3F Native** - Use normal React Three Fiber components whenever runtime behavior is clearer in code.
|
|
15
|
+
|
|
16
|
+
## Documentation
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
* Website: https://prnth.com/react-three-game
|
|
19
|
+
* Editor: https://prnth.com/react-three-game/editor
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
## Install
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
```bash
|
|
24
|
+
npm install react-three-game @react-three/drei @react-three/fiber @react-three/rapier three
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
22
28
|
|
|
23
|
-
|
|
29
|
+
Here is a minimal example that renders a prefab inside a normal R3F app:
|
|
24
30
|
|
|
25
|
-
```
|
|
31
|
+
```tsx
|
|
26
32
|
import { Physics } from "@react-three/rapier";
|
|
27
|
-
import { GameCanvas, PrefabRoot } from "react-three-game";
|
|
33
|
+
import { GameCanvas, PrefabRoot, ground } from "react-three-game";
|
|
28
34
|
|
|
29
|
-
const
|
|
35
|
+
const prefab = {
|
|
36
|
+
id: "starter-scene",
|
|
37
|
+
name: "Starter Scene",
|
|
30
38
|
root: {
|
|
31
|
-
id: "
|
|
39
|
+
id: "root",
|
|
32
40
|
children: [
|
|
33
|
-
{
|
|
34
|
-
id: "ground",
|
|
35
|
-
components: {
|
|
36
|
-
transform: { type: "Transform", properties: { position: [0, 0, 0], rotation: [-1.57, 0, 0] } },
|
|
37
|
-
geometry: { type: "Geometry", properties: { geometryType: "plane", args: [50, 50] } },
|
|
38
|
-
material: { type: "Material", properties: { color: "#3a3" } },
|
|
39
|
-
physics: { type: "Physics", properties: { type: "fixed" } }
|
|
40
|
-
}
|
|
41
|
-
},
|
|
41
|
+
ground({ size: 50, color: "#3a3" }),
|
|
42
42
|
{
|
|
43
43
|
id: "ball",
|
|
44
44
|
components: {
|
|
45
|
-
transform: {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
45
|
+
transform: {
|
|
46
|
+
type: "Transform",
|
|
47
|
+
properties: {
|
|
48
|
+
position: [0, 5, 0],
|
|
49
|
+
rotation: [0, 0, 0],
|
|
50
|
+
scale: [1, 1, 1],
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
geometry: {
|
|
54
|
+
type: "Geometry",
|
|
55
|
+
properties: { geometryType: "sphere", args: [0.5, 32, 32] },
|
|
56
|
+
},
|
|
57
|
+
material: {
|
|
58
|
+
type: "Material",
|
|
59
|
+
properties: { color: "#f66" },
|
|
60
|
+
},
|
|
61
|
+
physics: {
|
|
62
|
+
type: "Physics",
|
|
63
|
+
properties: { type: "dynamic" },
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
},
|
|
53
69
|
};
|
|
54
70
|
|
|
55
|
-
export default function
|
|
71
|
+
export default function App() {
|
|
56
72
|
return (
|
|
57
|
-
<
|
|
58
|
-
<
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
</GameCanvas>
|
|
64
|
-
</main>
|
|
73
|
+
<GameCanvas>
|
|
74
|
+
<Physics>
|
|
75
|
+
<ambientLight intensity={0.8} />
|
|
76
|
+
<PrefabRoot data={prefab} />
|
|
77
|
+
</Physics>
|
|
78
|
+
</GameCanvas>
|
|
65
79
|
);
|
|
66
80
|
}
|
|
67
81
|
```
|
|
68
82
|
|
|
69
|
-
|
|
83
|
+
This example renders a falling sphere above a ground plane.
|
|
70
84
|
|
|
71
85
|
## Prefab Editor
|
|
72
86
|
|
|
73
|
-
|
|
74
|
-
import { useRef } from 'react';
|
|
75
|
-
import { PrefabEditor } from 'react-three-game';
|
|
76
|
-
|
|
77
|
-
// Standalone editor
|
|
78
|
-
<PrefabEditor initialPrefab={sceneData} onPrefabChange={setSceneData} />
|
|
79
|
-
|
|
80
|
-
// Canvas-only editing mode (keeps canvas selection/gizmos, hides hierarchy + inspector + toolbar)
|
|
81
|
-
<PrefabEditor initialPrefab={sceneData} showUI={false} />
|
|
82
|
-
|
|
83
|
-
// With custom R3F components
|
|
84
|
-
<PrefabEditor initialPrefab={sceneData}>
|
|
85
|
-
<CustomComponent />
|
|
86
|
-
</PrefabEditor>
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### Embedded / Headless Editor
|
|
87
|
+
In addition to the runtime renderer, there is a visual editor for authoring prefabs.
|
|
90
88
|
|
|
91
89
|
```tsx
|
|
92
|
-
import {
|
|
93
|
-
import type { Object3D } from 'three';
|
|
94
|
-
import { PrefabEditor, type PrefabEditorRef } from 'react-three-game';
|
|
95
|
-
|
|
96
|
-
export function EmbeddedEditor({ prefab, onPrefabChange }: {
|
|
97
|
-
prefab: any;
|
|
98
|
-
onPrefabChange: (nextPrefab: any) => void;
|
|
99
|
-
}) {
|
|
100
|
-
const editorRef = useRef<PrefabEditorRef>(null);
|
|
101
|
-
|
|
102
|
-
function loadScene(nextPrefab: any) {
|
|
103
|
-
editorRef.current?.replacePrefab(nextPrefab);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function importRuntimeModel(model: Object3D) {
|
|
107
|
-
editorRef.current?.addModel('models/runtime/chair.glb', model, {
|
|
108
|
-
name: 'Chair',
|
|
109
|
-
parentId: 'root',
|
|
110
|
-
});
|
|
111
|
-
}
|
|
90
|
+
import { PrefabEditor } from "react-three-game";
|
|
112
91
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
<div style={{ position: 'absolute', top: 12, left: 12, zIndex: 10 }}>
|
|
116
|
-
<button onClick={() => loadScene(prefab)}>Reload Scene</button>
|
|
117
|
-
<button onClick={() => editorRef.current?.exportGLBData()}>Export GLB Data</button>
|
|
118
|
-
</div>
|
|
119
|
-
|
|
120
|
-
<PrefabEditor
|
|
121
|
-
ref={editorRef}
|
|
122
|
-
initialPrefab={prefab}
|
|
123
|
-
onPrefabChange={onPrefabChange}
|
|
124
|
-
showUI={false}
|
|
125
|
-
physics={false}
|
|
126
|
-
enableWindowDrop={false}
|
|
127
|
-
canvasProps={{ style: { height: '100%', width: '100%' } }}
|
|
128
|
-
/>
|
|
129
|
-
</div>
|
|
130
|
-
);
|
|
92
|
+
export default function App() {
|
|
93
|
+
return <PrefabEditor initialPrefab={prefab} onChange={console.log} />;
|
|
131
94
|
}
|
|
132
95
|
```
|
|
133
96
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
- `replacePrefab(prefab)` replaces the current scene through the editor state pipeline and resets editor history/selection.
|
|
137
|
-
- `setPrefab(prefab)` updates the current prefab in place and preserves selection when the selected node ID still exists.
|
|
138
|
-
- `addModel(path, model, options?)` creates a model node and injects the runtime asset in one step.
|
|
139
|
-
- `addTexture(path, texture, options?)` creates a textured plane node and injects the runtime texture in one step.
|
|
140
|
-
- `exportGLBData()` returns the GLB `ArrayBuffer` without triggering a download.
|
|
141
|
-
- `canvasProps` forwards canvas-level sizing, camera, event, and style props to `GameCanvas`.
|
|
142
|
-
|
|
143
|
-
### Editor State Bridge
|
|
144
|
-
|
|
145
|
-
Compose small helper components inside `PrefabEditor` when custom UI needs to control the editor.
|
|
146
|
-
|
|
147
|
-
```tsx
|
|
148
|
-
import { useEffect } from 'react';
|
|
149
|
-
import {
|
|
150
|
-
PrefabEditor,
|
|
151
|
-
useEditorContext,
|
|
152
|
-
type EditorContextType,
|
|
153
|
-
} from 'react-three-game';
|
|
97
|
+
Open the hosted editor here:
|
|
154
98
|
|
|
155
|
-
|
|
156
|
-
const editorState = useEditorContext();
|
|
157
|
-
|
|
158
|
-
useEffect(() => {
|
|
159
|
-
onReady(editorState);
|
|
160
|
-
}, [editorState, onReady]);
|
|
161
|
-
|
|
162
|
-
return null;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
function CustomEditor() {
|
|
166
|
-
return (
|
|
167
|
-
<PrefabEditor initialPrefab={sceneData} showUI={false}>
|
|
168
|
-
<EditorStateBridge onReady={({ setTransformMode }) => setTransformMode('translate')} />
|
|
169
|
-
</PrefabEditor>
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
```
|
|
99
|
+
* https://prnth.com/react-three-game/editor
|
|
173
100
|
|
|
174
|
-
|
|
175
|
-
- Use it for editor state: transform mode, edit/play checks, focus actions, and export buttons.
|
|
176
|
-
- Keep bridge components small and focused on one editor concern.
|
|
101
|
+
## Prefabs And Scenes
|
|
177
102
|
|
|
178
|
-
|
|
103
|
+
`Prefab` is the serializable pure data format.
|
|
179
104
|
|
|
180
|
-
|
|
181
|
-
- play mode: physics and runtime behavior
|
|
182
|
-
- skip editor-only code when `editMode` is `false`
|
|
183
|
-
- use `showUI={false}` for custom shells
|
|
184
|
-
- use `enableWindowDrop={false}` when the host app owns drag/drop
|
|
105
|
+
`Scene` is the live runtime/editor world handle.
|
|
185
106
|
|
|
186
|
-
|
|
107
|
+
That means a saved scene is just a prefab, and the same prefab can be:
|
|
187
108
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
109
|
+
* edited directly in `PrefabEditor`
|
|
110
|
+
* rendered directly with `PrefabRoot`
|
|
111
|
+
* loaded inside another scene as reusable content
|
|
191
112
|
|
|
192
|
-
##
|
|
113
|
+
## Prefab Format
|
|
193
114
|
|
|
194
|
-
```
|
|
115
|
+
```ts
|
|
195
116
|
interface Prefab {
|
|
196
117
|
id?: string;
|
|
197
118
|
name?: string;
|
|
@@ -202,176 +123,60 @@ interface GameObject {
|
|
|
202
123
|
id: string;
|
|
203
124
|
name?: string;
|
|
204
125
|
disabled?: boolean;
|
|
126
|
+
locked?: boolean;
|
|
205
127
|
components?: Record<string, { type: string; properties: any }>;
|
|
206
128
|
children?: GameObject[];
|
|
207
129
|
}
|
|
208
130
|
```
|
|
209
131
|
|
|
210
|
-
|
|
132
|
+
## Runtime Mutation
|
|
211
133
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
| Component | Key Properties |
|
|
215
|
-
|-----------|----------------|
|
|
216
|
-
| Transform | `position`, `rotation`, `scale` — all `[x,y,z]` arrays, rotation in radians |
|
|
217
|
-
| Geometry | `geometryType`: box/sphere/plane/cylinder, `args`: dimension array |
|
|
218
|
-
| Material | `color`, `texture?`, `metalness?`, `roughness?` |
|
|
219
|
-
| Physics | `type`: dynamic/fixed/kinematicPosition/kinematicVelocity, `mass?`, `restitution?` (bounciness), `friction?`, `linearVelocity?`, `angularVelocity?`, plus any Rapier props |
|
|
220
|
-
| Model | `filename` (GLB/FBX path), `instanced?` for GPU batching |
|
|
221
|
-
| SpotLight | `color`, `intensity`, `angle`, `penumbra` |
|
|
222
|
-
|
|
223
|
-
## Tree Utilities
|
|
224
|
-
|
|
225
|
-
```typescript
|
|
226
|
-
import { findNode, updateNode, updateNodeById, deleteNode, cloneNode, exportGLBData } from 'react-three-game';
|
|
227
|
-
|
|
228
|
-
const node = findNode(root, nodeId);
|
|
229
|
-
const updated = updateNode(root, nodeId, n => ({ ...n, disabled: true })); // or updateNodeById
|
|
230
|
-
const afterDelete = deleteNode(root, nodeId);
|
|
231
|
-
const cloned = cloneNode(node);
|
|
232
|
-
const glbData = await exportGLBData(sceneRoot); // export scene to GLB ArrayBuffer
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
### Scene State Updates
|
|
134
|
+
When you need to change the live world, use the `Scene` API from `PrefabEditorRef`.
|
|
236
135
|
|
|
237
136
|
```tsx
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
visible,
|
|
241
|
-
}: {
|
|
242
|
-
editorRef: React.RefObject<PrefabEditorRef | null>;
|
|
243
|
-
visible: boolean;
|
|
244
|
-
}) {
|
|
245
|
-
useEffect(() => {
|
|
246
|
-
const editor = editorRef.current;
|
|
247
|
-
if (!editor) return;
|
|
248
|
-
|
|
249
|
-
const prefab = editor.prefab;
|
|
250
|
-
const root = updateNodeById(prefab.root, 'helper-grid', node => ({
|
|
251
|
-
...node,
|
|
252
|
-
disabled: !visible,
|
|
253
|
-
}));
|
|
254
|
-
|
|
255
|
-
editor.setPrefab({ ...prefab, root });
|
|
256
|
-
}, [editorRef, visible]);
|
|
257
|
-
|
|
258
|
-
return null;
|
|
259
|
-
}
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
- Use `updateNode(...)` or `updateNodeById(...)` for scene state changes inside the prefab tree.
|
|
263
|
-
- For sensor and collision event patterns, see advanced physics examples.
|
|
264
|
-
|
|
265
|
-
## Custom Components
|
|
266
|
-
|
|
267
|
-
```tsx
|
|
268
|
-
import { useRef } from 'react';
|
|
269
|
-
import { Component, registerComponent, FieldRenderer, FieldDefinition } from 'react-three-game';
|
|
270
|
-
import { useFrame } from '@react-three/fiber';
|
|
271
|
-
import type { Group } from 'three';
|
|
272
|
-
|
|
273
|
-
const rotatorFields: FieldDefinition[] = [
|
|
274
|
-
{ name: 'speed', type: 'number', label: 'Speed', step: 0.1 },
|
|
275
|
-
{ name: 'axis', type: 'select', label: 'Axis', options: [
|
|
276
|
-
{ value: 'x', label: 'X' },
|
|
277
|
-
{ value: 'y', label: 'Y' },
|
|
278
|
-
{ value: 'z', label: 'Z' },
|
|
279
|
-
]},
|
|
280
|
-
];
|
|
281
|
-
|
|
282
|
-
const Rotator: Component = {
|
|
283
|
-
name: 'Rotator',
|
|
284
|
-
Editor: ({ component, onUpdate }) => (
|
|
285
|
-
<FieldRenderer fields={rotatorFields} values={component.properties} onChange={onUpdate} />
|
|
286
|
-
),
|
|
287
|
-
View: ({ properties, children }) => {
|
|
288
|
-
const ref = useRef<Group>(null);
|
|
289
|
-
useFrame((_, dt) => { ref.current!.rotation.y += dt * properties.speed });
|
|
290
|
-
return <group ref={ref}>{children}</group>;
|
|
291
|
-
},
|
|
292
|
-
defaultProperties: { speed: 1, axis: 'y' }
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
registerComponent(Rotator); // before rendering PrefabEditor
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
Components may render visible content, wrap child content, or contribute runtime behavior. Keep those semantics explicit in the component `View` rather than relying on hidden tree rules.
|
|
137
|
+
import { useEffect, useRef } from "react";
|
|
138
|
+
import { PrefabEditor, type PrefabEditorRef } from "react-three-game";
|
|
299
139
|
|
|
300
|
-
|
|
140
|
+
function RaiseBall() {
|
|
141
|
+
const editorRef = useRef<PrefabEditorRef>(null);
|
|
301
142
|
|
|
302
|
-
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
const transform = editorRef.current
|
|
145
|
+
?.scene
|
|
146
|
+
.find("ball")
|
|
147
|
+
?.getComponent<{ position: [number, number, number] }>("Transform");
|
|
303
148
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
| `vector3` | X/Y/Z inputs with drag-to-scrub | `snap?: number` |
|
|
307
|
-
| `number` | Numeric input | `min?`, `max?`, `step?` |
|
|
308
|
-
| `string` | Text input | `placeholder?` |
|
|
309
|
-
| `color` | Color picker + hex input | — |
|
|
310
|
-
| `boolean` | Checkbox | — |
|
|
311
|
-
| `select` | Dropdown | `options: { value, label }[]` |
|
|
312
|
-
| `custom` | Render function for one-off UI | `render: (props) => ReactNode` |
|
|
149
|
+
transform?.set("position", [0, 8, 0]);
|
|
150
|
+
}, []);
|
|
313
151
|
|
|
314
|
-
|
|
315
|
-
// Custom field example for complex one-off UI
|
|
316
|
-
{
|
|
317
|
-
name: 'gradient',
|
|
318
|
-
type: 'custom',
|
|
319
|
-
label: 'Gradient',
|
|
320
|
-
render: ({ value, onChange, values, onChangeMultiple }) => (
|
|
321
|
-
<GradientPicker value={value} onChange={onChange} />
|
|
322
|
-
),
|
|
152
|
+
return <PrefabEditor ref={editorRef} initialPrefab={prefab} />;
|
|
323
153
|
}
|
|
324
154
|
```
|
|
325
155
|
|
|
326
|
-
##
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
156
|
+
## Useful Exports
|
|
157
|
+
|
|
158
|
+
* `GameCanvas`
|
|
159
|
+
* `PrefabRoot`
|
|
160
|
+
* `PrefabEditor`
|
|
161
|
+
* `Prefab`
|
|
162
|
+
* `GameObject`
|
|
163
|
+
* `Scene`
|
|
164
|
+
* `Entity`
|
|
165
|
+
* `EntityComponent`
|
|
166
|
+
* `registerComponent`
|
|
167
|
+
* `ground(...)`
|
|
168
|
+
* `loadJson()` / `saveJson()`
|
|
169
|
+
* `loadModel()` / `loadTexture()`
|
|
170
|
+
* `exportGLB()` / `exportGLBData()`
|
|
331
171
|
|
|
332
172
|
## Development
|
|
333
173
|
|
|
334
174
|
```bash
|
|
335
|
-
npm run dev
|
|
336
|
-
npm run build
|
|
337
|
-
npm run release
|
|
338
|
-
```
|
|
339
|
-
|
|
175
|
+
npm run dev
|
|
176
|
+
npm run build
|
|
177
|
+
npm run release
|
|
340
178
|
```
|
|
341
|
-
/src → library (published)
|
|
342
|
-
/docs → Next.js demo site
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
---
|
|
346
|
-
|
|
347
|
-
React 19 · Three.js WebGPU · TypeScript 5 · Rapier WASM · MIT License
|
|
348
|
-
|
|
349
|
-
## Manifest generation script
|
|
350
|
-
|
|
351
|
-
A small helper script is included to auto-generate asset manifests from the `public` folder. See `docs/generate-manifests.sh`.
|
|
352
|
-
|
|
353
|
-
- **What it does:**
|
|
354
|
-
Searches `public/models` for `.glb`/`.fbx`, `public/textures` for `.jpg`/`.png`, and `public/sound` for `.mp3`/`.wav`, then writes JSON arrays to:
|
|
355
|
-
- `public/models/manifest.json`
|
|
356
|
-
- `public/textures/manifest.json`
|
|
357
|
-
- `public/sound/manifest.json`
|
|
358
|
-
|
|
359
|
-
These manifest files are used to populate the Asset Viewer in the Editor.
|
|
360
|
-
|
|
361
|
-
- **How to run:**
|
|
362
|
-
|
|
363
|
-
1. Make it executable (once):
|
|
364
|
-
|
|
365
|
-
```sh
|
|
366
|
-
chmod +x docs/generate-manifests.sh
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
2. Run the script from the repo root (zsh/bash):
|
|
370
|
-
|
|
371
|
-
```sh
|
|
372
|
-
./docs/generate-manifests.sh
|
|
373
|
-
```
|
|
374
179
|
|
|
180
|
+
## License
|
|
375
181
|
|
|
376
|
-
|
|
377
|
-
If you need different file types or output formatting, edit `docs/generate-manifests.sh`.
|
|
182
|
+
VPL
|
package/dist/index.d.ts
CHANGED
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
export { default as GameCanvas } from './shared/GameCanvas';
|
|
2
|
-
export
|
|
2
|
+
export type { GameCanvasProps } from './shared/GameCanvas';
|
|
3
|
+
export { ground } from './helpers';
|
|
4
|
+
export type { GroundOptions, Vec3 } from './helpers';
|
|
3
5
|
export { sound as soundManager } from './helpers/SoundManager';
|
|
4
6
|
export { default as PrefabEditor } from './tools/prefabeditor/PrefabEditor';
|
|
5
7
|
export { default as PrefabRoot } from './tools/prefabeditor/PrefabRoot';
|
|
6
8
|
export { useEditorContext } from './tools/prefabeditor/EditorContext';
|
|
7
9
|
export type { EditorContextType } from './tools/prefabeditor/EditorContext';
|
|
10
|
+
export { createPrefabStore, prefabStoreToPrefab } from './tools/prefabeditor/prefabStore';
|
|
11
|
+
export type { PrefabStoreApi, PrefabStoreState } from './tools/prefabeditor/prefabStore';
|
|
12
|
+
export { createScene } from './tools/prefabeditor/sceneApi';
|
|
8
13
|
export { registerComponent } from './tools/prefabeditor/components/ComponentRegistry';
|
|
9
14
|
export { FieldRenderer, FieldGroup, Label, Vector3Input, Vector3Field, NumberField, ColorInput, ColorField, StringInput, StringField, BooleanInput, BooleanField, SelectInput, SelectField, } from './tools/prefabeditor/components/Input';
|
|
10
|
-
export
|
|
15
|
+
export { loadJson, saveJson, exportGLB, exportGLBData, regenerateIds, computeParentWorldMatrix, createModelNode, createImageNode, } from './tools/prefabeditor/utils';
|
|
11
16
|
export type { ExportGLBOptions } from './tools/prefabeditor/utils';
|
|
12
|
-
export type {
|
|
13
|
-
export type {
|
|
17
|
+
export type { PrefabEditorProps, PrefabEditorRef, } from './tools/prefabeditor/PrefabEditor';
|
|
18
|
+
export type { SpawnOptions, Scene, Entity, EntityComponent, EntityData, EntityUpdate, PropertyPath, SceneUpdates, } from './tools/prefabeditor/sceneApi';
|
|
19
|
+
export type { PrefabRootProps, PrefabRootRef } from './tools/prefabeditor/PrefabRoot';
|
|
14
20
|
export type { Component } from './tools/prefabeditor/components/ComponentRegistry';
|
|
15
21
|
export type { FieldDefinition, FieldType } from './tools/prefabeditor/components/Input';
|
|
16
|
-
export type { Prefab, GameObject, ComponentData } from './tools/prefabeditor/types';
|
|
22
|
+
export type { Prefab, GameObject, ComponentData as ComponentDefinition } from './tools/prefabeditor/types';
|
|
17
23
|
export { gameEvents, useGameEvent, getEntityIdFromRigidBody } from './tools/prefabeditor/GameEvents';
|
|
18
24
|
export type { GameEventType, GameEventMap, GameEventPayload, PhysicsEventType, InteractionEventType, PhysicsEventPayload, ClickEventPayload } from './tools/prefabeditor/GameEvents';
|
|
19
|
-
export {
|
|
20
|
-
export type {
|
|
21
|
-
export
|
|
25
|
+
export { loadFiles } from './tools/dragdrop/DragDropLoader';
|
|
26
|
+
export type { AssetLoadOptions } from './tools/dragdrop/DragDropLoader';
|
|
27
|
+
export { loadModel, loadTexture } from './tools/dragdrop/modelLoader';
|
|
28
|
+
export type { LoadedModel, LoadedTexture, LoadedModels, LoadedTextures, ModelLoadResult, ProgressCallback, TextureLoadResult } from './tools/dragdrop/modelLoader';
|
|
22
29
|
export { TextureListViewer, ModelListViewer, SoundListViewer, TexturePicker, ModelPicker, SingleTextureViewer, SingleModelViewer, SingleSoundViewer, SharedCanvas, } from './tools/assetviewer/page';
|
package/dist/index.js
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
// Core
|
|
2
2
|
export { default as GameCanvas } from './shared/GameCanvas';
|
|
3
3
|
// Helpers
|
|
4
|
-
export
|
|
4
|
+
export { ground } from './helpers';
|
|
5
5
|
export { sound as soundManager } from './helpers/SoundManager';
|
|
6
|
-
// Prefab Editor
|
|
6
|
+
// Prefab Editor
|
|
7
7
|
export { default as PrefabEditor } from './tools/prefabeditor/PrefabEditor';
|
|
8
8
|
export { default as PrefabRoot } from './tools/prefabeditor/PrefabRoot';
|
|
9
9
|
export { useEditorContext } from './tools/prefabeditor/EditorContext';
|
|
10
|
+
// Prefab Editor - Store & Scene API
|
|
11
|
+
export { createPrefabStore, prefabStoreToPrefab } from './tools/prefabeditor/prefabStore';
|
|
12
|
+
export { createScene } from './tools/prefabeditor/sceneApi';
|
|
10
13
|
// Prefab Editor - Component Registry
|
|
11
14
|
export { registerComponent } from './tools/prefabeditor/components/ComponentRegistry';
|
|
12
15
|
// Prefab Editor - Input Components
|
|
13
16
|
export { FieldRenderer, FieldGroup, Label, Vector3Input, Vector3Field, NumberField, ColorInput, ColorField, StringInput, StringField, BooleanInput, BooleanField, SelectInput, SelectField, } from './tools/prefabeditor/components/Input';
|
|
14
|
-
// Prefab Editor -
|
|
15
|
-
export
|
|
17
|
+
// Prefab Editor - Utils
|
|
18
|
+
export { loadJson, saveJson, exportGLB, exportGLBData, regenerateIds, computeParentWorldMatrix, createModelNode, createImageNode, } from './tools/prefabeditor/utils';
|
|
16
19
|
// Game Events (physics + custom events)
|
|
17
20
|
export { gameEvents, useGameEvent, getEntityIdFromRigidBody } from './tools/prefabeditor/GameEvents';
|
|
18
|
-
//
|
|
19
|
-
export {
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
// Asset Loading
|
|
22
|
+
export { loadFiles } from './tools/dragdrop/DragDropLoader';
|
|
23
|
+
export { loadModel, loadTexture } from './tools/dragdrop/modelLoader';
|
|
24
|
+
// Asset Viewer
|
|
22
25
|
export { TextureListViewer, ModelListViewer, SoundListViewer, TexturePicker, ModelPicker, SingleTextureViewer, SingleModelViewer, SingleSoundViewer, SharedCanvas, } from './tools/assetviewer/page';
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { CanvasProps } from "@react-three/fiber";
|
|
2
2
|
import { WebGPURendererParameters } from "three/src/renderers/webgpu/WebGPURenderer.Nodes.js";
|
|
3
|
-
interface GameCanvasProps extends Omit<CanvasProps, 'children'> {
|
|
3
|
+
export interface GameCanvasProps extends Omit<CanvasProps, 'children'> {
|
|
4
4
|
loader?: boolean;
|
|
5
5
|
children: React.ReactNode;
|
|
6
6
|
glConfig?: WebGPURendererParameters;
|
|
7
7
|
canvasRef?: React.RefObject<HTMLCanvasElement | null>;
|
|
8
8
|
}
|
|
9
9
|
export default function GameCanvas({ loader, children, glConfig, canvasRef, onCreated, style, ...props }: GameCanvasProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
-
export {};
|
|
@@ -2,8 +2,8 @@ export interface EditorContextType {
|
|
|
2
2
|
editMode: boolean;
|
|
3
3
|
transformMode: "translate" | "rotate" | "scale";
|
|
4
4
|
setTransformMode: (mode: "translate" | "rotate" | "scale") => void;
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
scaleSnap: number;
|
|
6
|
+
setScaleSnap: (resolution: number) => void;
|
|
7
7
|
positionSnap: number;
|
|
8
8
|
setPositionSnap: (resolution: number) => void;
|
|
9
9
|
rotationSnap: number;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { Dispatch, SetStateAction } from 'react';
|
|
2
1
|
import { Prefab } from "./types";
|
|
3
|
-
export default function EditorTree({
|
|
4
|
-
prefabData?: Prefab;
|
|
5
|
-
setPrefabData?: Dispatch<SetStateAction<Prefab>>;
|
|
2
|
+
export default function EditorTree({ selectedId, setSelectedId, getPrefab, onReplacePrefab, onImportPrefab, onUndo, onRedo, canUndo, canRedo }: {
|
|
6
3
|
selectedId: string | null;
|
|
7
|
-
setSelectedId:
|
|
4
|
+
setSelectedId: (id: string | null) => void;
|
|
5
|
+
getPrefab: () => Prefab;
|
|
6
|
+
onReplacePrefab: (prefab: Prefab) => void;
|
|
7
|
+
onImportPrefab: (prefab: Prefab) => void;
|
|
8
8
|
onUndo?: () => void;
|
|
9
9
|
onRedo?: () => void;
|
|
10
10
|
canUndo?: boolean;
|
|
11
11
|
canRedo?: boolean;
|
|
12
|
-
}): import("react/jsx-runtime").JSX.Element
|
|
12
|
+
}): import("react/jsx-runtime").JSX.Element;
|