openscad-cpp-evaluator 0.33.0__tar.gz → 0.34.0__tar.gz
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.
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/CLAUDE.md +41 -2
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/evaluator.hpp +6 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/CMakeLists.txt +1 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/builtins.hpp +9 -0
- openscad_cpp_evaluator-0.34.0/src/builtins/dxf_dim.cpp +221 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/function_builtins.cpp +7 -2
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/registry.cpp +3 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/topology.cpp +70 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/csg_generate.cpp +107 -1
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/eval_context.cpp +6 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_booleans.cpp +180 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_dxf_svg_import.cpp +131 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_scoping.cpp +12 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/uv.lock +1 -1
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/README.md +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/bytecode_vm.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/user_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/tools/cli/main.cpp +0 -0
|
@@ -512,6 +512,9 @@ grep for `ponytail:`.
|
|
|
512
512
|
`Evaluator::evaluate()` also takes an optional `viewportParams` map (added after a test-suite
|
|
513
513
|
parity review found it missing entirely): seeds arbitrary `$`-prefixed entries into `ctx.dyn`
|
|
514
514
|
(e.g. `$vpt`/`$vpr`/`$vpd`/`$vpf` from a GUI host's current camera, or `$t` for animation time)
|
|
515
|
+
— note `EvalContext::makeRoot` also seeds `$preview` to **`false`**, always: there is no preview
|
|
516
|
+
mode here, and leaving it undef made the common `$preview ? cheap : real` idiom take the cheap
|
|
517
|
+
branch by accident while warning about an unknown variable
|
|
515
518
|
before evaluation starts, via a direct `ctx.dyn` write that deliberately never touches
|
|
516
519
|
`ctx.dynExplicit` — lets a caller tell "the script itself assigned this `$`-var"
|
|
517
520
|
(`dynExplicit`) apart from "merely present because the caller seeded it" after `evaluate()`
|
|
@@ -558,13 +561,49 @@ grep for `ponytail:`.
|
|
|
558
561
|
color instead of preserving each part's own, matching real OpenSCAD's actual behavior once fixed
|
|
559
562
|
(cross-checked triangle-color-count-and-values against the Python reference directly, not just
|
|
560
563
|
“does it run”).
|
|
561
|
-
- `src/builtins/
|
|
564
|
+
- `src/builtins/dxf_dim.cpp` — `dxf_dim()`/`dxf_cross()`, which read a measurement out of a DXF file
|
|
565
|
+
rather than out of the model. Ported from the reference's `io/dxfdim.cc` plus the DIMENSION/LINE
|
|
566
|
+
half of `io/DxfData.cc`: `dxf_dim()` returns the first matching DIMENSION's value by its type
|
|
567
|
+
(`70 & 7` — 0 rotated, 1 aligned, 2 angular, 3/4 diameter/radius, 6 ordinate; type 5 is
|
|
568
|
+
unsupported there too), `dxf_cross()` intersects the first two LINE entities. Note the reference's
|
|
569
|
+
own coordinate quirk, reproduced here: groups 11/12/16 (and 21/22/26) are scaled but NOT
|
|
570
|
+
origin-shifted, being extents rather than positions.
|
|
571
|
+
|
|
572
|
+
Deliberately its own group-code walk rather than sharing `src/import/dxf_import.cpp`'s: that one
|
|
573
|
+
produces closed contours, and these need the DIMENSION entities' seven coordinate slots and the
|
|
574
|
+
raw LINE endpoints, neither of which a contour list keeps. One divergence: `dxf_cross()` takes the
|
|
575
|
+
first two LINEs, where the reference walks every 2-point path — for a real cross (two strokes
|
|
576
|
+
meeting in the middle, not at their endpoints) that is the same set.
|
|
577
|
+
|
|
578
|
+
- `src/csg_generate.cpp` — `Evaluator::applyDimensionRules`, run centrally just before every node's
|
|
579
|
+
`GenerateFn` (and once more over the top-level list, which is an implicit union). Mirrors the
|
|
580
|
+
reference's `isValidDim` + `collectChildren2D`/`collectChildren3D`: a node's dimension is fixed by
|
|
581
|
+
its first non-background, non-empty child, and every child of the other dimension is dropped with
|
|
582
|
+
`Mixing 2D and 3D objects is not supported` followed by `Ignoring {N}D child object for {M}D
|
|
583
|
+
operation`. `linear_extrude`/`rotate_extrude`/`offset` are always-2D and `projection` always-3D, so
|
|
584
|
+
they skip the "mixing" line and emit only the second; `roof()` emits neither, matching the
|
|
585
|
+
reference. Background (`%`) children are exempt.
|
|
586
|
+
|
|
587
|
+
Doing this centrally is also what keeps `generateCsg` safe: it builds ONE result and switches on
|
|
588
|
+
whether it holds a `body` or a `section`, so a group that changed dimension part-way dereferenced
|
|
589
|
+
the empty optional -- `union() { cube(1); square(4); }` took the process down with "mutex lock
|
|
590
|
+
failed: Invalid argument". Filtering before dispatch means no `GenerateFn` ever sees a mixed group.
|
|
591
|
+
All 25 module/shape combinations were diffed against OpenSCAD 2026.02.01 warning for warning, with
|
|
592
|
+
the surviving geometry compared by STL volume.
|
|
593
|
+
|
|
594
|
+
- `src/builtins/topology.cpp` — `hull()`/`minkowski()`/`fill()`. All three splice their children transparently in
|
|
562
595
|
the CSG tree exactly like union/difference/intersection (resolve just evaluates them for the
|
|
563
596
|
side effect); `hull()` picks an all-3D (`Manifold::Hull`) or all-2D (`CrossSection::Hull`) hull of
|
|
564
597
|
the *foreground* (role-split) children, falling back to sections only when no child has a body;
|
|
565
598
|
`minkowski()` only ever operates on 3D bodies (a 2D sibling among the foreground children is
|
|
566
599
|
silently ignored, matching the reference exactly — no 2D `minkowski_sum` fallback the way hull
|
|
567
|
-
has one).
|
|
600
|
+
has one). All pass background/highlight/show_only bodies through untouched. `fill()` is 2D-only
|
|
601
|
+
(a 3D foreground child draws the reference's own `fill() not yet implemented for 3D` warning and
|
|
602
|
+
contributes nothing): it unions the foreground sections, keeps only the outlines with positive
|
|
603
|
+
signed area — outer boundaries, since Manifold winds a hole clockwise — and re-unions those,
|
|
604
|
+
which matters because two outers can overlap once the holes between them are gone. Ported from
|
|
605
|
+
the reference's `applyFill2D`, and checked shape-for-shape against OpenSCAD 2026.02.01 by
|
|
606
|
+
extruding and comparing STL volumes.
|
|
568
607
|
- `src/builtins/extrude.cpp` — `linear_extrude()`/`rotate_extrude()`/`projection(cut=)`. All three
|
|
569
608
|
union every 2D child into one `CrossSection` via `toCrossSection` first. `rotate_extrude`'s
|
|
570
609
|
segment count can't be resolved until generate time (it depends on the merged children's bounds,
|
|
@@ -330,6 +330,12 @@ public:
|
|
|
330
330
|
// free function, same reasoning as tagGenerated()/builtinChildren().
|
|
331
331
|
void warn(const std::string& message, const oscad::Position* position);
|
|
332
332
|
|
|
333
|
+
// Applies OpenSCAD's mixed-2D/3D rules to a node's children just
|
|
334
|
+
// before its GenerateFn runs -- see csg_generate.cpp.
|
|
335
|
+
void applyDimensionRules(CSGNode& node);
|
|
336
|
+
// ruleValue is a DimRule; the enum is file-local to csg_generate.cpp.
|
|
337
|
+
void applyDimensionRulesTo(const std::vector<CSGNode*>& children, int ruleValue);
|
|
338
|
+
|
|
333
339
|
// Apply `!`: replace the whole tree with the first show_only
|
|
334
340
|
// subtree, discarding its ancestors and every sibling. See its
|
|
335
341
|
// definition for why this cannot be done by tagging bodies.
|
|
@@ -160,6 +160,15 @@ CSGParams resolveHull(Evaluator& ev, const oscad::ModularCall& node, EvalContext
|
|
|
160
160
|
std::vector<ColoredBody> generateHull(Evaluator& ev, const CSGParams& params,
|
|
161
161
|
const std::vector<std::unique_ptr<CSGNode>>& children, const oscad::ASTNode& node);
|
|
162
162
|
|
|
163
|
+
// dxf_dim()/dxf_cross() -- read a dimension or a cross's centre out of a
|
|
164
|
+
// DXF file. Functions, not modules; dispatched from evalBuiltinFunction.
|
|
165
|
+
Value builtinDxfDim(Evaluator& ev, const CallArgs& args, const oscad::ASTNode& node);
|
|
166
|
+
Value builtinDxfCross(Evaluator& ev, const CallArgs& args, const oscad::ASTNode& node);
|
|
167
|
+
|
|
168
|
+
CSGParams resolveFill(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx);
|
|
169
|
+
std::vector<ColoredBody> generateFill(Evaluator& ev, const CSGParams& params,
|
|
170
|
+
const std::vector<std::unique_ptr<CSGNode>>& children,
|
|
171
|
+
const oscad::ASTNode& node);
|
|
163
172
|
CSGParams resolveMinkowski(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx);
|
|
164
173
|
std::vector<ColoredBody> generateMinkowski(Evaluator& ev, const CSGParams& params,
|
|
165
174
|
const std::vector<std::unique_ptr<CSGNode>>& children,
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
#include "builtins.hpp"
|
|
2
|
+
|
|
3
|
+
#include "openscad_cpp_evaluator/call_args.hpp"
|
|
4
|
+
#include "openscad_cpp_evaluator/evaluator.hpp"
|
|
5
|
+
|
|
6
|
+
#include <cmath>
|
|
7
|
+
#include <filesystem>
|
|
8
|
+
#include <fstream>
|
|
9
|
+
#include <sstream>
|
|
10
|
+
|
|
11
|
+
namespace oscadeval {
|
|
12
|
+
|
|
13
|
+
// dxf_dim() / dxf_cross() -- read a measurement straight out of a DXF file
|
|
14
|
+
// rather than out of the model. Ported from the reference's io/dxfdim.cc
|
|
15
|
+
// plus the DIMENSION/LINE half of io/DxfData.cc.
|
|
16
|
+
//
|
|
17
|
+
// These share the group-code walk with src/import/dxf_import.cpp but not its
|
|
18
|
+
// output: that one only cares about closed contours, while these two need
|
|
19
|
+
// the DIMENSION entities' seven coordinate slots and the raw LINE endpoints,
|
|
20
|
+
// neither of which a contour list keeps.
|
|
21
|
+
|
|
22
|
+
namespace {
|
|
23
|
+
|
|
24
|
+
struct Entity {
|
|
25
|
+
std::string type; // "DIMENSION", "LINE", ...
|
|
26
|
+
std::string layer;
|
|
27
|
+
std::string name; // group 1: DIMENSION's text override
|
|
28
|
+
int dimType = 0; // group 70
|
|
29
|
+
double angle = 0.0; // group 50
|
|
30
|
+
double coords[7][2] = {}; // groups 10-16 / 20-26
|
|
31
|
+
std::vector<double> xverts, yverts; // groups 10/11 and 20/21, in order
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
std::string trimmed(const std::string& s) {
|
|
35
|
+
const size_t b = s.find_first_not_of(" \t\r\n");
|
|
36
|
+
if (b == std::string::npos) return "";
|
|
37
|
+
return s.substr(b, s.find_last_not_of(" \t\r\n") - b + 1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// One entity per group-0 marker. Coordinates carry the origin shift and
|
|
41
|
+
// scale the reference applies while parsing, with its own exception: groups
|
|
42
|
+
// 11, 12 and 16 (and their 21/22/26 partners) are scaled but NOT shifted,
|
|
43
|
+
// since they are extents rather than positions.
|
|
44
|
+
std::vector<Entity> readEntities(const std::string& path, double xorigin, double yorigin, double scale) {
|
|
45
|
+
std::ifstream in(path);
|
|
46
|
+
std::vector<Entity> out;
|
|
47
|
+
if (!in) return out;
|
|
48
|
+
|
|
49
|
+
std::string codeLine, dataLine;
|
|
50
|
+
Entity cur;
|
|
51
|
+
bool started = false;
|
|
52
|
+
while (std::getline(in, codeLine) && std::getline(in, dataLine)) {
|
|
53
|
+
const std::string codeStr = trimmed(codeLine);
|
|
54
|
+
const std::string data = trimmed(dataLine);
|
|
55
|
+
if (codeStr.empty()) continue;
|
|
56
|
+
int code = 0;
|
|
57
|
+
try {
|
|
58
|
+
code = std::stoi(codeStr);
|
|
59
|
+
} catch (...) {
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
const auto num = [&]() -> double {
|
|
63
|
+
try {
|
|
64
|
+
return std::stod(data);
|
|
65
|
+
} catch (...) {
|
|
66
|
+
return 0.0;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
if (code == 0) {
|
|
71
|
+
if (started) out.push_back(cur);
|
|
72
|
+
cur = Entity{};
|
|
73
|
+
cur.type = data;
|
|
74
|
+
started = true;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (!started) continue;
|
|
78
|
+
|
|
79
|
+
if (code >= 10 && code <= 16) {
|
|
80
|
+
cur.coords[code - 10][0] =
|
|
81
|
+
(code == 11 || code == 12 || code == 16) ? num() * scale : (num() - xorigin) * scale;
|
|
82
|
+
} else if (code >= 20 && code <= 26) {
|
|
83
|
+
cur.coords[code - 20][1] =
|
|
84
|
+
(code == 21 || code == 22 || code == 26) ? num() * scale : (num() - yorigin) * scale;
|
|
85
|
+
}
|
|
86
|
+
switch (code) {
|
|
87
|
+
case 1: cur.name = data; break;
|
|
88
|
+
case 8: cur.layer = data; break;
|
|
89
|
+
case 10:
|
|
90
|
+
case 11: cur.xverts.push_back((num() - xorigin) * scale); break;
|
|
91
|
+
case 20:
|
|
92
|
+
case 21: cur.yverts.push_back((num() - yorigin) * scale); break;
|
|
93
|
+
case 50: cur.angle = num(); break;
|
|
94
|
+
case 70:
|
|
95
|
+
try {
|
|
96
|
+
cur.dimType = std::stoi(data);
|
|
97
|
+
} catch (...) {
|
|
98
|
+
}
|
|
99
|
+
break;
|
|
100
|
+
default: break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (started) out.push_back(cur);
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
double deg(double r) { return r * 180.0 / 3.14159265358979323846; }
|
|
108
|
+
double rad(double d) { return d * 3.14159265358979323846 / 180.0; }
|
|
109
|
+
|
|
110
|
+
struct CommonArgs {
|
|
111
|
+
std::string path;
|
|
112
|
+
std::string rawFile;
|
|
113
|
+
std::string layer;
|
|
114
|
+
double xorigin = 0.0, yorigin = 0.0, scale = 1.0;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
CommonArgs commonArgs(const CallArgs& args, const oscad::ASTNode& node) {
|
|
118
|
+
CommonArgs c;
|
|
119
|
+
const Value fileArg = getArg(args, 0, "file", Value{});
|
|
120
|
+
c.rawFile = std::holds_alternative<std::string>(fileArg) ? std::get<std::string>(fileArg) : fmtValue(fileArg);
|
|
121
|
+
c.path = resolveFilePath(fileArg, node);
|
|
122
|
+
const Value layerArg = getArg(args, std::nullopt, "layer", Value{});
|
|
123
|
+
if (const std::string* s = std::get_if<std::string>(&layerArg)) c.layer = *s;
|
|
124
|
+
const Value originArg = getArg(args, std::nullopt, "origin", Value{});
|
|
125
|
+
if (const ListPtr* l = std::get_if<ListPtr>(&originArg); l && *l && (*l)->items.size() >= 2) {
|
|
126
|
+
c.xorigin = toDoubleLenient((*l)->items[0]);
|
|
127
|
+
c.yorigin = toDoubleLenient((*l)->items[1]);
|
|
128
|
+
}
|
|
129
|
+
const Value scaleArg = getArg(args, std::nullopt, "scale", Value{1.0});
|
|
130
|
+
if (std::holds_alternative<double>(scaleArg)) c.scale = std::get<double>(scaleArg);
|
|
131
|
+
return c;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
} // namespace
|
|
135
|
+
|
|
136
|
+
Value builtinDxfDim(Evaluator& ev, const CallArgs& args, const oscad::ASTNode& node) {
|
|
137
|
+
const CommonArgs c = commonArgs(args, node);
|
|
138
|
+
const Value nameArg = getArg(args, std::nullopt, "name", Value{});
|
|
139
|
+
const std::string name = std::holds_alternative<std::string>(nameArg) ? std::get<std::string>(nameArg) : "";
|
|
140
|
+
|
|
141
|
+
if (!std::filesystem::exists(c.path)) {
|
|
142
|
+
ev.warn("Can't open DXF file '" + c.rawFile + "'!", &node.position());
|
|
143
|
+
return Value{};
|
|
144
|
+
}
|
|
145
|
+
for (const Entity& e : readEntities(c.path, c.xorigin, c.yorigin, c.scale)) {
|
|
146
|
+
if (e.type != "DIMENSION") continue;
|
|
147
|
+
if (!c.layer.empty() && c.layer != e.layer) continue;
|
|
148
|
+
if (!name.empty() && e.name != name) continue;
|
|
149
|
+
|
|
150
|
+
const int type = e.dimType & 7;
|
|
151
|
+
if (type == 0) { // rotated, horizontal or vertical
|
|
152
|
+
const double x = e.coords[4][0] - e.coords[3][0];
|
|
153
|
+
const double y = e.coords[4][1] - e.coords[3][1];
|
|
154
|
+
return Value{std::fabs(x * std::cos(rad(e.angle)) + y * std::sin(rad(e.angle)))};
|
|
155
|
+
}
|
|
156
|
+
if (type == 1) { // aligned
|
|
157
|
+
const double x = e.coords[4][0] - e.coords[3][0];
|
|
158
|
+
const double y = e.coords[4][1] - e.coords[3][1];
|
|
159
|
+
return Value{std::sqrt(x * x + y * y)};
|
|
160
|
+
}
|
|
161
|
+
if (type == 2) { // angular
|
|
162
|
+
const double a1 = deg(std::atan2(e.coords[0][0] - e.coords[5][0], e.coords[0][1] - e.coords[5][1]));
|
|
163
|
+
const double a2 = deg(std::atan2(e.coords[4][0] - e.coords[3][0], e.coords[4][1] - e.coords[3][1]));
|
|
164
|
+
return Value{std::fabs(a1 - a2)};
|
|
165
|
+
}
|
|
166
|
+
if (type == 3 || type == 4) { // diameter or radius
|
|
167
|
+
const double x = e.coords[5][0] - e.coords[0][0];
|
|
168
|
+
const double y = e.coords[5][1] - e.coords[0][1];
|
|
169
|
+
return Value{std::sqrt(x * x + y * y)};
|
|
170
|
+
}
|
|
171
|
+
if (type == 6) { // ordinate
|
|
172
|
+
return Value{(e.dimType & 64) ? e.coords[3][0] : e.coords[3][1]};
|
|
173
|
+
}
|
|
174
|
+
// type 5 (angular 3-point) falls through, as in the reference.
|
|
175
|
+
ev.warn("Dimension '" + name + "' in '" + c.rawFile + "', layer '" + c.layer + "' has unsupported type!",
|
|
176
|
+
&node.position());
|
|
177
|
+
return Value{};
|
|
178
|
+
}
|
|
179
|
+
ev.warn("Can't find dimension '" + name + "' in '" + c.rawFile + "', layer '" + c.layer + "'!",
|
|
180
|
+
&node.position());
|
|
181
|
+
return Value{};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
Value builtinDxfCross(Evaluator& ev, const CallArgs& args, const oscad::ASTNode& node) {
|
|
185
|
+
const CommonArgs c = commonArgs(args, node);
|
|
186
|
+
if (!std::filesystem::exists(c.path)) {
|
|
187
|
+
ev.warn("Can't open DXF file '" + c.rawFile + "'!", &node.position());
|
|
188
|
+
return Value{};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// The first two LINEs on the layer are taken to be the cross. The
|
|
192
|
+
// reference walks every 2-point path instead, which for a real cross is
|
|
193
|
+
// the same set: its two strokes meet in the middle rather than at their
|
|
194
|
+
// endpoints, so neither gets joined into a longer path.
|
|
195
|
+
double p[4][2];
|
|
196
|
+
int found = 0;
|
|
197
|
+
for (const Entity& e : readEntities(c.path, c.xorigin, c.yorigin, c.scale)) {
|
|
198
|
+
if (e.type != "LINE") continue;
|
|
199
|
+
if (!c.layer.empty() && c.layer != e.layer) continue;
|
|
200
|
+
if (e.xverts.size() < 2 || e.yverts.size() < 2) continue;
|
|
201
|
+
p[found][0] = e.xverts[0];
|
|
202
|
+
p[found][1] = e.yverts[0];
|
|
203
|
+
++found;
|
|
204
|
+
p[found][0] = e.xverts[1];
|
|
205
|
+
p[found][1] = e.yverts[1];
|
|
206
|
+
++found;
|
|
207
|
+
if (found == 4) {
|
|
208
|
+
const double x1 = p[0][0], y1 = p[0][1], x2 = p[1][0], y2 = p[1][1];
|
|
209
|
+
const double x3 = p[2][0], y3 = p[2][1], x4 = p[3][0], y4 = p[3][1];
|
|
210
|
+
const double dem = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
|
|
211
|
+
if (dem == 0.0) break; // parallel: no cross, same as the reference
|
|
212
|
+
const double ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / dem;
|
|
213
|
+
std::vector<Value> xy{Value{x1 + ua * (x2 - x1)}, Value{y1 + ua * (y2 - y1)}};
|
|
214
|
+
return Value{std::make_shared<const ValueList>(ValueList{std::move(xy)})};
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
ev.warn("Can't find cross in '" + c.rawFile + "', layer '" + c.layer + "'!", &node.position());
|
|
218
|
+
return Value{};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
} // namespace oscadeval
|
{openscad_cpp_evaluator-0.33.0 → openscad_cpp_evaluator-0.34.0}/src/builtins/function_builtins.cpp
RENAMED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
#include "openscad_cpp_evaluator/function_builtins.hpp"
|
|
2
2
|
|
|
3
|
+
#include "builtins.hpp" // builtinDxfDim/builtinDxfCross
|
|
4
|
+
|
|
3
5
|
#include "openscad_cpp_evaluator/dispatch.hpp"
|
|
4
6
|
#include "openscad_cpp_evaluator/evaluator.hpp"
|
|
5
7
|
#include "openscad_cpp_evaluator/segments.hpp"
|
|
@@ -447,7 +449,7 @@ bool isBuiltinFunctionName(const std::string& name) {
|
|
|
447
449
|
"acos", "atan", "atan2", "max", "min", "pow", "norm", "cross", "rands", "concat", "len", "str",
|
|
448
450
|
"chr", "ord", "is_undef", "is_num", "is_bool", "is_string", "is_list", "is_function", "is_object",
|
|
449
451
|
"search", "lookup", "has_key", "version", "version_num", "parent_module",
|
|
450
|
-
"object", "textmetrics", "fontmetrics",
|
|
452
|
+
"object", "textmetrics", "fontmetrics", "dxf_dim", "dxf_cross",
|
|
451
453
|
};
|
|
452
454
|
return names.count(name) > 0;
|
|
453
455
|
}
|
|
@@ -514,7 +516,7 @@ enum class BuiltinFnId {
|
|
|
514
516
|
TextMetrics, FontMetrics, Abs, Sign, Ceil, Floor, Round, Sqrt, Ln, Log, Exp, Sin, Cos, Tan,
|
|
515
517
|
Asin, Acos, Atan, Atan2, Max, Min, Pow, Norm, Cross, Rands, Concat, Len, Str, Chr, Ord,
|
|
516
518
|
IsUndef, IsNum, IsBool, IsString, IsList, IsFunction, IsObject, Search, Lookup, HasKey,
|
|
517
|
-
Version, VersionNum, ParentModule,
|
|
519
|
+
Version, VersionNum, ParentModule, DxfDim, DxfCross,
|
|
518
520
|
};
|
|
519
521
|
|
|
520
522
|
const std::unordered_map<std::string, BuiltinFnId>& builtinFnIds() {
|
|
@@ -536,6 +538,7 @@ const std::unordered_map<std::string, BuiltinFnId>& builtinFnIds() {
|
|
|
536
538
|
{"lookup", BuiltinFnId::Lookup}, {"has_key", BuiltinFnId::HasKey},
|
|
537
539
|
{"version", BuiltinFnId::Version}, {"version_num", BuiltinFnId::VersionNum},
|
|
538
540
|
{"parent_module", BuiltinFnId::ParentModule},
|
|
541
|
+
{"dxf_dim", BuiltinFnId::DxfDim}, {"dxf_cross", BuiltinFnId::DxfCross},
|
|
539
542
|
};
|
|
540
543
|
return ids;
|
|
541
544
|
}
|
|
@@ -949,6 +952,8 @@ Value evalBuiltinFunction(Evaluator& ev, const std::string& name, const CallArgs
|
|
|
949
952
|
if (!v || (v->size() != 2 && v->size() != 3)) return Value{};
|
|
950
953
|
return Value{(*v)[0] * 10000.0 + (*v)[1] * 100.0 + (v->size() == 3 ? (*v)[2] : 0.0)};
|
|
951
954
|
}
|
|
955
|
+
case BuiltinFnId::DxfDim: return builtinDxfDim(ev, args, node);
|
|
956
|
+
case BuiltinFnId::DxfCross: return builtinDxfCross(ev, args, node);
|
|
952
957
|
case BuiltinFnId::ParentModule: {
|
|
953
958
|
// Defaults to 1, not 0, when called with no argument at all --
|
|
954
959
|
// and an index past the end of the stack is a warning, not a
|
|
@@ -34,6 +34,7 @@ const std::unordered_map<std::string_view, ResolveFn>& resolveDispatch() {
|
|
|
34
34
|
{"rotate_extrude", &resolveRotateExtrude},
|
|
35
35
|
{"projection", &resolveProjection},
|
|
36
36
|
{"roof", &resolveRoof},
|
|
37
|
+
{"fill", &resolveFill},
|
|
37
38
|
{"offset", &resolveOffset},
|
|
38
39
|
{"surface", &resolveSurface},
|
|
39
40
|
{"text", &resolveText},
|
|
@@ -72,6 +73,7 @@ const std::unordered_map<std::string_view, GenerateFn>& generateDispatch() {
|
|
|
72
73
|
{"rotate_extrude", &generateRotateExtrude},
|
|
73
74
|
{"projection", &generateProjection},
|
|
74
75
|
{"roof", &generateRoof},
|
|
76
|
+
{"fill", &generateFill},
|
|
75
77
|
{"offset", &generateOffset},
|
|
76
78
|
{"surface", &generateSurface},
|
|
77
79
|
{"text", &generateText},
|
|
@@ -116,6 +118,7 @@ const std::vector<std::string>* builtinParamNames(const std::string& name) {
|
|
|
116
118
|
{"rotate_extrude", {"angle", "start", "convexity"}},
|
|
117
119
|
{"projection", {"cut", "convexity"}},
|
|
118
120
|
{"roof", {"method", "convexity"}},
|
|
121
|
+
{"fill", {}},
|
|
119
122
|
{"offset", {"r", "delta", "chamfer"}},
|
|
120
123
|
{"surface", {"file", "center", "convexity", "invert"}},
|
|
121
124
|
{"text", {"text", "size", "font", "direction", "language", "script", "halign", "valign", "spacing"}},
|
|
@@ -67,6 +67,76 @@ std::vector<ColoredBody> generateHull(Evaluator&, const CSGParams&, const std::v
|
|
|
67
67
|
return result;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
// fill() -- 2D only: union the children, then discard every hole, keeping
|
|
71
|
+
// just the outer boundaries. Ported from the reference's applyFill2D: union
|
|
72
|
+
// the children, keep only the *positive* outlines, then re-union those (two
|
|
73
|
+
// outers can overlap once the holes between them are gone, and the result
|
|
74
|
+
// has to come back as one sanitized region rather than a pile of loops).
|
|
75
|
+
//
|
|
76
|
+
// A 3D child gets the reference's own "not yet implemented for 3D" warning
|
|
77
|
+
// and contributes nothing.
|
|
78
|
+
|
|
79
|
+
CSGParams resolveFill(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
|
|
80
|
+
auto [args, effCtx] = resolveCallArgs(ev, node.arguments, ctx);
|
|
81
|
+
(void)args;
|
|
82
|
+
ev.evalChildren(node.children, effCtx);
|
|
83
|
+
return CSGParams{};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
namespace {
|
|
87
|
+
|
|
88
|
+
// Shoelace. Manifold orients an outer contour counter-clockwise (positive
|
|
89
|
+
// area) and a hole clockwise, so the sign is the whole test.
|
|
90
|
+
double signedArea(const manifold::SimplePolygon& poly) {
|
|
91
|
+
double a = 0.0;
|
|
92
|
+
for (size_t i = 0, n = poly.size(); i < n; ++i) {
|
|
93
|
+
const auto& p = poly[i];
|
|
94
|
+
const auto& q = poly[(i + 1) % n];
|
|
95
|
+
a += static_cast<double>(p.x) * q.y - static_cast<double>(q.x) * p.y;
|
|
96
|
+
}
|
|
97
|
+
return a / 2.0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
} // namespace
|
|
101
|
+
|
|
102
|
+
std::vector<ColoredBody> generateFill(Evaluator& ev, const CSGParams&,
|
|
103
|
+
const std::vector<std::unique_ptr<CSGNode>>& children,
|
|
104
|
+
const oscad::ASTNode& node) {
|
|
105
|
+
const std::vector<ColoredBody> bodies = flattenCsgTree(children);
|
|
106
|
+
if (bodies.empty()) return {};
|
|
107
|
+
const RoleSplit split = splitByRole(bodies);
|
|
108
|
+
|
|
109
|
+
std::optional<ColoredBody> filled;
|
|
110
|
+
if (!split.foreground.empty()) {
|
|
111
|
+
for (const ColoredBody& c : split.foreground) {
|
|
112
|
+
if (c.body) {
|
|
113
|
+
ev.warn("fill() not yet implemented for 3D", &node.position());
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (const std::optional<manifold::CrossSection> cs = toCrossSection(split.foreground)) {
|
|
118
|
+
manifold::Polygons outers;
|
|
119
|
+
for (const manifold::SimplePolygon& loop : cs->ToPolygons()) {
|
|
120
|
+
if (signedArea(loop) > 0.0) outers.push_back(loop);
|
|
121
|
+
}
|
|
122
|
+
if (!outers.empty()) {
|
|
123
|
+
ColoredBody cb;
|
|
124
|
+
cb.section = manifold::CrossSection(outers, manifold::CrossSection::FillRule::Positive);
|
|
125
|
+
cb.color = split.foreground.front().color;
|
|
126
|
+
filled = std::move(cb);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
std::vector<ColoredBody> result;
|
|
132
|
+
if (filled) result.push_back(std::move(*filled));
|
|
133
|
+
result.insert(result.end(), split.background.begin(), split.background.end());
|
|
134
|
+
result.insert(result.end(), split.highlight.begin(), split.highlight.end());
|
|
135
|
+
result.insert(result.end(), split.showOnly.begin(), split.showOnly.end());
|
|
136
|
+
result.insert(result.end(), split.displayOnly.begin(), split.displayOnly.end());
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
|
|
70
140
|
CSGParams resolveMinkowski(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
|
|
71
141
|
auto [args, effCtx] = resolveCallArgs(ev, node.arguments, ctx);
|
|
72
142
|
(void)args;
|
|
@@ -62,6 +62,8 @@ std::vector<ColoredBody> Evaluator::generateTreeImpl(const std::vector<CSGNode*>
|
|
|
62
62
|
for (const std::unique_ptr<CSGNode>& c : node.children) childPtrs.push_back(c.get());
|
|
63
63
|
generateTreeImpl(childPtrs);
|
|
64
64
|
|
|
65
|
+
applyDimensionRules(node);
|
|
66
|
+
|
|
65
67
|
auto it = dispatch.find(node.kind);
|
|
66
68
|
if (node.isBuiltin && it != dispatch.end()) {
|
|
67
69
|
// Resolve captured which user-level call reached this node;
|
|
@@ -90,11 +92,115 @@ std::vector<ColoredBody> Evaluator::generateTreeImpl(const std::vector<CSGNode*>
|
|
|
90
92
|
return topLevelBodies;
|
|
91
93
|
}
|
|
92
94
|
|
|
95
|
+
|
|
96
|
+
namespace {
|
|
97
|
+
|
|
98
|
+
// How a node treats children of the "wrong" dimension. Read off OpenSCAD
|
|
99
|
+
// 2026.02.01 module by module rather than inferred: essentially everything
|
|
100
|
+
// is Group (the reference routes it through applyToChildren, which calls
|
|
101
|
+
// isValidDim and then collectChildren2D/3D), with four exceptions.
|
|
102
|
+
enum class DimRule {
|
|
103
|
+
Group, // dimension comes from the first real child; mismatches warn twice
|
|
104
|
+
Only2D, // always 2D input; a 3D child is dropped with one warning
|
|
105
|
+
Only3D, // always 3D input; a 2D child is dropped with one warning
|
|
106
|
+
None, // no dimension diagnostics at all
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
DimRule dimRuleFor(const std::string& kind) {
|
|
110
|
+
if (kind == "linear_extrude" || kind == "rotate_extrude" || kind == "offset") return DimRule::Only2D;
|
|
111
|
+
if (kind == "projection") return DimRule::Only3D;
|
|
112
|
+
// roof() warns for neither in the reference, so neither do we.
|
|
113
|
+
if (kind == "roof") return DimRule::None;
|
|
114
|
+
return DimRule::Group;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
bool isEmptyBody(const ColoredBody& b) {
|
|
118
|
+
if (b.body) return b.body->NumTri() == 0;
|
|
119
|
+
if (b.section) return b.section->IsEmpty();
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 3 for a solid, 2 for a section, 0 for "no geometry at all" (which never
|
|
124
|
+
// takes part in the dimension decision).
|
|
125
|
+
int dimensionOf(const ColoredBody& b) {
|
|
126
|
+
if (b.body) return 3;
|
|
127
|
+
if (b.section) return 2;
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
} // namespace
|
|
132
|
+
|
|
133
|
+
// Drops children of the wrong dimension, with the reference's own two
|
|
134
|
+
// warnings. This is not only about diagnostics: generateCsg builds one
|
|
135
|
+
// result and switches on whether it holds a body or a section, so a group
|
|
136
|
+
// that changed dimension part-way dereferenced the empty optional and took
|
|
137
|
+
// the process down ("mutex lock failed" from the garbage read). Filtering
|
|
138
|
+
// here means no downstream generate ever sees a mixed group.
|
|
139
|
+
//
|
|
140
|
+
// Background (%) children are exempt, matching isValidDim's own
|
|
141
|
+
// isBackground() skip -- a ghost of the other dimension is not an error.
|
|
142
|
+
void Evaluator::applyDimensionRules(CSGNode& node) {
|
|
143
|
+
const DimRule rule = dimRuleFor(node.kind);
|
|
144
|
+
if (rule == DimRule::None) return;
|
|
145
|
+
std::vector<CSGNode*> kids;
|
|
146
|
+
kids.reserve(node.children.size());
|
|
147
|
+
for (const std::unique_ptr<CSGNode>& c : node.children) kids.push_back(c.get());
|
|
148
|
+
applyDimensionRulesTo(kids, static_cast<int>(rule));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// The top level is an implicit union, and the reference treats it as one for
|
|
152
|
+
// this too: `square(4); cube(1);` warns and keeps only the square.
|
|
153
|
+
void Evaluator::applyDimensionRulesTo(const std::vector<CSGNode*>& children, int ruleValue) {
|
|
154
|
+
const DimRule rule = static_cast<DimRule>(ruleValue);
|
|
155
|
+
int target = rule == DimRule::Only2D ? 2 : rule == DimRule::Only3D ? 3 : 0;
|
|
156
|
+
bool warnedMixing = false;
|
|
157
|
+
|
|
158
|
+
for (CSGNode* child : children) {
|
|
159
|
+
if (!child) continue;
|
|
160
|
+
std::vector<ColoredBody> kept;
|
|
161
|
+
kept.reserve(child->bodies.size());
|
|
162
|
+
for (ColoredBody& b : child->bodies) {
|
|
163
|
+
const int dim = dimensionOf(b);
|
|
164
|
+
if (b.role == BodyRole::Background || dim == 0 || isEmptyBody(b)) {
|
|
165
|
+
kept.push_back(std::move(b));
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (target == 0) {
|
|
169
|
+
target = dim; // first real child fixes the dimension
|
|
170
|
+
kept.push_back(std::move(b));
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (dim == target) {
|
|
174
|
+
kept.push_back(std::move(b));
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
const oscad::Position* pos = child->node ? &child->node->position() : nullptr;
|
|
178
|
+
if (rule == DimRule::Group && !warnedMixing) {
|
|
179
|
+
warn("Mixing 2D and 3D objects is not supported", pos);
|
|
180
|
+
warnedMixing = true;
|
|
181
|
+
}
|
|
182
|
+
warn(std::string("Ignoring ") + (dim == 3 ? "3D" : "2D") + " child object for " +
|
|
183
|
+
(target == 3 ? "3D" : "2D") + " operation",
|
|
184
|
+
pos);
|
|
185
|
+
// dropped
|
|
186
|
+
}
|
|
187
|
+
child->bodies = std::move(kept);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
93
191
|
std::vector<ColoredBody> Evaluator::generateTree(const std::vector<std::unique_ptr<CSGNode>>& tree) {
|
|
94
192
|
std::vector<CSGNode*> ptrs;
|
|
95
193
|
ptrs.reserve(tree.size());
|
|
96
194
|
for (const std::unique_ptr<CSGNode>& n : tree) ptrs.push_back(n.get());
|
|
97
|
-
|
|
195
|
+
std::vector<ColoredBody> bodies = generateTreeImpl(ptrs);
|
|
196
|
+
// The top level is an implicit union; give it the same Group treatment
|
|
197
|
+
// every other group node gets, then re-collect what survived.
|
|
198
|
+
applyDimensionRulesTo(ptrs, static_cast<int>(DimRule::Group));
|
|
199
|
+
bodies.clear();
|
|
200
|
+
for (CSGNode* n : ptrs) {
|
|
201
|
+
for (const ColoredBody& b : n->bodies) bodies.push_back(b);
|
|
202
|
+
}
|
|
203
|
+
return bodies;
|
|
98
204
|
}
|
|
99
205
|
|
|
100
206
|
std::vector<ColoredBody> Evaluator::generatePartialTree() {
|
|
@@ -15,6 +15,12 @@ EvalContext EvalContext::makeRoot(const oscad::Scope* rootScope) {
|
|
|
15
15
|
ctx.dyn->set("$fs", Value{2.0});
|
|
16
16
|
ctx.dyn->set("$t", Value{0.0});
|
|
17
17
|
ctx.dyn->set("$parent_modules", Value{0.0});
|
|
18
|
+
// Always false: there is no preview mode here, every render is a full
|
|
19
|
+
// CSG render. The variable still has to EXIST, though -- a script that
|
|
20
|
+
// branches on it (the `$preview ? cheap : real` idiom) would otherwise
|
|
21
|
+
// see undef, take the falsy branch by accident rather than by rule, and
|
|
22
|
+
// warn about an unknown variable while doing it.
|
|
23
|
+
ctx.dyn->set("$preview", Value{false});
|
|
18
24
|
ctx.let_ = TrailView<Value>::makeRoot();
|
|
19
25
|
ctx.dynPositions = TrailView<const oscad::Position*>::makeRoot();
|
|
20
26
|
ctx.childrenNodes = std::make_shared<const ChildrenNodeList>();
|