cyclecad 3.9.1 → 3.9.2
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 +211 -65
- package/app/js/modules/text-to-cad.js +1 -1
- package/cycleWASH-NRW-Prospects.xlsx +0 -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,72 @@
|
|
|
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: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);">
|
|
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 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;transition:background 0.2s;" onmouseover="this.style.background='#0369a1'" onmouseout="this.style.background='#0284C7'">
|
|
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 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;transition:background 0.2s;" onmouseover="this.style.background='#4b5563'" onmouseout="this.style.background='#374151'">
|
|
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 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;transition:background 0.2s;" onmouseover="this.style.background='#4b5563'" onmouseout="this.style.background='#374151'">
|
|
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 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;transition:background 0.2s;" onmouseover="this.style.background='#4b5563'" onmouseout="this.style.background='#374151'">
|
|
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
|
+
|
|
1344
|
+
<!-- Welcome Splash Screen -->
|
|
1345
|
+
<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;">
|
|
1346
|
+
<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);">
|
|
1347
|
+
<div style="font-size:36px;margin-bottom:4px;">
|
|
1348
|
+
<span style="color:#0284C7;font-weight:700;">cycle</span><span style="color:#e0e0e0;font-weight:300;">CAD</span>
|
|
1349
|
+
</div>
|
|
1350
|
+
<div style="color:#888;font-size:13px;margin-bottom:28px;">Agent-First Parametric 3D CAD Modeler</div>
|
|
1351
|
+
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:20px;">
|
|
1352
|
+
<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'">
|
|
1353
|
+
<div style="font-size:24px;margin-bottom:6px;">✏️</div>
|
|
1354
|
+
New Sketch
|
|
1355
|
+
<div style="font-size:11px;font-weight:400;color:rgba(255,255,255,0.7);margin-top:4px;">Start with a 2D sketch</div>
|
|
1356
|
+
</button>
|
|
1357
|
+
<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'">
|
|
1358
|
+
<div style="font-size:24px;margin-bottom:6px;">📂</div>
|
|
1359
|
+
Open / Import
|
|
1360
|
+
<div style="font-size:11px;font-weight:400;color:rgba(255,255,255,0.7);margin-top:4px;">STEP, STL, Inventor, JSON</div>
|
|
1361
|
+
</button>
|
|
1362
|
+
<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'">
|
|
1363
|
+
<div style="font-size:24px;margin-bottom:6px;">🤖</div>
|
|
1364
|
+
Text-to-CAD
|
|
1365
|
+
<div style="font-size:11px;font-weight:400;color:rgba(255,255,255,0.7);margin-top:4px;">Describe a part in English</div>
|
|
1366
|
+
</button>
|
|
1367
|
+
<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'">
|
|
1368
|
+
<div style="font-size:24px;margin-bottom:6px;">🏭</div>
|
|
1369
|
+
Inventor Project
|
|
1370
|
+
<div style="font-size:11px;font-weight:400;color:rgba(255,255,255,0.7);margin-top:4px;">Load .ipj / .ipt / .iam</div>
|
|
1371
|
+
</button>
|
|
1372
|
+
</div>
|
|
1373
|
+
<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>
|
|
1374
|
+
</div>
|
|
1375
|
+
</div>
|
|
1376
|
+
|
|
1309
1377
|
<!-- Modal Dialogs -->
|
|
1310
1378
|
<div id="dialog-overlay" class="modal-overlay">
|
|
1311
1379
|
<div class="modal-dialog">
|
|
@@ -1447,22 +1515,6 @@
|
|
|
1447
1515
|
const grid = new THREE.GridHelper(500, 50, 0x444444, 0x333333);
|
|
1448
1516
|
scene.add(grid);
|
|
1449
1517
|
|
|
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
1518
|
// Ground plane
|
|
1467
1519
|
const groundGeo = new THREE.PlaneGeometry(500, 500);
|
|
1468
1520
|
const groundMat = new THREE.ShadowMaterial({ opacity: 0.15 });
|
|
@@ -1475,11 +1527,89 @@
|
|
|
1475
1527
|
new ResizeObserver(resizeViewport).observe(viewportEl);
|
|
1476
1528
|
resizeViewport(); // Call initial resize to set canvas dimensions
|
|
1477
1529
|
|
|
1530
|
+
// ===== ViewCube =====
|
|
1531
|
+
const vcContainer = document.getElementById('viewcube');
|
|
1532
|
+
const vcScene = new THREE.Scene();
|
|
1533
|
+
const vcCamera = new THREE.PerspectiveCamera(40, 1, 0.1, 100);
|
|
1534
|
+
vcCamera.position.set(0, 0, 3.5);
|
|
1535
|
+
const vcRenderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
|
|
1536
|
+
vcRenderer.setSize(90, 90);
|
|
1537
|
+
vcRenderer.setPixelRatio(window.devicePixelRatio);
|
|
1538
|
+
vcContainer.appendChild(vcRenderer.domElement);
|
|
1539
|
+
|
|
1540
|
+
// Cube faces
|
|
1541
|
+
const faceLabels = ['Right', 'Left', 'Top', 'Bottom', 'Front', 'Back'];
|
|
1542
|
+
const faceColors = [0x3b82f6, 0x3b82f6, 0x10b981, 0x10b981, 0x0284C7, 0x0284C7];
|
|
1543
|
+
const cubeMats = faceLabels.map((label, i) => {
|
|
1544
|
+
const canvas = document.createElement('canvas');
|
|
1545
|
+
canvas.width = 128; canvas.height = 128;
|
|
1546
|
+
const ctx = canvas.getContext('2d');
|
|
1547
|
+
ctx.fillStyle = '#' + faceColors[i].toString(16).padStart(6, '0');
|
|
1548
|
+
ctx.fillRect(0, 0, 128, 128);
|
|
1549
|
+
ctx.strokeStyle = '#1e293b';
|
|
1550
|
+
ctx.lineWidth = 3;
|
|
1551
|
+
ctx.strokeRect(1, 1, 126, 126);
|
|
1552
|
+
ctx.fillStyle = '#fff';
|
|
1553
|
+
ctx.font = 'bold 22px Arial';
|
|
1554
|
+
ctx.textAlign = 'center';
|
|
1555
|
+
ctx.textBaseline = 'middle';
|
|
1556
|
+
ctx.fillText(label, 64, 64);
|
|
1557
|
+
const tex = new THREE.CanvasTexture(canvas);
|
|
1558
|
+
return new THREE.MeshBasicMaterial({ map: tex });
|
|
1559
|
+
});
|
|
1560
|
+
const vcCube = new THREE.Mesh(new THREE.BoxGeometry(1.6, 1.6, 1.6), cubeMats);
|
|
1561
|
+
vcScene.add(vcCube);
|
|
1562
|
+
|
|
1563
|
+
// Axis lines on viewcube
|
|
1564
|
+
const axLen = 1.3;
|
|
1565
|
+
const axMat = (c) => new THREE.LineBasicMaterial({ color: c });
|
|
1566
|
+
const axGeo = (v) => new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(), v]);
|
|
1567
|
+
vcScene.add(new THREE.Line(axGeo(new THREE.Vector3(axLen, 0, 0)), axMat(0xff4444)));
|
|
1568
|
+
vcScene.add(new THREE.Line(axGeo(new THREE.Vector3(0, axLen, 0)), axMat(0x44ff44)));
|
|
1569
|
+
vcScene.add(new THREE.Line(axGeo(new THREE.Vector3(0, 0, axLen)), axMat(0x4444ff)));
|
|
1570
|
+
|
|
1571
|
+
// ViewCube click → snap camera to face
|
|
1572
|
+
const vcViews = {
|
|
1573
|
+
Right: { x: 3, y: 0, z: 0 },
|
|
1574
|
+
Left: { x: -3, y: 0, z: 0 },
|
|
1575
|
+
Top: { x: 0, y: 3, z: 0 },
|
|
1576
|
+
Bottom: { x: 0, y: -3, z: 0 },
|
|
1577
|
+
Front: { x: 0, y: 0, z: 3 },
|
|
1578
|
+
Back: { x: 0, y: 0, z: -3 }
|
|
1579
|
+
};
|
|
1580
|
+
const vcRay = new THREE.Raycaster();
|
|
1581
|
+
const vcMouse = new THREE.Vector2();
|
|
1582
|
+
vcRenderer.domElement.addEventListener('click', (e) => {
|
|
1583
|
+
const rect = vcRenderer.domElement.getBoundingClientRect();
|
|
1584
|
+
vcMouse.x = ((e.clientX - rect.left) / rect.width) * 2 - 1;
|
|
1585
|
+
vcMouse.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;
|
|
1586
|
+
vcRay.setFromCamera(vcMouse, vcCamera);
|
|
1587
|
+
const hits = vcRay.intersectObject(vcCube);
|
|
1588
|
+
if (hits.length > 0) {
|
|
1589
|
+
const fi = hits[0].face.materialIndex;
|
|
1590
|
+
const label = faceLabels[fi];
|
|
1591
|
+
const v = vcViews[label];
|
|
1592
|
+
if (v) {
|
|
1593
|
+
const dist = camera.position.length();
|
|
1594
|
+
const s = dist / 3;
|
|
1595
|
+
camera.position.set(v.x * s, v.y * s, v.z * s);
|
|
1596
|
+
camera.lookAt(controls.target);
|
|
1597
|
+
controls.update();
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
});
|
|
1601
|
+
vcRenderer.domElement.style.cursor = 'pointer';
|
|
1602
|
+
|
|
1478
1603
|
// Animation loop
|
|
1479
1604
|
function animate() {
|
|
1480
1605
|
requestAnimationFrame(animate);
|
|
1481
1606
|
controls.update();
|
|
1482
1607
|
renderer.render(scene, camera);
|
|
1608
|
+
// Sync ViewCube with main camera
|
|
1609
|
+
const dir = new THREE.Vector3();
|
|
1610
|
+
camera.getWorldDirection(dir);
|
|
1611
|
+
vcCube.quaternion.copy(camera.quaternion).invert();
|
|
1612
|
+
vcRenderer.render(vcScene, vcCamera);
|
|
1483
1613
|
}
|
|
1484
1614
|
animate();
|
|
1485
1615
|
|
|
@@ -1513,6 +1643,34 @@
|
|
|
1513
1643
|
const statusBar = document.getElementById('status-bar');
|
|
1514
1644
|
const timelineContent = document.getElementById('timeline-content');
|
|
1515
1645
|
|
|
1646
|
+
// ===== Welcome Splash =====
|
|
1647
|
+
const welcomePanel = document.getElementById('welcome-panel');
|
|
1648
|
+
if (welcomePanel) {
|
|
1649
|
+
const dismissWelcome = () => { welcomePanel.style.display = 'none'; };
|
|
1650
|
+
const wb1 = welcomePanel.querySelector('[data-action="new-sketch"]');
|
|
1651
|
+
if (wb1) wb1.onclick = () => { dismissWelcome(); handleMenuAction('sketch-new'); };
|
|
1652
|
+
const wb2 = welcomePanel.querySelector('[data-action="import"]');
|
|
1653
|
+
if (wb2) wb2.onclick = () => { dismissWelcome(); handleMenuAction('file-import'); };
|
|
1654
|
+
const wb3 = welcomePanel.querySelector('[data-action="ai-generate"]');
|
|
1655
|
+
if (wb3) wb3.onclick = () => { dismissWelcome(); handleMenuAction('tools-text-to-cad'); };
|
|
1656
|
+
const wb4 = welcomePanel.querySelector('[data-action="load-inventor"]');
|
|
1657
|
+
if (wb4) wb4.onclick = () => { dismissWelcome(); handleMenuAction('file-import'); };
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
// ===== Welcome Splash =====
|
|
1661
|
+
const welcomePanel = document.getElementById('welcome-panel');
|
|
1662
|
+
if (welcomePanel) {
|
|
1663
|
+
const dismissWelcome = () => { welcomePanel.style.display = 'none'; };
|
|
1664
|
+
const wb1 = welcomePanel.querySelector('[data-action="new-sketch"]');
|
|
1665
|
+
if (wb1) wb1.onclick = () => { dismissWelcome(); handleMenuAction('sketch-new'); };
|
|
1666
|
+
const wb2 = welcomePanel.querySelector('[data-action="import"]');
|
|
1667
|
+
if (wb2) wb2.onclick = () => { dismissWelcome(); handleMenuAction('file-import'); };
|
|
1668
|
+
const wb3 = welcomePanel.querySelector('[data-action="ai-generate"]');
|
|
1669
|
+
if (wb3) wb3.onclick = () => { dismissWelcome(); handleMenuAction('tools-text-to-cad'); };
|
|
1670
|
+
const wb4 = welcomePanel.querySelector('[data-action="load-inventor"]');
|
|
1671
|
+
if (wb4) wb4.onclick = () => { dismissWelcome(); handleMenuAction('file-import'); };
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1516
1674
|
// ===== Menu Actions Handler =====
|
|
1517
1675
|
function handleMenuAction(action) {
|
|
1518
1676
|
switch (action) {
|
|
@@ -1562,99 +1720,87 @@
|
|
|
1562
1720
|
break;
|
|
1563
1721
|
case 'tools-text-to-cad':
|
|
1564
1722
|
if (window.CycleCAD && window.CycleCAD.TextToCAD) {
|
|
1565
|
-
const ttcPanel = window.CycleCAD.TextToCAD.getUI();
|
|
1566
1723
|
showDialog('Text-to-CAD (AI)', '');
|
|
1567
|
-
const
|
|
1568
|
-
if (
|
|
1569
|
-
}
|
|
1724
|
+
const db1 = document.getElementById('dialog-body');
|
|
1725
|
+
if (db1) { db1.innerHTML = ''; db1.appendChild(window.CycleCAD.TextToCAD.getUI()); db1.style.maxHeight = '500px'; db1.style.overflow = 'auto'; }
|
|
1726
|
+
} else { showToast('TextToCAD module not loaded', 'error'); }
|
|
1570
1727
|
break;
|
|
1571
1728
|
case 'tools-photo-to-cad':
|
|
1572
1729
|
if (window.CycleCAD && window.CycleCAD.PhotoToCAD) {
|
|
1573
|
-
const ptcPanel = window.CycleCAD.PhotoToCAD.getUI();
|
|
1574
1730
|
showDialog('Photo-to-CAD', '');
|
|
1575
|
-
const
|
|
1576
|
-
if (
|
|
1577
|
-
}
|
|
1731
|
+
const db2 = document.getElementById('dialog-body');
|
|
1732
|
+
if (db2) { db2.innerHTML = ''; db2.appendChild(window.CycleCAD.PhotoToCAD.getUI()); db2.style.maxHeight = '500px'; db2.style.overflow = 'auto'; }
|
|
1733
|
+
} else { showToast('PhotoToCAD module not loaded', 'error'); }
|
|
1578
1734
|
break;
|
|
1579
1735
|
case 'tools-dfm':
|
|
1580
1736
|
if (window.CycleCAD && window.CycleCAD.Manufacturability) {
|
|
1581
|
-
const dfmPanel = window.CycleCAD.Manufacturability.getUI();
|
|
1582
1737
|
showDialog('Manufacturability Check', '');
|
|
1583
|
-
const
|
|
1584
|
-
if (
|
|
1585
|
-
}
|
|
1738
|
+
const db3 = document.getElementById('dialog-body');
|
|
1739
|
+
if (db3) { db3.innerHTML = ''; db3.appendChild(window.CycleCAD.Manufacturability.getUI()); db3.style.maxHeight = '500px'; db3.style.overflow = 'auto'; }
|
|
1740
|
+
} else { showToast('Manufacturability module not loaded', 'error'); }
|
|
1586
1741
|
break;
|
|
1587
1742
|
case 'tools-generative':
|
|
1588
1743
|
if (window.CycleCAD && window.CycleCAD.GenerativeDesign) {
|
|
1589
|
-
const genPanel = window.CycleCAD.GenerativeDesign.getUI();
|
|
1590
1744
|
showDialog('Generative Design', '');
|
|
1591
|
-
const
|
|
1592
|
-
if (
|
|
1593
|
-
}
|
|
1745
|
+
const db4 = document.getElementById('dialog-body');
|
|
1746
|
+
if (db4) { db4.innerHTML = ''; db4.appendChild(window.CycleCAD.GenerativeDesign.getUI()); db4.style.maxHeight = '500px'; db4.style.overflow = 'auto'; }
|
|
1747
|
+
} else { showToast('GenerativeDesign module not loaded', 'error'); }
|
|
1594
1748
|
break;
|
|
1595
1749
|
case 'tools-physics':
|
|
1596
1750
|
if (window.CycleCAD && window.CycleCAD.MultiPhysics) {
|
|
1597
|
-
const physPanel = window.CycleCAD.MultiPhysics.getUI();
|
|
1598
1751
|
showDialog('Multi-Physics Simulation', '');
|
|
1599
|
-
const
|
|
1600
|
-
if (
|
|
1601
|
-
}
|
|
1752
|
+
const db5 = document.getElementById('dialog-body');
|
|
1753
|
+
if (db5) { db5.innerHTML = ''; db5.appendChild(window.CycleCAD.MultiPhysics.getUI()); db5.style.maxHeight = '500px'; db5.style.overflow = 'auto'; }
|
|
1754
|
+
} else { showToast('MultiPhysics module not loaded', 'error'); }
|
|
1602
1755
|
break;
|
|
1603
1756
|
case 'tools-parts':
|
|
1604
1757
|
if (window.CycleCAD && window.CycleCAD.SmartParts) {
|
|
1605
|
-
const partsPanel = window.CycleCAD.SmartParts.getUI();
|
|
1606
1758
|
showDialog('Smart Parts Library', '');
|
|
1607
|
-
const
|
|
1608
|
-
if (
|
|
1609
|
-
}
|
|
1759
|
+
const db6 = document.getElementById('dialog-body');
|
|
1760
|
+
if (db6) { db6.innerHTML = ''; db6.appendChild(window.CycleCAD.SmartParts.getUI()); db6.style.maxHeight = '500px'; db6.style.overflow = 'auto'; }
|
|
1761
|
+
} else { showToast('SmartParts module not loaded', 'error'); }
|
|
1610
1762
|
break;
|
|
1611
1763
|
case 'tools-smart-assembly':
|
|
1612
1764
|
if (window.CycleCAD && window.CycleCAD.SmartAssembly) {
|
|
1613
|
-
const saPanel = window.CycleCAD.SmartAssembly.getUI();
|
|
1614
1765
|
showDialog('Smart Assembly Mating', '');
|
|
1615
|
-
const
|
|
1616
|
-
if (
|
|
1617
|
-
}
|
|
1766
|
+
const db7 = document.getElementById('dialog-body');
|
|
1767
|
+
if (db7) { db7.innerHTML = ''; db7.appendChild(window.CycleCAD.SmartAssembly.getUI()); db7.style.maxHeight = '500px'; db7.style.overflow = 'auto'; }
|
|
1768
|
+
} else { showToast('SmartAssembly module not loaded', 'error'); }
|
|
1618
1769
|
break;
|
|
1619
1770
|
case 'tools-digital-twin':
|
|
1620
1771
|
if (window.CycleCAD && window.CycleCAD.DigitalTwin) {
|
|
1621
|
-
const dtPanel = window.CycleCAD.DigitalTwin.getUI();
|
|
1622
1772
|
showDialog('Digital Twin — Live Data', '');
|
|
1623
|
-
const
|
|
1624
|
-
if (
|
|
1625
|
-
}
|
|
1773
|
+
const db8 = document.getElementById('dialog-body');
|
|
1774
|
+
if (db8) { db8.innerHTML = ''; db8.appendChild(window.CycleCAD.DigitalTwin.getUI()); db8.style.maxHeight = '500px'; db8.style.overflow = 'auto'; }
|
|
1775
|
+
} else { showToast('DigitalTwin module not loaded', 'error'); }
|
|
1626
1776
|
break;
|
|
1627
1777
|
case 'tools-machine':
|
|
1628
1778
|
if (window.CycleCAD && window.CycleCAD.MachineControl) {
|
|
1629
|
-
const mcPanel = window.CycleCAD.MachineControl.getUI();
|
|
1630
1779
|
showDialog('Machine Control — CNC / 3D Printer', '');
|
|
1631
|
-
const
|
|
1632
|
-
if (
|
|
1633
|
-
}
|
|
1780
|
+
const db9 = document.getElementById('dialog-body');
|
|
1781
|
+
if (db9) { db9.innerHTML = ''; db9.appendChild(window.CycleCAD.MachineControl.getUI()); db9.style.maxHeight = '500px'; db9.style.overflow = 'auto'; }
|
|
1782
|
+
} else { showToast('MachineControl module not loaded', 'error'); }
|
|
1634
1783
|
break;
|
|
1635
1784
|
case 'tools-notebook':
|
|
1636
1785
|
if (window.CycleCAD && window.CycleCAD.EngineeringNotebook) {
|
|
1637
|
-
const nbPanel = window.CycleCAD.EngineeringNotebook.getUI();
|
|
1638
1786
|
showDialog('Engineering Notebook', '');
|
|
1639
|
-
const
|
|
1640
|
-
if (
|
|
1641
|
-
}
|
|
1787
|
+
const db10 = document.getElementById('dialog-body');
|
|
1788
|
+
if (db10) { db10.innerHTML = ''; db10.appendChild(window.CycleCAD.EngineeringNotebook.getUI()); db10.style.maxHeight = '500px'; db10.style.overflow = 'auto'; }
|
|
1789
|
+
} else { showToast('EngineeringNotebook module not loaded', 'error'); }
|
|
1642
1790
|
break;
|
|
1643
1791
|
case 'tools-auto-assembly':
|
|
1644
1792
|
if (window.CycleCAD && window.CycleCAD.AutoAssembly) {
|
|
1645
|
-
const aaPanel = window.CycleCAD.AutoAssembly.getUI();
|
|
1646
1793
|
showDialog('Auto-Assemble Parts', '');
|
|
1647
|
-
const
|
|
1648
|
-
if (
|
|
1649
|
-
}
|
|
1794
|
+
const db11 = document.getElementById('dialog-body');
|
|
1795
|
+
if (db11) { db11.innerHTML = ''; db11.appendChild(window.CycleCAD.AutoAssembly.getUI()); db11.style.maxHeight = '500px'; db11.style.overflow = 'auto'; }
|
|
1796
|
+
} else { showToast('AutoAssembly module not loaded', 'error'); }
|
|
1650
1797
|
break;
|
|
1651
1798
|
case 'tools-parametric':
|
|
1652
1799
|
if (window.CycleCAD && window.CycleCAD.ParametricFromExample) {
|
|
1653
|
-
const pfPanel = window.CycleCAD.ParametricFromExample.getUI();
|
|
1654
1800
|
showDialog('Parametric from Example', '');
|
|
1655
|
-
const
|
|
1656
|
-
if (
|
|
1657
|
-
}
|
|
1801
|
+
const db12 = document.getElementById('dialog-body');
|
|
1802
|
+
if (db12) { db12.innerHTML = ''; db12.appendChild(window.CycleCAD.ParametricFromExample.getUI()); db12.style.maxHeight = '500px'; db12.style.overflow = 'auto'; }
|
|
1803
|
+
} else { showToast('ParametricFromExample module not loaded', 'error'); }
|
|
1658
1804
|
break;
|
|
1659
1805
|
default:
|
|
1660
1806
|
showToast(`${action}`, 'success');
|
|
@@ -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
|
|
@@ -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