@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.
- package/README.md +175 -0
- package/dist/components/ScreenShareDisplay/hooks.d.ts +10 -0
- package/dist/components/ScreenShareDisplay/hooks.d.ts.map +1 -0
- package/dist/components/ScreenShareDisplay/hooks.js +57 -0
- package/dist/components/ScreenShareDisplay/hooks.js.map +1 -0
- package/dist/components/ScreenShareDisplay/index.d.ts +8 -0
- package/dist/components/ScreenShareDisplay/index.d.ts.map +1 -0
- package/dist/components/ScreenShareDisplay/index.js +30 -0
- package/dist/components/ScreenShareDisplay/index.js.map +1 -0
- package/dist/components/ScreenShareDisplay/types.d.ts +11 -0
- package/dist/components/ScreenShareDisplay/types.d.ts.map +1 -0
- package/dist/components/ScreenShareDisplay/types.js +2 -0
- package/dist/components/ScreenShareDisplay/types.js.map +1 -0
- package/dist/components/VideoScreen/index.d.ts +8 -0
- package/dist/components/VideoScreen/index.d.ts.map +1 -0
- package/dist/components/VideoScreen/index.js +90 -0
- package/dist/components/VideoScreen/index.js.map +1 -0
- package/dist/components/VideoScreen/types.d.ts +33 -0
- package/dist/components/VideoScreen/types.d.ts.map +1 -0
- package/dist/components/VideoScreen/types.js +2 -0
- package/dist/components/VideoScreen/types.js.map +1 -0
- package/dist/contexts/ScreenShareContext.d.ts +31 -0
- package/dist/contexts/ScreenShareContext.d.ts.map +1 -0
- package/dist/contexts/ScreenShareContext.js +25 -0
- package/dist/contexts/ScreenShareContext.js.map +1 -0
- package/dist/contexts/XRiftContext.d.ts +6 -1
- package/dist/contexts/XRiftContext.d.ts.map +1 -1
- package/dist/contexts/XRiftContext.js +3 -2
- package/dist/contexts/XRiftContext.js.map +1 -1
- package/dist/hooks/useVideoScreenControls.d.ts +57 -0
- package/dist/hooks/useVideoScreenControls.d.ts.map +1 -0
- package/dist/hooks/useVideoScreenControls.js +130 -0
- package/dist/hooks/useVideoScreenControls.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/scenes/TestScene.d.ts +6 -0
- package/dist/scenes/TestScene.d.ts.map +1 -0
- package/dist/scenes/TestScene.js +12 -0
- package/dist/scenes/TestScene.js.map +1 -0
- package/dist/scenes/TheaterScene.d.ts +6 -0
- package/dist/scenes/TheaterScene.d.ts.map +1 -0
- package/dist/scenes/TheaterScene.js +12 -0
- package/dist/scenes/TheaterScene.js.map +1 -0
- package/dist/scenes/VideoControlTest.d.ts +5 -0
- package/dist/scenes/VideoControlTest.d.ts.map +1 -0
- package/dist/scenes/VideoControlTest.js +17 -0
- package/dist/scenes/VideoControlTest.js.map +1 -0
- 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 @@
|
|
|
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 @@
|
|
|
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;
|
|
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;
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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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"}
|