scad-gltf 0.4.0 → 0.5.0

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.
@@ -0,0 +1 @@
1
+ import{A as e,C as t,Et as n,J as r,L as i,Q as a,S as ee,Tt as o,X as te,_ as s,a as ne,b as re,c as ie,d as ae,et as oe,f as c,g as se,h as l,i as ce,l as u,n as le,o as ue,p as de,s as d,t as fe,u as f,ut as p,x as pe}from"./shared-CDFEFgsW.js";var m=document.getElementById(`viewer-container`),h=document.getElementById(`viewer`),g=document.getElementById(`filename-input`),_=document.getElementById(`save-btn`),v=document.getElementById(`open-editor-btn`),y=document.getElementById(`show-grid-cb`),b=document.getElementById(`wireframe-cb`),x=document.getElementById(`fullscreen-btn`),S=document.getElementById(`screenshot-btn`),C=document.getElementById(`camera-select`),w=document.getElementById(`anim-controls`),T=document.getElementById(`anim-play-btn`),E=document.getElementById(`anim-select`),D=document.getElementById(`anim-slider`),O=null,k=null,A=!0,j=!1,M=[],N=``,P=!1,F=null,I=null,L=!1,R=[],z=null,B=new p;B.background=new e(2236962);var V=new a(60,window.innerWidth/window.innerHeight,.1,2e3);V.position.set(50,50,-50),z=V;var H=new pe({antialias:!0});H.setSize(window.innerWidth,window.innerHeight),H.setPixelRatio(Math.min(window.devicePixelRatio,2)),H.shadowMap.enabled=!0,H.shadowMap.type=2,H.toneMapping=4,H.toneMappingExposure=1,h.appendChild(H.domElement);var U=new de(H),W=new c(B,z);U.addPass(W);var me=new ae;U.addPass(me);var G=new s(V,H.domElement);G.enableDamping=!0,G.dampingFactor=.1,B.environment=new re(H).fromScene(new l,.04).texture,B.environmentIntensity=.8,C&&C.addEventListener(`change`,e=>{let t=e.target.value;t===``?(z=V,G.enabled=!0):(z=R[parseInt(t)],G.enabled=!1);let n=m?m.clientWidth:window.innerWidth,r=m?m.clientHeight:window.innerHeight;f(z,n,r),W.camera=z});var he=new oe(2e3,2e3),ge=new te({color:2236962,roughness:.8,metalness:.1}),K=new r(he,ge);K.rotation.x=-Math.PI/2,K.receiveShadow=!0,B.add(K);var q=new i(2e3,100,5592405,3355443);q.material.transparent=!0,q.material.opacity=.5,B.add(q);var J=new t(100);B.add(J),b&&b.addEventListener(`change`,()=>{let e=b.checked;O&&u(O,e)}),x&&m&&(x.addEventListener(`click`,()=>{document.fullscreenElement?document.exitFullscreen().catch(e=>{console.warn(`Error attempting to exit fullscreen: ${e.message}`)}):m.requestFullscreen().catch(e=>{console.warn(`Error attempting to enable fullscreen: ${e.message}`)})}),document.addEventListener(`fullscreenchange`,()=>{setTimeout(()=>window.dispatchEvent(new Event(`resize`)),100)})),S&&S.addEventListener(`click`,()=>{L=!0;let e=S.innerText;S.innerText=`✅`,setTimeout(()=>{S.innerText=e},1e3)});function Y(){k&&(A=!1,k.paused=!0,T&&(T.innerText=`▶ Play`))}function X(e){if(!I||!M[e])return;k&&k.stop();let t=M[e];k=I.clipAction(t),k.play(),k.time=0,I.update(0),A=!0,k.paused=!1,T&&(T.innerText=`⏸ Pause`),D&&(D.value=0)}E&&E.addEventListener(`change`,e=>{X(parseInt(e.target.value))}),T&&T.addEventListener(`click`,()=>{k&&(A=!A,k.paused=!A,T.innerText=A?`⏸ Pause`:`▶ Play`)}),D&&(D.addEventListener(`mousedown`,()=>{j=!0,Y()}),D.addEventListener(`mouseup`,()=>{j=!1}),D.addEventListener(`touchstart`,()=>{j=!0,Y()},{passive:!0}),D.addEventListener(`touchend`,()=>{j=!1},{passive:!0}),D.addEventListener(`input`,e=>{if(Y(),k){let t=k.getClip().duration;k.time=parseFloat(e.target.value)*t,I&&I.update(0)}}));var Z=performance.now();function Q(){requestAnimationFrame(Q);let e=performance.now(),t=(e-Z)/1e3;if(Z=e,I&&(I.update(t),k&&A&&!j)){let e=k.getClip().duration;if(e>0){let t=k.time%e;t<0&&(t+=e),D&&(D.value=t/e)}}G.update();let n=!y||y.checked;if(q.visible=n,J.visible=n,typeof pathTracer<`u`&&k&&A&&pathTracer.updateCamera(),U.render(),L){L=!1;let e=H.domElement.toDataURL(`image/png`);window.parent.postMessage({type:`ADD_IMAGE_TO_CHAT`,dataUrl:e},`*`)}}Q(),window.addEventListener(`resize`,()=>{let e=m?m.clientWidth:window.innerWidth,t=m?m.clientHeight:window.innerHeight;f(z,e,t),H.setSize(e,t),U.setSize(e,t)});function _e(e){return new Promise((t,n)=>{O&&=(I&&=(I.stopAllAction(),I.uncacheRoot(I.getRoot()),null),k=null,M=[],B.remove(O),O.traverse(e=>{e.isMesh&&(e.geometry.dispose(),Array.isArray(e.material)?e.material.forEach(e=>e.dispose()):e.material.dispose())}),null);let r=e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength);new se().parse(r,``,e=>{O=e.scene,M=e.animations||[];let n=b?b.checked:!1,r=ue(O);R=r.gltfCameras,r.gltfLights.forEach(e=>e.visible=!1),B.environmentIntensity=.8;let i=!1;C?R.length>0?(C.style.display=`inline-block`,C.innerHTML=`<option value="">Free Camera</option>`,R.forEach((e,t)=>{let n=document.createElement(`option`);n.value=t,n.innerText=e.name||`Camera ${t+1}`,C.appendChild(n)}),C.value=`0`,z=R[0],G.enabled=!1,i=!0):(C.style.display=`none`,C.value=``,z=V,G.enabled=!0):(z=V,G.enabled=!0);let a=h?h.clientWidth:window.innerWidth,o=h?h.clientHeight:window.innerHeight;f(z,a,o),W.camera=z,M.length>0?(I=new ee(O),i=!0,w?(T&&(T.style.display=``),E&&(E.style.display=``),D&&(D.style.display=``),E.innerHTML=``,M.forEach((e,t)=>{let n=document.createElement(`option`);n.value=t,n.innerText=e.name||`Animation ${t+1}`,E.appendChild(n)}),X(0)):(M.forEach(e=>{let t=I.clipAction(e);t.play(),t.time=0}),I.update(0))):(w&&(T&&(T.style.display=`none`),E&&(E.style.display=`none`),D&&(D.style.display=`none`)),k=null),w&&(w.style.display=i?`flex`:`none`),u(O,n),B.add(O),ve(),t()},e=>{console.error(e),n(e)})})}function ve(){if(!O)return;let e=le(O,M);if(e.isEmpty())return;K.position.y=e.min.y-.01,q.position.y=K.position.y+.001,J.position.y=K.position.y+.002;let{maxDim:t}=ie(V,G,null,B,e);fe(O,t*1.5)}async function ye(e){let t=`http://localhost:3000`,n=[];try{let e=await fetch(`${t}/api/scads`);e.ok&&(n=(await e.json()).files||[])}catch{return{}}return d(e,t,n)}async function $(e){if(P){F=e;return}P=!0;try{let t=await ye(e);await _e(await o(e,{wasmUrl:n,additionalFiles:t}))}catch(e){console.error(e)}finally{if(P=!1,F!==null){let e=F;F=null,$(e)}}}window.addEventListener(`message`,async e=>{if(e.data.type===`RENDER_SCAD`){N=e.data.code;let t=N.match(/\/\*\s*Model Name:\s*(.*?)\s*\*\//i);if(t&&t[1]){let e=t[1].trim().replace(/\s+/g,`_`).replace(/[^a-zA-Z0-9_-]/g,``);e&&(g.value=e)}await $(e.data.code)}}),_.addEventListener(`click`,async()=>{let e=g.value.trim();if(!e){alert(`Please enter a filename.`),g.focus();return}let t=`http://localhost:3000`;try{_.innerText=`Checking...`,_.disabled=!0;let n=await fetch(`${t}/api/scads`);if(!n.ok)throw Error("Could not reach `scad-gltf serve`.");let r=await n.json(),i=e.toLowerCase().endsWith(`.scad`)?e:`${e}.scad`;if(r.files&&r.files.includes(i)&&!confirm(`File "${i}" already exists. Overwrite?`)){_.innerText=`Save`,_.disabled=!1;return}_.innerText=`Saving...`;let a=await fetch(`${t}/api/scads`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({filename:e,content:N||``})});if(!a.ok){let e=await a.json();throw Error(e.error||`Save failed.`)}_.innerText=`✅ Saved!`,setTimeout(()=>{_.innerText=`Save`,_.disabled=!1},2e3)}catch(t){console.warn(`Backend not connected or save failed, falling back to download`,t);let n=new Blob([N||``],{type:`text/plain`}),r=e.toLowerCase().endsWith(`.scad`)?e:`${e}.scad`;ce(n,r),_.innerText=`✅ Downloaded!`,setTimeout(()=>{_.innerText=`Save`,_.disabled=!1},2e3)}}),v.addEventListener(`click`,async()=>{if(!N){alert(`No model loaded to open.`);return}try{v.disabled=!0,v.innerText=`Preparing...`;let e=`https://iliagrigorevdev.github.io/scad-gltf/#${await ne(N)}`;window.open(e,`_blank`),window.parent.postMessage({type:`CLOSE_PREVIEW`},`*`),v.innerText=`✅ Opened!`,setTimeout(()=>{v.innerText=`Edit`,v.disabled=!1},2e3)}catch(e){console.error(`Error creating editor link`,e),alert(`Error creating editor link: `+e.message),v.innerText=`Edit`,v.disabled=!1}});
@@ -1,4 +1,4 @@
1
- function e(e,t={}){if(!e)throw Error(`A description is required to generate a prompt.`);let n={basic:t.basic??!0,transmission:t.transmission??!0,clearcoat:t.clearcoat??!0,sheen:t.sheen??!0,emissive:t.emissive??!0,specular:t.specular??!0,iridescence:t.iridescence??!0,bakeColors:t.bakeColors??!1,bakeNormals:t.bakeNormals??!1,bakeOrm:t.bakeOrm??!1,bakeUvs:t.bakeUvs??!1,autoSmoothAngle:t.autoSmoothAngle??!0,animation:t.animation??!0,lazyUnion:t.lazyUnion??!1,modelName:t.modelName??!0},r=`Generate an OpenSCAD script to design the following: ${e}.`;n.modelName&&(r+=`
1
+ function e(e,t={}){if(!e)throw Error(`A description is required to generate a prompt.`);let n={basic:t.basic??!0,transmission:t.transmission??!0,clearcoat:t.clearcoat??!0,sheen:t.sheen??!0,emissive:t.emissive??!0,specular:t.specular??!0,iridescence:t.iridescence??!0,bakeColors:t.bakeColors??!1,bakeNormals:t.bakeNormals??!1,bakeOrm:t.bakeOrm??!1,bakeUvs:t.bakeUvs??!1,autoSmoothAngle:t.autoSmoothAngle??!0,animation:t.animation??!0,lazyUnion:t.lazyUnion??!1,modelName:t.modelName??!0,lights:t.lights??!1},r=`Generate an OpenSCAD script to design the following: ${e}.`;n.modelName&&(r+=`
2
2
 
3
3
  Important Output Rules:
4
4
  - You MUST wrap your code in a standard Markdown code block using the \`\`\`openscad language tag.
@@ -93,11 +93,12 @@ ${i} {
93
93
  bake(uvs=true) {
94
94
  color("white") cube([10, 10, 10]);
95
95
  }
96
- \`\`\``}return r}var t=`
96
+ \`\`\``}return n.lights&&(r+='\n\nImportant Lighting rules:\n- Lights: Use the \'light()\' module to add lights to the scene.\n- Syntax: `light(type="point", color=[1,1,1], intensity=2000.0, range=0.0, innerConeAngle=0.0, outerConeAngle=45.0) { ... }`\n- Supported light types: "directional", "point", "spot".\n- Intensity (Physically Correct): Directional lights use Lux (e.g., 300-500 for indoor lighting, 100000 for the sun). Point and Spot lights use Candelas and decay over distance via the inverse-square law. They require VERY HIGH values (e.g., 1000.0 to 10000.0+) to illuminate objects!\n- Orientation: A directional or spot light shines in the -Z direction by default. Use `translate()` and `rotate()` around the `light()` module to position and orient it.\n- Spot lights accept `innerConeAngle` and `outerConeAngle` (in degrees). Point/Spot lights accept `range` (0.0 means infinite).\n- Children inside a `light()` block are rendered normally in OpenSCAD and exported. The light transform automatically follows its enclosing transformations.\n\nExample Lighting Usage:\n```openscad\n// A spot light pointing down at an angle (Note the high intensity of 5000)\ntranslate([0, 0, 50]) rotate([0, 30, 0])\n light(type="spot", color=[1, 0.8, 0.8], intensity=5000.0, innerConeAngle=15.0, outerConeAngle=30.0)\n color("gray") cylinder(h=2, r=1, center=true); // A visual representation of the light fixture\n```'),r}var t=`
97
97
  <div class="scad-prompt-toggles">
98
98
  <label><input type="checkbox" id="opt-pbr-basic" checked /> Basic PBR</label>
99
99
  <label><input type="checkbox" id="opt-pbr-autosmooth" checked /> Auto Smooth</label>
100
100
  <label><input type="checkbox" id="opt-anim" checked /> Animations</label>
101
+ <label><input type="checkbox" id="opt-lights" /> Lights</label>
101
102
  </div>
102
103
 
103
104
  <div class="scad-prompt-group">
@@ -127,4 +128,4 @@ bake(uvs=true) {
127
128
  <label><input type="checkbox" class="bake-child" id="opt-bake-uvs" /> Bake UVs/Tangents</label>
128
129
  </div>
129
130
  </div>
130
- `;function n(e,t=`scad_prompt_settings`){let n=()=>{let n={};e.querySelectorAll(`input[type="checkbox"]`).forEach(e=>{e.id&&(n[e.id]=e.checked)}),localStorage.setItem(t,JSON.stringify(n))},r=(t,r)=>{let i=e.querySelector(t),a=e.querySelectorAll(r),o=()=>{if(!i||a.length===0)return;let e=Array.from(a).every(e=>e.checked),t=Array.from(a).some(e=>e.checked);i.checked=e,i.indeterminate=t&&!e};return i&&a.length>0&&(i.addEventListener(`change`,e=>{let t=e.target.checked;a.forEach(e=>e.checked=t),n()}),a.forEach(e=>{e.addEventListener(`change`,()=>{o(),n()})})),o},i=r(`#opt-pbr-all`,`.pbr-child`),a=r(`#opt-bake-all`,`.bake-child`);try{let n=localStorage.getItem(t);if(n){let t=JSON.parse(n);e.querySelectorAll(`input[type="checkbox"]`).forEach(e=>{e.id&&t[e.id]!==void 0&&(e.checked=t[e.id])})}}catch(e){console.warn(`Could not load SCAD prompt settings`,e)}e.addEventListener(`change`,e=>{e.target.type===`checkbox`&&n()}),i(),a()}function r(e){return{basic:e.querySelector(`#opt-pbr-basic`)?.checked??!0,transmission:e.querySelector(`#opt-pbr-transmission`)?.checked??!0,clearcoat:e.querySelector(`#opt-pbr-clearcoat`)?.checked??!0,sheen:e.querySelector(`#opt-pbr-sheen`)?.checked??!0,emissive:e.querySelector(`#opt-pbr-emissive`)?.checked??!0,specular:e.querySelector(`#opt-pbr-specular`)?.checked??!0,iridescence:e.querySelector(`#opt-pbr-iridescence`)?.checked??!0,autoSmoothAngle:e.querySelector(`#opt-pbr-autosmooth`)?.checked??!0,bakeColors:e.querySelector(`#opt-bake-colors`)?.checked??!1,bakeNormals:e.querySelector(`#opt-bake-normals`)?.checked??!1,bakeOrm:e.querySelector(`#opt-bake-orm`)?.checked??!1,bakeUvs:e.querySelector(`#opt-bake-uvs`)?.checked??!1,animation:e.querySelector(`#opt-anim`)?.checked??!0}}export{e as i,r as n,n as r,t};
131
+ `;function n(e,t=`scad_prompt_settings`){let n=()=>{let n={};e.querySelectorAll(`input[type="checkbox"]`).forEach(e=>{e.id&&(n[e.id]=e.checked)}),localStorage.setItem(t,JSON.stringify(n))},r=(t,r)=>{let i=e.querySelector(t),a=e.querySelectorAll(r),o=()=>{if(!i||a.length===0)return;let e=Array.from(a).every(e=>e.checked),t=Array.from(a).some(e=>e.checked);i.checked=e,i.indeterminate=t&&!e};return i&&a.length>0&&(i.addEventListener(`change`,e=>{let t=e.target.checked;a.forEach(e=>e.checked=t),n()}),a.forEach(e=>{e.addEventListener(`change`,()=>{o(),n()})})),o},i=r(`#opt-pbr-all`,`.pbr-child`),a=r(`#opt-bake-all`,`.bake-child`);try{let n=localStorage.getItem(t);if(n){let t=JSON.parse(n);e.querySelectorAll(`input[type="checkbox"]`).forEach(e=>{e.id&&t[e.id]!==void 0&&(e.checked=t[e.id])})}}catch(e){console.warn(`Could not load SCAD prompt settings`,e)}e.addEventListener(`change`,e=>{e.target.type===`checkbox`&&n()}),i(),a()}function r(e){return{basic:e.querySelector(`#opt-pbr-basic`)?.checked??!0,transmission:e.querySelector(`#opt-pbr-transmission`)?.checked??!0,clearcoat:e.querySelector(`#opt-pbr-clearcoat`)?.checked??!0,sheen:e.querySelector(`#opt-pbr-sheen`)?.checked??!0,emissive:e.querySelector(`#opt-pbr-emissive`)?.checked??!0,specular:e.querySelector(`#opt-pbr-specular`)?.checked??!0,iridescence:e.querySelector(`#opt-pbr-iridescence`)?.checked??!0,autoSmoothAngle:e.querySelector(`#opt-pbr-autosmooth`)?.checked??!0,bakeColors:e.querySelector(`#opt-bake-colors`)?.checked??!1,bakeNormals:e.querySelector(`#opt-bake-normals`)?.checked??!1,bakeOrm:e.querySelector(`#opt-bake-orm`)?.checked??!1,bakeUvs:e.querySelector(`#opt-bake-uvs`)?.checked??!1,animation:e.querySelector(`#opt-anim`)?.checked??!0,lights:e.querySelector(`#opt-lights`)?.checked??!1}}export{e as i,r as n,n as r,t};