react-three-game 0.0.69 → 0.0.71
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/dist/helpers/SoundManager.d.ts +2 -0
- package/dist/helpers/SoundManager.js +6 -0
- package/dist/index.d.ts +20 -13
- package/dist/index.js +14 -7
- package/dist/shared/GameCanvas.js +0 -2
- package/dist/tools/assetviewer/page.d.ts +5 -0
- package/dist/tools/assetviewer/page.js +3 -0
- package/dist/tools/dragdrop/DragDropLoader.d.ts +3 -2
- package/dist/tools/dragdrop/DragDropLoader.js +18 -3
- package/dist/tools/dragdrop/index.d.ts +2 -2
- package/dist/tools/dragdrop/index.js +1 -1
- package/dist/tools/dragdrop/modelLoader.d.ts +10 -0
- package/dist/tools/dragdrop/modelLoader.js +60 -0
- package/dist/tools/prefabeditor/EditorTree.js +6 -40
- package/dist/tools/prefabeditor/EditorTreeMenus.js +2 -20
- package/dist/tools/prefabeditor/EditorUI.js +8 -5
- package/dist/tools/prefabeditor/InstanceProvider.d.ts +2 -0
- package/dist/tools/prefabeditor/InstanceProvider.js +54 -52
- package/dist/tools/prefabeditor/PrefabEditor.d.ts +23 -1
- package/dist/tools/prefabeditor/PrefabEditor.js +79 -47
- package/dist/tools/prefabeditor/PrefabRoot.d.ts +26 -9
- package/dist/tools/prefabeditor/PrefabRoot.js +195 -159
- package/dist/tools/prefabeditor/RefBridge.d.ts +24 -0
- package/dist/tools/prefabeditor/RefBridge.js +44 -0
- package/dist/tools/prefabeditor/components/AmbientLightComponent.js +10 -7
- package/dist/tools/prefabeditor/components/CameraComponent.js +8 -14
- package/dist/tools/prefabeditor/components/ClickComponent.js +12 -7
- package/dist/tools/prefabeditor/components/ComponentRegistry.d.ts +31 -5
- package/dist/tools/prefabeditor/components/ComponentRegistry.js +6 -6
- package/dist/tools/prefabeditor/components/DirectionalLightComponent.js +124 -52
- package/dist/tools/prefabeditor/components/EnvironmentComponent.js +5 -3
- package/dist/tools/prefabeditor/components/GeometryComponent.js +1 -1
- package/dist/tools/prefabeditor/components/Input.d.ts +16 -0
- package/dist/tools/prefabeditor/components/Input.js +33 -0
- package/dist/tools/prefabeditor/components/MaterialComponent.js +19 -8
- package/dist/tools/prefabeditor/components/ModelComponent.js +39 -45
- package/dist/tools/prefabeditor/components/PhysicsComponent.d.ts +10 -1
- package/dist/tools/prefabeditor/components/PhysicsComponent.js +127 -31
- package/dist/tools/prefabeditor/components/PointLightComponent.d.ts +3 -0
- package/dist/tools/prefabeditor/components/PointLightComponent.js +55 -0
- package/dist/tools/prefabeditor/components/SoundComponent.d.ts +3 -0
- package/dist/tools/prefabeditor/components/SoundComponent.js +244 -0
- package/dist/tools/prefabeditor/components/SpotLightComponent.js +53 -24
- package/dist/tools/prefabeditor/components/TransformComponent.js +2 -2
- package/dist/tools/prefabeditor/components/index.js +4 -0
- package/dist/tools/prefabeditor/components/lightUtils.d.ts +13 -0
- package/dist/tools/prefabeditor/components/lightUtils.js +64 -0
- package/dist/tools/prefabeditor/prefab.d.ts +37 -0
- package/dist/tools/prefabeditor/prefab.js +229 -0
- package/dist/tools/prefabeditor/prefabStore.d.ts +4 -16
- package/dist/tools/prefabeditor/prefabStore.js +32 -173
- package/dist/tools/prefabeditor/{sceneApi.d.ts → scene.d.ts} +15 -1
- package/dist/tools/prefabeditor/{sceneApi.js → scene.js} +66 -32
- package/dist/tools/prefabeditor/styles.d.ts +1 -0
- package/dist/tools/prefabeditor/styles.js +9 -0
- package/dist/tools/prefabeditor/types.d.ts +13 -0
- package/dist/tools/prefabeditor/types.js +28 -1
- package/dist/tools/prefabeditor/useClickValid.d.ts +13 -0
- package/dist/tools/prefabeditor/useClickValid.js +21 -0
- package/dist/tools/prefabeditor/utils.d.ts +2 -4
- package/dist/tools/prefabeditor/utils.js +8 -46
- package/package.json +1 -1
- package/dist/tools/prefabeditor/EditorContext.d.ts +0 -16
- package/dist/tools/prefabeditor/EditorContext.js +0 -9
|
@@ -19,6 +19,8 @@ declare class SoundManager {
|
|
|
19
19
|
detune?: number;
|
|
20
20
|
pitch?: number;
|
|
21
21
|
}): void;
|
|
22
|
+
hasBuffer(path: string): boolean;
|
|
23
|
+
setBuffer(path: string, buffer: AudioBuffer): void;
|
|
22
24
|
/** Load and play SFX - accepts file path directly */
|
|
23
25
|
play(path: string, options?: {
|
|
24
26
|
volume?: number;
|
|
@@ -68,6 +68,12 @@ class SoundManager {
|
|
|
68
68
|
gain.connect(this.sfxGain);
|
|
69
69
|
src.start();
|
|
70
70
|
}
|
|
71
|
+
hasBuffer(path) {
|
|
72
|
+
return this.buffers.has(path);
|
|
73
|
+
}
|
|
74
|
+
setBuffer(path, buffer) {
|
|
75
|
+
this.buffers.set(path, buffer);
|
|
76
|
+
}
|
|
71
77
|
/** Load and play SFX - accepts file path directly */
|
|
72
78
|
play(path, options) {
|
|
73
79
|
return __awaiter(this, void 0, void 0, function* () {
|
package/dist/index.d.ts
CHANGED
|
@@ -4,26 +4,33 @@ export { ground } from './helpers';
|
|
|
4
4
|
export type { GroundOptions, Vec3 } from './helpers';
|
|
5
5
|
export { sound as soundManager } from './helpers/SoundManager';
|
|
6
6
|
export { default as PrefabEditor } from './tools/prefabeditor/PrefabEditor';
|
|
7
|
+
export { PrefabEditorMode } from './tools/prefabeditor/PrefabEditor';
|
|
7
8
|
export { default as PrefabRoot } from './tools/prefabeditor/PrefabRoot';
|
|
8
|
-
export { useEditorContext } from './tools/prefabeditor/
|
|
9
|
-
export type { EditorContextType } from './tools/prefabeditor/
|
|
10
|
-
export { createPrefabStore, prefabStoreToPrefab } from './tools/prefabeditor/prefabStore';
|
|
9
|
+
export { useEditorContext } from './tools/prefabeditor/PrefabEditor';
|
|
10
|
+
export type { EditorContextType } from './tools/prefabeditor/PrefabEditor';
|
|
11
|
+
export { createPrefabStore, prefabStoreToPrefab, usePrefabStoreApi } from './tools/prefabeditor/prefabStore';
|
|
11
12
|
export type { PrefabStoreApi, PrefabStoreState } from './tools/prefabeditor/prefabStore';
|
|
12
|
-
export { createScene } from './tools/prefabeditor/
|
|
13
|
+
export { createScene } from './tools/prefabeditor/scene';
|
|
14
|
+
export { denormalizePrefab } from './tools/prefabeditor/prefab';
|
|
13
15
|
export { registerComponent } from './tools/prefabeditor/components/ComponentRegistry';
|
|
14
|
-
export { FieldRenderer, FieldGroup, Label, Vector3Input, Vector3Field, NumberField, ColorInput, ColorField, StringInput, StringField, BooleanInput, BooleanField, SelectInput, SelectField, } from './tools/prefabeditor/components/Input';
|
|
15
|
-
export { loadJson, saveJson, exportGLB, exportGLBData, regenerateIds, computeParentWorldMatrix,
|
|
16
|
+
export { FieldRenderer, FieldGroup, ListEditor, Label, Vector3Input, Vector3Field, NumberField, ColorInput, ColorField, StringInput, StringField, BooleanInput, BooleanField, SelectInput, SelectField, } from './tools/prefabeditor/components/Input';
|
|
17
|
+
export { loadJson, saveJson, exportGLB, exportGLBData, regenerateIds, computeParentWorldMatrix, } from './tools/prefabeditor/utils';
|
|
16
18
|
export type { ExportGLBOptions } from './tools/prefabeditor/utils';
|
|
19
|
+
export { createModelNode, createImageNode, } from './tools/prefabeditor/prefab';
|
|
17
20
|
export type { PrefabEditorProps, PrefabEditorRef, } from './tools/prefabeditor/PrefabEditor';
|
|
18
|
-
export type { SpawnOptions, Scene, Entity, EntityComponent, EntityData, EntityUpdate, PropertyPath, SceneUpdates, } from './tools/prefabeditor/
|
|
19
|
-
export type { PrefabRootProps, PrefabRootRef } from './tools/prefabeditor/PrefabRoot';
|
|
20
|
-
export
|
|
21
|
+
export type { SpawnOptions, Scene, Entity, EntityComponent, EntityData, EntityUpdate, PropertyPath, SceneUpdates, } from './tools/prefabeditor/scene';
|
|
22
|
+
export type { PrefabRootProps, PrefabRootRef, SceneRuntime } from './tools/prefabeditor/PrefabRoot';
|
|
23
|
+
export { useSceneRuntime } from './tools/prefabeditor/PrefabRoot';
|
|
24
|
+
export type { Component, ComponentViewProps } from './tools/prefabeditor/components/ComponentRegistry';
|
|
21
25
|
export type { FieldDefinition, FieldType } from './tools/prefabeditor/components/Input';
|
|
22
|
-
export type { Prefab, GameObject, ComponentData
|
|
26
|
+
export type { Prefab, GameObject, ComponentData } from './tools/prefabeditor/types';
|
|
27
|
+
export { findComponent, findComponentEntry, hasComponent } from './tools/prefabeditor/types';
|
|
23
28
|
export { gameEvents, useGameEvent, getEntityIdFromRigidBody } from './tools/prefabeditor/GameEvents';
|
|
24
29
|
export type { GameEventType, GameEventMap, GameEventPayload, PhysicsEventType, InteractionEventType, PhysicsEventPayload, ClickEventPayload } from './tools/prefabeditor/GameEvents';
|
|
30
|
+
export { createRefBridge } from './tools/prefabeditor/RefBridge';
|
|
31
|
+
export type { RefBridge } from './tools/prefabeditor/RefBridge';
|
|
25
32
|
export { loadFiles } from './tools/dragdrop/DragDropLoader';
|
|
26
33
|
export type { AssetLoadOptions } from './tools/dragdrop/DragDropLoader';
|
|
27
|
-
export { loadModel, loadTexture } from './tools/dragdrop/modelLoader';
|
|
28
|
-
export type { LoadedModel,
|
|
29
|
-
export {
|
|
34
|
+
export { loadModel, loadSound, loadTexture } from './tools/dragdrop/modelLoader';
|
|
35
|
+
export type { LoadedModel, LoadedModels, ModelLoadResult, LoadedSound, LoadedSounds, SoundLoadResult, LoadedTexture, LoadedTextures, TextureLoadResult, ProgressCallback, } from './tools/dragdrop/modelLoader';
|
|
36
|
+
export { ModelListViewer, SoundListViewer, ModelPicker, SoundPicker, TextureListViewer, TexturePicker, SingleModelViewer, SingleSoundViewer, SingleTextureViewer, SharedCanvas, } from './tools/assetviewer/page';
|
package/dist/index.js
CHANGED
|
@@ -5,21 +5,28 @@ export { ground } from './helpers';
|
|
|
5
5
|
export { sound as soundManager } from './helpers/SoundManager';
|
|
6
6
|
// Prefab Editor
|
|
7
7
|
export { default as PrefabEditor } from './tools/prefabeditor/PrefabEditor';
|
|
8
|
+
export { PrefabEditorMode } from './tools/prefabeditor/PrefabEditor';
|
|
8
9
|
export { default as PrefabRoot } from './tools/prefabeditor/PrefabRoot';
|
|
9
|
-
export { useEditorContext } from './tools/prefabeditor/
|
|
10
|
+
export { useEditorContext } from './tools/prefabeditor/PrefabEditor';
|
|
10
11
|
// Prefab Editor - Store & Scene API
|
|
11
|
-
export { createPrefabStore, prefabStoreToPrefab } from './tools/prefabeditor/prefabStore';
|
|
12
|
-
export { createScene } from './tools/prefabeditor/
|
|
12
|
+
export { createPrefabStore, prefabStoreToPrefab, usePrefabStoreApi } from './tools/prefabeditor/prefabStore';
|
|
13
|
+
export { createScene } from './tools/prefabeditor/scene';
|
|
14
|
+
export { denormalizePrefab } from './tools/prefabeditor/prefab';
|
|
13
15
|
// Prefab Editor - Component Registry
|
|
14
16
|
export { registerComponent } from './tools/prefabeditor/components/ComponentRegistry';
|
|
15
17
|
// Prefab Editor - Input Components
|
|
16
|
-
export { FieldRenderer, FieldGroup, Label, Vector3Input, Vector3Field, NumberField, ColorInput, ColorField, StringInput, StringField, BooleanInput, BooleanField, SelectInput, SelectField, } from './tools/prefabeditor/components/Input';
|
|
18
|
+
export { FieldRenderer, FieldGroup, ListEditor, Label, Vector3Input, Vector3Field, NumberField, ColorInput, ColorField, StringInput, StringField, BooleanInput, BooleanField, SelectInput, SelectField, } from './tools/prefabeditor/components/Input';
|
|
17
19
|
// Prefab Editor - Utils
|
|
18
|
-
export { loadJson, saveJson, exportGLB, exportGLBData, regenerateIds, computeParentWorldMatrix,
|
|
20
|
+
export { loadJson, saveJson, exportGLB, exportGLBData, regenerateIds, computeParentWorldMatrix, } from './tools/prefabeditor/utils';
|
|
21
|
+
export { createModelNode, createImageNode, } from './tools/prefabeditor/prefab';
|
|
22
|
+
export { useSceneRuntime } from './tools/prefabeditor/PrefabRoot';
|
|
23
|
+
export { findComponent, findComponentEntry, hasComponent } from './tools/prefabeditor/types';
|
|
19
24
|
// Game Events (physics + custom events)
|
|
20
25
|
export { gameEvents, useGameEvent, getEntityIdFromRigidBody } from './tools/prefabeditor/GameEvents';
|
|
26
|
+
// RefBridge & Systems
|
|
27
|
+
export { createRefBridge } from './tools/prefabeditor/RefBridge';
|
|
21
28
|
// Asset Loading
|
|
22
29
|
export { loadFiles } from './tools/dragdrop/DragDropLoader';
|
|
23
|
-
export { loadModel, loadTexture } from './tools/dragdrop/modelLoader';
|
|
30
|
+
export { loadModel, loadSound, loadTexture } from './tools/dragdrop/modelLoader';
|
|
24
31
|
// Asset Viewer
|
|
25
|
-
export {
|
|
32
|
+
export { ModelListViewer, SoundListViewer, ModelPicker, SoundPicker, TextureListViewer, TexturePicker, SingleModelViewer, SingleSoundViewer, SingleTextureViewer, SharedCanvas, } from './tools/assetviewer/page';
|
|
@@ -23,8 +23,6 @@ import { Canvas, extend } from "@react-three/fiber";
|
|
|
23
23
|
import { WebGPURenderer, MeshBasicNodeMaterial, MeshStandardNodeMaterial, SpriteNodeMaterial, PCFShadowMap } from "three/webgpu";
|
|
24
24
|
import { Suspense, useState } from "react";
|
|
25
25
|
import { Loader } from "@react-three/drei";
|
|
26
|
-
// generic version
|
|
27
|
-
// extend(THREE as any)
|
|
28
26
|
extend({
|
|
29
27
|
MeshBasicNodeMaterial: MeshBasicNodeMaterial,
|
|
30
28
|
MeshStandardNodeMaterial: MeshStandardNodeMaterial,
|
|
@@ -30,6 +30,11 @@ export declare function ModelPicker({ value, onChange, basePath, pickerKey }: {
|
|
|
30
30
|
basePath?: string;
|
|
31
31
|
pickerKey?: string;
|
|
32
32
|
}): import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
export declare function SoundPicker({ value, onChange, basePath }: {
|
|
34
|
+
value: string | undefined;
|
|
35
|
+
onChange: (value: string | undefined) => void;
|
|
36
|
+
basePath?: string;
|
|
37
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
33
38
|
export declare function SingleTextureViewer({ file, basePath }: {
|
|
34
39
|
file?: string;
|
|
35
40
|
basePath?: string;
|
|
@@ -209,6 +209,9 @@ export function TexturePicker({ value, onChange, basePath = "" }) {
|
|
|
209
209
|
export function ModelPicker({ value, onChange, basePath = "", pickerKey }) {
|
|
210
210
|
return (_jsx(AssetPicker, { value: value, onChange: onChange, basePath: basePath, manifestFolder: "models", rootStyle: { maxHeight: 160, overflow: 'visible', position: 'relative', display: 'flex', gap: 8, alignItems: 'center', justifyContent: 'center' }, controlsStyle: { display: 'flex', flexDirection: 'column', gap: 6, flex: '0 0 84px', minWidth: 84, justifyContent: 'flex-end' }, changeButtonStyle: { width: '100%', padding: '6px 8px', backgroundColor: '#1f2937', color: 'inherit', fontSize: 10, cursor: 'pointer', border: '1px solid rgba(34, 211, 238, 0.3)' }, clearButtonStyle: { width: '100%', padding: '6px 8px', backgroundColor: '#1f2937', color: 'inherit', fontSize: 10, cursor: 'pointer', border: '1px solid rgba(34, 211, 238, 0.3)' }, popupStyle: { background: 'rgba(0,0,0,0.9)', border: '1px solid rgba(34, 211, 238, 0.3)' }, preview: _jsx("div", { style: { flex: '0 0 auto' }, children: _jsx(SingleModelViewer, { file: value ? `/${value}` : undefined, basePath: basePath }) }), renderList: ({ files, value: selectedValue, onSelect, basePath: currentBasePath }) => (_jsx(ModelListViewer, { files: files, selected: selectedValue ? `/${selectedValue}` : undefined, onSelect: (file) => onSelect(file.startsWith('/') ? file.slice(1) : file), basePath: currentBasePath }, pickerKey)) }));
|
|
211
211
|
}
|
|
212
|
+
export function SoundPicker({ value, onChange, basePath = "" }) {
|
|
213
|
+
return (_jsx(AssetPicker, { value: value, onChange: onChange, basePath: basePath, manifestFolder: "sound", rootStyle: { maxHeight: 76, overflow: 'visible', position: 'relative', display: 'flex', gap: 8, alignItems: 'center', justifyContent: 'center' }, controlsStyle: { display: 'flex', flexDirection: 'column', gap: 6, flex: '0 0 84px', minWidth: 84, justifyContent: 'flex-end' }, changeButtonStyle: { width: '100%', padding: '6px 8px', backgroundColor: '#1f2937', color: 'inherit', fontSize: 10, cursor: 'pointer', border: '1px solid rgba(255,255,255,0.12)', borderRadius: 3 }, clearButtonStyle: { width: '100%', padding: '6px 8px', backgroundColor: '#1f2937', color: 'inherit', fontSize: 10, cursor: 'pointer', border: '1px solid rgba(255,255,255,0.12)', borderRadius: 3 }, preview: _jsx("div", { style: { flex: '0 0 auto', minWidth: 84 }, children: value ? _jsx(SingleSoundViewer, { file: value, basePath: basePath }) : _jsx("div", { style: { width: 84, height: 60, backgroundColor: '#1f2937', border: '1px dashed rgba(255,255,255,0.12)', borderRadius: 4 } }) }), renderList: ({ files, value: selectedValue, onSelect, basePath: currentBasePath }) => (_jsx(SoundListViewer, { files: files, selected: selectedValue || undefined, onSelect: onSelect, basePath: currentBasePath })) }));
|
|
214
|
+
}
|
|
212
215
|
// Single Asset Viewer Components - display only one selected asset
|
|
213
216
|
export function SingleTextureViewer({ file, basePath = "" }) {
|
|
214
217
|
if (!file)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { HTMLAttributes, ReactNode } from "react";
|
|
2
|
-
import type { LoadedModel, LoadedTexture } from "./modelLoader";
|
|
2
|
+
import type { LoadedModel, LoadedSound, LoadedTexture } from "./modelLoader";
|
|
3
3
|
export interface AssetLoadOptions {
|
|
4
4
|
onModelLoaded?: (model: LoadedModel, filename: string, file: File) => void | Promise<void>;
|
|
5
5
|
onTextureLoaded?: (texture: LoadedTexture, filename: string, file: File) => void | Promise<void>;
|
|
6
|
+
onSoundLoaded?: (sound: LoadedSound, filename: string, file: File) => void | Promise<void>;
|
|
6
7
|
onUnhandledFile?: (file: File) => void | Promise<void>;
|
|
7
8
|
onFilesLoaded?: (files: File[]) => void | Promise<void>;
|
|
8
9
|
onLoadError?: (error: unknown, filename: string, file: File) => void | Promise<void>;
|
|
@@ -16,7 +17,7 @@ export interface FilePickerProps extends AssetLoadOptions, DivProps {
|
|
|
16
17
|
children?: ReactNode;
|
|
17
18
|
multiple?: boolean;
|
|
18
19
|
}
|
|
19
|
-
export declare function loadFiles(files: File[], { onModelLoaded, onTextureLoaded, onUnhandledFile, onFilesLoaded, onLoadError }: AssetLoadOptions): Promise<void>;
|
|
20
|
+
export declare function loadFiles(files: File[], { onModelLoaded, onTextureLoaded, onSoundLoaded, onUnhandledFile, onFilesLoaded, onLoadError }: AssetLoadOptions): Promise<void>;
|
|
20
21
|
export declare function DragDropLoader({ children, ...divProps }: DragDropLoaderProps): import("react/jsx-runtime").JSX.Element;
|
|
21
22
|
export declare function FilePicker({ accept, children, multiple, ...divProps }: FilePickerProps): import("react/jsx-runtime").JSX.Element;
|
|
22
23
|
export {};
|
|
@@ -20,16 +20,17 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
20
20
|
};
|
|
21
21
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
22
22
|
import { useRef } from "react";
|
|
23
|
-
import { canParseModelFile, canParseTextureFile, parseModelFromFile, parseTextureFromFile } from "./modelLoader";
|
|
24
|
-
const DEFAULT_ACCEPT = ".glb,.gltf,.fbx,.png,.jpg,.jpeg,.webp,.gif,.bmp,.svg";
|
|
23
|
+
import { canParseModelFile, canParseSoundFile, canParseTextureFile, parseModelFromFile, parseSoundFromFile, parseTextureFromFile } from "./modelLoader";
|
|
24
|
+
const DEFAULT_ACCEPT = ".glb,.gltf,.fbx,.png,.jpg,.jpeg,.webp,.gif,.bmp,.svg,.mp3,.wav,.ogg,.m4a";
|
|
25
25
|
function getFiles(fileList) {
|
|
26
26
|
return fileList ? Array.from(fileList) : [];
|
|
27
27
|
}
|
|
28
28
|
export function loadFiles(files_1, _a) {
|
|
29
|
-
return __awaiter(this, arguments, void 0, function* (files, { onModelLoaded, onTextureLoaded, onUnhandledFile, onFilesLoaded, onLoadError }) {
|
|
29
|
+
return __awaiter(this, arguments, void 0, function* (files, { onModelLoaded, onTextureLoaded, onSoundLoaded, onUnhandledFile, onFilesLoaded, onLoadError }) {
|
|
30
30
|
yield Promise.all(files.map((file) => __awaiter(this, void 0, void 0, function* () {
|
|
31
31
|
const shouldParseModel = canParseModelFile(file);
|
|
32
32
|
const shouldParseTexture = canParseTextureFile(file);
|
|
33
|
+
const shouldParseSound = canParseSoundFile(file);
|
|
33
34
|
if (shouldParseModel) {
|
|
34
35
|
const result = yield parseModelFromFile(file);
|
|
35
36
|
if (result.success && result.model) {
|
|
@@ -56,6 +57,19 @@ export function loadFiles(files_1, _a) {
|
|
|
56
57
|
console.error("Texture parse error:", result.error);
|
|
57
58
|
return;
|
|
58
59
|
}
|
|
60
|
+
if (shouldParseSound) {
|
|
61
|
+
const result = yield parseSoundFromFile(file);
|
|
62
|
+
if (result.success && result.sound) {
|
|
63
|
+
yield (onSoundLoaded === null || onSoundLoaded === void 0 ? void 0 : onSoundLoaded(result.sound, file.name, file));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (onLoadError) {
|
|
67
|
+
yield onLoadError(result.error, file.name, file);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
console.error("Sound parse error:", result.error);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
59
73
|
if (onUnhandledFile) {
|
|
60
74
|
yield onUnhandledFile(file);
|
|
61
75
|
}
|
|
@@ -70,6 +84,7 @@ function createLoadHandlers(options) {
|
|
|
70
84
|
return {
|
|
71
85
|
onFilesLoaded: options.onFilesLoaded,
|
|
72
86
|
onModelLoaded: options.onModelLoaded,
|
|
87
|
+
onSoundLoaded: options.onSoundLoaded,
|
|
73
88
|
onTextureLoaded: options.onTextureLoaded,
|
|
74
89
|
onUnhandledFile: options.onUnhandledFile,
|
|
75
90
|
onLoadError: options.onLoadError,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { DragDropLoader, FilePicker, loadFiles } from "./DragDropLoader";
|
|
2
2
|
export type { AssetLoadOptions, DragDropLoaderProps, FilePickerProps } from "./DragDropLoader";
|
|
3
|
-
export { loadModel, loadTexture, parseModelFromFile, parseTextureFromFile } from "./modelLoader";
|
|
4
|
-
export type { LoadedModel, LoadedTexture, LoadedModels, LoadedTextures, ModelLoadResult, ProgressCallback, TextureLoadResult } from "./modelLoader";
|
|
3
|
+
export { loadModel, loadSound, loadTexture, parseModelFromFile, parseSoundFromFile, parseTextureFromFile } from "./modelLoader";
|
|
4
|
+
export type { LoadedModel, LoadedSound, LoadedTexture, LoadedModels, LoadedSounds, LoadedTextures, ModelLoadResult, ProgressCallback, SoundLoadResult, TextureLoadResult } from "./modelLoader";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { DragDropLoader, FilePicker, loadFiles } from "./DragDropLoader";
|
|
2
|
-
export { loadModel, loadTexture, parseModelFromFile, parseTextureFromFile } from "./modelLoader";
|
|
2
|
+
export { loadModel, loadSound, loadTexture, parseModelFromFile, parseSoundFromFile, parseTextureFromFile } from "./modelLoader";
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { Object3D, Texture } from "three";
|
|
2
2
|
export type LoadedModel = Object3D;
|
|
3
3
|
export type LoadedTexture = Texture;
|
|
4
|
+
export type LoadedSound = AudioBuffer;
|
|
4
5
|
export type LoadedModels = Record<string, LoadedModel>;
|
|
5
6
|
export type LoadedTextures = Record<string, LoadedTexture>;
|
|
7
|
+
export type LoadedSounds = Record<string, LoadedSound>;
|
|
6
8
|
export type ModelLoadResult = {
|
|
7
9
|
success: boolean;
|
|
8
10
|
model?: LoadedModel;
|
|
@@ -13,10 +15,18 @@ export type TextureLoadResult = {
|
|
|
13
15
|
texture?: LoadedTexture;
|
|
14
16
|
error?: unknown;
|
|
15
17
|
};
|
|
18
|
+
export type SoundLoadResult = {
|
|
19
|
+
success: boolean;
|
|
20
|
+
sound?: LoadedSound;
|
|
21
|
+
error?: unknown;
|
|
22
|
+
};
|
|
16
23
|
export type ProgressCallback = (filename: string, loaded: number, total: number) => void;
|
|
17
24
|
export declare function canParseModelFile(file: File | string): boolean;
|
|
18
25
|
export declare function canParseTextureFile(file: File | string): boolean;
|
|
26
|
+
export declare function canParseSoundFile(file: File | string): boolean;
|
|
19
27
|
export declare function parseModelFromFile(file: File): Promise<ModelLoadResult>;
|
|
20
28
|
export declare function parseTextureFromFile(file: File): Promise<TextureLoadResult>;
|
|
29
|
+
export declare function parseSoundFromFile(file: File): Promise<SoundLoadResult>;
|
|
21
30
|
export declare function loadModel(filename: string, onProgress?: ProgressCallback): Promise<ModelLoadResult>;
|
|
22
31
|
export declare function loadTexture(filename: string): Promise<TextureLoadResult>;
|
|
32
|
+
export declare function loadSound(filename: string): Promise<SoundLoadResult>;
|
|
@@ -16,6 +16,21 @@ gltfLoader.setDRACOLoader(dracoLoader);
|
|
|
16
16
|
const fbxLoader = new FBXLoader();
|
|
17
17
|
const textureLoader = new TextureLoader();
|
|
18
18
|
const TEXTURE_FILE_EXTENSIONS = [".png", ".jpg", ".jpeg", ".webp", ".gif", ".bmp", ".svg"];
|
|
19
|
+
const SOUND_FILE_EXTENSIONS = [".mp3", ".wav", ".ogg", ".m4a"];
|
|
20
|
+
let decodeAudioContext = null;
|
|
21
|
+
function getAudioContext() {
|
|
22
|
+
if (typeof window === 'undefined') {
|
|
23
|
+
throw new Error('Audio loading is only supported in the browser');
|
|
24
|
+
}
|
|
25
|
+
if (!decodeAudioContext) {
|
|
26
|
+
const AudioCtx = window.AudioContext || window.webkitAudioContext;
|
|
27
|
+
if (!AudioCtx) {
|
|
28
|
+
throw new Error('Web Audio API is not available in this browser');
|
|
29
|
+
}
|
|
30
|
+
decodeAudioContext = new AudioCtx();
|
|
31
|
+
}
|
|
32
|
+
return decodeAudioContext;
|
|
33
|
+
}
|
|
19
34
|
function normalizeModelPath(name) {
|
|
20
35
|
return name.split(/[?#]/, 1)[0].toLowerCase();
|
|
21
36
|
}
|
|
@@ -38,6 +53,11 @@ export function canParseTextureFile(file) {
|
|
|
38
53
|
const normalizedName = normalizeModelPath(filename);
|
|
39
54
|
return TEXTURE_FILE_EXTENSIONS.some(extension => normalizedName.endsWith(extension));
|
|
40
55
|
}
|
|
56
|
+
export function canParseSoundFile(file) {
|
|
57
|
+
const filename = typeof file === "string" ? file : file.name;
|
|
58
|
+
const normalizedName = normalizeModelPath(filename);
|
|
59
|
+
return SOUND_FILE_EXTENSIONS.some(extension => normalizedName.endsWith(extension));
|
|
60
|
+
}
|
|
41
61
|
function parseModelBuffer(arrayBuffer, sourceName) {
|
|
42
62
|
const modelFileKind = getModelFileKind(sourceName);
|
|
43
63
|
if (modelFileKind === "gltf") {
|
|
@@ -89,6 +109,29 @@ export function parseTextureFromFile(file) {
|
|
|
89
109
|
});
|
|
90
110
|
});
|
|
91
111
|
}
|
|
112
|
+
export function parseSoundFromFile(file) {
|
|
113
|
+
return new Promise(resolve => {
|
|
114
|
+
const reader = new FileReader();
|
|
115
|
+
reader.onload = (event) => __awaiter(this, void 0, void 0, function* () {
|
|
116
|
+
var _a;
|
|
117
|
+
const arrayBuffer = (_a = event.target) === null || _a === void 0 ? void 0 : _a.result;
|
|
118
|
+
if (!arrayBuffer) {
|
|
119
|
+
resolve({ success: false, error: new Error('Failed to read file') });
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
const context = getAudioContext();
|
|
124
|
+
const sound = yield context.decodeAudioData(arrayBuffer.slice(0));
|
|
125
|
+
resolve({ success: true, sound });
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
resolve({ success: false, error });
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
reader.onerror = () => resolve({ success: false, error: reader.error });
|
|
132
|
+
reader.readAsArrayBuffer(file);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
92
135
|
export function loadModel(filename, onProgress) {
|
|
93
136
|
return __awaiter(this, void 0, void 0, function* () {
|
|
94
137
|
try {
|
|
@@ -141,3 +184,20 @@ export function loadTexture(filename) {
|
|
|
141
184
|
}
|
|
142
185
|
});
|
|
143
186
|
}
|
|
187
|
+
export function loadSound(filename) {
|
|
188
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
189
|
+
try {
|
|
190
|
+
if (!canParseSoundFile(filename)) {
|
|
191
|
+
return { success: false, error: new Error(`Unsupported file format: ${filename}`) };
|
|
192
|
+
}
|
|
193
|
+
const response = yield fetch(filename);
|
|
194
|
+
const arrayBuffer = yield response.arrayBuffer();
|
|
195
|
+
const context = getAudioContext();
|
|
196
|
+
const sound = yield context.decodeAudioData(arrayBuffer.slice(0));
|
|
197
|
+
return { success: true, sound };
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
return { success: false, error };
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
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
|
-
import { getComponent } from './components/ComponentRegistry';
|
|
4
3
|
import { base, colors, tree } from './styles';
|
|
5
|
-
import { useEditorContext } from './
|
|
4
|
+
import { useEditorContext } from './PrefabEditor';
|
|
6
5
|
import { Dropdown } from './Dropdown';
|
|
7
6
|
import { FileMenu, TreeContextMenu, TreeNodeMenu } from './EditorTreeMenus';
|
|
7
|
+
import { createEmptyNode } from './prefab';
|
|
8
8
|
import { usePrefabChildIds, usePrefabNode, usePrefabRootId, usePrefabStore, usePrefabStoreApi } from './prefabStore';
|
|
9
9
|
export default function EditorTree({ selectedId, setSelectedId, getPrefab, onReplacePrefab, onImportPrefab, onUndo, onRedo, canUndo, canRedo }) {
|
|
10
10
|
const { onFocusNode } = useEditorContext();
|
|
@@ -30,17 +30,7 @@ export default function EditorTree({ selectedId, setSelectedId, getPrefab, onRep
|
|
|
30
30
|
});
|
|
31
31
|
};
|
|
32
32
|
const handleAddChild = (parentId) => {
|
|
33
|
-
|
|
34
|
-
const newNode = {
|
|
35
|
-
id: crypto.randomUUID(),
|
|
36
|
-
name: "New Node",
|
|
37
|
-
components: {
|
|
38
|
-
transform: {
|
|
39
|
-
type: "Transform",
|
|
40
|
-
properties: Object.assign({}, (_a = getComponent('Transform')) === null || _a === void 0 ? void 0 : _a.defaultProperties)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
};
|
|
33
|
+
const newNode = createEmptyNode();
|
|
44
34
|
addChild(parentId, newNode);
|
|
45
35
|
setSelectedId(newNode.id);
|
|
46
36
|
};
|
|
@@ -142,37 +132,13 @@ const TreeNode = memo(function TreeNode({ nodeId, depth, rootId, visibleIds, col
|
|
|
142
132
|
marginRight: 4,
|
|
143
133
|
cursor: 'pointer',
|
|
144
134
|
visibility: hasChildren ? 'visible' : 'hidden'
|
|
145
|
-
}, onClick: (e) => hasChildren && onToggleCollapse(e, nodeId), children: isCollapsed ? '▶' : '▼' }), !isRoot && _jsx("span", { style: { marginRight: 4, opacity: 0.4 }, children: "\u22EE\u22EE" }), _jsx("span", { style: { overflow: 'hidden', textOverflow: 'ellipsis' }, children: (_a = node.name) !== null && _a !== void 0 ? _a : node.id }), node.locked && _jsx("span", { style: { marginLeft: 6, opacity: 0.6 }, children: "\uD83D\uDD12" })] }), !isRoot && (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Dropdown, { placement: "bottom-end", trigger: ({ ref, toggle }) => (_jsx("button", { ref: ref, title: "Node Actions", style: {
|
|
146
|
-
background: 'none',
|
|
147
|
-
border: 'none',
|
|
148
|
-
cursor: 'pointer',
|
|
149
|
-
padding: '0 4px',
|
|
150
|
-
fontSize: 14,
|
|
151
|
-
opacity: 0.7,
|
|
152
|
-
color: 'inherit',
|
|
153
|
-
}, onClick: (e) => {
|
|
135
|
+
}, onClick: (e) => hasChildren && onToggleCollapse(e, nodeId), children: isCollapsed ? '▶' : '▼' }), !isRoot && _jsx("span", { style: { marginRight: 4, opacity: 0.4 }, children: "\u22EE\u22EE" }), _jsx("span", { style: { overflow: 'hidden', textOverflow: 'ellipsis' }, children: (_a = node.name) !== null && _a !== void 0 ? _a : node.id }), node.locked && _jsx("span", { style: { marginLeft: 6, opacity: 0.6 }, children: "\uD83D\uDD12" })] }), !isRoot && (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Dropdown, { placement: "bottom-end", trigger: ({ ref, toggle }) => (_jsx("button", { ref: ref, title: "Node Actions", style: tree.iconButton, onClick: (e) => {
|
|
154
136
|
e.stopPropagation();
|
|
155
137
|
toggle();
|
|
156
|
-
}, children: "\u22EF" })), children: (close) => renderTreeNodeMenu(nodeId, false, close) }), _jsx("button", { style: {
|
|
157
|
-
background: 'none',
|
|
158
|
-
border: 'none',
|
|
159
|
-
cursor: 'pointer',
|
|
160
|
-
padding: '0 4px',
|
|
161
|
-
fontSize: 14,
|
|
162
|
-
opacity: node.disabled ? 0.5 : 0.7,
|
|
163
|
-
color: 'inherit',
|
|
164
|
-
}, onClick: (e) => {
|
|
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) => {
|
|
165
139
|
e.stopPropagation();
|
|
166
140
|
onToggleDisabled(nodeId);
|
|
167
|
-
}, title: node.disabled ? 'Enable' : 'Disable', children: node.disabled ? '◎' : '◉' })] })), isRoot && (_jsx(Dropdown, { placement: "bottom-end", trigger: ({ ref, toggle }) => (_jsx("button", { ref: ref, title: "Scene Actions", style: {
|
|
168
|
-
background: 'none',
|
|
169
|
-
border: 'none',
|
|
170
|
-
cursor: 'pointer',
|
|
171
|
-
padding: '0 4px',
|
|
172
|
-
fontSize: 14,
|
|
173
|
-
opacity: 0.7,
|
|
174
|
-
color: 'inherit',
|
|
175
|
-
}, onClick: (e) => {
|
|
141
|
+
}, title: node.disabled ? 'Enable' : 'Disable', children: node.disabled ? '◎' : '◉' })] })), isRoot && (_jsx(Dropdown, { placement: "bottom-end", trigger: ({ ref, toggle }) => (_jsx("button", { ref: ref, title: "Scene Actions", style: tree.iconButton, onClick: (e) => {
|
|
176
142
|
e.stopPropagation();
|
|
177
143
|
toggle();
|
|
178
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)))] }));
|
|
@@ -10,28 +10,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
11
|
import { useEffect, useRef, useState } from 'react';
|
|
12
12
|
import { createPortal } from 'react-dom';
|
|
13
|
+
import { createEmptyPrefab } from './prefab';
|
|
13
14
|
import { menu } from './styles';
|
|
14
|
-
import { useEditorContext } from './
|
|
15
|
-
import { getComponent } from './components/ComponentRegistry';
|
|
15
|
+
import { useEditorContext } from './PrefabEditor';
|
|
16
16
|
import { loadJson, saveJson } from './utils';
|
|
17
|
-
function createEmptyPrefab() {
|
|
18
|
-
var _a;
|
|
19
|
-
return {
|
|
20
|
-
id: crypto.randomUUID(),
|
|
21
|
-
name: 'New Prefab',
|
|
22
|
-
root: {
|
|
23
|
-
id: crypto.randomUUID(),
|
|
24
|
-
name: 'Root',
|
|
25
|
-
components: {
|
|
26
|
-
transform: {
|
|
27
|
-
type: 'Transform',
|
|
28
|
-
properties: Object.assign({}, (_a = getComponent('Transform')) === null || _a === void 0 ? void 0 : _a.defaultProperties)
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
children: []
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
17
|
function MenuPanel({ children, style, }) {
|
|
36
18
|
return (_jsx("div", { style: Object.assign(Object.assign(Object.assign({}, menu.container), { position: 'static' }), style), onClick: (e) => e.stopPropagation(), children: children }));
|
|
37
19
|
}
|
|
@@ -11,8 +11,10 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
13
13
|
import { useState } from 'react';
|
|
14
|
+
import { hasComponent } from "./types";
|
|
14
15
|
import EditorTree from './EditorTree';
|
|
15
|
-
import {
|
|
16
|
+
import { getAllComponentDefs } from './components/ComponentRegistry';
|
|
17
|
+
import { createComponentData } from './prefab';
|
|
16
18
|
import { base, colors, inspector, componentCard } from './styles';
|
|
17
19
|
import { usePrefabStore } from './prefabStore';
|
|
18
20
|
function EditorUI({ selectedId, setSelectedId, getPrefab, onReplacePrefab, onImportPrefab, basePath, onUndo, onRedo, canUndo, canRedo }) {
|
|
@@ -36,9 +38,9 @@ function EditorUI({ selectedId, setSelectedId, getPrefab, onReplacePrefab, onImp
|
|
|
36
38
|
}
|
|
37
39
|
function NodeInspector({ node, updateNode, deleteNode, basePath }) {
|
|
38
40
|
var _a;
|
|
39
|
-
const ALL_COMPONENTS =
|
|
41
|
+
const ALL_COMPONENTS = getAllComponentDefs();
|
|
40
42
|
const allKeys = Object.keys(ALL_COMPONENTS);
|
|
41
|
-
const available = allKeys.filter(k =>
|
|
43
|
+
const available = allKeys.filter(k => !hasComponent(node, k));
|
|
42
44
|
const [preferredAddType, setAddType] = useState(available[0] || "");
|
|
43
45
|
const addType = available.includes(preferredAddType) ? preferredAddType : (available[0] || "");
|
|
44
46
|
return _jsxs("div", { style: inspector.content, children: [_jsxs("div", { style: base.section, children: [_jsxs("div", { style: { display: "flex", marginBottom: 8, alignItems: 'center', gap: 8 }, children: [_jsx("div", { style: { fontSize: 10, color: colors.textDim, wordBreak: 'break-all', border: `1px solid ${colors.border}`, padding: '2px 6px', borderRadius: 3, flex: 1, fontFamily: 'monospace' }, children: node.id }), _jsx("button", { style: Object.assign(Object.assign({}, base.btn), base.btnDanger), title: "Delete Node", onClick: deleteNode, children: "\u274C" })] }), _jsx("input", { style: base.input, value: (_a = node.name) !== null && _a !== void 0 ? _a : "", placeholder: 'Node name', onChange: e => updateNode(n => (Object.assign(Object.assign({}, n), { name: e.target.value }))) })] }), _jsxs("div", { style: base.section, children: [_jsx("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }, children: _jsx("div", { style: base.label, children: "Components" }) }), node.components && Object.entries(node.components).map(([key, comp]) => {
|
|
@@ -48,7 +50,8 @@ function NodeInspector({ node, updateNode, deleteNode, basePath }) {
|
|
|
48
50
|
if (!def)
|
|
49
51
|
return _jsxs("div", { style: { color: colors.danger, fontSize: 11 }, children: ["Unknown: ", comp.type] }, key);
|
|
50
52
|
return (_jsxs("div", { style: componentCard.container, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 4 }, children: [_jsx("div", { style: { fontSize: 11, fontWeight: 500 }, children: key }), _jsx("button", { style: Object.assign(Object.assign({}, base.btn), { padding: '2px 6px' }), title: "Remove Component", onClick: () => updateNode(n => {
|
|
51
|
-
|
|
53
|
+
var _a;
|
|
54
|
+
const _b = (_a = n.components) !== null && _a !== void 0 ? _a : {}, _c = key, _ = _b[_c], rest = __rest(_b, [typeof _c === "symbol" ? _c : _c + ""]);
|
|
52
55
|
return Object.assign(Object.assign({}, n), { components: rest });
|
|
53
56
|
}), children: "\u2715" })] }), def.Editor && (_jsx(def.Editor, { component: comp, node: node, onUpdate: (newProps) => updateNode(n => (Object.assign(Object.assign({}, n), { components: Object.assign(Object.assign({}, n.components), { [key]: Object.assign(Object.assign({}, comp), { properties: Object.assign(Object.assign({}, comp.properties), newProps) }) }) }))), basePath: basePath }))] }, key));
|
|
54
57
|
})] }), available.length > 0 && (_jsx("div", { children: _jsxs("div", { style: base.row, children: [_jsx("select", { style: Object.assign(Object.assign({}, base.input), { flex: 1 }), value: addType, onChange: e => setAddType(e.target.value), children: available.map(k => _jsx("option", { value: k, children: k }, k)) }), _jsx("button", { style: base.btn, disabled: !addType, onClick: () => {
|
|
@@ -56,7 +59,7 @@ function NodeInspector({ node, updateNode, deleteNode, basePath }) {
|
|
|
56
59
|
return;
|
|
57
60
|
const def = ALL_COMPONENTS[addType];
|
|
58
61
|
if (def) {
|
|
59
|
-
updateNode(n => (Object.assign(Object.assign({}, n), { components: Object.assign(Object.assign({}, n.components), { [addType.toLowerCase()]:
|
|
62
|
+
updateNode(n => (Object.assign(Object.assign({}, n), { components: Object.assign(Object.assign({}, n.components), { [addType.toLowerCase()]: createComponentData(def.name) }) })));
|
|
60
63
|
}
|
|
61
64
|
}, title: "Add Component", children: "+" })] }) }))] });
|
|
62
65
|
}
|
|
@@ -13,6 +13,7 @@ export type InstanceData = {
|
|
|
13
13
|
id: string;
|
|
14
14
|
sourceId: string;
|
|
15
15
|
clickable?: boolean;
|
|
16
|
+
clickEventName?: string;
|
|
16
17
|
locked?: boolean;
|
|
17
18
|
position: [number, number, number];
|
|
18
19
|
rotation: [number, number, number];
|
|
@@ -35,6 +36,7 @@ export declare const GameInstance: React.ForwardRefExoticComponent<{
|
|
|
35
36
|
id: string;
|
|
36
37
|
sourceId?: string;
|
|
37
38
|
clickable?: boolean;
|
|
39
|
+
clickEventName?: string;
|
|
38
40
|
modelUrl: string;
|
|
39
41
|
locked?: boolean;
|
|
40
42
|
position: [number, number, number];
|