Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
50 most recent check-ins
|
2026-08-07
| ||
| 12:15 | projection(): cut=true via Section at z=0; cut=false warns not implemented and returns empty leaf check-in: 9de95418d4 user: johnfound tags: master, trunk | |
|
2026-08-06
| ||
| 14:08 | export() should be transparent for the geometry - use SCLGroup instead of SCLPart3. check-in: 35f560a673 user: johnfound tags: master, trunk | |
| 13:55 | Export progress bar in GUI; unified error messages without empty-file fallback check-in: 766a340a5e user: johnfound tags: master, trunk | |
|
2026-08-05
| ||
| 21:23 | Per-face color STEP test: bcad-generated fixture, import and roundtrip face-count stability check-in: 87463f1e6d user: johnfound tags: master, trunk | |
| 21:23 | Resolve include/use/import/surface paths relative to the calling file, not cwd check-in: aa72586c7f user: johnfound tags: master, trunk | |
| 20:44 | Editor: remove Ctrl+E debug flash indicator check-in: 810eb4d0b3 user: johnfound tags: master, trunk | |
| 20:44 | Settings: configurable recent files limit (default 20) in Preferences|General check-in: 956e36bbde user: johnfound tags: master, trunk | |
| 20:31 | Editor: Ctrl+Tab/Ctrl+Shift+Tab cycles through editor tabs; disable native window switcher check-in: d205ee0bde user: johnfound tags: master, trunk | |
| 18:43 | Editor: Ctrl+E opens the include/use file under the caret check-in: e7817610e1 user: johnfound tags: master, trunk | |
| 14:11 |
Fix moiré/z-fighting on STEP import of SolidWorks-style per-face colored files
read_step emitted a compound AND every sub-shape of a compound label, so faces stored as FACE sub-shapes (OVER_RIDING_STYLED_ITEM) rendered twice coincident with the same faces inside the solids, causing z-fighting/moiré (SFM4100.step imported as 666-4474 parts instead of 5). Compound branch now emits each SOLID/SHELL sub-shape once with per-face colors resolved via TopTools_IndexedMapOfShape (O(n) IsSame matching), absorbs matching FACE sub-shapes into their parent solid, and only emits the compound itself when it has no solid/shell children (loose faces). Orphan colored faces keep their own display entry. Non-compound simple shapes are emitted once as before, then per-face sub-shape colors override. TransferColored gains a default_color parameter (fallback for uncolored faces) threaded from _write_face_colors via get_default_color(). Add tests/test_step_perface.scad regression test: SFM4100.step imports as 5 parts/3689 faces, Straight.STEP as 13 parts/4483 faces, roundtrip keeps the face count (no duplication). check-in: 1dc6ecc20d user: johnfound tags: master, trunk | |
| 08:25 |
Fix children() leaking the enclosing module's block
children() now resolves its owner lexically: the innermost module frame, or the _lexical_owner carried by an active children-exec frame. Previously it did a dynamic reverse search for $children_block, which crossed module boundaries and made a module called without children render the block of an ancestor module (test_chain.scad produced 7 cylinders instead of 3). Every module frame now always sets $children_block (None when called without a block) and $children (0 without a block), so no-block modules shadow outer blocks and children() renders nothing instead of leaking. Exec frames keep parent=call_scope for lexical variable visibility. Remove the delete/restore hack around $children_block and the misleading 'No children to render' warning. Add tests/test_chain_children.scad regression test (3 cylinders -> 9 faces). check-in: 9073d86682 user: johnfound tags: master, trunk | |
|
2026-08-04
| ||
| 20:41 |
Clean up noisy STEP export logging and remove dead debug code
Remove all Russian INFO progress messages from the STEP writer (writer setup, transfer, file write steps) and keep a single informative 'STEP export written: file path' line. Warnings and errors are now in English and errors are reported once by the caller instead of being double-logged with a full traceback inside the writer. Suppress OCCT's 'Statistics on Transfer' block via the documented Message_Messenger API (SetTraceLevel(Message_Alarm)) instead of the previous console noise, since bcad surfaces OCCT failures programmatically. This silences the output process-wide. Delete dead Russian debug utilities from scl_context.py (_shape_type_str, debug_shape_structure, print_algo_diagnostics) and the Message_Warning/Message_Alarm imports they were the only users of. check-in: e325863644 user: johnfound tags: master, trunk | |
| 20:19 |
Fix STEP import losing whole-shape base color when per-face colors exist
import_file discarded the shape's base color whenever per-face colors were present, so non-overridden faces fell back to the default PERU. The STEP colors are encoded as base STYLED_ITEM (whole shape, readable via GetColor on the shape label) plus OVER_RIDING_STYLED_ITEM per face. Now the base color is always applied to all faces first and per-face overrides are merged on top. Files without a base color keep the same default behavior since the base falls back to PERU. Fixes scl_examples/spheres_freecad.step showing the red sphere as default color instead of red. Verified round-trip re-import keeps both colors. check-in: f90f47da14 user: johnfound tags: master, trunk | |
| 20:02 |
Preserve per-face colors in STEP round-trip; compact STYLED_ITEM emission
Bake assembly location into geometry during STEP import (BRepBuilderAPI_Transform copy=True), so exported shapes have an identity top Location. A located shape made XCAFDoc_ShapeTool::AddShape create a reference label, silently dropping per-face SetColor calls. TransferColored now sets the most frequent color as the base shape style and emits OVER_RIDING_STYLED_ITEMs only for the remaining faces, shrinking the color section from ~31.5k to ~4.7k entities. sfm4100 round-trip drops from 7.91 MB to 6.92 MB with all colors preserved. check-in: 9fda7bf056 user: johnfound tags: master, trunk | |
| 11:57 | Less contrast for the intent marker lines. check-in: 792299accc user: johnfound tags: master, trunk | |
| 10:02 |
Editor calltip: trigger parameter hint only on '(' and ',' instead of any input
The calltip (function/module parameter hint) was re-triggered on every keystroke inside the argument list, which made it intrusive. Now it is shown only when a call's argument list opens with a left paren, when an argument separator comma is typed, via Ctrl+Q as a manual fallback, or right after autocomplete inserts a function/module with the cursor placed between the parens. Language separation: the cheap trigger gate is now a language property (Language::isCallTrigger set to paren and comma in OpenscadLanguage), while the precise analysis lives in the generic editor: - findEnclosingCallParen scans backwards respecting parens, square and curly brackets, and only accepts a paren that is preceded by a module/function name, so a comma inside a vector/block literal or a grouping paren does not fire. - tryActivateCalltip ignores parens inside strings/comments. - CalltipState gains argumentIndex (index of the argument being edited), exposed to Python as argument_index. - findEnclosingOpenParen keeps the per-frame dismissal behavior. Regenerated TextEditor.cpp/.h and pybind patches. check-in: 68a7f75ba7 user: johnfound tags: master, trunk | |
| 08:44 |
Restrict module/function parameter definitions to ID or ID = expr
Parameter lists of module and function definitions used the generic varargslist grammar, so an expression like s-10 (missing '=') parsed as expr_binop. get_args_list then dereferenced a['id']/a['val'] on it and raised UnhandledCaseError, which killed the OCCT worker process. Add a strict paramdefs/paramdef_list/paramdef grammar (ID | ID = expr), matching OpenSCAD, and use it in module_definition and function_definition. Call sites still use the permissive parameters rule. Invalid definitions now produce a syntax error at the correct line instead of crashing. Fixes scl_examples/crash_arg.scad. Adds tests/test_module_param_defs.scad regression test. check-in: 1ce3d1c039 user: johnfound tags: master, trunk | |
| 07:22 |
Remove warnings from 2D primitives; skip degenerate edges silently
Line3/Arc3/Spline3.to_edge and SCLProfile2 no longer emit warnings (they crashed with AttributeError since edge classes lacked warn()). Degenerate elements (zero-length segments, duplicate consecutive polygon points) are now silently skipped and simply not drawn, matching OpenSCAD behavior. add_profile_shape leaves the shape unset on failure instead of warning. Fixes scl_examples/big_polygon.scad (duplicate point [16,31]). Adds tests/test_polygon_duplicate_points.scad regression test. check-in: ba050db5a4 user: johnfound tags: master, trunk | |
| 05:23 | Allow trailing commas in vector literals check-in: 7a41ea0fde user: johnfound tags: master, trunk | |
|
2026-08-03
| ||
| 14:48 | Compile all C++ sources with -Os for Linux and Windows. check-in: ae330c92ca user: johnfound tags: master, trunk | |
|
2026-08-02
| ||
| 22:39 |
Boolean ops: empty results are first-class shapes, not failures
Empty results of boolean operations (difference/intersection/union) are now legitimate: a completed op (IsDone) returns its shape even when it is an empty compound, silently. A None result means a real OCCT failure and always comes with a warning ('boolean operation failed — result omitted'). - get_children() returns direct children only — shapeless/failed nodes no longer leak their grandchildren into parent operations - New SCLRoot(SCLPart3) container: no own shape, display() renders children; SCLPart3.display() renders only its own shape (no children fallback) - _cut_parts returns None (failure) vs empty list (legitimately all removed); _fuse_parts returns empty compound for no parts; universal_optimized_common_colored returns (None, None) only on failure - _unify_shape early-returns empty input (no spurious UnifySameDomain warning) - SCLShape.display/display_with_modifier skip empty compounds early - Regression test: tests/test_bool_empty.scad (6 cases) - Fixes 3 spurious 'boolean cut failed — showing individual children' warnings in Cluster_loft3.scad check-in: 23a1ec95ae user: johnfound tags: master, trunk | |
| 17:07 |
Set OCCT release flags to -Os and keep exceptions on
- Override CMAKE_C_FLAGS_RELEASE/CXX_FLAGS_RELEASE to "-Os -DNDEBUG". GCC 16.1.1 miscompiles BRepClass3d_SClassifier at -O3: the shared UBTree Select devirtualizes Reject/Accept to the Line selector, so the point Select calls Line::Accept on a point selector and reads uninitialized myLC -> intermittent SIGSEGV (e.g. is_valid() on sfm4100.step). -Os avoids the crash. - Set BUILD_RELEASE_DISABLE_EXCEPTIONS=OFF explicitly (OCCT default is ON) so exceptions remain enabled for pythonocc. - Drop BUILD_MODULE_DETools=ON (absent from the Windows script, not required for the build). check-in: 7db63b36ff user: johnfound tags: master, trunk | |
|
2026-08-01
| ||
| 21:24 |
Persist main and auxiliary window state across sessions
Add a generic AuxWindow base class (bcad/binterpreter/aux_window.py) for auxiliary windows whose open state is persisted. Subclasses declare a settings key, title and default size; imgui is imported lazily in render() so modules shared with the OCCT worker process stay GUI-free. AuxWindow provides is_open/show/close/toggle/restore plus an activate() that sets a per-window focus flag consumed via set_window_focus() right after begin() (the same safe pattern the editor uses for tab activation). Refactor ColorPickerDialog and the measurement results window to subclass AuxWindow: - Color Picker (key 'color_picker', 350x500) keeps its dialog body in draw_content(). - Measurement (key 'measurement', 400x300) moves into measure_tools.py together with _parse_markers(), keeping the one-way coupling: enabling measure mode opens (and activates) the window, disabling it does not close it, opening it does not enable the mode. Transition detection via _mode_was_on covers both the Tools menu and the toolbar Meas button. Persist state in a new settings [windows] section (main_maximized, color_picker, measurement), saved at exit in _save_window_state() and restored at startup in _restore_window_state(). Main window maximization is saved/restored via glfw; non-maximized position/size are left to the OS. Render aux windows before the Output/Console log views so that on the first frame the newly appearing log windows steal focus last, keeping Console/Output as the active dock tabs after restoring open windows. Remove the now-dead _measure_lines/_show_measure/_fmt_display code from main_window.py. check-in: a745a4a683 user: johnfound tags: master, trunk | |
| 17:53 |
Honor $fn/$fa/$fs/$fe in STL export, add export() module
STL mesh resolution now follows OpenSCAD semantics (approximated by OCCT): make_writer reads all four special vars: $fn > 0 -> ang = 2PI/max(fn,3), else ang = radians($fa); lin = min($fs, $fe). SCLSTLWriter.Write replaces pythonocc write_stl_file (theForce=false kept the preview tessellation) with breptools.Clean + forced BRepMesh_IncrementalMesh + StlAPI_Writer, so GUI exports are no longer pinned to preview density. hull() uses the same min($fs, $fe) rule. New bcad-specific export() module: export('file') { children } writes a subtree to step/stl/dxf during evaluation (transparent SCLPart3 container, % background children skipped, relative paths against the script dir). Registered in _builtin_modules (FUNC_EXPORT=37). Uses _module_scope so the block is compiled before writing. The file name is never modified by make_writer: with an explicit fmt the format is determined by the parameter (/dev/null, extension-less and custom names all work); without fmt it is detected from the extension. Removed the now-dead extensions attributes from the writer classes. Test tests/test_stl_resolution.scad covers all four variables via export/import/capture/num_faces (each mesh density in its own if(true) block due to 3-phase evaluation). Docs updated (docs/export_module.md, docs/scl.md, AGENTS.md). check-in: 10a6d9bd57 user: johnfound tags: master, trunk | |
| 13:31 |
editor: fix crash when deleting large multi-line selections
The auto-strip-trailing-whitespace patch accessed document[previousCursorLine] with a stale frame-to-frame line index. Deleting a large selection shrinks the document below that index in the same frame, causing an out-of-bounds std::vector access and a segfault (small 1-3 line selections stayed in bounds, which is why they never crashed). - guard the strip block with previousCursorLine less than document.size() - keep previousCursorLine in sync with edits in TextEditor::deleteText/insertText using the same line-shift arithmetic as cursors, so it keeps pointing at the same logical line instead of a shifted one - reset previousCursorLine = -1 in setText() for a new document - AGENTS.md: drop stale cpp/imgui/ references, point to cpp/imgui-patches/, and document the strip mechanism and the crash guard check-in: 4cec3745b1 user: johnfound tags: master, trunk | |
| 12:33 |
linear_extrude: make caps disjoint to fix twist=360 self-overlap
When the profile extends along the sweep axis further than height, the bottom and top caps overlap coplanarly (the pipe closes on itself like a torus), producing a self-intersecting shell. As a boolean tool this hard- crashed Cut.Build() with fuzzy tolerance (thread twist=360 segfaulted). _disjoint_caps() mutually cuts the caps (BRepAlgoAPI_Cut) in all branches (twist/scale/plain) before sewing; when caps don't overlap the Cut is a no-op. Adds tall-profile regression tests: tool validity and difference() against the twist=360 tool. check-in: 75d4435721 user: johnfound tags: master, trunk | |
| 08:41 |
Boolean fuzzy tolerance: absolute floor prevents crash on small models
_bool_fuzzy() now takes a floor (default 2e-5) and returns max(bbox_diag * 2e-6, floor, Precision::Confusion()). On small models (diag below 10) the scale-relative tolerance drops below the OCCT noise floor (~1.5e-5), so near-tangent sliver faces turn into degenerate faces and can hard-crash the process. Reproduced at size=0.14 in scl_examples/bad_twist.scad: difference() of a tangent twisted sweep segfaulted; with the floor it yields a clean 10-face/15-edge solid. resolve_high_valence_vertices passes floor=Precision::Confusion() for the micro-disk cut: on small models the 2e-5 floor is comparable to the disk radius and would swallow the cut (offset silently becomes a no-op). check-in: a4ad319497 user: johnfound tags: master, trunk | |
| 07:57 |
Boolean ops: scale-relative fuzzy tolerance; offset micro-depth relative to shape scale
- _bool_op now always sets fuzzy: explicit value or scale-relative default _bool_fuzzy(args) = max(bbox_diag * 2e-6, Precision::Confusion()). Near-coincident geometry (tangent surfaces, sliver faces) collapses consistently at any model scale; fixes floating edges from difference()/ intersection() of a tangent twisted sweep (scl_examples/bad_twist.scad). - resolve_high_valence_vertices computes fuzzy from the micro-disks being cut, not from the whole shape: the shape-scale default can exceed the disk radius on large models and swallow the cut (offset silently became a no-op). - _offset_3d micro-depth is now scale-relative (_micro_depth): max(1e-5, |offset|/20, 1e-4*bbox_diag). The old absolute floor 0.001 made micro-disks comparable to small figures (size=0.01 -> disk 8% of diagonal) and killed the process below size=0.0001. - Add tests/test_bad_twist.scad regression for the sliver-free boolean. check-in: 27ea86e39e user: johnfound tags: master, trunk | |
|
2026-07-31
| ||
| 22:07 | Fix linear_extrude twist=360 producing invalid solid; add is_valid() builtin and docs check-in: dca7601e65 user: johnfound tags: master, trunk | |
| 05:43 | Add docs for planned visualization extensions (clipping planes, textures) and export() module check-in: 5b3a2a6818 user: johnfound tags: master, trunk | |
|
2026-07-30
| ||
| 14:06 | Add gen_patch.bat and gen_patch.py for Windows patch regeneration (imgui + occt) check-in: bc476e0ebb user: johnfound tags: master, trunk | |
| 13:33 | Restructure OCCT and ImGui patches into per-file split patches with timestamp sync in setup scripts check-in: 952ed2d6da user: johnfound tags: master, trunk | |
| 04:58 | Restore BRepOffsetAPI_ThruSections import removed by accident in _unify_shape refactor check-in: bd9bb50624 user: johnfound tags: master, trunk | |
|
2026-07-29
| ||
| 21:05 |
Measurement tool: richer face/edge info, horizontal scrollbar, compact layout
face_info: surface type name, edges count, perimeter, type-specific data (normal for Plane, axis for Cylinder/Cone, degrees for BSpline/Bezier) edge_info: curve type name, start/end points, direction for Line, radius/axis/arc angle for Circle, degrees for BSpline/Bezier Measurement window: wrap content in child with horizontal scrollbar, same_line(spacing=0) for compact copy-button layout check-in: a6052b014b user: johnfound tags: master, trunk | |
| 19:24 |
_fuse_parts: unwrap single-element Compound from fuse result
BRepAlgoAPI_Fuse may wrap a single solid in a Compound container. Unwrap it in _fuse_parts so the caller always gets the proper shape type (SOLID, SHELL, etc.) without double-wrapping. check-in: 4414c8c7f1 user: johnfound tags: master, trunk | |
| 18:16 |
linear_extrude: replace BSpline-interpolated helix with exact circular helix
make_helix_wire now builds a mathematically exact spiral via pcurve on Geom_CylindricalSurface (Geom2d_Line at angle twist_rad, trimmed to hypot(twist_rad, height)) instead of GeomAPI_Interpolate over N points. SetMode(guide_wire, True) (Frenet) is required because discrete mode cannot handle pcurve-based guide wires. Removed unused imports: GeomAPI_Interpolate, BRepOffsetAPI_ThruSections. check-in: d2e9d4050d user: johnfound tags: master, trunk | |
| 14:41 |
Regenerate imgui_color_text_edit.patch — clean patch without upstream delta
Previous patch (3156 lines) included the submodule delta ccd9a72..b18caeb merged into our customizations, because it was generated before the parent repo was updated to origin/main (09751a94) which already references submodule b18caeb. New patch (926 lines) is generated from clean upstream b18caeb and contains only bcad-specific customizations: - Auto-strip trailing whitespace (with undo-safe pruning) - Gutter background rendering - Bracket matching corner markers (replaced highlight fill) - Autocomplete: suggestionTypes labels, viewport clamping, scroll-into-view - Calltip popup for function/module parameter hints - Auto-indent fix for insertSpacesOnTabs mode - scrollToLine no longer clears ensureVisiblePos - OpenSCAD language definition + Python bindings - Python bindings for AutoCompleteState, AutoCompleteConfig, CalltipState check-in: 9a67153e72 user: johnfound tags: master, trunk | |
| 13:57 | Rebase imgui_color_text_edit.patch on upstream b18caeb check-in: f48440bb97 user: johnfound tags: master, trunk | |
| 13:41 | ImGuiColorTextEdit: fix auto-indent cursor position with insertSpacesOnTabs, fix gutter background to fill full window check-in: 4751588da5 user: johnfound tags: master, trunk | |
| 12:12 | Measurement window: marker-based click-to-copy, raw precision, native OCCT selection check-in: 8f5fb5bca1 user: johnfound tags: master, trunk | |
| 11:39 | Measurement tool: native OCCT selection, per-object/pair/angle report, Measurement window check-in: b46989dc52 user: johnfound tags: master, trunk | |
| 09:07 | Extract measurement logic into separate measure_tools module check-in: fe95b396c4 user: johnfound tags: master, trunk | |
| 09:00 | Add mode-measure icon (SVG source + PNG) check-in: 3aacdc7a72 user: johnfound tags: master, trunk | |
| 08:58 | Add measure mode: vertex/edge/face selection with distance, angle, and surface info check-in: e6e1218d0d user: johnfound tags: master, trunk | |
| 05:56 | Extract _unify_shape helper, apply UnifySameDomain to difference/intersection check-in: c98960b0f5 user: johnfound tags: master, trunk | |
|
2026-07-28
| ||
| 19:19 | Merged with the latest fixes from енÐengine_dev branch. check-in: 5293d2e003 user: johnfound tags: master, trunk | |
| 18:04 |
Remove packaging/ directory — obsolete build scripts
All 12 files removed: cross-build-wine.sh, build_appimage.sh, copy_deps.py, occ_analyzer.py, occ_filter.py, toolchain-mingw64.cmake, build_deb.sh, stdeb.cfg.in, run-dbst.sh, compress.sh, bcad.desktop, bcad.png. Replaced by pack2/ + development/ (PyInstaller-based, smaller distributions, no magic/shell wrappers). leaf check-in: a52fe0cb8e user: johnfound tags: engine_dev | |
| 17:47 |
Restore self.trsf for modifier transform chain + render timing
- self.trsf now set in all 6 SCLTransform handlers (Translate, Rotate, Scale, Multmatrix, Resize, Mirror) — was missing after the SCLTransform refactoring (e3442c946a). This broke #/% modifier transforms: the modifier loop walks ctx.parent via getattr(node, 'trsf', None), which returned None for all transform parents, so highlighted/background shapes appeared at literal positions without accumulated parent transforms. - Initialize self.trsf = None in SCLTransform.__init__ as fallback. - Print render time (ms or s) alongside cache stats at end of load_file() for performance visibility. check-in: 79cdb1c20e user: johnfound tags: engine_dev | |
| 16:56 |
Fix transform mutation and compound unpacking for SCLTransform/SCLGroup
- Stop mutating children in SCLTransform._build_from_children — copies are used for the parent compound, children remain immutable. - Unpack grouping containers (SCLTransform with _unpack=True) so their sub-shapes become separate children of the parent transform. This preserves per-object selection through nested transforms. E.g. rotate() { translate() { cube(); sphere(); } } now shows two AIS_ColoredShape objects instead of one compound. - Rename _group() to _group_from_wrappers() — takes pre-built wrappers list instead of reading from self.children. - Add _is_grouping_container() helper. - SCLGroup now extends SCLTransform (identity transform via _build_from_children(lambda s: None)) instead of SCLPart3, gaining compound unpacking and proper display. - Remove redundant __init__ from SCLGroup, SCLHull, SCLUnion, SCLDifference, SCLIntersection, SCLMinkowski, SCLOffset, SCLProjection — parent __init__ suffices in Python. - Disable caching for SCLGroup in _handle_group, _handle_render, children(), user-defined modules, and for loops (Pattern B: key propagation only, no cache get/put). SCLTransform operations are cheap (BRepBuilderAPI_Transform), caching overhead exceeds compute cost. check-in: 00c5bf98d8 user: johnfound tags: engine_dev | |
| 14:47 |
Refactor transforms: extract SCLTransform base class from SCLPart3
Introduce SCLTransform(SCLPart3) as a common base for all 7 transform operations (translate, rotate, scale, multmatrix, resize, mirror, color). Key changes: - SCLTransform._build_from_children(callback) — copies children shapes, applies callback, assembles compound for boolean ops - SCLTransform._group() — handles single/multi-child compound building - SCLTransform.display() — unpacks multi-child compounds into individual AIS_ColoredShape objects; single-child compounds (text, STEP, bool results) display as-is via _unpack flag - Each subclass reduced to public method + callback (2-12 lines) - ~200 lines of duplicated iteration/copy/compound boilerplate removed Also fix indentation in scl_examples/test_text.scad check-in: e3442c946a user: johnfound tags: engine_dev | |