@xrift/world-components 0.41.2 → 0.42.1

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 (71) hide show
  1. package/dist/components/DevEnvironment/components/ControlsHelp.d.ts.map +1 -1
  2. package/dist/components/DevEnvironment/components/ControlsHelp.js +1 -1
  3. package/dist/components/DevEnvironment/components/ControlsHelp.js.map +1 -1
  4. package/dist/components/DevEnvironment/components/GrabSystem/__tests__/store.test.d.ts +2 -0
  5. package/dist/components/DevEnvironment/components/GrabSystem/__tests__/store.test.d.ts.map +1 -0
  6. package/dist/components/DevEnvironment/components/GrabSystem/__tests__/store.test.js +114 -0
  7. package/dist/components/DevEnvironment/components/GrabSystem/__tests__/store.test.js.map +1 -0
  8. package/dist/components/DevEnvironment/components/GrabSystem/__tests__/utils.test.d.ts +2 -0
  9. package/dist/components/DevEnvironment/components/GrabSystem/__tests__/utils.test.d.ts.map +1 -0
  10. package/dist/components/DevEnvironment/components/GrabSystem/__tests__/utils.test.js +103 -0
  11. package/dist/components/DevEnvironment/components/GrabSystem/__tests__/utils.test.js.map +1 -0
  12. package/dist/components/DevEnvironment/components/GrabSystem/constants.d.ts +15 -0
  13. package/dist/components/DevEnvironment/components/GrabSystem/constants.d.ts.map +1 -0
  14. package/dist/components/DevEnvironment/components/GrabSystem/constants.js +15 -0
  15. package/dist/components/DevEnvironment/components/GrabSystem/constants.js.map +1 -0
  16. package/dist/components/DevEnvironment/components/GrabSystem/ghostAppearance.d.ts +9 -0
  17. package/dist/components/DevEnvironment/components/GrabSystem/ghostAppearance.d.ts.map +1 -0
  18. package/dist/components/DevEnvironment/components/GrabSystem/ghostAppearance.js +45 -0
  19. package/dist/components/DevEnvironment/components/GrabSystem/ghostAppearance.js.map +1 -0
  20. package/dist/components/DevEnvironment/components/GrabSystem/index.d.ts +12 -0
  21. package/dist/components/DevEnvironment/components/GrabSystem/index.d.ts.map +1 -0
  22. package/dist/components/DevEnvironment/components/GrabSystem/index.js +147 -0
  23. package/dist/components/DevEnvironment/components/GrabSystem/index.js.map +1 -0
  24. package/dist/components/DevEnvironment/components/GrabSystem/store.d.ts +43 -0
  25. package/dist/components/DevEnvironment/components/GrabSystem/store.d.ts.map +1 -0
  26. package/dist/components/DevEnvironment/components/GrabSystem/store.js +89 -0
  27. package/dist/components/DevEnvironment/components/GrabSystem/store.js.map +1 -0
  28. package/dist/components/DevEnvironment/components/GrabSystem/utils.d.ts +29 -0
  29. package/dist/components/DevEnvironment/components/GrabSystem/utils.d.ts.map +1 -0
  30. package/dist/components/DevEnvironment/components/GrabSystem/utils.js +54 -0
  31. package/dist/components/DevEnvironment/components/GrabSystem/utils.js.map +1 -0
  32. package/dist/components/DevEnvironment/index.d.ts.map +1 -1
  33. package/dist/components/DevEnvironment/index.js +6 -1
  34. package/dist/components/DevEnvironment/index.js.map +1 -1
  35. package/dist/components/Grabbable/__tests__/utils.test.d.ts +2 -0
  36. package/dist/components/Grabbable/__tests__/utils.test.d.ts.map +1 -0
  37. package/dist/components/Grabbable/__tests__/utils.test.js +59 -0
  38. package/dist/components/Grabbable/__tests__/utils.test.js.map +1 -0
  39. package/dist/components/Grabbable/constants.d.ts +7 -0
  40. package/dist/components/Grabbable/constants.d.ts.map +1 -0
  41. package/dist/components/Grabbable/constants.js +7 -0
  42. package/dist/components/Grabbable/constants.js.map +1 -0
  43. package/dist/components/Grabbable/index.d.ts +17 -0
  44. package/dist/components/Grabbable/index.d.ts.map +1 -0
  45. package/dist/components/Grabbable/index.js +76 -0
  46. package/dist/components/Grabbable/index.js.map +1 -0
  47. package/dist/components/Grabbable/types.d.ts +27 -0
  48. package/dist/components/Grabbable/types.d.ts.map +1 -0
  49. package/dist/components/Grabbable/types.js +2 -0
  50. package/dist/components/Grabbable/types.js.map +1 -0
  51. package/dist/components/Grabbable/utils.d.ts +26 -0
  52. package/dist/components/Grabbable/utils.d.ts.map +1 -0
  53. package/dist/components/Grabbable/utils.js +41 -0
  54. package/dist/components/Grabbable/utils.js.map +1 -0
  55. package/dist/constants/layers.d.ts +6 -0
  56. package/dist/constants/layers.d.ts.map +1 -1
  57. package/dist/constants/layers.js +7 -0
  58. package/dist/constants/layers.js.map +1 -1
  59. package/dist/contexts/GrabbableContext.d.ts +78 -0
  60. package/dist/contexts/GrabbableContext.d.ts.map +1 -0
  61. package/dist/contexts/GrabbableContext.js +38 -0
  62. package/dist/contexts/GrabbableContext.js.map +1 -0
  63. package/dist/contexts/XRiftContext.d.ts +7 -1
  64. package/dist/contexts/XRiftContext.d.ts.map +1 -1
  65. package/dist/contexts/XRiftContext.js +3 -1
  66. package/dist/contexts/XRiftContext.js.map +1 -1
  67. package/dist/index.d.ts +3 -0
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +3 -0
  70. package/dist/index.js.map +1 -1
  71. package/package.json +1 -1
@@ -0,0 +1,89 @@
1
+ import { clampHoldDistance, distanceBetween } from './utils';
2
+ const IDLE_PARTIAL = { phase: 'idle', grabbedId: null, hoveredId: null };
3
+ export function createDevGrabStore() {
4
+ const registry = new Map();
5
+ const listeners = new Set();
6
+ let state = {
7
+ phase: 'idle',
8
+ hoveredId: null,
9
+ grabbedId: null,
10
+ holdDistance: 0,
11
+ heldPosition: { x: 0, y: 0, z: 0 },
12
+ heldRotation: { x: 0, y: 0, z: 0 },
13
+ heldScale: 1,
14
+ };
15
+ const setState = (partial) => {
16
+ state = { ...state, ...partial };
17
+ for (const listener of listeners)
18
+ listener();
19
+ };
20
+ return {
21
+ getState: () => state,
22
+ subscribe: (listener) => {
23
+ listeners.add(listener);
24
+ return () => listeners.delete(listener);
25
+ },
26
+ getEntry: (id) => registry.get(id),
27
+ setHovered: (id) => {
28
+ if (state.hoveredId === id)
29
+ return;
30
+ setState({ hoveredId: id });
31
+ },
32
+ grab: (id, cameraPosition) => {
33
+ if (state.phase !== 'idle')
34
+ return;
35
+ const entry = registry.get(id);
36
+ if (!entry)
37
+ return;
38
+ const transform = entry.getTransform();
39
+ setState({
40
+ phase: 'holding',
41
+ grabbedId: id,
42
+ hoveredId: null,
43
+ holdDistance: clampHoldDistance(distanceBetween(cameraPosition, transform.position)),
44
+ heldPosition: transform.position,
45
+ heldRotation: transform.rotation,
46
+ heldScale: transform.scale,
47
+ });
48
+ },
49
+ adjustHoldDistance: (delta) => {
50
+ if (state.phase !== 'holding')
51
+ return;
52
+ setState({ holdDistance: clampHoldDistance(state.holdDistance + delta) });
53
+ },
54
+ updateHeldPosition: (position) => {
55
+ state = { ...state, heldPosition: position };
56
+ },
57
+ release: () => {
58
+ if (state.phase !== 'holding' || !state.grabbedId)
59
+ return;
60
+ const entry = registry.get(state.grabbedId);
61
+ entry?.onMove({ position: state.heldPosition, rotation: state.heldRotation });
62
+ setState(IDLE_PARTIAL);
63
+ },
64
+ cancel: () => {
65
+ if (state.phase !== 'holding')
66
+ return;
67
+ setState(IDLE_PARTIAL);
68
+ },
69
+ contextValue: {
70
+ registerGrabbable: (id, entry) => {
71
+ registry.set(id, entry);
72
+ },
73
+ unregisterGrabbable: (id) => {
74
+ registry.delete(id);
75
+ // 掴み中・ホバー中の対象がアンマウントされたら状態を戻す
76
+ if (state.grabbedId === id)
77
+ setState(IDLE_PARTIAL);
78
+ else if (state.hoveredId === id)
79
+ setState({ hoveredId: null });
80
+ },
81
+ getGrabbedId: () => state.grabbedId,
82
+ subscribeGrabbedId: (listener) => {
83
+ listeners.add(listener);
84
+ return () => listeners.delete(listener);
85
+ },
86
+ },
87
+ };
88
+ }
89
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../../src/components/DevEnvironment/components/GrabSystem/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { Object3D } from 'three';
2
+ import type { Position3D } from '../../../../types/movement';
3
+ /** クォータニオン(three に依存しない形) */
4
+ export interface QuaternionLike {
5
+ x: number;
6
+ y: number;
7
+ z: number;
8
+ w: number;
9
+ }
10
+ /** 掴み距離を [MIN, MAX] に収める */
11
+ export declare function clampHoldDistance(distance: number): number;
12
+ /** 2点間の距離 */
13
+ export declare function distanceBetween(a: Position3D, b: Position3D): number;
14
+ /**
15
+ * 視点(カメラ姿勢)から前方 distance[m] の位置を求める。
16
+ * cameraQuaternion を差し替えるだけで VR コントローラーの pose にも流用できる純粋関数。
17
+ * 前方ベクトル (0, 0, -1) をクォータニオンで回転して distance 倍する。
18
+ */
19
+ export declare function computeHeldPosition(cameraPosition: Position3D, cameraQuaternion: QuaternionLike, distance: number): Position3D;
20
+ /** ヒットした Object3D から親を辿り、grabbable ID を見つける。無ければ null */
21
+ export declare function findGrabbableId(object: Object3D | null): string | null;
22
+ /**
23
+ * レイキャスト結果(手前から順)を走査し、最初に見つかった grabbable ID を返す。
24
+ * どれも掴める対象でなければ null。
25
+ */
26
+ export declare function findFirstGrabbableId(intersects: readonly {
27
+ object: Object3D;
28
+ }[]): string | null;
29
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../src/components/DevEnvironment/components/GrabSystem/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACrC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAI5D,6BAA6B;AAC7B,MAAM,WAAW,cAAc;IAC7B,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED,4BAA4B;AAC5B,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,aAAa;AACb,wBAAgB,eAAe,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,MAAM,CAEpE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,UAAU,EAC1B,gBAAgB,EAAE,cAAc,EAChC,QAAQ,EAAE,MAAM,GACf,UAAU,CAeZ;AAED,yDAAyD;AACzD,wBAAgB,eAAe,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAQtE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,SAAS;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,EAAE,GAAG,MAAM,GAAG,IAAI,CAM/F"}
@@ -0,0 +1,54 @@
1
+ import { GRABBABLE_USER_DATA_KEY } from '../../../Grabbable/constants';
2
+ import { MAX_ANCESTOR_DEPTH, MAX_HOLD_DISTANCE, MIN_HOLD_DISTANCE } from './constants';
3
+ /** 掴み距離を [MIN, MAX] に収める */
4
+ export function clampHoldDistance(distance) {
5
+ return Math.min(MAX_HOLD_DISTANCE, Math.max(MIN_HOLD_DISTANCE, distance));
6
+ }
7
+ /** 2点間の距離 */
8
+ export function distanceBetween(a, b) {
9
+ return Math.hypot(a.x - b.x, a.y - b.y, a.z - b.z);
10
+ }
11
+ /**
12
+ * 視点(カメラ姿勢)から前方 distance[m] の位置を求める。
13
+ * cameraQuaternion を差し替えるだけで VR コントローラーの pose にも流用できる純粋関数。
14
+ * 前方ベクトル (0, 0, -1) をクォータニオンで回転して distance 倍する。
15
+ */
16
+ export function computeHeldPosition(cameraPosition, cameraQuaternion, distance) {
17
+ const q = cameraQuaternion;
18
+ // v = (0, 0, -1) を q で回転: v' = v + w*t + q×t, t = 2*(q×v)
19
+ const tx = 2 * -q.y;
20
+ const ty = 2 * q.x;
21
+ const tz = 0;
22
+ const dx = q.w * tx + (q.y * tz - q.z * ty);
23
+ const dy = q.w * ty + (q.z * tx - q.x * tz);
24
+ const dz = -1 + q.w * tz + (q.x * ty - q.y * tx);
25
+ return {
26
+ x: cameraPosition.x + dx * distance,
27
+ y: cameraPosition.y + dy * distance,
28
+ z: cameraPosition.z + dz * distance,
29
+ };
30
+ }
31
+ /** ヒットした Object3D から親を辿り、grabbable ID を見つける。無ければ null */
32
+ export function findGrabbableId(object) {
33
+ let current = object;
34
+ for (let i = 0; i < MAX_ANCESTOR_DEPTH && current; i++) {
35
+ const id = current.userData[GRABBABLE_USER_DATA_KEY];
36
+ if (typeof id === 'string')
37
+ return id;
38
+ current = current.parent;
39
+ }
40
+ return null;
41
+ }
42
+ /**
43
+ * レイキャスト結果(手前から順)を走査し、最初に見つかった grabbable ID を返す。
44
+ * どれも掴める対象でなければ null。
45
+ */
46
+ export function findFirstGrabbableId(intersects) {
47
+ for (const intersect of intersects) {
48
+ const id = findGrabbableId(intersect.object);
49
+ if (id)
50
+ return id;
51
+ }
52
+ return null;
53
+ }
54
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../src/components/DevEnvironment/components/GrabSystem/utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAA;AACtE,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAUtF,4BAA4B;AAC5B,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,OAAO,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC,CAAA;AAC3E,CAAC;AAED,aAAa;AACb,MAAM,UAAU,eAAe,CAAC,CAAa,EAAE,CAAa;IAC1D,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;AACpD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,cAA0B,EAC1B,gBAAgC,EAChC,QAAgB;IAEhB,MAAM,CAAC,GAAG,gBAAgB,CAAA;IAC1B,0DAA0D;IAC1D,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IACnB,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IAClB,MAAM,EAAE,GAAG,CAAC,CAAA;IACZ,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAA;IAC3C,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAA;IAC3C,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAA;IAEhD,OAAO;QACL,CAAC,EAAE,cAAc,CAAC,CAAC,GAAG,EAAE,GAAG,QAAQ;QACnC,CAAC,EAAE,cAAc,CAAC,CAAC,GAAG,EAAE,GAAG,QAAQ;QACnC,CAAC,EAAE,cAAc,CAAC,CAAC,GAAG,EAAE,GAAG,QAAQ;KACpC,CAAA;AACH,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,eAAe,CAAC,MAAuB;IACrD,IAAI,OAAO,GAAoB,MAAM,CAAA;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,kBAAkB,IAAI,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC;QACvD,MAAM,EAAE,GAAI,OAAO,CAAC,QAAoC,CAAC,uBAAuB,CAAC,CAAA;QACjF,IAAI,OAAO,EAAE,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAA;QACrC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAA;IAC1B,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,UAA2C;IAC9E,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,EAAE,GAAG,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;QAC5C,IAAI,EAAE;YAAE,OAAO,EAAE,CAAA;IACnB,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/DevEnvironment/index.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAmCpC,MAAM,MAAM,mBAAmB,GAAG,KAAK,CAAA;AAmBvC,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,MAAM,EACN,SAAsB,EACtB,OAAc,EACd,aAAsC,EACtC,gBAAsC,EACtC,aAAa,EACb,gBAAgB,EAAE,mBAAmB,GACtC,EAAE,KAAK,2CAqFP"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/DevEnvironment/index.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAqCpC,MAAM,MAAM,mBAAmB,GAAG,KAAK,CAAA;AAmBvC,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,MAAM,EACN,SAAsB,EACtB,OAAc,EACd,aAAsC,EACtC,gBAAsC,EACtC,aAAa,EACb,gBAAgB,EAAE,mBAAmB,GACtC,EAAE,KAAK,2CA0FP"}
@@ -3,12 +3,15 @@ import { useCallback, useMemo, useRef, useState, useSyncExternalStore } from 're
3
3
  import { Canvas } from '@react-three/fiber';
4
4
  import { PointerLockControls } from '@react-three/drei';
5
5
  import { Physics } from '@react-three/rapier';
6
+ import { GrabbableProvider } from '../../contexts/GrabbableContext';
6
7
  import { SpawnPointProvider } from '../../contexts/SpawnPointContext';
7
8
  import { UsersProvider } from '../../contexts/UsersContext';
8
9
  import { PCFShadowMap } from 'three';
9
10
  import { toThreeOutputBufferType } from './utils';
10
11
  import { DEFAULT_SPAWN_POSITION, DEFAULT_GRAVITY, DEFAULT_ALLOW_INFINITE_JUMP, DEFAULT_CAMERA_NEAR, DEFAULT_CAMERA_FAR, MOVE_SPEED, RESPAWN_Y_THRESHOLD, DEV_LOCAL_USER_ID, DEV_LOCAL_USER_DISPLAY_NAME, DEV_AVATAR_HEIGHT, DEV_EYE_HEIGHT, } from './constants';
11
12
  import { PhysicsPlayer } from './components/PhysicsPlayer';
13
+ import { GrabSystem } from './components/GrabSystem';
14
+ import { createDevGrabStore } from './components/GrabSystem/store';
12
15
  import { CenterRaycaster } from './components/CenterRaycaster';
13
16
  import { Crosshair } from './components/Crosshair';
14
17
  import { PointerLockStatus } from './components/PointerLockStatus';
@@ -40,6 +43,8 @@ function getPointerLockSnapshot() {
40
43
  }
41
44
  export function DevEnvironment({ children, camera, moveSpeed = MOVE_SPEED, shadows = true, spawnPosition = DEFAULT_SPAWN_POSITION, respawnThreshold = RESPAWN_Y_THRESHOLD, physicsConfig, outputBufferType: outputBufferTypeStr, }) {
42
45
  const [isHit, setIsHit] = useState(false);
46
+ // ローカル掴みストア(<Grabbable> の登録先 & 開発プレビュー用 GrabSystem の状態)
47
+ const [grabStore] = useState(createDevGrabStore);
43
48
  const isPointerLocked = useSyncExternalStore(subscribePointerLock, getPointerLockSnapshot, () => false);
44
49
  const handleHitChange = useCallback((hit) => setIsHit(hit), []);
45
50
  // ローカルユーザーの位置情報を保持する ref。PhysicsPlayer が毎フレーム書き込み、
@@ -76,6 +81,6 @@ export function DevEnvironment({ children, camera, moveSpeed = MOVE_SPEED, shado
76
81
  fov: cameraFov,
77
82
  near: cameraNear,
78
83
  far: cameraFar,
79
- }, gl: glProps, children: [_jsx(PointerLockControls, {}), _jsx(CenterRaycaster, { onHitChange: handleHitChange }), _jsx(Physics, { gravity: [0, -gravity, 0], timeStep: "vary", children: _jsx(SpawnPointProvider, { children: _jsxs(UsersProvider, { implementation: usersImplementation, children: [_jsx(PhysicsPlayer, { moveSpeed: moveSpeed, spawnPosition: spawnPosition, respawnThreshold: respawnThreshold, allowInfiniteJump: allowInfiniteJump, movementRef: localMovementRef }), children] }) }) })] }), _jsx(Crosshair, { active: isHit }), _jsx(PointerLockStatus, { isLocked: isPointerLocked }), _jsx(ControlsHelp, {})] }));
84
+ }, gl: glProps, children: [_jsx(PointerLockControls, {}), _jsx(CenterRaycaster, { onHitChange: handleHitChange }), _jsx(Physics, { gravity: [0, -gravity, 0], timeStep: "vary", children: _jsx(SpawnPointProvider, { children: _jsx(UsersProvider, { implementation: usersImplementation, children: _jsxs(GrabbableProvider, { implementation: grabStore.contextValue, children: [_jsx(PhysicsPlayer, { moveSpeed: moveSpeed, spawnPosition: spawnPosition, respawnThreshold: respawnThreshold, allowInfiniteJump: allowInfiniteJump, movementRef: localMovementRef }), _jsx(GrabSystem, { store: grabStore }), children] }) }) }) })] }), _jsx(Crosshair, { active: isHit }), _jsx(PointerLockStatus, { isLocked: isPointerLocked }), _jsx(ControlsHelp, {})] }));
80
85
  }
81
86
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/DevEnvironment/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/DevEnvironment/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=utils.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../../../../src/components/Grabbable/__tests__/utils.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,59 @@
1
+ import { Euler, Matrix4, Quaternion, Vector3 } from 'three';
2
+ import { describe, expect, it } from 'vitest';
3
+ import { decomposeWorldTransform, worldToLocalTransform } from '../utils';
4
+ describe('decomposeWorldTransform', () => {
5
+ it('単位行列は原点・無回転・スケール1', () => {
6
+ const t = decomposeWorldTransform(new Matrix4());
7
+ expect(t.position).toEqual({ x: 0, y: 0, z: 0 });
8
+ expect(t.scale).toBeCloseTo(1);
9
+ });
10
+ it('平行移動+スケールを分解できる', () => {
11
+ const m = new Matrix4().compose(new Vector3(1, 2, 3), new Quaternion(), new Vector3(2, 2, 2));
12
+ const t = decomposeWorldTransform(m);
13
+ expect(t.position.x).toBeCloseTo(1);
14
+ expect(t.position.y).toBeCloseTo(2);
15
+ expect(t.position.z).toBeCloseTo(3);
16
+ expect(t.scale).toBeCloseTo(2);
17
+ });
18
+ });
19
+ describe('worldToLocalTransform', () => {
20
+ it('親が単位行列ならワールド=ローカル(そのまま返る)', () => {
21
+ const local = worldToLocalTransform({ x: 1, y: 5, z: -2 }, { x: 0, y: 0, z: 0 }, new Matrix4());
22
+ expect(local.position.x).toBeCloseTo(1);
23
+ expect(local.position.y).toBeCloseTo(5);
24
+ expect(local.position.z).toBeCloseTo(-2);
25
+ });
26
+ it('親が平行移動している場合、その分を差し引く(-4 オフセットの再現)', () => {
27
+ // 親が y=-4 に平行移動 → ワールド y=-3 はローカル y=1
28
+ const parent = new Matrix4().makeTranslation(0, -4, 0);
29
+ const local = worldToLocalTransform({ x: 0, y: -3, z: 1 }, { x: 0, y: 0, z: 0 }, parent);
30
+ expect(local.position.x).toBeCloseTo(0);
31
+ expect(local.position.y).toBeCloseTo(1);
32
+ expect(local.position.z).toBeCloseTo(1);
33
+ });
34
+ it('ローカル→ワールド→ローカルで往復一致する(回転付き親)', () => {
35
+ const parent = new Matrix4().compose(new Vector3(2, -4, 1), new Quaternion().setFromEuler(new Euler(0, Math.PI / 3, 0)), new Vector3(1, 1, 1));
36
+ // 既知のローカル姿勢
37
+ const localPos = new Vector3(0.5, 1.2, -0.3);
38
+ const localEuler = new Euler(0.1, 0.4, -0.2);
39
+ const localQuat = new Quaternion().setFromEuler(localEuler);
40
+ // ローカル→ワールド
41
+ const worldMatrix = new Matrix4()
42
+ .copy(parent)
43
+ .multiply(new Matrix4().compose(localPos, localQuat, new Vector3(1, 1, 1)));
44
+ const wp = new Vector3();
45
+ const wq = new Quaternion();
46
+ const ws = new Vector3();
47
+ worldMatrix.decompose(wp, wq, ws);
48
+ const worldEuler = new Euler().setFromQuaternion(wq);
49
+ // ワールド→ローカルで元に戻る
50
+ const back = worldToLocalTransform({ x: wp.x, y: wp.y, z: wp.z }, { x: worldEuler.x, y: worldEuler.y, z: worldEuler.z }, parent);
51
+ expect(back.position.x).toBeCloseTo(localPos.x);
52
+ expect(back.position.y).toBeCloseTo(localPos.y);
53
+ expect(back.position.z).toBeCloseTo(localPos.z);
54
+ // 回転はクォータニオン一致で確認
55
+ const backQuat = new Quaternion().setFromEuler(new Euler(back.rotation.x, back.rotation.y, back.rotation.z));
56
+ expect(Math.abs(backQuat.dot(localQuat))).toBeCloseTo(1);
57
+ });
58
+ });
59
+ //# sourceMappingURL=utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../../../src/components/Grabbable/__tests__/utils.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * <Grabbable> のルート group に付与する userData キー。値は grabbable ID。
3
+ * GrabSystem のレイキャストがヒットしたメッシュから親を辿って掴める対象と判別する。
4
+ * プラットフォーム側(xrift-frontend)の GrabSystem と共有する契約のため変更しないこと。
5
+ */
6
+ export declare const GRABBABLE_USER_DATA_KEY = "__xriftGrabbableId";
7
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/components/Grabbable/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,uBAAuB,CAAA"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * <Grabbable> のルート group に付与する userData キー。値は grabbable ID。
3
+ * GrabSystem のレイキャストがヒットしたメッシュから親を辿って掴める対象と判別する。
4
+ * プラットフォーム側(xrift-frontend)の GrabSystem と共有する契約のため変更しないこと。
5
+ */
6
+ export const GRABBABLE_USER_DATA_KEY = '__xriftGrabbableId';
7
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/components/Grabbable/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,oBAAoB,CAAA"}
@@ -0,0 +1,17 @@
1
+ import { type FC } from 'react';
2
+ import type { Props } from './types';
3
+ /**
4
+ * 子オブジェクトを「掴める」と宣言するラッパー(<Interactable> と同じ明示オプトイン)
5
+ *
6
+ * - 配下メッシュを GRABBABLE レイヤーに載せ、ルート group に grabbable ID を付ける
7
+ * → GrabSystem のレイキャストが掴める対象と判別できる
8
+ * - transform をルート group に適用する(子はローカル座標で書く)
9
+ * - 掴んでいる間は実体を隠す(GrabSystem がゴーストを代わりに表示する)
10
+ * - 離した(確定)ときは onMove で新しい姿勢が返るので、ワールド側で state に反映する
11
+ *
12
+ * 掴む土台(レイキャスト・追従・確定)はプラットフォーム側の GrabSystem が担う。
13
+ * DevEnvironment 内では同梱のローカル GrabSystem で動作する。
14
+ */
15
+ export declare const Grabbable: FC<Props>;
16
+ export type { Props as GrabbableProps } from './types';
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Grabbable/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoD,KAAK,EAAE,EAAE,MAAM,OAAO,CAAA;AAKjF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAGpC;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,SAAS,EAAE,EAAE,CAAC,KAAK,CAsF/B,CAAA;AAED,YAAY,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,SAAS,CAAA"}
@@ -0,0 +1,76 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';
3
+ import { LAYERS } from '../../constants/layers';
4
+ import { useGrabbableContext } from '../../contexts/GrabbableContext';
5
+ import { GRABBABLE_USER_DATA_KEY } from './constants';
6
+ import { decomposeWorldTransform, worldToLocalTransform } from './utils';
7
+ /**
8
+ * 子オブジェクトを「掴める」と宣言するラッパー(<Interactable> と同じ明示オプトイン)
9
+ *
10
+ * - 配下メッシュを GRABBABLE レイヤーに載せ、ルート group に grabbable ID を付ける
11
+ * → GrabSystem のレイキャストが掴める対象と判別できる
12
+ * - transform をルート group に適用する(子はローカル座標で書く)
13
+ * - 掴んでいる間は実体を隠す(GrabSystem がゴーストを代わりに表示する)
14
+ * - 離した(確定)ときは onMove で新しい姿勢が返るので、ワールド側で state に反映する
15
+ *
16
+ * 掴む土台(レイキャスト・追従・確定)はプラットフォーム側の GrabSystem が担う。
17
+ * DevEnvironment 内では同梱のローカル GrabSystem で動作する。
18
+ */
19
+ export const Grabbable = ({ id, transform, onMove, renderGhost, enabled = true, children, }) => {
20
+ const { registerGrabbable, unregisterGrabbable, getGrabbedId, subscribeGrabbedId } = useGrabbableContext();
21
+ // 掴み中は実体を隠す(ゴーストが代わりに表示される)
22
+ const isGrabbed = useSyncExternalStore(subscribeGrabbedId, () => getGrabbedId() === id, () => false);
23
+ // 毎レンダーで参照が変わっても登録し直さないよう、最新値は ref で保持
24
+ const transformRef = useRef(transform);
25
+ const onMoveRef = useRef(onMove);
26
+ const renderGhostRef = useRef(renderGhost);
27
+ const childrenRef = useRef(children);
28
+ transformRef.current = transform;
29
+ onMoveRef.current = onMove;
30
+ renderGhostRef.current = renderGhost;
31
+ childrenRef.current = children;
32
+ const groupRef = useRef(null);
33
+ const userData = useMemo(() => ({ [GRABBABLE_USER_DATA_KEY]: id }), [id]);
34
+ useEffect(() => {
35
+ if (!enabled)
36
+ return;
37
+ const group = groupRef.current;
38
+ if (!group)
39
+ return;
40
+ // 配下メッシュを GRABBABLE レイヤーに載せてレイキャスト対象にする
41
+ group.traverse((obj) => obj.layers.enable(LAYERS.GRABBABLE));
42
+ registerGrabbable(id, {
43
+ // ゴースト未指定時は children をそのまま流用する
44
+ renderGhost: () => renderGhostRef.current?.() ?? childrenRef.current,
45
+ // GrabSystem はワールド座標で確定位置を返すため、ローカル(transform prop と同じ空間)へ
46
+ // 変換してからユーザーの onMove に渡す。変形された親の下に置いてもズレない
47
+ onMove: (world) => {
48
+ const parent = groupRef.current?.parent;
49
+ if (!parent) {
50
+ onMoveRef.current(world);
51
+ return;
52
+ }
53
+ parent.updateWorldMatrix(true, false);
54
+ onMoveRef.current(worldToLocalTransform(world.position, world.rotation, parent.matrixWorld));
55
+ },
56
+ // GrabSystem 向けにはワールド姿勢を返す(掴み距離・ゴーストの初期姿勢に使われる)。
57
+ // group 未マウント時のみ transform prop(ローカル)にフォールバック
58
+ getTransform: () => {
59
+ const group = groupRef.current;
60
+ if (!group) {
61
+ const t = transformRef.current;
62
+ return { position: t.position, rotation: t.rotation, scale: t.scale ?? 1 };
63
+ }
64
+ group.updateWorldMatrix(true, false);
65
+ return decomposeWorldTransform(group.matrixWorld);
66
+ },
67
+ });
68
+ return () => {
69
+ unregisterGrabbable(id);
70
+ group.traverse((obj) => obj.layers.disable(LAYERS.GRABBABLE));
71
+ };
72
+ }, [id, enabled, registerGrabbable, unregisterGrabbable]);
73
+ const { position, rotation, scale = 1 } = transform;
74
+ return (_jsx("group", { ref: groupRef, position: [position.x, position.y, position.z], rotation: [rotation.x, rotation.y, rotation.z], scale: scale, userData: userData, visible: !isGrabbed, children: children }));
75
+ };
76
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Grabbable/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { GrabbableTransform, GrabResultTransform } from '../../contexts/GrabbableContext';
3
+ export interface Props {
4
+ /** 掴める対象の一意なID */
5
+ id: string;
6
+ /**
7
+ * 対象の現在姿勢。Grabbable がルート group に適用するため、
8
+ * 子はローカル座標(原点基準)で書く
9
+ */
10
+ transform: GrabbableTransform;
11
+ /**
12
+ * 離した(確定)ときに新しい姿勢を受け取る
13
+ * ワールド側で state に反映して transform prop を更新する
14
+ */
15
+ onMove: (transform: GrabResultTransform) => void;
16
+ /**
17
+ * 掴んでいる間に表示するゴースト(半透明・物理なし)をローカル座標で返す
18
+ * 省略時は children をそのまま流用する
19
+ * 子に物理(RigidBody 等)を含む場合は物理なし版を必ず指定すること
20
+ */
21
+ renderGhost?: () => ReactNode;
22
+ /** 掴めるかどうか(false で一時的に掴めなくする) */
23
+ enabled?: boolean;
24
+ /** 子要素(3Dオブジェクト・ローカル座標で書く) */
25
+ children: ReactNode;
26
+ }
27
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/Grabbable/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAA;AAE9F,MAAM,WAAW,KAAK;IACpB,kBAAkB;IAClB,EAAE,EAAE,MAAM,CAAA;IACV;;;OAGG;IACH,SAAS,EAAE,kBAAkB,CAAA;IAC7B;;;OAGG;IACH,MAAM,EAAE,CAAC,SAAS,EAAE,mBAAmB,KAAK,IAAI,CAAA;IAChD;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,SAAS,CAAA;IAC7B,iCAAiC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,8BAA8B;IAC9B,QAAQ,EAAE,SAAS,CAAA;CACpB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/components/Grabbable/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ import { Matrix4 } from 'three';
2
+ import type { Position3D, Rotation3D } from '../../types/movement';
3
+ /** GrabSystem が扱う姿勢(位置・Euler回転・均一スケール) */
4
+ export interface WorldTransform {
5
+ position: Position3D;
6
+ rotation: Rotation3D;
7
+ scale: number;
8
+ }
9
+ /**
10
+ * ワールド行列を GrabSystem 向けの姿勢(位置・Euler回転・均一スケール)に分解する。
11
+ * <Grabbable> のルート group の matrixWorld を渡すと、変形された親の下にあっても
12
+ * 正しいワールド姿勢が得られる(getTransform 用)。
13
+ */
14
+ export declare function decomposeWorldTransform(matrixWorld: Matrix4): WorldTransform;
15
+ /**
16
+ * ワールド姿勢(位置+Euler回転)を、親のワールド行列に対するローカル姿勢へ変換する。
17
+ * GrabSystem はワールド座標で確定位置を返すため、変形された親を持つ <Grabbable> でも
18
+ * ユーザーの onMove にはローカル座標(transform prop と同じ空間)を渡せる(onMove 用)。
19
+ *
20
+ * 親が無変形(単位行列)ならワールド=ローカルなので、そのまま返るのと同じ結果になる。
21
+ */
22
+ export declare function worldToLocalTransform(worldPosition: Position3D, worldRotation: Rotation3D, parentMatrixWorld: Matrix4): {
23
+ position: Position3D;
24
+ rotation: Rotation3D;
25
+ };
26
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/components/Grabbable/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,OAAO,EAAuB,MAAM,OAAO,CAAA;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAElE,0CAA0C;AAC1C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,UAAU,CAAA;IACpB,QAAQ,EAAE,UAAU,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,OAAO,GAAG,cAAc,CAW5E;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,UAAU,EACzB,aAAa,EAAE,UAAU,EACzB,iBAAiB,EAAE,OAAO,GACzB;IAAE,QAAQ,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,UAAU,CAAA;CAAE,CAkBhD"}
@@ -0,0 +1,41 @@
1
+ import { Euler, Matrix4, Quaternion, Vector3 } from 'three';
2
+ /**
3
+ * ワールド行列を GrabSystem 向けの姿勢(位置・Euler回転・均一スケール)に分解する。
4
+ * <Grabbable> のルート group の matrixWorld を渡すと、変形された親の下にあっても
5
+ * 正しいワールド姿勢が得られる(getTransform 用)。
6
+ */
7
+ export function decomposeWorldTransform(matrixWorld) {
8
+ const position = new Vector3();
9
+ const quaternion = new Quaternion();
10
+ const scale = new Vector3();
11
+ matrixWorld.decompose(position, quaternion, scale);
12
+ const euler = new Euler().setFromQuaternion(quaternion);
13
+ return {
14
+ position: { x: position.x, y: position.y, z: position.z },
15
+ rotation: { x: euler.x, y: euler.y, z: euler.z },
16
+ scale: scale.x,
17
+ };
18
+ }
19
+ /**
20
+ * ワールド姿勢(位置+Euler回転)を、親のワールド行列に対するローカル姿勢へ変換する。
21
+ * GrabSystem はワールド座標で確定位置を返すため、変形された親を持つ <Grabbable> でも
22
+ * ユーザーの onMove にはローカル座標(transform prop と同じ空間)を渡せる(onMove 用)。
23
+ *
24
+ * 親が無変形(単位行列)ならワールド=ローカルなので、そのまま返るのと同じ結果になる。
25
+ */
26
+ export function worldToLocalTransform(worldPosition, worldRotation, parentMatrixWorld) {
27
+ const position = new Vector3(worldPosition.x, worldPosition.y, worldPosition.z);
28
+ const quaternion = new Quaternion().setFromEuler(new Euler(worldRotation.x, worldRotation.y, worldRotation.z));
29
+ const worldMatrix = new Matrix4().compose(position, quaternion, new Vector3(1, 1, 1));
30
+ const localMatrix = new Matrix4().copy(parentMatrixWorld).invert().multiply(worldMatrix);
31
+ const localPosition = new Vector3();
32
+ const localQuaternion = new Quaternion();
33
+ const localScale = new Vector3();
34
+ localMatrix.decompose(localPosition, localQuaternion, localScale);
35
+ const localEuler = new Euler().setFromQuaternion(localQuaternion);
36
+ return {
37
+ position: { x: localPosition.x, y: localPosition.y, z: localPosition.z },
38
+ rotation: { x: localEuler.x, y: localEuler.y, z: localEuler.z },
39
+ };
40
+ }
41
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/components/Grabbable/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAU3D;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,WAAoB;IAC1D,MAAM,QAAQ,GAAG,IAAI,OAAO,EAAE,CAAA;IAC9B,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAA;IACnC,MAAM,KAAK,GAAG,IAAI,OAAO,EAAE,CAAA;IAC3B,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,CAAA;IAClD,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAA;IACvD,OAAO;QACL,QAAQ,EAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE;QACzD,QAAQ,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE;QAChD,KAAK,EAAE,KAAK,CAAC,CAAC;KACf,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,aAAyB,EACzB,aAAyB,EACzB,iBAA0B;IAE1B,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;IAC/E,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC,YAAY,CAC9C,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,CAC7D,CAAA;IACD,MAAM,WAAW,GAAG,IAAI,OAAO,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IACrF,MAAM,WAAW,GAAG,IAAI,OAAO,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;IAExF,MAAM,aAAa,GAAG,IAAI,OAAO,EAAE,CAAA;IACnC,MAAM,eAAe,GAAG,IAAI,UAAU,EAAE,CAAA;IACxC,MAAM,UAAU,GAAG,IAAI,OAAO,EAAE,CAAA;IAChC,WAAW,CAAC,SAAS,CAAC,aAAa,EAAE,eAAe,EAAE,UAAU,CAAC,CAAA;IACjE,MAAM,UAAU,GAAG,IAAI,KAAK,EAAE,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAA;IAEjE,OAAO;QACL,QAAQ,EAAE,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE;QACxE,QAAQ,EAAE,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE;KAChE,CAAA;AACH,CAAC"}
@@ -30,6 +30,12 @@ export declare const LAYERS: {
30
30
  * - ボタン、ドア、アイテムなどのインタラクト可能な要素に設定
31
31
  */
32
32
  readonly INTERACTABLE: 11;
33
+ /**
34
+ * 掴める(Grabbable)オブジェクト
35
+ * - GrabSystem のレイキャスト対象
36
+ * - <Grabbable> で囲まれた対象のメッシュに付与し、掴める対象を明示する
37
+ */
38
+ readonly GRABBABLE: 14;
33
39
  };
34
40
  export type LayerName = keyof typeof LAYERS;
35
41
  export type LayerNumber = (typeof LAYERS)[LayerName];
@@ -1 +1 @@
1
- {"version":3,"file":"layers.d.ts","sourceRoot":"","sources":["../../src/constants/layers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,MAAM;IACjB,qCAAqC;;IAGrC;;;;OAIG;;IAGH;;;;OAIG;;IAGH;;;;OAIG;;CAEK,CAAA;AAEV,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,MAAM,CAAA;AAC3C,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,CAAA"}
1
+ {"version":3,"file":"layers.d.ts","sourceRoot":"","sources":["../../src/constants/layers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,MAAM;IACjB,qCAAqC;;IAGrC;;;;OAIG;;IAGH;;;;OAIG;;IAGH;;;;OAIG;;IAKH;;;;OAIG;;CAEK,CAAA;AAEV,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,MAAM,CAAA;AAC3C,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,CAAA"}
@@ -30,5 +30,12 @@ export const LAYERS = {
30
30
  * - ボタン、ドア、アイテムなどのインタラクト可能な要素に設定
31
31
  */
32
32
  INTERACTABLE: 11,
33
+ // 12(WORLD_SURFACE)・13(UI_OVERLAY)はプラットフォーム側(xrift-frontend)で予約済み
34
+ /**
35
+ * 掴める(Grabbable)オブジェクト
36
+ * - GrabSystem のレイキャスト対象
37
+ * - <Grabbable> で囲まれた対象のメッシュに付与し、掴める対象を明示する
38
+ */
39
+ GRABBABLE: 14,
33
40
  };
34
41
  //# sourceMappingURL=layers.js.map