@relu-interactives/spatial-ecs 0.3.10 → 0.3.12
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/{XRHandPose-hAtj9wm-.d.cts → XRHandPose-DawOR0uR.d.cts} +56 -14
- package/dist/{XRHandPose-CjacJ_16.d.ts → XRHandPose-DhAd9Qi6.d.ts} +56 -14
- package/dist/{chunk-NJOO7NO6.js → chunk-7ZIN6TGT.js} +3 -3
- package/dist/{chunk-NJOO7NO6.js.map → chunk-7ZIN6TGT.js.map} +1 -1
- package/dist/{chunk-5UVBEAGW.js → chunk-ID7U4FER.js} +4 -4
- package/dist/{chunk-5UVBEAGW.js.map → chunk-ID7U4FER.js.map} +1 -1
- package/dist/{chunk-O2HSIZFC.js → chunk-LCJ6IH2O.js} +324 -47
- package/dist/chunk-LCJ6IH2O.js.map +1 -0
- package/dist/{chunk-ELSZ5U3F.js → chunk-OMDYLFTN.js} +7 -4
- package/dist/chunk-OMDYLFTN.js.map +1 -0
- package/dist/components/index.cjs +5 -2
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.cts +2 -2
- package/dist/components/index.d.ts +2 -2
- package/dist/components/index.js +1 -1
- package/dist/docs/guide/vr-and-hand-poses.md +7 -3
- package/dist/factories/index.cjs +5 -2
- package/dist/factories/index.cjs.map +1 -1
- package/dist/factories/index.d.cts +1 -1
- package/dist/factories/index.d.ts +1 -1
- package/dist/factories/index.js +3 -3
- package/dist/{index-B7JDsx4a.d.ts → index-B49322Q3.d.ts} +2 -3
- package/dist/{index-DU-CF-3m.d.cts → index-DJ9bn9SF.d.cts} +70 -1
- package/dist/{index-B-KhN8Ox.d.ts → index-M0I5B3JA.d.ts} +70 -1
- package/dist/{index-B9JqYr3Q.d.cts → index-Xm3im4Pt.d.cts} +2 -3
- package/dist/index.cjs +326 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +8 -8
- package/dist/systems/index.cjs +326 -44
- package/dist/systems/index.cjs.map +1 -1
- package/dist/systems/index.d.cts +1 -1
- package/dist/systems/index.d.ts +1 -1
- package/dist/systems/index.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-ELSZ5U3F.js.map +0 -1
- package/dist/chunk-O2HSIZFC.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-7ZIN6TGT.js';
|
|
2
|
+
import { AnimationComponent, ModelComponent, CameraComponent, Object3DRef, Environment, Postprocessing, TransformComponent, PhysicsComponent, setPhysicsLiveRef, LightComponent, MaterialComponent, DEFAULT_MESH_GEOMETRY_PARAMETERS, MeshGeometryComponent, InstancedMeshComponent, ParentId, ScriptComponent, ScriptObjectComponent, XRRigComponent, VRTeleportAreaComponent, XRInteractableComponent, createAttachPoint, XRHandPoseComponent, createHandPoseEntry, XRInteractorComponent, XRInteractorSideComponent, InstanceSlotComponent, Name, ImageComponent, SpriteComponent, VideoComponent, AudioComponent, ImageTarget, Selectable, PrefabNode, PrefabInstance, handPoseDefinitionFor, getHandPosePreset } from './chunk-OMDYLFTN.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';
|
|
@@ -901,6 +901,20 @@ var _PostprocessingSyncSystem = class _PostprocessingSyncSystem {
|
|
|
901
901
|
__name(_PostprocessingSyncSystem, "PostprocessingSyncSystem");
|
|
902
902
|
var PostprocessingSyncSystem = _PostprocessingSyncSystem;
|
|
903
903
|
var MIN_SIZE = 1e-4;
|
|
904
|
+
function toBodyType(RAPIER, bodyType) {
|
|
905
|
+
switch (bodyType) {
|
|
906
|
+
case "fixed":
|
|
907
|
+
return RAPIER.RigidBodyType.Fixed;
|
|
908
|
+
case "kinematicPosition":
|
|
909
|
+
return RAPIER.RigidBodyType.KinematicPositionBased;
|
|
910
|
+
case "kinematicVelocity":
|
|
911
|
+
return RAPIER.RigidBodyType.KinematicVelocityBased;
|
|
912
|
+
case "dynamic":
|
|
913
|
+
default:
|
|
914
|
+
return RAPIER.RigidBodyType.Dynamic;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
__name(toBodyType, "toBodyType");
|
|
904
918
|
function createRigidBodyDesc(RAPIER, bodyType) {
|
|
905
919
|
if (bodyType === "fixed") {
|
|
906
920
|
return RAPIER.RigidBodyDesc.fixed();
|
|
@@ -1199,7 +1213,8 @@ var _PhysicsSyncSystem = class _PhysicsSyncSystem {
|
|
|
1199
1213
|
setPhysicsLiveRef(physics, "collider", null);
|
|
1200
1214
|
continue;
|
|
1201
1215
|
}
|
|
1202
|
-
const
|
|
1216
|
+
const { type: _desiredBodyType, ...rigidBodyRebuildValues } = physics.values.rigidbody;
|
|
1217
|
+
const rigidBodySignature = JSON.stringify(rigidBodyRebuildValues);
|
|
1203
1218
|
const previousRigidBodySignature = this.rigidBodySignatures.get(entityId);
|
|
1204
1219
|
const hasRigidBody = this.rigidBodyHandles.has(entityId);
|
|
1205
1220
|
const shouldRecreateBody = !hasRigidBody || previousRigidBodySignature !== rigidBodySignature;
|
|
@@ -1254,6 +1269,25 @@ var _PhysicsSyncSystem = class _PhysicsSyncSystem {
|
|
|
1254
1269
|
continue;
|
|
1255
1270
|
}
|
|
1256
1271
|
setPhysicsLiveRef(physics, "rigidBody", body);
|
|
1272
|
+
const desiredBodyType = this.isEditorMode ? "fixed" : physics.values.rigidbody.type;
|
|
1273
|
+
const desiredRapierType = toBodyType(this.rapier, desiredBodyType);
|
|
1274
|
+
if (body.bodyType() !== desiredRapierType) {
|
|
1275
|
+
body.setBodyType(desiredRapierType, true);
|
|
1276
|
+
if (!this.isEditorMode && desiredBodyType === "dynamic") {
|
|
1277
|
+
body.setAdditionalMass(physics.values.rigidbody.mass, true);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
const pending = physics.pendingVelocity;
|
|
1281
|
+
if (pending) {
|
|
1282
|
+
setPhysicsLiveRef(physics, "pendingVelocity", null);
|
|
1283
|
+
if (!this.isEditorMode && desiredBodyType === "dynamic") {
|
|
1284
|
+
try {
|
|
1285
|
+
body.setLinvel(pending.linear, true);
|
|
1286
|
+
body.setAngvel(pending.angular, true);
|
|
1287
|
+
} catch {
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1257
1291
|
if (this.isEditorMode || physics.values.rigidbody.type !== "dynamic") {
|
|
1258
1292
|
syncBodyFromTransform(body, transform);
|
|
1259
1293
|
}
|
|
@@ -2981,9 +3015,6 @@ function restorePostCreateComponents(world, objectManagementSystem, targetEntity
|
|
|
2981
3015
|
if (typeof sourceInteractable.pointable === "boolean") {
|
|
2982
3016
|
interactable.pointable = sourceInteractable.pointable;
|
|
2983
3017
|
}
|
|
2984
|
-
if (typeof sourceInteractable.grabMode === "string") {
|
|
2985
|
-
interactable.grabMode = sourceInteractable.grabMode;
|
|
2986
|
-
}
|
|
2987
3018
|
if (typeof sourceInteractable.grabReach === "string") {
|
|
2988
3019
|
interactable.grabReach = sourceInteractable.grabReach;
|
|
2989
3020
|
}
|
|
@@ -3042,8 +3073,16 @@ function restorePostCreateComponents(world, objectManagementSystem, targetEntity
|
|
|
3042
3073
|
z: typeof grabRot.z === "number" ? grabRot.z : 0
|
|
3043
3074
|
};
|
|
3044
3075
|
}
|
|
3045
|
-
if (typeof sourceInteractable.
|
|
3046
|
-
interactable.
|
|
3076
|
+
if (typeof sourceInteractable.hoverBehavior === "string") {
|
|
3077
|
+
interactable.hoverBehavior = sourceInteractable.hoverBehavior;
|
|
3078
|
+
} else if (sourceInteractable.highlightOnHover === false) {
|
|
3079
|
+
interactable.hoverBehavior = "none";
|
|
3080
|
+
}
|
|
3081
|
+
if (typeof sourceInteractable.hoverColor === "string") {
|
|
3082
|
+
interactable.hoverColor = sourceInteractable.hoverColor;
|
|
3083
|
+
}
|
|
3084
|
+
if (typeof sourceInteractable.hoverScale === "number") {
|
|
3085
|
+
interactable.hoverScale = sourceInteractable.hoverScale;
|
|
3047
3086
|
}
|
|
3048
3087
|
}
|
|
3049
3088
|
}
|
|
@@ -3095,6 +3134,12 @@ function restorePostCreateComponents(world, objectManagementSystem, targetEntity
|
|
|
3095
3134
|
if (typeof sourceInteractor.showRay === "boolean") {
|
|
3096
3135
|
interactor.showRay = sourceInteractor.showRay;
|
|
3097
3136
|
}
|
|
3137
|
+
if (typeof sourceInteractor.rayColor === "string") {
|
|
3138
|
+
interactor.rayColor = sourceInteractor.rayColor;
|
|
3139
|
+
}
|
|
3140
|
+
if (typeof sourceInteractor.rayThickness === "number") {
|
|
3141
|
+
interactor.rayThickness = sourceInteractor.rayThickness;
|
|
3142
|
+
}
|
|
3098
3143
|
}
|
|
3099
3144
|
}
|
|
3100
3145
|
{
|
|
@@ -6537,6 +6582,8 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6537
6582
|
this.raycaster = new THREE19.Raycaster();
|
|
6538
6583
|
this.grabs = /* @__PURE__ */ new Map();
|
|
6539
6584
|
this.hoveredEntityId = null;
|
|
6585
|
+
/** Per-hand hover, with the hit distance so the ray can stop at the surface. */
|
|
6586
|
+
this.hovers = /* @__PURE__ */ new Map();
|
|
6540
6587
|
/** Monotonic seconds, accumulated from deltaTime for velocity sampling. */
|
|
6541
6588
|
this.elapsed = 0;
|
|
6542
6589
|
this.inputSystem = inputSystem;
|
|
@@ -6550,6 +6597,7 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6550
6597
|
const inputs = this.inputSystem.getInputs();
|
|
6551
6598
|
const interactables = this.collectInteractables(world);
|
|
6552
6599
|
this.hoveredEntityId = null;
|
|
6600
|
+
this.hovers.clear();
|
|
6553
6601
|
for (const input of inputs) {
|
|
6554
6602
|
if (!input.connected) {
|
|
6555
6603
|
this.release(world, input);
|
|
@@ -6567,6 +6615,10 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6567
6615
|
if (this.hoveredEntityId === null) {
|
|
6568
6616
|
this.hoveredEntityId = candidate.entityId;
|
|
6569
6617
|
}
|
|
6618
|
+
this.hovers.set(input, {
|
|
6619
|
+
entityId: candidate.entityId,
|
|
6620
|
+
distance: candidate.distance
|
|
6621
|
+
});
|
|
6570
6622
|
const interactable = world.getComponent(
|
|
6571
6623
|
candidate.entityId,
|
|
6572
6624
|
XRInteractableComponent
|
|
@@ -6639,7 +6691,7 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6639
6691
|
transform.position.x - hand.x,
|
|
6640
6692
|
transform.position.y - hand.y,
|
|
6641
6693
|
transform.position.z - hand.z
|
|
6642
|
-
);
|
|
6694
|
+
).applyQuaternion(handQuaternion.clone().invert());
|
|
6643
6695
|
record.handRotationOffset = handQuaternion.clone().invert().multiply(objectQuaternion);
|
|
6644
6696
|
record.remote = false;
|
|
6645
6697
|
record.tracker.clear();
|
|
@@ -6750,13 +6802,22 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6750
6802
|
}
|
|
6751
6803
|
}
|
|
6752
6804
|
if (nearestId !== null) {
|
|
6753
|
-
return {
|
|
6805
|
+
return {
|
|
6806
|
+
entityId: nearestId,
|
|
6807
|
+
viaDistance: false,
|
|
6808
|
+
distance: nearestDistance
|
|
6809
|
+
};
|
|
6754
6810
|
}
|
|
6755
|
-
const
|
|
6756
|
-
if (
|
|
6811
|
+
const hit = this.raycast(input, interactables);
|
|
6812
|
+
if (hit === null) return null;
|
|
6813
|
+
const hitId = hit.entityId;
|
|
6757
6814
|
const interactable = world.getComponent(hitId, XRInteractableComponent);
|
|
6758
6815
|
const viaDistanceAllowed = interactable?.grabReach === "distance" || interactable?.grabReach === "both";
|
|
6759
|
-
return {
|
|
6816
|
+
return {
|
|
6817
|
+
entityId: hitId,
|
|
6818
|
+
viaDistance: viaDistanceAllowed,
|
|
6819
|
+
distance: hit.distance
|
|
6820
|
+
};
|
|
6760
6821
|
}
|
|
6761
6822
|
collectInteractables(world) {
|
|
6762
6823
|
const out = [];
|
|
@@ -6787,7 +6848,7 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6787
6848
|
nearestId = entry.entityId;
|
|
6788
6849
|
}
|
|
6789
6850
|
}
|
|
6790
|
-
return nearestId;
|
|
6851
|
+
return nearestId === null ? null : { entityId: nearestId, distance: nearestDistance };
|
|
6791
6852
|
}
|
|
6792
6853
|
/**
|
|
6793
6854
|
* Pick the authored hold this hand should take.
|
|
@@ -6862,7 +6923,7 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6862
6923
|
transform.position.x - hand.x,
|
|
6863
6924
|
transform.position.y - hand.y,
|
|
6864
6925
|
transform.position.z - hand.z
|
|
6865
|
-
);
|
|
6926
|
+
).applyQuaternion(handQuaternion.clone().invert());
|
|
6866
6927
|
}
|
|
6867
6928
|
const physics = world.getComponent(entityId, PhysicsComponent);
|
|
6868
6929
|
let restoreBodyType = null;
|
|
@@ -6997,9 +7058,10 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6997
7058
|
transform.position.z = hand.z - anchor.z;
|
|
6998
7059
|
writeEuler(transform.rotation, objectQuaternion);
|
|
6999
7060
|
} else {
|
|
7000
|
-
|
|
7001
|
-
transform.position.
|
|
7002
|
-
transform.position.
|
|
7061
|
+
const carried = held.offset.clone().applyQuaternion(handQuaternion);
|
|
7062
|
+
transform.position.x = hand.x + carried.x;
|
|
7063
|
+
transform.position.y = hand.y + carried.y;
|
|
7064
|
+
transform.position.z = hand.z + carried.z;
|
|
7003
7065
|
writeEuler(transform.rotation, objectQuaternion);
|
|
7004
7066
|
}
|
|
7005
7067
|
held.tracker.record(
|
|
@@ -7052,19 +7114,14 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
7052
7114
|
const physics = world.getComponent(held.entityId, PhysicsComponent);
|
|
7053
7115
|
if (held.restoreBodyType !== null && physics) {
|
|
7054
7116
|
physics.values.rigidbody.type = held.restoreBodyType;
|
|
7055
|
-
const body = physics.rigidBody;
|
|
7056
7117
|
const dynamic = held.restoreBodyType === "dynamic";
|
|
7057
|
-
if (
|
|
7118
|
+
if (dynamic && interactable?.throwOnRelease) {
|
|
7058
7119
|
const velocity = held.tracker.computeVelocity(this.elapsed).multiplyScalar(interactable.throwStrength);
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7064
|
-
const spin = held.angularVelocity;
|
|
7065
|
-
body.setAngvel({ x: spin.x, y: spin.y, z: spin.z }, true);
|
|
7066
|
-
} catch {
|
|
7067
|
-
}
|
|
7120
|
+
const spin = held.angularVelocity;
|
|
7121
|
+
setPhysicsLiveRef(physics, "pendingVelocity", {
|
|
7122
|
+
linear: { x: velocity.x, y: velocity.y, z: velocity.z },
|
|
7123
|
+
angular: { x: spin.x, y: spin.y, z: spin.z }
|
|
7124
|
+
});
|
|
7068
7125
|
}
|
|
7069
7126
|
}
|
|
7070
7127
|
held.tracker.clear();
|
|
@@ -7112,10 +7169,41 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
7112
7169
|
getHoveredEntityId() {
|
|
7113
7170
|
return this.hoveredEntityId;
|
|
7114
7171
|
}
|
|
7172
|
+
/**
|
|
7173
|
+
* What this hand is pointing at, with the distance to it.
|
|
7174
|
+
*
|
|
7175
|
+
* The distance is what lets the pointer ray stop at the surface instead of
|
|
7176
|
+
* passing through the object.
|
|
7177
|
+
*/
|
|
7178
|
+
getHoverFor(handedness) {
|
|
7179
|
+
for (const [input, hover] of this.hovers) {
|
|
7180
|
+
if (input.handedness === handedness) return hover;
|
|
7181
|
+
}
|
|
7182
|
+
return null;
|
|
7183
|
+
}
|
|
7184
|
+
/** Every entity under a pointer this frame — drives hover feedback. */
|
|
7185
|
+
getHoveredEntityIds() {
|
|
7186
|
+
const ids = /* @__PURE__ */ new Set();
|
|
7187
|
+
for (const hover of this.hovers.values()) ids.add(hover.entityId);
|
|
7188
|
+
return ids;
|
|
7189
|
+
}
|
|
7190
|
+
/** Entities currently held, so hover feedback can skip them. */
|
|
7191
|
+
getHeldEntityIds() {
|
|
7192
|
+
const ids = /* @__PURE__ */ new Set();
|
|
7193
|
+
for (const record of this.grabs.values()) ids.add(record.entityId);
|
|
7194
|
+
return ids;
|
|
7195
|
+
}
|
|
7115
7196
|
/** True when any source is holding something. */
|
|
7116
7197
|
isGrabbing() {
|
|
7117
7198
|
return this.grabs.size > 0;
|
|
7118
7199
|
}
|
|
7200
|
+
/** True when THIS hand is holding something. */
|
|
7201
|
+
isGrabbingWith(handedness) {
|
|
7202
|
+
for (const input of this.grabs.keys()) {
|
|
7203
|
+
if (input.handedness === handedness) return true;
|
|
7204
|
+
}
|
|
7205
|
+
return false;
|
|
7206
|
+
}
|
|
7119
7207
|
/**
|
|
7120
7208
|
* How an entity is currently held.
|
|
7121
7209
|
*
|
|
@@ -7672,6 +7760,10 @@ function applyHandMaterial(root, material) {
|
|
|
7672
7760
|
});
|
|
7673
7761
|
}
|
|
7674
7762
|
__name(applyHandMaterial, "applyHandMaterial");
|
|
7763
|
+
|
|
7764
|
+
// core/systems/XRControllerVisualSystem.ts
|
|
7765
|
+
var RAY_LENGTH = 5;
|
|
7766
|
+
var RAY_RADIUS = 3e-3;
|
|
7675
7767
|
var SLOTS = [
|
|
7676
7768
|
{ index: 0, side: "left" },
|
|
7677
7769
|
{ index: 1, side: "right" }
|
|
@@ -7681,6 +7773,8 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
|
7681
7773
|
this.controllerModelFactory = new XRControllerModelFactory();
|
|
7682
7774
|
this.handModelFactory = new XRHandModelFactory();
|
|
7683
7775
|
this.group = new THREE19.Group();
|
|
7776
|
+
/** Reused so a per-frame colour compare allocates nothing. */
|
|
7777
|
+
this.rayColorScratch = new THREE19.Color();
|
|
7684
7778
|
this.slots = /* @__PURE__ */ new Map();
|
|
7685
7779
|
this.attachedTo = null;
|
|
7686
7780
|
/** Last applied preset signature, so materials rebuild only on real change. */
|
|
@@ -7709,7 +7803,9 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
|
7709
7803
|
const hasHand = liveKind === null || liveKind === "hand";
|
|
7710
7804
|
visuals.controllerModel.visible = showControllers && hasController;
|
|
7711
7805
|
visuals.handModel.visible = showHands && hasHand;
|
|
7712
|
-
visuals.ray.visible = this.shouldShowRay(interactor);
|
|
7806
|
+
visuals.ray.visible = this.shouldShowRay(interactor, side);
|
|
7807
|
+
this.fitRayToHover(visuals.ray, side);
|
|
7808
|
+
this.applyRayStyle(visuals.ray, interactor);
|
|
7713
7809
|
if (showHands && this.handMaterial) {
|
|
7714
7810
|
applyHandMaterial(visuals.handModel, this.handMaterial);
|
|
7715
7811
|
}
|
|
@@ -7785,10 +7881,35 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
|
7785
7881
|
* off entirely; otherwise it appears on hover/grab so it isn't permanent
|
|
7786
7882
|
* clutter implying the whole scene is clickable.
|
|
7787
7883
|
*/
|
|
7788
|
-
shouldShowRay(interactor) {
|
|
7884
|
+
shouldShowRay(interactor, side) {
|
|
7789
7885
|
if (interactor && !interactor.showRay) return false;
|
|
7790
7886
|
if (!this.interactionSystem) return true;
|
|
7791
|
-
return this.interactionSystem.
|
|
7887
|
+
return this.interactionSystem.getHoverFor(side) !== null || this.interactionSystem.isGrabbingWith(side);
|
|
7888
|
+
}
|
|
7889
|
+
/** Push the author's ray colour and thickness onto the mesh. */
|
|
7890
|
+
applyRayStyle(ray, interactor) {
|
|
7891
|
+
if (!interactor) return;
|
|
7892
|
+
const material = ray.material;
|
|
7893
|
+
if (material?.color && !material.color.equals(this.rayColorScratch.set(interactor.rayColor))) {
|
|
7894
|
+
material.color.copy(this.rayColorScratch);
|
|
7895
|
+
}
|
|
7896
|
+
const radius = Math.max(5e-4, interactor.rayThickness / 2) / RAY_RADIUS;
|
|
7897
|
+
if (ray.scale.x !== radius) {
|
|
7898
|
+
ray.scale.x = radius;
|
|
7899
|
+
ray.scale.y = radius;
|
|
7900
|
+
}
|
|
7901
|
+
}
|
|
7902
|
+
/**
|
|
7903
|
+
* Stop the ray at whatever it is pointing at.
|
|
7904
|
+
*
|
|
7905
|
+
* A fixed-length ray drawn with depth testing off punches straight through the
|
|
7906
|
+
* object, so the user cannot tell where the pointer actually lands. Scaling it
|
|
7907
|
+
* to the hit distance turns it into a pointer that meets the surface.
|
|
7908
|
+
*/
|
|
7909
|
+
fitRayToHover(ray, side) {
|
|
7910
|
+
const hover = this.interactionSystem?.getHoverFor(side) ?? null;
|
|
7911
|
+
const length = hover && Number.isFinite(hover.distance) && hover.distance > 0 ? Math.min(hover.distance, RAY_LENGTH) : RAY_LENGTH;
|
|
7912
|
+
ray.scale.z = length;
|
|
7792
7913
|
}
|
|
7793
7914
|
/** Lazily build per-slot visuals; the device reports profiles late. */
|
|
7794
7915
|
ensureSlots(world) {
|
|
@@ -7828,22 +7949,32 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
|
7828
7949
|
target.add(this.group);
|
|
7829
7950
|
this.attachedTo = target;
|
|
7830
7951
|
}
|
|
7952
|
+
/**
|
|
7953
|
+
* The pointer ray.
|
|
7954
|
+
*
|
|
7955
|
+
* A cylinder rather than a `THREE.Line`, because WebGL ignores `linewidth` —
|
|
7956
|
+
* every line renders one pixel wide regardless, which is nearly invisible on a
|
|
7957
|
+
* headset. A thin mesh is the only way to get a ray with real thickness
|
|
7958
|
+
* without pulling in a line-rendering extension.
|
|
7959
|
+
*/
|
|
7831
7960
|
createRay() {
|
|
7832
|
-
const geometry = new THREE19.
|
|
7833
|
-
|
|
7834
|
-
|
|
7835
|
-
|
|
7836
|
-
const material = new THREE19.LineBasicMaterial({
|
|
7961
|
+
const geometry = new THREE19.CylinderGeometry(RAY_RADIUS, RAY_RADIUS, 1, 8, 1);
|
|
7962
|
+
geometry.rotateX(-Math.PI / 2);
|
|
7963
|
+
geometry.translate(0, 0, -0.5);
|
|
7964
|
+
const material = new THREE19.MeshBasicMaterial({
|
|
7837
7965
|
color: "#4da3ff",
|
|
7838
7966
|
transparent: true,
|
|
7839
|
-
opacity: 0.
|
|
7840
|
-
depthTest: false
|
|
7967
|
+
opacity: 0.75,
|
|
7968
|
+
depthTest: false,
|
|
7969
|
+
depthWrite: false
|
|
7841
7970
|
});
|
|
7842
|
-
const
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
7846
|
-
|
|
7971
|
+
const mesh = new THREE19.Mesh(geometry, material);
|
|
7972
|
+
mesh.name = "XRPointerRay";
|
|
7973
|
+
mesh.renderOrder = 999;
|
|
7974
|
+
mesh.visible = false;
|
|
7975
|
+
mesh.raycast = () => {
|
|
7976
|
+
};
|
|
7977
|
+
return mesh;
|
|
7847
7978
|
}
|
|
7848
7979
|
dispose() {
|
|
7849
7980
|
this.group.removeFromParent();
|
|
@@ -8494,7 +8625,153 @@ var _XRHandPoseSystem = class _XRHandPoseSystem {
|
|
|
8494
8625
|
};
|
|
8495
8626
|
__name(_XRHandPoseSystem, "XRHandPoseSystem");
|
|
8496
8627
|
var XRHandPoseSystem = _XRHandPoseSystem;
|
|
8628
|
+
var XR_HOVER_SHELL_FLAG = "__xrHoverShell";
|
|
8629
|
+
var SHELL_INFLATE = 1.04;
|
|
8630
|
+
var SCALE_SMOOTH_SECONDS = 0.09;
|
|
8631
|
+
var _XRHoverVisualSystem = class _XRHoverVisualSystem {
|
|
8632
|
+
constructor(interactionSystem) {
|
|
8633
|
+
this.records = /* @__PURE__ */ new Map();
|
|
8634
|
+
this.interactionSystem = interactionSystem;
|
|
8635
|
+
}
|
|
8636
|
+
update(world, deltaTime) {
|
|
8637
|
+
if (!world.isXrPresenting()) {
|
|
8638
|
+
this.clearAll(world);
|
|
8639
|
+
return;
|
|
8640
|
+
}
|
|
8641
|
+
const hovered = this.interactionSystem.getHoveredEntityIds();
|
|
8642
|
+
const held = this.interactionSystem.getHeldEntityIds();
|
|
8643
|
+
for (const entityId of hovered) {
|
|
8644
|
+
if (held.has(entityId)) continue;
|
|
8645
|
+
const interactable = world.getComponent(entityId, XRInteractableComponent);
|
|
8646
|
+
if (!interactable?.enabled) continue;
|
|
8647
|
+
if (interactable.hoverBehavior === "none") continue;
|
|
8648
|
+
this.begin(world, entityId, interactable);
|
|
8649
|
+
}
|
|
8650
|
+
for (const [entityId, record] of this.records) {
|
|
8651
|
+
if (!hovered.has(entityId) || held.has(entityId)) {
|
|
8652
|
+
record.active = false;
|
|
8653
|
+
}
|
|
8654
|
+
}
|
|
8655
|
+
this.animate(world, deltaTime);
|
|
8656
|
+
}
|
|
8657
|
+
begin(world, entityId, interactable) {
|
|
8658
|
+
const existing = this.records.get(entityId);
|
|
8659
|
+
if (existing) {
|
|
8660
|
+
existing.active = true;
|
|
8661
|
+
return;
|
|
8662
|
+
}
|
|
8663
|
+
const transform = world.getComponent(entityId, TransformComponent);
|
|
8664
|
+
if (!transform) return;
|
|
8665
|
+
const wantsColor = interactable.hoverBehavior === "color" || interactable.hoverBehavior === "both";
|
|
8666
|
+
this.records.set(entityId, {
|
|
8667
|
+
shell: wantsColor ? this.addShell(world, entityId, interactable) : null,
|
|
8668
|
+
baseScale: new THREE19.Vector3(
|
|
8669
|
+
transform.scale.x,
|
|
8670
|
+
transform.scale.y,
|
|
8671
|
+
transform.scale.z
|
|
8672
|
+
),
|
|
8673
|
+
progress: 0,
|
|
8674
|
+
active: true
|
|
8675
|
+
});
|
|
8676
|
+
}
|
|
8677
|
+
/** Build an inflated back-face copy of the object's meshes. */
|
|
8678
|
+
addShell(world, entityId, interactable) {
|
|
8679
|
+
const object = world.getComponent(entityId, Object3DRef)?.object;
|
|
8680
|
+
if (!object) return null;
|
|
8681
|
+
const material = new THREE19.MeshBasicMaterial({
|
|
8682
|
+
color: new THREE19.Color(interactable.hoverColor),
|
|
8683
|
+
// Back faces only, so the shell shows just outside the silhouette instead
|
|
8684
|
+
// of covering the object.
|
|
8685
|
+
side: THREE19.BackSide,
|
|
8686
|
+
transparent: true,
|
|
8687
|
+
opacity: 0.85,
|
|
8688
|
+
depthWrite: false
|
|
8689
|
+
});
|
|
8690
|
+
const group = new THREE19.Group();
|
|
8691
|
+
group.name = "XRHoverShell";
|
|
8692
|
+
group.userData[XR_HOVER_SHELL_FLAG] = true;
|
|
8693
|
+
group.renderOrder = 998;
|
|
8694
|
+
object.traverse((child) => {
|
|
8695
|
+
if (!(child instanceof THREE19.Mesh) || !child.geometry) return;
|
|
8696
|
+
if (child.userData[XR_HOVER_SHELL_FLAG]) return;
|
|
8697
|
+
const clone2 = new THREE19.Mesh(child.geometry, material);
|
|
8698
|
+
child.updateWorldMatrix(true, false);
|
|
8699
|
+
object.updateWorldMatrix(true, false);
|
|
8700
|
+
clone2.matrixAutoUpdate = false;
|
|
8701
|
+
clone2.matrix.copy(object.matrixWorld).invert().multiply(child.matrixWorld).scale(new THREE19.Vector3(SHELL_INFLATE, SHELL_INFLATE, SHELL_INFLATE));
|
|
8702
|
+
clone2.userData[XR_HOVER_SHELL_FLAG] = true;
|
|
8703
|
+
clone2.raycast = () => {
|
|
8704
|
+
};
|
|
8705
|
+
group.add(clone2);
|
|
8706
|
+
});
|
|
8707
|
+
if (group.children.length === 0) {
|
|
8708
|
+
material.dispose();
|
|
8709
|
+
return null;
|
|
8710
|
+
}
|
|
8711
|
+
object.add(group);
|
|
8712
|
+
return group;
|
|
8713
|
+
}
|
|
8714
|
+
animate(world, deltaTime) {
|
|
8715
|
+
const step = 1 - Math.exp(-Math.max(0, deltaTime) / SCALE_SMOOTH_SECONDS);
|
|
8716
|
+
for (const [entityId, record] of Array.from(this.records)) {
|
|
8717
|
+
const interactable = world.getComponent(entityId, XRInteractableComponent);
|
|
8718
|
+
const target = record.active ? 1 : 0;
|
|
8719
|
+
record.progress += (target - record.progress) * step;
|
|
8720
|
+
const wantsScale = interactable?.hoverBehavior === "scale" || interactable?.hoverBehavior === "both";
|
|
8721
|
+
if (wantsScale) {
|
|
8722
|
+
const transform = world.getComponent(entityId, TransformComponent);
|
|
8723
|
+
if (transform) {
|
|
8724
|
+
const factor = 1 + (interactable.hoverScale - 1) * Math.min(1, record.progress);
|
|
8725
|
+
transform.scale.x = record.baseScale.x * factor;
|
|
8726
|
+
transform.scale.y = record.baseScale.y * factor;
|
|
8727
|
+
transform.scale.z = record.baseScale.z * factor;
|
|
8728
|
+
}
|
|
8729
|
+
}
|
|
8730
|
+
if (!record.active && record.progress < 0.01) {
|
|
8731
|
+
this.finish(world, entityId, record);
|
|
8732
|
+
}
|
|
8733
|
+
}
|
|
8734
|
+
}
|
|
8735
|
+
/** Remove the effect and restore the authored scale exactly. */
|
|
8736
|
+
finish(world, entityId, record) {
|
|
8737
|
+
const transform = world.getComponent(entityId, TransformComponent);
|
|
8738
|
+
if (transform) {
|
|
8739
|
+
transform.scale.x = record.baseScale.x;
|
|
8740
|
+
transform.scale.y = record.baseScale.y;
|
|
8741
|
+
transform.scale.z = record.baseScale.z;
|
|
8742
|
+
}
|
|
8743
|
+
this.disposeShell(record.shell);
|
|
8744
|
+
this.records.delete(entityId);
|
|
8745
|
+
}
|
|
8746
|
+
disposeShell(shell) {
|
|
8747
|
+
if (!shell) return;
|
|
8748
|
+
shell.parent?.remove(shell);
|
|
8749
|
+
shell.traverse((child) => {
|
|
8750
|
+
if (child instanceof THREE19.Mesh) {
|
|
8751
|
+
const material = child.material;
|
|
8752
|
+
if (Array.isArray(material)) {
|
|
8753
|
+
for (const entry of material) entry.dispose();
|
|
8754
|
+
} else {
|
|
8755
|
+
material?.dispose();
|
|
8756
|
+
}
|
|
8757
|
+
}
|
|
8758
|
+
});
|
|
8759
|
+
}
|
|
8760
|
+
clearAll(world) {
|
|
8761
|
+
for (const [entityId, record] of Array.from(this.records)) {
|
|
8762
|
+
this.finish(world, entityId, record);
|
|
8763
|
+
}
|
|
8764
|
+
}
|
|
8765
|
+
dispose() {
|
|
8766
|
+
for (const record of this.records.values()) {
|
|
8767
|
+
this.disposeShell(record.shell);
|
|
8768
|
+
}
|
|
8769
|
+
this.records.clear();
|
|
8770
|
+
}
|
|
8771
|
+
};
|
|
8772
|
+
__name(_XRHoverVisualSystem, "XRHoverVisualSystem");
|
|
8773
|
+
var XRHoverVisualSystem = _XRHoverVisualSystem;
|
|
8497
8774
|
|
|
8498
|
-
export { ADDED_NODE_MARKER_COMPONENT, ARC_GRAVITY, ARC_MAX_TIME, ARC_SPEED, ARC_STEPS, AnimationSystem, AudioSystem, Behaviour, CURLED_COS, CameraSyncSystem, DEFAULT_ENTER_CONFIDENCE, DEFAULT_EXIT_CONFIDENCE, DEFAULT_LOST_GRACE_SECONDS, DEFAULT_MIN_HOLD_SECONDS, EnvironmentSyncSystem, FALLBACK_HAND_SCALE, HYDRATABLE_ENTITY_KINDS, HandPoseTracker, InputSystem, InstancedMeshSystem, KeyboardKeys, LightSyncSystem, MATCH_FALLOFF, MAX_PLAUSIBLE_SPEED, MAX_SAMPLE_AGE_SECONDS, MaterialSyncSystem, MeshGeometrySystem, NODE_KEY_SEPARATOR, NO_XR_CAPABILITIES, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectVisibilitySystem, PINCH_FINGERS, PREFAB_FILE_VERSION, PREFAB_FILE_VERSION_NESTED, PhysicsSyncSystem, PostprocessingSyncSystem, RenderSystem, SCRIPT_OBJECT_ROOT_FLAG, STRAIGHT_COS, ScriptBehaviourSystem, ScriptObject, ScriptObjectSystem, ThrowVelocityTracker, TransformSyncSystem, VELOCITY_SAMPLES, VRTeleportAreaSystem, VideoSystem, XRControllerVisualSystem, XRHandPoseSystem, XRInputSystem, XRInteractionSystem, XRLocomotionSystem, XRSessionSystem, XRTeleportVisualSystem, XR_FINGERS, angularVelocityFrom, applyHandMaterial, arcGroundCrossing, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearPrefabCache, collectDiffPaths, collectEntitySubtree, collectSnapshotSubtreeIds, computeFingerCurl, computeHandShape, computeInstanceOverrides, computePalmPose, computePalmWidth, computePinch, computeSpread, createHandMaterial, decanonicalizeComponentValue, despawnPrefab, encodeOverride, estimateHandScale, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadPrefab, matchHandPose, mergeComponentValue, parseOverride, parsePrefabAsset, prefabFileVersionFor, readXrCapabilities, restoreComponentState, restorePostCreateComponents, sampleTeleportArc, setPrefabAssetUrlResolver, spawnPrefab };
|
|
8499
|
-
//# sourceMappingURL=chunk-
|
|
8500
|
-
//# sourceMappingURL=chunk-
|
|
8775
|
+
export { ADDED_NODE_MARKER_COMPONENT, ARC_GRAVITY, ARC_MAX_TIME, ARC_SPEED, ARC_STEPS, AnimationSystem, AudioSystem, Behaviour, CURLED_COS, CameraSyncSystem, DEFAULT_ENTER_CONFIDENCE, DEFAULT_EXIT_CONFIDENCE, DEFAULT_LOST_GRACE_SECONDS, DEFAULT_MIN_HOLD_SECONDS, EnvironmentSyncSystem, FALLBACK_HAND_SCALE, HYDRATABLE_ENTITY_KINDS, HandPoseTracker, InputSystem, InstancedMeshSystem, KeyboardKeys, LightSyncSystem, MATCH_FALLOFF, MAX_PLAUSIBLE_SPEED, MAX_SAMPLE_AGE_SECONDS, MaterialSyncSystem, MeshGeometrySystem, NODE_KEY_SEPARATOR, NO_XR_CAPABILITIES, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectVisibilitySystem, PINCH_FINGERS, PREFAB_FILE_VERSION, PREFAB_FILE_VERSION_NESTED, PhysicsSyncSystem, PostprocessingSyncSystem, RenderSystem, SCRIPT_OBJECT_ROOT_FLAG, STRAIGHT_COS, ScriptBehaviourSystem, ScriptObject, ScriptObjectSystem, ThrowVelocityTracker, TransformSyncSystem, VELOCITY_SAMPLES, VRTeleportAreaSystem, VideoSystem, XRControllerVisualSystem, XRHandPoseSystem, 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 };
|
|
8776
|
+
//# sourceMappingURL=chunk-LCJ6IH2O.js.map
|
|
8777
|
+
//# sourceMappingURL=chunk-LCJ6IH2O.js.map
|