react-three-game 0.0.19 → 0.0.20

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,9 +1,10 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { Canvas, useLoader } from "@react-three/fiber";
4
- import { OrbitControls, useGLTF, useFBX, Stage, View, PerspectiveCamera } from "@react-three/drei";
4
+ import { OrbitControls, Stage, View, PerspectiveCamera } from "@react-three/drei";
5
5
  import { Suspense, useEffect, useState, useRef } from "react";
6
6
  import { TextureLoader } from "three";
7
+ import { loadModel } from "../dragdrop/modelLoader";
7
8
  // view models and textures in manifest, onselect callback
8
9
  function getItemsInPath(files, currentPath) {
9
10
  // Remove the leading category folder (e.g., /textures/, /models/, /sounds/)
@@ -100,18 +101,28 @@ function ModelCard({ file, onSelect, basePath = "" }) {
100
101
  return (_jsxs("div", { ref: ref, className: "aspect-square bg-gray-900 cursor-pointer hover:bg-gray-800 flex flex-col", onClick: () => onSelect(file), children: [_jsx("div", { className: "flex-1 relative", children: isInView ? (_jsxs(View, { className: "w-full h-full", children: [_jsx(PerspectiveCamera, { makeDefault: true, position: [0, 1, 3], fov: 50 }), _jsxs(Suspense, { fallback: null, children: [_jsx(Stage, { intensity: 0.5, environment: "city", children: _jsx(ModelPreview, { url: fullPath, onError: () => setError(true) }) }), _jsx(OrbitControls, { enableZoom: false })] })] })) : null }), _jsx("div", { className: "bg-black/60 text-[10px] px-1 truncate text-center", children: file.split('/').pop() })] }));
101
102
  }
102
103
  function ModelPreview({ url, onError }) {
103
- const isFbx = url.toLowerCase().endsWith('.fbx');
104
- if (isFbx)
105
- return _jsx(FBXModel, { url: url, onError: onError });
106
- return _jsx(GLTFModel, { url: url, onError: onError });
107
- }
108
- function GLTFModel({ url, onError }) {
109
- const { scene } = useGLTF(url);
110
- return _jsx("primitive", { object: scene });
111
- }
112
- function FBXModel({ url, onError }) {
113
- const fbx = useFBX(url);
114
- return _jsx("primitive", { object: fbx, scale: 0.01 });
104
+ const [model, setModel] = useState(null);
105
+ const onErrorRef = useRef(onError);
106
+ onErrorRef.current = onError;
107
+ useEffect(() => {
108
+ let cancelled = false;
109
+ setModel(null);
110
+ loadModel(url).then((result) => {
111
+ var _a;
112
+ if (cancelled)
113
+ return;
114
+ if (result.success && result.model) {
115
+ setModel(result.model);
116
+ }
117
+ else {
118
+ (_a = onErrorRef.current) === null || _a === void 0 ? void 0 : _a.call(onErrorRef);
119
+ }
120
+ });
121
+ return () => { cancelled = true; };
122
+ }, [url]);
123
+ if (!model)
124
+ return null;
125
+ return _jsx("primitive", { object: model });
115
126
  }
116
127
  export function SoundListViewer({ files, selected, onSelect, basePath = "" }) {
117
128
  return (_jsx(AssetListViewer, { files: files, selected: selected, onSelect: onSelect, renderCard: (file, onSelectHandler) => (_jsx(SoundCard, { file: file, basePath: basePath, onSelect: onSelectHandler })) }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-three-game",
3
- "version": "0.0.19",
3
+ "version": "0.0.20",
4
4
  "description": "Batteries included React Three Fiber game engine",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -15,10 +15,12 @@
15
15
  "author": "prnth",
16
16
  "license": "VPL",
17
17
  "type": "module",
18
- "workspaces": ["docs"],
18
+ "workspaces": [
19
+ "docs"
20
+ ],
19
21
  "peerDependencies": {
20
- "@react-three/fiber": ">=9.0.0",
21
22
  "@react-three/drei": ">=10.0.0",
23
+ "@react-three/fiber": ">=9.0.0",
22
24
  "@react-three/rapier": ">=2.0.0",
23
25
  "react": ">=18.0.0",
24
26
  "react-dom": ">=18.0.0",
@@ -36,5 +38,8 @@
36
38
  "react-dom": "^19.2.0",
37
39
  "three": "^0.182.0",
38
40
  "typescript": "^5.9.3"
41
+ },
42
+ "dependencies": {
43
+ "react-error-boundary": "^6.0.0"
39
44
  }
40
45
  }
@@ -1,9 +1,10 @@
1
1
  "use client";
2
2
 
3
3
  import { Canvas, useLoader } from "@react-three/fiber";
4
- import { OrbitControls, useGLTF, useFBX, Stage, View, PerspectiveCamera } from "@react-three/drei";
4
+ import { OrbitControls, Stage, View, PerspectiveCamera } from "@react-three/drei";
5
5
  import { Suspense, useEffect, useState, useRef } from "react";
6
6
  import { TextureLoader } from "three";
7
+ import { loadModel } from "../dragdrop/modelLoader";
7
8
 
8
9
  // view models and textures in manifest, onselect callback
9
10
 
@@ -290,19 +291,28 @@ function ModelCard({ file, onSelect, basePath = "" }: { file: string; onSelect:
290
291
  }
291
292
 
292
293
  function ModelPreview({ url, onError }: { url: string; onError?: () => void }) {
293
- const isFbx = url.toLowerCase().endsWith('.fbx');
294
- if (isFbx) return <FBXModel url={url} onError={onError} />;
295
- return <GLTFModel url={url} onError={onError} />;
296
- }
294
+ const [model, setModel] = useState<any>(null);
295
+ const onErrorRef = useRef(onError);
296
+ onErrorRef.current = onError;
297
297
 
298
- function GLTFModel({ url, onError }: { url: string; onError?: () => void }) {
299
- const { scene } = useGLTF(url);
300
- return <primitive object={scene} />;
301
- }
298
+ useEffect(() => {
299
+ let cancelled = false;
300
+ setModel(null);
301
+
302
+ loadModel(url).then((result) => {
303
+ if (cancelled) return;
304
+ if (result.success && result.model) {
305
+ setModel(result.model);
306
+ } else {
307
+ onErrorRef.current?.();
308
+ }
309
+ });
310
+
311
+ return () => { cancelled = true; };
312
+ }, [url]);
302
313
 
303
- function FBXModel({ url, onError }: { url: string; onError?: () => void }) {
304
- const fbx = useFBX(url);
305
- return <primitive object={fbx} scale={0.01} />;
314
+ if (!model) return null;
315
+ return <primitive object={model} />;
306
316
  }
307
317
 
308
318
  interface SoundListViewerProps {