// Inspection controls for the shared, CPU-rendered desk-robot conversation page. import {profiles} from './emotions.js'; export function attachDeskControls(rig){ const caption=document.createElement('p');caption.className='desk-caption';caption.textContent='Drag the robot to orbit · scroll to zoom · arrow keys also rotate the view. Camera tracking turns the head towards you.'; const details=document.createElement('details');details.className='desk-controls'; details.innerHTML=`Inspect the two-axis prototype ↗

Procedural reconstruction of your desk-robot proposal. No arms, heart, cross or mechanical roll. The camera aperture sits above the round display.

Head shell / depth
Ø 190 / ~110–125 mm
Base / total height
Ø 220 / ~315 mm
Display / active image
Ø 150 / Ø 127.6 mm
Display mounting
4 × M4, 75 × 75 mm
Conservative virtual limits
Pan ±90° · tilt ±15° · no roll

A visual, kinematic prototype—not manufacturing CAD, collision/torque simulation or a servo controller. Part fit, cable clearance and load limits require physical checks.

`; document.getElementById('avatar').after(caption,details); const $=id=>document.getElementById(id),r=x=>x*Math.PI/180; const manual=()=>{rig.setManual(+$('desk-pan').value,+$('desk-tilt').value,$('desk-manual').checked);$('desk-pan-value').value=$('desk-pan').value+'°';$('desk-tilt-value').value=$('desk-tilt').value+'°';}; for(const id of ['desk-pan','desk-tilt'])$(id).oninput=()=>{$('desk-manual').checked=true;manual();}; $('desk-manual').onchange=manual; $('desk-front').onclick=()=>{rig.state.view=0;rig.state.elevation=r(4);}; $('desk-threequarter').onclick=()=>{rig.state.view=r(-32);rig.state.elevation=r(12);}; $('desk-rear').onclick=()=>{rig.state.view=r(180);rig.state.elevation=r(8);}; $('desk-center').onclick=()=>{rig.center();$('desk-pan').value=$('desk-tilt').value=0;$('desk-manual').checked=$('desk-tour').checked=false;manual();}; $('desk-tour').onchange=()=>{rig.setTour($('desk-tour').checked);if($('desk-tour').checked){$('desk-manual').checked=false;rig.state.manual=false;}}; $('desk-grid').onchange=()=>rig.setBlueprint($('desk-grid').checked); $('desk-explode').oninput=()=>{rig.setExploded(+$('desk-explode').value);$('desk-explode-value').value=rig.state.exploded?Math.round(rig.state.exploded*100)+'% separated':'assembled';}; $('desk-quality').onchange=()=>rig.state.fps=+$('desk-quality').value; $('desk-zoom-in').onclick=()=>rig.state.distance=Math.max(450,rig.state.distance-60); $('desk-zoom-out').onclick=()=>rig.state.distance=Math.min(950,rig.state.distance+60); let emotionTimer=null,index=0; function stopPreview(){clearInterval(emotionTimer);emotionTimer=null;$('desk-emotions').textContent='Preview all 40 expressions';} $('expression').addEventListener('change',stopPreview); $('desk-emotions').onclick=()=>{ if(emotionTimer){stopPreview();$('expression').value='auto';return;} $('desk-emotions').textContent='Stop expression tour';index=0; const advance=()=>{$('expression').value=profiles[index++%profiles.length].slug;};advance();emotionTimer=setInterval(advance,1600); }; const stats=document.createElement('p');stats.id='desk-render-stats';stats.className='desk-caption';details.after(stats); const interval=setInterval(()=>{const s=rig.snapshot();if(s.renderCount)stats.textContent=`CPU software 3D · ${rig.state.fps} fps target · render p95 ${s.renderP95Ms.toFixed(1)} ms · pan ${s.pan.toFixed(1)}° · tilt ${s.tilt.toFixed(1)}° · roll 0°`;},800); addEventListener('pagehide',()=>{clearInterval(interval);stopPreview();rig.dispose();},{once:true}); }