@relu-interactives/spatial-ecs 0.3.8 → 0.3.10

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 (38) hide show
  1. package/dist/{XRHandPose-CxPz8VBp.d.ts → XRHandPose-CjacJ_16.d.ts} +70 -1
  2. package/dist/{XRHandPose-VuSbe4iz.d.cts → XRHandPose-hAtj9wm-.d.cts} +70 -1
  3. package/dist/{chunk-KIKIWCEB.js → chunk-5UVBEAGW.js} +4 -4
  4. package/dist/{chunk-KIKIWCEB.js.map → chunk-5UVBEAGW.js.map} +1 -1
  5. package/dist/{chunk-KVGGAL5V.js → chunk-ELSZ5U3F.js} +23 -3
  6. package/dist/chunk-ELSZ5U3F.js.map +1 -0
  7. package/dist/{chunk-L5BP727H.js → chunk-NJOO7NO6.js} +3 -3
  8. package/dist/{chunk-L5BP727H.js.map → chunk-NJOO7NO6.js.map} +1 -1
  9. package/dist/{chunk-LMTB4KQ4.js → chunk-O2HSIZFC.js} +591 -195
  10. package/dist/chunk-O2HSIZFC.js.map +1 -0
  11. package/dist/components/index.cjs +20 -0
  12. package/dist/components/index.cjs.map +1 -1
  13. package/dist/components/index.d.cts +2 -2
  14. package/dist/components/index.d.ts +2 -2
  15. package/dist/components/index.js +1 -1
  16. package/dist/docs/guide/vr-and-hand-poses.md +48 -0
  17. package/dist/factories/index.cjs +19 -0
  18. package/dist/factories/index.cjs.map +1 -1
  19. package/dist/factories/index.d.cts +1 -1
  20. package/dist/factories/index.d.ts +1 -1
  21. package/dist/factories/index.js +3 -3
  22. package/dist/{index-C7XQyrgE.d.ts → index-B-KhN8Ox.d.ts} +51 -0
  23. package/dist/{index-BxdXgqiI.d.ts → index-B7JDsx4a.d.ts} +9 -2
  24. package/dist/{index-BIQoaKAA.d.cts → index-B9JqYr3Q.d.cts} +9 -2
  25. package/dist/{index-DyN50JZo.d.cts → index-DU-CF-3m.d.cts} +51 -0
  26. package/dist/index.cjs +729 -312
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +29 -6
  29. package/dist/index.d.ts +29 -6
  30. package/dist/index.js +8 -8
  31. package/dist/systems/index.cjs +635 -220
  32. package/dist/systems/index.cjs.map +1 -1
  33. package/dist/systems/index.d.cts +1 -1
  34. package/dist/systems/index.d.ts +1 -1
  35. package/dist/systems/index.js +3 -3
  36. package/package.json +1 -1
  37. package/dist/chunk-KVGGAL5V.js.map +0 -1
  38. package/dist/chunk-LMTB4KQ4.js.map +0 -1
@@ -1,7 +1,7 @@
1
- import { resolveDracoDecoderPath, applyTransform, SHARED_MODEL_RESOURCE_FLAG } from './chunk-L5BP727H.js';
2
- import { AnimationComponent, ModelComponent, CameraComponent, Object3DRef, Environment, Postprocessing, TransformComponent, PhysicsComponent, setPhysicsLiveRef, LightComponent, MaterialComponent, DEFAULT_MESH_GEOMETRY_PARAMETERS, MeshGeometryComponent, InstancedMeshComponent, ParentId, ScriptComponent, ScriptObjectComponent, XRRigComponent, VRTeleportAreaComponent, XRInteractableComponent, XRHandPoseComponent, createHandPoseEntry, XRInteractorComponent, XRInteractorSideComponent, InstanceSlotComponent, Name, ImageComponent, SpriteComponent, VideoComponent, AudioComponent, ImageTarget, Selectable, PrefabNode, PrefabInstance, handPoseDefinitionFor, getHandPosePreset } from './chunk-KVGGAL5V.js';
1
+ import { resolveDracoDecoderPath, applyTransform, SHARED_MODEL_RESOURCE_FLAG } from './chunk-NJOO7NO6.js';
2
+ import { AnimationComponent, ModelComponent, CameraComponent, Object3DRef, Environment, Postprocessing, TransformComponent, PhysicsComponent, setPhysicsLiveRef, LightComponent, MaterialComponent, DEFAULT_MESH_GEOMETRY_PARAMETERS, MeshGeometryComponent, InstancedMeshComponent, ParentId, ScriptComponent, ScriptObjectComponent, XRRigComponent, VRTeleportAreaComponent, XRInteractableComponent, createAttachPoint, XRHandPoseComponent, createHandPoseEntry, XRInteractorComponent, XRInteractorSideComponent, InstanceSlotComponent, Name, ImageComponent, SpriteComponent, VideoComponent, AudioComponent, ImageTarget, Selectable, PrefabNode, PrefabInstance, handPoseDefinitionFor, getHandPosePreset } from './chunk-ELSZ5U3F.js';
3
3
  import { __name } from './chunk-OY7ZODZP.js';
4
- import * as THREE7 from 'three';
4
+ import * as THREE19 from 'three';
5
5
  import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
6
6
  import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js';
7
7
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
@@ -160,7 +160,7 @@ function transitionToClip(runtime, nextClipId, crossFadeDuration) {
160
160
  }
161
161
  __name(transitionToClip, "transitionToClip");
162
162
  function applyActionState(action, component, paused, shouldLoop) {
163
- const loopMode = shouldLoop ? THREE7.LoopRepeat : THREE7.LoopOnce;
163
+ const loopMode = shouldLoop ? THREE19.LoopRepeat : THREE19.LoopOnce;
164
164
  const repetitions = shouldLoop ? Infinity : 1;
165
165
  action.setLoop(loopMode, repetitions);
166
166
  action.clampWhenFinished = !shouldLoop;
@@ -333,7 +333,7 @@ var _AnimationSystem = class _AnimationSystem {
333
333
  if (runtime) {
334
334
  stopAllActions(runtime);
335
335
  }
336
- const mixer = new THREE7.AnimationMixer(root);
336
+ const mixer = new THREE19.AnimationMixer(root);
337
337
  const entries2 = readRuntimeClipEntries(animation);
338
338
  const indexedActions = createActions(mixer, entries2);
339
339
  runtime = {
@@ -459,11 +459,11 @@ function normalizeOrthoBounds(component) {
459
459
  }
460
460
  __name(normalizeOrthoBounds, "normalizeOrthoBounds");
461
461
  function isPerspectiveCamera(camera) {
462
- return camera instanceof THREE7.PerspectiveCamera;
462
+ return camera instanceof THREE19.PerspectiveCamera;
463
463
  }
464
464
  __name(isPerspectiveCamera, "isPerspectiveCamera");
465
465
  function isOrthographicCamera(camera) {
466
- return camera instanceof THREE7.OrthographicCamera;
466
+ return camera instanceof THREE19.OrthographicCamera;
467
467
  }
468
468
  __name(isOrthographicCamera, "isOrthographicCamera");
469
469
  function readWindowAspect() {
@@ -517,7 +517,7 @@ var _CameraSyncSystem = class _CameraSyncSystem {
517
517
  continue;
518
518
  }
519
519
  const camera = objectRef.object;
520
- if (!(camera instanceof THREE7.Camera)) {
520
+ if (!(camera instanceof THREE19.Camera)) {
521
521
  continue;
522
522
  }
523
523
  if (xrCamera !== null && camera === xrCamera) {
@@ -584,7 +584,7 @@ var MIN_DENSITY = 0;
584
584
  function createGradientTexture(effect, colors) {
585
585
  if (typeof document === "undefined") {
586
586
  const pixel = new Uint8Array([30, 30, 30, 255]);
587
- const fallback = new THREE7.DataTexture(pixel, 1, 1, THREE7.RGBAFormat);
587
+ const fallback = new THREE19.DataTexture(pixel, 1, 1, THREE19.RGBAFormat);
588
588
  fallback.needsUpdate = true;
589
589
  return fallback;
590
590
  }
@@ -593,7 +593,7 @@ function createGradientTexture(effect, colors) {
593
593
  canvas.height = 512;
594
594
  const context = canvas.getContext("2d");
595
595
  if (!context) {
596
- const fallback = new THREE7.CanvasTexture(canvas);
596
+ const fallback = new THREE19.CanvasTexture(canvas);
597
597
  fallback.needsUpdate = true;
598
598
  return fallback;
599
599
  }
@@ -621,15 +621,15 @@ function createGradientTexture(effect, colors) {
621
621
  context.fillRect(0, 0, 512, 512);
622
622
  context.globalCompositeOperation = "source-over";
623
623
  }
624
- const texture = new THREE7.CanvasTexture(canvas);
625
- texture.colorSpace = THREE7.SRGBColorSpace;
624
+ const texture = new THREE19.CanvasTexture(canvas);
625
+ texture.colorSpace = THREE19.SRGBColorSpace;
626
626
  texture.needsUpdate = true;
627
627
  return texture;
628
628
  }
629
629
  __name(createGradientTexture, "createGradientTexture");
630
630
  var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
631
631
  constructor(scene) {
632
- this.textureLoader = new THREE7.TextureLoader();
632
+ this.textureLoader = new THREE19.TextureLoader();
633
633
  this.signature = null;
634
634
  this.activeTexture = null;
635
635
  this.pendingImageUrl = null;
@@ -652,7 +652,7 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
652
652
  if (skybox.type === "color") {
653
653
  this.disposeActiveTexture();
654
654
  this.pendingImageUrl = null;
655
- this.scene.background = new THREE7.Color(skybox.color || "#1e1e1e");
655
+ this.scene.background = new THREE19.Color(skybox.color || "#1e1e1e");
656
656
  return;
657
657
  }
658
658
  if (skybox.type === "gradient") {
@@ -686,7 +686,7 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
686
686
  texture.dispose();
687
687
  return;
688
688
  }
689
- texture.colorSpace = THREE7.SRGBColorSpace;
689
+ texture.colorSpace = THREE19.SRGBColorSpace;
690
690
  this.activeTexture = texture;
691
691
  this.scene.background = texture;
692
692
  },
@@ -705,16 +705,16 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
705
705
  this.scene.fog = null;
706
706
  return;
707
707
  }
708
- const fogColor = new THREE7.Color(fog.color || "#1e1e1e");
708
+ const fogColor = new THREE19.Color(fog.color || "#1e1e1e");
709
709
  if (fog.type === "linear") {
710
710
  const near = Number.isFinite(fog.linear.near) ? fog.linear.near : 1;
711
711
  const farCandidate = Number.isFinite(fog.linear.far) ? fog.linear.far : near + 10;
712
712
  const far = Math.max(near + MIN_FOG_DELTA, farCandidate);
713
- this.scene.fog = new THREE7.Fog(fogColor, near, far);
713
+ this.scene.fog = new THREE19.Fog(fogColor, near, far);
714
714
  return;
715
715
  }
716
716
  const density = Number.isFinite(fog.exponential.density) ? Math.max(MIN_DENSITY, fog.exponential.density) : 2e-3;
717
- this.scene.fog = new THREE7.FogExp2(fogColor, density);
717
+ this.scene.fog = new THREE19.FogExp2(fogColor, density);
718
718
  }
719
719
  update(world) {
720
720
  const entityIds = world.query(Environment);
@@ -796,10 +796,10 @@ var _PostprocessingSyncSystem = class _PostprocessingSyncSystem {
796
796
  );
797
797
  }
798
798
  if (values.bloom.enabled) {
799
- const size = this.renderer.getSize(new THREE7.Vector2());
799
+ const size = this.renderer.getSize(new THREE19.Vector2());
800
800
  composer.addPass(
801
801
  new UnrealBloomPass(
802
- new THREE7.Vector2(size.width, size.height),
802
+ new THREE19.Vector2(size.width, size.height),
803
803
  values.bloom.intensity,
804
804
  values.bloom.radius,
805
805
  values.bloom.threshold
@@ -844,7 +844,7 @@ var _PostprocessingSyncSystem = class _PostprocessingSyncSystem {
844
844
  if (values.dotScreen.enabled) {
845
845
  composer.addPass(
846
846
  new DotScreenPass(
847
- new THREE7.Vector2(0, 0),
847
+ new THREE19.Vector2(0, 0),
848
848
  values.dotScreen.angle ?? values.dotScreen.dotScreenAngle,
849
849
  values.dotScreen.scale ?? values.dotScreen.dotScreenScale
850
850
  )
@@ -918,7 +918,7 @@ function computeColliderState(colliderValues, object) {
918
918
  if (!object) {
919
919
  return colliderValues;
920
920
  }
921
- const scale = new THREE7.Vector3();
921
+ const scale = new THREE19.Vector3();
922
922
  object.getWorldScale(scale);
923
923
  return {
924
924
  ...colliderValues,
@@ -969,8 +969,8 @@ function createColliderDesc(RAPIER, values, triMeshData) {
969
969
  values.offsetPosition.y,
970
970
  values.offsetPosition.z
971
971
  );
972
- const offsetQuaternion = new THREE7.Quaternion().setFromEuler(
973
- new THREE7.Euler(
972
+ const offsetQuaternion = new THREE19.Quaternion().setFromEuler(
973
+ new THREE19.Euler(
974
974
  values.offsetRotation.x,
975
975
  values.offsetRotation.y,
976
976
  values.offsetRotation.z
@@ -985,17 +985,17 @@ function collectTriMeshParts(object) {
985
985
  return null;
986
986
  }
987
987
  object.updateWorldMatrix(true, true);
988
- const worldScale = new THREE7.Vector3();
988
+ const worldScale = new THREE19.Vector3();
989
989
  object.getWorldScale(worldScale);
990
990
  const scale = {
991
991
  x: Math.abs(worldScale.x) || 1,
992
992
  y: Math.abs(worldScale.y) || 1,
993
993
  z: Math.abs(worldScale.z) || 1
994
994
  };
995
- const worldToObject = new THREE7.Matrix4().copy(object.matrixWorld).invert();
995
+ const worldToObject = new THREE19.Matrix4().copy(object.matrixWorld).invert();
996
996
  const parts = [];
997
997
  object.traverse((child) => {
998
- if (!(child instanceof THREE7.Mesh) || !child.geometry) {
998
+ if (!(child instanceof THREE19.Mesh) || !child.geometry) {
999
999
  return;
1000
1000
  }
1001
1001
  const geometry = child.geometry;
@@ -1012,7 +1012,7 @@ function collectTriMeshParts(object) {
1012
1012
  if (indexCount < 3) {
1013
1013
  return;
1014
1014
  }
1015
- const relativeMatrix = new THREE7.Matrix4().multiplyMatrices(
1015
+ const relativeMatrix = new THREE19.Matrix4().multiplyMatrices(
1016
1016
  worldToObject,
1017
1017
  child.matrixWorld
1018
1018
  );
@@ -1053,7 +1053,7 @@ function createTriMeshData(collected) {
1053
1053
  }
1054
1054
  const vertices = new Float32Array(vertexTotal * 3);
1055
1055
  const indices = new Uint32Array(indexTotal);
1056
- const point = new THREE7.Vector3();
1056
+ const point = new THREE19.Vector3();
1057
1057
  let vertexOffset = 0;
1058
1058
  let indexOffset = 0;
1059
1059
  for (const part of parts) {
@@ -1085,8 +1085,8 @@ function createTriMeshData(collected) {
1085
1085
  }
1086
1086
  __name(createTriMeshData, "createTriMeshData");
1087
1087
  function syncBodyFromTransform(body, transform) {
1088
- const quaternion = new THREE7.Quaternion().setFromEuler(
1089
- new THREE7.Euler(transform.rotation.x, transform.rotation.y, transform.rotation.z)
1088
+ const quaternion = new THREE19.Quaternion().setFromEuler(
1089
+ new THREE19.Euler(transform.rotation.x, transform.rotation.y, transform.rotation.z)
1090
1090
  );
1091
1091
  body.setTranslation(
1092
1092
  {
@@ -1113,8 +1113,8 @@ function syncTransformFromBody(transform, body) {
1113
1113
  transform.position.x = position.x;
1114
1114
  transform.position.y = position.y;
1115
1115
  transform.position.z = position.z;
1116
- const euler = new THREE7.Euler().setFromQuaternion(
1117
- new THREE7.Quaternion(rotation.x, rotation.y, rotation.z, rotation.w)
1116
+ const euler = new THREE19.Euler().setFromQuaternion(
1117
+ new THREE19.Quaternion(rotation.x, rotation.y, rotation.z, rotation.w)
1118
1118
  );
1119
1119
  transform.rotation.x = euler.x;
1120
1120
  transform.rotation.y = euler.y;
@@ -1226,8 +1226,8 @@ var _PhysicsSyncSystem = class _PhysicsSyncSystem {
1226
1226
  transform.position.y,
1227
1227
  transform.position.z
1228
1228
  );
1229
- const quaternion = new THREE7.Quaternion().setFromEuler(
1230
- new THREE7.Euler(
1229
+ const quaternion = new THREE19.Quaternion().setFromEuler(
1230
+ new THREE19.Euler(
1231
1231
  transform.rotation.x,
1232
1232
  transform.rotation.y,
1233
1233
  transform.rotation.z
@@ -1806,7 +1806,7 @@ function applyLightValues(lightComponent) {
1806
1806
  values.castShadow
1807
1807
  );
1808
1808
  }
1809
- if (light instanceof THREE7.PointLight) {
1809
+ if (light instanceof THREE19.PointLight) {
1810
1810
  if (typeof values.distance === "number" && Number.isFinite(values.distance)) {
1811
1811
  light.distance = Math.max(MIN_LIGHT_DISTANCE, values.distance);
1812
1812
  }
@@ -1814,7 +1814,7 @@ function applyLightValues(lightComponent) {
1814
1814
  light.decay = Math.max(0, values.decay);
1815
1815
  }
1816
1816
  }
1817
- if (light instanceof THREE7.SpotLight) {
1817
+ if (light instanceof THREE19.SpotLight) {
1818
1818
  if (typeof values.distance === "number" && Number.isFinite(values.distance)) {
1819
1819
  light.distance = Math.max(MIN_LIGHT_DISTANCE, values.distance);
1820
1820
  }
@@ -1828,7 +1828,7 @@ function applyLightValues(lightComponent) {
1828
1828
  light.penumbra = Math.max(0, Math.min(1, values.penumbra));
1829
1829
  }
1830
1830
  }
1831
- if (light instanceof THREE7.RectAreaLight) {
1831
+ if (light instanceof THREE19.RectAreaLight) {
1832
1832
  if (typeof values.width === "number" && Number.isFinite(values.width)) {
1833
1833
  light.width = Math.max(MIN_AREA_SIZE, values.width);
1834
1834
  }
@@ -1889,15 +1889,15 @@ function resolveMaterialPropertyKey(key) {
1889
1889
  __name(resolveMaterialPropertyKey, "resolveMaterialPropertyKey");
1890
1890
  function createMaterialByType(type) {
1891
1891
  if (type === "basic") {
1892
- return new THREE7.MeshBasicMaterial();
1892
+ return new THREE19.MeshBasicMaterial();
1893
1893
  }
1894
1894
  if (type === "phong") {
1895
- return new THREE7.MeshPhongMaterial();
1895
+ return new THREE19.MeshPhongMaterial();
1896
1896
  }
1897
1897
  if (type === "physical") {
1898
- return new THREE7.MeshPhysicalMaterial();
1898
+ return new THREE19.MeshPhysicalMaterial();
1899
1899
  }
1900
- return new THREE7.MeshStandardMaterial();
1900
+ return new THREE19.MeshStandardMaterial();
1901
1901
  }
1902
1902
  __name(createMaterialByType, "createMaterialByType");
1903
1903
  function replaceMaterialAcrossObject(object, previous, next) {
@@ -1956,12 +1956,12 @@ function applyTextureFiltering(material, filtering) {
1956
1956
  const target = material;
1957
1957
  for (const slot of materialTextureSlots) {
1958
1958
  const texture = target[slot];
1959
- if (!texture || !(texture instanceof THREE7.Texture)) {
1959
+ if (!texture || !(texture instanceof THREE19.Texture)) {
1960
1960
  continue;
1961
1961
  }
1962
1962
  const useMipmaps = texture.generateMipmaps !== false;
1963
- texture.magFilter = sharp ? THREE7.NearestFilter : THREE7.LinearFilter;
1964
- texture.minFilter = useMipmaps ? sharp ? THREE7.NearestMipmapNearestFilter : THREE7.LinearMipmapLinearFilter : sharp ? THREE7.NearestFilter : THREE7.LinearFilter;
1963
+ texture.magFilter = sharp ? THREE19.NearestFilter : THREE19.LinearFilter;
1964
+ texture.minFilter = useMipmaps ? sharp ? THREE19.NearestMipmapNearestFilter : THREE19.LinearMipmapLinearFilter : sharp ? THREE19.NearestFilter : THREE19.LinearFilter;
1965
1965
  texture.needsUpdate = true;
1966
1966
  }
1967
1967
  material.needsUpdate = true;
@@ -1971,12 +1971,12 @@ function setTextureMipmaps(material, enabled) {
1971
1971
  const target = material;
1972
1972
  for (const slot of materialTextureSlots) {
1973
1973
  const texture = target[slot];
1974
- if (!texture || !(texture instanceof THREE7.Texture)) {
1974
+ if (!texture || !(texture instanceof THREE19.Texture)) {
1975
1975
  continue;
1976
1976
  }
1977
1977
  texture.generateMipmaps = enabled;
1978
- const sharp = texture.magFilter === THREE7.NearestFilter;
1979
- texture.minFilter = enabled ? sharp ? THREE7.NearestMipmapNearestFilter : THREE7.LinearMipmapLinearFilter : sharp ? THREE7.NearestFilter : THREE7.LinearFilter;
1978
+ const sharp = texture.magFilter === THREE19.NearestFilter;
1979
+ texture.minFilter = enabled ? sharp ? THREE19.NearestMipmapNearestFilter : THREE19.LinearMipmapLinearFilter : sharp ? THREE19.NearestFilter : THREE19.LinearFilter;
1980
1980
  texture.needsUpdate = true;
1981
1981
  }
1982
1982
  material.needsUpdate = true;
@@ -1987,7 +1987,7 @@ function assignMaterialTexture(material, rawKey, url, textureCache) {
1987
1987
  const key = resolveMaterialPropertyKey(rawKey);
1988
1988
  let texture = textureCache.get(url);
1989
1989
  if (!texture) {
1990
- texture = new THREE7.TextureLoader().load(url);
1990
+ texture = new THREE19.TextureLoader().load(url);
1991
1991
  textureCache.set(url, texture);
1992
1992
  }
1993
1993
  target[key] = texture;
@@ -2025,7 +2025,7 @@ function applyMaterialState(material, value, textureCache) {
2025
2025
  }
2026
2026
  target.side = value.side;
2027
2027
  target.blending = value.blending;
2028
- target.premultipliedAlpha = value.blending === THREE7.MultiplyBlending || value.blending === THREE7.SubtractiveBlending;
2028
+ target.premultipliedAlpha = value.blending === THREE19.MultiplyBlending || value.blending === THREE19.SubtractiveBlending;
2029
2029
  target.depthTest = value.depthTest;
2030
2030
  target.depthWrite = value.depthWrite;
2031
2031
  target.wireframe = value.wireframe;
@@ -2186,12 +2186,12 @@ function resolvePrimaryMesh(object) {
2186
2186
  if (!object) {
2187
2187
  return null;
2188
2188
  }
2189
- if (object instanceof THREE7.Mesh) {
2189
+ if (object instanceof THREE19.Mesh) {
2190
2190
  return object;
2191
2191
  }
2192
2192
  let found = null;
2193
2193
  object.traverse((child) => {
2194
- if (!found && child instanceof THREE7.Mesh) {
2194
+ if (!found && child instanceof THREE19.Mesh) {
2195
2195
  found = child;
2196
2196
  }
2197
2197
  });
@@ -2212,22 +2212,22 @@ function applyGeometry(component) {
2212
2212
  switch (component.kind) {
2213
2213
  case "cube": {
2214
2214
  const params = sanitized;
2215
- nextGeometry = new THREE7.BoxGeometry(params.width, params.height, params.depth);
2215
+ nextGeometry = new THREE19.BoxGeometry(params.width, params.height, params.depth);
2216
2216
  break;
2217
2217
  }
2218
2218
  case "plane": {
2219
2219
  const params = sanitized;
2220
- nextGeometry = new THREE7.PlaneGeometry(params.width, params.height);
2220
+ nextGeometry = new THREE19.PlaneGeometry(params.width, params.height);
2221
2221
  break;
2222
2222
  }
2223
2223
  case "sphere": {
2224
2224
  const params = sanitized;
2225
- nextGeometry = new THREE7.SphereGeometry(params.radius, 24, 24);
2225
+ nextGeometry = new THREE19.SphereGeometry(params.radius, 24, 24);
2226
2226
  break;
2227
2227
  }
2228
2228
  case "cylinder": {
2229
2229
  const params = sanitized;
2230
- nextGeometry = new THREE7.CylinderGeometry(
2230
+ nextGeometry = new THREE19.CylinderGeometry(
2231
2231
  params.radius,
2232
2232
  params.radius,
2233
2233
  params.height,
@@ -2237,7 +2237,7 @@ function applyGeometry(component) {
2237
2237
  }
2238
2238
  case "capsule": {
2239
2239
  const params = sanitized;
2240
- nextGeometry = new THREE7.CapsuleGeometry(params.radius, params.height, 4, 8);
2240
+ nextGeometry = new THREE19.CapsuleGeometry(params.radius, params.height, 4, 8);
2241
2241
  break;
2242
2242
  }
2243
2243
  default:
@@ -2253,7 +2253,7 @@ function applyShadowFlags(component) {
2253
2253
  return;
2254
2254
  }
2255
2255
  component.object.traverse((child) => {
2256
- if (child instanceof THREE7.Mesh) {
2256
+ if (child instanceof THREE19.Mesh) {
2257
2257
  child.castShadow = component.castShadow;
2258
2258
  child.receiveShadow = component.receiveShadow;
2259
2259
  }
@@ -2336,35 +2336,35 @@ function buildGeometry(component) {
2336
2336
  switch (component.meshKind) {
2337
2337
  case "cube": {
2338
2338
  const params = p;
2339
- return new THREE7.BoxGeometry(params.width, params.height, params.depth);
2339
+ return new THREE19.BoxGeometry(params.width, params.height, params.depth);
2340
2340
  }
2341
2341
  case "plane": {
2342
2342
  const params = p;
2343
- return new THREE7.PlaneGeometry(params.width, params.height);
2343
+ return new THREE19.PlaneGeometry(params.width, params.height);
2344
2344
  }
2345
2345
  case "sphere": {
2346
2346
  const params = p;
2347
- return new THREE7.SphereGeometry(params.radius, 24, 24);
2347
+ return new THREE19.SphereGeometry(params.radius, 24, 24);
2348
2348
  }
2349
2349
  case "cylinder": {
2350
2350
  const params = p;
2351
- return new THREE7.CylinderGeometry(params.radius, params.radius, params.height, 20);
2351
+ return new THREE19.CylinderGeometry(params.radius, params.radius, params.height, 20);
2352
2352
  }
2353
2353
  case "capsule": {
2354
2354
  const params = p;
2355
- return new THREE7.CapsuleGeometry(params.radius, params.height, 4, 8);
2355
+ return new THREE19.CapsuleGeometry(params.radius, params.height, 4, 8);
2356
2356
  }
2357
2357
  default:
2358
- return new THREE7.BoxGeometry(1, 1, 1);
2358
+ return new THREE19.BoxGeometry(1, 1, 1);
2359
2359
  }
2360
2360
  }
2361
2361
  __name(buildGeometry, "buildGeometry");
2362
- var _position = new THREE7.Vector3();
2363
- var _quaternion = new THREE7.Quaternion();
2364
- var _euler = new THREE7.Euler();
2365
- var _scale = new THREE7.Vector3();
2366
- var _matrix = new THREE7.Matrix4();
2367
- var _modelMatrix = new THREE7.Matrix4();
2362
+ var _position = new THREE19.Vector3();
2363
+ var _quaternion = new THREE19.Quaternion();
2364
+ var _euler = new THREE19.Euler();
2365
+ var _scale = new THREE19.Vector3();
2366
+ var _matrix = new THREE19.Matrix4();
2367
+ var _modelMatrix = new THREE19.Matrix4();
2368
2368
  function instanceTransformFromComponent(transform, out) {
2369
2369
  _position.set(transform.position.x, transform.position.y, transform.position.z);
2370
2370
  _euler.set(transform.rotation.x, transform.rotation.y, transform.rotation.z, "XYZ");
@@ -2517,7 +2517,7 @@ var _InstancedMeshSystem = class _InstancedMeshSystem {
2517
2517
  const sourceMaterial = Array.isArray(meshChild.material) ? meshChild.material.map((m) => m.clone()) : meshChild.material.clone();
2518
2518
  meshChild.updateWorldMatrix(true, false);
2519
2519
  const localMatrix = meshChild.matrixWorld.clone();
2520
- const instancedMesh2 = new THREE7.InstancedMesh(
2520
+ const instancedMesh2 = new THREE19.InstancedMesh(
2521
2521
  geometry2,
2522
2522
  Array.isArray(sourceMaterial) ? sourceMaterial : sourceMaterial,
2523
2523
  count2
@@ -2542,7 +2542,7 @@ var _InstancedMeshSystem = class _InstancedMeshSystem {
2542
2542
  this.loadingSignatures.delete(targetEntityId);
2543
2543
  return;
2544
2544
  }
2545
- const group = new THREE7.Group();
2545
+ const group = new THREE19.Group();
2546
2546
  for (const entry of entries) {
2547
2547
  group.add(entry.instancedMesh);
2548
2548
  }
@@ -2560,8 +2560,8 @@ var _InstancedMeshSystem = class _InstancedMeshSystem {
2560
2560
  }
2561
2561
  const count = instanceCount;
2562
2562
  const geometry = buildGeometry(comp);
2563
- const material = new THREE7.MeshStandardMaterial({ color: "#ffffff" });
2564
- const instancedMesh = new THREE7.InstancedMesh(geometry, material, count);
2563
+ const material = new THREE19.MeshStandardMaterial({ color: "#ffffff" });
2564
+ const instancedMesh = new THREE19.InstancedMesh(geometry, material, count);
2565
2565
  instancedMesh.castShadow = comp.castShadow;
2566
2566
  instancedMesh.receiveShadow = comp.receiveShadow;
2567
2567
  for (let i = 0; i < count; i++) {
@@ -2912,13 +2912,9 @@ function restorePostCreateComponents(world, objectManagementSystem, targetEntity
2912
2912
  runtimeMessage: typeof entry.runtimeMessage === "string" ? entry.runtimeMessage : void 0
2913
2913
  };
2914
2914
  }).filter((entry) => entry.className || entry.scriptUrl) : [];
2915
- if (!entries.length) {
2916
- return;
2915
+ if (entries.length) {
2916
+ world.addComponent(targetEntityId, new ScriptComponent(entries));
2917
2917
  }
2918
- world.addComponent(
2919
- targetEntityId,
2920
- new ScriptComponent(entries)
2921
- );
2922
2918
  }
2923
2919
  const sourceScriptObject = asRecord(values.scriptObjectValues.get(sourceEntityId));
2924
2920
  if (sourceScriptObject) {
@@ -2967,10 +2963,14 @@ function restorePostCreateComponents(world, objectManagementSystem, targetEntity
2967
2963
  const sourceInteractable = asRecord(
2968
2964
  values.xrInteractableValues.get(sourceEntityId)
2969
2965
  );
2970
- const interactable = world.getComponent(
2966
+ let interactable = world.getComponent(
2971
2967
  targetEntityId,
2972
2968
  XRInteractableComponent
2973
2969
  );
2970
+ if (sourceInteractable && !interactable) {
2971
+ interactable = new XRInteractableComponent();
2972
+ world.addComponent(targetEntityId, interactable);
2973
+ }
2974
2974
  if (sourceInteractable && interactable) {
2975
2975
  if (typeof sourceInteractable.enabled === "boolean") {
2976
2976
  interactable.enabled = sourceInteractable.enabled;
@@ -2996,6 +2996,30 @@ function restorePostCreateComponents(world, objectManagementSystem, targetEntity
2996
2996
  if (typeof sourceInteractable.grabRadius === "number") {
2997
2997
  interactable.grabRadius = sourceInteractable.grabRadius;
2998
2998
  }
2999
+ if (typeof sourceInteractable.grabHands === "string") {
3000
+ interactable.grabHands = sourceInteractable.grabHands;
3001
+ }
3002
+ if (typeof sourceInteractable.twoHandRotation === "string") {
3003
+ interactable.twoHandRotation = sourceInteractable.twoHandRotation;
3004
+ }
3005
+ if (typeof sourceInteractable.allowTwoHandScale === "boolean") {
3006
+ interactable.allowTwoHandScale = sourceInteractable.allowTwoHandScale;
3007
+ }
3008
+ if (typeof sourceInteractable.minScale === "number") {
3009
+ interactable.minScale = sourceInteractable.minScale;
3010
+ }
3011
+ if (typeof sourceInteractable.maxScale === "number") {
3012
+ interactable.maxScale = sourceInteractable.maxScale;
3013
+ }
3014
+ if (Array.isArray(sourceInteractable.attachPoints)) {
3015
+ interactable.attachPoints = sourceInteractable.attachPoints.map((point) => asRecord(point)).filter(
3016
+ (point) => point !== null && typeof point.id === "string"
3017
+ ).map(
3018
+ (point) => createAttachPoint(
3019
+ point
3020
+ )
3021
+ );
3022
+ }
2999
3023
  if (typeof sourceInteractable.throwOnRelease === "boolean") {
3000
3024
  interactable.throwOnRelease = sourceInteractable.throwOnRelease;
3001
3025
  }
@@ -3027,7 +3051,11 @@ function restorePostCreateComponents(world, objectManagementSystem, targetEntity
3027
3051
  const sourceHandPose = asRecord(
3028
3052
  values.xrHandPoseValues.get(sourceEntityId)
3029
3053
  );
3030
- const handPose = world.getComponent(targetEntityId, XRHandPoseComponent);
3054
+ let handPose = world.getComponent(targetEntityId, XRHandPoseComponent);
3055
+ if (sourceHandPose && !handPose) {
3056
+ handPose = new XRHandPoseComponent();
3057
+ world.addComponent(targetEntityId, handPose);
3058
+ }
3031
3059
  if (sourceHandPose && handPose) {
3032
3060
  if (typeof sourceHandPose.enabled === "boolean") {
3033
3061
  handPose.enabled = sourceHandPose.enabled;
@@ -4743,7 +4771,7 @@ var _Behaviour = class _Behaviour {
4743
4771
  if (!this.threeRef) {
4744
4772
  return null;
4745
4773
  }
4746
- const position = new THREE7.Vector3();
4774
+ const position = new THREE19.Vector3();
4747
4775
  this.threeRef.object.getWorldPosition(position);
4748
4776
  return position;
4749
4777
  }
@@ -4755,7 +4783,7 @@ var _Behaviour = class _Behaviour {
4755
4783
  if (!this.threeRef) {
4756
4784
  return null;
4757
4785
  }
4758
- const target = new THREE7.Vector3();
4786
+ const target = new THREE19.Vector3();
4759
4787
  this.threeRef.object.getWorldDirection(target);
4760
4788
  return target;
4761
4789
  }
@@ -4817,7 +4845,7 @@ var _Behaviour = class _Behaviour {
4817
4845
  if (!this.threeRef) {
4818
4846
  return;
4819
4847
  }
4820
- const rotation = new THREE7.Quaternion();
4848
+ const rotation = new THREE19.Quaternion();
4821
4849
  this.threeRef.object.getWorldQuaternion(rotation);
4822
4850
  rotation.slerp(targetRotation, alpha);
4823
4851
  this.transform.setRotation(rotation);
@@ -4834,7 +4862,7 @@ var _Behaviour = class _Behaviour {
4834
4862
  return;
4835
4863
  }
4836
4864
  const clone2 = this.threeRef.object.clone();
4837
- const rotation = new THREE7.Quaternion();
4865
+ const rotation = new THREE19.Quaternion();
4838
4866
  clone2.lookAt(targetPosition);
4839
4867
  clone2.getWorldQuaternion(rotation);
4840
4868
  this.transform.setRotation(rotation);
@@ -4972,6 +5000,17 @@ var _Behaviour = class _Behaviour {
4972
5000
  *
4973
5001
  * @param input - The source doing the grabbing.
4974
5002
  */
5003
+ /**
5004
+ * A SECOND hand joined a two-hand grab on this entity.
5005
+ *
5006
+ * The first hand anchors the object and keeps holding it; this fires for the
5007
+ * hand that came second — the foregrip on a rifle, say.
5008
+ */
5009
+ onSecondaryGrab(_input) {
5010
+ }
5011
+ /** The second hand let go, leaving the object in the first hand alone. */
5012
+ onSecondaryRelease(_input) {
5013
+ }
4975
5014
  /**
4976
5015
  * A hand pose declared on this entity started being held.
4977
5016
  *
@@ -5189,8 +5228,8 @@ var _ScriptBehaviourSystem = class _ScriptBehaviourSystem {
5189
5228
  }, "onPointerUp");
5190
5229
  this.moduleLoader = moduleLoader ?? defaultModuleLoader;
5191
5230
  this.selectionCtx = selectionContext ?? null;
5192
- this.raycaster = new THREE7.Raycaster();
5193
- this.ndcPointer = new THREE7.Vector2();
5231
+ this.raycaster = new THREE19.Raycaster();
5232
+ this.ndcPointer = new THREE19.Vector2();
5194
5233
  if (this.selectionCtx) {
5195
5234
  this.selectionCtx.domElement.addEventListener("pointerdown", this.onPointerDown);
5196
5235
  this.selectionCtx.domElement.addEventListener("pointerup", this.onPointerUp);
@@ -5569,7 +5608,7 @@ function disposeBuiltObject(root) {
5569
5608
  for (const mat of materials) {
5570
5609
  if (mat.userData?.[SHARED_MODEL_RESOURCE_FLAG]) continue;
5571
5610
  for (const value of Object.values(mat)) {
5572
- if (value instanceof THREE7.Texture) value.dispose();
5611
+ if (value instanceof THREE19.Texture) value.dispose();
5573
5612
  }
5574
5613
  mat.dispose?.();
5575
5614
  }
@@ -5933,7 +5972,7 @@ var _AudioSystem = class _AudioSystem {
5933
5972
  if (!prev || prev.volume !== opts.volume) {
5934
5973
  sound.setVolume(opts.volume);
5935
5974
  }
5936
- if (opts.positional && sound instanceof THREE7.PositionalAudio) {
5975
+ if (opts.positional && sound instanceof THREE19.PositionalAudio) {
5937
5976
  if (!prev || prev.refDistance !== opts.refDistance) {
5938
5977
  sound.setRefDistance(opts.refDistance);
5939
5978
  }
@@ -6059,7 +6098,7 @@ var _VideoSystem = class _VideoSystem {
6059
6098
  component.object.scale.set(opts.width, opts.height, 1);
6060
6099
  }
6061
6100
  const material = component.material;
6062
- if (material instanceof THREE7.ShaderMaterial) {
6101
+ if (material instanceof THREE19.ShaderMaterial) {
6063
6102
  if (!prev || prev.backgroundColor !== opts.backgroundColor) {
6064
6103
  material.uniforms.keyColor.value.set(opts.backgroundColor);
6065
6104
  }
@@ -6073,7 +6112,7 @@ var _VideoSystem = class _VideoSystem {
6073
6112
  material.uniforms.spill.value = opts.spill;
6074
6113
  }
6075
6114
  }
6076
- if (opts.positional && component.audioNode instanceof THREE7.PositionalAudio) {
6115
+ if (opts.positional && component.audioNode instanceof THREE19.PositionalAudio) {
6077
6116
  const posAudio = component.audioNode;
6078
6117
  if (!prev || prev.refDistance !== opts.refDistance) {
6079
6118
  posAudio.setRefDistance(opts.refDistance);
@@ -6113,8 +6152,8 @@ function blankState(source) {
6113
6152
  handedness: handednessOf(source),
6114
6153
  kind: kindOf(source),
6115
6154
  connected: true,
6116
- rayOrigin: new THREE7.Vector3(),
6117
- rayDirection: new THREE7.Vector3(0, 0, -1),
6155
+ rayOrigin: new THREE19.Vector3(),
6156
+ rayDirection: new THREE19.Vector3(0, 0, -1),
6118
6157
  gripPosition: null,
6119
6158
  gripQuaternion: null,
6120
6159
  select: false,
@@ -6140,7 +6179,7 @@ function readHandJoints(frame, hand, referenceSpace, rigMatrix, existing) {
6140
6179
  }
6141
6180
  if (spaces.length === 0) return null;
6142
6181
  const target = existing ?? {};
6143
- const matrix = new THREE7.Matrix4();
6182
+ const matrix = new THREE19.Matrix4();
6144
6183
  const buffer = spaces.length * 16 <= JOINT_MATRIX_BUFFER.length ? JOINT_MATRIX_BUFFER : new Float32Array(spaces.length * 16);
6145
6184
  const fillPoses = frame.fillPoses;
6146
6185
  if (typeof fillPoses === "function") {
@@ -6153,7 +6192,7 @@ function readHandJoints(frame, hand, referenceSpace, rigMatrix, existing) {
6153
6192
  if (filled) {
6154
6193
  for (let i = 0; i < names.length; i += 1) {
6155
6194
  matrix.fromArray(buffer, i * 16).premultiply(rigMatrix);
6156
- const vector = target[names[i]] ?? new THREE7.Vector3();
6195
+ const vector = target[names[i]] ?? new THREE19.Vector3();
6157
6196
  vector.setFromMatrixPosition(matrix);
6158
6197
  target[names[i]] = vector;
6159
6198
  }
@@ -6171,7 +6210,7 @@ function readHandJoints(frame, hand, referenceSpace, rigMatrix, existing) {
6171
6210
  continue;
6172
6211
  }
6173
6212
  matrix.fromArray(pose.transform.matrix).premultiply(rigMatrix);
6174
- const vector = target[names[i]] ?? new THREE7.Vector3();
6213
+ const vector = target[names[i]] ?? new THREE19.Vector3();
6175
6214
  vector.setFromMatrixPosition(matrix);
6176
6215
  target[names[i]] = vector;
6177
6216
  anyTracked = true;
@@ -6183,7 +6222,7 @@ var _XRInputSystem = class _XRInputSystem {
6183
6222
  constructor() {
6184
6223
  this.records = /* @__PURE__ */ new Map();
6185
6224
  /** Reference-space → world matrix, rebuilt each frame from the XR rig. */
6186
- this.referenceToWorld = new THREE7.Matrix4();
6225
+ this.referenceToWorld = new THREE19.Matrix4();
6187
6226
  this.session = null;
6188
6227
  this.onSelectStart = /* @__PURE__ */ __name((event) => this.mark(event, "pendingSelectStart"), "onSelectStart");
6189
6228
  this.onSelectEnd = /* @__PURE__ */ __name((event) => this.mark(event, "pendingSelectEnd"), "onSelectEnd");
@@ -6281,19 +6320,19 @@ var _XRInputSystem = class _XRInputSystem {
6281
6320
  if (frame && referenceSpace && source.targetRaySpace) {
6282
6321
  const pose = frame.getPose(source.targetRaySpace, referenceSpace);
6283
6322
  if (pose) {
6284
- const m = new THREE7.Matrix4().fromArray(pose.transform.matrix).premultiply(rigMatrix);
6323
+ const m = new THREE19.Matrix4().fromArray(pose.transform.matrix).premultiply(rigMatrix);
6285
6324
  state.rayOrigin.setFromMatrixPosition(m);
6286
6325
  state.rayDirection.set(0, 0, -1).applyQuaternion(
6287
- new THREE7.Quaternion().setFromRotationMatrix(m)
6326
+ new THREE19.Quaternion().setFromRotationMatrix(m)
6288
6327
  ).normalize();
6289
6328
  }
6290
6329
  }
6291
6330
  if (frame && referenceSpace && source.gripSpace) {
6292
6331
  const gripPose = frame.getPose(source.gripSpace, referenceSpace);
6293
6332
  if (gripPose) {
6294
- const m = new THREE7.Matrix4().fromArray(gripPose.transform.matrix).premultiply(rigMatrix);
6295
- state.gripPosition ?? (state.gripPosition = new THREE7.Vector3());
6296
- state.gripQuaternion ?? (state.gripQuaternion = new THREE7.Quaternion());
6333
+ const m = new THREE19.Matrix4().fromArray(gripPose.transform.matrix).premultiply(rigMatrix);
6334
+ state.gripPosition ?? (state.gripPosition = new THREE19.Vector3());
6335
+ state.gripQuaternion ?? (state.gripQuaternion = new THREE19.Quaternion());
6297
6336
  state.gripPosition.setFromMatrixPosition(m);
6298
6337
  state.gripQuaternion.setFromRotationMatrix(m);
6299
6338
  }
@@ -6378,6 +6417,7 @@ __name(_XRInputSystem, "XRInputSystem");
6378
6417
  var XRInputSystem = _XRInputSystem;
6379
6418
  var VELOCITY_SAMPLES = 5;
6380
6419
  var MAX_SAMPLE_AGE_SECONDS = 0.2;
6420
+ var MAX_PLAUSIBLE_SPEED = 20;
6381
6421
  var _ThrowVelocityTracker = class _ThrowVelocityTracker {
6382
6422
  constructor() {
6383
6423
  this.samples = [];
@@ -6401,16 +6441,17 @@ var _ThrowVelocityTracker = class _ThrowVelocityTracker {
6401
6441
  const fresh = this.samples.filter(
6402
6442
  (sample) => now - sample.time <= MAX_SAMPLE_AGE_SECONDS
6403
6443
  );
6404
- if (fresh.length < 2) return new THREE7.Vector3();
6405
- let best = new THREE7.Vector3();
6444
+ if (fresh.length < 2) return new THREE19.Vector3();
6445
+ let best = new THREE19.Vector3();
6406
6446
  let bestSpeed = 0;
6407
6447
  for (let i = 1; i < fresh.length; i += 1) {
6408
6448
  const previous = fresh[i - 1];
6409
6449
  const current = fresh[i];
6410
6450
  const dt = current.time - previous.time;
6411
6451
  if (dt <= 1e-5) continue;
6412
- const velocity = new THREE7.Vector3().subVectors(current.position, previous.position).divideScalar(dt);
6452
+ const velocity = new THREE19.Vector3().subVectors(current.position, previous.position).divideScalar(dt);
6413
6453
  const speed = velocity.length();
6454
+ if (speed > MAX_PLAUSIBLE_SPEED) continue;
6414
6455
  if (speed > bestSpeed) {
6415
6456
  bestSpeed = speed;
6416
6457
  best = velocity;
@@ -6425,23 +6466,75 @@ var _ThrowVelocityTracker = class _ThrowVelocityTracker {
6425
6466
  __name(_ThrowVelocityTracker, "ThrowVelocityTracker");
6426
6467
  var ThrowVelocityTracker = _ThrowVelocityTracker;
6427
6468
  function angularVelocityFrom(previous, current, deltaTime) {
6428
- if (deltaTime <= 1e-5) return new THREE7.Vector3();
6469
+ if (deltaTime <= 1e-5) return new THREE19.Vector3();
6429
6470
  const delta = current.clone().multiply(previous.clone().invert());
6430
6471
  if (delta.w < 0) {
6431
6472
  delta.set(-delta.x, -delta.y, -delta.z, -delta.w);
6432
6473
  }
6433
- const angle = 2 * Math.acos(THREE7.MathUtils.clamp(delta.w, -1, 1));
6474
+ const angle = 2 * Math.acos(THREE19.MathUtils.clamp(delta.w, -1, 1));
6434
6475
  const sinHalf = Math.sqrt(Math.max(0, 1 - delta.w * delta.w));
6435
- if (sinHalf < 1e-6 || angle < 1e-6) return new THREE7.Vector3();
6436
- return new THREE7.Vector3(delta.x, delta.y, delta.z).divideScalar(sinHalf).multiplyScalar(angle / deltaTime);
6476
+ if (sinHalf < 1e-6 || angle < 1e-6) return new THREE19.Vector3();
6477
+ return new THREE19.Vector3(delta.x, delta.y, delta.z).divideScalar(sinHalf).multiplyScalar(angle / deltaTime);
6437
6478
  }
6438
6479
  __name(angularVelocityFrom, "angularVelocityFrom");
6480
+ var MIN_HAND_SEPARATION = 0.06;
6481
+ var MIN_ANCHOR_SEPARATION = 1e-3;
6482
+ var SCALE_DEADZONE = 0.05;
6483
+ function solveTwoHandTransform(primary, secondary, basis, options) {
6484
+ const separation = primary.position.distanceTo(secondary.position);
6485
+ const anchorDelta = new THREE19.Vector3().subVectors(
6486
+ basis.secondaryLocal,
6487
+ basis.primaryLocal
6488
+ );
6489
+ const anchorLength = anchorDelta.length();
6490
+ let factor = 1;
6491
+ if (options.allowScale && basis.initialSeparation > MIN_ANCHOR_SEPARATION && separation > MIN_ANCHOR_SEPARATION) {
6492
+ factor = separation / basis.initialSeparation;
6493
+ if (Math.abs(factor - 1) <= SCALE_DEADZONE) {
6494
+ factor = 1;
6495
+ } else {
6496
+ factor += factor > 1 ? -SCALE_DEADZONE : SCALE_DEADZONE;
6497
+ }
6498
+ factor = Math.min(options.maxScale, Math.max(options.minScale, factor));
6499
+ }
6500
+ const scale = basis.initialScale.clone().multiplyScalar(factor);
6501
+ const degenerate = separation < MIN_HAND_SEPARATION || anchorLength < MIN_ANCHOR_SEPARATION;
6502
+ const base = primary.quaternion.clone().multiply(basis.primaryHandOffset);
6503
+ let quaternion;
6504
+ if (options.rotationMode === "primary" || degenerate) {
6505
+ quaternion = base;
6506
+ } else {
6507
+ const axisLocal = anchorDelta.clone().normalize();
6508
+ const currentAxis = axisLocal.clone().applyQuaternion(base).normalize();
6509
+ const desiredAxis = new THREE19.Vector3().subVectors(secondary.position, primary.position).normalize();
6510
+ const correction = new THREE19.Quaternion().setFromUnitVectors(
6511
+ currentAxis,
6512
+ desiredAxis
6513
+ );
6514
+ quaternion = correction.multiply(base);
6515
+ }
6516
+ const anchorOffset = basis.primaryLocal.clone().multiply(scale).applyQuaternion(quaternion);
6517
+ const position = primary.position.clone().sub(anchorOffset);
6518
+ return { position, quaternion, scale, degenerate };
6519
+ }
6520
+ __name(solveTwoHandTransform, "solveTwoHandTransform");
6439
6521
 
6440
6522
  // core/systems/XRInteractionSystem.ts
6441
6523
  var RAYLESS_HOLD_DISTANCE = 0.5;
6524
+ function quatFromEulerVec(r) {
6525
+ return new THREE19.Quaternion().setFromEuler(new THREE19.Euler(r.x, r.y, r.z));
6526
+ }
6527
+ __name(quatFromEulerVec, "quatFromEulerVec");
6528
+ function writeEuler(target, q) {
6529
+ const euler = new THREE19.Euler().setFromQuaternion(q);
6530
+ target.x = euler.x;
6531
+ target.y = euler.y;
6532
+ target.z = euler.z;
6533
+ }
6534
+ __name(writeEuler, "writeEuler");
6442
6535
  var _XRInteractionSystem = class _XRInteractionSystem {
6443
6536
  constructor(inputSystem) {
6444
- this.raycaster = new THREE7.Raycaster();
6537
+ this.raycaster = new THREE19.Raycaster();
6445
6538
  this.grabs = /* @__PURE__ */ new Map();
6446
6539
  this.hoveredEntityId = null;
6447
6540
  /** Monotonic seconds, accumulated from deltaTime for velocity sampling. */
@@ -6464,7 +6557,6 @@ var _XRInteractionSystem = class _XRInteractionSystem {
6464
6557
  }
6465
6558
  const held = this.grabs.get(input);
6466
6559
  if (held) {
6467
- this.moveHeld(world, input, held, deltaTime);
6468
6560
  if (this.wantsRelease(world, input, held)) {
6469
6561
  this.release(world, input);
6470
6562
  }
@@ -6485,9 +6577,122 @@ var _XRInteractionSystem = class _XRInteractionSystem {
6485
6577
  /* starting */
6486
6578
  true
6487
6579
  )) {
6488
- this.grab(world, input, candidate.entityId, candidate.viaDistance);
6580
+ this.tryGrab(world, input, candidate.entityId, candidate.viaDistance);
6489
6581
  }
6490
6582
  }
6583
+ this.moveAllHeld(world, deltaTime);
6584
+ }
6585
+ /** Hands currently holding an entity. */
6586
+ holdersOf(entityId) {
6587
+ const holders = [];
6588
+ for (const [input, record] of this.grabs) {
6589
+ if (record.entityId === entityId) holders.push({ input, record });
6590
+ }
6591
+ return holders;
6592
+ }
6593
+ /**
6594
+ * Route a new grab: first hand, hand-off, or second hand.
6595
+ *
6596
+ * Which of those happens is the object's choice (`grabHands`), not the
6597
+ * hand's — a ball should pass between hands, a rifle should be held by both,
6598
+ * and a lever should stay with whoever grabbed it first.
6599
+ */
6600
+ tryGrab(world, input, entityId, viaDistance) {
6601
+ const interactable = world.getComponent(entityId, XRInteractableComponent);
6602
+ if (!interactable) return;
6603
+ const holders = this.holdersOf(entityId);
6604
+ if (holders.length === 0) {
6605
+ this.grab(world, input, entityId, viaDistance, "primary");
6606
+ return;
6607
+ }
6608
+ if (holders.some((holder) => holder.input === input)) return;
6609
+ if (interactable.grabHands === "single") return;
6610
+ if (interactable.grabHands === "handOff") {
6611
+ const previous = holders[0];
6612
+ this.grabs.delete(previous.input);
6613
+ const record = previous.record;
6614
+ record.role = "primary";
6615
+ record.twoHand = null;
6616
+ this.reanchor(world, input, record, interactable);
6617
+ this.grabs.set(input, record);
6618
+ this.dispatch(world, entityId, (b) => b.onGrab(input));
6619
+ return;
6620
+ }
6621
+ if (holders.length >= 2) return;
6622
+ this.grab(world, input, entityId, viaDistance, "secondary");
6623
+ this.beginTwoHand(world, entityId);
6624
+ }
6625
+ /**
6626
+ * Re-derive a record's hold from where the object is NOW.
6627
+ *
6628
+ * Used on hand-off and on promotion after the primary lets go. Without it the
6629
+ * object snaps to whatever offset the previous hand had, which reads as the
6630
+ * object jumping out of your grip at the moment you take it.
6631
+ */
6632
+ reanchor(world, input, record, interactable) {
6633
+ const transform = world.getComponent(record.entityId, TransformComponent);
6634
+ if (!transform) return;
6635
+ const hand = this.handPosition(input);
6636
+ const handQuaternion = this.handQuaternion(input);
6637
+ const objectQuaternion = quatFromEulerVec(transform.rotation);
6638
+ record.offset = new THREE19.Vector3(
6639
+ transform.position.x - hand.x,
6640
+ transform.position.y - hand.y,
6641
+ transform.position.z - hand.z
6642
+ );
6643
+ record.handRotationOffset = handQuaternion.clone().invert().multiply(objectQuaternion);
6644
+ record.remote = false;
6645
+ record.tracker.clear();
6646
+ record.tracker.record(hand, this.elapsed);
6647
+ record.lastHandQuaternion = handQuaternion.clone();
6648
+ if (record.attachLocal && interactable.attachPoints.length === 0) {
6649
+ record.attachLocal = null;
6650
+ record.attachQuaternion = null;
6651
+ record.attachPointId = null;
6652
+ }
6653
+ }
6654
+ /** Capture the two-hand basis once both hands are on the object. */
6655
+ beginTwoHand(world, entityId) {
6656
+ const holders = this.holdersOf(entityId);
6657
+ if (holders.length !== 2) return;
6658
+ const primary = holders.find((h) => h.record.role === "primary");
6659
+ const secondary = holders.find((h) => h.record.role === "secondary");
6660
+ if (!primary || !secondary) return;
6661
+ const transform = world.getComponent(entityId, TransformComponent);
6662
+ if (!transform) return;
6663
+ const primaryHand = this.handPosition(primary.input);
6664
+ const secondaryHand = this.handPosition(secondary.input);
6665
+ const primaryLocal = primary.record.attachLocal?.clone() ?? this.objectLocalPoint(transform, primaryHand);
6666
+ const secondaryLocal = secondary.record.attachLocal?.clone() ?? this.objectLocalPoint(transform, secondaryHand);
6667
+ primary.record.twoHand = {
6668
+ primaryLocal,
6669
+ secondaryLocal,
6670
+ initialScale: new THREE19.Vector3(
6671
+ transform.scale.x,
6672
+ transform.scale.y,
6673
+ transform.scale.z
6674
+ ),
6675
+ initialSeparation: primaryHand.distanceTo(secondaryHand),
6676
+ // How the object sits relative to the anchoring hand right now, so the
6677
+ // two-hand solve picks up exactly where the one-hand hold left off.
6678
+ primaryHandOffset: this.handQuaternion(primary.input).invert().multiply(quatFromEulerVec(transform.rotation)),
6679
+ initialQuaternion: quatFromEulerVec(transform.rotation)
6680
+ };
6681
+ this.dispatch(world, entityId, (b) => b.onSecondaryGrab(secondary.input));
6682
+ }
6683
+ /** World point → the object's UNSCALED local space. */
6684
+ objectLocalPoint(transform, worldPoint) {
6685
+ const local = worldPoint.clone().sub(
6686
+ new THREE19.Vector3(
6687
+ transform.position.x,
6688
+ transform.position.y,
6689
+ transform.position.z
6690
+ )
6691
+ ).applyQuaternion(quatFromEulerVec(transform.rotation).invert());
6692
+ local.x /= transform.scale.x || 1;
6693
+ local.y /= transform.scale.y || 1;
6694
+ local.z /= transform.scale.z || 1;
6695
+ return local;
6491
6696
  }
6492
6697
  /** Whether the grab gesture for this object is currently starting. */
6493
6698
  gestureMatches(input, interactable, starting) {
@@ -6536,7 +6741,7 @@ var _XRInteractionSystem = class _XRInteractionSystem {
6536
6741
  );
6537
6742
  if (!interactable2) continue;
6538
6743
  if (interactable2.grabReach === "distance") continue;
6539
- const position = new THREE7.Vector3();
6744
+ const position = new THREE19.Vector3();
6540
6745
  entry.object.getWorldPosition(position);
6541
6746
  const distance = position.distanceTo(hand);
6542
6747
  if (distance <= interactable2.grabRadius && distance < nearestDistance) {
@@ -6560,7 +6765,9 @@ var _XRInteractionSystem = class _XRInteractionSystem {
6560
6765
  if (!interactable?.enabled) continue;
6561
6766
  if (!world.isEntityVisible(entityId)) continue;
6562
6767
  const object = world.getComponent(entityId, Object3DRef)?.object;
6563
- if (object) out.push({ entityId, object });
6768
+ if (object) {
6769
+ out.push({ entityId, object, pointable: interactable.pointable });
6770
+ }
6564
6771
  }
6565
6772
  return out;
6566
6773
  }
@@ -6572,6 +6779,7 @@ var _XRInteractionSystem = class _XRInteractionSystem {
6572
6779
  let nearestId = null;
6573
6780
  let nearestDistance = Number.POSITIVE_INFINITY;
6574
6781
  for (const entry of interactables) {
6782
+ if (!entry.pointable) continue;
6575
6783
  const hit = this.raycaster.intersectObject(entry.object, true)[0];
6576
6784
  if (!hit) continue;
6577
6785
  if (hit.distance < nearestDistance) {
@@ -6581,7 +6789,52 @@ var _XRInteractionSystem = class _XRInteractionSystem {
6581
6789
  }
6582
6790
  return nearestId;
6583
6791
  }
6584
- grab(world, input, entityId, viaDistance) {
6792
+ /**
6793
+ * Pick the authored hold this hand should take.
6794
+ *
6795
+ * Filters by hand and by role — that is what makes "the trigger hand goes on
6796
+ * the grip" hold regardless of which hand reaches first — then takes the
6797
+ * nearest remaining one so grabbing near the foregrip picks the foregrip.
6798
+ */
6799
+ chooseAttachPoint(world, input, entityId, interactable, role) {
6800
+ if (interactable.attachPoints.length === 0) return null;
6801
+ const transform = world.getComponent(entityId, TransformComponent);
6802
+ if (!transform) return null;
6803
+ const taken = new Set(
6804
+ this.holdersOf(entityId).map((holder) => holder.record.attachPointId).filter((id) => id !== null)
6805
+ );
6806
+ const hand = this.handPosition(input);
6807
+ const objectPosition = new THREE19.Vector3(
6808
+ transform.position.x,
6809
+ transform.position.y,
6810
+ transform.position.z
6811
+ );
6812
+ const objectQuaternion = quatFromEulerVec(transform.rotation);
6813
+ const scale = new THREE19.Vector3(
6814
+ transform.scale.x,
6815
+ transform.scale.y,
6816
+ transform.scale.z
6817
+ );
6818
+ let best = null;
6819
+ let bestDistance = Number.POSITIVE_INFINITY;
6820
+ for (const point of interactable.attachPoints) {
6821
+ if (taken.has(point.id)) continue;
6822
+ if (point.hand !== "any" && point.hand !== input.handedness) continue;
6823
+ if (point.role !== "any" && point.role !== role) continue;
6824
+ const world3 = new THREE19.Vector3(
6825
+ point.position.x,
6826
+ point.position.y,
6827
+ point.position.z
6828
+ ).multiply(scale).applyQuaternion(objectQuaternion).add(objectPosition);
6829
+ const distance = world3.distanceTo(hand);
6830
+ if (distance < bestDistance) {
6831
+ bestDistance = distance;
6832
+ best = point;
6833
+ }
6834
+ }
6835
+ return best;
6836
+ }
6837
+ grab(world, input, entityId, viaDistance, role) {
6585
6838
  const transform = world.getComponent(entityId, TransformComponent);
6586
6839
  const interactable = world.getComponent(entityId, XRInteractableComponent);
6587
6840
  if (!transform || !interactable) return;
@@ -6591,21 +6844,21 @@ var _XRInteractionSystem = class _XRInteractionSystem {
6591
6844
  let offset;
6592
6845
  let remoteDistance = 0;
6593
6846
  if (remote) {
6594
- const position = new THREE7.Vector3(
6847
+ const position = new THREE19.Vector3(
6595
6848
  transform.position.x,
6596
6849
  transform.position.y,
6597
6850
  transform.position.z
6598
6851
  );
6599
6852
  remoteDistance = position.distanceTo(input.rayOrigin);
6600
- offset = new THREE7.Vector3();
6853
+ offset = new THREE19.Vector3();
6601
6854
  } else if (viaDistance) {
6602
- offset = new THREE7.Vector3(
6855
+ offset = new THREE19.Vector3(
6603
6856
  interactable.grabOffsetPosition.x,
6604
6857
  interactable.grabOffsetPosition.y,
6605
6858
  interactable.grabOffsetPosition.z
6606
6859
  );
6607
6860
  } else {
6608
- offset = new THREE7.Vector3(
6861
+ offset = new THREE19.Vector3(
6609
6862
  transform.position.x - hand.x,
6610
6863
  transform.position.y - hand.y,
6611
6864
  transform.position.z - hand.z
@@ -6619,11 +6872,30 @@ var _XRInteractionSystem = class _XRInteractionSystem {
6619
6872
  }
6620
6873
  const tracker = new ThrowVelocityTracker();
6621
6874
  tracker.record(hand, this.elapsed);
6875
+ const attachPoint = this.chooseAttachPoint(
6876
+ world,
6877
+ input,
6878
+ entityId,
6879
+ interactable,
6880
+ role
6881
+ );
6882
+ const objectQuaternion = quatFromEulerVec(transform.rotation);
6883
+ const handRotationOffset = handQuaternion.clone().invert().multiply(objectQuaternion);
6622
6884
  this.grabs.set(input, {
6623
6885
  entityId,
6886
+ role,
6887
+ attachPointId: attachPoint?.id ?? null,
6888
+ attachLocal: attachPoint ? new THREE19.Vector3(
6889
+ attachPoint.position.x,
6890
+ attachPoint.position.y,
6891
+ attachPoint.position.z
6892
+ ) : null,
6893
+ attachQuaternion: attachPoint ? quatFromEulerVec(attachPoint.rotation) : null,
6894
+ handRotationOffset,
6895
+ twoHand: null,
6624
6896
  offset,
6625
- rotationOffset: new THREE7.Quaternion().setFromEuler(
6626
- new THREE7.Euler(
6897
+ rotationOffset: new THREE19.Quaternion().setFromEuler(
6898
+ new THREE19.Euler(
6627
6899
  interactable.grabOffsetRotation.x,
6628
6900
  interactable.grabOffsetRotation.y,
6629
6901
  interactable.grabOffsetRotation.z
@@ -6634,33 +6906,110 @@ var _XRInteractionSystem = class _XRInteractionSystem {
6634
6906
  restoreBodyType,
6635
6907
  tracker,
6636
6908
  lastHandQuaternion: handQuaternion.clone(),
6637
- angularVelocity: new THREE7.Vector3()
6909
+ angularVelocity: new THREE19.Vector3()
6638
6910
  });
6639
- this.dispatch(world, entityId, (b) => b.onGrab(input));
6911
+ if (role === "primary") {
6912
+ this.dispatch(world, entityId, (b) => b.onGrab(input));
6913
+ }
6914
+ }
6915
+ /** Drive every held object, once each, after grabs and releases settle. */
6916
+ moveAllHeld(world, deltaTime) {
6917
+ const done = /* @__PURE__ */ new Set();
6918
+ for (const [input, record] of this.grabs) {
6919
+ if (done.has(record.entityId)) continue;
6920
+ done.add(record.entityId);
6921
+ const holders = this.holdersOf(record.entityId);
6922
+ if (holders.length >= 2) {
6923
+ this.moveTwoHand(world, record.entityId, holders, deltaTime);
6924
+ } else {
6925
+ this.moveHeld(world, input, record, deltaTime);
6926
+ }
6927
+ }
6928
+ }
6929
+ /** Solve and apply a two-hand hold. */
6930
+ moveTwoHand(world, entityId, holders, deltaTime) {
6931
+ const primary = holders.find((h) => h.record.role === "primary");
6932
+ const secondary = holders.find((h) => h.record.role === "secondary");
6933
+ const transform = world.getComponent(entityId, TransformComponent);
6934
+ const interactable = world.getComponent(entityId, XRInteractableComponent);
6935
+ const basis = primary?.record.twoHand ?? null;
6936
+ if (!primary || !secondary || !transform || !interactable || !basis) {
6937
+ if (primary) {
6938
+ this.moveHeld(world, primary.input, primary.record, deltaTime);
6939
+ }
6940
+ return;
6941
+ }
6942
+ const primaryHand = this.handPosition(primary.input);
6943
+ const primaryQuaternion = this.handQuaternion(primary.input);
6944
+ const solved = solveTwoHandTransform(
6945
+ { position: primaryHand, quaternion: primaryQuaternion },
6946
+ {
6947
+ position: this.handPosition(secondary.input),
6948
+ quaternion: this.handQuaternion(secondary.input)
6949
+ },
6950
+ basis,
6951
+ {
6952
+ rotationMode: interactable.twoHandRotation,
6953
+ allowScale: interactable.allowTwoHandScale,
6954
+ minScale: interactable.minScale,
6955
+ maxScale: interactable.maxScale
6956
+ }
6957
+ );
6958
+ transform.position.x = solved.position.x;
6959
+ transform.position.y = solved.position.y;
6960
+ transform.position.z = solved.position.z;
6961
+ writeEuler(transform.rotation, solved.quaternion);
6962
+ if (interactable.allowTwoHandScale) {
6963
+ transform.scale.x = solved.scale.x;
6964
+ transform.scale.y = solved.scale.y;
6965
+ transform.scale.z = solved.scale.z;
6966
+ }
6967
+ primary.record.tracker.record(primaryHand, this.elapsed);
6968
+ primary.record.angularVelocity = angularVelocityFrom(
6969
+ primary.record.lastHandQuaternion,
6970
+ primaryQuaternion,
6971
+ deltaTime
6972
+ );
6973
+ primary.record.lastHandQuaternion = primaryQuaternion.clone();
6640
6974
  }
6641
6975
  moveHeld(world, input, held, deltaTime) {
6642
6976
  const transform = world.getComponent(held.entityId, TransformComponent);
6643
6977
  if (!transform) return;
6644
6978
  const hand = this.handPosition(input);
6979
+ const handQuaternion = this.handQuaternion(input);
6980
+ const objectQuaternion = held.attachQuaternion ? handQuaternion.clone().multiply(held.rotationOffset).multiply(held.attachQuaternion.clone().invert()) : handQuaternion.clone().multiply(held.handRotationOffset);
6645
6981
  if (held.remote) {
6646
- const target = new THREE7.Vector3().copy(input.rayDirection).multiplyScalar(held.remoteDistance).add(input.rayOrigin);
6982
+ const target = new THREE19.Vector3().copy(input.rayDirection).multiplyScalar(held.remoteDistance).add(input.rayOrigin);
6647
6983
  transform.position.x = target.x;
6648
6984
  transform.position.y = target.y;
6649
6985
  transform.position.z = target.z;
6986
+ writeEuler(transform.rotation, objectQuaternion);
6987
+ } else if (held.attachLocal) {
6988
+ const anchor = held.attachLocal.clone().multiply(
6989
+ new THREE19.Vector3(
6990
+ transform.scale.x,
6991
+ transform.scale.y,
6992
+ transform.scale.z
6993
+ )
6994
+ ).applyQuaternion(objectQuaternion);
6995
+ transform.position.x = hand.x - anchor.x;
6996
+ transform.position.y = hand.y - anchor.y;
6997
+ transform.position.z = hand.z - anchor.z;
6998
+ writeEuler(transform.rotation, objectQuaternion);
6650
6999
  } else {
6651
7000
  transform.position.x = hand.x + held.offset.x;
6652
7001
  transform.position.y = hand.y + held.offset.y;
6653
7002
  transform.position.z = hand.z + held.offset.z;
7003
+ writeEuler(transform.rotation, objectQuaternion);
6654
7004
  }
6655
7005
  held.tracker.record(
6656
- held.remote ? new THREE7.Vector3(
7006
+ held.remote ? new THREE19.Vector3(
6657
7007
  transform.position.x,
6658
7008
  transform.position.y,
6659
7009
  transform.position.z
6660
7010
  ) : hand,
6661
7011
  this.elapsed
6662
7012
  );
6663
- const handQuaternion = this.handQuaternion(input);
6664
7013
  held.angularVelocity = angularVelocityFrom(
6665
7014
  held.lastHandQuaternion,
6666
7015
  handQuaternion,
@@ -6676,6 +7025,30 @@ var _XRInteractionSystem = class _XRInteractionSystem {
6676
7025
  held.entityId,
6677
7026
  XRInteractableComponent
6678
7027
  );
7028
+ const remaining = this.holdersOf(held.entityId);
7029
+ if (remaining.length > 0 && interactable) {
7030
+ if (held.role === "secondary") {
7031
+ const primary = remaining.find((h) => h.record.role === "primary");
7032
+ if (primary) {
7033
+ primary.record.twoHand = null;
7034
+ this.reanchor(world, primary.input, primary.record, interactable);
7035
+ }
7036
+ this.dispatch(
7037
+ world,
7038
+ held.entityId,
7039
+ (b) => b.onSecondaryRelease(input)
7040
+ );
7041
+ } else {
7042
+ const next = remaining[0];
7043
+ next.record.role = "primary";
7044
+ next.record.twoHand = null;
7045
+ next.record.restoreBodyType = held.restoreBodyType;
7046
+ this.reanchor(world, next.input, next.record, interactable);
7047
+ this.dispatch(world, held.entityId, (b) => b.onRelease(input));
7048
+ }
7049
+ held.tracker.clear();
7050
+ return;
7051
+ }
6679
7052
  const physics = world.getComponent(held.entityId, PhysicsComponent);
6680
7053
  if (held.restoreBodyType !== null && physics) {
6681
7054
  physics.values.rigidbody.type = held.restoreBodyType;
@@ -6709,7 +7082,7 @@ var _XRInteractionSystem = class _XRInteractionSystem {
6709
7082
  */
6710
7083
  handPosition(input) {
6711
7084
  if (input.gripPosition) return input.gripPosition;
6712
- return new THREE7.Vector3().copy(input.rayDirection).multiplyScalar(RAYLESS_HOLD_DISTANCE).add(input.rayOrigin);
7085
+ return new THREE19.Vector3().copy(input.rayDirection).multiplyScalar(RAYLESS_HOLD_DISTANCE).add(input.rayOrigin);
6713
7086
  }
6714
7087
  /**
6715
7088
  * Hand orientation. Grip-less sources (gaze / transient-pointer) have none,
@@ -6717,8 +7090,8 @@ var _XRInteractionSystem = class _XRInteractionSystem {
6717
7090
  */
6718
7091
  handQuaternion(input) {
6719
7092
  if (input.gripQuaternion) return input.gripQuaternion.clone();
6720
- return new THREE7.Quaternion().setFromUnitVectors(
6721
- new THREE7.Vector3(0, 0, -1),
7093
+ return new THREE19.Quaternion().setFromUnitVectors(
7094
+ new THREE19.Vector3(0, 0, -1),
6722
7095
  input.rayDirection.clone().normalize()
6723
7096
  );
6724
7097
  }
@@ -6743,6 +7116,29 @@ var _XRInteractionSystem = class _XRInteractionSystem {
6743
7116
  isGrabbing() {
6744
7117
  return this.grabs.size > 0;
6745
7118
  }
7119
+ /**
7120
+ * How an entity is currently held.
7121
+ *
7122
+ * Exposed for scripts: a Behaviour can poll this in `onUpdate` to drive
7123
+ * two-hand-specific behaviour — showing a bipod when both hands are on a
7124
+ * weapon, reading the live hand separation to gate a gesture, or reacting to
7125
+ * the scale a pull-apart produced. Returns null when nothing holds it.
7126
+ */
7127
+ getGrabInfo(entityId) {
7128
+ const holders = this.holdersOf(entityId);
7129
+ if (holders.length === 0) return null;
7130
+ const primary = holders.find((h) => h.record.role === "primary");
7131
+ const secondary = holders.find((h) => h.record.role === "secondary");
7132
+ return {
7133
+ hands: holders.length,
7134
+ primaryHandedness: primary?.input.handedness ?? null,
7135
+ secondaryHandedness: secondary?.input.handedness ?? null,
7136
+ handSeparation: primary && secondary ? this.handPosition(primary.input).distanceTo(
7137
+ this.handPosition(secondary.input)
7138
+ ) : null,
7139
+ attachPointIds: holders.map((h) => h.record.attachPointId)
7140
+ };
7141
+ }
6746
7142
  };
6747
7143
  __name(_XRInteractionSystem, "XRInteractionSystem");
6748
7144
  var XRInteractionSystem = _XRInteractionSystem;
@@ -6760,7 +7156,7 @@ function sampleTeleportArc(origin, direction, out = [], options) {
6760
7156
  for (let i = 0; i < steps; i += 1) {
6761
7157
  const t = i / (steps - 1) * maxTime;
6762
7158
  out.push(
6763
- new THREE7.Vector3(
7159
+ new THREE19.Vector3(
6764
7160
  origin.x + velocity.x * t,
6765
7161
  origin.y + velocity.y * t - 0.5 * gravity * t * t,
6766
7162
  origin.z + velocity.z * t
@@ -6777,7 +7173,7 @@ function arcGroundCrossing(points, groundY) {
6777
7173
  if (previous.y >= groundY && current.y <= groundY) {
6778
7174
  const span = previous.y - current.y;
6779
7175
  const alpha = span > 1e-6 ? (previous.y - groundY) / span : 0;
6780
- return new THREE7.Vector3().lerpVectors(previous, current, alpha);
7176
+ return new THREE19.Vector3().lerpVectors(previous, current, alpha);
6781
7177
  }
6782
7178
  }
6783
7179
  return null;
@@ -6785,11 +7181,11 @@ function arcGroundCrossing(points, groundY) {
6785
7181
  __name(arcGroundCrossing, "arcGroundCrossing");
6786
7182
 
6787
7183
  // core/systems/XRLocomotionSystem.ts
6788
- var UP = new THREE7.Vector3(0, 1, 0);
7184
+ var UP = new THREE19.Vector3(0, 1, 0);
6789
7185
  var AXIS_DEADZONE = 0.5;
6790
7186
  var _XRLocomotionSystem = class _XRLocomotionSystem {
6791
7187
  constructor(inputSystem) {
6792
- this.raycaster = new THREE7.Raycaster();
7188
+ this.raycaster = new THREE19.Raycaster();
6793
7189
  /** Per-source latch so one stick push yields exactly one snap turn. */
6794
7190
  this.turnLatched = /* @__PURE__ */ new WeakSet();
6795
7191
  /** Reused arc buffer — aiming runs every frame. */
@@ -6898,7 +7294,7 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
6898
7294
  }
6899
7295
  if (this.turnLatched.has(source)) continue;
6900
7296
  this.turnLatched.add(source);
6901
- transform.rotation.y -= Math.sign(x) * THREE7.MathUtils.degToRad(rig.snapTurnDegrees);
7297
+ transform.rotation.y -= Math.sign(x) * THREE19.MathUtils.degToRad(rig.snapTurnDegrees);
6902
7298
  }
6903
7299
  }
6904
7300
  applySmoothMove(world, rig, transform, inputs, deltaTime) {
@@ -6908,12 +7304,12 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
6908
7304
  const y = input.axes[1] ?? 0;
6909
7305
  if (Math.abs(x) < 0.15 && Math.abs(y) < 0.15) continue;
6910
7306
  const camera = world.getCamera();
6911
- const forward = new THREE7.Vector3();
7307
+ const forward = new THREE19.Vector3();
6912
7308
  camera.getWorldDirection(forward);
6913
7309
  forward.y = 0;
6914
7310
  if (forward.lengthSq() < 1e-6) continue;
6915
7311
  forward.normalize();
6916
- const right = new THREE7.Vector3().crossVectors(forward, UP).normalize();
7312
+ const right = new THREE19.Vector3().crossVectors(forward, UP).normalize();
6917
7313
  const step = rig.moveSpeed * Math.max(0, deltaTime);
6918
7314
  transform.position.x += (forward.x * -y + right.x * x) * step;
6919
7315
  transform.position.z += (forward.z * -y + right.z * x) * step;
@@ -6978,7 +7374,7 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
6978
7374
  for (let i = 1; i < points.length; i += 1) {
6979
7375
  const from = points[i - 1];
6980
7376
  const to = points[i];
6981
- const delta = new THREE7.Vector3().subVectors(to, from);
7377
+ const delta = new THREE19.Vector3().subVectors(to, from);
6982
7378
  const distance = delta.length();
6983
7379
  if (distance < 1e-6) continue;
6984
7380
  this.raycaster.set(from, delta.divideScalar(distance));
@@ -7186,9 +7582,9 @@ var XRSessionSystem = _XRSessionSystem;
7186
7582
  function buildGeometry2(area) {
7187
7583
  if (area.shape === "circle") {
7188
7584
  const radius = Math.max(5e-3, area.width / 2);
7189
- return new THREE7.CircleGeometry(radius, 48);
7585
+ return new THREE19.CircleGeometry(radius, 48);
7190
7586
  }
7191
- return new THREE7.PlaneGeometry(
7587
+ return new THREE19.PlaneGeometry(
7192
7588
  Math.max(0.01, area.width),
7193
7589
  Math.max(0.01, area.depth)
7194
7590
  );
@@ -7211,7 +7607,7 @@ var _VRTeleportAreaSystem = class _VRTeleportAreaSystem {
7211
7607
  for (const entityId of entityIds) {
7212
7608
  const area = world.getComponent(entityId, VRTeleportAreaComponent);
7213
7609
  const object = world.getComponent(entityId, Object3DRef)?.object;
7214
- if (!area || !(object instanceof THREE7.Mesh)) continue;
7610
+ if (!area || !(object instanceof THREE19.Mesh)) continue;
7215
7611
  const signature = signatureOf(area);
7216
7612
  if (this.signatures.get(entityId) === signature) continue;
7217
7613
  this.signatures.set(entityId, signature);
@@ -7223,18 +7619,18 @@ var _VRTeleportAreaSystem = class _VRTeleportAreaSystem {
7223
7619
  __name(_VRTeleportAreaSystem, "VRTeleportAreaSystem");
7224
7620
  var VRTeleportAreaSystem = _VRTeleportAreaSystem;
7225
7621
  function createHandMaterial(preset, options) {
7226
- const color = new THREE7.Color(options.color);
7622
+ const color = new THREE19.Color(options.color);
7227
7623
  switch (preset) {
7228
7624
  case "ghost":
7229
- return new THREE7.MeshBasicMaterial({
7625
+ return new THREE19.MeshBasicMaterial({
7230
7626
  color,
7231
7627
  transparent: true,
7232
7628
  opacity: Math.min(1, Math.max(0.05, options.opacity * 0.45)),
7233
7629
  depthWrite: false,
7234
- side: THREE7.DoubleSide
7630
+ side: THREE19.DoubleSide
7235
7631
  });
7236
7632
  case "neon":
7237
- return new THREE7.MeshStandardMaterial({
7633
+ return new THREE19.MeshStandardMaterial({
7238
7634
  color,
7239
7635
  emissive: color,
7240
7636
  emissiveIntensity: Math.max(0.5, options.emissiveIntensity || 2),
@@ -7244,7 +7640,7 @@ function createHandMaterial(preset, options) {
7244
7640
  opacity: options.opacity
7245
7641
  });
7246
7642
  case "skeleton":
7247
- return new THREE7.MeshBasicMaterial({
7643
+ return new THREE19.MeshBasicMaterial({
7248
7644
  color,
7249
7645
  wireframe: true,
7250
7646
  transparent: true,
@@ -7252,7 +7648,7 @@ function createHandMaterial(preset, options) {
7252
7648
  });
7253
7649
  case "custom":
7254
7650
  case "default":
7255
- return new THREE7.MeshStandardMaterial({
7651
+ return new THREE19.MeshStandardMaterial({
7256
7652
  color,
7257
7653
  roughness: 0.85,
7258
7654
  metalness: 0,
@@ -7260,10 +7656,10 @@ function createHandMaterial(preset, options) {
7260
7656
  emissiveIntensity: Math.max(0, options.emissiveIntensity),
7261
7657
  transparent: options.opacity < 1,
7262
7658
  opacity: options.opacity,
7263
- side: THREE7.DoubleSide
7659
+ side: THREE19.DoubleSide
7264
7660
  });
7265
7661
  default: {
7266
- return new THREE7.MeshStandardMaterial({ color });
7662
+ return new THREE19.MeshStandardMaterial({ color });
7267
7663
  }
7268
7664
  }
7269
7665
  }
@@ -7284,7 +7680,7 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
7284
7680
  constructor(options) {
7285
7681
  this.controllerModelFactory = new XRControllerModelFactory();
7286
7682
  this.handModelFactory = new XRHandModelFactory();
7287
- this.group = new THREE7.Group();
7683
+ this.group = new THREE19.Group();
7288
7684
  this.slots = /* @__PURE__ */ new Map();
7289
7685
  this.attachedTo = null;
7290
7686
  /** Last applied preset signature, so materials rebuild only on real change. */
@@ -7433,17 +7829,17 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
7433
7829
  this.attachedTo = target;
7434
7830
  }
7435
7831
  createRay() {
7436
- const geometry = new THREE7.BufferGeometry().setFromPoints([
7437
- new THREE7.Vector3(0, 0, 0),
7438
- new THREE7.Vector3(0, 0, -5)
7832
+ const geometry = new THREE19.BufferGeometry().setFromPoints([
7833
+ new THREE19.Vector3(0, 0, 0),
7834
+ new THREE19.Vector3(0, 0, -5)
7439
7835
  ]);
7440
- const material = new THREE7.LineBasicMaterial({
7836
+ const material = new THREE19.LineBasicMaterial({
7441
7837
  color: "#4da3ff",
7442
7838
  transparent: true,
7443
7839
  opacity: 0.6,
7444
7840
  depthTest: false
7445
7841
  });
7446
- const line = new THREE7.Line(geometry, material);
7842
+ const line = new THREE19.Line(geometry, material);
7447
7843
  line.name = "XRPointerRay";
7448
7844
  line.renderOrder = 999;
7449
7845
  line.visible = false;
@@ -7472,23 +7868,23 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
7472
7868
  __name(_XRControllerVisualSystem, "XRControllerVisualSystem");
7473
7869
  var XRControllerVisualSystem = _XRControllerVisualSystem;
7474
7870
  var MARKER_RADIUS = 0.28;
7475
- var ACCENT = new THREE7.Color("#4da3ff");
7476
- var BLOCKED = new THREE7.Color("#ff5a5a");
7871
+ var ACCENT = new THREE19.Color("#4da3ff");
7872
+ var BLOCKED = new THREE19.Color("#ff5a5a");
7477
7873
  var _XRTeleportVisualSystem = class _XRTeleportVisualSystem {
7478
7874
  constructor(locomotionSystem) {
7479
- this.group = new THREE7.Group();
7480
- this.arcGeometry = new THREE7.BufferGeometry();
7481
- this.marker = new THREE7.Group();
7875
+ this.group = new THREE19.Group();
7876
+ this.arcGeometry = new THREE19.BufferGeometry();
7877
+ this.marker = new THREE19.Group();
7482
7878
  this.attached = false;
7483
7879
  this.locomotionSystem = locomotionSystem;
7484
7880
  this.group.name = "XRTeleportVisuals";
7485
7881
  this.group.userData.ecsPreviewHidden = true;
7486
- const arcMaterial = new THREE7.LineBasicMaterial({
7882
+ const arcMaterial = new THREE19.LineBasicMaterial({
7487
7883
  vertexColors: true,
7488
7884
  transparent: true,
7489
7885
  depthTest: false
7490
7886
  });
7491
- this.arc = new THREE7.Line(this.arcGeometry, arcMaterial);
7887
+ this.arc = new THREE19.Line(this.arcGeometry, arcMaterial);
7492
7888
  this.arc.frustumCulled = false;
7493
7889
  this.arc.renderOrder = 998;
7494
7890
  this.group.add(this.arc);
@@ -7536,39 +7932,39 @@ var _XRTeleportVisualSystem = class _XRTeleportVisualSystem {
7536
7932
  }
7537
7933
  this.arcGeometry.setAttribute(
7538
7934
  "position",
7539
- new THREE7.BufferAttribute(positions, 3)
7935
+ new THREE19.BufferAttribute(positions, 3)
7540
7936
  );
7541
- this.arcGeometry.setAttribute("color", new THREE7.BufferAttribute(colors, 3));
7937
+ this.arcGeometry.setAttribute("color", new THREE19.BufferAttribute(colors, 3));
7542
7938
  this.arcGeometry.computeBoundingSphere();
7543
7939
  }
7544
7940
  createRing() {
7545
- const geometry = new THREE7.RingGeometry(
7941
+ const geometry = new THREE19.RingGeometry(
7546
7942
  MARKER_RADIUS * 0.72,
7547
7943
  MARKER_RADIUS,
7548
7944
  48
7549
7945
  );
7550
7946
  geometry.rotateX(-Math.PI / 2);
7551
- return new THREE7.Mesh(
7947
+ return new THREE19.Mesh(
7552
7948
  geometry,
7553
- new THREE7.MeshBasicMaterial({
7949
+ new THREE19.MeshBasicMaterial({
7554
7950
  color: ACCENT,
7555
7951
  transparent: true,
7556
7952
  opacity: 0.9,
7557
- side: THREE7.DoubleSide,
7953
+ side: THREE19.DoubleSide,
7558
7954
  depthTest: false
7559
7955
  })
7560
7956
  );
7561
7957
  }
7562
7958
  createDot() {
7563
- const geometry = new THREE7.CircleGeometry(MARKER_RADIUS * 0.16, 24);
7959
+ const geometry = new THREE19.CircleGeometry(MARKER_RADIUS * 0.16, 24);
7564
7960
  geometry.rotateX(-Math.PI / 2);
7565
- return new THREE7.Mesh(
7961
+ return new THREE19.Mesh(
7566
7962
  geometry,
7567
- new THREE7.MeshBasicMaterial({
7963
+ new THREE19.MeshBasicMaterial({
7568
7964
  color: ACCENT,
7569
7965
  transparent: true,
7570
7966
  opacity: 0.55,
7571
- side: THREE7.DoubleSide,
7967
+ side: THREE19.DoubleSide,
7572
7968
  depthTest: false
7573
7969
  })
7574
7970
  );
@@ -7670,7 +8066,7 @@ function boneDirections(joints, finger) {
7670
8066
  const from = joints[chain[i - 1]];
7671
8067
  const to = joints[chain[i]];
7672
8068
  if (!from || !to) return null;
7673
- const direction = new THREE7.Vector3().subVectors(to, from);
8069
+ const direction = new THREE19.Vector3().subVectors(to, from);
7674
8070
  if (direction.lengthSq() < 1e-12) return null;
7675
8071
  directions.push(direction.normalize());
7676
8072
  }
@@ -7743,8 +8139,8 @@ function computeSpread(joints, a, b) {
7743
8139
  const bBase = joints[METACARPAL_JOINTS[b]];
7744
8140
  const bTip = joints[TIP_JOINTS[b]];
7745
8141
  if (!aBase || !aTip || !bBase || !bTip) return null;
7746
- const dirA = new THREE7.Vector3().subVectors(aTip, aBase);
7747
- const dirB = new THREE7.Vector3().subVectors(bTip, bBase);
8142
+ const dirA = new THREE19.Vector3().subVectors(aTip, aBase);
8143
+ const dirB = new THREE19.Vector3().subVectors(bTip, bBase);
7748
8144
  if (dirA.lengthSq() < 1e-12 || dirB.lengthSq() < 1e-12) return null;
7749
8145
  return clamp01((1 - dirA.normalize().dot(dirB.normalize())) / 0.45);
7750
8146
  }
@@ -7754,18 +8150,18 @@ function computePalmPose(joints, handedness) {
7754
8150
  const indexBase = joints["index-finger-metacarpal"];
7755
8151
  const pinkyBase = joints["pinky-finger-metacarpal"];
7756
8152
  if (!wrist || !indexBase || !pinkyBase) return null;
7757
- const u = new THREE7.Vector3().subVectors(indexBase, wrist);
7758
- const v = new THREE7.Vector3().subVectors(pinkyBase, wrist);
7759
- const normal = new THREE7.Vector3().crossVectors(u, v);
8153
+ const u = new THREE19.Vector3().subVectors(indexBase, wrist);
8154
+ const v = new THREE19.Vector3().subVectors(pinkyBase, wrist);
8155
+ const normal = new THREE19.Vector3().crossVectors(u, v);
7760
8156
  if (normal.lengthSq() < 1e-12) return null;
7761
8157
  normal.normalize();
7762
8158
  if (handedness === "left") normal.multiplyScalar(-1);
7763
- const right = new THREE7.Vector3().subVectors(indexBase, pinkyBase);
8159
+ const right = new THREE19.Vector3().subVectors(indexBase, pinkyBase);
7764
8160
  if (right.lengthSq() < 1e-12) return null;
7765
8161
  right.normalize();
7766
8162
  if (handedness === "left") right.multiplyScalar(-1);
7767
- const up = new THREE7.Vector3().crossVectors(normal, right).normalize();
7768
- const center = new THREE7.Vector3().add(wrist).add(indexBase).add(pinkyBase).divideScalar(3);
8163
+ const up = new THREE19.Vector3().crossVectors(normal, right).normalize();
8164
+ const center = new THREE19.Vector3().add(wrist).add(indexBase).add(pinkyBase).divideScalar(3);
7769
8165
  return {
7770
8166
  center,
7771
8167
  normal,
@@ -7796,7 +8192,7 @@ function computeHandShape(joints, handedness) {
7796
8192
  const thumbTip = joints["thumb-tip"];
7797
8193
  let thumbDirection = null;
7798
8194
  if (thumbBase && thumbTip) {
7799
- const direction = new THREE7.Vector3().subVectors(thumbTip, thumbBase);
8195
+ const direction = new THREE19.Vector3().subVectors(thumbTip, thumbBase);
7800
8196
  if (direction.lengthSq() > 1e-12) thumbDirection = direction.normalize();
7801
8197
  }
7802
8198
  return {
@@ -7828,12 +8224,12 @@ function scoreAgainst(actual, target, tolerance) {
7828
8224
  }
7829
8225
  __name(scoreAgainst, "scoreAgainst");
7830
8226
  var WORLD_DIRECTIONS = {
7831
- up: new THREE7.Vector3(0, 1, 0),
7832
- down: new THREE7.Vector3(0, -1, 0),
7833
- forward: new THREE7.Vector3(0, 0, -1),
7834
- back: new THREE7.Vector3(0, 0, 1),
7835
- left: new THREE7.Vector3(-1, 0, 0),
7836
- right: new THREE7.Vector3(1, 0, 0)
8227
+ up: new THREE19.Vector3(0, 1, 0),
8228
+ down: new THREE19.Vector3(0, -1, 0),
8229
+ forward: new THREE19.Vector3(0, 0, -1),
8230
+ back: new THREE19.Vector3(0, 0, 1),
8231
+ left: new THREE19.Vector3(-1, 0, 0),
8232
+ right: new THREE19.Vector3(1, 0, 0)
7837
8233
  };
7838
8234
  function axisVector(shape, axis) {
7839
8235
  if (axis === "thumb") return shape.thumbDirection;
@@ -7848,7 +8244,7 @@ function resolveDirection(direction, shape, context) {
7848
8244
  const head = context?.headPosition;
7849
8245
  const origin = shape.palm?.center;
7850
8246
  if (!head || !origin) return null;
7851
- const toHead = new THREE7.Vector3().subVectors(head, origin);
8247
+ const toHead = new THREE19.Vector3().subVectors(head, origin);
7852
8248
  if (toHead.lengthSq() < 1e-12) return null;
7853
8249
  toHead.normalize();
7854
8250
  return direction === "toward-head" ? toHead : toHead.multiplyScalar(-1);
@@ -7898,8 +8294,8 @@ function matchHandPose(shape, definition, context) {
7898
8294
  if (!handAxis || !wanted) {
7899
8295
  consider(0, "orientation");
7900
8296
  } else {
7901
- const angle = THREE7.MathUtils.radToDeg(
7902
- Math.acos(THREE7.MathUtils.clamp(handAxis.dot(wanted), -1, 1))
8297
+ const angle = THREE19.MathUtils.radToDeg(
8298
+ Math.acos(THREE19.MathUtils.clamp(handAxis.dot(wanted), -1, 1))
7903
8299
  );
7904
8300
  const normalizedError = Math.max(0, angle - toleranceDegrees) / 90;
7905
8301
  consider(clamp01(1 - normalizedError / MATCH_FALLOFF), "orientation");
@@ -7977,7 +8373,7 @@ var _XRHandPoseSystem = class _XRHandPoseSystem {
7977
8373
  this.trackers = /* @__PURE__ */ new Map();
7978
8374
  this.shapes = /* @__PURE__ */ new Map();
7979
8375
  /** Reused so head-relative orientation checks allocate nothing per frame. */
7980
- this.headPosition = new THREE7.Vector3();
8376
+ this.headPosition = new THREE19.Vector3();
7981
8377
  this.elapsed = 0;
7982
8378
  this.inputSystem = inputSystem;
7983
8379
  }
@@ -8099,6 +8495,6 @@ var _XRHandPoseSystem = class _XRHandPoseSystem {
8099
8495
  __name(_XRHandPoseSystem, "XRHandPoseSystem");
8100
8496
  var XRHandPoseSystem = _XRHandPoseSystem;
8101
8497
 
8102
- export { ADDED_NODE_MARKER_COMPONENT, ARC_GRAVITY, ARC_MAX_TIME, ARC_SPEED, ARC_STEPS, AnimationSystem, AudioSystem, Behaviour, CURLED_COS, CameraSyncSystem, DEFAULT_ENTER_CONFIDENCE, DEFAULT_EXIT_CONFIDENCE, DEFAULT_LOST_GRACE_SECONDS, DEFAULT_MIN_HOLD_SECONDS, EnvironmentSyncSystem, FALLBACK_HAND_SCALE, HYDRATABLE_ENTITY_KINDS, HandPoseTracker, InputSystem, InstancedMeshSystem, KeyboardKeys, LightSyncSystem, MATCH_FALLOFF, MAX_SAMPLE_AGE_SECONDS, MaterialSyncSystem, MeshGeometrySystem, NODE_KEY_SEPARATOR, NO_XR_CAPABILITIES, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectVisibilitySystem, PINCH_FINGERS, PREFAB_FILE_VERSION, PREFAB_FILE_VERSION_NESTED, PhysicsSyncSystem, PostprocessingSyncSystem, RenderSystem, SCRIPT_OBJECT_ROOT_FLAG, STRAIGHT_COS, ScriptBehaviourSystem, ScriptObject, ScriptObjectSystem, ThrowVelocityTracker, TransformSyncSystem, VELOCITY_SAMPLES, VRTeleportAreaSystem, VideoSystem, XRControllerVisualSystem, XRHandPoseSystem, XRInputSystem, XRInteractionSystem, XRLocomotionSystem, XRSessionSystem, XRTeleportVisualSystem, XR_FINGERS, angularVelocityFrom, applyHandMaterial, arcGroundCrossing, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearPrefabCache, collectDiffPaths, collectEntitySubtree, collectSnapshotSubtreeIds, computeFingerCurl, computeHandShape, computeInstanceOverrides, computePalmPose, computePalmWidth, computePinch, computeSpread, createHandMaterial, decanonicalizeComponentValue, despawnPrefab, encodeOverride, estimateHandScale, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadPrefab, matchHandPose, mergeComponentValue, parseOverride, parsePrefabAsset, prefabFileVersionFor, readXrCapabilities, restoreComponentState, restorePostCreateComponents, sampleTeleportArc, setPrefabAssetUrlResolver, spawnPrefab };
8103
- //# sourceMappingURL=chunk-LMTB4KQ4.js.map
8104
- //# sourceMappingURL=chunk-LMTB4KQ4.js.map
8498
+ export { ADDED_NODE_MARKER_COMPONENT, ARC_GRAVITY, ARC_MAX_TIME, ARC_SPEED, ARC_STEPS, AnimationSystem, AudioSystem, Behaviour, CURLED_COS, CameraSyncSystem, DEFAULT_ENTER_CONFIDENCE, DEFAULT_EXIT_CONFIDENCE, DEFAULT_LOST_GRACE_SECONDS, DEFAULT_MIN_HOLD_SECONDS, EnvironmentSyncSystem, FALLBACK_HAND_SCALE, HYDRATABLE_ENTITY_KINDS, HandPoseTracker, InputSystem, InstancedMeshSystem, KeyboardKeys, LightSyncSystem, MATCH_FALLOFF, MAX_PLAUSIBLE_SPEED, MAX_SAMPLE_AGE_SECONDS, MaterialSyncSystem, MeshGeometrySystem, NODE_KEY_SEPARATOR, NO_XR_CAPABILITIES, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectVisibilitySystem, PINCH_FINGERS, PREFAB_FILE_VERSION, PREFAB_FILE_VERSION_NESTED, PhysicsSyncSystem, PostprocessingSyncSystem, RenderSystem, SCRIPT_OBJECT_ROOT_FLAG, STRAIGHT_COS, ScriptBehaviourSystem, ScriptObject, ScriptObjectSystem, ThrowVelocityTracker, TransformSyncSystem, VELOCITY_SAMPLES, VRTeleportAreaSystem, VideoSystem, XRControllerVisualSystem, XRHandPoseSystem, XRInputSystem, XRInteractionSystem, XRLocomotionSystem, XRSessionSystem, XRTeleportVisualSystem, XR_FINGERS, angularVelocityFrom, applyHandMaterial, arcGroundCrossing, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearPrefabCache, collectDiffPaths, collectEntitySubtree, collectSnapshotSubtreeIds, computeFingerCurl, computeHandShape, computeInstanceOverrides, computePalmPose, computePalmWidth, computePinch, computeSpread, createHandMaterial, decanonicalizeComponentValue, despawnPrefab, encodeOverride, estimateHandScale, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadPrefab, matchHandPose, mergeComponentValue, parseOverride, parsePrefabAsset, prefabFileVersionFor, readXrCapabilities, restoreComponentState, restorePostCreateComponents, sampleTeleportArc, setPrefabAssetUrlResolver, spawnPrefab };
8499
+ //# sourceMappingURL=chunk-O2HSIZFC.js.map
8500
+ //# sourceMappingURL=chunk-O2HSIZFC.js.map