@xrift/world-components 0.7.0 → 0.10.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 (50) hide show
  1. package/README.md +175 -0
  2. package/dist/components/ScreenShareDisplay/hooks.d.ts +10 -0
  3. package/dist/components/ScreenShareDisplay/hooks.d.ts.map +1 -0
  4. package/dist/components/ScreenShareDisplay/hooks.js +57 -0
  5. package/dist/components/ScreenShareDisplay/hooks.js.map +1 -0
  6. package/dist/components/ScreenShareDisplay/index.d.ts +8 -0
  7. package/dist/components/ScreenShareDisplay/index.d.ts.map +1 -0
  8. package/dist/components/ScreenShareDisplay/index.js +30 -0
  9. package/dist/components/ScreenShareDisplay/index.js.map +1 -0
  10. package/dist/components/ScreenShareDisplay/types.d.ts +11 -0
  11. package/dist/components/ScreenShareDisplay/types.d.ts.map +1 -0
  12. package/dist/components/ScreenShareDisplay/types.js +2 -0
  13. package/dist/components/ScreenShareDisplay/types.js.map +1 -0
  14. package/dist/components/VideoScreen/index.d.ts +8 -0
  15. package/dist/components/VideoScreen/index.d.ts.map +1 -0
  16. package/dist/components/VideoScreen/index.js +90 -0
  17. package/dist/components/VideoScreen/index.js.map +1 -0
  18. package/dist/components/VideoScreen/types.d.ts +33 -0
  19. package/dist/components/VideoScreen/types.d.ts.map +1 -0
  20. package/dist/components/VideoScreen/types.js +2 -0
  21. package/dist/components/VideoScreen/types.js.map +1 -0
  22. package/dist/contexts/ScreenShareContext.d.ts +31 -0
  23. package/dist/contexts/ScreenShareContext.d.ts.map +1 -0
  24. package/dist/contexts/ScreenShareContext.js +25 -0
  25. package/dist/contexts/ScreenShareContext.js.map +1 -0
  26. package/dist/contexts/XRiftContext.d.ts +6 -1
  27. package/dist/contexts/XRiftContext.d.ts.map +1 -1
  28. package/dist/contexts/XRiftContext.js +3 -2
  29. package/dist/contexts/XRiftContext.js.map +1 -1
  30. package/dist/hooks/useVideoScreenControls.d.ts +57 -0
  31. package/dist/hooks/useVideoScreenControls.d.ts.map +1 -0
  32. package/dist/hooks/useVideoScreenControls.js +130 -0
  33. package/dist/hooks/useVideoScreenControls.js.map +1 -0
  34. package/dist/index.d.ts +3 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +3 -0
  37. package/dist/index.js.map +1 -1
  38. package/dist/scenes/TestScene.d.ts +6 -0
  39. package/dist/scenes/TestScene.d.ts.map +1 -0
  40. package/dist/scenes/TestScene.js +12 -0
  41. package/dist/scenes/TestScene.js.map +1 -0
  42. package/dist/scenes/TheaterScene.d.ts +6 -0
  43. package/dist/scenes/TheaterScene.d.ts.map +1 -0
  44. package/dist/scenes/TheaterScene.js +12 -0
  45. package/dist/scenes/TheaterScene.js.map +1 -0
  46. package/dist/scenes/VideoControlTest.d.ts +5 -0
  47. package/dist/scenes/VideoControlTest.d.ts.map +1 -0
  48. package/dist/scenes/VideoControlTest.js +17 -0
  49. package/dist/scenes/VideoControlTest.js.map +1 -0
  50. package/package.json +1 -1
package/README.md CHANGED
@@ -184,6 +184,181 @@ function MyWorld() {
184
184
  - 物理コライダーは含まれていません。必要な場合は`@react-three/rapier`などを使って別途追加してください
185
185
  - Meta Quest(Android Chrome)での互換性のため、マルチサンプリングは無効化されています
186
186
 
187
+ ### VideoScreen コンポーネント
188
+
189
+ ワールド内で動画を再生できるスクリーンコンポーネントです。`useInstanceState`を使用してインスタンス内の全ユーザーで再生状態が同期されます。
190
+
191
+ ```tsx
192
+ import { VideoScreen } from '@xrift/world-components'
193
+
194
+ function MyWorld() {
195
+ return (
196
+ <>
197
+ {/* メインスクリーン */}
198
+ <VideoScreen
199
+ id="main-screen"
200
+ position={[0, 2, -5]}
201
+ scale={[16/9 * 3, 3]}
202
+ url="https://example.com/video.mp4"
203
+ />
204
+
205
+ {/* サブスクリーン */}
206
+ <VideoScreen
207
+ id="sub-screen"
208
+ position={[5, 1.5, -3]}
209
+ scale={[16/9 * 1.5, 1.5]}
210
+ />
211
+ </>
212
+ )
213
+ }
214
+ ```
215
+
216
+ #### Props
217
+
218
+ | プロパティ | 型 | 必須 | デフォルト | 説明 |
219
+ |-----------|-----|------|-----------|------|
220
+ | `id` | `string` | ✓ | - | スクリーンの一意なID(インスタンス内で一意である必要があります) |
221
+ | `position` | `[number, number, number]` | - | `[0, 2, -5]` | スクリーンの位置 |
222
+ | `rotation` | `[number, number, number]` | - | `[0, 0, 0]` | スクリーンの回転 |
223
+ | `scale` | `[number, number]` | - | `[16/9 * 3, 3]` | スクリーンのサイズ [幅, 高さ] |
224
+ | `url` | `string` | - | `''` | 動画のURL |
225
+ | `playing` | `boolean` | - | `true` | 再生中かどうか |
226
+ | `currentTime` | `number` | - | `0` | 再生位置(秒) |
227
+ | `sync` | `'global' \| 'local'` | - | `'global'` | 同期モード: `global` = インスタンス全体で同期, `local` = ローカルのみ |
228
+
229
+ #### 同期モード
230
+
231
+ VideoScreenは2つの同期モードをサポートしています:
232
+
233
+ - **`sync="global"`(デフォルト)**: インスタンス内の全ユーザーで動画の状態が同期されます。シアターのメインスクリーンなど、全員で同じ動画を見る場合に使用します。
234
+ - **`sync="local"`**: ローカルのみで動作し、他のユーザーとは同期されません。個人用モニターなど、各ユーザーが別々の動画を見る場合に使用します。
235
+
236
+ ```tsx
237
+ // グローバル同期(デフォルト)
238
+ <VideoScreen
239
+ id="theater-screen"
240
+ url="https://example.com/movie.mp4"
241
+ sync="global"
242
+ />
243
+
244
+ // ローカルのみ
245
+ <VideoScreen
246
+ id="personal-monitor"
247
+ url="https://example.com/video.mp4"
248
+ sync="local"
249
+ />
250
+ ```
251
+
252
+ #### 状態管理
253
+
254
+ VideoScreenは`useInstanceState`を使用して以下の状態を管理します:
255
+
256
+ ```tsx
257
+ interface VideoState {
258
+ url: string // 動画のURL
259
+ isPlaying: boolean // 再生中かどうか
260
+ currentTime: number // 現在の再生位置(秒)
261
+ serverTime: number // サーバータイム(VRChat方式の同期用)
262
+ }
263
+ ```
264
+
265
+ #### 再生状態の制御(方法1: propsで制御)
266
+
267
+ VideoScreenはpropsで直接制御できます:
268
+
269
+ ```tsx
270
+ import { VideoScreen, Interactable } from '@xrift/world-components'
271
+ import { useState } from 'react'
272
+
273
+ function MyWorld() {
274
+ const [playing, setPlaying] = useState(true)
275
+ const [currentTime, setCurrentTime] = useState(0)
276
+
277
+ return (
278
+ <>
279
+ <VideoScreen
280
+ id="main-screen"
281
+ position={[0, 2, -5]}
282
+ scale={[16/9 * 3, 3]}
283
+ url="https://example.com/video.mp4"
284
+ playing={playing}
285
+ currentTime={currentTime}
286
+ />
287
+
288
+ <Interactable
289
+ id="toggle-button"
290
+ onInteract={() => setPlaying(!playing)}
291
+ >
292
+ <mesh>
293
+ <boxGeometry />
294
+ <meshStandardMaterial color={playing ? 'red' : 'green'} />
295
+ </mesh>
296
+ </Interactable>
297
+
298
+ <Interactable
299
+ id="seek-button"
300
+ onInteract={() => setCurrentTime(currentTime + 10)}
301
+ >
302
+ <mesh>
303
+ <boxGeometry />
304
+ <meshStandardMaterial color="cyan" />
305
+ </mesh>
306
+ </Interactable>
307
+ </>
308
+ )
309
+ }
310
+ ```
311
+
312
+ #### 再生状態の制御(方法2: useInstanceStateで制御)
313
+
314
+ VideoScreenの状態は`useInstanceState`を使って外部から制御できます:
315
+
316
+ ```tsx
317
+ import { VideoScreen, useInstanceState } from '@xrift/world-components'
318
+
319
+ function MyWorld() {
320
+ const [videoState, setVideoState] = useInstanceState('video-main-screen', {
321
+ url: '',
322
+ isPlaying: false,
323
+ currentTime: 0,
324
+ serverTime: Date.now(),
325
+ })
326
+
327
+ const playVideo = (url: string) => {
328
+ setVideoState({
329
+ url,
330
+ isPlaying: true,
331
+ currentTime: 0,
332
+ serverTime: Date.now(),
333
+ })
334
+ }
335
+
336
+ return (
337
+ <>
338
+ <VideoScreen id="main-screen" />
339
+
340
+ <Interactable
341
+ id="play-button"
342
+ onInteract={() => playVideo('https://example.com/video.mp4')}
343
+ >
344
+ <mesh>
345
+ <boxGeometry />
346
+ <meshStandardMaterial color="green" />
347
+ </mesh>
348
+ </Interactable>
349
+ </>
350
+ )
351
+ }
352
+ ```
353
+
354
+ #### 注意事項
355
+
356
+ - 動画URLは直接アクセス可能なMP4などの動画ファイルである必要があります
357
+ - CORSの制約により、クロスオリジンの動画を再生する場合は、動画サーバー側で適切なCORSヘッダーの設定が必要です
358
+ - 再生位置の同期はVRChat方式(サーバータイム基準)を採用しており、約0.5秒の誤差で自動補正されます
359
+ - ブラウザのautoplay policyのため、動画は初期状態でミュートされています
360
+ - 物理コライダーは含まれていません。必要な場合は別途追加してください
361
+
187
362
  ### Skybox コンポーネント
188
363
 
189
364
  画像を使わずにグラデーションで空を表現するシンプルなskyboxコンポーネントです。
@@ -0,0 +1,10 @@
1
+ import * as THREE from 'three';
2
+ /**
3
+ * VideoElement から VideoTexture を作成し管理するフック
4
+ */
5
+ export declare const useVideoTexture: (videoElement: HTMLVideoElement | null) => {
6
+ texture: THREE.VideoTexture<HTMLVideoElement> | null;
7
+ hasVideo: boolean;
8
+ materialRef: import("react").RefObject<THREE.MeshBasicMaterial>;
9
+ };
10
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/components/ScreenShareDisplay/hooks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,cAAc,gBAAgB,GAAG,IAAI;;;;CAwDpE,CAAA"}
@@ -0,0 +1,57 @@
1
+ import { useFrame } from '@react-three/fiber';
2
+ import { useEffect, useRef, useState } from 'react';
3
+ import * as THREE from 'three';
4
+ /**
5
+ * VideoElement から VideoTexture を作成し管理するフック
6
+ */
7
+ export const useVideoTexture = (videoElement) => {
8
+ const materialRef = useRef(null);
9
+ const [texture, setTexture] = useState(null);
10
+ const hasVideo = texture !== null;
11
+ // VideoTextureの作成と更新
12
+ useEffect(() => {
13
+ if (!videoElement) {
14
+ setTexture(null);
15
+ return;
16
+ }
17
+ const videoTexture = new THREE.VideoTexture(videoElement);
18
+ videoTexture.minFilter = THREE.LinearFilter;
19
+ videoTexture.magFilter = THREE.LinearFilter;
20
+ videoTexture.colorSpace = THREE.SRGBColorSpace;
21
+ videoTexture.needsUpdate = true;
22
+ setTexture(videoTexture);
23
+ return () => {
24
+ videoTexture.dispose();
25
+ };
26
+ }, [videoElement]);
27
+ // マテリアルにテクスチャをセット
28
+ useEffect(() => {
29
+ if (!materialRef.current || !texture)
30
+ return;
31
+ materialRef.current.map = texture;
32
+ materialRef.current.needsUpdate = true;
33
+ }, [texture]);
34
+ // テクスチャ更新(毎フレーム)
35
+ useFrame(() => {
36
+ if (!texture)
37
+ return;
38
+ texture.needsUpdate = true;
39
+ });
40
+ // video要素が一時停止していたら再生を試みる
41
+ useEffect(() => {
42
+ if (!videoElement)
43
+ return;
44
+ const checkAndPlay = () => {
45
+ if (videoElement.paused) {
46
+ videoElement.play().catch(() => {
47
+ // 再生失敗は無視
48
+ });
49
+ }
50
+ };
51
+ checkAndPlay();
52
+ const interval = setInterval(checkAndPlay, 1000);
53
+ return () => clearInterval(interval);
54
+ }, [videoElement]);
55
+ return { texture, hasVideo, materialRef };
56
+ };
57
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/components/ScreenShareDisplay/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACnD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,YAAqC,EAAE,EAAE;IACvE,MAAM,WAAW,GAAG,MAAM,CAA0B,IAAI,CAAC,CAAA;IACzD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAA4B,IAAI,CAAC,CAAA;IACvE,MAAM,QAAQ,GAAG,OAAO,KAAK,IAAI,CAAA;IAEjC,qBAAqB;IACrB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,UAAU,CAAC,IAAI,CAAC,CAAA;YAChB,OAAM;QACR,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,KAAK,CAAC,YAAY,CAAC,YAAY,CAAC,CAAA;QACzD,YAAY,CAAC,SAAS,GAAG,KAAK,CAAC,YAAY,CAAA;QAC3C,YAAY,CAAC,SAAS,GAAG,KAAK,CAAC,YAAY,CAAA;QAC3C,YAAY,CAAC,UAAU,GAAG,KAAK,CAAC,cAAc,CAAA;QAC9C,YAAY,CAAC,WAAW,GAAG,IAAI,CAAA;QAC/B,UAAU,CAAC,YAAY,CAAC,CAAA;QAExB,OAAO,GAAG,EAAE;YACV,YAAY,CAAC,OAAO,EAAE,CAAA;QACxB,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAA;IAElB,kBAAkB;IAClB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,WAAW,CAAC,OAAO,IAAI,CAAC,OAAO;YAAE,OAAM;QAC5C,WAAW,CAAC,OAAO,CAAC,GAAG,GAAG,OAAO,CAAA;QACjC,WAAW,CAAC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAA;IACxC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAA;IAEb,iBAAiB;IACjB,QAAQ,CAAC,GAAG,EAAE;QACZ,IAAI,CAAC,OAAO;YAAE,OAAM;QACpB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAA;IAC5B,CAAC,CAAC,CAAA;IAEF,0BAA0B;IAC1B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,YAAY;YAAE,OAAM;QAEzB,MAAM,YAAY,GAAG,GAAG,EAAE;YACxB,IAAI,YAAY,CAAC,MAAM,EAAE,CAAC;gBACxB,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;oBAC7B,UAAU;gBACZ,CAAC,CAAC,CAAA;YACJ,CAAC;QACH,CAAC,CAAA;QAED,YAAY,EAAE,CAAA;QACd,MAAM,QAAQ,GAAG,WAAW,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;QAEhD,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;IACtC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAA;IAElB,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAA;AAC3C,CAAC,CAAA"}
@@ -0,0 +1,8 @@
1
+ import type { Props } from './types';
2
+ export type { Props as ScreenShareDisplayProps } from './types';
3
+ /**
4
+ * 映像を3D空間内にスクリーンとして表示するコンポーネント
5
+ * 画面共有やカメラ映像などの表示に使用可能
6
+ */
7
+ export declare const ScreenShareDisplay: import("react").MemoExoticComponent<({ id, position, rotation, scale, }: Props) => import("react/jsx-runtime").JSX.Element>;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ScreenShareDisplay/index.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAEpC,YAAY,EAAE,KAAK,IAAI,uBAAuB,EAAE,MAAM,SAAS,CAAA;AAO/D;;;GAGG;AACH,eAAO,MAAM,kBAAkB,2EAK5B,KAAK,6CA8CN,CAAA"}
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Text } from '@react-three/drei';
3
+ import { memo, useCallback } from 'react';
4
+ import * as THREE from 'three';
5
+ import { useScreenShareContext } from '../../contexts/ScreenShareContext';
6
+ import { Interactable } from '../Interactable';
7
+ import { useVideoTexture } from './hooks';
8
+ // デフォルト値
9
+ const DEFAULT_SCALE = [4, 4 * (9 / 16)];
10
+ const DEFAULT_POSITION = [0, 2, -5];
11
+ const DEFAULT_ROTATION = [0, 0, 0];
12
+ /**
13
+ * 映像を3D空間内にスクリーンとして表示するコンポーネント
14
+ * 画面共有やカメラ映像などの表示に使用可能
15
+ */
16
+ export const ScreenShareDisplay = memo(({ id, position = DEFAULT_POSITION, rotation = DEFAULT_ROTATION, scale = DEFAULT_SCALE, }) => {
17
+ const { videoElement, isSharing, startScreenShare, stopScreenShare } = useScreenShareContext();
18
+ const interactionText = isSharing ? '画面共有を停止' : '画面共有を開始';
19
+ const { texture, hasVideo, materialRef } = useVideoTexture(videoElement);
20
+ const handleInteract = useCallback(() => {
21
+ if (isSharing) {
22
+ stopScreenShare();
23
+ }
24
+ else {
25
+ startScreenShare();
26
+ }
27
+ }, [isSharing, startScreenShare, stopScreenShare]);
28
+ return (_jsxs("group", { position: position, rotation: rotation, children: [_jsx(Interactable, { id: id, onInteract: handleInteract, interactionText: interactionText, children: _jsxs("mesh", { children: [_jsx("planeGeometry", { args: [scale[0], scale[1]] }), _jsx("meshBasicMaterial", { ref: materialRef, map: texture, side: THREE.FrontSide, toneMapped: false, color: hasVideo ? 'white' : '#1a1a2a' })] }) }), !hasVideo && (_jsx(Text, { position: [0, 0, 0.01], fontSize: scale[0] * 0.05, color: "#666666", anchorX: "center", anchorY: "middle", children: "\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u753B\u9762\u5171\u6709" }))] }));
29
+ });
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ScreenShareDisplay/index.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AACxC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AACzC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAA;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAKzC,SAAS;AACT,MAAM,aAAa,GAAqB,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;AACzD,MAAM,gBAAgB,GAA6B,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AAC7D,MAAM,gBAAgB,GAA6B,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;AAE5D;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,CAAC,EACtC,EAAE,EACF,QAAQ,GAAG,gBAAgB,EAC3B,QAAQ,GAAG,gBAAgB,EAC3B,KAAK,GAAG,aAAa,GACf,EAAE,EAAE;IACV,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,GAAG,qBAAqB,EAAE,CAAA;IAC9F,MAAM,eAAe,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAA;IACzD,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,eAAe,CAAC,YAAY,CAAC,CAAA;IAExE,MAAM,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE;QACtC,IAAI,SAAS,EAAE,CAAC;YACd,eAAe,EAAE,CAAA;QACnB,CAAC;aAAM,CAAC;YACN,gBAAgB,EAAE,CAAA;QACpB,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,gBAAgB,EAAE,eAAe,CAAC,CAAC,CAAA;IAElD,OAAO,CACL,iBAAO,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,aAC3C,KAAC,YAAY,IACX,EAAE,EAAE,EAAE,EACN,UAAU,EAAE,cAAc,EAC1B,eAAe,EAAE,eAAe,YAEhC,2BACE,wBAAe,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAI,EAC7C,4BACE,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,KAAK,CAAC,SAAS,EACrB,UAAU,EAAE,KAAK,EACjB,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,GACrC,IACG,GACM,EAGd,CAAC,QAAQ,IAAI,CACZ,KAAC,IAAI,IACH,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EACtB,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,EACzB,KAAK,EAAC,SAAS,EACf,OAAO,EAAC,QAAQ,EAChB,OAAO,EAAC,QAAQ,6EAGX,CACR,IACK,CACT,CAAA;AACH,CAAC,CAAC,CAAA"}
@@ -0,0 +1,11 @@
1
+ export interface Props {
2
+ /** スクリーンの一意なID */
3
+ id: string;
4
+ /** スクリーンの位置 */
5
+ position?: [number, number, number];
6
+ /** スクリーンの回転 */
7
+ rotation?: [number, number, number];
8
+ /** スクリーンのサイズ [幅, 高さ] */
9
+ scale?: [number, number];
10
+ }
11
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/ScreenShareDisplay/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,KAAK;IACpB,kBAAkB;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,eAAe;IACf,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,eAAe;IACf,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,wBAAwB;IACxB,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACzB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/components/ScreenShareDisplay/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import { VideoScreenProps } from './types';
2
+ export type { VideoScreenProps, VideoState } from './types';
3
+ /**
4
+ * VideoScreenコンポーネント
5
+ * Suspenseでラップして使用する
6
+ */
7
+ export declare function VideoScreen(props: VideoScreenProps): import("react/jsx-runtime").JSX.Element;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/VideoScreen/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAc,MAAM,SAAS,CAAA;AAEtD,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAwG3D;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,2CA8BlD"}
@@ -0,0 +1,90 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Suspense, useEffect, useRef, useState } from 'react';
3
+ import { useVideoTexture } from '@react-three/drei';
4
+ import { useInstanceState } from '../../hooks/useInstanceState';
5
+ /**
6
+ * 動画を表示する内部コンポーネント
7
+ * useVideoTextureを使用するためSuspense内で使用する必要がある
8
+ */
9
+ function VideoScreenInner({ id, position = [0, 2, -5], rotation = [0, 0, 0], scale = [16 / 9 * 3, 3], url = '', playing = true, currentTime = 0, sync = 'global', }) {
10
+ // グローバル同期用の状態
11
+ const [globalState, setGlobalState] = useInstanceState(`video-${id}`, {
12
+ url: url,
13
+ isPlaying: playing,
14
+ currentTime: currentTime,
15
+ serverTime: Date.now(),
16
+ });
17
+ // ローカル専用の状態
18
+ const [localState, setLocalState] = useState({
19
+ url: url,
20
+ isPlaying: playing,
21
+ currentTime: currentTime,
22
+ serverTime: Date.now(),
23
+ });
24
+ // sync modeに応じて使用する状態を切り替え
25
+ const videoState = sync === 'global' ? globalState : localState;
26
+ const setVideoState = sync === 'global' ? setGlobalState : setLocalState;
27
+ // propsが変更されたら、状態も更新
28
+ // serverTimeは毎回Date.now()で変わってしまうので、本当に変更があった時だけ更新
29
+ useEffect(() => {
30
+ if (videoState.url !== url ||
31
+ videoState.isPlaying !== playing ||
32
+ videoState.currentTime !== currentTime) {
33
+ setVideoState({
34
+ url: url,
35
+ isPlaying: playing,
36
+ currentTime: currentTime,
37
+ serverTime: Date.now(),
38
+ });
39
+ }
40
+ }, [url, playing, currentTime, videoState, setVideoState]);
41
+ // useVideoTextureで動画テクスチャを取得
42
+ const texture = useVideoTexture(url || '', {
43
+ muted: true,
44
+ loop: true,
45
+ start: playing,
46
+ });
47
+ const videoRef = useRef(texture.image);
48
+ // 再生状態の同期
49
+ useEffect(() => {
50
+ const video = texture.image;
51
+ if (!video)
52
+ return;
53
+ if (playing) {
54
+ video.play().catch(err => {
55
+ console.error('Video play error:', err);
56
+ });
57
+ }
58
+ else {
59
+ video.pause();
60
+ }
61
+ }, [playing, texture]);
62
+ // 再生位置の同期ロジック(VRChat方式)
63
+ // currentTimeが外部から変更された場合のみ同期
64
+ const lastSyncTimeRef = useRef(currentTime);
65
+ useEffect(() => {
66
+ const video = texture.image;
67
+ if (!video)
68
+ return;
69
+ // currentTimeが外部から変更された場合のみシークする
70
+ if (lastSyncTimeRef.current !== currentTime) {
71
+ video.currentTime = currentTime;
72
+ lastSyncTimeRef.current = currentTime;
73
+ }
74
+ }, [currentTime, texture]);
75
+ return (_jsx("group", { position: position, rotation: rotation, children: _jsxs("mesh", { children: [_jsx("planeGeometry", { args: [scale[0], scale[1]] }), _jsx("meshBasicMaterial", { map: texture, toneMapped: false })] }) }));
76
+ }
77
+ /**
78
+ * VideoScreenコンポーネント
79
+ * Suspenseでラップして使用する
80
+ */
81
+ export function VideoScreen(props) {
82
+ const { position, rotation, scale, url } = props;
83
+ const scaleValue = scale || [16 / 9 * 3, 3];
84
+ // urlが空の場合は黒いスクリーンを表示
85
+ if (!url) {
86
+ return (_jsx("group", { position: position, rotation: rotation, children: _jsxs("mesh", { children: [_jsx("planeGeometry", { args: scaleValue }), _jsx("meshBasicMaterial", { color: "#000000" })] }) }));
87
+ }
88
+ return (_jsx(Suspense, { fallback: _jsx("group", { position: position, rotation: rotation, children: _jsxs("mesh", { children: [_jsx("planeGeometry", { args: scaleValue }), _jsx("meshBasicMaterial", { color: "#333333" })] }) }), children: _jsx(VideoScreenInner, { ...props }) }));
89
+ }
90
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/VideoScreen/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ export interface VideoScreenProps {
2
+ /** スクリーンの一意なID(インスタンス内で一意である必要があります) */
3
+ id: string;
4
+ /** スクリーンの位置 */
5
+ position?: [number, number, number];
6
+ /** スクリーンの回転 */
7
+ rotation?: [number, number, number];
8
+ /** スクリーンのサイズ [幅, 高さ] */
9
+ scale?: [number, number];
10
+ /** 動画のURL */
11
+ url?: string;
12
+ /** 再生中かどうか(デフォルト: true) */
13
+ playing?: boolean;
14
+ /** 再生位置(秒) */
15
+ currentTime?: number;
16
+ /** 同期モード: "global" = インスタンス全体で同期, "local" = ローカルのみ(デフォルト: "global") */
17
+ sync?: 'global' | 'local';
18
+ }
19
+ /**
20
+ * VideoScreenの状態
21
+ * useInstanceStateで同期される
22
+ */
23
+ export interface VideoState {
24
+ /** 動画のURL */
25
+ url: string;
26
+ /** 再生中かどうか */
27
+ isPlaying: boolean;
28
+ /** 現在の再生位置(秒) */
29
+ currentTime: number;
30
+ /** サーバータイム(VRChat方式の同期用) */
31
+ serverTime: number;
32
+ }
33
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/VideoScreen/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAA;IACV,eAAe;IACf,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,eAAe;IACf,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,wBAAwB;IACxB,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxB,aAAa;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,2BAA2B;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,cAAc;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uEAAuE;IACvE,IAAI,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAA;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,aAAa;IACb,GAAG,EAAE,MAAM,CAAA;IACX,cAAc;IACd,SAAS,EAAE,OAAO,CAAA;IAClB,iBAAiB;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAA;CACnB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/components/VideoScreen/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,31 @@
1
+ import { type ReactNode } from 'react';
2
+ export interface ScreenShareContextValue {
3
+ /** 表示する映像のvideo要素 */
4
+ videoElement: HTMLVideoElement | null;
5
+ /** 自分が共有中か */
6
+ isSharing: boolean;
7
+ /** 共有開始 */
8
+ startScreenShare: () => void;
9
+ /** 共有停止 */
10
+ stopScreenShare: () => void;
11
+ }
12
+ /**
13
+ * 画面共有の状態を提供するContext
14
+ * xrift-frontend側で値を注入し、ワールド側で参照できる
15
+ */
16
+ export declare const ScreenShareContext: import("react").Context<ScreenShareContextValue | null>;
17
+ interface Props {
18
+ value: ScreenShareContextValue;
19
+ children: ReactNode;
20
+ }
21
+ /**
22
+ * 画面共有の状態を提供するContextProvider
23
+ */
24
+ export declare const ScreenShareProvider: ({ value, children }: Props) => import("react/jsx-runtime").JSX.Element;
25
+ /**
26
+ * 画面共有の状態を取得するhook
27
+ * @throws {Error} ScreenShareProvider の外で呼び出された場合
28
+ */
29
+ export declare const useScreenShareContext: () => ScreenShareContextValue;
30
+ export {};
31
+ //# sourceMappingURL=ScreenShareContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScreenShareContext.d.ts","sourceRoot":"","sources":["../../src/contexts/ScreenShareContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAc,MAAM,OAAO,CAAA;AAEjE,MAAM,WAAW,uBAAuB;IACtC,qBAAqB;IACrB,YAAY,EAAE,gBAAgB,GAAG,IAAI,CAAA;IACrC,cAAc;IACd,SAAS,EAAE,OAAO,CAAA;IAClB,WAAW;IACX,gBAAgB,EAAE,MAAM,IAAI,CAAA;IAC5B,WAAW;IACX,eAAe,EAAE,MAAM,IAAI,CAAA;CAC5B;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,yDAAsD,CAAA;AAErF,UAAU,KAAK;IACb,KAAK,EAAE,uBAAuB,CAAA;IAC9B,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAAI,qBAAqB,KAAK,4CAE7D,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAO,uBAMxC,CAAA"}
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext } from 'react';
3
+ /**
4
+ * 画面共有の状態を提供するContext
5
+ * xrift-frontend側で値を注入し、ワールド側で参照できる
6
+ */
7
+ export const ScreenShareContext = createContext(null);
8
+ /**
9
+ * 画面共有の状態を提供するContextProvider
10
+ */
11
+ export const ScreenShareProvider = ({ value, children }) => {
12
+ return _jsx(ScreenShareContext.Provider, { value: value, children: children });
13
+ };
14
+ /**
15
+ * 画面共有の状態を取得するhook
16
+ * @throws {Error} ScreenShareProvider の外で呼び出された場合
17
+ */
18
+ export const useScreenShareContext = () => {
19
+ const context = useContext(ScreenShareContext);
20
+ if (!context) {
21
+ throw new Error('useScreenShareContext must be used within ScreenShareProvider');
22
+ }
23
+ return context;
24
+ };
25
+ //# sourceMappingURL=ScreenShareContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScreenShareContext.js","sourceRoot":"","sources":["../../src/contexts/ScreenShareContext.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAkB,UAAU,EAAE,MAAM,OAAO,CAAA;AAajE;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,aAAa,CAAiC,IAAI,CAAC,CAAA;AAOrF;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAS,EAAE,EAAE;IAChE,OAAO,KAAC,kBAAkB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAA+B,CAAA;AAC5F,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAA4B,EAAE;IACjE,MAAM,OAAO,GAAG,UAAU,CAAC,kBAAkB,CAAC,CAAA;IAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAA;IAClF,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
@@ -1,6 +1,7 @@
1
1
  import { type ReactNode } from 'react';
2
2
  import type { Object3D } from 'three';
3
3
  import { type InstanceStateContextValue } from './InstanceStateContext';
4
+ import { type ScreenShareContextValue } from './ScreenShareContext';
4
5
  export interface XRiftContextValue {
5
6
  /**
6
7
  * ワールドのベースURL(CDNのディレクトリパス)
@@ -39,6 +40,10 @@ interface Props {
39
40
  * 指定しない場合はデフォルト実装(ローカルstate)が使用される
40
41
  */
41
42
  instanceStateImplementation?: InstanceStateContextValue;
43
+ /**
44
+ * 画面共有の実装
45
+ */
46
+ screenShareImplementation: ScreenShareContextValue;
42
47
  children: ReactNode;
43
48
  }
44
49
  /**
@@ -46,7 +51,7 @@ interface Props {
46
51
  * Module Federationで動的にロードされたワールドコンポーネントに
47
52
  * 必要な情報を注入するために使用
48
53
  */
49
- export declare const XRiftProvider: ({ baseUrl, currentTarget, instanceStateImplementation, children }: Props) => import("react/jsx-runtime").JSX.Element;
54
+ export declare const XRiftProvider: ({ baseUrl, currentTarget, instanceStateImplementation, screenShareImplementation, children, }: Props) => import("react/jsx-runtime").JSX.Element;
50
55
  /**
51
56
  * XRift ワールドの情報を取得するhook
52
57
  * ワールドプロジェクト側でアセットの相対パスを絶対パスに変換する際に使用
@@ -1 +1 @@
1
- {"version":3,"file":"XRiftContext.d.ts","sourceRoot":"","sources":["../../src/contexts/XRiftContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAqC,MAAM,OAAO,CAAA;AACxF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACrC,OAAO,EAAyB,KAAK,yBAAyB,EAAE,MAAM,wBAAwB,CAAA;AAE9F,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,aAAa,EAAE,QAAQ,GAAG,IAAI,CAAA;IAC9B;;;OAGG;IACH,mBAAmB,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAA;IAClC;;OAEG;IACH,oBAAoB,EAAE,CAAC,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAA;IAChD;;OAEG;IACH,sBAAsB,EAAE,CAAC,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAA;CAKnD;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,mDAAgD,CAAA;AAEzE,UAAU,KAAK;IACb,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;IAC/B;;;OAGG;IACH,2BAA2B,CAAC,EAAE,yBAAyB,CAAA;IACvD,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,mEAK3B,KAAK,4CA6BP,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ,QAAO,iBAQ3B,CAAA"}
1
+ {"version":3,"file":"XRiftContext.d.ts","sourceRoot":"","sources":["../../src/contexts/XRiftContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAqC,MAAM,OAAO,CAAA;AACxF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACrC,OAAO,EAAyB,KAAK,yBAAyB,EAAE,MAAM,wBAAwB,CAAA;AAC9F,OAAO,EAAuB,KAAK,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAExF,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,aAAa,EAAE,QAAQ,GAAG,IAAI,CAAA;IAC9B;;;OAGG;IACH,mBAAmB,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAA;IAClC;;OAEG;IACH,oBAAoB,EAAE,CAAC,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAA;IAChD;;OAEG;IACH,sBAAsB,EAAE,CAAC,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAA;CAKnD;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,mDAAgD,CAAA;AAEzE,UAAU,KAAK;IACb,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;IAC/B;;;OAGG;IACH,2BAA2B,CAAC,EAAE,yBAAyB,CAAA;IACvD;;OAEG;IACH,yBAAyB,EAAE,uBAAuB,CAAA;IAClD,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,+FAM3B,KAAK,4CA+BP,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ,QAAO,iBAQ3B,CAAA"}
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { createContext, useCallback, useContext, useState } from 'react';
3
3
  import { InstanceStateProvider } from './InstanceStateContext';
4
+ import { ScreenShareProvider } from './ScreenShareContext';
4
5
  /**
5
6
  * XRift ワールドの情報を提供するContext
6
7
  * ワールド側でこのContextを直接参照して情報を取得できる
@@ -11,7 +12,7 @@ export const XRiftContext = createContext(null);
11
12
  * Module Federationで動的にロードされたワールドコンポーネントに
12
13
  * 必要な情報を注入するために使用
13
14
  */
14
- export const XRiftProvider = ({ baseUrl, currentTarget = null, instanceStateImplementation, children }) => {
15
+ export const XRiftProvider = ({ baseUrl, currentTarget = null, instanceStateImplementation, screenShareImplementation, children, }) => {
15
16
  // インタラクト可能なオブジェクトの管理
16
17
  const [interactableObjects] = useState(() => new Set());
17
18
  // オブジェクトの登録
@@ -28,7 +29,7 @@ export const XRiftProvider = ({ baseUrl, currentTarget = null, instanceStateImpl
28
29
  interactableObjects,
29
30
  registerInteractable,
30
31
  unregisterInteractable,
31
- }, children: _jsx(InstanceStateProvider, { implementation: instanceStateImplementation, children: children }) }));
32
+ }, children: _jsx(ScreenShareProvider, { value: screenShareImplementation, children: _jsx(InstanceStateProvider, { implementation: instanceStateImplementation, children: children }) }) }));
32
33
  };
33
34
  /**
34
35
  * XRift ワールドの情報を取得するhook
@@ -1 +1 @@
1
- {"version":3,"file":"XRiftContext.js","sourceRoot":"","sources":["../../src/contexts/XRiftContext.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAkB,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAExF,OAAO,EAAE,qBAAqB,EAAkC,MAAM,wBAAwB,CAAA;AAgC9F;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAA2B,IAAI,CAAC,CAAA;AAazE;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAC5B,OAAO,EACP,aAAa,GAAG,IAAI,EACpB,2BAA2B,EAC3B,QAAQ,EACF,EAAE,EAAE;IACV,qBAAqB;IACrB,MAAM,CAAC,mBAAmB,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,GAAG,EAAY,CAAC,CAAA;IAEjE,YAAY;IACZ,MAAM,oBAAoB,GAAG,WAAW,CAAC,CAAC,MAAgB,EAAE,EAAE;QAC5D,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IACjC,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAA;IAEzB,cAAc;IACd,MAAM,sBAAsB,GAAG,WAAW,CAAC,CAAC,MAAgB,EAAE,EAAE;QAC9D,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACpC,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAA;IAEzB,OAAO,CACL,KAAC,YAAY,CAAC,QAAQ,IACpB,KAAK,EAAE;YACL,OAAO;YACP,aAAa;YACb,mBAAmB;YACnB,oBAAoB;YACpB,sBAAsB;SACvB,YAED,KAAC,qBAAqB,IAAC,cAAc,EAAE,2BAA2B,YAC/D,QAAQ,GACa,GACF,CACzB,CAAA;AACH,CAAC,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAsB,EAAE;IAC9C,MAAM,OAAO,GAAG,UAAU,CAAC,YAAY,CAAC,CAAA;IAExC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IAC/D,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
1
+ {"version":3,"file":"XRiftContext.js","sourceRoot":"","sources":["../../src/contexts/XRiftContext.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAkB,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAExF,OAAO,EAAE,qBAAqB,EAAkC,MAAM,wBAAwB,CAAA;AAC9F,OAAO,EAAE,mBAAmB,EAAgC,MAAM,sBAAsB,CAAA;AAgCxF;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAA2B,IAAI,CAAC,CAAA;AAiBzE;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAC5B,OAAO,EACP,aAAa,GAAG,IAAI,EACpB,2BAA2B,EAC3B,yBAAyB,EACzB,QAAQ,GACF,EAAE,EAAE;IACV,qBAAqB;IACrB,MAAM,CAAC,mBAAmB,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,GAAG,EAAY,CAAC,CAAA;IAEjE,YAAY;IACZ,MAAM,oBAAoB,GAAG,WAAW,CAAC,CAAC,MAAgB,EAAE,EAAE;QAC5D,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IACjC,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAA;IAEzB,cAAc;IACd,MAAM,sBAAsB,GAAG,WAAW,CAAC,CAAC,MAAgB,EAAE,EAAE;QAC9D,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACpC,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAA;IAEzB,OAAO,CACL,KAAC,YAAY,CAAC,QAAQ,IACpB,KAAK,EAAE;YACL,OAAO;YACP,aAAa;YACb,mBAAmB;YACnB,oBAAoB;YACpB,sBAAsB;SACvB,YAED,KAAC,mBAAmB,IAAC,KAAK,EAAE,yBAAyB,YACnD,KAAC,qBAAqB,IAAC,cAAc,EAAE,2BAA2B,YAC/D,QAAQ,GACa,GACJ,GACA,CACzB,CAAA;AACH,CAAC,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAsB,EAAE;IAC9C,MAAM,OAAO,GAAG,UAAU,CAAC,YAAY,CAAC,CAAA;IAExC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IAC/D,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
@@ -0,0 +1,57 @@
1
+ import { VideoState } from '../components/VideoScreen/types';
2
+ /**
3
+ * VideoScreenの再生制御を行うためのhook
4
+ *
5
+ * @param screenId VideoScreenコンポーネントのid
6
+ * @returns 再生制御用の関数群
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * function MyWorld() {
11
+ * const controls = useVideoScreenControls('main-screen')
12
+ *
13
+ * return (
14
+ * <>
15
+ * <VideoScreen id="main-screen" defaultUrl="https://example.com/video.mp4" />
16
+ *
17
+ * <Interactable
18
+ * id="play-button"
19
+ * onInteract={() => controls.play()}
20
+ * >
21
+ * <mesh>
22
+ * <boxGeometry />
23
+ * <meshStandardMaterial color="green" />
24
+ * </mesh>
25
+ * </Interactable>
26
+ *
27
+ * <Interactable
28
+ * id="pause-button"
29
+ * onInteract={() => controls.pause()}
30
+ * >
31
+ * <mesh>
32
+ * <boxGeometry />
33
+ * <meshStandardMaterial color="red" />
34
+ * </mesh>
35
+ * </Interactable>
36
+ * </>
37
+ * )
38
+ * }
39
+ * ```
40
+ */
41
+ export declare function useVideoScreenControls(screenId: string): {
42
+ /** 現在の動画の状態 */
43
+ state: VideoState;
44
+ /** 動画を再生する */
45
+ play: () => void;
46
+ /** 動画を一時停止する */
47
+ pause: () => void;
48
+ /** 動画を再生/一時停止を切り替える */
49
+ toggle: () => void;
50
+ /** 動画のURLを変更する */
51
+ changeVideo: (url: string, autoPlay?: boolean) => void;
52
+ /** 再生位置を変更する */
53
+ seek: (time: number) => void;
54
+ /** 相対的に再生位置を変更する(例: seekRelative(10)で10秒進む) */
55
+ seekRelative: (seconds: number) => void;
56
+ };
57
+ //# sourceMappingURL=useVideoScreenControls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVideoScreenControls.d.ts","sourceRoot":"","sources":["../../src/hooks/useVideoScreenControls.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM;IA2FnD,eAAe;;IAEf,cAAc;;IAEd,gBAAgB;;IAEhB,uBAAuB;;IAEvB,kBAAkB;uBAlDZ,MAAM;IAoDZ,gBAAgB;iBApCT,MAAM;IAsCb,+CAA+C;4BAvBrC,MAAM;EA0BnB"}
@@ -0,0 +1,130 @@
1
+ import { useCallback } from 'react';
2
+ import { useInstanceState } from './useInstanceState';
3
+ /**
4
+ * VideoScreenの再生制御を行うためのhook
5
+ *
6
+ * @param screenId VideoScreenコンポーネントのid
7
+ * @returns 再生制御用の関数群
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * function MyWorld() {
12
+ * const controls = useVideoScreenControls('main-screen')
13
+ *
14
+ * return (
15
+ * <>
16
+ * <VideoScreen id="main-screen" defaultUrl="https://example.com/video.mp4" />
17
+ *
18
+ * <Interactable
19
+ * id="play-button"
20
+ * onInteract={() => controls.play()}
21
+ * >
22
+ * <mesh>
23
+ * <boxGeometry />
24
+ * <meshStandardMaterial color="green" />
25
+ * </mesh>
26
+ * </Interactable>
27
+ *
28
+ * <Interactable
29
+ * id="pause-button"
30
+ * onInteract={() => controls.pause()}
31
+ * >
32
+ * <mesh>
33
+ * <boxGeometry />
34
+ * <meshStandardMaterial color="red" />
35
+ * </mesh>
36
+ * </Interactable>
37
+ * </>
38
+ * )
39
+ * }
40
+ * ```
41
+ */
42
+ export function useVideoScreenControls(screenId) {
43
+ const [videoState, setVideoState] = useInstanceState(`video-${screenId}`, {
44
+ url: '',
45
+ isPlaying: false,
46
+ currentTime: 0,
47
+ serverTime: Date.now(),
48
+ });
49
+ /**
50
+ * 動画を再生する
51
+ */
52
+ const play = useCallback(() => {
53
+ setVideoState({
54
+ ...videoState,
55
+ isPlaying: true,
56
+ serverTime: Date.now(),
57
+ });
58
+ }, [videoState, setVideoState]);
59
+ /**
60
+ * 動画を一時停止する
61
+ */
62
+ const pause = useCallback(() => {
63
+ setVideoState({
64
+ ...videoState,
65
+ isPlaying: false,
66
+ });
67
+ }, [videoState, setVideoState]);
68
+ /**
69
+ * 動画を再生/一時停止を切り替える
70
+ */
71
+ const toggle = useCallback(() => {
72
+ setVideoState({
73
+ ...videoState,
74
+ isPlaying: !videoState.isPlaying,
75
+ serverTime: Date.now(),
76
+ });
77
+ }, [videoState, setVideoState]);
78
+ /**
79
+ * 動画のURLを変更する
80
+ * @param url 新しい動画URL
81
+ * @param autoPlay 自動再生するかどうか(デフォルト: true)
82
+ */
83
+ const changeVideo = useCallback((url, autoPlay = true) => {
84
+ setVideoState({
85
+ url,
86
+ isPlaying: autoPlay,
87
+ currentTime: 0,
88
+ serverTime: Date.now(),
89
+ });
90
+ }, [setVideoState]);
91
+ /**
92
+ * 再生位置を変更する
93
+ * @param time 新しい再生位置(秒)
94
+ */
95
+ const seek = useCallback((time) => {
96
+ setVideoState({
97
+ ...videoState,
98
+ currentTime: time,
99
+ serverTime: Date.now(),
100
+ });
101
+ }, [videoState, setVideoState]);
102
+ /**
103
+ * 相対的に再生位置を変更する
104
+ * @param seconds 進める/戻す秒数(負の値で戻す)
105
+ */
106
+ const seekRelative = useCallback((seconds) => {
107
+ setVideoState({
108
+ ...videoState,
109
+ currentTime: Math.max(0, videoState.currentTime + seconds),
110
+ serverTime: Date.now(),
111
+ });
112
+ }, [videoState, setVideoState]);
113
+ return {
114
+ /** 現在の動画の状態 */
115
+ state: videoState,
116
+ /** 動画を再生する */
117
+ play,
118
+ /** 動画を一時停止する */
119
+ pause,
120
+ /** 動画を再生/一時停止を切り替える */
121
+ toggle,
122
+ /** 動画のURLを変更する */
123
+ changeVideo,
124
+ /** 再生位置を変更する */
125
+ seek,
126
+ /** 相対的に再生位置を変更する(例: seekRelative(10)で10秒進む) */
127
+ seekRelative,
128
+ };
129
+ }
130
+ //# sourceMappingURL=useVideoScreenControls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVideoScreenControls.js","sourceRoot":"","sources":["../../src/hooks/useVideoScreenControls.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAGrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACrD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,gBAAgB,CAClD,SAAS,QAAQ,EAAE,EACnB;QACE,GAAG,EAAE,EAAE;QACP,SAAS,EAAE,KAAK;QAChB,WAAW,EAAE,CAAC;QACd,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;KACvB,CACF,CAAA;IAED;;OAEG;IACH,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5B,aAAa,CAAC;YACZ,GAAG,UAAU;YACb,SAAS,EAAE,IAAI;YACf,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;SACvB,CAAC,CAAA;IACJ,CAAC,EAAE,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,CAAA;IAE/B;;OAEG;IACH,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,aAAa,CAAC;YACZ,GAAG,UAAU;YACb,SAAS,EAAE,KAAK;SACjB,CAAC,CAAA;IACJ,CAAC,EAAE,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,CAAA;IAE/B;;OAEG;IACH,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE;QAC9B,aAAa,CAAC;YACZ,GAAG,UAAU;YACb,SAAS,EAAE,CAAC,UAAU,CAAC,SAAS;YAChC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;SACvB,CAAC,CAAA;IACJ,CAAC,EAAE,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,CAAA;IAE/B;;;;OAIG;IACH,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,GAAW,EAAE,QAAQ,GAAG,IAAI,EAAE,EAAE;QAC/B,aAAa,CAAC;YACZ,GAAG;YACH,SAAS,EAAE,QAAQ;YACnB,WAAW,EAAE,CAAC;YACd,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;SACvB,CAAC,CAAA;IACJ,CAAC,EACD,CAAC,aAAa,CAAC,CAChB,CAAA;IAED;;;OAGG;IACH,MAAM,IAAI,GAAG,WAAW,CACtB,CAAC,IAAY,EAAE,EAAE;QACf,aAAa,CAAC;YACZ,GAAG,UAAU;YACb,WAAW,EAAE,IAAI;YACjB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;SACvB,CAAC,CAAA;IACJ,CAAC,EACD,CAAC,UAAU,EAAE,aAAa,CAAC,CAC5B,CAAA;IAED;;;OAGG;IACH,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,OAAe,EAAE,EAAE;QAClB,aAAa,CAAC;YACZ,GAAG,UAAU;YACb,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,WAAW,GAAG,OAAO,CAAC;YAC1D,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;SACvB,CAAC,CAAA;IACJ,CAAC,EACD,CAAC,UAAU,EAAE,aAAa,CAAC,CAC5B,CAAA;IAED,OAAO;QACL,eAAe;QACf,KAAK,EAAE,UAAU;QACjB,cAAc;QACd,IAAI;QACJ,gBAAgB;QAChB,KAAK;QACL,uBAAuB;QACvB,MAAM;QACN,kBAAkB;QAClB,WAAW;QACX,gBAAgB;QAChB,IAAI;QACJ,+CAA+C;QAC/C,YAAY;KACb,CAAA;AACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,10 @@
1
1
  export { XRiftContext, XRiftProvider, useXRift, type XRiftContextValue, } from './contexts/XRiftContext';
2
2
  export { InstanceStateContext, useInstanceStateContext, type InstanceStateContextValue, } from './contexts/InstanceStateContext';
3
+ export { ScreenShareContext, ScreenShareProvider, useScreenShareContext, type ScreenShareContextValue, } from './contexts/ScreenShareContext';
3
4
  export { Interactable, type InteractableProps, } from './components/Interactable';
4
5
  export { Mirror, type MirrorProps } from './components/Mirror';
5
6
  export { Skybox, type SkyboxProps } from './components/Skybox';
7
+ export { VideoScreen, type VideoScreenProps, type VideoState, } from './components/VideoScreen';
8
+ export { ScreenShareDisplay, type ScreenShareDisplayProps, } from './components/ScreenShareDisplay';
6
9
  export { useInstanceState } from './hooks/useInstanceState';
7
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,KAAK,iBAAiB,GACvB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,KAAK,yBAAyB,GAC/B,MAAM,iCAAiC,CAAA;AAGxC,OAAO,EACL,YAAY,EACZ,KAAK,iBAAiB,GACvB,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAG9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,KAAK,iBAAiB,GACvB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,KAAK,yBAAyB,GAC/B,MAAM,iCAAiC,CAAA;AAExC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,+BAA+B,CAAA;AAGtC,OAAO,EACL,YAAY,EACZ,KAAK,iBAAiB,GACvB,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EACL,WAAW,EACX,KAAK,gBAAgB,EACrB,KAAK,UAAU,GAChB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,kBAAkB,EAClB,KAAK,uBAAuB,GAC7B,MAAM,iCAAiC,CAAA;AAGxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA"}
package/dist/index.js CHANGED
@@ -1,10 +1,13 @@
1
1
  // Contexts
2
2
  export { XRiftContext, XRiftProvider, useXRift, } from './contexts/XRiftContext';
3
3
  export { InstanceStateContext, useInstanceStateContext, } from './contexts/InstanceStateContext';
4
+ export { ScreenShareContext, ScreenShareProvider, useScreenShareContext, } from './contexts/ScreenShareContext';
4
5
  // Components
5
6
  export { Interactable, } from './components/Interactable';
6
7
  export { Mirror } from './components/Mirror';
7
8
  export { Skybox } from './components/Skybox';
9
+ export { VideoScreen, } from './components/VideoScreen';
10
+ export { ScreenShareDisplay, } from './components/ScreenShareDisplay';
8
11
  // Hooks
9
12
  export { useInstanceState } from './hooks/useInstanceState';
10
13
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,GAET,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,oBAAoB,EACpB,uBAAuB,GAExB,MAAM,iCAAiC,CAAA;AAExC,aAAa;AACb,OAAO,EACL,YAAY,GAEb,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAA;AAE9D,QAAQ;AACR,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,GAET,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,oBAAoB,EACpB,uBAAuB,GAExB,MAAM,iCAAiC,CAAA;AAExC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,GAEtB,MAAM,+BAA+B,CAAA;AAEtC,aAAa;AACb,OAAO,EACL,YAAY,GAEb,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EACL,WAAW,GAGZ,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,kBAAkB,GAEnB,MAAM,iCAAiC,CAAA;AAExC,QAAQ;AACR,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * VideoScreenとMirrorのテストシーン
3
+ * Triplexでコンポーネントを確認するためのシーン
4
+ */
5
+ export declare function TestScene(): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=TestScene.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TestScene.d.ts","sourceRoot":"","sources":["../../src/scenes/TestScene.tsx"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAgB,SAAS,4CAmExB"}
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { VideoScreen } from '../components/VideoScreen';
3
+ import { Mirror } from '../components/Mirror';
4
+ import { Skybox } from '../components/Skybox';
5
+ /**
6
+ * VideoScreenとMirrorのテストシーン
7
+ * Triplexでコンポーネントを確認するためのシーン
8
+ */
9
+ export function TestScene() {
10
+ return (_jsxs(_Fragment, { children: [_jsx(Skybox, {}), _jsx("ambientLight", { intensity: 0.5 }), _jsx("directionalLight", { position: [5, 10, 5], intensity: 1 }), _jsxs("mesh", { rotation: [-Math.PI / 2, 0, 0], position: [0, 0, 0], receiveShadow: true, children: [_jsx("planeGeometry", { args: [20, 20] }), _jsx("meshStandardMaterial", { color: "#cccccc" })] }), _jsx(VideoScreen, { id: "main-screen", position: [0, 2, -5], scale: [16 / 9 * 3, 3], url: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4", sync: "global" }), _jsx(VideoScreen, { id: "sub-screen", position: [5, 1.5, -3], scale: [16 / 9 * 1.5, 1.5], url: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4", sync: "local" }), _jsx(Mirror, { position: [-5, 2.5, -3], size: [3, 4], textureResolution: 512 }), _jsx(Mirror, { position: [-3, 1.5, -7], size: [2, 2], color: 0xffd700 }), _jsxs("mesh", { position: [0, 0.5, 0], children: [_jsx("boxGeometry", { args: [1, 1, 1] }), _jsx("meshStandardMaterial", { color: "orange" })] }), _jsxs("mesh", { position: [2, 1, -1], children: [_jsx("sphereGeometry", { args: [0.5, 32, 32] }), _jsx("meshStandardMaterial", { color: "blue", metalness: 0.8, roughness: 0.2 })] }), _jsxs("mesh", { position: [-2, 0.75, -1], children: [_jsx("cylinderGeometry", { args: [0.5, 0.5, 1.5, 32] }), _jsx("meshStandardMaterial", { color: "green" })] })] }));
11
+ }
12
+ //# sourceMappingURL=TestScene.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TestScene.js","sourceRoot":"","sources":["../../src/scenes/TestScene.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAG7C;;;GAGG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,CACL,8BAEE,KAAC,MAAM,KAAG,EAGV,uBAAc,SAAS,EAAE,GAAG,GAAI,EAChC,2BAAkB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,GAAI,EAGxD,gBAAM,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,aAAa,mBACtE,wBAAe,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAI,EACjC,+BAAsB,KAAK,EAAC,SAAS,GAAG,IACnC,EAGP,KAAC,WAAW,IACV,EAAE,EAAC,aAAa,EAChB,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EACpB,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EACtB,GAAG,EAAC,mFAAmF,EACvF,IAAI,EAAC,QAAQ,GACb,EAGF,KAAC,WAAW,IACV,EAAE,EAAC,YAAY,EACf,QAAQ,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EACtB,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,GAAG,CAAC,EAC1B,GAAG,EAAC,qFAAqF,EACzF,IAAI,EAAC,OAAO,GACZ,EAGF,KAAC,MAAM,IACL,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EACvB,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EACZ,iBAAiB,EAAE,GAAG,GACtB,EAGF,KAAC,MAAM,IACL,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EACvB,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EACZ,KAAK,EAAE,QAAQ,GACf,EAGF,gBAAM,QAAQ,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,aACzB,sBAAa,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAI,EAChC,+BAAsB,KAAK,EAAC,QAAQ,GAAG,IAClC,EAGP,gBAAM,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,aACxB,yBAAgB,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,GAAI,EACvC,+BAAsB,KAAK,EAAC,MAAM,EAAC,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,GAAI,IAChE,EAGP,gBAAM,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,aAC5B,2BAAkB,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAI,EAC/C,+BAAsB,KAAK,EAAC,OAAO,GAAG,IACjC,IACN,CACJ,CAAA;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * シアタールームのシーン
3
+ * VideoScreenを中心とした映画館風のレイアウト
4
+ */
5
+ export declare function TheaterScene(): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=TheaterScene.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TheaterScene.d.ts","sourceRoot":"","sources":["../../src/scenes/TheaterScene.tsx"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAgB,YAAY,4CAmH3B"}
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { VideoScreen } from '../components/VideoScreen';
3
+ import { Mirror } from '../components/Mirror';
4
+ import { Skybox } from '../components/Skybox';
5
+ /**
6
+ * シアタールームのシーン
7
+ * VideoScreenを中心とした映画館風のレイアウト
8
+ */
9
+ export function TheaterScene() {
10
+ return (_jsxs(_Fragment, { children: [_jsx(Skybox, { topColor: 0x000033, bottomColor: 0x000011 }), _jsx("ambientLight", { intensity: 0.2 }), _jsx("spotLight", { position: [0, 5, 5], angle: 0.3, penumbra: 0.5, intensity: 0.5 }), _jsxs("mesh", { rotation: [-Math.PI / 2, 0, 0], position: [0, 0, 0], children: [_jsx("planeGeometry", { args: [30, 30] }), _jsx("meshStandardMaterial", { color: "#1a1a1a" })] }), _jsx(VideoScreen, { id: "theater-main", position: [0, 3, -10], scale: [16 / 9 * 6, 6], url: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" }), _jsxs("mesh", { position: [0, 6.1, -10], children: [_jsx("boxGeometry", { args: [16 / 9 * 6 + 0.4, 0.2, 0.2] }), _jsx("meshStandardMaterial", { color: "#333333" })] }), _jsxs("mesh", { position: [0, -0.1, -10], children: [_jsx("boxGeometry", { args: [16 / 9 * 6 + 0.4, 0.2, 0.2] }), _jsx("meshStandardMaterial", { color: "#333333" })] }), _jsxs("mesh", { position: [-(16 / 9 * 6 + 0.4) / 2, 3, -10], children: [_jsx("boxGeometry", { args: [0.2, 6.4, 0.2] }), _jsx("meshStandardMaterial", { color: "#333333" })] }), _jsxs("mesh", { position: [(16 / 9 * 6 + 0.4) / 2, 3, -10], children: [_jsx("boxGeometry", { args: [0.2, 6.4, 0.2] }), _jsx("meshStandardMaterial", { color: "#333333" })] }), [-2, -1, 0, 1, 2].map((x) => (_jsxs("group", { position: [x * 1.2, 0.5, 2], children: [_jsxs("mesh", { children: [_jsx("boxGeometry", { args: [0.8, 0.5, 0.8] }), _jsx("meshStandardMaterial", { color: "#8b0000" })] }), _jsxs("mesh", { position: [0, 0.5, -0.2], children: [_jsx("boxGeometry", { args: [0.8, 0.6, 0.2] }), _jsx("meshStandardMaterial", { color: "#8b0000" })] })] }, `seat-1-${x}`))), [-2, -1, 0, 1, 2].map((x) => (_jsxs("group", { position: [x * 1.2, 0.5, 4], children: [_jsxs("mesh", { children: [_jsx("boxGeometry", { args: [0.8, 0.5, 0.8] }), _jsx("meshStandardMaterial", { color: "#8b0000" })] }), _jsxs("mesh", { position: [0, 0.5, -0.2], children: [_jsx("boxGeometry", { args: [0.8, 0.6, 0.2] }), _jsx("meshStandardMaterial", { color: "#8b0000" })] })] }, `seat-2-${x}`))), [-2, -1, 0, 1, 2].map((x) => (_jsxs("group", { position: [x * 1.2, 0.5, 6], children: [_jsxs("mesh", { children: [_jsx("boxGeometry", { args: [0.8, 0.5, 0.8] }), _jsx("meshStandardMaterial", { color: "#8b0000" })] }), _jsxs("mesh", { position: [0, 0.5, -0.2], children: [_jsx("boxGeometry", { args: [0.8, 0.6, 0.2] }), _jsx("meshStandardMaterial", { color: "#8b0000" })] })] }, `seat-3-${x}`))), _jsx(Mirror, { position: [-8, 2.5, -5], rotation: [0, Math.PI / 2, 0], size: [8, 4], textureResolution: 512 }), _jsx(Mirror, { position: [8, 2.5, -5], rotation: [0, -Math.PI / 2, 0], size: [8, 4], textureResolution: 512 }), _jsx(VideoScreen, { id: "lobby-monitor", position: [6, 1.5, 8], rotation: [0, Math.PI, 0], scale: [16 / 9 * 1, 1] })] }));
11
+ }
12
+ //# sourceMappingURL=TheaterScene.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TheaterScene.js","sourceRoot":"","sources":["../../src/scenes/TheaterScene.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * VideoScreenをpropsで制御するテストシーン
3
+ */
4
+ export declare function VideoControlTest(): import("react/jsx-runtime").JSX.Element;
5
+ //# sourceMappingURL=VideoControlTest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoControlTest.d.ts","sourceRoot":"","sources":["../../src/scenes/VideoControlTest.tsx"],"names":[],"mappings":"AAKA;;GAEG;AACH,wBAAgB,gBAAgB,4CAyF/B"}
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { VideoScreen } from '../components/VideoScreen';
4
+ import { Interactable } from '../components/Interactable';
5
+ import { Skybox } from '../components/Skybox';
6
+ /**
7
+ * VideoScreenをpropsで制御するテストシーン
8
+ */
9
+ export function VideoControlTest() {
10
+ const [playing, setPlaying] = useState(true);
11
+ const [currentTime, setCurrentTime] = useState(0);
12
+ return (_jsxs(_Fragment, { children: [_jsx(Skybox, {}), _jsx("ambientLight", { intensity: 0.5 }), _jsx("directionalLight", { position: [5, 10, 5], intensity: 1 }), _jsxs("mesh", { rotation: [-Math.PI / 2, 0, 0], position: [0, 0, 0], receiveShadow: true, children: [_jsx("planeGeometry", { args: [20, 20] }), _jsx("meshStandardMaterial", { color: "#cccccc" })] }), _jsx(VideoScreen, { id: "controlled-screen", position: [0, 2, -5], scale: [16 / 9 * 3, 3], url: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4", playing: playing, currentTime: currentTime }), _jsx(Interactable, { id: "toggle-button", onInteract: () => setPlaying(!playing), interactionText: playing ? '一時停止' : '再生', children: _jsxs("mesh", { position: [0, 0.5, 2], children: [_jsx("boxGeometry", { args: [0.6, 0.6, 0.6] }), _jsx("meshStandardMaterial", { color: playing ? 'red' : 'green' })] }) }), _jsx(Interactable, { id: "rewind-button", onInteract: () => setCurrentTime(Math.max(0, currentTime - 10)), interactionText: "10\u79D2\u623B\u308B", children: _jsxs("mesh", { position: [-1.5, 0.5, 2], children: [_jsx("boxGeometry", { args: [0.5, 0.5, 0.5] }), _jsx("meshStandardMaterial", { color: "yellow" })] }) }), _jsx(Interactable, { id: "forward-button", onInteract: () => setCurrentTime(currentTime + 10), interactionText: "10\u79D2\u9032\u3080", children: _jsxs("mesh", { position: [1.5, 0.5, 2], children: [_jsx("boxGeometry", { args: [0.5, 0.5, 0.5] }), _jsx("meshStandardMaterial", { color: "cyan" })] }) }), _jsx(Interactable, { id: "reset-button", onInteract: () => {
13
+ setCurrentTime(0);
14
+ setPlaying(true);
15
+ }, interactionText: "\u6700\u521D\u304B\u3089\u518D\u751F", children: _jsxs("mesh", { position: [0, 0.5, 3.5], children: [_jsx("boxGeometry", { args: [0.5, 0.5, 0.5] }), _jsx("meshStandardMaterial", { color: "blue" })] }) }), _jsx("group", { position: [0, 3.5, -5], children: _jsxs("mesh", { children: [_jsx("planeGeometry", { args: [2, 0.3] }), _jsx("meshBasicMaterial", { color: "#333333" })] }) })] }));
16
+ }
17
+ //# sourceMappingURL=VideoControlTest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoControlTest.js","sourceRoot":"","sources":["../../src/scenes/VideoControlTest.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xrift/world-components",
3
- "version": "0.7.0",
3
+ "version": "0.10.0",
4
4
  "description": "Shared components and utilities for Xrift worlds",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",