From 5d65b0d8a15bcf3fb7a6a98f8807db7f1e2df3a8 Mon Sep 17 00:00:00 2001 From: wenil Date: Mon, 25 May 2026 13:12:09 +0300 Subject: [PATCH] holder: fix decimal -D overrides being truncated to int MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _filter_params() had a stale short-circuit: v = float(v) if p.step and p.step != int(p.step) else int(float(v)) For auto-extracted params (the new majority of PARAMS), `p.step is None`, which is falsy. The conditional took the `int(float(v))` branch and truncated values like 0.2 -> 0, 0.7 -> 0, 1.5 -> 1. The /holder render silently dropped every clearance, tolerance, and offset to zero, so the holder pieces in "both" mode (and a handful of other configurations) came out merged at their edges. /scad never hit the bug because it doesn't pass -D overrides — the SCAD defaults applied unchanged. Fix: always coerce through float, then narrow back to int only when the result has no fractional part. Verified /holder render with all defaults now produces the exact same STL bytes as /scad with the bundled source (md5 match). --- holder.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/holder.py b/holder.py index 5a79ac3..a093b8f 100644 --- a/holder.py +++ b/holder.py @@ -305,10 +305,11 @@ def _filter_params(params: dict) -> dict: continue p = known[k] if p.kind == "number": - v = float(v) if p.step and p.step != int(p.step) else int(float(v)) - # keep ints for integer-step params - if isinstance(p.default, int) and float(v).is_integer(): - v = int(v) + # Always coerce through float — earlier logic short-circuited to + # int(float(v)) when step was None (most auto-extracted params), + # truncating decimals like box_clearance=0.2 → 0. + fv = float(v) + v = int(fv) if fv.is_integer() else fv elif p.kind == "bool": v = bool(v) elif p.kind == "select":