react-three-game 0.0.60 → 0.0.62

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 (66) hide show
  1. package/README.md +56 -0
  2. package/dist/index.d.ts +1 -1
  3. package/dist/shared/GameCanvas.d.ts +2 -1
  4. package/dist/shared/GameCanvas.js +7 -2
  5. package/dist/tools/prefabeditor/PrefabEditor.d.ts +18 -4
  6. package/dist/tools/prefabeditor/PrefabEditor.js +90 -36
  7. package/dist/tools/prefabeditor/utils.d.ts +2 -0
  8. package/dist/tools/prefabeditor/utils.js +15 -0
  9. package/package.json +9 -3
  10. package/.gitattributes +0 -2
  11. package/.github/copilot-instructions.md +0 -83
  12. package/.github/workflows/nextjs.yml +0 -99
  13. package/.gitmodules +0 -3
  14. package/assets/architecture.png +0 -0
  15. package/assets/editor.gif +0 -0
  16. package/assets/favicon.ico +0 -0
  17. package/assets/react-three-game-logo.png +0 -0
  18. package/dist/tools/dragdrop/page.d.ts +0 -1
  19. package/dist/tools/dragdrop/page.js +0 -11
  20. package/dist/tools/prefabeditor/EntityEvents.d.ts +0 -54
  21. package/dist/tools/prefabeditor/EntityEvents.js +0 -85
  22. package/dist/tools/prefabeditor/page.d.ts +0 -1
  23. package/dist/tools/prefabeditor/page.js +0 -5
  24. package/react-three-game-skill/.gitattributes +0 -2
  25. package/react-three-game-skill/README.md +0 -7
  26. package/react-three-game-skill/react-three-game/SKILL.md +0 -514
  27. package/react-three-game-skill/react-three-game/rules/ADVANCED_PHYSICS.md +0 -472
  28. package/react-three-game-skill/react-three-game/rules/LIGHTING.md +0 -6
  29. package/src/helpers/SoundManager.ts +0 -130
  30. package/src/helpers/index.ts +0 -91
  31. package/src/index.ts +0 -59
  32. package/src/shared/ContactShadow.tsx +0 -74
  33. package/src/shared/GameCanvas.tsx +0 -52
  34. package/src/tools/assetviewer/page.tsx +0 -425
  35. package/src/tools/dragdrop/DragDropLoader.tsx +0 -159
  36. package/src/tools/dragdrop/index.ts +0 -4
  37. package/src/tools/dragdrop/modelLoader.ts +0 -204
  38. package/src/tools/dragdrop/page.tsx +0 -45
  39. package/src/tools/prefabeditor/Dropdown.tsx +0 -112
  40. package/src/tools/prefabeditor/EditorContext.tsx +0 -25
  41. package/src/tools/prefabeditor/EditorTree.tsx +0 -452
  42. package/src/tools/prefabeditor/EditorTreeMenus.tsx +0 -307
  43. package/src/tools/prefabeditor/EditorUI.tsx +0 -204
  44. package/src/tools/prefabeditor/EventSystem.tsx +0 -36
  45. package/src/tools/prefabeditor/GameEvents.ts +0 -191
  46. package/src/tools/prefabeditor/InstanceProvider.tsx +0 -466
  47. package/src/tools/prefabeditor/PrefabEditor.tsx +0 -256
  48. package/src/tools/prefabeditor/PrefabRoot.tsx +0 -767
  49. package/src/tools/prefabeditor/components/AmbientLightComponent.tsx +0 -34
  50. package/src/tools/prefabeditor/components/CameraComponent.tsx +0 -117
  51. package/src/tools/prefabeditor/components/ComponentRegistry.ts +0 -40
  52. package/src/tools/prefabeditor/components/DirectionalLightComponent.tsx +0 -210
  53. package/src/tools/prefabeditor/components/EnvironmentComponent.tsx +0 -47
  54. package/src/tools/prefabeditor/components/GeometryComponent.tsx +0 -133
  55. package/src/tools/prefabeditor/components/Input.tsx +0 -820
  56. package/src/tools/prefabeditor/components/MaterialComponent.tsx +0 -431
  57. package/src/tools/prefabeditor/components/ModelComponent.tsx +0 -176
  58. package/src/tools/prefabeditor/components/PhysicsComponent.tsx +0 -188
  59. package/src/tools/prefabeditor/components/SpotLightComponent.tsx +0 -109
  60. package/src/tools/prefabeditor/components/TextComponent.tsx +0 -137
  61. package/src/tools/prefabeditor/components/TransformComponent.tsx +0 -173
  62. package/src/tools/prefabeditor/components/index.ts +0 -26
  63. package/src/tools/prefabeditor/page.tsx +0 -10
  64. package/src/tools/prefabeditor/styles.ts +0 -235
  65. package/src/tools/prefabeditor/types.ts +0 -20
  66. package/src/tools/prefabeditor/utils.ts +0 -312
@@ -1,256 +0,0 @@
1
- import GameCanvas from "../../shared/GameCanvas";
2
- import { useState, useRef, useEffect, forwardRef, useImperativeHandle } from "react";
3
- import { Prefab } from "./types";
4
- import PrefabRoot, { PrefabRootRef } from "./PrefabRoot";
5
- import { Physics } from "@react-three/rapier";
6
- import EditorUI from "./EditorUI";
7
- import { base, toolbar } from "./styles";
8
- import { EditorContext } from "./EditorContext";
9
- import { exportGLB, createModelNode, createImageNode } from "./utils";
10
- import { loadFiles } from "../dragdrop";
11
-
12
- export interface PrefabEditorRef {
13
- screenshot: () => void;
14
- exportGLB: () => void;
15
- prefab: Prefab;
16
- setPrefab: (prefab: Prefab) => void;
17
- rootRef: React.RefObject<PrefabRootRef | null>;
18
- }
19
-
20
- const DEFAULT_PREFAB: Prefab = {
21
- id: "prefab-default",
22
- name: "New Prefab",
23
- root: {
24
- id: "root",
25
- components: {
26
- transform: {
27
- type: "Transform",
28
- properties: { position: [0, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1] }
29
- }
30
- }
31
- }
32
- };
33
-
34
- const PrefabEditor = forwardRef<PrefabEditorRef, {
35
- basePath?: string;
36
- initialPrefab?: Prefab;
37
- physics?: boolean;
38
- onPrefabChange?: (prefab: Prefab) => void;
39
- uiPlugins?: React.ReactNode[] | React.ReactNode;
40
- children?: React.ReactNode;
41
- }>(({ basePath, initialPrefab, physics = true, onPrefabChange, uiPlugins, children }, ref) => {
42
- const [editMode, setEditMode] = useState(true);
43
- const [loadedPrefab, setLoadedPrefab] = useState<Prefab>(initialPrefab ?? DEFAULT_PREFAB);
44
- const [selectedId, setSelectedId] = useState<string | null>(null);
45
- const [transformMode, setTransformMode] = useState<"translate" | "rotate" | "scale">("translate");
46
- const [snapResolution, setSnapResolution] = useState(0);
47
- const [positionSnap, setPositionSnap] = useState(0.5);
48
- const [rotationSnap, setRotationSnap] = useState(Math.PI / 4);
49
- const [history, setHistory] = useState<Prefab[]>([loadedPrefab]);
50
- const [historyIndex, setHistoryIndex] = useState(0);
51
- const throttleRef = useRef<NodeJS.Timeout | null>(null);
52
- const lastDataRef = useRef(JSON.stringify(loadedPrefab));
53
- const prefabRootRef = useRef<PrefabRootRef>(null);
54
- const canvasRef = useRef<HTMLCanvasElement | null>(null);
55
-
56
- useEffect(() => {
57
- if (initialPrefab) setLoadedPrefab(initialPrefab);
58
- }, [initialPrefab]);
59
-
60
- const updatePrefab = (newPrefab: Prefab | ((prev: Prefab) => Prefab)) => {
61
- setLoadedPrefab(newPrefab);
62
- const resolved = typeof newPrefab === 'function' ? newPrefab(loadedPrefab) : newPrefab;
63
- onPrefabChange?.(resolved);
64
- };
65
-
66
- const applyHistory = (index: number) => {
67
- setHistoryIndex(index);
68
- lastDataRef.current = JSON.stringify(history[index]);
69
- setLoadedPrefab(history[index]);
70
- onPrefabChange?.(history[index]);
71
- };
72
-
73
- const undo = () => historyIndex > 0 && applyHistory(historyIndex - 1);
74
- const redo = () => historyIndex < history.length - 1 && applyHistory(historyIndex + 1);
75
-
76
- useEffect(() => {
77
- const handleKeyDown = (e: KeyboardEvent) => {
78
- if (!(e.ctrlKey || e.metaKey)) return;
79
- if (e.key === 'z' && !e.shiftKey) { e.preventDefault(); undo(); }
80
- else if ((e.shiftKey && e.key === 'z') || e.key === 'y') { e.preventDefault(); redo(); }
81
- };
82
- window.addEventListener('keydown', handleKeyDown);
83
- return () => window.removeEventListener('keydown', handleKeyDown);
84
- }, [historyIndex, history]);
85
-
86
- useEffect(() => {
87
- const currentStr = JSON.stringify(loadedPrefab);
88
- if (currentStr === lastDataRef.current) return;
89
- if (throttleRef.current) clearTimeout(throttleRef.current);
90
-
91
- throttleRef.current = setTimeout(() => {
92
- lastDataRef.current = currentStr;
93
- setHistory(prev => {
94
- const newHistory = [...prev.slice(0, historyIndex + 1), loadedPrefab];
95
- return newHistory.length > 50 ? newHistory.slice(1) : newHistory;
96
- });
97
- setHistoryIndex(prev => Math.min(prev + 1, 49));
98
- }, 500);
99
-
100
- return () => { if (throttleRef.current) clearTimeout(throttleRef.current); };
101
- }, [loadedPrefab]);
102
-
103
- const handleScreenshot = () => {
104
- const canvas = canvasRef.current;
105
- if (!canvas) return;
106
-
107
- canvas.toBlob((blob) => {
108
- if (!blob) return;
109
- const url = URL.createObjectURL(blob);
110
- const a = document.createElement('a');
111
- a.href = url;
112
- a.download = `${loadedPrefab.name || 'screenshot'}.png`;
113
- a.click();
114
- URL.revokeObjectURL(url);
115
- });
116
- };
117
-
118
- const handleExportGLB = () => {
119
- const sceneRoot = prefabRootRef.current?.root;
120
- if (!sceneRoot) return;
121
-
122
- exportGLB(sceneRoot, {
123
- filename: `${loadedPrefab.name || 'scene'}.glb`
124
- });
125
- };
126
-
127
- const handleFocusNode = (nodeId: string) => {
128
- prefabRootRef.current?.focusNode(nodeId);
129
- };
130
-
131
- useEffect(() => {
132
- const canvas = document.querySelector('canvas');
133
- if (canvas) canvasRef.current = canvas;
134
- }, []);
135
-
136
- // --- Drag & drop files to add nodes ---
137
- useEffect(() => {
138
- function handleDragOver(e: DragEvent) {
139
- e.preventDefault();
140
- e.stopPropagation();
141
- }
142
-
143
- function handleDrop(e: DragEvent) {
144
- e.preventDefault();
145
- e.stopPropagation();
146
-
147
- const files = e.dataTransfer?.files ? Array.from(e.dataTransfer.files) : [];
148
-
149
- void loadFiles(files, {
150
- onModelLoaded: (model, filename) => {
151
- const modelPath = `models/${filename}`;
152
- const baseName = filename.replace(/\.[^.]+$/, '');
153
- const newNode = createModelNode(modelPath, baseName);
154
-
155
- updatePrefab(prev => ({
156
- ...prev,
157
- root: { ...prev.root, children: [...(prev.root.children ?? []), newNode] }
158
- }));
159
-
160
- prefabRootRef.current?.injectModel(modelPath, model);
161
- },
162
- onTextureLoaded: (texture, filename) => {
163
- const texturePath = `textures/${filename}`;
164
- const baseName = filename.replace(/\.[^.]+$/, '');
165
- const newNode = createImageNode(texturePath, baseName);
166
-
167
- updatePrefab(prev => ({
168
- ...prev,
169
- root: { ...prev.root, children: [...(prev.root.children ?? []), newNode] }
170
- }));
171
-
172
- prefabRootRef.current?.injectTexture(texturePath, texture);
173
- },
174
- onLoadError: error => {
175
- console.error('Drop asset error:', error);
176
- },
177
- });
178
- }
179
-
180
- window.addEventListener('dragover', handleDragOver);
181
- window.addEventListener('drop', handleDrop);
182
- return () => {
183
- window.removeEventListener('dragover', handleDragOver);
184
- window.removeEventListener('drop', handleDrop);
185
- };
186
- }, [loadedPrefab]);
187
-
188
- useImperativeHandle(ref, () => ({
189
- screenshot: handleScreenshot,
190
- exportGLB: handleExportGLB,
191
- prefab: loadedPrefab,
192
- setPrefab: setLoadedPrefab,
193
- rootRef: prefabRootRef
194
- }), [loadedPrefab]);
195
-
196
- const content = (
197
- <>
198
- <ambientLight intensity={1.5} />
199
- <gridHelper args={[10, 10]} position={[0, -1, 0]} />
200
- <PrefabRoot
201
- ref={prefabRootRef}
202
- data={loadedPrefab}
203
- editMode={editMode}
204
- onPrefabChange={updatePrefab}
205
- selectedId={selectedId}
206
- onSelect={setSelectedId}
207
- basePath={basePath}
208
- />
209
- {children}
210
- </>
211
- );
212
-
213
- return <EditorContext.Provider value={{
214
- transformMode,
215
- setTransformMode,
216
- snapResolution,
217
- setSnapResolution,
218
- positionSnap,
219
- setPositionSnap,
220
- rotationSnap,
221
- setRotationSnap,
222
- onFocusNode: handleFocusNode,
223
- onScreenshot: handleScreenshot,
224
- onExportGLB: handleExportGLB
225
- }}>
226
- <GameCanvas camera={{ position: [0, 5, 15] }}>
227
- {physics ? (
228
- <Physics debug={editMode} paused={editMode}>
229
- {content}
230
- </Physics>
231
- ) : content}
232
- </GameCanvas>
233
-
234
- <div style={toolbar.panel}>
235
- <button style={base.btn} onClick={() => setEditMode(!editMode)}>
236
- {editMode ? "▶" : "⏸"}
237
- </button>
238
- {uiPlugins}
239
- </div>
240
- <EditorUI
241
- prefabData={loadedPrefab}
242
- setPrefabData={updatePrefab}
243
- selectedId={selectedId}
244
- setSelectedId={setSelectedId}
245
- basePath={basePath}
246
- onUndo={undo}
247
- onRedo={redo}
248
- canUndo={historyIndex > 0}
249
- canRedo={historyIndex < history.length - 1}
250
- />
251
- </EditorContext.Provider>
252
- });
253
-
254
- PrefabEditor.displayName = "PrefabEditor";
255
-
256
- export default PrefabEditor;