@relu-interactives/spatial-ecs 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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-PCOZLCXS.js} +160 -83
  8. package/dist/chunk-PCOZLCXS.js.map +1 -0
  9. package/dist/{chunk-7BPHZWQ6.js → chunk-U3MDYKPV.js} +47 -3
  10. package/dist/chunk-U3MDYKPV.js.map +1 -0
  11. package/dist/{chunk-7JFSEV7A.js → chunk-VXUVNC7S.js} +633 -6
  12. package/dist/chunk-VXUVNC7S.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 +228 -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-Gr8aCPRM.d.cts → index-CUFd71ri.d.cts} +12 -3
  24. package/dist/index-D84o_UA6.d.ts +488 -0
  25. package/dist/index-YYypJaVw.d.cts +488 -0
  26. package/dist/{index-BwiRJNIT.d.ts → index-w1oqWl_M.d.ts} +12 -3
  27. package/dist/index.cjs +971 -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 +24 -8
  32. package/dist/index.js.map +1 -1
  33. package/dist/systems/index.cjs +673 -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');
@@ -39,7 +39,7 @@ function _interopNamespace(e) {
39
39
  return Object.freeze(n);
40
40
  }
41
41
 
42
- var THREE36__namespace = /*#__PURE__*/_interopNamespace(THREE36);
42
+ var THREE38__namespace = /*#__PURE__*/_interopNamespace(THREE38);
43
43
 
44
44
  var __defProp = Object.defineProperty;
45
45
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
@@ -603,14 +603,14 @@ var _AnimationComponent = class _AnimationComponent extends Component {
603
603
  return;
604
604
  }
605
605
  this.importedClips = clips.map((entry) => {
606
- if (entry instanceof THREE36__namespace.AnimationClip) {
606
+ if (entry instanceof THREE38__namespace.AnimationClip) {
607
607
  return { clip: entry, sourceUrl: null };
608
608
  }
609
609
  if (!entry || typeof entry !== "object") {
610
610
  return null;
611
611
  }
612
612
  const candidate = entry;
613
- if (!(candidate.clip instanceof THREE36__namespace.AnimationClip)) {
613
+ if (!(candidate.clip instanceof THREE38__namespace.AnimationClip)) {
614
614
  return null;
615
615
  }
616
616
  return {
@@ -818,11 +818,11 @@ function normalizeDistanceModel(distanceModel) {
818
818
  }
819
819
  __name(normalizeDistanceModel, "normalizeDistanceModel");
820
820
  function createConfiguredAudio(listener, options) {
821
- const sound = options.positional ? new THREE36__namespace.PositionalAudio(listener) : new THREE36__namespace.Audio(listener);
821
+ const sound = options.positional ? new THREE38__namespace.PositionalAudio(listener) : new THREE38__namespace.Audio(listener);
822
822
  sound.setLoop(options.loop);
823
823
  sound.setVolume(options.volume);
824
824
  sound.setPlaybackRate(options.pitch);
825
- if (sound instanceof THREE36__namespace.PositionalAudio) {
825
+ if (sound instanceof THREE38__namespace.PositionalAudio) {
826
826
  sound.setRefDistance(options.refDistance);
827
827
  sound.setDistanceModel(normalizeDistanceModel(options.distanceModel));
828
828
  sound.setRolloffFactor(options.rolloffFactor);
@@ -832,16 +832,16 @@ function createConfiguredAudio(listener, options) {
832
832
  __name(createConfiguredAudio, "createConfiguredAudio");
833
833
  function createAudioEditorHelper() {
834
834
  if (typeof document === "undefined") {
835
- const geometry = new THREE36__namespace.EdgesGeometry(
836
- new THREE36__namespace.OctahedronGeometry(0.22, 0)
835
+ const geometry = new THREE38__namespace.EdgesGeometry(
836
+ new THREE38__namespace.OctahedronGeometry(0.22, 0)
837
837
  );
838
- const material2 = new THREE36__namespace.LineBasicMaterial({
838
+ const material2 = new THREE38__namespace.LineBasicMaterial({
839
839
  color: "#8bc8ff",
840
840
  transparent: true,
841
841
  opacity: 0.95,
842
842
  depthTest: false
843
843
  });
844
- const fallback = new THREE36__namespace.LineSegments(geometry, material2);
844
+ const fallback = new THREE38__namespace.LineSegments(geometry, material2);
845
845
  fallback.renderOrder = 10;
846
846
  fallback.userData.ecsHelper = true;
847
847
  fallback.visible = false;
@@ -853,7 +853,7 @@ function createAudioEditorHelper() {
853
853
  canvas.height = size;
854
854
  const ctx = canvas.getContext("2d");
855
855
  if (!ctx) {
856
- return new THREE36__namespace.Object3D();
856
+ return new THREE38__namespace.Object3D();
857
857
  }
858
858
  ctx.clearRect(0, 0, size, size);
859
859
  ctx.fillStyle = "rgba(27, 35, 52, 0.9)";
@@ -884,14 +884,14 @@ function createAudioEditorHelper() {
884
884
  ctx.beginPath();
885
885
  ctx.arc(56, 48, 16, -0.8, 0.8);
886
886
  ctx.stroke();
887
- const texture = new THREE36__namespace.CanvasTexture(canvas);
887
+ const texture = new THREE38__namespace.CanvasTexture(canvas);
888
888
  texture.needsUpdate = true;
889
- const material = new THREE36__namespace.SpriteMaterial({
889
+ const material = new THREE38__namespace.SpriteMaterial({
890
890
  map: texture,
891
891
  transparent: true,
892
892
  depthTest: false
893
893
  });
894
- const helper = new THREE36__namespace.Sprite(material);
894
+ const helper = new THREE38__namespace.Sprite(material);
895
895
  helper.scale.set(0.68, 0.68, 0.68);
896
896
  helper.renderOrder = 10;
897
897
  helper.userData.ecsHelper = true;
@@ -925,7 +925,7 @@ var DEFAULT_ORTHO_TOP = 5;
925
925
  var DEFAULT_ORTHO_BOTTOM = -5;
926
926
  var DEFAULT_ZOOM = 1;
927
927
  function inferProjection(camera) {
928
- if (camera instanceof THREE36__namespace.OrthographicCamera) {
928
+ if (camera instanceof THREE38__namespace.OrthographicCamera) {
929
929
  return "orthographic";
930
930
  }
931
931
  return "perspective";
@@ -946,7 +946,7 @@ function readCameraFar(camera) {
946
946
  }
947
947
  __name(readCameraFar, "readCameraFar");
948
948
  function inferFov(camera) {
949
- if (camera instanceof THREE36__namespace.PerspectiveCamera && Number.isFinite(camera.fov)) {
949
+ if (camera instanceof THREE38__namespace.PerspectiveCamera && Number.isFinite(camera.fov)) {
950
950
  return camera.fov;
951
951
  }
952
952
  return DEFAULT_FOV;
@@ -969,28 +969,28 @@ function inferFar(camera) {
969
969
  }
970
970
  __name(inferFar, "inferFar");
971
971
  function inferOrthoLeft(camera) {
972
- if (camera instanceof THREE36__namespace.OrthographicCamera && Number.isFinite(camera.left)) {
972
+ if (camera instanceof THREE38__namespace.OrthographicCamera && Number.isFinite(camera.left)) {
973
973
  return camera.left;
974
974
  }
975
975
  return DEFAULT_ORTHO_LEFT;
976
976
  }
977
977
  __name(inferOrthoLeft, "inferOrthoLeft");
978
978
  function inferOrthoRight(camera) {
979
- if (camera instanceof THREE36__namespace.OrthographicCamera && Number.isFinite(camera.right)) {
979
+ if (camera instanceof THREE38__namespace.OrthographicCamera && Number.isFinite(camera.right)) {
980
980
  return camera.right;
981
981
  }
982
982
  return DEFAULT_ORTHO_RIGHT;
983
983
  }
984
984
  __name(inferOrthoRight, "inferOrthoRight");
985
985
  function inferOrthoTop(camera) {
986
- if (camera instanceof THREE36__namespace.OrthographicCamera && Number.isFinite(camera.top)) {
986
+ if (camera instanceof THREE38__namespace.OrthographicCamera && Number.isFinite(camera.top)) {
987
987
  return camera.top;
988
988
  }
989
989
  return DEFAULT_ORTHO_TOP;
990
990
  }
991
991
  __name(inferOrthoTop, "inferOrthoTop");
992
992
  function inferOrthoBottom(camera) {
993
- if (camera instanceof THREE36__namespace.OrthographicCamera && Number.isFinite(camera.bottom)) {
993
+ if (camera instanceof THREE38__namespace.OrthographicCamera && Number.isFinite(camera.bottom)) {
994
994
  return camera.bottom;
995
995
  }
996
996
  return DEFAULT_ORTHO_BOTTOM;
@@ -1006,7 +1006,7 @@ __name(inferZoom, "inferZoom");
1006
1006
  var _CameraComponent = class _CameraComponent extends Component {
1007
1007
  constructor(payload = {}) {
1008
1008
  super();
1009
- this.camera = payload.camera ?? new THREE36__namespace.PerspectiveCamera();
1009
+ this.camera = payload.camera ?? new THREE38__namespace.PerspectiveCamera();
1010
1010
  this.type = payload.type ?? "3d";
1011
1011
  this.isDefault = typeof payload.isDefault === "boolean" ? payload.isDefault : false;
1012
1012
  this.projection = payload.projection ?? inferProjection(payload.camera);
@@ -1037,7 +1037,7 @@ var Object3DRef = _Object3DRef;
1037
1037
  // core/factories/components/CameraFactory.ts
1038
1038
  function createCameraComponent(world, entityId, payload = {}) {
1039
1039
  const object = world.getComponent(entityId, Object3DRef)?.object;
1040
- const objectCamera = object instanceof THREE36__namespace.Camera ? object : void 0;
1040
+ const objectCamera = object instanceof THREE38__namespace.Camera ? object : void 0;
1041
1041
  const component = new CameraComponent({
1042
1042
  ...payload,
1043
1043
  camera: payload.camera ?? objectCamera
@@ -1607,15 +1607,15 @@ function createValueState(light) {
1607
1607
  castShadow: light.castShadow ?? false,
1608
1608
  frustumCulling: light.frustumCulled
1609
1609
  };
1610
- if (light instanceof THREE36__namespace.PointLight) {
1610
+ if (light instanceof THREE38__namespace.PointLight) {
1611
1611
  base.distance = light.distance;
1612
1612
  base.decay = light.decay;
1613
- } else if (light instanceof THREE36__namespace.SpotLight) {
1613
+ } else if (light instanceof THREE38__namespace.SpotLight) {
1614
1614
  base.distance = light.distance;
1615
1615
  base.decay = light.decay;
1616
1616
  base.angle = light.angle;
1617
1617
  base.penumbra = light.penumbra;
1618
- } else if (light instanceof THREE36__namespace.RectAreaLight) {
1618
+ } else if (light instanceof THREE38__namespace.RectAreaLight) {
1619
1619
  base.width = light.width;
1620
1620
  base.height = light.height;
1621
1621
  }
@@ -1658,13 +1658,13 @@ function toHexColor2(value, fallback) {
1658
1658
  }
1659
1659
  __name(toHexColor2, "toHexColor");
1660
1660
  function getMaterialType(material) {
1661
- if (material instanceof THREE36__namespace.MeshPhysicalMaterial) {
1661
+ if (material instanceof THREE38__namespace.MeshPhysicalMaterial) {
1662
1662
  return "physical";
1663
1663
  }
1664
- if (material instanceof THREE36__namespace.MeshPhongMaterial) {
1664
+ if (material instanceof THREE38__namespace.MeshPhongMaterial) {
1665
1665
  return "phong";
1666
1666
  }
1667
- if (material instanceof THREE36__namespace.MeshBasicMaterial) {
1667
+ if (material instanceof THREE38__namespace.MeshBasicMaterial) {
1668
1668
  return "basic";
1669
1669
  }
1670
1670
  return "standard";
@@ -1699,8 +1699,8 @@ function createMaterialValue(material) {
1699
1699
  opacity: typeof materialRecord.opacity === "number" ? materialRecord.opacity : 1,
1700
1700
  emissive: toHexColor2(materialRecord.emissive, "#000000"),
1701
1701
  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,
1702
+ side: typeof materialRecord.side === "number" ? materialRecord.side : THREE38__namespace.FrontSide,
1703
+ blending: typeof materialRecord.blending === "number" ? materialRecord.blending : THREE38__namespace.NormalBlending,
1704
1704
  depthTest: materialRecord.depthTest !== false,
1705
1705
  depthWrite: materialRecord.depthWrite !== false,
1706
1706
  wireframe: Boolean(materialRecord.wireframe),
@@ -1732,7 +1732,7 @@ function createMaterialValue(material) {
1732
1732
  materialRecord.lightMap
1733
1733
  ),
1734
1734
  envMap: textureImageSrc(materialRecord.envMap),
1735
- textureFiltering: map?.magFilter === THREE36__namespace.NearestFilter ? "sharp" : "smooth",
1735
+ textureFiltering: map?.magFilter === THREE38__namespace.NearestFilter ? "sharp" : "smooth",
1736
1736
  useMipmaps: map?.generateMipmaps !== false
1737
1737
  };
1738
1738
  }
@@ -1747,8 +1747,8 @@ function defaultMaterialValue() {
1747
1747
  opacity: 1,
1748
1748
  emissive: "#000000",
1749
1749
  emissiveIntensity: 0,
1750
- side: THREE36__namespace.FrontSide,
1751
- blending: THREE36__namespace.NormalBlending,
1750
+ side: THREE38__namespace.FrontSide,
1751
+ blending: THREE38__namespace.NormalBlending,
1752
1752
  depthTest: true,
1753
1753
  depthWrite: true,
1754
1754
  wireframe: false,
@@ -2325,14 +2325,14 @@ var _TransformComponent = class _TransformComponent extends Component {
2325
2325
  z: scale.z ?? 1
2326
2326
  };
2327
2327
  }
2328
- toPositionVector3(target = new THREE36.Vector3()) {
2328
+ toPositionVector3(target = new THREE38.Vector3()) {
2329
2329
  return target.set(this.position.x, this.position.y, this.position.z);
2330
2330
  }
2331
- toRotationEuler(target = new THREE36.Euler(), order = "XYZ") {
2331
+ toRotationEuler(target = new THREE38.Euler(), order = "XYZ") {
2332
2332
  return target.set(this.rotation.x, this.rotation.y, this.rotation.z, order);
2333
2333
  }
2334
- toRotationQuaternion(target = new THREE36.Quaternion(), order = "XYZ") {
2335
- const euler = new THREE36.Euler(
2334
+ toRotationQuaternion(target = new THREE38.Quaternion(), order = "XYZ") {
2335
+ const euler = new THREE38.Euler(
2336
2336
  this.rotation.x,
2337
2337
  this.rotation.y,
2338
2338
  this.rotation.z,
@@ -2340,7 +2340,7 @@ var _TransformComponent = class _TransformComponent extends Component {
2340
2340
  );
2341
2341
  return target.setFromEuler(euler);
2342
2342
  }
2343
- toScaleVector3(target = new THREE36.Vector3()) {
2343
+ toScaleVector3(target = new THREE38.Vector3()) {
2344
2344
  return target.set(this.scale.x, this.scale.y, this.scale.z);
2345
2345
  }
2346
2346
  setPosition(input) {
@@ -2358,8 +2358,8 @@ var _TransformComponent = class _TransformComponent extends Component {
2358
2358
  return this;
2359
2359
  }
2360
2360
  setRotation(input, order = "XYZ") {
2361
- if (input instanceof THREE36.Quaternion) {
2362
- const euler = new THREE36.Euler().setFromQuaternion(input, order);
2361
+ if (input instanceof THREE38.Quaternion) {
2362
+ const euler = new THREE38.Euler().setFromQuaternion(input, order);
2363
2363
  this.rotation.x = euler.x;
2364
2364
  this.rotation.y = euler.y;
2365
2365
  this.rotation.z = euler.z;
@@ -2564,6 +2564,71 @@ function createVideoComponent(world, entityId, ...args) {
2564
2564
  }
2565
2565
  __name(createVideoComponent, "createVideoComponent");
2566
2566
 
2567
+ // core/components/XRRig.ts
2568
+ var _XRRigComponent = class _XRRigComponent extends Component {
2569
+ constructor(options) {
2570
+ super();
2571
+ this.locomotion = options?.locomotion ?? "teleport";
2572
+ this.moveSpeed = options?.moveSpeed ?? 2;
2573
+ this.snapTurn = options?.snapTurn ?? true;
2574
+ this.snapTurnDegrees = options?.snapTurnDegrees ?? 30;
2575
+ this.fallbackEyeHeight = options?.fallbackEyeHeight ?? 1.6;
2576
+ }
2577
+ };
2578
+ __name(_XRRigComponent, "XRRigComponent");
2579
+ var XRRigComponent = _XRRigComponent;
2580
+
2581
+ // core/factories/components/XRRigFactory.ts
2582
+ function createXRRigComponent(world, entityId, ...args) {
2583
+ const component = new XRRigComponent(...args);
2584
+ world.addComponent(entityId, component);
2585
+ return component;
2586
+ }
2587
+ __name(createXRRigComponent, "createXRRigComponent");
2588
+
2589
+ // core/components/VRTeleportArea.ts
2590
+ var _VRTeleportAreaComponent = class _VRTeleportAreaComponent extends Component {
2591
+ constructor(options) {
2592
+ super();
2593
+ this.enabled = options?.enabled ?? true;
2594
+ this.shape = options?.shape ?? "plane";
2595
+ this.width = options?.width ?? 10;
2596
+ this.depth = options?.depth ?? 10;
2597
+ }
2598
+ };
2599
+ __name(_VRTeleportAreaComponent, "VRTeleportAreaComponent");
2600
+ var VRTeleportAreaComponent = _VRTeleportAreaComponent;
2601
+
2602
+ // core/factories/components/VRTeleportAreaFactory.ts
2603
+ function createVRTeleportAreaComponent(world, entityId, ...args) {
2604
+ const component = new VRTeleportAreaComponent(...args);
2605
+ world.addComponent(entityId, component);
2606
+ return component;
2607
+ }
2608
+ __name(createVRTeleportAreaComponent, "createVRTeleportAreaComponent");
2609
+
2610
+ // core/components/XRInteractable.ts
2611
+ var _XRInteractableComponent = class _XRInteractableComponent extends Component {
2612
+ constructor(options) {
2613
+ super();
2614
+ this.enabled = options?.enabled ?? true;
2615
+ this.grabbable = options?.grabbable ?? true;
2616
+ this.pointable = options?.pointable ?? true;
2617
+ this.grabMode = options?.grabMode ?? "kinematic";
2618
+ this.highlightOnHover = options?.highlightOnHover ?? true;
2619
+ }
2620
+ };
2621
+ __name(_XRInteractableComponent, "XRInteractableComponent");
2622
+ var XRInteractableComponent = _XRInteractableComponent;
2623
+
2624
+ // core/factories/components/XRInteractableFactory.ts
2625
+ function createXRInteractableComponent(world, entityId, ...args) {
2626
+ const component = new XRInteractableComponent(...args);
2627
+ world.addComponent(entityId, component);
2628
+ return component;
2629
+ }
2630
+ __name(createXRInteractableComponent, "createXRInteractableComponent");
2631
+
2567
2632
  // core/factories/registerDefaultComponentFactories.ts
2568
2633
  function registerDefaultComponentFactories(objectManagementSystem) {
2569
2634
  objectManagementSystem.registerComponentFactory("animation", createAnimationComponent);
@@ -2573,6 +2638,9 @@ function registerDefaultComponentFactories(objectManagementSystem) {
2573
2638
  objectManagementSystem.registerComponentFactory("environment", createEnvironmentComponent);
2574
2639
  objectManagementSystem.registerComponentFactory("entityType", createEntityTypeComponent);
2575
2640
  objectManagementSystem.registerComponentFactory("image", createImageComponent);
2641
+ objectManagementSystem.registerComponentFactory("xrRig", createXRRigComponent);
2642
+ objectManagementSystem.registerComponentFactory("vrTeleportArea", createVRTeleportAreaComponent);
2643
+ objectManagementSystem.registerComponentFactory("xrInteractable", createXRInteractableComponent);
2576
2644
  objectManagementSystem.registerComponentFactory(
2577
2645
  "imageTargetAnchor",
2578
2646
  createImageTargetAnchorComponent
@@ -2616,7 +2684,7 @@ var SHARED_MODEL_RESOURCE_FLAG = "spatialEcsSharedModelResource";
2616
2684
  var modelCache = /* @__PURE__ */ new Map();
2617
2685
  function markSharedResources(root) {
2618
2686
  root.traverse((child) => {
2619
- if (!(child instanceof THREE36__namespace.Mesh)) {
2687
+ if (!(child instanceof THREE38__namespace.Mesh)) {
2620
2688
  return;
2621
2689
  }
2622
2690
  if (child.geometry) {
@@ -2695,10 +2763,10 @@ var _ObjectManagementSystem = class _ObjectManagementSystem {
2695
2763
  }
2696
2764
  getOrCreateAudioListener() {
2697
2765
  const existing = this.camera.userData.ecsAudioListener;
2698
- if (existing instanceof THREE36__namespace.AudioListener) {
2766
+ if (existing instanceof THREE38__namespace.AudioListener) {
2699
2767
  return existing;
2700
2768
  }
2701
- const listener = new THREE36__namespace.AudioListener();
2769
+ const listener = new THREE38__namespace.AudioListener();
2702
2770
  this.camera.add(listener);
2703
2771
  this.camera.userData.ecsAudioListener = listener;
2704
2772
  return listener;
@@ -2772,7 +2840,7 @@ var _ObjectManagementSystem = class _ObjectManagementSystem {
2772
2840
  }
2773
2841
  if (dispose && object3d) {
2774
2842
  object3d.traverse((child) => {
2775
- if (child instanceof THREE36__namespace.Mesh) {
2843
+ if (child instanceof THREE38__namespace.Mesh) {
2776
2844
  if (!child.geometry?.userData?.[SHARED_MODEL_RESOURCE_FLAG]) {
2777
2845
  child.geometry?.dispose();
2778
2846
  }
@@ -2909,10 +2977,10 @@ __name(createBaseEntity, "createBaseEntity");
2909
2977
  // core/factories/objects/AudioFactory.ts
2910
2978
  function getOrCreateListener(camera) {
2911
2979
  const existing = camera.userData.ecsAudioListener;
2912
- if (existing instanceof THREE36__namespace.AudioListener) {
2980
+ if (existing instanceof THREE38__namespace.AudioListener) {
2913
2981
  return existing;
2914
2982
  }
2915
- const listener = new THREE36__namespace.AudioListener();
2983
+ const listener = new THREE38__namespace.AudioListener();
2916
2984
  camera.add(listener);
2917
2985
  camera.userData.ecsAudioListener = listener;
2918
2986
  return listener;
@@ -2925,7 +2993,7 @@ function createAudio({
2925
2993
  payload,
2926
2994
  isEditor
2927
2995
  }) {
2928
- const anchor = new THREE36__namespace.Object3D();
2996
+ const anchor = new THREE38__namespace.Object3D();
2929
2997
  const entityId = createBaseEntity(world, anchor, {
2930
2998
  label: payload.name ?? "Audio",
2931
2999
  entityType: "audio",
@@ -2947,7 +3015,7 @@ function createAudio({
2947
3015
  return entityId;
2948
3016
  }
2949
3017
  if (!isEditor) {
2950
- const loader = new THREE36__namespace.AudioLoader();
3018
+ const loader = new THREE38__namespace.AudioLoader();
2951
3019
  loader.load(
2952
3020
  audio.path,
2953
3021
  (buffer) => {
@@ -3022,7 +3090,7 @@ function applyCameraSettings(camera, options) {
3022
3090
  const near = typeof options.near === "number" ? options.near : DEFAULT_NEAR2;
3023
3091
  const far = typeof options.far === "number" ? options.far : DEFAULT_FAR2;
3024
3092
  const projection = options.projection;
3025
- if (camera instanceof THREE36__namespace.PerspectiveCamera) {
3093
+ if (camera instanceof THREE38__namespace.PerspectiveCamera) {
3026
3094
  if (!projection || projection === "perspective") {
3027
3095
  camera.fov = typeof options.fov === "number" ? options.fov : DEFAULT_FOV2;
3028
3096
  }
@@ -3032,7 +3100,7 @@ function applyCameraSettings(camera, options) {
3032
3100
  camera.updateProjectionMatrix();
3033
3101
  return;
3034
3102
  }
3035
- if (camera instanceof THREE36__namespace.OrthographicCamera) {
3103
+ if (camera instanceof THREE38__namespace.OrthographicCamera) {
3036
3104
  camera.left = typeof options.left === "number" ? options.left : -DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
3037
3105
  camera.right = typeof options.right === "number" ? options.right : DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
3038
3106
  camera.top = typeof options.top === "number" ? options.top : DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
@@ -3053,7 +3121,7 @@ function createCameraObject(options) {
3053
3121
  const bottom = options.bottom ?? -DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
3054
3122
  const left = options.left ?? -DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
3055
3123
  const right = options.right ?? DEFAULT_ORTHOGRAPHIC_HALF_HEIGHT;
3056
- const camera = new THREE36__namespace.OrthographicCamera(
3124
+ const camera = new THREE38__namespace.OrthographicCamera(
3057
3125
  left,
3058
3126
  right,
3059
3127
  top,
@@ -3065,7 +3133,7 @@ function createCameraObject(options) {
3065
3133
  camera.updateProjectionMatrix();
3066
3134
  return camera;
3067
3135
  }
3068
- return new THREE36__namespace.PerspectiveCamera(
3136
+ return new THREE38__namespace.PerspectiveCamera(
3069
3137
  options.fov ?? DEFAULT_FOV2,
3070
3138
  readViewportAspect(),
3071
3139
  near,
@@ -3083,7 +3151,7 @@ function createCamera({ world, scene, camera, payload, isEditor }) {
3083
3151
  transformInput: payload.transform
3084
3152
  });
3085
3153
  const objectRef = world.getComponent(entityId, Object3DRef);
3086
- if (objectRef?.object instanceof THREE36__namespace.Camera) {
3154
+ if (objectRef?.object instanceof THREE38__namespace.Camera) {
3087
3155
  objectRef.object.userData.entityId = entityId;
3088
3156
  }
3089
3157
  const componentOptions = {
@@ -3115,9 +3183,9 @@ function createCapsule({
3115
3183
  scene,
3116
3184
  payload
3117
3185
  }) {
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);
3186
+ const geometry = new THREE38__namespace.CapsuleGeometry(0.5, 1, 4, 8);
3187
+ const material = new THREE38__namespace.MeshStandardMaterial({ color: "#ffffff" });
3188
+ const mesh = new THREE38__namespace.Mesh(geometry, material);
3121
3189
  const entityId = createBaseEntity(world, mesh, {
3122
3190
  label: payload.name ?? "Capsule",
3123
3191
  entityType: "capsule",
@@ -3137,9 +3205,9 @@ function createCapsule({
3137
3205
  }
3138
3206
  __name(createCapsule, "createCapsule");
3139
3207
  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);
3208
+ const geometry = new THREE38__namespace.BoxGeometry(1, 1, 1);
3209
+ const material = new THREE38__namespace.MeshStandardMaterial({ color: "#ffffff" });
3210
+ const mesh = new THREE38__namespace.Mesh(geometry, material);
3143
3211
  const entityId = createBaseEntity(world, mesh, {
3144
3212
  label: payload.name ?? "Cube",
3145
3213
  entityType: "cube",
@@ -3164,9 +3232,9 @@ function createCylinder({
3164
3232
  scene,
3165
3233
  payload
3166
3234
  }) {
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);
3235
+ const geometry = new THREE38__namespace.CylinderGeometry(0.5, 0.5, 1, 20);
3236
+ const material = new THREE38__namespace.MeshStandardMaterial({ color: "#ffffff" });
3237
+ const mesh = new THREE38__namespace.Mesh(geometry, material);
3170
3238
  const entityId = createBaseEntity(world, mesh, {
3171
3239
  label: payload.name ?? "Cylinder",
3172
3240
  entityType: "cylinder",
@@ -3186,7 +3254,7 @@ function createCylinder({
3186
3254
  }
3187
3255
  __name(createCylinder, "createCylinder");
3188
3256
  function createEmpty({ world, scene, payload, isEditor }) {
3189
- const object = new THREE36__namespace.Group();
3257
+ const object = new THREE38__namespace.Group();
3190
3258
  const entityId = createBaseEntity(world, object, {
3191
3259
  label: payload.name ?? "Empty",
3192
3260
  entityType: "empty",
@@ -3197,7 +3265,7 @@ function createEmpty({ world, scene, payload, isEditor }) {
3197
3265
  }
3198
3266
  __name(createEmpty, "createEmpty");
3199
3267
  function createImage({ world, scene, payload }) {
3200
- const anchor = new THREE36__namespace.Object3D();
3268
+ const anchor = new THREE38__namespace.Object3D();
3201
3269
  const imagePath = payload.path ?? "";
3202
3270
  const entityId = createBaseEntity(world, anchor, {
3203
3271
  label: payload.name ?? "Image",
@@ -3210,7 +3278,7 @@ function createImage({ world, scene, payload }) {
3210
3278
  if (!imagePath) {
3211
3279
  return entityId;
3212
3280
  }
3213
- const loader = new THREE36__namespace.TextureLoader();
3281
+ const loader = new THREE38__namespace.TextureLoader();
3214
3282
  loader.load(
3215
3283
  imagePath,
3216
3284
  (texture) => {
@@ -3218,13 +3286,13 @@ function createImage({ world, scene, payload }) {
3218
3286
  texture.dispose();
3219
3287
  return;
3220
3288
  }
3221
- const material = new THREE36__namespace.MeshBasicMaterial({
3289
+ const material = new THREE38__namespace.MeshBasicMaterial({
3222
3290
  map: texture,
3223
3291
  transparent: true,
3224
- side: THREE36__namespace.DoubleSide
3292
+ side: THREE38__namespace.DoubleSide
3225
3293
  });
3226
- const geometry = new THREE36__namespace.PlaneGeometry(1, 1);
3227
- const plane = new THREE36__namespace.Mesh(geometry, material);
3294
+ const geometry = new THREE38__namespace.PlaneGeometry(1, 1);
3295
+ const plane = new THREE38__namespace.Mesh(geometry, material);
3228
3296
  plane.userData.entityId = entityId;
3229
3297
  const textureImage = texture.image;
3230
3298
  const width = textureImage?.width ?? 1;
@@ -3270,7 +3338,7 @@ function createImageTarget({
3270
3338
  payload,
3271
3339
  isEditor
3272
3340
  }) {
3273
- const anchor = new THREE36__namespace.Object3D();
3341
+ const anchor = new THREE38__namespace.Object3D();
3274
3342
  const imagePath = payload.path ?? "";
3275
3343
  const entityId = createBaseEntity(world, anchor, {
3276
3344
  label: payload.name ?? "Image Target",
@@ -3287,7 +3355,7 @@ function createImageTarget({
3287
3355
  if (!isEditor || !imagePath) {
3288
3356
  return entityId;
3289
3357
  }
3290
- const loader = new THREE36__namespace.TextureLoader();
3358
+ const loader = new THREE38__namespace.TextureLoader();
3291
3359
  loader.load(
3292
3360
  imagePath,
3293
3361
  (texture) => {
@@ -3295,13 +3363,13 @@ function createImageTarget({
3295
3363
  texture.dispose();
3296
3364
  return;
3297
3365
  }
3298
- const material = new THREE36__namespace.MeshBasicMaterial({
3366
+ const material = new THREE38__namespace.MeshBasicMaterial({
3299
3367
  map: texture,
3300
3368
  transparent: true,
3301
- side: THREE36__namespace.DoubleSide
3369
+ side: THREE38__namespace.DoubleSide
3302
3370
  });
3303
- const geometry = new THREE36__namespace.PlaneGeometry(1, 1);
3304
- const plane = new THREE36__namespace.Mesh(geometry, material);
3371
+ const geometry = new THREE38__namespace.PlaneGeometry(1, 1);
3372
+ const plane = new THREE38__namespace.Mesh(geometry, material);
3305
3373
  plane.userData.entityId = entityId;
3306
3374
  const textureImage = texture.image;
3307
3375
  const width = textureImage?.width ?? 1;
@@ -3352,7 +3420,7 @@ function createInstancedMesh({
3352
3420
  scene,
3353
3421
  payload
3354
3422
  }) {
3355
- const anchor = new THREE36__namespace.Object3D();
3423
+ const anchor = new THREE38__namespace.Object3D();
3356
3424
  const opts = payload.options ?? {};
3357
3425
  const meshKind = isInstancedMeshKind(opts.meshKind) ? opts.meshKind : "cube";
3358
3426
  const meshParameters = opts.meshParameters && typeof opts.meshParameters === "object" ? opts.meshParameters : void 0;
@@ -3423,7 +3491,7 @@ function createAmbientLight({
3423
3491
  scene,
3424
3492
  payload
3425
3493
  }) {
3426
- const light = new THREE36__namespace.AmbientLight("#ffffff", 0.6);
3494
+ const light = new THREE38__namespace.AmbientLight("#ffffff", 0.6);
3427
3495
  const entityId = createBaseEntity(world, light, {
3428
3496
  label: payload.name ?? "Ambient Light",
3429
3497
  entityType: "ambientLight",
@@ -3440,7 +3508,7 @@ function createAreaLight({
3440
3508
  payload,
3441
3509
  isEditor
3442
3510
  }) {
3443
- const light = new THREE36__namespace.RectAreaLight("#ffffff", 5, 4, 4);
3511
+ const light = new THREE38__namespace.RectAreaLight("#ffffff", 5, 4, 4);
3444
3512
  light.lookAt(0, 0, 0);
3445
3513
  const entityId = createBaseEntity(world, light, {
3446
3514
  label: payload.name ?? "Area Light",
@@ -3469,7 +3537,7 @@ function createDirectionalLight({
3469
3537
  payload,
3470
3538
  isEditor
3471
3539
  }) {
3472
- const light = new THREE36__namespace.DirectionalLight("#ffffff", 1.5);
3540
+ const light = new THREE38__namespace.DirectionalLight("#ffffff", 1.5);
3473
3541
  light.castShadow = true;
3474
3542
  const entityId = createBaseEntity(world, light, {
3475
3543
  label: payload.name ?? "Directional Light",
@@ -3480,7 +3548,7 @@ function createDirectionalLight({
3480
3548
  });
3481
3549
  createLightComponent(world, entityId, light);
3482
3550
  if (isEditor) {
3483
- const helper = new THREE36__namespace.DirectionalLightHelper(light, 1.8, "#38bdf8");
3551
+ const helper = new THREE38__namespace.DirectionalLightHelper(light, 1.8, "#38bdf8");
3484
3552
  helper.onBeforeRender = () => {
3485
3553
  helper.update();
3486
3554
  };
@@ -3498,7 +3566,7 @@ function createPointLight({
3498
3566
  payload,
3499
3567
  isEditor
3500
3568
  }) {
3501
- const light = new THREE36__namespace.PointLight("#ffffff", 1, 10);
3569
+ const light = new THREE38__namespace.PointLight("#ffffff", 1, 10);
3502
3570
  const entityId = createBaseEntity(world, light, {
3503
3571
  label: payload.name ?? "Point Light",
3504
3572
  entityType: "pointLight",
@@ -3508,7 +3576,7 @@ function createPointLight({
3508
3576
  });
3509
3577
  createLightComponent(world, entityId, light);
3510
3578
  if (isEditor) {
3511
- const helper = new THREE36__namespace.PointLightHelper(light, 0.35, "#fbbf24");
3579
+ const helper = new THREE38__namespace.PointLightHelper(light, 0.35, "#fbbf24");
3512
3580
  helper.onBeforeRender = () => {
3513
3581
  helper.update();
3514
3582
  };
@@ -3526,7 +3594,7 @@ function createSpotLight({
3526
3594
  payload,
3527
3595
  isEditor
3528
3596
  }) {
3529
- const light = new THREE36__namespace.SpotLight("#ffffff", 1, 20, Math.PI / 6, 0.1, 1);
3597
+ const light = new THREE38__namespace.SpotLight("#ffffff", 1, 20, Math.PI / 6, 0.1, 1);
3530
3598
  const entityId = createBaseEntity(world, light, {
3531
3599
  label: payload.name ?? "Spot Light",
3532
3600
  entityType: "spotLight",
@@ -3536,7 +3604,7 @@ function createSpotLight({
3536
3604
  });
3537
3605
  createLightComponent(world, entityId, light);
3538
3606
  if (isEditor) {
3539
- const helper = new THREE36__namespace.SpotLightHelper(light, "#f59e0b");
3607
+ const helper = new THREE38__namespace.SpotLightHelper(light, "#f59e0b");
3540
3608
  helper.onBeforeRender = () => {
3541
3609
  helper.update();
3542
3610
  };
@@ -3619,7 +3687,10 @@ __export(components_exports, {
3619
3687
  SelectionTransformState: () => SelectionTransformState,
3620
3688
  SpriteComponent: () => SpriteComponent,
3621
3689
  TransformComponent: () => TransformComponent,
3690
+ VRTeleportAreaComponent: () => VRTeleportAreaComponent,
3622
3691
  VideoComponent: () => VideoComponent,
3692
+ XRInteractableComponent: () => XRInteractableComponent,
3693
+ XRRigComponent: () => XRRigComponent,
3623
3694
  defaultMaterialValue: () => defaultMaterialValue,
3624
3695
  normalizePhysicsState: () => normalizePhysicsState,
3625
3696
  setPhysicsLiveRef: () => setPhysicsLiveRef
@@ -3678,7 +3749,7 @@ function createModel({
3678
3749
  payload,
3679
3750
  isEditor
3680
3751
  }) {
3681
- const anchor = new THREE36__namespace.Object3D();
3752
+ const anchor = new THREE38__namespace.Object3D();
3682
3753
  const modelPath = payload.path ?? "";
3683
3754
  const entityId = createBaseEntity(world, anchor, {
3684
3755
  label: payload.name ?? "Model",
@@ -3744,12 +3815,12 @@ function createModel({
3744
3815
  }
3745
3816
  __name(createModel, "createModel");
3746
3817
  function createPlane({ world, scene, payload }) {
3747
- const geometry = new THREE36__namespace.PlaneGeometry(100, 100);
3748
- const material = new THREE36__namespace.MeshStandardMaterial({
3818
+ const geometry = new THREE38__namespace.PlaneGeometry(100, 100);
3819
+ const material = new THREE38__namespace.MeshStandardMaterial({
3749
3820
  color: "#ffffff",
3750
- side: THREE36__namespace.DoubleSide
3821
+ side: THREE38__namespace.DoubleSide
3751
3822
  });
3752
- const mesh = new THREE36__namespace.Mesh(geometry, material);
3823
+ const mesh = new THREE38__namespace.Mesh(geometry, material);
3753
3824
  const entityId = createBaseEntity(
3754
3825
  world,
3755
3826
  mesh,
@@ -3785,7 +3856,7 @@ function createScriptObject({
3785
3856
  scene,
3786
3857
  payload
3787
3858
  }) {
3788
- const object = new THREE36__namespace.Group();
3859
+ const object = new THREE38__namespace.Group();
3789
3860
  const entityId = createBaseEntity(world, object, {
3790
3861
  label: payload.name ?? "Script Object",
3791
3862
  entityType: "scriptObject",
@@ -3802,8 +3873,56 @@ function createScriptObject({
3802
3873
  return entityId;
3803
3874
  }
3804
3875
  __name(createScriptObject, "createScriptObject");
3876
+ function createTeleportArea({
3877
+ world,
3878
+ scene,
3879
+ payload
3880
+ }) {
3881
+ const options = payload.options ?? {};
3882
+ const width = typeof options.width === "number" ? options.width : 10;
3883
+ const depth = typeof options.depth === "number" ? options.depth : 10;
3884
+ const geometry = new THREE38__namespace.PlaneGeometry(width, depth);
3885
+ const material = new THREE38__namespace.MeshBasicMaterial({
3886
+ color: "#4da3ff",
3887
+ transparent: true,
3888
+ opacity: 0.18,
3889
+ side: THREE38__namespace.DoubleSide,
3890
+ depthWrite: false
3891
+ });
3892
+ const object = new THREE38__namespace.Mesh(geometry, material);
3893
+ object.rotation.x = -Math.PI / 2;
3894
+ const entityId = createBaseEntity(world, object, {
3895
+ label: payload.name ?? "Teleport Area",
3896
+ entityType: "teleportArea",
3897
+ transformInput: payload.transform
3898
+ });
3899
+ world.addComponent(
3900
+ entityId,
3901
+ new VRTeleportAreaComponent({ width, depth, ...options })
3902
+ );
3903
+ scene.add(object);
3904
+ return entityId;
3905
+ }
3906
+ __name(createTeleportArea, "createTeleportArea");
3907
+ function createXRRig({
3908
+ world,
3909
+ scene,
3910
+ payload
3911
+ }) {
3912
+ const object = new THREE38__namespace.Group();
3913
+ const entityId = createBaseEntity(world, object, {
3914
+ label: payload.name ?? "XR Rig",
3915
+ entityType: "xrRig",
3916
+ transformInput: payload.transform
3917
+ });
3918
+ const options = payload.options ?? {};
3919
+ world.addComponent(entityId, new XRRigComponent(options));
3920
+ scene.add(object);
3921
+ return entityId;
3922
+ }
3923
+ __name(createXRRig, "createXRRig");
3805
3924
  function createSprite({ world, scene, payload }) {
3806
- const anchor = new THREE36__namespace.Object3D();
3925
+ const anchor = new THREE38__namespace.Object3D();
3807
3926
  const imagePath = payload.path ?? "";
3808
3927
  const entityId = createBaseEntity(world, anchor, {
3809
3928
  label: payload.name ?? "Sprite",
@@ -3815,7 +3934,7 @@ function createSprite({ world, scene, payload }) {
3815
3934
  if (!imagePath) {
3816
3935
  return entityId;
3817
3936
  }
3818
- const loader = new THREE36__namespace.TextureLoader();
3937
+ const loader = new THREE38__namespace.TextureLoader();
3819
3938
  loader.load(
3820
3939
  imagePath,
3821
3940
  (texture) => {
@@ -3823,11 +3942,11 @@ function createSprite({ world, scene, payload }) {
3823
3942
  texture.dispose();
3824
3943
  return;
3825
3944
  }
3826
- const material = new THREE36__namespace.SpriteMaterial({
3945
+ const material = new THREE38__namespace.SpriteMaterial({
3827
3946
  map: texture,
3828
3947
  transparent: true
3829
3948
  });
3830
- const sprite = new THREE36__namespace.Sprite(material);
3949
+ const sprite = new THREE38__namespace.Sprite(material);
3831
3950
  sprite.userData.entityId = entityId;
3832
3951
  const textureImage = texture.image;
3833
3952
  spriteComponent.width = textureImage?.width ?? 1;
@@ -3845,9 +3964,9 @@ function createSprite({ world, scene, payload }) {
3845
3964
  }
3846
3965
  __name(createSprite, "createSprite");
3847
3966
  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);
3967
+ const geometry = new THREE38__namespace.SphereGeometry(0.5, 24, 24);
3968
+ const material = new THREE38__namespace.MeshStandardMaterial({ color: "#ffffff" });
3969
+ const mesh = new THREE38__namespace.Mesh(geometry, material);
3851
3970
  const entityId = createBaseEntity(world, mesh, {
3852
3971
  label: payload.name ?? "Sphere",
3853
3972
  entityType: "sphere",
@@ -3867,10 +3986,10 @@ function createSphere({ world, scene, payload }) {
3867
3986
  __name(createSphere, "createSphere");
3868
3987
  function getOrCreateListener2(camera) {
3869
3988
  const existing = camera.userData.ecsAudioListener;
3870
- if (existing instanceof THREE36__namespace.AudioListener) {
3989
+ if (existing instanceof THREE38__namespace.AudioListener) {
3871
3990
  return existing;
3872
3991
  }
3873
- const listener = new THREE36__namespace.AudioListener();
3992
+ const listener = new THREE38__namespace.AudioListener();
3874
3993
  camera.add(listener);
3875
3994
  camera.userData.ecsAudioListener = listener;
3876
3995
  return listener;
@@ -3920,10 +4039,10 @@ function normalizeOptions(input) {
3920
4039
  }
3921
4040
  __name(normalizeOptions, "normalizeOptions");
3922
4041
  function createChromaMaterial(texture, options) {
3923
- return new THREE36__namespace.ShaderMaterial({
4042
+ return new THREE38__namespace.ShaderMaterial({
3924
4043
  uniforms: {
3925
4044
  tex: { value: texture },
3926
- keyColor: { value: new THREE36__namespace.Color(options.backgroundColor) },
4045
+ keyColor: { value: new THREE38__namespace.Color(options.backgroundColor) },
3927
4046
  similarity: { value: options.similarity },
3928
4047
  smoothness: { value: options.smoothness },
3929
4048
  spill: { value: options.spill }
@@ -3955,22 +4074,22 @@ function createChromaMaterial(texture, options) {
3955
4074
  }
3956
4075
  `,
3957
4076
  transparent: true,
3958
- side: THREE36__namespace.DoubleSide
4077
+ side: THREE38__namespace.DoubleSide
3959
4078
  });
3960
4079
  }
3961
4080
  __name(createChromaMaterial, "createChromaMaterial");
3962
4081
  function createStandardMaterial(texture) {
3963
- return new THREE36__namespace.MeshBasicMaterial({
4082
+ return new THREE38__namespace.MeshBasicMaterial({
3964
4083
  map: texture,
3965
4084
  transparent: true,
3966
- side: THREE36__namespace.DoubleSide
4085
+ side: THREE38__namespace.DoubleSide
3967
4086
  });
3968
4087
  }
3969
4088
  __name(createStandardMaterial, "createStandardMaterial");
3970
4089
  function createVideoMesh(entityId, texture, options) {
3971
- const geometry = new THREE36__namespace.PlaneGeometry(1, 1);
4090
+ const geometry = new THREE38__namespace.PlaneGeometry(1, 1);
3972
4091
  const material = options.isGreenScreen ? createChromaMaterial(texture, options) : createStandardMaterial(texture);
3973
- const mesh = new THREE36__namespace.Mesh(geometry, material);
4092
+ const mesh = new THREE38__namespace.Mesh(geometry, material);
3974
4093
  mesh.userData.entityId = entityId;
3975
4094
  mesh.scale.set(options.width, options.height, 1);
3976
4095
  return { mesh, material };
@@ -4005,7 +4124,7 @@ function createVideo({
4005
4124
  payload,
4006
4125
  isEditor
4007
4126
  }) {
4008
- const anchor = new THREE36__namespace.Object3D();
4127
+ const anchor = new THREE38__namespace.Object3D();
4009
4128
  const path = payload.path ?? "";
4010
4129
  const options = normalizeOptions(payload.options);
4011
4130
  const entityId = createBaseEntity(world, anchor, {
@@ -4020,8 +4139,8 @@ function createVideo({
4020
4139
  return entityId;
4021
4140
  }
4022
4141
  const video = createVideoElement(path, options);
4023
- const texture = new THREE36__namespace.VideoTexture(video);
4024
- texture.colorSpace = THREE36__namespace.SRGBColorSpace;
4142
+ const texture = new THREE38__namespace.VideoTexture(video);
4143
+ texture.colorSpace = THREE38__namespace.SRGBColorSpace;
4025
4144
  texture.needsUpdate = true;
4026
4145
  const { mesh, material } = createVideoMesh(entityId, texture, options);
4027
4146
  anchor.add(mesh);
@@ -4037,7 +4156,7 @@ function createVideo({
4037
4156
  });
4038
4157
  if (!isEditor && options.positional) {
4039
4158
  const listener = getOrCreateListener2(camera);
4040
- const audioNode = new THREE36__namespace.PositionalAudio(listener);
4159
+ const audioNode = new THREE38__namespace.PositionalAudio(listener);
4041
4160
  audioNode.setVolume(options.volume);
4042
4161
  audioNode.setRefDistance(options.refDistance);
4043
4162
  audioNode.setDistanceModel(normalizeDistanceModel2(options.distanceModel));
@@ -4077,6 +4196,8 @@ function registerDefaultFactories(objectManagementSystem) {
4077
4196
  objectManagementSystem.register("spotLight", createSpotLight);
4078
4197
  objectManagementSystem.register("areaLight", createAreaLight);
4079
4198
  objectManagementSystem.register("scriptObject", createScriptObject);
4199
+ objectManagementSystem.register("xrRig", createXRRig);
4200
+ objectManagementSystem.register("teleportArea", createTeleportArea);
4080
4201
  registerDefaultComponentFactories(objectManagementSystem);
4081
4202
  }
4082
4203
  __name(registerDefaultFactories, "registerDefaultFactories");
@@ -4921,7 +5042,9 @@ var HYDRATABLE_ENTITY_KINDS = /* @__PURE__ */ new Set([
4921
5042
  "areaLight",
4922
5043
  "instancedMesh",
4923
5044
  "instanceSlot",
4924
- "scriptObject"
5045
+ "scriptObject",
5046
+ "xrRig",
5047
+ "teleportArea"
4925
5048
  ]);
4926
5049
 
4927
5050
  // core/hydration/hydrateWorld.ts
@@ -6025,7 +6148,7 @@ function transitionToClip(runtime, nextClipId, crossFadeDuration) {
6025
6148
  }
6026
6149
  __name(transitionToClip, "transitionToClip");
6027
6150
  function applyActionState(action, component, paused, shouldLoop) {
6028
- const loopMode = shouldLoop ? THREE36__namespace.LoopRepeat : THREE36__namespace.LoopOnce;
6151
+ const loopMode = shouldLoop ? THREE38__namespace.LoopRepeat : THREE38__namespace.LoopOnce;
6029
6152
  const repetitions = shouldLoop ? Infinity : 1;
6030
6153
  action.setLoop(loopMode, repetitions);
6031
6154
  action.clampWhenFinished = !shouldLoop;
@@ -6198,7 +6321,7 @@ var _AnimationSystem = class _AnimationSystem {
6198
6321
  if (runtime) {
6199
6322
  stopAllActions(runtime);
6200
6323
  }
6201
- const mixer = new THREE36__namespace.AnimationMixer(root);
6324
+ const mixer = new THREE38__namespace.AnimationMixer(root);
6202
6325
  const entries2 = readRuntimeClipEntries(animation);
6203
6326
  const indexedActions = createActions(mixer, entries2);
6204
6327
  runtime = {
@@ -6324,11 +6447,11 @@ function normalizeOrthoBounds(component) {
6324
6447
  }
6325
6448
  __name(normalizeOrthoBounds, "normalizeOrthoBounds");
6326
6449
  function isPerspectiveCamera(camera) {
6327
- return camera instanceof THREE36__namespace.PerspectiveCamera;
6450
+ return camera instanceof THREE38__namespace.PerspectiveCamera;
6328
6451
  }
6329
6452
  __name(isPerspectiveCamera, "isPerspectiveCamera");
6330
6453
  function isOrthographicCamera(camera) {
6331
- return camera instanceof THREE36__namespace.OrthographicCamera;
6454
+ return camera instanceof THREE38__namespace.OrthographicCamera;
6332
6455
  }
6333
6456
  __name(isOrthographicCamera, "isOrthographicCamera");
6334
6457
  function readWindowAspect() {
@@ -6368,6 +6491,7 @@ var _CameraSyncSystem = class _CameraSyncSystem {
6368
6491
  update(world) {
6369
6492
  const entityIds = world.query(CameraComponent, Object3DRef);
6370
6493
  const windowAspect = readWindowAspect();
6494
+ const xrCamera = world.isXrPresenting() ? world.getCamera() : null;
6371
6495
  const alive = new Set(entityIds);
6372
6496
  for (const trackedId of this.signatures.keys()) {
6373
6497
  if (!alive.has(trackedId)) {
@@ -6381,7 +6505,10 @@ var _CameraSyncSystem = class _CameraSyncSystem {
6381
6505
  continue;
6382
6506
  }
6383
6507
  const camera = objectRef.object;
6384
- if (!(camera instanceof THREE36__namespace.Camera)) {
6508
+ if (!(camera instanceof THREE38__namespace.Camera)) {
6509
+ continue;
6510
+ }
6511
+ if (xrCamera !== null && camera === xrCamera) {
6385
6512
  continue;
6386
6513
  }
6387
6514
  const nextSignature = buildSignature(component, camera, windowAspect);
@@ -6445,7 +6572,7 @@ var MIN_DENSITY = 0;
6445
6572
  function createGradientTexture(effect, colors) {
6446
6573
  if (typeof document === "undefined") {
6447
6574
  const pixel = new Uint8Array([30, 30, 30, 255]);
6448
- const fallback = new THREE36__namespace.DataTexture(pixel, 1, 1, THREE36__namespace.RGBAFormat);
6575
+ const fallback = new THREE38__namespace.DataTexture(pixel, 1, 1, THREE38__namespace.RGBAFormat);
6449
6576
  fallback.needsUpdate = true;
6450
6577
  return fallback;
6451
6578
  }
@@ -6454,7 +6581,7 @@ function createGradientTexture(effect, colors) {
6454
6581
  canvas.height = 512;
6455
6582
  const context = canvas.getContext("2d");
6456
6583
  if (!context) {
6457
- const fallback = new THREE36__namespace.CanvasTexture(canvas);
6584
+ const fallback = new THREE38__namespace.CanvasTexture(canvas);
6458
6585
  fallback.needsUpdate = true;
6459
6586
  return fallback;
6460
6587
  }
@@ -6482,15 +6609,15 @@ function createGradientTexture(effect, colors) {
6482
6609
  context.fillRect(0, 0, 512, 512);
6483
6610
  context.globalCompositeOperation = "source-over";
6484
6611
  }
6485
- const texture = new THREE36__namespace.CanvasTexture(canvas);
6486
- texture.colorSpace = THREE36__namespace.SRGBColorSpace;
6612
+ const texture = new THREE38__namespace.CanvasTexture(canvas);
6613
+ texture.colorSpace = THREE38__namespace.SRGBColorSpace;
6487
6614
  texture.needsUpdate = true;
6488
6615
  return texture;
6489
6616
  }
6490
6617
  __name(createGradientTexture, "createGradientTexture");
6491
6618
  var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
6492
6619
  constructor(scene) {
6493
- this.textureLoader = new THREE36__namespace.TextureLoader();
6620
+ this.textureLoader = new THREE38__namespace.TextureLoader();
6494
6621
  this.signature = null;
6495
6622
  this.activeTexture = null;
6496
6623
  this.pendingImageUrl = null;
@@ -6513,7 +6640,7 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
6513
6640
  if (skybox.type === "color") {
6514
6641
  this.disposeActiveTexture();
6515
6642
  this.pendingImageUrl = null;
6516
- this.scene.background = new THREE36__namespace.Color(skybox.color || "#1e1e1e");
6643
+ this.scene.background = new THREE38__namespace.Color(skybox.color || "#1e1e1e");
6517
6644
  return;
6518
6645
  }
6519
6646
  if (skybox.type === "gradient") {
@@ -6547,7 +6674,7 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
6547
6674
  texture.dispose();
6548
6675
  return;
6549
6676
  }
6550
- texture.colorSpace = THREE36__namespace.SRGBColorSpace;
6677
+ texture.colorSpace = THREE38__namespace.SRGBColorSpace;
6551
6678
  this.activeTexture = texture;
6552
6679
  this.scene.background = texture;
6553
6680
  },
@@ -6566,16 +6693,16 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
6566
6693
  this.scene.fog = null;
6567
6694
  return;
6568
6695
  }
6569
- const fogColor = new THREE36__namespace.Color(fog.color || "#1e1e1e");
6696
+ const fogColor = new THREE38__namespace.Color(fog.color || "#1e1e1e");
6570
6697
  if (fog.type === "linear") {
6571
6698
  const near = Number.isFinite(fog.linear.near) ? fog.linear.near : 1;
6572
6699
  const farCandidate = Number.isFinite(fog.linear.far) ? fog.linear.far : near + 10;
6573
6700
  const far = Math.max(near + MIN_FOG_DELTA, farCandidate);
6574
- this.scene.fog = new THREE36__namespace.Fog(fogColor, near, far);
6701
+ this.scene.fog = new THREE38__namespace.Fog(fogColor, near, far);
6575
6702
  return;
6576
6703
  }
6577
6704
  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);
6705
+ this.scene.fog = new THREE38__namespace.FogExp2(fogColor, density);
6579
6706
  }
6580
6707
  update(world) {
6581
6708
  const entityIds = world.query(Environment);
@@ -6657,10 +6784,10 @@ var _PostprocessingSyncSystem = class _PostprocessingSyncSystem {
6657
6784
  );
6658
6785
  }
6659
6786
  if (values.bloom.enabled) {
6660
- const size = this.renderer.getSize(new THREE36__namespace.Vector2());
6787
+ const size = this.renderer.getSize(new THREE38__namespace.Vector2());
6661
6788
  composer.addPass(
6662
6789
  new UnrealBloomPass_js.UnrealBloomPass(
6663
- new THREE36__namespace.Vector2(size.width, size.height),
6790
+ new THREE38__namespace.Vector2(size.width, size.height),
6664
6791
  values.bloom.intensity,
6665
6792
  values.bloom.radius,
6666
6793
  values.bloom.threshold
@@ -6705,7 +6832,7 @@ var _PostprocessingSyncSystem = class _PostprocessingSyncSystem {
6705
6832
  if (values.dotScreen.enabled) {
6706
6833
  composer.addPass(
6707
6834
  new DotScreenPass_js.DotScreenPass(
6708
- new THREE36__namespace.Vector2(0, 0),
6835
+ new THREE38__namespace.Vector2(0, 0),
6709
6836
  values.dotScreen.angle ?? values.dotScreen.dotScreenAngle,
6710
6837
  values.dotScreen.scale ?? values.dotScreen.dotScreenScale
6711
6838
  )
@@ -6779,7 +6906,7 @@ function computeColliderState(colliderValues, object) {
6779
6906
  if (!object) {
6780
6907
  return colliderValues;
6781
6908
  }
6782
- const scale = new THREE36__namespace.Vector3();
6909
+ const scale = new THREE38__namespace.Vector3();
6783
6910
  object.getWorldScale(scale);
6784
6911
  return {
6785
6912
  ...colliderValues,
@@ -6830,8 +6957,8 @@ function createColliderDesc(RAPIER, values, triMeshData) {
6830
6957
  values.offsetPosition.y,
6831
6958
  values.offsetPosition.z
6832
6959
  );
6833
- const offsetQuaternion = new THREE36__namespace.Quaternion().setFromEuler(
6834
- new THREE36__namespace.Euler(
6960
+ const offsetQuaternion = new THREE38__namespace.Quaternion().setFromEuler(
6961
+ new THREE38__namespace.Euler(
6835
6962
  values.offsetRotation.x,
6836
6963
  values.offsetRotation.y,
6837
6964
  values.offsetRotation.z
@@ -6846,17 +6973,17 @@ function collectTriMeshParts(object) {
6846
6973
  return null;
6847
6974
  }
6848
6975
  object.updateWorldMatrix(true, true);
6849
- const worldScale = new THREE36__namespace.Vector3();
6976
+ const worldScale = new THREE38__namespace.Vector3();
6850
6977
  object.getWorldScale(worldScale);
6851
6978
  const scale = {
6852
6979
  x: Math.abs(worldScale.x) || 1,
6853
6980
  y: Math.abs(worldScale.y) || 1,
6854
6981
  z: Math.abs(worldScale.z) || 1
6855
6982
  };
6856
- const worldToObject = new THREE36__namespace.Matrix4().copy(object.matrixWorld).invert();
6983
+ const worldToObject = new THREE38__namespace.Matrix4().copy(object.matrixWorld).invert();
6857
6984
  const parts = [];
6858
6985
  object.traverse((child) => {
6859
- if (!(child instanceof THREE36__namespace.Mesh) || !child.geometry) {
6986
+ if (!(child instanceof THREE38__namespace.Mesh) || !child.geometry) {
6860
6987
  return;
6861
6988
  }
6862
6989
  const geometry = child.geometry;
@@ -6873,7 +7000,7 @@ function collectTriMeshParts(object) {
6873
7000
  if (indexCount < 3) {
6874
7001
  return;
6875
7002
  }
6876
- const relativeMatrix = new THREE36__namespace.Matrix4().multiplyMatrices(
7003
+ const relativeMatrix = new THREE38__namespace.Matrix4().multiplyMatrices(
6877
7004
  worldToObject,
6878
7005
  child.matrixWorld
6879
7006
  );
@@ -6914,7 +7041,7 @@ function createTriMeshData(collected) {
6914
7041
  }
6915
7042
  const vertices = new Float32Array(vertexTotal * 3);
6916
7043
  const indices = new Uint32Array(indexTotal);
6917
- const point = new THREE36__namespace.Vector3();
7044
+ const point = new THREE38__namespace.Vector3();
6918
7045
  let vertexOffset = 0;
6919
7046
  let indexOffset = 0;
6920
7047
  for (const part of parts) {
@@ -6946,8 +7073,8 @@ function createTriMeshData(collected) {
6946
7073
  }
6947
7074
  __name(createTriMeshData, "createTriMeshData");
6948
7075
  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)
7076
+ const quaternion = new THREE38__namespace.Quaternion().setFromEuler(
7077
+ new THREE38__namespace.Euler(transform.rotation.x, transform.rotation.y, transform.rotation.z)
6951
7078
  );
6952
7079
  body.setTranslation(
6953
7080
  {
@@ -6974,8 +7101,8 @@ function syncTransformFromBody(transform, body) {
6974
7101
  transform.position.x = position.x;
6975
7102
  transform.position.y = position.y;
6976
7103
  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)
7104
+ const euler = new THREE38__namespace.Euler().setFromQuaternion(
7105
+ new THREE38__namespace.Quaternion(rotation.x, rotation.y, rotation.z, rotation.w)
6979
7106
  );
6980
7107
  transform.rotation.x = euler.x;
6981
7108
  transform.rotation.y = euler.y;
@@ -7087,8 +7214,8 @@ var _PhysicsSyncSystem = class _PhysicsSyncSystem {
7087
7214
  transform.position.y,
7088
7215
  transform.position.z
7089
7216
  );
7090
- const quaternion = new THREE36__namespace.Quaternion().setFromEuler(
7091
- new THREE36__namespace.Euler(
7217
+ const quaternion = new THREE38__namespace.Quaternion().setFromEuler(
7218
+ new THREE38__namespace.Euler(
7092
7219
  transform.rotation.x,
7093
7220
  transform.rotation.y,
7094
7221
  transform.rotation.z
@@ -7667,7 +7794,7 @@ function applyLightValues(lightComponent) {
7667
7794
  values.castShadow
7668
7795
  );
7669
7796
  }
7670
- if (light instanceof THREE36__namespace.PointLight) {
7797
+ if (light instanceof THREE38__namespace.PointLight) {
7671
7798
  if (typeof values.distance === "number" && Number.isFinite(values.distance)) {
7672
7799
  light.distance = Math.max(MIN_LIGHT_DISTANCE, values.distance);
7673
7800
  }
@@ -7675,7 +7802,7 @@ function applyLightValues(lightComponent) {
7675
7802
  light.decay = Math.max(0, values.decay);
7676
7803
  }
7677
7804
  }
7678
- if (light instanceof THREE36__namespace.SpotLight) {
7805
+ if (light instanceof THREE38__namespace.SpotLight) {
7679
7806
  if (typeof values.distance === "number" && Number.isFinite(values.distance)) {
7680
7807
  light.distance = Math.max(MIN_LIGHT_DISTANCE, values.distance);
7681
7808
  }
@@ -7689,7 +7816,7 @@ function applyLightValues(lightComponent) {
7689
7816
  light.penumbra = Math.max(0, Math.min(1, values.penumbra));
7690
7817
  }
7691
7818
  }
7692
- if (light instanceof THREE36__namespace.RectAreaLight) {
7819
+ if (light instanceof THREE38__namespace.RectAreaLight) {
7693
7820
  if (typeof values.width === "number" && Number.isFinite(values.width)) {
7694
7821
  light.width = Math.max(MIN_AREA_SIZE, values.width);
7695
7822
  }
@@ -7750,15 +7877,15 @@ function resolveMaterialPropertyKey(key) {
7750
7877
  __name(resolveMaterialPropertyKey, "resolveMaterialPropertyKey");
7751
7878
  function createMaterialByType(type) {
7752
7879
  if (type === "basic") {
7753
- return new THREE36__namespace.MeshBasicMaterial();
7880
+ return new THREE38__namespace.MeshBasicMaterial();
7754
7881
  }
7755
7882
  if (type === "phong") {
7756
- return new THREE36__namespace.MeshPhongMaterial();
7883
+ return new THREE38__namespace.MeshPhongMaterial();
7757
7884
  }
7758
7885
  if (type === "physical") {
7759
- return new THREE36__namespace.MeshPhysicalMaterial();
7886
+ return new THREE38__namespace.MeshPhysicalMaterial();
7760
7887
  }
7761
- return new THREE36__namespace.MeshStandardMaterial();
7888
+ return new THREE38__namespace.MeshStandardMaterial();
7762
7889
  }
7763
7890
  __name(createMaterialByType, "createMaterialByType");
7764
7891
  function replaceMaterialAcrossObject(object, previous, next) {
@@ -7817,12 +7944,12 @@ function applyTextureFiltering(material, filtering) {
7817
7944
  const target = material;
7818
7945
  for (const slot of materialTextureSlots) {
7819
7946
  const texture = target[slot];
7820
- if (!texture || !(texture instanceof THREE36__namespace.Texture)) {
7947
+ if (!texture || !(texture instanceof THREE38__namespace.Texture)) {
7821
7948
  continue;
7822
7949
  }
7823
7950
  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;
7951
+ texture.magFilter = sharp ? THREE38__namespace.NearestFilter : THREE38__namespace.LinearFilter;
7952
+ texture.minFilter = useMipmaps ? sharp ? THREE38__namespace.NearestMipmapNearestFilter : THREE38__namespace.LinearMipmapLinearFilter : sharp ? THREE38__namespace.NearestFilter : THREE38__namespace.LinearFilter;
7826
7953
  texture.needsUpdate = true;
7827
7954
  }
7828
7955
  material.needsUpdate = true;
@@ -7832,12 +7959,12 @@ function setTextureMipmaps(material, enabled) {
7832
7959
  const target = material;
7833
7960
  for (const slot of materialTextureSlots) {
7834
7961
  const texture = target[slot];
7835
- if (!texture || !(texture instanceof THREE36__namespace.Texture)) {
7962
+ if (!texture || !(texture instanceof THREE38__namespace.Texture)) {
7836
7963
  continue;
7837
7964
  }
7838
7965
  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;
7966
+ const sharp = texture.magFilter === THREE38__namespace.NearestFilter;
7967
+ texture.minFilter = enabled ? sharp ? THREE38__namespace.NearestMipmapNearestFilter : THREE38__namespace.LinearMipmapLinearFilter : sharp ? THREE38__namespace.NearestFilter : THREE38__namespace.LinearFilter;
7841
7968
  texture.needsUpdate = true;
7842
7969
  }
7843
7970
  material.needsUpdate = true;
@@ -7848,7 +7975,7 @@ function assignMaterialTexture(material, rawKey, url, textureCache) {
7848
7975
  const key = resolveMaterialPropertyKey(rawKey);
7849
7976
  let texture = textureCache.get(url);
7850
7977
  if (!texture) {
7851
- texture = new THREE36__namespace.TextureLoader().load(url);
7978
+ texture = new THREE38__namespace.TextureLoader().load(url);
7852
7979
  textureCache.set(url, texture);
7853
7980
  }
7854
7981
  target[key] = texture;
@@ -7886,7 +8013,7 @@ function applyMaterialState(material, value, textureCache) {
7886
8013
  }
7887
8014
  target.side = value.side;
7888
8015
  target.blending = value.blending;
7889
- target.premultipliedAlpha = value.blending === THREE36__namespace.MultiplyBlending || value.blending === THREE36__namespace.SubtractiveBlending;
8016
+ target.premultipliedAlpha = value.blending === THREE38__namespace.MultiplyBlending || value.blending === THREE38__namespace.SubtractiveBlending;
7890
8017
  target.depthTest = value.depthTest;
7891
8018
  target.depthWrite = value.depthWrite;
7892
8019
  target.wireframe = value.wireframe;
@@ -8047,12 +8174,12 @@ function resolvePrimaryMesh(object) {
8047
8174
  if (!object) {
8048
8175
  return null;
8049
8176
  }
8050
- if (object instanceof THREE36__namespace.Mesh) {
8177
+ if (object instanceof THREE38__namespace.Mesh) {
8051
8178
  return object;
8052
8179
  }
8053
8180
  let found = null;
8054
8181
  object.traverse((child) => {
8055
- if (!found && child instanceof THREE36__namespace.Mesh) {
8182
+ if (!found && child instanceof THREE38__namespace.Mesh) {
8056
8183
  found = child;
8057
8184
  }
8058
8185
  });
@@ -8073,22 +8200,22 @@ function applyGeometry(component) {
8073
8200
  switch (component.kind) {
8074
8201
  case "cube": {
8075
8202
  const params = sanitized;
8076
- nextGeometry = new THREE36__namespace.BoxGeometry(params.width, params.height, params.depth);
8203
+ nextGeometry = new THREE38__namespace.BoxGeometry(params.width, params.height, params.depth);
8077
8204
  break;
8078
8205
  }
8079
8206
  case "plane": {
8080
8207
  const params = sanitized;
8081
- nextGeometry = new THREE36__namespace.PlaneGeometry(params.width, params.height);
8208
+ nextGeometry = new THREE38__namespace.PlaneGeometry(params.width, params.height);
8082
8209
  break;
8083
8210
  }
8084
8211
  case "sphere": {
8085
8212
  const params = sanitized;
8086
- nextGeometry = new THREE36__namespace.SphereGeometry(params.radius, 24, 24);
8213
+ nextGeometry = new THREE38__namespace.SphereGeometry(params.radius, 24, 24);
8087
8214
  break;
8088
8215
  }
8089
8216
  case "cylinder": {
8090
8217
  const params = sanitized;
8091
- nextGeometry = new THREE36__namespace.CylinderGeometry(
8218
+ nextGeometry = new THREE38__namespace.CylinderGeometry(
8092
8219
  params.radius,
8093
8220
  params.radius,
8094
8221
  params.height,
@@ -8098,7 +8225,7 @@ function applyGeometry(component) {
8098
8225
  }
8099
8226
  case "capsule": {
8100
8227
  const params = sanitized;
8101
- nextGeometry = new THREE36__namespace.CapsuleGeometry(params.radius, params.height, 4, 8);
8228
+ nextGeometry = new THREE38__namespace.CapsuleGeometry(params.radius, params.height, 4, 8);
8102
8229
  break;
8103
8230
  }
8104
8231
  default:
@@ -8114,7 +8241,7 @@ function applyShadowFlags(component) {
8114
8241
  return;
8115
8242
  }
8116
8243
  component.object.traverse((child) => {
8117
- if (child instanceof THREE36__namespace.Mesh) {
8244
+ if (child instanceof THREE38__namespace.Mesh) {
8118
8245
  child.castShadow = component.castShadow;
8119
8246
  child.receiveShadow = component.receiveShadow;
8120
8247
  }
@@ -8197,35 +8324,35 @@ function buildGeometry(component) {
8197
8324
  switch (component.meshKind) {
8198
8325
  case "cube": {
8199
8326
  const params = p;
8200
- return new THREE36__namespace.BoxGeometry(params.width, params.height, params.depth);
8327
+ return new THREE38__namespace.BoxGeometry(params.width, params.height, params.depth);
8201
8328
  }
8202
8329
  case "plane": {
8203
8330
  const params = p;
8204
- return new THREE36__namespace.PlaneGeometry(params.width, params.height);
8331
+ return new THREE38__namespace.PlaneGeometry(params.width, params.height);
8205
8332
  }
8206
8333
  case "sphere": {
8207
8334
  const params = p;
8208
- return new THREE36__namespace.SphereGeometry(params.radius, 24, 24);
8335
+ return new THREE38__namespace.SphereGeometry(params.radius, 24, 24);
8209
8336
  }
8210
8337
  case "cylinder": {
8211
8338
  const params = p;
8212
- return new THREE36__namespace.CylinderGeometry(params.radius, params.radius, params.height, 20);
8339
+ return new THREE38__namespace.CylinderGeometry(params.radius, params.radius, params.height, 20);
8213
8340
  }
8214
8341
  case "capsule": {
8215
8342
  const params = p;
8216
- return new THREE36__namespace.CapsuleGeometry(params.radius, params.height, 4, 8);
8343
+ return new THREE38__namespace.CapsuleGeometry(params.radius, params.height, 4, 8);
8217
8344
  }
8218
8345
  default:
8219
- return new THREE36__namespace.BoxGeometry(1, 1, 1);
8346
+ return new THREE38__namespace.BoxGeometry(1, 1, 1);
8220
8347
  }
8221
8348
  }
8222
8349
  __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();
8350
+ var _position = new THREE38__namespace.Vector3();
8351
+ var _quaternion = new THREE38__namespace.Quaternion();
8352
+ var _euler = new THREE38__namespace.Euler();
8353
+ var _scale = new THREE38__namespace.Vector3();
8354
+ var _matrix = new THREE38__namespace.Matrix4();
8355
+ var _modelMatrix = new THREE38__namespace.Matrix4();
8229
8356
  function instanceTransformFromComponent(transform, out) {
8230
8357
  _position.set(transform.position.x, transform.position.y, transform.position.z);
8231
8358
  _euler.set(transform.rotation.x, transform.rotation.y, transform.rotation.z, "XYZ");
@@ -8378,7 +8505,7 @@ var _InstancedMeshSystem = class _InstancedMeshSystem {
8378
8505
  const sourceMaterial = Array.isArray(meshChild.material) ? meshChild.material.map((m) => m.clone()) : meshChild.material.clone();
8379
8506
  meshChild.updateWorldMatrix(true, false);
8380
8507
  const localMatrix = meshChild.matrixWorld.clone();
8381
- const instancedMesh2 = new THREE36__namespace.InstancedMesh(
8508
+ const instancedMesh2 = new THREE38__namespace.InstancedMesh(
8382
8509
  geometry2,
8383
8510
  Array.isArray(sourceMaterial) ? sourceMaterial : sourceMaterial,
8384
8511
  count2
@@ -8403,7 +8530,7 @@ var _InstancedMeshSystem = class _InstancedMeshSystem {
8403
8530
  this.loadingSignatures.delete(targetEntityId);
8404
8531
  return;
8405
8532
  }
8406
- const group = new THREE36__namespace.Group();
8533
+ const group = new THREE38__namespace.Group();
8407
8534
  for (const entry of entries) {
8408
8535
  group.add(entry.instancedMesh);
8409
8536
  }
@@ -8421,8 +8548,8 @@ var _InstancedMeshSystem = class _InstancedMeshSystem {
8421
8548
  }
8422
8549
  const count = instanceCount;
8423
8550
  const geometry = buildGeometry(comp);
8424
- const material = new THREE36__namespace.MeshStandardMaterial({ color: "#ffffff" });
8425
- const instancedMesh = new THREE36__namespace.InstancedMesh(geometry, material, count);
8551
+ const material = new THREE38__namespace.MeshStandardMaterial({ color: "#ffffff" });
8552
+ const instancedMesh = new THREE38__namespace.InstancedMesh(geometry, material, count);
8426
8553
  instancedMesh.castShadow = comp.castShadow;
8427
8554
  instancedMesh.receiveShadow = comp.receiveShadow;
8428
8555
  for (let i = 0; i < count; i++) {
@@ -8605,7 +8732,7 @@ var _Behaviour = class _Behaviour {
8605
8732
  if (!this.threeRef) {
8606
8733
  return null;
8607
8734
  }
8608
- const position = new THREE36__namespace.Vector3();
8735
+ const position = new THREE38__namespace.Vector3();
8609
8736
  this.threeRef.object.getWorldPosition(position);
8610
8737
  return position;
8611
8738
  }
@@ -8617,7 +8744,7 @@ var _Behaviour = class _Behaviour {
8617
8744
  if (!this.threeRef) {
8618
8745
  return null;
8619
8746
  }
8620
- const target = new THREE36__namespace.Vector3();
8747
+ const target = new THREE38__namespace.Vector3();
8621
8748
  this.threeRef.object.getWorldDirection(target);
8622
8749
  return target;
8623
8750
  }
@@ -8679,7 +8806,7 @@ var _Behaviour = class _Behaviour {
8679
8806
  if (!this.threeRef) {
8680
8807
  return;
8681
8808
  }
8682
- const rotation = new THREE36__namespace.Quaternion();
8809
+ const rotation = new THREE38__namespace.Quaternion();
8683
8810
  this.threeRef.object.getWorldQuaternion(rotation);
8684
8811
  rotation.slerp(targetRotation, alpha);
8685
8812
  this.transform.setRotation(rotation);
@@ -8696,7 +8823,7 @@ var _Behaviour = class _Behaviour {
8696
8823
  return;
8697
8824
  }
8698
8825
  const clone3 = this.threeRef.object.clone();
8699
- const rotation = new THREE36__namespace.Quaternion();
8826
+ const rotation = new THREE38__namespace.Quaternion();
8700
8827
  clone3.lookAt(targetPosition);
8701
8828
  clone3.getWorldQuaternion(rotation);
8702
8829
  this.transform.setRotation(rotation);
@@ -8796,6 +8923,49 @@ var _Behaviour = class _Behaviour {
8796
8923
  */
8797
8924
  onTargetLost(target) {
8798
8925
  }
8926
+ // ─── WebXR (VR / MR) hooks ────────────────────────────────────────────────
8927
+ // Dispatched by XRSessionSystem / XRInteractionSystem, following the same
8928
+ // pattern as the AR hooks above: public no-op methods that subclasses opt
8929
+ // into by overriding. They never fire outside an immersive session.
8930
+ /**
8931
+ * Called once when an immersive session starts. Optional XR hook.
8932
+ *
8933
+ * Use it to set up XR-only state. Inspect `capabilities` rather than guessing
8934
+ * by device: feature support differs sharply per headset (for example Vision
8935
+ * Pro grants no passthrough on the web today).
8936
+ *
8937
+ * @param capabilities - What the session actually granted, read from
8938
+ * `XRSession.enabledFeatures`.
8939
+ */
8940
+ onXRSessionStart(capabilities) {
8941
+ }
8942
+ /** Called once when the immersive session ends. Optional XR hook. */
8943
+ onXRSessionEnd() {
8944
+ }
8945
+ /**
8946
+ * Called when a primary action begins — controller trigger, hand pinch, or
8947
+ * Vision Pro gaze-pinch. Optional XR hook.
8948
+ *
8949
+ * @param input - Normalized state for the source that acted.
8950
+ */
8951
+ onSelectStart(input) {
8952
+ }
8953
+ /** Called when the primary action ends. Optional XR hook. */
8954
+ onSelectEnd(input) {
8955
+ }
8956
+ /**
8957
+ * Called when this entity is grabbed. Optional XR hook.
8958
+ *
8959
+ * Only fires for entities carrying an enabled, grabbable
8960
+ * `XRInteractableComponent`.
8961
+ *
8962
+ * @param input - The source doing the grabbing.
8963
+ */
8964
+ onGrab(input) {
8965
+ }
8966
+ /** Called when this entity is released. Optional XR hook. */
8967
+ onRelease(input) {
8968
+ }
8799
8969
  };
8800
8970
  __name(_Behaviour, "Behaviour");
8801
8971
  /**
@@ -8997,8 +9167,8 @@ var _ScriptBehaviourSystem = class _ScriptBehaviourSystem {
8997
9167
  }, "onPointerUp");
8998
9168
  this.moduleLoader = moduleLoader ?? defaultModuleLoader;
8999
9169
  this.selectionCtx = selectionContext ?? null;
9000
- this.raycaster = new THREE36__namespace.Raycaster();
9001
- this.ndcPointer = new THREE36__namespace.Vector2();
9170
+ this.raycaster = new THREE38__namespace.Raycaster();
9171
+ this.ndcPointer = new THREE38__namespace.Vector2();
9002
9172
  if (this.selectionCtx) {
9003
9173
  this.selectionCtx.domElement.addEventListener("pointerdown", this.onPointerDown);
9004
9174
  this.selectionCtx.domElement.addEventListener("pointerup", this.onPointerUp);
@@ -9377,7 +9547,7 @@ function disposeBuiltObject(root) {
9377
9547
  for (const mat of materials) {
9378
9548
  if (mat.userData?.[SHARED_MODEL_RESOURCE_FLAG]) continue;
9379
9549
  for (const value of Object.values(mat)) {
9380
- if (value instanceof THREE36__namespace.Texture) value.dispose();
9550
+ if (value instanceof THREE38__namespace.Texture) value.dispose();
9381
9551
  }
9382
9552
  mat.dispose?.();
9383
9553
  }
@@ -9643,12 +9813,16 @@ var ScriptObjectSystem = _ScriptObjectSystem;
9643
9813
  var _TransformSyncSystem = class _TransformSyncSystem {
9644
9814
  update(world) {
9645
9815
  const entities = world.query(TransformComponent, Object3DRef);
9816
+ const xrCamera = world.isXrPresenting() ? world.getCamera() : null;
9646
9817
  for (const entityId of entities) {
9647
9818
  const transform = world.getComponent(entityId, TransformComponent);
9648
9819
  const object = world.getComponent(entityId, Object3DRef)?.object;
9649
9820
  if (!transform || !object) {
9650
9821
  continue;
9651
9822
  }
9823
+ if (xrCamera !== null && object === xrCamera) {
9824
+ continue;
9825
+ }
9652
9826
  applyTransform(object, transform);
9653
9827
  object.updateMatrixWorld(true);
9654
9828
  }
@@ -9737,7 +9911,7 @@ var _AudioSystem = class _AudioSystem {
9737
9911
  if (!prev || prev.volume !== opts.volume) {
9738
9912
  sound.setVolume(opts.volume);
9739
9913
  }
9740
- if (opts.positional && sound instanceof THREE36__namespace.PositionalAudio) {
9914
+ if (opts.positional && sound instanceof THREE38__namespace.PositionalAudio) {
9741
9915
  if (!prev || prev.refDistance !== opts.refDistance) {
9742
9916
  sound.setRefDistance(opts.refDistance);
9743
9917
  }
@@ -9863,7 +10037,7 @@ var _VideoSystem = class _VideoSystem {
9863
10037
  component.object.scale.set(opts.width, opts.height, 1);
9864
10038
  }
9865
10039
  const material = component.material;
9866
- if (material instanceof THREE36__namespace.ShaderMaterial) {
10040
+ if (material instanceof THREE38__namespace.ShaderMaterial) {
9867
10041
  if (!prev || prev.backgroundColor !== opts.backgroundColor) {
9868
10042
  material.uniforms.keyColor.value.set(opts.backgroundColor);
9869
10043
  }
@@ -9877,7 +10051,7 @@ var _VideoSystem = class _VideoSystem {
9877
10051
  material.uniforms.spill.value = opts.spill;
9878
10052
  }
9879
10053
  }
9880
- if (opts.positional && component.audioNode instanceof THREE36__namespace.PositionalAudio) {
10054
+ if (opts.positional && component.audioNode instanceof THREE38__namespace.PositionalAudio) {
9881
10055
  const posAudio = component.audioNode;
9882
10056
  if (!prev || prev.refDistance !== opts.refDistance) {
9883
10057
  posAudio.setRefDistance(opts.refDistance);
@@ -9899,6 +10073,580 @@ var _VideoSystem = class _VideoSystem {
9899
10073
  };
9900
10074
  __name(_VideoSystem, "VideoSystem");
9901
10075
  var VideoSystem = _VideoSystem;
10076
+ function handednessOf(source) {
10077
+ const value = source.handedness;
10078
+ return value === "left" || value === "right" ? value : "none";
10079
+ }
10080
+ __name(handednessOf, "handednessOf");
10081
+ function kindOf(source) {
10082
+ const mode = source.targetRayMode;
10083
+ if (mode === "transient-pointer") return "transient-pointer";
10084
+ if (mode === "gaze") return "gaze";
10085
+ if (source.hand) return "hand";
10086
+ return "controller";
10087
+ }
10088
+ __name(kindOf, "kindOf");
10089
+ function blankState(source) {
10090
+ return {
10091
+ handedness: handednessOf(source),
10092
+ kind: kindOf(source),
10093
+ connected: true,
10094
+ rayOrigin: new THREE38__namespace.Vector3(),
10095
+ rayDirection: new THREE38__namespace.Vector3(0, 0, -1),
10096
+ gripPosition: null,
10097
+ gripQuaternion: null,
10098
+ select: false,
10099
+ selectStart: false,
10100
+ selectEnd: false,
10101
+ squeeze: false,
10102
+ squeezeStart: false,
10103
+ squeezeEnd: false,
10104
+ axes: [],
10105
+ hasAxes: false,
10106
+ buttons: []
10107
+ };
10108
+ }
10109
+ __name(blankState, "blankState");
10110
+ var _XRInputSystem = class _XRInputSystem {
10111
+ constructor() {
10112
+ this.records = /* @__PURE__ */ new Map();
10113
+ this.session = null;
10114
+ this.onSelectStart = /* @__PURE__ */ __name((event) => this.mark(event, "pendingSelectStart"), "onSelectStart");
10115
+ this.onSelectEnd = /* @__PURE__ */ __name((event) => this.mark(event, "pendingSelectEnd"), "onSelectEnd");
10116
+ this.onSqueezeStart = /* @__PURE__ */ __name((event) => this.mark(event, "pendingSqueezeStart"), "onSqueezeStart");
10117
+ this.onSqueezeEnd = /* @__PURE__ */ __name((event) => this.mark(event, "pendingSqueezeEnd"), "onSqueezeEnd");
10118
+ }
10119
+ mark(event, flag) {
10120
+ const record = this.ensureRecord(event.inputSource);
10121
+ record[flag] = true;
10122
+ }
10123
+ ensureRecord(source) {
10124
+ let record = this.records.get(source);
10125
+ if (!record) {
10126
+ record = {
10127
+ source,
10128
+ state: blankState(source),
10129
+ pendingSelectStart: false,
10130
+ pendingSelectEnd: false,
10131
+ pendingSqueezeStart: false,
10132
+ pendingSqueezeEnd: false,
10133
+ removed: false
10134
+ };
10135
+ this.records.set(source, record);
10136
+ }
10137
+ return record;
10138
+ }
10139
+ /** Bind to a session. Called by {@link XRSessionSystem} on session start. */
10140
+ attachSession(session) {
10141
+ this.detachSession();
10142
+ this.session = session;
10143
+ session.addEventListener("selectstart", this.onSelectStart);
10144
+ session.addEventListener("selectend", this.onSelectEnd);
10145
+ session.addEventListener(
10146
+ "squeezestart",
10147
+ this.onSqueezeStart
10148
+ );
10149
+ session.addEventListener("squeezeend", this.onSqueezeEnd);
10150
+ }
10151
+ /** Unbind and drop all per-source state. */
10152
+ detachSession() {
10153
+ const session = this.session;
10154
+ if (session) {
10155
+ session.removeEventListener(
10156
+ "selectstart",
10157
+ this.onSelectStart
10158
+ );
10159
+ session.removeEventListener(
10160
+ "selectend",
10161
+ this.onSelectEnd
10162
+ );
10163
+ session.removeEventListener(
10164
+ "squeezestart",
10165
+ this.onSqueezeStart
10166
+ );
10167
+ session.removeEventListener(
10168
+ "squeezeend",
10169
+ this.onSqueezeEnd
10170
+ );
10171
+ }
10172
+ this.session = null;
10173
+ this.records.clear();
10174
+ }
10175
+ update(world) {
10176
+ for (const [source, record] of this.records) {
10177
+ if (record.removed) {
10178
+ this.records.delete(source);
10179
+ continue;
10180
+ }
10181
+ record.state.selectStart = false;
10182
+ record.state.selectEnd = false;
10183
+ record.state.squeezeStart = false;
10184
+ record.state.squeezeEnd = false;
10185
+ }
10186
+ const session = this.session;
10187
+ if (!session || !world.isXrPresenting()) return;
10188
+ const renderer = world.getRenderer();
10189
+ const referenceSpace = renderer.xr.getReferenceSpace();
10190
+ const frame = renderer.xr.getFrame?.();
10191
+ const live = /* @__PURE__ */ new Set();
10192
+ for (const source of session.inputSources) {
10193
+ live.add(source);
10194
+ const record = this.ensureRecord(source);
10195
+ const state = record.state;
10196
+ state.connected = true;
10197
+ state.handedness = handednessOf(source);
10198
+ state.kind = kindOf(source);
10199
+ if (frame && referenceSpace && source.targetRaySpace) {
10200
+ const pose = frame.getPose(source.targetRaySpace, referenceSpace);
10201
+ if (pose) {
10202
+ const m = new THREE38__namespace.Matrix4().fromArray(pose.transform.matrix);
10203
+ state.rayOrigin.setFromMatrixPosition(m);
10204
+ state.rayDirection.set(0, 0, -1).applyQuaternion(
10205
+ new THREE38__namespace.Quaternion().setFromRotationMatrix(m)
10206
+ ).normalize();
10207
+ }
10208
+ }
10209
+ if (frame && referenceSpace && source.gripSpace) {
10210
+ const gripPose = frame.getPose(source.gripSpace, referenceSpace);
10211
+ if (gripPose) {
10212
+ const m = new THREE38__namespace.Matrix4().fromArray(gripPose.transform.matrix);
10213
+ state.gripPosition ?? (state.gripPosition = new THREE38__namespace.Vector3());
10214
+ state.gripQuaternion ?? (state.gripQuaternion = new THREE38__namespace.Quaternion());
10215
+ state.gripPosition.setFromMatrixPosition(m);
10216
+ state.gripQuaternion.setFromRotationMatrix(m);
10217
+ }
10218
+ } else {
10219
+ state.gripPosition = null;
10220
+ state.gripQuaternion = null;
10221
+ }
10222
+ const gamepad = source.gamepad;
10223
+ if (gamepad) {
10224
+ state.axes = Array.from(gamepad.axes);
10225
+ state.hasAxes = gamepad.axes.some((axis) => Number.isFinite(axis));
10226
+ state.buttons = gamepad.buttons.map((button) => button.pressed);
10227
+ } else {
10228
+ state.axes = [];
10229
+ state.hasAxes = false;
10230
+ state.buttons = [];
10231
+ }
10232
+ if (record.pendingSelectStart) {
10233
+ state.select = true;
10234
+ state.selectStart = true;
10235
+ record.pendingSelectStart = false;
10236
+ }
10237
+ if (record.pendingSelectEnd) {
10238
+ state.select = false;
10239
+ state.selectEnd = true;
10240
+ record.pendingSelectEnd = false;
10241
+ }
10242
+ if (record.pendingSqueezeStart) {
10243
+ state.squeeze = true;
10244
+ state.squeezeStart = true;
10245
+ record.pendingSqueezeStart = false;
10246
+ }
10247
+ if (record.pendingSqueezeEnd) {
10248
+ state.squeeze = false;
10249
+ state.squeezeEnd = true;
10250
+ record.pendingSqueezeEnd = false;
10251
+ }
10252
+ }
10253
+ for (const [source, record] of this.records) {
10254
+ if (live.has(source)) continue;
10255
+ record.state.connected = false;
10256
+ record.removed = true;
10257
+ }
10258
+ }
10259
+ /** Every input source active this frame. */
10260
+ getInputs() {
10261
+ return Array.from(this.records.values(), (record) => record.state);
10262
+ }
10263
+ /** The first source for a hand, or null. Prefer this for hand-specific logic. */
10264
+ getInput(handedness) {
10265
+ for (const record of this.records.values()) {
10266
+ if (record.state.handedness === handedness) return record.state;
10267
+ }
10268
+ return null;
10269
+ }
10270
+ /** True while ANY source is selecting — the portable "is the user acting" check. */
10271
+ isSelecting() {
10272
+ for (const record of this.records.values()) {
10273
+ if (record.state.select) return true;
10274
+ }
10275
+ return false;
10276
+ }
10277
+ dispose() {
10278
+ this.detachSession();
10279
+ }
10280
+ };
10281
+ __name(_XRInputSystem, "XRInputSystem");
10282
+ var XRInputSystem = _XRInputSystem;
10283
+ var RAYLESS_HOLD_DISTANCE = 0.5;
10284
+ var _XRInteractionSystem = class _XRInteractionSystem {
10285
+ constructor(inputSystem) {
10286
+ this.raycaster = new THREE38__namespace.Raycaster();
10287
+ /** Which entity each source is holding. Keyed by source state identity. */
10288
+ this.grabs = /* @__PURE__ */ new Map();
10289
+ this.hoveredEntityId = null;
10290
+ this.inputSystem = inputSystem;
10291
+ }
10292
+ update(world) {
10293
+ if (!world.isXrPresenting()) {
10294
+ this.releaseAll(world);
10295
+ return;
10296
+ }
10297
+ const inputs = this.inputSystem.getInputs();
10298
+ const interactables = this.collectInteractables(world);
10299
+ this.hoveredEntityId = null;
10300
+ for (const input of inputs) {
10301
+ if (!input.connected) {
10302
+ this.release(world, input);
10303
+ continue;
10304
+ }
10305
+ const held = this.grabs.get(input);
10306
+ if (held) {
10307
+ this.moveHeld(world, input, held);
10308
+ if (input.selectEnd) this.release(world, input);
10309
+ continue;
10310
+ }
10311
+ const hitEntityId = this.raycast(input, interactables);
10312
+ if (hitEntityId === null) continue;
10313
+ if (this.hoveredEntityId === null) {
10314
+ this.hoveredEntityId = hitEntityId;
10315
+ }
10316
+ const interactable = world.getComponent(
10317
+ hitEntityId,
10318
+ XRInteractableComponent
10319
+ );
10320
+ if (input.selectStart && interactable?.grabbable) {
10321
+ this.grab(world, input, hitEntityId);
10322
+ }
10323
+ }
10324
+ }
10325
+ collectInteractables(world) {
10326
+ const out = [];
10327
+ for (const entityId of world.query(XRInteractableComponent, Object3DRef)) {
10328
+ const interactable = world.getComponent(entityId, XRInteractableComponent);
10329
+ if (!interactable?.enabled || !interactable.pointable) continue;
10330
+ if (!world.isEntityVisible(entityId)) continue;
10331
+ const object = world.getComponent(entityId, Object3DRef)?.object;
10332
+ if (object) out.push({ entityId, object });
10333
+ }
10334
+ return out;
10335
+ }
10336
+ /** Entity id of the nearest pointable hit along this source's ray, or null. */
10337
+ raycast(input, interactables) {
10338
+ if (interactables.length === 0) return null;
10339
+ this.raycaster.set(input.rayOrigin, input.rayDirection);
10340
+ let nearestId = null;
10341
+ let nearestDistance = Number.POSITIVE_INFINITY;
10342
+ for (const entry of interactables) {
10343
+ const hit = this.raycaster.intersectObject(entry.object, true)[0];
10344
+ if (!hit) continue;
10345
+ if (hit.distance < nearestDistance) {
10346
+ nearestDistance = hit.distance;
10347
+ nearestId = entry.entityId;
10348
+ }
10349
+ }
10350
+ return nearestId;
10351
+ }
10352
+ grab(world, input, entityId) {
10353
+ const transform = world.getComponent(entityId, TransformComponent);
10354
+ if (!transform) return;
10355
+ const hand = this.handPosition(input);
10356
+ const offset = new THREE38__namespace.Vector3(
10357
+ transform.position.x - hand.x,
10358
+ transform.position.y - hand.y,
10359
+ transform.position.z - hand.z
10360
+ );
10361
+ const physics = world.getComponent(entityId, PhysicsComponent);
10362
+ let restoreBodyType = null;
10363
+ const interactable = world.getComponent(entityId, XRInteractableComponent);
10364
+ if (physics && interactable?.grabMode === "kinematic") {
10365
+ restoreBodyType = physics.values.rigidbody.type;
10366
+ physics.values.rigidbody.type = "kinematicPosition";
10367
+ }
10368
+ this.grabs.set(input, { entityId, offset, restoreBodyType });
10369
+ this.dispatch(world, entityId, (b) => b.onGrab(input));
10370
+ }
10371
+ moveHeld(world, input, held) {
10372
+ const transform = world.getComponent(held.entityId, TransformComponent);
10373
+ if (!transform) return;
10374
+ const hand = this.handPosition(input);
10375
+ transform.position.x = hand.x + held.offset.x;
10376
+ transform.position.y = hand.y + held.offset.y;
10377
+ transform.position.z = hand.z + held.offset.z;
10378
+ }
10379
+ release(world, input) {
10380
+ const held = this.grabs.get(input);
10381
+ if (!held) return;
10382
+ this.grabs.delete(input);
10383
+ if (held.restoreBodyType !== null) {
10384
+ const physics = world.getComponent(held.entityId, PhysicsComponent);
10385
+ if (physics) {
10386
+ physics.values.rigidbody.type = held.restoreBodyType;
10387
+ }
10388
+ }
10389
+ this.dispatch(world, held.entityId, (b) => b.onRelease(input));
10390
+ }
10391
+ releaseAll(world) {
10392
+ for (const input of Array.from(this.grabs.keys())) {
10393
+ this.release(world, input);
10394
+ }
10395
+ }
10396
+ /**
10397
+ * Where the "hand" is for this source. Controllers and tracked hands report a
10398
+ * grip pose; gaze and transient-pointer sources have none, so we hold the
10399
+ * object a fixed distance along the ray instead.
10400
+ */
10401
+ handPosition(input) {
10402
+ if (input.gripPosition) return input.gripPosition;
10403
+ return new THREE38__namespace.Vector3().copy(input.rayDirection).multiplyScalar(RAYLESS_HOLD_DISTANCE).add(input.rayOrigin);
10404
+ }
10405
+ dispatch(world, entityId, visit) {
10406
+ const script = world.getComponent(entityId, ScriptComponent);
10407
+ const instances = script?.scriptInstances;
10408
+ if (!instances) return;
10409
+ for (const instance of instances.values()) {
10410
+ if (!(instance instanceof Behaviour)) continue;
10411
+ try {
10412
+ visit(instance);
10413
+ } catch (error) {
10414
+ console.error("[XRInteractionSystem] Behaviour hook failed:", error);
10415
+ }
10416
+ }
10417
+ }
10418
+ /** Entity currently under a pointer this frame, or null. */
10419
+ getHoveredEntityId() {
10420
+ return this.hoveredEntityId;
10421
+ }
10422
+ /** True when any source is holding something. */
10423
+ isGrabbing() {
10424
+ return this.grabs.size > 0;
10425
+ }
10426
+ };
10427
+ __name(_XRInteractionSystem, "XRInteractionSystem");
10428
+ var XRInteractionSystem = _XRInteractionSystem;
10429
+ var UP = new THREE38__namespace.Vector3(0, 1, 0);
10430
+ var AXIS_DEADZONE = 0.5;
10431
+ var _XRLocomotionSystem = class _XRLocomotionSystem {
10432
+ constructor(inputSystem) {
10433
+ this.raycaster = new THREE38__namespace.Raycaster();
10434
+ /** Per-source latch so one stick push yields exactly one snap turn. */
10435
+ this.turnLatched = /* @__PURE__ */ new WeakSet();
10436
+ /** Where the pointer currently lands, for the consumer to draw a marker. */
10437
+ this.teleportPoint = null;
10438
+ this.inputSystem = inputSystem;
10439
+ }
10440
+ update(world, deltaTime) {
10441
+ this.teleportPoint = null;
10442
+ if (!world.isXrPresenting()) return;
10443
+ const rigEntityId = world.query(XRRigComponent, TransformComponent)[0];
10444
+ if (typeof rigEntityId !== "number") return;
10445
+ const rig = world.getComponent(rigEntityId, XRRigComponent);
10446
+ const rigTransform = world.getComponent(rigEntityId, TransformComponent);
10447
+ if (!rig || !rigTransform) return;
10448
+ const inputs = this.inputSystem.getInputs();
10449
+ if (inputs.length === 0) return;
10450
+ if (rig.snapTurn) {
10451
+ this.applySnapTurn(rig, rigTransform, inputs);
10452
+ }
10453
+ if (rig.locomotion === "teleport") {
10454
+ this.applyTeleport(world, rigTransform, inputs);
10455
+ } else if (rig.locomotion === "smooth") {
10456
+ this.applySmoothMove(world, rig, rigTransform, inputs, deltaTime);
10457
+ }
10458
+ }
10459
+ /**
10460
+ * Snap turning, not smooth turning — rotating the view continuously is the
10461
+ * single biggest cause of VR nausea, so the comfort-safe option is the one
10462
+ * wired to the stick.
10463
+ */
10464
+ applySnapTurn(rig, transform, inputs) {
10465
+ for (const input of inputs) {
10466
+ if (!input.hasAxes || input.axes.length < 3) continue;
10467
+ const x = input.axes[2] ?? 0;
10468
+ const source = input;
10469
+ if (Math.abs(x) < AXIS_DEADZONE) {
10470
+ this.turnLatched.delete(source);
10471
+ continue;
10472
+ }
10473
+ if (this.turnLatched.has(source)) continue;
10474
+ this.turnLatched.add(source);
10475
+ const step = THREE38__namespace.MathUtils.degToRad(rig.snapTurnDegrees);
10476
+ transform.rotation.y -= Math.sign(x) * step;
10477
+ }
10478
+ }
10479
+ applySmoothMove(world, rig, transform, inputs, deltaTime) {
10480
+ for (const input of inputs) {
10481
+ if (!input.hasAxes || input.axes.length < 2) continue;
10482
+ const x = input.axes[0] ?? 0;
10483
+ const y = input.axes[1] ?? 0;
10484
+ if (Math.abs(x) < 0.15 && Math.abs(y) < 0.15) continue;
10485
+ const camera = world.getCamera();
10486
+ const forward = new THREE38__namespace.Vector3();
10487
+ camera.getWorldDirection(forward);
10488
+ forward.y = 0;
10489
+ if (forward.lengthSq() < 1e-6) continue;
10490
+ forward.normalize();
10491
+ const right = new THREE38__namespace.Vector3().crossVectors(forward, UP).normalize();
10492
+ const step = rig.moveSpeed * Math.max(0, deltaTime);
10493
+ transform.position.x += (forward.x * -y + right.x * x) * step;
10494
+ transform.position.z += (forward.z * -y + right.z * x) * step;
10495
+ }
10496
+ }
10497
+ applyTeleport(world, transform, inputs) {
10498
+ const targets = this.collectTeleportTargets(world);
10499
+ if (targets.length === 0) return;
10500
+ for (const input of inputs) {
10501
+ this.raycaster.set(input.rayOrigin, input.rayDirection);
10502
+ const hit = this.raycaster.intersectObjects(targets, true)[0];
10503
+ if (!hit) continue;
10504
+ this.teleportPoint = hit.point.clone();
10505
+ if (input.selectEnd) {
10506
+ transform.position.x = hit.point.x;
10507
+ transform.position.y = hit.point.y;
10508
+ transform.position.z = hit.point.z;
10509
+ }
10510
+ }
10511
+ }
10512
+ collectTeleportTargets(world) {
10513
+ const objects = [];
10514
+ for (const entityId of world.query(VRTeleportAreaComponent, Object3DRef)) {
10515
+ const area = world.getComponent(entityId, VRTeleportAreaComponent);
10516
+ if (!area?.enabled) continue;
10517
+ if (!world.isEntityVisible(entityId)) continue;
10518
+ const object = world.getComponent(entityId, Object3DRef)?.object;
10519
+ if (object) objects.push(object);
10520
+ }
10521
+ return objects;
10522
+ }
10523
+ /**
10524
+ * Where the teleport pointer currently lands this frame, or null.
10525
+ * Consumers use this to render an aim marker.
10526
+ */
10527
+ getTeleportPoint() {
10528
+ return this.teleportPoint;
10529
+ }
10530
+ };
10531
+ __name(_XRLocomotionSystem, "XRLocomotionSystem");
10532
+ var XRLocomotionSystem = _XRLocomotionSystem;
10533
+
10534
+ // core/xr/types.ts
10535
+ var NO_XR_CAPABILITIES = {
10536
+ mode: "inline",
10537
+ handTracking: false,
10538
+ planeDetection: false,
10539
+ meshDetection: false,
10540
+ depthSensing: false,
10541
+ anchors: false,
10542
+ hitTest: false,
10543
+ enabledFeatures: []
10544
+ };
10545
+ function readXrCapabilities(session, mode = "immersive-vr") {
10546
+ if (!session) return NO_XR_CAPABILITIES;
10547
+ const raw = session.enabledFeatures;
10548
+ const features = Array.isArray(raw) ? Array.from(raw) : [];
10549
+ const has = /* @__PURE__ */ __name((name) => features.includes(name), "has");
10550
+ return {
10551
+ mode,
10552
+ handTracking: has("hand-tracking"),
10553
+ planeDetection: has("plane-detection"),
10554
+ meshDetection: has("mesh-detection"),
10555
+ depthSensing: has("depth-sensing"),
10556
+ anchors: has("anchors"),
10557
+ hitTest: has("hit-test"),
10558
+ enabledFeatures: features
10559
+ };
10560
+ }
10561
+ __name(readXrCapabilities, "readXrCapabilities");
10562
+
10563
+ // core/systems/XRSessionSystem.ts
10564
+ var _XRSessionSystem = class _XRSessionSystem {
10565
+ constructor(inputSystem) {
10566
+ this.presenting = false;
10567
+ this.capabilities = NO_XR_CAPABILITIES;
10568
+ this.inputSystem = inputSystem ?? null;
10569
+ }
10570
+ update(world) {
10571
+ const presenting = world.isXrPresenting();
10572
+ if (presenting !== this.presenting) {
10573
+ this.presenting = presenting;
10574
+ if (presenting) {
10575
+ this.handleSessionStart(world);
10576
+ } else {
10577
+ this.handleSessionEnd(world);
10578
+ }
10579
+ }
10580
+ if (presenting) {
10581
+ this.dispatchInputEdges(world);
10582
+ }
10583
+ }
10584
+ handleSessionStart(world) {
10585
+ const session = world.getRenderer().xr.getSession();
10586
+ const mode = session && session.environmentBlendMode !== "opaque" ? "immersive-ar" : "immersive-vr";
10587
+ this.capabilities = readXrCapabilities(session ?? null, mode);
10588
+ if (session && this.inputSystem) {
10589
+ this.inputSystem.attachSession(session);
10590
+ }
10591
+ this.forEachBehaviour(world, (behaviour) => {
10592
+ behaviour.onXRSessionStart(this.capabilities);
10593
+ });
10594
+ }
10595
+ handleSessionEnd(world) {
10596
+ this.capabilities = NO_XR_CAPABILITIES;
10597
+ this.inputSystem?.detachSession();
10598
+ this.forEachBehaviour(world, (behaviour) => {
10599
+ behaviour.onXRSessionEnd();
10600
+ });
10601
+ }
10602
+ /**
10603
+ * Relay this frame's one-frame select edges. Polling the latched state (rather
10604
+ * than dispatching from the DOM event) keeps hook delivery on the ECS tick, so
10605
+ * a Behaviour's `onSelectStart` always observes the same world state its
10606
+ * `onUpdate` would.
10607
+ */
10608
+ dispatchInputEdges(world) {
10609
+ const inputs = this.inputSystem?.getInputs();
10610
+ if (!inputs || inputs.length === 0) return;
10611
+ for (const input of inputs) {
10612
+ if (input.selectStart) {
10613
+ this.forEachBehaviour(world, (b) => b.onSelectStart(input));
10614
+ }
10615
+ if (input.selectEnd) {
10616
+ this.forEachBehaviour(world, (b) => b.onSelectEnd(input));
10617
+ }
10618
+ }
10619
+ }
10620
+ forEachBehaviour(world, visit) {
10621
+ for (const entityId of world.query(ScriptComponent)) {
10622
+ const script = world.getComponent(entityId, ScriptComponent);
10623
+ const instances = script?.scriptInstances;
10624
+ if (!instances) continue;
10625
+ for (const instance of instances.values()) {
10626
+ if (!(instance instanceof Behaviour)) continue;
10627
+ try {
10628
+ visit(instance);
10629
+ } catch (error) {
10630
+ console.error("[XRSessionSystem] Behaviour hook failed:", error);
10631
+ }
10632
+ }
10633
+ }
10634
+ }
10635
+ /** What the active session granted. `NO_XR_CAPABILITIES` when not presenting. */
10636
+ getCapabilities() {
10637
+ return this.capabilities;
10638
+ }
10639
+ /** True while an immersive session is presenting. */
10640
+ isPresenting() {
10641
+ return this.presenting;
10642
+ }
10643
+ /** Convenience passthrough so consumers need only hold this system. */
10644
+ getInputs() {
10645
+ return this.inputSystem?.getInputs() ?? [];
10646
+ }
10647
+ };
10648
+ __name(_XRSessionSystem, "XRSessionSystem");
10649
+ var XRSessionSystem = _XRSessionSystem;
9902
10650
 
9903
10651
  // core/World.ts
9904
10652
  var _World = class _World {
@@ -10304,6 +11052,22 @@ var _World = class _World {
10304
11052
  isEditorMode() {
10305
11053
  return this.isEditor;
10306
11054
  }
11055
+ /**
11056
+ * `true` while an immersive WebXR session is actively presenting.
11057
+ *
11058
+ * While presenting, three's `WebXRManager` OWNS the render camera: each frame
11059
+ * `updateUserCamera()` writes the headset pose into the camera's
11060
+ * position/quaternion/scale and copies the XR projection (including a derived
11061
+ * `fov`) onto it. Systems that also drive the camera must stand down for the
11062
+ * duration, or they ping-pong with the headset every frame and defeat their
11063
+ * own dirty-checks.
11064
+ *
11065
+ * Locomotion therefore moves the camera's PARENT (the XR rig) — three composes
11066
+ * the head pose as `parent.matrixWorld × headPose`.
11067
+ */
11068
+ isXrPresenting() {
11069
+ return this.renderer.xr?.isPresenting === true;
11070
+ }
10307
11071
  /**
10308
11072
  * Pauses world simulation. While paused, `update()` skips all system ticks so
10309
11073
  * physics, animation, scripts, and rendering stop advancing. The last rendered
@@ -10551,8 +11315,8 @@ var _World = class _World {
10551
11315
  * ```
10552
11316
  */
10553
11317
  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(
11318
+ const rayOrigin = new THREE38__namespace.Vector3(origin.x, origin.y, origin.z);
11319
+ const rayDirection = new THREE38__namespace.Vector3(
10556
11320
  direction.x,
10557
11321
  direction.y,
10558
11322
  direction.z
@@ -10561,7 +11325,7 @@ var _World = class _World {
10561
11325
  return [];
10562
11326
  }
10563
11327
  rayDirection.normalize();
10564
- const raycaster = new THREE36__namespace.Raycaster(rayOrigin, rayDirection, near, far);
11328
+ const raycaster = new THREE38__namespace.Raycaster(rayOrigin, rayDirection, near, far);
10565
11329
  const intersections = raycaster.intersectObjects(
10566
11330
  this.scene.children,
10567
11331
  true
@@ -10595,14 +11359,14 @@ var _World = class _World {
10595
11359
  if (!sourceObject) {
10596
11360
  return [];
10597
11361
  }
10598
- const rayOrigin = new THREE36__namespace.Vector3();
10599
- const rayDirection = new THREE36__namespace.Vector3();
11362
+ const rayOrigin = new THREE38__namespace.Vector3();
11363
+ const rayDirection = new THREE38__namespace.Vector3();
10600
11364
  sourceObject.getWorldPosition(rayOrigin);
10601
11365
  sourceObject.getWorldDirection(rayDirection);
10602
11366
  if (rayDirection.lengthSq() === 0) {
10603
11367
  return [];
10604
11368
  }
10605
- const raycaster = new THREE36__namespace.Raycaster(rayOrigin, rayDirection, near, far);
11369
+ const raycaster = new THREE38__namespace.Raycaster(rayOrigin, rayDirection, near, far);
10606
11370
  const intersections = raycaster.intersectObjects(
10607
11371
  this.scene.children,
10608
11372
  true
@@ -11272,6 +12036,7 @@ exports.LightSyncSystem = LightSyncSystem;
11272
12036
  exports.MaterialSyncSystem = MaterialSyncSystem;
11273
12037
  exports.MeshGeometrySystem = MeshGeometrySystem;
11274
12038
  exports.NODE_KEY_SEPARATOR = NODE_KEY_SEPARATOR;
12039
+ exports.NO_XR_CAPABILITIES = NO_XR_CAPABILITIES;
11275
12040
  exports.OVERRIDE_DIFF_EXCLUDED_COMPONENTS = OVERRIDE_DIFF_EXCLUDED_COMPONENTS;
11276
12041
  exports.OVERRIDE_ROOT_EXCLUDED_COMPONENTS = OVERRIDE_ROOT_EXCLUDED_COMPONENTS;
11277
12042
  exports.ObjectManagementSystem = ObjectManagementSystem;
@@ -11289,6 +12054,10 @@ exports.ScriptObjectSystem = ScriptObjectSystem;
11289
12054
  exports.TransformSyncSystem = TransformSyncSystem;
11290
12055
  exports.VideoSystem = VideoSystem;
11291
12056
  exports.World = World;
12057
+ exports.XRInputSystem = XRInputSystem;
12058
+ exports.XRInteractionSystem = XRInteractionSystem;
12059
+ exports.XRLocomotionSystem = XRLocomotionSystem;
12060
+ exports.XRSessionSystem = XRSessionSystem;
11292
12061
  exports.applyPrefabToSnapshotInstances = applyPrefabToSnapshotInstances;
11293
12062
  exports.buildComponentValueMaps = buildComponentValueMaps;
11294
12063
  exports.buildNodeKeyMapsFromSnapshot = buildNodeKeyMapsFromSnapshot;
@@ -11327,7 +12096,10 @@ exports.createSelectableComponent = createSelectableComponent;
11327
12096
  exports.createSelectionTransformStateComponent = createSelectionTransformStateComponent;
11328
12097
  exports.createSpriteComponent = createSpriteComponent;
11329
12098
  exports.createTransformComponent = createTransformComponent;
12099
+ exports.createVRTeleportAreaComponent = createVRTeleportAreaComponent;
11330
12100
  exports.createVideoComponent = createVideoComponent;
12101
+ exports.createXRInteractableComponent = createXRInteractableComponent;
12102
+ exports.createXRRigComponent = createXRRigComponent;
11331
12103
  exports.decanonicalizeComponentValue = decanonicalizeComponentValue;
11332
12104
  exports.despawnPrefab = despawnPrefab;
11333
12105
  exports.encodeOverride = encodeOverride;
@@ -11344,6 +12116,7 @@ exports.mergeComponentValue = mergeComponentValue;
11344
12116
  exports.parseOverride = parseOverride;
11345
12117
  exports.parsePrefabAsset = parsePrefabAsset;
11346
12118
  exports.prefabFileVersionFor = prefabFileVersionFor;
12119
+ exports.readXrCapabilities = readXrCapabilities;
11347
12120
  exports.registerDefaultComponentFactories = registerDefaultComponentFactories;
11348
12121
  exports.registerDefaultFactories = registerDefaultFactories;
11349
12122
  exports.remapSnapshotEntityIds = remapSnapshotEntityIds;