cyclecad 0.8.6 → 0.9.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.
@@ -397,8 +397,106 @@ export function createPrimitive(type, params = {}, options = {}) {
397
397
  );
398
398
  break;
399
399
 
400
+ case 'bracket': {
401
+ // L-shaped bracket from width, height, thickness
402
+ const bw = params.width || 80;
403
+ const bh = params.height || 40;
404
+ const bt = params.thickness || 5;
405
+ const shape = new THREE.Shape();
406
+ shape.moveTo(0, 0);
407
+ shape.lineTo(bw, 0);
408
+ shape.lineTo(bw, bt);
409
+ shape.lineTo(bt, bt);
410
+ shape.lineTo(bt, bh);
411
+ shape.lineTo(0, bh);
412
+ shape.lineTo(0, 0);
413
+ geometry = new THREE.ExtrudeGeometry(shape, { depth: bt, bevelEnabled: false });
414
+ geometry.center();
415
+ break;
416
+ }
417
+
418
+ case 'flange': {
419
+ // Annular flange: outer ring with center hole
420
+ const fo = (params.outerDiameter || params.outerRadius * 2 || 60) / 2;
421
+ const fi = (params.innerDiameter || params.innerRadius * 2 || 20) / 2;
422
+ const fh = params.height || params.thickness || 10;
423
+ const outerShape = new THREE.Shape();
424
+ outerShape.absarc(0, 0, fo, 0, Math.PI * 2, false);
425
+ const holePath = new THREE.Path();
426
+ holePath.absarc(0, 0, fi, 0, Math.PI * 2, true);
427
+ outerShape.holes.push(holePath);
428
+ geometry = new THREE.ExtrudeGeometry(outerShape, { depth: fh, bevelEnabled: false });
429
+ geometry.center();
430
+ break;
431
+ }
432
+
433
+ case 'washer': {
434
+ const wo = (params.outerDiameter || 20) / 2;
435
+ const wi = (params.innerDiameter || 10) / 2;
436
+ const wt = params.thickness || 2;
437
+ const wShape = new THREE.Shape();
438
+ wShape.absarc(0, 0, wo, 0, Math.PI * 2, false);
439
+ const wHole = new THREE.Path();
440
+ wHole.absarc(0, 0, wi, 0, Math.PI * 2, true);
441
+ wShape.holes.push(wHole);
442
+ geometry = new THREE.ExtrudeGeometry(wShape, { depth: wt, bevelEnabled: false });
443
+ geometry.center();
444
+ break;
445
+ }
446
+
447
+ case 'spacer': {
448
+ const so = (params.outerDiameter || params.diameter || 15) / 2;
449
+ const si = (params.innerDiameter || params.holeDiameter || 6) / 2;
450
+ const sh = params.height || params.length || 20;
451
+ const sShape = new THREE.Shape();
452
+ sShape.absarc(0, 0, so, 0, Math.PI * 2, false);
453
+ const sHole = new THREE.Path();
454
+ sHole.absarc(0, 0, si, 0, Math.PI * 2, true);
455
+ sShape.holes.push(sHole);
456
+ geometry = new THREE.ExtrudeGeometry(sShape, { depth: sh, bevelEnabled: false });
457
+ geometry.center();
458
+ break;
459
+ }
460
+
461
+ case 'gear': {
462
+ // Simple spur gear approximation
463
+ const gr = params.radius || params.diameter / 2 || 30;
464
+ const gt = params.teeth || 20;
465
+ const gd = params.depth || params.thickness || 10;
466
+ const toothH = gr * 0.15;
467
+ const gShape = new THREE.Shape();
468
+ for (let i = 0; i < gt; i++) {
469
+ const a0 = (i / gt) * Math.PI * 2;
470
+ const a1 = ((i + 0.3) / gt) * Math.PI * 2;
471
+ const a2 = ((i + 0.5) / gt) * Math.PI * 2;
472
+ const a3 = ((i + 0.8) / gt) * Math.PI * 2;
473
+ if (i === 0) gShape.moveTo(Math.cos(a0) * gr, Math.sin(a0) * gr);
474
+ gShape.lineTo(Math.cos(a1) * (gr + toothH), Math.sin(a1) * (gr + toothH));
475
+ gShape.lineTo(Math.cos(a2) * (gr + toothH), Math.sin(a2) * (gr + toothH));
476
+ gShape.lineTo(Math.cos(a3) * gr, Math.sin(a3) * gr);
477
+ }
478
+ gShape.closePath();
479
+ geometry = new THREE.ExtrudeGeometry(gShape, { depth: gd, bevelEnabled: false });
480
+ geometry.center();
481
+ break;
482
+ }
483
+
484
+ case 'plate': {
485
+ const pw = params.width || 100;
486
+ const ph = params.height || params.depth || 50;
487
+ const pt = params.thickness || 5;
488
+ geometry = new THREE.BoxGeometry(pw, pt, ph);
489
+ break;
490
+ }
491
+
400
492
  default:
401
- throw new Error(`Unknown primitive type: ${type}`);
493
+ // Fallback: treat unknown as a box with available dimensions
494
+ console.warn(`Unknown primitive type "${type}" — creating box fallback`);
495
+ geometry = new THREE.BoxGeometry(
496
+ params.width || params.diameter || 50,
497
+ params.height || params.thickness || 50,
498
+ params.depth || params.thickness || 50
499
+ );
402
500
  }
403
501
 
404
502
  // Create mesh
@@ -46,7 +46,7 @@ const SHORTCUT_MAP = {
46
46
  // Display
47
47
  'g': { action: 'toggleGrid', label: 'Toggle Grid', category: 'Display' },
48
48
  'w': { action: 'toggleWireframe', label: 'Toggle Wireframe', category: 'Display' },
49
- 'shift+f': { action: 'fitAll', label: 'Fit All', category: 'Display' },
49
+ 'h': { action: 'fitAll', label: 'Fit All / Home View', category: 'Display' },
50
50
 
51
51
  // Export & Save
52
52
  'ctrl+s': { action: 'save', label: 'Save (Export JSON)', category: 'File' },
@@ -13,7 +13,7 @@
13
13
  export function initTokenDashboard() {
14
14
  // Create panel HTML
15
15
  const panelHTML = `
16
- <div id="tab-tokens" style="display: none; padding: 12px; overflow-y: auto;">
16
+ <div style="padding: 12px; overflow-y: auto;">
17
17
  <!-- Balance Card -->
18
18
  <div style="background: var(--bg-tertiary); border: 1px solid var(--border-color); border-radius: 6px; padding: 12px; margin-bottom: 12px;">
19
19
  <div style="font-size: 11px; color: var(--text-secondary); text-transform: uppercase; margin-bottom: 6px;">Balance</div>
package/app/js/tree.js CHANGED
@@ -310,7 +310,20 @@ export function onSelect(callback) {
310
310
  */
311
311
  export function suppressFeature(index) {
312
312
  if (index >= 0 && index < treeState.features.length) {
313
- treeState.features[index].suppressed = !treeState.features[index].suppressed;
313
+ const feature = treeState.features[index];
314
+ feature.suppressed = !feature.suppressed;
315
+ // Toggle mesh visibility in 3D scene
316
+ if (feature.mesh) {
317
+ feature.mesh.visible = !feature.suppressed;
318
+ }
319
+ // Also sync with APP.features if available
320
+ const appFeatures = window.APP?.features;
321
+ if (appFeatures && appFeatures[index]) {
322
+ appFeatures[index].suppressed = feature.suppressed;
323
+ if (appFeatures[index].mesh) {
324
+ appFeatures[index].mesh.visible = !feature.suppressed;
325
+ }
326
+ }
314
327
  renderTree();
315
328
  }
316
329
  }
@@ -521,6 +521,14 @@ export function toggleReferencePlanes(visible, plane = null) {
521
521
  * @param {boolean} enabled - Enable/disable wireframe mode
522
522
  */
523
523
  export function toggleWireframe(enabled) {
524
+ // If no argument, toggle based on current state
525
+ if (enabled === undefined) {
526
+ window._wireframeEnabled = !window._wireframeEnabled;
527
+ enabled = window._wireframeEnabled;
528
+ } else {
529
+ window._wireframeEnabled = !!enabled;
530
+ }
531
+
524
532
  if (scene) {
525
533
  scene.traverse((obj) => {
526
534
  // Skip reference planes and grid
package/linkedin-post.md CHANGED
@@ -1,24 +1,29 @@
1
1
  # cycleCAD Launch Post
2
2
 
3
- We just shipped cycleCAD an open-source, browser-based 3D CAD modeler that runs on your phone.
3
+ **We just shipped the first AI-first CAD modeler that runs in your browser.**
4
4
 
5
- The origin story: I was building the cycleWASH DUO (a robotic bike washing machine) and needed CAD software. Every option cost $500-$4000/year, required Windows/Mac + installation, and wouldn't let me design parts faster. 19 modules later, we have something better.
5
+ cycleCAD is open-source, free, and agent-ready. No install. No subscriptions required. Just solid 3D parametric design with a twist: agents can design parts as easily as humans.
6
6
 
7
- **The revolutionary part?** cycleCAD is agent-first. Forget clicking buttons. You describe what you need "build a cylinder 50mm diameter, add a hole, fillet the edges" and agents (or you) execute it via text or voice commands. No GUI needed. It's CAD designed for AI to design manufacturing.
7
+ **The story:** I was building cycleWASH (a robotic bike washing machine) and every CAD tool cost $500-$4000/year and required Windows. 19 modules, 18,800 lines of JavaScript, and a lot of coffee later here we are.
8
8
 
9
- What's inside:
10
- ✨ Browser-native (zero install)
11
- Free & open-source
12
- ✨ AI-powered design assistant (Gemini + Groq)
13
- Parses Inventor files natively
14
- Runs on desktop + mobile
15
- Agent API (55 commands for AI integration)
9
+ **What you get:**
10
+ ✨ Browser-native 3D CAD modeler (sketch → extrude → fillet → export)
11
+ Inventor file parsing (open your .ipt/.iam directly)
12
+ ✨ AI co-pilot (Gemini + Groq + local NLP fallback)
13
+ Agent API 55 commands for autonomous design
14
+ MCP Server + CLI tool (integrate into any AI workflow)
15
+ Model marketplace (publish, earn, collaborate)
16
+ ✨ ExplodeView integration (40+ analysis tools: BOM, DIN specs, McMaster-Carr, QR codes, AR)
16
17
 
17
- We're merging ExplodeView (our 3D viewer with 40+ analysis tools) into cycleCAD to create a complete design + analysis + collaboration platform.
18
+ **Free tier. Pro €49/mo. Enterprise €299/mo.**
18
19
 
19
- **Try it now:** https://cyclecad.com or `npm install cyclecad`
20
- **Star us on GitHub:** https://github.com/vvlars-cmd/cyclecad
20
+ We're building the OS of manufacturing where agents design, humans review, and machines build.
21
21
 
22
- This is just the beginning. We're building the OS of manufacturing — where agents design parts, humans review, and machines build them.
22
+ **Try it now:**
23
+ → https://cyclecad.com
24
+ → npm install cyclecad
25
+ → https://github.com/vvlars-cmd/cyclecad
23
26
 
24
- #OpenSource #CAD #Manufacturing #AI #Agents #3D #Design #FreeCAD #Engineering
27
+ Star us. Contribute. Let's build the future of CAD together.
28
+
29
+ #OpenSource #CAD #AI #Manufacturing #Agents #Engineering #3D #Design #BuildingInPublic #FreeCAD
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cyclecad",
3
- "version": "0.8.6",
3
+ "version": "0.9.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": {