react-three-game 0.0.65 → 0.0.66
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/LICENSE +2 -660
- package/README.md +164 -91
- package/dist/index.d.ts +4 -2
- package/dist/index.js +2 -1
- package/dist/tools/assetviewer/page.js +4 -4
- package/dist/tools/prefabeditor/EditorContext.d.ts +2 -2
- package/dist/tools/prefabeditor/EditorTree.js +17 -3
- package/dist/tools/prefabeditor/EditorTreeMenus.d.ts +3 -1
- package/dist/tools/prefabeditor/EditorTreeMenus.js +7 -8
- package/dist/tools/prefabeditor/EditorUI.js +3 -7
- package/dist/tools/prefabeditor/GameEvents.d.ts +14 -1
- package/dist/tools/prefabeditor/GameEvents.js +2 -1
- package/dist/tools/prefabeditor/InstanceProvider.d.ts +4 -0
- package/dist/tools/prefabeditor/InstanceProvider.js +44 -12
- package/dist/tools/prefabeditor/PrefabEditor.js +77 -16
- package/dist/tools/prefabeditor/PrefabRoot.d.ts +3 -1
- package/dist/tools/prefabeditor/PrefabRoot.js +36 -119
- package/dist/tools/prefabeditor/components/CameraComponent.js +1 -1
- package/dist/tools/prefabeditor/components/ClickComponent.d.ts +3 -0
- package/dist/tools/prefabeditor/components/ClickComponent.js +45 -0
- package/dist/tools/prefabeditor/components/ComponentRegistry.js +0 -3
- package/dist/tools/prefabeditor/components/DirectionalLightComponent.js +3 -3
- package/dist/tools/prefabeditor/components/Input.d.ts +5 -2
- package/dist/tools/prefabeditor/components/Input.js +71 -38
- package/dist/tools/prefabeditor/components/MaterialComponent.js +3 -3
- package/dist/tools/prefabeditor/components/ModelComponent.js +2 -2
- package/dist/tools/prefabeditor/components/PhysicsComponent.d.ts +2 -0
- package/dist/tools/prefabeditor/components/PhysicsComponent.js +77 -10
- package/dist/tools/prefabeditor/components/index.js +2 -0
- package/dist/tools/prefabeditor/types.d.ts +1 -0
- package/dist/tools/prefabeditor/utils.d.ts +7 -1
- package/dist/tools/prefabeditor/utils.js +34 -1
- package/package.json +1 -1
|
@@ -129,9 +129,23 @@ function emitCollisionExit(sourceId, payload) {
|
|
|
129
129
|
targetRigidBody: payload.other.rigidBody,
|
|
130
130
|
});
|
|
131
131
|
}
|
|
132
|
+
function emitClick(sourceId, instanceId, event) {
|
|
133
|
+
gameEvents.emit('click', {
|
|
134
|
+
sourceEntityId: sourceId,
|
|
135
|
+
instanceEntityId: instanceId && instanceId !== sourceId ? instanceId : undefined,
|
|
136
|
+
point: [event.point.x, event.point.y, event.point.z],
|
|
137
|
+
button: event.button,
|
|
138
|
+
altKey: event.nativeEvent.altKey,
|
|
139
|
+
ctrlKey: event.nativeEvent.ctrlKey,
|
|
140
|
+
metaKey: event.nativeEvent.metaKey,
|
|
141
|
+
shiftKey: event.nativeEvent.shiftKey,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
132
144
|
function instanceEquals(a, b) {
|
|
133
145
|
return a.id === b.id &&
|
|
134
146
|
a.sourceId === b.sourceId &&
|
|
147
|
+
a.clickable === b.clickable &&
|
|
148
|
+
a.locked === b.locked &&
|
|
135
149
|
a.meshPath === b.meshPath &&
|
|
136
150
|
arrayEquals(a.position, b.position) &&
|
|
137
151
|
arrayEquals(a.rotation, b.rotation) &&
|
|
@@ -308,22 +322,30 @@ function InstancedRigidGroup({ group, modelKey, partCount, flatMeshes, onSelect,
|
|
|
308
322
|
}, [group.instances]);
|
|
309
323
|
// Handle click on instanced mesh in edit mode
|
|
310
324
|
const handleClick = (e) => {
|
|
311
|
-
if (!editMode || !onSelect)
|
|
312
|
-
return;
|
|
313
|
-
e.stopPropagation();
|
|
314
|
-
// Get the instance index from the intersection
|
|
315
325
|
const instanceId = e.instanceId;
|
|
316
|
-
|
|
317
|
-
|
|
326
|
+
const instance = instanceId !== undefined ? group.instances[instanceId] : undefined;
|
|
327
|
+
if (!instance)
|
|
328
|
+
return;
|
|
329
|
+
if (editMode) {
|
|
330
|
+
if (!onSelect || instance.locked)
|
|
331
|
+
return;
|
|
332
|
+
e.stopPropagation();
|
|
333
|
+
onSelect(instance.sourceId);
|
|
334
|
+
return;
|
|
318
335
|
}
|
|
336
|
+
if (!instance.clickable)
|
|
337
|
+
return;
|
|
338
|
+
e.stopPropagation();
|
|
339
|
+
emitClick(instance.sourceId, instance.id, e);
|
|
319
340
|
};
|
|
341
|
+
const shouldHandleClick = editMode || group.instances.some(inst => inst.clickable);
|
|
320
342
|
// Add key to force remount when instance count changes significantly (helps with cleanup)
|
|
321
343
|
const rigidBodyKey = `rb_${modelKey}_${group.instances.map(inst => `${inst.id}:${getPhysicsSignature(inst.physics)}`).join('|')}`;
|
|
322
344
|
return (_jsx(InstancedRigidBodies, { ref: rigidBodiesRef, instances: instances, children: Array.from({ length: partCount }).map((_, i) => {
|
|
323
345
|
const mesh = flatMeshes[`${modelKey}__${i}`];
|
|
324
346
|
if (!mesh)
|
|
325
347
|
return null;
|
|
326
|
-
return (_jsx("instancedMesh", { ref: el => { meshRefs.current[i] = el; }, args: [mesh.geometry, mesh.material, group.instances.length], castShadow: true, receiveShadow: true, frustumCulled: false, onClick:
|
|
348
|
+
return (_jsx("instancedMesh", { ref: el => { meshRefs.current[i] = el; }, args: [mesh.geometry, mesh.material, group.instances.length], castShadow: true, receiveShadow: true, frustumCulled: false, onClick: shouldHandleClick ? handleClick : undefined }, i));
|
|
327
349
|
}) }, rigidBodyKey));
|
|
328
350
|
}
|
|
329
351
|
// Render non-physics instances using Merged (instancing without rigid bodies)
|
|
@@ -336,7 +358,10 @@ function NonPhysicsInstancedGroup({ modelKey, group, partCount, instancesMap, on
|
|
|
336
358
|
function InstanceGroupItem({ instance, InstanceComponents, onSelect, registerRef, selectedId, editMode }) {
|
|
337
359
|
const clickValid = useRef(false);
|
|
338
360
|
const groupRef = useRef(null);
|
|
361
|
+
const isLocked = Boolean(instance.locked);
|
|
339
362
|
const isSelected = selectedId === instance.id || selectedId === instance.sourceId;
|
|
363
|
+
const canSelect = editMode && !isLocked;
|
|
364
|
+
const canClick = !editMode && Boolean(instance.clickable);
|
|
340
365
|
// Use BoxHelper when object is selected in edit mode
|
|
341
366
|
useHelper(editMode && isSelected ? groupRef : null, BoxHelper, 'cyan');
|
|
342
367
|
useEffect(() => {
|
|
@@ -345,13 +370,18 @@ function InstanceGroupItem({ instance, InstanceComponents, onSelect, registerRef
|
|
|
345
370
|
registerRef === null || registerRef === void 0 ? void 0 : registerRef(instance.id, groupRef.current);
|
|
346
371
|
return () => registerRef === null || registerRef === void 0 ? void 0 : registerRef(instance.id, null);
|
|
347
372
|
}, [editMode, instance.id, registerRef]);
|
|
348
|
-
return (_jsx("group", { ref: groupRef, position: instance.position, rotation: instance.rotation, scale: instance.scale, onPointerDown: (e) => { e.stopPropagation(); clickValid.current = true; }, onPointerMove: () => { clickValid.current = false; }, onPointerUp: (e) => {
|
|
373
|
+
return (_jsx("group", { ref: groupRef, position: instance.position, rotation: instance.rotation, scale: instance.scale, onPointerDown: canSelect || canClick ? (e) => { e.stopPropagation(); clickValid.current = true; } : undefined, onPointerMove: canSelect || canClick ? () => { clickValid.current = false; } : undefined, onPointerUp: canSelect || canClick ? (e) => {
|
|
349
374
|
if (clickValid.current) {
|
|
350
375
|
e.stopPropagation();
|
|
351
|
-
|
|
376
|
+
if (editMode) {
|
|
377
|
+
onSelect === null || onSelect === void 0 ? void 0 : onSelect(instance.sourceId);
|
|
378
|
+
}
|
|
379
|
+
else if (instance.clickable) {
|
|
380
|
+
emitClick(instance.sourceId, instance.id, e);
|
|
381
|
+
}
|
|
352
382
|
}
|
|
353
383
|
clickValid.current = false;
|
|
354
|
-
}, children: InstanceComponents.map((Instance, i) => _jsx(Instance, {}, i)) }));
|
|
384
|
+
} : undefined, children: InstanceComponents.map((Instance, i) => _jsx(Instance, {}, i)) }));
|
|
355
385
|
}
|
|
356
386
|
// Hook to check if an instance exists
|
|
357
387
|
export function useInstanceCheck(id) {
|
|
@@ -360,19 +390,21 @@ export function useInstanceCheck(id) {
|
|
|
360
390
|
return (_a = ctx === null || ctx === void 0 ? void 0 : ctx.hasInstance(id)) !== null && _a !== void 0 ? _a : false;
|
|
361
391
|
}
|
|
362
392
|
// GameInstance component: registers an instance for batch rendering (renders nothing itself)
|
|
363
|
-
export const GameInstance = React.forwardRef(({ id, sourceId, modelUrl, position, rotation, scale, physics = undefined, }, ref) => {
|
|
393
|
+
export const GameInstance = React.forwardRef(({ id, sourceId, clickable = false, modelUrl, locked = false, position, rotation, scale, physics = undefined, }, ref) => {
|
|
364
394
|
const ctx = useContext(GameInstanceContext);
|
|
365
395
|
const addInstance = ctx === null || ctx === void 0 ? void 0 : ctx.addInstance;
|
|
366
396
|
const removeInstance = ctx === null || ctx === void 0 ? void 0 : ctx.removeInstance;
|
|
367
397
|
const instance = useMemo(() => ({
|
|
368
398
|
id,
|
|
369
399
|
sourceId: sourceId !== null && sourceId !== void 0 ? sourceId : id,
|
|
400
|
+
clickable,
|
|
401
|
+
locked,
|
|
370
402
|
meshPath: modelUrl,
|
|
371
403
|
position,
|
|
372
404
|
rotation,
|
|
373
405
|
scale,
|
|
374
406
|
physics,
|
|
375
|
-
}), [id, sourceId, modelUrl, JSON.stringify(position), JSON.stringify(rotation), JSON.stringify(scale), getPhysicsSignature(physics)]);
|
|
407
|
+
}), [id, sourceId, clickable, locked, modelUrl, JSON.stringify(position), JSON.stringify(rotation), JSON.stringify(scale), getPhysicsSignature(physics)]);
|
|
376
408
|
useEffect(() => {
|
|
377
409
|
if (!addInstance || !removeInstance)
|
|
378
410
|
return;
|
|
@@ -8,6 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { MapControls, TransformControls } from "@react-three/drei";
|
|
11
12
|
import GameCanvas from "../../shared/GameCanvas";
|
|
12
13
|
import { useState, useRef, useEffect, forwardRef, useImperativeHandle } from "react";
|
|
13
14
|
import PrefabRoot from "./PrefabRoot";
|
|
@@ -15,7 +16,7 @@ import { Physics } from "@react-three/rapier";
|
|
|
15
16
|
import EditorUI from "./EditorUI";
|
|
16
17
|
import { base, toolbar } from "./styles";
|
|
17
18
|
import { EditorContext } from "./EditorContext";
|
|
18
|
-
import { createImageNode, createModelNode, exportGLB as exportSceneGLB, exportGLBData, insertNode } from "./utils";
|
|
19
|
+
import { computeParentWorldMatrix, createImageNode, createModelNode, decompose, exportGLB as exportSceneGLB, exportGLBData, findNode, focusCameraOnObject, insertNode, updateNode } from "./utils";
|
|
19
20
|
import { loadFiles } from "../dragdrop";
|
|
20
21
|
const DEFAULT_PREFAB = {
|
|
21
22
|
id: "prefab-default",
|
|
@@ -40,29 +41,57 @@ const PrefabEditor = forwardRef(({ basePath, initialPrefab, physics = true, onPr
|
|
|
40
41
|
const [rotationSnap, setRotationSnap] = useState(Math.PI / 4);
|
|
41
42
|
const [history, setHistory] = useState([loadedPrefab]);
|
|
42
43
|
const [historyIndex, setHistoryIndex] = useState(0);
|
|
44
|
+
const [selectedObject, setSelectedObject] = useState(null);
|
|
43
45
|
const throttleRef = useRef(null);
|
|
44
46
|
const lastDataRef = useRef(JSON.stringify(loadedPrefab));
|
|
45
47
|
const prefabRootRef = useRef(null);
|
|
46
48
|
const canvasRef = useRef(null);
|
|
49
|
+
const controlsRef = useRef(null);
|
|
47
50
|
const onPrefabChangeRef = useRef(onPrefabChange);
|
|
48
51
|
const pendingPrefabChangeRef = useRef(null);
|
|
49
52
|
const [injectedModels, setInjectedModels] = useState({});
|
|
50
53
|
const [injectedTextures, setInjectedTextures] = useState({});
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
onPrefabChangeRef.current = onPrefabChange;
|
|
55
|
+
const setSelection = (nodeId) => {
|
|
56
|
+
var _a, _b;
|
|
57
|
+
const nextNode = nodeId ? findNode(loadedPrefab.root, nodeId) : null;
|
|
58
|
+
if (nextNode === null || nextNode === void 0 ? void 0 : nextNode.locked) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
setSelectedId(nodeId);
|
|
62
|
+
setSelectedObject(nodeId ? (_b = (_a = prefabRootRef.current) === null || _a === void 0 ? void 0 : _a.getObject(nodeId)) !== null && _b !== void 0 ? _b : null : null);
|
|
63
|
+
};
|
|
64
|
+
const toggleEditMode = () => {
|
|
65
|
+
setEditMode(prev => {
|
|
66
|
+
const next = !prev;
|
|
67
|
+
if (!next) {
|
|
68
|
+
setSelectedId(null);
|
|
69
|
+
setSelectedObject(null);
|
|
70
|
+
}
|
|
71
|
+
return next;
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
const setSelectedIdState = (value) => {
|
|
75
|
+
setSelection(typeof value === 'function' ? value(selectedId) : value);
|
|
76
|
+
};
|
|
54
77
|
const replacePrefab = (prefab, options) => {
|
|
55
78
|
if (throttleRef.current)
|
|
56
79
|
clearTimeout(throttleRef.current);
|
|
57
80
|
lastDataRef.current = JSON.stringify(prefab);
|
|
58
81
|
pendingPrefabChangeRef.current = (options === null || options === void 0 ? void 0 : options.notifyChange) === false ? null : prefab;
|
|
59
|
-
|
|
82
|
+
setSelection(null);
|
|
60
83
|
setInjectedModels({});
|
|
61
84
|
setInjectedTextures({});
|
|
62
85
|
setHistory([prefab]);
|
|
63
86
|
setHistoryIndex(0);
|
|
64
87
|
setLoadedPrefab(prefab);
|
|
65
88
|
};
|
|
89
|
+
const setPrefab = (prefab) => {
|
|
90
|
+
if (selectedId && !findNode(prefab.root, selectedId)) {
|
|
91
|
+
setSelection(null);
|
|
92
|
+
}
|
|
93
|
+
updatePrefab(prefab);
|
|
94
|
+
};
|
|
66
95
|
useEffect(() => {
|
|
67
96
|
if (initialPrefab)
|
|
68
97
|
replacePrefab(initialPrefab, { notifyChange: false });
|
|
@@ -90,7 +119,7 @@ const PrefabEditor = forwardRef(({ basePath, initialPrefab, physics = true, onPr
|
|
|
90
119
|
return Object.assign(Object.assign({}, prev), { root: insertNode(prev.root, node, options === null || options === void 0 ? void 0 : options.parentId) });
|
|
91
120
|
});
|
|
92
121
|
if ((options === null || options === void 0 ? void 0 : options.select) !== false) {
|
|
93
|
-
|
|
122
|
+
setSelection(node.id);
|
|
94
123
|
}
|
|
95
124
|
return node;
|
|
96
125
|
};
|
|
@@ -115,6 +144,8 @@ const PrefabEditor = forwardRef(({ basePath, initialPrefab, physics = true, onPr
|
|
|
115
144
|
const undo = () => historyIndex > 0 && applyHistory(historyIndex - 1);
|
|
116
145
|
const redo = () => historyIndex < history.length - 1 && applyHistory(historyIndex + 1);
|
|
117
146
|
useEffect(() => {
|
|
147
|
+
if (!editMode)
|
|
148
|
+
return;
|
|
118
149
|
const handleKeyDown = (e) => {
|
|
119
150
|
if (!(e.ctrlKey || e.metaKey))
|
|
120
151
|
return;
|
|
@@ -129,7 +160,7 @@ const PrefabEditor = forwardRef(({ basePath, initialPrefab, physics = true, onPr
|
|
|
129
160
|
};
|
|
130
161
|
window.addEventListener('keydown', handleKeyDown);
|
|
131
162
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
132
|
-
}, [historyIndex, history]);
|
|
163
|
+
}, [editMode, historyIndex, history]);
|
|
133
164
|
useEffect(() => {
|
|
134
165
|
const currentStr = JSON.stringify(loadedPrefab);
|
|
135
166
|
if (currentStr === lastDataRef.current)
|
|
@@ -165,7 +196,7 @@ const PrefabEditor = forwardRef(({ basePath, initialPrefab, physics = true, onPr
|
|
|
165
196
|
const clearSelection = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
166
197
|
if (!selectedId)
|
|
167
198
|
return;
|
|
168
|
-
|
|
199
|
+
setSelection(null);
|
|
169
200
|
yield new Promise(resolve => {
|
|
170
201
|
requestAnimationFrame(() => {
|
|
171
202
|
requestAnimationFrame(() => resolve());
|
|
@@ -190,11 +221,31 @@ const PrefabEditor = forwardRef(({ basePath, initialPrefab, physics = true, onPr
|
|
|
190
221
|
});
|
|
191
222
|
const handleFocusNode = (nodeId) => {
|
|
192
223
|
var _a;
|
|
193
|
-
(_a = prefabRootRef.current) === null || _a === void 0 ? void 0 : _a.
|
|
224
|
+
const object = (_a = prefabRootRef.current) === null || _a === void 0 ? void 0 : _a.getObject(nodeId);
|
|
225
|
+
const controls = controlsRef.current;
|
|
226
|
+
const camera = controls === null || controls === void 0 ? void 0 : controls.object;
|
|
227
|
+
if (!object || !controls || !camera)
|
|
228
|
+
return;
|
|
229
|
+
focusCameraOnObject(object, camera, controls.target, () => { var _a; return (_a = controls.update) === null || _a === void 0 ? void 0 : _a.call(controls); });
|
|
230
|
+
};
|
|
231
|
+
const handleTransformChange = () => {
|
|
232
|
+
var _a;
|
|
233
|
+
if (!selectedId)
|
|
234
|
+
return;
|
|
235
|
+
const object = (_a = prefabRootRef.current) === null || _a === void 0 ? void 0 : _a.getObject(selectedId);
|
|
236
|
+
if (!object)
|
|
237
|
+
return;
|
|
238
|
+
const parentWorld = computeParentWorldMatrix(loadedPrefab.root, selectedId);
|
|
239
|
+
const local = parentWorld.clone().invert().multiply(object.matrixWorld);
|
|
240
|
+
const { position, rotation, scale } = decompose(local);
|
|
241
|
+
updatePrefab(prev => (Object.assign(Object.assign({}, prev), { root: updateNode(prev.root, selectedId, node => (Object.assign(Object.assign({}, node), { components: Object.assign(Object.assign({}, node.components), { transform: {
|
|
242
|
+
type: "Transform",
|
|
243
|
+
properties: { position, rotation, scale },
|
|
244
|
+
} }) }))) })));
|
|
194
245
|
};
|
|
195
246
|
// --- Drag & drop files to add nodes ---
|
|
196
247
|
useEffect(() => {
|
|
197
|
-
if (!enableWindowDrop)
|
|
248
|
+
if (!enableWindowDrop || !editMode)
|
|
198
249
|
return;
|
|
199
250
|
function handleDragOver(e) {
|
|
200
251
|
e.preventDefault();
|
|
@@ -227,21 +278,22 @@ const PrefabEditor = forwardRef(({ basePath, initialPrefab, physics = true, onPr
|
|
|
227
278
|
window.removeEventListener('dragover', handleDragOver);
|
|
228
279
|
window.removeEventListener('drop', handleDrop);
|
|
229
280
|
};
|
|
230
|
-
}, [enableWindowDrop]);
|
|
281
|
+
}, [editMode, enableWindowDrop]);
|
|
231
282
|
useImperativeHandle(ref, () => ({
|
|
232
283
|
screenshot: handleScreenshot,
|
|
233
284
|
exportGLB: handleExportGLB,
|
|
234
285
|
exportGLBData: handleExportGLBData,
|
|
235
286
|
clearSelection,
|
|
236
287
|
prefab: loadedPrefab,
|
|
237
|
-
setPrefab
|
|
288
|
+
setPrefab,
|
|
238
289
|
replacePrefab,
|
|
239
290
|
addModel,
|
|
240
291
|
addTexture,
|
|
241
292
|
rootRef: prefabRootRef
|
|
242
|
-
})
|
|
243
|
-
const content = (_jsxs(_Fragment, { children: [_jsx("ambientLight", { intensity: 1.5 }), _jsx("gridHelper", { args: [10, 10], position: [0, -1, 0] }), _jsx(PrefabRoot, { ref: prefabRootRef, data: loadedPrefab, editMode: editMode,
|
|
293
|
+
}));
|
|
294
|
+
const content = (_jsxs(_Fragment, { children: [_jsx("ambientLight", { intensity: 1.5 }), _jsx("gridHelper", { args: [10, 10], position: [0, -1, 0] }), _jsx(PrefabRoot, { ref: prefabRootRef, data: loadedPrefab, editMode: editMode, selectedId: selectedId, onSelect: setSelection, onSelectedObjectChange: editMode ? setSelectedObject : undefined, onFocusNode: editMode ? handleFocusNode : undefined, basePath: basePath, injectedModels: injectedModels, injectedTextures: injectedTextures }), children] }));
|
|
244
295
|
return _jsxs(EditorContext.Provider, { value: {
|
|
296
|
+
editMode,
|
|
245
297
|
transformMode,
|
|
246
298
|
setTransformMode,
|
|
247
299
|
snapResolution,
|
|
@@ -250,10 +302,19 @@ const PrefabEditor = forwardRef(({ basePath, initialPrefab, physics = true, onPr
|
|
|
250
302
|
setPositionSnap,
|
|
251
303
|
rotationSnap,
|
|
252
304
|
setRotationSnap,
|
|
253
|
-
onFocusNode: handleFocusNode,
|
|
305
|
+
onFocusNode: editMode ? handleFocusNode : undefined,
|
|
254
306
|
onScreenshot: handleScreenshot,
|
|
255
307
|
onExportGLB: handleExportGLB
|
|
256
|
-
}, children: [
|
|
308
|
+
}, children: [_jsxs(GameCanvas, Object.assign({ camera: { position: [0, 5, 15] }, canvasRef: canvasRef }, canvasProps, { onPointerMissed: editMode
|
|
309
|
+
? (event) => {
|
|
310
|
+
var _a, _b, _c, _d;
|
|
311
|
+
const button = (_c = (_a = event.button) !== null && _a !== void 0 ? _a : (_b = event.sourceEvent) === null || _b === void 0 ? void 0 : _b.button) !== null && _c !== void 0 ? _c : 0;
|
|
312
|
+
if (button === 0 && selectedId) {
|
|
313
|
+
setSelection(null);
|
|
314
|
+
}
|
|
315
|
+
(_d = canvasProps === null || canvasProps === void 0 ? void 0 : canvasProps.onPointerMissed) === null || _d === void 0 ? void 0 : _d.call(canvasProps, event);
|
|
316
|
+
}
|
|
317
|
+
: canvasProps === null || canvasProps === void 0 ? void 0 : canvasProps.onPointerMissed, children: [physics ? (_jsx(Physics, { debug: editMode, paused: editMode, children: content })) : content, editMode && (_jsxs(_Fragment, { children: [_jsx(MapControls, { ref: controlsRef, makeDefault: true }), selectedObject && (_jsx(TransformControls, { object: selectedObject, mode: transformMode, space: "local", onObjectChange: handleTransformChange, translationSnap: positionSnap > 0 ? positionSnap : undefined, rotationSnap: rotationSnap > 0 ? rotationSnap : undefined, scaleSnap: snapResolution > 0 ? snapResolution : undefined }, `transform-${transformMode}-${positionSnap}-${rotationSnap}-${snapResolution}`))] }))] })), showUI && (_jsxs(_Fragment, { children: [_jsxs("div", { style: toolbar.panel, children: [_jsx("button", { style: base.btn, onClick: toggleEditMode, children: editMode ? "▶" : "⏸" }), uiPlugins] }), editMode && (_jsx(EditorUI, { prefabData: loadedPrefab, setPrefabData: updatePrefab, selectedId: selectedId, setSelectedId: setSelectedIdState, basePath: basePath, onUndo: undo, onRedo: redo, canUndo: historyIndex > 0, canRedo: historyIndex < history.length - 1 }))] }))] });
|
|
257
318
|
});
|
|
258
319
|
PrefabEditor.displayName = "PrefabEditor";
|
|
259
320
|
export default PrefabEditor;
|
|
@@ -4,15 +4,17 @@ import { Prefab, GameObject as GameObjectType } from "./types";
|
|
|
4
4
|
export interface PrefabRootRef {
|
|
5
5
|
root: Group | null;
|
|
6
6
|
rigidBodyRefs: Map<string, any>;
|
|
7
|
+
getObject: (nodeId: string) => Object3D | null;
|
|
7
8
|
focusNode: (nodeId: string) => void;
|
|
8
9
|
}
|
|
9
10
|
export declare const PrefabRoot: import("react").ForwardRefExoticComponent<{
|
|
10
11
|
editMode?: boolean;
|
|
11
12
|
data: Prefab;
|
|
12
|
-
onPrefabChange?: (data: Prefab) => void;
|
|
13
13
|
selectedId?: string | null;
|
|
14
14
|
onSelect?: (id: string | null) => void;
|
|
15
15
|
onClick?: (event: ThreeEvent<PointerEvent>, entity: GameObjectType) => void;
|
|
16
|
+
onSelectedObjectChange?: (object: Object3D | null) => void;
|
|
17
|
+
onFocusNode?: (nodeId: string) => void;
|
|
16
18
|
basePath?: string;
|
|
17
19
|
injectedModels?: Record<string, Object3D>;
|
|
18
20
|
injectedTextures?: Record<string, Texture>;
|
|
@@ -8,25 +8,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
-
import {
|
|
12
|
-
import { forwardRef, useCallback,
|
|
13
|
-
import { BoxHelper, Euler, Matrix4, Quaternion,
|
|
14
|
-
import { getComponent, registerComponent
|
|
11
|
+
import { useHelper } from "@react-three/drei";
|
|
12
|
+
import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
|
|
13
|
+
import { BoxHelper, Euler, Matrix4, Quaternion, Vector3, } from "three";
|
|
14
|
+
import { getComponent, registerComponent } from "./components/ComponentRegistry";
|
|
15
15
|
import components from "./components";
|
|
16
|
-
import { loadModel } from "../dragdrop";
|
|
16
|
+
import { loadModel, loadTexture } from "../dragdrop";
|
|
17
17
|
import { GameInstance, GameInstanceProvider, getRepeatAxesFromModelProperties, useInstanceCheck } from "./InstanceProvider";
|
|
18
|
-
import {
|
|
19
|
-
import { EditorContext } from "./EditorContext";
|
|
18
|
+
import { decompose } from "./utils";
|
|
20
19
|
components.forEach(registerComponent);
|
|
21
20
|
const IDENTITY = new Matrix4();
|
|
22
|
-
export const PrefabRoot = forwardRef(({ editMode, data,
|
|
23
|
-
var _a, _b, _c, _d;
|
|
24
|
-
// optional editor context
|
|
25
|
-
const editorContext = useContext(EditorContext);
|
|
26
|
-
const transformMode = (_a = editorContext === null || editorContext === void 0 ? void 0 : editorContext.transformMode) !== null && _a !== void 0 ? _a : "translate";
|
|
27
|
-
const snapResolution = (_b = editorContext === null || editorContext === void 0 ? void 0 : editorContext.snapResolution) !== null && _b !== void 0 ? _b : 0;
|
|
28
|
-
const positionSnap = (_c = editorContext === null || editorContext === void 0 ? void 0 : editorContext.positionSnap) !== null && _c !== void 0 ? _c : 0.5;
|
|
29
|
-
const rotationSnap = (_d = editorContext === null || editorContext === void 0 ? void 0 : editorContext.rotationSnap) !== null && _d !== void 0 ? _d : Math.PI / 4;
|
|
21
|
+
export const PrefabRoot = forwardRef(({ editMode, data, selectedId, onSelect, onClick, onSelectedObjectChange, onFocusNode, basePath = "", injectedModels = {}, injectedTextures = {} }, ref) => {
|
|
30
22
|
// prefab root state
|
|
31
23
|
const [models, setModels] = useState({});
|
|
32
24
|
const [textures, setTextures] = useState({});
|
|
@@ -34,28 +26,21 @@ export const PrefabRoot = forwardRef(({ editMode, data, onPrefabChange, selected
|
|
|
34
26
|
const failedTextures = useRef(new Set());
|
|
35
27
|
const objectRefs = useRef({});
|
|
36
28
|
const rigidBodyRefs = useRef(new Map());
|
|
37
|
-
const [selectedObject, setSelectedObject] = useState(null);
|
|
38
29
|
const rootRef = useRef(null);
|
|
39
|
-
const controlsRef = useRef(null);
|
|
40
30
|
const availableModels = useMemo(() => (Object.assign(Object.assign({}, models), injectedModels)), [models, injectedModels]);
|
|
41
31
|
const availableTextures = useMemo(() => (Object.assign(Object.assign({}, textures), injectedTextures)), [textures, injectedTextures]);
|
|
42
32
|
useImperativeHandle(ref, () => ({
|
|
43
33
|
root: rootRef.current,
|
|
44
34
|
rigidBodyRefs: rigidBodyRefs.current,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const camera = controls === null || controls === void 0 ? void 0 : controls.object;
|
|
49
|
-
if (!object || !controls || !camera)
|
|
50
|
-
return;
|
|
51
|
-
focusCameraOnObject(object, camera, controls.target, () => { var _a; return (_a = controls.update) === null || _a === void 0 ? void 0 : _a.call(controls); });
|
|
52
|
-
}
|
|
53
|
-
}), []);
|
|
35
|
+
getObject: (nodeId) => { var _a; return (_a = objectRefs.current[nodeId]) !== null && _a !== void 0 ? _a : null; },
|
|
36
|
+
focusNode: (nodeId) => onFocusNode === null || onFocusNode === void 0 ? void 0 : onFocusNode(nodeId),
|
|
37
|
+
}), [onFocusNode]);
|
|
54
38
|
const registerRef = useCallback((id, obj) => {
|
|
55
39
|
objectRefs.current[id] = obj;
|
|
56
|
-
if (id === selectedId)
|
|
57
|
-
|
|
58
|
-
|
|
40
|
+
if (id === selectedId) {
|
|
41
|
+
onSelectedObjectChange === null || onSelectedObjectChange === void 0 ? void 0 : onSelectedObjectChange(obj);
|
|
42
|
+
}
|
|
43
|
+
}, [onSelectedObjectChange, selectedId]);
|
|
59
44
|
const registerRigidBodyRef = useCallback((id, rb) => {
|
|
60
45
|
rigidBodyRefs.current.set(id, rb);
|
|
61
46
|
}, []);
|
|
@@ -68,25 +53,6 @@ export const PrefabRoot = forwardRef(({ editMode, data, onPrefabChange, selected
|
|
|
68
53
|
};
|
|
69
54
|
return () => { console.error = originalError; };
|
|
70
55
|
}, []);
|
|
71
|
-
useEffect(() => {
|
|
72
|
-
var _a;
|
|
73
|
-
setSelectedObject(selectedId ? (_a = objectRefs.current[selectedId]) !== null && _a !== void 0 ? _a : null : null);
|
|
74
|
-
}, [selectedId]);
|
|
75
|
-
const onTransformChange = () => {
|
|
76
|
-
if (!selectedId || !onPrefabChange)
|
|
77
|
-
return;
|
|
78
|
-
const obj = objectRefs.current[selectedId];
|
|
79
|
-
if (!obj)
|
|
80
|
-
return;
|
|
81
|
-
const parentWorld = computeParentWorldMatrix(data.root, selectedId);
|
|
82
|
-
const local = parentWorld.clone().invert().multiply(obj.matrixWorld);
|
|
83
|
-
const { position, rotation, scale } = decompose(local);
|
|
84
|
-
const root = updateNode(data.root, selectedId, node => (Object.assign(Object.assign({}, node), { components: Object.assign(Object.assign({}, node.components), { transform: {
|
|
85
|
-
type: "Transform",
|
|
86
|
-
properties: { position, rotation, scale },
|
|
87
|
-
} }) })));
|
|
88
|
-
onPrefabChange(Object.assign(Object.assign({}, data), { root }));
|
|
89
|
-
};
|
|
90
56
|
useEffect(() => {
|
|
91
57
|
const modelsToLoad = new Set();
|
|
92
58
|
const texturesToLoad = new Set();
|
|
@@ -112,7 +78,6 @@ export const PrefabRoot = forwardRef(({ editMode, data, onPrefabChange, selected
|
|
|
112
78
|
setModels(m => (Object.assign(Object.assign({}, m), { [file]: model })));
|
|
113
79
|
}
|
|
114
80
|
}));
|
|
115
|
-
const loader = new TextureLoader();
|
|
116
81
|
texturesToLoad.forEach(file => {
|
|
117
82
|
if (availableTextures[file] || loading.current.has(file) || failedTextures.current.has(file))
|
|
118
83
|
return;
|
|
@@ -123,17 +88,18 @@ export const PrefabRoot = forwardRef(({ editMode, data, onPrefabChange, selected
|
|
|
123
88
|
: file.startsWith("/")
|
|
124
89
|
? `${basePath}${file}`
|
|
125
90
|
: `${basePath}/${file}`;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
91
|
+
void loadTexture(path).then(result => {
|
|
92
|
+
if (result.success && result.texture) {
|
|
93
|
+
setTextures(t => (Object.assign(Object.assign({}, t), { [file]: result.texture })));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
console.warn(`Failed to load texture: ${path}`, result.error);
|
|
131
97
|
loading.current.delete(file);
|
|
132
98
|
failedTextures.current.add(file);
|
|
133
99
|
});
|
|
134
100
|
});
|
|
135
101
|
}, [data, availableModels, availableTextures, basePath]);
|
|
136
|
-
return (
|
|
102
|
+
return (_jsx("group", { ref: rootRef, children: _jsx(GameInstanceProvider, { models: availableModels, selectedId: selectedId, editMode: editMode, onSelect: editMode ? onSelect : undefined, registerRef: registerRef, children: _jsx(GameObjectRenderer, { gameObject: data.root, selectedId: selectedId, onSelect: editMode ? onSelect : undefined, onClick: onClick, registerRef: registerRef, registerRigidBodyRef: registerRigidBodyRef, loadedModels: availableModels, loadedTextures: availableTextures, editMode: editMode, parentMatrix: IDENTITY }) }) }));
|
|
137
103
|
});
|
|
138
104
|
export function GameObjectRenderer(props) {
|
|
139
105
|
var _a, _b, _c;
|
|
@@ -162,12 +128,14 @@ function isPhysicsProps(v) {
|
|
|
162
128
|
return (v === null || v === void 0 ? void 0 : v.type) === "fixed" || (v === null || v === void 0 ? void 0 : v.type) === "dynamic" || (v === null || v === void 0 ? void 0 : v.type) === "kinematicPosition" || (v === null || v === void 0 ? void 0 : v.type) === "kinematicVelocity";
|
|
163
129
|
}
|
|
164
130
|
function InstancedNode({ gameObject, parentMatrix = IDENTITY, editMode, registerRef, selectedId: _selectedId, onSelect, onClick }) {
|
|
165
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
131
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
166
132
|
const localTransform = getNodeTransformProps(gameObject);
|
|
167
|
-
const
|
|
168
|
-
|
|
133
|
+
const isLocked = Boolean(gameObject.locked);
|
|
134
|
+
const clickable = Object.values((_a = gameObject.components) !== null && _a !== void 0 ? _a : {}).some(component => (component === null || component === void 0 ? void 0 : component.type) === 'Click');
|
|
135
|
+
const physicsProps = isPhysicsProps((_c = (_b = gameObject.components) === null || _b === void 0 ? void 0 : _b.physics) === null || _c === void 0 ? void 0 : _c.properties)
|
|
136
|
+
? (_e = (_d = gameObject.components) === null || _d === void 0 ? void 0 : _d.physics) === null || _e === void 0 ? void 0 : _e.properties
|
|
169
137
|
: undefined;
|
|
170
|
-
const modelUrl = (
|
|
138
|
+
const modelUrl = (_h = (_g = (_f = gameObject.components) === null || _f === void 0 ? void 0 : _f.model) === null || _g === void 0 ? void 0 : _g.properties) === null || _h === void 0 ? void 0 : _h.filename;
|
|
171
139
|
const instances = useMemo(() => buildRepeatedInstances(gameObject, parentMatrix, modelUrl, physicsProps), [gameObject, modelUrl, parentMatrix, physicsProps]);
|
|
172
140
|
const groupRef = useRef(null);
|
|
173
141
|
const clickValid = useRef(false);
|
|
@@ -178,22 +146,23 @@ function InstancedNode({ gameObject, parentMatrix = IDENTITY, editMode, register
|
|
|
178
146
|
}
|
|
179
147
|
}, [gameObject.id, registerRef, editMode]);
|
|
180
148
|
if (editMode) {
|
|
181
|
-
return (_jsxs(_Fragment, { children: [_jsx("group", { ref: groupRef, position: localTransform.position, rotation: localTransform.rotation, scale: localTransform.scale, onPointerDown: (e) => { e.stopPropagation(); clickValid.current = true; }, onPointerMove: () => { clickValid.current = false; }, onPointerUp: (e) => {
|
|
149
|
+
return (_jsxs(_Fragment, { children: [_jsx("group", { ref: groupRef, position: localTransform.position, rotation: localTransform.rotation, scale: localTransform.scale, onPointerDown: isLocked ? undefined : (e) => { e.stopPropagation(); clickValid.current = true; }, onPointerMove: isLocked ? undefined : () => { clickValid.current = false; }, onPointerUp: isLocked ? undefined : (e) => {
|
|
182
150
|
if (clickValid.current) {
|
|
183
151
|
e.stopPropagation();
|
|
184
152
|
onSelect === null || onSelect === void 0 ? void 0 : onSelect(gameObject.id);
|
|
185
153
|
onClick === null || onClick === void 0 ? void 0 : onClick(e, gameObject);
|
|
186
154
|
}
|
|
187
155
|
clickValid.current = false;
|
|
188
|
-
}, children: _jsx("mesh", { visible: false, children: _jsx("boxGeometry", { args: [0.01, 0.01, 0.01] }) }) }), instances.map(instance => (_jsx(GameInstance, { id: instance.id, sourceId: gameObject.id, modelUrl: instance.modelUrl, position: instance.position, rotation: instance.rotation, scale: instance.scale, physics: instance.physics }, instance.id)))] }));
|
|
156
|
+
}, children: _jsx("mesh", { visible: false, children: _jsx("boxGeometry", { args: [0.01, 0.01, 0.01] }) }) }), instances.map(instance => (_jsx(GameInstance, { id: instance.id, sourceId: gameObject.id, clickable: clickable, modelUrl: instance.modelUrl, position: instance.position, rotation: instance.rotation, scale: instance.scale, locked: isLocked, physics: instance.physics }, instance.id)))] }));
|
|
189
157
|
}
|
|
190
|
-
return (_jsx(_Fragment, { children: instances.map(instance => (_jsx(GameInstance, { id: instance.id, sourceId: gameObject.id, modelUrl: instance.modelUrl, position: instance.position, rotation: instance.rotation, scale: instance.scale, physics: instance.physics }, instance.id))) }));
|
|
158
|
+
return (_jsx(_Fragment, { children: instances.map(instance => (_jsx(GameInstance, { id: instance.id, sourceId: gameObject.id, clickable: clickable, modelUrl: instance.modelUrl, position: instance.position, rotation: instance.rotation, scale: instance.scale, locked: isLocked, physics: instance.physics }, instance.id))) }));
|
|
191
159
|
}
|
|
192
160
|
function StandardNode({ gameObject, selectedId, onSelect, onClick, registerRef, registerRigidBodyRef, loadedModels, loadedTextures, editMode, parentMatrix = IDENTITY, }) {
|
|
193
161
|
var _a, _b, _c, _d, _e;
|
|
194
162
|
const groupRef = useRef(null);
|
|
195
163
|
const helperRef = useRef(null);
|
|
196
164
|
const clickValid = useRef(false);
|
|
165
|
+
const isLocked = Boolean(gameObject.locked);
|
|
197
166
|
const isSelected = selectedId === gameObject.id;
|
|
198
167
|
const stillInstanced = useInstanceCheck(gameObject.id);
|
|
199
168
|
useHelper(editMode && isSelected ? helperRef : null, BoxHelper, "cyan");
|
|
@@ -235,26 +204,22 @@ function StandardNode({ gameObject, selectedId, onSelect, onClick, registerRef,
|
|
|
235
204
|
loadedTextures,
|
|
236
205
|
editMode,
|
|
237
206
|
});
|
|
238
|
-
const inner = (_jsx("group", { onPointerDown: editMode ? onDown : undefined, onPointerMove: editMode ? () => (clickValid.current = false) : undefined, onPointerUp: editMode ? onUp : undefined, children: renderCompositionNode(gameObject, renderCtx, parentMatrix, childNodes) }));
|
|
207
|
+
const inner = (_jsx("group", { onPointerDown: editMode && !isLocked ? onDown : undefined, onPointerMove: editMode && !isLocked ? () => (clickValid.current = false) : undefined, onPointerUp: editMode && !isLocked ? onUp : undefined, children: renderCompositionNode(gameObject, renderCtx, parentMatrix, childNodes) }));
|
|
239
208
|
if (editMode) {
|
|
240
209
|
return (_jsxs(_Fragment, { children: [_jsx("group", { ref: groupRef, position: transform.position, rotation: transform.rotation, scale: transform.scale, children: _jsx("mesh", { visible: false, children: _jsx("boxGeometry", { args: [0.01, 0.01, 0.01] }) }) }), _jsx("group", { ref: helperRef, position: transform.position, rotation: transform.rotation, scale: transform.scale, children: inner }), hasPhysics && (physicsDef === null || physicsDef === void 0 ? void 0 : physicsDef.View) ? (_jsx(physicsDef.View, { properties: physics.properties, position: transform.position, rotation: transform.rotation, scale: transform.scale, editMode: editMode, nodeId: gameObject.id, registerRigidBodyRef: registerRigidBodyRef, children: inner }, physicsKey)) : null] }));
|
|
241
210
|
}
|
|
242
211
|
if (hasPhysics && (physicsDef === null || physicsDef === void 0 ? void 0 : physicsDef.View)) {
|
|
243
212
|
return (_jsx(physicsDef.View, { properties: physics.properties, position: transform.position, rotation: transform.rotation, scale: transform.scale, editMode: editMode, nodeId: gameObject.id, registerRigidBodyRef: registerRigidBodyRef, children: inner }, physicsKey));
|
|
244
213
|
}
|
|
245
|
-
return (_jsx("group", { ref: groupRef, position: transform.position, rotation: transform.rotation, scale: transform.scale,
|
|
246
|
-
}
|
|
247
|
-
const CHILD_HOST_COMPONENT_TYPES = new Set(["Environment"]);
|
|
248
|
-
function isChildHostType(type) {
|
|
249
|
-
return CHILD_HOST_COMPONENT_TYPES.has(type);
|
|
214
|
+
return (_jsx("group", { ref: groupRef, position: transform.position, rotation: transform.rotation, scale: transform.scale, children: inner }));
|
|
250
215
|
}
|
|
251
216
|
function getChildHostComponents(gameObject) {
|
|
252
217
|
var _a;
|
|
253
218
|
return Object.entries((_a = gameObject.components) !== null && _a !== void 0 ? _a : {}).flatMap(([key, comp]) => {
|
|
254
|
-
if (!(comp === null || comp === void 0 ? void 0 : comp.type)
|
|
219
|
+
if (!(comp === null || comp === void 0 ? void 0 : comp.type))
|
|
255
220
|
return [];
|
|
256
221
|
const def = getComponent(comp.type);
|
|
257
|
-
if (!(def === null || def === void 0 ? void 0 : def.View))
|
|
222
|
+
if (!(def === null || def === void 0 ? void 0 : def.View) || def.nonComposable)
|
|
258
223
|
return [];
|
|
259
224
|
return { key, View: def.View, properties: comp.properties };
|
|
260
225
|
});
|
|
@@ -327,16 +292,6 @@ function buildRepeatedInstances(gameObject, parentMatrix, modelUrl, physics) {
|
|
|
327
292
|
}
|
|
328
293
|
return instances;
|
|
329
294
|
}
|
|
330
|
-
function decompose(m) {
|
|
331
|
-
const p = new Vector3(), q = new Quaternion(), s = new Vector3();
|
|
332
|
-
m.decompose(p, q, s);
|
|
333
|
-
const e = new Euler().setFromQuaternion(q);
|
|
334
|
-
return {
|
|
335
|
-
position: [p.x, p.y, p.z],
|
|
336
|
-
rotation: [e.x, e.y, e.z],
|
|
337
|
-
scale: [s.x, s.y, s.z],
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
295
|
function getNodeTransformProps(node) {
|
|
341
296
|
var _a, _b, _c, _d, _e;
|
|
342
297
|
const t = (_b = (_a = node === null || node === void 0 ? void 0 : node.components) === null || _a === void 0 ? void 0 : _a.transform) === null || _b === void 0 ? void 0 : _b.properties;
|
|
@@ -346,20 +301,6 @@ function getNodeTransformProps(node) {
|
|
|
346
301
|
scale: (_e = t === null || t === void 0 ? void 0 : t.scale) !== null && _e !== void 0 ? _e : [1, 1, 1],
|
|
347
302
|
};
|
|
348
303
|
}
|
|
349
|
-
function computeParentWorldMatrix(root, targetId) {
|
|
350
|
-
let result = null;
|
|
351
|
-
const visit = (node, parent) => {
|
|
352
|
-
var _a;
|
|
353
|
-
if (node.id === targetId) {
|
|
354
|
-
result = parent.clone();
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
const world = parent.clone().multiply(compose(node));
|
|
358
|
-
(_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach(c => !result && visit(c, world));
|
|
359
|
-
};
|
|
360
|
-
visit(root, IDENTITY);
|
|
361
|
-
return result !== null && result !== void 0 ? result : IDENTITY;
|
|
362
|
-
}
|
|
363
304
|
function renderCompositionSubtree(gameObject, ctx, parentMatrix = IDENTITY) {
|
|
364
305
|
if (!gameObject || gameObject.disabled)
|
|
365
306
|
return null;
|
|
@@ -374,9 +315,7 @@ function renderHostedChildren(gameObject, ctx, parentMatrix) {
|
|
|
374
315
|
}
|
|
375
316
|
function renderCompositionNode(gameObject, ctx, parentMatrix, childNodes) {
|
|
376
317
|
const ownContent = renderNodeOwnContent(gameObject, ctx, parentMatrix);
|
|
377
|
-
|
|
378
|
-
const subtree = _jsxs(_Fragment, { children: [ownContent, siblingContent, childNodes] });
|
|
379
|
-
return wrapWithChildHosts(gameObject, ctx, parentMatrix, subtree);
|
|
318
|
+
return wrapWithChildHosts(gameObject, ctx, parentMatrix, _jsxs(_Fragment, { children: [ownContent, childNodes] }));
|
|
380
319
|
}
|
|
381
320
|
function renderNodeOwnContent(gameObject, ctx, parentMatrix) {
|
|
382
321
|
var _a, _b, _c, _d;
|
|
@@ -412,28 +351,6 @@ function renderNodeOwnContent(gameObject, ctx, parentMatrix) {
|
|
|
412
351
|
}
|
|
413
352
|
return core;
|
|
414
353
|
}
|
|
415
|
-
function renderNodeSiblingComponents(gameObject, ctx, parentMatrix) {
|
|
416
|
-
var _a;
|
|
417
|
-
const contextProps = {
|
|
418
|
-
loadedModels: ctx.loadedModels,
|
|
419
|
-
loadedTextures: ctx.loadedTextures,
|
|
420
|
-
editMode: ctx.editMode,
|
|
421
|
-
isSelected: ctx.selectedId === gameObject.id,
|
|
422
|
-
nodeId: gameObject.id,
|
|
423
|
-
parentMatrix,
|
|
424
|
-
registerRef: ctx.registerRef,
|
|
425
|
-
};
|
|
426
|
-
return Object.entries((_a = gameObject.components) !== null && _a !== void 0 ? _a : {})
|
|
427
|
-
.filter(([key]) => !getNonComposableKeys().includes(key))
|
|
428
|
-
.flatMap(([key, comp]) => {
|
|
429
|
-
if (!(comp === null || comp === void 0 ? void 0 : comp.type) || isChildHostType(comp.type))
|
|
430
|
-
return [];
|
|
431
|
-
const def = getComponent(comp.type);
|
|
432
|
-
if (!(def === null || def === void 0 ? void 0 : def.View))
|
|
433
|
-
return [];
|
|
434
|
-
return _jsx(def.View, Object.assign({ properties: comp.properties }, contextProps), key);
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
354
|
function wrapWithChildHosts(gameObject, ctx, parentMatrix, subtree) {
|
|
438
355
|
const contextProps = {
|
|
439
356
|
loadedModels: ctx.loadedModels,
|
|
@@ -34,7 +34,7 @@ function CameraComponentView({ properties, editMode, isSelected }) {
|
|
|
34
34
|
cameraHelper.update();
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
|
-
return (_jsxs(_Fragment, { children: [_jsx(PerspectiveCamera, { ref: (instance) => setCamera(instance), makeDefault: !editMode, fov: fov, near: near, zoom: zoom, far: far }), editMode && isSelected && cameraHelper && (_jsx("primitive", { object: cameraHelper })), editMode
|
|
37
|
+
return (_jsxs(_Fragment, { children: [_jsx(PerspectiveCamera, { ref: (instance) => setCamera(instance), makeDefault: !editMode, fov: fov, near: near, zoom: zoom, far: far }), editMode && isSelected && cameraHelper && (_jsx("primitive", { object: cameraHelper })), editMode ? (_jsxs("group", { children: [_jsxs("mesh", { children: [_jsx("boxGeometry", { args: [0.3, 0.3, 0.5] }), _jsx("meshBasicMaterial", { color: '#22d3ee', wireframe: true })] }), _jsxs("mesh", { position: [0, 0, -0.25], rotation: [Math.PI / 2, 0, 0], children: [_jsx("coneGeometry", { args: [0.08, 0.16, 16] }), _jsx("meshBasicMaterial", { color: '#22d3ee', wireframe: true })] })] })) : null] }));
|
|
38
38
|
}
|
|
39
39
|
const CameraComponent = {
|
|
40
40
|
name: 'Camera',
|