@relu-interactives/spatial-ecs 0.3.9 → 0.3.11
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-CxPz8VBp.d.ts → XRHandPose-B6I4y1lj.d.ts} +117 -14
- package/dist/{XRHandPose-VuSbe4iz.d.cts → XRHandPose-C-KJeYcJ.d.cts} +117 -14
- package/dist/{chunk-KIKIWCEB.js → chunk-FSHRPY65.js} +4 -4
- package/dist/{chunk-KIKIWCEB.js.map → chunk-FSHRPY65.js.map} +1 -1
- package/dist/{chunk-W5TSYV6Q.js → chunk-KLU2M43M.js} +836 -212
- package/dist/chunk-KLU2M43M.js.map +1 -0
- package/dist/{chunk-KVGGAL5V.js → chunk-TXEGYR76.js} +26 -5
- package/dist/chunk-TXEGYR76.js.map +1 -0
- package/dist/{chunk-L5BP727H.js → chunk-Y3AC3VZ2.js} +3 -3
- package/dist/{chunk-L5BP727H.js.map → chunk-Y3AC3VZ2.js.map} +1 -1
- package/dist/components/index.cjs +23 -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 +55 -3
- package/dist/factories/index.cjs +22 -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-C7XQyrgE.d.ts → index-Bi_wIo1o.d.ts} +107 -1
- package/dist/{index-BxdXgqiI.d.ts → index-CEZp7qLL.d.ts} +9 -3
- package/dist/{index-BIQoaKAA.d.cts → index-DPRnnSI-.d.cts} +9 -3
- package/dist/{index-DyN50JZo.d.cts → index-jlgDou9W.d.cts} +107 -1
- package/dist/index.cjs +978 -331
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -5
- package/dist/index.d.ts +14 -5
- package/dist/index.js +8 -8
- package/dist/systems/index.cjs +885 -239
- 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-KVGGAL5V.js.map +0 -1
- package/dist/chunk-W5TSYV6Q.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
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, 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-Y3AC3VZ2.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-TXEGYR76.js';
|
|
3
3
|
import { __name } from './chunk-OY7ZODZP.js';
|
|
4
|
-
import * as
|
|
4
|
+
import * as THREE19 from 'three';
|
|
5
5
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
|
|
6
6
|
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js';
|
|
7
7
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
@@ -160,7 +160,7 @@ function transitionToClip(runtime, nextClipId, crossFadeDuration) {
|
|
|
160
160
|
}
|
|
161
161
|
__name(transitionToClip, "transitionToClip");
|
|
162
162
|
function applyActionState(action, component, paused, shouldLoop) {
|
|
163
|
-
const loopMode = shouldLoop ?
|
|
163
|
+
const loopMode = shouldLoop ? THREE19.LoopRepeat : THREE19.LoopOnce;
|
|
164
164
|
const repetitions = shouldLoop ? Infinity : 1;
|
|
165
165
|
action.setLoop(loopMode, repetitions);
|
|
166
166
|
action.clampWhenFinished = !shouldLoop;
|
|
@@ -333,7 +333,7 @@ var _AnimationSystem = class _AnimationSystem {
|
|
|
333
333
|
if (runtime) {
|
|
334
334
|
stopAllActions(runtime);
|
|
335
335
|
}
|
|
336
|
-
const mixer = new
|
|
336
|
+
const mixer = new THREE19.AnimationMixer(root);
|
|
337
337
|
const entries2 = readRuntimeClipEntries(animation);
|
|
338
338
|
const indexedActions = createActions(mixer, entries2);
|
|
339
339
|
runtime = {
|
|
@@ -459,11 +459,11 @@ function normalizeOrthoBounds(component) {
|
|
|
459
459
|
}
|
|
460
460
|
__name(normalizeOrthoBounds, "normalizeOrthoBounds");
|
|
461
461
|
function isPerspectiveCamera(camera) {
|
|
462
|
-
return camera instanceof
|
|
462
|
+
return camera instanceof THREE19.PerspectiveCamera;
|
|
463
463
|
}
|
|
464
464
|
__name(isPerspectiveCamera, "isPerspectiveCamera");
|
|
465
465
|
function isOrthographicCamera(camera) {
|
|
466
|
-
return camera instanceof
|
|
466
|
+
return camera instanceof THREE19.OrthographicCamera;
|
|
467
467
|
}
|
|
468
468
|
__name(isOrthographicCamera, "isOrthographicCamera");
|
|
469
469
|
function readWindowAspect() {
|
|
@@ -517,7 +517,7 @@ var _CameraSyncSystem = class _CameraSyncSystem {
|
|
|
517
517
|
continue;
|
|
518
518
|
}
|
|
519
519
|
const camera = objectRef.object;
|
|
520
|
-
if (!(camera instanceof
|
|
520
|
+
if (!(camera instanceof THREE19.Camera)) {
|
|
521
521
|
continue;
|
|
522
522
|
}
|
|
523
523
|
if (xrCamera !== null && camera === xrCamera) {
|
|
@@ -584,7 +584,7 @@ var MIN_DENSITY = 0;
|
|
|
584
584
|
function createGradientTexture(effect, colors) {
|
|
585
585
|
if (typeof document === "undefined") {
|
|
586
586
|
const pixel = new Uint8Array([30, 30, 30, 255]);
|
|
587
|
-
const fallback = new
|
|
587
|
+
const fallback = new THREE19.DataTexture(pixel, 1, 1, THREE19.RGBAFormat);
|
|
588
588
|
fallback.needsUpdate = true;
|
|
589
589
|
return fallback;
|
|
590
590
|
}
|
|
@@ -593,7 +593,7 @@ function createGradientTexture(effect, colors) {
|
|
|
593
593
|
canvas.height = 512;
|
|
594
594
|
const context = canvas.getContext("2d");
|
|
595
595
|
if (!context) {
|
|
596
|
-
const fallback = new
|
|
596
|
+
const fallback = new THREE19.CanvasTexture(canvas);
|
|
597
597
|
fallback.needsUpdate = true;
|
|
598
598
|
return fallback;
|
|
599
599
|
}
|
|
@@ -621,15 +621,15 @@ function createGradientTexture(effect, colors) {
|
|
|
621
621
|
context.fillRect(0, 0, 512, 512);
|
|
622
622
|
context.globalCompositeOperation = "source-over";
|
|
623
623
|
}
|
|
624
|
-
const texture = new
|
|
625
|
-
texture.colorSpace =
|
|
624
|
+
const texture = new THREE19.CanvasTexture(canvas);
|
|
625
|
+
texture.colorSpace = THREE19.SRGBColorSpace;
|
|
626
626
|
texture.needsUpdate = true;
|
|
627
627
|
return texture;
|
|
628
628
|
}
|
|
629
629
|
__name(createGradientTexture, "createGradientTexture");
|
|
630
630
|
var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
|
|
631
631
|
constructor(scene) {
|
|
632
|
-
this.textureLoader = new
|
|
632
|
+
this.textureLoader = new THREE19.TextureLoader();
|
|
633
633
|
this.signature = null;
|
|
634
634
|
this.activeTexture = null;
|
|
635
635
|
this.pendingImageUrl = null;
|
|
@@ -652,7 +652,7 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
|
|
|
652
652
|
if (skybox.type === "color") {
|
|
653
653
|
this.disposeActiveTexture();
|
|
654
654
|
this.pendingImageUrl = null;
|
|
655
|
-
this.scene.background = new
|
|
655
|
+
this.scene.background = new THREE19.Color(skybox.color || "#1e1e1e");
|
|
656
656
|
return;
|
|
657
657
|
}
|
|
658
658
|
if (skybox.type === "gradient") {
|
|
@@ -686,7 +686,7 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
|
|
|
686
686
|
texture.dispose();
|
|
687
687
|
return;
|
|
688
688
|
}
|
|
689
|
-
texture.colorSpace =
|
|
689
|
+
texture.colorSpace = THREE19.SRGBColorSpace;
|
|
690
690
|
this.activeTexture = texture;
|
|
691
691
|
this.scene.background = texture;
|
|
692
692
|
},
|
|
@@ -705,16 +705,16 @@ var _EnvironmentSyncSystem = class _EnvironmentSyncSystem {
|
|
|
705
705
|
this.scene.fog = null;
|
|
706
706
|
return;
|
|
707
707
|
}
|
|
708
|
-
const fogColor = new
|
|
708
|
+
const fogColor = new THREE19.Color(fog.color || "#1e1e1e");
|
|
709
709
|
if (fog.type === "linear") {
|
|
710
710
|
const near = Number.isFinite(fog.linear.near) ? fog.linear.near : 1;
|
|
711
711
|
const farCandidate = Number.isFinite(fog.linear.far) ? fog.linear.far : near + 10;
|
|
712
712
|
const far = Math.max(near + MIN_FOG_DELTA, farCandidate);
|
|
713
|
-
this.scene.fog = new
|
|
713
|
+
this.scene.fog = new THREE19.Fog(fogColor, near, far);
|
|
714
714
|
return;
|
|
715
715
|
}
|
|
716
716
|
const density = Number.isFinite(fog.exponential.density) ? Math.max(MIN_DENSITY, fog.exponential.density) : 2e-3;
|
|
717
|
-
this.scene.fog = new
|
|
717
|
+
this.scene.fog = new THREE19.FogExp2(fogColor, density);
|
|
718
718
|
}
|
|
719
719
|
update(world) {
|
|
720
720
|
const entityIds = world.query(Environment);
|
|
@@ -796,10 +796,10 @@ var _PostprocessingSyncSystem = class _PostprocessingSyncSystem {
|
|
|
796
796
|
);
|
|
797
797
|
}
|
|
798
798
|
if (values.bloom.enabled) {
|
|
799
|
-
const size = this.renderer.getSize(new
|
|
799
|
+
const size = this.renderer.getSize(new THREE19.Vector2());
|
|
800
800
|
composer.addPass(
|
|
801
801
|
new UnrealBloomPass(
|
|
802
|
-
new
|
|
802
|
+
new THREE19.Vector2(size.width, size.height),
|
|
803
803
|
values.bloom.intensity,
|
|
804
804
|
values.bloom.radius,
|
|
805
805
|
values.bloom.threshold
|
|
@@ -844,7 +844,7 @@ var _PostprocessingSyncSystem = class _PostprocessingSyncSystem {
|
|
|
844
844
|
if (values.dotScreen.enabled) {
|
|
845
845
|
composer.addPass(
|
|
846
846
|
new DotScreenPass(
|
|
847
|
-
new
|
|
847
|
+
new THREE19.Vector2(0, 0),
|
|
848
848
|
values.dotScreen.angle ?? values.dotScreen.dotScreenAngle,
|
|
849
849
|
values.dotScreen.scale ?? values.dotScreen.dotScreenScale
|
|
850
850
|
)
|
|
@@ -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();
|
|
@@ -918,7 +932,7 @@ function computeColliderState(colliderValues, object) {
|
|
|
918
932
|
if (!object) {
|
|
919
933
|
return colliderValues;
|
|
920
934
|
}
|
|
921
|
-
const scale = new
|
|
935
|
+
const scale = new THREE19.Vector3();
|
|
922
936
|
object.getWorldScale(scale);
|
|
923
937
|
return {
|
|
924
938
|
...colliderValues,
|
|
@@ -969,8 +983,8 @@ function createColliderDesc(RAPIER, values, triMeshData) {
|
|
|
969
983
|
values.offsetPosition.y,
|
|
970
984
|
values.offsetPosition.z
|
|
971
985
|
);
|
|
972
|
-
const offsetQuaternion = new
|
|
973
|
-
new
|
|
986
|
+
const offsetQuaternion = new THREE19.Quaternion().setFromEuler(
|
|
987
|
+
new THREE19.Euler(
|
|
974
988
|
values.offsetRotation.x,
|
|
975
989
|
values.offsetRotation.y,
|
|
976
990
|
values.offsetRotation.z
|
|
@@ -985,17 +999,17 @@ function collectTriMeshParts(object) {
|
|
|
985
999
|
return null;
|
|
986
1000
|
}
|
|
987
1001
|
object.updateWorldMatrix(true, true);
|
|
988
|
-
const worldScale = new
|
|
1002
|
+
const worldScale = new THREE19.Vector3();
|
|
989
1003
|
object.getWorldScale(worldScale);
|
|
990
1004
|
const scale = {
|
|
991
1005
|
x: Math.abs(worldScale.x) || 1,
|
|
992
1006
|
y: Math.abs(worldScale.y) || 1,
|
|
993
1007
|
z: Math.abs(worldScale.z) || 1
|
|
994
1008
|
};
|
|
995
|
-
const worldToObject = new
|
|
1009
|
+
const worldToObject = new THREE19.Matrix4().copy(object.matrixWorld).invert();
|
|
996
1010
|
const parts = [];
|
|
997
1011
|
object.traverse((child) => {
|
|
998
|
-
if (!(child instanceof
|
|
1012
|
+
if (!(child instanceof THREE19.Mesh) || !child.geometry) {
|
|
999
1013
|
return;
|
|
1000
1014
|
}
|
|
1001
1015
|
const geometry = child.geometry;
|
|
@@ -1012,7 +1026,7 @@ function collectTriMeshParts(object) {
|
|
|
1012
1026
|
if (indexCount < 3) {
|
|
1013
1027
|
return;
|
|
1014
1028
|
}
|
|
1015
|
-
const relativeMatrix = new
|
|
1029
|
+
const relativeMatrix = new THREE19.Matrix4().multiplyMatrices(
|
|
1016
1030
|
worldToObject,
|
|
1017
1031
|
child.matrixWorld
|
|
1018
1032
|
);
|
|
@@ -1053,7 +1067,7 @@ function createTriMeshData(collected) {
|
|
|
1053
1067
|
}
|
|
1054
1068
|
const vertices = new Float32Array(vertexTotal * 3);
|
|
1055
1069
|
const indices = new Uint32Array(indexTotal);
|
|
1056
|
-
const point = new
|
|
1070
|
+
const point = new THREE19.Vector3();
|
|
1057
1071
|
let vertexOffset = 0;
|
|
1058
1072
|
let indexOffset = 0;
|
|
1059
1073
|
for (const part of parts) {
|
|
@@ -1085,8 +1099,8 @@ function createTriMeshData(collected) {
|
|
|
1085
1099
|
}
|
|
1086
1100
|
__name(createTriMeshData, "createTriMeshData");
|
|
1087
1101
|
function syncBodyFromTransform(body, transform) {
|
|
1088
|
-
const quaternion = new
|
|
1089
|
-
new
|
|
1102
|
+
const quaternion = new THREE19.Quaternion().setFromEuler(
|
|
1103
|
+
new THREE19.Euler(transform.rotation.x, transform.rotation.y, transform.rotation.z)
|
|
1090
1104
|
);
|
|
1091
1105
|
body.setTranslation(
|
|
1092
1106
|
{
|
|
@@ -1113,8 +1127,8 @@ function syncTransformFromBody(transform, body) {
|
|
|
1113
1127
|
transform.position.x = position.x;
|
|
1114
1128
|
transform.position.y = position.y;
|
|
1115
1129
|
transform.position.z = position.z;
|
|
1116
|
-
const euler = new
|
|
1117
|
-
new
|
|
1130
|
+
const euler = new THREE19.Euler().setFromQuaternion(
|
|
1131
|
+
new THREE19.Quaternion(rotation.x, rotation.y, rotation.z, rotation.w)
|
|
1118
1132
|
);
|
|
1119
1133
|
transform.rotation.x = euler.x;
|
|
1120
1134
|
transform.rotation.y = euler.y;
|
|
@@ -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;
|
|
@@ -1226,8 +1241,8 @@ var _PhysicsSyncSystem = class _PhysicsSyncSystem {
|
|
|
1226
1241
|
transform.position.y,
|
|
1227
1242
|
transform.position.z
|
|
1228
1243
|
);
|
|
1229
|
-
const quaternion = new
|
|
1230
|
-
new
|
|
1244
|
+
const quaternion = new THREE19.Quaternion().setFromEuler(
|
|
1245
|
+
new THREE19.Euler(
|
|
1231
1246
|
transform.rotation.x,
|
|
1232
1247
|
transform.rotation.y,
|
|
1233
1248
|
transform.rotation.z
|
|
@@ -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
|
}
|
|
@@ -1806,7 +1840,7 @@ function applyLightValues(lightComponent) {
|
|
|
1806
1840
|
values.castShadow
|
|
1807
1841
|
);
|
|
1808
1842
|
}
|
|
1809
|
-
if (light instanceof
|
|
1843
|
+
if (light instanceof THREE19.PointLight) {
|
|
1810
1844
|
if (typeof values.distance === "number" && Number.isFinite(values.distance)) {
|
|
1811
1845
|
light.distance = Math.max(MIN_LIGHT_DISTANCE, values.distance);
|
|
1812
1846
|
}
|
|
@@ -1814,7 +1848,7 @@ function applyLightValues(lightComponent) {
|
|
|
1814
1848
|
light.decay = Math.max(0, values.decay);
|
|
1815
1849
|
}
|
|
1816
1850
|
}
|
|
1817
|
-
if (light instanceof
|
|
1851
|
+
if (light instanceof THREE19.SpotLight) {
|
|
1818
1852
|
if (typeof values.distance === "number" && Number.isFinite(values.distance)) {
|
|
1819
1853
|
light.distance = Math.max(MIN_LIGHT_DISTANCE, values.distance);
|
|
1820
1854
|
}
|
|
@@ -1828,7 +1862,7 @@ function applyLightValues(lightComponent) {
|
|
|
1828
1862
|
light.penumbra = Math.max(0, Math.min(1, values.penumbra));
|
|
1829
1863
|
}
|
|
1830
1864
|
}
|
|
1831
|
-
if (light instanceof
|
|
1865
|
+
if (light instanceof THREE19.RectAreaLight) {
|
|
1832
1866
|
if (typeof values.width === "number" && Number.isFinite(values.width)) {
|
|
1833
1867
|
light.width = Math.max(MIN_AREA_SIZE, values.width);
|
|
1834
1868
|
}
|
|
@@ -1889,15 +1923,15 @@ function resolveMaterialPropertyKey(key) {
|
|
|
1889
1923
|
__name(resolveMaterialPropertyKey, "resolveMaterialPropertyKey");
|
|
1890
1924
|
function createMaterialByType(type) {
|
|
1891
1925
|
if (type === "basic") {
|
|
1892
|
-
return new
|
|
1926
|
+
return new THREE19.MeshBasicMaterial();
|
|
1893
1927
|
}
|
|
1894
1928
|
if (type === "phong") {
|
|
1895
|
-
return new
|
|
1929
|
+
return new THREE19.MeshPhongMaterial();
|
|
1896
1930
|
}
|
|
1897
1931
|
if (type === "physical") {
|
|
1898
|
-
return new
|
|
1932
|
+
return new THREE19.MeshPhysicalMaterial();
|
|
1899
1933
|
}
|
|
1900
|
-
return new
|
|
1934
|
+
return new THREE19.MeshStandardMaterial();
|
|
1901
1935
|
}
|
|
1902
1936
|
__name(createMaterialByType, "createMaterialByType");
|
|
1903
1937
|
function replaceMaterialAcrossObject(object, previous, next) {
|
|
@@ -1956,12 +1990,12 @@ function applyTextureFiltering(material, filtering) {
|
|
|
1956
1990
|
const target = material;
|
|
1957
1991
|
for (const slot of materialTextureSlots) {
|
|
1958
1992
|
const texture = target[slot];
|
|
1959
|
-
if (!texture || !(texture instanceof
|
|
1993
|
+
if (!texture || !(texture instanceof THREE19.Texture)) {
|
|
1960
1994
|
continue;
|
|
1961
1995
|
}
|
|
1962
1996
|
const useMipmaps = texture.generateMipmaps !== false;
|
|
1963
|
-
texture.magFilter = sharp ?
|
|
1964
|
-
texture.minFilter = useMipmaps ? sharp ?
|
|
1997
|
+
texture.magFilter = sharp ? THREE19.NearestFilter : THREE19.LinearFilter;
|
|
1998
|
+
texture.minFilter = useMipmaps ? sharp ? THREE19.NearestMipmapNearestFilter : THREE19.LinearMipmapLinearFilter : sharp ? THREE19.NearestFilter : THREE19.LinearFilter;
|
|
1965
1999
|
texture.needsUpdate = true;
|
|
1966
2000
|
}
|
|
1967
2001
|
material.needsUpdate = true;
|
|
@@ -1971,12 +2005,12 @@ function setTextureMipmaps(material, enabled) {
|
|
|
1971
2005
|
const target = material;
|
|
1972
2006
|
for (const slot of materialTextureSlots) {
|
|
1973
2007
|
const texture = target[slot];
|
|
1974
|
-
if (!texture || !(texture instanceof
|
|
2008
|
+
if (!texture || !(texture instanceof THREE19.Texture)) {
|
|
1975
2009
|
continue;
|
|
1976
2010
|
}
|
|
1977
2011
|
texture.generateMipmaps = enabled;
|
|
1978
|
-
const sharp = texture.magFilter ===
|
|
1979
|
-
texture.minFilter = enabled ? sharp ?
|
|
2012
|
+
const sharp = texture.magFilter === THREE19.NearestFilter;
|
|
2013
|
+
texture.minFilter = enabled ? sharp ? THREE19.NearestMipmapNearestFilter : THREE19.LinearMipmapLinearFilter : sharp ? THREE19.NearestFilter : THREE19.LinearFilter;
|
|
1980
2014
|
texture.needsUpdate = true;
|
|
1981
2015
|
}
|
|
1982
2016
|
material.needsUpdate = true;
|
|
@@ -1987,7 +2021,7 @@ function assignMaterialTexture(material, rawKey, url, textureCache) {
|
|
|
1987
2021
|
const key = resolveMaterialPropertyKey(rawKey);
|
|
1988
2022
|
let texture = textureCache.get(url);
|
|
1989
2023
|
if (!texture) {
|
|
1990
|
-
texture = new
|
|
2024
|
+
texture = new THREE19.TextureLoader().load(url);
|
|
1991
2025
|
textureCache.set(url, texture);
|
|
1992
2026
|
}
|
|
1993
2027
|
target[key] = texture;
|
|
@@ -2025,7 +2059,7 @@ function applyMaterialState(material, value, textureCache) {
|
|
|
2025
2059
|
}
|
|
2026
2060
|
target.side = value.side;
|
|
2027
2061
|
target.blending = value.blending;
|
|
2028
|
-
target.premultipliedAlpha = value.blending ===
|
|
2062
|
+
target.premultipliedAlpha = value.blending === THREE19.MultiplyBlending || value.blending === THREE19.SubtractiveBlending;
|
|
2029
2063
|
target.depthTest = value.depthTest;
|
|
2030
2064
|
target.depthWrite = value.depthWrite;
|
|
2031
2065
|
target.wireframe = value.wireframe;
|
|
@@ -2186,12 +2220,12 @@ function resolvePrimaryMesh(object) {
|
|
|
2186
2220
|
if (!object) {
|
|
2187
2221
|
return null;
|
|
2188
2222
|
}
|
|
2189
|
-
if (object instanceof
|
|
2223
|
+
if (object instanceof THREE19.Mesh) {
|
|
2190
2224
|
return object;
|
|
2191
2225
|
}
|
|
2192
2226
|
let found = null;
|
|
2193
2227
|
object.traverse((child) => {
|
|
2194
|
-
if (!found && child instanceof
|
|
2228
|
+
if (!found && child instanceof THREE19.Mesh) {
|
|
2195
2229
|
found = child;
|
|
2196
2230
|
}
|
|
2197
2231
|
});
|
|
@@ -2212,22 +2246,22 @@ function applyGeometry(component) {
|
|
|
2212
2246
|
switch (component.kind) {
|
|
2213
2247
|
case "cube": {
|
|
2214
2248
|
const params = sanitized;
|
|
2215
|
-
nextGeometry = new
|
|
2249
|
+
nextGeometry = new THREE19.BoxGeometry(params.width, params.height, params.depth);
|
|
2216
2250
|
break;
|
|
2217
2251
|
}
|
|
2218
2252
|
case "plane": {
|
|
2219
2253
|
const params = sanitized;
|
|
2220
|
-
nextGeometry = new
|
|
2254
|
+
nextGeometry = new THREE19.PlaneGeometry(params.width, params.height);
|
|
2221
2255
|
break;
|
|
2222
2256
|
}
|
|
2223
2257
|
case "sphere": {
|
|
2224
2258
|
const params = sanitized;
|
|
2225
|
-
nextGeometry = new
|
|
2259
|
+
nextGeometry = new THREE19.SphereGeometry(params.radius, 24, 24);
|
|
2226
2260
|
break;
|
|
2227
2261
|
}
|
|
2228
2262
|
case "cylinder": {
|
|
2229
2263
|
const params = sanitized;
|
|
2230
|
-
nextGeometry = new
|
|
2264
|
+
nextGeometry = new THREE19.CylinderGeometry(
|
|
2231
2265
|
params.radius,
|
|
2232
2266
|
params.radius,
|
|
2233
2267
|
params.height,
|
|
@@ -2237,7 +2271,7 @@ function applyGeometry(component) {
|
|
|
2237
2271
|
}
|
|
2238
2272
|
case "capsule": {
|
|
2239
2273
|
const params = sanitized;
|
|
2240
|
-
nextGeometry = new
|
|
2274
|
+
nextGeometry = new THREE19.CapsuleGeometry(params.radius, params.height, 4, 8);
|
|
2241
2275
|
break;
|
|
2242
2276
|
}
|
|
2243
2277
|
default:
|
|
@@ -2253,7 +2287,7 @@ function applyShadowFlags(component) {
|
|
|
2253
2287
|
return;
|
|
2254
2288
|
}
|
|
2255
2289
|
component.object.traverse((child) => {
|
|
2256
|
-
if (child instanceof
|
|
2290
|
+
if (child instanceof THREE19.Mesh) {
|
|
2257
2291
|
child.castShadow = component.castShadow;
|
|
2258
2292
|
child.receiveShadow = component.receiveShadow;
|
|
2259
2293
|
}
|
|
@@ -2336,35 +2370,35 @@ function buildGeometry(component) {
|
|
|
2336
2370
|
switch (component.meshKind) {
|
|
2337
2371
|
case "cube": {
|
|
2338
2372
|
const params = p;
|
|
2339
|
-
return new
|
|
2373
|
+
return new THREE19.BoxGeometry(params.width, params.height, params.depth);
|
|
2340
2374
|
}
|
|
2341
2375
|
case "plane": {
|
|
2342
2376
|
const params = p;
|
|
2343
|
-
return new
|
|
2377
|
+
return new THREE19.PlaneGeometry(params.width, params.height);
|
|
2344
2378
|
}
|
|
2345
2379
|
case "sphere": {
|
|
2346
2380
|
const params = p;
|
|
2347
|
-
return new
|
|
2381
|
+
return new THREE19.SphereGeometry(params.radius, 24, 24);
|
|
2348
2382
|
}
|
|
2349
2383
|
case "cylinder": {
|
|
2350
2384
|
const params = p;
|
|
2351
|
-
return new
|
|
2385
|
+
return new THREE19.CylinderGeometry(params.radius, params.radius, params.height, 20);
|
|
2352
2386
|
}
|
|
2353
2387
|
case "capsule": {
|
|
2354
2388
|
const params = p;
|
|
2355
|
-
return new
|
|
2389
|
+
return new THREE19.CapsuleGeometry(params.radius, params.height, 4, 8);
|
|
2356
2390
|
}
|
|
2357
2391
|
default:
|
|
2358
|
-
return new
|
|
2392
|
+
return new THREE19.BoxGeometry(1, 1, 1);
|
|
2359
2393
|
}
|
|
2360
2394
|
}
|
|
2361
2395
|
__name(buildGeometry, "buildGeometry");
|
|
2362
|
-
var _position = new
|
|
2363
|
-
var _quaternion = new
|
|
2364
|
-
var _euler = new
|
|
2365
|
-
var _scale = new
|
|
2366
|
-
var _matrix = new
|
|
2367
|
-
var _modelMatrix = new
|
|
2396
|
+
var _position = new THREE19.Vector3();
|
|
2397
|
+
var _quaternion = new THREE19.Quaternion();
|
|
2398
|
+
var _euler = new THREE19.Euler();
|
|
2399
|
+
var _scale = new THREE19.Vector3();
|
|
2400
|
+
var _matrix = new THREE19.Matrix4();
|
|
2401
|
+
var _modelMatrix = new THREE19.Matrix4();
|
|
2368
2402
|
function instanceTransformFromComponent(transform, out) {
|
|
2369
2403
|
_position.set(transform.position.x, transform.position.y, transform.position.z);
|
|
2370
2404
|
_euler.set(transform.rotation.x, transform.rotation.y, transform.rotation.z, "XYZ");
|
|
@@ -2517,7 +2551,7 @@ var _InstancedMeshSystem = class _InstancedMeshSystem {
|
|
|
2517
2551
|
const sourceMaterial = Array.isArray(meshChild.material) ? meshChild.material.map((m) => m.clone()) : meshChild.material.clone();
|
|
2518
2552
|
meshChild.updateWorldMatrix(true, false);
|
|
2519
2553
|
const localMatrix = meshChild.matrixWorld.clone();
|
|
2520
|
-
const instancedMesh2 = new
|
|
2554
|
+
const instancedMesh2 = new THREE19.InstancedMesh(
|
|
2521
2555
|
geometry2,
|
|
2522
2556
|
Array.isArray(sourceMaterial) ? sourceMaterial : sourceMaterial,
|
|
2523
2557
|
count2
|
|
@@ -2542,7 +2576,7 @@ var _InstancedMeshSystem = class _InstancedMeshSystem {
|
|
|
2542
2576
|
this.loadingSignatures.delete(targetEntityId);
|
|
2543
2577
|
return;
|
|
2544
2578
|
}
|
|
2545
|
-
const group = new
|
|
2579
|
+
const group = new THREE19.Group();
|
|
2546
2580
|
for (const entry of entries) {
|
|
2547
2581
|
group.add(entry.instancedMesh);
|
|
2548
2582
|
}
|
|
@@ -2560,8 +2594,8 @@ var _InstancedMeshSystem = class _InstancedMeshSystem {
|
|
|
2560
2594
|
}
|
|
2561
2595
|
const count = instanceCount;
|
|
2562
2596
|
const geometry = buildGeometry(comp);
|
|
2563
|
-
const material = new
|
|
2564
|
-
const instancedMesh = new
|
|
2597
|
+
const material = new THREE19.MeshStandardMaterial({ color: "#ffffff" });
|
|
2598
|
+
const instancedMesh = new THREE19.InstancedMesh(geometry, material, count);
|
|
2565
2599
|
instancedMesh.castShadow = comp.castShadow;
|
|
2566
2600
|
instancedMesh.receiveShadow = comp.receiveShadow;
|
|
2567
2601
|
for (let i = 0; i < count; i++) {
|
|
@@ -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
|
}
|
|
@@ -2996,6 +3027,30 @@ function restorePostCreateComponents(world, objectManagementSystem, targetEntity
|
|
|
2996
3027
|
if (typeof sourceInteractable.grabRadius === "number") {
|
|
2997
3028
|
interactable.grabRadius = sourceInteractable.grabRadius;
|
|
2998
3029
|
}
|
|
3030
|
+
if (typeof sourceInteractable.grabHands === "string") {
|
|
3031
|
+
interactable.grabHands = sourceInteractable.grabHands;
|
|
3032
|
+
}
|
|
3033
|
+
if (typeof sourceInteractable.twoHandRotation === "string") {
|
|
3034
|
+
interactable.twoHandRotation = sourceInteractable.twoHandRotation;
|
|
3035
|
+
}
|
|
3036
|
+
if (typeof sourceInteractable.allowTwoHandScale === "boolean") {
|
|
3037
|
+
interactable.allowTwoHandScale = sourceInteractable.allowTwoHandScale;
|
|
3038
|
+
}
|
|
3039
|
+
if (typeof sourceInteractable.minScale === "number") {
|
|
3040
|
+
interactable.minScale = sourceInteractable.minScale;
|
|
3041
|
+
}
|
|
3042
|
+
if (typeof sourceInteractable.maxScale === "number") {
|
|
3043
|
+
interactable.maxScale = sourceInteractable.maxScale;
|
|
3044
|
+
}
|
|
3045
|
+
if (Array.isArray(sourceInteractable.attachPoints)) {
|
|
3046
|
+
interactable.attachPoints = sourceInteractable.attachPoints.map((point) => asRecord(point)).filter(
|
|
3047
|
+
(point) => point !== null && typeof point.id === "string"
|
|
3048
|
+
).map(
|
|
3049
|
+
(point) => createAttachPoint(
|
|
3050
|
+
point
|
|
3051
|
+
)
|
|
3052
|
+
);
|
|
3053
|
+
}
|
|
2999
3054
|
if (typeof sourceInteractable.throwOnRelease === "boolean") {
|
|
3000
3055
|
interactable.throwOnRelease = sourceInteractable.throwOnRelease;
|
|
3001
3056
|
}
|
|
@@ -3018,8 +3073,16 @@ function restorePostCreateComponents(world, objectManagementSystem, targetEntity
|
|
|
3018
3073
|
z: typeof grabRot.z === "number" ? grabRot.z : 0
|
|
3019
3074
|
};
|
|
3020
3075
|
}
|
|
3021
|
-
if (typeof sourceInteractable.
|
|
3022
|
-
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;
|
|
3023
3086
|
}
|
|
3024
3087
|
}
|
|
3025
3088
|
}
|
|
@@ -4747,7 +4810,7 @@ var _Behaviour = class _Behaviour {
|
|
|
4747
4810
|
if (!this.threeRef) {
|
|
4748
4811
|
return null;
|
|
4749
4812
|
}
|
|
4750
|
-
const position = new
|
|
4813
|
+
const position = new THREE19.Vector3();
|
|
4751
4814
|
this.threeRef.object.getWorldPosition(position);
|
|
4752
4815
|
return position;
|
|
4753
4816
|
}
|
|
@@ -4759,7 +4822,7 @@ var _Behaviour = class _Behaviour {
|
|
|
4759
4822
|
if (!this.threeRef) {
|
|
4760
4823
|
return null;
|
|
4761
4824
|
}
|
|
4762
|
-
const target = new
|
|
4825
|
+
const target = new THREE19.Vector3();
|
|
4763
4826
|
this.threeRef.object.getWorldDirection(target);
|
|
4764
4827
|
return target;
|
|
4765
4828
|
}
|
|
@@ -4821,7 +4884,7 @@ var _Behaviour = class _Behaviour {
|
|
|
4821
4884
|
if (!this.threeRef) {
|
|
4822
4885
|
return;
|
|
4823
4886
|
}
|
|
4824
|
-
const rotation = new
|
|
4887
|
+
const rotation = new THREE19.Quaternion();
|
|
4825
4888
|
this.threeRef.object.getWorldQuaternion(rotation);
|
|
4826
4889
|
rotation.slerp(targetRotation, alpha);
|
|
4827
4890
|
this.transform.setRotation(rotation);
|
|
@@ -4838,7 +4901,7 @@ var _Behaviour = class _Behaviour {
|
|
|
4838
4901
|
return;
|
|
4839
4902
|
}
|
|
4840
4903
|
const clone2 = this.threeRef.object.clone();
|
|
4841
|
-
const rotation = new
|
|
4904
|
+
const rotation = new THREE19.Quaternion();
|
|
4842
4905
|
clone2.lookAt(targetPosition);
|
|
4843
4906
|
clone2.getWorldQuaternion(rotation);
|
|
4844
4907
|
this.transform.setRotation(rotation);
|
|
@@ -4976,6 +5039,17 @@ var _Behaviour = class _Behaviour {
|
|
|
4976
5039
|
*
|
|
4977
5040
|
* @param input - The source doing the grabbing.
|
|
4978
5041
|
*/
|
|
5042
|
+
/**
|
|
5043
|
+
* A SECOND hand joined a two-hand grab on this entity.
|
|
5044
|
+
*
|
|
5045
|
+
* The first hand anchors the object and keeps holding it; this fires for the
|
|
5046
|
+
* hand that came second — the foregrip on a rifle, say.
|
|
5047
|
+
*/
|
|
5048
|
+
onSecondaryGrab(_input) {
|
|
5049
|
+
}
|
|
5050
|
+
/** The second hand let go, leaving the object in the first hand alone. */
|
|
5051
|
+
onSecondaryRelease(_input) {
|
|
5052
|
+
}
|
|
4979
5053
|
/**
|
|
4980
5054
|
* A hand pose declared on this entity started being held.
|
|
4981
5055
|
*
|
|
@@ -5193,8 +5267,8 @@ var _ScriptBehaviourSystem = class _ScriptBehaviourSystem {
|
|
|
5193
5267
|
}, "onPointerUp");
|
|
5194
5268
|
this.moduleLoader = moduleLoader ?? defaultModuleLoader;
|
|
5195
5269
|
this.selectionCtx = selectionContext ?? null;
|
|
5196
|
-
this.raycaster = new
|
|
5197
|
-
this.ndcPointer = new
|
|
5270
|
+
this.raycaster = new THREE19.Raycaster();
|
|
5271
|
+
this.ndcPointer = new THREE19.Vector2();
|
|
5198
5272
|
if (this.selectionCtx) {
|
|
5199
5273
|
this.selectionCtx.domElement.addEventListener("pointerdown", this.onPointerDown);
|
|
5200
5274
|
this.selectionCtx.domElement.addEventListener("pointerup", this.onPointerUp);
|
|
@@ -5573,7 +5647,7 @@ function disposeBuiltObject(root) {
|
|
|
5573
5647
|
for (const mat of materials) {
|
|
5574
5648
|
if (mat.userData?.[SHARED_MODEL_RESOURCE_FLAG]) continue;
|
|
5575
5649
|
for (const value of Object.values(mat)) {
|
|
5576
|
-
if (value instanceof
|
|
5650
|
+
if (value instanceof THREE19.Texture) value.dispose();
|
|
5577
5651
|
}
|
|
5578
5652
|
mat.dispose?.();
|
|
5579
5653
|
}
|
|
@@ -5937,7 +6011,7 @@ var _AudioSystem = class _AudioSystem {
|
|
|
5937
6011
|
if (!prev || prev.volume !== opts.volume) {
|
|
5938
6012
|
sound.setVolume(opts.volume);
|
|
5939
6013
|
}
|
|
5940
|
-
if (opts.positional && sound instanceof
|
|
6014
|
+
if (opts.positional && sound instanceof THREE19.PositionalAudio) {
|
|
5941
6015
|
if (!prev || prev.refDistance !== opts.refDistance) {
|
|
5942
6016
|
sound.setRefDistance(opts.refDistance);
|
|
5943
6017
|
}
|
|
@@ -6063,7 +6137,7 @@ var _VideoSystem = class _VideoSystem {
|
|
|
6063
6137
|
component.object.scale.set(opts.width, opts.height, 1);
|
|
6064
6138
|
}
|
|
6065
6139
|
const material = component.material;
|
|
6066
|
-
if (material instanceof
|
|
6140
|
+
if (material instanceof THREE19.ShaderMaterial) {
|
|
6067
6141
|
if (!prev || prev.backgroundColor !== opts.backgroundColor) {
|
|
6068
6142
|
material.uniforms.keyColor.value.set(opts.backgroundColor);
|
|
6069
6143
|
}
|
|
@@ -6077,7 +6151,7 @@ var _VideoSystem = class _VideoSystem {
|
|
|
6077
6151
|
material.uniforms.spill.value = opts.spill;
|
|
6078
6152
|
}
|
|
6079
6153
|
}
|
|
6080
|
-
if (opts.positional && component.audioNode instanceof
|
|
6154
|
+
if (opts.positional && component.audioNode instanceof THREE19.PositionalAudio) {
|
|
6081
6155
|
const posAudio = component.audioNode;
|
|
6082
6156
|
if (!prev || prev.refDistance !== opts.refDistance) {
|
|
6083
6157
|
posAudio.setRefDistance(opts.refDistance);
|
|
@@ -6117,8 +6191,8 @@ function blankState(source) {
|
|
|
6117
6191
|
handedness: handednessOf(source),
|
|
6118
6192
|
kind: kindOf(source),
|
|
6119
6193
|
connected: true,
|
|
6120
|
-
rayOrigin: new
|
|
6121
|
-
rayDirection: new
|
|
6194
|
+
rayOrigin: new THREE19.Vector3(),
|
|
6195
|
+
rayDirection: new THREE19.Vector3(0, 0, -1),
|
|
6122
6196
|
gripPosition: null,
|
|
6123
6197
|
gripQuaternion: null,
|
|
6124
6198
|
select: false,
|
|
@@ -6144,7 +6218,7 @@ function readHandJoints(frame, hand, referenceSpace, rigMatrix, existing) {
|
|
|
6144
6218
|
}
|
|
6145
6219
|
if (spaces.length === 0) return null;
|
|
6146
6220
|
const target = existing ?? {};
|
|
6147
|
-
const matrix = new
|
|
6221
|
+
const matrix = new THREE19.Matrix4();
|
|
6148
6222
|
const buffer = spaces.length * 16 <= JOINT_MATRIX_BUFFER.length ? JOINT_MATRIX_BUFFER : new Float32Array(spaces.length * 16);
|
|
6149
6223
|
const fillPoses = frame.fillPoses;
|
|
6150
6224
|
if (typeof fillPoses === "function") {
|
|
@@ -6157,7 +6231,7 @@ function readHandJoints(frame, hand, referenceSpace, rigMatrix, existing) {
|
|
|
6157
6231
|
if (filled) {
|
|
6158
6232
|
for (let i = 0; i < names.length; i += 1) {
|
|
6159
6233
|
matrix.fromArray(buffer, i * 16).premultiply(rigMatrix);
|
|
6160
|
-
const vector = target[names[i]] ?? new
|
|
6234
|
+
const vector = target[names[i]] ?? new THREE19.Vector3();
|
|
6161
6235
|
vector.setFromMatrixPosition(matrix);
|
|
6162
6236
|
target[names[i]] = vector;
|
|
6163
6237
|
}
|
|
@@ -6175,7 +6249,7 @@ function readHandJoints(frame, hand, referenceSpace, rigMatrix, existing) {
|
|
|
6175
6249
|
continue;
|
|
6176
6250
|
}
|
|
6177
6251
|
matrix.fromArray(pose.transform.matrix).premultiply(rigMatrix);
|
|
6178
|
-
const vector = target[names[i]] ?? new
|
|
6252
|
+
const vector = target[names[i]] ?? new THREE19.Vector3();
|
|
6179
6253
|
vector.setFromMatrixPosition(matrix);
|
|
6180
6254
|
target[names[i]] = vector;
|
|
6181
6255
|
anyTracked = true;
|
|
@@ -6187,7 +6261,7 @@ var _XRInputSystem = class _XRInputSystem {
|
|
|
6187
6261
|
constructor() {
|
|
6188
6262
|
this.records = /* @__PURE__ */ new Map();
|
|
6189
6263
|
/** Reference-space → world matrix, rebuilt each frame from the XR rig. */
|
|
6190
|
-
this.referenceToWorld = new
|
|
6264
|
+
this.referenceToWorld = new THREE19.Matrix4();
|
|
6191
6265
|
this.session = null;
|
|
6192
6266
|
this.onSelectStart = /* @__PURE__ */ __name((event) => this.mark(event, "pendingSelectStart"), "onSelectStart");
|
|
6193
6267
|
this.onSelectEnd = /* @__PURE__ */ __name((event) => this.mark(event, "pendingSelectEnd"), "onSelectEnd");
|
|
@@ -6285,19 +6359,19 @@ var _XRInputSystem = class _XRInputSystem {
|
|
|
6285
6359
|
if (frame && referenceSpace && source.targetRaySpace) {
|
|
6286
6360
|
const pose = frame.getPose(source.targetRaySpace, referenceSpace);
|
|
6287
6361
|
if (pose) {
|
|
6288
|
-
const m = new
|
|
6362
|
+
const m = new THREE19.Matrix4().fromArray(pose.transform.matrix).premultiply(rigMatrix);
|
|
6289
6363
|
state.rayOrigin.setFromMatrixPosition(m);
|
|
6290
6364
|
state.rayDirection.set(0, 0, -1).applyQuaternion(
|
|
6291
|
-
new
|
|
6365
|
+
new THREE19.Quaternion().setFromRotationMatrix(m)
|
|
6292
6366
|
).normalize();
|
|
6293
6367
|
}
|
|
6294
6368
|
}
|
|
6295
6369
|
if (frame && referenceSpace && source.gripSpace) {
|
|
6296
6370
|
const gripPose = frame.getPose(source.gripSpace, referenceSpace);
|
|
6297
6371
|
if (gripPose) {
|
|
6298
|
-
const m = new
|
|
6299
|
-
state.gripPosition ?? (state.gripPosition = new
|
|
6300
|
-
state.gripQuaternion ?? (state.gripQuaternion = new
|
|
6372
|
+
const m = new THREE19.Matrix4().fromArray(gripPose.transform.matrix).premultiply(rigMatrix);
|
|
6373
|
+
state.gripPosition ?? (state.gripPosition = new THREE19.Vector3());
|
|
6374
|
+
state.gripQuaternion ?? (state.gripQuaternion = new THREE19.Quaternion());
|
|
6301
6375
|
state.gripPosition.setFromMatrixPosition(m);
|
|
6302
6376
|
state.gripQuaternion.setFromRotationMatrix(m);
|
|
6303
6377
|
}
|
|
@@ -6406,15 +6480,15 @@ var _ThrowVelocityTracker = class _ThrowVelocityTracker {
|
|
|
6406
6480
|
const fresh = this.samples.filter(
|
|
6407
6481
|
(sample) => now - sample.time <= MAX_SAMPLE_AGE_SECONDS
|
|
6408
6482
|
);
|
|
6409
|
-
if (fresh.length < 2) return new
|
|
6410
|
-
let best = new
|
|
6483
|
+
if (fresh.length < 2) return new THREE19.Vector3();
|
|
6484
|
+
let best = new THREE19.Vector3();
|
|
6411
6485
|
let bestSpeed = 0;
|
|
6412
6486
|
for (let i = 1; i < fresh.length; i += 1) {
|
|
6413
6487
|
const previous = fresh[i - 1];
|
|
6414
6488
|
const current = fresh[i];
|
|
6415
6489
|
const dt = current.time - previous.time;
|
|
6416
6490
|
if (dt <= 1e-5) continue;
|
|
6417
|
-
const velocity = new
|
|
6491
|
+
const velocity = new THREE19.Vector3().subVectors(current.position, previous.position).divideScalar(dt);
|
|
6418
6492
|
const speed = velocity.length();
|
|
6419
6493
|
if (speed > MAX_PLAUSIBLE_SPEED) continue;
|
|
6420
6494
|
if (speed > bestSpeed) {
|
|
@@ -6431,25 +6505,79 @@ var _ThrowVelocityTracker = class _ThrowVelocityTracker {
|
|
|
6431
6505
|
__name(_ThrowVelocityTracker, "ThrowVelocityTracker");
|
|
6432
6506
|
var ThrowVelocityTracker = _ThrowVelocityTracker;
|
|
6433
6507
|
function angularVelocityFrom(previous, current, deltaTime) {
|
|
6434
|
-
if (deltaTime <= 1e-5) return new
|
|
6508
|
+
if (deltaTime <= 1e-5) return new THREE19.Vector3();
|
|
6435
6509
|
const delta = current.clone().multiply(previous.clone().invert());
|
|
6436
6510
|
if (delta.w < 0) {
|
|
6437
6511
|
delta.set(-delta.x, -delta.y, -delta.z, -delta.w);
|
|
6438
6512
|
}
|
|
6439
|
-
const angle = 2 * Math.acos(
|
|
6513
|
+
const angle = 2 * Math.acos(THREE19.MathUtils.clamp(delta.w, -1, 1));
|
|
6440
6514
|
const sinHalf = Math.sqrt(Math.max(0, 1 - delta.w * delta.w));
|
|
6441
|
-
if (sinHalf < 1e-6 || angle < 1e-6) return new
|
|
6442
|
-
return new
|
|
6515
|
+
if (sinHalf < 1e-6 || angle < 1e-6) return new THREE19.Vector3();
|
|
6516
|
+
return new THREE19.Vector3(delta.x, delta.y, delta.z).divideScalar(sinHalf).multiplyScalar(angle / deltaTime);
|
|
6443
6517
|
}
|
|
6444
6518
|
__name(angularVelocityFrom, "angularVelocityFrom");
|
|
6519
|
+
var MIN_HAND_SEPARATION = 0.06;
|
|
6520
|
+
var MIN_ANCHOR_SEPARATION = 1e-3;
|
|
6521
|
+
var SCALE_DEADZONE = 0.05;
|
|
6522
|
+
function solveTwoHandTransform(primary, secondary, basis, options) {
|
|
6523
|
+
const separation = primary.position.distanceTo(secondary.position);
|
|
6524
|
+
const anchorDelta = new THREE19.Vector3().subVectors(
|
|
6525
|
+
basis.secondaryLocal,
|
|
6526
|
+
basis.primaryLocal
|
|
6527
|
+
);
|
|
6528
|
+
const anchorLength = anchorDelta.length();
|
|
6529
|
+
let factor = 1;
|
|
6530
|
+
if (options.allowScale && basis.initialSeparation > MIN_ANCHOR_SEPARATION && separation > MIN_ANCHOR_SEPARATION) {
|
|
6531
|
+
factor = separation / basis.initialSeparation;
|
|
6532
|
+
if (Math.abs(factor - 1) <= SCALE_DEADZONE) {
|
|
6533
|
+
factor = 1;
|
|
6534
|
+
} else {
|
|
6535
|
+
factor += factor > 1 ? -SCALE_DEADZONE : SCALE_DEADZONE;
|
|
6536
|
+
}
|
|
6537
|
+
factor = Math.min(options.maxScale, Math.max(options.minScale, factor));
|
|
6538
|
+
}
|
|
6539
|
+
const scale = basis.initialScale.clone().multiplyScalar(factor);
|
|
6540
|
+
const degenerate = separation < MIN_HAND_SEPARATION || anchorLength < MIN_ANCHOR_SEPARATION;
|
|
6541
|
+
const base = primary.quaternion.clone().multiply(basis.primaryHandOffset);
|
|
6542
|
+
let quaternion;
|
|
6543
|
+
if (options.rotationMode === "primary" || degenerate) {
|
|
6544
|
+
quaternion = base;
|
|
6545
|
+
} else {
|
|
6546
|
+
const axisLocal = anchorDelta.clone().normalize();
|
|
6547
|
+
const currentAxis = axisLocal.clone().applyQuaternion(base).normalize();
|
|
6548
|
+
const desiredAxis = new THREE19.Vector3().subVectors(secondary.position, primary.position).normalize();
|
|
6549
|
+
const correction = new THREE19.Quaternion().setFromUnitVectors(
|
|
6550
|
+
currentAxis,
|
|
6551
|
+
desiredAxis
|
|
6552
|
+
);
|
|
6553
|
+
quaternion = correction.multiply(base);
|
|
6554
|
+
}
|
|
6555
|
+
const anchorOffset = basis.primaryLocal.clone().multiply(scale).applyQuaternion(quaternion);
|
|
6556
|
+
const position = primary.position.clone().sub(anchorOffset);
|
|
6557
|
+
return { position, quaternion, scale, degenerate };
|
|
6558
|
+
}
|
|
6559
|
+
__name(solveTwoHandTransform, "solveTwoHandTransform");
|
|
6445
6560
|
|
|
6446
6561
|
// core/systems/XRInteractionSystem.ts
|
|
6447
6562
|
var RAYLESS_HOLD_DISTANCE = 0.5;
|
|
6563
|
+
function quatFromEulerVec(r) {
|
|
6564
|
+
return new THREE19.Quaternion().setFromEuler(new THREE19.Euler(r.x, r.y, r.z));
|
|
6565
|
+
}
|
|
6566
|
+
__name(quatFromEulerVec, "quatFromEulerVec");
|
|
6567
|
+
function writeEuler(target, q) {
|
|
6568
|
+
const euler = new THREE19.Euler().setFromQuaternion(q);
|
|
6569
|
+
target.x = euler.x;
|
|
6570
|
+
target.y = euler.y;
|
|
6571
|
+
target.z = euler.z;
|
|
6572
|
+
}
|
|
6573
|
+
__name(writeEuler, "writeEuler");
|
|
6448
6574
|
var _XRInteractionSystem = class _XRInteractionSystem {
|
|
6449
6575
|
constructor(inputSystem) {
|
|
6450
|
-
this.raycaster = new
|
|
6576
|
+
this.raycaster = new THREE19.Raycaster();
|
|
6451
6577
|
this.grabs = /* @__PURE__ */ new Map();
|
|
6452
6578
|
this.hoveredEntityId = null;
|
|
6579
|
+
/** Per-hand hover, with the hit distance so the ray can stop at the surface. */
|
|
6580
|
+
this.hovers = /* @__PURE__ */ new Map();
|
|
6453
6581
|
/** Monotonic seconds, accumulated from deltaTime for velocity sampling. */
|
|
6454
6582
|
this.elapsed = 0;
|
|
6455
6583
|
this.inputSystem = inputSystem;
|
|
@@ -6463,6 +6591,7 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6463
6591
|
const inputs = this.inputSystem.getInputs();
|
|
6464
6592
|
const interactables = this.collectInteractables(world);
|
|
6465
6593
|
this.hoveredEntityId = null;
|
|
6594
|
+
this.hovers.clear();
|
|
6466
6595
|
for (const input of inputs) {
|
|
6467
6596
|
if (!input.connected) {
|
|
6468
6597
|
this.release(world, input);
|
|
@@ -6470,7 +6599,6 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6470
6599
|
}
|
|
6471
6600
|
const held = this.grabs.get(input);
|
|
6472
6601
|
if (held) {
|
|
6473
|
-
this.moveHeld(world, input, held, deltaTime);
|
|
6474
6602
|
if (this.wantsRelease(world, input, held)) {
|
|
6475
6603
|
this.release(world, input);
|
|
6476
6604
|
}
|
|
@@ -6481,6 +6609,10 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6481
6609
|
if (this.hoveredEntityId === null) {
|
|
6482
6610
|
this.hoveredEntityId = candidate.entityId;
|
|
6483
6611
|
}
|
|
6612
|
+
this.hovers.set(input, {
|
|
6613
|
+
entityId: candidate.entityId,
|
|
6614
|
+
distance: candidate.distance
|
|
6615
|
+
});
|
|
6484
6616
|
const interactable = world.getComponent(
|
|
6485
6617
|
candidate.entityId,
|
|
6486
6618
|
XRInteractableComponent
|
|
@@ -6491,9 +6623,122 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6491
6623
|
/* starting */
|
|
6492
6624
|
true
|
|
6493
6625
|
)) {
|
|
6494
|
-
this.
|
|
6626
|
+
this.tryGrab(world, input, candidate.entityId, candidate.viaDistance);
|
|
6495
6627
|
}
|
|
6496
6628
|
}
|
|
6629
|
+
this.moveAllHeld(world, deltaTime);
|
|
6630
|
+
}
|
|
6631
|
+
/** Hands currently holding an entity. */
|
|
6632
|
+
holdersOf(entityId) {
|
|
6633
|
+
const holders = [];
|
|
6634
|
+
for (const [input, record] of this.grabs) {
|
|
6635
|
+
if (record.entityId === entityId) holders.push({ input, record });
|
|
6636
|
+
}
|
|
6637
|
+
return holders;
|
|
6638
|
+
}
|
|
6639
|
+
/**
|
|
6640
|
+
* Route a new grab: first hand, hand-off, or second hand.
|
|
6641
|
+
*
|
|
6642
|
+
* Which of those happens is the object's choice (`grabHands`), not the
|
|
6643
|
+
* hand's — a ball should pass between hands, a rifle should be held by both,
|
|
6644
|
+
* and a lever should stay with whoever grabbed it first.
|
|
6645
|
+
*/
|
|
6646
|
+
tryGrab(world, input, entityId, viaDistance) {
|
|
6647
|
+
const interactable = world.getComponent(entityId, XRInteractableComponent);
|
|
6648
|
+
if (!interactable) return;
|
|
6649
|
+
const holders = this.holdersOf(entityId);
|
|
6650
|
+
if (holders.length === 0) {
|
|
6651
|
+
this.grab(world, input, entityId, viaDistance, "primary");
|
|
6652
|
+
return;
|
|
6653
|
+
}
|
|
6654
|
+
if (holders.some((holder) => holder.input === input)) return;
|
|
6655
|
+
if (interactable.grabHands === "single") return;
|
|
6656
|
+
if (interactable.grabHands === "handOff") {
|
|
6657
|
+
const previous = holders[0];
|
|
6658
|
+
this.grabs.delete(previous.input);
|
|
6659
|
+
const record = previous.record;
|
|
6660
|
+
record.role = "primary";
|
|
6661
|
+
record.twoHand = null;
|
|
6662
|
+
this.reanchor(world, input, record, interactable);
|
|
6663
|
+
this.grabs.set(input, record);
|
|
6664
|
+
this.dispatch(world, entityId, (b) => b.onGrab(input));
|
|
6665
|
+
return;
|
|
6666
|
+
}
|
|
6667
|
+
if (holders.length >= 2) return;
|
|
6668
|
+
this.grab(world, input, entityId, viaDistance, "secondary");
|
|
6669
|
+
this.beginTwoHand(world, entityId);
|
|
6670
|
+
}
|
|
6671
|
+
/**
|
|
6672
|
+
* Re-derive a record's hold from where the object is NOW.
|
|
6673
|
+
*
|
|
6674
|
+
* Used on hand-off and on promotion after the primary lets go. Without it the
|
|
6675
|
+
* object snaps to whatever offset the previous hand had, which reads as the
|
|
6676
|
+
* object jumping out of your grip at the moment you take it.
|
|
6677
|
+
*/
|
|
6678
|
+
reanchor(world, input, record, interactable) {
|
|
6679
|
+
const transform = world.getComponent(record.entityId, TransformComponent);
|
|
6680
|
+
if (!transform) return;
|
|
6681
|
+
const hand = this.handPosition(input);
|
|
6682
|
+
const handQuaternion = this.handQuaternion(input);
|
|
6683
|
+
const objectQuaternion = quatFromEulerVec(transform.rotation);
|
|
6684
|
+
record.offset = new THREE19.Vector3(
|
|
6685
|
+
transform.position.x - hand.x,
|
|
6686
|
+
transform.position.y - hand.y,
|
|
6687
|
+
transform.position.z - hand.z
|
|
6688
|
+
).applyQuaternion(handQuaternion.clone().invert());
|
|
6689
|
+
record.handRotationOffset = handQuaternion.clone().invert().multiply(objectQuaternion);
|
|
6690
|
+
record.remote = false;
|
|
6691
|
+
record.tracker.clear();
|
|
6692
|
+
record.tracker.record(hand, this.elapsed);
|
|
6693
|
+
record.lastHandQuaternion = handQuaternion.clone();
|
|
6694
|
+
if (record.attachLocal && interactable.attachPoints.length === 0) {
|
|
6695
|
+
record.attachLocal = null;
|
|
6696
|
+
record.attachQuaternion = null;
|
|
6697
|
+
record.attachPointId = null;
|
|
6698
|
+
}
|
|
6699
|
+
}
|
|
6700
|
+
/** Capture the two-hand basis once both hands are on the object. */
|
|
6701
|
+
beginTwoHand(world, entityId) {
|
|
6702
|
+
const holders = this.holdersOf(entityId);
|
|
6703
|
+
if (holders.length !== 2) return;
|
|
6704
|
+
const primary = holders.find((h) => h.record.role === "primary");
|
|
6705
|
+
const secondary = holders.find((h) => h.record.role === "secondary");
|
|
6706
|
+
if (!primary || !secondary) return;
|
|
6707
|
+
const transform = world.getComponent(entityId, TransformComponent);
|
|
6708
|
+
if (!transform) return;
|
|
6709
|
+
const primaryHand = this.handPosition(primary.input);
|
|
6710
|
+
const secondaryHand = this.handPosition(secondary.input);
|
|
6711
|
+
const primaryLocal = primary.record.attachLocal?.clone() ?? this.objectLocalPoint(transform, primaryHand);
|
|
6712
|
+
const secondaryLocal = secondary.record.attachLocal?.clone() ?? this.objectLocalPoint(transform, secondaryHand);
|
|
6713
|
+
primary.record.twoHand = {
|
|
6714
|
+
primaryLocal,
|
|
6715
|
+
secondaryLocal,
|
|
6716
|
+
initialScale: new THREE19.Vector3(
|
|
6717
|
+
transform.scale.x,
|
|
6718
|
+
transform.scale.y,
|
|
6719
|
+
transform.scale.z
|
|
6720
|
+
),
|
|
6721
|
+
initialSeparation: primaryHand.distanceTo(secondaryHand),
|
|
6722
|
+
// How the object sits relative to the anchoring hand right now, so the
|
|
6723
|
+
// two-hand solve picks up exactly where the one-hand hold left off.
|
|
6724
|
+
primaryHandOffset: this.handQuaternion(primary.input).invert().multiply(quatFromEulerVec(transform.rotation)),
|
|
6725
|
+
initialQuaternion: quatFromEulerVec(transform.rotation)
|
|
6726
|
+
};
|
|
6727
|
+
this.dispatch(world, entityId, (b) => b.onSecondaryGrab(secondary.input));
|
|
6728
|
+
}
|
|
6729
|
+
/** World point → the object's UNSCALED local space. */
|
|
6730
|
+
objectLocalPoint(transform, worldPoint) {
|
|
6731
|
+
const local = worldPoint.clone().sub(
|
|
6732
|
+
new THREE19.Vector3(
|
|
6733
|
+
transform.position.x,
|
|
6734
|
+
transform.position.y,
|
|
6735
|
+
transform.position.z
|
|
6736
|
+
)
|
|
6737
|
+
).applyQuaternion(quatFromEulerVec(transform.rotation).invert());
|
|
6738
|
+
local.x /= transform.scale.x || 1;
|
|
6739
|
+
local.y /= transform.scale.y || 1;
|
|
6740
|
+
local.z /= transform.scale.z || 1;
|
|
6741
|
+
return local;
|
|
6497
6742
|
}
|
|
6498
6743
|
/** Whether the grab gesture for this object is currently starting. */
|
|
6499
6744
|
gestureMatches(input, interactable, starting) {
|
|
@@ -6542,7 +6787,7 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6542
6787
|
);
|
|
6543
6788
|
if (!interactable2) continue;
|
|
6544
6789
|
if (interactable2.grabReach === "distance") continue;
|
|
6545
|
-
const position = new
|
|
6790
|
+
const position = new THREE19.Vector3();
|
|
6546
6791
|
entry.object.getWorldPosition(position);
|
|
6547
6792
|
const distance = position.distanceTo(hand);
|
|
6548
6793
|
if (distance <= interactable2.grabRadius && distance < nearestDistance) {
|
|
@@ -6551,13 +6796,22 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6551
6796
|
}
|
|
6552
6797
|
}
|
|
6553
6798
|
if (nearestId !== null) {
|
|
6554
|
-
return {
|
|
6799
|
+
return {
|
|
6800
|
+
entityId: nearestId,
|
|
6801
|
+
viaDistance: false,
|
|
6802
|
+
distance: nearestDistance
|
|
6803
|
+
};
|
|
6555
6804
|
}
|
|
6556
|
-
const
|
|
6557
|
-
if (
|
|
6805
|
+
const hit = this.raycast(input, interactables);
|
|
6806
|
+
if (hit === null) return null;
|
|
6807
|
+
const hitId = hit.entityId;
|
|
6558
6808
|
const interactable = world.getComponent(hitId, XRInteractableComponent);
|
|
6559
6809
|
const viaDistanceAllowed = interactable?.grabReach === "distance" || interactable?.grabReach === "both";
|
|
6560
|
-
return {
|
|
6810
|
+
return {
|
|
6811
|
+
entityId: hitId,
|
|
6812
|
+
viaDistance: viaDistanceAllowed,
|
|
6813
|
+
distance: hit.distance
|
|
6814
|
+
};
|
|
6561
6815
|
}
|
|
6562
6816
|
collectInteractables(world) {
|
|
6563
6817
|
const out = [];
|
|
@@ -6588,9 +6842,54 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6588
6842
|
nearestId = entry.entityId;
|
|
6589
6843
|
}
|
|
6590
6844
|
}
|
|
6591
|
-
return nearestId;
|
|
6845
|
+
return nearestId === null ? null : { entityId: nearestId, distance: nearestDistance };
|
|
6846
|
+
}
|
|
6847
|
+
/**
|
|
6848
|
+
* Pick the authored hold this hand should take.
|
|
6849
|
+
*
|
|
6850
|
+
* Filters by hand and by role — that is what makes "the trigger hand goes on
|
|
6851
|
+
* the grip" hold regardless of which hand reaches first — then takes the
|
|
6852
|
+
* nearest remaining one so grabbing near the foregrip picks the foregrip.
|
|
6853
|
+
*/
|
|
6854
|
+
chooseAttachPoint(world, input, entityId, interactable, role) {
|
|
6855
|
+
if (interactable.attachPoints.length === 0) return null;
|
|
6856
|
+
const transform = world.getComponent(entityId, TransformComponent);
|
|
6857
|
+
if (!transform) return null;
|
|
6858
|
+
const taken = new Set(
|
|
6859
|
+
this.holdersOf(entityId).map((holder) => holder.record.attachPointId).filter((id) => id !== null)
|
|
6860
|
+
);
|
|
6861
|
+
const hand = this.handPosition(input);
|
|
6862
|
+
const objectPosition = new THREE19.Vector3(
|
|
6863
|
+
transform.position.x,
|
|
6864
|
+
transform.position.y,
|
|
6865
|
+
transform.position.z
|
|
6866
|
+
);
|
|
6867
|
+
const objectQuaternion = quatFromEulerVec(transform.rotation);
|
|
6868
|
+
const scale = new THREE19.Vector3(
|
|
6869
|
+
transform.scale.x,
|
|
6870
|
+
transform.scale.y,
|
|
6871
|
+
transform.scale.z
|
|
6872
|
+
);
|
|
6873
|
+
let best = null;
|
|
6874
|
+
let bestDistance = Number.POSITIVE_INFINITY;
|
|
6875
|
+
for (const point of interactable.attachPoints) {
|
|
6876
|
+
if (taken.has(point.id)) continue;
|
|
6877
|
+
if (point.hand !== "any" && point.hand !== input.handedness) continue;
|
|
6878
|
+
if (point.role !== "any" && point.role !== role) continue;
|
|
6879
|
+
const world3 = new THREE19.Vector3(
|
|
6880
|
+
point.position.x,
|
|
6881
|
+
point.position.y,
|
|
6882
|
+
point.position.z
|
|
6883
|
+
).multiply(scale).applyQuaternion(objectQuaternion).add(objectPosition);
|
|
6884
|
+
const distance = world3.distanceTo(hand);
|
|
6885
|
+
if (distance < bestDistance) {
|
|
6886
|
+
bestDistance = distance;
|
|
6887
|
+
best = point;
|
|
6888
|
+
}
|
|
6889
|
+
}
|
|
6890
|
+
return best;
|
|
6592
6891
|
}
|
|
6593
|
-
grab(world, input, entityId, viaDistance) {
|
|
6892
|
+
grab(world, input, entityId, viaDistance, role) {
|
|
6594
6893
|
const transform = world.getComponent(entityId, TransformComponent);
|
|
6595
6894
|
const interactable = world.getComponent(entityId, XRInteractableComponent);
|
|
6596
6895
|
if (!transform || !interactable) return;
|
|
@@ -6600,25 +6899,25 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6600
6899
|
let offset;
|
|
6601
6900
|
let remoteDistance = 0;
|
|
6602
6901
|
if (remote) {
|
|
6603
|
-
const position = new
|
|
6902
|
+
const position = new THREE19.Vector3(
|
|
6604
6903
|
transform.position.x,
|
|
6605
6904
|
transform.position.y,
|
|
6606
6905
|
transform.position.z
|
|
6607
6906
|
);
|
|
6608
6907
|
remoteDistance = position.distanceTo(input.rayOrigin);
|
|
6609
|
-
offset = new
|
|
6908
|
+
offset = new THREE19.Vector3();
|
|
6610
6909
|
} else if (viaDistance) {
|
|
6611
|
-
offset = new
|
|
6910
|
+
offset = new THREE19.Vector3(
|
|
6612
6911
|
interactable.grabOffsetPosition.x,
|
|
6613
6912
|
interactable.grabOffsetPosition.y,
|
|
6614
6913
|
interactable.grabOffsetPosition.z
|
|
6615
6914
|
);
|
|
6616
6915
|
} else {
|
|
6617
|
-
offset = new
|
|
6916
|
+
offset = new THREE19.Vector3(
|
|
6618
6917
|
transform.position.x - hand.x,
|
|
6619
6918
|
transform.position.y - hand.y,
|
|
6620
6919
|
transform.position.z - hand.z
|
|
6621
|
-
);
|
|
6920
|
+
).applyQuaternion(handQuaternion.clone().invert());
|
|
6622
6921
|
}
|
|
6623
6922
|
const physics = world.getComponent(entityId, PhysicsComponent);
|
|
6624
6923
|
let restoreBodyType = null;
|
|
@@ -6628,11 +6927,30 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6628
6927
|
}
|
|
6629
6928
|
const tracker = new ThrowVelocityTracker();
|
|
6630
6929
|
tracker.record(hand, this.elapsed);
|
|
6930
|
+
const attachPoint = this.chooseAttachPoint(
|
|
6931
|
+
world,
|
|
6932
|
+
input,
|
|
6933
|
+
entityId,
|
|
6934
|
+
interactable,
|
|
6935
|
+
role
|
|
6936
|
+
);
|
|
6937
|
+
const objectQuaternion = quatFromEulerVec(transform.rotation);
|
|
6938
|
+
const handRotationOffset = handQuaternion.clone().invert().multiply(objectQuaternion);
|
|
6631
6939
|
this.grabs.set(input, {
|
|
6632
6940
|
entityId,
|
|
6941
|
+
role,
|
|
6942
|
+
attachPointId: attachPoint?.id ?? null,
|
|
6943
|
+
attachLocal: attachPoint ? new THREE19.Vector3(
|
|
6944
|
+
attachPoint.position.x,
|
|
6945
|
+
attachPoint.position.y,
|
|
6946
|
+
attachPoint.position.z
|
|
6947
|
+
) : null,
|
|
6948
|
+
attachQuaternion: attachPoint ? quatFromEulerVec(attachPoint.rotation) : null,
|
|
6949
|
+
handRotationOffset,
|
|
6950
|
+
twoHand: null,
|
|
6633
6951
|
offset,
|
|
6634
|
-
rotationOffset: new
|
|
6635
|
-
new
|
|
6952
|
+
rotationOffset: new THREE19.Quaternion().setFromEuler(
|
|
6953
|
+
new THREE19.Euler(
|
|
6636
6954
|
interactable.grabOffsetRotation.x,
|
|
6637
6955
|
interactable.grabOffsetRotation.y,
|
|
6638
6956
|
interactable.grabOffsetRotation.z
|
|
@@ -6643,33 +6961,111 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6643
6961
|
restoreBodyType,
|
|
6644
6962
|
tracker,
|
|
6645
6963
|
lastHandQuaternion: handQuaternion.clone(),
|
|
6646
|
-
angularVelocity: new
|
|
6964
|
+
angularVelocity: new THREE19.Vector3()
|
|
6647
6965
|
});
|
|
6648
|
-
|
|
6966
|
+
if (role === "primary") {
|
|
6967
|
+
this.dispatch(world, entityId, (b) => b.onGrab(input));
|
|
6968
|
+
}
|
|
6969
|
+
}
|
|
6970
|
+
/** Drive every held object, once each, after grabs and releases settle. */
|
|
6971
|
+
moveAllHeld(world, deltaTime) {
|
|
6972
|
+
const done = /* @__PURE__ */ new Set();
|
|
6973
|
+
for (const [input, record] of this.grabs) {
|
|
6974
|
+
if (done.has(record.entityId)) continue;
|
|
6975
|
+
done.add(record.entityId);
|
|
6976
|
+
const holders = this.holdersOf(record.entityId);
|
|
6977
|
+
if (holders.length >= 2) {
|
|
6978
|
+
this.moveTwoHand(world, record.entityId, holders, deltaTime);
|
|
6979
|
+
} else {
|
|
6980
|
+
this.moveHeld(world, input, record, deltaTime);
|
|
6981
|
+
}
|
|
6982
|
+
}
|
|
6983
|
+
}
|
|
6984
|
+
/** Solve and apply a two-hand hold. */
|
|
6985
|
+
moveTwoHand(world, entityId, holders, deltaTime) {
|
|
6986
|
+
const primary = holders.find((h) => h.record.role === "primary");
|
|
6987
|
+
const secondary = holders.find((h) => h.record.role === "secondary");
|
|
6988
|
+
const transform = world.getComponent(entityId, TransformComponent);
|
|
6989
|
+
const interactable = world.getComponent(entityId, XRInteractableComponent);
|
|
6990
|
+
const basis = primary?.record.twoHand ?? null;
|
|
6991
|
+
if (!primary || !secondary || !transform || !interactable || !basis) {
|
|
6992
|
+
if (primary) {
|
|
6993
|
+
this.moveHeld(world, primary.input, primary.record, deltaTime);
|
|
6994
|
+
}
|
|
6995
|
+
return;
|
|
6996
|
+
}
|
|
6997
|
+
const primaryHand = this.handPosition(primary.input);
|
|
6998
|
+
const primaryQuaternion = this.handQuaternion(primary.input);
|
|
6999
|
+
const solved = solveTwoHandTransform(
|
|
7000
|
+
{ position: primaryHand, quaternion: primaryQuaternion },
|
|
7001
|
+
{
|
|
7002
|
+
position: this.handPosition(secondary.input),
|
|
7003
|
+
quaternion: this.handQuaternion(secondary.input)
|
|
7004
|
+
},
|
|
7005
|
+
basis,
|
|
7006
|
+
{
|
|
7007
|
+
rotationMode: interactable.twoHandRotation,
|
|
7008
|
+
allowScale: interactable.allowTwoHandScale,
|
|
7009
|
+
minScale: interactable.minScale,
|
|
7010
|
+
maxScale: interactable.maxScale
|
|
7011
|
+
}
|
|
7012
|
+
);
|
|
7013
|
+
transform.position.x = solved.position.x;
|
|
7014
|
+
transform.position.y = solved.position.y;
|
|
7015
|
+
transform.position.z = solved.position.z;
|
|
7016
|
+
writeEuler(transform.rotation, solved.quaternion);
|
|
7017
|
+
if (interactable.allowTwoHandScale) {
|
|
7018
|
+
transform.scale.x = solved.scale.x;
|
|
7019
|
+
transform.scale.y = solved.scale.y;
|
|
7020
|
+
transform.scale.z = solved.scale.z;
|
|
7021
|
+
}
|
|
7022
|
+
primary.record.tracker.record(primaryHand, this.elapsed);
|
|
7023
|
+
primary.record.angularVelocity = angularVelocityFrom(
|
|
7024
|
+
primary.record.lastHandQuaternion,
|
|
7025
|
+
primaryQuaternion,
|
|
7026
|
+
deltaTime
|
|
7027
|
+
);
|
|
7028
|
+
primary.record.lastHandQuaternion = primaryQuaternion.clone();
|
|
6649
7029
|
}
|
|
6650
7030
|
moveHeld(world, input, held, deltaTime) {
|
|
6651
7031
|
const transform = world.getComponent(held.entityId, TransformComponent);
|
|
6652
7032
|
if (!transform) return;
|
|
6653
7033
|
const hand = this.handPosition(input);
|
|
7034
|
+
const handQuaternion = this.handQuaternion(input);
|
|
7035
|
+
const objectQuaternion = held.attachQuaternion ? handQuaternion.clone().multiply(held.rotationOffset).multiply(held.attachQuaternion.clone().invert()) : handQuaternion.clone().multiply(held.handRotationOffset);
|
|
6654
7036
|
if (held.remote) {
|
|
6655
|
-
const target = new
|
|
7037
|
+
const target = new THREE19.Vector3().copy(input.rayDirection).multiplyScalar(held.remoteDistance).add(input.rayOrigin);
|
|
6656
7038
|
transform.position.x = target.x;
|
|
6657
7039
|
transform.position.y = target.y;
|
|
6658
7040
|
transform.position.z = target.z;
|
|
7041
|
+
writeEuler(transform.rotation, objectQuaternion);
|
|
7042
|
+
} else if (held.attachLocal) {
|
|
7043
|
+
const anchor = held.attachLocal.clone().multiply(
|
|
7044
|
+
new THREE19.Vector3(
|
|
7045
|
+
transform.scale.x,
|
|
7046
|
+
transform.scale.y,
|
|
7047
|
+
transform.scale.z
|
|
7048
|
+
)
|
|
7049
|
+
).applyQuaternion(objectQuaternion);
|
|
7050
|
+
transform.position.x = hand.x - anchor.x;
|
|
7051
|
+
transform.position.y = hand.y - anchor.y;
|
|
7052
|
+
transform.position.z = hand.z - anchor.z;
|
|
7053
|
+
writeEuler(transform.rotation, objectQuaternion);
|
|
6659
7054
|
} else {
|
|
6660
|
-
|
|
6661
|
-
transform.position.
|
|
6662
|
-
transform.position.
|
|
7055
|
+
const carried = held.offset.clone().applyQuaternion(handQuaternion);
|
|
7056
|
+
transform.position.x = hand.x + carried.x;
|
|
7057
|
+
transform.position.y = hand.y + carried.y;
|
|
7058
|
+
transform.position.z = hand.z + carried.z;
|
|
7059
|
+
writeEuler(transform.rotation, objectQuaternion);
|
|
6663
7060
|
}
|
|
6664
7061
|
held.tracker.record(
|
|
6665
|
-
held.remote ? new
|
|
7062
|
+
held.remote ? new THREE19.Vector3(
|
|
6666
7063
|
transform.position.x,
|
|
6667
7064
|
transform.position.y,
|
|
6668
7065
|
transform.position.z
|
|
6669
7066
|
) : hand,
|
|
6670
7067
|
this.elapsed
|
|
6671
7068
|
);
|
|
6672
|
-
const handQuaternion = this.handQuaternion(input);
|
|
6673
7069
|
held.angularVelocity = angularVelocityFrom(
|
|
6674
7070
|
held.lastHandQuaternion,
|
|
6675
7071
|
handQuaternion,
|
|
@@ -6685,22 +7081,41 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6685
7081
|
held.entityId,
|
|
6686
7082
|
XRInteractableComponent
|
|
6687
7083
|
);
|
|
7084
|
+
const remaining = this.holdersOf(held.entityId);
|
|
7085
|
+
if (remaining.length > 0 && interactable) {
|
|
7086
|
+
if (held.role === "secondary") {
|
|
7087
|
+
const primary = remaining.find((h) => h.record.role === "primary");
|
|
7088
|
+
if (primary) {
|
|
7089
|
+
primary.record.twoHand = null;
|
|
7090
|
+
this.reanchor(world, primary.input, primary.record, interactable);
|
|
7091
|
+
}
|
|
7092
|
+
this.dispatch(
|
|
7093
|
+
world,
|
|
7094
|
+
held.entityId,
|
|
7095
|
+
(b) => b.onSecondaryRelease(input)
|
|
7096
|
+
);
|
|
7097
|
+
} else {
|
|
7098
|
+
const next = remaining[0];
|
|
7099
|
+
next.record.role = "primary";
|
|
7100
|
+
next.record.twoHand = null;
|
|
7101
|
+
next.record.restoreBodyType = held.restoreBodyType;
|
|
7102
|
+
this.reanchor(world, next.input, next.record, interactable);
|
|
7103
|
+
this.dispatch(world, held.entityId, (b) => b.onRelease(input));
|
|
7104
|
+
}
|
|
7105
|
+
held.tracker.clear();
|
|
7106
|
+
return;
|
|
7107
|
+
}
|
|
6688
7108
|
const physics = world.getComponent(held.entityId, PhysicsComponent);
|
|
6689
7109
|
if (held.restoreBodyType !== null && physics) {
|
|
6690
7110
|
physics.values.rigidbody.type = held.restoreBodyType;
|
|
6691
|
-
const body = physics.rigidBody;
|
|
6692
7111
|
const dynamic = held.restoreBodyType === "dynamic";
|
|
6693
|
-
if (
|
|
7112
|
+
if (dynamic && interactable?.throwOnRelease) {
|
|
6694
7113
|
const velocity = held.tracker.computeVelocity(this.elapsed).multiplyScalar(interactable.throwStrength);
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
const spin = held.angularVelocity;
|
|
6701
|
-
body.setAngvel({ x: spin.x, y: spin.y, z: spin.z }, true);
|
|
6702
|
-
} catch {
|
|
6703
|
-
}
|
|
7114
|
+
const spin = held.angularVelocity;
|
|
7115
|
+
setPhysicsLiveRef(physics, "pendingVelocity", {
|
|
7116
|
+
linear: { x: velocity.x, y: velocity.y, z: velocity.z },
|
|
7117
|
+
angular: { x: spin.x, y: spin.y, z: spin.z }
|
|
7118
|
+
});
|
|
6704
7119
|
}
|
|
6705
7120
|
}
|
|
6706
7121
|
held.tracker.clear();
|
|
@@ -6718,7 +7133,7 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6718
7133
|
*/
|
|
6719
7134
|
handPosition(input) {
|
|
6720
7135
|
if (input.gripPosition) return input.gripPosition;
|
|
6721
|
-
return new
|
|
7136
|
+
return new THREE19.Vector3().copy(input.rayDirection).multiplyScalar(RAYLESS_HOLD_DISTANCE).add(input.rayOrigin);
|
|
6722
7137
|
}
|
|
6723
7138
|
/**
|
|
6724
7139
|
* Hand orientation. Grip-less sources (gaze / transient-pointer) have none,
|
|
@@ -6726,8 +7141,8 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6726
7141
|
*/
|
|
6727
7142
|
handQuaternion(input) {
|
|
6728
7143
|
if (input.gripQuaternion) return input.gripQuaternion.clone();
|
|
6729
|
-
return new
|
|
6730
|
-
new
|
|
7144
|
+
return new THREE19.Quaternion().setFromUnitVectors(
|
|
7145
|
+
new THREE19.Vector3(0, 0, -1),
|
|
6731
7146
|
input.rayDirection.clone().normalize()
|
|
6732
7147
|
);
|
|
6733
7148
|
}
|
|
@@ -6748,10 +7163,57 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
6748
7163
|
getHoveredEntityId() {
|
|
6749
7164
|
return this.hoveredEntityId;
|
|
6750
7165
|
}
|
|
7166
|
+
/**
|
|
7167
|
+
* What this hand is pointing at, with the distance to it.
|
|
7168
|
+
*
|
|
7169
|
+
* The distance is what lets the pointer ray stop at the surface instead of
|
|
7170
|
+
* passing through the object.
|
|
7171
|
+
*/
|
|
7172
|
+
getHoverFor(handedness) {
|
|
7173
|
+
for (const [input, hover] of this.hovers) {
|
|
7174
|
+
if (input.handedness === handedness) return hover;
|
|
7175
|
+
}
|
|
7176
|
+
return null;
|
|
7177
|
+
}
|
|
7178
|
+
/** Every entity under a pointer this frame — drives hover feedback. */
|
|
7179
|
+
getHoveredEntityIds() {
|
|
7180
|
+
const ids = /* @__PURE__ */ new Set();
|
|
7181
|
+
for (const hover of this.hovers.values()) ids.add(hover.entityId);
|
|
7182
|
+
return ids;
|
|
7183
|
+
}
|
|
7184
|
+
/** Entities currently held, so hover feedback can skip them. */
|
|
7185
|
+
getHeldEntityIds() {
|
|
7186
|
+
const ids = /* @__PURE__ */ new Set();
|
|
7187
|
+
for (const record of this.grabs.values()) ids.add(record.entityId);
|
|
7188
|
+
return ids;
|
|
7189
|
+
}
|
|
6751
7190
|
/** True when any source is holding something. */
|
|
6752
7191
|
isGrabbing() {
|
|
6753
7192
|
return this.grabs.size > 0;
|
|
6754
7193
|
}
|
|
7194
|
+
/**
|
|
7195
|
+
* How an entity is currently held.
|
|
7196
|
+
*
|
|
7197
|
+
* Exposed for scripts: a Behaviour can poll this in `onUpdate` to drive
|
|
7198
|
+
* two-hand-specific behaviour — showing a bipod when both hands are on a
|
|
7199
|
+
* weapon, reading the live hand separation to gate a gesture, or reacting to
|
|
7200
|
+
* the scale a pull-apart produced. Returns null when nothing holds it.
|
|
7201
|
+
*/
|
|
7202
|
+
getGrabInfo(entityId) {
|
|
7203
|
+
const holders = this.holdersOf(entityId);
|
|
7204
|
+
if (holders.length === 0) return null;
|
|
7205
|
+
const primary = holders.find((h) => h.record.role === "primary");
|
|
7206
|
+
const secondary = holders.find((h) => h.record.role === "secondary");
|
|
7207
|
+
return {
|
|
7208
|
+
hands: holders.length,
|
|
7209
|
+
primaryHandedness: primary?.input.handedness ?? null,
|
|
7210
|
+
secondaryHandedness: secondary?.input.handedness ?? null,
|
|
7211
|
+
handSeparation: primary && secondary ? this.handPosition(primary.input).distanceTo(
|
|
7212
|
+
this.handPosition(secondary.input)
|
|
7213
|
+
) : null,
|
|
7214
|
+
attachPointIds: holders.map((h) => h.record.attachPointId)
|
|
7215
|
+
};
|
|
7216
|
+
}
|
|
6755
7217
|
};
|
|
6756
7218
|
__name(_XRInteractionSystem, "XRInteractionSystem");
|
|
6757
7219
|
var XRInteractionSystem = _XRInteractionSystem;
|
|
@@ -6769,7 +7231,7 @@ function sampleTeleportArc(origin, direction, out = [], options) {
|
|
|
6769
7231
|
for (let i = 0; i < steps; i += 1) {
|
|
6770
7232
|
const t = i / (steps - 1) * maxTime;
|
|
6771
7233
|
out.push(
|
|
6772
|
-
new
|
|
7234
|
+
new THREE19.Vector3(
|
|
6773
7235
|
origin.x + velocity.x * t,
|
|
6774
7236
|
origin.y + velocity.y * t - 0.5 * gravity * t * t,
|
|
6775
7237
|
origin.z + velocity.z * t
|
|
@@ -6786,7 +7248,7 @@ function arcGroundCrossing(points, groundY) {
|
|
|
6786
7248
|
if (previous.y >= groundY && current.y <= groundY) {
|
|
6787
7249
|
const span = previous.y - current.y;
|
|
6788
7250
|
const alpha = span > 1e-6 ? (previous.y - groundY) / span : 0;
|
|
6789
|
-
return new
|
|
7251
|
+
return new THREE19.Vector3().lerpVectors(previous, current, alpha);
|
|
6790
7252
|
}
|
|
6791
7253
|
}
|
|
6792
7254
|
return null;
|
|
@@ -6794,11 +7256,11 @@ function arcGroundCrossing(points, groundY) {
|
|
|
6794
7256
|
__name(arcGroundCrossing, "arcGroundCrossing");
|
|
6795
7257
|
|
|
6796
7258
|
// core/systems/XRLocomotionSystem.ts
|
|
6797
|
-
var UP = new
|
|
7259
|
+
var UP = new THREE19.Vector3(0, 1, 0);
|
|
6798
7260
|
var AXIS_DEADZONE = 0.5;
|
|
6799
7261
|
var _XRLocomotionSystem = class _XRLocomotionSystem {
|
|
6800
7262
|
constructor(inputSystem) {
|
|
6801
|
-
this.raycaster = new
|
|
7263
|
+
this.raycaster = new THREE19.Raycaster();
|
|
6802
7264
|
/** Per-source latch so one stick push yields exactly one snap turn. */
|
|
6803
7265
|
this.turnLatched = /* @__PURE__ */ new WeakSet();
|
|
6804
7266
|
/** Reused arc buffer — aiming runs every frame. */
|
|
@@ -6907,7 +7369,7 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
|
|
|
6907
7369
|
}
|
|
6908
7370
|
if (this.turnLatched.has(source)) continue;
|
|
6909
7371
|
this.turnLatched.add(source);
|
|
6910
|
-
transform.rotation.y -= Math.sign(x) *
|
|
7372
|
+
transform.rotation.y -= Math.sign(x) * THREE19.MathUtils.degToRad(rig.snapTurnDegrees);
|
|
6911
7373
|
}
|
|
6912
7374
|
}
|
|
6913
7375
|
applySmoothMove(world, rig, transform, inputs, deltaTime) {
|
|
@@ -6917,12 +7379,12 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
|
|
|
6917
7379
|
const y = input.axes[1] ?? 0;
|
|
6918
7380
|
if (Math.abs(x) < 0.15 && Math.abs(y) < 0.15) continue;
|
|
6919
7381
|
const camera = world.getCamera();
|
|
6920
|
-
const forward = new
|
|
7382
|
+
const forward = new THREE19.Vector3();
|
|
6921
7383
|
camera.getWorldDirection(forward);
|
|
6922
7384
|
forward.y = 0;
|
|
6923
7385
|
if (forward.lengthSq() < 1e-6) continue;
|
|
6924
7386
|
forward.normalize();
|
|
6925
|
-
const right = new
|
|
7387
|
+
const right = new THREE19.Vector3().crossVectors(forward, UP).normalize();
|
|
6926
7388
|
const step = rig.moveSpeed * Math.max(0, deltaTime);
|
|
6927
7389
|
transform.position.x += (forward.x * -y + right.x * x) * step;
|
|
6928
7390
|
transform.position.z += (forward.z * -y + right.z * x) * step;
|
|
@@ -6987,7 +7449,7 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
|
|
|
6987
7449
|
for (let i = 1; i < points.length; i += 1) {
|
|
6988
7450
|
const from = points[i - 1];
|
|
6989
7451
|
const to = points[i];
|
|
6990
|
-
const delta = new
|
|
7452
|
+
const delta = new THREE19.Vector3().subVectors(to, from);
|
|
6991
7453
|
const distance = delta.length();
|
|
6992
7454
|
if (distance < 1e-6) continue;
|
|
6993
7455
|
this.raycaster.set(from, delta.divideScalar(distance));
|
|
@@ -7195,9 +7657,9 @@ var XRSessionSystem = _XRSessionSystem;
|
|
|
7195
7657
|
function buildGeometry2(area) {
|
|
7196
7658
|
if (area.shape === "circle") {
|
|
7197
7659
|
const radius = Math.max(5e-3, area.width / 2);
|
|
7198
|
-
return new
|
|
7660
|
+
return new THREE19.CircleGeometry(radius, 48);
|
|
7199
7661
|
}
|
|
7200
|
-
return new
|
|
7662
|
+
return new THREE19.PlaneGeometry(
|
|
7201
7663
|
Math.max(0.01, area.width),
|
|
7202
7664
|
Math.max(0.01, area.depth)
|
|
7203
7665
|
);
|
|
@@ -7220,7 +7682,7 @@ var _VRTeleportAreaSystem = class _VRTeleportAreaSystem {
|
|
|
7220
7682
|
for (const entityId of entityIds) {
|
|
7221
7683
|
const area = world.getComponent(entityId, VRTeleportAreaComponent);
|
|
7222
7684
|
const object = world.getComponent(entityId, Object3DRef)?.object;
|
|
7223
|
-
if (!area || !(object instanceof
|
|
7685
|
+
if (!area || !(object instanceof THREE19.Mesh)) continue;
|
|
7224
7686
|
const signature = signatureOf(area);
|
|
7225
7687
|
if (this.signatures.get(entityId) === signature) continue;
|
|
7226
7688
|
this.signatures.set(entityId, signature);
|
|
@@ -7232,18 +7694,18 @@ var _VRTeleportAreaSystem = class _VRTeleportAreaSystem {
|
|
|
7232
7694
|
__name(_VRTeleportAreaSystem, "VRTeleportAreaSystem");
|
|
7233
7695
|
var VRTeleportAreaSystem = _VRTeleportAreaSystem;
|
|
7234
7696
|
function createHandMaterial(preset, options) {
|
|
7235
|
-
const color = new
|
|
7697
|
+
const color = new THREE19.Color(options.color);
|
|
7236
7698
|
switch (preset) {
|
|
7237
7699
|
case "ghost":
|
|
7238
|
-
return new
|
|
7700
|
+
return new THREE19.MeshBasicMaterial({
|
|
7239
7701
|
color,
|
|
7240
7702
|
transparent: true,
|
|
7241
7703
|
opacity: Math.min(1, Math.max(0.05, options.opacity * 0.45)),
|
|
7242
7704
|
depthWrite: false,
|
|
7243
|
-
side:
|
|
7705
|
+
side: THREE19.DoubleSide
|
|
7244
7706
|
});
|
|
7245
7707
|
case "neon":
|
|
7246
|
-
return new
|
|
7708
|
+
return new THREE19.MeshStandardMaterial({
|
|
7247
7709
|
color,
|
|
7248
7710
|
emissive: color,
|
|
7249
7711
|
emissiveIntensity: Math.max(0.5, options.emissiveIntensity || 2),
|
|
@@ -7253,7 +7715,7 @@ function createHandMaterial(preset, options) {
|
|
|
7253
7715
|
opacity: options.opacity
|
|
7254
7716
|
});
|
|
7255
7717
|
case "skeleton":
|
|
7256
|
-
return new
|
|
7718
|
+
return new THREE19.MeshBasicMaterial({
|
|
7257
7719
|
color,
|
|
7258
7720
|
wireframe: true,
|
|
7259
7721
|
transparent: true,
|
|
@@ -7261,7 +7723,7 @@ function createHandMaterial(preset, options) {
|
|
|
7261
7723
|
});
|
|
7262
7724
|
case "custom":
|
|
7263
7725
|
case "default":
|
|
7264
|
-
return new
|
|
7726
|
+
return new THREE19.MeshStandardMaterial({
|
|
7265
7727
|
color,
|
|
7266
7728
|
roughness: 0.85,
|
|
7267
7729
|
metalness: 0,
|
|
@@ -7269,10 +7731,10 @@ function createHandMaterial(preset, options) {
|
|
|
7269
7731
|
emissiveIntensity: Math.max(0, options.emissiveIntensity),
|
|
7270
7732
|
transparent: options.opacity < 1,
|
|
7271
7733
|
opacity: options.opacity,
|
|
7272
|
-
side:
|
|
7734
|
+
side: THREE19.DoubleSide
|
|
7273
7735
|
});
|
|
7274
7736
|
default: {
|
|
7275
|
-
return new
|
|
7737
|
+
return new THREE19.MeshStandardMaterial({ color });
|
|
7276
7738
|
}
|
|
7277
7739
|
}
|
|
7278
7740
|
}
|
|
@@ -7285,6 +7747,9 @@ function applyHandMaterial(root, material) {
|
|
|
7285
7747
|
});
|
|
7286
7748
|
}
|
|
7287
7749
|
__name(applyHandMaterial, "applyHandMaterial");
|
|
7750
|
+
|
|
7751
|
+
// core/systems/XRControllerVisualSystem.ts
|
|
7752
|
+
var RAY_LENGTH = 5;
|
|
7288
7753
|
var SLOTS = [
|
|
7289
7754
|
{ index: 0, side: "left" },
|
|
7290
7755
|
{ index: 1, side: "right" }
|
|
@@ -7293,7 +7758,7 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
|
7293
7758
|
constructor(options) {
|
|
7294
7759
|
this.controllerModelFactory = new XRControllerModelFactory();
|
|
7295
7760
|
this.handModelFactory = new XRHandModelFactory();
|
|
7296
|
-
this.group = new
|
|
7761
|
+
this.group = new THREE19.Group();
|
|
7297
7762
|
this.slots = /* @__PURE__ */ new Map();
|
|
7298
7763
|
this.attachedTo = null;
|
|
7299
7764
|
/** Last applied preset signature, so materials rebuild only on real change. */
|
|
@@ -7323,6 +7788,7 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
|
7323
7788
|
visuals.controllerModel.visible = showControllers && hasController;
|
|
7324
7789
|
visuals.handModel.visible = showHands && hasHand;
|
|
7325
7790
|
visuals.ray.visible = this.shouldShowRay(interactor);
|
|
7791
|
+
this.fitRayToHover(visuals.ray, side);
|
|
7326
7792
|
if (showHands && this.handMaterial) {
|
|
7327
7793
|
applyHandMaterial(visuals.handModel, this.handMaterial);
|
|
7328
7794
|
}
|
|
@@ -7403,6 +7869,18 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
|
7403
7869
|
if (!this.interactionSystem) return true;
|
|
7404
7870
|
return this.interactionSystem.getHoveredEntityId() !== null || this.interactionSystem.isGrabbing();
|
|
7405
7871
|
}
|
|
7872
|
+
/**
|
|
7873
|
+
* Stop the ray at whatever it is pointing at.
|
|
7874
|
+
*
|
|
7875
|
+
* A fixed-length ray drawn with depth testing off punches straight through the
|
|
7876
|
+
* object, so the user cannot tell where the pointer actually lands. Scaling it
|
|
7877
|
+
* to the hit distance turns it into a pointer that meets the surface.
|
|
7878
|
+
*/
|
|
7879
|
+
fitRayToHover(ray, side) {
|
|
7880
|
+
const hover = this.interactionSystem?.getHoverFor(side) ?? null;
|
|
7881
|
+
const length = hover && Number.isFinite(hover.distance) && hover.distance > 0 ? Math.min(hover.distance, RAY_LENGTH) : RAY_LENGTH;
|
|
7882
|
+
ray.scale.z = length / RAY_LENGTH;
|
|
7883
|
+
}
|
|
7406
7884
|
/** Lazily build per-slot visuals; the device reports profiles late. */
|
|
7407
7885
|
ensureSlots(world) {
|
|
7408
7886
|
const renderer = world.getRenderer();
|
|
@@ -7442,17 +7920,17 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
|
7442
7920
|
this.attachedTo = target;
|
|
7443
7921
|
}
|
|
7444
7922
|
createRay() {
|
|
7445
|
-
const geometry = new
|
|
7446
|
-
new
|
|
7447
|
-
new
|
|
7923
|
+
const geometry = new THREE19.BufferGeometry().setFromPoints([
|
|
7924
|
+
new THREE19.Vector3(0, 0, 0),
|
|
7925
|
+
new THREE19.Vector3(0, 0, -RAY_LENGTH)
|
|
7448
7926
|
]);
|
|
7449
|
-
const material = new
|
|
7927
|
+
const material = new THREE19.LineBasicMaterial({
|
|
7450
7928
|
color: "#4da3ff",
|
|
7451
7929
|
transparent: true,
|
|
7452
7930
|
opacity: 0.6,
|
|
7453
7931
|
depthTest: false
|
|
7454
7932
|
});
|
|
7455
|
-
const line = new
|
|
7933
|
+
const line = new THREE19.Line(geometry, material);
|
|
7456
7934
|
line.name = "XRPointerRay";
|
|
7457
7935
|
line.renderOrder = 999;
|
|
7458
7936
|
line.visible = false;
|
|
@@ -7481,23 +7959,23 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
|
7481
7959
|
__name(_XRControllerVisualSystem, "XRControllerVisualSystem");
|
|
7482
7960
|
var XRControllerVisualSystem = _XRControllerVisualSystem;
|
|
7483
7961
|
var MARKER_RADIUS = 0.28;
|
|
7484
|
-
var ACCENT = new
|
|
7485
|
-
var BLOCKED = new
|
|
7962
|
+
var ACCENT = new THREE19.Color("#4da3ff");
|
|
7963
|
+
var BLOCKED = new THREE19.Color("#ff5a5a");
|
|
7486
7964
|
var _XRTeleportVisualSystem = class _XRTeleportVisualSystem {
|
|
7487
7965
|
constructor(locomotionSystem) {
|
|
7488
|
-
this.group = new
|
|
7489
|
-
this.arcGeometry = new
|
|
7490
|
-
this.marker = new
|
|
7966
|
+
this.group = new THREE19.Group();
|
|
7967
|
+
this.arcGeometry = new THREE19.BufferGeometry();
|
|
7968
|
+
this.marker = new THREE19.Group();
|
|
7491
7969
|
this.attached = false;
|
|
7492
7970
|
this.locomotionSystem = locomotionSystem;
|
|
7493
7971
|
this.group.name = "XRTeleportVisuals";
|
|
7494
7972
|
this.group.userData.ecsPreviewHidden = true;
|
|
7495
|
-
const arcMaterial = new
|
|
7973
|
+
const arcMaterial = new THREE19.LineBasicMaterial({
|
|
7496
7974
|
vertexColors: true,
|
|
7497
7975
|
transparent: true,
|
|
7498
7976
|
depthTest: false
|
|
7499
7977
|
});
|
|
7500
|
-
this.arc = new
|
|
7978
|
+
this.arc = new THREE19.Line(this.arcGeometry, arcMaterial);
|
|
7501
7979
|
this.arc.frustumCulled = false;
|
|
7502
7980
|
this.arc.renderOrder = 998;
|
|
7503
7981
|
this.group.add(this.arc);
|
|
@@ -7545,39 +8023,39 @@ var _XRTeleportVisualSystem = class _XRTeleportVisualSystem {
|
|
|
7545
8023
|
}
|
|
7546
8024
|
this.arcGeometry.setAttribute(
|
|
7547
8025
|
"position",
|
|
7548
|
-
new
|
|
8026
|
+
new THREE19.BufferAttribute(positions, 3)
|
|
7549
8027
|
);
|
|
7550
|
-
this.arcGeometry.setAttribute("color", new
|
|
8028
|
+
this.arcGeometry.setAttribute("color", new THREE19.BufferAttribute(colors, 3));
|
|
7551
8029
|
this.arcGeometry.computeBoundingSphere();
|
|
7552
8030
|
}
|
|
7553
8031
|
createRing() {
|
|
7554
|
-
const geometry = new
|
|
8032
|
+
const geometry = new THREE19.RingGeometry(
|
|
7555
8033
|
MARKER_RADIUS * 0.72,
|
|
7556
8034
|
MARKER_RADIUS,
|
|
7557
8035
|
48
|
|
7558
8036
|
);
|
|
7559
8037
|
geometry.rotateX(-Math.PI / 2);
|
|
7560
|
-
return new
|
|
8038
|
+
return new THREE19.Mesh(
|
|
7561
8039
|
geometry,
|
|
7562
|
-
new
|
|
8040
|
+
new THREE19.MeshBasicMaterial({
|
|
7563
8041
|
color: ACCENT,
|
|
7564
8042
|
transparent: true,
|
|
7565
8043
|
opacity: 0.9,
|
|
7566
|
-
side:
|
|
8044
|
+
side: THREE19.DoubleSide,
|
|
7567
8045
|
depthTest: false
|
|
7568
8046
|
})
|
|
7569
8047
|
);
|
|
7570
8048
|
}
|
|
7571
8049
|
createDot() {
|
|
7572
|
-
const geometry = new
|
|
8050
|
+
const geometry = new THREE19.CircleGeometry(MARKER_RADIUS * 0.16, 24);
|
|
7573
8051
|
geometry.rotateX(-Math.PI / 2);
|
|
7574
|
-
return new
|
|
8052
|
+
return new THREE19.Mesh(
|
|
7575
8053
|
geometry,
|
|
7576
|
-
new
|
|
8054
|
+
new THREE19.MeshBasicMaterial({
|
|
7577
8055
|
color: ACCENT,
|
|
7578
8056
|
transparent: true,
|
|
7579
8057
|
opacity: 0.55,
|
|
7580
|
-
side:
|
|
8058
|
+
side: THREE19.DoubleSide,
|
|
7581
8059
|
depthTest: false
|
|
7582
8060
|
})
|
|
7583
8061
|
);
|
|
@@ -7679,7 +8157,7 @@ function boneDirections(joints, finger) {
|
|
|
7679
8157
|
const from = joints[chain[i - 1]];
|
|
7680
8158
|
const to = joints[chain[i]];
|
|
7681
8159
|
if (!from || !to) return null;
|
|
7682
|
-
const direction = new
|
|
8160
|
+
const direction = new THREE19.Vector3().subVectors(to, from);
|
|
7683
8161
|
if (direction.lengthSq() < 1e-12) return null;
|
|
7684
8162
|
directions.push(direction.normalize());
|
|
7685
8163
|
}
|
|
@@ -7752,8 +8230,8 @@ function computeSpread(joints, a, b) {
|
|
|
7752
8230
|
const bBase = joints[METACARPAL_JOINTS[b]];
|
|
7753
8231
|
const bTip = joints[TIP_JOINTS[b]];
|
|
7754
8232
|
if (!aBase || !aTip || !bBase || !bTip) return null;
|
|
7755
|
-
const dirA = new
|
|
7756
|
-
const dirB = new
|
|
8233
|
+
const dirA = new THREE19.Vector3().subVectors(aTip, aBase);
|
|
8234
|
+
const dirB = new THREE19.Vector3().subVectors(bTip, bBase);
|
|
7757
8235
|
if (dirA.lengthSq() < 1e-12 || dirB.lengthSq() < 1e-12) return null;
|
|
7758
8236
|
return clamp01((1 - dirA.normalize().dot(dirB.normalize())) / 0.45);
|
|
7759
8237
|
}
|
|
@@ -7763,18 +8241,18 @@ function computePalmPose(joints, handedness) {
|
|
|
7763
8241
|
const indexBase = joints["index-finger-metacarpal"];
|
|
7764
8242
|
const pinkyBase = joints["pinky-finger-metacarpal"];
|
|
7765
8243
|
if (!wrist || !indexBase || !pinkyBase) return null;
|
|
7766
|
-
const u = new
|
|
7767
|
-
const v = new
|
|
7768
|
-
const normal = new
|
|
8244
|
+
const u = new THREE19.Vector3().subVectors(indexBase, wrist);
|
|
8245
|
+
const v = new THREE19.Vector3().subVectors(pinkyBase, wrist);
|
|
8246
|
+
const normal = new THREE19.Vector3().crossVectors(u, v);
|
|
7769
8247
|
if (normal.lengthSq() < 1e-12) return null;
|
|
7770
8248
|
normal.normalize();
|
|
7771
8249
|
if (handedness === "left") normal.multiplyScalar(-1);
|
|
7772
|
-
const right = new
|
|
8250
|
+
const right = new THREE19.Vector3().subVectors(indexBase, pinkyBase);
|
|
7773
8251
|
if (right.lengthSq() < 1e-12) return null;
|
|
7774
8252
|
right.normalize();
|
|
7775
8253
|
if (handedness === "left") right.multiplyScalar(-1);
|
|
7776
|
-
const up = new
|
|
7777
|
-
const center = new
|
|
8254
|
+
const up = new THREE19.Vector3().crossVectors(normal, right).normalize();
|
|
8255
|
+
const center = new THREE19.Vector3().add(wrist).add(indexBase).add(pinkyBase).divideScalar(3);
|
|
7778
8256
|
return {
|
|
7779
8257
|
center,
|
|
7780
8258
|
normal,
|
|
@@ -7805,7 +8283,7 @@ function computeHandShape(joints, handedness) {
|
|
|
7805
8283
|
const thumbTip = joints["thumb-tip"];
|
|
7806
8284
|
let thumbDirection = null;
|
|
7807
8285
|
if (thumbBase && thumbTip) {
|
|
7808
|
-
const direction = new
|
|
8286
|
+
const direction = new THREE19.Vector3().subVectors(thumbTip, thumbBase);
|
|
7809
8287
|
if (direction.lengthSq() > 1e-12) thumbDirection = direction.normalize();
|
|
7810
8288
|
}
|
|
7811
8289
|
return {
|
|
@@ -7837,12 +8315,12 @@ function scoreAgainst(actual, target, tolerance) {
|
|
|
7837
8315
|
}
|
|
7838
8316
|
__name(scoreAgainst, "scoreAgainst");
|
|
7839
8317
|
var WORLD_DIRECTIONS = {
|
|
7840
|
-
up: new
|
|
7841
|
-
down: new
|
|
7842
|
-
forward: new
|
|
7843
|
-
back: new
|
|
7844
|
-
left: new
|
|
7845
|
-
right: new
|
|
8318
|
+
up: new THREE19.Vector3(0, 1, 0),
|
|
8319
|
+
down: new THREE19.Vector3(0, -1, 0),
|
|
8320
|
+
forward: new THREE19.Vector3(0, 0, -1),
|
|
8321
|
+
back: new THREE19.Vector3(0, 0, 1),
|
|
8322
|
+
left: new THREE19.Vector3(-1, 0, 0),
|
|
8323
|
+
right: new THREE19.Vector3(1, 0, 0)
|
|
7846
8324
|
};
|
|
7847
8325
|
function axisVector(shape, axis) {
|
|
7848
8326
|
if (axis === "thumb") return shape.thumbDirection;
|
|
@@ -7857,7 +8335,7 @@ function resolveDirection(direction, shape, context) {
|
|
|
7857
8335
|
const head = context?.headPosition;
|
|
7858
8336
|
const origin = shape.palm?.center;
|
|
7859
8337
|
if (!head || !origin) return null;
|
|
7860
|
-
const toHead = new
|
|
8338
|
+
const toHead = new THREE19.Vector3().subVectors(head, origin);
|
|
7861
8339
|
if (toHead.lengthSq() < 1e-12) return null;
|
|
7862
8340
|
toHead.normalize();
|
|
7863
8341
|
return direction === "toward-head" ? toHead : toHead.multiplyScalar(-1);
|
|
@@ -7907,8 +8385,8 @@ function matchHandPose(shape, definition, context) {
|
|
|
7907
8385
|
if (!handAxis || !wanted) {
|
|
7908
8386
|
consider(0, "orientation");
|
|
7909
8387
|
} else {
|
|
7910
|
-
const angle =
|
|
7911
|
-
Math.acos(
|
|
8388
|
+
const angle = THREE19.MathUtils.radToDeg(
|
|
8389
|
+
Math.acos(THREE19.MathUtils.clamp(handAxis.dot(wanted), -1, 1))
|
|
7912
8390
|
);
|
|
7913
8391
|
const normalizedError = Math.max(0, angle - toleranceDegrees) / 90;
|
|
7914
8392
|
consider(clamp01(1 - normalizedError / MATCH_FALLOFF), "orientation");
|
|
@@ -7986,7 +8464,7 @@ var _XRHandPoseSystem = class _XRHandPoseSystem {
|
|
|
7986
8464
|
this.trackers = /* @__PURE__ */ new Map();
|
|
7987
8465
|
this.shapes = /* @__PURE__ */ new Map();
|
|
7988
8466
|
/** Reused so head-relative orientation checks allocate nothing per frame. */
|
|
7989
|
-
this.headPosition = new
|
|
8467
|
+
this.headPosition = new THREE19.Vector3();
|
|
7990
8468
|
this.elapsed = 0;
|
|
7991
8469
|
this.inputSystem = inputSystem;
|
|
7992
8470
|
}
|
|
@@ -8107,7 +8585,153 @@ var _XRHandPoseSystem = class _XRHandPoseSystem {
|
|
|
8107
8585
|
};
|
|
8108
8586
|
__name(_XRHandPoseSystem, "XRHandPoseSystem");
|
|
8109
8587
|
var XRHandPoseSystem = _XRHandPoseSystem;
|
|
8588
|
+
var XR_HOVER_SHELL_FLAG = "__xrHoverShell";
|
|
8589
|
+
var SHELL_INFLATE = 1.04;
|
|
8590
|
+
var SCALE_SMOOTH_SECONDS = 0.09;
|
|
8591
|
+
var _XRHoverVisualSystem = class _XRHoverVisualSystem {
|
|
8592
|
+
constructor(interactionSystem) {
|
|
8593
|
+
this.records = /* @__PURE__ */ new Map();
|
|
8594
|
+
this.interactionSystem = interactionSystem;
|
|
8595
|
+
}
|
|
8596
|
+
update(world, deltaTime) {
|
|
8597
|
+
if (!world.isXrPresenting()) {
|
|
8598
|
+
this.clearAll(world);
|
|
8599
|
+
return;
|
|
8600
|
+
}
|
|
8601
|
+
const hovered = this.interactionSystem.getHoveredEntityIds();
|
|
8602
|
+
const held = this.interactionSystem.getHeldEntityIds();
|
|
8603
|
+
for (const entityId of hovered) {
|
|
8604
|
+
if (held.has(entityId)) continue;
|
|
8605
|
+
const interactable = world.getComponent(entityId, XRInteractableComponent);
|
|
8606
|
+
if (!interactable?.enabled) continue;
|
|
8607
|
+
if (interactable.hoverBehavior === "none") continue;
|
|
8608
|
+
this.begin(world, entityId, interactable);
|
|
8609
|
+
}
|
|
8610
|
+
for (const [entityId, record] of this.records) {
|
|
8611
|
+
if (!hovered.has(entityId) || held.has(entityId)) {
|
|
8612
|
+
record.active = false;
|
|
8613
|
+
}
|
|
8614
|
+
}
|
|
8615
|
+
this.animate(world, deltaTime);
|
|
8616
|
+
}
|
|
8617
|
+
begin(world, entityId, interactable) {
|
|
8618
|
+
const existing = this.records.get(entityId);
|
|
8619
|
+
if (existing) {
|
|
8620
|
+
existing.active = true;
|
|
8621
|
+
return;
|
|
8622
|
+
}
|
|
8623
|
+
const transform = world.getComponent(entityId, TransformComponent);
|
|
8624
|
+
if (!transform) return;
|
|
8625
|
+
const wantsColor = interactable.hoverBehavior === "color" || interactable.hoverBehavior === "both";
|
|
8626
|
+
this.records.set(entityId, {
|
|
8627
|
+
shell: wantsColor ? this.addShell(world, entityId, interactable) : null,
|
|
8628
|
+
baseScale: new THREE19.Vector3(
|
|
8629
|
+
transform.scale.x,
|
|
8630
|
+
transform.scale.y,
|
|
8631
|
+
transform.scale.z
|
|
8632
|
+
),
|
|
8633
|
+
progress: 0,
|
|
8634
|
+
active: true
|
|
8635
|
+
});
|
|
8636
|
+
}
|
|
8637
|
+
/** Build an inflated back-face copy of the object's meshes. */
|
|
8638
|
+
addShell(world, entityId, interactable) {
|
|
8639
|
+
const object = world.getComponent(entityId, Object3DRef)?.object;
|
|
8640
|
+
if (!object) return null;
|
|
8641
|
+
const material = new THREE19.MeshBasicMaterial({
|
|
8642
|
+
color: new THREE19.Color(interactable.hoverColor),
|
|
8643
|
+
// Back faces only, so the shell shows just outside the silhouette instead
|
|
8644
|
+
// of covering the object.
|
|
8645
|
+
side: THREE19.BackSide,
|
|
8646
|
+
transparent: true,
|
|
8647
|
+
opacity: 0.85,
|
|
8648
|
+
depthWrite: false
|
|
8649
|
+
});
|
|
8650
|
+
const group = new THREE19.Group();
|
|
8651
|
+
group.name = "XRHoverShell";
|
|
8652
|
+
group.userData[XR_HOVER_SHELL_FLAG] = true;
|
|
8653
|
+
group.renderOrder = 998;
|
|
8654
|
+
object.traverse((child) => {
|
|
8655
|
+
if (!(child instanceof THREE19.Mesh) || !child.geometry) return;
|
|
8656
|
+
if (child.userData[XR_HOVER_SHELL_FLAG]) return;
|
|
8657
|
+
const clone2 = new THREE19.Mesh(child.geometry, material);
|
|
8658
|
+
child.updateWorldMatrix(true, false);
|
|
8659
|
+
object.updateWorldMatrix(true, false);
|
|
8660
|
+
clone2.matrixAutoUpdate = false;
|
|
8661
|
+
clone2.matrix.copy(object.matrixWorld).invert().multiply(child.matrixWorld).scale(new THREE19.Vector3(SHELL_INFLATE, SHELL_INFLATE, SHELL_INFLATE));
|
|
8662
|
+
clone2.userData[XR_HOVER_SHELL_FLAG] = true;
|
|
8663
|
+
clone2.raycast = () => {
|
|
8664
|
+
};
|
|
8665
|
+
group.add(clone2);
|
|
8666
|
+
});
|
|
8667
|
+
if (group.children.length === 0) {
|
|
8668
|
+
material.dispose();
|
|
8669
|
+
return null;
|
|
8670
|
+
}
|
|
8671
|
+
object.add(group);
|
|
8672
|
+
return group;
|
|
8673
|
+
}
|
|
8674
|
+
animate(world, deltaTime) {
|
|
8675
|
+
const step = 1 - Math.exp(-Math.max(0, deltaTime) / SCALE_SMOOTH_SECONDS);
|
|
8676
|
+
for (const [entityId, record] of Array.from(this.records)) {
|
|
8677
|
+
const interactable = world.getComponent(entityId, XRInteractableComponent);
|
|
8678
|
+
const target = record.active ? 1 : 0;
|
|
8679
|
+
record.progress += (target - record.progress) * step;
|
|
8680
|
+
const wantsScale = interactable?.hoverBehavior === "scale" || interactable?.hoverBehavior === "both";
|
|
8681
|
+
if (wantsScale) {
|
|
8682
|
+
const transform = world.getComponent(entityId, TransformComponent);
|
|
8683
|
+
if (transform) {
|
|
8684
|
+
const factor = 1 + (interactable.hoverScale - 1) * Math.min(1, record.progress);
|
|
8685
|
+
transform.scale.x = record.baseScale.x * factor;
|
|
8686
|
+
transform.scale.y = record.baseScale.y * factor;
|
|
8687
|
+
transform.scale.z = record.baseScale.z * factor;
|
|
8688
|
+
}
|
|
8689
|
+
}
|
|
8690
|
+
if (!record.active && record.progress < 0.01) {
|
|
8691
|
+
this.finish(world, entityId, record);
|
|
8692
|
+
}
|
|
8693
|
+
}
|
|
8694
|
+
}
|
|
8695
|
+
/** Remove the effect and restore the authored scale exactly. */
|
|
8696
|
+
finish(world, entityId, record) {
|
|
8697
|
+
const transform = world.getComponent(entityId, TransformComponent);
|
|
8698
|
+
if (transform) {
|
|
8699
|
+
transform.scale.x = record.baseScale.x;
|
|
8700
|
+
transform.scale.y = record.baseScale.y;
|
|
8701
|
+
transform.scale.z = record.baseScale.z;
|
|
8702
|
+
}
|
|
8703
|
+
this.disposeShell(record.shell);
|
|
8704
|
+
this.records.delete(entityId);
|
|
8705
|
+
}
|
|
8706
|
+
disposeShell(shell) {
|
|
8707
|
+
if (!shell) return;
|
|
8708
|
+
shell.parent?.remove(shell);
|
|
8709
|
+
shell.traverse((child) => {
|
|
8710
|
+
if (child instanceof THREE19.Mesh) {
|
|
8711
|
+
const material = child.material;
|
|
8712
|
+
if (Array.isArray(material)) {
|
|
8713
|
+
for (const entry of material) entry.dispose();
|
|
8714
|
+
} else {
|
|
8715
|
+
material?.dispose();
|
|
8716
|
+
}
|
|
8717
|
+
}
|
|
8718
|
+
});
|
|
8719
|
+
}
|
|
8720
|
+
clearAll(world) {
|
|
8721
|
+
for (const [entityId, record] of Array.from(this.records)) {
|
|
8722
|
+
this.finish(world, entityId, record);
|
|
8723
|
+
}
|
|
8724
|
+
}
|
|
8725
|
+
dispose() {
|
|
8726
|
+
for (const record of this.records.values()) {
|
|
8727
|
+
this.disposeShell(record.shell);
|
|
8728
|
+
}
|
|
8729
|
+
this.records.clear();
|
|
8730
|
+
}
|
|
8731
|
+
};
|
|
8732
|
+
__name(_XRHoverVisualSystem, "XRHoverVisualSystem");
|
|
8733
|
+
var XRHoverVisualSystem = _XRHoverVisualSystem;
|
|
8110
8734
|
|
|
8111
|
-
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 };
|
|
8112
|
-
//# sourceMappingURL=chunk-
|
|
8113
|
-
//# sourceMappingURL=chunk-
|
|
8735
|
+
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 };
|
|
8736
|
+
//# sourceMappingURL=chunk-KLU2M43M.js.map
|
|
8737
|
+
//# sourceMappingURL=chunk-KLU2M43M.js.map
|