react-three-game 0.0.10 → 0.0.12
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/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/tools/assetviewer/page.d.ts +0 -3
- package/dist/tools/assetviewer/page.js +0 -23
- package/dist/tools/prefabeditor/EditorTree.js +1 -1
- package/dist/tools/prefabeditor/PrefabEditor.d.ts +2 -1
- package/dist/tools/prefabeditor/PrefabEditor.js +16 -4
- package/package.json +1 -1
- package/src/index.ts +0 -1
- package/src/tools/assetviewer/page.tsx +0 -48
- package/src/tools/prefabeditor/EditorTree.tsx +1 -0
- package/src/tools/prefabeditor/PrefabEditor.tsx +18 -4
package/dist/index.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ export { default as GameCanvas } from './shared/GameCanvas';
|
|
|
2
2
|
export { default as PrefabEditor } from './tools/prefabeditor/PrefabEditor';
|
|
3
3
|
export { default as PrefabRoot } from './tools/prefabeditor/PrefabRoot';
|
|
4
4
|
export { DragDropLoader } from './tools/dragdrop/DragDropLoader';
|
|
5
|
-
export {
|
|
5
|
+
export { TextureListViewer, ModelListViewer, SoundListViewer, SharedCanvas, } from './tools/assetviewer/page';
|
|
6
6
|
export type { Prefab, GameObject } from './tools/prefabeditor/types';
|
package/dist/index.js
CHANGED
|
@@ -3,4 +3,4 @@ export { default as GameCanvas } from './shared/GameCanvas';
|
|
|
3
3
|
export { default as PrefabEditor } from './tools/prefabeditor/PrefabEditor';
|
|
4
4
|
export { default as PrefabRoot } from './tools/prefabeditor/PrefabRoot';
|
|
5
5
|
export { DragDropLoader } from './tools/dragdrop/DragDropLoader';
|
|
6
|
-
export {
|
|
6
|
+
export { TextureListViewer, ModelListViewer, SoundListViewer, SharedCanvas, } from './tools/assetviewer/page';
|
|
@@ -49,29 +49,6 @@ function useInView() {
|
|
|
49
49
|
}, []);
|
|
50
50
|
return { ref, isInView };
|
|
51
51
|
}
|
|
52
|
-
export default function AssetViewerPage({ basePath = "" } = {}) {
|
|
53
|
-
const [textures, setTextures] = useState([]);
|
|
54
|
-
const [models, setModels] = useState([]);
|
|
55
|
-
const [sounds, setSounds] = useState([]);
|
|
56
|
-
const [loading, setLoading] = useState(true);
|
|
57
|
-
useEffect(() => {
|
|
58
|
-
const base = basePath ? `${basePath}/` : '';
|
|
59
|
-
Promise.all([
|
|
60
|
-
fetch(`/${base}textures/manifest.json`).then(r => r.json()),
|
|
61
|
-
fetch(`/${base}models/manifest.json`).then(r => r.json()),
|
|
62
|
-
fetch(`/${base}sound/manifest.json`).then(r => r.json()).catch(() => [])
|
|
63
|
-
]).then(([textureData, modelData, soundData]) => {
|
|
64
|
-
setTextures(textureData);
|
|
65
|
-
setModels(modelData);
|
|
66
|
-
setSounds(soundData);
|
|
67
|
-
setLoading(false);
|
|
68
|
-
});
|
|
69
|
-
}, [basePath]);
|
|
70
|
-
if (loading) {
|
|
71
|
-
return _jsx("div", { className: "p-4 text-gray-300", children: "Loading manifests..." });
|
|
72
|
-
}
|
|
73
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "p-2 text-gray-300 overflow-y-auto h-screen text-sm", children: [_jsx("h1", { className: "text-lg mb-2 font-bold", children: "Asset Viewer" }), _jsxs("h2", { className: "text-sm mt-4 mb-1 font-semibold", children: ["Textures (", textures.length, ")"] }), _jsx(TextureListViewer, { files: textures, basePath: basePath, onSelect: (file) => console.log('Selected texture:', file) }), _jsxs("h2", { className: "text-sm mt-4 mb-1 font-semibold", children: ["Models (", models.length, ")"] }), _jsx(ModelListViewer, { files: models, basePath: basePath, onSelect: (file) => console.log('Selected model:', file) }), sounds.length > 0 && (_jsxs(_Fragment, { children: [_jsxs("h2", { className: "text-sm mt-4 mb-1 font-semibold", children: ["Sounds (", sounds.length, ")"] }), _jsx(SoundListViewer, { files: sounds, basePath: basePath, onSelect: (file) => console.log('Selected sound:', file) })] }))] }), _jsx(SharedCanvas, {})] }));
|
|
74
|
-
}
|
|
75
52
|
function AssetListViewer({ files, selected, onSelect, renderCard }) {
|
|
76
53
|
const [currentPath, setCurrentPath] = useState('');
|
|
77
54
|
const [showPicker, setShowPicker] = useState(false);
|
|
@@ -136,7 +136,7 @@ export default function EditorTree({ prefabData, setPrefabData, selectedId, setS
|
|
|
136
136
|
const hasChildren = node.children && node.children.length > 0;
|
|
137
137
|
return (_jsxs("div", { className: "select-none", children: [_jsxs("div", { className: `flex items-center py-0.5 px-1 cursor-pointer border-b border-cyan-500/10 ${isSelected ? 'bg-cyan-500/30 hover:bg-cyan-500/40 border-cyan-400/30' : 'hover:bg-cyan-500/10'}`, style: { paddingLeft: `${depth * 8 + 4}px` }, onClick: (e) => { e.stopPropagation(); setSelectedId(node.id); }, onContextMenu: (e) => handleContextMenu(e, node.id), draggable: node.id !== prefabData.root.id, onDragStart: (e) => handleDragStart(e, node.id), onDragOver: (e) => handleDragOver(e, node.id), onDrop: (e) => handleDrop(e, node.id), children: [_jsx("span", { className: `mr-0.5 w-3 text-center text-cyan-400/50 hover:text-cyan-400 cursor-pointer text-[8px] ${hasChildren ? '' : 'invisible'}`, onClick: (e) => hasChildren && toggleCollapse(e, node.id), children: isCollapsed ? '▶' : '▼' }), _jsx("span", { className: "text-[10px] truncate font-mono text-cyan-300", children: node.id })] }), !isCollapsed && node.children && (_jsx("div", { children: node.children.map(child => renderNode(child, depth + 1)) }))] }, node.id));
|
|
138
138
|
};
|
|
139
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "bg-black/70 backdrop-blur-sm text-white border border-cyan-500/30 max-h-[85vh] overflow-y-auto flex flex-col", style: { width: isTreeCollapsed ? 'auto' : '14rem' }, onClick: closeContextMenu, children: [_jsxs("div", { className: "px-1.5 py-1 font-mono text-[10px] bg-cyan-500/10 border-b border-cyan-500/30 sticky top-0 uppercase tracking-wider text-cyan-400/80 cursor-pointer hover:bg-cyan-500/20 flex items-center justify-between", onClick: (e) => { e.stopPropagation(); setIsTreeCollapsed(!isTreeCollapsed); }, children: [_jsx("span", { children: "Prefab Graph" }), _jsx("span", { className: "text-[8px]", children: isTreeCollapsed ? '▶' : '◀' })] }), !isTreeCollapsed && (_jsx("div", { className: "flex-1 py-0.5", children: renderNode(prefabData.root) }))] }), contextMenu && (_jsxs("div", { className: "fixed bg-black/90 backdrop-blur-sm border border-cyan-500/40 z-50 min-w-[100px]", style: { top: contextMenu.y, left: contextMenu.x }, onClick: (e) => e.stopPropagation(), children: [_jsx("button", { className: "w-full text-left px-2 py-1 hover:bg-cyan-500/20 text-[10px] text-cyan-300 font-mono border-b border-cyan-500/20", onClick: () => handleAddChild(contextMenu.nodeId), children: "Add Child" }), contextMenu.nodeId !== prefabData.root.id && (_jsxs(_Fragment, { children: [_jsx("button", { className: "w-full text-left px-2 py-1 hover:bg-cyan-500/20 text-[10px] text-cyan-300 font-mono border-b border-cyan-500/20", onClick: () => handleDuplicate(contextMenu.nodeId), children: "Duplicate" }), _jsx("button", { className: "w-full text-left px-2 py-1 hover:bg-red-500/20 text-[10px] text-red-400 font-mono", onClick: () => handleDelete(contextMenu.nodeId), children: "Delete" })] }))] }))] }));
|
|
139
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "bg-black/70 backdrop-blur-sm text-white border border-cyan-500/30 max-h-[85vh] overflow-y-auto flex flex-col", style: { width: isTreeCollapsed ? 'auto' : '14rem' }, onClick: closeContextMenu, children: [_jsxs("div", { className: "px-1.5 py-1 font-mono text-[10px] bg-cyan-500/10 border-b border-cyan-500/30 sticky top-0 uppercase tracking-wider text-cyan-400/80 cursor-pointer hover:bg-cyan-500/20 flex items-center justify-between", onClick: (e) => { e.stopPropagation(); setIsTreeCollapsed(!isTreeCollapsed); }, children: [_jsx("span", { children: "Prefab Graph" }), _jsx("span", { className: "text-[8px]", children: isTreeCollapsed ? '▶' : '◀' })] }), !isTreeCollapsed && (_jsx("div", { className: "flex-1 py-0.5", children: renderNode(prefabData.root) }))] }), contextMenu && (_jsxs("div", { className: "fixed bg-black/90 backdrop-blur-sm border border-cyan-500/40 z-50 min-w-[100px]", style: { top: contextMenu.y, left: contextMenu.x }, onClick: (e) => e.stopPropagation(), onPointerLeave: closeContextMenu, children: [_jsx("button", { className: "w-full text-left px-2 py-1 hover:bg-cyan-500/20 text-[10px] text-cyan-300 font-mono border-b border-cyan-500/20", onClick: () => handleAddChild(contextMenu.nodeId), children: "Add Child" }), contextMenu.nodeId !== prefabData.root.id && (_jsxs(_Fragment, { children: [_jsx("button", { className: "w-full text-left px-2 py-1 hover:bg-cyan-500/20 text-[10px] text-cyan-300 font-mono border-b border-cyan-500/20", onClick: () => handleDuplicate(contextMenu.nodeId), children: "Duplicate" }), _jsx("button", { className: "w-full text-left px-2 py-1 hover:bg-red-500/20 text-[10px] text-red-400 font-mono", onClick: () => handleDelete(contextMenu.nodeId), children: "Delete" })] }))] }))] }));
|
|
140
140
|
}
|
|
141
141
|
// --- Helpers ---
|
|
142
142
|
function findNode(root, id) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Prefab } from "./types";
|
|
2
|
-
declare const PrefabEditor: ({ basePath, initialPrefab, children }: {
|
|
2
|
+
declare const PrefabEditor: ({ basePath, initialPrefab, onPrefabChange, children }: {
|
|
3
3
|
basePath?: string;
|
|
4
4
|
initialPrefab?: Prefab;
|
|
5
|
+
onPrefabChange?: (prefab: Prefab) => void;
|
|
5
6
|
children?: React.ReactNode;
|
|
6
7
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
7
8
|
export default PrefabEditor;
|
|
@@ -10,11 +10,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
12
12
|
import GameCanvas from "../../shared/GameCanvas";
|
|
13
|
-
import { useState, useRef, } from "react";
|
|
13
|
+
import { useState, useRef, useEffect } from "react";
|
|
14
14
|
import PrefabRoot from "./PrefabRoot";
|
|
15
15
|
import { Physics } from "@react-three/rapier";
|
|
16
16
|
import EditorUI from "./EditorUI";
|
|
17
|
-
const PrefabEditor = ({ basePath, initialPrefab, children }) => {
|
|
17
|
+
const PrefabEditor = ({ basePath, initialPrefab, onPrefabChange, children }) => {
|
|
18
18
|
const [editMode, setEditMode] = useState(true);
|
|
19
19
|
const [loadedPrefab, setLoadedPrefab] = useState(initialPrefab !== null && initialPrefab !== void 0 ? initialPrefab : {
|
|
20
20
|
"id": "prefab-default",
|
|
@@ -38,13 +38,25 @@ const PrefabEditor = ({ basePath, initialPrefab, children }) => {
|
|
|
38
38
|
const [selectedId, setSelectedId] = useState(null);
|
|
39
39
|
const [transformMode, setTransformMode] = useState("translate");
|
|
40
40
|
const prefabRef = useRef(null);
|
|
41
|
+
// Sync internal state with external initialPrefab prop
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (initialPrefab) {
|
|
44
|
+
setLoadedPrefab(initialPrefab);
|
|
45
|
+
}
|
|
46
|
+
}, [initialPrefab]);
|
|
47
|
+
// Wrapper to update prefab and notify parent
|
|
48
|
+
const updatePrefab = (newPrefab) => {
|
|
49
|
+
setLoadedPrefab(newPrefab);
|
|
50
|
+
const resolved = typeof newPrefab === 'function' ? newPrefab(loadedPrefab) : newPrefab;
|
|
51
|
+
onPrefabChange === null || onPrefabChange === void 0 ? void 0 : onPrefabChange(resolved);
|
|
52
|
+
};
|
|
41
53
|
return _jsxs(_Fragment, { children: [_jsx(GameCanvas, { children: _jsxs(Physics, { paused: editMode, children: [_jsx("ambientLight", { intensity: 1.5 }), _jsx("gridHelper", { args: [10, 10], position: [0, -1, 0] }), _jsx(PrefabRoot, { data: loadedPrefab, ref: prefabRef,
|
|
42
54
|
// props for edit mode
|
|
43
|
-
editMode: editMode, onPrefabChange:
|
|
55
|
+
editMode: editMode, onPrefabChange: updatePrefab, selectedId: selectedId, onSelect: setSelectedId, transformMode: transformMode, setTransformMode: setTransformMode, basePath: basePath }), children] }) }), _jsxs("div", { style: { position: "absolute", top: "0.5rem", left: "50%", transform: "translateX(-50%)" }, className: "bg-black/70 backdrop-blur-sm border border-cyan-500/30 px-2 py-1 flex items-center gap-1", children: [_jsx("button", { className: "px-1 py-0.5 text-[10px] font-mono text-cyan-300 hover:bg-cyan-500/20 border border-cyan-500/30", onClick: () => setEditMode(!editMode), children: editMode ? "▶" : "⏸" }), _jsx("span", { className: "text-cyan-500/30 text-[10px]", children: "|" }), _jsx("button", { className: "px-1 py-0.5 text-[10px] font-mono text-cyan-300 hover:bg-cyan-500/20 border border-cyan-500/30", onClick: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
44
56
|
const prefab = yield loadJson();
|
|
45
57
|
if (prefab)
|
|
46
58
|
setLoadedPrefab(prefab);
|
|
47
|
-
}), children: "\uD83D\uDCE5" }), _jsx("button", { className: "px-1 py-0.5 text-[10px] font-mono text-cyan-300 hover:bg-cyan-500/20 border border-cyan-500/30", onClick: () => saveJson(loadedPrefab, "prefab"), children: "\uD83D\uDCBE" })] }), editMode && _jsx(EditorUI, { prefabData: loadedPrefab, setPrefabData:
|
|
59
|
+
}), children: "\uD83D\uDCE5" }), _jsx("button", { className: "px-1 py-0.5 text-[10px] font-mono text-cyan-300 hover:bg-cyan-500/20 border border-cyan-500/30", onClick: () => saveJson(loadedPrefab, "prefab"), children: "\uD83D\uDCBE" })] }), editMode && _jsx(EditorUI, { prefabData: loadedPrefab, setPrefabData: updatePrefab, selectedId: selectedId, setSelectedId: setSelectedId, transformMode: transformMode, setTransformMode: setTransformMode, basePath: basePath })] });
|
|
48
60
|
};
|
|
49
61
|
const saveJson = (data, filename) => {
|
|
50
62
|
const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(data, null, 2));
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -4,7 +4,6 @@ export { default as PrefabEditor } from './tools/prefabeditor/PrefabEditor';
|
|
|
4
4
|
export { default as PrefabRoot } from './tools/prefabeditor/PrefabRoot';
|
|
5
5
|
export { DragDropLoader } from './tools/dragdrop/DragDropLoader';
|
|
6
6
|
export {
|
|
7
|
-
default as AssetViewerPage,
|
|
8
7
|
TextureListViewer,
|
|
9
8
|
ModelListViewer,
|
|
10
9
|
SoundListViewer,
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import { Canvas, useLoader } from "@react-three/fiber";
|
|
4
4
|
import { OrbitControls, useGLTF, useFBX, Stage, View, PerspectiveCamera } from "@react-three/drei";
|
|
5
5
|
import { Suspense, useEffect, useState, useRef } from "react";
|
|
6
|
-
import * as React from "react";
|
|
7
6
|
import { TextureLoader } from "three";
|
|
8
7
|
|
|
9
8
|
// view models and textures in manifest, onselect callback
|
|
@@ -74,53 +73,6 @@ function useInView() {
|
|
|
74
73
|
return { ref, isInView };
|
|
75
74
|
}
|
|
76
75
|
|
|
77
|
-
export default function AssetViewerPage({ basePath = "" }: { basePath?: string } = {}) {
|
|
78
|
-
const [textures, setTextures] = useState<string[]>([]);
|
|
79
|
-
const [models, setModels] = useState<string[]>([]);
|
|
80
|
-
const [sounds, setSounds] = useState<string[]>([]);
|
|
81
|
-
const [loading, setLoading] = useState(true);
|
|
82
|
-
|
|
83
|
-
useEffect(() => {
|
|
84
|
-
const base = basePath ? `${basePath}/` : '';
|
|
85
|
-
Promise.all([
|
|
86
|
-
fetch(`/${base}textures/manifest.json`).then(r => r.json()),
|
|
87
|
-
fetch(`/${base}models/manifest.json`).then(r => r.json()),
|
|
88
|
-
fetch(`/${base}sound/manifest.json`).then(r => r.json()).catch(() => [])
|
|
89
|
-
]).then(([textureData, modelData, soundData]) => {
|
|
90
|
-
setTextures(textureData);
|
|
91
|
-
setModels(modelData);
|
|
92
|
-
setSounds(soundData);
|
|
93
|
-
setLoading(false);
|
|
94
|
-
});
|
|
95
|
-
}, [basePath]);
|
|
96
|
-
|
|
97
|
-
if (loading) {
|
|
98
|
-
return <div className="p-4 text-gray-300">Loading manifests...</div>;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return (
|
|
102
|
-
<>
|
|
103
|
-
<div className="p-2 text-gray-300 overflow-y-auto h-screen text-sm">
|
|
104
|
-
<h1 className="text-lg mb-2 font-bold">Asset Viewer</h1>
|
|
105
|
-
|
|
106
|
-
<h2 className="text-sm mt-4 mb-1 font-semibold">Textures ({textures.length})</h2>
|
|
107
|
-
<TextureListViewer files={textures} basePath={basePath} onSelect={(file) => console.log('Selected texture:', file)} />
|
|
108
|
-
|
|
109
|
-
<h2 className="text-sm mt-4 mb-1 font-semibold">Models ({models.length})</h2>
|
|
110
|
-
<ModelListViewer files={models} basePath={basePath} onSelect={(file) => console.log('Selected model:', file)} />
|
|
111
|
-
|
|
112
|
-
{sounds.length > 0 && (
|
|
113
|
-
<>
|
|
114
|
-
<h2 className="text-sm mt-4 mb-1 font-semibold">Sounds ({sounds.length})</h2>
|
|
115
|
-
<SoundListViewer files={sounds} basePath={basePath} onSelect={(file) => console.log('Selected sound:', file)} />
|
|
116
|
-
</>
|
|
117
|
-
)}
|
|
118
|
-
</div>
|
|
119
|
-
<SharedCanvas />
|
|
120
|
-
</>
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
76
|
interface AssetListViewerProps {
|
|
125
77
|
files: string[];
|
|
126
78
|
selected?: string;
|
|
@@ -206,6 +206,7 @@ export default function EditorTree({ prefabData, setPrefabData, selectedId, setS
|
|
|
206
206
|
className="fixed bg-black/90 backdrop-blur-sm border border-cyan-500/40 z-50 min-w-[100px]"
|
|
207
207
|
style={{ top: contextMenu.y, left: contextMenu.x }}
|
|
208
208
|
onClick={(e) => e.stopPropagation()}
|
|
209
|
+
onPointerLeave={closeContextMenu}
|
|
209
210
|
>
|
|
210
211
|
<button
|
|
211
212
|
className="w-full text-left px-2 py-1 hover:bg-cyan-500/20 text-[10px] text-cyan-300 font-mono border-b border-cyan-500/20"
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import GameCanvas from "../../shared/GameCanvas";
|
|
4
|
-
import { useState, useRef, } from "react";
|
|
4
|
+
import { useState, useRef, useEffect } from "react";
|
|
5
5
|
import { Group, } from "three";
|
|
6
6
|
import { Prefab, } from "./types";
|
|
7
7
|
import PrefabRoot from "./PrefabRoot";
|
|
8
8
|
import { Physics } from "@react-three/rapier";
|
|
9
9
|
import EditorUI from "./EditorUI";
|
|
10
10
|
|
|
11
|
-
const PrefabEditor = ({ basePath, initialPrefab, children }: { basePath?: string, initialPrefab?: Prefab, children?: React.ReactNode }) => {
|
|
11
|
+
const PrefabEditor = ({ basePath, initialPrefab, onPrefabChange, children }: { basePath?: string, initialPrefab?: Prefab, onPrefabChange?: (prefab: Prefab) => void, children?: React.ReactNode }) => {
|
|
12
12
|
const [editMode, setEditMode] = useState(true);
|
|
13
13
|
const [loadedPrefab, setLoadedPrefab] = useState<Prefab>(initialPrefab ?? {
|
|
14
14
|
"id": "prefab-default",
|
|
@@ -33,6 +33,20 @@ const PrefabEditor = ({ basePath, initialPrefab, children }: { basePath?: string
|
|
|
33
33
|
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | "scale">("translate");
|
|
34
34
|
const prefabRef = useRef<Group>(null);
|
|
35
35
|
|
|
36
|
+
// Sync internal state with external initialPrefab prop
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (initialPrefab) {
|
|
39
|
+
setLoadedPrefab(initialPrefab);
|
|
40
|
+
}
|
|
41
|
+
}, [initialPrefab]);
|
|
42
|
+
|
|
43
|
+
// Wrapper to update prefab and notify parent
|
|
44
|
+
const updatePrefab = (newPrefab: Prefab | ((prev: Prefab) => Prefab)) => {
|
|
45
|
+
setLoadedPrefab(newPrefab);
|
|
46
|
+
const resolved = typeof newPrefab === 'function' ? newPrefab(loadedPrefab) : newPrefab;
|
|
47
|
+
onPrefabChange?.(resolved);
|
|
48
|
+
};
|
|
49
|
+
|
|
36
50
|
return <>
|
|
37
51
|
<GameCanvas>
|
|
38
52
|
<Physics paused={editMode}>
|
|
@@ -44,7 +58,7 @@ const PrefabEditor = ({ basePath, initialPrefab, children }: { basePath?: string
|
|
|
44
58
|
|
|
45
59
|
// props for edit mode
|
|
46
60
|
editMode={editMode}
|
|
47
|
-
onPrefabChange={
|
|
61
|
+
onPrefabChange={updatePrefab}
|
|
48
62
|
selectedId={selectedId}
|
|
49
63
|
onSelect={setSelectedId}
|
|
50
64
|
transformMode={transformMode}
|
|
@@ -81,7 +95,7 @@ const PrefabEditor = ({ basePath, initialPrefab, children }: { basePath?: string
|
|
|
81
95
|
</div>
|
|
82
96
|
{editMode && <EditorUI
|
|
83
97
|
prefabData={loadedPrefab}
|
|
84
|
-
setPrefabData={
|
|
98
|
+
setPrefabData={updatePrefab}
|
|
85
99
|
selectedId={selectedId}
|
|
86
100
|
setSelectedId={setSelectedId}
|
|
87
101
|
transformMode={transformMode}
|