@heliguy-xyz/splat-viewer 1.0.0-rc.26 → 1.0.0-rc.28

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.
Files changed (25) hide show
  1. package/README.md +52 -336
  2. package/dist/web-component/splat-viewer.esm.js +88 -19
  3. package/dist/web-component/splat-viewer.esm.min.js +1 -1
  4. package/dist/web-component/splat-viewer.js +88 -19
  5. package/dist/web-component/splat-viewer.min.js +1 -1
  6. package/dist/web-component/supersplat-core/controllers.d.ts +5 -0
  7. package/dist/web-component/supersplat-core/controllers.d.ts.map +1 -1
  8. package/dist/web-component/supersplat-core/splat.d.ts.map +1 -1
  9. package/dist/web-component/types/supersplat-core/controllers.d.ts +5 -0
  10. package/dist/web-component/types/supersplat-core/controllers.d.ts.map +1 -1
  11. package/dist/web-component/types/supersplat-core/splat.d.ts.map +1 -1
  12. package/dist/web-component/types/web-component/OrbitCameraScript.d.ts.map +1 -1
  13. package/dist/web-component/types/web-component/SplatViewerCore.d.ts.map +1 -1
  14. package/dist/web-component/types/web-component/SupersplatAdapter.d.ts +9 -0
  15. package/dist/web-component/types/web-component/SupersplatAdapter.d.ts.map +1 -1
  16. package/dist/web-component/types/web-component/utils/config.d.ts +1 -0
  17. package/dist/web-component/types/web-component/utils/config.d.ts.map +1 -1
  18. package/dist/web-component/web-component/OrbitCameraScript.d.ts.map +1 -1
  19. package/dist/web-component/web-component/SplatViewerCore.d.ts.map +1 -1
  20. package/dist/web-component/web-component/SupersplatAdapter.d.ts +9 -0
  21. package/dist/web-component/web-component/SupersplatAdapter.d.ts.map +1 -1
  22. package/dist/web-component/web-component/utils/config.d.ts +1 -0
  23. package/dist/web-component/web-component/utils/config.d.ts.map +1 -1
  24. package/package.json +5 -12
  25. package/CHANGELOG.md +0 -78
@@ -139564,11 +139564,15 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput {
139564
139564
  }
139565
139565
  /**
139566
139566
  * Convert a string to a boolean value
139567
+ * For HTML boolean attributes, an empty string means the attribute is present (true)
139567
139568
  */
139568
139569
  function parseBoolean(value) {
139569
139570
  if (typeof value === 'boolean')
139570
139571
  return value;
139571
139572
  if (typeof value === 'string') {
139573
+ // Empty string means attribute is present without value (should be true for boolean attributes)
139574
+ if (value === '')
139575
+ return true;
139572
139576
  return value.toLowerCase() === 'true' || value === '1';
139573
139577
  }
139574
139578
  return false;
@@ -140459,6 +140463,10 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput {
140459
140463
  this.isPanning = false;
140460
140464
  // Allow host to temporarily disable camera input (e.g., while dragging gizmos)
140461
140465
  this._inputEnabled = true;
140466
+ // Granular control over specific input types
140467
+ this._orbitEnabled = true;
140468
+ this._panEnabled = true;
140469
+ this._zoomEnabled = true;
140462
140470
  // Setup context menu prevention
140463
140471
  this.setupContextMenuPrevention();
140464
140472
  // Use PlayCanvas mouse events for reliable input handling
@@ -140496,6 +140504,19 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput {
140496
140504
  this.isPanning = false;
140497
140505
  }
140498
140506
  };
140507
+ OrbitCamera.prototype.setInputControls = function (options) {
140508
+ if (options.orbit !== undefined)
140509
+ this._orbitEnabled = !!options.orbit;
140510
+ if (options.pan !== undefined)
140511
+ this._panEnabled = !!options.pan;
140512
+ if (options.zoom !== undefined)
140513
+ this._zoomEnabled = !!options.zoom;
140514
+ // Clear any in-progress interactions if being disabled
140515
+ if (this._orbitEnabled === false)
140516
+ this.isOrbiting = false;
140517
+ if (this._panEnabled === false)
140518
+ this.isPanning = false;
140519
+ };
140499
140520
  OrbitCamera.prototype.update = function (dt) {
140500
140521
  // Update navigation cube if enabled
140501
140522
  if (this.navigationCube &&
@@ -140512,12 +140533,13 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput {
140512
140533
  typeof this.navigationCube.cancelTransition === 'function') {
140513
140534
  this.navigationCube.cancelTransition('manual-interaction');
140514
140535
  }
140515
- if (event.button === MOUSEBUTTON_LEFT) {
140536
+ if (event.button === MOUSEBUTTON_LEFT && this._orbitEnabled !== false) {
140516
140537
  this.isOrbiting = true;
140517
140538
  this.emitInteractionEvent?.('interaction-start', 'rotate');
140518
140539
  }
140519
- else if (event.button === MOUSEBUTTON_RIGHT ||
140520
- event.button === MOUSEBUTTON_MIDDLE) {
140540
+ else if ((event.button === MOUSEBUTTON_RIGHT ||
140541
+ event.button === MOUSEBUTTON_MIDDLE) &&
140542
+ this._panEnabled !== false) {
140521
140543
  this.isPanning = true;
140522
140544
  this.emitInteractionEvent?.('interaction-start', 'pan');
140523
140545
  }
@@ -140565,7 +140587,7 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput {
140565
140587
  }
140566
140588
  };
140567
140589
  OrbitCamera.prototype.onMouseWheel = function (event) {
140568
- if (this._inputEnabled === false)
140590
+ if (this._inputEnabled === false || this._zoomEnabled === false)
140569
140591
  return;
140570
140592
  // Cancel any ongoing navigation cube transition when manual zoom interaction starts
140571
140593
  if (this.navigationCube &&
@@ -142701,6 +142723,10 @@ bool initCenter(SplatSource source, vec3 modelCenter, out SplatCenter center) {
142701
142723
  this.entity.setEulerAngles(orientation);
142702
142724
  this.entity.addComponent('gsplat', { asset });
142703
142725
  const instance = this.entity.gsplat.instance;
142726
+ // Check if the gsplat component initialized properly
142727
+ if (!instance || !instance.meshInstance) {
142728
+ throw new Error('Failed to initialize gsplat component. The file may not contain valid Gaussian Splatting data.');
142729
+ }
142704
142730
  // use custom render order distance calculation for splats
142705
142731
  instance.meshInstance.calculateSortDistance = (meshInstance, pos, dir) => {
142706
142732
  const bound = this.localBound;
@@ -143809,6 +143835,10 @@ bool initCenter(SplatSource source, vec3 modelCenter, out SplatCenter center) {
143809
143835
  };
143810
143836
  // Allow temporarily disabling camera controls (e.g. while dragging gizmos).
143811
143837
  let enabled = true;
143838
+ // Granular control over specific input types
143839
+ let orbitEnabled = true;
143840
+ let panEnabled = true;
143841
+ let zoomEnabled = true;
143812
143842
  const resetState = () => {
143813
143843
  pressedButton = -1;
143814
143844
  touches = [];
@@ -143915,13 +143945,13 @@ bool initCenter(SplatSource source, vec3 modelCenter, out SplatCenter center) {
143915
143945
  (event.shiftKey || event.ctrlKey ? 'orbit' :
143916
143946
  (event.altKey || event.metaKey ? 'zoom' : null)) :
143917
143947
  null;
143918
- if (mod === 'orbit' || (mod === null && pressedButton === 0)) {
143948
+ if ((mod === 'orbit' || (mod === null && pressedButton === 0)) && orbitEnabled) {
143919
143949
  orbit(dx, dy);
143920
143950
  }
143921
- else if (mod === 'zoom' || (mod === null && pressedButton === 1)) {
143951
+ else if ((mod === 'zoom' || (mod === null && pressedButton === 1)) && zoomEnabled) {
143922
143952
  zoom(dy * -0.02);
143923
143953
  }
143924
- else if (mod === 'pan' || (mod === null && pressedButton === 2)) {
143954
+ else if ((mod === 'pan' || (mod === null && pressedButton === 2)) && panEnabled) {
143925
143955
  pan(x, y, dx, dy);
143926
143956
  }
143927
143957
  }
@@ -143932,7 +143962,9 @@ bool initCenter(SplatSource source, vec3 modelCenter, out SplatCenter center) {
143932
143962
  const dy = event.offsetY - touch.y;
143933
143963
  touch.x = event.offsetX;
143934
143964
  touch.y = event.offsetY;
143935
- orbit(dx, dy);
143965
+ if (orbitEnabled) {
143966
+ orbit(dx, dy);
143967
+ }
143936
143968
  }
143937
143969
  else if (touches.length === 2) {
143938
143970
  const touch = touches[touches.map(t => t.id).indexOf(event.pointerId)];
@@ -143941,8 +143973,12 @@ bool initCenter(SplatSource source, vec3 modelCenter, out SplatCenter center) {
143941
143973
  const mx = (touches[0].x + touches[1].x) * 0.5;
143942
143974
  const my = (touches[0].y + touches[1].y) * 0.5;
143943
143975
  const ml = dist(touches[0].x, touches[0].y, touches[1].x, touches[1].y);
143944
- pan(mx, my, (mx - midx), (my - midy));
143945
- zoom((ml - midlen) * 0.01);
143976
+ if (panEnabled) {
143977
+ pan(mx, my, (mx - midx), (my - midy));
143978
+ }
143979
+ if (zoomEnabled) {
143980
+ zoom((ml - midlen) * 0.01);
143981
+ }
143946
143982
  midx = mx;
143947
143983
  midy = my;
143948
143984
  midlen = ml;
@@ -143960,16 +143996,20 @@ bool initCenter(SplatSource source, vec3 modelCenter, out SplatCenter center) {
143960
143996
  return;
143961
143997
  const { deltaX, deltaY } = event;
143962
143998
  if (isMouseEvent(deltaX, deltaY)) {
143963
- zoom(deltaY * -2e-3);
143999
+ if (zoomEnabled)
144000
+ zoom(deltaY * -2e-3);
143964
144001
  }
143965
144002
  else if (event.ctrlKey || event.metaKey) {
143966
- zoom(deltaY * -0.02);
144003
+ if (zoomEnabled)
144004
+ zoom(deltaY * -0.02);
143967
144005
  }
143968
144006
  else if (event.shiftKey) {
143969
- pan(event.offsetX, event.offsetY, deltaX, deltaY);
144007
+ if (panEnabled)
144008
+ pan(event.offsetX, event.offsetY, deltaX, deltaY);
143970
144009
  }
143971
144010
  else {
143972
- orbit(deltaX, deltaY);
144011
+ if (orbitEnabled)
144012
+ orbit(deltaX, deltaY);
143973
144013
  }
143974
144014
  event.preventDefault();
143975
144015
  };
@@ -144037,6 +144077,14 @@ bool initCenter(SplatSource source, vec3 modelCenter, out SplatCenter center) {
144037
144077
  resetState();
144038
144078
  }
144039
144079
  };
144080
+ this.setInputControls = (options) => {
144081
+ if (options.orbit !== undefined)
144082
+ orbitEnabled = !!options.orbit;
144083
+ if (options.pan !== undefined)
144084
+ panEnabled = !!options.pan;
144085
+ if (options.zoom !== undefined)
144086
+ zoomEnabled = !!options.zoom;
144087
+ };
144040
144088
  }
144041
144089
  }
144042
144090
 
@@ -147341,6 +147389,26 @@ bool initCenter(SplatSource source, vec3 modelCenter, out SplatCenter center) {
147341
147389
  console.warn('SupersplatAdapter: Failed to toggle camera controls', e);
147342
147390
  }
147343
147391
  }
147392
+ /**
147393
+ * Configure granular control over specific camera input types.
147394
+ * Allows enabling/disabling orbit, pan, and zoom independently.
147395
+ */
147396
+ setCameraInputControls(options) {
147397
+ const controller = this.scene?.camera?.controller;
147398
+ if (!controller)
147399
+ return;
147400
+ try {
147401
+ if (typeof controller.setInputControls === 'function') {
147402
+ controller.setInputControls(options);
147403
+ }
147404
+ else {
147405
+ console.warn('SupersplatAdapter: Camera controller does not support setInputControls');
147406
+ }
147407
+ }
147408
+ catch (e) {
147409
+ console.warn('SupersplatAdapter: Failed to set camera input controls', e);
147410
+ }
147411
+ }
147344
147412
  /**
147345
147413
  * Enable/disable supersplat-core camera auto-update (orbit tweens).
147346
147414
  * When enabled, the camera entity transform may be driven by an external controller (fly mode).
@@ -147799,9 +147867,9 @@ bool initCenter(SplatSource source, vec3 modelCenter, out SplatCenter center) {
147799
147867
  this._supersplatReady = this._supersplat.init();
147800
147868
  this._supersplatReady
147801
147869
  ?.then(() => {
147802
- // Disable camera controls in preview mode
147870
+ // In preview mode, enable zoom only (disable orbit and pan)
147803
147871
  if (this.previewMode && this._supersplat) {
147804
- this._supersplat.setCameraControlsEnabled?.(false);
147872
+ this._supersplat.setCameraInputControls?.({ orbit: false, pan: false, zoom: true });
147805
147873
  }
147806
147874
  // Only set up fly camera if not in preview mode
147807
147875
  if (!this.previewMode) {
@@ -150014,11 +150082,12 @@ bool initCenter(SplatSource source, vec3 modelCenter, out SplatCenter center) {
150014
150082
  detail: { type: interactionType },
150015
150083
  });
150016
150084
  };
150017
- // Disable camera controls in preview mode
150085
+ // In preview mode, enable zoom only (disable orbit and pan)
150018
150086
  if (this.previewMode && this._orbit) {
150019
150087
  const orbitAny = this._orbit;
150020
- if (typeof orbitAny.setEnabled === 'function') {
150021
- orbitAny.setEnabled(false);
150088
+ if (typeof orbitAny.setInputControls === 'function') {
150089
+ // Enable zoom, disable orbit and pan
150090
+ orbitAny.setInputControls({ orbit: false, pan: false, zoom: true });
150022
150091
  }
150023
150092
  }
150024
150093
  this.entities.camera.setPosition(0, 0, 10);