cyclecad 0.8.7 → 0.9.7

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
@@ -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
  }