@relu-interactives/spatial-ecs 0.3.4 → 0.3.5
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/{chunk-ID266ZUA.js → chunk-G53MZVKQ.js} +260 -22
- package/dist/chunk-G53MZVKQ.js.map +1 -0
- package/dist/{index-CRmfSYdj.d.ts → index-B-CViRMx.d.ts} +57 -10
- package/dist/{index-Bc0YCz1A.d.cts → index-BvCmmuJ0.d.cts} +57 -10
- package/dist/index.cjs +264 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +44 -3
- package/dist/index.d.ts +44 -3
- package/dist/index.js +2 -2
- package/dist/systems/index.cjs +245 -19
- 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 +1 -1
- package/package.json +1 -1
- package/dist/chunk-ID266ZUA.js.map +0 -1
|
@@ -429,24 +429,42 @@ declare class XRLocomotionSystem implements EcsSystem {
|
|
|
429
429
|
private readonly raycaster;
|
|
430
430
|
/** Per-source latch so one stick push yields exactly one snap turn. */
|
|
431
431
|
private readonly turnLatched;
|
|
432
|
-
/**
|
|
433
|
-
private
|
|
432
|
+
/** Reused arc buffer — aiming runs every frame. */
|
|
433
|
+
private readonly arcPoints;
|
|
434
|
+
/** Curve up to the landing point, for the visual system. Empty when not aiming. */
|
|
435
|
+
private aimCurve;
|
|
436
|
+
private landingPoint;
|
|
437
|
+
/** True once we've tried to self-heal camera parenting for this session. */
|
|
438
|
+
private parentingChecked;
|
|
434
439
|
constructor(inputSystem: XRInputSystem);
|
|
435
440
|
update(world: World, deltaTime: number): void;
|
|
441
|
+
/**
|
|
442
|
+
* Guarantee the render camera is a CHILD of the rig.
|
|
443
|
+
*
|
|
444
|
+
* Locomotion moves the rig, and three composes the head pose against
|
|
445
|
+
* `camera.parent` — so if the camera sits at the scene root instead, moving
|
|
446
|
+
* the rig does nothing at all and the player is frozen in place. Scenes
|
|
447
|
+
* authored before the rig existed (or with the camera re-parented by hand)
|
|
448
|
+
* would otherwise silently fail to move, which is exactly the symptom that is
|
|
449
|
+
* hardest to diagnose from inside a headset. Repairing it via `ParentId` lets
|
|
450
|
+
* `ObjectManagementSystem` reconcile the scene graph normally.
|
|
451
|
+
*/
|
|
452
|
+
private ensureCameraUnderRig;
|
|
436
453
|
/**
|
|
437
454
|
* Snap turning, not smooth turning — rotating the view continuously is the
|
|
438
|
-
* single biggest cause of VR nausea, so the comfort-safe option is
|
|
455
|
+
* single biggest cause of VR nausea, so the comfort-safe option is what's
|
|
439
456
|
* wired to the stick.
|
|
440
457
|
*/
|
|
441
458
|
private applySnapTurn;
|
|
442
459
|
private applySmoothMove;
|
|
443
460
|
private applyTeleport;
|
|
461
|
+
/** Walk the arc segment-by-segment, returning the first surface hit. */
|
|
462
|
+
private raycastArc;
|
|
444
463
|
private collectTeleportTargets;
|
|
445
|
-
/**
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
getTeleportPoint(): THREE.Vector3 | null;
|
|
464
|
+
/** Arc points up to the landing spot this frame; empty when not aiming. */
|
|
465
|
+
getAimCurve(): THREE.Vector3[];
|
|
466
|
+
/** Where the arc currently lands, or null when not aiming at a valid area. */
|
|
467
|
+
getLandingPoint(): THREE.Vector3 | null;
|
|
450
468
|
}
|
|
451
469
|
|
|
452
470
|
/**
|
|
@@ -500,8 +518,21 @@ declare class XRControllerVisualSystem implements EcsSystem {
|
|
|
500
518
|
private readonly ready;
|
|
501
519
|
/** How many controller slots to wire. Two covers every current headset. */
|
|
502
520
|
private readonly slots;
|
|
503
|
-
|
|
521
|
+
/** Optional — when provided, the aim ray only shows over interactables. */
|
|
522
|
+
private readonly interactionSystem;
|
|
523
|
+
private readonly rays;
|
|
524
|
+
constructor(options?: {
|
|
525
|
+
slots?: number;
|
|
526
|
+
interactionSystem?: XRInteractionSystem;
|
|
527
|
+
});
|
|
504
528
|
update(world: World): void;
|
|
529
|
+
/**
|
|
530
|
+
* Show the aim ray only when it is meaningful: hovering something
|
|
531
|
+
* interactive, or mid-grab. A permanently-drawn ray is visual noise, and it
|
|
532
|
+
* implies everything is clickable when most of the scene is not. Teleport
|
|
533
|
+
* aiming has its own arc, so the straight ray stays hidden for that.
|
|
534
|
+
*/
|
|
535
|
+
private updateRayVisibility;
|
|
505
536
|
/**
|
|
506
537
|
* Parent the visuals to the XR rig when there is one, so locomotion moves the
|
|
507
538
|
* hands with the player. Falls back to the scene root.
|
|
@@ -511,4 +542,20 @@ declare class XRControllerVisualSystem implements EcsSystem {
|
|
|
511
542
|
dispose(): void;
|
|
512
543
|
}
|
|
513
544
|
|
|
514
|
-
|
|
545
|
+
declare class XRTeleportVisualSystem implements EcsSystem {
|
|
546
|
+
private readonly locomotionSystem;
|
|
547
|
+
private readonly group;
|
|
548
|
+
private readonly arc;
|
|
549
|
+
private readonly arcGeometry;
|
|
550
|
+
private readonly marker;
|
|
551
|
+
private attached;
|
|
552
|
+
constructor(locomotionSystem: XRLocomotionSystem);
|
|
553
|
+
update(world: World): void;
|
|
554
|
+
private updateArcGeometry;
|
|
555
|
+
private createRing;
|
|
556
|
+
private createDot;
|
|
557
|
+
private setVisible;
|
|
558
|
+
dispose(): void;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
export { AnimationSystem as A, CameraSyncSystem as C, EnvironmentSyncSystem as E, InstancedMeshSystem as I, LightSyncSystem as L, MaterialSyncSystem as M, NO_XR_CAPABILITIES as N, ObjectVisibilitySystem as O, PhysicsSyncSystem as P, SCRIPT_OBJECT_ROOT_FLAG as S, VRTeleportAreaSystem as V, type XrCapabilities as X, type XrInputState as a, AudioSystem as b, MeshGeometrySystem as c, type ModuleLoader as d, PostprocessingSyncSystem as e, ScriptBehaviourSystem as f, ScriptObjectSystem as g, type SelectionContext as h, VideoSystem as i, XRControllerVisualSystem as j, XRInputSystem as k, XRInteractionSystem as l, XRLocomotionSystem as m, XRSessionSystem as n, XRTeleportVisualSystem as o, type XrHandedness as p, type XrInputKind as q, readXrCapabilities as r };
|
|
@@ -429,24 +429,42 @@ declare class XRLocomotionSystem implements EcsSystem {
|
|
|
429
429
|
private readonly raycaster;
|
|
430
430
|
/** Per-source latch so one stick push yields exactly one snap turn. */
|
|
431
431
|
private readonly turnLatched;
|
|
432
|
-
/**
|
|
433
|
-
private
|
|
432
|
+
/** Reused arc buffer — aiming runs every frame. */
|
|
433
|
+
private readonly arcPoints;
|
|
434
|
+
/** Curve up to the landing point, for the visual system. Empty when not aiming. */
|
|
435
|
+
private aimCurve;
|
|
436
|
+
private landingPoint;
|
|
437
|
+
/** True once we've tried to self-heal camera parenting for this session. */
|
|
438
|
+
private parentingChecked;
|
|
434
439
|
constructor(inputSystem: XRInputSystem);
|
|
435
440
|
update(world: World, deltaTime: number): void;
|
|
441
|
+
/**
|
|
442
|
+
* Guarantee the render camera is a CHILD of the rig.
|
|
443
|
+
*
|
|
444
|
+
* Locomotion moves the rig, and three composes the head pose against
|
|
445
|
+
* `camera.parent` — so if the camera sits at the scene root instead, moving
|
|
446
|
+
* the rig does nothing at all and the player is frozen in place. Scenes
|
|
447
|
+
* authored before the rig existed (or with the camera re-parented by hand)
|
|
448
|
+
* would otherwise silently fail to move, which is exactly the symptom that is
|
|
449
|
+
* hardest to diagnose from inside a headset. Repairing it via `ParentId` lets
|
|
450
|
+
* `ObjectManagementSystem` reconcile the scene graph normally.
|
|
451
|
+
*/
|
|
452
|
+
private ensureCameraUnderRig;
|
|
436
453
|
/**
|
|
437
454
|
* Snap turning, not smooth turning — rotating the view continuously is the
|
|
438
|
-
* single biggest cause of VR nausea, so the comfort-safe option is
|
|
455
|
+
* single biggest cause of VR nausea, so the comfort-safe option is what's
|
|
439
456
|
* wired to the stick.
|
|
440
457
|
*/
|
|
441
458
|
private applySnapTurn;
|
|
442
459
|
private applySmoothMove;
|
|
443
460
|
private applyTeleport;
|
|
461
|
+
/** Walk the arc segment-by-segment, returning the first surface hit. */
|
|
462
|
+
private raycastArc;
|
|
444
463
|
private collectTeleportTargets;
|
|
445
|
-
/**
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
getTeleportPoint(): THREE.Vector3 | null;
|
|
464
|
+
/** Arc points up to the landing spot this frame; empty when not aiming. */
|
|
465
|
+
getAimCurve(): THREE.Vector3[];
|
|
466
|
+
/** Where the arc currently lands, or null when not aiming at a valid area. */
|
|
467
|
+
getLandingPoint(): THREE.Vector3 | null;
|
|
450
468
|
}
|
|
451
469
|
|
|
452
470
|
/**
|
|
@@ -500,8 +518,21 @@ declare class XRControllerVisualSystem implements EcsSystem {
|
|
|
500
518
|
private readonly ready;
|
|
501
519
|
/** How many controller slots to wire. Two covers every current headset. */
|
|
502
520
|
private readonly slots;
|
|
503
|
-
|
|
521
|
+
/** Optional — when provided, the aim ray only shows over interactables. */
|
|
522
|
+
private readonly interactionSystem;
|
|
523
|
+
private readonly rays;
|
|
524
|
+
constructor(options?: {
|
|
525
|
+
slots?: number;
|
|
526
|
+
interactionSystem?: XRInteractionSystem;
|
|
527
|
+
});
|
|
504
528
|
update(world: World): void;
|
|
529
|
+
/**
|
|
530
|
+
* Show the aim ray only when it is meaningful: hovering something
|
|
531
|
+
* interactive, or mid-grab. A permanently-drawn ray is visual noise, and it
|
|
532
|
+
* implies everything is clickable when most of the scene is not. Teleport
|
|
533
|
+
* aiming has its own arc, so the straight ray stays hidden for that.
|
|
534
|
+
*/
|
|
535
|
+
private updateRayVisibility;
|
|
505
536
|
/**
|
|
506
537
|
* Parent the visuals to the XR rig when there is one, so locomotion moves the
|
|
507
538
|
* hands with the player. Falls back to the scene root.
|
|
@@ -511,4 +542,20 @@ declare class XRControllerVisualSystem implements EcsSystem {
|
|
|
511
542
|
dispose(): void;
|
|
512
543
|
}
|
|
513
544
|
|
|
514
|
-
|
|
545
|
+
declare class XRTeleportVisualSystem implements EcsSystem {
|
|
546
|
+
private readonly locomotionSystem;
|
|
547
|
+
private readonly group;
|
|
548
|
+
private readonly arc;
|
|
549
|
+
private readonly arcGeometry;
|
|
550
|
+
private readonly marker;
|
|
551
|
+
private attached;
|
|
552
|
+
constructor(locomotionSystem: XRLocomotionSystem);
|
|
553
|
+
update(world: World): void;
|
|
554
|
+
private updateArcGeometry;
|
|
555
|
+
private createRing;
|
|
556
|
+
private createDot;
|
|
557
|
+
private setVisible;
|
|
558
|
+
dispose(): void;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
export { AnimationSystem as A, CameraSyncSystem as C, EnvironmentSyncSystem as E, InstancedMeshSystem as I, LightSyncSystem as L, MaterialSyncSystem as M, NO_XR_CAPABILITIES as N, ObjectVisibilitySystem as O, PhysicsSyncSystem as P, SCRIPT_OBJECT_ROOT_FLAG as S, VRTeleportAreaSystem as V, type XrCapabilities as X, type XrInputState as a, AudioSystem as b, MeshGeometrySystem as c, type ModuleLoader as d, PostprocessingSyncSystem as e, ScriptBehaviourSystem as f, ScriptObjectSystem as g, type SelectionContext as h, VideoSystem as i, XRControllerVisualSystem as j, XRInputSystem as k, XRInteractionSystem as l, XRLocomotionSystem as m, XRSessionSystem as n, XRTeleportVisualSystem as o, type XrHandedness as p, type XrInputKind as q, readXrCapabilities as r };
|
package/dist/index.cjs
CHANGED
|
@@ -10507,6 +10507,45 @@ var _XRInteractionSystem = class _XRInteractionSystem {
|
|
|
10507
10507
|
};
|
|
10508
10508
|
__name(_XRInteractionSystem, "XRInteractionSystem");
|
|
10509
10509
|
var XRInteractionSystem = _XRInteractionSystem;
|
|
10510
|
+
var ARC_GRAVITY = 9.8;
|
|
10511
|
+
var ARC_SPEED = 7;
|
|
10512
|
+
var ARC_STEPS = 24;
|
|
10513
|
+
var ARC_MAX_TIME = 2;
|
|
10514
|
+
function sampleTeleportArc(origin, direction, out = [], options) {
|
|
10515
|
+
const speed = options?.speed ?? ARC_SPEED;
|
|
10516
|
+
const gravity = options?.gravity ?? ARC_GRAVITY;
|
|
10517
|
+
const steps = Math.max(2, options?.steps ?? ARC_STEPS);
|
|
10518
|
+
const maxTime = options?.maxTime ?? ARC_MAX_TIME;
|
|
10519
|
+
out.length = 0;
|
|
10520
|
+
const velocity = direction.clone().normalize().multiplyScalar(speed);
|
|
10521
|
+
for (let i = 0; i < steps; i += 1) {
|
|
10522
|
+
const t = i / (steps - 1) * maxTime;
|
|
10523
|
+
out.push(
|
|
10524
|
+
new THREE38__namespace.Vector3(
|
|
10525
|
+
origin.x + velocity.x * t,
|
|
10526
|
+
origin.y + velocity.y * t - 0.5 * gravity * t * t,
|
|
10527
|
+
origin.z + velocity.z * t
|
|
10528
|
+
)
|
|
10529
|
+
);
|
|
10530
|
+
}
|
|
10531
|
+
return out;
|
|
10532
|
+
}
|
|
10533
|
+
__name(sampleTeleportArc, "sampleTeleportArc");
|
|
10534
|
+
function arcGroundCrossing(points, groundY) {
|
|
10535
|
+
for (let i = 1; i < points.length; i += 1) {
|
|
10536
|
+
const previous = points[i - 1];
|
|
10537
|
+
const current = points[i];
|
|
10538
|
+
if (previous.y >= groundY && current.y <= groundY) {
|
|
10539
|
+
const span = previous.y - current.y;
|
|
10540
|
+
const alpha = span > 1e-6 ? (previous.y - groundY) / span : 0;
|
|
10541
|
+
return new THREE38__namespace.Vector3().lerpVectors(previous, current, alpha);
|
|
10542
|
+
}
|
|
10543
|
+
}
|
|
10544
|
+
return null;
|
|
10545
|
+
}
|
|
10546
|
+
__name(arcGroundCrossing, "arcGroundCrossing");
|
|
10547
|
+
|
|
10548
|
+
// core/systems/XRLocomotionSystem.ts
|
|
10510
10549
|
var UP = new THREE38__namespace.Vector3(0, 1, 0);
|
|
10511
10550
|
var AXIS_DEADZONE = 0.5;
|
|
10512
10551
|
var _XRLocomotionSystem = class _XRLocomotionSystem {
|
|
@@ -10514,13 +10553,26 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
|
|
|
10514
10553
|
this.raycaster = new THREE38__namespace.Raycaster();
|
|
10515
10554
|
/** Per-source latch so one stick push yields exactly one snap turn. */
|
|
10516
10555
|
this.turnLatched = /* @__PURE__ */ new WeakSet();
|
|
10517
|
-
/**
|
|
10518
|
-
this.
|
|
10556
|
+
/** Reused arc buffer — aiming runs every frame. */
|
|
10557
|
+
this.arcPoints = [];
|
|
10558
|
+
/** Curve up to the landing point, for the visual system. Empty when not aiming. */
|
|
10559
|
+
this.aimCurve = [];
|
|
10560
|
+
this.landingPoint = null;
|
|
10561
|
+
/** True once we've tried to self-heal camera parenting for this session. */
|
|
10562
|
+
this.parentingChecked = false;
|
|
10519
10563
|
this.inputSystem = inputSystem;
|
|
10520
10564
|
}
|
|
10521
10565
|
update(world, deltaTime) {
|
|
10522
|
-
this.
|
|
10523
|
-
|
|
10566
|
+
this.aimCurve = [];
|
|
10567
|
+
this.landingPoint = null;
|
|
10568
|
+
if (!world.isXrPresenting()) {
|
|
10569
|
+
this.parentingChecked = false;
|
|
10570
|
+
return;
|
|
10571
|
+
}
|
|
10572
|
+
if (!this.parentingChecked) {
|
|
10573
|
+
this.parentingChecked = true;
|
|
10574
|
+
this.ensureCameraUnderRig(world);
|
|
10575
|
+
}
|
|
10524
10576
|
const rigEntityId = world.query(XRRigComponent, TransformComponent)[0];
|
|
10525
10577
|
if (typeof rigEntityId !== "number") return;
|
|
10526
10578
|
const rig = world.getComponent(rigEntityId, XRRigComponent);
|
|
@@ -10537,9 +10589,37 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
|
|
|
10537
10589
|
this.applySmoothMove(world, rig, rigTransform, inputs, deltaTime);
|
|
10538
10590
|
}
|
|
10539
10591
|
}
|
|
10592
|
+
/**
|
|
10593
|
+
* Guarantee the render camera is a CHILD of the rig.
|
|
10594
|
+
*
|
|
10595
|
+
* Locomotion moves the rig, and three composes the head pose against
|
|
10596
|
+
* `camera.parent` — so if the camera sits at the scene root instead, moving
|
|
10597
|
+
* the rig does nothing at all and the player is frozen in place. Scenes
|
|
10598
|
+
* authored before the rig existed (or with the camera re-parented by hand)
|
|
10599
|
+
* would otherwise silently fail to move, which is exactly the symptom that is
|
|
10600
|
+
* hardest to diagnose from inside a headset. Repairing it via `ParentId` lets
|
|
10601
|
+
* `ObjectManagementSystem` reconcile the scene graph normally.
|
|
10602
|
+
*/
|
|
10603
|
+
ensureCameraUnderRig(world) {
|
|
10604
|
+
const rigEntityId = world.query(XRRigComponent)[0];
|
|
10605
|
+
if (typeof rigEntityId !== "number") return;
|
|
10606
|
+
const activeCamera = world.getCamera();
|
|
10607
|
+
for (const entityId of world.query(CameraComponent, Object3DRef)) {
|
|
10608
|
+
if (world.getComponent(entityId, Object3DRef)?.object !== activeCamera) {
|
|
10609
|
+
continue;
|
|
10610
|
+
}
|
|
10611
|
+
const parent = world.getComponent(entityId, ParentId);
|
|
10612
|
+
if (parent) {
|
|
10613
|
+
if (parent.value !== rigEntityId) parent.value = rigEntityId;
|
|
10614
|
+
} else {
|
|
10615
|
+
world.addComponent(entityId, new ParentId(rigEntityId));
|
|
10616
|
+
}
|
|
10617
|
+
return;
|
|
10618
|
+
}
|
|
10619
|
+
}
|
|
10540
10620
|
/**
|
|
10541
10621
|
* Snap turning, not smooth turning — rotating the view continuously is the
|
|
10542
|
-
* single biggest cause of VR nausea, so the comfort-safe option is
|
|
10622
|
+
* single biggest cause of VR nausea, so the comfort-safe option is what's
|
|
10543
10623
|
* wired to the stick.
|
|
10544
10624
|
*/
|
|
10545
10625
|
applySnapTurn(rig, transform, inputs) {
|
|
@@ -10553,8 +10633,7 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
|
|
|
10553
10633
|
}
|
|
10554
10634
|
if (this.turnLatched.has(source)) continue;
|
|
10555
10635
|
this.turnLatched.add(source);
|
|
10556
|
-
|
|
10557
|
-
transform.rotation.y -= Math.sign(x) * step;
|
|
10636
|
+
transform.rotation.y -= Math.sign(x) * THREE38__namespace.MathUtils.degToRad(rig.snapTurnDegrees);
|
|
10558
10637
|
}
|
|
10559
10638
|
}
|
|
10560
10639
|
applySmoothMove(world, rig, transform, inputs, deltaTime) {
|
|
@@ -10579,16 +10658,41 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
|
|
|
10579
10658
|
const targets = this.collectTeleportTargets(world);
|
|
10580
10659
|
if (targets.length === 0) return;
|
|
10581
10660
|
for (const input of inputs) {
|
|
10582
|
-
|
|
10583
|
-
const
|
|
10661
|
+
if (!input.select && !input.selectEnd) continue;
|
|
10662
|
+
const points = sampleTeleportArc(
|
|
10663
|
+
input.rayOrigin,
|
|
10664
|
+
input.rayDirection,
|
|
10665
|
+
this.arcPoints
|
|
10666
|
+
);
|
|
10667
|
+
const hit = this.raycastArc(points, targets);
|
|
10584
10668
|
if (!hit) continue;
|
|
10585
|
-
this.
|
|
10669
|
+
this.landingPoint = hit.point;
|
|
10670
|
+
this.aimCurve = points.slice(0, hit.segmentIndex + 1).concat(hit.point);
|
|
10586
10671
|
if (input.selectEnd) {
|
|
10587
10672
|
transform.position.x = hit.point.x;
|
|
10588
10673
|
transform.position.y = hit.point.y;
|
|
10589
10674
|
transform.position.z = hit.point.z;
|
|
10675
|
+
this.aimCurve = [];
|
|
10676
|
+
this.landingPoint = null;
|
|
10677
|
+
}
|
|
10678
|
+
}
|
|
10679
|
+
}
|
|
10680
|
+
/** Walk the arc segment-by-segment, returning the first surface hit. */
|
|
10681
|
+
raycastArc(points, targets) {
|
|
10682
|
+
for (let i = 1; i < points.length; i += 1) {
|
|
10683
|
+
const from = points[i - 1];
|
|
10684
|
+
const to = points[i];
|
|
10685
|
+
const delta = new THREE38__namespace.Vector3().subVectors(to, from);
|
|
10686
|
+
const distance = delta.length();
|
|
10687
|
+
if (distance < 1e-6) continue;
|
|
10688
|
+
this.raycaster.set(from, delta.divideScalar(distance));
|
|
10689
|
+
this.raycaster.far = distance;
|
|
10690
|
+
const hit = this.raycaster.intersectObjects(targets, true)[0];
|
|
10691
|
+
if (hit) {
|
|
10692
|
+
return { point: hit.point.clone(), segmentIndex: i - 1 };
|
|
10590
10693
|
}
|
|
10591
10694
|
}
|
|
10695
|
+
return null;
|
|
10592
10696
|
}
|
|
10593
10697
|
collectTeleportTargets(world) {
|
|
10594
10698
|
const objects = [];
|
|
@@ -10601,12 +10705,13 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
|
|
|
10601
10705
|
}
|
|
10602
10706
|
return objects;
|
|
10603
10707
|
}
|
|
10604
|
-
/**
|
|
10605
|
-
|
|
10606
|
-
|
|
10607
|
-
|
|
10608
|
-
|
|
10609
|
-
|
|
10708
|
+
/** Arc points up to the landing spot this frame; empty when not aiming. */
|
|
10709
|
+
getAimCurve() {
|
|
10710
|
+
return this.aimCurve;
|
|
10711
|
+
}
|
|
10712
|
+
/** Where the arc currently lands, or null when not aiming at a valid area. */
|
|
10713
|
+
getLandingPoint() {
|
|
10714
|
+
return this.landingPoint;
|
|
10610
10715
|
}
|
|
10611
10716
|
};
|
|
10612
10717
|
__name(_XRLocomotionSystem, "XRLocomotionSystem");
|
|
@@ -10768,7 +10873,7 @@ var _VRTeleportAreaSystem = class _VRTeleportAreaSystem {
|
|
|
10768
10873
|
__name(_VRTeleportAreaSystem, "VRTeleportAreaSystem");
|
|
10769
10874
|
var VRTeleportAreaSystem = _VRTeleportAreaSystem;
|
|
10770
10875
|
var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
10771
|
-
constructor(
|
|
10876
|
+
constructor(options) {
|
|
10772
10877
|
this.controllerModelFactory = new XRControllerModelFactory_js.XRControllerModelFactory();
|
|
10773
10878
|
this.handModelFactory = new XRHandModelFactory_js.XRHandModelFactory();
|
|
10774
10879
|
this.group = new THREE38__namespace.Group();
|
|
@@ -10776,7 +10881,9 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
|
10776
10881
|
this.attachedTo = null;
|
|
10777
10882
|
/** Index → whether we've already attached visuals for that slot. */
|
|
10778
10883
|
this.ready = /* @__PURE__ */ new Set();
|
|
10779
|
-
this.
|
|
10884
|
+
this.rays = [];
|
|
10885
|
+
this.slots = options?.slots ?? 2;
|
|
10886
|
+
this.interactionSystem = options?.interactionSystem ?? null;
|
|
10780
10887
|
this.group.name = "XRControllerVisuals";
|
|
10781
10888
|
this.group.userData.ecsPreviewHidden = true;
|
|
10782
10889
|
}
|
|
@@ -10784,6 +10891,7 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
|
10784
10891
|
const renderer = world.getRenderer();
|
|
10785
10892
|
if (!renderer.xr?.enabled) return;
|
|
10786
10893
|
this.ensureAttached(world);
|
|
10894
|
+
this.updateRayVisibility();
|
|
10787
10895
|
if (this.built) return;
|
|
10788
10896
|
for (let index = 0; index < this.slots; index += 1) {
|
|
10789
10897
|
if (this.ready.has(index)) continue;
|
|
@@ -10791,7 +10899,9 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
|
10791
10899
|
const grip = renderer.xr.getControllerGrip(index);
|
|
10792
10900
|
const hand = renderer.xr.getHand(index);
|
|
10793
10901
|
if (!controller || !grip || !hand) continue;
|
|
10794
|
-
|
|
10902
|
+
const ray = this.createRay();
|
|
10903
|
+
this.rays.push(ray);
|
|
10904
|
+
controller.add(ray);
|
|
10795
10905
|
this.group.add(controller);
|
|
10796
10906
|
grip.add(this.controllerModelFactory.createControllerModel(grip));
|
|
10797
10907
|
this.group.add(grip);
|
|
@@ -10803,6 +10913,17 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
|
10803
10913
|
this.built = true;
|
|
10804
10914
|
}
|
|
10805
10915
|
}
|
|
10916
|
+
/**
|
|
10917
|
+
* Show the aim ray only when it is meaningful: hovering something
|
|
10918
|
+
* interactive, or mid-grab. A permanently-drawn ray is visual noise, and it
|
|
10919
|
+
* implies everything is clickable when most of the scene is not. Teleport
|
|
10920
|
+
* aiming has its own arc, so the straight ray stays hidden for that.
|
|
10921
|
+
*/
|
|
10922
|
+
updateRayVisibility() {
|
|
10923
|
+
if (!this.interactionSystem) return;
|
|
10924
|
+
const active = this.interactionSystem.getHoveredEntityId() !== null || this.interactionSystem.isGrabbing();
|
|
10925
|
+
for (const ray of this.rays) ray.visible = active;
|
|
10926
|
+
}
|
|
10806
10927
|
/**
|
|
10807
10928
|
* Parent the visuals to the XR rig when there is one, so locomotion moves the
|
|
10808
10929
|
* hands with the player. Falls back to the scene root.
|
|
@@ -10828,6 +10949,7 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
|
10828
10949
|
const line = new THREE38__namespace.Line(geometry, material);
|
|
10829
10950
|
line.name = "XRPointerRay";
|
|
10830
10951
|
line.renderOrder = 999;
|
|
10952
|
+
line.visible = this.interactionSystem === null;
|
|
10831
10953
|
return line;
|
|
10832
10954
|
}
|
|
10833
10955
|
dispose() {
|
|
@@ -10843,6 +10965,7 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
|
10843
10965
|
}
|
|
10844
10966
|
});
|
|
10845
10967
|
this.group.clear();
|
|
10968
|
+
this.rays.length = 0;
|
|
10846
10969
|
this.ready.clear();
|
|
10847
10970
|
this.built = false;
|
|
10848
10971
|
this.attachedTo = null;
|
|
@@ -10850,6 +10973,121 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
|
|
|
10850
10973
|
};
|
|
10851
10974
|
__name(_XRControllerVisualSystem, "XRControllerVisualSystem");
|
|
10852
10975
|
var XRControllerVisualSystem = _XRControllerVisualSystem;
|
|
10976
|
+
var MARKER_RADIUS = 0.28;
|
|
10977
|
+
var ACCENT = new THREE38__namespace.Color("#4da3ff");
|
|
10978
|
+
var _XRTeleportVisualSystem = class _XRTeleportVisualSystem {
|
|
10979
|
+
constructor(locomotionSystem) {
|
|
10980
|
+
this.group = new THREE38__namespace.Group();
|
|
10981
|
+
this.arcGeometry = new THREE38__namespace.BufferGeometry();
|
|
10982
|
+
this.marker = new THREE38__namespace.Group();
|
|
10983
|
+
this.attached = false;
|
|
10984
|
+
this.locomotionSystem = locomotionSystem;
|
|
10985
|
+
this.group.name = "XRTeleportVisuals";
|
|
10986
|
+
this.group.userData.ecsPreviewHidden = true;
|
|
10987
|
+
const arcMaterial = new THREE38__namespace.LineBasicMaterial({
|
|
10988
|
+
vertexColors: true,
|
|
10989
|
+
transparent: true,
|
|
10990
|
+
depthTest: false
|
|
10991
|
+
});
|
|
10992
|
+
this.arc = new THREE38__namespace.Line(this.arcGeometry, arcMaterial);
|
|
10993
|
+
this.arc.frustumCulled = false;
|
|
10994
|
+
this.arc.renderOrder = 998;
|
|
10995
|
+
this.group.add(this.arc);
|
|
10996
|
+
this.marker.add(this.createRing(), this.createDot());
|
|
10997
|
+
this.marker.renderOrder = 999;
|
|
10998
|
+
this.group.add(this.marker);
|
|
10999
|
+
this.setVisible(false);
|
|
11000
|
+
}
|
|
11001
|
+
update(world) {
|
|
11002
|
+
if (!this.attached) {
|
|
11003
|
+
world.getScene().add(this.group);
|
|
11004
|
+
this.attached = true;
|
|
11005
|
+
}
|
|
11006
|
+
const curve = this.locomotionSystem.getAimCurve();
|
|
11007
|
+
const landing = this.locomotionSystem.getLandingPoint();
|
|
11008
|
+
if (!landing || curve.length < 2) {
|
|
11009
|
+
this.setVisible(false);
|
|
11010
|
+
return;
|
|
11011
|
+
}
|
|
11012
|
+
this.updateArcGeometry(curve);
|
|
11013
|
+
this.marker.position.copy(landing);
|
|
11014
|
+
this.marker.position.y += 0.01;
|
|
11015
|
+
this.setVisible(true);
|
|
11016
|
+
}
|
|
11017
|
+
updateArcGeometry(curve) {
|
|
11018
|
+
const count = curve.length;
|
|
11019
|
+
const positions = new Float32Array(count * 3);
|
|
11020
|
+
const colors = new Float32Array(count * 3);
|
|
11021
|
+
for (let i = 0; i < count; i += 1) {
|
|
11022
|
+
const point = curve[i];
|
|
11023
|
+
positions[i * 3] = point.x;
|
|
11024
|
+
positions[i * 3 + 1] = point.y;
|
|
11025
|
+
positions[i * 3 + 2] = point.z;
|
|
11026
|
+
const t = count > 1 ? i / (count - 1) : 0;
|
|
11027
|
+
const fade = 1 - t * 0.75;
|
|
11028
|
+
colors[i * 3] = ACCENT.r * fade;
|
|
11029
|
+
colors[i * 3 + 1] = ACCENT.g * fade;
|
|
11030
|
+
colors[i * 3 + 2] = ACCENT.b * fade;
|
|
11031
|
+
}
|
|
11032
|
+
this.arcGeometry.setAttribute(
|
|
11033
|
+
"position",
|
|
11034
|
+
new THREE38__namespace.BufferAttribute(positions, 3)
|
|
11035
|
+
);
|
|
11036
|
+
this.arcGeometry.setAttribute("color", new THREE38__namespace.BufferAttribute(colors, 3));
|
|
11037
|
+
this.arcGeometry.computeBoundingSphere();
|
|
11038
|
+
}
|
|
11039
|
+
createRing() {
|
|
11040
|
+
const geometry = new THREE38__namespace.RingGeometry(
|
|
11041
|
+
MARKER_RADIUS * 0.72,
|
|
11042
|
+
MARKER_RADIUS,
|
|
11043
|
+
48
|
|
11044
|
+
);
|
|
11045
|
+
geometry.rotateX(-Math.PI / 2);
|
|
11046
|
+
return new THREE38__namespace.Mesh(
|
|
11047
|
+
geometry,
|
|
11048
|
+
new THREE38__namespace.MeshBasicMaterial({
|
|
11049
|
+
color: ACCENT,
|
|
11050
|
+
transparent: true,
|
|
11051
|
+
opacity: 0.9,
|
|
11052
|
+
side: THREE38__namespace.DoubleSide,
|
|
11053
|
+
depthTest: false
|
|
11054
|
+
})
|
|
11055
|
+
);
|
|
11056
|
+
}
|
|
11057
|
+
createDot() {
|
|
11058
|
+
const geometry = new THREE38__namespace.CircleGeometry(MARKER_RADIUS * 0.16, 24);
|
|
11059
|
+
geometry.rotateX(-Math.PI / 2);
|
|
11060
|
+
return new THREE38__namespace.Mesh(
|
|
11061
|
+
geometry,
|
|
11062
|
+
new THREE38__namespace.MeshBasicMaterial({
|
|
11063
|
+
color: ACCENT,
|
|
11064
|
+
transparent: true,
|
|
11065
|
+
opacity: 0.55,
|
|
11066
|
+
side: THREE38__namespace.DoubleSide,
|
|
11067
|
+
depthTest: false
|
|
11068
|
+
})
|
|
11069
|
+
);
|
|
11070
|
+
}
|
|
11071
|
+
setVisible(visible) {
|
|
11072
|
+
this.group.visible = visible;
|
|
11073
|
+
}
|
|
11074
|
+
dispose() {
|
|
11075
|
+
this.group.removeFromParent();
|
|
11076
|
+
this.group.traverse((child) => {
|
|
11077
|
+
const mesh = child;
|
|
11078
|
+
mesh.geometry?.dispose?.();
|
|
11079
|
+
const material = mesh.material;
|
|
11080
|
+
if (Array.isArray(material)) {
|
|
11081
|
+
for (const entry of material) entry.dispose?.();
|
|
11082
|
+
} else {
|
|
11083
|
+
material?.dispose?.();
|
|
11084
|
+
}
|
|
11085
|
+
});
|
|
11086
|
+
this.attached = false;
|
|
11087
|
+
}
|
|
11088
|
+
};
|
|
11089
|
+
__name(_XRTeleportVisualSystem, "XRTeleportVisualSystem");
|
|
11090
|
+
var XRTeleportVisualSystem = _XRTeleportVisualSystem;
|
|
10853
11091
|
|
|
10854
11092
|
// core/World.ts
|
|
10855
11093
|
var _World = class _World {
|
|
@@ -12224,6 +12462,10 @@ function serializeEntitySubtree(world, rootId, options) {
|
|
|
12224
12462
|
__name(serializeEntitySubtree, "serializeEntitySubtree");
|
|
12225
12463
|
|
|
12226
12464
|
exports.ADDED_NODE_MARKER_COMPONENT = ADDED_NODE_MARKER_COMPONENT;
|
|
12465
|
+
exports.ARC_GRAVITY = ARC_GRAVITY;
|
|
12466
|
+
exports.ARC_MAX_TIME = ARC_MAX_TIME;
|
|
12467
|
+
exports.ARC_SPEED = ARC_SPEED;
|
|
12468
|
+
exports.ARC_STEPS = ARC_STEPS;
|
|
12227
12469
|
exports.AnimationStateMachine = AnimationStateMachine;
|
|
12228
12470
|
exports.AnimationStateManager = AnimationStateManager;
|
|
12229
12471
|
exports.AnimationSystem = AnimationSystem;
|
|
@@ -12265,7 +12507,9 @@ exports.XRInputSystem = XRInputSystem;
|
|
|
12265
12507
|
exports.XRInteractionSystem = XRInteractionSystem;
|
|
12266
12508
|
exports.XRLocomotionSystem = XRLocomotionSystem;
|
|
12267
12509
|
exports.XRSessionSystem = XRSessionSystem;
|
|
12510
|
+
exports.XRTeleportVisualSystem = XRTeleportVisualSystem;
|
|
12268
12511
|
exports.applyPrefabToSnapshotInstances = applyPrefabToSnapshotInstances;
|
|
12512
|
+
exports.arcGroundCrossing = arcGroundCrossing;
|
|
12269
12513
|
exports.buildComponentValueMaps = buildComponentValueMaps;
|
|
12270
12514
|
exports.buildNodeKeyMapsFromSnapshot = buildNodeKeyMapsFromSnapshot;
|
|
12271
12515
|
exports.buildNodeMapsFromSnapshot = buildNodeMapsFromSnapshot;
|
|
@@ -12330,6 +12574,7 @@ exports.remapSnapshotEntityIds = remapSnapshotEntityIds;
|
|
|
12330
12574
|
exports.resolveDracoDecoderPath = resolveDracoDecoderPath;
|
|
12331
12575
|
exports.restoreComponentState = restoreComponentState;
|
|
12332
12576
|
exports.restorePostCreateComponents = restorePostCreateComponents;
|
|
12577
|
+
exports.sampleTeleportArc = sampleTeleportArc;
|
|
12333
12578
|
exports.serializeEntitySubtree = serializeEntitySubtree;
|
|
12334
12579
|
exports.setDracoDecoderPath = setDracoDecoderPath;
|
|
12335
12580
|
exports.setPrefabAssetUrlResolver = setPrefabAssetUrlResolver;
|