@relu-interactives/spatial-ecs 0.3.20 → 0.4.0
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.
- package/dist/{System-BhnLw0fZ.d.cts → System-QjjSc6LZ.d.cts} +14 -0
- package/dist/{System-BhnLw0fZ.d.ts → System-QjjSc6LZ.d.ts} +14 -0
- package/dist/{XRHandPose-CLl4MiHx.d.cts → XRHandPose-Capx-RTD.d.cts} +47 -2
- package/dist/{XRHandPose-CrzI57JA.d.ts → XRHandPose-Csd3QGkj.d.ts} +47 -2
- package/dist/{chunk-CDSE7476.js → chunk-24ZMSBR7.js} +540 -5
- package/dist/chunk-24ZMSBR7.js.map +1 -0
- package/dist/{chunk-D6KXWNYT.js → chunk-2GTFFLGG.js} +3 -3
- package/dist/{chunk-D6KXWNYT.js.map → chunk-2GTFFLGG.js.map} +1 -1
- package/dist/{chunk-P42OE3RU.js → chunk-OWQPGEBB.js} +4 -4
- package/dist/{chunk-P42OE3RU.js.map → chunk-OWQPGEBB.js.map} +1 -1
- package/dist/{chunk-H6DQ7JRE.js → chunk-ZWONFM2F.js} +33 -3
- package/dist/chunk-ZWONFM2F.js.map +1 -0
- package/dist/components/index.cjs +30 -0
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.cts +3 -3
- package/dist/components/index.d.ts +3 -3
- package/dist/components/index.js +1 -1
- package/dist/docs/guide/accessing-components.md +7 -6
- package/dist/docs/guide/behaviour-data-binding/component-input.md +10 -6
- package/dist/docs/guide/behaviour-data-binding/entity-input.md +13 -5
- package/dist/docs/guide/camera-rigs.md +2 -2
- package/dist/docs/guide/components/animation.md +12 -5
- package/dist/docs/guide/components/audio.md +13 -6
- package/dist/docs/guide/components/camera.md +10 -4
- package/dist/docs/guide/components/entity-type.md +13 -6
- package/dist/docs/guide/components/image-target-anchor.md +6 -2
- package/dist/docs/guide/components/image-target.md +10 -5
- package/dist/docs/guide/components/image.md +10 -4
- package/dist/docs/guide/components/instance-slot.md +7 -3
- package/dist/docs/guide/components/instanced-mesh.md +15 -7
- package/dist/docs/guide/components/light.md +10 -4
- package/dist/docs/guide/components/material.md +14 -8
- package/dist/docs/guide/components/mesh-geometry.md +10 -4
- package/dist/docs/guide/components/mesh.md +10 -4
- package/dist/docs/guide/components/model.md +4 -2
- package/dist/docs/guide/components/name.md +11 -6
- package/dist/docs/guide/components/object3d-ref.md +7 -3
- package/dist/docs/guide/components/parent-id.md +10 -4
- package/dist/docs/guide/components/physics.md +12 -6
- package/dist/docs/guide/components/script.md +10 -4
- package/dist/docs/guide/components/sprite.md +10 -4
- package/dist/docs/guide/components/transform.md +6 -2
- package/dist/docs/guide/components/video.md +10 -4
- package/dist/docs/guide/prefabs.md +2 -0
- package/dist/docs/guide/runtime-entity-management.md +1 -1
- package/dist/docs/guide/spawning/instanced-mesh.md +11 -6
- package/dist/docs/guide/systems/input-system.md +4 -1
- package/dist/docs/guide/systems/script-object-system.md +9 -1
- package/dist/docs/guide/vr-and-hand-poses.md +7 -3
- package/dist/docs/guide/world-api.md +23 -15
- package/dist/factories/index.cjs +6 -0
- package/dist/factories/index.cjs.map +1 -1
- package/dist/factories/index.d.cts +2 -2
- package/dist/factories/index.d.ts +2 -2
- package/dist/factories/index.js +3 -3
- package/dist/{index-6l4hn2Sh.d.ts → index-BAeeVJ6f.d.ts} +94 -2
- package/dist/{index-g777AmFv.d.cts → index-BRATaqTT.d.ts} +78 -4
- package/dist/{index-JRcoel9F.d.ts → index-C1rprGz_.d.cts} +78 -4
- package/dist/{index-C2I5PxCI.d.cts → index-SC9Mgjht.d.cts} +94 -2
- package/dist/index.cjs +586 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +26 -8
- package/dist/index.js.map +1 -1
- package/dist/systems/index.cjs +566 -0
- package/dist/systems/index.cjs.map +1 -1
- package/dist/systems/index.d.cts +2 -2
- package/dist/systems/index.d.ts +2 -2
- package/dist/systems/index.js +3 -3
- package/dist/types.d.cts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/worldSnapshotUtils.d.cts +1 -1
- package/dist/worldSnapshotUtils.d.ts +1 -1
- package/package.json +4 -2
- package/dist/chunk-CDSE7476.js.map +0 -1
- package/dist/chunk-H6DQ7JRE.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { resolveDracoDecoderPath, applyTransform, SHARED_MODEL_RESOURCE_FLAG } from './chunk-
|
|
2
|
-
import { AnimationComponent, ModelComponent, CameraComponent, Object3DRef, Environment, Postprocessing, TransformComponent, PhysicsComponent, setPhysicsLiveRef, LightComponent, MaterialComponent, DEFAULT_MESH_GEOMETRY_PARAMETERS, MeshGeometryComponent, InstancedMeshComponent, ParentId, ScriptComponent, ScriptObjectComponent, XRRigComponent, VRTeleportAreaComponent, XRInteractableComponent, createAttachPoint, XRHandPoseComponent, createHandPoseEntry, XRInteractorComponent, XRInteractorSideComponent, InstanceSlotComponent, Name, ImageComponent, SpriteComponent, VideoComponent, AudioComponent, ImageTarget, Selectable, PrefabNode, PrefabInstance, handPoseDefinitionFor, getHandPosePreset } from './chunk-
|
|
1
|
+
import { resolveDracoDecoderPath, applyTransform, SHARED_MODEL_RESOURCE_FLAG } from './chunk-2GTFFLGG.js';
|
|
2
|
+
import { AnimationComponent, ModelComponent, CameraComponent, Object3DRef, Environment, Postprocessing, TransformComponent, PhysicsComponent, setPhysicsLiveRef, LightComponent, MaterialComponent, DEFAULT_MESH_GEOMETRY_PARAMETERS, MeshGeometryComponent, InstancedMeshComponent, ParentId, ScriptComponent, ScriptObjectComponent, XRRigComponent, VRTeleportAreaComponent, XRInteractableComponent, createAttachPoint, XRHandPoseComponent, createHandPoseEntry, XRInteractorComponent, XRInteractorSideComponent, InstanceSlotComponent, Name, ImageComponent, SpriteComponent, VideoComponent, AudioComponent, ImageTarget, Selectable, PrefabNode, PrefabInstance, XREnvironmentComponent, XRAnchorComponent, handPoseDefinitionFor, getHandPosePreset } from './chunk-ZWONFM2F.js';
|
|
3
3
|
import { __name } from './chunk-OY7ZODZP.js';
|
|
4
4
|
import * as THREE19 from 'three';
|
|
5
5
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
|
|
@@ -633,6 +633,8 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
|
|
|
633
633
|
this.signature = null;
|
|
634
634
|
this.activeTexture = null;
|
|
635
635
|
this.pendingImageUrl = null;
|
|
636
|
+
/** Whether the skybox is currently withheld because passthrough is on. */
|
|
637
|
+
this.passthroughSuppressed = false;
|
|
636
638
|
this.scene = scene;
|
|
637
639
|
}
|
|
638
640
|
disposeActiveTexture() {
|
|
@@ -717,6 +719,18 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
|
|
|
717
719
|
this.scene.fog = new THREE19.FogExp2(fogColor, density);
|
|
718
720
|
}
|
|
719
721
|
update(world) {
|
|
722
|
+
const passthrough = world.isXrPassthrough();
|
|
723
|
+
if (passthrough !== this.passthroughSuppressed) {
|
|
724
|
+
this.passthroughSuppressed = passthrough;
|
|
725
|
+
if (passthrough) {
|
|
726
|
+
this.scene.background = null;
|
|
727
|
+
} else {
|
|
728
|
+
this.signature = null;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
if (passthrough) {
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
720
734
|
const entityIds = world.query(Environment);
|
|
721
735
|
if (entityIds.length === 0) {
|
|
722
736
|
if (this.signature !== null) {
|
|
@@ -2986,6 +3000,24 @@ function restorePostCreateComponents(world, objectManagementSystem, targetEntity
|
|
|
2986
3000
|
if (typeof sourceXrRig.fallbackEyeHeight === "number") {
|
|
2987
3001
|
rig.fallbackEyeHeight = sourceXrRig.fallbackEyeHeight;
|
|
2988
3002
|
}
|
|
3003
|
+
if (typeof sourceXrRig.passthrough === "boolean") {
|
|
3004
|
+
rig.passthrough = sourceXrRig.passthrough;
|
|
3005
|
+
}
|
|
3006
|
+
if (typeof sourceXrRig.depthOcclusion === "boolean") {
|
|
3007
|
+
rig.depthOcclusion = sourceXrRig.depthOcclusion;
|
|
3008
|
+
}
|
|
3009
|
+
if (typeof sourceXrRig.environmentPhysics === "string") {
|
|
3010
|
+
rig.environmentPhysics = sourceXrRig.environmentPhysics;
|
|
3011
|
+
}
|
|
3012
|
+
if (typeof sourceXrRig.environmentDebug === "boolean") {
|
|
3013
|
+
rig.environmentDebug = sourceXrRig.environmentDebug;
|
|
3014
|
+
}
|
|
3015
|
+
if (typeof sourceXrRig.hitTest === "boolean") {
|
|
3016
|
+
rig.hitTest = sourceXrRig.hitTest;
|
|
3017
|
+
}
|
|
3018
|
+
if (typeof sourceXrRig.anchors === "boolean") {
|
|
3019
|
+
rig.anchors = sourceXrRig.anchors;
|
|
3020
|
+
}
|
|
2989
3021
|
}
|
|
2990
3022
|
}
|
|
2991
3023
|
{
|
|
@@ -7794,6 +7826,509 @@ var _XRSessionSystem = class _XRSessionSystem {
|
|
|
7794
7826
|
};
|
|
7795
7827
|
__name(_XRSessionSystem, "XRSessionSystem");
|
|
7796
7828
|
var XRSessionSystem = _XRSessionSystem;
|
|
7829
|
+
var PLANE_COLLIDER_THICKNESS = 0.02;
|
|
7830
|
+
var MIN_PLANE_EXTENT = 0.01;
|
|
7831
|
+
function planeColliderFromPolygon(polygon) {
|
|
7832
|
+
if (!polygon || polygon.length < 3) return null;
|
|
7833
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
7834
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
7835
|
+
let minZ = Number.POSITIVE_INFINITY;
|
|
7836
|
+
let maxZ = Number.NEGATIVE_INFINITY;
|
|
7837
|
+
for (const point of polygon) {
|
|
7838
|
+
if (!Number.isFinite(point.x) || !Number.isFinite(point.z)) return null;
|
|
7839
|
+
minX = Math.min(minX, point.x);
|
|
7840
|
+
maxX = Math.max(maxX, point.x);
|
|
7841
|
+
minZ = Math.min(minZ, point.z);
|
|
7842
|
+
maxZ = Math.max(maxZ, point.z);
|
|
7843
|
+
}
|
|
7844
|
+
const width = maxX - minX;
|
|
7845
|
+
const depth = maxZ - minZ;
|
|
7846
|
+
if (width < MIN_PLANE_EXTENT || depth < MIN_PLANE_EXTENT) return null;
|
|
7847
|
+
return {
|
|
7848
|
+
// Thin on Y: that is the plane's normal in plane space.
|
|
7849
|
+
size: { x: width, y: PLANE_COLLIDER_THICKNESS, z: depth },
|
|
7850
|
+
// The polygon is not necessarily centred on its own origin, so the box has
|
|
7851
|
+
// to be offset to sit over it. Pushed DOWN half its thickness so the
|
|
7852
|
+
// collider's top face lines up with the real surface — otherwise objects
|
|
7853
|
+
// rest a centimetre above the floor, or sink a centimetre into it.
|
|
7854
|
+
offset: {
|
|
7855
|
+
x: (minX + maxX) / 2,
|
|
7856
|
+
y: -PLANE_COLLIDER_THICKNESS / 2,
|
|
7857
|
+
z: (minZ + maxZ) / 2
|
|
7858
|
+
}
|
|
7859
|
+
};
|
|
7860
|
+
}
|
|
7861
|
+
__name(planeColliderFromPolygon, "planeColliderFromPolygon");
|
|
7862
|
+
function writeXrMeshGeometry(vertices, indices, existing) {
|
|
7863
|
+
const geometry = existing ?? new THREE19.BufferGeometry();
|
|
7864
|
+
geometry.setAttribute("position", new THREE19.BufferAttribute(vertices, 3));
|
|
7865
|
+
geometry.setIndex(new THREE19.BufferAttribute(indices, 1));
|
|
7866
|
+
geometry.computeBoundingSphere();
|
|
7867
|
+
geometry.computeVertexNormals();
|
|
7868
|
+
return geometry;
|
|
7869
|
+
}
|
|
7870
|
+
__name(writeXrMeshGeometry, "writeXrMeshGeometry");
|
|
7871
|
+
function decomposeXrPose(matrixElements, target) {
|
|
7872
|
+
const matrix = new THREE19.Matrix4().fromArray(
|
|
7873
|
+
matrixElements
|
|
7874
|
+
);
|
|
7875
|
+
const position = new THREE19.Vector3();
|
|
7876
|
+
const quaternion = new THREE19.Quaternion();
|
|
7877
|
+
const scale = new THREE19.Vector3();
|
|
7878
|
+
matrix.decompose(position, quaternion, scale);
|
|
7879
|
+
const euler = new THREE19.Euler().setFromQuaternion(quaternion, "XYZ");
|
|
7880
|
+
target.position.x = position.x;
|
|
7881
|
+
target.position.y = position.y;
|
|
7882
|
+
target.position.z = position.z;
|
|
7883
|
+
target.rotation.x = euler.x;
|
|
7884
|
+
target.rotation.y = euler.y;
|
|
7885
|
+
target.rotation.z = euler.z;
|
|
7886
|
+
}
|
|
7887
|
+
__name(decomposeXrPose, "decomposeXrPose");
|
|
7888
|
+
|
|
7889
|
+
// core/systems/XREnvironmentSystem.ts
|
|
7890
|
+
var DEBUG_COLOR = 5088255;
|
|
7891
|
+
var _XREnvironmentSystem = class _XREnvironmentSystem {
|
|
7892
|
+
constructor() {
|
|
7893
|
+
/** Keyed by the XRPlane/XRMesh object itself — the runtime's own identity. */
|
|
7894
|
+
this.planes = /* @__PURE__ */ new Map();
|
|
7895
|
+
this.meshes = /* @__PURE__ */ new Map();
|
|
7896
|
+
this.presenting = false;
|
|
7897
|
+
this.debugVisible = false;
|
|
7898
|
+
}
|
|
7899
|
+
update(world) {
|
|
7900
|
+
const presenting = world.isXrPresenting();
|
|
7901
|
+
if (!presenting) {
|
|
7902
|
+
if (this.presenting) {
|
|
7903
|
+
this.presenting = false;
|
|
7904
|
+
this.clearAll(world);
|
|
7905
|
+
}
|
|
7906
|
+
return;
|
|
7907
|
+
}
|
|
7908
|
+
this.presenting = true;
|
|
7909
|
+
const rig = this.findRig(world);
|
|
7910
|
+
const mode = rig?.environmentPhysics ?? "none";
|
|
7911
|
+
if (mode === "none") {
|
|
7912
|
+
if (this.planes.size > 0 || this.meshes.size > 0) this.clearAll(world);
|
|
7913
|
+
return;
|
|
7914
|
+
}
|
|
7915
|
+
const debug = rig?.environmentDebug === true;
|
|
7916
|
+
if (debug !== this.debugVisible) {
|
|
7917
|
+
this.debugVisible = debug;
|
|
7918
|
+
this.applyDebugVisibility(world);
|
|
7919
|
+
}
|
|
7920
|
+
const xr = world.getRenderer().xr;
|
|
7921
|
+
const frame = xr.getFrame?.();
|
|
7922
|
+
const referenceSpace = xr.getReferenceSpace();
|
|
7923
|
+
if (!frame || !referenceSpace) return;
|
|
7924
|
+
const meshesAvailable = Boolean(frame.detectedMeshes);
|
|
7925
|
+
const useMesh = (mode === "mesh" || mode === "auto") && meshesAvailable;
|
|
7926
|
+
const usePlanes = mode === "planes" || mode === "auto" && !useMesh;
|
|
7927
|
+
if (usePlanes) {
|
|
7928
|
+
this.syncPlanes(world, frame, referenceSpace);
|
|
7929
|
+
} else if (this.planes.size > 0) {
|
|
7930
|
+
this.clearMap(world, this.planes);
|
|
7931
|
+
}
|
|
7932
|
+
if (useMesh) {
|
|
7933
|
+
this.syncMeshes(world, frame, referenceSpace);
|
|
7934
|
+
} else if (this.meshes.size > 0) {
|
|
7935
|
+
this.clearMap(world, this.meshes);
|
|
7936
|
+
}
|
|
7937
|
+
}
|
|
7938
|
+
/** How many pieces of real geometry are currently colliding. Script-facing. */
|
|
7939
|
+
getDetectedCount() {
|
|
7940
|
+
return { planes: this.planes.size, meshes: this.meshes.size };
|
|
7941
|
+
}
|
|
7942
|
+
findRig(world) {
|
|
7943
|
+
const ids = world.query(XRRigComponent);
|
|
7944
|
+
if (ids.length === 0) return null;
|
|
7945
|
+
return world.getComponent(ids[0], XRRigComponent) ?? null;
|
|
7946
|
+
}
|
|
7947
|
+
syncPlanes(world, frame, referenceSpace) {
|
|
7948
|
+
const detected = frame.detectedPlanes;
|
|
7949
|
+
if (!detected) return;
|
|
7950
|
+
for (const [plane, entry] of this.planes) {
|
|
7951
|
+
if (!detected.has(plane)) {
|
|
7952
|
+
this.destroyEntry(world, entry);
|
|
7953
|
+
this.planes.delete(plane);
|
|
7954
|
+
}
|
|
7955
|
+
}
|
|
7956
|
+
for (const plane of detected) {
|
|
7957
|
+
const pose = frame.getPose(plane.planeSpace, referenceSpace);
|
|
7958
|
+
if (!pose) continue;
|
|
7959
|
+
let entry = this.planes.get(plane);
|
|
7960
|
+
const changed = plane.lastChangedTime ?? 0;
|
|
7961
|
+
if (!entry) {
|
|
7962
|
+
const created = this.createPlaneEntity(world, plane);
|
|
7963
|
+
if (!created) continue;
|
|
7964
|
+
entry = created;
|
|
7965
|
+
this.planes.set(plane, entry);
|
|
7966
|
+
} else if (changed !== entry.lastChangedTime) {
|
|
7967
|
+
entry.lastChangedTime = changed;
|
|
7968
|
+
this.applyPlaneCollider(world, entry.entityId, plane);
|
|
7969
|
+
}
|
|
7970
|
+
this.applyPose(world, entry.entityId, pose);
|
|
7971
|
+
}
|
|
7972
|
+
}
|
|
7973
|
+
syncMeshes(world, frame, referenceSpace) {
|
|
7974
|
+
const detected = frame.detectedMeshes;
|
|
7975
|
+
if (!detected) return;
|
|
7976
|
+
for (const [mesh, entry] of this.meshes) {
|
|
7977
|
+
if (!detected.has(mesh)) {
|
|
7978
|
+
this.destroyEntry(world, entry);
|
|
7979
|
+
this.meshes.delete(mesh);
|
|
7980
|
+
}
|
|
7981
|
+
}
|
|
7982
|
+
for (const mesh of detected) {
|
|
7983
|
+
const pose = frame.getPose(mesh.meshSpace, referenceSpace);
|
|
7984
|
+
if (!pose) continue;
|
|
7985
|
+
let entry = this.meshes.get(mesh);
|
|
7986
|
+
const changed = mesh.lastChangedTime ?? 0;
|
|
7987
|
+
if (!entry) {
|
|
7988
|
+
const created = this.createMeshEntity(world, mesh);
|
|
7989
|
+
if (!created) continue;
|
|
7990
|
+
entry = created;
|
|
7991
|
+
this.meshes.set(mesh, entry);
|
|
7992
|
+
} else if (changed !== entry.lastChangedTime) {
|
|
7993
|
+
entry.lastChangedTime = changed;
|
|
7994
|
+
writeXrMeshGeometry(mesh.vertices, mesh.indices, entry.geometry);
|
|
7995
|
+
}
|
|
7996
|
+
this.applyPose(world, entry.entityId, pose);
|
|
7997
|
+
}
|
|
7998
|
+
}
|
|
7999
|
+
createPlaneEntity(world, plane) {
|
|
8000
|
+
const collider = planeColliderFromPolygon(plane.polygon);
|
|
8001
|
+
if (!collider) return null;
|
|
8002
|
+
const entityId = world.createEntity();
|
|
8003
|
+
world.addComponents(entityId, [
|
|
8004
|
+
new TransformComponent(),
|
|
8005
|
+
new XREnvironmentComponent(
|
|
8006
|
+
"plane",
|
|
8007
|
+
plane.semanticLabel ?? null,
|
|
8008
|
+
normalizeOrientation(plane.orientation)
|
|
8009
|
+
)
|
|
8010
|
+
]);
|
|
8011
|
+
this.applyPlaneCollider(world, entityId, plane);
|
|
8012
|
+
const entry = {
|
|
8013
|
+
entityId,
|
|
8014
|
+
lastChangedTime: plane.lastChangedTime ?? 0,
|
|
8015
|
+
geometry: null,
|
|
8016
|
+
material: null
|
|
8017
|
+
};
|
|
8018
|
+
if (this.debugVisible) this.attachPlaneDebug(world, entry, collider);
|
|
8019
|
+
return entry;
|
|
8020
|
+
}
|
|
8021
|
+
applyPlaneCollider(world, entityId, plane) {
|
|
8022
|
+
const collider = planeColliderFromPolygon(plane.polygon);
|
|
8023
|
+
if (!collider) return;
|
|
8024
|
+
const existing = world.getComponent(entityId, PhysicsComponent);
|
|
8025
|
+
const values = {
|
|
8026
|
+
// Fixed: the real room does not move because something hit it.
|
|
8027
|
+
rigidbody: { type: "fixed" },
|
|
8028
|
+
collider: {
|
|
8029
|
+
shape: "cuboid",
|
|
8030
|
+
size: collider.size,
|
|
8031
|
+
offsetPosition: collider.offset
|
|
8032
|
+
}
|
|
8033
|
+
};
|
|
8034
|
+
if (existing) {
|
|
8035
|
+
existing.setValues(values);
|
|
8036
|
+
} else {
|
|
8037
|
+
world.addComponent(entityId, new PhysicsComponent(values));
|
|
8038
|
+
}
|
|
8039
|
+
}
|
|
8040
|
+
createMeshEntity(world, mesh) {
|
|
8041
|
+
if (!mesh.vertices?.length || !mesh.indices?.length) return null;
|
|
8042
|
+
const geometry = writeXrMeshGeometry(mesh.vertices, mesh.indices);
|
|
8043
|
+
const material = new THREE19.MeshBasicMaterial({
|
|
8044
|
+
color: DEBUG_COLOR,
|
|
8045
|
+
wireframe: true
|
|
8046
|
+
});
|
|
8047
|
+
const root = new THREE19.Group();
|
|
8048
|
+
const child = new THREE19.Mesh(geometry, material);
|
|
8049
|
+
child.visible = this.debugVisible;
|
|
8050
|
+
root.add(child);
|
|
8051
|
+
const entityId = world.createEntity();
|
|
8052
|
+
world.addComponents(entityId, [
|
|
8053
|
+
new TransformComponent(),
|
|
8054
|
+
new Object3DRef(root),
|
|
8055
|
+
new XREnvironmentComponent("mesh", mesh.semanticLabel ?? null, null),
|
|
8056
|
+
new PhysicsComponent({
|
|
8057
|
+
rigidbody: { type: "fixed" },
|
|
8058
|
+
collider: { shape: "trimesh" }
|
|
8059
|
+
})
|
|
8060
|
+
]);
|
|
8061
|
+
return {
|
|
8062
|
+
entityId,
|
|
8063
|
+
lastChangedTime: mesh.lastChangedTime ?? 0,
|
|
8064
|
+
geometry,
|
|
8065
|
+
material
|
|
8066
|
+
};
|
|
8067
|
+
}
|
|
8068
|
+
/** A thin box so a detected plane can be SEEN, not just collided with. */
|
|
8069
|
+
attachPlaneDebug(world, entry, collider) {
|
|
8070
|
+
const geometry = new THREE19.BoxGeometry(
|
|
8071
|
+
collider.size.x,
|
|
8072
|
+
collider.size.y,
|
|
8073
|
+
collider.size.z
|
|
8074
|
+
);
|
|
8075
|
+
const material = new THREE19.MeshBasicMaterial({
|
|
8076
|
+
color: DEBUG_COLOR,
|
|
8077
|
+
wireframe: true
|
|
8078
|
+
});
|
|
8079
|
+
const root = new THREE19.Group();
|
|
8080
|
+
root.add(new THREE19.Mesh(geometry, material));
|
|
8081
|
+
entry.geometry = geometry;
|
|
8082
|
+
entry.material = material;
|
|
8083
|
+
world.addComponent(entry.entityId, new Object3DRef(root));
|
|
8084
|
+
}
|
|
8085
|
+
applyPose(world, entityId, pose) {
|
|
8086
|
+
const transform = world.getComponent(entityId, TransformComponent);
|
|
8087
|
+
if (!transform) return;
|
|
8088
|
+
decomposeXrPose(pose.transform.matrix, transform);
|
|
8089
|
+
}
|
|
8090
|
+
applyDebugVisibility(world) {
|
|
8091
|
+
for (const map of [this.planes, this.meshes]) {
|
|
8092
|
+
for (const entry of map.values()) {
|
|
8093
|
+
const ref = world.getComponent(entry.entityId, Object3DRef);
|
|
8094
|
+
ref?.object.traverse((child) => {
|
|
8095
|
+
if (child.isMesh) child.visible = this.debugVisible;
|
|
8096
|
+
});
|
|
8097
|
+
}
|
|
8098
|
+
}
|
|
8099
|
+
}
|
|
8100
|
+
destroyEntry(world, entry) {
|
|
8101
|
+
entry.geometry?.dispose();
|
|
8102
|
+
entry.material?.dispose();
|
|
8103
|
+
world.destroyEntity(entry.entityId);
|
|
8104
|
+
}
|
|
8105
|
+
clearMap(world, map) {
|
|
8106
|
+
for (const entry of map.values()) this.destroyEntry(world, entry);
|
|
8107
|
+
map.clear();
|
|
8108
|
+
}
|
|
8109
|
+
clearAll(world) {
|
|
8110
|
+
this.clearMap(world, this.planes);
|
|
8111
|
+
this.clearMap(world, this.meshes);
|
|
8112
|
+
}
|
|
8113
|
+
dispose(world) {
|
|
8114
|
+
this.clearAll(world);
|
|
8115
|
+
}
|
|
8116
|
+
};
|
|
8117
|
+
__name(_XREnvironmentSystem, "XREnvironmentSystem");
|
|
8118
|
+
var XREnvironmentSystem = _XREnvironmentSystem;
|
|
8119
|
+
function normalizeOrientation(value) {
|
|
8120
|
+
return value === "horizontal" || value === "vertical" ? value : null;
|
|
8121
|
+
}
|
|
8122
|
+
__name(normalizeOrientation, "normalizeOrientation");
|
|
8123
|
+
var _XRHitTestSystem = class _XRHitTestSystem {
|
|
8124
|
+
constructor() {
|
|
8125
|
+
this.sources = /* @__PURE__ */ new Map();
|
|
8126
|
+
/** Targets whose async request is in flight, so it is not fired twice. */
|
|
8127
|
+
this.pending = /* @__PURE__ */ new Set();
|
|
8128
|
+
this.results = /* @__PURE__ */ new Map();
|
|
8129
|
+
this.presenting = false;
|
|
8130
|
+
this.enabled = false;
|
|
8131
|
+
}
|
|
8132
|
+
update(world) {
|
|
8133
|
+
const presenting = world.isXrPresenting();
|
|
8134
|
+
if (!presenting) {
|
|
8135
|
+
if (this.presenting) {
|
|
8136
|
+
this.presenting = false;
|
|
8137
|
+
this.teardown();
|
|
8138
|
+
}
|
|
8139
|
+
return;
|
|
8140
|
+
}
|
|
8141
|
+
if (!this.presenting) {
|
|
8142
|
+
this.presenting = true;
|
|
8143
|
+
this.enabled = this.rigWantsHitTest(world);
|
|
8144
|
+
}
|
|
8145
|
+
if (!this.enabled) return;
|
|
8146
|
+
const xr = world.getRenderer().xr;
|
|
8147
|
+
const session = xr.getSession();
|
|
8148
|
+
const referenceSpace = xr.getReferenceSpace();
|
|
8149
|
+
const frame = xr.getFrame?.();
|
|
8150
|
+
if (!session || !referenceSpace || !frame) return;
|
|
8151
|
+
this.ensureViewerSource(session);
|
|
8152
|
+
this.ensureInputSources(session);
|
|
8153
|
+
this.results.clear();
|
|
8154
|
+
for (const [key, source] of this.sources) {
|
|
8155
|
+
const hits = frame.getHitTestResults(source);
|
|
8156
|
+
if (!hits || hits.length === 0) continue;
|
|
8157
|
+
const pose = hits[0].getPose(referenceSpace);
|
|
8158
|
+
if (!pose) continue;
|
|
8159
|
+
const matrix = new THREE19.Matrix4().fromArray(
|
|
8160
|
+
pose.transform.matrix
|
|
8161
|
+
);
|
|
8162
|
+
const position = new THREE19.Vector3();
|
|
8163
|
+
const quaternion = new THREE19.Quaternion();
|
|
8164
|
+
matrix.decompose(position, quaternion, new THREE19.Vector3());
|
|
8165
|
+
this.results.set(key, { position, quaternion });
|
|
8166
|
+
}
|
|
8167
|
+
}
|
|
8168
|
+
/**
|
|
8169
|
+
* Where the given ray meets the real world this frame, or null.
|
|
8170
|
+
*
|
|
8171
|
+
* Null is the normal case, not an error: the source may still be being
|
|
8172
|
+
* requested, the ray may point at nothing recognised, or the runtime may not
|
|
8173
|
+
* have granted `hit-test` at all.
|
|
8174
|
+
*/
|
|
8175
|
+
getHitResult(target = "viewer") {
|
|
8176
|
+
return this.results.get(target) ?? null;
|
|
8177
|
+
}
|
|
8178
|
+
rigWantsHitTest(world) {
|
|
8179
|
+
const ids = world.query(XRRigComponent);
|
|
8180
|
+
if (ids.length === 0) return false;
|
|
8181
|
+
return world.getComponent(ids[0], XRRigComponent)?.hitTest === true;
|
|
8182
|
+
}
|
|
8183
|
+
ensureViewerSource(session) {
|
|
8184
|
+
if (this.sources.has("viewer") || this.pending.has("viewer")) return;
|
|
8185
|
+
if (typeof session.requestHitTestSource !== "function") return;
|
|
8186
|
+
this.pending.add("viewer");
|
|
8187
|
+
void session.requestReferenceSpace("viewer").then((space) => session.requestHitTestSource?.({ space })).then((source) => {
|
|
8188
|
+
if (source && this.presenting) this.sources.set("viewer", source);
|
|
8189
|
+
else source?.cancel?.();
|
|
8190
|
+
}).catch(() => {
|
|
8191
|
+
}).finally(() => this.pending.delete("viewer"));
|
|
8192
|
+
}
|
|
8193
|
+
ensureInputSources(session) {
|
|
8194
|
+
if (typeof session.requestHitTestSource !== "function") return;
|
|
8195
|
+
if (!session.inputSources) return;
|
|
8196
|
+
for (const input of session.inputSources) {
|
|
8197
|
+
const handedness = input.handedness;
|
|
8198
|
+
if (!handedness || handedness === "none") continue;
|
|
8199
|
+
if (!input.targetRaySpace) continue;
|
|
8200
|
+
if (this.sources.has(handedness) || this.pending.has(handedness)) continue;
|
|
8201
|
+
this.pending.add(handedness);
|
|
8202
|
+
const request = session.requestHitTestSource({
|
|
8203
|
+
space: input.targetRaySpace
|
|
8204
|
+
});
|
|
8205
|
+
if (!request) {
|
|
8206
|
+
this.pending.delete(handedness);
|
|
8207
|
+
continue;
|
|
8208
|
+
}
|
|
8209
|
+
void request.then((source) => {
|
|
8210
|
+
if (source && this.presenting) this.sources.set(handedness, source);
|
|
8211
|
+
else source?.cancel?.();
|
|
8212
|
+
}).catch(() => {
|
|
8213
|
+
}).finally(() => this.pending.delete(handedness));
|
|
8214
|
+
}
|
|
8215
|
+
}
|
|
8216
|
+
teardown() {
|
|
8217
|
+
for (const source of this.sources.values()) source.cancel?.();
|
|
8218
|
+
this.sources.clear();
|
|
8219
|
+
this.results.clear();
|
|
8220
|
+
this.pending.clear();
|
|
8221
|
+
this.enabled = false;
|
|
8222
|
+
}
|
|
8223
|
+
dispose() {
|
|
8224
|
+
this.presenting = false;
|
|
8225
|
+
this.teardown();
|
|
8226
|
+
}
|
|
8227
|
+
};
|
|
8228
|
+
__name(_XRHitTestSystem, "XRHitTestSystem");
|
|
8229
|
+
var XRHitTestSystem = _XRHitTestSystem;
|
|
8230
|
+
var _XRAnchorSystem = class _XRAnchorSystem {
|
|
8231
|
+
constructor() {
|
|
8232
|
+
this.anchors = /* @__PURE__ */ new Map();
|
|
8233
|
+
/** In-flight creations, so one entity is not anchored twice. */
|
|
8234
|
+
this.pending = /* @__PURE__ */ new Set();
|
|
8235
|
+
this.presenting = false;
|
|
8236
|
+
}
|
|
8237
|
+
update(world) {
|
|
8238
|
+
const presenting = world.isXrPresenting();
|
|
8239
|
+
if (!presenting) {
|
|
8240
|
+
if (this.presenting) {
|
|
8241
|
+
this.presenting = false;
|
|
8242
|
+
this.releaseAll();
|
|
8243
|
+
}
|
|
8244
|
+
return;
|
|
8245
|
+
}
|
|
8246
|
+
this.presenting = true;
|
|
8247
|
+
const xr = world.getRenderer().xr;
|
|
8248
|
+
const referenceSpace = xr.getReferenceSpace();
|
|
8249
|
+
const frame = xr.getFrame?.();
|
|
8250
|
+
if (!frame || !referenceSpace) return;
|
|
8251
|
+
const entityIds = world.query(XRAnchorComponent, TransformComponent);
|
|
8252
|
+
const live = new Set(entityIds);
|
|
8253
|
+
for (const [entityId, anchor] of this.anchors) {
|
|
8254
|
+
if (!live.has(entityId)) {
|
|
8255
|
+
anchor.delete?.();
|
|
8256
|
+
this.anchors.delete(entityId);
|
|
8257
|
+
}
|
|
8258
|
+
}
|
|
8259
|
+
for (const entityId of entityIds) {
|
|
8260
|
+
const component = world.getComponent(entityId, XRAnchorComponent);
|
|
8261
|
+
const transform = world.getComponent(entityId, TransformComponent);
|
|
8262
|
+
if (!component || !transform) continue;
|
|
8263
|
+
if (!component.enabled) {
|
|
8264
|
+
const existing = this.anchors.get(entityId);
|
|
8265
|
+
if (existing) {
|
|
8266
|
+
existing.delete?.();
|
|
8267
|
+
this.anchors.delete(entityId);
|
|
8268
|
+
}
|
|
8269
|
+
continue;
|
|
8270
|
+
}
|
|
8271
|
+
const anchor = this.anchors.get(entityId);
|
|
8272
|
+
if (!anchor) {
|
|
8273
|
+
this.requestAnchor(entityId, transform, frame, referenceSpace);
|
|
8274
|
+
continue;
|
|
8275
|
+
}
|
|
8276
|
+
const pose = frame.getPose(anchor.anchorSpace, referenceSpace);
|
|
8277
|
+
if (pose) decomposeXrPose(pose.transform.matrix, transform);
|
|
8278
|
+
}
|
|
8279
|
+
}
|
|
8280
|
+
/** Whether this entity's pose is currently being driven by an anchor. */
|
|
8281
|
+
isAnchored(entityId) {
|
|
8282
|
+
return this.anchors.has(entityId);
|
|
8283
|
+
}
|
|
8284
|
+
requestAnchor(entityId, transform, frame, referenceSpace) {
|
|
8285
|
+
if (this.pending.has(entityId)) return;
|
|
8286
|
+
if (typeof frame.createAnchor !== "function") return;
|
|
8287
|
+
const RigidTransform = globalThis.XRRigidTransform;
|
|
8288
|
+
if (!RigidTransform) return;
|
|
8289
|
+
const quaternion = new THREE19.Quaternion().setFromEuler(
|
|
8290
|
+
new THREE19.Euler(
|
|
8291
|
+
transform.rotation.x,
|
|
8292
|
+
transform.rotation.y,
|
|
8293
|
+
transform.rotation.z,
|
|
8294
|
+
"XYZ"
|
|
8295
|
+
)
|
|
8296
|
+
);
|
|
8297
|
+
const pose = new RigidTransform(
|
|
8298
|
+
{
|
|
8299
|
+
x: transform.position.x,
|
|
8300
|
+
y: transform.position.y,
|
|
8301
|
+
z: transform.position.z,
|
|
8302
|
+
w: 1
|
|
8303
|
+
},
|
|
8304
|
+
{
|
|
8305
|
+
x: quaternion.x,
|
|
8306
|
+
y: quaternion.y,
|
|
8307
|
+
z: quaternion.z,
|
|
8308
|
+
w: quaternion.w
|
|
8309
|
+
}
|
|
8310
|
+
);
|
|
8311
|
+
const request = frame.createAnchor(pose, referenceSpace);
|
|
8312
|
+
if (!request) return;
|
|
8313
|
+
this.pending.add(entityId);
|
|
8314
|
+
void request.then((anchor) => {
|
|
8315
|
+
if (anchor && this.presenting) this.anchors.set(entityId, anchor);
|
|
8316
|
+
else anchor?.delete?.();
|
|
8317
|
+
}).catch(() => {
|
|
8318
|
+
}).finally(() => this.pending.delete(entityId));
|
|
8319
|
+
}
|
|
8320
|
+
releaseAll() {
|
|
8321
|
+
for (const anchor of this.anchors.values()) anchor.delete?.();
|
|
8322
|
+
this.anchors.clear();
|
|
8323
|
+
this.pending.clear();
|
|
8324
|
+
}
|
|
8325
|
+
dispose() {
|
|
8326
|
+
this.presenting = false;
|
|
8327
|
+
this.releaseAll();
|
|
8328
|
+
}
|
|
8329
|
+
};
|
|
8330
|
+
__name(_XRAnchorSystem, "XRAnchorSystem");
|
|
8331
|
+
var XRAnchorSystem = _XRAnchorSystem;
|
|
7797
8332
|
function buildGeometry2(area) {
|
|
7798
8333
|
if (area.shape === "circle") {
|
|
7799
8334
|
const radius = Math.max(5e-3, area.width / 2);
|
|
@@ -9028,6 +9563,6 @@ var _XRHoverVisualSystem = class _XRHoverVisualSystem {
|
|
|
9028
9563
|
__name(_XRHoverVisualSystem, "XRHoverVisualSystem");
|
|
9029
9564
|
var XRHoverVisualSystem = _XRHoverVisualSystem;
|
|
9030
9565
|
|
|
9031
|
-
export { ADDED_NODE_MARKER_COMPONENT, ARC_GRAVITY, ARC_MAX_TIME, ARC_SPEED, ARC_STEPS, AnimationSystem, AudioSystem, Behaviour, CURLED_COS, CameraSyncSystem, DEFAULT_DIRECTION_TOLERANCE, DEFAULT_ENTER_CONFIDENCE, DEFAULT_EXIT_CONFIDENCE, DEFAULT_LOST_GRACE_SECONDS, DEFAULT_MIN_HOLD_SECONDS, EnvironmentSyncSystem, FALLBACK_HAND_SCALE, HYDRATABLE_ENTITY_KINDS, HandPoseTracker, InputSystem, InstancedMeshSystem, KeyboardKeys, LightSyncSystem, MATCH_FALLOFF, MAX_PLAUSIBLE_SPEED, MAX_SAMPLE_AGE_SECONDS, MaterialSyncSystem, MeshGeometrySystem, NODE_KEY_SEPARATOR, NO_XR_CAPABILITIES, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectVisibilitySystem, PINCH_FINGERS, PREFAB_FILE_VERSION, PREFAB_FILE_VERSION_NESTED, PhysicsSyncSystem, PostprocessingSyncSystem, RenderSystem, SCRIPT_OBJECT_ROOT_FLAG, STRAIGHT_COS, ScriptBehaviourSystem, ScriptObject, ScriptObjectSystem, TeleportAimGate, ThrowVelocityTracker, TransformSyncSystem, VELOCITY_SAMPLES, VRTeleportAreaSystem, VideoSystem, XRControllerVisualSystem, XRHandPoseSystem, XRHoverVisualSystem, XRInputSystem, XRInteractionSystem, XRLocomotionSystem, XRSessionSystem, XRTeleportVisualSystem, XR_FINGERS, XR_HOVER_SHELL_FLAG, angularVelocityFrom, applyHandMaterial, arcGroundCrossing, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearPrefabCache, collectDiffPaths, collectEntitySubtree, collectSnapshotSubtreeIds, computeFingerCurl, computeHandShape, computeInstanceOverrides, computePalmPose, computePalmWidth, computePinch, computeSpread, createHandMaterial, decanonicalizeComponentValue, despawnPrefab, encodeOverride, estimateHandScale, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadPrefab, matchHandPose, mergeComponentValue, parseOverride, parsePrefabAsset, prefabFileVersionFor, readXrCapabilities, restoreComponentState, restorePostCreateComponents, sampleTeleportArc, setPrefabAssetUrlResolver, spawnPrefab };
|
|
9032
|
-
//# sourceMappingURL=chunk-
|
|
9033
|
-
//# sourceMappingURL=chunk-
|
|
9566
|
+
export { ADDED_NODE_MARKER_COMPONENT, ARC_GRAVITY, ARC_MAX_TIME, ARC_SPEED, ARC_STEPS, AnimationSystem, AudioSystem, Behaviour, CURLED_COS, CameraSyncSystem, DEFAULT_DIRECTION_TOLERANCE, DEFAULT_ENTER_CONFIDENCE, DEFAULT_EXIT_CONFIDENCE, DEFAULT_LOST_GRACE_SECONDS, DEFAULT_MIN_HOLD_SECONDS, EnvironmentSyncSystem, FALLBACK_HAND_SCALE, HYDRATABLE_ENTITY_KINDS, HandPoseTracker, InputSystem, InstancedMeshSystem, KeyboardKeys, LightSyncSystem, MATCH_FALLOFF, MAX_PLAUSIBLE_SPEED, MAX_SAMPLE_AGE_SECONDS, MaterialSyncSystem, MeshGeometrySystem, NODE_KEY_SEPARATOR, NO_XR_CAPABILITIES, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectVisibilitySystem, PINCH_FINGERS, PREFAB_FILE_VERSION, PREFAB_FILE_VERSION_NESTED, PhysicsSyncSystem, PostprocessingSyncSystem, RenderSystem, SCRIPT_OBJECT_ROOT_FLAG, STRAIGHT_COS, ScriptBehaviourSystem, ScriptObject, ScriptObjectSystem, TeleportAimGate, ThrowVelocityTracker, TransformSyncSystem, VELOCITY_SAMPLES, VRTeleportAreaSystem, VideoSystem, XRAnchorSystem, XRControllerVisualSystem, XREnvironmentSystem, XRHandPoseSystem, XRHitTestSystem, XRHoverVisualSystem, XRInputSystem, XRInteractionSystem, XRLocomotionSystem, XRSessionSystem, XRTeleportVisualSystem, XR_FINGERS, XR_HOVER_SHELL_FLAG, angularVelocityFrom, applyHandMaterial, arcGroundCrossing, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearPrefabCache, collectDiffPaths, collectEntitySubtree, collectSnapshotSubtreeIds, computeFingerCurl, computeHandShape, computeInstanceOverrides, computePalmPose, computePalmWidth, computePinch, computeSpread, createHandMaterial, decanonicalizeComponentValue, despawnPrefab, encodeOverride, estimateHandScale, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadPrefab, matchHandPose, mergeComponentValue, parseOverride, parsePrefabAsset, prefabFileVersionFor, readXrCapabilities, restoreComponentState, restorePostCreateComponents, sampleTeleportArc, setPrefabAssetUrlResolver, spawnPrefab };
|
|
9567
|
+
//# sourceMappingURL=chunk-24ZMSBR7.js.map
|
|
9568
|
+
//# sourceMappingURL=chunk-24ZMSBR7.js.map
|