@chocodrop/mcp 0.1.0-alpha.0

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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +19 -0
  3. package/bin/chocodrop-mcp.js +13 -0
  4. package/package.json +42 -0
  5. package/runtime/.chocodrop-mcp-runtime +1 -0
  6. package/runtime/asset-bridge.js +460 -0
  7. package/runtime/mcp-server.js +107 -0
  8. package/runtime/site/examples/basic/README.md +38 -0
  9. package/runtime/site/examples/basic/index.html +1730 -0
  10. package/runtime/site/examples/bookmarklet-v2.html +141 -0
  11. package/runtime/site/examples/bookmarklet.html +126 -0
  12. package/runtime/site/examples/lofi-room/index.html +2570 -0
  13. package/runtime/site/examples/lofi-room/sandbox-lite.html +124 -0
  14. package/runtime/site/examples/music-garden/index.html +2150 -0
  15. package/runtime/site/examples/pixel-ocean/index.html +1780 -0
  16. package/runtime/site/examples/react-three-fiber/AdvancedExample.jsx +338 -0
  17. package/runtime/site/examples/react-three-fiber/App.jsx +97 -0
  18. package/runtime/site/examples/react-three-fiber/README.md +294 -0
  19. package/runtime/site/examples/react-three-fiber/package.json +25 -0
  20. package/runtime/site/examples/sdk-test/README.md +70 -0
  21. package/runtime/site/examples/space/index.html +1975 -0
  22. package/runtime/site/examples/toy-city/index.html +2288 -0
  23. package/runtime/site/examples/wabi-sabi/index.html +2515 -0
  24. package/runtime/site/getting-started.html +84 -0
  25. package/runtime/site/index.html +1370 -0
  26. package/runtime/site/public/CommandUI.js +6341 -0
  27. package/runtime/site/public/LiveCommandClient.js +432 -0
  28. package/runtime/site/public/SceneManager.js +5493 -0
  29. package/runtime/site/public/bookmarklet.js +206 -0
  30. package/runtime/site/public/bootstrap.js +50 -0
  31. package/runtime/site/public/chocodrop-demo.umd.js +24020 -0
  32. package/runtime/site/public/chocodrop-demo.umd.min.js +24020 -0
  33. package/runtime/site/public/chocodrop.esm.js +2 -0
  34. package/runtime/site/public/html-sandbox/frame.js +865 -0
  35. package/runtime/site/public/icons/icon-192.png +0 -0
  36. package/runtime/site/public/icons/icon-512.png +0 -0
  37. package/runtime/site/public/icons/icon-maskable-512.png +0 -0
  38. package/runtime/site/public/immersive-launcher.js +175 -0
  39. package/runtime/site/public/immersive.html +165 -0
  40. package/runtime/site/public/index.html +1011 -0
  41. package/runtime/site/public/index.js +9 -0
  42. package/runtime/site/public/load-chocodrop.js +25 -0
  43. package/runtime/site/public/load-three.js +26 -0
  44. package/runtime/site/public/manifest.webmanifest +59 -0
  45. package/runtime/site/public/pwa-bootstrap.js +128 -0
  46. package/runtime/site/public/sample-card.svg +15 -0
  47. package/runtime/site/public/service-worker.js +117 -0
  48. package/runtime/site/public/translation-dictionary.js +257 -0
  49. package/runtime/site/public/xr/xr-ui.css +338 -0
  50. package/runtime/site/public/xr-viewer.html +263 -0
  51. package/runtime/site/src/client/local-bridge.js +83 -0
@@ -0,0 +1,338 @@
1
+ import React, { useRef, useEffect, useState } from 'react';
2
+ import * as THREE from 'three';
3
+ import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
4
+ import { SceneManager, CommandUI, createChocoDrop } from 'chocodrop';
5
+
6
+ /**
7
+ * React Three.js Scene with ChocoDrop integration
8
+ * This example demonstrates how to integrate ChocoDrop with React
9
+ */
10
+ const ChocoDropScene = () => {
11
+ const mountRef = useRef(null);
12
+ const sceneRef = useRef(null);
13
+ const rendererRef = useRef(null);
14
+ const cameraRef = useRef(null);
15
+ const controlsRef = useRef(null);
16
+ const sceneManagerRef = useRef(null);
17
+ const commandUIRef = useRef(null);
18
+ const animationIdRef = useRef(null);
19
+
20
+ const [isReady, setIsReady] = useState(false);
21
+ const [stats, setStats] = useState({
22
+ objects: 0,
23
+ commands: 0
24
+ });
25
+
26
+ useEffect(() => {
27
+ if (!mountRef.current) return;
28
+
29
+ // Scene setup
30
+ const scene = new THREE.Scene();
31
+ const camera = new THREE.PerspectiveCamera(
32
+ 75,
33
+ window.innerWidth / window.innerHeight,
34
+ 0.1,
35
+ 1000
36
+ );
37
+ const renderer = new THREE.WebGLRenderer({ antialias: true });
38
+
39
+ renderer.setSize(window.innerWidth, window.innerHeight);
40
+ renderer.shadowMap.enabled = true;
41
+ renderer.shadowMap.type = THREE.PCFSoftShadowMap;
42
+ renderer.setClearColor(0x87ceeb);
43
+
44
+ mountRef.current.appendChild(renderer.domElement);
45
+
46
+ // Environment setup
47
+ scene.fog = new THREE.Fog(0x87ceeb, 50, 200);
48
+
49
+ // Lighting
50
+ const ambientLight = new THREE.AmbientLight(0x404040, 0.6);
51
+ scene.add(ambientLight);
52
+
53
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
54
+ directionalLight.position.set(50, 50, 50);
55
+ directionalLight.castShadow = true;
56
+ scene.add(directionalLight);
57
+
58
+ // Ground
59
+ const groundGeometry = new THREE.PlaneGeometry(200, 200);
60
+ const groundMaterial = new THREE.MeshLambertMaterial({ color: 0x90ee90 });
61
+ const ground = new THREE.Mesh(groundGeometry, groundMaterial);
62
+ ground.rotation.x = -Math.PI / 2;
63
+ ground.receiveShadow = true;
64
+ scene.add(ground);
65
+
66
+ // Camera
67
+ camera.position.set(0, 10, 20);
68
+
69
+ // Controls
70
+ const controls = new OrbitControls(camera, renderer.domElement);
71
+ controls.enableDamping = true;
72
+ controls.dampingFactor = 0.05;
73
+
74
+ // ChocoDrop Integration
75
+ const sceneManager = new SceneManager(scene, {
76
+ camera,
77
+ renderer, // rendererを渡す
78
+ serverUrl: 'http://localhost:3011',
79
+ showLocationIndicator: true,
80
+ indicatorDuration: 2000,
81
+ enableMouseInteraction: true // マウス操作を明示的に有効化(オプション)
82
+ });
83
+
84
+ const commandUI = new CommandUI({
85
+ sceneManager,
86
+ activationKey: '@',
87
+ position: 'bottom-right',
88
+ onControlsToggle: (disabled) => {
89
+ controls.enabled = !disabled;
90
+ }
91
+ });
92
+
93
+ // Store refs
94
+ sceneRef.current = scene;
95
+ rendererRef.current = renderer;
96
+ cameraRef.current = camera;
97
+ controlsRef.current = controls;
98
+ sceneManagerRef.current = sceneManager;
99
+ commandUIRef.current = commandUI;
100
+
101
+ // Animation loop
102
+ const animate = () => {
103
+ animationIdRef.current = requestAnimationFrame(animate);
104
+
105
+ controls.update();
106
+ renderer.render(scene, camera);
107
+
108
+ // Update stats
109
+ const objects = sceneManager.getSpawnedObjects();
110
+ const commands = sceneManager.getCommandHistory();
111
+ setStats({
112
+ objects: objects.length,
113
+ commands: commands.length
114
+ });
115
+ };
116
+
117
+ animate();
118
+ setIsReady(true);
119
+
120
+ // Handle window resize
121
+ const handleResize = () => {
122
+ if (!camera || !renderer) return;
123
+
124
+ camera.aspect = window.innerWidth / window.innerHeight;
125
+ camera.updateProjectionMatrix();
126
+ renderer.setSize(window.innerWidth, window.innerHeight);
127
+ };
128
+
129
+ window.addEventListener('resize', handleResize);
130
+
131
+ // Cleanup
132
+ return () => {
133
+ window.removeEventListener('resize', handleResize);
134
+
135
+ if (animationIdRef.current) {
136
+ cancelAnimationFrame(animationIdRef.current);
137
+ }
138
+
139
+ if (commandUI) {
140
+ commandUI.dispose();
141
+ }
142
+
143
+ if (sceneManager) {
144
+ sceneManager.dispose();
145
+ }
146
+
147
+ if (controls) {
148
+ controls.dispose();
149
+ }
150
+
151
+ if (renderer) {
152
+ renderer.dispose();
153
+ }
154
+
155
+ if (mountRef.current && renderer) {
156
+ mountRef.current.removeChild(renderer.domElement);
157
+ }
158
+ };
159
+ }, []);
160
+
161
+ const clearAllObjects = () => {
162
+ if (sceneManagerRef.current) {
163
+ sceneManagerRef.current.clearAll();
164
+ }
165
+ };
166
+
167
+ const showCommandHistory = () => {
168
+ if (commandUIRef.current) {
169
+ commandUIRef.current.showHistory();
170
+ }
171
+ };
172
+
173
+ const showExamples = () => {
174
+ if (commandUIRef.current) {
175
+ commandUIRef.current.showExamples();
176
+ }
177
+ };
178
+
179
+ return (
180
+ <div className="live-command-scene">
181
+ {/* Control Panel */}
182
+ <div className="control-panel" style={{
183
+ position: 'fixed',
184
+ top: '10px',
185
+ left: '10px',
186
+ background: 'rgba(0, 0, 0, 0.8)',
187
+ color: 'white',
188
+ padding: '15px',
189
+ borderRadius: '8px',
190
+ fontFamily: 'monospace',
191
+ fontSize: '14px',
192
+ zIndex: 100
193
+ }}>
194
+ <h3 style={{ margin: '0 0 10px 0', color: '#4a90e2' }}>
195
+ 🧪 ChocoDrop
196
+ </h3>
197
+
198
+ <div style={{ marginBottom: '10px' }}>
199
+ <strong>Status:</strong> {isReady ? '🟢 Ready' : '🟡 Loading...'}
200
+ </div>
201
+
202
+ <div style={{ marginBottom: '10px' }}>
203
+ <strong>Objects:</strong> {stats.objects}<br/>
204
+ <strong>Commands:</strong> {stats.commands}
205
+ </div>
206
+
207
+ <div style={{ marginBottom: '15px' }}>
208
+ <strong>Activation:</strong> Press <code>@</code>
209
+ </div>
210
+
211
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '5px' }}>
212
+ <button
213
+ onClick={showExamples}
214
+ style={{
215
+ padding: '8px',
216
+ background: '#4a90e2',
217
+ border: 'none',
218
+ borderRadius: '4px',
219
+ color: 'white',
220
+ cursor: 'pointer',
221
+ fontSize: '12px'
222
+ }}
223
+ >
224
+ Show Examples
225
+ </button>
226
+
227
+ <button
228
+ onClick={showCommandHistory}
229
+ style={{
230
+ padding: '8px',
231
+ background: '#95a5a6',
232
+ border: 'none',
233
+ borderRadius: '4px',
234
+ color: 'white',
235
+ cursor: 'pointer',
236
+ fontSize: '12px'
237
+ }}
238
+ >
239
+ Show History
240
+ </button>
241
+
242
+ <button
243
+ onClick={clearAllObjects}
244
+ style={{
245
+ padding: '8px',
246
+ background: '#e74c3c',
247
+ border: 'none',
248
+ borderRadius: '4px',
249
+ color: 'white',
250
+ cursor: 'pointer',
251
+ fontSize: '12px'
252
+ }}
253
+ >
254
+ Clear All
255
+ </button>
256
+ </div>
257
+ </div>
258
+
259
+ {/* Three.js mount point */}
260
+ <div
261
+ ref={mountRef}
262
+ style={{
263
+ width: '100vw',
264
+ height: '100vh',
265
+ overflow: 'hidden'
266
+ }}
267
+ />
268
+ </div>
269
+ );
270
+ };
271
+
272
+ /**
273
+ * Main App Component
274
+ */
275
+ const App = () => {
276
+ return (
277
+ <div className="app">
278
+ <ChocoDropScene />
279
+
280
+ {/* Instructions overlay */}
281
+ <div style={{
282
+ position: 'fixed',
283
+ bottom: '10px',
284
+ left: '10px',
285
+ background: 'rgba(0, 0, 0, 0.7)',
286
+ color: 'white',
287
+ padding: '10px',
288
+ borderRadius: '5px',
289
+ fontFamily: 'Arial, sans-serif',
290
+ fontSize: '12px',
291
+ maxWidth: '300px'
292
+ }}>
293
+ <strong>使用方法:</strong><br/>
294
+ • <code>@</code> キーでコマンド入力画面を表示<br/>
295
+ • 例: 「右上にドラゴンを作って」<br/>
296
+ • <code>Escape</code> でUI非表示<br/>
297
+ • マウスでカメラ操作
298
+ </div>
299
+ </div>
300
+ );
301
+ };
302
+
303
+ export default App;
304
+
305
+ // Usage instructions for package.json scripts:
306
+ /*
307
+ {
308
+ "name": "live-command-react-example",
309
+ "version": "1.0.0",
310
+ "type": "module",
311
+ "dependencies": {
312
+ "react": "^18.0.0",
313
+ "react-dom": "^18.0.0",
314
+ "three": "^0.158.0",
315
+ "chocodrop": "file:../",
316
+ "@vitejs/plugin-react": "^4.0.0",
317
+ "vite": "^4.0.0"
318
+ },
319
+ "scripts": {
320
+ "dev": "vite",
321
+ "build": "vite build",
322
+ "preview": "vite preview"
323
+ }
324
+ }
325
+ */
326
+
327
+ // Vite configuration (vite.config.js):
328
+ /*
329
+ import { defineConfig } from 'vite';
330
+ import react from '@vitejs/plugin-react';
331
+
332
+ export default defineConfig({
333
+ plugins: [react()],
334
+ server: {
335
+ port: 3000
336
+ }
337
+ });
338
+ */
@@ -0,0 +1,97 @@
1
+ import React, { useRef, useEffect } from 'react';
2
+ import { Canvas, useThree } from '@react-three/fiber';
3
+ import { OrbitControls, Box, Sphere } from '@react-three/drei';
4
+ import { createChocoDrop } from 'chocodrop';
5
+
6
+ /**
7
+ * ChocoDrop統合コンポーネント
8
+ * React Three Fiberのシーンに ChocoDrop を統合
9
+ */
10
+ function ChocoDropIntegration() {
11
+ const { scene, camera, gl } = useThree();
12
+ const chocoDropRef = useRef(null);
13
+ const controlsRef = useRef(null);
14
+
15
+ useEffect(() => {
16
+ // ChocoDrop初期化
17
+ const chocoDrop = createChocoDrop(scene, {
18
+ camera,
19
+ renderer: gl,
20
+ serverUrl: 'http://localhost:3011', // 省略可能(自動検出)
21
+ onControlsToggle: (disabled) => {
22
+ // UI開閉時にOrbitControlsを制御
23
+ if (controlsRef.current) {
24
+ controlsRef.current.enabled = !disabled;
25
+ }
26
+ }
27
+ });
28
+
29
+ chocoDropRef.current = chocoDrop;
30
+
31
+ // クリーンアップ
32
+ return () => {
33
+ chocoDrop.dispose();
34
+ };
35
+ }, [scene, camera, gl]);
36
+
37
+ return (
38
+ <>
39
+ {/* React Three Fiberのコントロール */}
40
+ <OrbitControls
41
+ ref={controlsRef}
42
+ enablePan={true}
43
+ enableZoom={true}
44
+ enableRotate={true}
45
+ />
46
+
47
+ {/* 既存の3Dオブジェクト */}
48
+ <ambientLight intensity={0.5} />
49
+ <pointLight position={[10, 10, 10]} />
50
+
51
+ <Box position={[-2, 0, 0]} onClick={() => console.log('Box clicked')}>
52
+ <meshStandardMaterial color="orange" />
53
+ </Box>
54
+
55
+ <Sphere position={[2, 0, 0]}>
56
+ <meshStandardMaterial color="hotpink" />
57
+ </Sphere>
58
+ </>
59
+ );
60
+ }
61
+
62
+ /**
63
+ * メインアプリケーション
64
+ */
65
+ function App() {
66
+ return (
67
+ <div style={{ width: '100vw', height: '100vh' }}>
68
+ <Canvas camera={{ position: [0, 0, 5] }}>
69
+ <ChocoDropIntegration />
70
+ </Canvas>
71
+
72
+ {/* 使用方法ガイド */}
73
+ <div style={{
74
+ position: 'fixed',
75
+ top: 10,
76
+ left: 10,
77
+ color: 'white',
78
+ backgroundColor: 'rgba(0, 0, 0, 0.7)',
79
+ padding: '10px',
80
+ borderRadius: '5px',
81
+ fontSize: '14px',
82
+ zIndex: 100
83
+ }}>
84
+ <h3>ChocoDrop + React Three Fiber</h3>
85
+ <p><strong>@キー</strong> - コマンドUI起動</p>
86
+ <p><strong>使用例:</strong></p>
87
+ <ul>
88
+ <li>"ドラゴンを右上に作って"</li>
89
+ <li>"桜を中央に配置"</li>
90
+ <li>"青い猫を左下に"</li>
91
+ </ul>
92
+ </div>
93
+ </div>
94
+ );
95
+ }
96
+
97
+ export default App;
@@ -0,0 +1,294 @@
1
+ # React Three Fiber + ChocoDrop
2
+
3
+ React Three Fiberプロジェクトに ChocoDrop を統合する例です。
4
+
5
+ ## 🚀 セットアップ
6
+
7
+ ### 1. 依存関係インストール
8
+
9
+ ```bash
10
+ npm install react react-dom
11
+ npm install @react-three/fiber @react-three/drei three
12
+ npm install chocodrop
13
+ ```
14
+
15
+ ### 2. 開発環境
16
+
17
+ ```bash
18
+ npm install -D vite @vitejs/plugin-react
19
+ ```
20
+
21
+ ### 3. Vite設定 (vite.config.js)
22
+
23
+ ```javascript
24
+ import { defineConfig } from 'vite';
25
+ import react from '@vitejs/plugin-react';
26
+
27
+ export default defineConfig({
28
+ plugins: [react()],
29
+ optimizeDeps: {
30
+ include: ['chocodrop']
31
+ }
32
+ });
33
+ ```
34
+
35
+ ## 🎮 使用方法
36
+
37
+ ### 基本統合
38
+
39
+ ```jsx
40
+ import { useThree } from '@react-three/fiber';
41
+ import { createChocoDrop } from 'chocodrop';
42
+
43
+ function ChocoDropIntegration() {
44
+ const { scene, camera, gl } = useThree();
45
+
46
+ useEffect(() => {
47
+ const chocoDrop = createChocoDrop(scene, {
48
+ camera,
49
+ renderer: gl,
50
+ onControlsToggle: (disabled) => {
51
+ // OrbitControls制御
52
+ controlsRef.current.enabled = !disabled;
53
+ }
54
+ });
55
+
56
+ return () => chocoDrop.dispose();
57
+ }, [scene, camera, gl]);
58
+
59
+ return <OrbitControls ref={controlsRef} />;
60
+ }
61
+ ```
62
+
63
+ ### フック化
64
+
65
+ ```jsx
66
+ import { useChocoDrop } from './hooks/useChocoDrop';
67
+
68
+ function Scene() {
69
+ const chocoDropRef = useChocoDrop({
70
+ serverUrl: 'http://localhost:3011'
71
+ });
72
+
73
+ const handleGenerateImage = async () => {
74
+ if (chocoDropRef.current) {
75
+ await chocoDropRef.current.client.generateImage('beautiful landscape');
76
+ }
77
+ };
78
+
79
+ return (
80
+ <>
81
+ <OrbitControls />
82
+ <button onClick={handleGenerateImage}>Generate Landscape</button>
83
+ </>
84
+ );
85
+ }
86
+ ```
87
+
88
+ ## 🔧 カスタムフック例
89
+
90
+ ### useChocoDrop.js
91
+
92
+ ```javascript
93
+ import { useRef, useEffect } from 'react';
94
+ import { useThree } from '@react-three/fiber';
95
+ import { createChocoDrop } from 'chocodrop';
96
+
97
+ export function useChocoDrop(options = {}) {
98
+ const { scene, camera, gl } = useThree();
99
+ const chocoDropRef = useRef(null);
100
+ const controlsRef = useRef(null);
101
+
102
+ useEffect(() => {
103
+ const chocoDrop = createChocoDrop(scene, {
104
+ camera,
105
+ renderer: gl,
106
+ onControlsToggle: (disabled) => {
107
+ if (controlsRef.current) {
108
+ controlsRef.current.enabled = !disabled;
109
+ }
110
+ },
111
+ ...options
112
+ });
113
+
114
+ chocoDropRef.current = chocoDrop;
115
+
116
+ return () => {
117
+ chocoDrop.dispose();
118
+ };
119
+ }, [scene, camera, gl]);
120
+
121
+ return { chocoDropRef, controlsRef };
122
+ }
123
+ ```
124
+
125
+ ## 🎨 統合パターン
126
+
127
+ ### 1. 基本統合
128
+
129
+ ```jsx
130
+ function App() {
131
+ return (
132
+ <Canvas>
133
+ <ChocoDropIntegration />
134
+ <Box position={[0, 0, 0]} />
135
+ </Canvas>
136
+ );
137
+ }
138
+ ```
139
+
140
+ ### 2. State管理統合
141
+
142
+ ```jsx
143
+ import { atom, useAtom } from 'jotai';
144
+
145
+ const chocoDropAtom = atom(null);
146
+
147
+ function Scene() {
148
+ const [chocoDrop, setChocoDrop] = useAtom(chocoDropAtom);
149
+ const { scene, camera, gl } = useThree();
150
+
151
+ useEffect(() => {
152
+ const instance = createChocoDrop(scene, { camera, renderer: gl });
153
+ setChocoDrop(instance);
154
+ return () => instance.dispose();
155
+ }, []);
156
+
157
+ return <OrbitControls />;
158
+ }
159
+ ```
160
+
161
+ ### 3. コンテキスト統合
162
+
163
+ ```jsx
164
+ const ChocoDropContext = createContext(null);
165
+
166
+ export function ChocoDropProvider({ children }) {
167
+ const [chocoDrop, setChocoDrop] = useState(null);
168
+
169
+ return (
170
+ <ChocoDropContext.Provider value={chocoDrop}>
171
+ <Canvas>
172
+ <ChocoDropSetup onReady={setChocoDrop} />
173
+ {children}
174
+ </Canvas>
175
+ </ChocoDropContext.Provider>
176
+ );
177
+ }
178
+
179
+ export function useChocoDropContext() {
180
+ return useContext(ChocoDropContext);
181
+ }
182
+ ```
183
+
184
+ ## 🎭 イベント処理
185
+
186
+ ### UI状態管理
187
+
188
+ ```jsx
189
+ function ChocoDropUI() {
190
+ const [isUIOpen, setIsUIOpen] = useState(false);
191
+ const chocoDrop = useChocoDrop({
192
+ onControlsToggle: (disabled) => {
193
+ setIsUIOpen(disabled);
194
+ }
195
+ });
196
+
197
+ return (
198
+ <>
199
+ {isUIOpen && (
200
+ <div className="ui-overlay">
201
+ ChocoDrop UI is active
202
+ </div>
203
+ )}
204
+ </>
205
+ );
206
+ }
207
+ ```
208
+
209
+ ### カスタムコマンド
210
+
211
+ ```jsx
212
+ function CustomCommands() {
213
+ const { chocoDropRef } = useChocoDrop();
214
+
215
+ const handleCustomCommand = async (command) => {
216
+ if (chocoDropRef.current) {
217
+ await chocoDropRef.current.client.executeCommand(command);
218
+ }
219
+ };
220
+
221
+ return (
222
+ <div>
223
+ <button onClick={() => handleCustomCommand('ドラゴンを作って')}>
224
+ ドラゴン生成
225
+ </button>
226
+ <button onClick={() => handleCustomCommand('全て削除')}>
227
+ 全削除
228
+ </button>
229
+ </div>
230
+ );
231
+ }
232
+ ```
233
+
234
+ ## 🏗️ TypeScript 対応
235
+
236
+ ### 型定義
237
+
238
+ ```typescript
239
+ import { RefObject } from 'react';
240
+ import { Object3D } from 'three';
241
+
242
+ interface ChocoDropInstance {
243
+ client: ChocoDropClient;
244
+ sceneManager: SceneManager;
245
+ ui: CommandUI;
246
+ dispose: () => void;
247
+ }
248
+
249
+ interface UseChocoDropReturn {
250
+ chocoDropRef: RefObject<ChocoDropInstance | null>;
251
+ controlsRef: RefObject<any>;
252
+ }
253
+
254
+ export function useChocoDrop(options?: ChocoDropOptions): UseChocoDropReturn;
255
+ ```
256
+
257
+ ## 🔧 トラブルシューティング
258
+
259
+ ### よくある問題
260
+
261
+ 1. **レンダラーの取得に失敗**
262
+ ```jsx
263
+ // ✅ 正しい
264
+ const { gl } = useThree();
265
+
266
+ // ❌ 間違い
267
+ const renderer = new THREE.WebGLRenderer();
268
+ ```
269
+
270
+ 2. **コントロールの競合**
271
+ ```jsx
272
+ // ✅ 正しい
273
+ onControlsToggle: (disabled) => {
274
+ controlsRef.current.enabled = !disabled;
275
+ }
276
+
277
+ // ❌ 間違い - コントロール無効化なし
278
+ onControlsToggle: () => {}
279
+ ```
280
+
281
+ 3. **依存関係の問題**
282
+ ```bash
283
+ # Three.jsバージョン確認
284
+ npm ls three
285
+
286
+ # React Three Fiber互換性確認
287
+ npm ls @react-three/fiber
288
+ ```
289
+
290
+ ## 📚 関連リンク
291
+
292
+ - [React Three Fiber 公式](https://docs.pmnd.rs/react-three-fiber)
293
+ - [Three.js Drei 公式](https://github.com/pmndrs/drei)
294
+ - [ChocoDrop API](../docs/API.md)