react-three-game 0.0.77 → 0.0.78

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.
@@ -1,20 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Canvas } from "@react-three/fiber";
3
3
  import { OrbitControls, View, PerspectiveCamera } from "@react-three/drei";
4
- import { Component as ReactComponent, Suspense, useEffect, useLayoutEffect, useState, useRef } from "react";
4
+ import { Suspense, useEffect, useLayoutEffect, useState, useRef } from "react";
5
5
  import { createPortal } from 'react-dom';
6
6
  import { TextureLoader } from "three";
7
7
  import { loadModel } from "../dragdrop/modelLoader";
8
- class ErrorBoundary extends ReactComponent {
9
- constructor(props) {
10
- super(props);
11
- this.state = { hasError: false };
12
- }
13
- static getDerivedStateFromError() { return { hasError: true }; }
14
- componentDidCatch() { var _a, _b; (_b = (_a = this.props).onError) === null || _b === void 0 ? void 0 : _b.call(_a); }
15
- render() { return this.state.hasError ? null : this.props.children; }
16
- }
17
- // view models and textures in manifest, onselect callback
18
8
  const styles = {
19
9
  errorIcon: { color: '#fca5a5', fontSize: 12 }, // text-red-400 text-xs
20
10
  flexFillRelative: { flex: 1, position: 'relative' },
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
11
11
  import { MapControls, TransformControls } from "@react-three/drei";
12
12
  import GameCanvas from "../../shared/GameCanvas";
13
- import { useCallback, useEffect, useMemo, useRef, useState, forwardRef, useImperativeHandle, createContext, useContext } from "react";
13
+ import { useCallback, useEffect, useMemo, useReducer, useRef, useState, forwardRef, useImperativeHandle, createContext, useContext } from "react";
14
14
  import { findComponentEntry } from "./types";
15
15
  import PrefabRoot from "./PrefabRoot";
16
16
  import { Physics } from "@react-three/rapier";
@@ -21,6 +21,17 @@ import { loadFiles } from "../dragdrop";
21
21
  import { denormalizePrefab, createImageNode, createModelNode, createNode } from './prefab';
22
22
  import { createPrefabStore, PrefabStoreProvider } from "./prefabStore";
23
23
  import { createScene } from "./scene";
24
+ function isObjectAttachedToRoot(root, object) {
25
+ if (!root || !object)
26
+ return false;
27
+ let current = object;
28
+ while (current) {
29
+ if (current === root)
30
+ return true;
31
+ current = current.parent;
32
+ }
33
+ return false;
34
+ }
24
35
  export var PrefabEditorMode;
25
36
  (function (PrefabEditorMode) {
26
37
  PrefabEditorMode["Edit"] = "edit";
@@ -42,6 +53,7 @@ const DEFAULT_PREFAB = {
42
53
  root: createNode('Root', {}, { id: 'root' })
43
54
  };
44
55
  const PrefabEditor = forwardRef(({ basePath, initialPrefab, physics = true, mode: initialMode = PrefabEditorMode.Edit, onChange, showUI = true, enableWindowDrop = true, canvasProps, uiPlugins, children }, ref) => {
56
+ var _a, _b;
45
57
  const [mode, setMode] = useState(initialMode);
46
58
  const [selectedId, setSelectedId] = useState(null);
47
59
  const [transformMode, setTransformMode] = useState("translate");
@@ -54,7 +66,7 @@ const PrefabEditor = forwardRef(({ basePath, initialPrefab, physics = true, mode
54
66
  const [historyIndex, setHistoryIndex] = useState(0);
55
67
  const changeOriginRef = useRef(null);
56
68
  const historyIndexRef = useRef(0);
57
- const [selectedObject, setSelectedObject] = useState(null);
69
+ const [, bumpSelectedObjectVersion] = useReducer((value) => value + 1, 0);
58
70
  const prefabRootRef = useRef(null);
59
71
  const canvasRef = useRef(null);
60
72
  const controlsRef = useRef(null);
@@ -63,6 +75,11 @@ const PrefabEditor = forwardRef(({ basePath, initialPrefab, physics = true, mode
63
75
  const getPrefab = useCallback(() => denormalizePrefab(prefabStore.getState()), [prefabStore]);
64
76
  const getObject = useCallback((nodeId) => { var _a, _b; return (_b = (_a = prefabRootRef.current) === null || _a === void 0 ? void 0 : _a.getObject(nodeId)) !== null && _b !== void 0 ? _b : null; }, []);
65
77
  const getRigidBody = useCallback((nodeId) => { var _a, _b; return (_b = (_a = prefabRootRef.current) === null || _a === void 0 ? void 0 : _a.getRigidBody(nodeId)) !== null && _b !== void 0 ? _b : null; }, []);
78
+ const handleObjectRefChange = useCallback((nodeId) => {
79
+ if (nodeId !== selectedId)
80
+ return;
81
+ bumpSelectedObjectVersion();
82
+ }, [selectedId]);
66
83
  onChangeRef.current = onChange;
67
84
  const setSelection = useCallback((nodeId) => {
68
85
  const nextNode = nodeId ? prefabStore.getState().nodesById[nodeId] : null;
@@ -77,7 +94,6 @@ const PrefabEditor = forwardRef(({ basePath, initialPrefab, physics = true, mode
77
94
  return prev;
78
95
  if (nextMode === PrefabEditorMode.Play) {
79
96
  setSelectedId(null);
80
- setSelectedObject(null);
81
97
  }
82
98
  return nextMode;
83
99
  });
@@ -91,7 +107,6 @@ const PrefabEditor = forwardRef(({ basePath, initialPrefab, physics = true, mode
91
107
  const loadPrefab = useCallback((prefab, options) => {
92
108
  changeOriginRef.current = (options === null || options === void 0 ? void 0 : options.notifyChange) === false ? "replace-silent" : "replace";
93
109
  prefabStore.getState().replacePrefab(prefab);
94
- setSelectedObject(null);
95
110
  if (options === null || options === void 0 ? void 0 : options.resetHistory) {
96
111
  setSelectedId(null);
97
112
  setHistory([prefab]);
@@ -154,23 +169,13 @@ const PrefabEditor = forwardRef(({ basePath, initialPrefab, physics = true, mode
154
169
  if (state.nodesById[selectedId])
155
170
  return;
156
171
  setSelectedId(null);
157
- setSelectedObject(null);
158
172
  });
159
173
  return () => unsubscribe();
160
174
  }, [prefabStore, selectedId]);
161
- useEffect(() => {
162
- if (!selectedId) {
163
- setSelectedObject(null);
164
- return;
165
- }
166
- setSelectedObject(getObject(selectedId));
167
- }, [getObject, selectedId]);
168
- const handleObjectRefChange = useCallback((nodeId, obj) => {
169
- if (nodeId !== selectedId) {
170
- return;
171
- }
172
- setSelectedObject(current => current === obj ? current : obj);
173
- }, [selectedId]);
175
+ const selectedObject = selectedId ? getObject(selectedId) : null;
176
+ const transformObject = isObjectAttachedToRoot((_b = (_a = prefabRootRef.current) === null || _a === void 0 ? void 0 : _a.root) !== null && _b !== void 0 ? _b : null, selectedObject)
177
+ ? selectedObject
178
+ : null;
174
179
  const addNode = useCallback((node, options) => {
175
180
  var _a;
176
181
  const { addChild, rootId } = prefabStore.getState();
@@ -202,7 +207,6 @@ const PrefabEditor = forwardRef(({ basePath, initialPrefab, physics = true, mode
202
207
  prefabStore.getState().replacePrefab(history[index]);
203
208
  historyIndexRef.current = index;
204
209
  setHistoryIndex(index);
205
- setSelectedObject(null);
206
210
  setSelectedId(prev => prev && prefabStore.getState().nodesById[prev] ? prev : null);
207
211
  };
208
212
  const undo = () => historyIndex > 0 && applyHistory(historyIndex - 1);
@@ -377,7 +381,7 @@ const PrefabEditor = forwardRef(({ basePath, initialPrefab, physics = true, mode
377
381
  }
378
382
  (_d = canvasProps === null || canvasProps === void 0 ? void 0 : canvasProps.onPointerMissed) === null || _d === void 0 ? void 0 : _d.call(canvasProps, event);
379
383
  }
380
- : canvasProps === null || canvasProps === void 0 ? void 0 : canvasProps.onPointerMissed, children: [physics ? (_jsx(Physics, { debug: isEditMode, paused: isEditMode, children: content })) : content, isEditMode && (_jsxs(_Fragment, { children: [_jsx(MapControls, { ref: controlsRef, enableDamping: false, makeDefault: true }), selectedObject && (_jsx(TransformControls, { object: selectedObject, mode: transformMode, space: "local", onObjectChange: handleTransformChange, translationSnap: positionSnap > 0 ? positionSnap : undefined, rotationSnap: rotationSnap > 0 ? rotationSnap : undefined, scaleSnap: scaleSnap > 0 ? scaleSnap : undefined }, `transform-${transformMode}-${positionSnap}-${rotationSnap}-${scaleSnap}`))] }))] })), showUI && (_jsxs(_Fragment, { children: [_jsxs("div", { style: toolbar.panel, children: [_jsx("button", { style: base.btn, onClick: toggleMode, children: isEditMode ? "▶" : "⏸" }), uiPlugins] }), isEditMode && (_jsx(EditorUI, { selectedId: selectedId, setSelectedId: setSelection, getPrefab: getPrefab, onReplacePrefab: (prefab) => loadPrefab(prefab, { resetHistory: true }), onImportPrefab: importPrefab, basePath: basePath, onUndo: undo, onRedo: redo, canUndo: historyIndex > 0, canRedo: historyIndex < history.length - 1 }))] }))] }) });
384
+ : canvasProps === null || canvasProps === void 0 ? void 0 : canvasProps.onPointerMissed, children: [physics ? (_jsx(Physics, { debug: isEditMode, paused: isEditMode, children: content })) : content, isEditMode && (_jsxs(_Fragment, { children: [_jsx(MapControls, { ref: controlsRef, enableDamping: false, makeDefault: true }), transformObject && (_jsx(TransformControls, { object: transformObject, mode: transformMode, space: "local", onObjectChange: handleTransformChange, translationSnap: positionSnap > 0 ? positionSnap : undefined, rotationSnap: rotationSnap > 0 ? rotationSnap : undefined, scaleSnap: scaleSnap > 0 ? scaleSnap : undefined }, `transform-${selectedId}-${transformMode}-${positionSnap}-${rotationSnap}-${scaleSnap}`))] }))] })), showUI && (_jsxs(_Fragment, { children: [_jsxs("div", { style: toolbar.panel, children: [_jsx("button", { style: base.btn, onClick: toggleMode, children: isEditMode ? "▶" : "⏸" }), uiPlugins] }), isEditMode && (_jsx(EditorUI, { selectedId: selectedId, setSelectedId: setSelection, getPrefab: getPrefab, onReplacePrefab: (prefab) => loadPrefab(prefab, { resetHistory: true }), onImportPrefab: importPrefab, basePath: basePath, onUndo: undo, onRedo: redo, canUndo: historyIndex > 0, canRedo: historyIndex < history.length - 1 }))] }))] }) });
381
385
  });
382
386
  PrefabEditor.displayName = "PrefabEditor";
383
387
  export default PrefabEditor;
@@ -18,7 +18,7 @@ export interface PrefabRootProps {
18
18
  selectedId?: string | null;
19
19
  onSelect?: (id: string | null) => void;
20
20
  onClick?: (event: ThreeEvent<PointerEvent>, entity: GameObjectType) => void;
21
- onObjectRefChange?: (id: string, obj: Object3D | null) => void;
21
+ onObjectRefChange?: (id: string, object: Object3D | null) => void;
22
22
  basePath?: string;
23
23
  }
24
24
  export declare const PrefabRoot: import("react").ForwardRefExoticComponent<PrefabRootProps & import("react").RefAttributes<PrefabRootRef>>;
@@ -118,7 +118,6 @@ function DirectionalLightView({ properties, children }) {
118
118
  const shadowCameraLeft = merged.shadowCameraLeft;
119
119
  const shadowCameraRight = merged.shadowCameraRight;
120
120
  const targetOffset = merged.targetOffset;
121
- const lightInstanceKey = castShadow ? 'shadow-on' : 'shadow-off';
122
121
  const directionalLightRef = useRef(null);
123
122
  const targetRef = useRef(null);
124
123
  const shadowCameraRef = useRef(null);
@@ -162,7 +161,7 @@ function DirectionalLightView({ properties, children }) {
162
161
  shadowCamera.updateMatrixWorld();
163
162
  }
164
163
  });
165
- return (_jsxs(_Fragment, { children: [_jsx("directionalLight", { ref: directionalLightRef, color: color, intensity: intensity, castShadow: castShadow, "shadow-mapSize-width": shadowMapSize, "shadow-mapSize-height": shadowMapSize, "shadow-camera-near": shadowCameraNear, "shadow-camera-far": shadowCameraFar, "shadow-camera-top": shadowCameraTop, "shadow-camera-bottom": shadowCameraBottom, "shadow-camera-left": shadowCameraLeft, "shadow-camera-right": shadowCameraRight, "shadow-bias": shadowBias, "shadow-normalBias": shadowNormalBias, "shadow-autoUpdate": shadowAutoUpdate }, lightInstanceKey), _jsx("object3D", { ref: targetRef, position: targetOffset }), editMode && isSelected && (_jsxs(_Fragment, { children: [_jsxs("mesh", { children: [_jsx("sphereGeometry", { args: [0.3, 8, 6] }), _jsx("meshBasicMaterial", { color: color, wireframe: true })] }), _jsxs("mesh", { position: targetOffset, children: [_jsx("sphereGeometry", { args: [0.2, 8, 6] }), _jsx("meshBasicMaterial", { color: color, wireframe: true, opacity: 0.5, transparent: true })] }), _jsxs("line", { children: [_jsx("bufferGeometry", { onUpdate: (geo) => {
164
+ return (_jsxs(_Fragment, { children: [_jsx("directionalLight", { ref: directionalLightRef, color: color, intensity: intensity, castShadow: castShadow, "shadow-mapSize-width": shadowMapSize, "shadow-mapSize-height": shadowMapSize, "shadow-camera-near": shadowCameraNear, "shadow-camera-far": shadowCameraFar, "shadow-camera-top": shadowCameraTop, "shadow-camera-bottom": shadowCameraBottom, "shadow-camera-left": shadowCameraLeft, "shadow-camera-right": shadowCameraRight, "shadow-bias": shadowBias, "shadow-normalBias": shadowNormalBias, "shadow-autoUpdate": shadowAutoUpdate }), _jsx("object3D", { ref: targetRef, position: targetOffset }), editMode && isSelected && (_jsxs(_Fragment, { children: [_jsxs("mesh", { children: [_jsx("sphereGeometry", { args: [0.3, 8, 6] }), _jsx("meshBasicMaterial", { color: color, wireframe: true })] }), _jsxs("mesh", { position: targetOffset, children: [_jsx("sphereGeometry", { args: [0.2, 8, 6] }), _jsx("meshBasicMaterial", { color: color, wireframe: true, opacity: 0.5, transparent: true })] }), _jsxs("line", { children: [_jsx("bufferGeometry", { onUpdate: (geo) => {
166
165
  const points = [
167
166
  new Vector3(0, 0, 0),
168
167
  new Vector3(targetOffset[0], targetOffset[1], targetOffset[2])
@@ -36,7 +36,6 @@ function PointLightView({ properties, children }) {
36
36
  const shadowAutoUpdate = merged.shadowAutoUpdate;
37
37
  const shadowCameraNear = merged.shadowCameraNear;
38
38
  const shadowCameraFar = merged.shadowCameraFar;
39
- const lightInstanceKey = castShadow ? 'shadow-on' : 'shadow-off';
40
39
  const lightRef = useRef(null);
41
40
  useHelper(editMode && isSelected ? lightRef : null, PointLightHelper, 0.5, color);
42
41
  useEffect(() => {
@@ -47,7 +46,7 @@ function PointLightView({ properties, children }) {
47
46
  shadow.needsUpdate = true;
48
47
  shadow.camera.updateProjectionMatrix();
49
48
  }, [castShadow, shadowMapSize, shadowBias, shadowNormalBias, shadowAutoUpdate, shadowCameraNear, shadowCameraFar]);
50
- return (_jsxs(_Fragment, { children: [_jsx("pointLight", { ref: lightRef, color: color, intensity: intensity, distance: distance, decay: decay, castShadow: castShadow, "shadow-mapSize-width": shadowMapSize, "shadow-mapSize-height": shadowMapSize, "shadow-bias": shadowBias, "shadow-normalBias": shadowNormalBias, "shadow-autoUpdate": shadowAutoUpdate, "shadow-camera-near": shadowCameraNear, "shadow-camera-far": shadowCameraFar }, lightInstanceKey), editMode && isSelected ? (_jsxs("mesh", { children: [_jsx("sphereGeometry", { args: [0.2, 10, 8] }), _jsx("meshBasicMaterial", { color: color, wireframe: true })] })) : null, children] }));
49
+ return (_jsxs(_Fragment, { children: [_jsx("pointLight", { ref: lightRef, color: color, intensity: intensity, distance: distance, decay: decay, castShadow: castShadow, "shadow-mapSize-width": shadowMapSize, "shadow-mapSize-height": shadowMapSize, "shadow-bias": shadowBias, "shadow-normalBias": shadowNormalBias, "shadow-autoUpdate": shadowAutoUpdate, "shadow-camera-near": shadowCameraNear, "shadow-camera-far": shadowCameraFar }), editMode && isSelected ? (_jsxs("mesh", { children: [_jsx("sphereGeometry", { args: [0.2, 10, 8] }), _jsx("meshBasicMaterial", { color: color, wireframe: true })] })) : null, children] }));
51
50
  }
52
51
  const PointLightComponent = {
53
52
  name: 'PointLight',
@@ -48,7 +48,6 @@ function SpotLightView({ properties, children }) {
48
48
  const shadowCameraFar = merged.shadowCameraFar;
49
49
  const targetOffset = merged.targetOffset;
50
50
  const textureMap = merged.map ? (_a = getTexture(merged.map)) !== null && _a !== void 0 ? _a : undefined : undefined;
51
- const lightInstanceKey = castShadow ? 'shadow-on' : 'shadow-off';
52
51
  const spotLightRef = useRef(null);
53
52
  const targetRef = useRef(null);
54
53
  useHelper(editMode && isSelected ? spotLightRef : null, SpotLightHelper, color);
@@ -71,7 +70,7 @@ function SpotLightView({ properties, children }) {
71
70
  spotLightRef.current.target.updateMatrixWorld();
72
71
  }
73
72
  });
74
- return (_jsxs(_Fragment, { children: [_jsx("spotLight", { ref: spotLightRef, color: color, intensity: intensity, angle: angle, penumbra: penumbra, distance: distance, decay: decay, map: textureMap, castShadow: castShadow, "shadow-mapSize-width": shadowMapSize, "shadow-mapSize-height": shadowMapSize, "shadow-bias": shadowBias, "shadow-normalBias": shadowNormalBias, "shadow-autoUpdate": shadowAutoUpdate, "shadow-camera-near": shadowCameraNear, "shadow-camera-far": shadowCameraFar }, lightInstanceKey), _jsx("object3D", { ref: targetRef, position: targetOffset }), editMode && isSelected && (_jsxs(_Fragment, { children: [_jsxs("mesh", { children: [_jsx("sphereGeometry", { args: [0.2, 8, 6] }), _jsx("meshBasicMaterial", { color: color, wireframe: true })] }), _jsxs("mesh", { position: targetOffset, children: [_jsx("sphereGeometry", { args: [0.15, 8, 6] }), _jsx("meshBasicMaterial", { color: color, wireframe: true, opacity: 0.5, transparent: true })] })] })), children] }));
73
+ return (_jsxs(_Fragment, { children: [_jsx("spotLight", { ref: spotLightRef, color: color, intensity: intensity, angle: angle, penumbra: penumbra, distance: distance, decay: decay, map: textureMap, castShadow: castShadow, "shadow-mapSize-width": shadowMapSize, "shadow-mapSize-height": shadowMapSize, "shadow-bias": shadowBias, "shadow-normalBias": shadowNormalBias, "shadow-autoUpdate": shadowAutoUpdate, "shadow-camera-near": shadowCameraNear, "shadow-camera-far": shadowCameraFar }), _jsx("object3D", { ref: targetRef, position: targetOffset }), editMode && isSelected && (_jsxs(_Fragment, { children: [_jsxs("mesh", { children: [_jsx("sphereGeometry", { args: [0.2, 8, 6] }), _jsx("meshBasicMaterial", { color: color, wireframe: true })] }), _jsxs("mesh", { position: targetOffset, children: [_jsx("sphereGeometry", { args: [0.15, 8, 6] }), _jsx("meshBasicMaterial", { color: color, wireframe: true, opacity: 0.5, transparent: true })] })] })), children] }));
75
74
  }
76
75
  const SpotLightComponent = {
77
76
  name: 'SpotLight',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-three-game",
3
- "version": "0.0.77",
3
+ "version": "0.0.78",
4
4
  "description": "high performance 3D game engine built in React",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -48,7 +48,6 @@
48
48
  "vite": "^7.3.1"
49
49
  },
50
50
  "dependencies": {
51
- "react-error-boundary": "^6.1.0",
52
51
  "zustand": "^5.0.12"
53
52
  }
54
53
  }