← Commit history

Embedded viewer UX: close the Layers menu on any click outside it, and make the Bottom-light button work (the shipped bundle has no setBottomLight, so add our own bottom-fill hemispheric light toggled by the button).

AravK ·ff423483b3 ·3mo ago ·parent 5ef0609
1 file changed +23−1
IN-S42ATR-viewer.html+23−1
@@ -107,6 +107,20 @@   const ptLight = scene.lights.find(l => l.getClassName && l.getClassName() === 'PointLight');   const modelParent = (led && led.parent) || null;          // share the model's coordinate space +  // Bottom-fill light: the shipped bundle exposes no setBottomLight() and builds no bottomLight,+  // so create our own (matching his design — a downward hemispheric that lights the part's+  // underside), using his Babylon instance via the existing hemi's constructor. Toggled by the button.+  let bottomFill = scene.getLightByName('bottomLight');+  if (!bottomFill) {+    const hemi = scene.getLightByName('light') || scene.lights.find(l => l.getClassName && l.getClassName() === 'HemisphericLight');+    if (hemi) {+      const HL = hemi.constructor;+      bottomFill = new HL('our_bottom_fill', new B.Vector3(0,0,-1), scene);+      bottomFill.diffuse = new B.Color3(1,1,1); bottomFill.groundColor = new B.Color3(0.5,0.5,0.5);+      bottomFill.intensity = 0;+    }+  }+   // Replicate his loadModel shadow step (ThreeDViewer.svelte ~159-166): register the loaded   // model as shadow casters/receivers. (His current source does this; the shipped bundle is   // older, so we do it here — same effect, no change to his code.) refreshRate=1 keeps the@@ -252,9 +266,17 @@   document.getElementById('mode-static').onclick = () => setMode('static');   document.getElementById('mode-pnp').onclick    = () => setMode('pnp');   document.getElementById('btn-ground').onclick = function(){ this.classList.toggle('on'); viewer.setGroundVisible(this.classList.contains('on')); };-  document.getElementById('btn-bottom').onclick = function(){ this.classList.toggle('on'); viewer.setBottomLight(this.classList.contains('on')); };+  document.getElementById('btn-bottom').onclick = function(){ this.classList.toggle('on'); if (bottomFill) bottomFill.intensity = this.classList.contains('on') ? 0.6 : 0; };   document.getElementById('btn-layers').onclick = function(){ document.getElementById('layer-menu').classList.toggle('open'); this.classList.toggle('on'); }; +  // Close the Layers menu on any click outside it (and outside the Layers button).+  document.addEventListener('click', (e) => {+    const menu = document.getElementById('layer-menu'), btn = document.getElementById('btn-layers');+    if (menu.classList.contains('open') && !menu.contains(e.target) && !btn.contains(e.target)) {+      menu.classList.remove('open'); btn.classList.remove('on');+    }+  }, true);+   setMode('static');   window._v = { viewer, scene, B, setMode };   // debug hook   } catch (e) { statusEl.textContent = 'init error: ' + e.message; window._err = (e.stack || e.message); console.error(e); }