react-three-game 0.0.108 → 0.0.110
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 +9 -16
- package/dist/editor.d.ts +22 -0
- package/dist/editor.js +15 -0
- package/dist/plugins/crashcat/CrashcatPhysicsComponent.js +47 -9
- package/dist/plugins/crashcat/CrashcatRagdoll.d.ts +1 -1
- package/dist/plugins/crashcat/CrashcatRuntime.d.ts +1 -1
- package/dist/plugins/crashcat/CrashcatRuntime.js +1 -1
- package/dist/shared/ContactShadow.d.ts +1 -1
- package/dist/shared/GameCanvas.d.ts +1 -1
- package/dist/tools/assetviewer/page.d.ts +10 -10
- package/dist/tools/dragdrop/DragDropLoader.d.ts +2 -2
- package/dist/tools/prefabeditor/Dropdown.d.ts +1 -1
- package/dist/tools/prefabeditor/EditorContext.d.ts +36 -0
- package/dist/tools/prefabeditor/EditorContext.js +17 -0
- package/dist/tools/prefabeditor/EditorTree.d.ts +1 -1
- package/dist/tools/prefabeditor/EditorTree.js +1 -1
- package/dist/tools/prefabeditor/EditorTreeMenus.d.ts +2 -2
- package/dist/tools/prefabeditor/EditorTreeMenus.js +1 -1
- package/dist/tools/prefabeditor/EditorUI.d.ts +1 -1
- package/dist/tools/prefabeditor/EditorUI.js +1 -1
- package/dist/tools/prefabeditor/InstanceProvider.d.ts +1 -1
- package/dist/tools/prefabeditor/PrefabEditor.d.ts +4 -37
- package/dist/tools/prefabeditor/PrefabEditor.js +72 -71
- package/dist/tools/prefabeditor/PrefabRoot.d.ts +5 -29
- package/dist/tools/prefabeditor/PrefabRoot.js +72 -188
- package/dist/tools/prefabeditor/SceneContext.d.ts +28 -0
- package/dist/tools/prefabeditor/SceneContext.js +14 -0
- package/dist/tools/prefabeditor/SceneProvider.d.ts +14 -0
- package/dist/tools/prefabeditor/SceneProvider.js +68 -0
- package/dist/tools/prefabeditor/assetRuntime.d.ts +29 -2
- package/dist/tools/prefabeditor/assetRuntime.js +115 -1
- package/dist/tools/prefabeditor/components/ComponentRegistry.d.ts +1 -1
- package/dist/tools/prefabeditor/components/EnvironmentComponent.js +3 -3
- package/dist/tools/prefabeditor/components/Input.d.ts +19 -19
- package/dist/tools/prefabeditor/components/MaterialComponent.d.ts +1 -1
- package/dist/tools/prefabeditor/components/MaterialComponent.js +13 -14
- package/dist/tools/prefabeditor/components/ModelComponent.js +3 -4
- package/dist/tools/prefabeditor/components/PrefabRefComponent.js +43 -19
- package/dist/tools/prefabeditor/components/SoundComponent.js +6 -2
- package/dist/tools/prefabeditor/components/SpotLightComponent.js +2 -5
- package/dist/tools/prefabeditor/components/TransformComponent.js +1 -1
- package/dist/tools/prefabeditor/components/index.d.ts +1 -0
- package/dist/tools/prefabeditor/components/index.js +8 -0
- package/dist/tools/prefabeditor/components/lightUtils.d.ts +2 -2
- package/dist/tools/prefabeditor/prefabStore.d.ts +2 -1
- package/dist/tools/prefabeditor/prefabStore.js +16 -1
- package/dist/tools/prefabeditor/runtimeUtils.d.ts +10 -0
- package/dist/tools/prefabeditor/runtimeUtils.js +30 -0
- package/dist/tools/prefabeditor/utils.d.ts +1 -9
- package/dist/tools/prefabeditor/utils.js +3 -28
- package/dist/viewer.d.ts +21 -0
- package/dist/viewer.js +12 -0
- package/package.json +18 -16
- package/dist/index.d.ts +0 -40
- package/dist/index.js +0 -32
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ npm install react-three-game @react-three/drei @react-three/fiber three
|
|
|
29
29
|
Here is a minimal example that renders a prefab inside a normal R3F app:
|
|
30
30
|
|
|
31
31
|
```tsx
|
|
32
|
-
import { GameCanvas, PrefabRoot, ground } from "react-three-game";
|
|
32
|
+
import { GameCanvas, PrefabRoot, ground } from "react-three-game/viewer";
|
|
33
33
|
|
|
34
34
|
const prefab = {
|
|
35
35
|
id: "starter-scene",
|
|
@@ -80,7 +80,7 @@ This example renders a simple authored prefab with a ground plane and mesh conte
|
|
|
80
80
|
In addition to the runtime renderer, there is a visual editor for authoring prefabs.
|
|
81
81
|
|
|
82
82
|
```tsx
|
|
83
|
-
import { PrefabEditor } from "react-three-game";
|
|
83
|
+
import { PrefabEditor } from "react-three-game/editor";
|
|
84
84
|
|
|
85
85
|
export default function App() {
|
|
86
86
|
return <PrefabEditor initialPrefab={prefab} onChange={console.log} />;
|
|
@@ -153,6 +153,7 @@ interface GameObject {
|
|
|
153
153
|
name?: string;
|
|
154
154
|
disabled?: boolean;
|
|
155
155
|
locked?: boolean;
|
|
156
|
+
hidden?: boolean;
|
|
156
157
|
components?: Record<string, { type: string; properties: any }>;
|
|
157
158
|
children?: GameObject[];
|
|
158
159
|
}
|
|
@@ -164,7 +165,7 @@ Use the editor or root ref for scene-native object access, and the `Scene` mutat
|
|
|
164
165
|
|
|
165
166
|
```tsx
|
|
166
167
|
import { useEffect, useRef } from "react";
|
|
167
|
-
import { PrefabEditor, type PrefabEditorRef } from "react-three-game";
|
|
168
|
+
import { PrefabEditor, type PrefabEditorRef } from "react-three-game/editor";
|
|
168
169
|
|
|
169
170
|
function RaiseBall() {
|
|
170
171
|
const editorRef = useRef<PrefabEditorRef>(null);
|
|
@@ -199,7 +200,7 @@ ball?.rotateY(0.5);
|
|
|
199
200
|
For runtime integrations that need to react to authored scene changes, subscribe through the prefab store:
|
|
200
201
|
|
|
201
202
|
```tsx
|
|
202
|
-
import { usePrefabStoreApi } from "react-three-game";
|
|
203
|
+
import { usePrefabStoreApi } from "react-three-game/editor";
|
|
203
204
|
|
|
204
205
|
const store = usePrefabStoreApi();
|
|
205
206
|
const stop = store.subscribe(
|
|
@@ -214,7 +215,7 @@ For runtime-owned imperative state, register node-local handles instead of reach
|
|
|
214
215
|
|
|
215
216
|
```tsx
|
|
216
217
|
import { useEffect } from "react";
|
|
217
|
-
import { useAssetRuntime, useNode, useNodeHandle } from "react-three-game";
|
|
218
|
+
import { useAssetRuntime, useNode, useNodeHandle } from "react-three-game/viewer";
|
|
218
219
|
|
|
219
220
|
function SpinnerView({ children }: { children?: React.ReactNode }) {
|
|
220
221
|
const { nodeId } = useNode();
|
|
@@ -280,17 +281,9 @@ Custom component `View`s use normal React and R3F behavior — `useFrame`, refs,
|
|
|
280
281
|
|
|
281
282
|
## Useful Exports
|
|
282
283
|
|
|
283
|
-
* `GameCanvas`, `PrefabRoot`, `
|
|
284
|
-
* `
|
|
285
|
-
* `
|
|
286
|
-
* `useScene`, `useEditorRef`, `useEditorContext`
|
|
287
|
-
* `useNode`, `useNodeObject`, `useNodeHandle`, `useAssetRuntime`
|
|
288
|
-
* `usePrefabStore`, `usePrefabStoreApi`
|
|
289
|
-
* `gameEvents`, `useGameEvent`, `useClickEvent`
|
|
290
|
-
* `loadJson`, `saveJson`, `loadFiles`, `loadModel`, `loadTexture`, `loadSound`
|
|
291
|
-
* `exportGLB`, `exportGLBData`, `regenerateIds`, `computeParentWorldMatrix`
|
|
292
|
-
* `ground`, `soundManager`
|
|
293
|
-
* `FieldRenderer`, `Vector3Field`, `NumberField`, `StringField`, `BooleanField`, `SelectField`, `ColorField`
|
|
284
|
+
* `react-three-game/viewer`: `GameCanvas`, `PrefabRoot`, `PrefabEditorMode`, `registerComponent`, scene hooks, event hooks, asset/runtime hooks, prefab types, loaders, `ground`, and `soundManager`
|
|
285
|
+
* `react-three-game/editor`: everything from `/viewer`, plus `PrefabEditor`, editor refs/context, prefab store hooks, inspector field components, JSON import/export helpers, GLB export helpers, material overrides, model decomposition, asset viewer components, and `three/tsl` helpers
|
|
286
|
+
* `react-three-game/plugins/crashcat`: `CrashcatRuntime`, `CrashcatPhysicsComponent`, `CrashcatRagdollComponent`, ragdoll helpers, static body helpers, and `useCrashcat`
|
|
294
287
|
|
|
295
288
|
## Development
|
|
296
289
|
|
package/dist/editor.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { registerBuiltinComponents } from "./tools/prefabeditor/components";
|
|
2
|
+
import "./viewer";
|
|
3
|
+
export { registerBuiltinComponents };
|
|
4
|
+
export * from "./viewer";
|
|
5
|
+
export { default as PrefabEditor } from "./tools/prefabeditor/PrefabEditor";
|
|
6
|
+
export type { PrefabEditorProps, PrefabEditorRef } from "./tools/prefabeditor/PrefabEditor";
|
|
7
|
+
export { useEditorContext, useEditorRef } from "./tools/prefabeditor/EditorContext";
|
|
8
|
+
export type { EditorContextType } from "./tools/prefabeditor/EditorContext";
|
|
9
|
+
export { usePrefabStore, usePrefabStoreApi } from "./tools/prefabeditor/prefabStore";
|
|
10
|
+
export type { PrefabStoreApi, PrefabStoreState } from "./tools/prefabeditor/prefabStore";
|
|
11
|
+
export { FieldRenderer, FieldGroup, ListEditor, Label, Vector3Input, Vector3Field, NumberField, ColorInput, ColorField, StringInput, StringField, BooleanInput, BooleanField, SelectInput, SelectField, } from "./tools/prefabeditor/components/Input";
|
|
12
|
+
export { loadJson, saveJson, exportGLB, exportGLBData, regenerateIds, computeParentWorldMatrix, } from "./tools/prefabeditor/utils";
|
|
13
|
+
export type { ExportGLBOptions } from "./tools/prefabeditor/utils";
|
|
14
|
+
export { decomposeModelToPrefabNodes } from "./tools/prefabeditor/modelPrefab";
|
|
15
|
+
export type { DecomposeModelOptions } from "./tools/prefabeditor/modelPrefab";
|
|
16
|
+
export type { FieldDefinition, FieldType } from "./tools/prefabeditor/components/Input";
|
|
17
|
+
export { MaterialOverridesProvider, useMaterialOverrides } from "./tools/prefabeditor/components/MaterialComponent";
|
|
18
|
+
export type { MaterialOverrides } from "./tools/prefabeditor/components/MaterialComponent";
|
|
19
|
+
export { float, positionLocal, sin, time, uniform, vec3, } from "three/tsl";
|
|
20
|
+
export { loadFiles } from "./tools/dragdrop/DragDropLoader";
|
|
21
|
+
export type { AssetLoadOptions } from "./tools/dragdrop/DragDropLoader";
|
|
22
|
+
export { ModelListViewer, SoundListViewer, ModelPicker, SoundPicker, TextureListViewer, TexturePicker, SingleModelViewer, SingleSoundViewer, SingleTextureViewer, SharedCanvas, } from "./tools/assetviewer/page";
|
package/dist/editor.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { registerBuiltinComponents } from "./tools/prefabeditor/components";
|
|
2
|
+
import "./viewer";
|
|
3
|
+
registerBuiltinComponents();
|
|
4
|
+
export { registerBuiltinComponents };
|
|
5
|
+
export * from "./viewer";
|
|
6
|
+
export { default as PrefabEditor } from "./tools/prefabeditor/PrefabEditor";
|
|
7
|
+
export { useEditorContext, useEditorRef } from "./tools/prefabeditor/EditorContext";
|
|
8
|
+
export { usePrefabStore, usePrefabStoreApi } from "./tools/prefabeditor/prefabStore";
|
|
9
|
+
export { FieldRenderer, FieldGroup, ListEditor, Label, Vector3Input, Vector3Field, NumberField, ColorInput, ColorField, StringInput, StringField, BooleanInput, BooleanField, SelectInput, SelectField, } from "./tools/prefabeditor/components/Input";
|
|
10
|
+
export { loadJson, saveJson, exportGLB, exportGLBData, regenerateIds, computeParentWorldMatrix, } from "./tools/prefabeditor/utils";
|
|
11
|
+
export { decomposeModelToPrefabNodes } from "./tools/prefabeditor/modelPrefab";
|
|
12
|
+
export { MaterialOverridesProvider, useMaterialOverrides } from "./tools/prefabeditor/components/MaterialComponent";
|
|
13
|
+
export { float, positionLocal, sin, time, uniform, vec3, } from "three/tsl";
|
|
14
|
+
export { loadFiles } from "./tools/dragdrop/DragDropLoader";
|
|
15
|
+
export { ModelListViewer, SoundListViewer, ModelPicker, SoundPicker, TextureListViewer, TexturePicker, SingleModelViewer, SingleSoundViewer, SingleTextureViewer, SharedCanvas, } from "./tools/assetviewer/page";
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useFrame } from "@react-three/fiber";
|
|
4
|
-
import { useEffect, useMemo, useRef } from "react";
|
|
4
|
+
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
5
|
+
import { useStore } from "zustand";
|
|
5
6
|
import { BooleanField, FieldRenderer, StringField, Vector3Field, } from "../../tools/prefabeditor/components/Input";
|
|
6
|
-
import {
|
|
7
|
+
import { useModelAsset, useNode } from "../../tools/prefabeditor/assetRuntime";
|
|
7
8
|
import { usePrefabStoreApi } from "../../tools/prefabeditor/prefabStore";
|
|
8
|
-
import { PrefabEditorMode, useScene } from "../../tools/prefabeditor/
|
|
9
|
+
import { PrefabEditorMode, useScene } from "../../tools/prefabeditor/SceneContext";
|
|
9
10
|
import { box, capsule, convexHull, MotionQuality, MotionType, rigidBody, sphere, triangleMesh, } from "crashcat";
|
|
10
11
|
import { Matrix4, Quaternion, Vector3 } from "three";
|
|
11
12
|
import { useCrashcat } from "./CrashcatRuntime";
|
|
@@ -51,7 +52,26 @@ const scratchBoundsSize = new Vector3();
|
|
|
51
52
|
const worldQuaternion = new Quaternion();
|
|
52
53
|
const parentWorldQuaternion = new Quaternion();
|
|
53
54
|
const localQuaternion = new Quaternion();
|
|
55
|
+
// Extracted collider geometry is keyed by the sequence of geometry UUIDs in the
|
|
56
|
+
// object's subtree. Clones of the same model share geometry instances and have
|
|
57
|
+
// identical model-internal transforms, and the extraction is expressed in
|
|
58
|
+
// object-local space (the object's own world transform is divided out), so the
|
|
59
|
+
// result is identical across every instance/body of that model. Extracting once
|
|
60
|
+
// avoids re-walking thousands of vertices per rigid body.
|
|
61
|
+
const geometryDataCache = new Map();
|
|
54
62
|
function collectGeometryData(object) {
|
|
63
|
+
let cacheKey = "";
|
|
64
|
+
object.traverse((child) => {
|
|
65
|
+
var _a;
|
|
66
|
+
const geometry = child.geometry;
|
|
67
|
+
if (((_a = geometry === null || geometry === void 0 ? void 0 : geometry.attributes) === null || _a === void 0 ? void 0 : _a.position) && geometry.uuid)
|
|
68
|
+
cacheKey += `${geometry.uuid};`;
|
|
69
|
+
});
|
|
70
|
+
if (cacheKey) {
|
|
71
|
+
const cached = geometryDataCache.get(cacheKey);
|
|
72
|
+
if (cached)
|
|
73
|
+
return cached;
|
|
74
|
+
}
|
|
55
75
|
const positions = [];
|
|
56
76
|
const indices = [];
|
|
57
77
|
let vertexOffset = 0;
|
|
@@ -83,7 +103,10 @@ function collectGeometryData(object) {
|
|
|
83
103
|
});
|
|
84
104
|
if (positions.length === 0 || indices.length < 3)
|
|
85
105
|
return null;
|
|
86
|
-
|
|
106
|
+
const result = { positions, indices };
|
|
107
|
+
if (cacheKey)
|
|
108
|
+
geometryDataCache.set(cacheKey, result);
|
|
109
|
+
return result;
|
|
87
110
|
}
|
|
88
111
|
function createShapeForObject(object, physics) {
|
|
89
112
|
var _a, _b;
|
|
@@ -246,8 +269,23 @@ function CrashcatPhysicsView({ properties, children }) {
|
|
|
246
269
|
const scene = useScene();
|
|
247
270
|
const store = usePrefabStoreApi();
|
|
248
271
|
const api = useCrashcat();
|
|
249
|
-
|
|
250
|
-
|
|
272
|
+
// Subscribe only to this node's Model filename (not its full node, which would
|
|
273
|
+
// re-render on every transform edit), then to that one model's loaded asset.
|
|
274
|
+
// Colliders rebuild when *this* node's mesh loads, not when any asset loads.
|
|
275
|
+
const modelPath = useStore(store, useCallback((s) => {
|
|
276
|
+
var _a, _b;
|
|
277
|
+
const node = s.nodesById[nodeId];
|
|
278
|
+
if (!node)
|
|
279
|
+
return null;
|
|
280
|
+
for (const key in node.components) {
|
|
281
|
+
const component = node.components[key];
|
|
282
|
+
if ((component === null || component === void 0 ? void 0 : component.type) === "Model") {
|
|
283
|
+
return (_b = (_a = component.properties) === null || _a === void 0 ? void 0 : _a.filename) !== null && _b !== void 0 ? _b : null;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return null;
|
|
287
|
+
}, [nodeId]));
|
|
288
|
+
const loadedModel = useModelAsset(modelPath);
|
|
251
289
|
const bodyRef = useRef(null);
|
|
252
290
|
const motionTypeRef = useRef(MotionType.STATIC);
|
|
253
291
|
const needsRegistrationRef = useRef(false);
|
|
@@ -307,8 +345,8 @@ function CrashcatPhysicsView({ properties, children }) {
|
|
|
307
345
|
lastQuaternionRef.current = null;
|
|
308
346
|
};
|
|
309
347
|
useEffect(() => {
|
|
310
|
-
// Rebuild mesh-derived colliders when referenced
|
|
311
|
-
void
|
|
348
|
+
// Rebuild mesh-derived colliders when this node's referenced model finishes loading.
|
|
349
|
+
void loadedModel;
|
|
312
350
|
needsRegistrationRef.current = true;
|
|
313
351
|
if (api) {
|
|
314
352
|
api.unregister(nodeId);
|
|
@@ -325,7 +363,7 @@ function CrashcatPhysicsView({ properties, children }) {
|
|
|
325
363
|
getObject,
|
|
326
364
|
nodeId,
|
|
327
365
|
physics,
|
|
328
|
-
|
|
366
|
+
loadedModel,
|
|
329
367
|
]);
|
|
330
368
|
useFrame(() => {
|
|
331
369
|
if (needsRegistrationRef.current) {
|
|
@@ -52,7 +52,7 @@ export type CrashcatRagdollProps = {
|
|
|
52
52
|
nodeInteractionHandlers?: NodeInteractionHandlers;
|
|
53
53
|
};
|
|
54
54
|
export declare function createRagdollSettings(scale?: number, angleA?: number, angleB?: number, twistAngle?: number): RagdollSettings;
|
|
55
|
-
export declare function CrashcatRagdoll({ position, scale, swingAngle, shoulderAngle, twistAngle, stabilize, initialLinearVelocity, initialAngularVelocity, color, clickImpulse, nodeInteractionHandlers, }: CrashcatRagdollProps): import("react
|
|
55
|
+
export declare function CrashcatRagdoll({ position, scale, swingAngle, shoulderAngle, twistAngle, stabilize, initialLinearVelocity, initialAngularVelocity, color, clickImpulse, nodeInteractionHandlers, }: CrashcatRagdollProps): import("react").JSX.Element;
|
|
56
56
|
declare const CrashcatRagdollComponent: Component;
|
|
57
57
|
export default CrashcatRagdollComponent;
|
|
58
58
|
export declare function createStaticBoxBody(world: World, objectLayer: number, halfExtents: Vec3, position: Vec3): rigidBody.RigidBody;
|
|
@@ -5,7 +5,7 @@ import { addBroadphaseLayer, addObjectLayer, createWorld, createWorldSettings, e
|
|
|
5
5
|
import { debugRenderer } from "crashcat/three";
|
|
6
6
|
import { useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
7
7
|
import { gameEvents } from "../../tools/prefabeditor/GameEvents";
|
|
8
|
-
import { PrefabEditorMode, useScene } from "../../tools/prefabeditor/
|
|
8
|
+
import { PrefabEditorMode, useScene } from "../../tools/prefabeditor/SceneContext";
|
|
9
9
|
const SLEEP_TIME_BEFORE_REST = 0.1;
|
|
10
10
|
const SLEEP_POINT_VELOCITY_THRESHOLD = 0.06;
|
|
11
11
|
const MAX_PHYSICS_STEP_DELTA = 1 / 60;
|
|
@@ -4,5 +4,5 @@ interface ContactShadowProps {
|
|
|
4
4
|
scale?: number;
|
|
5
5
|
yOffset?: number;
|
|
6
6
|
}
|
|
7
|
-
declare const ContactShadow: ({ opacity, blur, scale, yOffset, }: ContactShadowProps) => import("react
|
|
7
|
+
declare const ContactShadow: ({ opacity, blur, scale, yOffset, }: ContactShadowProps) => import("react").JSX.Element;
|
|
8
8
|
export default ContactShadow;
|
|
@@ -5,4 +5,4 @@ export interface GameCanvasProps extends Omit<CanvasProps, 'children'> {
|
|
|
5
5
|
children: React.ReactNode;
|
|
6
6
|
glConfig?: WebGPURendererParameters;
|
|
7
7
|
}
|
|
8
|
-
export default function GameCanvas({ loader, children, glConfig, onCreated, style, ...props }: GameCanvasProps): import("react
|
|
8
|
+
export default function GameCanvas({ loader, children, glConfig, onCreated, style, ...props }: GameCanvasProps): import("react").JSX.Element;
|
|
@@ -4,48 +4,48 @@ interface TextureListViewerProps {
|
|
|
4
4
|
onSelect: (file: string) => void;
|
|
5
5
|
basePath?: string;
|
|
6
6
|
}
|
|
7
|
-
export declare function TextureListViewer({ files, selected, onSelect, basePath }: TextureListViewerProps): import("react
|
|
7
|
+
export declare function TextureListViewer({ files, selected, onSelect, basePath }: TextureListViewerProps): import("react").JSX.Element;
|
|
8
8
|
interface ModelListViewerProps {
|
|
9
9
|
files: string[];
|
|
10
10
|
selected?: string;
|
|
11
11
|
onSelect: (file: string) => void;
|
|
12
12
|
basePath?: string;
|
|
13
13
|
}
|
|
14
|
-
export declare function ModelListViewer({ files, selected, onSelect, basePath }: ModelListViewerProps): import("react
|
|
14
|
+
export declare function ModelListViewer({ files, selected, onSelect, basePath }: ModelListViewerProps): import("react").JSX.Element;
|
|
15
15
|
interface SoundListViewerProps {
|
|
16
16
|
files: string[];
|
|
17
17
|
selected?: string;
|
|
18
18
|
onSelect: (file: string) => void;
|
|
19
19
|
basePath?: string;
|
|
20
20
|
}
|
|
21
|
-
export declare function SoundListViewer({ files, selected, onSelect, basePath }: SoundListViewerProps): import("react
|
|
21
|
+
export declare function SoundListViewer({ files, selected, onSelect, basePath }: SoundListViewerProps): import("react").JSX.Element;
|
|
22
22
|
export declare function TexturePicker({ value, onChange, basePath }: {
|
|
23
23
|
value: string | undefined;
|
|
24
24
|
onChange: (value: string | undefined) => void;
|
|
25
25
|
basePath?: string;
|
|
26
|
-
}): import("react
|
|
26
|
+
}): import("react").JSX.Element;
|
|
27
27
|
export declare function ModelPicker({ value, onChange, basePath, pickerKey }: {
|
|
28
28
|
value: string | undefined;
|
|
29
29
|
onChange: (value: string | undefined) => void;
|
|
30
30
|
basePath?: string;
|
|
31
31
|
pickerKey?: string;
|
|
32
|
-
}): import("react
|
|
32
|
+
}): import("react").JSX.Element;
|
|
33
33
|
export declare function SoundPicker({ value, onChange, basePath }: {
|
|
34
34
|
value: string | undefined;
|
|
35
35
|
onChange: (value: string | undefined) => void;
|
|
36
36
|
basePath?: string;
|
|
37
|
-
}): import("react
|
|
37
|
+
}): import("react").JSX.Element;
|
|
38
38
|
export declare function SingleTextureViewer({ file, basePath }: {
|
|
39
39
|
file?: string;
|
|
40
40
|
basePath?: string;
|
|
41
|
-
}): import("react
|
|
41
|
+
}): import("react").JSX.Element;
|
|
42
42
|
export declare function SingleModelViewer({ file, basePath }: {
|
|
43
43
|
file?: string;
|
|
44
44
|
basePath?: string;
|
|
45
|
-
}): import("react
|
|
45
|
+
}): import("react").JSX.Element;
|
|
46
46
|
export declare function SingleSoundViewer({ file, basePath }: {
|
|
47
47
|
file?: string;
|
|
48
48
|
basePath?: string;
|
|
49
|
-
}): import("react
|
|
50
|
-
export declare function SharedCanvas(): import("react
|
|
49
|
+
}): import("react").JSX.Element | null;
|
|
50
|
+
export declare function SharedCanvas(): import("react").JSX.Element;
|
|
51
51
|
export {};
|
|
@@ -21,6 +21,6 @@ export declare function loadDroppedAssets(dataTransfer: DataTransfer | null, opt
|
|
|
21
21
|
export declare function loadUrls(urls: string[], options: AssetLoadOptions): Promise<void>;
|
|
22
22
|
export declare function loadUrl(url: string, options: AssetLoadOptions): Promise<void>;
|
|
23
23
|
export declare function loadFiles(files: File[], { onModelLoaded, onTextureLoaded, onSoundLoaded, onUnhandledFile, onFilesLoaded, onLoadError }: AssetLoadOptions): Promise<void>;
|
|
24
|
-
export declare function DragDropLoader({ children, ...divProps }: DragDropLoaderProps): import("react
|
|
25
|
-
export declare function FilePicker({ accept, children, multiple, ...divProps }: FilePickerProps): import("react
|
|
24
|
+
export declare function DragDropLoader({ children, ...divProps }: DragDropLoaderProps): import("react").JSX.Element;
|
|
25
|
+
export declare function FilePicker({ accept, children, multiple, ...divProps }: FilePickerProps): import("react").JSX.Element;
|
|
26
26
|
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { PrefabEditorMode, Scene } from "./SceneContext";
|
|
2
|
+
import type { Prefab } from "./types";
|
|
3
|
+
import type { ExportGLBOptions } from "./utils";
|
|
4
|
+
export interface PrefabEditorRef extends Scene {
|
|
5
|
+
save: () => Prefab;
|
|
6
|
+
load: (prefab: Prefab, options?: {
|
|
7
|
+
resetHistory?: boolean;
|
|
8
|
+
notifyChange?: boolean;
|
|
9
|
+
}) => void;
|
|
10
|
+
undo: () => void;
|
|
11
|
+
redo: () => void;
|
|
12
|
+
screenshot: () => void;
|
|
13
|
+
exportGLB: (options?: ExportGLBOptions) => Promise<ArrayBuffer | undefined>;
|
|
14
|
+
exportGLBData: () => Promise<ArrayBuffer | undefined>;
|
|
15
|
+
clearSelection: () => Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
export interface EditorContextType {
|
|
18
|
+
mode: PrefabEditorMode;
|
|
19
|
+
basePath: string;
|
|
20
|
+
setMode: (mode: PrefabEditorMode) => void;
|
|
21
|
+
transformMode: "translate" | "rotate" | "scale";
|
|
22
|
+
setTransformMode: (mode: "translate" | "rotate" | "scale") => void;
|
|
23
|
+
scaleSnap: number;
|
|
24
|
+
setScaleSnap: (resolution: number) => void;
|
|
25
|
+
positionSnap: number;
|
|
26
|
+
setPositionSnap: (resolution: number) => void;
|
|
27
|
+
rotationSnap: number;
|
|
28
|
+
setRotationSnap: (resolution: number) => void;
|
|
29
|
+
onFocusNode?: (nodeId: string) => void;
|
|
30
|
+
onScreenshot?: () => void;
|
|
31
|
+
onExportGLB?: () => void;
|
|
32
|
+
}
|
|
33
|
+
export declare const EditorContext: import("react").Context<EditorContextType | null>;
|
|
34
|
+
export declare const EditorRefContext: import("react").Context<PrefabEditorRef | null>;
|
|
35
|
+
export declare function useEditorContext(): EditorContextType;
|
|
36
|
+
export declare function useEditorRef(): PrefabEditorRef;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
export const EditorContext = createContext(null);
|
|
3
|
+
export const EditorRefContext = createContext(null);
|
|
4
|
+
export function useEditorContext() {
|
|
5
|
+
const context = useContext(EditorContext);
|
|
6
|
+
if (!context) {
|
|
7
|
+
throw new Error("useEditorContext must be used within EditorContext.Provider");
|
|
8
|
+
}
|
|
9
|
+
return context;
|
|
10
|
+
}
|
|
11
|
+
export function useEditorRef() {
|
|
12
|
+
const editorRef = useContext(EditorRefContext);
|
|
13
|
+
if (!editorRef) {
|
|
14
|
+
throw new Error("useEditorRef must be used within PrefabEditor");
|
|
15
|
+
}
|
|
16
|
+
return editorRef;
|
|
17
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { memo, useCallback, useState } from 'react';
|
|
3
3
|
import { base, colors, tree } from './styles';
|
|
4
|
-
import { useEditorContext, useEditorRef } from './
|
|
4
|
+
import { useEditorContext, useEditorRef } from './EditorContext';
|
|
5
5
|
import { Dropdown } from './Dropdown';
|
|
6
6
|
import { FileMenu, TreeContextMenu, TreeNodeMenu } from './EditorTreeMenus';
|
|
7
7
|
import { createEmptyNode, createPackedPrefabNode } from './prefab';
|
|
@@ -14,7 +14,7 @@ export declare function TreeNodeMenu({ isRoot, nodeId, locked, onAddChild, onFoc
|
|
|
14
14
|
onDuplicate?: (nodeId: string) => void;
|
|
15
15
|
onDelete?: (nodeId: string) => void;
|
|
16
16
|
onClose: () => void;
|
|
17
|
-
}): import("react
|
|
17
|
+
}): import("react").JSX.Element;
|
|
18
18
|
export declare function TreeContextMenu({ contextMenu, onClose, children, }: {
|
|
19
19
|
contextMenu: TreeContextMenuState;
|
|
20
20
|
onClose: () => void;
|
|
@@ -26,4 +26,4 @@ export declare function FileMenu({ getPrefab, onReplacePrefab, onImportPrefab, o
|
|
|
26
26
|
onImportPrefab: (prefab: Prefab) => void;
|
|
27
27
|
onImportPackedPrefab: (url: string) => void;
|
|
28
28
|
onClose: () => void;
|
|
29
|
-
}): import("react
|
|
29
|
+
}): import("react").JSX.Element;
|
|
@@ -12,7 +12,7 @@ import { useEffect, useRef, useState } from 'react';
|
|
|
12
12
|
import { createPortal } from 'react-dom';
|
|
13
13
|
import { createEmptyPrefab } from './prefab';
|
|
14
14
|
import { menu } from './styles';
|
|
15
|
-
import { useEditorContext } from './
|
|
15
|
+
import { useEditorContext } from './EditorContext';
|
|
16
16
|
import { loadJson, loadJsonFile, saveJson, withBasePath } from './utils';
|
|
17
17
|
function MenuPanel({ children, style, }) {
|
|
18
18
|
return (_jsx("div", { style: Object.assign(Object.assign(Object.assign({}, menu.container), { position: 'static' }), style), onClick: (e) => e.stopPropagation(), children: children }));
|
|
@@ -14,7 +14,7 @@ import { useState } from 'react';
|
|
|
14
14
|
import EditorTree from './EditorTree';
|
|
15
15
|
import { canAddComponentToNode, getAllComponentDefs, getNextComponentKey } from './components/ComponentRegistry';
|
|
16
16
|
import { createComponentData } from './prefab';
|
|
17
|
-
import { useEditorRef } from './
|
|
17
|
+
import { useEditorRef } from './EditorContext';
|
|
18
18
|
import { base, colors, inspector, componentCard } from './styles';
|
|
19
19
|
import { usePrefabStore } from './prefabStore';
|
|
20
20
|
function EditorUI({ selectedId, setSelectedId, getPrefab, onReplacePrefab, onImportPrefab, basePath, onUndo, onRedo, canUndo, canRedo }) {
|
|
@@ -29,7 +29,7 @@ export declare function GameInstanceProvider({ children, models, onSelect, onCli
|
|
|
29
29
|
registerRef?: (id: string, obj: Object3D | null) => void;
|
|
30
30
|
selectedId?: string | null;
|
|
31
31
|
editMode?: boolean;
|
|
32
|
-
}): import("react
|
|
32
|
+
}): import("react").JSX.Element;
|
|
33
33
|
export declare function useInstanceCheck(id: string): boolean;
|
|
34
34
|
export declare function GameInstance({ id, sourceId, modelUrl, locked, position, rotation, scale, visible, onClick: _onClick, }: {
|
|
35
35
|
id: string;
|
|
@@ -1,44 +1,11 @@
|
|
|
1
|
-
import GameCanvas from "../../shared/GameCanvas";
|
|
2
1
|
import type { Prefab } from "./types";
|
|
3
|
-
import {
|
|
4
|
-
import type
|
|
2
|
+
import { GameCanvas, PrefabEditorMode } from "../../viewer";
|
|
3
|
+
import { type PrefabEditorRef } from "./EditorContext";
|
|
5
4
|
export { isExternalPath as isAbsoluteAssetPath } from "./utils";
|
|
6
5
|
export declare function resolvePrefabAssetPath(basePath: string, file: string): string;
|
|
7
6
|
export declare function getPrefabAssetRef(assetRef: string, folder: "models" | "textures" | "sound"): string;
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
load: (prefab: Prefab, options?: {
|
|
11
|
-
resetHistory?: boolean;
|
|
12
|
-
notifyChange?: boolean;
|
|
13
|
-
}) => void;
|
|
14
|
-
undo: () => void;
|
|
15
|
-
redo: () => void;
|
|
16
|
-
screenshot: () => void;
|
|
17
|
-
exportGLB: (options?: ExportGLBOptions) => Promise<ArrayBuffer | undefined>;
|
|
18
|
-
exportGLBData: () => Promise<ArrayBuffer | undefined>;
|
|
19
|
-
clearSelection: () => Promise<void>;
|
|
20
|
-
}
|
|
21
|
-
export type { PrefabNode } from "./PrefabRoot";
|
|
22
|
-
export interface EditorContextType {
|
|
23
|
-
mode: PrefabEditorMode;
|
|
24
|
-
basePath: string;
|
|
25
|
-
setMode: (mode: PrefabEditorMode) => void;
|
|
26
|
-
transformMode: "translate" | "rotate" | "scale";
|
|
27
|
-
setTransformMode: (mode: "translate" | "rotate" | "scale") => void;
|
|
28
|
-
scaleSnap: number;
|
|
29
|
-
setScaleSnap: (resolution: number) => void;
|
|
30
|
-
positionSnap: number;
|
|
31
|
-
setPositionSnap: (resolution: number) => void;
|
|
32
|
-
rotationSnap: number;
|
|
33
|
-
setRotationSnap: (resolution: number) => void;
|
|
34
|
-
onFocusNode?: (nodeId: string) => void;
|
|
35
|
-
onScreenshot?: () => void;
|
|
36
|
-
onExportGLB?: () => void;
|
|
37
|
-
}
|
|
38
|
-
export declare const EditorContext: import("react").Context<EditorContextType | null>;
|
|
39
|
-
export declare const EditorRefContext: import("react").Context<PrefabEditorRef | null>;
|
|
40
|
-
export declare function useEditorContext(): EditorContextType;
|
|
41
|
-
export declare function useEditorRef(): PrefabEditorRef;
|
|
7
|
+
export type { EditorContextType, PrefabEditorRef } from "./EditorContext";
|
|
8
|
+
export { EditorContext, EditorRefContext, useEditorContext, useEditorRef } from "./EditorContext";
|
|
42
9
|
export interface PrefabEditorProps {
|
|
43
10
|
basePath?: string;
|
|
44
11
|
initialPrefab?: Prefab;
|