diff --git a/modules/printvault/api.php b/modules/printvault/api.php index ca23798..e347cff 100644 --- a/modules/printvault/api.php +++ b/modules/printvault/api.php @@ -238,6 +238,51 @@ if ($action === 'models') { } } +// ── GCODE PATHS ──────────────────────────────────────────────────────────────── +if ($action === 'gcode_paths') { + $id = (int)($_GET['id'] ?? 0); + $max = min((int)($_GET['max'] ?? 30000), 80000); + $s = $pdo->prepare("SELECT filename, file_type FROM pf_pv_models WHERE id=?"); $s->execute([$id]); + $row = $s->fetch(); if (!$row) pvErr('Introuvable', 404); + $ext = strtolower($row['file_type']); + if (!in_array($ext, ['gcode','gco','g'])) pvErr('Pas un fichier GCode'); + $path = PV_MODEL_DIR . $row['filename']; + if (!file_exists($path)) pvErr('Fichier introuvable', 404); + + $segments = []; + $x=0.0; $y=0.0; $z=0.0; $e=0.0; $lastE=0.0; + $minZ=PHP_FLOAT_MAX; $maxZ=0.0; + + $handle = fopen($path, 'r'); + while (!feof($handle) && count($segments) < $max) { + $line = trim(fgets($handle)); + if (($p = strpos($line, ';')) !== false) $line = substr($line, 0, $p); + $line = trim($line); + if (!$line) continue; + $cmd = strtoupper(strtok($line, ' ')); + if ($cmd === 'G92') { + if (preg_match('/E([-\d.]+)/i', $line, $m)) $lastE = (float)$m[1]; + continue; + } + if ($cmd !== 'G0' && $cmd !== 'G1') continue; + $nx=$x; $ny=$y; $nz=$z; $ne=$e; + if (preg_match('/X([-\d.]+)/i', $line, $m)) $nx = (float)$m[1]; + if (preg_match('/Y([-\d.]+)/i', $line, $m)) $ny = (float)$m[1]; + if (preg_match('/Z([-\d.]+)/i', $line, $m)) $nz = (float)$m[1]; + if (preg_match('/E([-\d.]+)/i', $line, $m)) $ne = (float)$m[1]; + $extruding = ($cmd === 'G1' && $ne > $lastE) ? 1 : 0; + if ($nx !== $x || $ny !== $y || $nz !== $z) { + $segments[] = [$x, $y, $z, $nx, $ny, $nz, $extruding]; + $minZ = min($minZ, $nz); + $maxZ = max($maxZ, $nz); + } + $x=$nx; $y=$ny; $z=$nz; + if ($ne !== $e) { $lastE = $e = $ne; } + } + fclose($handle); + pvOk(['segments' => $segments, 'min_z' => $minZ === PHP_FLOAT_MAX ? 0 : $minZ, 'max_z' => $maxZ, 'total' => count($segments)]); +} + // ── FILE SERVE ───────────────────────────────────────────────────────────────── if ($action === 'file') { $id = (int)($_GET['id'] ?? 0); diff --git a/modules/printvault/assets/viewer.css b/modules/printvault/assets/viewer.css index abebc8e..4cc73d2 100644 --- a/modules/printvault/assets/viewer.css +++ b/modules/printvault/assets/viewer.css @@ -146,6 +146,20 @@ font-size: .72rem; color: var(--text-muted); line-height: 1.3; } +/* GCode legend */ +.pv-gcode-viewer-legend { + position: absolute; bottom: 2.5rem; left: 1rem; + background: rgba(15,23,42,.8); backdrop-filter: blur(4px); + border: 1px solid rgba(255,255,255,.1); + border-radius: 8px; padding: .5rem .75rem; + display: flex; flex-direction: column; gap: .3rem; + pointer-events: none; +} +.pv-legend-item { + font-size: .72rem; color: #94a3b8; + display: flex; align-items: center; gap: .5rem; +} + /* Responsive */ @media (max-width: 900px) { .pv-detail-body { grid-template-columns: 1fr; grid-template-rows: 55vh 1fr; } diff --git a/printvault-viewer.php b/printvault-viewer.php index 4cc95dc..fd45602 100644 --- a/printvault-viewer.php +++ b/printvault-viewer.php @@ -14,7 +14,7 @@ $s2 = $pdo->query("SELECT name, color FROM pf_pv_categories ORDER BY name"); $categories = $s2->fetchAll(); $ext = strtolower($model['file_type']); -$canView = in_array($ext, ['stl','3mf']); +$canView = in_array($ext, ['stl','3mf','gcode','gco','g']); $isGcode = in_array($ext, ['gcode','gco','g']); $thumbUrl = $model['thumb'] ? '/uploads/printvault/thumbs/' . rawurlencode($model['thumb']) : null; $typeIcon = ['stl'=>'🟣','3mf'=>'🔵','gcode'=>'🟢','gco'=>'🟢','g'=>'🟢'][$ext] ?? '📄'; @@ -65,7 +65,17 @@ require __DIR__ . '/header.php';