holder: expose all 59 scad parameters auto-extracted from the .scad source

The bundled hex_cell.scad has many more knobs than the dozen we used to
expose (box clearances, cap/box wall, vertical stacking, busbar template,
etc). Maintaining a hand-curated PARAMS list in Python next to a SCAD file
that already documents every variable inline was always going to drift.

Sync + auto-extract approach:
- scad/hex_cell.scad: replace with the upstream master file from
  Albert Phan's Hex-Cell-Holder fork (adds the BUSBAR TEMPLATE section
  and the "busbar template" part option).
- holder.py: PARAMS now built at import time by _scan_scad(), which
  regexes top-level `name = literal;  // help` lines into Param entries
  up until the // END OF CONFIGURATION marker. Scan handles bool /
  number / string literals; derived expressions and helper variables
  are skipped automatically.
- Manual maps stay small and explicit: _SELECT_OPTIONS for the few
  string-enum params (part, pack_style, box_style, template_outline,
  template_hole_style, etc.), _GROUP_RULES for UI sectioning, and
  _NUMBER_HINTS for sensible min/max/step on the most-tweaked numbers.

UI:
- holder-app.js: extra GROUP_ORDER / GROUP_LABELS for the new
  sections (cap, box, insulator, bolts, wires, stacking, template,
  advanced). Group titles are now click-to-collapse; the advanced
  groups start collapsed so the form isn't a wall of inputs on load.
- holder.css: caret marker on the group title, smooth rotate on
  collapse, hides the body via .collapsed class.

Net effect: every variable in the .scad — including the new busbar
template knobs — is editable from the page, with helpful comments
copied straight from the .scad source.
This commit is contained in:
wenil
2026-05-25 12:44:45 +03:00
parent dfef1453aa
commit 5bba0e3c4a
4 changed files with 337 additions and 55 deletions
+31 -6
View File
@@ -53,13 +53,31 @@ function _whenViewerReady(cb) {
// ----- form generation ------------------------------------------------------
const GROUP_ORDER = ["part", "cell", "size", "holder"];
const GROUP_ORDER = [
"part", "cell", "size", "holder",
"cap", "box", "insulator",
"bolts", "wires",
"stacking", "template", "advanced",
];
const GROUP_LABELS = {
part: "Part / pack",
cell: "Cell",
size: "Pack size",
holder: "Holder",
part: "Part / pack",
cell: "Cell",
size: "Pack size",
holder: "Holder",
cap: "Cap",
box: "Box",
insulator: "Insulator",
bolts: "Bolts & zipties",
wires: "Wires & clamp",
stacking: "Vertical stacking",
template: "Busbar template",
advanced: "Advanced",
};
// Groups that start collapsed (user opens with a click). Basics stay open.
const GROUPS_COLLAPSED = new Set([
"cap", "box", "insulator", "bolts", "wires",
"stacking", "template", "advanced",
]);
function _renderForm(schema, defaults) {
const root = $("param-form");
@@ -77,11 +95,18 @@ function _renderForm(schema, defaults) {
for (const g of groups) {
const wrap = document.createElement("div");
wrap.className = "param-group";
if (GROUPS_COLLAPSED.has(g)) wrap.classList.add("collapsed");
const title = document.createElement("h3");
title.className = "param-group-title";
title.textContent = GROUP_LABELS[g] || g;
title.addEventListener("click", () => wrap.classList.toggle("collapsed"));
wrap.appendChild(title);
const body = document.createElement("div");
body.className = "param-group-body";
wrap.appendChild(body);
for (const p of byGroup.get(g)) {
const row = document.createElement("div");
row.className = "param-row";
@@ -123,7 +148,7 @@ function _renderForm(schema, defaults) {
h.textContent = p.help;
row.appendChild(h);
}
wrap.appendChild(row);
body.appendChild(row);
}
root.appendChild(wrap);
}