react-three-game 0.0.92 → 0.0.93
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 +68 -33
- package/dist/helpers/index.d.ts +0 -3
- package/dist/helpers/index.js +1 -8
- package/dist/index.d.ts +5 -8
- package/dist/index.js +3 -4
- package/dist/tools/prefabeditor/EditorTree.js +2 -2
- package/dist/tools/prefabeditor/GameEvents.d.ts +6 -12
- package/dist/tools/prefabeditor/GameEvents.js +0 -8
- package/dist/tools/prefabeditor/InstanceProvider.d.ts +6 -4
- package/dist/tools/prefabeditor/InstanceProvider.js +84 -199
- package/dist/tools/prefabeditor/PrefabEditor.d.ts +18 -6
- package/dist/tools/prefabeditor/PrefabEditor.js +55 -39
- package/dist/tools/prefabeditor/PrefabRoot.d.ts +15 -8
- package/dist/tools/prefabeditor/PrefabRoot.js +141 -117
- package/dist/tools/prefabeditor/assetRuntime.d.ts +13 -11
- package/dist/tools/prefabeditor/assetRuntime.js +15 -15
- package/dist/tools/prefabeditor/components/BufferGeometryComponent.js +1 -1
- package/dist/tools/prefabeditor/components/CameraComponent.js +2 -2
- package/dist/tools/prefabeditor/components/ComponentRegistry.d.ts +3 -3
- package/dist/tools/prefabeditor/components/DirectionalLightComponent.js +2 -2
- package/dist/tools/prefabeditor/components/ModelComponent.js +1 -1
- package/dist/tools/prefabeditor/components/PointLightComponent.js +2 -2
- package/dist/tools/prefabeditor/components/SoundComponent.js +2 -2
- package/dist/tools/prefabeditor/components/SpotLightComponent.js +2 -2
- package/dist/tools/prefabeditor/components/index.js +0 -2
- package/dist/tools/prefabeditor/types.d.ts +1 -0
- package/dist/tools/prefabeditor/usePointerEvents.d.ts +3 -3
- package/dist/tools/prefabeditor/usePointerEvents.js +5 -5
- package/package.json +1 -3
- package/dist/tools/prefabeditor/components/PhysicsComponent.d.ts +0 -26
- package/dist/tools/prefabeditor/components/PhysicsComponent.js +0 -302
- package/dist/tools/prefabeditor/scene.d.ts +0 -70
- package/dist/tools/prefabeditor/scene.js +0 -237
package/README.md
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
# react-three-game
|
|
2
2
|
|
|
3
|
-

|
|
4
4
|
|
|
5
|
-
JSON-first
|
|
5
|
+
JSON-first prefab mounting and authoring for React Three Fiber.
|
|
6
6
|
|
|
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/
|
|
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/drei](https://github.com/pmndrs/drei).
|
|
8
8
|
|
|
9
|
-
* **🧱 Prefabs** - Save
|
|
10
|
-
* **🎬
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* **🔧 Direct Runtime Access** - Get native `Object3D`, Rapier rigid body, and prefab store access without a parallel engine API.
|
|
9
|
+
* **🧱 Prefabs** - Save prefabs as serializable JSON and load them on their own or inside larger app worlds.
|
|
10
|
+
* **🎬 Prefab Editor** - Edit prefabs visually with hierarchy, inspector, transform gizmos, and play mode.
|
|
11
|
+
* **🧩 Components** - Build prefabs from reusable `GameObject` + component composition.
|
|
12
|
+
* **🔧 Direct Runtime Access** - Get native `Object3D`, runtime handles, and authored prefab mutation APIs without a parallel engine API.
|
|
14
13
|
* **⚡ R3F Native** - Use normal React Three Fiber components whenever runtime behavior is clearer in code.
|
|
15
14
|
|
|
16
15
|
## Documentation
|
|
@@ -21,7 +20,7 @@ Built on top of [three.js](https://github.com/mrdoob/three.js), [@react-three/fi
|
|
|
21
20
|
## Install
|
|
22
21
|
|
|
23
22
|
```bash
|
|
24
|
-
npm install react-three-game @react-three/drei @react-three/fiber
|
|
23
|
+
npm install react-three-game @react-three/drei @react-three/fiber three
|
|
25
24
|
```
|
|
26
25
|
|
|
27
26
|
## Usage
|
|
@@ -29,12 +28,11 @@ npm install react-three-game @react-three/drei @react-three/fiber @react-three/r
|
|
|
29
28
|
Here is a minimal example that renders a prefab inside a normal R3F app:
|
|
30
29
|
|
|
31
30
|
```tsx
|
|
32
|
-
import { Physics } from "@react-three/rapier";
|
|
33
31
|
import { GameCanvas, PrefabRoot, ground } from "react-three-game";
|
|
34
32
|
|
|
35
33
|
const prefab = {
|
|
36
34
|
id: "starter-scene",
|
|
37
|
-
name: "Starter
|
|
35
|
+
name: "Starter Prefab",
|
|
38
36
|
root: {
|
|
39
37
|
id: "root",
|
|
40
38
|
children: [
|
|
@@ -58,10 +56,6 @@ const prefab = {
|
|
|
58
56
|
type: "Material",
|
|
59
57
|
properties: { color: "#f66" },
|
|
60
58
|
},
|
|
61
|
-
physics: {
|
|
62
|
-
type: "Physics",
|
|
63
|
-
properties: { type: "dynamic" },
|
|
64
|
-
},
|
|
65
59
|
},
|
|
66
60
|
},
|
|
67
61
|
],
|
|
@@ -71,16 +65,14 @@ const prefab = {
|
|
|
71
65
|
export default function App() {
|
|
72
66
|
return (
|
|
73
67
|
<GameCanvas>
|
|
74
|
-
<
|
|
75
|
-
|
|
76
|
-
<PrefabRoot data={prefab} />
|
|
77
|
-
</Physics>
|
|
68
|
+
<ambientLight intensity={0.8} />
|
|
69
|
+
<PrefabRoot data={prefab} />
|
|
78
70
|
</GameCanvas>
|
|
79
71
|
);
|
|
80
72
|
}
|
|
81
73
|
```
|
|
82
74
|
|
|
83
|
-
This example renders a
|
|
75
|
+
This example renders a simple authored prefab with a ground plane and mesh content.
|
|
84
76
|
|
|
85
77
|
## Prefab Editor
|
|
86
78
|
|
|
@@ -98,22 +90,21 @@ Open the hosted editor here:
|
|
|
98
90
|
|
|
99
91
|
* https://prnth.com/react-three-game/editor
|
|
100
92
|
|
|
101
|
-
## Prefabs And Mounted
|
|
93
|
+
## Prefabs And Mounted Objects
|
|
102
94
|
|
|
103
95
|
`Prefab` is the serializable pure data format.
|
|
104
96
|
|
|
105
|
-
That means
|
|
97
|
+
That means authored content stays as a prefab, and the same prefab can be:
|
|
106
98
|
|
|
107
99
|
* edited directly in `PrefabEditor`
|
|
108
100
|
* rendered directly with `PrefabRoot`
|
|
109
|
-
* loaded inside another scene as reusable content
|
|
101
|
+
* loaded inside another prefab or app scene as reusable content
|
|
110
102
|
|
|
111
103
|
`PrefabRoot` keeps the rendering model narrow and compositional:
|
|
112
104
|
|
|
113
105
|
* `Transform` is the renderer-owned outer transform
|
|
114
106
|
* `Geometry` or `BufferGeometry` + `Material` become the primary mesh content
|
|
115
107
|
* non-instanced `Model` becomes the node's primary content
|
|
116
|
-
* `Physics` is a renderer-owned outer wrapper
|
|
117
108
|
* every other component `View` wraps the current subtree
|
|
118
109
|
|
|
119
110
|
Custom component `View`s use normal React Three Fiber composition with `children`.
|
|
@@ -161,7 +152,7 @@ interface GameObject {
|
|
|
161
152
|
|
|
162
153
|
## Runtime Mutation
|
|
163
154
|
|
|
164
|
-
Use
|
|
155
|
+
Use editor or root refs for scene-native object access, and use the editor mutation methods for authored data changes.
|
|
165
156
|
|
|
166
157
|
```tsx
|
|
167
158
|
import { useEffect, useRef } from "react";
|
|
@@ -171,7 +162,7 @@ function RaiseBall() {
|
|
|
171
162
|
const editorRef = useRef<PrefabEditorRef>(null);
|
|
172
163
|
|
|
173
164
|
useEffect(() => {
|
|
174
|
-
editorRef.current?.
|
|
165
|
+
editorRef.current?.updateNode("ball", (node) => ({
|
|
175
166
|
...node,
|
|
176
167
|
components: {
|
|
177
168
|
...node.components,
|
|
@@ -193,10 +184,55 @@ function RaiseBall() {
|
|
|
193
184
|
For live Three.js access, use mounted objects directly:
|
|
194
185
|
|
|
195
186
|
```tsx
|
|
196
|
-
const ball = editorRef.current?.
|
|
187
|
+
const ball = editorRef.current?.getNodeObject("ball");
|
|
197
188
|
ball?.rotateY(0.5);
|
|
198
189
|
```
|
|
199
190
|
|
|
191
|
+
For runtime integrations that need edit-time re-sync, subscribe to authored scene changes:
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
const stop = editorRef.current?.onSceneChange((revision) => {
|
|
195
|
+
console.log("scene changed", revision);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
stop?.();
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
For runtime-owned imperative state, use node-local handles instead of reaching for ad hoc globals:
|
|
202
|
+
|
|
203
|
+
```tsx
|
|
204
|
+
import { useEffect } from "react";
|
|
205
|
+
import { useAssetRuntime, useCurrentNode, useCurrentNodeHandle } from "react-three-game";
|
|
206
|
+
|
|
207
|
+
function SpinnerView({ children }: { children?: React.ReactNode }) {
|
|
208
|
+
const { nodeId } = useCurrentNode();
|
|
209
|
+
const { registerNodeHandle } = useAssetRuntime();
|
|
210
|
+
|
|
211
|
+
useEffect(() => {
|
|
212
|
+
const handle = {
|
|
213
|
+
setSpeed(next: number) {
|
|
214
|
+
console.log("speed", next);
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
registerNodeHandle(nodeId, "spinner", handle);
|
|
219
|
+
return () => registerNodeHandle(nodeId, "spinner", null);
|
|
220
|
+
}, [nodeId, registerNodeHandle]);
|
|
221
|
+
|
|
222
|
+
return <>{children}</>;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function SpinnerStatus() {
|
|
226
|
+
const spinnerRef = useCurrentNodeHandle<{ setSpeed: (next: number) => void }>("spinner");
|
|
227
|
+
|
|
228
|
+
useEffect(() => {
|
|
229
|
+
spinnerRef.current?.setSpeed(2);
|
|
230
|
+
}, [spinnerRef]);
|
|
231
|
+
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
200
236
|
Mounted node metadata is mirrored onto the canonical Three.js wrapper object:
|
|
201
237
|
|
|
202
238
|
* `GameObject.id` -> `object.userData.prefabNodeId`
|
|
@@ -213,7 +249,7 @@ const playerById = editorRef.current?.root?.getObjectByProperty("userData.prefab
|
|
|
213
249
|
Treat names as a convenience surface, not the primary lookup key:
|
|
214
250
|
|
|
215
251
|
* names are not guaranteed unique
|
|
216
|
-
* `
|
|
252
|
+
* `getNodeObject(id)` is the clearest stable authored-node lookup
|
|
217
253
|
* traversal metadata is applied to the prefab node transform object, not necessarily the inner mesh or model child
|
|
218
254
|
|
|
219
255
|
You can author extra `userData` from the editor with a `Data` component:
|
|
@@ -231,7 +267,7 @@ You can author extra `userData` from the editor with a `Data` component:
|
|
|
231
267
|
For batched authored updates, write through the store once:
|
|
232
268
|
|
|
233
269
|
```tsx
|
|
234
|
-
editorRef.current?.
|
|
270
|
+
editorRef.current?.updateNodes([
|
|
235
271
|
{
|
|
236
272
|
id: "orb1",
|
|
237
273
|
update: (node) => ({
|
|
@@ -280,11 +316,10 @@ Custom component `View`s should use normal React and R3F behavior, such as `useF
|
|
|
280
316
|
* `Prefab`
|
|
281
317
|
* `GameObject`
|
|
282
318
|
* `registerComponent`
|
|
283
|
-
* `
|
|
284
|
-
* `
|
|
285
|
-
* `useAssetRuntime()` / `useEntityRuntime()`
|
|
286
|
-
* `useEntityObjectRef()` / `useEntityRigidBodyRef()`
|
|
319
|
+
* `useAssetRuntime()` / `useCurrentNode()`
|
|
320
|
+
* `useCurrentNodeObject()` / `useCurrentNodeHandle()`
|
|
287
321
|
* `ground(...)`
|
|
322
|
+
* `gameEvents` / `useGameEvent()` / `useClickEvent()`
|
|
288
323
|
* `loadJson()` / `saveJson()`
|
|
289
324
|
* `loadModel()` / `loadTexture()`
|
|
290
325
|
* `loadSound()` / `loadFiles()`
|
package/dist/helpers/index.d.ts
CHANGED
|
@@ -16,8 +16,6 @@ export interface GroundOptions {
|
|
|
16
16
|
repeat?: boolean;
|
|
17
17
|
/** Texture repeat counts when repeat=true. Defaults to [25,25]. */
|
|
18
18
|
repeatCount?: [number, number];
|
|
19
|
-
/** Physics body type. Defaults to "fixed". */
|
|
20
|
-
physicsType?: "fixed" | "dynamic" | "kinematic";
|
|
21
19
|
/** Set true to disable the node. */
|
|
22
20
|
disabled?: boolean;
|
|
23
21
|
}
|
|
@@ -28,6 +26,5 @@ export interface GroundOptions {
|
|
|
28
26
|
* - Transform (rotated to lie flat)
|
|
29
27
|
* - Geometry (plane)
|
|
30
28
|
* - Material (optional texture + repeat)
|
|
31
|
-
* - Physics (fixed by default)
|
|
32
29
|
*/
|
|
33
30
|
export declare function ground(options?: GroundOptions): GameObject;
|
package/dist/helpers/index.js
CHANGED
|
@@ -5,10 +5,9 @@
|
|
|
5
5
|
* - Transform (rotated to lie flat)
|
|
6
6
|
* - Geometry (plane)
|
|
7
7
|
* - Material (optional texture + repeat)
|
|
8
|
-
* - Physics (fixed by default)
|
|
9
8
|
*/
|
|
10
9
|
export function ground(options = {}) {
|
|
11
|
-
const { id = "ground", size = 50, position = [0, 0, 0], rotation = [-Math.PI / 2, 0, 0], scale = [1, 1, 1], color = "#eeeeee", texture, repeat = texture ? true : false, repeatCount = [25, 25],
|
|
10
|
+
const { id = "ground", size = 50, position = [0, 0, 0], rotation = [-Math.PI / 2, 0, 0], scale = [1, 1, 1], color = "#eeeeee", texture, repeat = texture ? true : false, repeatCount = [25, 25], disabled = false, } = options;
|
|
12
11
|
return {
|
|
13
12
|
id,
|
|
14
13
|
disabled,
|
|
@@ -32,12 +31,6 @@ export function ground(options = {}) {
|
|
|
32
31
|
type: "Material",
|
|
33
32
|
properties: Object.assign(Object.assign({ color }, (texture ? { texture } : {})), (repeat ? { repeat: true, repeatCount } : {})),
|
|
34
33
|
},
|
|
35
|
-
physics: {
|
|
36
|
-
type: "Physics",
|
|
37
|
-
properties: {
|
|
38
|
-
type: physicsType,
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
34
|
},
|
|
42
35
|
};
|
|
43
36
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,21 +8,18 @@ export { PrefabEditorMode } from './tools/prefabeditor/PrefabEditor';
|
|
|
8
8
|
export { default as PrefabRoot } from './tools/prefabeditor/PrefabRoot';
|
|
9
9
|
export { useEditorContext } from './tools/prefabeditor/PrefabEditor';
|
|
10
10
|
export type { EditorContextType } from './tools/prefabeditor/PrefabEditor';
|
|
11
|
-
export { createPrefabStore, prefabStoreToPrefab, usePrefabStoreApi } from './tools/prefabeditor/prefabStore';
|
|
12
|
-
export type { PrefabStoreApi, PrefabStoreState } from './tools/prefabeditor/prefabStore';
|
|
13
11
|
export { denormalizePrefab } from './tools/prefabeditor/prefab';
|
|
14
|
-
export { gameEvents,
|
|
15
|
-
export type { ClickEventPayload, GameEventHandler, GameEventMap
|
|
12
|
+
export { gameEvents, useClickEvent, useGameEvent } from './tools/prefabeditor/GameEvents';
|
|
13
|
+
export type { ClickEventPayload, ContactEventPayload, GameEventHandler, GameEventMap } from './tools/prefabeditor/GameEvents';
|
|
16
14
|
export { registerComponent } from './tools/prefabeditor/components/ComponentRegistry';
|
|
17
15
|
export { FieldRenderer, FieldGroup, ListEditor, Label, Vector3Input, Vector3Field, NumberField, ColorInput, ColorField, StringInput, StringField, BooleanInput, BooleanField, SelectInput, SelectField, } from './tools/prefabeditor/components/Input';
|
|
18
16
|
export { loadJson, saveJson, exportGLB, exportGLBData, regenerateIds, computeParentWorldMatrix, } from './tools/prefabeditor/utils';
|
|
19
17
|
export type { ExportGLBOptions } from './tools/prefabeditor/utils';
|
|
20
18
|
export { createModelNode, createImageNode, } from './tools/prefabeditor/prefab';
|
|
21
|
-
export type { PrefabEditorProps, PrefabEditorRef, } from './tools/prefabeditor/PrefabEditor';
|
|
22
|
-
export type { Entity, EntityComponent, EntityData, EntityUpdate, PropertyPath, Scene, SceneUpdates, SpawnOptions, } from './tools/prefabeditor/scene';
|
|
19
|
+
export type { PrefabEditorProps, PrefabNode, PrefabEditorRef, SpawnOptions, } from './tools/prefabeditor/PrefabEditor';
|
|
23
20
|
export type { PrefabRootProps } from './tools/prefabeditor/PrefabRoot';
|
|
24
|
-
export type { AssetRuntime,
|
|
25
|
-
export { useAssetRuntime,
|
|
21
|
+
export type { AssetRuntime, CurrentNodeRuntime, LiveHandleRef, LiveObjectRef, CurrentNodeHandleRef, CurrentNodeObjectRef } from './tools/prefabeditor/assetRuntime';
|
|
22
|
+
export { useAssetRuntime, useCurrentNode, useCurrentNodeHandle, useCurrentNodeObject } from './tools/prefabeditor/assetRuntime';
|
|
26
23
|
export type { Component, ComponentViewProps } from './tools/prefabeditor/components/ComponentRegistry';
|
|
27
24
|
export type { FieldDefinition, FieldType } from './tools/prefabeditor/components/Input';
|
|
28
25
|
export { MaterialOverridesProvider, useMaterialOverrides } from './tools/prefabeditor/components/MaterialComponent';
|
package/dist/index.js
CHANGED
|
@@ -8,10 +8,9 @@ export { default as PrefabEditor } from './tools/prefabeditor/PrefabEditor';
|
|
|
8
8
|
export { PrefabEditorMode } from './tools/prefabeditor/PrefabEditor';
|
|
9
9
|
export { default as PrefabRoot } from './tools/prefabeditor/PrefabRoot';
|
|
10
10
|
export { useEditorContext } from './tools/prefabeditor/PrefabEditor';
|
|
11
|
-
// Prefab Editor -
|
|
12
|
-
export { createPrefabStore, prefabStoreToPrefab, usePrefabStoreApi } from './tools/prefabeditor/prefabStore';
|
|
11
|
+
// Prefab Editor - Data API
|
|
13
12
|
export { denormalizePrefab } from './tools/prefabeditor/prefab';
|
|
14
|
-
export { gameEvents,
|
|
13
|
+
export { gameEvents, useClickEvent, useGameEvent } from './tools/prefabeditor/GameEvents';
|
|
15
14
|
// Prefab Editor - Component Registry
|
|
16
15
|
export { registerComponent } from './tools/prefabeditor/components/ComponentRegistry';
|
|
17
16
|
// Prefab Editor - Input Components
|
|
@@ -19,7 +18,7 @@ export { FieldRenderer, FieldGroup, ListEditor, Label, Vector3Input, Vector3Fiel
|
|
|
19
18
|
// Prefab Editor - Utils
|
|
20
19
|
export { loadJson, saveJson, exportGLB, exportGLBData, regenerateIds, computeParentWorldMatrix, } from './tools/prefabeditor/utils';
|
|
21
20
|
export { createModelNode, createImageNode, } from './tools/prefabeditor/prefab';
|
|
22
|
-
export { useAssetRuntime,
|
|
21
|
+
export { useAssetRuntime, useCurrentNode, useCurrentNodeHandle, useCurrentNodeObject } from './tools/prefabeditor/assetRuntime';
|
|
23
22
|
export { MaterialOverridesProvider, useMaterialOverrides } from './tools/prefabeditor/components/MaterialComponent';
|
|
24
23
|
export { findComponent, findComponentEntry, hasComponent } from './tools/prefabeditor/types';
|
|
25
24
|
export { float, positionLocal, sin, time, uniform, vec3, } from 'three/tsl';
|
|
@@ -104,7 +104,7 @@ export default function EditorTree({ selectedId, setSelectedId, getPrefab, onRep
|
|
|
104
104
|
setDropTarget(null);
|
|
105
105
|
};
|
|
106
106
|
const visibleIds = usePrefabStore(useCallback(state => searchQuery ? buildVisibleIds(state, rootId, searchQuery) : null, [rootId, searchQuery]));
|
|
107
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { style: Object.assign(Object.assign({}, tree.panel), { width: collapsed ? 'auto' : 224 }), children: [_jsxs("div", { style: base.header, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 6, cursor: 'pointer' }, onClick: () => setCollapsed(!collapsed), children: [_jsx("span", { children: collapsed ? '▶' : '▼' }), _jsx("span", { children: "
|
|
107
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { style: Object.assign(Object.assign({}, tree.panel), { width: collapsed ? 'auto' : 224 }), children: [_jsxs("div", { style: base.header, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 6, cursor: 'pointer' }, onClick: () => setCollapsed(!collapsed), children: [_jsx("span", { children: collapsed ? '▶' : '▼' }), _jsx("span", { children: "Prefab" })] }), !collapsed && (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 4 }, children: [_jsx("button", { style: Object.assign(Object.assign({}, base.btn), { padding: '2px 6px', fontSize: 10, opacity: canUndo ? 1 : 0.4 }), onClick: (e) => { e.stopPropagation(); onUndo === null || onUndo === void 0 ? void 0 : onUndo(); }, disabled: !canUndo, title: "Undo", children: "\u21B6" }), _jsx("button", { style: Object.assign(Object.assign({}, base.btn), { padding: '2px 6px', fontSize: 10, opacity: canRedo ? 1 : 0.4 }), onClick: (e) => { e.stopPropagation(); onRedo === null || onRedo === void 0 ? void 0 : onRedo(); }, disabled: !canRedo, title: "Redo", children: "\u21B7" }), _jsx(Dropdown, { placement: "bottom-end", trigger: ({ ref, toggle }) => (_jsx("button", { ref: ref, title: "Menu", style: Object.assign(Object.assign({}, base.btn), { padding: '2px 6px', fontSize: 10 }), onClick: (e) => {
|
|
108
108
|
e.stopPropagation();
|
|
109
109
|
toggle();
|
|
110
110
|
}, children: "\u22EE" })), children: (close) => (_jsx(FileMenu, { getPrefab: getPrefab, onReplacePrefab: onReplacePrefab, onImportPrefab: onImportPrefab, onClose: close })) })] }))] }), !collapsed && (_jsxs(_Fragment, { children: [_jsx("div", { style: { padding: '4px 4px', borderBottom: `1px solid ${colors.borderLight}` }, children: _jsx("input", { type: "text", placeholder: "Search nodes...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), onClick: (e) => e.stopPropagation(), style: Object.assign(Object.assign({}, base.input), { padding: '4px 8px' }) }) }), _jsx("div", { style: tree.scroll, children: _jsx(TreeNode, { nodeId: rootId, depth: 0, rootId: rootId, visibleIds: visibleIds, collapsedIds: collapsedIds, dropTarget: dropTarget, selectedNodeId: selectedId, onToggleCollapse: toggleCollapse, onOpenContextMenu: openContextMenu, onDragStart: handleDragStart, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, onDragEnd: () => { setDraggedId(null); setDropTarget(null); }, renderTreeNodeMenu: renderTreeNodeMenu, onToggleDisabled: handleToggleDisabled, setSelectedId: setSelectedId }) })] }))] }), _jsx(TreeContextMenu, { contextMenu: contextMenu, onClose: closeContextMenu, children: (nodeId, close) => renderTreeNodeMenu(nodeId, nodeId === rootId, close) })] }));
|
|
@@ -138,7 +138,7 @@ const TreeNode = memo(function TreeNode({ nodeId, depth, rootId, visibleIds, col
|
|
|
138
138
|
}, children: "\u22EF" })), children: (close) => renderTreeNodeMenu(nodeId, false, close) }), _jsx("button", { style: Object.assign(Object.assign({}, tree.iconButton), { opacity: node.disabled ? 0.5 : 0.7 }), onClick: (e) => {
|
|
139
139
|
e.stopPropagation();
|
|
140
140
|
onToggleDisabled(nodeId);
|
|
141
|
-
}, title: node.disabled ? 'Enable' : 'Disable', children: node.disabled ? '◎' : '◉' })] })), isRoot && (_jsx(Dropdown, { placement: "bottom-end", trigger: ({ ref, toggle }) => (_jsx("button", { ref: ref, title: "
|
|
141
|
+
}, title: node.disabled ? 'Enable' : 'Disable', children: node.disabled ? '◎' : '◉' })] })), isRoot && (_jsx(Dropdown, { placement: "bottom-end", trigger: ({ ref, toggle }) => (_jsx("button", { ref: ref, title: "Prefab Actions", style: tree.iconButton, onClick: (e) => {
|
|
142
142
|
e.stopPropagation();
|
|
143
143
|
toggle();
|
|
144
144
|
}, children: "\u22EF" })), children: (close) => renderTreeNodeMenu(nodeId, true, close) }))] }), !isCollapsed && childIds.map(childId => (_jsx(TreeNode, { nodeId: childId, depth: depth + 1, rootId: rootId, visibleIds: visibleIds, collapsedIds: collapsedIds, dropTarget: dropTarget, selectedNodeId: selectedNodeId, onToggleCollapse: onToggleCollapse, onOpenContextMenu: onOpenContextMenu, onDragStart: onDragStart, onDragOver: onDragOver, onDragLeave: onDragLeave, onDrop: onDrop, onDragEnd: onDragEnd, renderTreeNodeMenu: renderTreeNodeMenu, onToggleDisabled: onToggleDisabled, setSelectedId: setSelectedId }, childId)))] }));
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
export type GameEventHandler<TPayload = unknown> = (payload: TPayload) => void;
|
|
2
|
-
export type
|
|
2
|
+
export type ContactEventPayload = {
|
|
3
3
|
sourceEntityId?: string;
|
|
4
4
|
sourceNodeId?: string;
|
|
5
5
|
sourceObject?: unknown;
|
|
6
|
-
sourceRigidBody?: unknown;
|
|
7
6
|
targetEntityId?: string | null;
|
|
8
7
|
targetNodeId?: string | null;
|
|
9
8
|
targetObject?: unknown;
|
|
10
|
-
|
|
11
|
-
rapierEvent?: unknown;
|
|
9
|
+
event?: unknown;
|
|
12
10
|
};
|
|
13
11
|
export type ClickEventPayload = {
|
|
14
12
|
sourceEntityId?: string;
|
|
@@ -26,10 +24,10 @@ export type ClickEventPayload = {
|
|
|
26
24
|
r3fEvent?: unknown;
|
|
27
25
|
};
|
|
28
26
|
export interface GameEventMap {
|
|
29
|
-
'sensor:enter':
|
|
30
|
-
'sensor:exit':
|
|
31
|
-
'collision:enter':
|
|
32
|
-
'collision:exit':
|
|
27
|
+
'sensor:enter': ContactEventPayload;
|
|
28
|
+
'sensor:exit': ContactEventPayload;
|
|
29
|
+
'collision:enter': ContactEventPayload;
|
|
30
|
+
'collision:exit': ContactEventPayload;
|
|
33
31
|
click: ClickEventPayload;
|
|
34
32
|
[eventType: string]: unknown;
|
|
35
33
|
}
|
|
@@ -40,8 +38,4 @@ export declare const gameEvents: {
|
|
|
40
38
|
hasListeners(type: string): boolean;
|
|
41
39
|
};
|
|
42
40
|
export declare function useGameEvent<TType extends string>(type: TType, handler: GameEventHandler<TType extends keyof GameEventMap ? GameEventMap[TType] : unknown>, deps?: React.DependencyList): void;
|
|
43
|
-
export declare function usePhysicsEvent<TType extends string>(type: TType, handler: GameEventHandler<TType extends keyof GameEventMap ? GameEventMap[TType] : unknown>, deps?: React.DependencyList): void;
|
|
44
41
|
export declare function useClickEvent<TType extends string>(type: TType, handler: GameEventHandler<TType extends keyof GameEventMap ? GameEventMap[TType] : unknown>, deps?: React.DependencyList): void;
|
|
45
|
-
export declare function getEntityIdFromRigidBody(rigidBody: {
|
|
46
|
-
userData?: unknown;
|
|
47
|
-
} | null | undefined): string | null;
|
|
@@ -53,14 +53,6 @@ export function useGameEvent(type, handler, deps = []) {
|
|
|
53
53
|
return gameEvents.on(type, stableHandler);
|
|
54
54
|
}, [type, stableHandler]);
|
|
55
55
|
}
|
|
56
|
-
export function usePhysicsEvent(type, handler, deps = []) {
|
|
57
|
-
useGameEvent(type, handler, deps);
|
|
58
|
-
}
|
|
59
56
|
export function useClickEvent(type, handler, deps = []) {
|
|
60
57
|
useGameEvent(type, handler, deps);
|
|
61
58
|
}
|
|
62
|
-
export function getEntityIdFromRigidBody(rigidBody) {
|
|
63
|
-
var _a;
|
|
64
|
-
const entityId = (_a = rigidBody === null || rigidBody === void 0 ? void 0 : rigidBody.userData) === null || _a === void 0 ? void 0 : _a.entityId;
|
|
65
|
-
return typeof entityId === 'string' ? entityId : null;
|
|
66
|
-
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { ThreeEvent } from '@react-three/fiber';
|
|
2
3
|
import { Object3D, Group } from "three";
|
|
3
|
-
import { PhysicsProps } from "./components/PhysicsComponent";
|
|
4
4
|
export type RepeatAxisConfig = {
|
|
5
5
|
axis: 'x' | 'y' | 'z';
|
|
6
6
|
count: number;
|
|
@@ -13,18 +13,19 @@ export type InstanceData = {
|
|
|
13
13
|
id: string;
|
|
14
14
|
sourceId: string;
|
|
15
15
|
locked?: boolean;
|
|
16
|
+
visible?: boolean;
|
|
16
17
|
position: [number, number, number];
|
|
17
18
|
rotation: [number, number, number];
|
|
18
19
|
scale: [number, number, number];
|
|
19
20
|
meshPath: string;
|
|
20
|
-
physics?: PhysicsProps | undefined;
|
|
21
21
|
};
|
|
22
|
-
export declare function GameInstanceProvider({ children, models, onSelect, registerRef, selectedId, editMode }: {
|
|
22
|
+
export declare function GameInstanceProvider({ children, models, onSelect, onClick, registerRef, selectedId, editMode }: {
|
|
23
23
|
children: React.ReactNode;
|
|
24
24
|
models: {
|
|
25
25
|
[filename: string]: Object3D;
|
|
26
26
|
};
|
|
27
27
|
onSelect?: (id: string | null) => void;
|
|
28
|
+
onClick?: (event: ThreeEvent<PointerEvent>, nodeId: string, object: Object3D | null) => void;
|
|
28
29
|
registerRef?: (id: string, obj: Object3D | null) => void;
|
|
29
30
|
selectedId?: string | null;
|
|
30
31
|
editMode?: boolean;
|
|
@@ -38,5 +39,6 @@ export declare const GameInstance: React.ForwardRefExoticComponent<{
|
|
|
38
39
|
position: [number, number, number];
|
|
39
40
|
rotation: [number, number, number];
|
|
40
41
|
scale: [number, number, number];
|
|
41
|
-
|
|
42
|
+
visible?: boolean;
|
|
43
|
+
onClick?: (event: ThreeEvent<PointerEvent>, nodeId: string, object: Object3D | null) => void;
|
|
42
44
|
} & React.RefAttributes<Group<import("three").Object3DEventMap>>>;
|