@heliguy-xyz/splat-viewer 1.0.0-rc.4 → 1.0.0-rc.6

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.
@@ -104343,10 +104343,13 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput {
104343
104343
  if (nextMode === this.mode)
104344
104344
  return;
104345
104345
  const prev = this.mode;
104346
- // Preserve camera transform
104346
+ // Preserve camera transform (position + rotation)
104347
104347
  const pos = this.camera.getPosition
104348
104348
  ? this.camera.getPosition().clone()
104349
104349
  : { x: 0, y: 0, z: 10 };
104350
+ const rot = this.camera.getRotation
104351
+ ? this.camera.getRotation().clone()
104352
+ : null;
104350
104353
  // Switch
104351
104354
  if (nextMode === 'fly') {
104352
104355
  this.deactivateOrbitMode();
@@ -104357,6 +104360,9 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput {
104357
104360
  this.activateOrbitMode();
104358
104361
  }
104359
104362
  this.camera.setPosition(pos);
104363
+ if (rot && this.camera.setRotation) {
104364
+ this.camera.setRotation(rot);
104365
+ }
104360
104366
  this.mode = nextMode;
104361
104367
  // Emit camera-mode-changed
104362
104368
  this.emit('camera-mode-changed', { mode: nextMode, previousMode: prev });
@@ -104461,6 +104467,22 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput {
104461
104467
  return;
104462
104468
  if (typeof this.fly.activate === 'function')
104463
104469
  this.fly.activate();
104470
+ // Align fly camera internal orientation with the current camera rotation so that
104471
+ // switching from orbit -> fly does not snap the view back to the initial direction.
104472
+ try {
104473
+ const euler = this.camera.getEulerAngles
104474
+ ? this.camera.getEulerAngles()
104475
+ : null;
104476
+ if (euler) {
104477
+ // These properties are part of the FlyCamera runtime state
104478
+ ;
104479
+ this.fly._pitch = euler.x || 0;
104480
+ this.fly._yaw = euler.y || 0;
104481
+ }
104482
+ }
104483
+ catch {
104484
+ // Best-effort sync; ignore if camera or script API differs
104485
+ }
104464
104486
  }
104465
104487
  deactivateFlyMode() {
104466
104488
  if (!this.fly)
@@ -104580,7 +104602,11 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput {
104580
104602
  : { x: 0, y: 0, z: 0 };
104581
104603
  this.emitFlyEvent?.('fly-camera-move', {
104582
104604
  position: { x: pos.x, y: pos.y, z: pos.z },
104583
- velocity: { x: this._velocity.x, y: this._velocity.y, z: this._velocity.z },
104605
+ velocity: {
104606
+ x: this._velocity.x,
104607
+ y: this._velocity.y,
104608
+ z: this._velocity.z,
104609
+ },
104584
104610
  });
104585
104611
  this._lastMoveEmitTime = now;
104586
104612
  }
@@ -104611,7 +104637,8 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput {
104611
104637
  document.addEventListener('mousemove', this._onMouseMove);
104612
104638
  document.addEventListener('pointerlockchange', this._onPointerLockChange);
104613
104639
  const canvas = this.app.graphicsDevice.canvas;
104614
- this._onClickToLock = this._onClickToLock || (() => this._requestPointerLock());
104640
+ this._onClickToLock =
104641
+ this._onClickToLock || (() => this._requestPointerLock());
104615
104642
  canvas.addEventListener('mousedown', this._onClickToLock);
104616
104643
  };
104617
104644
  FlyCamera.prototype.deactivate = function () {
@@ -104661,7 +104688,11 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput {
104661
104688
  return {
104662
104689
  position: { x: pos.x, y: pos.y, z: pos.z },
104663
104690
  rotation: { pitch: this._pitch, yaw: this._yaw },
104664
- velocity: { x: this._velocity.x, y: this._velocity.y, z: this._velocity.z },
104691
+ velocity: {
104692
+ x: this._velocity.x,
104693
+ y: this._velocity.y,
104694
+ z: this._velocity.z,
104695
+ },
104665
104696
  isMoving: Math.abs(this._velocity.x) +
104666
104697
  Math.abs(this._velocity.y) +
104667
104698
  Math.abs(this._velocity.z) >
@@ -104669,17 +104700,47 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput {
104669
104700
  };
104670
104701
  };
104671
104702
  FlyCamera.prototype._handleKeyDown = function (e) {
104672
- this._pressed.add(e.code);
104703
+ const keys = [];
104704
+ if (e.code) {
104705
+ keys.push(e.code);
104706
+ }
104707
+ if (e.key) {
104708
+ keys.push(e.key);
104709
+ if (e.key.length === 1) {
104710
+ // Allow matching against both `KeyW` style codes and plain characters
104711
+ keys.push(`Key${e.key.toUpperCase()}`);
104712
+ keys.push(e.key.toUpperCase());
104713
+ keys.push(e.key.toLowerCase());
104714
+ }
104715
+ }
104716
+ for (const k of keys) {
104717
+ this._pressed.add(k);
104718
+ }
104673
104719
  };
104674
104720
  FlyCamera.prototype._handleKeyUp = function (e) {
104675
- this._pressed.delete(e.code);
104721
+ const keys = [];
104722
+ if (e.code) {
104723
+ keys.push(e.code);
104724
+ }
104725
+ if (e.key) {
104726
+ keys.push(e.key);
104727
+ if (e.key.length === 1) {
104728
+ keys.push(`Key${e.key.toUpperCase()}`);
104729
+ keys.push(e.key.toUpperCase());
104730
+ keys.push(e.key.toLowerCase());
104731
+ }
104732
+ }
104733
+ for (const k of keys) {
104734
+ this._pressed.delete(k);
104735
+ }
104676
104736
  };
104677
104737
  FlyCamera.prototype._handleMouseMove = function (e) {
104678
104738
  if (!this._isPointerLocked || !this._isActive)
104679
104739
  return;
104740
+ // Invert horizontal (yaw) rotation: moving mouse right rotates view left, and vice versa
104680
104741
  const dx = e.movementX * this.lookSensitivity;
104681
104742
  const dy = e.movementY * this.lookSensitivity * (this.invertY ? 1 : -1);
104682
- this._yaw = (this._yaw + dx) % 360;
104743
+ this._yaw = (this._yaw - dx) % 360;
104683
104744
  this._pitch = Math.max(-89, Math.min(89, this._pitch + dy));
104684
104745
  };
104685
104746
  FlyCamera.prototype._handlePointerLockChange = function () {
@@ -104702,15 +104763,19 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput {
104702
104763
  }
104703
104764
  }
104704
104765
  };
104705
- FlyCamera.prototype._updateVelocity = function (dt) {
104766
+ FlyCamera.prototype._updateVelocity = function (_dt) {
104706
104767
  // Input direction (local space)
104707
104768
  const kb = this.keyBindings;
104708
- const forward = this._pressed.has(kb.forward) ? 1 : 0;
104709
- const backward = this._pressed.has(kb.backward) ? 1 : 0;
104710
- const left = this._pressed.has(kb.left) ? 1 : 0;
104711
- const right = this._pressed.has(kb.right) ? 1 : 0;
104712
- const up = this._pressed.has(kb.up) ? 1 : 0;
104713
- const down = this._pressed.has(kb.down) ? 1 : 0;
104769
+ const isPressed = (binding, fallbacks) => {
104770
+ const all = [binding, ...fallbacks].filter(Boolean);
104771
+ return all.some(k => this._pressed.has(k));
104772
+ };
104773
+ const forward = isPressed(kb.forward, ['KeyW', 'w', 'W']) ? 1 : 0;
104774
+ const backward = isPressed(kb.backward, ['KeyS', 's', 'S']) ? 1 : 0;
104775
+ const left = isPressed(kb.left, ['KeyA', 'a', 'A']) ? 1 : 0;
104776
+ const right = isPressed(kb.right, ['KeyD', 'd', 'D']) ? 1 : 0;
104777
+ const up = isPressed(kb.up, ['KeyE', 'e', 'E']) ? 1 : 0;
104778
+ const down = isPressed(kb.down, ['KeyQ', 'q', 'Q']) ? 1 : 0;
104714
104779
  const inputZ = forward - backward;
104715
104780
  const inputX = right - left;
104716
104781
  const inputY = up - down;
@@ -104718,17 +104783,25 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput {
104718
104783
  const planarLen = Math.hypot(inputX, inputZ);
104719
104784
  const nx = planarLen > 0 ? inputX / planarLen : 0;
104720
104785
  const nz = planarLen > 0 ? inputZ / planarLen : 0;
104721
- // Effective speed with modifiers
104722
- const speed = this._getEffectiveSpeed();
104723
- // Compute direction vectors from current yaw/pitch
104724
- const yawRad = (this._yaw * Math.PI) / 180;
104725
- const pitchRad = (this._pitch * Math.PI) / 180;
104726
- // Forward vector (normalized)
104727
- const fwd = new Vec3(Math.cos(pitchRad) * Math.sin(yawRad), Math.sin(pitchRad), Math.cos(pitchRad) * Math.cos(yawRad));
104728
- // Right vector (perpendicular to yaw on horizontal plane)
104729
- const rightVec = new Vec3(Math.sin(yawRad - Math.PI / 2), 0, Math.cos(yawRad - Math.PI / 2));
104730
- // Up vector (world up)
104731
- const upVec = Vec3.UP.clone();
104786
+ // Effective speed with modifiers (scaled x2 as requested)
104787
+ const speed = this._getEffectiveSpeed() * 2;
104788
+ // Compute direction vectors from the camera entity so movement matches look direction
104789
+ const entity = this.entity;
104790
+ const fwd = entity?.forward && entity.forward.clone
104791
+ ? entity.forward.clone()
104792
+ : entity?.forward
104793
+ ? new Vec3(entity.forward.x, entity.forward.y, entity.forward.z)
104794
+ : new Vec3(0, 0, -1);
104795
+ const rightVec = entity?.right && entity.right.clone
104796
+ ? entity.right.clone()
104797
+ : entity?.right
104798
+ ? new Vec3(entity.right.x, entity.right.y, entity.right.z)
104799
+ : new Vec3(1, 0, 0);
104800
+ const upVec = entity?.up && entity.up.clone
104801
+ ? entity.up.clone()
104802
+ : entity?.up
104803
+ ? new Vec3(entity.up.x, entity.up.y, entity.up.z)
104804
+ : Vec3.UP.clone();
104732
104805
  // Target velocity in world space
104733
104806
  const target = new Vec3(0, 0, 0);
104734
104807
  target.add(fwd.mulScalar(nz * speed));
@@ -104763,7 +104836,9 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput {
104763
104836
  }
104764
104837
  };
104765
104838
  FlyCamera.prototype._applyConstraints = function () {
104766
- if (!this.enableCollision && this.minHeight == null && this.maxHeight == null) {
104839
+ if (!this.enableCollision &&
104840
+ this.minHeight == null &&
104841
+ this.maxHeight == null) {
104767
104842
  return;
104768
104843
  }
104769
104844
  const pos = this.entity.getPosition