@relu-interactives/spatial-ecs 0.3.4 → 0.3.6

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 (44) hide show
  1. package/dist/{System-vrU46Vuw.d.cts → System-TmC2EijF.d.cts} +2 -2
  2. package/dist/{System-vrU46Vuw.d.ts → System-TmC2EijF.d.ts} +2 -2
  3. package/dist/{XRRig-2686IqLQ.d.cts → XRInteractor-CCUzSqg9.d.ts} +96 -2
  4. package/dist/{XRRig-D2QURXl1.d.ts → XRInteractor-I2q6TKtF.d.cts} +96 -2
  5. package/dist/{chunk-4BZYK3JP.js → chunk-FQTOC7HK.js} +135 -88
  6. package/dist/chunk-FQTOC7HK.js.map +1 -0
  7. package/dist/{chunk-2LVFGVWI.js → chunk-JRJ3CL5H.js} +3 -3
  8. package/dist/{chunk-2LVFGVWI.js.map → chunk-JRJ3CL5H.js.map} +1 -1
  9. package/dist/{chunk-6QC2PJLD.js → chunk-N4GKZ7IV.js} +29 -3
  10. package/dist/chunk-N4GKZ7IV.js.map +1 -0
  11. package/dist/{chunk-ID266ZUA.js → chunk-WRJ2K3LZ.js} +525 -41
  12. package/dist/chunk-WRJ2K3LZ.js.map +1 -0
  13. package/dist/components/index.cjs +26 -0
  14. package/dist/components/index.cjs.map +1 -1
  15. package/dist/components/index.d.cts +3 -3
  16. package/dist/components/index.d.ts +3 -3
  17. package/dist/components/index.js +1 -1
  18. package/dist/factories/index.cjs +185 -112
  19. package/dist/factories/index.cjs.map +1 -1
  20. package/dist/factories/index.d.cts +7 -3
  21. package/dist/factories/index.d.ts +7 -3
  22. package/dist/factories/index.js +3 -3
  23. package/dist/{index-BtKOaHfY.d.ts → index-BltjPEhg.d.cts} +10 -3
  24. package/dist/{index-CRmfSYdj.d.ts → index-BpbmZuOz.d.ts} +92 -16
  25. package/dist/{index-Bc0YCz1A.d.cts → index-C5FrDt3z.d.cts} +92 -16
  26. package/dist/{index-Xu238jLn.d.cts → index-W8pUajCW.d.ts} +10 -3
  27. package/dist/index.cjs +829 -261
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +76 -9
  30. package/dist/index.d.ts +76 -9
  31. package/dist/index.js +8 -8
  32. package/dist/systems/index.cjs +532 -36
  33. package/dist/systems/index.cjs.map +1 -1
  34. package/dist/systems/index.d.cts +2 -2
  35. package/dist/systems/index.d.ts +2 -2
  36. package/dist/systems/index.js +3 -3
  37. package/dist/types.d.cts +1 -1
  38. package/dist/types.d.ts +1 -1
  39. package/dist/worldSnapshotUtils.d.cts +1 -1
  40. package/dist/worldSnapshotUtils.d.ts +1 -1
  41. package/package.json +1 -1
  42. package/dist/chunk-4BZYK3JP.js.map +0 -1
  43. package/dist/chunk-6QC2PJLD.js.map +0 -1
  44. package/dist/chunk-ID266ZUA.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var THREE38 = require('three');
3
+ var THREE39 = require('three');
4
4
  var SkeletonUtils_js = require('three/examples/jsm/utils/SkeletonUtils.js');
5
5
  var RectAreaLightHelper_js = require('three/examples/jsm/helpers/RectAreaLightHelper.js');
6
6
  var DRACOLoader_js = require('three/examples/jsm/loaders/DRACOLoader.js');
@@ -41,7 +41,7 @@ function _interopNamespace(e) {
41
41
  return Object.freeze(n);
42
42
  }
43
43
 
44
- var THREE38__namespace = /*#__PURE__*/_interopNamespace(THREE38);
44
+ var THREE39__namespace = /*#__PURE__*/_interopNamespace(THREE39);
45
45
 
46
46
  var __defProp = Object.defineProperty;
47
47
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
@@ -605,14 +605,14 @@ var _AnimationComponent = class _AnimationComponent extends Component {
605
605
  return;
606
606
  }
607
607
  this.importedClips = clips.map((entry) => {
608
- if (entry instanceof THREE38__namespace.AnimationClip) {
608
+ if (entry instanceof THREE39__namespace.AnimationClip) {
609
609
  return { clip: entry, sourceUrl: null };
610
610
  }
611
611
  if (!entry || typeof entry !== "object") {
612
612
  return null;
613
613
  }
614
614
  const candidate = entry;
615
- if (!(candidate.clip instanceof THREE38__namespace.AnimationClip)) {
615
+ if (!(candidate.clip instanceof THREE39__namespace.AnimationClip)) {
616
616
  return null;
617
617
  }
618
618
  return {
@@ -820,11 +820,11 @@ function normalizeDistanceModel(distanceModel) {
820
820
  }
821
821
  __name(normalizeDistanceModel, "normalizeDistanceModel");
822
822
  function createConfiguredAudio(listener, options) {
823
- const sound = options.positional ? new THREE38__namespace.PositionalAudio(listener) : new THREE38__namespace.Audio(listener);
823
+ const sound = options.positional ? new THREE39__namespace.PositionalAudio(listener) : new THREE39__namespace.Audio(listener);
824
824
  sound.setLoop(options.loop);
825
825
  sound.setVolume(options.volume);
826
826
  sound.setPlaybackRate(options.pitch);
827
- if (sound instanceof THREE38__namespace.PositionalAudio) {
827
+ if (sound instanceof THREE39__namespace.PositionalAudio) {
828
828
  sound.setRefDistance(options.refDistance);
829
829
  sound.setDistanceModel(normalizeDistanceModel(options.distanceModel));
830
830
  sound.setRolloffFactor(options.rolloffFactor);
@@ -834,16 +834,16 @@ function createConfiguredAudio(listener, options) {
834
834
  __name(createConfiguredAudio, "createConfiguredAudio");
835
835
  function createAudioEditorHelper() {
836
836
  if (typeof document === "undefined") {
837
- const geometry = new THREE38__namespace.EdgesGeometry(
838
- new THREE38__namespace.OctahedronGeometry(0.22, 0)
837
+ const geometry = new THREE39__namespace.EdgesGeometry(
838
+ new THREE39__namespace.OctahedronGeometry(0.22, 0)
839
839
  );
840
- const material2 = new THREE38__namespace.LineBasicMaterial({
840
+ const material2 = new THREE39__namespace.LineBasicMaterial({
841
841
  color: "#8bc8ff",
842
842
  transparent: true,
843
843
  opacity: 0.95,
844
844
  depthTest: false
845
845
  });
846
- const fallback = new THREE38__namespace.LineSegments(geometry, material2);
846
+ const fallback = new THREE39__namespace.LineSegments(geometry, material2);
847
847
  fallback.renderOrder = 10;
848
848
  fallback.userData.ecsHelper = true;
849
849
  fallback.visible = false;
@@ -855,7 +855,7 @@ function createAudioEditorHelper() {
855
855
  canvas.height = size;
856
856
  const ctx = canvas.getContext("2d");
857
857
  if (!ctx) {
858
- return new THREE38__namespace.Object3D();
858
+ return new THREE39__namespace.Object3D();
859
859
  }
860
860
  ctx.clearRect(0, 0, size, size);
861
861
  ctx.fillStyle = "rgba(27, 35, 52, 0.9)";
@@ -886,14 +886,14 @@ function createAudioEditorHelper() {
886
886
  ctx.beginPath();
887
887
  ctx.arc(56, 48, 16, -0.8, 0.8);
888
888
  ctx.stroke();
889
- const texture = new THREE38__namespace.CanvasTexture(canvas);
889
+ const texture = new THREE39__namespace.CanvasTexture(canvas);
890
890
  texture.needsUpdate = true;
891
- const material = new THREE38__namespace.SpriteMaterial({
891
+ const material = new THREE39__namespace.SpriteMaterial({
892
892
  map: texture,
893
893
  transparent: true,
894
894
  depthTest: false
895
895
  });
896
- const helper = new THREE38__namespace.Sprite(material);
896
+ const helper = new THREE39__namespace.Sprite(material);
897
897
  helper.scale.set(0.68, 0.68, 0.68);
898
898
  helper.renderOrder = 10;
899
899
  helper.userData.ecsHelper = true;
@@ -927,7 +927,7 @@ var DEFAULT_ORTHO_TOP = 5;
927
927
  var DEFAULT_ORTHO_BOTTOM = -5;
928
928
  var DEFAULT_ZOOM = 1;
929
929
  function inferProjection(camera) {
930
- if (camera instanceof THREE38__namespace.OrthographicCamera) {
930
+ if (camera instanceof THREE39__namespace.OrthographicCamera) {
931
931
  return "orthographic";
932
932
  }
933
933
  return "perspective";
@@ -948,7 +948,7 @@ function readCameraFar(camera) {
948
948
  }
949
949
  __name(readCameraFar, "readCameraFar");
950
950
  function inferFov(camera) {
951
- if (camera instanceof THREE38__namespace.PerspectiveCamera && Number.isFinite(camera.fov)) {
951
+ if (camera instanceof THREE39__namespace.PerspectiveCamera && Number.isFinite(camera.fov)) {
952
952
  return camera.fov;
953
953
  }
954
954
  return DEFAULT_FOV;
@@ -971,28 +971,28 @@ function inferFar(camera) {
971
971
  }
972
972
  __name(inferFar, "inferFar");
973
973
  function inferOrthoLeft(camera) {
974
- if (camera instanceof THREE38__namespace.OrthographicCamera && Number.isFinite(camera.left)) {
974
+ if (camera instanceof THREE39__namespace.OrthographicCamera && Number.isFinite(camera.left)) {
975
975
  return camera.left;
976
976
  }
977
977
  return DEFAULT_ORTHO_LEFT;
978
978
  }
979
979
  __name(inferOrthoLeft, "inferOrthoLeft");
980
980
  function inferOrthoRight(camera) {
981
- if (camera instanceof THREE38__namespace.OrthographicCamera && Number.isFinite(camera.right)) {
981
+ if (camera instanceof THREE39__namespace.OrthographicCamera && Number.isFinite(camera.right)) {
982
982
  return camera.right;
983
983
  }
984
984
  return DEFAULT_ORTHO_RIGHT;
985
985
  }
986
986
  __name(inferOrthoRight, "inferOrthoRight");
987
987
  function inferOrthoTop(camera) {
988
- if (camera instanceof THREE38__namespace.OrthographicCamera && Number.isFinite(camera.top)) {
988
+ if (camera instanceof THREE39__namespace.OrthographicCamera && Number.isFinite(camera.top)) {
989
989
  return camera.top;
990
990
  }
991
991
  return DEFAULT_ORTHO_TOP;
992
992
  }
993
993
  __name(inferOrthoTop, "inferOrthoTop");
994
994
  function inferOrthoBottom(camera) {
995
- if (camera instanceof THREE38__namespace.OrthographicCamera && Number.isFinite(camera.bottom)) {
995
+ if (camera instanceof THREE39__namespace.OrthographicCamera && Number.isFinite(camera.bottom)) {
996
996
  return camera.bottom;
997
997
  }
998
998
  return DEFAULT_ORTHO_BOTTOM;
@@ -1008,7 +1008,7 @@ __name(inferZoom, "inferZoom");
1008
1008
  var _CameraComponent = class _CameraComponent extends Component {
1009
1009
  constructor(payload = {}) {
1010
1010
  super();
1011
- this.camera = payload.camera ?? new THREE38__namespace.PerspectiveCamera();
1011
+ this.camera = payload.camera ?? new THREE39__namespace.PerspectiveCamera();
1012
1012
  this.type = payload.type ?? "3d";
1013
1013
  this.isDefault = typeof payload.isDefault === "boolean" ? payload.isDefault : false;
1014
1014
  this.projection = payload.projection ?? inferProjection(payload.camera);
@@ -1039,7 +1039,7 @@ var Object3DRef = _Object3DRef;
1039
1039
  // core/factories/components/CameraFactory.ts
1040
1040
  function createCameraComponent(world, entityId, payload = {}) {
1041
1041
  const object = world.getComponent(entityId, Object3DRef)?.object;
1042
- const objectCamera = object instanceof THREE38__namespace.Camera ? object : void 0;
1042
+ const objectCamera = object instanceof THREE39__namespace.Camera ? object : void 0;
1043
1043
  const component = new CameraComponent({
1044
1044
  ...payload,
1045
1045
  camera: payload.camera ?? objectCamera
@@ -1609,15 +1609,15 @@ function createValueState(light) {
1609
1609
  castShadow: light.castShadow ?? false,
1610
1610
  frustumCulling: light.frustumCulled
1611
1611
  };
1612
- if (light instanceof THREE38__namespace.PointLight) {
1612
+ if (light instanceof THREE39__namespace.PointLight) {
1613
1613
  base.distance = light.distance;
1614
1614
  base.decay = light.decay;
1615
- } else if (light instanceof THREE38__namespace.SpotLight) {
1615
+ } else if (light instanceof THREE39__namespace.SpotLight) {
1616
1616
  base.distance = light.distance;
1617
1617
  base.decay = light.decay;
1618
1618
  base.angle = light.angle;
1619
1619
  base.penumbra = light.penumbra;
1620
- } else if (light instanceof THREE38__namespace.RectAreaLight) {
1620
+ } else if (light instanceof THREE39__namespace.RectAreaLight) {
1621
1621
  base.width = light.width;
1622
1622
  base.height = light.height;
1623
1623
  }
@@ -1660,13 +1660,13 @@ function toHexColor2(value, fallback) {
1660
1660
  }
1661
1661
  __name(toHexColor2, "toHexColor");
1662
1662
  function getMaterialType(material) {
1663
- if (material instanceof THREE38__namespace.MeshPhysicalMaterial) {
1663
+ if (material instanceof THREE39__namespace.MeshPhysicalMaterial) {
1664
1664
  return "physical";
1665
1665
  }
1666
- if (material instanceof THREE38__namespace.MeshPhongMaterial) {
1666
+ if (material instanceof THREE39__namespace.MeshPhongMaterial) {
1667
1667
  return "phong";
1668
1668
  }
1669
- if (material instanceof THREE38__namespace.MeshBasicMaterial) {
1669
+ if (material instanceof THREE39__namespace.MeshBasicMaterial) {
1670
1670
  return "basic";
1671
1671
  }
1672
1672
  return "standard";
@@ -1701,8 +1701,8 @@ function createMaterialValue(material) {
1701
1701
  opacity: typeof materialRecord.opacity === "number" ? materialRecord.opacity : 1,
1702
1702
  emissive: toHexColor2(materialRecord.emissive, "#000000"),
1703
1703
  emissiveIntensity: typeof materialRecord.emissiveIntensity === "number" ? materialRecord.emissiveIntensity : 0,
1704
- side: typeof materialRecord.side === "number" ? materialRecord.side : THREE38__namespace.FrontSide,
1705
- blending: typeof materialRecord.blending === "number" ? materialRecord.blending : THREE38__namespace.NormalBlending,
1704
+ side: typeof materialRecord.side === "number" ? materialRecord.side : THREE39__namespace.FrontSide,
1705
+ blending: typeof materialRecord.blending === "number" ? materialRecord.blending : THREE39__namespace.NormalBlending,
1706
1706
  depthTest: materialRecord.depthTest !== false,
1707
1707
  depthWrite: materialRecord.depthWrite !== false,
1708
1708
  wireframe: Boolean(materialRecord.wireframe),
@@ -1734,7 +1734,7 @@ function createMaterialValue(material) {
1734
1734
  materialRecord.lightMap
1735
1735
  ),
1736
1736
  envMap: textureImageSrc(materialRecord.envMap),
1737
- textureFiltering: map?.magFilter === THREE38__namespace.NearestFilter ? "sharp" : "smooth",
1737
+ textureFiltering: map?.magFilter === THREE39__namespace.NearestFilter ? "sharp" : "smooth",
1738
1738
  useMipmaps: map?.generateMipmaps !== false
1739
1739
  };
1740
1740
  }
@@ -1749,8 +1749,8 @@ function defaultMaterialValue() {
1749
1749
  opacity: 1,
1750
1750
  emissive: "#000000",
1751
1751
  emissiveIntensity: 0,
1752
- side: THREE38__namespace.FrontSide,
1753
- blending: THREE38__namespace.NormalBlending,
1752
+ side: THREE39__namespace.FrontSide,
1753
+ blending: THREE39__namespace.NormalBlending,
1754
1754
  depthTest: true,
1755
1755
  depthWrite: true,
1756
1756
  wireframe: false,
@@ -2327,14 +2327,14 @@ var _TransformComponent = class _TransformComponent extends Component {
2327
2327
  z: scale.z ?? 1
2328
2328
  };
2329
2329
  }
2330
- toPositionVector3(target = new THREE38.Vector3()) {
2330
+ toPositionVector3(target = new THREE39.Vector3()) {
2331
2331
  return target.set(this.position.x, this.position.y, this.position.z);
2332
2332
  }
2333
- toRotationEuler(target = new THREE38.Euler(), order = "XYZ") {
2333
+ toRotationEuler(target = new THREE39.Euler(), order = "XYZ") {
2334
2334
  return target.set(this.rotation.x, this.rotation.y, this.rotation.z, order);
2335
2335
  }
2336
- toRotationQuaternion(target = new THREE38.Quaternion(), order = "XYZ") {
2337
- const euler = new THREE38.Euler(
2336
+ toRotationQuaternion(target = new THREE39.Quaternion(), order = "XYZ") {
2337
+ const euler = new THREE39.Euler(
2338
2338
  this.rotation.x,
2339
2339
  this.rotation.y,
2340
2340
  this.rotation.z,
@@ -2342,7 +2342,7 @@ var _TransformComponent = class _TransformComponent extends Component {
2342
2342
  );
2343
2343
  return target.setFromEuler(euler);
2344
2344
  }
2345
- toScaleVector3(target = new THREE38.Vector3()) {
2345
+ toScaleVector3(target = new THREE39.Vector3()) {
2346
2346
  return target.set(this.scale.x, this.scale.y, this.scale.z);
2347
2347
  }
2348
2348
  setPosition(input) {
@@ -2360,8 +2360,8 @@ var _TransformComponent = class _TransformComponent extends Component {
2360
2360
  return this;
2361
2361
  }
2362
2362
  setRotation(input, order = "XYZ") {
2363
- if (input instanceof THREE38.Quaternion) {
2364
- const euler = new THREE38.Euler().setFromQuaternion(input, order);
2363
+ if (input instanceof THREE39.Quaternion) {
2364
+ const euler = new THREE39.Euler().setFromQuaternion(input, order);
2365
2365
  this.rotation.x = euler.x;
2366
2366
  this.rotation.y = euler.y;
2367
2367
  this.rotation.z = euler.z;
@@ -2570,6 +2570,7 @@ __name(createVideoComponent, "createVideoComponent");
2570
2570
  var _XRRigComponent = class _XRRigComponent extends Component {
2571
2571
  constructor(options) {
2572
2572
  super();
2573
+ this.trackingOrigin = options?.trackingOrigin ?? "floor";
2573
2574
  this.locomotion = options?.locomotion ?? "teleport";
2574
2575
  this.moveSpeed = options?.moveSpeed ?? 2;
2575
2576
  this.snapTurn = options?.snapTurn ?? true;
@@ -2632,6 +2633,45 @@ function createXRInteractableComponent(world, entityId, ...args) {
2632
2633
  }
2633
2634
  __name(createXRInteractableComponent, "createXRInteractableComponent");
2634
2635
 
2636
+ // core/components/XRInteractor.ts
2637
+ var _XRInteractorComponent = class _XRInteractorComponent extends Component {
2638
+ constructor(options) {
2639
+ super();
2640
+ this.interactorType = options?.interactorType ?? "both";
2641
+ this.handPreset = options?.handPreset ?? "default";
2642
+ this.handColor = options?.handColor ?? "#e8b48a";
2643
+ this.handOpacity = options?.handOpacity ?? 1;
2644
+ this.handEmissiveIntensity = options?.handEmissiveIntensity ?? 0;
2645
+ this.showRay = options?.showRay ?? true;
2646
+ }
2647
+ };
2648
+ __name(_XRInteractorComponent, "XRInteractorComponent");
2649
+ var XRInteractorComponent = _XRInteractorComponent;
2650
+ var _XRInteractorSideComponent = class _XRInteractorSideComponent extends Component {
2651
+ constructor(options) {
2652
+ super();
2653
+ this.side = options?.side ?? "left";
2654
+ }
2655
+ };
2656
+ __name(_XRInteractorSideComponent, "XRInteractorSideComponent");
2657
+ var XRInteractorSideComponent = _XRInteractorSideComponent;
2658
+
2659
+ // core/factories/components/XRInteractorFactory.ts
2660
+ function createXRInteractorComponent(world, entityId, ...args) {
2661
+ const component = new XRInteractorComponent(...args);
2662
+ world.addComponent(entityId, component);
2663
+ return component;
2664
+ }
2665
+ __name(createXRInteractorComponent, "createXRInteractorComponent");
2666
+
2667
+ // core/factories/components/XRInteractorSideFactory.ts
2668
+ function createXRInteractorSideComponent(world, entityId, ...args) {
2669
+ const component = new XRInteractorSideComponent(...args);
2670
+ world.addComponent(entityId, component);
2671
+ return component;
2672
+ }
2673
+ __name(createXRInteractorSideComponent, "createXRInteractorSideComponent");
2674
+
2635
2675
  // core/factories/registerDefaultComponentFactories.ts
2636
2676
  function registerDefaultComponentFactories(objectManagementSystem) {
2637
2677
  objectManagementSystem.registerComponentFactory("animation", createAnimationComponent);
@@ -2644,6 +2684,8 @@ function registerDefaultComponentFactories(objectManagementSystem) {
2644
2684
  objectManagementSystem.registerComponentFactory("xrRig", createXRRigComponent);
2645
2685
  objectManagementSystem.registerComponentFactory("vrTeleportArea", createVRTeleportAreaComponent);
2646
2686
  objectManagementSystem.registerComponentFactory("xrInteractable", createXRInteractableComponent);
2687
+ objectManagementSystem.registerComponentFactory("xrInteractor", createXRInteractorComponent);
2688
+ objectManagementSystem.registerComponentFactory("xrInteractorSide", createXRInteractorSideComponent);
2647
2689
  objectManagementSystem.registerComponentFactory(
2648
2690
  "imageTargetAnchor",
2649
2691
  createImageTargetAnchorComponent
@@ -2687,7 +2729,7 @@ var SHARED_MODEL_RESOURCE_FLAG = "spatialEcsSharedModelResource";
2687
2729
  var modelCache = /* @__PURE__ */ new Map();
2688
2730
  function markSharedResources(root) {
2689
2731
  root.traverse((child) => {
2690
- if (!(child instanceof THREE38__namespace.Mesh)) {
2732
+ if (!(child instanceof THREE39__namespace.Mesh)) {
2691
2733
  return;
2692
2734
  }
2693
2735
  if (child.geometry) {
@@ -2766,10 +2808,10 @@ var _ObjectManagementSystem = class _ObjectManagementSystem {
2766
2808
  }
2767
2809
  getOrCreateAudioListener() {
2768
2810
  const existing = this.camera.userData.ecsAudioListener;
2769
- if (existing instanceof THREE38__namespace.AudioListener) {
2811
+ if (existing instanceof THREE39__namespace.AudioListener) {
2770
2812
  return existing;
2771
2813
  }
2772
- const listener = new THREE38__namespace.AudioListener();
2814
+ const listener = new THREE39__namespace.AudioListener();
2773
2815
  this.camera.add(listener);
2774
2816
  this.camera.userData.ecsAudioListener = listener;
2775
2817
  return listener;
@@ -2843,7 +2885,7 @@ var _ObjectManagementSystem = class _ObjectManagementSystem {
2843
2885
  }
2844
2886
  if (dispose && object3d) {
2845
2887
  object3d.traverse((child) => {
2846
- if (child instanceof THREE38__namespace.Mesh) {
2888
+ if (child instanceof THREE39__namespace.Mesh) {
2847
2889
  if (!child.geometry?.userData?.[SHARED_MODEL_RESOURCE_FLAG]) {
2848
2890
  child.geometry?.dispose();
2849
2891
  }
@@ -2980,10 +3022,10 @@ __name(createBaseEntity, "createBaseEntity");
2980
3022
  // core/factories/objects/AudioFactory.ts
2981
3023
  function getOrCreateListener(camera) {
2982
3024
  const existing = camera.userData.ecsAudioListener;
2983
- if (existing instanceof THREE38__namespace.AudioListener) {
3025
+ if (existing instanceof THREE39__namespace.AudioListener) {
2984
3026
  return existing;
2985
3027
  }
2986
- const listener = new THREE38__namespace.AudioListener();
3028
+ const listener = new THREE39__namespace.AudioListener();
2987
3029
  camera.add(listener);
2988
3030
  camera.userData.ecsAudioListener = listener;
2989
3031
  return listener;
@@ -2996,7 +3038,7 @@ function createAudio({
2996
3038
  payload,
2997
3039
  isEditor
2998
3040
  }) {
2999
- const anchor = new THREE38__namespace.Object3D();
3041
+ const anchor = new THREE39__namespace.Object3D();
3000
3042
  const entityId = createBaseEntity(world, anchor, {
3001
3043
  label: payload.name ?? "Audio",
3002
3044
  entityType: "audio",
@@ -3018,7 +3060,7 @@ function createAudio({
3018
3060
  return entityId;
3019
3061
  }
3020
3062
  if (!isEditor) {
3021
- const loader = new THREE38__namespace.AudioLoader();
3063
+ const loader = new THREE39__namespace.AudioLoader();
3022
3064
  loader.load(
3023
3065
  audio.path,
3024
3066
  (buffer) => {
@@ -3093,7 +3135,7 @@ function applyCameraSettings(camera, options) {
3093
3135
  const near = typeof options.near === "number" ? options.near : DEFAULT_NEAR2;
3094
3136
  const far = typeof options.far === "number" ? options.far : DEFAULT_FAR2;
3095
3137
  const projection = options.projection;
3096
- if (camera instanceof THREE38__namespace.PerspectiveCamera) {
3138
+ if (camera instanceof THREE39__namespace.PerspectiveCamera) {
3097
3139
  if (!projection || projection === "perspective") {
3098
3140
  camera.fov = typeof options.fov === "number" ? options.fov : DEFAULT_FOV2;
3099
3141
  }
@@ -3103,7 +3145,7 @@ function applyCameraSettings(camera, options) {
3103
3145
  camera.updateProjectionMatrix();
3104
3146
  return;
3105
3147
  }
3106
- if (camera instanceof THREE38__namespace.OrthographicCamera) {
3148
+ if (camera instanceof THREE39__namespace.OrthographicCamera) {
3107
3149
  camera.left = typeof options.left === "number" ? options.left : -DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
3108
3150
  camera.right = typeof options.right === "number" ? options.right : DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
3109
3151
  camera.top = typeof options.top === "number" ? options.top : DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
@@ -3124,7 +3166,7 @@ function createCameraObject(options) {
3124
3166
  const bottom = options.bottom ?? -DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
3125
3167
  const left = options.left ?? -DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
3126
3168
  const right = options.right ?? DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
3127
- const camera = new THREE38__namespace.OrthographicCamera(
3169
+ const camera = new THREE39__namespace.OrthographicCamera(
3128
3170
  left,
3129
3171
  right,
3130
3172
  top,
@@ -3136,7 +3178,7 @@ function createCameraObject(options) {
3136
3178
  camera.updateProjectionMatrix();
3137
3179
  return camera;
3138
3180
  }
3139
- return new THREE38__namespace.PerspectiveCamera(
3181
+ return new THREE39__namespace.PerspectiveCamera(
3140
3182
  options.fov ?? DEFAULT_FOV2,
3141
3183
  readViewportAspect(),
3142
3184
  near,
@@ -3154,7 +3196,7 @@ function createCamera({ world, scene, camera, payload, isEditor }) {
3154
3196
  transformInput: payload.transform
3155
3197
  });
3156
3198
  const objectRef = world.getComponent(entityId, Object3DRef);
3157
- if (objectRef?.object instanceof THREE38__namespace.Camera) {
3199
+ if (objectRef?.object instanceof THREE39__namespace.Camera) {
3158
3200
  objectRef.object.userData.entityId = entityId;
3159
3201
  }
3160
3202
  const componentOptions = {
@@ -3186,9 +3228,9 @@ function createCapsule({
3186
3228
  scene,
3187
3229
  payload
3188
3230
  }) {
3189
- const geometry = new THREE38__namespace.CapsuleGeometry(0.5, 1, 4, 8);
3190
- const material = new THREE38__namespace.MeshStandardMaterial({ color: "#ffffff" });
3191
- const mesh = new THREE38__namespace.Mesh(geometry, material);
3231
+ const geometry = new THREE39__namespace.CapsuleGeometry(0.5, 1, 4, 8);
3232
+ const material = new THREE39__namespace.MeshStandardMaterial({ color: "#ffffff" });
3233
+ const mesh = new THREE39__namespace.Mesh(geometry, material);
3192
3234
  const entityId = createBaseEntity(world, mesh, {
3193
3235
  label: payload.name ?? "Capsule",
3194
3236
  entityType: "capsule",
@@ -3208,9 +3250,9 @@ function createCapsule({
3208
3250
  }
3209
3251
  __name(createCapsule, "createCapsule");
3210
3252
  function createCube({ world, scene, payload }) {
3211
- const geometry = new THREE38__namespace.BoxGeometry(1, 1, 1);
3212
- const material = new THREE38__namespace.MeshStandardMaterial({ color: "#ffffff" });
3213
- const mesh = new THREE38__namespace.Mesh(geometry, material);
3253
+ const geometry = new THREE39__namespace.BoxGeometry(1, 1, 1);
3254
+ const material = new THREE39__namespace.MeshStandardMaterial({ color: "#ffffff" });
3255
+ const mesh = new THREE39__namespace.Mesh(geometry, material);
3214
3256
  const entityId = createBaseEntity(world, mesh, {
3215
3257
  label: payload.name ?? "Cube",
3216
3258
  entityType: "cube",
@@ -3235,9 +3277,9 @@ function createCylinder({
3235
3277
  scene,
3236
3278
  payload
3237
3279
  }) {
3238
- const geometry = new THREE38__namespace.CylinderGeometry(0.5, 0.5, 1, 20);
3239
- const material = new THREE38__namespace.MeshStandardMaterial({ color: "#ffffff" });
3240
- const mesh = new THREE38__namespace.Mesh(geometry, material);
3280
+ const geometry = new THREE39__namespace.CylinderGeometry(0.5, 0.5, 1, 20);
3281
+ const material = new THREE39__namespace.MeshStandardMaterial({ color: "#ffffff" });
3282
+ const mesh = new THREE39__namespace.Mesh(geometry, material);
3241
3283
  const entityId = createBaseEntity(world, mesh, {
3242
3284
  label: payload.name ?? "Cylinder",
3243
3285
  entityType: "cylinder",
@@ -3257,7 +3299,7 @@ function createCylinder({
3257
3299
  }
3258
3300
  __name(createCylinder, "createCylinder");
3259
3301
  function createEmpty({ world, scene, payload, isEditor }) {
3260
- const object = new THREE38__namespace.Group();
3302
+ const object = new THREE39__namespace.Group();
3261
3303
  const entityId = createBaseEntity(world, object, {
3262
3304
  label: payload.name ?? "Empty",
3263
3305
  entityType: "empty",
@@ -3268,7 +3310,7 @@ function createEmpty({ world, scene, payload, isEditor }) {
3268
3310
  }
3269
3311
  __name(createEmpty, "createEmpty");
3270
3312
  function createImage({ world, scene, payload }) {
3271
- const anchor = new THREE38__namespace.Object3D();
3313
+ const anchor = new THREE39__namespace.Object3D();
3272
3314
  const imagePath = payload.path ?? "";
3273
3315
  const entityId = createBaseEntity(world, anchor, {
3274
3316
  label: payload.name ?? "Image",
@@ -3281,7 +3323,7 @@ function createImage({ world, scene, payload }) {
3281
3323
  if (!imagePath) {
3282
3324
  return entityId;
3283
3325
  }
3284
- const loader = new THREE38__namespace.TextureLoader();
3326
+ const loader = new THREE39__namespace.TextureLoader();
3285
3327
  loader.load(
3286
3328
  imagePath,
3287
3329
  (texture) => {
@@ -3289,13 +3331,13 @@ function createImage({ world, scene, payload }) {
3289
3331
  texture.dispose();
3290
3332
  return;
3291
3333
  }
3292
- const material = new THREE38__namespace.MeshBasicMaterial({
3334
+ const material = new THREE39__namespace.MeshBasicMaterial({
3293
3335
  map: texture,
3294
3336
  transparent: true,
3295
- side: THREE38__namespace.DoubleSide
3337
+ side: THREE39__namespace.DoubleSide
3296
3338
  });
3297
- const geometry = new THREE38__namespace.PlaneGeometry(1, 1);
3298
- const plane = new THREE38__namespace.Mesh(geometry, material);
3339
+ const geometry = new THREE39__namespace.PlaneGeometry(1, 1);
3340
+ const plane = new THREE39__namespace.Mesh(geometry, material);
3299
3341
  plane.userData.entityId = entityId;
3300
3342
  const textureImage = texture.image;
3301
3343
  const width = textureImage?.width ?? 1;
@@ -3341,7 +3383,7 @@ function createImageTarget({
3341
3383
  payload,
3342
3384
  isEditor
3343
3385
  }) {
3344
- const anchor = new THREE38__namespace.Object3D();
3386
+ const anchor = new THREE39__namespace.Object3D();
3345
3387
  const imagePath = payload.path ?? "";
3346
3388
  const entityId = createBaseEntity(world, anchor, {
3347
3389
  label: payload.name ?? "Image Target",
@@ -3358,7 +3400,7 @@ function createImageTarget({
3358
3400
  if (!isEditor || !imagePath) {
3359
3401
  return entityId;
3360
3402
  }
3361
- const loader = new THREE38__namespace.TextureLoader();
3403
+ const loader = new THREE39__namespace.TextureLoader();
3362
3404
  loader.load(
3363
3405
  imagePath,
3364
3406
  (texture) => {
@@ -3366,13 +3408,13 @@ function createImageTarget({
3366
3408
  texture.dispose();
3367
3409
  return;
3368
3410
  }
3369
- const material = new THREE38__namespace.MeshBasicMaterial({
3411
+ const material = new THREE39__namespace.MeshBasicMaterial({
3370
3412
  map: texture,
3371
3413
  transparent: true,
3372
- side: THREE38__namespace.DoubleSide
3414
+ side: THREE39__namespace.DoubleSide
3373
3415
  });
3374
- const geometry = new THREE38__namespace.PlaneGeometry(1, 1);
3375
- const plane = new THREE38__namespace.Mesh(geometry, material);
3416
+ const geometry = new THREE39__namespace.PlaneGeometry(1, 1);
3417
+ const plane = new THREE39__namespace.Mesh(geometry, material);
3376
3418
  plane.userData.entityId = entityId;
3377
3419
  const textureImage = texture.image;
3378
3420
  const width = textureImage?.width ?? 1;
@@ -3423,7 +3465,7 @@ function createInstancedMesh({
3423
3465
  scene,
3424
3466
  payload
3425
3467
  }) {
3426
- const anchor = new THREE38__namespace.Object3D();
3468
+ const anchor = new THREE39__namespace.Object3D();
3427
3469
  const opts = payload.options ?? {};
3428
3470
  const meshKind = isInstancedMeshKind(opts.meshKind) ? opts.meshKind : "cube";
3429
3471
  const meshParameters = opts.meshParameters && typeof opts.meshParameters === "object" ? opts.meshParameters : void 0;
@@ -3494,7 +3536,7 @@ function createAmbientLight({
3494
3536
  scene,
3495
3537
  payload
3496
3538
  }) {
3497
- const light = new THREE38__namespace.AmbientLight("#ffffff", 0.6);
3539
+ const light = new THREE39__namespace.AmbientLight("#ffffff", 0.6);
3498
3540
  const entityId = createBaseEntity(world, light, {
3499
3541
  label: payload.name ?? "Ambient Light",
3500
3542
  entityType: "ambientLight",
@@ -3511,7 +3553,7 @@ function createAreaLight({
3511
3553
  payload,
3512
3554
  isEditor
3513
3555
  }) {
3514
- const light = new THREE38__namespace.RectAreaLight("#ffffff", 5, 4, 4);
3556
+ const light = new THREE39__namespace.RectAreaLight("#ffffff", 5, 4, 4);
3515
3557
  light.lookAt(0, 0, 0);
3516
3558
  const entityId = createBaseEntity(world, light, {
3517
3559
  label: payload.name ?? "Area Light",
@@ -3540,7 +3582,7 @@ function createDirectionalLight({
3540
3582
  payload,
3541
3583
  isEditor
3542
3584
  }) {
3543
- const light = new THREE38__namespace.DirectionalLight("#ffffff", 1.5);
3585
+ const light = new THREE39__namespace.DirectionalLight("#ffffff", 1.5);
3544
3586
  light.castShadow = true;
3545
3587
  const entityId = createBaseEntity(world, light, {
3546
3588
  label: payload.name ?? "Directional Light",
@@ -3551,7 +3593,7 @@ function createDirectionalLight({
3551
3593
  });
3552
3594
  createLightComponent(world, entityId, light);
3553
3595
  if (isEditor) {
3554
- const helper = new THREE38__namespace.DirectionalLightHelper(light, 1.8, "#38bdf8");
3596
+ const helper = new THREE39__namespace.DirectionalLightHelper(light, 1.8, "#38bdf8");
3555
3597
  helper.onBeforeRender = () => {
3556
3598
  helper.update();
3557
3599
  };
@@ -3569,7 +3611,7 @@ function createPointLight({
3569
3611
  payload,
3570
3612
  isEditor
3571
3613
  }) {
3572
- const light = new THREE38__namespace.PointLight("#ffffff", 1, 10);
3614
+ const light = new THREE39__namespace.PointLight("#ffffff", 1, 10);
3573
3615
  const entityId = createBaseEntity(world, light, {
3574
3616
  label: payload.name ?? "Point Light",
3575
3617
  entityType: "pointLight",
@@ -3579,7 +3621,7 @@ function createPointLight({
3579
3621
  });
3580
3622
  createLightComponent(world, entityId, light);
3581
3623
  if (isEditor) {
3582
- const helper = new THREE38__namespace.PointLightHelper(light, 0.35, "#fbbf24");
3624
+ const helper = new THREE39__namespace.PointLightHelper(light, 0.35, "#fbbf24");
3583
3625
  helper.onBeforeRender = () => {
3584
3626
  helper.update();
3585
3627
  };
@@ -3597,7 +3639,7 @@ function createSpotLight({
3597
3639
  payload,
3598
3640
  isEditor
3599
3641
  }) {
3600
- const light = new THREE38__namespace.SpotLight("#ffffff", 1, 20, Math.PI / 6, 0.1, 1);
3642
+ const light = new THREE39__namespace.SpotLight("#ffffff", 1, 20, Math.PI / 6, 0.1, 1);
3601
3643
  const entityId = createBaseEntity(world, light, {
3602
3644
  label: payload.name ?? "Spot Light",
3603
3645
  entityType: "spotLight",
@@ -3607,7 +3649,7 @@ function createSpotLight({
3607
3649
  });
3608
3650
  createLightComponent(world, entityId, light);
3609
3651
  if (isEditor) {
3610
- const helper = new THREE38__namespace.SpotLightHelper(light, "#f59e0b");
3652
+ const helper = new THREE39__namespace.SpotLightHelper(light, "#f59e0b");
3611
3653
  helper.onBeforeRender = () => {
3612
3654
  helper.update();
3613
3655
  };
@@ -3693,6 +3735,8 @@ __export(components_exports, {
3693
3735
  VRTeleportAreaComponent: () => VRTeleportAreaComponent,
3694
3736
  VideoComponent: () => VideoComponent,
3695
3737
  XRInteractableComponent: () => XRInteractableComponent,
3738
+ XRInteractorComponent: () => XRInteractorComponent,
3739
+ XRInteractorSideComponent: () => XRInteractorSideComponent,
3696
3740
  XRRigComponent: () => XRRigComponent,
3697
3741
  defaultMaterialValue: () => defaultMaterialValue,
3698
3742
  normalizePhysicsState: () => normalizePhysicsState,
@@ -3752,7 +3796,7 @@ function createModel({
3752
3796
  payload,
3753
3797
  isEditor
3754
3798
  }) {
3755
- const anchor = new THREE38__namespace.Object3D();
3799
+ const anchor = new THREE39__namespace.Object3D();
3756
3800
  const modelPath = payload.path ?? "";
3757
3801
  const entityId = createBaseEntity(world, anchor, {
3758
3802
  label: payload.name ?? "Model",
@@ -3818,12 +3862,12 @@ function createModel({
3818
3862
  }
3819
3863
  __name(createModel, "createModel");
3820
3864
  function createPlane({ world, scene, payload }) {
3821
- const geometry = new THREE38__namespace.PlaneGeometry(100, 100);
3822
- const material = new THREE38__namespace.MeshStandardMaterial({
3865
+ const geometry = new THREE39__namespace.PlaneGeometry(100, 100);
3866
+ const material = new THREE39__namespace.MeshStandardMaterial({
3823
3867
  color: "#ffffff",
3824
- side: THREE38__namespace.DoubleSide
3868
+ side: THREE39__namespace.DoubleSide
3825
3869
  });
3826
- const mesh = new THREE38__namespace.Mesh(geometry, material);
3870
+ const mesh = new THREE39__namespace.Mesh(geometry, material);
3827
3871
  const entityId = createBaseEntity(
3828
3872
  world,
3829
3873
  mesh,
@@ -3859,7 +3903,7 @@ function createScriptObject({
3859
3903
  scene,
3860
3904
  payload
3861
3905
  }) {
3862
- const object = new THREE38__namespace.Group();
3906
+ const object = new THREE39__namespace.Group();
3863
3907
  const entityId = createBaseEntity(world, object, {
3864
3908
  label: payload.name ?? "Script Object",
3865
3909
  entityType: "scriptObject",
@@ -3884,15 +3928,15 @@ function createTeleportArea({
3884
3928
  const options = payload.options ?? {};
3885
3929
  const width = typeof options.width === "number" ? options.width : 10;
3886
3930
  const depth = typeof options.depth === "number" ? options.depth : 10;
3887
- const geometry = new THREE38__namespace.PlaneGeometry(width, depth);
3888
- const material = new THREE38__namespace.MeshBasicMaterial({
3931
+ const geometry = new THREE39__namespace.PlaneGeometry(width, depth);
3932
+ const material = new THREE39__namespace.MeshBasicMaterial({
3889
3933
  color: "#4da3ff",
3890
3934
  transparent: true,
3891
3935
  opacity: 0.18,
3892
- side: THREE38__namespace.DoubleSide,
3936
+ side: THREE39__namespace.DoubleSide,
3893
3937
  depthWrite: false
3894
3938
  });
3895
- const object = new THREE38__namespace.Mesh(geometry, material);
3939
+ const object = new THREE39__namespace.Mesh(geometry, material);
3896
3940
  const entityId = createBaseEntity(world, object, {
3897
3941
  label: payload.name ?? "Teleport Area",
3898
3942
  entityType: "teleportArea",
@@ -3915,12 +3959,40 @@ function createTeleportArea({
3915
3959
  return entityId;
3916
3960
  }
3917
3961
  __name(createTeleportArea, "createTeleportArea");
3962
+ function createXRInteractor({
3963
+ world,
3964
+ scene,
3965
+ payload
3966
+ }) {
3967
+ const root = new THREE39__namespace.Group();
3968
+ const options = payload.options ?? {};
3969
+ const entityId = createBaseEntity(world, root, {
3970
+ label: payload.name ?? "XR Interactor",
3971
+ entityType: "xrInteractor",
3972
+ transformInput: payload.transform
3973
+ });
3974
+ world.addComponent(entityId, new XRInteractorComponent(options));
3975
+ scene.add(root);
3976
+ for (const side of ["left", "right"]) {
3977
+ const slot = new THREE39__namespace.Group();
3978
+ const label = side === "left" ? "Left Interactor" : "Right Interactor";
3979
+ const slotEntityId = createBaseEntity(world, slot, {
3980
+ label,
3981
+ entityType: "empty",
3982
+ parentId: entityId
3983
+ });
3984
+ world.addComponent(slotEntityId, new XRInteractorSideComponent({ side }));
3985
+ scene.add(slot);
3986
+ }
3987
+ return entityId;
3988
+ }
3989
+ __name(createXRInteractor, "createXRInteractor");
3918
3990
  function createXRRig({
3919
3991
  world,
3920
3992
  scene,
3921
3993
  payload
3922
3994
  }) {
3923
- const object = new THREE38__namespace.Group();
3995
+ const object = new THREE39__namespace.Group();
3924
3996
  const entityId = createBaseEntity(world, object, {
3925
3997
  label: payload.name ?? "XR Rig",
3926
3998
  entityType: "xrRig",
@@ -3933,7 +4005,7 @@ function createXRRig({
3933
4005
  }
3934
4006
  __name(createXRRig, "createXRRig");
3935
4007
  function createSprite({ world, scene, payload }) {
3936
- const anchor = new THREE38__namespace.Object3D();
4008
+ const anchor = new THREE39__namespace.Object3D();
3937
4009
  const imagePath = payload.path ?? "";
3938
4010
  const entityId = createBaseEntity(world, anchor, {
3939
4011
  label: payload.name ?? "Sprite",
@@ -3945,7 +4017,7 @@ function createSprite({ world, scene, payload }) {
3945
4017
  if (!imagePath) {
3946
4018
  return entityId;
3947
4019
  }
3948
- const loader = new THREE38__namespace.TextureLoader();
4020
+ const loader = new THREE39__namespace.TextureLoader();
3949
4021
  loader.load(
3950
4022
  imagePath,
3951
4023
  (texture) => {
@@ -3953,11 +4025,11 @@ function createSprite({ world, scene, payload }) {
3953
4025
  texture.dispose();
3954
4026
  return;
3955
4027
  }
3956
- const material = new THREE38__namespace.SpriteMaterial({
4028
+ const material = new THREE39__namespace.SpriteMaterial({
3957
4029
  map: texture,
3958
4030
  transparent: true
3959
4031
  });
3960
- const sprite = new THREE38__namespace.Sprite(material);
4032
+ const sprite = new THREE39__namespace.Sprite(material);
3961
4033
  sprite.userData.entityId = entityId;
3962
4034
  const textureImage = texture.image;
3963
4035
  spriteComponent.width = textureImage?.width ?? 1;
@@ -3975,9 +4047,9 @@ function createSprite({ world, scene, payload }) {
3975
4047
  }
3976
4048
  __name(createSprite, "createSprite");
3977
4049
  function createSphere({ world, scene, payload }) {
3978
- const geometry = new THREE38__namespace.SphereGeometry(0.5, 24, 24);
3979
- const material = new THREE38__namespace.MeshStandardMaterial({ color: "#ffffff" });
3980
- const mesh = new THREE38__namespace.Mesh(geometry, material);
4050
+ const geometry = new THREE39__namespace.SphereGeometry(0.5, 24, 24);
4051
+ const material = new THREE39__namespace.MeshStandardMaterial({ color: "#ffffff" });
4052
+ const mesh = new THREE39__namespace.Mesh(geometry, material);
3981
4053
  const entityId = createBaseEntity(world, mesh, {
3982
4054
  label: payload.name ?? "Sphere",
3983
4055
  entityType: "sphere",
@@ -3997,10 +4069,10 @@ function createSphere({ world, scene, payload }) {
3997
4069
  __name(createSphere, "createSphere");
3998
4070
  function getOrCreateListener2(camera) {
3999
4071
  const existing = camera.userData.ecsAudioListener;
4000
- if (existing instanceof THREE38__namespace.AudioListener) {
4072
+ if (existing instanceof THREE39__namespace.AudioListener) {
4001
4073
  return existing;
4002
4074
  }
4003
- const listener = new THREE38__namespace.AudioListener();
4075
+ const listener = new THREE39__namespace.AudioListener();
4004
4076
  camera.add(listener);
4005
4077
  camera.userData.ecsAudioListener = listener;
4006
4078
  return listener;
@@ -4050,10 +4122,10 @@ function normalizeOptions(input) {
4050
4122
  }
4051
4123
  __name(normalizeOptions, "normalizeOptions");
4052
4124
  function createChromaMaterial(texture, options) {
4053
- return new THREE38__namespace.ShaderMaterial({
4125
+ return new THREE39__namespace.ShaderMaterial({
4054
4126
  uniforms: {
4055
4127
  tex: { value: texture },
4056
- keyColor: { value: new THREE38__namespace.Color(options.backgroundColor) },
4128
+ keyColor: { value: new THREE39__namespace.Color(options.backgroundColor) },
4057
4129
  similarity: { value: options.similarity },
4058
4130
  smoothness: { value: options.smoothness },
4059
4131
  spill: { value: options.spill }
@@ -4085,22 +4157,22 @@ function createChromaMaterial(texture, options) {
4085
4157
  }
4086
4158
  `,
4087
4159
  transparent: true,
4088
- side: THREE38__namespace.DoubleSide
4160
+ side: THREE39__namespace.DoubleSide
4089
4161
  });
4090
4162
  }
4091
4163
  __name(createChromaMaterial, "createChromaMaterial");
4092
4164
  function createStandardMaterial(texture) {
4093
- return new THREE38__namespace.MeshBasicMaterial({
4165
+ return new THREE39__namespace.MeshBasicMaterial({
4094
4166
  map: texture,
4095
4167
  transparent: true,
4096
- side: THREE38__namespace.DoubleSide
4168
+ side: THREE39__namespace.DoubleSide
4097
4169
  });
4098
4170
  }
4099
4171
  __name(createStandardMaterial, "createStandardMaterial");
4100
4172
  function createVideoMesh(entityId, texture, options) {
4101
- const geometry = new THREE38__namespace.PlaneGeometry(1, 1);
4173
+ const geometry = new THREE39__namespace.PlaneGeometry(1, 1);
4102
4174
  const material = options.isGreenScreen ? createChromaMaterial(texture, options) : createStandardMaterial(texture);
4103
- const mesh = new THREE38__namespace.Mesh(geometry, material);
4175
+ const mesh = new THREE39__namespace.Mesh(geometry, material);
4104
4176
  mesh.userData.entityId = entityId;
4105
4177
  mesh.scale.set(options.width, options.height, 1);
4106
4178
  return { mesh, material };
@@ -4135,7 +4207,7 @@ function createVideo({
4135
4207
  payload,
4136
4208
  isEditor
4137
4209
  }) {
4138
- const anchor = new THREE38__namespace.Object3D();
4210
+ const anchor = new THREE39__namespace.Object3D();
4139
4211
  const path = payload.path ?? "";
4140
4212
  const options = normalizeOptions(payload.options);
4141
4213
  const entityId = createBaseEntity(world, anchor, {
@@ -4150,8 +4222,8 @@ function createVideo({
4150
4222
  return entityId;
4151
4223
  }
4152
4224
  const video = createVideoElement(path, options);
4153
- const texture = new THREE38__namespace.VideoTexture(video);
4154
- texture.colorSpace = THREE38__namespace.SRGBColorSpace;
4225
+ const texture = new THREE39__namespace.VideoTexture(video);
4226
+ texture.colorSpace = THREE39__namespace.SRGBColorSpace;
4155
4227
  texture.needsUpdate = true;
4156
4228
  const { mesh, material } = createVideoMesh(entityId, texture, options);
4157
4229
  anchor.add(mesh);
@@ -4167,7 +4239,7 @@ function createVideo({
4167
4239
  });
4168
4240
  if (!isEditor && options.positional) {
4169
4241
  const listener = getOrCreateListener2(camera);
4170
- const audioNode = new THREE38__namespace.PositionalAudio(listener);
4242
+ const audioNode = new THREE39__namespace.PositionalAudio(listener);
4171
4243
  audioNode.setVolume(options.volume);
4172
4244
  audioNode.setRefDistance(options.refDistance);
4173
4245
  audioNode.setDistanceModel(normalizeDistanceModel2(options.distanceModel));
@@ -4208,6 +4280,7 @@ function registerDefaultFactories(objectManagementSystem) {
4208
4280
  objectManagementSystem.register("areaLight", createAreaLight);
4209
4281
  objectManagementSystem.register("scriptObject", createScriptObject);
4210
4282
  objectManagementSystem.register("xrRig", createXRRig);
4283
+ objectManagementSystem.register("xrInteractor", createXRInteractor);
4211
4284
  objectManagementSystem.register("teleportArea", createTeleportArea);
4212
4285
  registerDefaultComponentFactories(objectManagementSystem);
4213
4286
  }
@@ -4350,6 +4423,14 @@ function buildComponentValueMaps(snapshot) {
4350
4423
  snapshot.components,
4351
4424
  "XRInteractableComponent"
4352
4425
  ),
4426
+ xrInteractorValues: readByComponent(
4427
+ snapshot.components,
4428
+ "XRInteractorComponent"
4429
+ ),
4430
+ xrInteractorSideValues: readByComponent(
4431
+ snapshot.components,
4432
+ "XRInteractorSideComponent"
4433
+ ),
4353
4434
  instancedMeshValues: readByComponent(snapshot.components, "InstancedMeshComponent"),
4354
4435
  instanceSlotValues: readByComponent(snapshot.components, "InstanceSlotComponent"),
4355
4436
  prefabNodeValues: readByComponent(snapshot.components, "PrefabNode"),
@@ -4536,6 +4617,60 @@ function restorePostCreateComponents(world, objectManagementSystem, targetEntity
4536
4617
  }
4537
4618
  }
4538
4619
  }
4620
+ {
4621
+ const sourceInteractor = asRecord3(
4622
+ values.xrInteractorValues.get(sourceEntityId)
4623
+ );
4624
+ const interactor = world.getComponent(targetEntityId, XRInteractorComponent);
4625
+ if (sourceInteractor && interactor) {
4626
+ if (typeof sourceInteractor.interactorType === "string") {
4627
+ interactor.interactorType = sourceInteractor.interactorType;
4628
+ }
4629
+ if (typeof sourceInteractor.handPreset === "string") {
4630
+ interactor.handPreset = sourceInteractor.handPreset;
4631
+ }
4632
+ if (typeof sourceInteractor.handColor === "string") {
4633
+ interactor.handColor = sourceInteractor.handColor;
4634
+ }
4635
+ if (typeof sourceInteractor.handOpacity === "number") {
4636
+ interactor.handOpacity = sourceInteractor.handOpacity;
4637
+ }
4638
+ if (typeof sourceInteractor.handEmissiveIntensity === "number") {
4639
+ interactor.handEmissiveIntensity = sourceInteractor.handEmissiveIntensity;
4640
+ }
4641
+ if (typeof sourceInteractor.showRay === "boolean") {
4642
+ interactor.showRay = sourceInteractor.showRay;
4643
+ }
4644
+ }
4645
+ }
4646
+ {
4647
+ const sourceSide = asRecord3(
4648
+ values.xrInteractorSideValues.get(sourceEntityId)
4649
+ );
4650
+ if (sourceSide && typeof sourceSide.side === "string") {
4651
+ const existing = world.getComponent(
4652
+ targetEntityId,
4653
+ XRInteractorSideComponent
4654
+ );
4655
+ if (existing) {
4656
+ existing.side = sourceSide.side;
4657
+ } else {
4658
+ world.addComponent(
4659
+ targetEntityId,
4660
+ new XRInteractorSideComponent({
4661
+ side: sourceSide.side
4662
+ })
4663
+ );
4664
+ }
4665
+ }
4666
+ }
4667
+ {
4668
+ const sourceRigOrigin = asRecord3(values.xrRigValues.get(sourceEntityId));
4669
+ const rigForOrigin = world.getComponent(targetEntityId, XRRigComponent);
4670
+ if (sourceRigOrigin && rigForOrigin && typeof sourceRigOrigin.trackingOrigin === "string") {
4671
+ rigForOrigin.trackingOrigin = sourceRigOrigin.trackingOrigin;
4672
+ }
4673
+ }
4539
4674
  {
4540
4675
  const imComponent = world.getComponent(targetEntityId, InstancedMeshComponent);
4541
4676
  if (imComponent && imComponent.instanceEntityIds.length > 0) {
@@ -5125,6 +5260,7 @@ var HYDRATABLE_ENTITY_KINDS = /* @__PURE__ */ new Set([
5125
5260
  "instanceSlot",
5126
5261
  "scriptObject",
5127
5262
  "xrRig",
5263
+ "xrInteractor",
5128
5264
  "teleportArea"
5129
5265
  ]);
5130
5266
 
@@ -6229,7 +6365,7 @@ function transitionToClip(runtime, nextClipId, crossFadeDuration) {
6229
6365
  }
6230
6366
  __name(transitionToClip, "transitionToClip");
6231
6367
  function applyActionState(action, component, paused, shouldLoop) {
6232
- const loopMode = shouldLoop ? THREE38__namespace.LoopRepeat : THREE38__namespace.LoopOnce;
6368
+ const loopMode = shouldLoop ? THREE39__namespace.LoopRepeat : THREE39__namespace.LoopOnce;
6233
6369
  const repetitions = shouldLoop ? Infinity : 1;
6234
6370
  action.setLoop(loopMode, repetitions);
6235
6371
  action.clampWhenFinished = !shouldLoop;
@@ -6402,7 +6538,7 @@ var _AnimationSystem = class _AnimationSystem {
6402
6538
  if (runtime) {
6403
6539
  stopAllActions(runtime);
6404
6540
  }
6405
- const mixer = new THREE38__namespace.AnimationMixer(root);
6541
+ const mixer = new THREE39__namespace.AnimationMixer(root);
6406
6542
  const entries2 = readRuntimeClipEntries(animation);
6407
6543
  const indexedActions = createActions(mixer, entries2);
6408
6544
  runtime = {
@@ -6528,11 +6664,11 @@ function normalizeOrthoBounds(component) {
6528
6664
  }
6529
6665
  __name(normalizeOrthoBounds, "normalizeOrthoBounds");
6530
6666
  function isPerspectiveCamera(camera) {
6531
- return camera instanceof THREE38__namespace.PerspectiveCamera;
6667
+ return camera instanceof THREE39__namespace.PerspectiveCamera;
6532
6668
  }
6533
6669
  __name(isPerspectiveCamera, "isPerspectiveCamera");
6534
6670
  function isOrthographicCamera(camera) {
6535
- return camera instanceof THREE38__namespace.OrthographicCamera;
6671
+ return camera instanceof THREE39__namespace.OrthographicCamera;
6536
6672
  }
6537
6673
  __name(isOrthographicCamera, "isOrthographicCamera");
6538
6674
  function readWindowAspect() {
@@ -6586,7 +6722,7 @@ var _CameraSyncSystem = class _CameraSyncSystem {
6586
6722
  continue;
6587
6723
  }
6588
6724
  const camera = objectRef.object;
6589
- if (!(camera instanceof THREE38__namespace.Camera)) {
6725
+ if (!(camera instanceof THREE39__namespace.Camera)) {
6590
6726
  continue;
6591
6727
  }
6592
6728
  if (xrCamera !== null && camera === xrCamera) {
@@ -6653,7 +6789,7 @@ var MIN_DENSITY = 0;
6653
6789
  function createGradientTexture(effect, colors) {
6654
6790
  if (typeof document === "undefined") {
6655
6791
  const pixel = new Uint8Array([30, 30, 30, 255]);
6656
- const fallback = new THREE38__namespace.DataTexture(pixel, 1, 1, THREE38__namespace.RGBAFormat);
6792
+ const fallback = new THREE39__namespace.DataTexture(pixel, 1, 1, THREE39__namespace.RGBAFormat);
6657
6793
  fallback.needsUpdate = true;
6658
6794
  return fallback;
6659
6795
  }
@@ -6662,7 +6798,7 @@ function createGradientTexture(effect, colors) {
6662
6798
  canvas.height = 512;
6663
6799
  const context = canvas.getContext("2d");
6664
6800
  if (!context) {
6665
- const fallback = new THREE38__namespace.CanvasTexture(canvas);
6801
+ const fallback = new THREE39__namespace.CanvasTexture(canvas);
6666
6802
  fallback.needsUpdate = true;
6667
6803
  return fallback;
6668
6804
  }
@@ -6690,15 +6826,15 @@ function createGradientTexture(effect, colors) {
6690
6826
  context.fillRect(0, 0, 512, 512);
6691
6827
  context.globalCompositeOperation = "source-over";
6692
6828
  }
6693
- const texture = new THREE38__namespace.CanvasTexture(canvas);
6694
- texture.colorSpace = THREE38__namespace.SRGBColorSpace;
6829
+ const texture = new THREE39__namespace.CanvasTexture(canvas);
6830
+ texture.colorSpace = THREE39__namespace.SRGBColorSpace;
6695
6831
  texture.needsUpdate = true;
6696
6832
  return texture;
6697
6833
  }
6698
6834
  __name(createGradientTexture, "createGradientTexture");
6699
6835
  var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
6700
6836
  constructor(scene) {
6701
- this.textureLoader = new THREE38__namespace.TextureLoader();
6837
+ this.textureLoader = new THREE39__namespace.TextureLoader();
6702
6838
  this.signature = null;
6703
6839
  this.activeTexture = null;
6704
6840
  this.pendingImageUrl = null;
@@ -6721,7 +6857,7 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
6721
6857
  if (skybox.type === "color") {
6722
6858
  this.disposeActiveTexture();
6723
6859
  this.pendingImageUrl = null;
6724
- this.scene.background = new THREE38__namespace.Color(skybox.color || "#1e1e1e");
6860
+ this.scene.background = new THREE39__namespace.Color(skybox.color || "#1e1e1e");
6725
6861
  return;
6726
6862
  }
6727
6863
  if (skybox.type === "gradient") {
@@ -6755,7 +6891,7 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
6755
6891
  texture.dispose();
6756
6892
  return;
6757
6893
  }
6758
- texture.colorSpace = THREE38__namespace.SRGBColorSpace;
6894
+ texture.colorSpace = THREE39__namespace.SRGBColorSpace;
6759
6895
  this.activeTexture = texture;
6760
6896
  this.scene.background = texture;
6761
6897
  },
@@ -6774,16 +6910,16 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
6774
6910
  this.scene.fog = null;
6775
6911
  return;
6776
6912
  }
6777
- const fogColor = new THREE38__namespace.Color(fog.color || "#1e1e1e");
6913
+ const fogColor = new THREE39__namespace.Color(fog.color || "#1e1e1e");
6778
6914
  if (fog.type === "linear") {
6779
6915
  const near = Number.isFinite(fog.linear.near) ? fog.linear.near : 1;
6780
6916
  const farCandidate = Number.isFinite(fog.linear.far) ? fog.linear.far : near + 10;
6781
6917
  const far = Math.max(near + MIN_FOG_DELTA, farCandidate);
6782
- this.scene.fog = new THREE38__namespace.Fog(fogColor, near, far);
6918
+ this.scene.fog = new THREE39__namespace.Fog(fogColor, near, far);
6783
6919
  return;
6784
6920
  }
6785
6921
  const density = Number.isFinite(fog.exponential.density) ? Math.max(MIN_DENSITY, fog.exponential.density) : 2e-3;
6786
- this.scene.fog = new THREE38__namespace.FogExp2(fogColor, density);
6922
+ this.scene.fog = new THREE39__namespace.FogExp2(fogColor, density);
6787
6923
  }
6788
6924
  update(world) {
6789
6925
  const entityIds = world.query(Environment);
@@ -6865,10 +7001,10 @@ var _PostprocessingSyncSystem = class _PostprocessingSyncSystem {
6865
7001
  );
6866
7002
  }
6867
7003
  if (values.bloom.enabled) {
6868
- const size = this.renderer.getSize(new THREE38__namespace.Vector2());
7004
+ const size = this.renderer.getSize(new THREE39__namespace.Vector2());
6869
7005
  composer.addPass(
6870
7006
  new UnrealBloomPass_js.UnrealBloomPass(
6871
- new THREE38__namespace.Vector2(size.width, size.height),
7007
+ new THREE39__namespace.Vector2(size.width, size.height),
6872
7008
  values.bloom.intensity,
6873
7009
  values.bloom.radius,
6874
7010
  values.bloom.threshold
@@ -6913,7 +7049,7 @@ var _PostprocessingSyncSystem = class _PostprocessingSyncSystem {
6913
7049
  if (values.dotScreen.enabled) {
6914
7050
  composer.addPass(
6915
7051
  new DotScreenPass_js.DotScreenPass(
6916
- new THREE38__namespace.Vector2(0, 0),
7052
+ new THREE39__namespace.Vector2(0, 0),
6917
7053
  values.dotScreen.angle ?? values.dotScreen.dotScreenAngle,
6918
7054
  values.dotScreen.scale ?? values.dotScreen.dotScreenScale
6919
7055
  )
@@ -6987,7 +7123,7 @@ function computeColliderState(colliderValues, object) {
6987
7123
  if (!object) {
6988
7124
  return colliderValues;
6989
7125
  }
6990
- const scale = new THREE38__namespace.Vector3();
7126
+ const scale = new THREE39__namespace.Vector3();
6991
7127
  object.getWorldScale(scale);
6992
7128
  return {
6993
7129
  ...colliderValues,
@@ -7038,8 +7174,8 @@ function createColliderDesc(RAPIER, values, triMeshData) {
7038
7174
  values.offsetPosition.y,
7039
7175
  values.offsetPosition.z
7040
7176
  );
7041
- const offsetQuaternion = new THREE38__namespace.Quaternion().setFromEuler(
7042
- new THREE38__namespace.Euler(
7177
+ const offsetQuaternion = new THREE39__namespace.Quaternion().setFromEuler(
7178
+ new THREE39__namespace.Euler(
7043
7179
  values.offsetRotation.x,
7044
7180
  values.offsetRotation.y,
7045
7181
  values.offsetRotation.z
@@ -7054,17 +7190,17 @@ function collectTriMeshParts(object) {
7054
7190
  return null;
7055
7191
  }
7056
7192
  object.updateWorldMatrix(true, true);
7057
- const worldScale = new THREE38__namespace.Vector3();
7193
+ const worldScale = new THREE39__namespace.Vector3();
7058
7194
  object.getWorldScale(worldScale);
7059
7195
  const scale = {
7060
7196
  x: Math.abs(worldScale.x) || 1,
7061
7197
  y: Math.abs(worldScale.y) || 1,
7062
7198
  z: Math.abs(worldScale.z) || 1
7063
7199
  };
7064
- const worldToObject = new THREE38__namespace.Matrix4().copy(object.matrixWorld).invert();
7200
+ const worldToObject = new THREE39__namespace.Matrix4().copy(object.matrixWorld).invert();
7065
7201
  const parts = [];
7066
7202
  object.traverse((child) => {
7067
- if (!(child instanceof THREE38__namespace.Mesh) || !child.geometry) {
7203
+ if (!(child instanceof THREE39__namespace.Mesh) || !child.geometry) {
7068
7204
  return;
7069
7205
  }
7070
7206
  const geometry = child.geometry;
@@ -7081,7 +7217,7 @@ function collectTriMeshParts(object) {
7081
7217
  if (indexCount < 3) {
7082
7218
  return;
7083
7219
  }
7084
- const relativeMatrix = new THREE38__namespace.Matrix4().multiplyMatrices(
7220
+ const relativeMatrix = new THREE39__namespace.Matrix4().multiplyMatrices(
7085
7221
  worldToObject,
7086
7222
  child.matrixWorld
7087
7223
  );
@@ -7122,7 +7258,7 @@ function createTriMeshData(collected) {
7122
7258
  }
7123
7259
  const vertices = new Float32Array(vertexTotal * 3);
7124
7260
  const indices = new Uint32Array(indexTotal);
7125
- const point = new THREE38__namespace.Vector3();
7261
+ const point = new THREE39__namespace.Vector3();
7126
7262
  let vertexOffset = 0;
7127
7263
  let indexOffset = 0;
7128
7264
  for (const part of parts) {
@@ -7154,8 +7290,8 @@ function createTriMeshData(collected) {
7154
7290
  }
7155
7291
  __name(createTriMeshData, "createTriMeshData");
7156
7292
  function syncBodyFromTransform(body, transform) {
7157
- const quaternion = new THREE38__namespace.Quaternion().setFromEuler(
7158
- new THREE38__namespace.Euler(transform.rotation.x, transform.rotation.y, transform.rotation.z)
7293
+ const quaternion = new THREE39__namespace.Quaternion().setFromEuler(
7294
+ new THREE39__namespace.Euler(transform.rotation.x, transform.rotation.y, transform.rotation.z)
7159
7295
  );
7160
7296
  body.setTranslation(
7161
7297
  {
@@ -7182,8 +7318,8 @@ function syncTransformFromBody(transform, body) {
7182
7318
  transform.position.x = position.x;
7183
7319
  transform.position.y = position.y;
7184
7320
  transform.position.z = position.z;
7185
- const euler = new THREE38__namespace.Euler().setFromQuaternion(
7186
- new THREE38__namespace.Quaternion(rotation.x, rotation.y, rotation.z, rotation.w)
7321
+ const euler = new THREE39__namespace.Euler().setFromQuaternion(
7322
+ new THREE39__namespace.Quaternion(rotation.x, rotation.y, rotation.z, rotation.w)
7187
7323
  );
7188
7324
  transform.rotation.x = euler.x;
7189
7325
  transform.rotation.y = euler.y;
@@ -7295,8 +7431,8 @@ var _PhysicsSyncSystem = class _PhysicsSyncSystem {
7295
7431
  transform.position.y,
7296
7432
  transform.position.z
7297
7433
  );
7298
- const quaternion = new THREE38__namespace.Quaternion().setFromEuler(
7299
- new THREE38__namespace.Euler(
7434
+ const quaternion = new THREE39__namespace.Quaternion().setFromEuler(
7435
+ new THREE39__namespace.Euler(
7300
7436
  transform.rotation.x,
7301
7437
  transform.rotation.y,
7302
7438
  transform.rotation.z
@@ -7875,7 +8011,7 @@ function applyLightValues(lightComponent) {
7875
8011
  values.castShadow
7876
8012
  );
7877
8013
  }
7878
- if (light instanceof THREE38__namespace.PointLight) {
8014
+ if (light instanceof THREE39__namespace.PointLight) {
7879
8015
  if (typeof values.distance === "number" && Number.isFinite(values.distance)) {
7880
8016
  light.distance = Math.max(MIN_LIGHT_DISTANCE, values.distance);
7881
8017
  }
@@ -7883,7 +8019,7 @@ function applyLightValues(lightComponent) {
7883
8019
  light.decay = Math.max(0, values.decay);
7884
8020
  }
7885
8021
  }
7886
- if (light instanceof THREE38__namespace.SpotLight) {
8022
+ if (light instanceof THREE39__namespace.SpotLight) {
7887
8023
  if (typeof values.distance === "number" && Number.isFinite(values.distance)) {
7888
8024
  light.distance = Math.max(MIN_LIGHT_DISTANCE, values.distance);
7889
8025
  }
@@ -7897,7 +8033,7 @@ function applyLightValues(lightComponent) {
7897
8033
  light.penumbra = Math.max(0, Math.min(1, values.penumbra));
7898
8034
  }
7899
8035
  }
7900
- if (light instanceof THREE38__namespace.RectAreaLight) {
8036
+ if (light instanceof THREE39__namespace.RectAreaLight) {
7901
8037
  if (typeof values.width === "number" && Number.isFinite(values.width)) {
7902
8038
  light.width = Math.max(MIN_AREA_SIZE, values.width);
7903
8039
  }
@@ -7958,15 +8094,15 @@ function resolveMaterialPropertyKey(key) {
7958
8094
  __name(resolveMaterialPropertyKey, "resolveMaterialPropertyKey");
7959
8095
  function createMaterialByType(type) {
7960
8096
  if (type === "basic") {
7961
- return new THREE38__namespace.MeshBasicMaterial();
8097
+ return new THREE39__namespace.MeshBasicMaterial();
7962
8098
  }
7963
8099
  if (type === "phong") {
7964
- return new THREE38__namespace.MeshPhongMaterial();
8100
+ return new THREE39__namespace.MeshPhongMaterial();
7965
8101
  }
7966
8102
  if (type === "physical") {
7967
- return new THREE38__namespace.MeshPhysicalMaterial();
8103
+ return new THREE39__namespace.MeshPhysicalMaterial();
7968
8104
  }
7969
- return new THREE38__namespace.MeshStandardMaterial();
8105
+ return new THREE39__namespace.MeshStandardMaterial();
7970
8106
  }
7971
8107
  __name(createMaterialByType, "createMaterialByType");
7972
8108
  function replaceMaterialAcrossObject(object, previous, next) {
@@ -8025,12 +8161,12 @@ function applyTextureFiltering(material, filtering) {
8025
8161
  const target = material;
8026
8162
  for (const slot of materialTextureSlots) {
8027
8163
  const texture = target[slot];
8028
- if (!texture || !(texture instanceof THREE38__namespace.Texture)) {
8164
+ if (!texture || !(texture instanceof THREE39__namespace.Texture)) {
8029
8165
  continue;
8030
8166
  }
8031
8167
  const useMipmaps = texture.generateMipmaps !== false;
8032
- texture.magFilter = sharp ? THREE38__namespace.NearestFilter : THREE38__namespace.LinearFilter;
8033
- texture.minFilter = useMipmaps ? sharp ? THREE38__namespace.NearestMipmapNearestFilter : THREE38__namespace.LinearMipmapLinearFilter : sharp ? THREE38__namespace.NearestFilter : THREE38__namespace.LinearFilter;
8168
+ texture.magFilter = sharp ? THREE39__namespace.NearestFilter : THREE39__namespace.LinearFilter;
8169
+ texture.minFilter = useMipmaps ? sharp ? THREE39__namespace.NearestMipmapNearestFilter : THREE39__namespace.LinearMipmapLinearFilter : sharp ? THREE39__namespace.NearestFilter : THREE39__namespace.LinearFilter;
8034
8170
  texture.needsUpdate = true;
8035
8171
  }
8036
8172
  material.needsUpdate = true;
@@ -8040,12 +8176,12 @@ function setTextureMipmaps(material, enabled) {
8040
8176
  const target = material;
8041
8177
  for (const slot of materialTextureSlots) {
8042
8178
  const texture = target[slot];
8043
- if (!texture || !(texture instanceof THREE38__namespace.Texture)) {
8179
+ if (!texture || !(texture instanceof THREE39__namespace.Texture)) {
8044
8180
  continue;
8045
8181
  }
8046
8182
  texture.generateMipmaps = enabled;
8047
- const sharp = texture.magFilter === THREE38__namespace.NearestFilter;
8048
- texture.minFilter = enabled ? sharp ? THREE38__namespace.NearestMipmapNearestFilter : THREE38__namespace.LinearMipmapLinearFilter : sharp ? THREE38__namespace.NearestFilter : THREE38__namespace.LinearFilter;
8183
+ const sharp = texture.magFilter === THREE39__namespace.NearestFilter;
8184
+ texture.minFilter = enabled ? sharp ? THREE39__namespace.NearestMipmapNearestFilter : THREE39__namespace.LinearMipmapLinearFilter : sharp ? THREE39__namespace.NearestFilter : THREE39__namespace.LinearFilter;
8049
8185
  texture.needsUpdate = true;
8050
8186
  }
8051
8187
  material.needsUpdate = true;
@@ -8056,7 +8192,7 @@ function assignMaterialTexture(material, rawKey, url, textureCache) {
8056
8192
  const key = resolveMaterialPropertyKey(rawKey);
8057
8193
  let texture = textureCache.get(url);
8058
8194
  if (!texture) {
8059
- texture = new THREE38__namespace.TextureLoader().load(url);
8195
+ texture = new THREE39__namespace.TextureLoader().load(url);
8060
8196
  textureCache.set(url, texture);
8061
8197
  }
8062
8198
  target[key] = texture;
@@ -8094,7 +8230,7 @@ function applyMaterialState(material, value, textureCache) {
8094
8230
  }
8095
8231
  target.side = value.side;
8096
8232
  target.blending = value.blending;
8097
- target.premultipliedAlpha = value.blending === THREE38__namespace.MultiplyBlending || value.blending === THREE38__namespace.SubtractiveBlending;
8233
+ target.premultipliedAlpha = value.blending === THREE39__namespace.MultiplyBlending || value.blending === THREE39__namespace.SubtractiveBlending;
8098
8234
  target.depthTest = value.depthTest;
8099
8235
  target.depthWrite = value.depthWrite;
8100
8236
  target.wireframe = value.wireframe;
@@ -8255,12 +8391,12 @@ function resolvePrimaryMesh(object) {
8255
8391
  if (!object) {
8256
8392
  return null;
8257
8393
  }
8258
- if (object instanceof THREE38__namespace.Mesh) {
8394
+ if (object instanceof THREE39__namespace.Mesh) {
8259
8395
  return object;
8260
8396
  }
8261
8397
  let found = null;
8262
8398
  object.traverse((child) => {
8263
- if (!found && child instanceof THREE38__namespace.Mesh) {
8399
+ if (!found && child instanceof THREE39__namespace.Mesh) {
8264
8400
  found = child;
8265
8401
  }
8266
8402
  });
@@ -8281,22 +8417,22 @@ function applyGeometry(component) {
8281
8417
  switch (component.kind) {
8282
8418
  case "cube": {
8283
8419
  const params = sanitized;
8284
- nextGeometry = new THREE38__namespace.BoxGeometry(params.width, params.height, params.depth);
8420
+ nextGeometry = new THREE39__namespace.BoxGeometry(params.width, params.height, params.depth);
8285
8421
  break;
8286
8422
  }
8287
8423
  case "plane": {
8288
8424
  const params = sanitized;
8289
- nextGeometry = new THREE38__namespace.PlaneGeometry(params.width, params.height);
8425
+ nextGeometry = new THREE39__namespace.PlaneGeometry(params.width, params.height);
8290
8426
  break;
8291
8427
  }
8292
8428
  case "sphere": {
8293
8429
  const params = sanitized;
8294
- nextGeometry = new THREE38__namespace.SphereGeometry(params.radius, 24, 24);
8430
+ nextGeometry = new THREE39__namespace.SphereGeometry(params.radius, 24, 24);
8295
8431
  break;
8296
8432
  }
8297
8433
  case "cylinder": {
8298
8434
  const params = sanitized;
8299
- nextGeometry = new THREE38__namespace.CylinderGeometry(
8435
+ nextGeometry = new THREE39__namespace.CylinderGeometry(
8300
8436
  params.radius,
8301
8437
  params.radius,
8302
8438
  params.height,
@@ -8306,7 +8442,7 @@ function applyGeometry(component) {
8306
8442
  }
8307
8443
  case "capsule": {
8308
8444
  const params = sanitized;
8309
- nextGeometry = new THREE38__namespace.CapsuleGeometry(params.radius, params.height, 4, 8);
8445
+ nextGeometry = new THREE39__namespace.CapsuleGeometry(params.radius, params.height, 4, 8);
8310
8446
  break;
8311
8447
  }
8312
8448
  default:
@@ -8322,7 +8458,7 @@ function applyShadowFlags(component) {
8322
8458
  return;
8323
8459
  }
8324
8460
  component.object.traverse((child) => {
8325
- if (child instanceof THREE38__namespace.Mesh) {
8461
+ if (child instanceof THREE39__namespace.Mesh) {
8326
8462
  child.castShadow = component.castShadow;
8327
8463
  child.receiveShadow = component.receiveShadow;
8328
8464
  }
@@ -8405,35 +8541,35 @@ function buildGeometry(component) {
8405
8541
  switch (component.meshKind) {
8406
8542
  case "cube": {
8407
8543
  const params = p;
8408
- return new THREE38__namespace.BoxGeometry(params.width, params.height, params.depth);
8544
+ return new THREE39__namespace.BoxGeometry(params.width, params.height, params.depth);
8409
8545
  }
8410
8546
  case "plane": {
8411
8547
  const params = p;
8412
- return new THREE38__namespace.PlaneGeometry(params.width, params.height);
8548
+ return new THREE39__namespace.PlaneGeometry(params.width, params.height);
8413
8549
  }
8414
8550
  case "sphere": {
8415
8551
  const params = p;
8416
- return new THREE38__namespace.SphereGeometry(params.radius, 24, 24);
8552
+ return new THREE39__namespace.SphereGeometry(params.radius, 24, 24);
8417
8553
  }
8418
8554
  case "cylinder": {
8419
8555
  const params = p;
8420
- return new THREE38__namespace.CylinderGeometry(params.radius, params.radius, params.height, 20);
8556
+ return new THREE39__namespace.CylinderGeometry(params.radius, params.radius, params.height, 20);
8421
8557
  }
8422
8558
  case "capsule": {
8423
8559
  const params = p;
8424
- return new THREE38__namespace.CapsuleGeometry(params.radius, params.height, 4, 8);
8560
+ return new THREE39__namespace.CapsuleGeometry(params.radius, params.height, 4, 8);
8425
8561
  }
8426
8562
  default:
8427
- return new THREE38__namespace.BoxGeometry(1, 1, 1);
8563
+ return new THREE39__namespace.BoxGeometry(1, 1, 1);
8428
8564
  }
8429
8565
  }
8430
8566
  __name(buildGeometry, "buildGeometry");
8431
- var _position = new THREE38__namespace.Vector3();
8432
- var _quaternion = new THREE38__namespace.Quaternion();
8433
- var _euler = new THREE38__namespace.Euler();
8434
- var _scale = new THREE38__namespace.Vector3();
8435
- var _matrix = new THREE38__namespace.Matrix4();
8436
- var _modelMatrix = new THREE38__namespace.Matrix4();
8567
+ var _position = new THREE39__namespace.Vector3();
8568
+ var _quaternion = new THREE39__namespace.Quaternion();
8569
+ var _euler = new THREE39__namespace.Euler();
8570
+ var _scale = new THREE39__namespace.Vector3();
8571
+ var _matrix = new THREE39__namespace.Matrix4();
8572
+ var _modelMatrix = new THREE39__namespace.Matrix4();
8437
8573
  function instanceTransformFromComponent(transform, out) {
8438
8574
  _position.set(transform.position.x, transform.position.y, transform.position.z);
8439
8575
  _euler.set(transform.rotation.x, transform.rotation.y, transform.rotation.z, "XYZ");
@@ -8586,7 +8722,7 @@ var _InstancedMeshSystem = class _InstancedMeshSystem {
8586
8722
  const sourceMaterial = Array.isArray(meshChild.material) ? meshChild.material.map((m) => m.clone()) : meshChild.material.clone();
8587
8723
  meshChild.updateWorldMatrix(true, false);
8588
8724
  const localMatrix = meshChild.matrixWorld.clone();
8589
- const instancedMesh2 = new THREE38__namespace.InstancedMesh(
8725
+ const instancedMesh2 = new THREE39__namespace.InstancedMesh(
8590
8726
  geometry2,
8591
8727
  Array.isArray(sourceMaterial) ? sourceMaterial : sourceMaterial,
8592
8728
  count2
@@ -8611,7 +8747,7 @@ var _InstancedMeshSystem = class _InstancedMeshSystem {
8611
8747
  this.loadingSignatures.delete(targetEntityId);
8612
8748
  return;
8613
8749
  }
8614
- const group = new THREE38__namespace.Group();
8750
+ const group = new THREE39__namespace.Group();
8615
8751
  for (const entry of entries) {
8616
8752
  group.add(entry.instancedMesh);
8617
8753
  }
@@ -8629,8 +8765,8 @@ var _InstancedMeshSystem = class _InstancedMeshSystem {
8629
8765
  }
8630
8766
  const count = instanceCount;
8631
8767
  const geometry = buildGeometry(comp);
8632
- const material = new THREE38__namespace.MeshStandardMaterial({ color: "#ffffff" });
8633
- const instancedMesh = new THREE38__namespace.InstancedMesh(geometry, material, count);
8768
+ const material = new THREE39__namespace.MeshStandardMaterial({ color: "#ffffff" });
8769
+ const instancedMesh = new THREE39__namespace.InstancedMesh(geometry, material, count);
8634
8770
  instancedMesh.castShadow = comp.castShadow;
8635
8771
  instancedMesh.receiveShadow = comp.receiveShadow;
8636
8772
  for (let i = 0; i < count; i++) {
@@ -8813,7 +8949,7 @@ var _Behaviour = class _Behaviour {
8813
8949
  if (!this.threeRef) {
8814
8950
  return null;
8815
8951
  }
8816
- const position = new THREE38__namespace.Vector3();
8952
+ const position = new THREE39__namespace.Vector3();
8817
8953
  this.threeRef.object.getWorldPosition(position);
8818
8954
  return position;
8819
8955
  }
@@ -8825,7 +8961,7 @@ var _Behaviour = class _Behaviour {
8825
8961
  if (!this.threeRef) {
8826
8962
  return null;
8827
8963
  }
8828
- const target = new THREE38__namespace.Vector3();
8964
+ const target = new THREE39__namespace.Vector3();
8829
8965
  this.threeRef.object.getWorldDirection(target);
8830
8966
  return target;
8831
8967
  }
@@ -8887,7 +9023,7 @@ var _Behaviour = class _Behaviour {
8887
9023
  if (!this.threeRef) {
8888
9024
  return;
8889
9025
  }
8890
- const rotation = new THREE38__namespace.Quaternion();
9026
+ const rotation = new THREE39__namespace.Quaternion();
8891
9027
  this.threeRef.object.getWorldQuaternion(rotation);
8892
9028
  rotation.slerp(targetRotation, alpha);
8893
9029
  this.transform.setRotation(rotation);
@@ -8904,7 +9040,7 @@ var _Behaviour = class _Behaviour {
8904
9040
  return;
8905
9041
  }
8906
9042
  const clone3 = this.threeRef.object.clone();
8907
- const rotation = new THREE38__namespace.Quaternion();
9043
+ const rotation = new THREE39__namespace.Quaternion();
8908
9044
  clone3.lookAt(targetPosition);
8909
9045
  clone3.getWorldQuaternion(rotation);
8910
9046
  this.transform.setRotation(rotation);
@@ -9248,8 +9384,8 @@ var _ScriptBehaviourSystem = class _ScriptBehaviourSystem {
9248
9384
  }, "onPointerUp");
9249
9385
  this.moduleLoader = moduleLoader ?? defaultModuleLoader;
9250
9386
  this.selectionCtx = selectionContext ?? null;
9251
- this.raycaster = new THREE38__namespace.Raycaster();
9252
- this.ndcPointer = new THREE38__namespace.Vector2();
9387
+ this.raycaster = new THREE39__namespace.Raycaster();
9388
+ this.ndcPointer = new THREE39__namespace.Vector2();
9253
9389
  if (this.selectionCtx) {
9254
9390
  this.selectionCtx.domElement.addEventListener("pointerdown", this.onPointerDown);
9255
9391
  this.selectionCtx.domElement.addEventListener("pointerup", this.onPointerUp);
@@ -9628,7 +9764,7 @@ function disposeBuiltObject(root) {
9628
9764
  for (const mat of materials) {
9629
9765
  if (mat.userData?.[SHARED_MODEL_RESOURCE_FLAG]) continue;
9630
9766
  for (const value of Object.values(mat)) {
9631
- if (value instanceof THREE38__namespace.Texture) value.dispose();
9767
+ if (value instanceof THREE39__namespace.Texture) value.dispose();
9632
9768
  }
9633
9769
  mat.dispose?.();
9634
9770
  }
@@ -9992,7 +10128,7 @@ var _AudioSystem = class _AudioSystem {
9992
10128
  if (!prev || prev.volume !== opts.volume) {
9993
10129
  sound.setVolume(opts.volume);
9994
10130
  }
9995
- if (opts.positional && sound instanceof THREE38__namespace.PositionalAudio) {
10131
+ if (opts.positional && sound instanceof THREE39__namespace.PositionalAudio) {
9996
10132
  if (!prev || prev.refDistance !== opts.refDistance) {
9997
10133
  sound.setRefDistance(opts.refDistance);
9998
10134
  }
@@ -10118,7 +10254,7 @@ var _VideoSystem = class _VideoSystem {
10118
10254
  component.object.scale.set(opts.width, opts.height, 1);
10119
10255
  }
10120
10256
  const material = component.material;
10121
- if (material instanceof THREE38__namespace.ShaderMaterial) {
10257
+ if (material instanceof THREE39__namespace.ShaderMaterial) {
10122
10258
  if (!prev || prev.backgroundColor !== opts.backgroundColor) {
10123
10259
  material.uniforms.keyColor.value.set(opts.backgroundColor);
10124
10260
  }
@@ -10132,7 +10268,7 @@ var _VideoSystem = class _VideoSystem {
10132
10268
  material.uniforms.spill.value = opts.spill;
10133
10269
  }
10134
10270
  }
10135
- if (opts.positional && component.audioNode instanceof THREE38__namespace.PositionalAudio) {
10271
+ if (opts.positional && component.audioNode instanceof THREE39__namespace.PositionalAudio) {
10136
10272
  const posAudio = component.audioNode;
10137
10273
  if (!prev || prev.refDistance !== opts.refDistance) {
10138
10274
  posAudio.setRefDistance(opts.refDistance);
@@ -10172,8 +10308,8 @@ function blankState(source) {
10172
10308
  handedness: handednessOf(source),
10173
10309
  kind: kindOf(source),
10174
10310
  connected: true,
10175
- rayOrigin: new THREE38__namespace.Vector3(),
10176
- rayDirection: new THREE38__namespace.Vector3(0, 0, -1),
10311
+ rayOrigin: new THREE39__namespace.Vector3(),
10312
+ rayDirection: new THREE39__namespace.Vector3(0, 0, -1),
10177
10313
  gripPosition: null,
10178
10314
  gripQuaternion: null,
10179
10315
  select: false,
@@ -10280,19 +10416,19 @@ var _XRInputSystem = class _XRInputSystem {
10280
10416
  if (frame && referenceSpace && source.targetRaySpace) {
10281
10417
  const pose = frame.getPose(source.targetRaySpace, referenceSpace);
10282
10418
  if (pose) {
10283
- const m = new THREE38__namespace.Matrix4().fromArray(pose.transform.matrix);
10419
+ const m = new THREE39__namespace.Matrix4().fromArray(pose.transform.matrix);
10284
10420
  state.rayOrigin.setFromMatrixPosition(m);
10285
10421
  state.rayDirection.set(0, 0, -1).applyQuaternion(
10286
- new THREE38__namespace.Quaternion().setFromRotationMatrix(m)
10422
+ new THREE39__namespace.Quaternion().setFromRotationMatrix(m)
10287
10423
  ).normalize();
10288
10424
  }
10289
10425
  }
10290
10426
  if (frame && referenceSpace && source.gripSpace) {
10291
10427
  const gripPose = frame.getPose(source.gripSpace, referenceSpace);
10292
10428
  if (gripPose) {
10293
- const m = new THREE38__namespace.Matrix4().fromArray(gripPose.transform.matrix);
10294
- state.gripPosition ?? (state.gripPosition = new THREE38__namespace.Vector3());
10295
- state.gripQuaternion ?? (state.gripQuaternion = new THREE38__namespace.Quaternion());
10429
+ const m = new THREE39__namespace.Matrix4().fromArray(gripPose.transform.matrix);
10430
+ state.gripPosition ?? (state.gripPosition = new THREE39__namespace.Vector3());
10431
+ state.gripQuaternion ?? (state.gripQuaternion = new THREE39__namespace.Quaternion());
10296
10432
  state.gripPosition.setFromMatrixPosition(m);
10297
10433
  state.gripQuaternion.setFromRotationMatrix(m);
10298
10434
  }
@@ -10310,6 +10446,9 @@ var _XRInputSystem = class _XRInputSystem {
10310
10446
  state.hasAxes = false;
10311
10447
  state.buttons = [];
10312
10448
  }
10449
+ }
10450
+ for (const record of this.records.values()) {
10451
+ const state = record.state;
10313
10452
  if (record.pendingSelectStart) {
10314
10453
  state.select = true;
10315
10454
  state.selectStart = true;
@@ -10364,7 +10503,7 @@ var XRInputSystem = _XRInputSystem;
10364
10503
  var RAYLESS_HOLD_DISTANCE = 0.5;
10365
10504
  var _XRInteractionSystem = class _XRInteractionSystem {
10366
10505
  constructor(inputSystem) {
10367
- this.raycaster = new THREE38__namespace.Raycaster();
10506
+ this.raycaster = new THREE39__namespace.Raycaster();
10368
10507
  /** Which entity each source is holding. Keyed by source state identity. */
10369
10508
  this.grabs = /* @__PURE__ */ new Map();
10370
10509
  this.hoveredEntityId = null;
@@ -10434,7 +10573,7 @@ var _XRInteractionSystem = class _XRInteractionSystem {
10434
10573
  const transform = world.getComponent(entityId, TransformComponent);
10435
10574
  if (!transform) return;
10436
10575
  const hand = this.handPosition(input);
10437
- const offset = new THREE38__namespace.Vector3(
10576
+ const offset = new THREE39__namespace.Vector3(
10438
10577
  transform.position.x - hand.x,
10439
10578
  transform.position.y - hand.y,
10440
10579
  transform.position.z - hand.z
@@ -10481,7 +10620,7 @@ var _XRInteractionSystem = class _XRInteractionSystem {
10481
10620
  */
10482
10621
  handPosition(input) {
10483
10622
  if (input.gripPosition) return input.gripPosition;
10484
- return new THREE38__namespace.Vector3().copy(input.rayDirection).multiplyScalar(RAYLESS_HOLD_DISTANCE).add(input.rayOrigin);
10623
+ return new THREE39__namespace.Vector3().copy(input.rayDirection).multiplyScalar(RAYLESS_HOLD_DISTANCE).add(input.rayOrigin);
10485
10624
  }
10486
10625
  dispatch(world, entityId, visit) {
10487
10626
  const script = world.getComponent(entityId, ScriptComponent);
@@ -10507,20 +10646,72 @@ var _XRInteractionSystem = class _XRInteractionSystem {
10507
10646
  };
10508
10647
  __name(_XRInteractionSystem, "XRInteractionSystem");
10509
10648
  var XRInteractionSystem = _XRInteractionSystem;
10510
- var UP = new THREE38__namespace.Vector3(0, 1, 0);
10649
+ var ARC_GRAVITY = 9.8;
10650
+ var ARC_SPEED = 7;
10651
+ var ARC_STEPS = 24;
10652
+ var ARC_MAX_TIME = 2;
10653
+ function sampleTeleportArc(origin, direction, out = [], options) {
10654
+ const speed = options?.speed ?? ARC_SPEED;
10655
+ const gravity = options?.gravity ?? ARC_GRAVITY;
10656
+ const steps = Math.max(2, options?.steps ?? ARC_STEPS);
10657
+ const maxTime = options?.maxTime ?? ARC_MAX_TIME;
10658
+ out.length = 0;
10659
+ const velocity = direction.clone().normalize().multiplyScalar(speed);
10660
+ for (let i = 0; i < steps; i += 1) {
10661
+ const t = i / (steps - 1) * maxTime;
10662
+ out.push(
10663
+ new THREE39__namespace.Vector3(
10664
+ origin.x + velocity.x * t,
10665
+ origin.y + velocity.y * t - 0.5 * gravity * t * t,
10666
+ origin.z + velocity.z * t
10667
+ )
10668
+ );
10669
+ }
10670
+ return out;
10671
+ }
10672
+ __name(sampleTeleportArc, "sampleTeleportArc");
10673
+ function arcGroundCrossing(points, groundY) {
10674
+ for (let i = 1; i < points.length; i += 1) {
10675
+ const previous = points[i - 1];
10676
+ const current = points[i];
10677
+ if (previous.y >= groundY && current.y <= groundY) {
10678
+ const span = previous.y - current.y;
10679
+ const alpha = span > 1e-6 ? (previous.y - groundY) / span : 0;
10680
+ return new THREE39__namespace.Vector3().lerpVectors(previous, current, alpha);
10681
+ }
10682
+ }
10683
+ return null;
10684
+ }
10685
+ __name(arcGroundCrossing, "arcGroundCrossing");
10686
+
10687
+ // core/systems/XRLocomotionSystem.ts
10688
+ var UP = new THREE39__namespace.Vector3(0, 1, 0);
10511
10689
  var AXIS_DEADZONE = 0.5;
10512
10690
  var _XRLocomotionSystem = class _XRLocomotionSystem {
10513
10691
  constructor(inputSystem) {
10514
- this.raycaster = new THREE38__namespace.Raycaster();
10692
+ this.raycaster = new THREE39__namespace.Raycaster();
10515
10693
  /** Per-source latch so one stick push yields exactly one snap turn. */
10516
10694
  this.turnLatched = /* @__PURE__ */ new WeakSet();
10517
- /** Where the pointer currently lands, for the consumer to draw a marker. */
10518
- this.teleportPoint = null;
10695
+ /** Reused arc buffer — aiming runs every frame. */
10696
+ this.arcPoints = [];
10697
+ /** Curve up to the landing point, for the visual system. Empty when not aiming. */
10698
+ this.aimCurve = [];
10699
+ this.landingPoint = null;
10700
+ /** True once we've tried to self-heal camera parenting for this session. */
10701
+ this.parentingChecked = false;
10519
10702
  this.inputSystem = inputSystem;
10520
10703
  }
10521
10704
  update(world, deltaTime) {
10522
- this.teleportPoint = null;
10523
- if (!world.isXrPresenting()) return;
10705
+ this.aimCurve = [];
10706
+ this.landingPoint = null;
10707
+ if (!world.isXrPresenting()) {
10708
+ this.parentingChecked = false;
10709
+ return;
10710
+ }
10711
+ if (!this.parentingChecked) {
10712
+ this.parentingChecked = true;
10713
+ this.ensureCameraUnderRig(world);
10714
+ }
10524
10715
  const rigEntityId = world.query(XRRigComponent, TransformComponent)[0];
10525
10716
  if (typeof rigEntityId !== "number") return;
10526
10717
  const rig = world.getComponent(rigEntityId, XRRigComponent);
@@ -10537,9 +10728,37 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
10537
10728
  this.applySmoothMove(world, rig, rigTransform, inputs, deltaTime);
10538
10729
  }
10539
10730
  }
10731
+ /**
10732
+ * Guarantee the render camera is a CHILD of the rig.
10733
+ *
10734
+ * Locomotion moves the rig, and three composes the head pose against
10735
+ * `camera.parent` — so if the camera sits at the scene root instead, moving
10736
+ * the rig does nothing at all and the player is frozen in place. Scenes
10737
+ * authored before the rig existed (or with the camera re-parented by hand)
10738
+ * would otherwise silently fail to move, which is exactly the symptom that is
10739
+ * hardest to diagnose from inside a headset. Repairing it via `ParentId` lets
10740
+ * `ObjectManagementSystem` reconcile the scene graph normally.
10741
+ */
10742
+ ensureCameraUnderRig(world) {
10743
+ const rigEntityId = world.query(XRRigComponent)[0];
10744
+ if (typeof rigEntityId !== "number") return;
10745
+ const activeCamera = world.getCamera();
10746
+ for (const entityId of world.query(CameraComponent, Object3DRef)) {
10747
+ if (world.getComponent(entityId, Object3DRef)?.object !== activeCamera) {
10748
+ continue;
10749
+ }
10750
+ const parent = world.getComponent(entityId, ParentId);
10751
+ if (parent) {
10752
+ if (parent.value !== rigEntityId) parent.value = rigEntityId;
10753
+ } else {
10754
+ world.addComponent(entityId, new ParentId(rigEntityId));
10755
+ }
10756
+ return;
10757
+ }
10758
+ }
10540
10759
  /**
10541
10760
  * Snap turning, not smooth turning — rotating the view continuously is the
10542
- * single biggest cause of VR nausea, so the comfort-safe option is the one
10761
+ * single biggest cause of VR nausea, so the comfort-safe option is what's
10543
10762
  * wired to the stick.
10544
10763
  */
10545
10764
  applySnapTurn(rig, transform, inputs) {
@@ -10553,8 +10772,7 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
10553
10772
  }
10554
10773
  if (this.turnLatched.has(source)) continue;
10555
10774
  this.turnLatched.add(source);
10556
- const step = THREE38__namespace.MathUtils.degToRad(rig.snapTurnDegrees);
10557
- transform.rotation.y -= Math.sign(x) * step;
10775
+ transform.rotation.y -= Math.sign(x) * THREE39__namespace.MathUtils.degToRad(rig.snapTurnDegrees);
10558
10776
  }
10559
10777
  }
10560
10778
  applySmoothMove(world, rig, transform, inputs, deltaTime) {
@@ -10564,12 +10782,12 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
10564
10782
  const y = input.axes[1] ?? 0;
10565
10783
  if (Math.abs(x) < 0.15 && Math.abs(y) < 0.15) continue;
10566
10784
  const camera = world.getCamera();
10567
- const forward = new THREE38__namespace.Vector3();
10785
+ const forward = new THREE39__namespace.Vector3();
10568
10786
  camera.getWorldDirection(forward);
10569
10787
  forward.y = 0;
10570
10788
  if (forward.lengthSq() < 1e-6) continue;
10571
10789
  forward.normalize();
10572
- const right = new THREE38__namespace.Vector3().crossVectors(forward, UP).normalize();
10790
+ const right = new THREE39__namespace.Vector3().crossVectors(forward, UP).normalize();
10573
10791
  const step = rig.moveSpeed * Math.max(0, deltaTime);
10574
10792
  transform.position.x += (forward.x * -y + right.x * x) * step;
10575
10793
  transform.position.z += (forward.z * -y + right.z * x) * step;
@@ -10579,17 +10797,42 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
10579
10797
  const targets = this.collectTeleportTargets(world);
10580
10798
  if (targets.length === 0) return;
10581
10799
  for (const input of inputs) {
10582
- this.raycaster.set(input.rayOrigin, input.rayDirection);
10583
- const hit = this.raycaster.intersectObjects(targets, true)[0];
10800
+ if (!input.select && !input.selectEnd) continue;
10801
+ const points = sampleTeleportArc(
10802
+ input.rayOrigin,
10803
+ input.rayDirection,
10804
+ this.arcPoints
10805
+ );
10806
+ const hit = this.raycastArc(points, targets);
10584
10807
  if (!hit) continue;
10585
- this.teleportPoint = hit.point.clone();
10808
+ this.landingPoint = hit.point;
10809
+ this.aimCurve = points.slice(0, hit.segmentIndex + 1).concat(hit.point);
10586
10810
  if (input.selectEnd) {
10587
10811
  transform.position.x = hit.point.x;
10588
10812
  transform.position.y = hit.point.y;
10589
10813
  transform.position.z = hit.point.z;
10814
+ this.aimCurve = [];
10815
+ this.landingPoint = null;
10590
10816
  }
10591
10817
  }
10592
10818
  }
10819
+ /** Walk the arc segment-by-segment, returning the first surface hit. */
10820
+ raycastArc(points, targets) {
10821
+ for (let i = 1; i < points.length; i += 1) {
10822
+ const from = points[i - 1];
10823
+ const to = points[i];
10824
+ const delta = new THREE39__namespace.Vector3().subVectors(to, from);
10825
+ const distance = delta.length();
10826
+ if (distance < 1e-6) continue;
10827
+ this.raycaster.set(from, delta.divideScalar(distance));
10828
+ this.raycaster.far = distance;
10829
+ const hit = this.raycaster.intersectObjects(targets, true)[0];
10830
+ if (hit) {
10831
+ return { point: hit.point.clone(), segmentIndex: i - 1 };
10832
+ }
10833
+ }
10834
+ return null;
10835
+ }
10593
10836
  collectTeleportTargets(world) {
10594
10837
  const objects = [];
10595
10838
  for (const entityId of world.query(VRTeleportAreaComponent, Object3DRef)) {
@@ -10601,12 +10844,13 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
10601
10844
  }
10602
10845
  return objects;
10603
10846
  }
10604
- /**
10605
- * Where the teleport pointer currently lands this frame, or null.
10606
- * Consumers use this to render an aim marker.
10607
- */
10608
- getTeleportPoint() {
10609
- return this.teleportPoint;
10847
+ /** Arc points up to the landing spot this frame; empty when not aiming. */
10848
+ getAimCurve() {
10849
+ return this.aimCurve;
10850
+ }
10851
+ /** Where the arc currently lands, or null when not aiming at a valid area. */
10852
+ getLandingPoint() {
10853
+ return this.landingPoint;
10610
10854
  }
10611
10855
  };
10612
10856
  __name(_XRLocomotionSystem, "XRLocomotionSystem");
@@ -10646,6 +10890,8 @@ var _XRSessionSystem = class _XRSessionSystem {
10646
10890
  constructor(inputSystem) {
10647
10891
  this.presenting = false;
10648
10892
  this.capabilities = NO_XR_CAPABILITIES;
10893
+ /** Y compensation applied when a floor-relative space was requested but not granted. */
10894
+ this.appliedOriginOffset = 0;
10649
10895
  this.inputSystem = inputSystem ?? null;
10650
10896
  }
10651
10897
  update(world) {
@@ -10669,11 +10915,59 @@ var _XRSessionSystem = class _XRSessionSystem {
10669
10915
  if (session && this.inputSystem) {
10670
10916
  this.inputSystem.attachSession(session);
10671
10917
  }
10918
+ this.applyTrackingOrigin(world, session ?? null);
10672
10919
  this.forEachBehaviour(world, (behaviour) => {
10673
10920
  behaviour.onXRSessionStart(this.capabilities);
10674
10921
  });
10675
10922
  }
10923
+ /**
10924
+ * Apply the rig's authored tracking origin, and compensate when the device
10925
+ * cannot honour it.
10926
+ *
10927
+ * `floor` (`local-floor`) puts Y=0 on the user's real floor, which is what a
10928
+ * scene authored standing on the ground expects. `eye` (`local`) puts Y=0 at
10929
+ * the headset, for seated experiences.
10930
+ *
10931
+ * The compensation matters: `local-floor` is only ever REQUESTED as an
10932
+ * optional feature (requiring it would make `requestSession` reject outright
10933
+ * on devices that lack it). When it isn't granted, the runtime silently falls
10934
+ * back to `local` — the origin jumps to head height and a floor-authored
10935
+ * scene swallows the user, which is exactly the "I'm standing under the
10936
+ * building" symptom. Offsetting the rig down by the eye height restores the
10937
+ * intended floor relationship instead of leaving it broken.
10938
+ */
10939
+ applyTrackingOrigin(world, session) {
10940
+ const rigEntityId = world.query(XRRigComponent, TransformComponent)[0];
10941
+ if (typeof rigEntityId !== "number") return;
10942
+ const rig = world.getComponent(rigEntityId, XRRigComponent);
10943
+ const transform = world.getComponent(rigEntityId, TransformComponent);
10944
+ if (!rig || !transform) return;
10945
+ const renderer = world.getRenderer();
10946
+ const wantsFloor = rig.trackingOrigin === "floor";
10947
+ try {
10948
+ renderer.xr.setReferenceSpaceType(wantsFloor ? "local-floor" : "local");
10949
+ } catch {
10950
+ }
10951
+ const granted = session?.enabledFeatures;
10952
+ const floorGranted = Array.isArray(granted) ? granted.includes("local-floor") : (
10953
+ // No report at all: trust the request, since a wrong offset is worse
10954
+ // than none on devices that did honour it.
10955
+ true
10956
+ );
10957
+ this.appliedOriginOffset = wantsFloor && !floorGranted ? rig.fallbackEyeHeight : 0;
10958
+ if (this.appliedOriginOffset !== 0) {
10959
+ transform.position.y -= this.appliedOriginOffset;
10960
+ }
10961
+ }
10676
10962
  handleSessionEnd(world) {
10963
+ if (this.appliedOriginOffset !== 0) {
10964
+ const rigEntityId = world.query(XRRigComponent, TransformComponent)[0];
10965
+ if (typeof rigEntityId === "number") {
10966
+ const transform = world.getComponent(rigEntityId, TransformComponent);
10967
+ if (transform) transform.position.y += this.appliedOriginOffset;
10968
+ }
10969
+ this.appliedOriginOffset = 0;
10970
+ }
10677
10971
  this.capabilities = NO_XR_CAPABILITIES;
10678
10972
  this.inputSystem?.detachSession();
10679
10973
  this.forEachBehaviour(world, (behaviour) => {
@@ -10731,9 +11025,9 @@ var XRSessionSystem = _XRSessionSystem;
10731
11025
  function buildGeometry2(area) {
10732
11026
  if (area.shape === "circle") {
10733
11027
  const radius = Math.max(5e-3, area.width / 2);
10734
- return new THREE38__namespace.CircleGeometry(radius, 48);
11028
+ return new THREE39__namespace.CircleGeometry(radius, 48);
10735
11029
  }
10736
- return new THREE38__namespace.PlaneGeometry(
11030
+ return new THREE39__namespace.PlaneGeometry(
10737
11031
  Math.max(0.01, area.width),
10738
11032
  Math.max(0.01, area.depth)
10739
11033
  );
@@ -10756,7 +11050,7 @@ var _VRTeleportAreaSystem = class _VRTeleportAreaSystem {
10756
11050
  for (const entityId of entityIds) {
10757
11051
  const area = world.getComponent(entityId, VRTeleportAreaComponent);
10758
11052
  const object = world.getComponent(entityId, Object3DRef)?.object;
10759
- if (!area || !(object instanceof THREE38__namespace.Mesh)) continue;
11053
+ if (!area || !(object instanceof THREE39__namespace.Mesh)) continue;
10760
11054
  const signature = signatureOf(area);
10761
11055
  if (this.signatures.get(entityId) === signature) continue;
10762
11056
  this.signatures.set(entityId, signature);
@@ -10767,16 +11061,75 @@ var _VRTeleportAreaSystem = class _VRTeleportAreaSystem {
10767
11061
  };
10768
11062
  __name(_VRTeleportAreaSystem, "VRTeleportAreaSystem");
10769
11063
  var VRTeleportAreaSystem = _VRTeleportAreaSystem;
11064
+ function createHandMaterial(preset, options) {
11065
+ const color = new THREE39__namespace.Color(options.color);
11066
+ switch (preset) {
11067
+ case "ghost":
11068
+ return new THREE39__namespace.MeshBasicMaterial({
11069
+ color,
11070
+ transparent: true,
11071
+ opacity: Math.min(1, Math.max(0.05, options.opacity * 0.45)),
11072
+ depthWrite: false,
11073
+ side: THREE39__namespace.DoubleSide
11074
+ });
11075
+ case "neon":
11076
+ return new THREE39__namespace.MeshStandardMaterial({
11077
+ color,
11078
+ emissive: color,
11079
+ emissiveIntensity: Math.max(0.5, options.emissiveIntensity || 2),
11080
+ roughness: 0.35,
11081
+ metalness: 0,
11082
+ transparent: options.opacity < 1,
11083
+ opacity: options.opacity
11084
+ });
11085
+ case "skeleton":
11086
+ return new THREE39__namespace.MeshBasicMaterial({
11087
+ color,
11088
+ wireframe: true,
11089
+ transparent: true,
11090
+ opacity: options.opacity
11091
+ });
11092
+ case "custom":
11093
+ case "default":
11094
+ return new THREE39__namespace.MeshStandardMaterial({
11095
+ color,
11096
+ roughness: 0.85,
11097
+ metalness: 0,
11098
+ emissive: color,
11099
+ emissiveIntensity: Math.max(0, options.emissiveIntensity),
11100
+ transparent: options.opacity < 1,
11101
+ opacity: options.opacity,
11102
+ side: THREE39__namespace.DoubleSide
11103
+ });
11104
+ default: {
11105
+ return new THREE39__namespace.MeshStandardMaterial({ color });
11106
+ }
11107
+ }
11108
+ }
11109
+ __name(createHandMaterial, "createHandMaterial");
11110
+ function applyHandMaterial(root, material) {
11111
+ root.traverse((child) => {
11112
+ const mesh = child;
11113
+ if (!mesh.isMesh) return;
11114
+ mesh.material = material;
11115
+ });
11116
+ }
11117
+ __name(applyHandMaterial, "applyHandMaterial");
11118
+ var SLOTS = [
11119
+ { index: 0, side: "left" },
11120
+ { index: 1, side: "right" }
11121
+ ];
10770
11122
  var _XRControllerVisualSystem = class _XRControllerVisualSystem {
10771
- constructor(slots = 2) {
11123
+ constructor(options) {
10772
11124
  this.controllerModelFactory = new XRControllerModelFactory_js.XRControllerModelFactory();
10773
11125
  this.handModelFactory = new XRHandModelFactory_js.XRHandModelFactory();
10774
- this.group = new THREE38__namespace.Group();
10775
- this.built = false;
11126
+ this.group = new THREE39__namespace.Group();
11127
+ this.slots = /* @__PURE__ */ new Map();
10776
11128
  this.attachedTo = null;
10777
- /** Index → whether we've already attached visuals for that slot. */
10778
- this.ready = /* @__PURE__ */ new Set();
10779
- this.slots = slots;
11129
+ /** Last applied preset signature, so materials rebuild only on real change. */
11130
+ this.handStyleSignature = "";
11131
+ this.handMaterial = null;
11132
+ this.interactionSystem = options?.interactionSystem ?? null;
10780
11133
  this.group.name = "XRControllerVisuals";
10781
11134
  this.group.userData.ecsPreviewHidden = true;
10782
11135
  }
@@ -10784,23 +11137,109 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
10784
11137
  const renderer = world.getRenderer();
10785
11138
  if (!renderer.xr?.enabled) return;
10786
11139
  this.ensureAttached(world);
10787
- if (this.built) return;
10788
- for (let index = 0; index < this.slots; index += 1) {
10789
- if (this.ready.has(index)) continue;
11140
+ this.ensureSlots(world);
11141
+ const interactor = this.resolveInteractor(world);
11142
+ const type = interactor?.interactorType ?? "both";
11143
+ const showControllers = type === "controllers" || type === "both";
11144
+ const showHands = type === "hands" || type === "both";
11145
+ this.syncHandMaterial(interactor);
11146
+ for (const { index, side } of SLOTS) {
11147
+ const visuals = this.slots.get(index);
11148
+ if (!visuals) continue;
11149
+ visuals.controllerModel.visible = showControllers;
11150
+ visuals.handModel.visible = showHands;
11151
+ visuals.ray.visible = this.shouldShowRay(interactor);
11152
+ if (showHands && this.handMaterial) {
11153
+ applyHandMaterial(visuals.handModel, this.handMaterial);
11154
+ }
11155
+ this.syncCustomContent(world, visuals, side);
11156
+ }
11157
+ }
11158
+ /** The scene's interactor config, if one was authored. */
11159
+ resolveInteractor(world) {
11160
+ const entityId = world.query(XRInteractorComponent)[0];
11161
+ if (typeof entityId !== "number") return null;
11162
+ return world.getComponent(entityId, XRInteractorComponent) ?? null;
11163
+ }
11164
+ /**
11165
+ * Re-parent the author's left/right interactor content onto the tracked grip
11166
+ * space so it follows the hand.
11167
+ *
11168
+ * `ObjectManagementSystem` reconciles ECS objects back under their ParentId
11169
+ * every frame, so this re-attach has to be re-asserted — the same coexistence
11170
+ * dance the AR anchor system performs.
11171
+ */
11172
+ syncCustomContent(world, visuals, side) {
11173
+ let content = null;
11174
+ for (const entityId of world.query(
11175
+ XRInteractorSideComponent,
11176
+ Object3DRef
11177
+ )) {
11178
+ const slot = world.getComponent(entityId, XRInteractorSideComponent);
11179
+ if (slot?.side !== side) continue;
11180
+ content = world.getComponent(entityId, Object3DRef)?.object ?? null;
11181
+ break;
11182
+ }
11183
+ if (!content) {
11184
+ visuals.attachedCustom = null;
11185
+ return;
11186
+ }
11187
+ if (content.parent !== visuals.grip) {
11188
+ visuals.grip.add(content);
11189
+ }
11190
+ visuals.attachedCustom = content;
11191
+ }
11192
+ /** Rebuild the hand material only when the authored style actually changes. */
11193
+ syncHandMaterial(interactor) {
11194
+ const preset = interactor?.handPreset ?? "default";
11195
+ const color = interactor?.handColor ?? "#e8b48a";
11196
+ const opacity = interactor?.handOpacity ?? 1;
11197
+ const emissive = interactor?.handEmissiveIntensity ?? 0;
11198
+ const signature = `${preset}:${color}:${opacity}:${emissive}`;
11199
+ if (signature === this.handStyleSignature && this.handMaterial) return;
11200
+ this.handStyleSignature = signature;
11201
+ this.handMaterial?.dispose();
11202
+ this.handMaterial = createHandMaterial(preset, {
11203
+ color,
11204
+ opacity,
11205
+ emissiveIntensity: emissive
11206
+ });
11207
+ }
11208
+ /**
11209
+ * The ray is meaningful only when it points at something. Authors can turn it
11210
+ * off entirely; otherwise it appears on hover/grab so it isn't permanent
11211
+ * clutter implying the whole scene is clickable.
11212
+ */
11213
+ shouldShowRay(interactor) {
11214
+ if (interactor && !interactor.showRay) return false;
11215
+ if (!this.interactionSystem) return true;
11216
+ return this.interactionSystem.getHoveredEntityId() !== null || this.interactionSystem.isGrabbing();
11217
+ }
11218
+ /** Lazily build per-slot visuals; the device reports profiles late. */
11219
+ ensureSlots(world) {
11220
+ const renderer = world.getRenderer();
11221
+ for (const { index } of SLOTS) {
11222
+ if (this.slots.has(index)) continue;
10790
11223
  const controller = renderer.xr.getController(index);
10791
11224
  const grip = renderer.xr.getControllerGrip(index);
10792
11225
  const hand = renderer.xr.getHand(index);
10793
11226
  if (!controller || !grip || !hand) continue;
10794
- controller.add(this.createRay());
10795
- this.group.add(controller);
10796
- grip.add(this.controllerModelFactory.createControllerModel(grip));
10797
- this.group.add(grip);
10798
- hand.add(this.handModelFactory.createHandModel(hand, "mesh"));
10799
- this.group.add(hand);
10800
- this.ready.add(index);
10801
- }
10802
- if (this.ready.size >= this.slots) {
10803
- this.built = true;
11227
+ const ray = this.createRay();
11228
+ controller.add(ray);
11229
+ const controllerModel = this.controllerModelFactory.createControllerModel(grip);
11230
+ grip.add(controllerModel);
11231
+ const handModel = this.handModelFactory.createHandModel(hand, "mesh");
11232
+ hand.add(handModel);
11233
+ this.group.add(controller, grip, hand);
11234
+ this.slots.set(index, {
11235
+ controller,
11236
+ grip,
11237
+ hand,
11238
+ ray,
11239
+ controllerModel,
11240
+ handModel,
11241
+ attachedCustom: null
11242
+ });
10804
11243
  }
10805
11244
  }
10806
11245
  /**
@@ -10815,19 +11254,20 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
10815
11254
  this.attachedTo = target;
10816
11255
  }
10817
11256
  createRay() {
10818
- const geometry = new THREE38__namespace.BufferGeometry().setFromPoints([
10819
- new THREE38__namespace.Vector3(0, 0, 0),
10820
- new THREE38__namespace.Vector3(0, 0, -5)
11257
+ const geometry = new THREE39__namespace.BufferGeometry().setFromPoints([
11258
+ new THREE39__namespace.Vector3(0, 0, 0),
11259
+ new THREE39__namespace.Vector3(0, 0, -5)
10821
11260
  ]);
10822
- const material = new THREE38__namespace.LineBasicMaterial({
11261
+ const material = new THREE39__namespace.LineBasicMaterial({
10823
11262
  color: "#4da3ff",
10824
11263
  transparent: true,
10825
11264
  opacity: 0.6,
10826
11265
  depthTest: false
10827
11266
  });
10828
- const line = new THREE38__namespace.Line(geometry, material);
11267
+ const line = new THREE39__namespace.Line(geometry, material);
10829
11268
  line.name = "XRPointerRay";
10830
11269
  line.renderOrder = 999;
11270
+ line.visible = false;
10831
11271
  return line;
10832
11272
  }
10833
11273
  dispose() {
@@ -10843,13 +11283,130 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
10843
11283
  }
10844
11284
  });
10845
11285
  this.group.clear();
10846
- this.ready.clear();
10847
- this.built = false;
11286
+ this.slots.clear();
11287
+ this.handMaterial?.dispose();
11288
+ this.handMaterial = null;
11289
+ this.handStyleSignature = "";
10848
11290
  this.attachedTo = null;
10849
11291
  }
10850
11292
  };
10851
11293
  __name(_XRControllerVisualSystem, "XRControllerVisualSystem");
10852
11294
  var XRControllerVisualSystem = _XRControllerVisualSystem;
11295
+ var MARKER_RADIUS = 0.28;
11296
+ var ACCENT = new THREE39__namespace.Color("#4da3ff");
11297
+ var _XRTeleportVisualSystem = class _XRTeleportVisualSystem {
11298
+ constructor(locomotionSystem) {
11299
+ this.group = new THREE39__namespace.Group();
11300
+ this.arcGeometry = new THREE39__namespace.BufferGeometry();
11301
+ this.marker = new THREE39__namespace.Group();
11302
+ this.attached = false;
11303
+ this.locomotionSystem = locomotionSystem;
11304
+ this.group.name = "XRTeleportVisuals";
11305
+ this.group.userData.ecsPreviewHidden = true;
11306
+ const arcMaterial = new THREE39__namespace.LineBasicMaterial({
11307
+ vertexColors: true,
11308
+ transparent: true,
11309
+ depthTest: false
11310
+ });
11311
+ this.arc = new THREE39__namespace.Line(this.arcGeometry, arcMaterial);
11312
+ this.arc.frustumCulled = false;
11313
+ this.arc.renderOrder = 998;
11314
+ this.group.add(this.arc);
11315
+ this.marker.add(this.createRing(), this.createDot());
11316
+ this.marker.renderOrder = 999;
11317
+ this.group.add(this.marker);
11318
+ this.setVisible(false);
11319
+ }
11320
+ update(world) {
11321
+ if (!this.attached) {
11322
+ world.getScene().add(this.group);
11323
+ this.attached = true;
11324
+ }
11325
+ const curve = this.locomotionSystem.getAimCurve();
11326
+ const landing = this.locomotionSystem.getLandingPoint();
11327
+ if (!landing || curve.length < 2) {
11328
+ this.setVisible(false);
11329
+ return;
11330
+ }
11331
+ this.updateArcGeometry(curve);
11332
+ this.marker.position.copy(landing);
11333
+ this.marker.position.y += 0.01;
11334
+ this.setVisible(true);
11335
+ }
11336
+ updateArcGeometry(curve) {
11337
+ const count = curve.length;
11338
+ const positions = new Float32Array(count * 3);
11339
+ const colors = new Float32Array(count * 3);
11340
+ for (let i = 0; i < count; i += 1) {
11341
+ const point = curve[i];
11342
+ positions[i * 3] = point.x;
11343
+ positions[i * 3 + 1] = point.y;
11344
+ positions[i * 3 + 2] = point.z;
11345
+ const t = count > 1 ? i / (count - 1) : 0;
11346
+ const fade = 1 - t * 0.75;
11347
+ colors[i * 3] = ACCENT.r * fade;
11348
+ colors[i * 3 + 1] = ACCENT.g * fade;
11349
+ colors[i * 3 + 2] = ACCENT.b * fade;
11350
+ }
11351
+ this.arcGeometry.setAttribute(
11352
+ "position",
11353
+ new THREE39__namespace.BufferAttribute(positions, 3)
11354
+ );
11355
+ this.arcGeometry.setAttribute("color", new THREE39__namespace.BufferAttribute(colors, 3));
11356
+ this.arcGeometry.computeBoundingSphere();
11357
+ }
11358
+ createRing() {
11359
+ const geometry = new THREE39__namespace.RingGeometry(
11360
+ MARKER_RADIUS * 0.72,
11361
+ MARKER_RADIUS,
11362
+ 48
11363
+ );
11364
+ geometry.rotateX(-Math.PI / 2);
11365
+ return new THREE39__namespace.Mesh(
11366
+ geometry,
11367
+ new THREE39__namespace.MeshBasicMaterial({
11368
+ color: ACCENT,
11369
+ transparent: true,
11370
+ opacity: 0.9,
11371
+ side: THREE39__namespace.DoubleSide,
11372
+ depthTest: false
11373
+ })
11374
+ );
11375
+ }
11376
+ createDot() {
11377
+ const geometry = new THREE39__namespace.CircleGeometry(MARKER_RADIUS * 0.16, 24);
11378
+ geometry.rotateX(-Math.PI / 2);
11379
+ return new THREE39__namespace.Mesh(
11380
+ geometry,
11381
+ new THREE39__namespace.MeshBasicMaterial({
11382
+ color: ACCENT,
11383
+ transparent: true,
11384
+ opacity: 0.55,
11385
+ side: THREE39__namespace.DoubleSide,
11386
+ depthTest: false
11387
+ })
11388
+ );
11389
+ }
11390
+ setVisible(visible) {
11391
+ this.group.visible = visible;
11392
+ }
11393
+ dispose() {
11394
+ this.group.removeFromParent();
11395
+ this.group.traverse((child) => {
11396
+ const mesh = child;
11397
+ mesh.geometry?.dispose?.();
11398
+ const material = mesh.material;
11399
+ if (Array.isArray(material)) {
11400
+ for (const entry of material) entry.dispose?.();
11401
+ } else {
11402
+ material?.dispose?.();
11403
+ }
11404
+ });
11405
+ this.attached = false;
11406
+ }
11407
+ };
11408
+ __name(_XRTeleportVisualSystem, "XRTeleportVisualSystem");
11409
+ var XRTeleportVisualSystem = _XRTeleportVisualSystem;
10853
11410
 
10854
11411
  // core/World.ts
10855
11412
  var _World = class _World {
@@ -11520,8 +12077,8 @@ var _World = class _World {
11520
12077
  * ```
11521
12078
  */
11522
12079
  raycast(origin, direction, near = 0, far = Infinity) {
11523
- const rayOrigin = new THREE38__namespace.Vector3(origin.x, origin.y, origin.z);
11524
- const rayDirection = new THREE38__namespace.Vector3(
12080
+ const rayOrigin = new THREE39__namespace.Vector3(origin.x, origin.y, origin.z);
12081
+ const rayDirection = new THREE39__namespace.Vector3(
11525
12082
  direction.x,
11526
12083
  direction.y,
11527
12084
  direction.z
@@ -11530,7 +12087,7 @@ var _World = class _World {
11530
12087
  return [];
11531
12088
  }
11532
12089
  rayDirection.normalize();
11533
- const raycaster = new THREE38__namespace.Raycaster(rayOrigin, rayDirection, near, far);
12090
+ const raycaster = new THREE39__namespace.Raycaster(rayOrigin, rayDirection, near, far);
11534
12091
  const intersections = raycaster.intersectObjects(
11535
12092
  this.scene.children,
11536
12093
  true
@@ -11564,14 +12121,14 @@ var _World = class _World {
11564
12121
  if (!sourceObject) {
11565
12122
  return [];
11566
12123
  }
11567
- const rayOrigin = new THREE38__namespace.Vector3();
11568
- const rayDirection = new THREE38__namespace.Vector3();
12124
+ const rayOrigin = new THREE39__namespace.Vector3();
12125
+ const rayDirection = new THREE39__namespace.Vector3();
11569
12126
  sourceObject.getWorldPosition(rayOrigin);
11570
12127
  sourceObject.getWorldDirection(rayDirection);
11571
12128
  if (rayDirection.lengthSq() === 0) {
11572
12129
  return [];
11573
12130
  }
11574
- const raycaster = new THREE38__namespace.Raycaster(rayOrigin, rayDirection, near, far);
12131
+ const raycaster = new THREE39__namespace.Raycaster(rayOrigin, rayDirection, near, far);
11575
12132
  const intersections = raycaster.intersectObjects(
11576
12133
  this.scene.children,
11577
12134
  true
@@ -12224,6 +12781,10 @@ function serializeEntitySubtree(world, rootId, options) {
12224
12781
  __name(serializeEntitySubtree, "serializeEntitySubtree");
12225
12782
 
12226
12783
  exports.ADDED_NODE_MARKER_COMPONENT = ADDED_NODE_MARKER_COMPONENT;
12784
+ exports.ARC_GRAVITY = ARC_GRAVITY;
12785
+ exports.ARC_MAX_TIME = ARC_MAX_TIME;
12786
+ exports.ARC_SPEED = ARC_SPEED;
12787
+ exports.ARC_STEPS = ARC_STEPS;
12227
12788
  exports.AnimationStateMachine = AnimationStateMachine;
12228
12789
  exports.AnimationStateManager = AnimationStateManager;
12229
12790
  exports.AnimationSystem = AnimationSystem;
@@ -12265,7 +12826,10 @@ exports.XRInputSystem = XRInputSystem;
12265
12826
  exports.XRInteractionSystem = XRInteractionSystem;
12266
12827
  exports.XRLocomotionSystem = XRLocomotionSystem;
12267
12828
  exports.XRSessionSystem = XRSessionSystem;
12829
+ exports.XRTeleportVisualSystem = XRTeleportVisualSystem;
12830
+ exports.applyHandMaterial = applyHandMaterial;
12268
12831
  exports.applyPrefabToSnapshotInstances = applyPrefabToSnapshotInstances;
12832
+ exports.arcGroundCrossing = arcGroundCrossing;
12269
12833
  exports.buildComponentValueMaps = buildComponentValueMaps;
12270
12834
  exports.buildNodeKeyMapsFromSnapshot = buildNodeKeyMapsFromSnapshot;
12271
12835
  exports.buildNodeMapsFromSnapshot = buildNodeMapsFromSnapshot;
@@ -12282,6 +12846,7 @@ exports.createAudioComponent = createAudioComponent;
12282
12846
  exports.createCameraComponent = createCameraComponent;
12283
12847
  exports.createEntityTypeComponent = createEntityTypeComponent;
12284
12848
  exports.createEnvironmentComponent = createEnvironmentComponent;
12849
+ exports.createHandMaterial = createHandMaterial;
12285
12850
  exports.createImageComponent = createImageComponent;
12286
12851
  exports.createImageTargetAnchorComponent = createImageTargetAnchorComponent;
12287
12852
  exports.createImageTargetComponent = createImageTargetComponent;
@@ -12306,6 +12871,8 @@ exports.createTransformComponent = createTransformComponent;
12306
12871
  exports.createVRTeleportAreaComponent = createVRTeleportAreaComponent;
12307
12872
  exports.createVideoComponent = createVideoComponent;
12308
12873
  exports.createXRInteractableComponent = createXRInteractableComponent;
12874
+ exports.createXRInteractorComponent = createXRInteractorComponent;
12875
+ exports.createXRInteractorSideComponent = createXRInteractorSideComponent;
12309
12876
  exports.createXRRigComponent = createXRRigComponent;
12310
12877
  exports.decanonicalizeComponentValue = decanonicalizeComponentValue;
12311
12878
  exports.despawnPrefab = despawnPrefab;
@@ -12330,6 +12897,7 @@ exports.remapSnapshotEntityIds = remapSnapshotEntityIds;
12330
12897
  exports.resolveDracoDecoderPath = resolveDracoDecoderPath;
12331
12898
  exports.restoreComponentState = restoreComponentState;
12332
12899
  exports.restorePostCreateComponents = restorePostCreateComponents;
12900
+ exports.sampleTeleportArc = sampleTeleportArc;
12333
12901
  exports.serializeEntitySubtree = serializeEntitySubtree;
12334
12902
  exports.setDracoDecoderPath = setDracoDecoderPath;
12335
12903
  exports.setPrefabAssetUrlResolver = setPrefabAssetUrlResolver;