@relu-interactives/spatial-ecs 0.3.0 → 0.3.2

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 (45) hide show
  1. package/dist/{System-CYWZ_Zx5.d.cts → System-vrU46Vuw.d.cts} +16 -2
  2. package/dist/{System-CYWZ_Zx5.d.ts → System-vrU46Vuw.d.ts} +16 -2
  3. package/dist/{Video-AIQYTAAr.d.cts → XRRig-CAmf04NX.d.ts} +131 -4
  4. package/dist/{Video-DlZ4G9ig.d.ts → XRRig-Cu-EyliG.d.cts} +131 -4
  5. package/dist/{chunk-PZ4CAALA.js → chunk-67WGASUJ.js} +3 -3
  6. package/dist/{chunk-PZ4CAALA.js.map → chunk-67WGASUJ.js.map} +1 -1
  7. package/dist/{chunk-AT5SPSPM.js → chunk-JWTRFJBL.js} +168 -83
  8. package/dist/chunk-JWTRFJBL.js.map +1 -0
  9. package/dist/{chunk-7JFSEV7A.js → chunk-SALBG747.js} +757 -6
  10. package/dist/chunk-SALBG747.js.map +1 -0
  11. package/dist/{chunk-7BPHZWQ6.js → chunk-U3MDYKPV.js} +47 -3
  12. package/dist/chunk-U3MDYKPV.js.map +1 -0
  13. package/dist/components/index.cjs +44 -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 +236 -107
  19. package/dist/factories/index.cjs.map +1 -1
  20. package/dist/factories/index.d.cts +9 -3
  21. package/dist/factories/index.d.ts +9 -3
  22. package/dist/factories/index.js +3 -3
  23. package/dist/index-Bc0YCz1A.d.cts +514 -0
  24. package/dist/index-CRmfSYdj.d.ts +514 -0
  25. package/dist/{index-Gr8aCPRM.d.cts → index-CUFd71ri.d.cts} +12 -3
  26. package/dist/{index-BwiRJNIT.d.ts → index-w1oqWl_M.d.ts} +12 -3
  27. package/dist/index.cjs +1107 -198
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +42 -8
  30. package/dist/index.d.ts +42 -8
  31. package/dist/index.js +26 -8
  32. package/dist/index.js.map +1 -1
  33. package/dist/systems/index.cjs +799 -1
  34. package/dist/systems/index.cjs.map +1 -1
  35. package/dist/systems/index.d.cts +3 -278
  36. package/dist/systems/index.d.ts +3 -278
  37. package/dist/systems/index.js +3 -3
  38. package/dist/types.d.cts +1 -1
  39. package/dist/types.d.ts +1 -1
  40. package/dist/worldSnapshotUtils.d.cts +1 -1
  41. package/dist/worldSnapshotUtils.d.ts +1 -1
  42. package/package.json +1 -1
  43. package/dist/chunk-7BPHZWQ6.js.map +0 -1
  44. package/dist/chunk-7JFSEV7A.js.map +0 -1
  45. package/dist/chunk-AT5SPSPM.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var THREE36 = require('three');
3
+ var THREE38 = 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');
@@ -19,6 +19,8 @@ var OutputPass_js = require('three/examples/jsm/postprocessing/OutputPass.js');
19
19
  var HueSaturationShader_js = require('three/examples/jsm/shaders/HueSaturationShader.js');
20
20
  var SepiaShader_js = require('three/examples/jsm/shaders/SepiaShader.js');
21
21
  var VignetteShader_js = require('three/examples/jsm/shaders/VignetteShader.js');
22
+ var XRControllerModelFactory_js = require('three/examples/jsm/webxr/XRControllerModelFactory.js');
23
+ var XRHandModelFactory_js = require('three/examples/jsm/webxr/XRHandModelFactory.js');
22
24
 
23
25
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
24
26
  function _interopNamespace(e) {
@@ -39,7 +41,7 @@ function _interopNamespace(e) {
39
41
  return Object.freeze(n);
40
42
  }
41
43
 
42
- var THREE36__namespace = /*#__PURE__*/_interopNamespace(THREE36);
44
+ var THREE38__namespace = /*#__PURE__*/_interopNamespace(THREE38);
43
45
 
44
46
  var __defProp = Object.defineProperty;
45
47
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
@@ -603,14 +605,14 @@ var _AnimationComponent = class _AnimationComponent extends Component {
603
605
  return;
604
606
  }
605
607
  this.importedClips = clips.map((entry) => {
606
- if (entry instanceof THREE36__namespace.AnimationClip) {
608
+ if (entry instanceof THREE38__namespace.AnimationClip) {
607
609
  return { clip: entry, sourceUrl: null };
608
610
  }
609
611
  if (!entry || typeof entry !== "object") {
610
612
  return null;
611
613
  }
612
614
  const candidate = entry;
613
- if (!(candidate.clip instanceof THREE36__namespace.AnimationClip)) {
615
+ if (!(candidate.clip instanceof THREE38__namespace.AnimationClip)) {
614
616
  return null;
615
617
  }
616
618
  return {
@@ -818,11 +820,11 @@ function normalizeDistanceModel(distanceModel) {
818
820
  }
819
821
  __name(normalizeDistanceModel, "normalizeDistanceModel");
820
822
  function createConfiguredAudio(listener, options) {
821
- const sound = options.positional ? new THREE36__namespace.PositionalAudio(listener) : new THREE36__namespace.Audio(listener);
823
+ const sound = options.positional ? new THREE38__namespace.PositionalAudio(listener) : new THREE38__namespace.Audio(listener);
822
824
  sound.setLoop(options.loop);
823
825
  sound.setVolume(options.volume);
824
826
  sound.setPlaybackRate(options.pitch);
825
- if (sound instanceof THREE36__namespace.PositionalAudio) {
827
+ if (sound instanceof THREE38__namespace.PositionalAudio) {
826
828
  sound.setRefDistance(options.refDistance);
827
829
  sound.setDistanceModel(normalizeDistanceModel(options.distanceModel));
828
830
  sound.setRolloffFactor(options.rolloffFactor);
@@ -832,16 +834,16 @@ function createConfiguredAudio(listener, options) {
832
834
  __name(createConfiguredAudio, "createConfiguredAudio");
833
835
  function createAudioEditorHelper() {
834
836
  if (typeof document === "undefined") {
835
- const geometry = new THREE36__namespace.EdgesGeometry(
836
- new THREE36__namespace.OctahedronGeometry(0.22, 0)
837
+ const geometry = new THREE38__namespace.EdgesGeometry(
838
+ new THREE38__namespace.OctahedronGeometry(0.22, 0)
837
839
  );
838
- const material2 = new THREE36__namespace.LineBasicMaterial({
840
+ const material2 = new THREE38__namespace.LineBasicMaterial({
839
841
  color: "#8bc8ff",
840
842
  transparent: true,
841
843
  opacity: 0.95,
842
844
  depthTest: false
843
845
  });
844
- const fallback = new THREE36__namespace.LineSegments(geometry, material2);
846
+ const fallback = new THREE38__namespace.LineSegments(geometry, material2);
845
847
  fallback.renderOrder = 10;
846
848
  fallback.userData.ecsHelper = true;
847
849
  fallback.visible = false;
@@ -853,7 +855,7 @@ function createAudioEditorHelper() {
853
855
  canvas.height = size;
854
856
  const ctx = canvas.getContext("2d");
855
857
  if (!ctx) {
856
- return new THREE36__namespace.Object3D();
858
+ return new THREE38__namespace.Object3D();
857
859
  }
858
860
  ctx.clearRect(0, 0, size, size);
859
861
  ctx.fillStyle = "rgba(27, 35, 52, 0.9)";
@@ -884,14 +886,14 @@ function createAudioEditorHelper() {
884
886
  ctx.beginPath();
885
887
  ctx.arc(56, 48, 16, -0.8, 0.8);
886
888
  ctx.stroke();
887
- const texture = new THREE36__namespace.CanvasTexture(canvas);
889
+ const texture = new THREE38__namespace.CanvasTexture(canvas);
888
890
  texture.needsUpdate = true;
889
- const material = new THREE36__namespace.SpriteMaterial({
891
+ const material = new THREE38__namespace.SpriteMaterial({
890
892
  map: texture,
891
893
  transparent: true,
892
894
  depthTest: false
893
895
  });
894
- const helper = new THREE36__namespace.Sprite(material);
896
+ const helper = new THREE38__namespace.Sprite(material);
895
897
  helper.scale.set(0.68, 0.68, 0.68);
896
898
  helper.renderOrder = 10;
897
899
  helper.userData.ecsHelper = true;
@@ -925,7 +927,7 @@ var DEFAULT_ORTHO_TOP = 5;
925
927
  var DEFAULT_ORTHO_BOTTOM = -5;
926
928
  var DEFAULT_ZOOM = 1;
927
929
  function inferProjection(camera) {
928
- if (camera instanceof THREE36__namespace.OrthographicCamera) {
930
+ if (camera instanceof THREE38__namespace.OrthographicCamera) {
929
931
  return "orthographic";
930
932
  }
931
933
  return "perspective";
@@ -946,7 +948,7 @@ function readCameraFar(camera) {
946
948
  }
947
949
  __name(readCameraFar, "readCameraFar");
948
950
  function inferFov(camera) {
949
- if (camera instanceof THREE36__namespace.PerspectiveCamera && Number.isFinite(camera.fov)) {
951
+ if (camera instanceof THREE38__namespace.PerspectiveCamera && Number.isFinite(camera.fov)) {
950
952
  return camera.fov;
951
953
  }
952
954
  return DEFAULT_FOV;
@@ -969,28 +971,28 @@ function inferFar(camera) {
969
971
  }
970
972
  __name(inferFar, "inferFar");
971
973
  function inferOrthoLeft(camera) {
972
- if (camera instanceof THREE36__namespace.OrthographicCamera && Number.isFinite(camera.left)) {
974
+ if (camera instanceof THREE38__namespace.OrthographicCamera && Number.isFinite(camera.left)) {
973
975
  return camera.left;
974
976
  }
975
977
  return DEFAULT_ORTHO_LEFT;
976
978
  }
977
979
  __name(inferOrthoLeft, "inferOrthoLeft");
978
980
  function inferOrthoRight(camera) {
979
- if (camera instanceof THREE36__namespace.OrthographicCamera && Number.isFinite(camera.right)) {
981
+ if (camera instanceof THREE38__namespace.OrthographicCamera && Number.isFinite(camera.right)) {
980
982
  return camera.right;
981
983
  }
982
984
  return DEFAULT_ORTHO_RIGHT;
983
985
  }
984
986
  __name(inferOrthoRight, "inferOrthoRight");
985
987
  function inferOrthoTop(camera) {
986
- if (camera instanceof THREE36__namespace.OrthographicCamera && Number.isFinite(camera.top)) {
988
+ if (camera instanceof THREE38__namespace.OrthographicCamera && Number.isFinite(camera.top)) {
987
989
  return camera.top;
988
990
  }
989
991
  return DEFAULT_ORTHO_TOP;
990
992
  }
991
993
  __name(inferOrthoTop, "inferOrthoTop");
992
994
  function inferOrthoBottom(camera) {
993
- if (camera instanceof THREE36__namespace.OrthographicCamera && Number.isFinite(camera.bottom)) {
995
+ if (camera instanceof THREE38__namespace.OrthographicCamera && Number.isFinite(camera.bottom)) {
994
996
  return camera.bottom;
995
997
  }
996
998
  return DEFAULT_ORTHO_BOTTOM;
@@ -1006,7 +1008,7 @@ __name(inferZoom, "inferZoom");
1006
1008
  var _CameraComponent = class _CameraComponent extends Component {
1007
1009
  constructor(payload = {}) {
1008
1010
  super();
1009
- this.camera = payload.camera ?? new THREE36__namespace.PerspectiveCamera();
1011
+ this.camera = payload.camera ?? new THREE38__namespace.PerspectiveCamera();
1010
1012
  this.type = payload.type ?? "3d";
1011
1013
  this.isDefault = typeof payload.isDefault === "boolean" ? payload.isDefault : false;
1012
1014
  this.projection = payload.projection ?? inferProjection(payload.camera);
@@ -1037,7 +1039,7 @@ var Object3DRef = _Object3DRef;
1037
1039
  // core/factories/components/CameraFactory.ts
1038
1040
  function createCameraComponent(world, entityId, payload = {}) {
1039
1041
  const object = world.getComponent(entityId, Object3DRef)?.object;
1040
- const objectCamera = object instanceof THREE36__namespace.Camera ? object : void 0;
1042
+ const objectCamera = object instanceof THREE38__namespace.Camera ? object : void 0;
1041
1043
  const component = new CameraComponent({
1042
1044
  ...payload,
1043
1045
  camera: payload.camera ?? objectCamera
@@ -1607,15 +1609,15 @@ function createValueState(light) {
1607
1609
  castShadow: light.castShadow ?? false,
1608
1610
  frustumCulling: light.frustumCulled
1609
1611
  };
1610
- if (light instanceof THREE36__namespace.PointLight) {
1612
+ if (light instanceof THREE38__namespace.PointLight) {
1611
1613
  base.distance = light.distance;
1612
1614
  base.decay = light.decay;
1613
- } else if (light instanceof THREE36__namespace.SpotLight) {
1615
+ } else if (light instanceof THREE38__namespace.SpotLight) {
1614
1616
  base.distance = light.distance;
1615
1617
  base.decay = light.decay;
1616
1618
  base.angle = light.angle;
1617
1619
  base.penumbra = light.penumbra;
1618
- } else if (light instanceof THREE36__namespace.RectAreaLight) {
1620
+ } else if (light instanceof THREE38__namespace.RectAreaLight) {
1619
1621
  base.width = light.width;
1620
1622
  base.height = light.height;
1621
1623
  }
@@ -1658,13 +1660,13 @@ function toHexColor2(value, fallback) {
1658
1660
  }
1659
1661
  __name(toHexColor2, "toHexColor");
1660
1662
  function getMaterialType(material) {
1661
- if (material instanceof THREE36__namespace.MeshPhysicalMaterial) {
1663
+ if (material instanceof THREE38__namespace.MeshPhysicalMaterial) {
1662
1664
  return "physical";
1663
1665
  }
1664
- if (material instanceof THREE36__namespace.MeshPhongMaterial) {
1666
+ if (material instanceof THREE38__namespace.MeshPhongMaterial) {
1665
1667
  return "phong";
1666
1668
  }
1667
- if (material instanceof THREE36__namespace.MeshBasicMaterial) {
1669
+ if (material instanceof THREE38__namespace.MeshBasicMaterial) {
1668
1670
  return "basic";
1669
1671
  }
1670
1672
  return "standard";
@@ -1699,8 +1701,8 @@ function createMaterialValue(material) {
1699
1701
  opacity: typeof materialRecord.opacity === "number" ? materialRecord.opacity : 1,
1700
1702
  emissive: toHexColor2(materialRecord.emissive, "#000000"),
1701
1703
  emissiveIntensity: typeof materialRecord.emissiveIntensity === "number" ? materialRecord.emissiveIntensity : 0,
1702
- side: typeof materialRecord.side === "number" ? materialRecord.side : THREE36__namespace.FrontSide,
1703
- blending: typeof materialRecord.blending === "number" ? materialRecord.blending : THREE36__namespace.NormalBlending,
1704
+ side: typeof materialRecord.side === "number" ? materialRecord.side : THREE38__namespace.FrontSide,
1705
+ blending: typeof materialRecord.blending === "number" ? materialRecord.blending : THREE38__namespace.NormalBlending,
1704
1706
  depthTest: materialRecord.depthTest !== false,
1705
1707
  depthWrite: materialRecord.depthWrite !== false,
1706
1708
  wireframe: Boolean(materialRecord.wireframe),
@@ -1732,7 +1734,7 @@ function createMaterialValue(material) {
1732
1734
  materialRecord.lightMap
1733
1735
  ),
1734
1736
  envMap: textureImageSrc(materialRecord.envMap),
1735
- textureFiltering: map?.magFilter === THREE36__namespace.NearestFilter ? "sharp" : "smooth",
1737
+ textureFiltering: map?.magFilter === THREE38__namespace.NearestFilter ? "sharp" : "smooth",
1736
1738
  useMipmaps: map?.generateMipmaps !== false
1737
1739
  };
1738
1740
  }
@@ -1747,8 +1749,8 @@ function defaultMaterialValue() {
1747
1749
  opacity: 1,
1748
1750
  emissive: "#000000",
1749
1751
  emissiveIntensity: 0,
1750
- side: THREE36__namespace.FrontSide,
1751
- blending: THREE36__namespace.NormalBlending,
1752
+ side: THREE38__namespace.FrontSide,
1753
+ blending: THREE38__namespace.NormalBlending,
1752
1754
  depthTest: true,
1753
1755
  depthWrite: true,
1754
1756
  wireframe: false,
@@ -2325,14 +2327,14 @@ var _TransformComponent = class _TransformComponent extends Component {
2325
2327
  z: scale.z ?? 1
2326
2328
  };
2327
2329
  }
2328
- toPositionVector3(target = new THREE36.Vector3()) {
2330
+ toPositionVector3(target = new THREE38.Vector3()) {
2329
2331
  return target.set(this.position.x, this.position.y, this.position.z);
2330
2332
  }
2331
- toRotationEuler(target = new THREE36.Euler(), order = "XYZ") {
2333
+ toRotationEuler(target = new THREE38.Euler(), order = "XYZ") {
2332
2334
  return target.set(this.rotation.x, this.rotation.y, this.rotation.z, order);
2333
2335
  }
2334
- toRotationQuaternion(target = new THREE36.Quaternion(), order = "XYZ") {
2335
- const euler = new THREE36.Euler(
2336
+ toRotationQuaternion(target = new THREE38.Quaternion(), order = "XYZ") {
2337
+ const euler = new THREE38.Euler(
2336
2338
  this.rotation.x,
2337
2339
  this.rotation.y,
2338
2340
  this.rotation.z,
@@ -2340,7 +2342,7 @@ var _TransformComponent = class _TransformComponent extends Component {
2340
2342
  );
2341
2343
  return target.setFromEuler(euler);
2342
2344
  }
2343
- toScaleVector3(target = new THREE36.Vector3()) {
2345
+ toScaleVector3(target = new THREE38.Vector3()) {
2344
2346
  return target.set(this.scale.x, this.scale.y, this.scale.z);
2345
2347
  }
2346
2348
  setPosition(input) {
@@ -2358,8 +2360,8 @@ var _TransformComponent = class _TransformComponent extends Component {
2358
2360
  return this;
2359
2361
  }
2360
2362
  setRotation(input, order = "XYZ") {
2361
- if (input instanceof THREE36.Quaternion) {
2362
- const euler = new THREE36.Euler().setFromQuaternion(input, order);
2363
+ if (input instanceof THREE38.Quaternion) {
2364
+ const euler = new THREE38.Euler().setFromQuaternion(input, order);
2363
2365
  this.rotation.x = euler.x;
2364
2366
  this.rotation.y = euler.y;
2365
2367
  this.rotation.z = euler.z;
@@ -2564,6 +2566,71 @@ function createVideoComponent(world, entityId, ...args) {
2564
2566
  }
2565
2567
  __name(createVideoComponent, "createVideoComponent");
2566
2568
 
2569
+ // core/components/XRRig.ts
2570
+ var _XRRigComponent = class _XRRigComponent extends Component {
2571
+ constructor(options) {
2572
+ super();
2573
+ this.locomotion = options?.locomotion ?? "teleport";
2574
+ this.moveSpeed = options?.moveSpeed ?? 2;
2575
+ this.snapTurn = options?.snapTurn ?? true;
2576
+ this.snapTurnDegrees = options?.snapTurnDegrees ?? 30;
2577
+ this.fallbackEyeHeight = options?.fallbackEyeHeight ?? 1.6;
2578
+ }
2579
+ };
2580
+ __name(_XRRigComponent, "XRRigComponent");
2581
+ var XRRigComponent = _XRRigComponent;
2582
+
2583
+ // core/factories/components/XRRigFactory.ts
2584
+ function createXRRigComponent(world, entityId, ...args) {
2585
+ const component = new XRRigComponent(...args);
2586
+ world.addComponent(entityId, component);
2587
+ return component;
2588
+ }
2589
+ __name(createXRRigComponent, "createXRRigComponent");
2590
+
2591
+ // core/components/VRTeleportArea.ts
2592
+ var _VRTeleportAreaComponent = class _VRTeleportAreaComponent extends Component {
2593
+ constructor(options) {
2594
+ super();
2595
+ this.enabled = options?.enabled ?? true;
2596
+ this.shape = options?.shape ?? "plane";
2597
+ this.width = options?.width ?? 10;
2598
+ this.depth = options?.depth ?? 10;
2599
+ }
2600
+ };
2601
+ __name(_VRTeleportAreaComponent, "VRTeleportAreaComponent");
2602
+ var VRTeleportAreaComponent = _VRTeleportAreaComponent;
2603
+
2604
+ // core/factories/components/VRTeleportAreaFactory.ts
2605
+ function createVRTeleportAreaComponent(world, entityId, ...args) {
2606
+ const component = new VRTeleportAreaComponent(...args);
2607
+ world.addComponent(entityId, component);
2608
+ return component;
2609
+ }
2610
+ __name(createVRTeleportAreaComponent, "createVRTeleportAreaComponent");
2611
+
2612
+ // core/components/XRInteractable.ts
2613
+ var _XRInteractableComponent = class _XRInteractableComponent extends Component {
2614
+ constructor(options) {
2615
+ super();
2616
+ this.enabled = options?.enabled ?? true;
2617
+ this.grabbable = options?.grabbable ?? true;
2618
+ this.pointable = options?.pointable ?? true;
2619
+ this.grabMode = options?.grabMode ?? "kinematic";
2620
+ this.highlightOnHover = options?.highlightOnHover ?? true;
2621
+ }
2622
+ };
2623
+ __name(_XRInteractableComponent, "XRInteractableComponent");
2624
+ var XRInteractableComponent = _XRInteractableComponent;
2625
+
2626
+ // core/factories/components/XRInteractableFactory.ts
2627
+ function createXRInteractableComponent(world, entityId, ...args) {
2628
+ const component = new XRInteractableComponent(...args);
2629
+ world.addComponent(entityId, component);
2630
+ return component;
2631
+ }
2632
+ __name(createXRInteractableComponent, "createXRInteractableComponent");
2633
+
2567
2634
  // core/factories/registerDefaultComponentFactories.ts
2568
2635
  function registerDefaultComponentFactories(objectManagementSystem) {
2569
2636
  objectManagementSystem.registerComponentFactory("animation", createAnimationComponent);
@@ -2573,6 +2640,9 @@ function registerDefaultComponentFactories(objectManagementSystem) {
2573
2640
  objectManagementSystem.registerComponentFactory("environment", createEnvironmentComponent);
2574
2641
  objectManagementSystem.registerComponentFactory("entityType", createEntityTypeComponent);
2575
2642
  objectManagementSystem.registerComponentFactory("image", createImageComponent);
2643
+ objectManagementSystem.registerComponentFactory("xrRig", createXRRigComponent);
2644
+ objectManagementSystem.registerComponentFactory("vrTeleportArea", createVRTeleportAreaComponent);
2645
+ objectManagementSystem.registerComponentFactory("xrInteractable", createXRInteractableComponent);
2576
2646
  objectManagementSystem.registerComponentFactory(
2577
2647
  "imageTargetAnchor",
2578
2648
  createImageTargetAnchorComponent
@@ -2616,7 +2686,7 @@ var SHARED_MODEL_RESOURCE_FLAG = "spatialEcsSharedModelResource";
2616
2686
  var modelCache = /* @__PURE__ */ new Map();
2617
2687
  function markSharedResources(root) {
2618
2688
  root.traverse((child) => {
2619
- if (!(child instanceof THREE36__namespace.Mesh)) {
2689
+ if (!(child instanceof THREE38__namespace.Mesh)) {
2620
2690
  return;
2621
2691
  }
2622
2692
  if (child.geometry) {
@@ -2695,10 +2765,10 @@ var _ObjectManagementSystem = class _ObjectManagementSystem {
2695
2765
  }
2696
2766
  getOrCreateAudioListener() {
2697
2767
  const existing = this.camera.userData.ecsAudioListener;
2698
- if (existing instanceof THREE36__namespace.AudioListener) {
2768
+ if (existing instanceof THREE38__namespace.AudioListener) {
2699
2769
  return existing;
2700
2770
  }
2701
- const listener = new THREE36__namespace.AudioListener();
2771
+ const listener = new THREE38__namespace.AudioListener();
2702
2772
  this.camera.add(listener);
2703
2773
  this.camera.userData.ecsAudioListener = listener;
2704
2774
  return listener;
@@ -2772,7 +2842,7 @@ var _ObjectManagementSystem = class _ObjectManagementSystem {
2772
2842
  }
2773
2843
  if (dispose && object3d) {
2774
2844
  object3d.traverse((child) => {
2775
- if (child instanceof THREE36__namespace.Mesh) {
2845
+ if (child instanceof THREE38__namespace.Mesh) {
2776
2846
  if (!child.geometry?.userData?.[SHARED_MODEL_RESOURCE_FLAG]) {
2777
2847
  child.geometry?.dispose();
2778
2848
  }
@@ -2909,10 +2979,10 @@ __name(createBaseEntity, "createBaseEntity");
2909
2979
  // core/factories/objects/AudioFactory.ts
2910
2980
  function getOrCreateListener(camera) {
2911
2981
  const existing = camera.userData.ecsAudioListener;
2912
- if (existing instanceof THREE36__namespace.AudioListener) {
2982
+ if (existing instanceof THREE38__namespace.AudioListener) {
2913
2983
  return existing;
2914
2984
  }
2915
- const listener = new THREE36__namespace.AudioListener();
2985
+ const listener = new THREE38__namespace.AudioListener();
2916
2986
  camera.add(listener);
2917
2987
  camera.userData.ecsAudioListener = listener;
2918
2988
  return listener;
@@ -2925,7 +2995,7 @@ function createAudio({
2925
2995
  payload,
2926
2996
  isEditor
2927
2997
  }) {
2928
- const anchor = new THREE36__namespace.Object3D();
2998
+ const anchor = new THREE38__namespace.Object3D();
2929
2999
  const entityId = createBaseEntity(world, anchor, {
2930
3000
  label: payload.name ?? "Audio",
2931
3001
  entityType: "audio",
@@ -2947,7 +3017,7 @@ function createAudio({
2947
3017
  return entityId;
2948
3018
  }
2949
3019
  if (!isEditor) {
2950
- const loader = new THREE36__namespace.AudioLoader();
3020
+ const loader = new THREE38__namespace.AudioLoader();
2951
3021
  loader.load(
2952
3022
  audio.path,
2953
3023
  (buffer) => {
@@ -3022,7 +3092,7 @@ function applyCameraSettings(camera, options) {
3022
3092
  const near = typeof options.near === "number" ? options.near : DEFAULT_NEAR2;
3023
3093
  const far = typeof options.far === "number" ? options.far : DEFAULT_FAR2;
3024
3094
  const projection = options.projection;
3025
- if (camera instanceof THREE36__namespace.PerspectiveCamera) {
3095
+ if (camera instanceof THREE38__namespace.PerspectiveCamera) {
3026
3096
  if (!projection || projection === "perspective") {
3027
3097
  camera.fov = typeof options.fov === "number" ? options.fov : DEFAULT_FOV2;
3028
3098
  }
@@ -3032,7 +3102,7 @@ function applyCameraSettings(camera, options) {
3032
3102
  camera.updateProjectionMatrix();
3033
3103
  return;
3034
3104
  }
3035
- if (camera instanceof THREE36__namespace.OrthographicCamera) {
3105
+ if (camera instanceof THREE38__namespace.OrthographicCamera) {
3036
3106
  camera.left = typeof options.left === "number" ? options.left : -DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
3037
3107
  camera.right = typeof options.right === "number" ? options.right : DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
3038
3108
  camera.top = typeof options.top === "number" ? options.top : DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
@@ -3053,7 +3123,7 @@ function createCameraObject(options) {
3053
3123
  const bottom = options.bottom ?? -DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
3054
3124
  const left = options.left ?? -DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
3055
3125
  const right = options.right ?? DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
3056
- const camera = new THREE36__namespace.OrthographicCamera(
3126
+ const camera = new THREE38__namespace.OrthographicCamera(
3057
3127
  left,
3058
3128
  right,
3059
3129
  top,
@@ -3065,7 +3135,7 @@ function createCameraObject(options) {
3065
3135
  camera.updateProjectionMatrix();
3066
3136
  return camera;
3067
3137
  }
3068
- return new THREE36__namespace.PerspectiveCamera(
3138
+ return new THREE38__namespace.PerspectiveCamera(
3069
3139
  options.fov ?? DEFAULT_FOV2,
3070
3140
  readViewportAspect(),
3071
3141
  near,
@@ -3083,7 +3153,7 @@ function createCamera({ world, scene, camera, payload, isEditor }) {
3083
3153
  transformInput: payload.transform
3084
3154
  });
3085
3155
  const objectRef = world.getComponent(entityId, Object3DRef);
3086
- if (objectRef?.object instanceof THREE36__namespace.Camera) {
3156
+ if (objectRef?.object instanceof THREE38__namespace.Camera) {
3087
3157
  objectRef.object.userData.entityId = entityId;
3088
3158
  }
3089
3159
  const componentOptions = {
@@ -3115,9 +3185,9 @@ function createCapsule({
3115
3185
  scene,
3116
3186
  payload
3117
3187
  }) {
3118
- const geometry = new THREE36__namespace.CapsuleGeometry(0.5, 1, 4, 8);
3119
- const material = new THREE36__namespace.MeshStandardMaterial({ color: "#ffffff" });
3120
- const mesh = new THREE36__namespace.Mesh(geometry, material);
3188
+ const geometry = new THREE38__namespace.CapsuleGeometry(0.5, 1, 4, 8);
3189
+ const material = new THREE38__namespace.MeshStandardMaterial({ color: "#ffffff" });
3190
+ const mesh = new THREE38__namespace.Mesh(geometry, material);
3121
3191
  const entityId = createBaseEntity(world, mesh, {
3122
3192
  label: payload.name ?? "Capsule",
3123
3193
  entityType: "capsule",
@@ -3137,9 +3207,9 @@ function createCapsule({
3137
3207
  }
3138
3208
  __name(createCapsule, "createCapsule");
3139
3209
  function createCube({ world, scene, payload }) {
3140
- const geometry = new THREE36__namespace.BoxGeometry(1, 1, 1);
3141
- const material = new THREE36__namespace.MeshStandardMaterial({ color: "#ffffff" });
3142
- const mesh = new THREE36__namespace.Mesh(geometry, material);
3210
+ const geometry = new THREE38__namespace.BoxGeometry(1, 1, 1);
3211
+ const material = new THREE38__namespace.MeshStandardMaterial({ color: "#ffffff" });
3212
+ const mesh = new THREE38__namespace.Mesh(geometry, material);
3143
3213
  const entityId = createBaseEntity(world, mesh, {
3144
3214
  label: payload.name ?? "Cube",
3145
3215
  entityType: "cube",
@@ -3164,9 +3234,9 @@ function createCylinder({
3164
3234
  scene,
3165
3235
  payload
3166
3236
  }) {
3167
- const geometry = new THREE36__namespace.CylinderGeometry(0.5, 0.5, 1, 20);
3168
- const material = new THREE36__namespace.MeshStandardMaterial({ color: "#ffffff" });
3169
- const mesh = new THREE36__namespace.Mesh(geometry, material);
3237
+ const geometry = new THREE38__namespace.CylinderGeometry(0.5, 0.5, 1, 20);
3238
+ const material = new THREE38__namespace.MeshStandardMaterial({ color: "#ffffff" });
3239
+ const mesh = new THREE38__namespace.Mesh(geometry, material);
3170
3240
  const entityId = createBaseEntity(world, mesh, {
3171
3241
  label: payload.name ?? "Cylinder",
3172
3242
  entityType: "cylinder",
@@ -3186,7 +3256,7 @@ function createCylinder({
3186
3256
  }
3187
3257
  __name(createCylinder, "createCylinder");
3188
3258
  function createEmpty({ world, scene, payload, isEditor }) {
3189
- const object = new THREE36__namespace.Group();
3259
+ const object = new THREE38__namespace.Group();
3190
3260
  const entityId = createBaseEntity(world, object, {
3191
3261
  label: payload.name ?? "Empty",
3192
3262
  entityType: "empty",
@@ -3197,7 +3267,7 @@ function createEmpty({ world, scene, payload, isEditor }) {
3197
3267
  }
3198
3268
  __name(createEmpty, "createEmpty");
3199
3269
  function createImage({ world, scene, payload }) {
3200
- const anchor = new THREE36__namespace.Object3D();
3270
+ const anchor = new THREE38__namespace.Object3D();
3201
3271
  const imagePath = payload.path ?? "";
3202
3272
  const entityId = createBaseEntity(world, anchor, {
3203
3273
  label: payload.name ?? "Image",
@@ -3210,7 +3280,7 @@ function createImage({ world, scene, payload }) {
3210
3280
  if (!imagePath) {
3211
3281
  return entityId;
3212
3282
  }
3213
- const loader = new THREE36__namespace.TextureLoader();
3283
+ const loader = new THREE38__namespace.TextureLoader();
3214
3284
  loader.load(
3215
3285
  imagePath,
3216
3286
  (texture) => {
@@ -3218,13 +3288,13 @@ function createImage({ world, scene, payload }) {
3218
3288
  texture.dispose();
3219
3289
  return;
3220
3290
  }
3221
- const material = new THREE36__namespace.MeshBasicMaterial({
3291
+ const material = new THREE38__namespace.MeshBasicMaterial({
3222
3292
  map: texture,
3223
3293
  transparent: true,
3224
- side: THREE36__namespace.DoubleSide
3294
+ side: THREE38__namespace.DoubleSide
3225
3295
  });
3226
- const geometry = new THREE36__namespace.PlaneGeometry(1, 1);
3227
- const plane = new THREE36__namespace.Mesh(geometry, material);
3296
+ const geometry = new THREE38__namespace.PlaneGeometry(1, 1);
3297
+ const plane = new THREE38__namespace.Mesh(geometry, material);
3228
3298
  plane.userData.entityId = entityId;
3229
3299
  const textureImage = texture.image;
3230
3300
  const width = textureImage?.width ?? 1;
@@ -3270,7 +3340,7 @@ function createImageTarget({
3270
3340
  payload,
3271
3341
  isEditor
3272
3342
  }) {
3273
- const anchor = new THREE36__namespace.Object3D();
3343
+ const anchor = new THREE38__namespace.Object3D();
3274
3344
  const imagePath = payload.path ?? "";
3275
3345
  const entityId = createBaseEntity(world, anchor, {
3276
3346
  label: payload.name ?? "Image Target",
@@ -3287,7 +3357,7 @@ function createImageTarget({
3287
3357
  if (!isEditor || !imagePath) {
3288
3358
  return entityId;
3289
3359
  }
3290
- const loader = new THREE36__namespace.TextureLoader();
3360
+ const loader = new THREE38__namespace.TextureLoader();
3291
3361
  loader.load(
3292
3362
  imagePath,
3293
3363
  (texture) => {
@@ -3295,13 +3365,13 @@ function createImageTarget({
3295
3365
  texture.dispose();
3296
3366
  return;
3297
3367
  }
3298
- const material = new THREE36__namespace.MeshBasicMaterial({
3368
+ const material = new THREE38__namespace.MeshBasicMaterial({
3299
3369
  map: texture,
3300
3370
  transparent: true,
3301
- side: THREE36__namespace.DoubleSide
3371
+ side: THREE38__namespace.DoubleSide
3302
3372
  });
3303
- const geometry = new THREE36__namespace.PlaneGeometry(1, 1);
3304
- const plane = new THREE36__namespace.Mesh(geometry, material);
3373
+ const geometry = new THREE38__namespace.PlaneGeometry(1, 1);
3374
+ const plane = new THREE38__namespace.Mesh(geometry, material);
3305
3375
  plane.userData.entityId = entityId;
3306
3376
  const textureImage = texture.image;
3307
3377
  const width = textureImage?.width ?? 1;
@@ -3352,7 +3422,7 @@ function createInstancedMesh({
3352
3422
  scene,
3353
3423
  payload
3354
3424
  }) {
3355
- const anchor = new THREE36__namespace.Object3D();
3425
+ const anchor = new THREE38__namespace.Object3D();
3356
3426
  const opts = payload.options ?? {};
3357
3427
  const meshKind = isInstancedMeshKind(opts.meshKind) ? opts.meshKind : "cube";
3358
3428
  const meshParameters = opts.meshParameters && typeof opts.meshParameters === "object" ? opts.meshParameters : void 0;
@@ -3423,7 +3493,7 @@ function createAmbientLight({
3423
3493
  scene,
3424
3494
  payload
3425
3495
  }) {
3426
- const light = new THREE36__namespace.AmbientLight("#ffffff", 0.6);
3496
+ const light = new THREE38__namespace.AmbientLight("#ffffff", 0.6);
3427
3497
  const entityId = createBaseEntity(world, light, {
3428
3498
  label: payload.name ?? "Ambient Light",
3429
3499
  entityType: "ambientLight",
@@ -3440,7 +3510,7 @@ function createAreaLight({
3440
3510
  payload,
3441
3511
  isEditor
3442
3512
  }) {
3443
- const light = new THREE36__namespace.RectAreaLight("#ffffff", 5, 4, 4);
3513
+ const light = new THREE38__namespace.RectAreaLight("#ffffff", 5, 4, 4);
3444
3514
  light.lookAt(0, 0, 0);
3445
3515
  const entityId = createBaseEntity(world, light, {
3446
3516
  label: payload.name ?? "Area Light",
@@ -3469,7 +3539,7 @@ function createDirectionalLight({
3469
3539
  payload,
3470
3540
  isEditor
3471
3541
  }) {
3472
- const light = new THREE36__namespace.DirectionalLight("#ffffff", 1.5);
3542
+ const light = new THREE38__namespace.DirectionalLight("#ffffff", 1.5);
3473
3543
  light.castShadow = true;
3474
3544
  const entityId = createBaseEntity(world, light, {
3475
3545
  label: payload.name ?? "Directional Light",
@@ -3480,7 +3550,7 @@ function createDirectionalLight({
3480
3550
  });
3481
3551
  createLightComponent(world, entityId, light);
3482
3552
  if (isEditor) {
3483
- const helper = new THREE36__namespace.DirectionalLightHelper(light, 1.8, "#38bdf8");
3553
+ const helper = new THREE38__namespace.DirectionalLightHelper(light, 1.8, "#38bdf8");
3484
3554
  helper.onBeforeRender = () => {
3485
3555
  helper.update();
3486
3556
  };
@@ -3498,7 +3568,7 @@ function createPointLight({
3498
3568
  payload,
3499
3569
  isEditor
3500
3570
  }) {
3501
- const light = new THREE36__namespace.PointLight("#ffffff", 1, 10);
3571
+ const light = new THREE38__namespace.PointLight("#ffffff", 1, 10);
3502
3572
  const entityId = createBaseEntity(world, light, {
3503
3573
  label: payload.name ?? "Point Light",
3504
3574
  entityType: "pointLight",
@@ -3508,7 +3578,7 @@ function createPointLight({
3508
3578
  });
3509
3579
  createLightComponent(world, entityId, light);
3510
3580
  if (isEditor) {
3511
- const helper = new THREE36__namespace.PointLightHelper(light, 0.35, "#fbbf24");
3581
+ const helper = new THREE38__namespace.PointLightHelper(light, 0.35, "#fbbf24");
3512
3582
  helper.onBeforeRender = () => {
3513
3583
  helper.update();
3514
3584
  };
@@ -3526,7 +3596,7 @@ function createSpotLight({
3526
3596
  payload,
3527
3597
  isEditor
3528
3598
  }) {
3529
- const light = new THREE36__namespace.SpotLight("#ffffff", 1, 20, Math.PI / 6, 0.1, 1);
3599
+ const light = new THREE38__namespace.SpotLight("#ffffff", 1, 20, Math.PI / 6, 0.1, 1);
3530
3600
  const entityId = createBaseEntity(world, light, {
3531
3601
  label: payload.name ?? "Spot Light",
3532
3602
  entityType: "spotLight",
@@ -3536,7 +3606,7 @@ function createSpotLight({
3536
3606
  });
3537
3607
  createLightComponent(world, entityId, light);
3538
3608
  if (isEditor) {
3539
- const helper = new THREE36__namespace.SpotLightHelper(light, "#f59e0b");
3609
+ const helper = new THREE38__namespace.SpotLightHelper(light, "#f59e0b");
3540
3610
  helper.onBeforeRender = () => {
3541
3611
  helper.update();
3542
3612
  };
@@ -3619,7 +3689,10 @@ __export(components_exports, {
3619
3689
  SelectionTransformState: () => SelectionTransformState,
3620
3690
  SpriteComponent: () => SpriteComponent,
3621
3691
  TransformComponent: () => TransformComponent,
3692
+ VRTeleportAreaComponent: () => VRTeleportAreaComponent,
3622
3693
  VideoComponent: () => VideoComponent,
3694
+ XRInteractableComponent: () => XRInteractableComponent,
3695
+ XRRigComponent: () => XRRigComponent,
3623
3696
  defaultMaterialValue: () => defaultMaterialValue,
3624
3697
  normalizePhysicsState: () => normalizePhysicsState,
3625
3698
  setPhysicsLiveRef: () => setPhysicsLiveRef
@@ -3678,7 +3751,7 @@ function createModel({
3678
3751
  payload,
3679
3752
  isEditor
3680
3753
  }) {
3681
- const anchor = new THREE36__namespace.Object3D();
3754
+ const anchor = new THREE38__namespace.Object3D();
3682
3755
  const modelPath = payload.path ?? "";
3683
3756
  const entityId = createBaseEntity(world, anchor, {
3684
3757
  label: payload.name ?? "Model",
@@ -3744,12 +3817,12 @@ function createModel({
3744
3817
  }
3745
3818
  __name(createModel, "createModel");
3746
3819
  function createPlane({ world, scene, payload }) {
3747
- const geometry = new THREE36__namespace.PlaneGeometry(100, 100);
3748
- const material = new THREE36__namespace.MeshStandardMaterial({
3820
+ const geometry = new THREE38__namespace.PlaneGeometry(100, 100);
3821
+ const material = new THREE38__namespace.MeshStandardMaterial({
3749
3822
  color: "#ffffff",
3750
- side: THREE36__namespace.DoubleSide
3823
+ side: THREE38__namespace.DoubleSide
3751
3824
  });
3752
- const mesh = new THREE36__namespace.Mesh(geometry, material);
3825
+ const mesh = new THREE38__namespace.Mesh(geometry, material);
3753
3826
  const entityId = createBaseEntity(
3754
3827
  world,
3755
3828
  mesh,
@@ -3785,7 +3858,7 @@ function createScriptObject({
3785
3858
  scene,
3786
3859
  payload
3787
3860
  }) {
3788
- const object = new THREE36__namespace.Group();
3861
+ const object = new THREE38__namespace.Group();
3789
3862
  const entityId = createBaseEntity(world, object, {
3790
3863
  label: payload.name ?? "Script Object",
3791
3864
  entityType: "scriptObject",
@@ -3802,8 +3875,64 @@ function createScriptObject({
3802
3875
  return entityId;
3803
3876
  }
3804
3877
  __name(createScriptObject, "createScriptObject");
3878
+ function createTeleportArea({
3879
+ world,
3880
+ scene,
3881
+ payload
3882
+ }) {
3883
+ const options = payload.options ?? {};
3884
+ const width = typeof options.width === "number" ? options.width : 10;
3885
+ const depth = typeof options.depth === "number" ? options.depth : 10;
3886
+ const geometry = new THREE38__namespace.PlaneGeometry(width, depth);
3887
+ const material = new THREE38__namespace.MeshBasicMaterial({
3888
+ color: "#4da3ff",
3889
+ transparent: true,
3890
+ opacity: 0.18,
3891
+ side: THREE38__namespace.DoubleSide,
3892
+ depthWrite: false
3893
+ });
3894
+ const object = new THREE38__namespace.Mesh(geometry, material);
3895
+ const entityId = createBaseEntity(world, object, {
3896
+ label: payload.name ?? "Teleport Area",
3897
+ entityType: "teleportArea",
3898
+ // The flat-on-the-ground rotation must live in the ECS TRANSFORM, not on
3899
+ // the Object3D: createBaseEntity applies the transform over the object, and
3900
+ // TransformSyncSystem re-applies it every frame — so a rotation set
3901
+ // directly on the mesh is overwritten immediately and the area stands up
3902
+ // like a wall. Same convention as the `plane` primitive.
3903
+ transformInput: {
3904
+ position: payload.transform?.position,
3905
+ rotation: payload.transform?.rotation ?? { x: -Math.PI / 2, y: 0, z: 0 },
3906
+ scale: payload.transform?.scale
3907
+ }
3908
+ });
3909
+ world.addComponent(
3910
+ entityId,
3911
+ new VRTeleportAreaComponent({ width, depth, ...options })
3912
+ );
3913
+ scene.add(object);
3914
+ return entityId;
3915
+ }
3916
+ __name(createTeleportArea, "createTeleportArea");
3917
+ function createXRRig({
3918
+ world,
3919
+ scene,
3920
+ payload
3921
+ }) {
3922
+ const object = new THREE38__namespace.Group();
3923
+ const entityId = createBaseEntity(world, object, {
3924
+ label: payload.name ?? "XR Rig",
3925
+ entityType: "xrRig",
3926
+ transformInput: payload.transform
3927
+ });
3928
+ const options = payload.options ?? {};
3929
+ world.addComponent(entityId, new XRRigComponent(options));
3930
+ scene.add(object);
3931
+ return entityId;
3932
+ }
3933
+ __name(createXRRig, "createXRRig");
3805
3934
  function createSprite({ world, scene, payload }) {
3806
- const anchor = new THREE36__namespace.Object3D();
3935
+ const anchor = new THREE38__namespace.Object3D();
3807
3936
  const imagePath = payload.path ?? "";
3808
3937
  const entityId = createBaseEntity(world, anchor, {
3809
3938
  label: payload.name ?? "Sprite",
@@ -3815,7 +3944,7 @@ function createSprite({ world, scene, payload }) {
3815
3944
  if (!imagePath) {
3816
3945
  return entityId;
3817
3946
  }
3818
- const loader = new THREE36__namespace.TextureLoader();
3947
+ const loader = new THREE38__namespace.TextureLoader();
3819
3948
  loader.load(
3820
3949
  imagePath,
3821
3950
  (texture) => {
@@ -3823,11 +3952,11 @@ function createSprite({ world, scene, payload }) {
3823
3952
  texture.dispose();
3824
3953
  return;
3825
3954
  }
3826
- const material = new THREE36__namespace.SpriteMaterial({
3955
+ const material = new THREE38__namespace.SpriteMaterial({
3827
3956
  map: texture,
3828
3957
  transparent: true
3829
3958
  });
3830
- const sprite = new THREE36__namespace.Sprite(material);
3959
+ const sprite = new THREE38__namespace.Sprite(material);
3831
3960
  sprite.userData.entityId = entityId;
3832
3961
  const textureImage = texture.image;
3833
3962
  spriteComponent.width = textureImage?.width ?? 1;
@@ -3845,9 +3974,9 @@ function createSprite({ world, scene, payload }) {
3845
3974
  }
3846
3975
  __name(createSprite, "createSprite");
3847
3976
  function createSphere({ world, scene, payload }) {
3848
- const geometry = new THREE36__namespace.SphereGeometry(0.5, 24, 24);
3849
- const material = new THREE36__namespace.MeshStandardMaterial({ color: "#ffffff" });
3850
- const mesh = new THREE36__namespace.Mesh(geometry, material);
3977
+ const geometry = new THREE38__namespace.SphereGeometry(0.5, 24, 24);
3978
+ const material = new THREE38__namespace.MeshStandardMaterial({ color: "#ffffff" });
3979
+ const mesh = new THREE38__namespace.Mesh(geometry, material);
3851
3980
  const entityId = createBaseEntity(world, mesh, {
3852
3981
  label: payload.name ?? "Sphere",
3853
3982
  entityType: "sphere",
@@ -3867,10 +3996,10 @@ function createSphere({ world, scene, payload }) {
3867
3996
  __name(createSphere, "createSphere");
3868
3997
  function getOrCreateListener2(camera) {
3869
3998
  const existing = camera.userData.ecsAudioListener;
3870
- if (existing instanceof THREE36__namespace.AudioListener) {
3999
+ if (existing instanceof THREE38__namespace.AudioListener) {
3871
4000
  return existing;
3872
4001
  }
3873
- const listener = new THREE36__namespace.AudioListener();
4002
+ const listener = new THREE38__namespace.AudioListener();
3874
4003
  camera.add(listener);
3875
4004
  camera.userData.ecsAudioListener = listener;
3876
4005
  return listener;
@@ -3920,10 +4049,10 @@ function normalizeOptions(input) {
3920
4049
  }
3921
4050
  __name(normalizeOptions, "normalizeOptions");
3922
4051
  function createChromaMaterial(texture, options) {
3923
- return new THREE36__namespace.ShaderMaterial({
4052
+ return new THREE38__namespace.ShaderMaterial({
3924
4053
  uniforms: {
3925
4054
  tex: { value: texture },
3926
- keyColor: { value: new THREE36__namespace.Color(options.backgroundColor) },
4055
+ keyColor: { value: new THREE38__namespace.Color(options.backgroundColor) },
3927
4056
  similarity: { value: options.similarity },
3928
4057
  smoothness: { value: options.smoothness },
3929
4058
  spill: { value: options.spill }
@@ -3955,22 +4084,22 @@ function createChromaMaterial(texture, options) {
3955
4084
  }
3956
4085
  `,
3957
4086
  transparent: true,
3958
- side: THREE36__namespace.DoubleSide
4087
+ side: THREE38__namespace.DoubleSide
3959
4088
  });
3960
4089
  }
3961
4090
  __name(createChromaMaterial, "createChromaMaterial");
3962
4091
  function createStandardMaterial(texture) {
3963
- return new THREE36__namespace.MeshBasicMaterial({
4092
+ return new THREE38__namespace.MeshBasicMaterial({
3964
4093
  map: texture,
3965
4094
  transparent: true,
3966
- side: THREE36__namespace.DoubleSide
4095
+ side: THREE38__namespace.DoubleSide
3967
4096
  });
3968
4097
  }
3969
4098
  __name(createStandardMaterial, "createStandardMaterial");
3970
4099
  function createVideoMesh(entityId, texture, options) {
3971
- const geometry = new THREE36__namespace.PlaneGeometry(1, 1);
4100
+ const geometry = new THREE38__namespace.PlaneGeometry(1, 1);
3972
4101
  const material = options.isGreenScreen ? createChromaMaterial(texture, options) : createStandardMaterial(texture);
3973
- const mesh = new THREE36__namespace.Mesh(geometry, material);
4102
+ const mesh = new THREE38__namespace.Mesh(geometry, material);
3974
4103
  mesh.userData.entityId = entityId;
3975
4104
  mesh.scale.set(options.width, options.height, 1);
3976
4105
  return { mesh, material };
@@ -4005,7 +4134,7 @@ function createVideo({
4005
4134
  payload,
4006
4135
  isEditor
4007
4136
  }) {
4008
- const anchor = new THREE36__namespace.Object3D();
4137
+ const anchor = new THREE38__namespace.Object3D();
4009
4138
  const path = payload.path ?? "";
4010
4139
  const options = normalizeOptions(payload.options);
4011
4140
  const entityId = createBaseEntity(world, anchor, {
@@ -4020,8 +4149,8 @@ function createVideo({
4020
4149
  return entityId;
4021
4150
  }
4022
4151
  const video = createVideoElement(path, options);
4023
- const texture = new THREE36__namespace.VideoTexture(video);
4024
- texture.colorSpace = THREE36__namespace.SRGBColorSpace;
4152
+ const texture = new THREE38__namespace.VideoTexture(video);
4153
+ texture.colorSpace = THREE38__namespace.SRGBColorSpace;
4025
4154
  texture.needsUpdate = true;
4026
4155
  const { mesh, material } = createVideoMesh(entityId, texture, options);
4027
4156
  anchor.add(mesh);
@@ -4037,7 +4166,7 @@ function createVideo({
4037
4166
  });
4038
4167
  if (!isEditor && options.positional) {
4039
4168
  const listener = getOrCreateListener2(camera);
4040
- const audioNode = new THREE36__namespace.PositionalAudio(listener);
4169
+ const audioNode = new THREE38__namespace.PositionalAudio(listener);
4041
4170
  audioNode.setVolume(options.volume);
4042
4171
  audioNode.setRefDistance(options.refDistance);
4043
4172
  audioNode.setDistanceModel(normalizeDistanceModel2(options.distanceModel));
@@ -4077,6 +4206,8 @@ function registerDefaultFactories(objectManagementSystem) {
4077
4206
  objectManagementSystem.register("spotLight", createSpotLight);
4078
4207
  objectManagementSystem.register("areaLight", createAreaLight);
4079
4208
  objectManagementSystem.register("scriptObject", createScriptObject);
4209
+ objectManagementSystem.register("xrRig", createXRRig);
4210
+ objectManagementSystem.register("teleportArea", createTeleportArea);
4080
4211
  registerDefaultComponentFactories(objectManagementSystem);
4081
4212
  }
4082
4213
  __name(registerDefaultFactories, "registerDefaultFactories");
@@ -4921,7 +5052,9 @@ var HYDRATABLE_ENTITY_KINDS = /* @__PURE__ */ new Set([
4921
5052
  "areaLight",
4922
5053
  "instancedMesh",
4923
5054
  "instanceSlot",
4924
- "scriptObject"
5055
+ "scriptObject",
5056
+ "xrRig",
5057
+ "teleportArea"
4925
5058
  ]);
4926
5059
 
4927
5060
  // core/hydration/hydrateWorld.ts
@@ -6025,7 +6158,7 @@ function transitionToClip(runtime, nextClipId, crossFadeDuration) {
6025
6158
  }
6026
6159
  __name(transitionToClip, "transitionToClip");
6027
6160
  function applyActionState(action, component, paused, shouldLoop) {
6028
- const loopMode = shouldLoop ? THREE36__namespace.LoopRepeat : THREE36__namespace.LoopOnce;
6161
+ const loopMode = shouldLoop ? THREE38__namespace.LoopRepeat : THREE38__namespace.LoopOnce;
6029
6162
  const repetitions = shouldLoop ? Infinity : 1;
6030
6163
  action.setLoop(loopMode, repetitions);
6031
6164
  action.clampWhenFinished = !shouldLoop;
@@ -6198,7 +6331,7 @@ var _AnimationSystem = class _AnimationSystem {
6198
6331
  if (runtime) {
6199
6332
  stopAllActions(runtime);
6200
6333
  }
6201
- const mixer = new THREE36__namespace.AnimationMixer(root);
6334
+ const mixer = new THREE38__namespace.AnimationMixer(root);
6202
6335
  const entries2 = readRuntimeClipEntries(animation);
6203
6336
  const indexedActions = createActions(mixer, entries2);
6204
6337
  runtime = {
@@ -6324,11 +6457,11 @@ function normalizeOrthoBounds(component) {
6324
6457
  }
6325
6458
  __name(normalizeOrthoBounds, "normalizeOrthoBounds");
6326
6459
  function isPerspectiveCamera(camera) {
6327
- return camera instanceof THREE36__namespace.PerspectiveCamera;
6460
+ return camera instanceof THREE38__namespace.PerspectiveCamera;
6328
6461
  }
6329
6462
  __name(isPerspectiveCamera, "isPerspectiveCamera");
6330
6463
  function isOrthographicCamera(camera) {
6331
- return camera instanceof THREE36__namespace.OrthographicCamera;
6464
+ return camera instanceof THREE38__namespace.OrthographicCamera;
6332
6465
  }
6333
6466
  __name(isOrthographicCamera, "isOrthographicCamera");
6334
6467
  function readWindowAspect() {
@@ -6368,6 +6501,7 @@ var _CameraSyncSystem = class _CameraSyncSystem {
6368
6501
  update(world) {
6369
6502
  const entityIds = world.query(CameraComponent, Object3DRef);
6370
6503
  const windowAspect = readWindowAspect();
6504
+ const xrCamera = world.isXrPresenting() ? world.getCamera() : null;
6371
6505
  const alive = new Set(entityIds);
6372
6506
  for (const trackedId of this.signatures.keys()) {
6373
6507
  if (!alive.has(trackedId)) {
@@ -6381,7 +6515,10 @@ var _CameraSyncSystem = class _CameraSyncSystem {
6381
6515
  continue;
6382
6516
  }
6383
6517
  const camera = objectRef.object;
6384
- if (!(camera instanceof THREE36__namespace.Camera)) {
6518
+ if (!(camera instanceof THREE38__namespace.Camera)) {
6519
+ continue;
6520
+ }
6521
+ if (xrCamera !== null && camera === xrCamera) {
6385
6522
  continue;
6386
6523
  }
6387
6524
  const nextSignature = buildSignature(component, camera, windowAspect);
@@ -6445,7 +6582,7 @@ var MIN_DENSITY = 0;
6445
6582
  function createGradientTexture(effect, colors) {
6446
6583
  if (typeof document === "undefined") {
6447
6584
  const pixel = new Uint8Array([30, 30, 30, 255]);
6448
- const fallback = new THREE36__namespace.DataTexture(pixel, 1, 1, THREE36__namespace.RGBAFormat);
6585
+ const fallback = new THREE38__namespace.DataTexture(pixel, 1, 1, THREE38__namespace.RGBAFormat);
6449
6586
  fallback.needsUpdate = true;
6450
6587
  return fallback;
6451
6588
  }
@@ -6454,7 +6591,7 @@ function createGradientTexture(effect, colors) {
6454
6591
  canvas.height = 512;
6455
6592
  const context = canvas.getContext("2d");
6456
6593
  if (!context) {
6457
- const fallback = new THREE36__namespace.CanvasTexture(canvas);
6594
+ const fallback = new THREE38__namespace.CanvasTexture(canvas);
6458
6595
  fallback.needsUpdate = true;
6459
6596
  return fallback;
6460
6597
  }
@@ -6482,15 +6619,15 @@ function createGradientTexture(effect, colors) {
6482
6619
  context.fillRect(0, 0, 512, 512);
6483
6620
  context.globalCompositeOperation = "source-over";
6484
6621
  }
6485
- const texture = new THREE36__namespace.CanvasTexture(canvas);
6486
- texture.colorSpace = THREE36__namespace.SRGBColorSpace;
6622
+ const texture = new THREE38__namespace.CanvasTexture(canvas);
6623
+ texture.colorSpace = THREE38__namespace.SRGBColorSpace;
6487
6624
  texture.needsUpdate = true;
6488
6625
  return texture;
6489
6626
  }
6490
6627
  __name(createGradientTexture, "createGradientTexture");
6491
6628
  var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
6492
6629
  constructor(scene) {
6493
- this.textureLoader = new THREE36__namespace.TextureLoader();
6630
+ this.textureLoader = new THREE38__namespace.TextureLoader();
6494
6631
  this.signature = null;
6495
6632
  this.activeTexture = null;
6496
6633
  this.pendingImageUrl = null;
@@ -6513,7 +6650,7 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
6513
6650
  if (skybox.type === "color") {
6514
6651
  this.disposeActiveTexture();
6515
6652
  this.pendingImageUrl = null;
6516
- this.scene.background = new THREE36__namespace.Color(skybox.color || "#1e1e1e");
6653
+ this.scene.background = new THREE38__namespace.Color(skybox.color || "#1e1e1e");
6517
6654
  return;
6518
6655
  }
6519
6656
  if (skybox.type === "gradient") {
@@ -6547,7 +6684,7 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
6547
6684
  texture.dispose();
6548
6685
  return;
6549
6686
  }
6550
- texture.colorSpace = THREE36__namespace.SRGBColorSpace;
6687
+ texture.colorSpace = THREE38__namespace.SRGBColorSpace;
6551
6688
  this.activeTexture = texture;
6552
6689
  this.scene.background = texture;
6553
6690
  },
@@ -6566,16 +6703,16 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
6566
6703
  this.scene.fog = null;
6567
6704
  return;
6568
6705
  }
6569
- const fogColor = new THREE36__namespace.Color(fog.color || "#1e1e1e");
6706
+ const fogColor = new THREE38__namespace.Color(fog.color || "#1e1e1e");
6570
6707
  if (fog.type === "linear") {
6571
6708
  const near = Number.isFinite(fog.linear.near) ? fog.linear.near : 1;
6572
6709
  const farCandidate = Number.isFinite(fog.linear.far) ? fog.linear.far : near + 10;
6573
6710
  const far = Math.max(near + MIN_FOG_DELTA, farCandidate);
6574
- this.scene.fog = new THREE36__namespace.Fog(fogColor, near, far);
6711
+ this.scene.fog = new THREE38__namespace.Fog(fogColor, near, far);
6575
6712
  return;
6576
6713
  }
6577
6714
  const density = Number.isFinite(fog.exponential.density) ? Math.max(MIN_DENSITY, fog.exponential.density) : 2e-3;
6578
- this.scene.fog = new THREE36__namespace.FogExp2(fogColor, density);
6715
+ this.scene.fog = new THREE38__namespace.FogExp2(fogColor, density);
6579
6716
  }
6580
6717
  update(world) {
6581
6718
  const entityIds = world.query(Environment);
@@ -6657,10 +6794,10 @@ var _PostprocessingSyncSystem = class _PostprocessingSyncSystem {
6657
6794
  );
6658
6795
  }
6659
6796
  if (values.bloom.enabled) {
6660
- const size = this.renderer.getSize(new THREE36__namespace.Vector2());
6797
+ const size = this.renderer.getSize(new THREE38__namespace.Vector2());
6661
6798
  composer.addPass(
6662
6799
  new UnrealBloomPass_js.UnrealBloomPass(
6663
- new THREE36__namespace.Vector2(size.width, size.height),
6800
+ new THREE38__namespace.Vector2(size.width, size.height),
6664
6801
  values.bloom.intensity,
6665
6802
  values.bloom.radius,
6666
6803
  values.bloom.threshold
@@ -6705,7 +6842,7 @@ var _PostprocessingSyncSystem = class _PostprocessingSyncSystem {
6705
6842
  if (values.dotScreen.enabled) {
6706
6843
  composer.addPass(
6707
6844
  new DotScreenPass_js.DotScreenPass(
6708
- new THREE36__namespace.Vector2(0, 0),
6845
+ new THREE38__namespace.Vector2(0, 0),
6709
6846
  values.dotScreen.angle ?? values.dotScreen.dotScreenAngle,
6710
6847
  values.dotScreen.scale ?? values.dotScreen.dotScreenScale
6711
6848
  )
@@ -6779,7 +6916,7 @@ function computeColliderState(colliderValues, object) {
6779
6916
  if (!object) {
6780
6917
  return colliderValues;
6781
6918
  }
6782
- const scale = new THREE36__namespace.Vector3();
6919
+ const scale = new THREE38__namespace.Vector3();
6783
6920
  object.getWorldScale(scale);
6784
6921
  return {
6785
6922
  ...colliderValues,
@@ -6830,8 +6967,8 @@ function createColliderDesc(RAPIER, values, triMeshData) {
6830
6967
  values.offsetPosition.y,
6831
6968
  values.offsetPosition.z
6832
6969
  );
6833
- const offsetQuaternion = new THREE36__namespace.Quaternion().setFromEuler(
6834
- new THREE36__namespace.Euler(
6970
+ const offsetQuaternion = new THREE38__namespace.Quaternion().setFromEuler(
6971
+ new THREE38__namespace.Euler(
6835
6972
  values.offsetRotation.x,
6836
6973
  values.offsetRotation.y,
6837
6974
  values.offsetRotation.z
@@ -6846,17 +6983,17 @@ function collectTriMeshParts(object) {
6846
6983
  return null;
6847
6984
  }
6848
6985
  object.updateWorldMatrix(true, true);
6849
- const worldScale = new THREE36__namespace.Vector3();
6986
+ const worldScale = new THREE38__namespace.Vector3();
6850
6987
  object.getWorldScale(worldScale);
6851
6988
  const scale = {
6852
6989
  x: Math.abs(worldScale.x) || 1,
6853
6990
  y: Math.abs(worldScale.y) || 1,
6854
6991
  z: Math.abs(worldScale.z) || 1
6855
6992
  };
6856
- const worldToObject = new THREE36__namespace.Matrix4().copy(object.matrixWorld).invert();
6993
+ const worldToObject = new THREE38__namespace.Matrix4().copy(object.matrixWorld).invert();
6857
6994
  const parts = [];
6858
6995
  object.traverse((child) => {
6859
- if (!(child instanceof THREE36__namespace.Mesh) || !child.geometry) {
6996
+ if (!(child instanceof THREE38__namespace.Mesh) || !child.geometry) {
6860
6997
  return;
6861
6998
  }
6862
6999
  const geometry = child.geometry;
@@ -6873,7 +7010,7 @@ function collectTriMeshParts(object) {
6873
7010
  if (indexCount < 3) {
6874
7011
  return;
6875
7012
  }
6876
- const relativeMatrix = new THREE36__namespace.Matrix4().multiplyMatrices(
7013
+ const relativeMatrix = new THREE38__namespace.Matrix4().multiplyMatrices(
6877
7014
  worldToObject,
6878
7015
  child.matrixWorld
6879
7016
  );
@@ -6914,7 +7051,7 @@ function createTriMeshData(collected) {
6914
7051
  }
6915
7052
  const vertices = new Float32Array(vertexTotal * 3);
6916
7053
  const indices = new Uint32Array(indexTotal);
6917
- const point = new THREE36__namespace.Vector3();
7054
+ const point = new THREE38__namespace.Vector3();
6918
7055
  let vertexOffset = 0;
6919
7056
  let indexOffset = 0;
6920
7057
  for (const part of parts) {
@@ -6946,8 +7083,8 @@ function createTriMeshData(collected) {
6946
7083
  }
6947
7084
  __name(createTriMeshData, "createTriMeshData");
6948
7085
  function syncBodyFromTransform(body, transform) {
6949
- const quaternion = new THREE36__namespace.Quaternion().setFromEuler(
6950
- new THREE36__namespace.Euler(transform.rotation.x, transform.rotation.y, transform.rotation.z)
7086
+ const quaternion = new THREE38__namespace.Quaternion().setFromEuler(
7087
+ new THREE38__namespace.Euler(transform.rotation.x, transform.rotation.y, transform.rotation.z)
6951
7088
  );
6952
7089
  body.setTranslation(
6953
7090
  {
@@ -6974,8 +7111,8 @@ function syncTransformFromBody(transform, body) {
6974
7111
  transform.position.x = position.x;
6975
7112
  transform.position.y = position.y;
6976
7113
  transform.position.z = position.z;
6977
- const euler = new THREE36__namespace.Euler().setFromQuaternion(
6978
- new THREE36__namespace.Quaternion(rotation.x, rotation.y, rotation.z, rotation.w)
7114
+ const euler = new THREE38__namespace.Euler().setFromQuaternion(
7115
+ new THREE38__namespace.Quaternion(rotation.x, rotation.y, rotation.z, rotation.w)
6979
7116
  );
6980
7117
  transform.rotation.x = euler.x;
6981
7118
  transform.rotation.y = euler.y;
@@ -7087,8 +7224,8 @@ var _PhysicsSyncSystem = class _PhysicsSyncSystem {
7087
7224
  transform.position.y,
7088
7225
  transform.position.z
7089
7226
  );
7090
- const quaternion = new THREE36__namespace.Quaternion().setFromEuler(
7091
- new THREE36__namespace.Euler(
7227
+ const quaternion = new THREE38__namespace.Quaternion().setFromEuler(
7228
+ new THREE38__namespace.Euler(
7092
7229
  transform.rotation.x,
7093
7230
  transform.rotation.y,
7094
7231
  transform.rotation.z
@@ -7667,7 +7804,7 @@ function applyLightValues(lightComponent) {
7667
7804
  values.castShadow
7668
7805
  );
7669
7806
  }
7670
- if (light instanceof THREE36__namespace.PointLight) {
7807
+ if (light instanceof THREE38__namespace.PointLight) {
7671
7808
  if (typeof values.distance === "number" && Number.isFinite(values.distance)) {
7672
7809
  light.distance = Math.max(MIN_LIGHT_DISTANCE, values.distance);
7673
7810
  }
@@ -7675,7 +7812,7 @@ function applyLightValues(lightComponent) {
7675
7812
  light.decay = Math.max(0, values.decay);
7676
7813
  }
7677
7814
  }
7678
- if (light instanceof THREE36__namespace.SpotLight) {
7815
+ if (light instanceof THREE38__namespace.SpotLight) {
7679
7816
  if (typeof values.distance === "number" && Number.isFinite(values.distance)) {
7680
7817
  light.distance = Math.max(MIN_LIGHT_DISTANCE, values.distance);
7681
7818
  }
@@ -7689,7 +7826,7 @@ function applyLightValues(lightComponent) {
7689
7826
  light.penumbra = Math.max(0, Math.min(1, values.penumbra));
7690
7827
  }
7691
7828
  }
7692
- if (light instanceof THREE36__namespace.RectAreaLight) {
7829
+ if (light instanceof THREE38__namespace.RectAreaLight) {
7693
7830
  if (typeof values.width === "number" && Number.isFinite(values.width)) {
7694
7831
  light.width = Math.max(MIN_AREA_SIZE, values.width);
7695
7832
  }
@@ -7750,15 +7887,15 @@ function resolveMaterialPropertyKey(key) {
7750
7887
  __name(resolveMaterialPropertyKey, "resolveMaterialPropertyKey");
7751
7888
  function createMaterialByType(type) {
7752
7889
  if (type === "basic") {
7753
- return new THREE36__namespace.MeshBasicMaterial();
7890
+ return new THREE38__namespace.MeshBasicMaterial();
7754
7891
  }
7755
7892
  if (type === "phong") {
7756
- return new THREE36__namespace.MeshPhongMaterial();
7893
+ return new THREE38__namespace.MeshPhongMaterial();
7757
7894
  }
7758
7895
  if (type === "physical") {
7759
- return new THREE36__namespace.MeshPhysicalMaterial();
7896
+ return new THREE38__namespace.MeshPhysicalMaterial();
7760
7897
  }
7761
- return new THREE36__namespace.MeshStandardMaterial();
7898
+ return new THREE38__namespace.MeshStandardMaterial();
7762
7899
  }
7763
7900
  __name(createMaterialByType, "createMaterialByType");
7764
7901
  function replaceMaterialAcrossObject(object, previous, next) {
@@ -7817,12 +7954,12 @@ function applyTextureFiltering(material, filtering) {
7817
7954
  const target = material;
7818
7955
  for (const slot of materialTextureSlots) {
7819
7956
  const texture = target[slot];
7820
- if (!texture || !(texture instanceof THREE36__namespace.Texture)) {
7957
+ if (!texture || !(texture instanceof THREE38__namespace.Texture)) {
7821
7958
  continue;
7822
7959
  }
7823
7960
  const useMipmaps = texture.generateMipmaps !== false;
7824
- texture.magFilter = sharp ? THREE36__namespace.NearestFilter : THREE36__namespace.LinearFilter;
7825
- texture.minFilter = useMipmaps ? sharp ? THREE36__namespace.NearestMipmapNearestFilter : THREE36__namespace.LinearMipmapLinearFilter : sharp ? THREE36__namespace.NearestFilter : THREE36__namespace.LinearFilter;
7961
+ texture.magFilter = sharp ? THREE38__namespace.NearestFilter : THREE38__namespace.LinearFilter;
7962
+ texture.minFilter = useMipmaps ? sharp ? THREE38__namespace.NearestMipmapNearestFilter : THREE38__namespace.LinearMipmapLinearFilter : sharp ? THREE38__namespace.NearestFilter : THREE38__namespace.LinearFilter;
7826
7963
  texture.needsUpdate = true;
7827
7964
  }
7828
7965
  material.needsUpdate = true;
@@ -7832,12 +7969,12 @@ function setTextureMipmaps(material, enabled) {
7832
7969
  const target = material;
7833
7970
  for (const slot of materialTextureSlots) {
7834
7971
  const texture = target[slot];
7835
- if (!texture || !(texture instanceof THREE36__namespace.Texture)) {
7972
+ if (!texture || !(texture instanceof THREE38__namespace.Texture)) {
7836
7973
  continue;
7837
7974
  }
7838
7975
  texture.generateMipmaps = enabled;
7839
- const sharp = texture.magFilter === THREE36__namespace.NearestFilter;
7840
- texture.minFilter = enabled ? sharp ? THREE36__namespace.NearestMipmapNearestFilter : THREE36__namespace.LinearMipmapLinearFilter : sharp ? THREE36__namespace.NearestFilter : THREE36__namespace.LinearFilter;
7976
+ const sharp = texture.magFilter === THREE38__namespace.NearestFilter;
7977
+ texture.minFilter = enabled ? sharp ? THREE38__namespace.NearestMipmapNearestFilter : THREE38__namespace.LinearMipmapLinearFilter : sharp ? THREE38__namespace.NearestFilter : THREE38__namespace.LinearFilter;
7841
7978
  texture.needsUpdate = true;
7842
7979
  }
7843
7980
  material.needsUpdate = true;
@@ -7848,7 +7985,7 @@ function assignMaterialTexture(material, rawKey, url, textureCache) {
7848
7985
  const key = resolveMaterialPropertyKey(rawKey);
7849
7986
  let texture = textureCache.get(url);
7850
7987
  if (!texture) {
7851
- texture = new THREE36__namespace.TextureLoader().load(url);
7988
+ texture = new THREE38__namespace.TextureLoader().load(url);
7852
7989
  textureCache.set(url, texture);
7853
7990
  }
7854
7991
  target[key] = texture;
@@ -7886,7 +8023,7 @@ function applyMaterialState(material, value, textureCache) {
7886
8023
  }
7887
8024
  target.side = value.side;
7888
8025
  target.blending = value.blending;
7889
- target.premultipliedAlpha = value.blending === THREE36__namespace.MultiplyBlending || value.blending === THREE36__namespace.SubtractiveBlending;
8026
+ target.premultipliedAlpha = value.blending === THREE38__namespace.MultiplyBlending || value.blending === THREE38__namespace.SubtractiveBlending;
7890
8027
  target.depthTest = value.depthTest;
7891
8028
  target.depthWrite = value.depthWrite;
7892
8029
  target.wireframe = value.wireframe;
@@ -8047,12 +8184,12 @@ function resolvePrimaryMesh(object) {
8047
8184
  if (!object) {
8048
8185
  return null;
8049
8186
  }
8050
- if (object instanceof THREE36__namespace.Mesh) {
8187
+ if (object instanceof THREE38__namespace.Mesh) {
8051
8188
  return object;
8052
8189
  }
8053
8190
  let found = null;
8054
8191
  object.traverse((child) => {
8055
- if (!found && child instanceof THREE36__namespace.Mesh) {
8192
+ if (!found && child instanceof THREE38__namespace.Mesh) {
8056
8193
  found = child;
8057
8194
  }
8058
8195
  });
@@ -8073,22 +8210,22 @@ function applyGeometry(component) {
8073
8210
  switch (component.kind) {
8074
8211
  case "cube": {
8075
8212
  const params = sanitized;
8076
- nextGeometry = new THREE36__namespace.BoxGeometry(params.width, params.height, params.depth);
8213
+ nextGeometry = new THREE38__namespace.BoxGeometry(params.width, params.height, params.depth);
8077
8214
  break;
8078
8215
  }
8079
8216
  case "plane": {
8080
8217
  const params = sanitized;
8081
- nextGeometry = new THREE36__namespace.PlaneGeometry(params.width, params.height);
8218
+ nextGeometry = new THREE38__namespace.PlaneGeometry(params.width, params.height);
8082
8219
  break;
8083
8220
  }
8084
8221
  case "sphere": {
8085
8222
  const params = sanitized;
8086
- nextGeometry = new THREE36__namespace.SphereGeometry(params.radius, 24, 24);
8223
+ nextGeometry = new THREE38__namespace.SphereGeometry(params.radius, 24, 24);
8087
8224
  break;
8088
8225
  }
8089
8226
  case "cylinder": {
8090
8227
  const params = sanitized;
8091
- nextGeometry = new THREE36__namespace.CylinderGeometry(
8228
+ nextGeometry = new THREE38__namespace.CylinderGeometry(
8092
8229
  params.radius,
8093
8230
  params.radius,
8094
8231
  params.height,
@@ -8098,7 +8235,7 @@ function applyGeometry(component) {
8098
8235
  }
8099
8236
  case "capsule": {
8100
8237
  const params = sanitized;
8101
- nextGeometry = new THREE36__namespace.CapsuleGeometry(params.radius, params.height, 4, 8);
8238
+ nextGeometry = new THREE38__namespace.CapsuleGeometry(params.radius, params.height, 4, 8);
8102
8239
  break;
8103
8240
  }
8104
8241
  default:
@@ -8114,7 +8251,7 @@ function applyShadowFlags(component) {
8114
8251
  return;
8115
8252
  }
8116
8253
  component.object.traverse((child) => {
8117
- if (child instanceof THREE36__namespace.Mesh) {
8254
+ if (child instanceof THREE38__namespace.Mesh) {
8118
8255
  child.castShadow = component.castShadow;
8119
8256
  child.receiveShadow = component.receiveShadow;
8120
8257
  }
@@ -8197,35 +8334,35 @@ function buildGeometry(component) {
8197
8334
  switch (component.meshKind) {
8198
8335
  case "cube": {
8199
8336
  const params = p;
8200
- return new THREE36__namespace.BoxGeometry(params.width, params.height, params.depth);
8337
+ return new THREE38__namespace.BoxGeometry(params.width, params.height, params.depth);
8201
8338
  }
8202
8339
  case "plane": {
8203
8340
  const params = p;
8204
- return new THREE36__namespace.PlaneGeometry(params.width, params.height);
8341
+ return new THREE38__namespace.PlaneGeometry(params.width, params.height);
8205
8342
  }
8206
8343
  case "sphere": {
8207
8344
  const params = p;
8208
- return new THREE36__namespace.SphereGeometry(params.radius, 24, 24);
8345
+ return new THREE38__namespace.SphereGeometry(params.radius, 24, 24);
8209
8346
  }
8210
8347
  case "cylinder": {
8211
8348
  const params = p;
8212
- return new THREE36__namespace.CylinderGeometry(params.radius, params.radius, params.height, 20);
8349
+ return new THREE38__namespace.CylinderGeometry(params.radius, params.radius, params.height, 20);
8213
8350
  }
8214
8351
  case "capsule": {
8215
8352
  const params = p;
8216
- return new THREE36__namespace.CapsuleGeometry(params.radius, params.height, 4, 8);
8353
+ return new THREE38__namespace.CapsuleGeometry(params.radius, params.height, 4, 8);
8217
8354
  }
8218
8355
  default:
8219
- return new THREE36__namespace.BoxGeometry(1, 1, 1);
8356
+ return new THREE38__namespace.BoxGeometry(1, 1, 1);
8220
8357
  }
8221
8358
  }
8222
8359
  __name(buildGeometry, "buildGeometry");
8223
- var _position = new THREE36__namespace.Vector3();
8224
- var _quaternion = new THREE36__namespace.Quaternion();
8225
- var _euler = new THREE36__namespace.Euler();
8226
- var _scale = new THREE36__namespace.Vector3();
8227
- var _matrix = new THREE36__namespace.Matrix4();
8228
- var _modelMatrix = new THREE36__namespace.Matrix4();
8360
+ var _position = new THREE38__namespace.Vector3();
8361
+ var _quaternion = new THREE38__namespace.Quaternion();
8362
+ var _euler = new THREE38__namespace.Euler();
8363
+ var _scale = new THREE38__namespace.Vector3();
8364
+ var _matrix = new THREE38__namespace.Matrix4();
8365
+ var _modelMatrix = new THREE38__namespace.Matrix4();
8229
8366
  function instanceTransformFromComponent(transform, out) {
8230
8367
  _position.set(transform.position.x, transform.position.y, transform.position.z);
8231
8368
  _euler.set(transform.rotation.x, transform.rotation.y, transform.rotation.z, "XYZ");
@@ -8378,7 +8515,7 @@ var _InstancedMeshSystem = class _InstancedMeshSystem {
8378
8515
  const sourceMaterial = Array.isArray(meshChild.material) ? meshChild.material.map((m) => m.clone()) : meshChild.material.clone();
8379
8516
  meshChild.updateWorldMatrix(true, false);
8380
8517
  const localMatrix = meshChild.matrixWorld.clone();
8381
- const instancedMesh2 = new THREE36__namespace.InstancedMesh(
8518
+ const instancedMesh2 = new THREE38__namespace.InstancedMesh(
8382
8519
  geometry2,
8383
8520
  Array.isArray(sourceMaterial) ? sourceMaterial : sourceMaterial,
8384
8521
  count2
@@ -8403,7 +8540,7 @@ var _InstancedMeshSystem = class _InstancedMeshSystem {
8403
8540
  this.loadingSignatures.delete(targetEntityId);
8404
8541
  return;
8405
8542
  }
8406
- const group = new THREE36__namespace.Group();
8543
+ const group = new THREE38__namespace.Group();
8407
8544
  for (const entry of entries) {
8408
8545
  group.add(entry.instancedMesh);
8409
8546
  }
@@ -8421,8 +8558,8 @@ var _InstancedMeshSystem = class _InstancedMeshSystem {
8421
8558
  }
8422
8559
  const count = instanceCount;
8423
8560
  const geometry = buildGeometry(comp);
8424
- const material = new THREE36__namespace.MeshStandardMaterial({ color: "#ffffff" });
8425
- const instancedMesh = new THREE36__namespace.InstancedMesh(geometry, material, count);
8561
+ const material = new THREE38__namespace.MeshStandardMaterial({ color: "#ffffff" });
8562
+ const instancedMesh = new THREE38__namespace.InstancedMesh(geometry, material, count);
8426
8563
  instancedMesh.castShadow = comp.castShadow;
8427
8564
  instancedMesh.receiveShadow = comp.receiveShadow;
8428
8565
  for (let i = 0; i < count; i++) {
@@ -8605,7 +8742,7 @@ var _Behaviour = class _Behaviour {
8605
8742
  if (!this.threeRef) {
8606
8743
  return null;
8607
8744
  }
8608
- const position = new THREE36__namespace.Vector3();
8745
+ const position = new THREE38__namespace.Vector3();
8609
8746
  this.threeRef.object.getWorldPosition(position);
8610
8747
  return position;
8611
8748
  }
@@ -8617,7 +8754,7 @@ var _Behaviour = class _Behaviour {
8617
8754
  if (!this.threeRef) {
8618
8755
  return null;
8619
8756
  }
8620
- const target = new THREE36__namespace.Vector3();
8757
+ const target = new THREE38__namespace.Vector3();
8621
8758
  this.threeRef.object.getWorldDirection(target);
8622
8759
  return target;
8623
8760
  }
@@ -8679,7 +8816,7 @@ var _Behaviour = class _Behaviour {
8679
8816
  if (!this.threeRef) {
8680
8817
  return;
8681
8818
  }
8682
- const rotation = new THREE36__namespace.Quaternion();
8819
+ const rotation = new THREE38__namespace.Quaternion();
8683
8820
  this.threeRef.object.getWorldQuaternion(rotation);
8684
8821
  rotation.slerp(targetRotation, alpha);
8685
8822
  this.transform.setRotation(rotation);
@@ -8696,7 +8833,7 @@ var _Behaviour = class _Behaviour {
8696
8833
  return;
8697
8834
  }
8698
8835
  const clone3 = this.threeRef.object.clone();
8699
- const rotation = new THREE36__namespace.Quaternion();
8836
+ const rotation = new THREE38__namespace.Quaternion();
8700
8837
  clone3.lookAt(targetPosition);
8701
8838
  clone3.getWorldQuaternion(rotation);
8702
8839
  this.transform.setRotation(rotation);
@@ -8796,6 +8933,49 @@ var _Behaviour = class _Behaviour {
8796
8933
  */
8797
8934
  onTargetLost(target) {
8798
8935
  }
8936
+ // ─── WebXR (VR / MR) hooks ────────────────────────────────────────────────
8937
+ // Dispatched by XRSessionSystem / XRInteractionSystem, following the same
8938
+ // pattern as the AR hooks above: public no-op methods that subclasses opt
8939
+ // into by overriding. They never fire outside an immersive session.
8940
+ /**
8941
+ * Called once when an immersive session starts. Optional XR hook.
8942
+ *
8943
+ * Use it to set up XR-only state. Inspect `capabilities` rather than guessing
8944
+ * by device: feature support differs sharply per headset (for example Vision
8945
+ * Pro grants no passthrough on the web today).
8946
+ *
8947
+ * @param capabilities - What the session actually granted, read from
8948
+ * `XRSession.enabledFeatures`.
8949
+ */
8950
+ onXRSessionStart(capabilities) {
8951
+ }
8952
+ /** Called once when the immersive session ends. Optional XR hook. */
8953
+ onXRSessionEnd() {
8954
+ }
8955
+ /**
8956
+ * Called when a primary action begins — controller trigger, hand pinch, or
8957
+ * Vision Pro gaze-pinch. Optional XR hook.
8958
+ *
8959
+ * @param input - Normalized state for the source that acted.
8960
+ */
8961
+ onSelectStart(input) {
8962
+ }
8963
+ /** Called when the primary action ends. Optional XR hook. */
8964
+ onSelectEnd(input) {
8965
+ }
8966
+ /**
8967
+ * Called when this entity is grabbed. Optional XR hook.
8968
+ *
8969
+ * Only fires for entities carrying an enabled, grabbable
8970
+ * `XRInteractableComponent`.
8971
+ *
8972
+ * @param input - The source doing the grabbing.
8973
+ */
8974
+ onGrab(input) {
8975
+ }
8976
+ /** Called when this entity is released. Optional XR hook. */
8977
+ onRelease(input) {
8978
+ }
8799
8979
  };
8800
8980
  __name(_Behaviour, "Behaviour");
8801
8981
  /**
@@ -8997,8 +9177,8 @@ var _ScriptBehaviourSystem = class _ScriptBehaviourSystem {
8997
9177
  }, "onPointerUp");
8998
9178
  this.moduleLoader = moduleLoader ?? defaultModuleLoader;
8999
9179
  this.selectionCtx = selectionContext ?? null;
9000
- this.raycaster = new THREE36__namespace.Raycaster();
9001
- this.ndcPointer = new THREE36__namespace.Vector2();
9180
+ this.raycaster = new THREE38__namespace.Raycaster();
9181
+ this.ndcPointer = new THREE38__namespace.Vector2();
9002
9182
  if (this.selectionCtx) {
9003
9183
  this.selectionCtx.domElement.addEventListener("pointerdown", this.onPointerDown);
9004
9184
  this.selectionCtx.domElement.addEventListener("pointerup", this.onPointerUp);
@@ -9377,7 +9557,7 @@ function disposeBuiltObject(root) {
9377
9557
  for (const mat of materials) {
9378
9558
  if (mat.userData?.[SHARED_MODEL_RESOURCE_FLAG]) continue;
9379
9559
  for (const value of Object.values(mat)) {
9380
- if (value instanceof THREE36__namespace.Texture) value.dispose();
9560
+ if (value instanceof THREE38__namespace.Texture) value.dispose();
9381
9561
  }
9382
9562
  mat.dispose?.();
9383
9563
  }
@@ -9643,12 +9823,16 @@ var ScriptObjectSystem = _ScriptObjectSystem;
9643
9823
  var _TransformSyncSystem = class _TransformSyncSystem {
9644
9824
  update(world) {
9645
9825
  const entities = world.query(TransformComponent, Object3DRef);
9826
+ const xrCamera = world.isXrPresenting() ? world.getCamera() : null;
9646
9827
  for (const entityId of entities) {
9647
9828
  const transform = world.getComponent(entityId, TransformComponent);
9648
9829
  const object = world.getComponent(entityId, Object3DRef)?.object;
9649
9830
  if (!transform || !object) {
9650
9831
  continue;
9651
9832
  }
9833
+ if (xrCamera !== null && object === xrCamera) {
9834
+ continue;
9835
+ }
9652
9836
  applyTransform(object, transform);
9653
9837
  object.updateMatrixWorld(true);
9654
9838
  }
@@ -9737,7 +9921,7 @@ var _AudioSystem = class _AudioSystem {
9737
9921
  if (!prev || prev.volume !== opts.volume) {
9738
9922
  sound.setVolume(opts.volume);
9739
9923
  }
9740
- if (opts.positional && sound instanceof THREE36__namespace.PositionalAudio) {
9924
+ if (opts.positional && sound instanceof THREE38__namespace.PositionalAudio) {
9741
9925
  if (!prev || prev.refDistance !== opts.refDistance) {
9742
9926
  sound.setRefDistance(opts.refDistance);
9743
9927
  }
@@ -9863,7 +10047,7 @@ var _VideoSystem = class _VideoSystem {
9863
10047
  component.object.scale.set(opts.width, opts.height, 1);
9864
10048
  }
9865
10049
  const material = component.material;
9866
- if (material instanceof THREE36__namespace.ShaderMaterial) {
10050
+ if (material instanceof THREE38__namespace.ShaderMaterial) {
9867
10051
  if (!prev || prev.backgroundColor !== opts.backgroundColor) {
9868
10052
  material.uniforms.keyColor.value.set(opts.backgroundColor);
9869
10053
  }
@@ -9877,7 +10061,7 @@ var _VideoSystem = class _VideoSystem {
9877
10061
  material.uniforms.spill.value = opts.spill;
9878
10062
  }
9879
10063
  }
9880
- if (opts.positional && component.audioNode instanceof THREE36__namespace.PositionalAudio) {
10064
+ if (opts.positional && component.audioNode instanceof THREE38__namespace.PositionalAudio) {
9881
10065
  const posAudio = component.audioNode;
9882
10066
  if (!prev || prev.refDistance !== opts.refDistance) {
9883
10067
  posAudio.setRefDistance(opts.refDistance);
@@ -9899,6 +10083,702 @@ var _VideoSystem = class _VideoSystem {
9899
10083
  };
9900
10084
  __name(_VideoSystem, "VideoSystem");
9901
10085
  var VideoSystem = _VideoSystem;
10086
+ function handednessOf(source) {
10087
+ const value = source.handedness;
10088
+ return value === "left" || value === "right" ? value : "none";
10089
+ }
10090
+ __name(handednessOf, "handednessOf");
10091
+ function kindOf(source) {
10092
+ const mode = source.targetRayMode;
10093
+ if (mode === "transient-pointer") return "transient-pointer";
10094
+ if (mode === "gaze") return "gaze";
10095
+ if (source.hand) return "hand";
10096
+ return "controller";
10097
+ }
10098
+ __name(kindOf, "kindOf");
10099
+ function blankState(source) {
10100
+ return {
10101
+ handedness: handednessOf(source),
10102
+ kind: kindOf(source),
10103
+ connected: true,
10104
+ rayOrigin: new THREE38__namespace.Vector3(),
10105
+ rayDirection: new THREE38__namespace.Vector3(0, 0, -1),
10106
+ gripPosition: null,
10107
+ gripQuaternion: null,
10108
+ select: false,
10109
+ selectStart: false,
10110
+ selectEnd: false,
10111
+ squeeze: false,
10112
+ squeezeStart: false,
10113
+ squeezeEnd: false,
10114
+ axes: [],
10115
+ hasAxes: false,
10116
+ buttons: []
10117
+ };
10118
+ }
10119
+ __name(blankState, "blankState");
10120
+ var _XRInputSystem = class _XRInputSystem {
10121
+ constructor() {
10122
+ this.records = /* @__PURE__ */ new Map();
10123
+ this.session = null;
10124
+ this.onSelectStart = /* @__PURE__ */ __name((event) => this.mark(event, "pendingSelectStart"), "onSelectStart");
10125
+ this.onSelectEnd = /* @__PURE__ */ __name((event) => this.mark(event, "pendingSelectEnd"), "onSelectEnd");
10126
+ this.onSqueezeStart = /* @__PURE__ */ __name((event) => this.mark(event, "pendingSqueezeStart"), "onSqueezeStart");
10127
+ this.onSqueezeEnd = /* @__PURE__ */ __name((event) => this.mark(event, "pendingSqueezeEnd"), "onSqueezeEnd");
10128
+ }
10129
+ mark(event, flag) {
10130
+ const record = this.ensureRecord(event.inputSource);
10131
+ record[flag] = true;
10132
+ }
10133
+ ensureRecord(source) {
10134
+ let record = this.records.get(source);
10135
+ if (!record) {
10136
+ record = {
10137
+ source,
10138
+ state: blankState(source),
10139
+ pendingSelectStart: false,
10140
+ pendingSelectEnd: false,
10141
+ pendingSqueezeStart: false,
10142
+ pendingSqueezeEnd: false,
10143
+ removed: false
10144
+ };
10145
+ this.records.set(source, record);
10146
+ }
10147
+ return record;
10148
+ }
10149
+ /** Bind to a session. Called by {@link XRSessionSystem} on session start. */
10150
+ attachSession(session) {
10151
+ this.detachSession();
10152
+ this.session = session;
10153
+ session.addEventListener("selectstart", this.onSelectStart);
10154
+ session.addEventListener("selectend", this.onSelectEnd);
10155
+ session.addEventListener(
10156
+ "squeezestart",
10157
+ this.onSqueezeStart
10158
+ );
10159
+ session.addEventListener("squeezeend", this.onSqueezeEnd);
10160
+ }
10161
+ /** Unbind and drop all per-source state. */
10162
+ detachSession() {
10163
+ const session = this.session;
10164
+ if (session) {
10165
+ session.removeEventListener(
10166
+ "selectstart",
10167
+ this.onSelectStart
10168
+ );
10169
+ session.removeEventListener(
10170
+ "selectend",
10171
+ this.onSelectEnd
10172
+ );
10173
+ session.removeEventListener(
10174
+ "squeezestart",
10175
+ this.onSqueezeStart
10176
+ );
10177
+ session.removeEventListener(
10178
+ "squeezeend",
10179
+ this.onSqueezeEnd
10180
+ );
10181
+ }
10182
+ this.session = null;
10183
+ this.records.clear();
10184
+ }
10185
+ update(world) {
10186
+ for (const [source, record] of this.records) {
10187
+ if (record.removed) {
10188
+ this.records.delete(source);
10189
+ continue;
10190
+ }
10191
+ record.state.selectStart = false;
10192
+ record.state.selectEnd = false;
10193
+ record.state.squeezeStart = false;
10194
+ record.state.squeezeEnd = false;
10195
+ }
10196
+ const session = this.session;
10197
+ if (!session || !world.isXrPresenting()) return;
10198
+ const renderer = world.getRenderer();
10199
+ const referenceSpace = renderer.xr.getReferenceSpace();
10200
+ const frame = renderer.xr.getFrame?.();
10201
+ const live = /* @__PURE__ */ new Set();
10202
+ for (const source of session.inputSources) {
10203
+ live.add(source);
10204
+ const record = this.ensureRecord(source);
10205
+ const state = record.state;
10206
+ state.connected = true;
10207
+ state.handedness = handednessOf(source);
10208
+ state.kind = kindOf(source);
10209
+ if (frame && referenceSpace && source.targetRaySpace) {
10210
+ const pose = frame.getPose(source.targetRaySpace, referenceSpace);
10211
+ if (pose) {
10212
+ const m = new THREE38__namespace.Matrix4().fromArray(pose.transform.matrix);
10213
+ state.rayOrigin.setFromMatrixPosition(m);
10214
+ state.rayDirection.set(0, 0, -1).applyQuaternion(
10215
+ new THREE38__namespace.Quaternion().setFromRotationMatrix(m)
10216
+ ).normalize();
10217
+ }
10218
+ }
10219
+ if (frame && referenceSpace && source.gripSpace) {
10220
+ const gripPose = frame.getPose(source.gripSpace, referenceSpace);
10221
+ if (gripPose) {
10222
+ const m = new THREE38__namespace.Matrix4().fromArray(gripPose.transform.matrix);
10223
+ state.gripPosition ?? (state.gripPosition = new THREE38__namespace.Vector3());
10224
+ state.gripQuaternion ?? (state.gripQuaternion = new THREE38__namespace.Quaternion());
10225
+ state.gripPosition.setFromMatrixPosition(m);
10226
+ state.gripQuaternion.setFromRotationMatrix(m);
10227
+ }
10228
+ } else {
10229
+ state.gripPosition = null;
10230
+ state.gripQuaternion = null;
10231
+ }
10232
+ const gamepad = source.gamepad;
10233
+ if (gamepad) {
10234
+ state.axes = Array.from(gamepad.axes);
10235
+ state.hasAxes = gamepad.axes.some((axis) => Number.isFinite(axis));
10236
+ state.buttons = gamepad.buttons.map((button) => button.pressed);
10237
+ } else {
10238
+ state.axes = [];
10239
+ state.hasAxes = false;
10240
+ state.buttons = [];
10241
+ }
10242
+ if (record.pendingSelectStart) {
10243
+ state.select = true;
10244
+ state.selectStart = true;
10245
+ record.pendingSelectStart = false;
10246
+ }
10247
+ if (record.pendingSelectEnd) {
10248
+ state.select = false;
10249
+ state.selectEnd = true;
10250
+ record.pendingSelectEnd = false;
10251
+ }
10252
+ if (record.pendingSqueezeStart) {
10253
+ state.squeeze = true;
10254
+ state.squeezeStart = true;
10255
+ record.pendingSqueezeStart = false;
10256
+ }
10257
+ if (record.pendingSqueezeEnd) {
10258
+ state.squeeze = false;
10259
+ state.squeezeEnd = true;
10260
+ record.pendingSqueezeEnd = false;
10261
+ }
10262
+ }
10263
+ for (const [source, record] of this.records) {
10264
+ if (live.has(source)) continue;
10265
+ record.state.connected = false;
10266
+ record.removed = true;
10267
+ }
10268
+ }
10269
+ /** Every input source active this frame. */
10270
+ getInputs() {
10271
+ return Array.from(this.records.values(), (record) => record.state);
10272
+ }
10273
+ /** The first source for a hand, or null. Prefer this for hand-specific logic. */
10274
+ getInput(handedness) {
10275
+ for (const record of this.records.values()) {
10276
+ if (record.state.handedness === handedness) return record.state;
10277
+ }
10278
+ return null;
10279
+ }
10280
+ /** True while ANY source is selecting — the portable "is the user acting" check. */
10281
+ isSelecting() {
10282
+ for (const record of this.records.values()) {
10283
+ if (record.state.select) return true;
10284
+ }
10285
+ return false;
10286
+ }
10287
+ dispose() {
10288
+ this.detachSession();
10289
+ }
10290
+ };
10291
+ __name(_XRInputSystem, "XRInputSystem");
10292
+ var XRInputSystem = _XRInputSystem;
10293
+ var RAYLESS_HOLD_DISTANCE = 0.5;
10294
+ var _XRInteractionSystem = class _XRInteractionSystem {
10295
+ constructor(inputSystem) {
10296
+ this.raycaster = new THREE38__namespace.Raycaster();
10297
+ /** Which entity each source is holding. Keyed by source state identity. */
10298
+ this.grabs = /* @__PURE__ */ new Map();
10299
+ this.hoveredEntityId = null;
10300
+ this.inputSystem = inputSystem;
10301
+ }
10302
+ update(world) {
10303
+ if (!world.isXrPresenting()) {
10304
+ this.releaseAll(world);
10305
+ return;
10306
+ }
10307
+ const inputs = this.inputSystem.getInputs();
10308
+ const interactables = this.collectInteractables(world);
10309
+ this.hoveredEntityId = null;
10310
+ for (const input of inputs) {
10311
+ if (!input.connected) {
10312
+ this.release(world, input);
10313
+ continue;
10314
+ }
10315
+ const held = this.grabs.get(input);
10316
+ if (held) {
10317
+ this.moveHeld(world, input, held);
10318
+ if (input.selectEnd) this.release(world, input);
10319
+ continue;
10320
+ }
10321
+ const hitEntityId = this.raycast(input, interactables);
10322
+ if (hitEntityId === null) continue;
10323
+ if (this.hoveredEntityId === null) {
10324
+ this.hoveredEntityId = hitEntityId;
10325
+ }
10326
+ const interactable = world.getComponent(
10327
+ hitEntityId,
10328
+ XRInteractableComponent
10329
+ );
10330
+ if (input.selectStart && interactable?.grabbable) {
10331
+ this.grab(world, input, hitEntityId);
10332
+ }
10333
+ }
10334
+ }
10335
+ collectInteractables(world) {
10336
+ const out = [];
10337
+ for (const entityId of world.query(XRInteractableComponent, Object3DRef)) {
10338
+ const interactable = world.getComponent(entityId, XRInteractableComponent);
10339
+ if (!interactable?.enabled || !interactable.pointable) continue;
10340
+ if (!world.isEntityVisible(entityId)) continue;
10341
+ const object = world.getComponent(entityId, Object3DRef)?.object;
10342
+ if (object) out.push({ entityId, object });
10343
+ }
10344
+ return out;
10345
+ }
10346
+ /** Entity id of the nearest pointable hit along this source's ray, or null. */
10347
+ raycast(input, interactables) {
10348
+ if (interactables.length === 0) return null;
10349
+ this.raycaster.set(input.rayOrigin, input.rayDirection);
10350
+ let nearestId = null;
10351
+ let nearestDistance = Number.POSITIVE_INFINITY;
10352
+ for (const entry of interactables) {
10353
+ const hit = this.raycaster.intersectObject(entry.object, true)[0];
10354
+ if (!hit) continue;
10355
+ if (hit.distance < nearestDistance) {
10356
+ nearestDistance = hit.distance;
10357
+ nearestId = entry.entityId;
10358
+ }
10359
+ }
10360
+ return nearestId;
10361
+ }
10362
+ grab(world, input, entityId) {
10363
+ const transform = world.getComponent(entityId, TransformComponent);
10364
+ if (!transform) return;
10365
+ const hand = this.handPosition(input);
10366
+ const offset = new THREE38__namespace.Vector3(
10367
+ transform.position.x - hand.x,
10368
+ transform.position.y - hand.y,
10369
+ transform.position.z - hand.z
10370
+ );
10371
+ const physics = world.getComponent(entityId, PhysicsComponent);
10372
+ let restoreBodyType = null;
10373
+ const interactable = world.getComponent(entityId, XRInteractableComponent);
10374
+ if (physics && interactable?.grabMode === "kinematic") {
10375
+ restoreBodyType = physics.values.rigidbody.type;
10376
+ physics.values.rigidbody.type = "kinematicPosition";
10377
+ }
10378
+ this.grabs.set(input, { entityId, offset, restoreBodyType });
10379
+ this.dispatch(world, entityId, (b) => b.onGrab(input));
10380
+ }
10381
+ moveHeld(world, input, held) {
10382
+ const transform = world.getComponent(held.entityId, TransformComponent);
10383
+ if (!transform) return;
10384
+ const hand = this.handPosition(input);
10385
+ transform.position.x = hand.x + held.offset.x;
10386
+ transform.position.y = hand.y + held.offset.y;
10387
+ transform.position.z = hand.z + held.offset.z;
10388
+ }
10389
+ release(world, input) {
10390
+ const held = this.grabs.get(input);
10391
+ if (!held) return;
10392
+ this.grabs.delete(input);
10393
+ if (held.restoreBodyType !== null) {
10394
+ const physics = world.getComponent(held.entityId, PhysicsComponent);
10395
+ if (physics) {
10396
+ physics.values.rigidbody.type = held.restoreBodyType;
10397
+ }
10398
+ }
10399
+ this.dispatch(world, held.entityId, (b) => b.onRelease(input));
10400
+ }
10401
+ releaseAll(world) {
10402
+ for (const input of Array.from(this.grabs.keys())) {
10403
+ this.release(world, input);
10404
+ }
10405
+ }
10406
+ /**
10407
+ * Where the "hand" is for this source. Controllers and tracked hands report a
10408
+ * grip pose; gaze and transient-pointer sources have none, so we hold the
10409
+ * object a fixed distance along the ray instead.
10410
+ */
10411
+ handPosition(input) {
10412
+ if (input.gripPosition) return input.gripPosition;
10413
+ return new THREE38__namespace.Vector3().copy(input.rayDirection).multiplyScalar(RAYLESS_HOLD_DISTANCE).add(input.rayOrigin);
10414
+ }
10415
+ dispatch(world, entityId, visit) {
10416
+ const script = world.getComponent(entityId, ScriptComponent);
10417
+ const instances = script?.scriptInstances;
10418
+ if (!instances) return;
10419
+ for (const instance of instances.values()) {
10420
+ if (!(instance instanceof Behaviour)) continue;
10421
+ try {
10422
+ visit(instance);
10423
+ } catch (error) {
10424
+ console.error("[XRInteractionSystem] Behaviour hook failed:", error);
10425
+ }
10426
+ }
10427
+ }
10428
+ /** Entity currently under a pointer this frame, or null. */
10429
+ getHoveredEntityId() {
10430
+ return this.hoveredEntityId;
10431
+ }
10432
+ /** True when any source is holding something. */
10433
+ isGrabbing() {
10434
+ return this.grabs.size > 0;
10435
+ }
10436
+ };
10437
+ __name(_XRInteractionSystem, "XRInteractionSystem");
10438
+ var XRInteractionSystem = _XRInteractionSystem;
10439
+ var UP = new THREE38__namespace.Vector3(0, 1, 0);
10440
+ var AXIS_DEADZONE = 0.5;
10441
+ var _XRLocomotionSystem = class _XRLocomotionSystem {
10442
+ constructor(inputSystem) {
10443
+ this.raycaster = new THREE38__namespace.Raycaster();
10444
+ /** Per-source latch so one stick push yields exactly one snap turn. */
10445
+ this.turnLatched = /* @__PURE__ */ new WeakSet();
10446
+ /** Where the pointer currently lands, for the consumer to draw a marker. */
10447
+ this.teleportPoint = null;
10448
+ this.inputSystem = inputSystem;
10449
+ }
10450
+ update(world, deltaTime) {
10451
+ this.teleportPoint = null;
10452
+ if (!world.isXrPresenting()) return;
10453
+ const rigEntityId = world.query(XRRigComponent, TransformComponent)[0];
10454
+ if (typeof rigEntityId !== "number") return;
10455
+ const rig = world.getComponent(rigEntityId, XRRigComponent);
10456
+ const rigTransform = world.getComponent(rigEntityId, TransformComponent);
10457
+ if (!rig || !rigTransform) return;
10458
+ const inputs = this.inputSystem.getInputs();
10459
+ if (inputs.length === 0) return;
10460
+ if (rig.snapTurn) {
10461
+ this.applySnapTurn(rig, rigTransform, inputs);
10462
+ }
10463
+ if (rig.locomotion === "teleport") {
10464
+ this.applyTeleport(world, rigTransform, inputs);
10465
+ } else if (rig.locomotion === "smooth") {
10466
+ this.applySmoothMove(world, rig, rigTransform, inputs, deltaTime);
10467
+ }
10468
+ }
10469
+ /**
10470
+ * Snap turning, not smooth turning — rotating the view continuously is the
10471
+ * single biggest cause of VR nausea, so the comfort-safe option is the one
10472
+ * wired to the stick.
10473
+ */
10474
+ applySnapTurn(rig, transform, inputs) {
10475
+ for (const input of inputs) {
10476
+ if (!input.hasAxes || input.axes.length < 3) continue;
10477
+ const x = input.axes[2] ?? 0;
10478
+ const source = input;
10479
+ if (Math.abs(x) < AXIS_DEADZONE) {
10480
+ this.turnLatched.delete(source);
10481
+ continue;
10482
+ }
10483
+ if (this.turnLatched.has(source)) continue;
10484
+ this.turnLatched.add(source);
10485
+ const step = THREE38__namespace.MathUtils.degToRad(rig.snapTurnDegrees);
10486
+ transform.rotation.y -= Math.sign(x) * step;
10487
+ }
10488
+ }
10489
+ applySmoothMove(world, rig, transform, inputs, deltaTime) {
10490
+ for (const input of inputs) {
10491
+ if (!input.hasAxes || input.axes.length < 2) continue;
10492
+ const x = input.axes[0] ?? 0;
10493
+ const y = input.axes[1] ?? 0;
10494
+ if (Math.abs(x) < 0.15 && Math.abs(y) < 0.15) continue;
10495
+ const camera = world.getCamera();
10496
+ const forward = new THREE38__namespace.Vector3();
10497
+ camera.getWorldDirection(forward);
10498
+ forward.y = 0;
10499
+ if (forward.lengthSq() < 1e-6) continue;
10500
+ forward.normalize();
10501
+ const right = new THREE38__namespace.Vector3().crossVectors(forward, UP).normalize();
10502
+ const step = rig.moveSpeed * Math.max(0, deltaTime);
10503
+ transform.position.x += (forward.x * -y + right.x * x) * step;
10504
+ transform.position.z += (forward.z * -y + right.z * x) * step;
10505
+ }
10506
+ }
10507
+ applyTeleport(world, transform, inputs) {
10508
+ const targets = this.collectTeleportTargets(world);
10509
+ if (targets.length === 0) return;
10510
+ for (const input of inputs) {
10511
+ this.raycaster.set(input.rayOrigin, input.rayDirection);
10512
+ const hit = this.raycaster.intersectObjects(targets, true)[0];
10513
+ if (!hit) continue;
10514
+ this.teleportPoint = hit.point.clone();
10515
+ if (input.selectEnd) {
10516
+ transform.position.x = hit.point.x;
10517
+ transform.position.y = hit.point.y;
10518
+ transform.position.z = hit.point.z;
10519
+ }
10520
+ }
10521
+ }
10522
+ collectTeleportTargets(world) {
10523
+ const objects = [];
10524
+ for (const entityId of world.query(VRTeleportAreaComponent, Object3DRef)) {
10525
+ const area = world.getComponent(entityId, VRTeleportAreaComponent);
10526
+ if (!area?.enabled) continue;
10527
+ if (!world.isEntityVisible(entityId)) continue;
10528
+ const object = world.getComponent(entityId, Object3DRef)?.object;
10529
+ if (object) objects.push(object);
10530
+ }
10531
+ return objects;
10532
+ }
10533
+ /**
10534
+ * Where the teleport pointer currently lands this frame, or null.
10535
+ * Consumers use this to render an aim marker.
10536
+ */
10537
+ getTeleportPoint() {
10538
+ return this.teleportPoint;
10539
+ }
10540
+ };
10541
+ __name(_XRLocomotionSystem, "XRLocomotionSystem");
10542
+ var XRLocomotionSystem = _XRLocomotionSystem;
10543
+
10544
+ // core/xr/types.ts
10545
+ var NO_XR_CAPABILITIES = {
10546
+ mode: "inline",
10547
+ handTracking: false,
10548
+ planeDetection: false,
10549
+ meshDetection: false,
10550
+ depthSensing: false,
10551
+ anchors: false,
10552
+ hitTest: false,
10553
+ enabledFeatures: []
10554
+ };
10555
+ function readXrCapabilities(session, mode = "immersive-vr") {
10556
+ if (!session) return NO_XR_CAPABILITIES;
10557
+ const raw = session.enabledFeatures;
10558
+ const features = Array.isArray(raw) ? Array.from(raw) : [];
10559
+ const has = /* @__PURE__ */ __name((name) => features.includes(name), "has");
10560
+ return {
10561
+ mode,
10562
+ handTracking: has("hand-tracking"),
10563
+ planeDetection: has("plane-detection"),
10564
+ meshDetection: has("mesh-detection"),
10565
+ depthSensing: has("depth-sensing"),
10566
+ anchors: has("anchors"),
10567
+ hitTest: has("hit-test"),
10568
+ enabledFeatures: features
10569
+ };
10570
+ }
10571
+ __name(readXrCapabilities, "readXrCapabilities");
10572
+
10573
+ // core/systems/XRSessionSystem.ts
10574
+ var _XRSessionSystem = class _XRSessionSystem {
10575
+ constructor(inputSystem) {
10576
+ this.presenting = false;
10577
+ this.capabilities = NO_XR_CAPABILITIES;
10578
+ this.inputSystem = inputSystem ?? null;
10579
+ }
10580
+ update(world) {
10581
+ const presenting = world.isXrPresenting();
10582
+ if (presenting !== this.presenting) {
10583
+ this.presenting = presenting;
10584
+ if (presenting) {
10585
+ this.handleSessionStart(world);
10586
+ } else {
10587
+ this.handleSessionEnd(world);
10588
+ }
10589
+ }
10590
+ if (presenting) {
10591
+ this.dispatchInputEdges(world);
10592
+ }
10593
+ }
10594
+ handleSessionStart(world) {
10595
+ const session = world.getRenderer().xr.getSession();
10596
+ const mode = session && session.environmentBlendMode !== "opaque" ? "immersive-ar" : "immersive-vr";
10597
+ this.capabilities = readXrCapabilities(session ?? null, mode);
10598
+ if (session && this.inputSystem) {
10599
+ this.inputSystem.attachSession(session);
10600
+ }
10601
+ this.forEachBehaviour(world, (behaviour) => {
10602
+ behaviour.onXRSessionStart(this.capabilities);
10603
+ });
10604
+ }
10605
+ handleSessionEnd(world) {
10606
+ this.capabilities = NO_XR_CAPABILITIES;
10607
+ this.inputSystem?.detachSession();
10608
+ this.forEachBehaviour(world, (behaviour) => {
10609
+ behaviour.onXRSessionEnd();
10610
+ });
10611
+ }
10612
+ /**
10613
+ * Relay this frame's one-frame select edges. Polling the latched state (rather
10614
+ * than dispatching from the DOM event) keeps hook delivery on the ECS tick, so
10615
+ * a Behaviour's `onSelectStart` always observes the same world state its
10616
+ * `onUpdate` would.
10617
+ */
10618
+ dispatchInputEdges(world) {
10619
+ const inputs = this.inputSystem?.getInputs();
10620
+ if (!inputs || inputs.length === 0) return;
10621
+ for (const input of inputs) {
10622
+ if (input.selectStart) {
10623
+ this.forEachBehaviour(world, (b) => b.onSelectStart(input));
10624
+ }
10625
+ if (input.selectEnd) {
10626
+ this.forEachBehaviour(world, (b) => b.onSelectEnd(input));
10627
+ }
10628
+ }
10629
+ }
10630
+ forEachBehaviour(world, visit) {
10631
+ for (const entityId of world.query(ScriptComponent)) {
10632
+ const script = world.getComponent(entityId, ScriptComponent);
10633
+ const instances = script?.scriptInstances;
10634
+ if (!instances) continue;
10635
+ for (const instance of instances.values()) {
10636
+ if (!(instance instanceof Behaviour)) continue;
10637
+ try {
10638
+ visit(instance);
10639
+ } catch (error) {
10640
+ console.error("[XRSessionSystem] Behaviour hook failed:", error);
10641
+ }
10642
+ }
10643
+ }
10644
+ }
10645
+ /** What the active session granted. `NO_XR_CAPABILITIES` when not presenting. */
10646
+ getCapabilities() {
10647
+ return this.capabilities;
10648
+ }
10649
+ /** True while an immersive session is presenting. */
10650
+ isPresenting() {
10651
+ return this.presenting;
10652
+ }
10653
+ /** Convenience passthrough so consumers need only hold this system. */
10654
+ getInputs() {
10655
+ return this.inputSystem?.getInputs() ?? [];
10656
+ }
10657
+ };
10658
+ __name(_XRSessionSystem, "XRSessionSystem");
10659
+ var XRSessionSystem = _XRSessionSystem;
10660
+ function buildGeometry2(area) {
10661
+ if (area.shape === "cylinder") {
10662
+ const radius = Math.max(5e-3, area.width / 2);
10663
+ return new THREE38__namespace.CircleGeometry(radius, 48);
10664
+ }
10665
+ return new THREE38__namespace.PlaneGeometry(
10666
+ Math.max(0.01, area.width),
10667
+ Math.max(0.01, area.depth)
10668
+ );
10669
+ }
10670
+ __name(buildGeometry2, "buildGeometry");
10671
+ function signatureOf(area) {
10672
+ return `${area.shape}:${area.width}:${area.depth}`;
10673
+ }
10674
+ __name(signatureOf, "signatureOf");
10675
+ var _VRTeleportAreaSystem = class _VRTeleportAreaSystem {
10676
+ constructor() {
10677
+ this.signatures = /* @__PURE__ */ new Map();
10678
+ }
10679
+ update(world) {
10680
+ const entityIds = world.query(VRTeleportAreaComponent, Object3DRef);
10681
+ const alive = new Set(entityIds);
10682
+ for (const tracked of this.signatures.keys()) {
10683
+ if (!alive.has(tracked)) this.signatures.delete(tracked);
10684
+ }
10685
+ for (const entityId of entityIds) {
10686
+ const area = world.getComponent(entityId, VRTeleportAreaComponent);
10687
+ const object = world.getComponent(entityId, Object3DRef)?.object;
10688
+ if (!area || !(object instanceof THREE38__namespace.Mesh)) continue;
10689
+ const signature = signatureOf(area);
10690
+ if (this.signatures.get(entityId) === signature) continue;
10691
+ this.signatures.set(entityId, signature);
10692
+ object.geometry?.dispose?.();
10693
+ object.geometry = buildGeometry2(area);
10694
+ }
10695
+ }
10696
+ };
10697
+ __name(_VRTeleportAreaSystem, "VRTeleportAreaSystem");
10698
+ var VRTeleportAreaSystem = _VRTeleportAreaSystem;
10699
+ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
10700
+ constructor(slots = 2) {
10701
+ this.controllerModelFactory = new XRControllerModelFactory_js.XRControllerModelFactory();
10702
+ this.handModelFactory = new XRHandModelFactory_js.XRHandModelFactory();
10703
+ this.group = new THREE38__namespace.Group();
10704
+ this.built = false;
10705
+ this.attachedTo = null;
10706
+ /** Index → whether we've already attached visuals for that slot. */
10707
+ this.ready = /* @__PURE__ */ new Set();
10708
+ this.slots = slots;
10709
+ this.group.name = "XRControllerVisuals";
10710
+ this.group.userData.ecsPreviewHidden = true;
10711
+ }
10712
+ update(world) {
10713
+ const renderer = world.getRenderer();
10714
+ if (!renderer.xr?.enabled) return;
10715
+ this.ensureAttached(world);
10716
+ if (this.built) return;
10717
+ for (let index = 0; index < this.slots; index += 1) {
10718
+ if (this.ready.has(index)) continue;
10719
+ const controller = renderer.xr.getController(index);
10720
+ const grip = renderer.xr.getControllerGrip(index);
10721
+ const hand = renderer.xr.getHand(index);
10722
+ if (!controller || !grip || !hand) continue;
10723
+ controller.add(this.createRay());
10724
+ this.group.add(controller);
10725
+ grip.add(this.controllerModelFactory.createControllerModel(grip));
10726
+ this.group.add(grip);
10727
+ hand.add(this.handModelFactory.createHandModel(hand, "mesh"));
10728
+ this.group.add(hand);
10729
+ this.ready.add(index);
10730
+ }
10731
+ if (this.ready.size >= this.slots) {
10732
+ this.built = true;
10733
+ }
10734
+ }
10735
+ /**
10736
+ * Parent the visuals to the XR rig when there is one, so locomotion moves the
10737
+ * hands with the player. Falls back to the scene root.
10738
+ */
10739
+ ensureAttached(world) {
10740
+ const camera = world.getCamera();
10741
+ const target = camera.parent ?? world.getScene();
10742
+ if (this.attachedTo === target) return;
10743
+ target.add(this.group);
10744
+ this.attachedTo = target;
10745
+ }
10746
+ createRay() {
10747
+ const geometry = new THREE38__namespace.BufferGeometry().setFromPoints([
10748
+ new THREE38__namespace.Vector3(0, 0, 0),
10749
+ new THREE38__namespace.Vector3(0, 0, -5)
10750
+ ]);
10751
+ const material = new THREE38__namespace.LineBasicMaterial({
10752
+ color: "#4da3ff",
10753
+ transparent: true,
10754
+ opacity: 0.6,
10755
+ depthTest: false
10756
+ });
10757
+ const line = new THREE38__namespace.Line(geometry, material);
10758
+ line.name = "XRPointerRay";
10759
+ line.renderOrder = 999;
10760
+ return line;
10761
+ }
10762
+ dispose() {
10763
+ this.group.removeFromParent();
10764
+ this.group.traverse((child) => {
10765
+ const mesh = child;
10766
+ mesh.geometry?.dispose?.();
10767
+ const material = mesh.material;
10768
+ if (Array.isArray(material)) {
10769
+ for (const entry of material) entry.dispose?.();
10770
+ } else {
10771
+ material?.dispose?.();
10772
+ }
10773
+ });
10774
+ this.group.clear();
10775
+ this.ready.clear();
10776
+ this.built = false;
10777
+ this.attachedTo = null;
10778
+ }
10779
+ };
10780
+ __name(_XRControllerVisualSystem, "XRControllerVisualSystem");
10781
+ var XRControllerVisualSystem = _XRControllerVisualSystem;
9902
10782
 
9903
10783
  // core/World.ts
9904
10784
  var _World = class _World {
@@ -10244,6 +11124,7 @@ var _World = class _World {
10244
11124
  const postprocessingSyncSystem = this.featureFlags.supportPostprocessing ? new PostprocessingSyncSystem(this.renderer, this.scene, this.camera) : null;
10245
11125
  const lightSyncSystem = new LightSyncSystem();
10246
11126
  const materialSyncSystem = new MaterialSyncSystem();
11127
+ const vrTeleportAreaSystem = new VRTeleportAreaSystem();
10247
11128
  const physicsSyncSystem = new PhysicsSyncSystem({
10248
11129
  isEditor: isEditor ?? false
10249
11130
  });
@@ -10273,6 +11154,7 @@ var _World = class _World {
10273
11154
  }
10274
11155
  this.addSystems([
10275
11156
  ...coreSystems,
11157
+ vrTeleportAreaSystem,
10276
11158
  physicsSyncSystem,
10277
11159
  ...systems,
10278
11160
  objectVisibilitySystem,
@@ -10304,6 +11186,22 @@ var _World = class _World {
10304
11186
  isEditorMode() {
10305
11187
  return this.isEditor;
10306
11188
  }
11189
+ /**
11190
+ * `true` while an immersive WebXR session is actively presenting.
11191
+ *
11192
+ * While presenting, three's `WebXRManager` OWNS the render camera: each frame
11193
+ * `updateUserCamera()` writes the headset pose into the camera's
11194
+ * position/quaternion/scale and copies the XR projection (including a derived
11195
+ * `fov`) onto it. Systems that also drive the camera must stand down for the
11196
+ * duration, or they ping-pong with the headset every frame and defeat their
11197
+ * own dirty-checks.
11198
+ *
11199
+ * Locomotion therefore moves the camera's PARENT (the XR rig) — three composes
11200
+ * the head pose as `parent.matrixWorld × headPose`.
11201
+ */
11202
+ isXrPresenting() {
11203
+ return this.renderer.xr?.isPresenting === true;
11204
+ }
10307
11205
  /**
10308
11206
  * Pauses world simulation. While paused, `update()` skips all system ticks so
10309
11207
  * physics, animation, scripts, and rendering stop advancing. The last rendered
@@ -10551,8 +11449,8 @@ var _World = class _World {
10551
11449
  * ```
10552
11450
  */
10553
11451
  raycast(origin, direction, near = 0, far = Infinity) {
10554
- const rayOrigin = new THREE36__namespace.Vector3(origin.x, origin.y, origin.z);
10555
- const rayDirection = new THREE36__namespace.Vector3(
11452
+ const rayOrigin = new THREE38__namespace.Vector3(origin.x, origin.y, origin.z);
11453
+ const rayDirection = new THREE38__namespace.Vector3(
10556
11454
  direction.x,
10557
11455
  direction.y,
10558
11456
  direction.z
@@ -10561,7 +11459,7 @@ var _World = class _World {
10561
11459
  return [];
10562
11460
  }
10563
11461
  rayDirection.normalize();
10564
- const raycaster = new THREE36__namespace.Raycaster(rayOrigin, rayDirection, near, far);
11462
+ const raycaster = new THREE38__namespace.Raycaster(rayOrigin, rayDirection, near, far);
10565
11463
  const intersections = raycaster.intersectObjects(
10566
11464
  this.scene.children,
10567
11465
  true
@@ -10595,14 +11493,14 @@ var _World = class _World {
10595
11493
  if (!sourceObject) {
10596
11494
  return [];
10597
11495
  }
10598
- const rayOrigin = new THREE36__namespace.Vector3();
10599
- const rayDirection = new THREE36__namespace.Vector3();
11496
+ const rayOrigin = new THREE38__namespace.Vector3();
11497
+ const rayDirection = new THREE38__namespace.Vector3();
10600
11498
  sourceObject.getWorldPosition(rayOrigin);
10601
11499
  sourceObject.getWorldDirection(rayDirection);
10602
11500
  if (rayDirection.lengthSq() === 0) {
10603
11501
  return [];
10604
11502
  }
10605
- const raycaster = new THREE36__namespace.Raycaster(rayOrigin, rayDirection, near, far);
11503
+ const raycaster = new THREE38__namespace.Raycaster(rayOrigin, rayDirection, near, far);
10606
11504
  const intersections = raycaster.intersectObjects(
10607
11505
  this.scene.children,
10608
11506
  true
@@ -11272,6 +12170,7 @@ exports.LightSyncSystem = LightSyncSystem;
11272
12170
  exports.MaterialSyncSystem = MaterialSyncSystem;
11273
12171
  exports.MeshGeometrySystem = MeshGeometrySystem;
11274
12172
  exports.NODE_KEY_SEPARATOR = NODE_KEY_SEPARATOR;
12173
+ exports.NO_XR_CAPABILITIES = NO_XR_CAPABILITIES;
11275
12174
  exports.OVERRIDE_DIFF_EXCLUDED_COMPONENTS = OVERRIDE_DIFF_EXCLUDED_COMPONENTS;
11276
12175
  exports.OVERRIDE_ROOT_EXCLUDED_COMPONENTS = OVERRIDE_ROOT_EXCLUDED_COMPONENTS;
11277
12176
  exports.ObjectManagementSystem = ObjectManagementSystem;
@@ -11287,8 +12186,14 @@ exports.ScriptBehaviourSystem = ScriptBehaviourSystem;
11287
12186
  exports.ScriptObject = ScriptObject;
11288
12187
  exports.ScriptObjectSystem = ScriptObjectSystem;
11289
12188
  exports.TransformSyncSystem = TransformSyncSystem;
12189
+ exports.VRTeleportAreaSystem = VRTeleportAreaSystem;
11290
12190
  exports.VideoSystem = VideoSystem;
11291
12191
  exports.World = World;
12192
+ exports.XRControllerVisualSystem = XRControllerVisualSystem;
12193
+ exports.XRInputSystem = XRInputSystem;
12194
+ exports.XRInteractionSystem = XRInteractionSystem;
12195
+ exports.XRLocomotionSystem = XRLocomotionSystem;
12196
+ exports.XRSessionSystem = XRSessionSystem;
11292
12197
  exports.applyPrefabToSnapshotInstances = applyPrefabToSnapshotInstances;
11293
12198
  exports.buildComponentValueMaps = buildComponentValueMaps;
11294
12199
  exports.buildNodeKeyMapsFromSnapshot = buildNodeKeyMapsFromSnapshot;
@@ -11327,7 +12232,10 @@ exports.createSelectableComponent = createSelectableComponent;
11327
12232
  exports.createSelectionTransformStateComponent = createSelectionTransformStateComponent;
11328
12233
  exports.createSpriteComponent = createSpriteComponent;
11329
12234
  exports.createTransformComponent = createTransformComponent;
12235
+ exports.createVRTeleportAreaComponent = createVRTeleportAreaComponent;
11330
12236
  exports.createVideoComponent = createVideoComponent;
12237
+ exports.createXRInteractableComponent = createXRInteractableComponent;
12238
+ exports.createXRRigComponent = createXRRigComponent;
11331
12239
  exports.decanonicalizeComponentValue = decanonicalizeComponentValue;
11332
12240
  exports.despawnPrefab = despawnPrefab;
11333
12241
  exports.encodeOverride = encodeOverride;
@@ -11344,6 +12252,7 @@ exports.mergeComponentValue = mergeComponentValue;
11344
12252
  exports.parseOverride = parseOverride;
11345
12253
  exports.parsePrefabAsset = parsePrefabAsset;
11346
12254
  exports.prefabFileVersionFor = prefabFileVersionFor;
12255
+ exports.readXrCapabilities = readXrCapabilities;
11347
12256
  exports.registerDefaultComponentFactories = registerDefaultComponentFactories;
11348
12257
  exports.registerDefaultFactories = registerDefaultFactories;
11349
12258
  exports.remapSnapshotEntityIds = remapSnapshotEntityIds;