cyclecad 1.0.5 → 1.0.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.
package/app/index.html CHANGED
@@ -2904,6 +2904,11 @@
2904
2904
  const pParams = prompt.params || prompt;
2905
2905
  const result = createPrimitive(pType, pParams);
2906
2906
  const mesh = result.mesh || result;
2907
+ // Apply position offset for multi-item placement (e.g., 4 holes around a part)
2908
+ if (pParams._offsetX || pParams._offsetZ) {
2909
+ mesh.position.x += (pParams._offsetX || 0) * 0.1;
2910
+ mesh.position.z += (pParams._offsetZ || 0) * 0.1;
2911
+ }
2907
2912
  addToScene(mesh);
2908
2913
  if (result.wireframe) addToScene(result.wireframe);
2909
2914
 
@@ -3554,7 +3559,7 @@
3554
3559
  init();
3555
3560
  }
3556
3561
 
3557
- window.cycleCAD = Object.assign(window.cycleCAD || {}, { version: '1.0.0', APP, init });
3562
+ window.cycleCAD = Object.assign(window.cycleCAD || {}, { version: '1.0.6', APP, init });
3558
3563
 
3559
3564
  // Expose dialog functions globally so inline onclick="" handlers work
3560
3565
  window.openDialog = openDialog;
@@ -5267,6 +5272,6 @@
5267
5272
  </div>
5268
5273
  </div>
5269
5274
 
5270
- <span id="version-badge" style="position:fixed;bottom:42px;left:50%;transform:translateX(-50%);z-index:999;font-size:0.9rem;color:rgba(255,255,255,0.9);letter-spacing:0.1em;white-space:nowrap;padding:6px 16px;user-select:all;pointer-events:auto;font-family:monospace;font-weight:700;background:rgba(0,0,0,0.7);border:1px solid rgba(88,166,255,0.4);border-radius:6px;text-shadow:0 1px 3px rgba(0,0,0,0.5);" title="cycleCAD version">cycleCAD v1.0.5</span>
5275
+ <span id="version-badge" style="position:fixed;bottom:42px;left:50%;transform:translateX(-50%);z-index:999;font-size:0.9rem;color:rgba(255,255,255,0.9);letter-spacing:0.1em;white-space:nowrap;padding:6px 16px;user-select:all;pointer-events:auto;font-family:monospace;font-weight:700;background:rgba(0,0,0,0.7);border:1px solid rgba(88,166,255,0.4);border-radius:6px;text-shadow:0 1px 3px rgba(0,0,0,0.5);" title="cycleCAD version">cycleCAD v1.0.6</span>
5271
5276
  </body>
5272
5277
  </html>
@@ -948,7 +948,19 @@ export async function executeTextCommand(prompt) {
948
948
  if (window._executeParsedPrompt) {
949
949
  const method = cmd.method || '';
950
950
  const type = method.replace('shape.', '').replace('feature.', '');
951
- window._executeParsedPrompt({ type, params: cmd.params || {} });
951
+ // Handle count param (e.g., 4 mounting holes)
952
+ const count = cmd.params?.count || 1;
953
+ for (let ci = 0; ci < count; ci++) {
954
+ const p = Object.assign({}, cmd.params);
955
+ // Offset multiple items so they don't stack
956
+ if (count > 1) {
957
+ const angle = (ci / count) * Math.PI * 2;
958
+ const spread = (p.radius || 5) * 4;
959
+ p._offsetX = Math.cos(angle) * spread;
960
+ p._offsetZ = Math.sin(angle) * spread;
961
+ }
962
+ window._executeParsedPrompt({ type, params: p });
963
+ }
952
964
  results.push({ ok: true, method });
953
965
  } else if (window.cycleCAD && window.cycleCAD.execute) {
954
966
  const result = await window.cycleCAD.execute(cmd);
@@ -349,10 +349,9 @@ export function createPrimitive(type, params = {}, options = {}) {
349
349
  const { material = 'steel' } = options;
350
350
  let geometry;
351
351
 
352
- // Scale factor: AI copilot provides dimensions in millimeters, but we render at 1:1 scene units
353
- // For a 100mm cube to look reasonable in viewport, scale down by 1.0 (1:1 scale)
354
- // Most CAD systems use 1 scene unit = 1 mm
355
- const SCALE = 1.0;
352
+ // Scale factor: dimensions in mm, viewport units are ~10x smaller for good camera framing
353
+ // Camera starts at (150,100,150) so a 100mm cube should be ~10 units to look right
354
+ const SCALE = 0.1;
356
355
 
357
356
  switch (type) {
358
357
  case 'box':
@@ -403,19 +402,17 @@ export function createPrimitive(type, params = {}, options = {}) {
403
402
  break;
404
403
 
405
404
  case 'hole': {
406
- // Create a cylinder for hole preview (visual aid — actual hole subtraction happens in boolean operations)
407
- // Used by feature.hole commands from AI copilot
405
+ // Create a dark cylinder for hole preview (visual subtract indicator)
408
406
  const holeRadius = (params.radius || 5) * SCALE;
409
- const holeDepth = (params.depth || 20) * SCALE;
410
- geometry = new THREE.CylinderGeometry(
411
- holeRadius,
412
- holeRadius,
413
- holeDepth,
414
- 16,
415
- 1,
416
- false
417
- );
418
- break;
407
+ const holeDepth = (params.depth || params.height || 20) * SCALE;
408
+ geometry = new THREE.CylinderGeometry(holeRadius, holeRadius, holeDepth, 16, 1, false);
409
+ // Override material to dark red so holes are clearly visible
410
+ const holeMat = new THREE.MeshStandardMaterial({ color: 0x882222, metalness: 0.3, roughness: 0.7, transparent: true, opacity: 0.85 });
411
+ const holeMesh = new THREE.Mesh(geometry, holeMat);
412
+ holeMesh.castShadow = true;
413
+ holeMesh.receiveShadow = true;
414
+ const holeWire = createWireframeEdges(holeMesh);
415
+ return { mesh: holeMesh, wireframe: holeWire, params: { type, params, options } };
419
416
  }
420
417
 
421
418
  case 'bracket': {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cyclecad",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Browser-based parametric 3D CAD modeler with AI-powered tools, native Inventor file parsing, and smart assembly management. No install required.",
5
5
  "main": "index.html",
6
6
  "bin": {