@xrift/world-components 0.2.5 → 0.4.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 +53 -0
- package/dist/components/Interactable/index.d.ts.map +1 -1
- package/dist/components/Interactable/index.js +7 -3
- package/dist/components/Interactable/index.js.map +1 -1
- package/dist/contexts/InstanceStateContext.d.ts +45 -0
- package/dist/contexts/InstanceStateContext.d.ts.map +1 -0
- package/dist/contexts/InstanceStateContext.js +51 -0
- package/dist/contexts/InstanceStateContext.js.map +1 -0
- package/dist/contexts/XRiftContext.d.ts +20 -1
- package/dist/contexts/XRiftContext.d.ts.map +1 -1
- package/dist/contexts/XRiftContext.js +17 -3
- package/dist/contexts/XRiftContext.js.map +1 -1
- package/dist/hooks/useInstanceState.d.ts +38 -0
- package/dist/hooks/useInstanceState.d.ts.map +1 -0
- package/dist/hooks/useInstanceState.js +42 -0
- package/dist/hooks/useInstanceState.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,6 +48,59 @@ function MyWorld() {
|
|
|
48
48
|
}
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
### useInstanceState フック
|
|
52
|
+
|
|
53
|
+
インスタンス全体で同期される状態を管理するフックです。React の `useState` と同じAPIを提供します。
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
import { useInstanceState } from '@xrift/world-components'
|
|
57
|
+
|
|
58
|
+
function MyWorld() {
|
|
59
|
+
// インスタンス全体で同期される状態
|
|
60
|
+
const [buttonState, setButtonState] = useInstanceState('button-1', { enabled: false })
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<Interactable
|
|
64
|
+
id="button-1"
|
|
65
|
+
onInteract={() => {
|
|
66
|
+
// 状態を更新(全てのクライアントで同期される)
|
|
67
|
+
setButtonState({ enabled: !buttonState.enabled })
|
|
68
|
+
}}
|
|
69
|
+
>
|
|
70
|
+
<mesh>
|
|
71
|
+
<meshStandardMaterial color={buttonState.enabled ? 'green' : 'red'} />
|
|
72
|
+
</mesh>
|
|
73
|
+
</Interactable>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
#### 使用方法
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
const [state, setState] = useInstanceState<T>(stateId, initialState)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
- `stateId`: 状態の一意識別子(インスタンス内で一意である必要があります)
|
|
85
|
+
- `initialState`: 初期状態
|
|
86
|
+
- `setState`: 状態を更新する関数(直接値 or 関数型アップデートをサポート)
|
|
87
|
+
|
|
88
|
+
#### 関数型アップデート
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
// 直接値を設定
|
|
92
|
+
setState({ enabled: true })
|
|
93
|
+
|
|
94
|
+
// 前の状態を基に更新
|
|
95
|
+
setState(prev => ({ enabled: !prev.enabled }))
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### 注意事項
|
|
99
|
+
|
|
100
|
+
- Context未設定時はローカル `useState` として動作します
|
|
101
|
+
- プラットフォーム側(xrift-frontend)がWebSocket実装を注入することで、インスタンス全体での同期が有効になります
|
|
102
|
+
- 状態はシリアライズ可能な値(JSON)である必要があります
|
|
103
|
+
|
|
51
104
|
### Interactable コンポーネント
|
|
52
105
|
|
|
53
106
|
3Dオブジェクトをインタラクション可能にするラッパーコンポーネントです。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Interactable/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAAsE,KAAK,EAAE,EAAE,MAAM,OAAO,CAAA;AAGnG,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAIpC,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Interactable/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAAsE,KAAK,EAAE,EAAE,MAAM,OAAO,CAAA;AAGnG,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAIpC,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,KAAK,CAgHlC,CAAA;AAED,YAAY,EAAE,KAAK,IAAI,iBAAiB,EAAE,MAAM,SAAS,CAAA"}
|
|
@@ -4,9 +4,9 @@ import { Children, cloneElement, isValidElement, useEffect, useMemo, useRef } fr
|
|
|
4
4
|
import { useXRift } from '../../contexts/XRiftContext';
|
|
5
5
|
const INTERACTABLE_LAYER = 10;
|
|
6
6
|
export const Interactable = ({ id, type = 'button', onInteract, interactionText, enabled = true, children, }) => {
|
|
7
|
-
const { currentTarget } = useXRift();
|
|
7
|
+
const { currentTarget, registerInteractable, unregisterInteractable } = useXRift();
|
|
8
8
|
const groupRef = useRef(null);
|
|
9
|
-
// userDataにインタラクション情報を設定 & レイヤー設定
|
|
9
|
+
// userDataにインタラクション情報を設定 & レイヤー設定 & オブジェクト登録
|
|
10
10
|
useEffect(() => {
|
|
11
11
|
const object = groupRef.current;
|
|
12
12
|
if (!object)
|
|
@@ -24,8 +24,12 @@ export const Interactable = ({ id, type = 'button', onInteract, interactionText,
|
|
|
24
24
|
object.traverse((child) => {
|
|
25
25
|
child.layers.enable(INTERACTABLE_LAYER);
|
|
26
26
|
});
|
|
27
|
+
// インタラクト可能オブジェクトとして登録
|
|
28
|
+
registerInteractable(object);
|
|
27
29
|
// クリーンアップ: userDataからインタラクション情報を削除
|
|
28
30
|
return () => {
|
|
31
|
+
// 登録解除
|
|
32
|
+
unregisterInteractable(object);
|
|
29
33
|
if (object.userData) {
|
|
30
34
|
delete object.userData.id;
|
|
31
35
|
delete object.userData.type;
|
|
@@ -38,7 +42,7 @@ export const Interactable = ({ id, type = 'button', onInteract, interactionText,
|
|
|
38
42
|
child.layers.disable(INTERACTABLE_LAYER);
|
|
39
43
|
});
|
|
40
44
|
};
|
|
41
|
-
}, [id, type, onInteract, interactionText, enabled]);
|
|
45
|
+
}, [id, type, onInteract, interactionText, enabled, registerInteractable, unregisterInteractable]);
|
|
42
46
|
// 現在のターゲットかどうかで視覚的フィードバックを提供
|
|
43
47
|
const isTargeted = currentTarget !== null && currentTarget.uuid === groupRef.current?.uuid;
|
|
44
48
|
// 再帰的に子要素を探索して、すべての<mesh>に<Outlines>を追加する関数
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Interactable/index.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAW,MAAM,OAAO,CAAA;AAEnG,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAGtD,MAAM,kBAAkB,GAAG,EAAE,CAAA;AAE7B,MAAM,CAAC,MAAM,YAAY,GAAc,CAAC,EACtC,EAAE,EACF,IAAI,GAAG,QAAQ,EACf,UAAU,EACV,eAAe,EACf,OAAO,GAAG,IAAI,EACd,QAAQ,GACT,EAAE,EAAE;IACH,MAAM,EAAE,aAAa,EAAE,GAAG,QAAQ,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Interactable/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* インスタンス状態を管理するためのインターフェース
|
|
4
|
+
* プラットフォーム側(xrift-frontend)がWebSocket実装を注入する
|
|
5
|
+
*/
|
|
6
|
+
export interface InstanceStateContextValue {
|
|
7
|
+
/**
|
|
8
|
+
* 指定されたIDの状態を取得する
|
|
9
|
+
* @param stateId 状態の一意識別子
|
|
10
|
+
* @param initialState 初期状態
|
|
11
|
+
* @returns [現在の状態, 状態更新関数]
|
|
12
|
+
*/
|
|
13
|
+
getState: <T>(stateId: string, initialState: T) => [T, (state: T | ((prevState: T) => T)) => void];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* インスタンス状態を管理するContext
|
|
17
|
+
* ワールド作成者はこのContextを通じてインスタンス全体で同期される状態にアクセスする
|
|
18
|
+
*/
|
|
19
|
+
export declare const InstanceStateContext: import("react").Context<InstanceStateContextValue>;
|
|
20
|
+
interface Props {
|
|
21
|
+
/**
|
|
22
|
+
* プラットフォーム側が提供する実装(WebSocket同期など)
|
|
23
|
+
* 未指定の場合はデフォルト実装(ローカルstate)が使用される
|
|
24
|
+
*/
|
|
25
|
+
implementation?: InstanceStateContextValue;
|
|
26
|
+
children: ReactNode;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* インスタンス状態を提供するContextProvider
|
|
30
|
+
* プラットフォーム側(xrift-frontend)がWebSocket実装を注入するために使用
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // プラットフォーム側での使用例
|
|
34
|
+
* <InstanceStateProvider implementation={webSocketImplementation}>
|
|
35
|
+
* <WorldComponent />
|
|
36
|
+
* </InstanceStateProvider>
|
|
37
|
+
*/
|
|
38
|
+
export declare const InstanceStateProvider: ({ implementation, children }: Props) => import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
/**
|
|
40
|
+
* インスタンス状態のContextを取得するhook
|
|
41
|
+
* 通常、ワールド作成者は直接このhookを使用せず、useInstanceStateを使用する
|
|
42
|
+
*/
|
|
43
|
+
export declare const useInstanceStateContext: () => InstanceStateContextValue;
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=InstanceStateContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InstanceStateContext.d.ts","sourceRoot":"","sources":["../../src/contexts/InstanceStateContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAwB,MAAM,OAAO,CAAA;AAE3E;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;;;OAKG;IACH,QAAQ,EAAE,CAAC,CAAC,EACV,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,CAAC,KACZ,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAA;CACrD;AA2BD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,oDAEhC,CAAA;AAED,UAAU,KAAK;IACb;;;OAGG;IACH,cAAc,CAAC,EAAE,yBAAyB,CAAA;IAC1C,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,GAAI,8BAA8B,KAAK,4CASxE,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,QAAO,yBAE1C,CAAA"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useState } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* デフォルト実装: Context未設定時はローカルuseStateとして動作
|
|
5
|
+
* 開発時やテスト時に使用される
|
|
6
|
+
*/
|
|
7
|
+
const createDefaultImplementation = () => {
|
|
8
|
+
const stateMap = new Map();
|
|
9
|
+
const setterMap = new Map();
|
|
10
|
+
return {
|
|
11
|
+
getState: (stateId, initialState) => {
|
|
12
|
+
// このstateIdで既に状態が存在する場合は既存の状態を返す
|
|
13
|
+
if (stateMap.has(stateId)) {
|
|
14
|
+
return [stateMap.get(stateId), setterMap.get(stateId)];
|
|
15
|
+
}
|
|
16
|
+
// 新しい状態を作成
|
|
17
|
+
const [state, setState] = useState(initialState);
|
|
18
|
+
stateMap.set(stateId, state);
|
|
19
|
+
setterMap.set(stateId, setState);
|
|
20
|
+
return [state, setState];
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* インスタンス状態を管理するContext
|
|
26
|
+
* ワールド作成者はこのContextを通じてインスタンス全体で同期される状態にアクセスする
|
|
27
|
+
*/
|
|
28
|
+
export const InstanceStateContext = createContext(createDefaultImplementation());
|
|
29
|
+
/**
|
|
30
|
+
* インスタンス状態を提供するContextProvider
|
|
31
|
+
* プラットフォーム側(xrift-frontend)がWebSocket実装を注入するために使用
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // プラットフォーム側での使用例
|
|
35
|
+
* <InstanceStateProvider implementation={webSocketImplementation}>
|
|
36
|
+
* <WorldComponent />
|
|
37
|
+
* </InstanceStateProvider>
|
|
38
|
+
*/
|
|
39
|
+
export const InstanceStateProvider = ({ implementation, children }) => {
|
|
40
|
+
const defaultImplementation = createDefaultImplementation();
|
|
41
|
+
const value = implementation || defaultImplementation;
|
|
42
|
+
return (_jsx(InstanceStateContext.Provider, { value: value, children: children }));
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* インスタンス状態のContextを取得するhook
|
|
46
|
+
* 通常、ワールド作成者は直接このhookを使用せず、useInstanceStateを使用する
|
|
47
|
+
*/
|
|
48
|
+
export const useInstanceStateContext = () => {
|
|
49
|
+
return useContext(InstanceStateContext);
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=InstanceStateContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InstanceStateContext.js","sourceRoot":"","sources":["../../src/contexts/InstanceStateContext.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAkB,UAAU,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAmB3E;;;GAGG;AACH,MAAM,2BAA2B,GAAG,GAA8B,EAAE;IAClE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAe,CAAA;IACvC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAgC,CAAA;IAEzD,OAAO;QACL,QAAQ,EAAE,CAAK,OAAe,EAAE,YAAe,EAAE,EAAE;YACjD,iCAAiC;YACjC,IAAI,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC,CAAA;YACzD,CAAC;YAED,WAAW;YACX,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAI,YAAY,CAAC,CAAA;YACnD,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;YAC5B,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;YAEhC,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QAC1B,CAAC;KACF,CAAA;AACH,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,aAAa,CAC/C,2BAA2B,EAAE,CAC9B,CAAA;AAWD;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,EAAE,cAAc,EAAE,QAAQ,EAAS,EAAE,EAAE;IAC3E,MAAM,qBAAqB,GAAG,2BAA2B,EAAE,CAAA;IAC3D,MAAM,KAAK,GAAG,cAAc,IAAI,qBAAqB,CAAA;IAErD,OAAO,CACL,KAAC,oBAAoB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YACxC,QAAQ,GACqB,CACjC,CAAA;AACH,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAA8B,EAAE;IACrE,OAAO,UAAU,CAAC,oBAAoB,CAAC,CAAA;AACzC,CAAC,CAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import type { Object3D } from 'three';
|
|
3
|
+
import { type InstanceStateContextValue } from './InstanceStateContext';
|
|
3
4
|
export interface XRiftContextValue {
|
|
4
5
|
/**
|
|
5
6
|
* ワールドのベースURL(CDNのディレクトリパス)
|
|
@@ -11,6 +12,19 @@ export interface XRiftContextValue {
|
|
|
11
12
|
* xrift-frontend側のRaycastDetectorが設定する
|
|
12
13
|
*/
|
|
13
14
|
currentTarget: Object3D | null;
|
|
15
|
+
/**
|
|
16
|
+
* インタラクト可能なオブジェクトのセット
|
|
17
|
+
* レイキャストのパフォーマンス最適化のために使用
|
|
18
|
+
*/
|
|
19
|
+
interactableObjects: Set<Object3D>;
|
|
20
|
+
/**
|
|
21
|
+
* インタラクト可能なオブジェクトを登録
|
|
22
|
+
*/
|
|
23
|
+
registerInteractable: (object: Object3D) => void;
|
|
24
|
+
/**
|
|
25
|
+
* インタラクト可能なオブジェクトの登録を解除
|
|
26
|
+
*/
|
|
27
|
+
unregisterInteractable: (object: Object3D) => void;
|
|
14
28
|
}
|
|
15
29
|
/**
|
|
16
30
|
* XRift ワールドの情報を提供するContext
|
|
@@ -20,6 +34,11 @@ export declare const XRiftContext: import("react").Context<XRiftContextValue | n
|
|
|
20
34
|
interface Props {
|
|
21
35
|
baseUrl: string;
|
|
22
36
|
currentTarget?: Object3D | null;
|
|
37
|
+
/**
|
|
38
|
+
* インスタンス状態管理の実装(オプション)
|
|
39
|
+
* 指定しない場合はデフォルト実装(ローカルstate)が使用される
|
|
40
|
+
*/
|
|
41
|
+
instanceStateImplementation?: InstanceStateContextValue;
|
|
23
42
|
children: ReactNode;
|
|
24
43
|
}
|
|
25
44
|
/**
|
|
@@ -27,7 +46,7 @@ interface Props {
|
|
|
27
46
|
* Module Federationで動的にロードされたワールドコンポーネントに
|
|
28
47
|
* 必要な情報を注入するために使用
|
|
29
48
|
*/
|
|
30
|
-
export declare const XRiftProvider: ({ baseUrl, currentTarget, children }: Props) => import("react/jsx-runtime").JSX.Element;
|
|
49
|
+
export declare const XRiftProvider: ({ baseUrl, currentTarget, instanceStateImplementation, children }: Props) => import("react/jsx-runtime").JSX.Element;
|
|
31
50
|
/**
|
|
32
51
|
* XRift ワールドの情報を取得するhook
|
|
33
52
|
* ワールドプロジェクト側でアセットの相対パスを絶対パスに変換する際に使用
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"XRiftContext.d.ts","sourceRoot":"","sources":["../../src/contexts/XRiftContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,
|
|
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,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { createContext, useContext } from 'react';
|
|
2
|
+
import { createContext, useCallback, useContext, useState } from 'react';
|
|
3
|
+
import { InstanceStateProvider } from './InstanceStateContext';
|
|
3
4
|
/**
|
|
4
5
|
* XRift ワールドの情報を提供するContext
|
|
5
6
|
* ワールド側でこのContextを直接参照して情報を取得できる
|
|
@@ -10,11 +11,24 @@ export const XRiftContext = createContext(null);
|
|
|
10
11
|
* Module Federationで動的にロードされたワールドコンポーネントに
|
|
11
12
|
* 必要な情報を注入するために使用
|
|
12
13
|
*/
|
|
13
|
-
export const XRiftProvider = ({ baseUrl, currentTarget = null, children }) => {
|
|
14
|
+
export const XRiftProvider = ({ baseUrl, currentTarget = null, instanceStateImplementation, children }) => {
|
|
15
|
+
// インタラクト可能なオブジェクトの管理
|
|
16
|
+
const [interactableObjects] = useState(() => new Set());
|
|
17
|
+
// オブジェクトの登録
|
|
18
|
+
const registerInteractable = useCallback((object) => {
|
|
19
|
+
interactableObjects.add(object);
|
|
20
|
+
}, [interactableObjects]);
|
|
21
|
+
// オブジェクトの登録解除
|
|
22
|
+
const unregisterInteractable = useCallback((object) => {
|
|
23
|
+
interactableObjects.delete(object);
|
|
24
|
+
}, [interactableObjects]);
|
|
14
25
|
return (_jsx(XRiftContext.Provider, { value: {
|
|
15
26
|
baseUrl,
|
|
16
27
|
currentTarget,
|
|
17
|
-
|
|
28
|
+
interactableObjects,
|
|
29
|
+
registerInteractable,
|
|
30
|
+
unregisterInteractable,
|
|
31
|
+
}, children: _jsx(InstanceStateProvider, { implementation: instanceStateImplementation, children: children }) }));
|
|
18
32
|
};
|
|
19
33
|
/**
|
|
20
34
|
* XRift ワールドの情報を取得するhook
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"XRiftContext.js","sourceRoot":"","sources":["../../src/contexts/XRiftContext.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAkB,UAAU,EAAE,MAAM,OAAO,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;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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* インスタンス全体で同期される状態を管理するhook
|
|
3
|
+
*
|
|
4
|
+
* React の useState と同じAPIを提供します。
|
|
5
|
+
* Context未設定時はローカルstateとして動作し、
|
|
6
|
+
* プラットフォーム側が実装を注入することでWebSocket同期などが可能になります。
|
|
7
|
+
*
|
|
8
|
+
* @param stateId 状態の一意識別子(インスタンス内で一意である必要があります)
|
|
9
|
+
* @param initialState 初期状態
|
|
10
|
+
* @returns [現在の状態, 状態更新関数]
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* // ボタンの有効/無効状態を管理
|
|
14
|
+
* const [buttonState, setButtonState] = useInstanceState('button-1', { enabled: false })
|
|
15
|
+
*
|
|
16
|
+
* // 直接値を設定
|
|
17
|
+
* setButtonState({ enabled: true })
|
|
18
|
+
*
|
|
19
|
+
* // 関数型アップデート
|
|
20
|
+
* setButtonState(prev => ({ enabled: !prev.enabled }))
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* // より複雑な状態の管理
|
|
24
|
+
* interface DoorState {
|
|
25
|
+
* isOpen: boolean
|
|
26
|
+
* openedBy: string | null
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* const [doorState, setDoorState] = useInstanceState<DoorState>('main-door', {
|
|
30
|
+
* isOpen: false,
|
|
31
|
+
* openedBy: null
|
|
32
|
+
* })
|
|
33
|
+
*
|
|
34
|
+
* // ドアを開く
|
|
35
|
+
* setDoorState({ isOpen: true, openedBy: 'player-123' })
|
|
36
|
+
*/
|
|
37
|
+
export declare function useInstanceState<T>(stateId: string, initialState: T): [T, (state: T | ((prevState: T) => T)) => void];
|
|
38
|
+
//# sourceMappingURL=useInstanceState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInstanceState.d.ts","sourceRoot":"","sources":["../../src/hooks/useInstanceState.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,CAAC,GACd,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAGjD"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { useInstanceStateContext } from '../contexts/InstanceStateContext';
|
|
2
|
+
/**
|
|
3
|
+
* インスタンス全体で同期される状態を管理するhook
|
|
4
|
+
*
|
|
5
|
+
* React の useState と同じAPIを提供します。
|
|
6
|
+
* Context未設定時はローカルstateとして動作し、
|
|
7
|
+
* プラットフォーム側が実装を注入することでWebSocket同期などが可能になります。
|
|
8
|
+
*
|
|
9
|
+
* @param stateId 状態の一意識別子(インスタンス内で一意である必要があります)
|
|
10
|
+
* @param initialState 初期状態
|
|
11
|
+
* @returns [現在の状態, 状態更新関数]
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // ボタンの有効/無効状態を管理
|
|
15
|
+
* const [buttonState, setButtonState] = useInstanceState('button-1', { enabled: false })
|
|
16
|
+
*
|
|
17
|
+
* // 直接値を設定
|
|
18
|
+
* setButtonState({ enabled: true })
|
|
19
|
+
*
|
|
20
|
+
* // 関数型アップデート
|
|
21
|
+
* setButtonState(prev => ({ enabled: !prev.enabled }))
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // より複雑な状態の管理
|
|
25
|
+
* interface DoorState {
|
|
26
|
+
* isOpen: boolean
|
|
27
|
+
* openedBy: string | null
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* const [doorState, setDoorState] = useInstanceState<DoorState>('main-door', {
|
|
31
|
+
* isOpen: false,
|
|
32
|
+
* openedBy: null
|
|
33
|
+
* })
|
|
34
|
+
*
|
|
35
|
+
* // ドアを開く
|
|
36
|
+
* setDoorState({ isOpen: true, openedBy: 'player-123' })
|
|
37
|
+
*/
|
|
38
|
+
export function useInstanceState(stateId, initialState) {
|
|
39
|
+
const context = useInstanceStateContext();
|
|
40
|
+
return context.getState(stateId, initialState);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=useInstanceState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInstanceState.js","sourceRoot":"","sources":["../../src/hooks/useInstanceState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAA;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAe,EACf,YAAe;IAEf,MAAM,OAAO,GAAG,uBAAuB,EAAE,CAAA;IACzC,OAAO,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;AAChD,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { XRiftContext, XRiftProvider, useXRift, type XRiftContextValue, } from './contexts/XRiftContext';
|
|
2
|
+
export { InstanceStateContext, useInstanceStateContext, type InstanceStateContextValue, } from './contexts/InstanceStateContext';
|
|
2
3
|
export { Interactable, type InteractableProps, } from './components/Interactable';
|
|
4
|
+
export { useInstanceState } from './hooks/useInstanceState';
|
|
3
5
|
//# 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;
|
|
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;AAGlC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
// Contexts
|
|
2
2
|
export { XRiftContext, XRiftProvider, useXRift, } from './contexts/XRiftContext';
|
|
3
|
+
export { InstanceStateContext, useInstanceStateContext, } from './contexts/InstanceStateContext';
|
|
3
4
|
// Components
|
|
4
5
|
export { Interactable, } from './components/Interactable';
|
|
6
|
+
// Hooks
|
|
7
|
+
export { useInstanceState } from './hooks/useInstanceState';
|
|
5
8
|
//# 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,aAAa;AACb,OAAO,EACL,YAAY,GAEb,MAAM,2BAA2B,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,aAAa;AACb,OAAO,EACL,YAAY,GAEb,MAAM,2BAA2B,CAAA;AAElC,QAAQ;AACR,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA"}
|