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.
Files changed (33) hide show
  1. package/LICENSE +2 -660
  2. package/README.md +164 -91
  3. package/dist/index.d.ts +4 -2
  4. package/dist/index.js +2 -1
  5. package/dist/tools/assetviewer/page.js +4 -4
  6. package/dist/tools/prefabeditor/EditorContext.d.ts +2 -2
  7. package/dist/tools/prefabeditor/EditorTree.js +17 -3
  8. package/dist/tools/prefabeditor/EditorTreeMenus.d.ts +3 -1
  9. package/dist/tools/prefabeditor/EditorTreeMenus.js +7 -8
  10. package/dist/tools/prefabeditor/EditorUI.js +3 -7
  11. package/dist/tools/prefabeditor/GameEvents.d.ts +14 -1
  12. package/dist/tools/prefabeditor/GameEvents.js +2 -1
  13. package/dist/tools/prefabeditor/InstanceProvider.d.ts +4 -0
  14. package/dist/tools/prefabeditor/InstanceProvider.js +44 -12
  15. package/dist/tools/prefabeditor/PrefabEditor.js +77 -16
  16. package/dist/tools/prefabeditor/PrefabRoot.d.ts +3 -1
  17. package/dist/tools/prefabeditor/PrefabRoot.js +36 -119
  18. package/dist/tools/prefabeditor/components/CameraComponent.js +1 -1
  19. package/dist/tools/prefabeditor/components/ClickComponent.d.ts +3 -0
  20. package/dist/tools/prefabeditor/components/ClickComponent.js +45 -0
  21. package/dist/tools/prefabeditor/components/ComponentRegistry.js +0 -3
  22. package/dist/tools/prefabeditor/components/DirectionalLightComponent.js +3 -3
  23. package/dist/tools/prefabeditor/components/Input.d.ts +5 -2
  24. package/dist/tools/prefabeditor/components/Input.js +71 -38
  25. package/dist/tools/prefabeditor/components/MaterialComponent.js +3 -3
  26. package/dist/tools/prefabeditor/components/ModelComponent.js +2 -2
  27. package/dist/tools/prefabeditor/components/PhysicsComponent.d.ts +2 -0
  28. package/dist/tools/prefabeditor/components/PhysicsComponent.js +77 -10
  29. package/dist/tools/prefabeditor/components/index.js +2 -0
  30. package/dist/tools/prefabeditor/types.d.ts +1 -0
  31. package/dist/tools/prefabeditor/utils.d.ts +7 -1
  32. package/dist/tools/prefabeditor/utils.js +34 -1
  33. 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
- if (instanceId !== undefined && group.instances[instanceId]) {
317
- onSelect(group.instances[instanceId].sourceId);
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: editMode ? handleClick : undefined }, i));
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
- onSelect === null || onSelect === void 0 ? void 0 : onSelect(instance.sourceId);
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
- useEffect(() => {
52
- onPrefabChangeRef.current = onPrefabChange;
53
- }, [onPrefabChange]);
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
- setSelectedId(null);
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
- setSelectedId(node.id);
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
- setSelectedId(null);
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.focusNode(nodeId);
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: replacePrefab,
288
+ setPrefab,
238
289
  replacePrefab,
239
290
  addModel,
240
291
  addTexture,
241
292
  rootRef: prefabRootRef
242
- }), [loadedPrefab]);
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, onPrefabChange: updatePrefab, selectedId: selectedId, onSelect: setSelectedId, basePath: basePath, injectedModels: injectedModels, injectedTextures: injectedTextures }), children] }));
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: [_jsx(GameCanvas, Object.assign({ camera: { position: [0, 5, 15] }, canvasRef: canvasRef }, canvasProps, { children: physics ? (_jsx(Physics, { debug: editMode, paused: editMode, children: content })) : content })), showUI && (_jsxs(_Fragment, { children: [_jsxs("div", { style: toolbar.panel, children: [_jsx("button", { style: base.btn, onClick: () => setEditMode(!editMode), children: editMode ? "▶" : "⏸" }), uiPlugins] }), _jsx(EditorUI, { prefabData: loadedPrefab, setPrefabData: updatePrefab, selectedId: selectedId, setSelectedId: setSelectedId, basePath: basePath, onUndo: undo, onRedo: redo, canUndo: historyIndex > 0, canRedo: historyIndex < history.length - 1 })] }))] });
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 { MapControls, TransformControls, useHelper } from "@react-three/drei";
12
- import { forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
13
- import { BoxHelper, Euler, Matrix4, Quaternion, SRGBColorSpace, TextureLoader, Vector3, } from "three";
14
- import { getComponent, registerComponent, getNonComposableKeys } from "./components/ComponentRegistry";
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 { focusCameraOnObject, updateNode } from "./utils";
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, onPrefabChange, selectedId, onSelect, onClick, basePath = "", injectedModels = {}, injectedTextures = {} }, ref) => {
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
- focusNode: (nodeId) => {
46
- const object = objectRefs.current[nodeId];
47
- const controls = controlsRef.current;
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
- setSelectedObject(obj);
58
- }, [selectedId]);
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
- loader.load(path, tex => {
127
- tex.colorSpace = SRGBColorSpace;
128
- setTextures(t => (Object.assign(Object.assign({}, t), { [file]: tex })));
129
- }, undefined, (err) => {
130
- console.warn(`Failed to load texture: ${path}`, err);
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 (_jsxs("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 }) }), editMode && (_jsxs(_Fragment, { children: [_jsx(MapControls, { ref: controlsRef, makeDefault: true }), selectedObject && (_jsx(TransformControls, { object: selectedObject, mode: transformMode, space: "local", onObjectChange: onTransformChange, translationSnap: positionSnap > 0 ? positionSnap : undefined, rotationSnap: rotationSnap > 0 ? rotationSnap : undefined, scaleSnap: snapResolution > 0 ? snapResolution : undefined }, `transform-${transformMode}-${positionSnap}-${rotationSnap}-${snapResolution}`))] }))] }));
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 physicsProps = isPhysicsProps((_b = (_a = gameObject.components) === null || _a === void 0 ? void 0 : _a.physics) === null || _b === void 0 ? void 0 : _b.properties)
168
- ? (_d = (_c = gameObject.components) === null || _c === void 0 ? void 0 : _c.physics) === null || _d === void 0 ? void 0 : _d.properties
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 = (_g = (_f = (_e = gameObject.components) === null || _e === void 0 ? void 0 : _e.model) === null || _f === void 0 ? void 0 : _f.properties) === null || _g === void 0 ? void 0 : _g.filename;
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, onPointerDown: onDown, onPointerMove: () => (clickValid.current = false), onPointerUp: onUp, children: inner }));
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) || !isChildHostType(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
- const siblingContent = renderNodeSiblingComponents(gameObject, ctx, parentMatrix);
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 && !isSelected ? (_jsxs("mesh", { children: [_jsx("boxGeometry", { args: [0.34, 0.22, 0.18] }), _jsx("meshBasicMaterial", { color: "#22d3ee", wireframe: true })] })) : null] }));
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',
@@ -0,0 +1,3 @@
1
+ import { Component } from './ComponentRegistry';
2
+ declare const ClickComponent: Component;
3
+ export default ClickComponent;