react-three-game 0.0.60 → 0.0.61

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 (58) hide show
  1. package/package.json +9 -3
  2. package/.gitattributes +0 -2
  3. package/.github/copilot-instructions.md +0 -83
  4. package/.github/workflows/nextjs.yml +0 -99
  5. package/.gitmodules +0 -3
  6. package/assets/architecture.png +0 -0
  7. package/assets/editor.gif +0 -0
  8. package/assets/favicon.ico +0 -0
  9. package/assets/react-three-game-logo.png +0 -0
  10. package/dist/tools/dragdrop/page.d.ts +0 -1
  11. package/dist/tools/dragdrop/page.js +0 -11
  12. package/dist/tools/prefabeditor/EntityEvents.d.ts +0 -54
  13. package/dist/tools/prefabeditor/EntityEvents.js +0 -85
  14. package/dist/tools/prefabeditor/page.d.ts +0 -1
  15. package/dist/tools/prefabeditor/page.js +0 -5
  16. package/react-three-game-skill/.gitattributes +0 -2
  17. package/react-three-game-skill/README.md +0 -7
  18. package/react-three-game-skill/react-three-game/SKILL.md +0 -514
  19. package/react-three-game-skill/react-three-game/rules/ADVANCED_PHYSICS.md +0 -472
  20. package/react-three-game-skill/react-three-game/rules/LIGHTING.md +0 -6
  21. package/src/helpers/SoundManager.ts +0 -130
  22. package/src/helpers/index.ts +0 -91
  23. package/src/index.ts +0 -59
  24. package/src/shared/ContactShadow.tsx +0 -74
  25. package/src/shared/GameCanvas.tsx +0 -52
  26. package/src/tools/assetviewer/page.tsx +0 -425
  27. package/src/tools/dragdrop/DragDropLoader.tsx +0 -159
  28. package/src/tools/dragdrop/index.ts +0 -4
  29. package/src/tools/dragdrop/modelLoader.ts +0 -204
  30. package/src/tools/dragdrop/page.tsx +0 -45
  31. package/src/tools/prefabeditor/Dropdown.tsx +0 -112
  32. package/src/tools/prefabeditor/EditorContext.tsx +0 -25
  33. package/src/tools/prefabeditor/EditorTree.tsx +0 -452
  34. package/src/tools/prefabeditor/EditorTreeMenus.tsx +0 -307
  35. package/src/tools/prefabeditor/EditorUI.tsx +0 -204
  36. package/src/tools/prefabeditor/EventSystem.tsx +0 -36
  37. package/src/tools/prefabeditor/GameEvents.ts +0 -191
  38. package/src/tools/prefabeditor/InstanceProvider.tsx +0 -466
  39. package/src/tools/prefabeditor/PrefabEditor.tsx +0 -256
  40. package/src/tools/prefabeditor/PrefabRoot.tsx +0 -767
  41. package/src/tools/prefabeditor/components/AmbientLightComponent.tsx +0 -34
  42. package/src/tools/prefabeditor/components/CameraComponent.tsx +0 -117
  43. package/src/tools/prefabeditor/components/ComponentRegistry.ts +0 -40
  44. package/src/tools/prefabeditor/components/DirectionalLightComponent.tsx +0 -210
  45. package/src/tools/prefabeditor/components/EnvironmentComponent.tsx +0 -47
  46. package/src/tools/prefabeditor/components/GeometryComponent.tsx +0 -133
  47. package/src/tools/prefabeditor/components/Input.tsx +0 -820
  48. package/src/tools/prefabeditor/components/MaterialComponent.tsx +0 -431
  49. package/src/tools/prefabeditor/components/ModelComponent.tsx +0 -176
  50. package/src/tools/prefabeditor/components/PhysicsComponent.tsx +0 -188
  51. package/src/tools/prefabeditor/components/SpotLightComponent.tsx +0 -109
  52. package/src/tools/prefabeditor/components/TextComponent.tsx +0 -137
  53. package/src/tools/prefabeditor/components/TransformComponent.tsx +0 -173
  54. package/src/tools/prefabeditor/components/index.ts +0 -26
  55. package/src/tools/prefabeditor/page.tsx +0 -10
  56. package/src/tools/prefabeditor/styles.ts +0 -235
  57. package/src/tools/prefabeditor/types.ts +0 -20
  58. 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;