cyclecad 3.9.1 → 3.9.3
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/_test_write +0 -0
- package/app/index.html +176 -65
- package/app/js/modules/text-to-cad.js +1 -1
- package/cycleWASH-NRW-Prospects.xlsx +0 -0
- package/fix-splash-v2.sh +123 -0
- package/fix-splash-viewcube.sh +181 -0
- package/package.json +1 -1
package/_test_write
ADDED
|
File without changes
|
package/app/index.html
CHANGED
|
@@ -1145,8 +1145,10 @@
|
|
|
1145
1145
|
</div>
|
|
1146
1146
|
|
|
1147
1147
|
<!-- Viewport -->
|
|
1148
|
-
<div id="viewport-container">
|
|
1148
|
+
<div id="viewport-container" style="position:relative;">
|
|
1149
1149
|
<canvas id="viewport"></canvas>
|
|
1150
|
+
<!-- ViewCube -->
|
|
1151
|
+
<div id="viewcube" style="position:absolute;top:12px;right:12px;width:90px;height:90px;pointer-events:auto;z-index:100;"></div>
|
|
1150
1152
|
</div>
|
|
1151
1153
|
|
|
1152
1154
|
<!-- Right Panel (Properties) -->
|
|
@@ -1306,6 +1308,52 @@
|
|
|
1306
1308
|
|
|
1307
1309
|
</div>
|
|
1308
1310
|
|
|
1311
|
+
<!-- Welcome Splash Screen -->
|
|
1312
|
+
<div id="welcome-panel" style="position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.75);display:flex;align-items:center;justify-content:center;z-index:9999;">
|
|
1313
|
+
<div style="background:#252526;border:1px solid #3c3c3c;border-radius:12px;padding:40px 48px;max-width:560px;width:90%;text-align:center;box-shadow:0 20px 60px rgba(0,0,0,0.5);">
|
|
1314
|
+
<div style="font-size:36px;margin-bottom:4px;">
|
|
1315
|
+
<span style="color:#0284C7;font-weight:700;">cycle</span><span style="color:#e0e0e0;font-weight:300;">CAD</span>
|
|
1316
|
+
</div>
|
|
1317
|
+
<div style="color:#888;font-size:13px;margin-bottom:28px;">Agent-First Parametric 3D CAD Modeler</div>
|
|
1318
|
+
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:20px;">
|
|
1319
|
+
<button onclick="window._dismissSplash('sketch')" style="background:#0284C7;color:#fff;border:none;border-radius:8px;padding:18px 16px;cursor:pointer;font-size:14px;font-weight:600;">
|
|
1320
|
+
<div style="font-size:24px;margin-bottom:6px;">✏️</div>
|
|
1321
|
+
New Sketch
|
|
1322
|
+
<div style="font-size:11px;font-weight:400;color:rgba(255,255,255,0.7);margin-top:4px;">Start with a 2D sketch</div>
|
|
1323
|
+
</button>
|
|
1324
|
+
<button onclick="window._dismissSplash('import')" style="background:#374151;color:#fff;border:1px solid #4b5563;border-radius:8px;padding:18px 16px;cursor:pointer;font-size:14px;font-weight:600;">
|
|
1325
|
+
<div style="font-size:24px;margin-bottom:6px;">📂</div>
|
|
1326
|
+
Open / Import
|
|
1327
|
+
<div style="font-size:11px;font-weight:400;color:rgba(255,255,255,0.7);margin-top:4px;">STEP, STL, Inventor, JSON</div>
|
|
1328
|
+
</button>
|
|
1329
|
+
<button onclick="window._dismissSplash('textcad')" style="background:#374151;color:#fff;border:1px solid #4b5563;border-radius:8px;padding:18px 16px;cursor:pointer;font-size:14px;font-weight:600;">
|
|
1330
|
+
<div style="font-size:24px;margin-bottom:6px;">🤖</div>
|
|
1331
|
+
Text-to-CAD
|
|
1332
|
+
<div style="font-size:11px;font-weight:400;color:rgba(255,255,255,0.7);margin-top:4px;">Describe a part in English</div>
|
|
1333
|
+
</button>
|
|
1334
|
+
<button onclick="window._dismissSplash('inventor')" style="background:#374151;color:#fff;border:1px solid #4b5563;border-radius:8px;padding:18px 16px;cursor:pointer;font-size:14px;font-weight:600;">
|
|
1335
|
+
<div style="font-size:24px;margin-bottom:6px;">🏭</div>
|
|
1336
|
+
Inventor Project
|
|
1337
|
+
<div style="font-size:11px;font-weight:400;color:rgba(255,255,255,0.7);margin-top:4px;">Load .ipj / .ipt / .iam</div>
|
|
1338
|
+
</button>
|
|
1339
|
+
</div>
|
|
1340
|
+
<div style="color:#666;font-size:11px;">v0.9.0 · 12 killer features · 46 modules · <a href="https://github.com/vvlars-cmd/cyclecad" target="_blank" style="color:#0284C7;text-decoration:none;">GitHub</a></div>
|
|
1341
|
+
</div>
|
|
1342
|
+
</div>
|
|
1343
|
+
<script>
|
|
1344
|
+
window._dismissSplash = function(action) {
|
|
1345
|
+
document.getElementById('welcome-panel').style.display = 'none';
|
|
1346
|
+
if (action === 'sketch') {
|
|
1347
|
+
// Will be handled by module script once loaded
|
|
1348
|
+
window._pendingSplashAction = 'sketch-new';
|
|
1349
|
+
} else if (action === 'import' || action === 'inventor') {
|
|
1350
|
+
window._pendingSplashAction = 'file-import';
|
|
1351
|
+
} else if (action === 'textcad') {
|
|
1352
|
+
window._pendingSplashAction = 'tools-text-to-cad';
|
|
1353
|
+
}
|
|
1354
|
+
};
|
|
1355
|
+
</script>
|
|
1356
|
+
|
|
1309
1357
|
<!-- Modal Dialogs -->
|
|
1310
1358
|
<div id="dialog-overlay" class="modal-overlay">
|
|
1311
1359
|
<div class="modal-dialog">
|
|
@@ -1447,22 +1495,6 @@
|
|
|
1447
1495
|
const grid = new THREE.GridHelper(500, 50, 0x444444, 0x333333);
|
|
1448
1496
|
scene.add(grid);
|
|
1449
1497
|
|
|
1450
|
-
// Demo geometry — a sample part so viewport isn't empty
|
|
1451
|
-
const boxGeo = new THREE.BoxGeometry(60, 40, 80);
|
|
1452
|
-
const boxMat = new THREE.MeshStandardMaterial({ color: 0x0284C7, metalness: 0.3, roughness: 0.6 });
|
|
1453
|
-
const box = new THREE.Mesh(boxGeo, boxMat);
|
|
1454
|
-
box.position.y = 20;
|
|
1455
|
-
box.castShadow = true;
|
|
1456
|
-
box.receiveShadow = true;
|
|
1457
|
-
scene.add(box);
|
|
1458
|
-
|
|
1459
|
-
const cylGeo = new THREE.CylinderGeometry(12, 12, 50, 32);
|
|
1460
|
-
const cylMat = new THREE.MeshStandardMaterial({ color: 0x10b981, metalness: 0.4, roughness: 0.5 });
|
|
1461
|
-
const cyl = new THREE.Mesh(cylGeo, cylMat);
|
|
1462
|
-
cyl.position.set(0, 45, 0);
|
|
1463
|
-
cyl.castShadow = true;
|
|
1464
|
-
scene.add(cyl);
|
|
1465
|
-
|
|
1466
1498
|
// Ground plane
|
|
1467
1499
|
const groundGeo = new THREE.PlaneGeometry(500, 500);
|
|
1468
1500
|
const groundMat = new THREE.ShadowMaterial({ opacity: 0.15 });
|
|
@@ -1475,11 +1507,89 @@
|
|
|
1475
1507
|
new ResizeObserver(resizeViewport).observe(viewportEl);
|
|
1476
1508
|
resizeViewport(); // Call initial resize to set canvas dimensions
|
|
1477
1509
|
|
|
1510
|
+
// ===== ViewCube =====
|
|
1511
|
+
const vcContainer = document.getElementById('viewcube');
|
|
1512
|
+
const vcScene = new THREE.Scene();
|
|
1513
|
+
const vcCamera = new THREE.PerspectiveCamera(40, 1, 0.1, 100);
|
|
1514
|
+
vcCamera.position.set(0, 0, 3.5);
|
|
1515
|
+
const vcRenderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
|
|
1516
|
+
vcRenderer.setSize(90, 90);
|
|
1517
|
+
vcRenderer.setPixelRatio(window.devicePixelRatio);
|
|
1518
|
+
vcContainer.appendChild(vcRenderer.domElement);
|
|
1519
|
+
|
|
1520
|
+
// Cube faces
|
|
1521
|
+
const faceLabels = ['Right', 'Left', 'Top', 'Bottom', 'Front', 'Back'];
|
|
1522
|
+
const faceColors = [0x3b82f6, 0x3b82f6, 0x10b981, 0x10b981, 0x0284C7, 0x0284C7];
|
|
1523
|
+
const cubeMats = faceLabels.map((label, i) => {
|
|
1524
|
+
const canvas = document.createElement('canvas');
|
|
1525
|
+
canvas.width = 128; canvas.height = 128;
|
|
1526
|
+
const ctx = canvas.getContext('2d');
|
|
1527
|
+
ctx.fillStyle = '#' + faceColors[i].toString(16).padStart(6, '0');
|
|
1528
|
+
ctx.fillRect(0, 0, 128, 128);
|
|
1529
|
+
ctx.strokeStyle = '#1e293b';
|
|
1530
|
+
ctx.lineWidth = 3;
|
|
1531
|
+
ctx.strokeRect(1, 1, 126, 126);
|
|
1532
|
+
ctx.fillStyle = '#fff';
|
|
1533
|
+
ctx.font = 'bold 22px Arial';
|
|
1534
|
+
ctx.textAlign = 'center';
|
|
1535
|
+
ctx.textBaseline = 'middle';
|
|
1536
|
+
ctx.fillText(label, 64, 64);
|
|
1537
|
+
const tex = new THREE.CanvasTexture(canvas);
|
|
1538
|
+
return new THREE.MeshBasicMaterial({ map: tex });
|
|
1539
|
+
});
|
|
1540
|
+
const vcCube = new THREE.Mesh(new THREE.BoxGeometry(1.6, 1.6, 1.6), cubeMats);
|
|
1541
|
+
vcScene.add(vcCube);
|
|
1542
|
+
|
|
1543
|
+
// Axis lines on viewcube
|
|
1544
|
+
const axLen = 1.3;
|
|
1545
|
+
const axMat = (c) => new THREE.LineBasicMaterial({ color: c });
|
|
1546
|
+
const axGeo = (v) => new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(), v]);
|
|
1547
|
+
vcScene.add(new THREE.Line(axGeo(new THREE.Vector3(axLen, 0, 0)), axMat(0xff4444)));
|
|
1548
|
+
vcScene.add(new THREE.Line(axGeo(new THREE.Vector3(0, axLen, 0)), axMat(0x44ff44)));
|
|
1549
|
+
vcScene.add(new THREE.Line(axGeo(new THREE.Vector3(0, 0, axLen)), axMat(0x4444ff)));
|
|
1550
|
+
|
|
1551
|
+
// ViewCube click → snap camera to face
|
|
1552
|
+
const vcViews = {
|
|
1553
|
+
Right: { x: 3, y: 0, z: 0 },
|
|
1554
|
+
Left: { x: -3, y: 0, z: 0 },
|
|
1555
|
+
Top: { x: 0, y: 3, z: 0 },
|
|
1556
|
+
Bottom: { x: 0, y: -3, z: 0 },
|
|
1557
|
+
Front: { x: 0, y: 0, z: 3 },
|
|
1558
|
+
Back: { x: 0, y: 0, z: -3 }
|
|
1559
|
+
};
|
|
1560
|
+
const vcRay = new THREE.Raycaster();
|
|
1561
|
+
const vcMouse = new THREE.Vector2();
|
|
1562
|
+
vcRenderer.domElement.addEventListener('click', (e) => {
|
|
1563
|
+
const rect = vcRenderer.domElement.getBoundingClientRect();
|
|
1564
|
+
vcMouse.x = ((e.clientX - rect.left) / rect.width) * 2 - 1;
|
|
1565
|
+
vcMouse.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;
|
|
1566
|
+
vcRay.setFromCamera(vcMouse, vcCamera);
|
|
1567
|
+
const hits = vcRay.intersectObject(vcCube);
|
|
1568
|
+
if (hits.length > 0) {
|
|
1569
|
+
const fi = hits[0].face.materialIndex;
|
|
1570
|
+
const label = faceLabels[fi];
|
|
1571
|
+
const v = vcViews[label];
|
|
1572
|
+
if (v) {
|
|
1573
|
+
const dist = camera.position.length();
|
|
1574
|
+
const s = dist / 3;
|
|
1575
|
+
camera.position.set(v.x * s, v.y * s, v.z * s);
|
|
1576
|
+
camera.lookAt(controls.target);
|
|
1577
|
+
controls.update();
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
});
|
|
1581
|
+
vcRenderer.domElement.style.cursor = 'pointer';
|
|
1582
|
+
|
|
1478
1583
|
// Animation loop
|
|
1479
1584
|
function animate() {
|
|
1480
1585
|
requestAnimationFrame(animate);
|
|
1481
1586
|
controls.update();
|
|
1482
1587
|
renderer.render(scene, camera);
|
|
1588
|
+
// Sync ViewCube with main camera
|
|
1589
|
+
const dir = new THREE.Vector3();
|
|
1590
|
+
camera.getWorldDirection(dir);
|
|
1591
|
+
vcCube.quaternion.copy(camera.quaternion).invert();
|
|
1592
|
+
vcRenderer.render(vcScene, vcCamera);
|
|
1483
1593
|
}
|
|
1484
1594
|
animate();
|
|
1485
1595
|
|
|
@@ -1562,105 +1672,106 @@
|
|
|
1562
1672
|
break;
|
|
1563
1673
|
case 'tools-text-to-cad':
|
|
1564
1674
|
if (window.CycleCAD && window.CycleCAD.TextToCAD) {
|
|
1565
|
-
const ttcPanel = window.CycleCAD.TextToCAD.getUI();
|
|
1566
1675
|
showDialog('Text-to-CAD (AI)', '');
|
|
1567
|
-
const
|
|
1568
|
-
if (
|
|
1569
|
-
}
|
|
1676
|
+
const db1 = document.getElementById('dialog-body');
|
|
1677
|
+
if (db1) { db1.innerHTML = ''; db1.appendChild(window.CycleCAD.TextToCAD.getUI()); db1.style.maxHeight = '500px'; db1.style.overflow = 'auto'; }
|
|
1678
|
+
} else { showToast('TextToCAD module not loaded', 'error'); }
|
|
1570
1679
|
break;
|
|
1571
1680
|
case 'tools-photo-to-cad':
|
|
1572
1681
|
if (window.CycleCAD && window.CycleCAD.PhotoToCAD) {
|
|
1573
|
-
const ptcPanel = window.CycleCAD.PhotoToCAD.getUI();
|
|
1574
1682
|
showDialog('Photo-to-CAD', '');
|
|
1575
|
-
const
|
|
1576
|
-
if (
|
|
1577
|
-
}
|
|
1683
|
+
const db2 = document.getElementById('dialog-body');
|
|
1684
|
+
if (db2) { db2.innerHTML = ''; db2.appendChild(window.CycleCAD.PhotoToCAD.getUI()); db2.style.maxHeight = '500px'; db2.style.overflow = 'auto'; }
|
|
1685
|
+
} else { showToast('PhotoToCAD module not loaded', 'error'); }
|
|
1578
1686
|
break;
|
|
1579
1687
|
case 'tools-dfm':
|
|
1580
1688
|
if (window.CycleCAD && window.CycleCAD.Manufacturability) {
|
|
1581
|
-
const dfmPanel = window.CycleCAD.Manufacturability.getUI();
|
|
1582
1689
|
showDialog('Manufacturability Check', '');
|
|
1583
|
-
const
|
|
1584
|
-
if (
|
|
1585
|
-
}
|
|
1690
|
+
const db3 = document.getElementById('dialog-body');
|
|
1691
|
+
if (db3) { db3.innerHTML = ''; db3.appendChild(window.CycleCAD.Manufacturability.getUI()); db3.style.maxHeight = '500px'; db3.style.overflow = 'auto'; }
|
|
1692
|
+
} else { showToast('Manufacturability module not loaded', 'error'); }
|
|
1586
1693
|
break;
|
|
1587
1694
|
case 'tools-generative':
|
|
1588
1695
|
if (window.CycleCAD && window.CycleCAD.GenerativeDesign) {
|
|
1589
|
-
const genPanel = window.CycleCAD.GenerativeDesign.getUI();
|
|
1590
1696
|
showDialog('Generative Design', '');
|
|
1591
|
-
const
|
|
1592
|
-
if (
|
|
1593
|
-
}
|
|
1697
|
+
const db4 = document.getElementById('dialog-body');
|
|
1698
|
+
if (db4) { db4.innerHTML = ''; db4.appendChild(window.CycleCAD.GenerativeDesign.getUI()); db4.style.maxHeight = '500px'; db4.style.overflow = 'auto'; }
|
|
1699
|
+
} else { showToast('GenerativeDesign module not loaded', 'error'); }
|
|
1594
1700
|
break;
|
|
1595
1701
|
case 'tools-physics':
|
|
1596
1702
|
if (window.CycleCAD && window.CycleCAD.MultiPhysics) {
|
|
1597
|
-
const physPanel = window.CycleCAD.MultiPhysics.getUI();
|
|
1598
1703
|
showDialog('Multi-Physics Simulation', '');
|
|
1599
|
-
const
|
|
1600
|
-
if (
|
|
1601
|
-
}
|
|
1704
|
+
const db5 = document.getElementById('dialog-body');
|
|
1705
|
+
if (db5) { db5.innerHTML = ''; db5.appendChild(window.CycleCAD.MultiPhysics.getUI()); db5.style.maxHeight = '500px'; db5.style.overflow = 'auto'; }
|
|
1706
|
+
} else { showToast('MultiPhysics module not loaded', 'error'); }
|
|
1602
1707
|
break;
|
|
1603
1708
|
case 'tools-parts':
|
|
1604
1709
|
if (window.CycleCAD && window.CycleCAD.SmartParts) {
|
|
1605
|
-
const partsPanel = window.CycleCAD.SmartParts.getUI();
|
|
1606
1710
|
showDialog('Smart Parts Library', '');
|
|
1607
|
-
const
|
|
1608
|
-
if (
|
|
1609
|
-
}
|
|
1711
|
+
const db6 = document.getElementById('dialog-body');
|
|
1712
|
+
if (db6) { db6.innerHTML = ''; db6.appendChild(window.CycleCAD.SmartParts.getUI()); db6.style.maxHeight = '500px'; db6.style.overflow = 'auto'; }
|
|
1713
|
+
} else { showToast('SmartParts module not loaded', 'error'); }
|
|
1610
1714
|
break;
|
|
1611
1715
|
case 'tools-smart-assembly':
|
|
1612
1716
|
if (window.CycleCAD && window.CycleCAD.SmartAssembly) {
|
|
1613
|
-
const saPanel = window.CycleCAD.SmartAssembly.getUI();
|
|
1614
1717
|
showDialog('Smart Assembly Mating', '');
|
|
1615
|
-
const
|
|
1616
|
-
if (
|
|
1617
|
-
}
|
|
1718
|
+
const db7 = document.getElementById('dialog-body');
|
|
1719
|
+
if (db7) { db7.innerHTML = ''; db7.appendChild(window.CycleCAD.SmartAssembly.getUI()); db7.style.maxHeight = '500px'; db7.style.overflow = 'auto'; }
|
|
1720
|
+
} else { showToast('SmartAssembly module not loaded', 'error'); }
|
|
1618
1721
|
break;
|
|
1619
1722
|
case 'tools-digital-twin':
|
|
1620
1723
|
if (window.CycleCAD && window.CycleCAD.DigitalTwin) {
|
|
1621
|
-
const dtPanel = window.CycleCAD.DigitalTwin.getUI();
|
|
1622
1724
|
showDialog('Digital Twin — Live Data', '');
|
|
1623
|
-
const
|
|
1624
|
-
if (
|
|
1625
|
-
}
|
|
1725
|
+
const db8 = document.getElementById('dialog-body');
|
|
1726
|
+
if (db8) { db8.innerHTML = ''; db8.appendChild(window.CycleCAD.DigitalTwin.getUI()); db8.style.maxHeight = '500px'; db8.style.overflow = 'auto'; }
|
|
1727
|
+
} else { showToast('DigitalTwin module not loaded', 'error'); }
|
|
1626
1728
|
break;
|
|
1627
1729
|
case 'tools-machine':
|
|
1628
1730
|
if (window.CycleCAD && window.CycleCAD.MachineControl) {
|
|
1629
|
-
const mcPanel = window.CycleCAD.MachineControl.getUI();
|
|
1630
1731
|
showDialog('Machine Control — CNC / 3D Printer', '');
|
|
1631
|
-
const
|
|
1632
|
-
if (
|
|
1633
|
-
}
|
|
1732
|
+
const db9 = document.getElementById('dialog-body');
|
|
1733
|
+
if (db9) { db9.innerHTML = ''; db9.appendChild(window.CycleCAD.MachineControl.getUI()); db9.style.maxHeight = '500px'; db9.style.overflow = 'auto'; }
|
|
1734
|
+
} else { showToast('MachineControl module not loaded', 'error'); }
|
|
1634
1735
|
break;
|
|
1635
1736
|
case 'tools-notebook':
|
|
1636
1737
|
if (window.CycleCAD && window.CycleCAD.EngineeringNotebook) {
|
|
1637
|
-
const nbPanel = window.CycleCAD.EngineeringNotebook.getUI();
|
|
1638
1738
|
showDialog('Engineering Notebook', '');
|
|
1639
|
-
const
|
|
1640
|
-
if (
|
|
1641
|
-
}
|
|
1739
|
+
const db10 = document.getElementById('dialog-body');
|
|
1740
|
+
if (db10) { db10.innerHTML = ''; db10.appendChild(window.CycleCAD.EngineeringNotebook.getUI()); db10.style.maxHeight = '500px'; db10.style.overflow = 'auto'; }
|
|
1741
|
+
} else { showToast('EngineeringNotebook module not loaded', 'error'); }
|
|
1642
1742
|
break;
|
|
1643
1743
|
case 'tools-auto-assembly':
|
|
1644
1744
|
if (window.CycleCAD && window.CycleCAD.AutoAssembly) {
|
|
1645
|
-
const aaPanel = window.CycleCAD.AutoAssembly.getUI();
|
|
1646
1745
|
showDialog('Auto-Assemble Parts', '');
|
|
1647
|
-
const
|
|
1648
|
-
if (
|
|
1649
|
-
}
|
|
1746
|
+
const db11 = document.getElementById('dialog-body');
|
|
1747
|
+
if (db11) { db11.innerHTML = ''; db11.appendChild(window.CycleCAD.AutoAssembly.getUI()); db11.style.maxHeight = '500px'; db11.style.overflow = 'auto'; }
|
|
1748
|
+
} else { showToast('AutoAssembly module not loaded', 'error'); }
|
|
1650
1749
|
break;
|
|
1651
1750
|
case 'tools-parametric':
|
|
1652
1751
|
if (window.CycleCAD && window.CycleCAD.ParametricFromExample) {
|
|
1653
|
-
const pfPanel = window.CycleCAD.ParametricFromExample.getUI();
|
|
1654
1752
|
showDialog('Parametric from Example', '');
|
|
1655
|
-
const
|
|
1656
|
-
if (
|
|
1657
|
-
}
|
|
1753
|
+
const db12 = document.getElementById('dialog-body');
|
|
1754
|
+
if (db12) { db12.innerHTML = ''; db12.appendChild(window.CycleCAD.ParametricFromExample.getUI()); db12.style.maxHeight = '500px'; db12.style.overflow = 'auto'; }
|
|
1755
|
+
} else { showToast('ParametricFromExample module not loaded', 'error'); }
|
|
1658
1756
|
break;
|
|
1659
1757
|
default:
|
|
1660
1758
|
showToast(`${action}`, 'success');
|
|
1661
1759
|
}
|
|
1662
1760
|
}
|
|
1663
1761
|
|
|
1762
|
+
// ===== Handle pending splash action =====
|
|
1763
|
+
if (window._pendingSplashAction) {
|
|
1764
|
+
const pa = window._pendingSplashAction;
|
|
1765
|
+
window._pendingSplashAction = null;
|
|
1766
|
+
handleMenuAction(pa);
|
|
1767
|
+
}
|
|
1768
|
+
// Process splash actions dispatched after module load
|
|
1769
|
+
Object.defineProperty(window, '_pendingSplashAction', {
|
|
1770
|
+
set(v) { if (v) { setTimeout(() => handleMenuAction(v), 100); } },
|
|
1771
|
+
get() { return null; },
|
|
1772
|
+
configurable: true
|
|
1773
|
+
});
|
|
1774
|
+
|
|
1664
1775
|
// ===== Workspace Switching =====
|
|
1665
1776
|
workspaceTabs.forEach(tab => {
|
|
1666
1777
|
tab.addEventListener('click', (e) => {
|
|
@@ -212,7 +212,7 @@
|
|
|
212
212
|
if (/add|with|plus/.test(lower)) return 'add';
|
|
213
213
|
if (/(fillet|chamfer|pattern|shell|subtract|cut)/.test(lower)) return 'modify';
|
|
214
214
|
if (/combine|merge|join|union/.test(lower)) return 'combine';
|
|
215
|
-
if /(array|repeat|pattern)/.test(lower)) return 'pattern';
|
|
215
|
+
if (/(array|repeat|pattern)/.test(lower)) return 'pattern';
|
|
216
216
|
if (/export|save|output/.test(lower)) return 'export';
|
|
217
217
|
return 'create';
|
|
218
218
|
}
|
|
Binary file
|
package/fix-splash-v2.sh
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Fix splash screen buttons - v2 (uses global onclick + inline handlers)
|
|
3
|
+
# Run from ~/cyclecad: bash fix-splash-v2.sh
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
cd "$(dirname "$0")"
|
|
7
|
+
|
|
8
|
+
echo "=== Replacing welcome splash with working version ==="
|
|
9
|
+
|
|
10
|
+
python3 << 'PYEOF'
|
|
11
|
+
with open('app/index.html', 'r') as f:
|
|
12
|
+
content = f.read()
|
|
13
|
+
|
|
14
|
+
# Remove old welcome panel if it exists
|
|
15
|
+
import re
|
|
16
|
+
content = re.sub(
|
|
17
|
+
r'<!-- Welcome Splash Screen -->.*?</div>\s*</div>\s*</div>\s*\n\n',
|
|
18
|
+
'',
|
|
19
|
+
content,
|
|
20
|
+
flags=re.DOTALL
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# Remove old welcome splash JS wiring if it exists
|
|
24
|
+
content = content.replace(
|
|
25
|
+
""" // ===== Welcome Splash =====
|
|
26
|
+
const welcomePanel = document.getElementById('welcome-panel');
|
|
27
|
+
if (welcomePanel) {
|
|
28
|
+
const dismissWelcome = () => { welcomePanel.style.display = 'none'; };
|
|
29
|
+
const wb1 = welcomePanel.querySelector('[data-action="new-sketch"]');
|
|
30
|
+
if (wb1) wb1.onclick = () => { dismissWelcome(); handleMenuAction('sketch-new'); };
|
|
31
|
+
const wb2 = welcomePanel.querySelector('[data-action="import"]');
|
|
32
|
+
if (wb2) wb2.onclick = () => { dismissWelcome(); handleMenuAction('file-import'); };
|
|
33
|
+
const wb3 = welcomePanel.querySelector('[data-action="ai-generate"]');
|
|
34
|
+
if (wb3) wb3.onclick = () => { dismissWelcome(); handleMenuAction('tools-text-to-cad'); };
|
|
35
|
+
const wb4 = welcomePanel.querySelector('[data-action="load-inventor"]');
|
|
36
|
+
if (wb4) wb4.onclick = () => { dismissWelcome(); handleMenuAction('file-import'); };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
""",
|
|
40
|
+
""
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# New splash with INLINE onclick handlers that use a global function
|
|
44
|
+
new_splash = '''<!-- Welcome Splash Screen -->
|
|
45
|
+
<div id="welcome-panel" style="position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.75);display:flex;align-items:center;justify-content:center;z-index:9999;">
|
|
46
|
+
<div style="background:#252526;border:1px solid #3c3c3c;border-radius:12px;padding:40px 48px;max-width:560px;width:90%;text-align:center;box-shadow:0 20px 60px rgba(0,0,0,0.5);">
|
|
47
|
+
<div style="font-size:36px;margin-bottom:4px;">
|
|
48
|
+
<span style="color:#0284C7;font-weight:700;">cycle</span><span style="color:#e0e0e0;font-weight:300;">CAD</span>
|
|
49
|
+
</div>
|
|
50
|
+
<div style="color:#888;font-size:13px;margin-bottom:28px;">Agent-First Parametric 3D CAD Modeler</div>
|
|
51
|
+
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:20px;">
|
|
52
|
+
<button onclick="window._dismissSplash('sketch')" style="background:#0284C7;color:#fff;border:none;border-radius:8px;padding:18px 16px;cursor:pointer;font-size:14px;font-weight:600;">
|
|
53
|
+
<div style="font-size:24px;margin-bottom:6px;">✏️</div>
|
|
54
|
+
New Sketch
|
|
55
|
+
<div style="font-size:11px;font-weight:400;color:rgba(255,255,255,0.7);margin-top:4px;">Start with a 2D sketch</div>
|
|
56
|
+
</button>
|
|
57
|
+
<button onclick="window._dismissSplash('import')" style="background:#374151;color:#fff;border:1px solid #4b5563;border-radius:8px;padding:18px 16px;cursor:pointer;font-size:14px;font-weight:600;">
|
|
58
|
+
<div style="font-size:24px;margin-bottom:6px;">📂</div>
|
|
59
|
+
Open / Import
|
|
60
|
+
<div style="font-size:11px;font-weight:400;color:rgba(255,255,255,0.7);margin-top:4px;">STEP, STL, Inventor, JSON</div>
|
|
61
|
+
</button>
|
|
62
|
+
<button onclick="window._dismissSplash('textcad')" style="background:#374151;color:#fff;border:1px solid #4b5563;border-radius:8px;padding:18px 16px;cursor:pointer;font-size:14px;font-weight:600;">
|
|
63
|
+
<div style="font-size:24px;margin-bottom:6px;">🤖</div>
|
|
64
|
+
Text-to-CAD
|
|
65
|
+
<div style="font-size:11px;font-weight:400;color:rgba(255,255,255,0.7);margin-top:4px;">Describe a part in English</div>
|
|
66
|
+
</button>
|
|
67
|
+
<button onclick="window._dismissSplash('inventor')" style="background:#374151;color:#fff;border:1px solid #4b5563;border-radius:8px;padding:18px 16px;cursor:pointer;font-size:14px;font-weight:600;">
|
|
68
|
+
<div style="font-size:24px;margin-bottom:6px;">🏭</div>
|
|
69
|
+
Inventor Project
|
|
70
|
+
<div style="font-size:11px;font-weight:400;color:rgba(255,255,255,0.7);margin-top:4px;">Load .ipj / .ipt / .iam</div>
|
|
71
|
+
</button>
|
|
72
|
+
</div>
|
|
73
|
+
<div style="color:#666;font-size:11px;">v0.9.0 · 12 killer features · 46 modules · <a href="https://github.com/vvlars-cmd/cyclecad" target="_blank" style="color:#0284C7;text-decoration:none;">GitHub</a></div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
<script>
|
|
77
|
+
window._dismissSplash = function(action) {
|
|
78
|
+
document.getElementById('welcome-panel').style.display = 'none';
|
|
79
|
+
if (action === 'sketch') {
|
|
80
|
+
// Will be handled by module script once loaded
|
|
81
|
+
window._pendingSplashAction = 'sketch-new';
|
|
82
|
+
} else if (action === 'import' || action === 'inventor') {
|
|
83
|
+
window._pendingSplashAction = 'file-import';
|
|
84
|
+
} else if (action === 'textcad') {
|
|
85
|
+
window._pendingSplashAction = 'tools-text-to-cad';
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
</script>
|
|
89
|
+
|
|
90
|
+
'''
|
|
91
|
+
|
|
92
|
+
# Insert before modal dialogs
|
|
93
|
+
content = content.replace('<!-- Modal Dialogs -->', new_splash + '<!-- Modal Dialogs -->')
|
|
94
|
+
|
|
95
|
+
# Add pending action handler inside the module script, right after menu handler definition
|
|
96
|
+
# Find the end of handleMenuAction and add a check for pending splash action
|
|
97
|
+
old_menu_end = " // ===== Workspace Switching ====="
|
|
98
|
+
new_menu_end = """ // ===== Handle pending splash action =====
|
|
99
|
+
if (window._pendingSplashAction) {
|
|
100
|
+
const pa = window._pendingSplashAction;
|
|
101
|
+
window._pendingSplashAction = null;
|
|
102
|
+
handleMenuAction(pa);
|
|
103
|
+
}
|
|
104
|
+
// Process splash actions dispatched after module load
|
|
105
|
+
Object.defineProperty(window, '_pendingSplashAction', {
|
|
106
|
+
set(v) { if (v) { setTimeout(() => handleMenuAction(v), 100); } },
|
|
107
|
+
get() { return null; },
|
|
108
|
+
configurable: true
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// ===== Workspace Switching ====="""
|
|
112
|
+
|
|
113
|
+
content = content.replace(old_menu_end, new_menu_end, 1)
|
|
114
|
+
|
|
115
|
+
with open('app/index.html', 'w') as f:
|
|
116
|
+
f.write(content)
|
|
117
|
+
|
|
118
|
+
print('Splash v2 applied successfully!')
|
|
119
|
+
PYEOF
|
|
120
|
+
|
|
121
|
+
echo ""
|
|
122
|
+
echo "=== Done! Now run: ==="
|
|
123
|
+
echo " git add app/index.html && git commit -m 'Fix splash buttons with global onclick handlers' && git push origin main"
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# cycleCAD Fix: Welcome Splash + ViewCube + Dialog Selectors + Remove Demo Geometry
|
|
3
|
+
# Run from ~/cyclecad: bash fix-splash-viewcube.sh
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
cd "$(dirname "$0")"
|
|
7
|
+
|
|
8
|
+
echo "=== Fix 1: text-to-cad.js syntax error (line 215) ==="
|
|
9
|
+
sed -i.bak 's/ if \/(array|repeat|pattern)\/.test(lower)) return '\''pattern'\'';/ if (\/(array|repeat|pattern)\/.test(lower)) return '\''pattern'\'';/' app/js/modules/text-to-cad.js
|
|
10
|
+
rm -f app/js/modules/text-to-cad.js.bak
|
|
11
|
+
|
|
12
|
+
echo "=== Fix 2: Replace .dialog-content with #dialog-body in all 12 tool handlers ==="
|
|
13
|
+
sed -i.bak "s/document.querySelector('.dialog-content')/document.getElementById('dialog-body')/g" app/index.html
|
|
14
|
+
rm -f app/index.html.bak
|
|
15
|
+
|
|
16
|
+
echo "=== Fix 3: Remove demo geometry (box + cylinder) ==="
|
|
17
|
+
# Remove the demo geometry block between "Demo geometry" and "Ground plane"
|
|
18
|
+
python3 -c "
|
|
19
|
+
import re
|
|
20
|
+
with open('app/index.html', 'r') as f:
|
|
21
|
+
content = f.read()
|
|
22
|
+
|
|
23
|
+
# Remove demo geometry block
|
|
24
|
+
content = re.sub(
|
|
25
|
+
r' // Demo geometry.*?scene\.add\(cyl\);\n\n // Ground plane',
|
|
26
|
+
' // Ground plane',
|
|
27
|
+
content,
|
|
28
|
+
flags=re.DOTALL
|
|
29
|
+
)
|
|
30
|
+
with open('app/index.html', 'w') as f:
|
|
31
|
+
f.write(content)
|
|
32
|
+
print('Demo geometry removed')
|
|
33
|
+
"
|
|
34
|
+
|
|
35
|
+
echo "=== Fix 4: Add welcome splash panel ==="
|
|
36
|
+
python3 -c "
|
|
37
|
+
with open('app/index.html', 'r') as f:
|
|
38
|
+
content = f.read()
|
|
39
|
+
|
|
40
|
+
splash = '''<!-- Welcome Splash Screen -->
|
|
41
|
+
<div id=\"welcome-panel\" style=\"position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.75);display:flex;align-items:center;justify-content:center;z-index:9999;\">
|
|
42
|
+
<div style=\"background:var(--bg-secondary,#252526);border:1px solid var(--border-color,#3c3c3c);border-radius:12px;padding:40px 48px;max-width:560px;width:90%;text-align:center;box-shadow:0 20px 60px rgba(0,0,0,0.5);\">
|
|
43
|
+
<div style=\"font-size:36px;margin-bottom:4px;\">
|
|
44
|
+
<span style=\"color:#0284C7;font-weight:700;\">cycle</span><span style=\"color:#e0e0e0;font-weight:300;\">CAD</span>
|
|
45
|
+
</div>
|
|
46
|
+
<div style=\"color:#888;font-size:13px;margin-bottom:28px;\">Agent-First Parametric 3D CAD Modeler</div>
|
|
47
|
+
<div style=\"display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:20px;\">
|
|
48
|
+
<button data-action=\"new-sketch\" style=\"background:#0284C7;color:#fff;border:none;border-radius:8px;padding:18px 16px;cursor:pointer;font-size:14px;font-weight:600;\" onmouseover=\"this.style.background='#0369a1'\" onmouseout=\"this.style.background='#0284C7'\">
|
|
49
|
+
<div style=\"font-size:24px;margin-bottom:6px;\">✏️</div>
|
|
50
|
+
New Sketch
|
|
51
|
+
<div style=\"font-size:11px;font-weight:400;color:rgba(255,255,255,0.7);margin-top:4px;\">Start with a 2D sketch</div>
|
|
52
|
+
</button>
|
|
53
|
+
<button data-action=\"import\" style=\"background:#374151;color:#fff;border:1px solid #4b5563;border-radius:8px;padding:18px 16px;cursor:pointer;font-size:14px;font-weight:600;\" onmouseover=\"this.style.background='#4b5563'\" onmouseout=\"this.style.background='#374151'\">
|
|
54
|
+
<div style=\"font-size:24px;margin-bottom:6px;\">📂</div>
|
|
55
|
+
Open / Import
|
|
56
|
+
<div style=\"font-size:11px;font-weight:400;color:rgba(255,255,255,0.7);margin-top:4px;\">STEP, STL, Inventor, JSON</div>
|
|
57
|
+
</button>
|
|
58
|
+
<button data-action=\"ai-generate\" style=\"background:#374151;color:#fff;border:1px solid #4b5563;border-radius:8px;padding:18px 16px;cursor:pointer;font-size:14px;font-weight:600;\" onmouseover=\"this.style.background='#4b5563'\" onmouseout=\"this.style.background='#374151'\">
|
|
59
|
+
<div style=\"font-size:24px;margin-bottom:6px;\">🤖</div>
|
|
60
|
+
Text-to-CAD
|
|
61
|
+
<div style=\"font-size:11px;font-weight:400;color:rgba(255,255,255,0.7);margin-top:4px;\">Describe a part in English</div>
|
|
62
|
+
</button>
|
|
63
|
+
<button data-action=\"load-inventor\" style=\"background:#374151;color:#fff;border:1px solid #4b5563;border-radius:8px;padding:18px 16px;cursor:pointer;font-size:14px;font-weight:600;\" onmouseover=\"this.style.background='#4b5563'\" onmouseout=\"this.style.background='#374151'\">
|
|
64
|
+
<div style=\"font-size:24px;margin-bottom:6px;\">🏭</div>
|
|
65
|
+
Inventor Project
|
|
66
|
+
<div style=\"font-size:11px;font-weight:400;color:rgba(255,255,255,0.7);margin-top:4px;\">Load .ipj / .ipt / .iam</div>
|
|
67
|
+
</button>
|
|
68
|
+
</div>
|
|
69
|
+
<div style=\"color:#666;font-size:11px;\">v0.9.0 · 12 killer features · 46 modules · <a href=\"https://github.com/vvlars-cmd/cyclecad\" target=\"_blank\" style=\"color:#0284C7;text-decoration:none;\">GitHub</a></div>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
'''
|
|
74
|
+
|
|
75
|
+
# Insert before modal dialogs
|
|
76
|
+
content = content.replace('<!-- Modal Dialogs -->', splash + '<!-- Modal Dialogs -->')
|
|
77
|
+
with open('app/index.html', 'w') as f:
|
|
78
|
+
f.write(content)
|
|
79
|
+
print('Welcome splash added')
|
|
80
|
+
"
|
|
81
|
+
|
|
82
|
+
echo "=== Fix 5: Add ViewCube to viewport ==="
|
|
83
|
+
python3 -c "
|
|
84
|
+
with open('app/index.html', 'r') as f:
|
|
85
|
+
content = f.read()
|
|
86
|
+
|
|
87
|
+
# Add position:relative and viewcube div to viewport-container
|
|
88
|
+
content = content.replace(
|
|
89
|
+
'<div id=\"viewport-container\">',
|
|
90
|
+
'<div id=\"viewport-container\" style=\"position:relative;\">'
|
|
91
|
+
)
|
|
92
|
+
content = content.replace(
|
|
93
|
+
'</canvas>\n </div>\n\n <!-- Right Panel',
|
|
94
|
+
'</canvas>\n <div id=\"viewcube\" style=\"position:absolute;top:12px;right:12px;width:90px;height:90px;pointer-events:auto;z-index:100;\"></div>\n </div>\n\n <!-- Right Panel'
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# Add ViewCube JS before animation loop
|
|
98
|
+
viewcube_js = ''' // ===== ViewCube =====
|
|
99
|
+
const vcContainer = document.getElementById('viewcube');
|
|
100
|
+
const vcScene = new THREE.Scene();
|
|
101
|
+
const vcCamera = new THREE.PerspectiveCamera(40, 1, 0.1, 100);
|
|
102
|
+
vcCamera.position.set(0, 0, 3.5);
|
|
103
|
+
const vcRenderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
|
|
104
|
+
vcRenderer.setSize(90, 90);
|
|
105
|
+
vcRenderer.setPixelRatio(window.devicePixelRatio);
|
|
106
|
+
vcContainer.appendChild(vcRenderer.domElement);
|
|
107
|
+
const faceLabels = ['Right', 'Left', 'Top', 'Bottom', 'Front', 'Back'];
|
|
108
|
+
const faceColors = [0x3b82f6, 0x3b82f6, 0x10b981, 0x10b981, 0x0284C7, 0x0284C7];
|
|
109
|
+
const cubeMats = faceLabels.map((label, i) => {
|
|
110
|
+
const canvas = document.createElement('canvas');
|
|
111
|
+
canvas.width = 128; canvas.height = 128;
|
|
112
|
+
const ctx = canvas.getContext('2d');
|
|
113
|
+
ctx.fillStyle = '#' + faceColors[i].toString(16).padStart(6, '0');
|
|
114
|
+
ctx.fillRect(0, 0, 128, 128);
|
|
115
|
+
ctx.strokeStyle = '#1e293b'; ctx.lineWidth = 3; ctx.strokeRect(1, 1, 126, 126);
|
|
116
|
+
ctx.fillStyle = '#fff'; ctx.font = 'bold 22px Arial'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle';
|
|
117
|
+
ctx.fillText(label, 64, 64);
|
|
118
|
+
return new THREE.MeshBasicMaterial({ map: new THREE.CanvasTexture(canvas) });
|
|
119
|
+
});
|
|
120
|
+
const vcCube = new THREE.Mesh(new THREE.BoxGeometry(1.6, 1.6, 1.6), cubeMats);
|
|
121
|
+
vcScene.add(vcCube);
|
|
122
|
+
const axLen = 1.3;
|
|
123
|
+
const axMat = (c) => new THREE.LineBasicMaterial({ color: c });
|
|
124
|
+
const axGeo = (v) => new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(), v]);
|
|
125
|
+
vcScene.add(new THREE.Line(axGeo(new THREE.Vector3(axLen, 0, 0)), axMat(0xff4444)));
|
|
126
|
+
vcScene.add(new THREE.Line(axGeo(new THREE.Vector3(0, axLen, 0)), axMat(0x44ff44)));
|
|
127
|
+
vcScene.add(new THREE.Line(axGeo(new THREE.Vector3(0, 0, axLen)), axMat(0x4444ff)));
|
|
128
|
+
const vcViews = { Right:{x:3,y:0,z:0}, Left:{x:-3,y:0,z:0}, Top:{x:0,y:3,z:0}, Bottom:{x:0,y:-3,z:0}, Front:{x:0,y:0,z:3}, Back:{x:0,y:0,z:-3} };
|
|
129
|
+
const vcRay = new THREE.Raycaster(); const vcMouse = new THREE.Vector2();
|
|
130
|
+
vcRenderer.domElement.addEventListener('click', (e) => {
|
|
131
|
+
const rect = vcRenderer.domElement.getBoundingClientRect();
|
|
132
|
+
vcMouse.x = ((e.clientX - rect.left) / rect.width) * 2 - 1;
|
|
133
|
+
vcMouse.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;
|
|
134
|
+
vcRay.setFromCamera(vcMouse, vcCamera);
|
|
135
|
+
const hits = vcRay.intersectObject(vcCube);
|
|
136
|
+
if (hits.length > 0) {
|
|
137
|
+
const v = vcViews[faceLabels[hits[0].face.materialIndex]];
|
|
138
|
+
if (v) { const s = camera.position.length() / 3; camera.position.set(v.x*s, v.y*s, v.z*s); camera.lookAt(controls.target); controls.update(); }
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
vcRenderer.domElement.style.cursor = 'pointer';
|
|
142
|
+
|
|
143
|
+
'''
|
|
144
|
+
|
|
145
|
+
content = content.replace(
|
|
146
|
+
' // Animation loop\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }',
|
|
147
|
+
viewcube_js + ' // Animation loop\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n vcCube.quaternion.copy(camera.quaternion).invert();\n vcRenderer.render(vcScene, vcCamera);\n }'
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
# Add welcome splash wiring before menu handler
|
|
151
|
+
splash_js = ''' // ===== Welcome Splash =====
|
|
152
|
+
const welcomePanel = document.getElementById('welcome-panel');
|
|
153
|
+
if (welcomePanel) {
|
|
154
|
+
const dismissWelcome = () => { welcomePanel.style.display = 'none'; };
|
|
155
|
+
const wb1 = welcomePanel.querySelector('[data-action=\"new-sketch\"]');
|
|
156
|
+
if (wb1) wb1.onclick = () => { dismissWelcome(); handleMenuAction('sketch-new'); };
|
|
157
|
+
const wb2 = welcomePanel.querySelector('[data-action=\"import\"]');
|
|
158
|
+
if (wb2) wb2.onclick = () => { dismissWelcome(); handleMenuAction('file-import'); };
|
|
159
|
+
const wb3 = welcomePanel.querySelector('[data-action=\"ai-generate\"]');
|
|
160
|
+
if (wb3) wb3.onclick = () => { dismissWelcome(); handleMenuAction('tools-text-to-cad'); };
|
|
161
|
+
const wb4 = welcomePanel.querySelector('[data-action=\"load-inventor\"]');
|
|
162
|
+
if (wb4) wb4.onclick = () => { dismissWelcome(); handleMenuAction('file-import'); };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
'''
|
|
166
|
+
|
|
167
|
+
content = content.replace(' // ===== Menu Actions Handler =====', splash_js + ' // ===== Menu Actions Handler =====')
|
|
168
|
+
|
|
169
|
+
with open('app/index.html', 'w') as f:
|
|
170
|
+
f.write(content)
|
|
171
|
+
print('ViewCube + welcome wiring added')
|
|
172
|
+
"
|
|
173
|
+
|
|
174
|
+
echo ""
|
|
175
|
+
echo "=== All fixes applied! ==="
|
|
176
|
+
echo ""
|
|
177
|
+
echo "Now run:"
|
|
178
|
+
echo " git add app/index.html app/js/modules/text-to-cad.js"
|
|
179
|
+
echo " git commit -m 'Fix: welcome splash, ViewCube, dialog selectors, remove demo geometry'"
|
|
180
|
+
echo " git push origin main"
|
|
181
|
+
echo " npm version patch && npm publish"
|
package/package.json
CHANGED