From 7e0199746ef683c2bda80c5649b5c4150880a9c3 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 16 Aug 2019 16:17:37 +0200 Subject: [PATCH] more clang warnings enabled, performance measuring Succesfull build on mingw-w64 fix sandboxes Mingw fixes and full parallel support tree gen. --- CMakeLists.txt | 63 ++- deps/CMakeLists.txt | 5 +- deps/deps-mingw.cmake | 76 +++ deps/deps-unix-common.cmake | 7 + sandboxes/CMakeLists.txt | 1 + sandboxes/slabasebed/slabasebed.cpp | 17 +- sandboxes/slasupporttree/CMakeLists.txt | 2 + sandboxes/slasupporttree/slasupporttree.cpp | 42 ++ src/CMakeLists.txt | 36 +- src/PrusaSlicer.cpp | 238 ++++----- src/PrusaSlicer_app_msvc.cpp | 381 +++++++-------- src/avrdude/CMakeLists.txt | 8 +- src/avrdude/lexer.c | 2 +- src/avrdude/main-standalone.cpp | 4 + src/avrdude/windows/unistd.h | 2 +- src/libigl/igl/SortableRow.h | 84 ++-- .../libnest2d/backends/clipper/geometries.hpp | 8 + src/libslic3r/Arrange.cpp | 10 + src/libslic3r/CMakeLists.txt | 6 +- src/libslic3r/GCode/ToolOrdering.hpp | 73 +-- src/libslic3r/PrintConfig.cpp | 402 ++++++++-------- src/libslic3r/SLA/SLAAutoSupports.cpp | 88 ++-- src/libslic3r/SLA/SLASupportTree.cpp | 328 ++++++------- src/libslic3r/SLA/SLASupportTreeIGL.cpp | 13 +- src/libslic3r/SLAPrint.cpp | 192 ++++---- src/slic3r/GUI/wxExtensions.hpp | 451 +++++++++--------- src/slic3r/Utils/Time.hpp | 2 +- 27 files changed, 1393 insertions(+), 1148 deletions(-) create mode 100644 deps/deps-mingw.cmake create mode 100644 sandboxes/slasupporttree/CMakeLists.txt create mode 100644 sandboxes/slasupporttree/slasupporttree.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a29a144fe..9b8a1c848 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,13 +13,13 @@ if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) endif() if(DEFINED ENV{SLIC3R_STATIC}) - set(SLIC3R_STATIC_INITIAL $ENV{SLIC3R_STATIC}) + set(SLIC3R_STATIC_INITIAL $ENV{SLIC3R_STATIC}) else() - if (MSVC OR MINGW OR APPLE) - set(SLIC3R_STATIC_INITIAL 1) - else() - set(SLIC3R_STATIC_INITIAL 0) - endif() + if (MSVC OR MINGW OR APPLE) + set(SLIC3R_STATIC_INITIAL 1) + else() + set(SLIC3R_STATIC_INITIAL 0) + endif() endif() option(SLIC3R_STATIC "Compile PrusaSlicer with static libraries (Boost, TBB, glew)" ${SLIC3R_STATIC_INITIAL}) @@ -54,13 +54,19 @@ endif () if (MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL Clang) set(IS_CLANG_CL TRUE) + + # clang-cl can interpret SYSTEM header paths if -imsvc is used + set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-imsvc") + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall \ + -Wno-old-style-cast -Wno-reserved-id-macro -Wno-c++98-compat-pedantic") else () set(IS_CLANG_CL FALSE) endif () if (MSVC) if (SLIC3R_MSVC_COMPILE_PARALLEL AND NOT IS_CLANG_CL) - add_compile_options(/MP) + add_compile_options(/MP) endif () # /bigobj (Increase Number of Sections in .Obj file) # error C3859: virtual memory range for PCH exceeded; please recompile with a command line option of '-Zm90' or greater @@ -68,6 +74,10 @@ if (MSVC) add_compile_options(-bigobj -Zm520 /Zi) endif () +if (MINGW) + add_compile_options(-Wa,-mbig-obj) +endif () + # Display and check CMAKE_PREFIX_PATH message(STATUS "SLIC3R_STATIC: ${SLIC3R_STATIC}") if (NOT "${CMAKE_PREFIX_PATH}" STREQUAL "") @@ -107,17 +117,17 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON) # WIN10SDK_PATH is used to point CMake to the WIN10 SDK installation directory. # We pick it from environment if it is not defined in another way if(WIN32) - if(NOT DEFINED WIN10SDK_PATH) - if(DEFINED ENV{WIN10SDK_PATH}) - set(WIN10SDK_PATH "$ENV{WIN10SDK_PATH}") - endif() - endif() - if(DEFINED WIN10SDK_PATH AND NOT EXISTS "${WIN10SDK_PATH}/include/winrt/windows.graphics.printing3d.h") - message("WIN10SDK_PATH is invalid: ${WIN10SDK_PATH}") - message("${WIN10SDK_PATH}/include/winrt/windows.graphics.printing3d.h was not found") - message("STL fixing by the Netfabb service will not be compiled") - unset(WIN10SDK_PATH) - endif() + if(NOT DEFINED WIN10SDK_PATH) + if(DEFINED ENV{WIN10SDK_PATH}) + set(WIN10SDK_PATH "$ENV{WIN10SDK_PATH}") + endif() + endif() + if(DEFINED WIN10SDK_PATH AND NOT EXISTS "${WIN10SDK_PATH}/include/winrt/windows.graphics.printing3d.h") + message("WIN10SDK_PATH is invalid: ${WIN10SDK_PATH}") + message("${WIN10SDK_PATH}/include/winrt/windows.graphics.printing3d.h was not found") + message("STL fixing by the Netfabb service will not be compiled") + unset(WIN10SDK_PATH) + endif() if(WIN10SDK_PATH) message("Building with Win10 Netfabb STL fixing service support") add_definitions(-DHAS_WIN10SDK) @@ -155,7 +165,9 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUXX) endif() if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" ) + if (NOT MINGW) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" ) + endif () set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reorder" ) # On GCC and Clang, no return from a non-void function is a warning only. Here, we make it an error. @@ -201,9 +213,12 @@ include_directories(${LIBDIR_BIN}/platform) include_directories(${LIBDIR}/clipper ${LIBDIR}/polypartition) if(WIN32) - # BOOST_ALL_NO_LIB: Avoid the automatic linking of Boost libraries on Windows. Rather rely on explicit linking. - add_definitions(-D_USE_MATH_DEFINES -D_WIN32 -DBOOST_ALL_NO_LIB -DBOOST_USE_WINAPI_VERSION=0x601 -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS) -endif() + add_definitions(-D_USE_MATH_DEFINES -D_WIN32 -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS) + if(MSVC) + # BOOST_ALL_NO_LIB: Avoid the automatic linking of Boost libraries on Windows. Rather rely on explicit linking. + add_definitions(-DBOOST_ALL_NO_LIB -DBOOST_USE_WINAPI_VERSION=0x601 ) + endif(MSVC) +endif(WIN32) add_definitions(-DwxUSE_UNICODE -D_UNICODE -DUNICODE -DWXINTL_NO_GETTEXT_MACRO) @@ -234,7 +249,7 @@ if(SLIC3R_STATIC) # set(Boost_USE_STATIC_RUNTIME ON) endif() #set(Boost_DEBUG ON) -# set(Boost_COMPILER "-vc120") +# set(Boost_COMPILER "-mgw81") if(NOT WIN32) # boost::process was introduced first in version 1.64.0 set(MINIMUM_BOOST_VERSION "1.64.0") @@ -256,7 +271,7 @@ endif() if(TARGET Boost::system) message(STATUS "Boost::boost exists") target_link_libraries(boost_headeronly INTERFACE Boost::boost) - target_link_libraries(boost_libs INTERFACE + target_link_libraries(boost_libs INTERFACE boost_headeronly # includes the custom compile definitions as well Boost::system Boost::filesystem diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index f6a80f3ca..90ad6f0fa 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -76,7 +76,10 @@ elseif (APPLE) endif () include("deps-macos.cmake") -else () +elseif (MINGW) + message(STATUS "Building for MinGW...") + include("deps-mingw.cmake") +else() include("deps-linux.cmake") endif() diff --git a/deps/deps-mingw.cmake b/deps/deps-mingw.cmake new file mode 100644 index 000000000..bfe5f9fe4 --- /dev/null +++ b/deps/deps-mingw.cmake @@ -0,0 +1,76 @@ +set(DEP_CMAKE_OPTS "-DCMAKE_POSITION_INDEPENDENT_CODE=ON") +set(DEP_BOOST_TOOLSET "gcc") +set(DEP_BITS 64) + +find_package(Git REQUIRED) + +# TODO make sure to build tbb with -flifetime-dse=1 +include("deps-unix-common.cmake") + +ExternalProject_Add(dep_boost + EXCLUDE_FROM_ALL 1 + URL "https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz" + URL_HASH SHA256=882b48708d211a5f48e60b0124cf5863c1534cd544ecd0664bb534a4b5d506e9 + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND bootstrap.bat + BUILD_COMMAND b2.exe + -j "${NPROC}" + --with-system + --with-filesystem + --with-thread + --with-log + --with-locale + --with-regex + "--prefix=${DESTDIR}/usr/local" + "address-model=${DEPS_BITS}" + "toolset=${DEP_BOOST_TOOLSET}" + link=static + define=BOOST_USE_WINAPI_VERSION=0x0502 + variant=release + threading=multi + boost.locale.icu=off + "${DEP_BOOST_DEBUG}" release install + INSTALL_COMMAND "" # b2 does that already +) + +ExternalProject_Add(dep_libcurl + EXCLUDE_FROM_ALL 1 + URL "https://curl.haxx.se/download/curl-7.58.0.tar.gz" + URL_HASH SHA256=cc245bf9a1a42a45df491501d97d5593392a03f7b4f07b952793518d97666115 + CMAKE_ARGS + -DBUILD_SHARED_LIBS=OFF + -DBUILD_TESTING=OFF + -DCURL_STATICLIB=ON + -DCURL_STATIC_CRT=ON + -DENABLE_THREADED_RESOLVER=ON + -DCURL_DISABLE_FTP=ON + -DCURL_DISABLE_LDAP=ON + -DCURL_DISABLE_LDAPS=ON + -DCURL_DISABLE_TELNET=ON + -DCURL_DISABLE_DICT=ON + -DCURL_DISABLE_FILE=ON + -DCURL_DISABLE_TFTP=ON + -DCURL_DISABLE_RTSP=ON + -DCURL_DISABLE_POP3=ON + -DCURL_DISABLE_IMAP=ON + -DCURL_DISABLE_SMTP=ON + -DCURL_DISABLE_GOPHER=ON + -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local + ${DEP_CMAKE_OPTS} +) + +ExternalProject_Add(dep_wxwidgets + EXCLUDE_FROM_ALL 1 + GIT_REPOSITORY "https://github.com/prusa3d/wxWidgets" + GIT_TAG v3.1.1-patched +# URL "https://github.com/wxWidgets/wxWidgets/releases/download/v3.1.1/wxWidgets-3.1.1.tar.bz2" +# URL_HASH SHA256=c925dfe17e8f8b09eb7ea9bfdcfcc13696a3e14e92750effd839f5e10726159e +# PATCH_COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}\\wxwidgets-pngprefix.h" src\\png\\pngprefix.h + CMAKE_ARGS + -DBUILD_SHARED_LIBS=OFF + -DwxUSE_LIBPNG=builtin + -DwxUSE_ZLIB=builtin + -DwxUSE_OPENGL=ON + -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local + ${DEP_CMAKE_OPTS} +) \ No newline at end of file diff --git a/deps/deps-unix-common.cmake b/deps/deps-unix-common.cmake index e323460a6..6e559d05a 100644 --- a/deps/deps-unix-common.cmake +++ b/deps/deps-unix-common.cmake @@ -1,6 +1,12 @@ # The unix common part expects DEP_CMAKE_OPTS to be set +if (MINGW) + set(TBB_MINGW_WORKAROUND "-flifetime-dse=1") +else () + set(TBB_MINGW_WORKAROUND "") +endif () + ExternalProject_Add(dep_tbb EXCLUDE_FROM_ALL 1 URL "https://github.com/wjakob/tbb/archive/a0dc9bf76d0120f917b641ed095360448cabc85b.tar.gz" @@ -8,6 +14,7 @@ ExternalProject_Add(dep_tbb CMAKE_ARGS -DTBB_BUILD_SHARED=OFF -DTBB_BUILD_TESTS=OFF + -DCMAKE_CXX_FLAGS=${TBB_MINGW_WORKAROUND} -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local ${DEP_CMAKE_OPTS} ) diff --git a/sandboxes/CMakeLists.txt b/sandboxes/CMakeLists.txt index 0e1f52d6c..5905c438e 100644 --- a/sandboxes/CMakeLists.txt +++ b/sandboxes/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(slabasebed) +add_subdirectory(slasupporttree) diff --git a/sandboxes/slabasebed/slabasebed.cpp b/sandboxes/slabasebed/slabasebed.cpp index 5393f61fd..b8b94d86f 100644 --- a/sandboxes/slabasebed/slabasebed.cpp +++ b/sandboxes/slabasebed/slabasebed.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -15,8 +16,8 @@ const std::string USAGE_STR = { namespace Slic3r { namespace sla { -Contour3D create_base_pool(const Polygons &ground_layer, - const Polygons &holes = {}, +Contour3D create_base_pool(const Polygons &ground_layer, + const ExPolygons &holes = {}, const PoolConfig& cfg = PoolConfig()); Contour3D walls(const Polygon& floor_plate, const Polygon& ceiling, @@ -43,22 +44,22 @@ int main(const int argc, const char *argv[]) { model.ReadSTLFile(argv[1]); model.align_to_origin(); - Polygons ground_slice; + ExPolygons ground_slice; sla::base_plate(model, ground_slice, 0.1f); if(ground_slice.empty()) return EXIT_FAILURE; - Polygon gndfirst; gndfirst = ground_slice.front(); - sla::offset_with_breakstick_holes(gndfirst, 0.5, 10, 0.3); + ground_slice = offset_ex(ground_slice, 0.5); + ExPolygon gndfirst; gndfirst = ground_slice.front(); + sla::breakstick_holes(gndfirst, 0.5, 10, 0.3); sla::Contour3D mesh; - bench.start(); sla::PoolConfig cfg; cfg.min_wall_height_mm = 0; cfg.edge_radius_mm = 0; - mesh = sla::create_base_pool(ground_slice, {}, cfg); + mesh = sla::create_base_pool(to_polygons(ground_slice), {}, cfg); bench.stop(); @@ -75,7 +76,7 @@ int main(const int argc, const char *argv[]) { if(std::abs(a) < 1e-6) std::cout << "degenerate triangle" << std::endl; } -// basepool.write_ascii("out.stl"); + // basepool.write_ascii("out.stl"); std::fstream outstream("out.obj", std::fstream::out); mesh.to_obj(outstream); diff --git a/sandboxes/slasupporttree/CMakeLists.txt b/sandboxes/slasupporttree/CMakeLists.txt new file mode 100644 index 000000000..79adb842b --- /dev/null +++ b/sandboxes/slasupporttree/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(slasupporttree slasupporttree.cpp) +target_link_libraries(slasupporttree libslic3r ${Boost_LIBRARIES} ${TBB_LIBRARIES} ${Boost_LIBRARIES} ${CMAKE_DL_LIBS}) diff --git a/sandboxes/slasupporttree/slasupporttree.cpp b/sandboxes/slasupporttree/slasupporttree.cpp new file mode 100644 index 000000000..dcaddf6d3 --- /dev/null +++ b/sandboxes/slasupporttree/slasupporttree.cpp @@ -0,0 +1,42 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +const std::string USAGE_STR = { + "Usage: slasupporttree stlfilename.stl" +}; + +int main(const int argc, const char *argv[]) { + using namespace Slic3r; + using std::cout; using std::endl; + + if(argc < 2) { + cout << USAGE_STR << endl; + return EXIT_SUCCESS; + } + + DynamicPrintConfig config; + + Model model = Model::read_from_file(argv[1], &config); + + SLAPrint print; + + print.apply(model, config); + print.process(); + + + return EXIT_SUCCESS; +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3ee46289a..9f3dbcec8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -47,7 +47,7 @@ if (SLIC3R_GUI) endif () endif () else () - find_package(wxWidgets 3.1 REQUIRED COMPONENTS base core adv html gl) + find_package(wxWidgets 3.1 REQUIRED COMPONENTS html adv gl core base) endif () if(UNIX) @@ -56,6 +56,9 @@ if (SLIC3R_GUI) include(${wxWidgets_USE_FILE}) +# list(REMOVE_ITEM wxWidgets_LIBRARIES oleacc) + message(STATUS "wx libs: ${wxWidgets_LIBRARIES}") + add_subdirectory(slic3r) endif() @@ -65,12 +68,18 @@ endif() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/msw/PrusaSlicer.rc.in ${CMAKE_CURRENT_BINARY_DIR}/PrusaSlicer.rc @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/msw/PrusaSlicer.manifest.in ${CMAKE_CURRENT_BINARY_DIR}/PrusaSlicer.manifest @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/osx/Info.plist.in ${CMAKE_CURRENT_BINARY_DIR}/Info.plist @ONLY) -if (MSVC) +if (WIN32) add_library(PrusaSlicer SHARED PrusaSlicer.cpp PrusaSlicer.hpp) else () add_executable(PrusaSlicer PrusaSlicer.cpp PrusaSlicer.hpp) endif () -if (NOT MSVC) + +if (MINGW) + target_link_options(PrusaSlicer PUBLIC "-Wl,-allow-multiple-definition") + set_target_properties(PrusaSlicer PROPERTIES PREFIX "") +endif (MINGW) + +if (NOT WIN32) # Binary name on unix like systems (OSX, Linux) set_target_properties(PrusaSlicer PROPERTIES OUTPUT_NAME "prusa-slicer") endif () @@ -91,11 +100,12 @@ endif () # Add the Slic3r GUI library, libcurl, OpenGL and GLU libraries. if (SLIC3R_GUI) - target_link_libraries(PrusaSlicer libslic3r_gui ${wxWidgets_LIBRARIES}) +# target_link_libraries(PrusaSlicer ws2_32 uxtheme setupapi libslic3r_gui ${wxWidgets_LIBRARIES}) +target_link_libraries(PrusaSlicer libslic3r_gui ${wxWidgets_LIBRARIES}) # Configure libcurl and its dependencies OpenSSL & zlib find_package(CURL REQUIRED) - if (NOT MSVC) + if (NOT WIN32) # Required by libcurl find_package(ZLIB REQUIRED) endif() @@ -123,7 +133,7 @@ if (SLIC3R_GUI) target_link_options(PrusaSlicer PUBLIC "$<$:/DEBUG>") target_link_libraries(PrusaSlicer user32.lib Setupapi.lib OpenGL32.Lib GlU32.Lib) elseif (MINGW) - target_link_libraries(PrusaSlicer -lopengl32) + target_link_libraries(PrusaSlicer opengl32 ws2_32 uxtheme setupapi) elseif (APPLE) target_link_libraries(PrusaSlicer "-framework OpenGL") else () @@ -133,10 +143,16 @@ endif () # On Windows, a shim application is required to produce a console / non console version of the Slic3r application. # Also the shim may load the Mesa software OpenGL renderer if the default renderer does not support OpenGL 2.0 and higher. -if (MSVC) +if (WIN32) + if (MINGW) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -municode") + endif() + add_executable(PrusaSlicer_app_gui WIN32 PrusaSlicer_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/PrusaSlicer.rc) # Generate debug symbols even in release mode. - target_link_options(PrusaSlicer_app_gui PUBLIC "$<$:/DEBUG>") + if(MSVC) + target_link_options(PrusaSlicer_app_gui PUBLIC "$<$:/DEBUG>") + endif() target_compile_definitions(PrusaSlicer_app_gui PRIVATE -DSLIC3R_WRAPPER_NOCONSOLE) add_dependencies(PrusaSlicer_app_gui PrusaSlicer) set_target_properties(PrusaSlicer_app_gui PROPERTIES OUTPUT_NAME "prusa-slicer") @@ -144,7 +160,9 @@ if (MSVC) add_executable(PrusaSlicer_app_console PrusaSlicer_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/PrusaSlicer.rc) # Generate debug symbols even in release mode. + if (MSVC) target_link_options(PrusaSlicer_app_console PUBLIC "$<$:/DEBUG>") + endif () target_compile_definitions(PrusaSlicer_app_console PRIVATE -DSLIC3R_WRAPPER_CONSOLE) add_dependencies(PrusaSlicer_app_console PrusaSlicer) set_target_properties(PrusaSlicer_app_console PROPERTIES OUTPUT_NAME "prusa-slicer-console") @@ -152,7 +170,7 @@ if (MSVC) endif () # Link the resources dir to where Slic3r GUI expects it -if (MSVC) +if (WIN32) if (CMAKE_CONFIGURATION_TYPES) foreach (CONF ${CMAKE_CONFIGURATION_TYPES}) file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${CONF}" WIN_CONF_OUTPUT_DIR) diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp index b1ba30553..c8cf9b42d 100644 --- a/src/PrusaSlicer.cpp +++ b/src/PrusaSlicer.cpp @@ -7,8 +7,8 @@ #include #include #ifdef SLIC3R_GUI - extern "C" - { + extern "C" + { // Let the NVIDIA and AMD know we want to use their graphics card // on a dual graphics card system. __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; @@ -53,28 +53,28 @@ using namespace Slic3r; PrinterTechnology get_printer_technology(const DynamicConfig &config) { - const ConfigOptionEnum *opt = config.option>("printer_technology"); + const ConfigOptionEnum *opt = config.option>("printer_technology"); return (opt == nullptr) ? ptUnknown : opt->value; } -int CLI::run(int argc, char **argv) +int CLI::run(int argc, char **argv) { - if (! this->setup(argc, argv)) - return 1; + if (! this->setup(argc, argv)) + return 1; m_extra_config.apply(m_config, true); m_extra_config.normalize(); bool start_gui = m_actions.empty() && // cutting transformations are setting an "export" action. - std::find(m_transforms.begin(), m_transforms.end(), "cut") == m_transforms.end() && - std::find(m_transforms.begin(), m_transforms.end(), "cut_x") == m_transforms.end() && - std::find(m_transforms.begin(), m_transforms.end(), "cut_y") == m_transforms.end(); + std::find(m_transforms.begin(), m_transforms.end(), "cut") == m_transforms.end() && + std::find(m_transforms.begin(), m_transforms.end(), "cut_x") == m_transforms.end() && + std::find(m_transforms.begin(), m_transforms.end(), "cut_y") == m_transforms.end(); PrinterTechnology printer_technology = get_printer_technology(m_extra_config); - const std::vector &load_configs = m_config.option("load", true)->values; - + const std::vector &load_configs = m_config.option("load", true)->values; + // load config files supplied via --load - for (auto const &file : load_configs) { + for (auto const &file : load_configs) { if (! boost::filesystem::exists(file)) { if (m_config.opt_bool("ignore_nonexistent_config")) { continue; @@ -100,7 +100,7 @@ int CLI::run(int argc, char **argv) } m_print_config.apply(config); } - + // Read input file(s) if any. for (const std::string &file : m_input_files) { if (! boost::filesystem::exists(file)) { @@ -136,21 +136,21 @@ int CLI::run(int argc, char **argv) m_print_config.normalize(); if (printer_technology == ptUnknown) - printer_technology = std::find(m_actions.begin(), m_actions.end(), "export_sla") == m_actions.end() ? ptFFF : ptSLA; + printer_technology = std::find(m_actions.begin(), m_actions.end(), "export_sla") == m_actions.end() ? ptFFF : ptSLA; // Initialize full print configs for both the FFF and SLA technologies. FullPrintConfig fff_print_config; // SLAFullPrintConfig sla_print_config; fff_print_config.apply(m_print_config, true); // sla_print_config.apply(m_print_config, true); - + // Loop through transform options. for (auto const &opt_key : m_transforms) { if (opt_key == "merge") { Model m; for (auto &model : m_models) - for (ModelObject *o : model.objects) - m.add_object(*o); + for (ModelObject *o : model.objects) + m.add_object(*o); // Rearrange instances unless --dont-arrange is supplied if (! m_config.opt_bool("dont_arrange")) { m.add_default_instances(); @@ -162,8 +162,8 @@ int CLI::run(int argc, char **argv) this->has_print_action() ? &bb : nullptr ); } - m_models.clear(); - m_models.emplace_back(std::move(m)); + m_models.clear(); + m_models.emplace_back(std::move(m)); } else if (opt_key == "duplicate") { const BoundingBoxf &bb = fff_print_config.bed_shape.values; for (auto &model : m_models) { @@ -192,11 +192,11 @@ int CLI::run(int argc, char **argv) // this affects instances: model.center_instances_around_point(m_config.option("center")->value); // this affects volumes: - //FIXME Vojtech: Who knows why the complete model should be aligned with Z as a single rigid body? + //FIXME Vojtech: Who knows why the complete model should be aligned with Z as a single rigid body? //model.align_to_ground(); BoundingBoxf3 bbox; for (ModelObject *model_object : model.objects) - // We are interested into the Z span only, therefore it is sufficient to measure the bounding box of the 1st instance only. + // We are interested into the Z span only, therefore it is sufficient to measure the bounding box of the 1st instance only. bbox.merge(model_object->instance_bounding_box(0, false)); for (ModelObject *model_object : model.objects) for (ModelInstance *model_instance : model_object->instances) @@ -207,7 +207,7 @@ int CLI::run(int argc, char **argv) for (auto &model : m_models) { BoundingBoxf3 bb = model.bounding_box(); // this affects volumes: - model.translate(-(bb.min.x() - p.x()), -(bb.min.y() - p.y()), -bb.min.z()); + model.translate(-(bb.min.x() - p.x()), -(bb.min.y() - p.y()), -bb.min.z()); } } else if (opt_key == "dont_arrange") { // do nothing - this option alters other transform options @@ -245,8 +245,8 @@ int CLI::run(int argc, char **argv) std::vector new_models; for (auto &model : m_models) { model.translate(0, 0, -model.bounding_box().min.z()); // align to z = 0 - size_t num_objects = model.objects.size(); - for (size_t i = 0; i < num_objects; ++ i) { + size_t num_objects = model.objects.size(); + for (size_t i = 0; i < num_objects; ++ i) { #if 0 if (opt_key == "cut_x") { @@ -257,15 +257,15 @@ int CLI::run(int argc, char **argv) o->cut(Z, m_config.opt_float("cut"), &out); } #else - model.objects.front()->cut(0, m_config.opt_float("cut"), true, true, true); + model.objects.front()->cut(0, m_config.opt_float("cut"), true, true, true); #endif - model.delete_object(size_t(0)); + model.delete_object(size_t(0)); } } - + // TODO: copy less stuff around using pointers m_models = new_models; - + if (m_actions.empty()) m_actions.push_back("export_stl"); } @@ -275,7 +275,7 @@ int CLI::run(int argc, char **argv) for (auto &model : m_models) { TriangleMesh mesh = model.mesh(); mesh.repair(); - + TriangleMeshPtrs meshes = mesh.cut_by_grid(m_config.option("cut_grid")->value); size_t i = 0; for (TriangleMesh* m : meshes) { @@ -286,10 +286,10 @@ int CLI::run(int argc, char **argv) delete m; } } - + // TODO: copy less stuff around using pointers m_models = new_models; - + if (m_actions.empty()) m_actions.push_back("export_stl"); } @@ -303,7 +303,7 @@ int CLI::run(int argc, char **argv) } } } else if (opt_key == "repair") { - // Models are repaired by default. + // Models are repaired by default. //for (auto &model : m_models) // model.repair(); } else { @@ -311,7 +311,7 @@ int CLI::run(int argc, char **argv) return 1; } } - + // loop through action options for (auto const &opt_key : m_actions) { if (opt_key == "help") { @@ -354,14 +354,14 @@ int CLI::run(int argc, char **argv) boost::nowide::cerr << "error: cannot export SLA slices for a SLA configuration" << std::endl; return 1; } - // Make a copy of the model if the current action is not the last action, as the model may be - // modified by the centering and such. - Model model_copy; - bool make_copy = &opt_key != &m_actions.back(); + // Make a copy of the model if the current action is not the last action, as the model may be + // modified by the centering and such. + Model model_copy; + bool make_copy = &opt_key != &m_actions.back(); for (Model &model_in : m_models) { - if (make_copy) - model_copy = model_in; - Model &model = make_copy ? model_copy : model_in; + if (make_copy) + model_copy = model_in; + Model &model = make_copy ? model_copy : model_in; // If all objects have defined instances, their relative positions will be // honored when printing (they will be only centered, unless --dont-arrange // is supplied); if any object has no instances, it will get a default one @@ -381,7 +381,7 @@ int CLI::run(int argc, char **argv) if (! m_config.opt_bool("dont_arrange")) { //FIXME make the min_object_distance configurable. model.arrange_objects(fff_print.config().min_object_distance()); - model.center_instances_around_point(m_config.option("center")->value); + model.center_instances_around_point(m_config.option("center")->value); } if (printer_technology == ptFFF) { for (auto* mo : model.objects) @@ -395,40 +395,40 @@ int CLI::run(int argc, char **argv) } if (print->empty()) boost::nowide::cout << "Nothing to print for " << outfile << " . Either the print is empty or no object is fully inside the print volume." << std::endl; - else + else try { std::string outfile_final; - print->process(); + print->process(); if (printer_technology == ptFFF) { // The outfile is processed by a PlaceholderParser. outfile = fff_print.export_gcode(outfile, nullptr); outfile_final = fff_print.print_statistics().finalize_output_path(outfile); } else { - outfile = sla_print.output_filepath(outfile); + outfile = sla_print.output_filepath(outfile); // We need to finalize the filename beforehand because the export function sets the filename inside the zip metadata outfile_final = sla_print.print_statistics().finalize_output_path(outfile); - sla_print.export_raster(outfile_final); + sla_print.export_raster(outfile_final); } if (outfile != outfile_final && Slic3r::rename_file(outfile, outfile_final) != 0) { - boost::nowide::cerr << "Renaming file " << outfile << " to " << outfile_final << " failed" << std::endl; + boost::nowide::cerr << "Renaming file " << outfile << " to " << outfile_final << " failed" << std::endl; return 1; } boost::nowide::cout << "Slicing result exported to " << outfile << std::endl; } catch (const std::exception &ex) { - boost::nowide::cerr << ex.what() << std::endl; - return 1; + boost::nowide::cerr << ex.what() << std::endl; + return 1; } /* print.center = ! m_config.has("center") && ! m_config.has("align_xy") && ! m_config.opt_bool("dont_arrange"); print.set_model(model); - + // start chronometer typedef std::chrono::high_resolution_clock clock_; typedef std::chrono::duration > second_; std::chrono::time_point t0{ clock_::now() }; - + const std::string outfile = this->output_filepath(model, IO::Gcode); try { print.export_gcode(outfile); @@ -437,7 +437,7 @@ int CLI::run(int argc, char **argv) return 1; } boost::nowide::cout << "G-code exported to " << outfile << std::endl; - + // output some statistics double duration { std::chrono::duration_cast(clock_::now() - t0).count() }; boost::nowide::cout << std::fixed << std::setprecision(0) @@ -454,45 +454,45 @@ int CLI::run(int argc, char **argv) return 1; } } - - if (start_gui) { + + if (start_gui) { #ifdef SLIC3R_GUI // #ifdef USE_WX - GUI::GUI_App *gui = new GUI::GUI_App(); + GUI::GUI_App *gui = new GUI::GUI_App(); // gui->autosave = m_config.opt_string("autosave"); - GUI::GUI_App::SetInstance(gui); - gui->CallAfter([gui, this, &load_configs] { - if (!gui->initialized()) { - return; - } + GUI::GUI_App::SetInstance(gui); + gui->CallAfter([gui, this, &load_configs] { + if (!gui->initialized()) { + return; + } #if 0 - // Load the cummulative config over the currently active profiles. - //FIXME if multiple configs are loaded, only the last one will have an effect. - // We need to decide what to do about loading of separate presets (just print preset, just filament preset etc). - // As of now only the full configs are supported here. - if (!m_print_config.empty()) - gui->mainframe->load_config(m_print_config); + // Load the cummulative config over the currently active profiles. + //FIXME if multiple configs are loaded, only the last one will have an effect. + // We need to decide what to do about loading of separate presets (just print preset, just filament preset etc). + // As of now only the full configs are supported here. + if (!m_print_config.empty()) + gui->mainframe->load_config(m_print_config); #endif - if (! load_configs.empty()) - // Load the last config to give it a name at the UI. The name of the preset may be later - // changed by loading an AMF or 3MF. - //FIXME this is not strictly correct, as one may pass a print/filament/printer profile here instead of a full config. - gui->mainframe->load_config_file(load_configs.back()); - // If loading a 3MF file, the config is loaded from the last one. - if (! m_input_files.empty()) - gui->plater()->load_files(m_input_files, true, true); - if (! m_extra_config.empty()) - gui->mainframe->load_config(m_extra_config); - }); - return wxEntry(argc, argv); + if (! load_configs.empty()) + // Load the last config to give it a name at the UI. The name of the preset may be later + // changed by loading an AMF or 3MF. + //FIXME this is not strictly correct, as one may pass a print/filament/printer profile here instead of a full config. + gui->mainframe->load_config_file(load_configs.back()); + // If loading a 3MF file, the config is loaded from the last one. + if (! m_input_files.empty()) + gui->plater()->load_files(m_input_files, true, true); + if (! m_extra_config.empty()) + gui->mainframe->load_config(m_extra_config); + }); + return wxEntry(argc, argv); #else /* SLIC3R_GUI */ - // No GUI support. Just print out a help. - this->print_help(false); - // If started without a parameter, consider it to be OK, otherwise report an error code (no action etc). - return (argc == 0) ? 0 : 1; + // No GUI support. Just print out a help. + this->print_help(false); + // If started without a parameter, consider it to be OK, otherwise report an error code (no action etc). + return (argc == 0) ? 0 : 1; #endif /* SLIC3R_GUI */ } - + return 0; } @@ -539,18 +539,18 @@ bool CLI::setup(int argc, char **argv) // If any option is unsupported, print usage and abort immediately. t_config_option_keys opt_order; if (! m_config.read_cli(argc, argv, &m_input_files, &opt_order)) { - // Separate error message reported by the CLI parser from the help. - boost::nowide::cerr << std::endl; + // Separate error message reported by the CLI parser from the help. + boost::nowide::cerr << std::endl; this->print_help(); - return false; + return false; + } + // Parse actions and transform options. + for (auto const &opt_key : opt_order) { + if (cli_actions_config_def.has(opt_key)) + m_actions.emplace_back(opt_key); + else if (cli_transform_config_def.has(opt_key)) + m_transforms.emplace_back(opt_key); } - // Parse actions and transform options. - for (auto const &opt_key : opt_order) { - if (cli_actions_config_def.has(opt_key)) - m_actions.emplace_back(opt_key); - else if (cli_transform_config_def.has(opt_key)) - m_transforms.emplace_back(opt_key); - } { const ConfigOptionInt *opt_loglevel = m_config.opt("loglevel"); @@ -563,15 +563,15 @@ bool CLI::setup(int argc, char **argv) for (const std::pair &optdef : *options) m_config.optptr(optdef.first, true); - set_data_dir(m_config.opt_string("datadir")); + set_data_dir(m_config.opt_string("datadir")); - return true; + return true; } -void CLI::print_help(bool include_print_options, PrinterTechnology printer_technology) const +void CLI::print_help(bool include_print_options, PrinterTechnology printer_technology) const { boost::nowide::cout - << SLIC3R_BUILD_ID << " " << "based on Slic3r" + << SLIC3R_BUILD_ID << " " << "based on Slic3r" #ifdef SLIC3R_GUI << " (with GUI support)" #else /* SLIC3R_GUI */ @@ -583,20 +583,20 @@ void CLI::print_help(bool include_print_options, PrinterTechnology printer_techn << std::endl << "Actions:" << std::endl; cli_actions_config_def.print_cli_help(boost::nowide::cout, false); - + boost::nowide::cout << std::endl << "Transform options:" << std::endl; cli_transform_config_def.print_cli_help(boost::nowide::cout, false); - + boost::nowide::cout << std::endl << "Other options:" << std::endl; cli_misc_config_def.print_cli_help(boost::nowide::cout, false); - + if (include_print_options) { boost::nowide::cout << std::endl; - print_config_def.print_cli_help(boost::nowide::cout, true, [printer_technology](const ConfigOptionDef &def) + print_config_def.print_cli_help(boost::nowide::cout, true, [printer_technology](const ConfigOptionDef &def) { return printer_technology == ptAny || def.printer_technology == ptAny || printer_technology == def.printer_technology; }); } else { boost::nowide::cout @@ -613,14 +613,14 @@ bool CLI::export_models(IO::ExportFormat format) switch (format) { case IO::AMF: success = Slic3r::store_amf(path.c_str(), &model, nullptr); break; case IO::OBJ: success = Slic3r::store_obj(path.c_str(), &model); break; - case IO::STL: success = Slic3r::store_stl(path.c_str(), &model, true); break; - case IO::TMF: success = Slic3r::store_3mf(path.c_str(), &model, nullptr); break; + case IO::STL: success = Slic3r::store_stl(path.c_str(), &model, true); break; + case IO::TMF: success = Slic3r::store_3mf(path.c_str(), &model, nullptr); break; default: assert(false); break; } if (success) - std::cout << "File exported to " << path << std::endl; + std::cout << "File exported to " << path << std::endl; else { - std::cerr << "File export to " << path << " failed" << std::endl; + std::cerr << "File export to " << path << " failed" << std::endl; return false; } } @@ -634,12 +634,12 @@ std::string CLI::output_filepath(const Model &model, IO::ExportFormat format) co case IO::AMF: ext = ".zip.amf"; break; case IO::OBJ: ext = ".obj"; break; case IO::STL: ext = ".stl"; break; - case IO::TMF: ext = ".3mf"; break; + case IO::TMF: ext = ".3mf"; break; default: assert(false); break; }; auto proposed_path = boost::filesystem::path(model.propose_export_file_name_and_path(ext)); // use --output when available - std::string cmdline_param = m_config.opt_string("output"); + std::string cmdline_param = m_config.opt_string("output"); if (! cmdline_param.empty()) { // if we were supplied a directory, use it and append our automatically generated filename boost::filesystem::path cmdline_path(cmdline_param); @@ -651,20 +651,20 @@ std::string CLI::output_filepath(const Model &model, IO::ExportFormat format) co return proposed_path.string(); } -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__MINGW32__) extern "C" { - __declspec(dllexport) int __stdcall slic3r_main(int argc, wchar_t **argv) - { - // Convert wchar_t arguments to UTF8. - std::vector argv_narrow; - std::vector argv_ptrs(argc + 1, nullptr); - for (size_t i = 0; i < argc; ++ i) - argv_narrow.emplace_back(boost::nowide::narrow(argv[i])); - for (size_t i = 0; i < argc; ++ i) - argv_ptrs[i] = const_cast(argv_narrow[i].data()); - // Call the UTF8 main. - return CLI().run(argc, argv_ptrs.data()); - } + __declspec(dllexport) int __stdcall slic3r_main(int argc, wchar_t **argv) + { + // Convert wchar_t arguments to UTF8. + std::vector argv_narrow; + std::vector argv_ptrs(argc + 1, nullptr); + for (size_t i = 0; i < argc; ++ i) + argv_narrow.emplace_back(boost::nowide::narrow(argv[i])); + for (size_t i = 0; i < argc; ++ i) + argv_ptrs[i] = const_cast(argv_narrow[i].data()); + // Call the UTF8 main. + return CLI().run(argc, argv_ptrs.data()); + } } #else /* _MSC_VER */ int main(int argc, char **argv) diff --git a/src/PrusaSlicer_app_msvc.cpp b/src/PrusaSlicer_app_msvc.cpp index 95dd4fb07..b3d1e8bb4 100644 --- a/src/PrusaSlicer_app_msvc.cpp +++ b/src/PrusaSlicer_app_msvc.cpp @@ -8,12 +8,12 @@ #include #ifdef SLIC3R_GUI -extern "C" -{ - // Let the NVIDIA and AMD know we want to use their graphics card - // on a dual graphics card system. - __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; - __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; +extern "C" +{ + // Let the NVIDIA and AMD know we want to use their graphics card + // on a dual graphics card system. + __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; + __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; } #endif /* SLIC3R_GUI */ @@ -21,7 +21,7 @@ extern "C" #include #ifdef SLIC3R_GUI - #include + #include #endif /* SLIC3R_GUI */ #include @@ -36,97 +36,97 @@ extern "C" class OpenGLVersionCheck { public: - std::string version; - std::string glsl_version; - std::string vendor; - std::string renderer; + std::string version; + std::string glsl_version; + std::string vendor; + std::string renderer; - HINSTANCE hOpenGL = nullptr; - bool success = false; + HINSTANCE hOpenGL = nullptr; + bool success = false; - bool load_opengl_dll() - { - MSG msg = {0}; - WNDCLASS wc = {0}; - wc.lpfnWndProc = OpenGLVersionCheck::supports_opengl2_wndproc; - wc.hInstance = (HINSTANCE)GetModuleHandle(nullptr); - wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND); - wc.lpszClassName = L"PrusaSlicer_opengl_version_check"; - wc.style = CS_OWNDC; - if (RegisterClass(&wc)) { - HWND hwnd = CreateWindowW(wc.lpszClassName, L"PrusaSlicer_opengl_version_check", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, 0, 0, wc.hInstance, (LPVOID)this); - if (hwnd) { - message_pump_exit = false; - while (GetMessage(&msg, NULL, 0, 0 ) > 0 && ! message_pump_exit) - DispatchMessage(&msg); - } - } - return this->success; - } + bool load_opengl_dll() + { + MSG msg = {0}; + WNDCLASS wc = {0}; + wc.lpfnWndProc = OpenGLVersionCheck::supports_opengl2_wndproc; + wc.hInstance = (HINSTANCE)GetModuleHandle(nullptr); + wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND); + wc.lpszClassName = L"PrusaSlicer_opengl_version_check"; + wc.style = CS_OWNDC; + if (RegisterClass(&wc)) { + HWND hwnd = CreateWindowW(wc.lpszClassName, L"PrusaSlicer_opengl_version_check", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, 0, 0, wc.hInstance, (LPVOID)this); + if (hwnd) { + message_pump_exit = false; + while (GetMessage(&msg, NULL, 0, 0 ) > 0 && ! message_pump_exit) + DispatchMessage(&msg); + } + } + return this->success; + } - void unload_opengl_dll() - { - if (this->hOpenGL) { - BOOL released = FreeLibrary(this->hOpenGL); - if (released) - printf("System OpenGL library released\n"); - else - printf("System OpenGL library NOT released\n"); - this->hOpenGL = nullptr; - } - } + void unload_opengl_dll() + { + if (this->hOpenGL) { + BOOL released = FreeLibrary(this->hOpenGL); + if (released) + printf("System OpenGL library released\n"); + else + printf("System OpenGL library NOT released\n"); + this->hOpenGL = nullptr; + } + } - bool is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const - { - // printf("is_version_greater_or_equal_to, version: %s\n", version.c_str()); - std::vector tokens; - boost::split(tokens, version, boost::is_any_of(" "), boost::token_compress_on); - if (tokens.empty()) - return false; + bool is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const + { + // printf("is_version_greater_or_equal_to, version: %s\n", version.c_str()); + std::vector tokens; + boost::split(tokens, version, boost::is_any_of(" "), boost::token_compress_on); + if (tokens.empty()) + return false; - std::vector numbers; - boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on); + std::vector numbers; + boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on); - unsigned int gl_major = 0; - unsigned int gl_minor = 0; - if (numbers.size() > 0) - gl_major = ::atoi(numbers[0].c_str()); - if (numbers.size() > 1) - gl_minor = ::atoi(numbers[1].c_str()); - // printf("Major: %d, minor: %d\n", gl_major, gl_minor); - if (gl_major < major) - return false; - else if (gl_major > major) - return true; - else - return gl_minor >= minor; - } + unsigned int gl_major = 0; + unsigned int gl_minor = 0; + if (numbers.size() > 0) + gl_major = ::atoi(numbers[0].c_str()); + if (numbers.size() > 1) + gl_minor = ::atoi(numbers[1].c_str()); + // printf("Major: %d, minor: %d\n", gl_major, gl_minor); + if (gl_major < major) + return false; + else if (gl_major > major) + return true; + else + return gl_minor >= minor; + } protected: - static bool message_pump_exit; + static bool message_pump_exit; - void check(HWND hWnd) - { - hOpenGL = LoadLibraryExW(L"opengl32.dll", nullptr, 0); - if (hOpenGL == nullptr) { - printf("Failed loading the system opengl32.dll\n"); - return; - } + void check(HWND hWnd) + { + hOpenGL = LoadLibraryExW(L"opengl32.dll", nullptr, 0); + if (hOpenGL == nullptr) { + printf("Failed loading the system opengl32.dll\n"); + return; + } - typedef HGLRC (WINAPI *Func_wglCreateContext)(HDC); - typedef BOOL (WINAPI *Func_wglMakeCurrent )(HDC, HGLRC); - typedef BOOL (WINAPI *Func_wglDeleteContext)(HGLRC); - typedef GLubyte* (WINAPI *Func_glGetString )(GLenum); + typedef HGLRC (WINAPI *Func_wglCreateContext)(HDC); + typedef BOOL (WINAPI *Func_wglMakeCurrent )(HDC, HGLRC); + typedef BOOL (WINAPI *Func_wglDeleteContext)(HGLRC); + typedef GLubyte* (WINAPI *Func_glGetString )(GLenum); - Func_wglCreateContext wglCreateContext = (Func_wglCreateContext)GetProcAddress(hOpenGL, "wglCreateContext"); - Func_wglMakeCurrent wglMakeCurrent = (Func_wglMakeCurrent) GetProcAddress(hOpenGL, "wglMakeCurrent"); - Func_wglDeleteContext wglDeleteContext = (Func_wglDeleteContext)GetProcAddress(hOpenGL, "wglDeleteContext"); - Func_glGetString glGetString = (Func_glGetString) GetProcAddress(hOpenGL, "glGetString"); + Func_wglCreateContext wglCreateContext = (Func_wglCreateContext)GetProcAddress(hOpenGL, "wglCreateContext"); + Func_wglMakeCurrent wglMakeCurrent = (Func_wglMakeCurrent) GetProcAddress(hOpenGL, "wglMakeCurrent"); + Func_wglDeleteContext wglDeleteContext = (Func_wglDeleteContext)GetProcAddress(hOpenGL, "wglDeleteContext"); + Func_glGetString glGetString = (Func_glGetString) GetProcAddress(hOpenGL, "glGetString"); - if (wglCreateContext == nullptr || wglMakeCurrent == nullptr || wglDeleteContext == nullptr || glGetString == nullptr) { - printf("Failed loading the system opengl32.dll: The library is invalid.\n"); - return; - } + if (wglCreateContext == nullptr || wglMakeCurrent == nullptr || wglDeleteContext == nullptr || glGetString == nullptr) { + printf("Failed loading the system opengl32.dll: The library is invalid.\n"); + return; + } PIXELFORMATDESCRIPTOR pfd = { @@ -149,152 +149,155 @@ protected: }; HDC ourWindowHandleToDeviceContext = ::GetDC(hWnd); - // Gdi32.dll - int letWindowsChooseThisPixelFormat = ::ChoosePixelFormat(ourWindowHandleToDeviceContext, &pfd); - // Gdi32.dll + // Gdi32.dll + int letWindowsChooseThisPixelFormat = ::ChoosePixelFormat(ourWindowHandleToDeviceContext, &pfd); + // Gdi32.dll SetPixelFormat(ourWindowHandleToDeviceContext, letWindowsChooseThisPixelFormat, &pfd); - // Opengl32.dll + // Opengl32.dll HGLRC glcontext = wglCreateContext(ourWindowHandleToDeviceContext); wglMakeCurrent(ourWindowHandleToDeviceContext, glcontext); // Opengl32.dll - const char *data = (const char*)glGetString(GL_VERSION); - if (data != nullptr) - this->version = data; - // printf("check -version: %s\n", version.c_str()); - data = (const char*)glGetString(0x8B8C); // GL_SHADING_LANGUAGE_VERSION - if (data != nullptr) - this->glsl_version = data; - data = (const char*)glGetString(GL_VENDOR); - if (data != nullptr) - this->vendor = data; - data = (const char*)glGetString(GL_RENDERER); - if (data != nullptr) - this->renderer = data; + const char *data = (const char*)glGetString(GL_VERSION); + if (data != nullptr) + this->version = data; + // printf("check -version: %s\n", version.c_str()); + data = (const char*)glGetString(0x8B8C); // GL_SHADING_LANGUAGE_VERSION + if (data != nullptr) + this->glsl_version = data; + data = (const char*)glGetString(GL_VENDOR); + if (data != nullptr) + this->vendor = data; + data = (const char*)glGetString(GL_RENDERER); + if (data != nullptr) + this->renderer = data; // Opengl32.dll wglDeleteContext(glcontext); - ::ReleaseDC(hWnd, ourWindowHandleToDeviceContext); + ::ReleaseDC(hWnd, ourWindowHandleToDeviceContext); this->success = true; - } + } - static LRESULT CALLBACK supports_opengl2_wndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) - { - switch(message) - { - case WM_CREATE: - { - CREATESTRUCT *pCreate = reinterpret_cast(lParam); - OpenGLVersionCheck *ogl_data = reinterpret_cast(pCreate->lpCreateParams); - ogl_data->check(hWnd); - DestroyWindow(hWnd); - return 0; - } - case WM_NCDESTROY: - message_pump_exit = true; - return 0; - default: - return DefWindowProc(hWnd, message, wParam, lParam); - } - } + static LRESULT CALLBACK supports_opengl2_wndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) + { + switch(message) + { + case WM_CREATE: + { + CREATESTRUCT *pCreate = reinterpret_cast(lParam); + OpenGLVersionCheck *ogl_data = reinterpret_cast(pCreate->lpCreateParams); + ogl_data->check(hWnd); + DestroyWindow(hWnd); + return 0; + } + case WM_NCDESTROY: + message_pump_exit = true; + return 0; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + } }; bool OpenGLVersionCheck::message_pump_exit = false; #endif /* SLIC3R_GUI */ extern "C" { - typedef int (__stdcall *Slic3rMainFunc)(int argc, wchar_t **argv); - Slic3rMainFunc slic3r_main = nullptr; + typedef int (__stdcall *Slic3rMainFunc)(int argc, wchar_t **argv); + Slic3rMainFunc slic3r_main = nullptr; } +extern "C" { + #ifdef SLIC3R_WRAPPER_NOCONSOLE int APIENTRY wWinMain(HINSTANCE /* hInstance */, HINSTANCE /* hPrevInstance */, PWSTR /* lpCmdLine */, int /* nCmdShow */) { - int argc; - wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + int argc; + wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); #else int wmain(int argc, wchar_t **argv) { #endif - std::vector argv_extended; - argv_extended.emplace_back(argv[0]); + std::vector argv_extended; + argv_extended.emplace_back(argv[0]); #ifdef SLIC3R_GUI - // Here one may push some additional parameters based on the wrapper type. - bool force_mesa = false; + // Here one may push some additional parameters based on the wrapper type. + bool force_mesa = false; #endif /* SLIC3R_GUI */ - for (int i = 1; i < argc; ++ i) { + for (int i = 1; i < argc; ++ i) { #ifdef SLIC3R_GUI - if (wcscmp(argv[i], L"--sw-renderer") == 0) - force_mesa = true; - else if (wcscmp(argv[i], L"--no-sw-renderer") == 0) - force_mesa = false; + if (wcscmp(argv[i], L"--sw-renderer") == 0) + force_mesa = true; + else if (wcscmp(argv[i], L"--no-sw-renderer") == 0) + force_mesa = false; #endif /* SLIC3R_GUI */ - argv_extended.emplace_back(argv[i]); - } - argv_extended.emplace_back(nullptr); + argv_extended.emplace_back(argv[i]); + } + argv_extended.emplace_back(nullptr); #ifdef SLIC3R_GUI - OpenGLVersionCheck opengl_version_check; - bool load_mesa = - // Forced from the command line. - force_mesa || - // Running over a rempote desktop, and the RemoteFX is not enabled, therefore Windows will only provide SW OpenGL 1.1 context. - // In that case, use Mesa. - ::GetSystemMetrics(SM_REMOTESESSION) || - // Try to load the default OpenGL driver and test its context version. - ! opengl_version_check.load_opengl_dll() || ! opengl_version_check.is_version_greater_or_equal_to(2, 0); + OpenGLVersionCheck opengl_version_check; + bool load_mesa = + // Forced from the command line. + force_mesa || + // Running over a rempote desktop, and the RemoteFX is not enabled, therefore Windows will only provide SW OpenGL 1.1 context. + // In that case, use Mesa. + ::GetSystemMetrics(SM_REMOTESESSION) || + // Try to load the default OpenGL driver and test its context version. + ! opengl_version_check.load_opengl_dll() || ! opengl_version_check.is_version_greater_or_equal_to(2, 0); #endif /* SLIC3R_GUI */ - wchar_t path_to_exe[MAX_PATH + 1] = { 0 }; - ::GetModuleFileNameW(nullptr, path_to_exe, MAX_PATH); - wchar_t drive[_MAX_DRIVE]; - wchar_t dir[_MAX_DIR]; - wchar_t fname[_MAX_FNAME]; - wchar_t ext[_MAX_EXT]; - _wsplitpath(path_to_exe, drive, dir, fname, ext); - _wmakepath(path_to_exe, drive, dir, nullptr, nullptr); + wchar_t path_to_exe[MAX_PATH + 1] = { 0 }; + ::GetModuleFileNameW(nullptr, path_to_exe, MAX_PATH); + wchar_t drive[_MAX_DRIVE]; + wchar_t dir[_MAX_DIR]; + wchar_t fname[_MAX_FNAME]; + wchar_t ext[_MAX_EXT]; + _wsplitpath(path_to_exe, drive, dir, fname, ext); + _wmakepath(path_to_exe, drive, dir, nullptr, nullptr); #ifdef SLIC3R_GUI // https://wiki.qt.io/Cross_compiling_Mesa_for_Windows // http://download.qt.io/development_releases/prebuilt/llvmpipe/windows/ - if (load_mesa) { - opengl_version_check.unload_opengl_dll(); - wchar_t path_to_mesa[MAX_PATH + 1] = { 0 }; - wcscpy(path_to_mesa, path_to_exe); - wcscat(path_to_mesa, L"mesa\\opengl32.dll"); - printf("Loading MESA OpenGL library: %S\n", path_to_mesa); - HINSTANCE hInstance_OpenGL = LoadLibraryExW(path_to_mesa, nullptr, 0); - if (hInstance_OpenGL == nullptr) { - printf("MESA OpenGL library was not loaded\n"); - } else - printf("MESA OpenGL library was loaded sucessfully\n"); - } + if (load_mesa) { + opengl_version_check.unload_opengl_dll(); + wchar_t path_to_mesa[MAX_PATH + 1] = { 0 }; + wcscpy(path_to_mesa, path_to_exe); + wcscat(path_to_mesa, L"mesa\\opengl32.dll"); + printf("Loading MESA OpenGL library: %S\n", path_to_mesa); + HINSTANCE hInstance_OpenGL = LoadLibraryExW(path_to_mesa, nullptr, 0); + if (hInstance_OpenGL == nullptr) { + printf("MESA OpenGL library was not loaded\n"); + } else + printf("MESA OpenGL library was loaded sucessfully\n"); + } #endif /* SLIC3R_GUI */ - wchar_t path_to_slic3r[MAX_PATH + 1] = { 0 }; - wcscpy(path_to_slic3r, path_to_exe); - wcscat(path_to_slic3r, L"PrusaSlicer.dll"); + wchar_t path_to_slic3r[MAX_PATH + 1] = { 0 }; + wcscpy(path_to_slic3r, path_to_exe); + wcscat(path_to_slic3r, L"PrusaSlicer.dll"); // printf("Loading Slic3r library: %S\n", path_to_slic3r); - HINSTANCE hInstance_Slic3r = LoadLibraryExW(path_to_slic3r, nullptr, 0); - if (hInstance_Slic3r == nullptr) { - printf("PrusaSlicer.dll was not loaded\n"); - return -1; - } + HINSTANCE hInstance_Slic3r = LoadLibraryExW(path_to_slic3r, nullptr, 0); + if (hInstance_Slic3r == nullptr) { + printf("PrusaSlicer.dll was not loaded\n"); + return -1; + } - // resolve function address here - slic3r_main = (Slic3rMainFunc)GetProcAddress(hInstance_Slic3r, + // resolve function address here + slic3r_main = (Slic3rMainFunc)GetProcAddress(hInstance_Slic3r, #ifdef _WIN64 - // there is just a single calling conversion, therefore no mangling of the function name. - "slic3r_main" + // there is just a single calling conversion, therefore no mangling of the function name. + "slic3r_main" #else // stdcall calling convention declaration - "_slic3r_main@8" + "_slic3r_main@8" #endif - ); - if (slic3r_main == nullptr) { - printf("could not locate the function slic3r_main in PrusaSlicer.dll\n"); - return -1; - } - // argc minus the trailing nullptr of the argv - return slic3r_main((int)argv_extended.size() - 1, argv_extended.data()); + ); + if (slic3r_main == nullptr) { + printf("could not locate the function slic3r_main in PrusaSlicer.dll\n"); + return -1; + } + // argc minus the trailing nullptr of the argv + return slic3r_main((int)argv_extended.size() - 1, argv_extended.data()); +} } diff --git a/src/avrdude/CMakeLists.txt b/src/avrdude/CMakeLists.txt index 0e9b9e6d4..a1930ad5f 100644 --- a/src/avrdude/CMakeLists.txt +++ b/src/avrdude/CMakeLists.txt @@ -74,6 +74,10 @@ if (MSVC) windows/unistd.cpp windows/getopt.c ) +elseif (MINGW) + set(AVRDUDE_SOURCES ${AVRDUDE_SOURCES} + windows/utf8.c + ) endif() add_executable(avrdude-conf-gen conf-generate.cpp) @@ -98,5 +102,7 @@ target_link_libraries(avrdude-slic3r avrdude) if (WIN32) target_compile_definitions(avrdude PRIVATE WIN32NATIVE=1) - target_include_directories(avrdude SYSTEM PRIVATE windows) # So that sources find the getopt.h windows drop-in + if(MSVC) + target_include_directories(avrdude SYSTEM PRIVATE windows) # So that sources find the getopt.h windows drop-in + endif(MSVC) endif() diff --git a/src/avrdude/lexer.c b/src/avrdude/lexer.c index f2d8adb4b..46d88170f 100644 --- a/src/avrdude/lexer.c +++ b/src/avrdude/lexer.c @@ -30,7 +30,7 @@ /* C99 systems have . Non-C99 systems may or may not. */ -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(_MSC_VER) /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. diff --git a/src/avrdude/main-standalone.cpp b/src/avrdude/main-standalone.cpp index df6d79e13..f7cd6d1d4 100644 --- a/src/avrdude/main-standalone.cpp +++ b/src/avrdude/main-standalone.cpp @@ -38,6 +38,10 @@ struct ArgvUtf8 : std::vector } }; +#endif + +#ifdef _MSC_VER + int wmain(int argc_w, wchar_t *argv_w[]) { ArgvUtf8 argv_utf8(argc_w, argv_w); diff --git a/src/avrdude/windows/unistd.h b/src/avrdude/windows/unistd.h index fe6a8fb87..c88b780bf 100644 --- a/src/avrdude/windows/unistd.h +++ b/src/avrdude/windows/unistd.h @@ -63,7 +63,7 @@ extern "C" { #define STDOUT_FILENO 1 #define STDERR_FILENO 2 -#ifdef _MSC_VER +#if defined(_MSC_VER) && defined(__clang__) #include struct timezone; struct timeval; diff --git a/src/libigl/igl/SortableRow.h b/src/libigl/igl/SortableRow.h index 5f172987b..182bf8134 100644 --- a/src/libigl/igl/SortableRow.h +++ b/src/libigl/igl/SortableRow.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_SORTABLE_ROW_H #define IGL_SORTABLE_ROW_H @@ -14,57 +14,53 @@ namespace igl { - // Templates: - // T should be a matrix that implements .size(), and operator(int i) - template - class SortableRow - { - public: - T data; - public: - SortableRow():data(){}; - SortableRow(const T & data):data(data){}; - bool operator<(const SortableRow & that) const - { - // Get reference so that I can use parenthesis - const SortableRow & THIS = *this; +// Templates: +// T should be a matrix that implements .size(), and operator(int i) +template +class SortableRow +{ +public: + T data; +public: + SortableRow():data(){}; + SortableRow(const T & data):data(data){}; + bool operator<(const SortableRow & that) const + { // Lexicographical - int minc = (THIS.data.size() < that.data.size()? - THIS.data.size() : that.data.size()); + int minc = (this->data.size() < that.data.size()? + this->data.size() : that.data.size()); // loop over columns for(int i = 0;idata(i) == that.data(i)) + { + continue; + } + return this->data(i) < that.data(i); } // All characters the same, comes done to length - return THIS.data.size() & THIS = *this; - if(THIS.data.size() != that.data.size()) + return this->data.size()data.size() != that.data.size()) { - return false; - } - for(int i = 0;idata.size();i++) + { + if(this->data(i) != that.data(i)) + { + return false; + } } return true; - }; - bool operator!=(const SortableRow & that) const - { + }; + bool operator!=(const SortableRow & that) const + { return !(*this == that); - }; - }; + }; +}; } #endif diff --git a/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp b/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp index 06afbd187..56330e15e 100644 --- a/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp +++ b/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp @@ -337,7 +337,15 @@ merge(const TMultiShape& shapes) //#define DISABLE_BOOST_SERIALIZE //#define DISABLE_BOOST_UNSERIALIZE +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4244) +#pragma warning(disable: 4267) +#endif // All other operators and algorithms are implemented with boost #include +#ifdef _MSC_VER +#pragma warning(pop) +#endif #endif // CLIPPER_BACKEND_HPP diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp index ed599d11d..1b7451f8f 100644 --- a/src/libslic3r/Arrange.cpp +++ b/src/libslic3r/Arrange.cpp @@ -133,8 +133,18 @@ protected: PConfig m_pconf; // Placement configuration TBin m_bin; double m_bin_area; + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4244) +#pragma warning(disable: 4267) +#endif SpatIndex m_rtree; // spatial index for the normal (bigger) objects SpatIndex m_smallsrtree; // spatial index for only the smaller items +#ifdef _MSC_VER +#pragma warning(pop) +#endif + double m_norm; // A coefficient to scale distances MultiPolygon m_merged_pile; // The already merged pile (vector of items) Box m_pilebb; // The bounding box of the merged pile. diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 4842b5123..1ebd922e2 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -5,6 +5,10 @@ include(PrecompiledHeader) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libslic3r_version.h.in ${CMAKE_CURRENT_BINARY_DIR}/libslic3r_version.h @ONLY) +if (MINGW) + add_compile_options(-Wa,-mbig-obj) +endif () + add_library(libslic3r STATIC pchheader.cpp pchheader.hpp @@ -70,7 +74,7 @@ add_library(libslic3r STATIC GCode/CoolingBuffer.cpp GCode/CoolingBuffer.hpp GCode/PostProcessor.cpp - GCode/PostProcessor.hpp + GCode/PostProcessor.hpp # GCode/PressureEqualizer.cpp # GCode/PressureEqualizer.hpp GCode/PreviewData.cpp diff --git a/src/libslic3r/GCode/ToolOrdering.hpp b/src/libslic3r/GCode/ToolOrdering.hpp index 538127810..d4006120d 100644 --- a/src/libslic3r/GCode/ToolOrdering.hpp +++ b/src/libslic3r/GCode/ToolOrdering.hpp @@ -102,45 +102,60 @@ private: class ToolOrdering { public: - ToolOrdering() {} + ToolOrdering() {} - // For the use case when each object is printed separately - // (print.config.complete_objects is true). - ToolOrdering(const PrintObject &object, unsigned int first_extruder = (unsigned int)-1, bool prime_multi_material = false); + // For the use case when each object is printed separately + // (print.config.complete_objects is true). + ToolOrdering(const PrintObject &object, unsigned int first_extruder = (unsigned int)-1, bool prime_multi_material = false); - // For the use case when all objects are printed at once. - // (print.config.complete_objects is false). - ToolOrdering(const Print &print, unsigned int first_extruder = (unsigned int)-1, bool prime_multi_material = false); + // For the use case when all objects are printed at once. + // (print.config.complete_objects is false). + ToolOrdering(const Print &print, unsigned int first_extruder = (unsigned int)-1, bool prime_multi_material = false); - void clear() { m_layer_tools.clear(); } + void clear() { m_layer_tools.clear(); } - // Get the first extruder printing, including the extruder priming areas, returns -1 if there is no layer printed. - unsigned int first_extruder() const { return m_first_printing_extruder; } + // Get the first extruder printing, including the extruder priming areas, returns -1 if there is no layer printed. + unsigned int first_extruder() const { return m_first_printing_extruder; } - // Get the first extruder printing the layer_tools, returns -1 if there is no layer printed. - unsigned int last_extruder() const { return m_last_printing_extruder; } + // Get the first extruder printing the layer_tools, returns -1 if there is no layer printed. + unsigned int last_extruder() const { return m_last_printing_extruder; } - // For a multi-material print, the printing extruders are ordered in the order they shall be primed. - const std::vector& all_extruders() const { return m_all_printing_extruders; } + // For a multi-material print, the printing extruders are ordered in the order they shall be primed. + const std::vector& all_extruders() const { return m_all_printing_extruders; } - // Find LayerTools with the closest print_z. - LayerTools& tools_for_layer(coordf_t print_z); - const LayerTools& tools_for_layer(coordf_t print_z) const - { return *const_cast(&const_cast(this)->tools_for_layer(print_z)); } + template static auto tools_for_layer(Self& self, coordf_t print_z) -> decltype (*self.m_layer_tools.begin()) + { + auto it_layer_tools = std::lower_bound(self.m_layer_tools.begin(), self.m_layer_tools.end(), LayerTools(print_z - EPSILON)); + assert(it_layer_tools != self.m_layer_tools.end()); + coordf_t dist_min = std::abs(it_layer_tools->print_z - print_z); + for (++ it_layer_tools; it_layer_tools != self.m_layer_tools.end(); ++it_layer_tools) { + coordf_t d = std::abs(it_layer_tools->print_z - print_z); + if (d >= dist_min) + break; + dist_min = d; + } + -- it_layer_tools; + assert(dist_min < EPSILON); + return *it_layer_tools; + } - const LayerTools& front() const { return m_layer_tools.front(); } - const LayerTools& back() const { return m_layer_tools.back(); } - std::vector::const_iterator begin() const { return m_layer_tools.begin(); } - std::vector::const_iterator end() const { return m_layer_tools.end(); } - bool empty() const { return m_layer_tools.empty(); } - std::vector& layer_tools() { return m_layer_tools; } - bool has_wipe_tower() const { return ! m_layer_tools.empty() && m_first_printing_extruder != (unsigned int)-1 && m_layer_tools.front().wipe_tower_partitions > 0; } + // Find LayerTools with the closest print_z. + LayerTools& tools_for_layer(coordf_t print_z) { return tools_for_layer(*this, print_z); } + const LayerTools& tools_for_layer(coordf_t print_z) const { return tools_for_layer(*this, print_z); } + + const LayerTools& front() const { return m_layer_tools.front(); } + const LayerTools& back() const { return m_layer_tools.back(); } + std::vector::const_iterator begin() const { return m_layer_tools.begin(); } + std::vector::const_iterator end() const { return m_layer_tools.end(); } + bool empty() const { return m_layer_tools.empty(); } + std::vector& layer_tools() { return m_layer_tools; } + bool has_wipe_tower() const { return ! m_layer_tools.empty() && m_first_printing_extruder != (unsigned int)-1 && m_layer_tools.front().wipe_tower_partitions > 0; } private: - void initialize_layers(std::vector &zs); - void collect_extruders(const PrintObject &object); - void reorder_extruders(unsigned int last_extruder_id); - void fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z); + void initialize_layers(std::vector &zs); + void collect_extruders(const PrintObject &object); + void reorder_extruders(unsigned int last_extruder_id); + void fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z); void collect_extruder_statistics(bool prime_multi_material); std::vector m_layer_tools; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 304f6f749..f38ef662d 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -12,7 +12,7 @@ namespace Slic3r { -//! macro used to mark string used at localization, +//! macro used to mark string used at localization, //! return same string #define L(s) (s) #define _(s) Slic3r::I18N::translate(s) @@ -51,7 +51,7 @@ void PrintConfigDef::init_common_params() def->label = L("Bed shape"); def->mode = comAdvanced; def->set_default_value(new ConfigOptionPoints{ Vec2d(0, 0), Vec2d(200, 0), Vec2d(200, 200), Vec2d(0, 200) }); - + def = this->add("bed_custom_texture", coString); def->label = L("Bed custom texture"); def->mode = comAdvanced; @@ -85,8 +85,8 @@ void PrintConfigDef::init_common_params() "The gap closing operation may reduce the final print resolution, therefore it is advisable to keep the value reasonably low."); def->sidetext = L("mm"); def->min = 0; - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionFloat(0.049)); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(0.049)); def = this->add("print_host", coString); def->label = L("Hostname, IP or URL"); @@ -101,7 +101,7 @@ void PrintConfigDef::init_common_params() "the API Key or the password required for authentication."); def->mode = comAdvanced; def->set_default_value(new ConfigOptionString("")); - + def = this->add("printhost_cafile", coString); def->label = L("HTTPS CA File"); def->tooltip = L("Custom CA certificate file can be specified for HTTPS OctoPrint connections, in crt/pem format. " @@ -117,9 +117,9 @@ void PrintConfigDef::init_fff_params() // Maximum extruder temperature, bumped to 1500 to support printing of glass. const int max_temp = 1500; - def = this->add("avoid_crossing_perimeters", coBool); + def = this->add("avoid_crossing_perimeters", coBool); def->label = L("Avoid crossing perimeters"); - def->tooltip = L("Optimize travel moves in order to minimize the crossing of perimeters. " + def->tooltip = L("Optimize travel moves in order to minimize the crossing of perimeters. " "This is mostly useful with Bowden extruders which suffer from oozing. " "This feature slows down both the print and the G-code generation."); def->mode = comExpert; @@ -178,7 +178,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Bridging angle override. If left to zero, the bridging angle will be calculated " "automatically. Otherwise the provided angle will be used for all bridges. " "Use 180° for zero angle."); - def->sidetext = L("°"); + def->sidetext = L("°"); def->min = 0; def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(0.)); @@ -200,9 +200,9 @@ void PrintConfigDef::init_fff_params() "although default settings are usually good and you should experiment " "with cooling (use a fan) before tweaking this."); def->min = 0; - def->max = 2; + def->max = 2; def->mode = comAdvanced; - def->set_default_value(new ConfigOptionFloat(1)); + def->set_default_value(new ConfigOptionFloat(1)); def = this->add("bridge_speed", coFloat); def->label = L("Bridges"); @@ -531,7 +531,7 @@ void PrintConfigDef::init_fff_params() "check filament diameter and your firmware E steps."); def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloats { 1. }); - + def = this->add("extrusion_width", coFloatOrPercent); def->label = L("Default extrusion width"); def->category = L("Extrusion Width"); @@ -677,7 +677,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("This string is edited by RammingDialog and contains ramming specific parameters."); def->mode = comExpert; def->set_default_value(new ConfigOptionStrings { "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0|" - " 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" }); + " 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" }); def = this->add("filament_unload_time", coFloats); def->label = L("Filament unload time"); @@ -743,7 +743,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("money/kg"); def->min = 0; def->set_default_value(new ConfigOptionFloats { 0. }); - + def = this->add("filament_settings_id", coStrings); def->set_default_value(new ConfigOptionStrings { "" }); def->cli = ConfigOptionDef::nocli; @@ -889,7 +889,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = max_temp; def->set_default_value(new ConfigOptionInts { 200 }); - + def = this->add("gap_fill_speed", coFloat); def->label = L("Gap fill"); def->category = L("Speed"); @@ -1072,85 +1072,85 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->set_default_value(new ConfigOptionBool(false)); - def = this->add("silent_mode", coBool); - def->label = L("Supports stealth mode"); - def->tooltip = L("The firmware supports stealth mode"); + def = this->add("silent_mode", coBool); + def->label = L("Supports stealth mode"); + def->tooltip = L("The firmware supports stealth mode"); def->mode = comExpert; - def->set_default_value(new ConfigOptionBool(true)); + def->set_default_value(new ConfigOptionBool(true)); - const int machine_limits_opt_width = 7; - { - struct AxisDefault { - std::string name; - std::vector max_feedrate; - std::vector max_acceleration; - std::vector max_jerk; - }; - std::vector axes { - // name, max_feedrate, max_acceleration, max_jerk - { "x", { 500., 200. }, { 9000., 1000. }, { 10. , 10. } }, - { "y", { 500., 200. }, { 9000., 1000. }, { 10. , 10. } }, - { "z", { 12., 12. }, { 500., 200. }, { 0.2, 0.4 } }, - { "e", { 120., 120. }, { 10000., 5000. }, { 2.5, 2.5 } } - }; - for (const AxisDefault &axis : axes) { - std::string axis_upper = boost::to_upper_copy(axis.name); - // Add the machine feedrate limits for XYZE axes. (M203) - def = this->add("machine_max_feedrate_" + axis.name, coFloats); - def->full_label = (boost::format("Maximum feedrate %1%") % axis_upper).str(); - (void)L("Maximum feedrate X"); - (void)L("Maximum feedrate Y"); - (void)L("Maximum feedrate Z"); - (void)L("Maximum feedrate E"); - def->category = L("Machine limits"); - def->tooltip = (boost::format("Maximum feedrate of the %1% axis") % axis_upper).str(); - (void)L("Maximum feedrate of the X axis"); - (void)L("Maximum feedrate of the Y axis"); - (void)L("Maximum feedrate of the Z axis"); - (void)L("Maximum feedrate of the E axis"); - def->sidetext = L("mm/s"); - def->min = 0; - def->width = machine_limits_opt_width; + const int machine_limits_opt_width = 7; + { + struct AxisDefault { + std::string name; + std::vector max_feedrate; + std::vector max_acceleration; + std::vector max_jerk; + }; + std::vector axes { + // name, max_feedrate, max_acceleration, max_jerk + { "x", { 500., 200. }, { 9000., 1000. }, { 10. , 10. } }, + { "y", { 500., 200. }, { 9000., 1000. }, { 10. , 10. } }, + { "z", { 12., 12. }, { 500., 200. }, { 0.2, 0.4 } }, + { "e", { 120., 120. }, { 10000., 5000. }, { 2.5, 2.5 } } + }; + for (const AxisDefault &axis : axes) { + std::string axis_upper = boost::to_upper_copy(axis.name); + // Add the machine feedrate limits for XYZE axes. (M203) + def = this->add("machine_max_feedrate_" + axis.name, coFloats); + def->full_label = (boost::format("Maximum feedrate %1%") % axis_upper).str(); + (void)L("Maximum feedrate X"); + (void)L("Maximum feedrate Y"); + (void)L("Maximum feedrate Z"); + (void)L("Maximum feedrate E"); + def->category = L("Machine limits"); + def->tooltip = (boost::format("Maximum feedrate of the %1% axis") % axis_upper).str(); + (void)L("Maximum feedrate of the X axis"); + (void)L("Maximum feedrate of the Y axis"); + (void)L("Maximum feedrate of the Z axis"); + (void)L("Maximum feedrate of the E axis"); + def->sidetext = L("mm/s"); + def->min = 0; + def->width = machine_limits_opt_width; def->mode = comAdvanced; - def->set_default_value(new ConfigOptionFloats(axis.max_feedrate)); - // Add the machine acceleration limits for XYZE axes (M201) - def = this->add("machine_max_acceleration_" + axis.name, coFloats); - def->full_label = (boost::format("Maximum acceleration %1%") % axis_upper).str(); - (void)L("Maximum acceleration X"); - (void)L("Maximum acceleration Y"); - (void)L("Maximum acceleration Z"); - (void)L("Maximum acceleration E"); - def->category = L("Machine limits"); - def->tooltip = (boost::format("Maximum acceleration of the %1% axis") % axis_upper).str(); - (void)L("Maximum acceleration of the X axis"); - (void)L("Maximum acceleration of the Y axis"); - (void)L("Maximum acceleration of the Z axis"); - (void)L("Maximum acceleration of the E axis"); - def->sidetext = L("mm/s²"); - def->min = 0; - def->width = machine_limits_opt_width; + def->set_default_value(new ConfigOptionFloats(axis.max_feedrate)); + // Add the machine acceleration limits for XYZE axes (M201) + def = this->add("machine_max_acceleration_" + axis.name, coFloats); + def->full_label = (boost::format("Maximum acceleration %1%") % axis_upper).str(); + (void)L("Maximum acceleration X"); + (void)L("Maximum acceleration Y"); + (void)L("Maximum acceleration Z"); + (void)L("Maximum acceleration E"); + def->category = L("Machine limits"); + def->tooltip = (boost::format("Maximum acceleration of the %1% axis") % axis_upper).str(); + (void)L("Maximum acceleration of the X axis"); + (void)L("Maximum acceleration of the Y axis"); + (void)L("Maximum acceleration of the Z axis"); + (void)L("Maximum acceleration of the E axis"); + def->sidetext = L("mm/s²"); + def->min = 0; + def->width = machine_limits_opt_width; def->mode = comAdvanced; - def->set_default_value(new ConfigOptionFloats(axis.max_acceleration)); - // Add the machine jerk limits for XYZE axes (M205) - def = this->add("machine_max_jerk_" + axis.name, coFloats); - def->full_label = (boost::format("Maximum jerk %1%") % axis_upper).str(); - (void)L("Maximum jerk X"); - (void)L("Maximum jerk Y"); - (void)L("Maximum jerk Z"); - (void)L("Maximum jerk E"); - def->category = L("Machine limits"); - def->tooltip = (boost::format("Maximum jerk of the %1% axis") % axis_upper).str(); - (void)L("Maximum jerk of the X axis"); - (void)L("Maximum jerk of the Y axis"); - (void)L("Maximum jerk of the Z axis"); - (void)L("Maximum jerk of the E axis"); - def->sidetext = L("mm/s"); - def->min = 0; - def->width = machine_limits_opt_width; + def->set_default_value(new ConfigOptionFloats(axis.max_acceleration)); + // Add the machine jerk limits for XYZE axes (M205) + def = this->add("machine_max_jerk_" + axis.name, coFloats); + def->full_label = (boost::format("Maximum jerk %1%") % axis_upper).str(); + (void)L("Maximum jerk X"); + (void)L("Maximum jerk Y"); + (void)L("Maximum jerk Z"); + (void)L("Maximum jerk E"); + def->category = L("Machine limits"); + def->tooltip = (boost::format("Maximum jerk of the %1% axis") % axis_upper).str(); + (void)L("Maximum jerk of the X axis"); + (void)L("Maximum jerk of the Y axis"); + (void)L("Maximum jerk of the Z axis"); + (void)L("Maximum jerk of the E axis"); + def->sidetext = L("mm/s"); + def->min = 0; + def->width = machine_limits_opt_width; def->mode = comAdvanced; - def->set_default_value(new ConfigOptionFloats(axis.max_jerk)); - } - } + def->set_default_value(new ConfigOptionFloats(axis.max_jerk)); + } + } // M205 S... [mm/sec] def = this->add("machine_min_extruding_rate", coFloats); @@ -1159,9 +1159,9 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Minimum feedrate when extruding (M205 S)"); def->sidetext = L("mm/s"); def->min = 0; - def->width = machine_limits_opt_width; + def->width = machine_limits_opt_width; def->mode = comAdvanced; - def->set_default_value(new ConfigOptionFloats{ 0., 0. }); + def->set_default_value(new ConfigOptionFloats{ 0., 0. }); // M205 T... [mm/sec] def = this->add("machine_min_travel_rate", coFloats); @@ -1170,9 +1170,9 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Minimum travel feedrate (M205 T)"); def->sidetext = L("mm/s"); def->min = 0; - def->width = machine_limits_opt_width; + def->width = machine_limits_opt_width; def->mode = comAdvanced; - def->set_default_value(new ConfigOptionFloats{ 0., 0. }); + def->set_default_value(new ConfigOptionFloats{ 0., 0. }); // M204 S... [mm/sec^2] def = this->add("machine_max_acceleration_extruding", coFloats); @@ -1181,7 +1181,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Maximum acceleration when extruding (M204 S)"); def->sidetext = L("mm/s²"); def->min = 0; - def->width = machine_limits_opt_width; + def->width = machine_limits_opt_width; def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloats{ 1500., 1250. }); @@ -1192,7 +1192,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Maximum acceleration when retracting (M204 T)"); def->sidetext = L("mm/s²"); def->min = 0; - def->width = machine_limits_opt_width; + def->width = machine_limits_opt_width; def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloats{ 1500., 1250. }); @@ -1436,9 +1436,9 @@ void PrintConfigDef::init_fff_params() def->gui_flags = "serialized"; def->multiline = true; def->full_width = true; - def->height = 6; + def->height = 6; def->mode = comExpert; - def->set_default_value(new ConfigOptionStrings()); + def->set_default_value(new ConfigOptionStrings()); def = this->add("printer_model", coString); def->label = L("Printer type"); @@ -1470,7 +1470,7 @@ void PrintConfigDef::init_fff_params() def = this->add("print_settings_id", coString); def->set_default_value(new ConfigOptionString("")); def->cli = ConfigOptionDef::nocli; - + def = this->add("printer_settings_id", coString); def->set_default_value(new ConfigOptionString("")); def->cli = ConfigOptionDef::nocli; @@ -1510,7 +1510,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("%"); def->mode = comAdvanced; def->set_default_value(new ConfigOptionPercents { 0. }); - + def = this->add("retract_layer_change", coBools); def->label = L("Retract on layer change"); def->tooltip = L("This flag enforces a retraction whenever a Z move is done."); @@ -1607,7 +1607,7 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back(L("Random")); def->enum_labels.push_back(L("Nearest")); def->enum_labels.push_back(L("Aligned")); - def->enum_labels.push_back(L("Rear")); + def->enum_labels.push_back(L("Rear")); def->mode = comSimple; def->set_default_value(new ConfigOptionEnum(spAligned)); @@ -1678,7 +1678,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->mode = comAdvanced; def->set_default_value(new ConfigOptionInt(1)); - + def = this->add("slowdown_below_layer_time", coInts); def->label = L("Slow down if layer print time is below"); def->tooltip = L("If layer print time is estimated below this number of seconds, print moves " @@ -1774,7 +1774,7 @@ void PrintConfigDef::init_fff_params() def->label = L("Temperature variation"); def->tooltip = L("Temperature difference to be applied when an extruder is not active. " "Enables a full-height \"sacrificial\" skirt on which the nozzles are periodically wiped."); - def->sidetext = "∆°C"; + def->sidetext = "∆°C"; def->min = -max_temp; def->max = max_temp; def->mode = comExpert; @@ -1816,7 +1816,7 @@ void PrintConfigDef::init_fff_params() def->label = L("Single Extruder Multi Material"); def->tooltip = L("The printer multiplexes filaments into a single hot end."); def->mode = comExpert; - def->set_default_value(new ConfigOptionBool(false)); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("single_extruder_multi_material_priming", coBool); def->label = L("Prime all printing extruders"); @@ -1878,8 +1878,8 @@ void PrintConfigDef::init_fff_params() // def->min = 0; def->enum_values.push_back("0"); def->enum_values.push_back("0.2"); - def->enum_labels.push_back(L("0 (soluble)")); - def->enum_labels.push_back(L("0.2 (detachable)")); + def->enum_labels.push_back(L("0 (soluble)")); + def->enum_labels.push_back(L("0.2 (detachable)")); def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(0.2)); @@ -1968,7 +1968,7 @@ void PrintConfigDef::init_fff_params() def->enum_values.push_back("rectilinear"); def->enum_values.push_back("rectilinear-grid"); def->enum_values.push_back("honeycomb"); - def->enum_labels.push_back(L("Rectilinear")); + def->enum_labels.push_back(L("Rectilinear")); def->enum_labels.push_back(L("Rectilinear grid")); def->enum_labels.push_back(L("Honeycomb")); def->mode = comAdvanced; @@ -2030,7 +2030,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = max_temp; def->set_default_value(new ConfigOptionInts { 200 }); - + def = this->add("thin_walls", coBool); def->label = L("Detect thin walls"); def->category = L("Layers and Perimeters"); @@ -2050,7 +2050,7 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionInt(threads > 0 ? threads : 2)); def->cli == ConfigOptionDef::nocli; } - + def = this->add("toolchange_gcode", coString); def->label = L("Tool change G-code"); def->tooltip = L("This custom code is inserted at every extruder change. If you don't leave this empty, you are " @@ -2242,45 +2242,45 @@ void PrintConfigDef::init_fff_params() // Declare retract values for filament profile, overriding the printer's extruder profile. for (const char *opt_key : { - // floats - "retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed", "deretract_speed", "retract_restart_extra", "retract_before_travel", - // bools - "retract_layer_change", "wipe", - // percents - "retract_before_wipe"}) { - auto it_opt = options.find(opt_key); - assert(it_opt != options.end()); - def = this->add_nullable(std::string("filament_") + opt_key, it_opt->second.type); - def->label = it_opt->second.label; - def->full_label = it_opt->second.full_label; - def->tooltip = it_opt->second.tooltip; - def->sidetext = it_opt->second.sidetext; - def->mode = it_opt->second.mode; - switch (def->type) { - case coFloats : def->set_default_value(new ConfigOptionFloatsNullable (static_cast(it_opt->second.default_value.get())->values)); break; - case coPercents : def->set_default_value(new ConfigOptionPercentsNullable(static_cast(it_opt->second.default_value.get())->values)); break; - case coBools : def->set_default_value(new ConfigOptionBoolsNullable (static_cast(it_opt->second.default_value.get())->values)); break; - default: assert(false); - } + // floats + "retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed", "deretract_speed", "retract_restart_extra", "retract_before_travel", + // bools + "retract_layer_change", "wipe", + // percents + "retract_before_wipe"}) { + auto it_opt = options.find(opt_key); + assert(it_opt != options.end()); + def = this->add_nullable(std::string("filament_") + opt_key, it_opt->second.type); + def->label = it_opt->second.label; + def->full_label = it_opt->second.full_label; + def->tooltip = it_opt->second.tooltip; + def->sidetext = it_opt->second.sidetext; + def->mode = it_opt->second.mode; + switch (def->type) { + case coFloats : def->set_default_value(new ConfigOptionFloatsNullable (static_cast(it_opt->second.default_value.get())->values)); break; + case coPercents : def->set_default_value(new ConfigOptionPercentsNullable(static_cast(it_opt->second.default_value.get())->values)); break; + case coBools : def->set_default_value(new ConfigOptionBoolsNullable (static_cast(it_opt->second.default_value.get())->values)); break; + default: assert(false); + } } } void PrintConfigDef::init_extruder_retract_keys() { - m_extruder_retract_keys = { - "deretract_speed", - "retract_before_travel", - "retract_before_wipe", - "retract_layer_change", - "retract_length", - "retract_lift", - "retract_lift_above", - "retract_lift_below", - "retract_restart_extra", - "retract_speed", - "wipe" - }; - assert(std::is_sorted(m_extruder_retract_keys.begin(), m_extruder_retract_keys.end())); + m_extruder_retract_keys = { + "deretract_speed", + "retract_before_travel", + "retract_before_wipe", + "retract_layer_change", + "retract_length", + "retract_lift", + "retract_lift_above", + "retract_lift_below", + "retract_restart_extra", + "retract_speed", + "wipe" + }; + assert(std::is_sorted(m_extruder_retract_keys.begin(), m_extruder_retract_keys.end())); } void PrintConfigDef::init_sla_params() @@ -2374,7 +2374,7 @@ void PrintConfigDef::init_sla_params() def->min = 0; def->mode = comExpert; def->set_default_value(new ConfigOptionFloats( { 1., 1. } )); - + def = this->add("absolute_correction", coFloat); def->label = L("Printer absolute correction"); def->full_label = L("Printer absolute correction"); @@ -2382,7 +2382,7 @@ void PrintConfigDef::init_sla_params() "to the sign of the correction."); def->mode = comExpert; def->set_default_value(new ConfigOptionFloat(0.0)); - + def = this->add("gamma_correction", coFloat); def->label = L("Printer gamma correction"); def->full_label = L("Printer gamma correction"); @@ -2393,7 +2393,7 @@ void PrintConfigDef::init_sla_params() def->min = 0; def->mode = comExpert; def->set_default_value(new ConfigOptionFloat(1.0)); - + // SLA Material settings. def = this->add("initial_layer_height", coFloat); @@ -2560,7 +2560,7 @@ void PrintConfigDef::init_sla_params() def->min = 0; def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(1.0)); - + def = this->add("support_base_safety_distance", coFloat); def->label = L("Support base safety distance"); def->category = L("Supports"); @@ -2694,7 +2694,7 @@ void PrintConfigDef::init_sla_params() def->max = 90; def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(45.0)); - + def = this->add("pad_object_gap", coFloat); def->label = L("Pad object gap"); def->category = L("Pad"); @@ -2705,7 +2705,7 @@ void PrintConfigDef::init_sla_params() def->max = 10; def->mode = comExpert; def->set_default_value(new ConfigOptionFloat(1)); - + def = this->add("pad_object_connector_stride", coFloat); def->label = L("Pad object connector stride"); def->category = L("Pad"); @@ -2715,7 +2715,7 @@ void PrintConfigDef::init_sla_params() def->min = 0; def->mode = comExpert; def->set_default_value(new ConfigOptionFloat(10)); - + def = this->add("pad_object_connector_width", coFloat); def->label = L("Pad object connector width"); def->category = L("Pad"); @@ -2725,7 +2725,7 @@ void PrintConfigDef::init_sla_params() def->min = 0; def->mode = comExpert; def->set_default_value(new ConfigOptionFloat(0.5)); - + def = this->add("pad_object_connector_penetration", coFloat); def->label = L("Pad object connector penetration"); def->category = L("Pad"); @@ -2746,7 +2746,7 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va if (opt_key == "bottom_layer_speed") opt_key = "first_layer_speed"; try { float v = boost::lexical_cast(value); - if (v != 0) + if (v != 0) value = boost::lexical_cast(v*100) + "%"; } catch (boost::bad_lexical_cast &) { value = "0"; @@ -2786,14 +2786,14 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va } else if (opt_key == "octoprint_apikey") { opt_key = "printhost_apikey"; } - + // Ignore the following obsolete configuration keys: static std::set ignore = { "duplicate_x", "duplicate_y", "gcode_arcs", "multiply_x", "multiply_y", - "support_material_tool", "acceleration", "adjust_overhang_flow", + "support_material_tool", "acceleration", "adjust_overhang_flow", "standby_temperature", "scale", "rotate", "duplicate", "duplicate_grid", - "start_perimeters_at_concave_points", "start_perimeters_at_non_overhang", "randomize_start", - "seal_position", "vibration_limit", "bed_size", + "start_perimeters_at_concave_points", "start_perimeters_at_non_overhang", "randomize_start", + "seal_position", "vibration_limit", "bed_size", "print_center", "g0", "threads", "pressure_advance", "wipe_tower_per_color_wipe" #ifndef HAS_PRESSURE_EQUALIZER , "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative" @@ -2804,7 +2804,7 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va opt_key = ""; return; } - + if (! print_config_def.has(opt_key)) { opt_key = ""; return; @@ -2844,10 +2844,10 @@ void DynamicPrintConfig::normalize() // this->option("support_material_interface_extruder", true)->setInt(extruder); } } - + if (!this->has("solid_infill_extruder") && this->has("infill_extruder")) this->option("solid_infill_extruder", true)->setInt(this->option("infill_extruder")->getInt()); - + if (this->has("spiral_vase") && this->opt("spiral_vase", true)->value) { { // this should be actually done only on the spiral layers instead of all @@ -2865,8 +2865,8 @@ void DynamicPrintConfig::normalize() std::string DynamicPrintConfig::validate() { // Full print config is initialized from the defaults. - const ConfigOption *opt = this->option("printer_technology", false); - auto printer_technology = (opt == nullptr) ? ptFFF : static_cast(dynamic_cast(opt)->value); + const ConfigOption *opt = this->option("printer_technology", false); + auto printer_technology = (opt == nullptr) ? ptFFF : static_cast(dynamic_cast(opt)->value); switch (printer_technology) { case ptFFF: { @@ -2890,7 +2890,7 @@ double PrintConfig::min_object_distance(const ConfigBase *config) { double extruder_clearance_radius = config->option("extruder_clearance_radius")->getFloat(); double duplicate_distance = config->option("duplicate_distance")->getFloat(); - + // min object distance is max(duplicate_distance, clearance_radius) return (config->option("complete_objects")->getBool() && extruder_clearance_radius > duplicate_distance) ? extruder_clearance_radius @@ -2919,7 +2919,7 @@ std::string FullPrintConfig::validate() for (double nd : this->nozzle_diameter.values) if (nd < 0.005) return "Invalid value for --nozzle-diameter"; - + // --perimeters if (this->perimeters.value < 0) return "Invalid value for --perimeters"; @@ -2929,8 +2929,8 @@ std::string FullPrintConfig::validate() return "Invalid value for --top-solid-layers"; if (this->bottom_solid_layers < 0) return "Invalid value for --bottom-solid-layers"; - - if (this->use_firmware_retraction.value && + + if (this->use_firmware_retraction.value && this->gcode_flavor.value != gcfSmoothie && this->gcode_flavor.value != gcfRepRap && this->gcode_flavor.value != gcfMarlin && @@ -2942,15 +2942,15 @@ std::string FullPrintConfig::validate() for (unsigned char wipe : this->wipe.values) if (wipe) return "--use-firmware-retraction is not compatible with --wipe"; - + // --gcode-flavor if (! print_config_def.get("gcode_flavor")->has_enum_value(this->gcode_flavor.serialize())) return "Invalid value for --gcode-flavor"; - + // --fill-pattern if (! print_config_def.get("fill_pattern")->has_enum_value(this->fill_pattern.serialize())) return "Invalid value for --fill-pattern"; - + // --top-fill-pattern if (! print_config_def.get("top_fill_pattern")->has_enum_value(this->top_fill_pattern.serialize())) return "Invalid value for --top-fill-pattern"; @@ -2963,7 +2963,7 @@ std::string FullPrintConfig::validate() if (fabs(this->fill_density.value - 100.) < EPSILON && ! print_config_def.get("top_fill_pattern")->has_enum_value(this->fill_pattern.serialize())) return "The selected fill pattern is not supposed to work at 100% density"; - + // --infill-every-layers if (this->infill_every_layers < 1) return "Invalid value for --infill-every-layers"; @@ -2971,11 +2971,11 @@ std::string FullPrintConfig::validate() // --skirt-height if (this->skirt_height < -1) // -1 means as tall as the object return "Invalid value for --skirt-height"; - + // --bridge-flow-ratio if (this->bridge_flow_ratio <= 0) return "Invalid value for --bridge-flow-ratio"; - + // extruder clearance if (this->extruder_clearance_radius <= 0) return "Invalid value for --extruder-clearance-radius"; @@ -3007,7 +3007,7 @@ std::string FullPrintConfig::validate() if (this->support_material || this->support_material_enforce_layers > 0) return "Spiral vase mode is not compatible with support material"; } - + // extrusion widths { double max_nozzle_diameter = 0.; @@ -3064,7 +3064,7 @@ std::string FullPrintConfig::validate() if (out_of_range) return std::string("Value out of range: " + opt_key); } - + // The configuration is valid. return ""; } @@ -3087,20 +3087,20 @@ StaticPrintConfig::StaticCache SLAFullPrint CLIActionsConfigDef::CLIActionsConfigDef() { ConfigOptionDef* def; - + // Actions: def = this->add("export_obj", coBool); def->label = L("Export OBJ"); def->tooltip = L("Export the model(s) as OBJ."); def->set_default_value(new ConfigOptionBool(false)); - + /* def = this->add("export_svg", coBool); def->label = L("Export SVG"); def->tooltip = L("Slice the model and export solid slices as SVG."); def->set_default_value(new ConfigOptionBool(false)); */ - + def = this->add("export_sla", coBool); def->label = L("Export SLA"); def->tooltip = L("Slice the model and export SLA printing layers as PNG."); @@ -3149,12 +3149,12 @@ CLIActionsConfigDef::CLIActionsConfigDef() def->label = L("Help (SLA options)"); def->tooltip = L("Show the full list of SLA print configuration options."); def->set_default_value(new ConfigOptionBool(false)); - + def = this->add("info", coBool); def->label = L("Output Model Info"); def->tooltip = L("Write information about the model to the console."); def->set_default_value(new ConfigOptionBool(false)); - + def = this->add("save", coString); def->label = L("Save config file"); def->tooltip = L("Save configuration to the specified file."); @@ -3164,35 +3164,35 @@ CLIActionsConfigDef::CLIActionsConfigDef() CLITransformConfigDef::CLITransformConfigDef() { ConfigOptionDef* def; - + // Transform options: def = this->add("align_xy", coPoint); def->label = L("Align XY"); def->tooltip = L("Align the model to the given point."); def->set_default_value(new ConfigOptionPoint(Vec2d(100,100))); - + def = this->add("cut", coFloat); def->label = L("Cut"); def->tooltip = L("Cut model at the given Z."); def->set_default_value(new ConfigOptionFloat(0)); - + /* def = this->add("cut_grid", coFloat); def->label = L("Cut"); def->tooltip = L("Cut model in the XY plane into tiles of the specified max size."); def->set_default_value(new ConfigOptionPoint()); - + def = this->add("cut_x", coFloat); def->label = L("Cut"); def->tooltip = L("Cut model at the given X."); def->set_default_value(new ConfigOptionFloat(0)); - + def = this->add("cut_y", coFloat); def->label = L("Cut"); def->tooltip = L("Cut model at the given Y."); def->set_default_value(new ConfigOptionFloat(0)); */ - + def = this->add("center", coPoint); def->label = L("Center"); def->tooltip = L("Center the print around the given center."); @@ -3201,12 +3201,12 @@ CLITransformConfigDef::CLITransformConfigDef() def = this->add("dont_arrange", coBool); def->label = L("Don't arrange"); def->tooltip = L("Do not rearrange the given models before merging and keep their original XY coordinates."); - + def = this->add("duplicate", coInt); def->label = L("Duplicate"); def->tooltip =L("Multiply copies by this factor."); def->min = 1; - + def = this->add("duplicate_grid", coPoint); def->label = L("Duplicate by grid"); def->tooltip = L("Multiply copies by creating a grid."); @@ -3219,22 +3219,22 @@ CLITransformConfigDef::CLITransformConfigDef() def = this->add("repair", coBool); def->label = L("Repair"); def->tooltip = L("Try to repair any non-manifold meshes (this option is implicitly added whenever we need to slice the model to perform the requested action)."); - + def = this->add("rotate", coFloat); def->label = L("Rotate"); def->tooltip = L("Rotation angle around the Z axis in degrees."); def->set_default_value(new ConfigOptionFloat(0)); - + def = this->add("rotate_x", coFloat); def->label = L("Rotate around X"); def->tooltip = L("Rotation angle around the X axis in degrees."); def->set_default_value(new ConfigOptionFloat(0)); - + def = this->add("rotate_y", coFloat); def->label = L("Rotate around Y"); def->tooltip = L("Rotation angle around the Y axis in degrees."); def->set_default_value(new ConfigOptionFloat(0)); - + def = this->add("scale", coFloatOrPercent); def->label = L("Scale"); def->tooltip = L("Scaling factor or percentage."); @@ -3243,7 +3243,7 @@ CLITransformConfigDef::CLITransformConfigDef() def = this->add("split", coBool); def->label = L("Split"); def->tooltip = L("Detect unconnected parts in the given model(s) and split them into separate objects."); - + def = this->add("scale_to_fit", coPoint3); def->label = L("Scale to Fit"); def->tooltip = L("Scale to fit the given volume."); @@ -3253,26 +3253,26 @@ CLITransformConfigDef::CLITransformConfigDef() CLIMiscConfigDef::CLIMiscConfigDef() { ConfigOptionDef* def; - + def = this->add("ignore_nonexistent_config", coBool); def->label = L("Ignore non-existent config files"); def->tooltip = L("Do not fail if a file supplied to --load does not exist."); - + def = this->add("load", coStrings); def->label = L("Load config file"); def->tooltip = L("Load configuration from the specified file. It can be used more than once to load options from multiple files."); - + def = this->add("output", coString); def->label = L("Output File"); def->tooltip = L("The file where the output will be written (if not specified, it will be based on the input file)."); def->cli = "output|o"; -/* +/* def = this->add("autosave", coString); def->label = L("Autosave"); def->tooltip = L("Automatically export current configuration to the specified file."); */ - + def = this->add("datadir", coString); def->label = L("Data directory"); def->tooltip = L("Load and store settings at the given directory. This is useful for maintaining different profiles or including configurations from a network storage."); @@ -3282,7 +3282,7 @@ CLIMiscConfigDef::CLIMiscConfigDef() def->tooltip = L("Messages with severity lower or eqal to the loglevel will be printed out. 0:trace, 1:debug, 2:info, 3:warning, 4:error, 5:fatal"); def->min = 0; -#if defined(_MSC_VER) && defined(SLIC3R_GUI) +#if (defined(_MSC_VER) || defined(__MINGW32__)) && defined(SLIC3R_GUI) def = this->add("sw_renderer", coBool); def->label = L("Render with a software renderer"); def->tooltip = L("Render with a software renderer. The bundled MESA software renderer is loaded instead of the default OpenGL driver."); @@ -3298,15 +3298,15 @@ DynamicPrintAndCLIConfig::PrintAndCLIConfigDef DynamicPrintAndCLIConfig::s_def; void DynamicPrintAndCLIConfig::handle_legacy(t_config_option_key &opt_key, std::string &value) const { - if (cli_actions_config_def .options.find(opt_key) == cli_actions_config_def .options.end() && - cli_transform_config_def.options.find(opt_key) == cli_transform_config_def.options.end() && - cli_misc_config_def .options.find(opt_key) == cli_misc_config_def .options.end()) { - PrintConfigDef::handle_legacy(opt_key, value); - } + if (cli_actions_config_def .options.find(opt_key) == cli_actions_config_def .options.end() && + cli_transform_config_def.options.find(opt_key) == cli_transform_config_def.options.end() && + cli_misc_config_def .options.find(opt_key) == cli_misc_config_def .options.end()) { + PrintConfigDef::handle_legacy(opt_key, value); + } } } #include CEREAL_REGISTER_TYPE(Slic3r::DynamicPrintConfig) -CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::DynamicConfig, Slic3r::DynamicPrintConfig) +CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::DynamicConfig, Slic3r::DynamicPrintConfig) diff --git a/src/libslic3r/SLA/SLAAutoSupports.cpp b/src/libslic3r/SLA/SLAAutoSupports.cpp index 78efd0806..36378df39 100644 --- a/src/libslic3r/SLA/SLAAutoSupports.cpp +++ b/src/libslic3r/SLA/SLAAutoSupports.cpp @@ -1,5 +1,5 @@ -#include "igl/random_points_on_mesh.h" -#include "igl/AABB.h" +//#include "igl/random_points_on_mesh.h" +//#include "igl/AABB.h" #include @@ -101,7 +101,7 @@ static std::vector make_layers( std::vector layers; layers.reserve(slices.size()); for (size_t i = 0; i < slices.size(); ++ i) - layers.emplace_back(i, heights[i]); + layers.emplace_back(i, heights[i]); // FIXME: calculate actual pixel area from printer config: //const float pixel_area = pow(wxGetApp().preset_bundle->project_config.option("display_width") / wxGetApp().preset_bundle->project_config.option("display_pixels_x"), 2.f); // @@ -114,47 +114,47 @@ static std::vector make_layers( if ((layer_id % 8) == 0) // Don't call the following function too often as it flushes CPU write caches due to synchronization primitves. throw_on_cancel(); - SLAAutoSupports::MyLayer &layer = layers[layer_id]; + SLAAutoSupports::MyLayer &layer = layers[layer_id]; const ExPolygons &islands = slices[layer_id]; //FIXME WTF? const float height = (layer_id>2 ? heights[layer_id-3] : heights[0]-(heights[1]-heights[0])); - layer.islands.reserve(islands.size()); + layer.islands.reserve(islands.size()); for (const ExPolygon &island : islands) { float area = float(island.area() * SCALING_FACTOR * SCALING_FACTOR); if (area >= pixel_area) //FIXME this is not a correct centroid of a polygon with holes. - layer.islands.emplace_back(layer, island, get_extents(island.contour), Slic3r::unscale(island.contour.centroid()).cast(), area, height); + layer.islands.emplace_back(layer, island, get_extents(island.contour), Slic3r::unscale(island.contour.centroid()).cast(), area, height); } } }); - // Calculate overlap of successive layers. Link overlapping islands. - tbb::parallel_for(tbb::blocked_range(1, layers.size(), 8), - [&layers, &heights, throw_on_cancel](const tbb::blocked_range& range) { - for (size_t layer_id = range.begin(); layer_id < range.end(); ++layer_id) { - if ((layer_id % 2) == 0) - // Don't call the following function too often as it flushes CPU write caches due to synchronization primitves. - throw_on_cancel(); - SLAAutoSupports::MyLayer &layer_above = layers[layer_id]; - SLAAutoSupports::MyLayer &layer_below = layers[layer_id - 1]; + // Calculate overlap of successive layers. Link overlapping islands. + tbb::parallel_for(tbb::blocked_range(1, layers.size(), 8), + [&layers, &heights, throw_on_cancel](const tbb::blocked_range& range) { + for (size_t layer_id = range.begin(); layer_id < range.end(); ++layer_id) { + if ((layer_id % 2) == 0) + // Don't call the following function too often as it flushes CPU write caches due to synchronization primitves. + throw_on_cancel(); + SLAAutoSupports::MyLayer &layer_above = layers[layer_id]; + SLAAutoSupports::MyLayer &layer_below = layers[layer_id - 1]; //FIXME WTF? const float layer_height = (layer_id!=0 ? heights[layer_id]-heights[layer_id-1] : heights[0]); const float safe_angle = 5.f * (float(M_PI)/180.f); // smaller number - less supports const float between_layers_offset = float(scale_(layer_height / std::tan(safe_angle))); const float slope_angle = 75.f * (float(M_PI)/180.f); // smaller number - less supports const float slope_offset = float(scale_(layer_height / std::tan(slope_angle))); - //FIXME This has a quadratic time complexity, it will be excessively slow for many tiny islands. - for (SLAAutoSupports::Structure &top : layer_above.islands) { - for (SLAAutoSupports::Structure &bottom : layer_below.islands) { + //FIXME This has a quadratic time complexity, it will be excessively slow for many tiny islands. + for (SLAAutoSupports::Structure &top : layer_above.islands) { + for (SLAAutoSupports::Structure &bottom : layer_below.islands) { float overlap_area = top.overlap_area(bottom); if (overlap_area > 0) { - top.islands_below.emplace_back(&bottom, overlap_area); + top.islands_below.emplace_back(&bottom, overlap_area); bottom.islands_above.emplace_back(&top, overlap_area); } } if (! top.islands_below.empty()) { Polygons top_polygons = to_polygons(*top.polygon); - Polygons bottom_polygons = top.polygons_below(); + Polygons bottom_polygons = top.polygons_below(); top.overhangs = diff_ex(top_polygons, bottom_polygons); if (! top.overhangs.empty()) { top.overhangs_area = 0.f; @@ -164,21 +164,21 @@ static std::vector make_layers( expolys_with_areas.emplace_back(&ex, area); top.overhangs_area += area; } - std::sort(expolys_with_areas.begin(), expolys_with_areas.end(), + std::sort(expolys_with_areas.begin(), expolys_with_areas.end(), [](const std::pair &p1, const std::pair &p2) { return p1.second > p2.second; }); ExPolygons overhangs_sorted; for (auto &p : expolys_with_areas) overhangs_sorted.emplace_back(std::move(*p.first)); - top.overhangs = std::move(overhangs_sorted); + top.overhangs = std::move(overhangs_sorted); top.overhangs_area *= float(SCALING_FACTOR * SCALING_FACTOR); top.overhangs_slopes = diff_ex(top_polygons, offset(bottom_polygons, slope_offset)); top.dangling_areas = diff_ex(top_polygons, offset(bottom_polygons, between_layers_offset)); } } - } - } - }); + } + } + }); return layers; } @@ -207,14 +207,14 @@ void SLAAutoSupports::process(const std::vector& slices, const std:: support_force_bottom[i] = layer_bottom->islands[i].supports_force_total(); } for (Structure &top : layer_top->islands) - for (Structure::Link &bottom_link : top.islands_below) { + for (Structure::Link &bottom_link : top.islands_below) { Structure &bottom = *bottom_link.island; //float centroids_dist = (bottom.centroid - top.centroid).norm(); // Penalization resulting from centroid offset: // bottom.supports_force *= std::min(1.f, 1.f - std::min(1.f, (1600.f * layer_height) * centroids_dist * centroids_dist / bottom.area)); float &support_force = support_force_bottom[&bottom - layer_bottom->islands.data()]; //FIXME this condition does not reflect a bifurcation into a one large island and one tiny island well, it incorrectly resets the support force to zero. -// One should rather work with the overlap area vs overhang area. +// One should rather work with the overlap area vs overhang area. // support_force *= std::min(1.f, 1.f - std::min(1.f, 0.1f * centroids_dist * centroids_dist / bottom.area)); // Penalization resulting from increasing polygon area: support_force *= std::min(1.f, 20.f * bottom.area / top.area); @@ -224,10 +224,10 @@ void SLAAutoSupports::process(const std::vector& slices, const std:: for (Structure &below : layer_bottom->islands) { float below_support_force = support_force_bottom[&below - layer_bottom->islands.data()]; float above_overlap_area = 0.f; - for (Structure::Link &above_link : below.islands_above) - above_overlap_area += above_link.overlap_area; - for (Structure::Link &above_link : below.islands_above) - above_link.island->supports_force_inherited += below_support_force * above_link.overlap_area / above_overlap_area; + for (Structure::Link &above_link : below.islands_above) + above_overlap_area += above_link.overlap_area; + for (Structure::Link &above_link : below.islands_above) + above_link.island->supports_force_inherited += below_support_force * above_link.overlap_area / above_overlap_area; } } // Now iterate over all polygons and append new points if needed. @@ -266,7 +266,7 @@ void SLAAutoSupports::process(const std::vector& slices, const std:: } std::vector sample_expolygon(const ExPolygon &expoly, float samples_per_mm2, std::mt19937 &rng) -{ +{ // Triangulate the polygon with holes into triplets of 3D points. std::vector triangles = Slic3r::triangulate_expolygon_2f(expoly); @@ -347,7 +347,7 @@ static inline std::vector poisson_disk_from_samples(const std::vector(); raw_samples_sorted.emplace_back(sample); } - std::sort(raw_samples_sorted.begin(), raw_samples_sorted.end(), [](const RawSample &lhs, const RawSample &rhs) + std::sort(raw_samples_sorted.begin(), raw_samples_sorted.end(), [](const RawSample &lhs, const RawSample &rhs) { return lhs.cell_id.x() < rhs.cell_id.x() || (lhs.cell_id.x() == rhs.cell_id.x() && lhs.cell_id.y() < rhs.cell_id.y()); }); struct PoissonDiskGridEntry { @@ -464,10 +464,10 @@ void SLAAutoSupports::uniformly_cover(const ExPolygons& islands, Structure& stru //FIXME share the random generator. The random generator may be not so cheap to initialize, also we don't want the random generator to be restarted for each polygon. std::random_device rd; std::mt19937 rng(rd()); - std::vector raw_samples = sample_expolygon_with_boundary(islands, samples_per_mm2, 5.f / poisson_radius, rng); + std::vector raw_samples = sample_expolygon_with_boundary(islands, samples_per_mm2, 5.f / poisson_radius, rng); std::vector poisson_samples; for (size_t iter = 0; iter < 4; ++ iter) { - poisson_samples = poisson_disk_from_samples(raw_samples, poisson_radius, + poisson_samples = poisson_disk_from_samples(raw_samples, poisson_radius, [&structure, &grid3d, min_spacing](const Vec2f &pos) { return grid3d.collides_with(pos, &structure, min_spacing); }); @@ -481,21 +481,21 @@ void SLAAutoSupports::uniformly_cover(const ExPolygons& islands, Structure& stru } #ifdef SLA_AUTOSUPPORTS_DEBUG - { - static int irun = 0; - Slic3r::SVG svg(debug_out_path("SLA_supports-uniformly_cover-%d.svg", irun ++), get_extents(islands)); + { + static int irun = 0; + Slic3r::SVG svg(debug_out_path("SLA_supports-uniformly_cover-%d.svg", irun ++), get_extents(islands)); for (const ExPolygon &island : islands) svg.draw(island); - for (const Vec2f &pt : raw_samples) - svg.draw(Point(scale_(pt.x()), scale_(pt.y())), "red"); - for (const Vec2f &pt : poisson_samples) - svg.draw(Point(scale_(pt.x()), scale_(pt.y())), "blue"); - } + for (const Vec2f &pt : raw_samples) + svg.draw(Point(scale_(pt.x()), scale_(pt.y())), "red"); + for (const Vec2f &pt : poisson_samples) + svg.draw(Point(scale_(pt.x()), scale_(pt.y())), "blue"); + } #endif /* NDEBUG */ // assert(! poisson_samples.empty()); if (poisson_samples_target < poisson_samples.size()) { - std::shuffle(poisson_samples.begin(), poisson_samples.end(), rng); + std::shuffle(poisson_samples.begin(), poisson_samples.end(), rng); poisson_samples.erase(poisson_samples.begin() + poisson_samples_target, poisson_samples.end()); } for (const Vec2f &pt : poisson_samples) { diff --git a/src/libslic3r/SLA/SLASupportTree.cpp b/src/libslic3r/SLA/SLASupportTree.cpp index 6f4ac6c21..5e4820988 100644 --- a/src/libslic3r/SLA/SLASupportTree.cpp +++ b/src/libslic3r/SLA/SLASupportTree.cpp @@ -85,7 +85,7 @@ using Portion = std::tuple; // Set this to true to enable full parallelism in this module. // Only the well tested parts will be concurrent if this is set to false. -const constexpr bool USE_FULL_CONCURRENCY = false; +const constexpr bool USE_FULL_CONCURRENCY = true; template struct _ccr {}; @@ -580,13 +580,13 @@ struct CompactBridge { double fa = 2*PI/steps; auto upperball = sphere(r, Portion{PI / 2 - fa, PI}, fa); for(auto& p : upperball.points) p += startp; - + if(endball) { auto lowerball = sphere(r, Portion{0, PI/2 + 2*fa}, fa); for(auto& p : lowerball.points) p += endp; mesh.merge(lowerball); } - + mesh.merge(upperball); } }; @@ -604,15 +604,15 @@ struct Pad { double ground_level, const PoolConfig& pcfg) : cfg(pcfg), - zlevel(ground_level + + zlevel(ground_level + sla::get_pad_fullheight(pcfg) - sla::get_pad_elevation(pcfg)) { Polygons basep; auto &thr = cfg.throw_on_cancel; - + thr(); - + // Get a sample for the pad from the support mesh { ExPolygons platetmp; @@ -626,20 +626,20 @@ struct Pad { for (const ExPolygon &bp : platetmp) basep.emplace_back(std::move(bp.contour)); } - + if(pcfg.embed_object) { - + // If the zero elevation mode is ON, we need to process the model // base silhouette. Create the offsetted version and punch the // breaksticks across its perimeter. - + ExPolygons modelbase_offs = modelbase; - + if (pcfg.embed_object.object_gap_mm > 0.0) modelbase_offs = offset_ex(modelbase_offs, float(scaled(pcfg.embed_object.object_gap_mm))); - + // Create a spatial index of the support silhouette polygons. // This will be used to check for intersections with the model // silhouette polygons. If there is no intersection, then a certain @@ -653,35 +653,35 @@ struct Pad { bindex.insert(bb, idx++); } } - + ExPolygons concaveh = offset_ex( concave_hull(basep, pcfg.max_merge_distance_mm, thr), scaled(pcfg.min_wall_thickness_mm)); - + // Punching the breaksticks across the offsetted polygon perimeters auto pad_stickholes = reserve_vector(modelbase.size()); for(auto& poly : modelbase_offs) { - + bool overlap = false; for (const ExPolygon &p : concaveh) overlap = overlap || poly.overlaps(p); - + auto bb = poly.contour.bounding_box(); bb.offset(scaled(pcfg.min_wall_thickness_mm)); - + std::vector qres = bindex.query(bb, BoxIndex::qtIntersects); - + if (!qres.empty() || overlap) { - + // The model silhouette polygon 'poly' HAS an intersection // with the support silhouettes. Include this polygon // in the pad holes with the breaksticks and merge the // original (offsetted) version with the rest of the pad // base plate. - + basep.emplace_back(poly.contour); - + // The holes of 'poly' will become positive parts of the // pad, so they has to be checked for intersections as well // and erased if there is no intersection with the supports @@ -693,7 +693,7 @@ struct Pad { else ++it; } - + // Punch the breaksticks sla::breakstick_holes( poly, @@ -701,11 +701,11 @@ struct Pad { pcfg.embed_object.stick_stride_mm, pcfg.embed_object.stick_width_mm, pcfg.embed_object.stick_penetration_mm); - + pad_stickholes.emplace_back(poly); } } - + create_base_pool(basep, tmesh, pad_stickholes, cfg); } else { for (const ExPolygon &bp : modelbase) basep.emplace_back(bp.contour); @@ -775,78 +775,78 @@ class SLASupportTree::Impl { // For heads it is beneficial to use the same IDs as for the support points. std::vector m_heads; std::vector m_head_indices; - + std::vector m_pillars; std::vector m_junctions; std::vector m_bridges; std::vector m_compact_bridges; Controller m_ctl; - + Pad m_pad; - + using Mutex = ccr::Mutex; - + mutable Mutex m_mutex; mutable TriangleMesh meshcache; mutable bool meshcache_valid = false; mutable double model_height = 0; // the full height of the model - + public: double ground_level = 0; - + Impl() = default; inline Impl(const Controller& ctl): m_ctl(ctl) {} - + const Controller& ctl() const { return m_ctl; } - + template Head& add_head(unsigned id, Args&&... args) { std::lock_guard lk(m_mutex); m_heads.emplace_back(std::forward(args)...); m_heads.back().id = id; - + if (id >= m_head_indices.size()) m_head_indices.resize(id + 1); m_head_indices[id] = m_heads.size() - 1; - + meshcache_valid = false; return m_heads.back(); } - + template Pillar& add_pillar(unsigned headid, Args&&... args) { std::lock_guard lk(m_mutex); - + assert(headid < m_head_indices.size()); Head &head = m_heads[m_head_indices[headid]]; - + m_pillars.emplace_back(head, std::forward(args)...); Pillar& pillar = m_pillars.back(); pillar.id = long(m_pillars.size() - 1); head.pillar_id = pillar.id; pillar.start_junction_id = head.id; pillar.starts_from_head = true; - + meshcache_valid = false; return m_pillars.back(); } - + void increment_bridges(const Pillar& pillar) { std::lock_guard lk(m_mutex); assert(pillar.id >= 0 && size_t(pillar.id) < m_pillars.size()); - - if(pillar.id >= 0 && size_t(pillar.id) < m_pillars.size()) + + if(pillar.id >= 0 && size_t(pillar.id) < m_pillars.size()) m_pillars[size_t(pillar.id)].bridges++; } - + void increment_links(const Pillar& pillar) { std::lock_guard lk(m_mutex); assert(pillar.id >= 0 && size_t(pillar.id) < m_pillars.size()); - + if(pillar.id >= 0 && size_t(pillar.id) < m_pillars.size()) - m_pillars[size_t(pillar.id)].links++; + m_pillars[size_t(pillar.id)].links++; } - + template Pillar& add_pillar(Args&&...args) { std::lock_guard lk(m_mutex); @@ -857,30 +857,30 @@ public: meshcache_valid = false; return m_pillars.back(); } - + const Head& pillar_head(long pillar_id) const { std::lock_guard lk(m_mutex); assert(pillar_id >= 0 && pillar_id < long(m_pillars.size())); - + const Pillar& p = m_pillars[size_t(pillar_id)]; assert(p.starts_from_head && p.start_junction_id >= 0); assert(size_t(p.start_junction_id) < m_head_indices.size()); - + return m_heads[m_head_indices[p.start_junction_id]]; } - + const Pillar& head_pillar(unsigned headid) const { std::lock_guard lk(m_mutex); assert(headid < m_head_indices.size()); - + const Head& h = m_heads[m_head_indices[headid]]; assert(h.pillar_id >= 0 && h.pillar_id < long(m_pillars.size())); - + return m_pillars[size_t(h.pillar_id)]; } - + template const Junction& add_junction(Args&&... args) { std::lock_guard lk(m_mutex); @@ -889,7 +889,7 @@ public: meshcache_valid = false; return m_junctions.back(); } - + template const Bridge& add_bridge(Args&&... args) { std::lock_guard lk(m_mutex); @@ -898,7 +898,7 @@ public: meshcache_valid = false; return m_bridges.back(); } - + template const CompactBridge& add_compact_bridge(Args&&...args) { std::lock_guard lk(m_mutex); @@ -907,30 +907,30 @@ public: meshcache_valid = false; return m_compact_bridges.back(); } - + Head &head(unsigned id) { std::lock_guard lk(m_mutex); assert(id < m_head_indices.size()); - + meshcache_valid = false; return m_heads[m_head_indices[id]]; } - + inline size_t pillarcount() const { std::lock_guard lk(m_mutex); return m_pillars.size(); } - + template inline IntegerOnly pillar(T id) const { std::lock_guard lk(m_mutex); assert(id >= 0 && size_t(id) < m_pillars.size() && size_t(id) < std::numeric_limits::max()); - + return m_pillars[size_t(id)]; } - + const Pad &create_pad(const TriangleMesh &object_supports, const ExPolygons & modelbase, const PoolConfig & cfg) @@ -938,86 +938,88 @@ public: m_pad = Pad(object_supports, modelbase, ground_level, cfg); return m_pad; } - + void remove_pad() { m_pad = Pad(); } - + const Pad& pad() const { return m_pad; } - + // WITHOUT THE PAD!!! const TriangleMesh &merged_mesh() const { if (meshcache_valid) return meshcache; - + + std::cout << "merging mesh" << std::endl; + Contour3D merged; - + for (auto &head : m_heads) { if (m_ctl.stopcondition()) break; if (head.is_valid()) merged.merge(head.mesh); } - + for (auto &stick : m_pillars) { if (m_ctl.stopcondition()) break; merged.merge(stick.mesh); merged.merge(stick.base); } - + for (auto &j : m_junctions) { if (m_ctl.stopcondition()) break; merged.merge(j.mesh); } - + for (auto &cb : m_compact_bridges) { if (m_ctl.stopcondition()) break; merged.merge(cb.mesh); } - + for (auto &bs : m_bridges) { if (m_ctl.stopcondition()) break; merged.merge(bs.mesh); } - + if (m_ctl.stopcondition()) { // In case of failure we have to return an empty mesh meshcache = TriangleMesh(); return meshcache; } - + meshcache = mesh(merged); - + // The mesh will be passed by const-pointer to TriangleMeshSlicer, // which will need this. if (!meshcache.empty()) meshcache.require_shared_vertices(); - + BoundingBoxf3 &&bb = meshcache.bounding_box(); model_height = bb.max(Z) - bb.min(Z); - + meshcache_valid = true; return meshcache; } - + // WITH THE PAD double full_height() const { if (merged_mesh().empty() && !pad().empty()) return get_pad_fullheight(pad().cfg); - + double h = mesh_height(); if (!pad().empty()) h += sla::get_pad_elevation(pad().cfg); return h; } - + // WITHOUT THE PAD!!! double mesh_height() const { if (!meshcache_valid) merged_mesh(); return model_height; } - + // Intended to be called after the generation is fully complete void merge_and_cleanup() { merged_mesh(); // in case the mesh is not generated, it should be... - + // Doing clear() does not garantee to release the memory. m_heads = {}; m_head_indices = {}; @@ -1194,7 +1196,7 @@ class SLASupportTree::Algorithm { // Now a and b vectors are perpendicular to v and to each other. // Together they define the plane where we have to iterate with the // given angles in the 'phis' vector - ccr_par::enumerate(phis.begin(), phis.end(), + ccr_seq::enumerate(phis.begin(), phis.end(), [&hits, &m, sd, r_pin, r_back, s, a, b, c] (double phi, size_t i) { @@ -1296,8 +1298,8 @@ class SLASupportTree::Algorithm { // Hit results std::array hits; - - ccr_par::enumerate(phis.begin(), phis.end(), + + ccr_seq::enumerate(phis.begin(), phis.end(), [&m, a, b, sd, dir, r, s, ins_check, &hits] (double phi, size_t i) { @@ -1431,11 +1433,11 @@ class SLASupportTree::Algorithm { // For connecting a head to a nearby pillar. bool connect_to_nearpillar(const Head& head, long nearpillar_id) { - + auto nearpillar = [this, nearpillar_id]() { return m_result.pillar(nearpillar_id); }; - + if (nearpillar().bridges > m_cfg.max_bridges_on_pillar) return false; Vec3d headjp = head.junction_point(); @@ -1539,7 +1541,7 @@ class SLASupportTree::Algorithm { return nearest_id >= 0; } - + // This is a proxy function for pillar creation which will mind the gap // between the pad and the model bottom in zero elevation mode. void create_ground_pillar(const Vec3d &jp, @@ -1594,7 +1596,7 @@ class SLASupportTree::Algorithm { endp = jp + SQR2 * mv * dir; Vec3d pgnd = {endp(X), endp(Y), gndlvl}; can_add_base = result.score > min_dist; - + double gnd_offs = m_mesh.ground_level_offset(); auto abort_in_shame = [gnd_offs, &normal_mode, &can_add_base, &endp, jp, gndlvl]() @@ -1612,7 +1614,7 @@ class SLASupportTree::Algorithm { if (endp(Z) < gndlvl) endp = endp - SQR2 * (gndlvl - endp(Z)) * dir; // back off else { - + auto hit = bridge_mesh_intersect(endp, DOWN, radius); if (!std::isinf(hit.distance())) abort_in_shame(); @@ -1636,7 +1638,7 @@ class SLASupportTree::Algorithm { m_result.add_pillar(unsigned(head_id), jp, radius); } } - + if (normal_mode) { Pillar &plr = head_id >= 0 ? m_result.add_pillar(unsigned(head_id), @@ -1648,8 +1650,8 @@ class SLASupportTree::Algorithm { plr.add_base(m_cfg.base_height_mm, m_cfg.base_radius_mm); pillar_id = plr.id; - } - + } + if(pillar_id >= 0) // Save the pillar endpoint in the spatial index m_pillar_index.insert(endp, pillar_id); } @@ -1716,52 +1718,52 @@ public: using libnest2d::opt::initvals; using libnest2d::opt::GeneticOptimizer; using libnest2d::opt::StopCriteria; - + ccr::Mutex mutex; auto addfn = [&mutex](PtIndices &container, unsigned val) { std::lock_guard lk(mutex); container.emplace_back(val); }; - + ccr::enumerate(filtered_indices.begin(), filtered_indices.end(), [this, &nmls, addfn](unsigned fidx, size_t i) { m_thr(); - + auto n = nmls.row(i); - + // for all normals we generate the spherical coordinates and // saturate the polar angle to 45 degrees from the bottom then // convert back to standard coordinates to get the new normal. // Then we just create a quaternion from the two normals // (Quaternion::FromTwoVectors) and apply the rotation to the // arrow head. - + double z = n(2); double r = 1.0; // for normalized vector double polar = std::acos(z / r); double azimuth = std::atan2(n(1), n(0)); - + // skip if the tilt is not sane if(polar >= PI - m_cfg.normal_cutoff_angle) { - + // We saturate the polar angle to 3pi/4 polar = std::max(polar, 3*PI / 4); - + // save the head (pinpoint) position Vec3d hp = m_points.row(fidx); - + double w = m_cfg.head_width_mm + m_cfg.head_back_radius_mm + 2*m_cfg.head_front_radius_mm; - + double pin_r = double(m_support_pts[fidx].head_front_radius); - + // Reassemble the now corrected normal auto nn = Vec3d(std::cos(azimuth) * std::sin(polar), std::sin(azimuth) * std::sin(polar), std::cos(polar)).normalized(); - + // check available distance EigenMesh3D::hit_result t = pinhead_mesh_intersect(hp, // touching point @@ -1769,20 +1771,20 @@ public: pin_r, m_cfg.head_back_radius_mm, w); - + if(t.distance() <= w) { - + // Let's try to optimize this angle, there might be a // viable normal that doesn't collide with the model // geometry and its very close to the default. - + StopCriteria stc; stc.max_iterations = m_cfg.optimizer_max_iterations; stc.relative_score_difference = m_cfg.optimizer_rel_score_diff; stc.stop_score = w; // space greater than w is enough GeneticOptimizer solver(stc); solver.seed(0); // we want deterministic behavior - + auto oresult = solver.optimize_max( [this, pin_r, w, hp](double plr, double azm) { @@ -1799,7 +1801,7 @@ public: bound(3*PI/4, PI), // Must not exceed the tilt limit bound(-PI, PI) // azimuth can be a full search ); - + if(oresult.score > w) { polar = std::get<0>(oresult.optimum); azimuth = std::get<1>(oresult.optimum); @@ -1809,10 +1811,10 @@ public: t = oresult.score; } } - + // save the verified and corrected normal m_support_nmls.row(fidx) = nn; - + if (t.distance() > w) { // Check distance from ground, we might have zero elevation. if (hp(Z) + w * nn(Z) < m_result.ground_level) { @@ -1889,7 +1891,7 @@ public: // from each other in the XY plane to not cross their pillar bases // These clusters of support points will join in one pillar, // possibly in their centroid support point. - + auto pointfn = [this](unsigned i) { return m_result.head(i).junction_point(); }; @@ -2178,7 +2180,7 @@ public: m_pillar_index.insert(pillar.endpoint(), pillid); } } - + // Helper function for interconnect_pillars where pairs of already connected // pillars should be checked for not to be processed again. This can be done // in O(log) or even constant time with a set or an unordered set of hash @@ -2187,17 +2189,17 @@ public: template static I pairhash(I a, I b) { using std::ceil; using std::log2; using std::max; using std::min; - + static_assert(std::is_integral::value, "This function works only for integral types."); I g = min(a, b), l = max(a, b); - + auto bits_g = g ? int(ceil(log2(g))) : 0; // Assume the hash will fit into the output variable assert((l ? (ceil(log2(l))) : 0) + bits_g < int(sizeof(I) * CHAR_BIT)); - + return (l << bits_g) + g; } @@ -2217,7 +2219,7 @@ public: double min_height_ratio = 0.5; std::set pairs; - + // A function to connect one pillar with its neighbors. THe number of // neighbors is given in the configuration. This function if called // for every pillar in the pillar index. A pair of pillar will not @@ -2229,7 +2231,7 @@ public: Vec3d qp = el.first; // endpoint of the pillar const Pillar& pillar = m_result.pillar(el.second); // actual pillar - + // Get the max number of neighbors a pillar should connect to unsigned neighbors = m_cfg.pillar_cascade_neighbors; @@ -2255,10 +2257,10 @@ public: // Get unique hash for the given pair (order doesn't matter) auto hashval = pairhash(a, b); - + // Search for the pair amongst the remembered pairs if(pairs.find(hashval) != pairs.end()) continue; - + const Pillar& neighborpillar = m_result.pillar(re.second); // this neighbor is occupied, skip @@ -2283,10 +2285,10 @@ public: if(pillar.links >= neighbors) break; } }; - + // Run the cascade for the pillars in the index m_pillar_index.foreach(cascadefn); - + // We would be done here if we could allow some pillars to not be // connected with any neighbors. But this might leave the support tree // unprintable. @@ -2294,16 +2296,16 @@ public: // The current solution is to insert additional pillars next to these // lonely pillars. One or even two additional pillar might get inserted // depending on the length of the lonely pillar. - + size_t pillarcount = m_result.pillarcount(); - + // Again, go through all pillars, this time in the whole support tree // not just the index. for(size_t pid = 0; pid < pillarcount; pid++) { auto pillar = [this, pid]() { return m_result.pillar(pid); }; - + // Decide how many additional pillars will be needed: - + unsigned needpillars = 0; if (pillar().bridges > m_cfg.max_bridges_on_pillar) needpillars = 3; @@ -2332,7 +2334,7 @@ public: double gnd = m_result.ground_level; double min_dist = m_cfg.pillar_base_safety_distance_mm + m_cfg.base_radius_mm + EPSILON; - + while(!found && alpha < 2*PI) { for (unsigned n = 0; n < needpillars && (!n || canplace[n - 1]); @@ -2343,11 +2345,11 @@ public: s(X) += std::cos(a) * r; s(Y) += std::sin(a) * r; spts[n] = s; - - // Check the path vertically down + + // Check the path vertically down auto hr = bridge_mesh_intersect(s, {0, 0, -1}, pillar().r); Vec3d gndsp{s(X), s(Y), gnd}; - + // If the path is clear, check for pillar base collisions canplace[n] = std::isinf(hr.distance()) && std::sqrt(m_mesh.squared_distance(gndsp)) > @@ -2365,7 +2367,7 @@ public: newpills.reserve(needpillars); if(found) for(unsigned n = 0; n < needpillars; n++) { - Vec3d s = spts[n]; + Vec3d s = spts[n]; Pillar p(s, Vec3d(s(X), s(Y), gnd), pillar().r); p.add_base(m_cfg.base_height_mm, m_cfg.base_radius_mm); @@ -2447,8 +2449,8 @@ public: m_result.add_compact_bridge(sp, ej, n, R, !std::isinf(dist)); } } - - void merge_result() { m_result.merge_and_cleanup(); } + + void merge_result() { /*m_result.merge_and_cleanup();*/ } }; bool SLASupportTree::generate(const std::vector &support_points, @@ -2457,9 +2459,9 @@ bool SLASupportTree::generate(const std::vector &support_points, const Controller &ctl) { if(support_points.empty()) return false; - + Algorithm alg(cfg, mesh, support_points, *m_impl, ctl.cancelfn); - + // Let's define the individual steps of the processing. We can experiment // later with the ordering and the dependencies between them. enum Steps { @@ -2477,41 +2479,41 @@ bool SLASupportTree::generate(const std::vector &support_points, NUM_STEPS //... }; - + // Collect the algorithm steps into a nice sequence std::array, NUM_STEPS> program = { [] () { // Begin... // Potentially clear up the shared data (not needed for now) }, - + std::bind(&Algorithm::filter, &alg), - + std::bind(&Algorithm::add_pinheads, &alg), - + std::bind(&Algorithm::classify, &alg), - + std::bind(&Algorithm::routing_to_ground, &alg), - + std::bind(&Algorithm::routing_to_model, &alg), - + std::bind(&Algorithm::interconnect_pillars, &alg), - + std::bind(&Algorithm::routing_headless, &alg), - + std::bind(&Algorithm::merge_result, &alg), - + [] () { // Done }, - + [] () { // Abort } }; - + Steps pc = BEGIN; - + if(cfg.ground_facing_only) { program[ROUTING_NONGROUND] = []() { BOOST_LOG_TRIVIAL(info) @@ -2522,7 +2524,7 @@ bool SLASupportTree::generate(const std::vector &support_points, " requested."; }; } - + // Let's define a simple automaton that will run our program. auto progress = [&ctl, &pc] () { static const std::array stepstr { @@ -2538,7 +2540,7 @@ bool SLASupportTree::generate(const std::vector &support_points, "Done", "Abort" }; - + static const std::array stepstate { 0, 10, @@ -2552,9 +2554,9 @@ bool SLASupportTree::generate(const std::vector &support_points, 100, 0 }; - + if(ctl.stopcondition()) pc = ABORT; - + switch(pc) { case BEGIN: pc = FILTER; break; case FILTER: pc = PINHEADS; break; @@ -2569,16 +2571,16 @@ bool SLASupportTree::generate(const std::vector &support_points, case ABORT: break; default: ; } - + ctl.statuscb(stepstate[pc], stepstr[pc]); }; - + // Just here we run the computation... while(pc < DONE) { progress(); program[pc](); } - + return pc == ABORT; } @@ -2588,7 +2590,7 @@ SLASupportTree::SLASupportTree(double gnd_lvl): m_impl(new Impl()) { const TriangleMesh &SLASupportTree::merged_mesh() const { - return get().merged_mesh(); + return m_impl->merged_mesh(); } void SLASupportTree::merged_mesh_with_pad(TriangleMesh &outmesh) const { @@ -2601,34 +2603,34 @@ std::vector SLASupportTree::slice( { const TriangleMesh &sup_mesh = m_impl->merged_mesh(); const TriangleMesh &pad_mesh = get_pad(); - + std::vector sup_slices; - if (!sup_mesh.empty()) { + if (!sup_mesh.empty()) { TriangleMeshSlicer sup_slicer(&sup_mesh); sup_slicer.slice(heights, cr, &sup_slices, m_impl->ctl().cancelfn); } - + auto bb = pad_mesh.bounding_box(); auto maxzit = std::upper_bound(heights.begin(), heights.end(), bb.max.z()); - + auto padgrid = reserve_vector(heights.end() - maxzit); std::copy(heights.begin(), maxzit, std::back_inserter(padgrid)); - + std::vector pad_slices; - if (!pad_mesh.empty()) { + if (!pad_mesh.empty()) { TriangleMeshSlicer pad_slicer(&pad_mesh); pad_slicer.slice(padgrid, cr, &pad_slices, m_impl->ctl().cancelfn); } - + size_t len = std::min(heights.size(), pad_slices.size()); len = std::min(len, sup_slices.size()); - + for (size_t i = 0; i < len; ++i) { std::copy(pad_slices[i].begin(), pad_slices[i].end(), std::back_inserter(sup_slices[i])); - pad_slices[i] = {}; + pad_slices[i] = {}; } - + return sup_slices; } diff --git a/src/libslic3r/SLA/SLASupportTreeIGL.cpp b/src/libslic3r/SLA/SLASupportTreeIGL.cpp index d48b5bf73..95d451271 100644 --- a/src/libslic3r/SLA/SLASupportTreeIGL.cpp +++ b/src/libslic3r/SLA/SLASupportTreeIGL.cpp @@ -148,9 +148,9 @@ std::vector BoxIndex::query(const BoundingBox &qrbb, BoxIndex::QueryType qt) { namespace bgi = boost::geometry::index; - + std::vector ret; ret.reserve(m_impl->m_store.size()); - + switch (qt) { case qtIntersects: m_impl->m_store.query(bgi::intersects(qrbb), std::back_inserter(ret)); @@ -158,7 +158,7 @@ std::vector BoxIndex::query(const BoundingBox &qrbb, case qtWithin: m_impl->m_store.query(bgi::within(qrbb), std::back_inserter(ret)); } - + return ret; } @@ -198,9 +198,9 @@ EigenMesh3D::EigenMesh3D(const TriangleMesh& tmesh): m_aabb(new AABBImpl()) { F.resize(stl.stats.number_of_facets, 3); for (unsigned int i = 0; i < stl.stats.number_of_facets; ++i) { const stl_facet &facet = stl.facet_start[i]; - V.block<1, 3>(3 * i + 0, 0) = facet.vertex[0].cast(); - V.block<1, 3>(3 * i + 1, 0) = facet.vertex[1].cast(); - V.block<1, 3>(3 * i + 2, 0) = facet.vertex[2].cast(); + V.block<1, 3>(3 * i + 0, 0) = facet.vertex[0].cast(); + V.block<1, 3>(3 * i + 1, 0) = facet.vertex[1].cast(); + V.block<1, 3>(3 * i + 2, 0) = facet.vertex[2].cast(); F(i, 0) = int(3*i+0); F(i, 1) = int(3*i+1); F(i, 2) = int(3*i+2); @@ -306,6 +306,7 @@ PointSet normals(const PointSet& points, PointSet ret(range.size(), 3); +// for (size_t ridx = 0; ridx < range.size(); ++ridx) tbb::parallel_for(size_t(0), range.size(), [&ret, &range, &mesh, &points, thr, eps](size_t ridx) { diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 45f8a0c83..fa85d497f 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -16,6 +16,12 @@ // For geometry algorithms with native Clipper types (no copies and conversions) #include +#define SLAPRINT_DO_BENCHMARK + +#ifdef SLAPRINT_DO_BENCHMARK +#include +#endif + //#include //#include "tbb/mutex.h" #include "I18N.hpp" @@ -52,7 +58,7 @@ const std::array OBJ_STEP_LEVELS = }; // Object step to status label. The labels are localized at the time of calling, thus supporting language switching. -std::string OBJ_STEP_LABELS(size_t idx) +std::string OBJ_STEP_LABELS(size_t idx) { switch (idx) { case slaposObjectSlice: return L("Slicing model"); @@ -365,7 +371,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con // Synchronize Object's config. bool object_config_changed = model_object.config != model_object_new.config; if (object_config_changed) - static_cast(model_object.config) = static_cast(model_object_new.config); + static_cast(model_object.config) = static_cast(model_object_new.config); if (! object_diff.empty() || object_config_changed) { SLAPrintObjectConfig new_config = m_default_object_config; normalize_and_apply_config(new_config, model_object.config); @@ -424,10 +430,10 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con print_object->set_trafo(sla_trafo(*this, model_object), model_object.instances.front()->is_left_handed()); print_object->set_instances(std::move(new_instances)); - - SLAPrintObjectConfig new_config = m_default_object_config; - normalize_and_apply_config(new_config, model_object.config); - print_object->config_apply(new_config, true); + + SLAPrintObjectConfig new_config = m_default_object_config; + normalize_and_apply_config(new_config, model_object.config); + print_object->config_apply(new_config, true); print_objects_new.emplace_back(print_object); new_objects = true; } @@ -446,7 +452,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con if (new_objects) update_apply_status(false); } - + if(m_objects.empty()) { m_printer.release(); m_printer_input.clear(); @@ -596,16 +602,16 @@ sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c) { scfg.pillar_base_safety_distance_mm = c.support_base_safety_distance.getFloat() < EPSILON ? scfg.safety_distance_mm : c.support_base_safety_distance.getFloat(); - + return scfg; } sla::PoolConfig::EmbedObject builtin_pad_cfg(const SLAPrintObjectConfig& c) { sla::PoolConfig::EmbedObject ret; - + ret.enabled = c.support_object_elevation.getFloat() <= EPSILON && c.pad_enable.getBool() && c.supports_enable.getBool(); - + if(ret.enabled) { ret.object_gap_mm = c.pad_object_gap.getFloat(); ret.stick_width_mm = c.pad_object_connector_width.getFloat(); @@ -613,7 +619,7 @@ sla::PoolConfig::EmbedObject builtin_pad_cfg(const SLAPrintObjectConfig& c) { ret.stick_penetration_mm = c.pad_object_connector_penetration .getFloat(); } - + return ret; } @@ -622,16 +628,16 @@ sla::PoolConfig make_pool_config(const SLAPrintObjectConfig& c) { pcfg.min_wall_thickness_mm = c.pad_wall_thickness.getFloat(); pcfg.wall_slope = c.pad_wall_slope.getFloat() * PI / 180.0; - + // We do not support radius for now pcfg.edge_radius_mm = 0.0; //c.pad_edge_radius.getFloat(); - + pcfg.max_merge_distance_mm = c.pad_max_merge_distance.getFloat(); pcfg.min_wall_height_mm = c.pad_wall_height.getFloat(); // set builtin pad implicitly ON pcfg.embed_object = builtin_pad_cfg(c); - + return pcfg; } @@ -657,12 +663,12 @@ std::string SLAPrint::validate() const cfg.head_width_mm + 2 * cfg.head_back_radius_mm - cfg.head_penetration_mm; - + double elv = cfg.object_elevation_mm; if(supports_en && elv > EPSILON && elv < pinhead_width ) return L("Elevation is too low for object."); - + sla::PoolConfig::EmbedObject builtinpad = builtin_pad_cfg(po->config()); if(supports_en && builtinpad.enabled && cfg.pillar_base_safety_distance_mm < builtinpad.object_gap_mm) { @@ -740,15 +746,15 @@ void SLAPrint::process() coord_t maxZs = scaled(maxZ); po.m_slice_index.clear(); - + size_t cap = size_t(1 + (maxZs - minZs - ilhs) / lhs); po.m_slice_index.reserve(cap); - + po.m_slice_index.emplace_back(minZs + ilhs, minZf + ilh / 2.f, ilh); for(coord_t h = minZs + ilhs + lhs; h <= maxZs; h += lhs) po.m_slice_index.emplace_back(h, unscaled(h) - lh / 2.f, lh); - + // Just get the first record that is form the model: auto slindex_it = po.closest_slice_record(po.m_slice_index, float(bb3d.min(Z))); @@ -781,9 +787,9 @@ void SLAPrint::process() { // We apply the printer correction offset here. if(clpr_offs != 0) - po.m_model_slices[id] = + po.m_model_slices[id] = offset_ex(po.m_model_slices[id], float(clpr_offs)); - + mit->set_model_slice_idx(po, id); ++mit; } @@ -876,7 +882,7 @@ void SLAPrint::process() // removed them on purpose. No calculation will be done. po.m_supportdata->support_points = po.transformed_support_points(); } - + // If the zero elevation mode is engaged, we have to filter out all the // points that are on the bottom of the object if (po.config().support_object_elevation.getFloat() <= EPSILON) { @@ -894,7 +900,7 @@ void SLAPrint::process() double diff = std::abs(gnd - double(sp.pos(Z))); return diff <= tolerance; }); - + // erase all elements after the new end pts.erase(endit, pts.end()); } @@ -904,7 +910,7 @@ void SLAPrint::process() auto support_tree = [this, ostepd](SLAPrintObject& po) { if(!po.m_supportdata) return; - + sla::PoolConfig pcfg = make_pool_config(po.m_config); if (pcfg.embed_object) @@ -912,11 +918,11 @@ void SLAPrint::process() pcfg.min_wall_thickness_mm); if(!po.m_config.supports_enable.getBool()) { - + // Generate empty support tree. It can still host a pad po.m_supportdata->support_tree_ptr.reset( new SLASupportTree(po.m_supportdata->emesh.ground_level())); - + return; } @@ -940,7 +946,7 @@ void SLAPrint::process() ctl.stopcondition = [this](){ return canceled(); }; ctl.cancelfn = [this]() { throw_if_canceled(); }; - + po.m_supportdata->support_tree_ptr.reset( new SLASupportTree(po.m_supportdata->support_points, po.m_supportdata->emesh, scfg, ctl)); @@ -948,20 +954,20 @@ void SLAPrint::process() throw_if_canceled(); // Create the unified mesh - auto rc = SlicingStatus::RELOAD_SCENE; + // auto rc = SlicingStatus::RELOAD_SCENE; // This is to prevent "Done." being displayed during merged_mesh() - m_report_status(*this, -1, L("Visualizing supports")); - po.m_supportdata->support_tree_ptr->merged_mesh(); + // m_report_status(*this, -1, L("Visualizing supports")); + // po.m_supportdata->support_tree_ptr->merged_mesh(); BOOST_LOG_TRIVIAL(debug) << "Processed support point count " << po.m_supportdata->support_points.size(); // Check the mesh for later troubleshooting. - if(po.support_mesh().empty()) - BOOST_LOG_TRIVIAL(warning) << "Support mesh is empty"; +// if(po.support_mesh().empty()) +// BOOST_LOG_TRIVIAL(warning) << "Support mesh is empty"; - m_report_status(*this, -1, L("Visualizing supports"), rc); +// m_report_status(*this, -1, L("Visualizing supports"), rc); }; // This step generates the sla base pad @@ -970,6 +976,10 @@ void SLAPrint::process() // and before the supports had been sliced. (or the slicing has to be // repeated) + std::cout << "Should only merge mesh after this" << std::endl; + po.m_supportdata->support_tree_ptr->merged_mesh(); + m_report_status(*this, -1, L("Visualizing supports"), SlicingStatus::RELOAD_SCENE); + if(po.m_config.pad_enable.getBool()) { // Get the distilled pad configuration from the config @@ -1040,7 +1050,7 @@ void SLAPrint::process() if(clpr_offs != 0) sd->support_slices[i] = offset_ex(sd->support_slices[i], float(clpr_offs)); - + po.m_slice_index[i].set_support_slice_idx(po, i); } @@ -1268,7 +1278,7 @@ void SLAPrint::process() const SLAPrintObject *po = record.print_obj(); const ExPolygons &modelslices = record.get_slice(soModel); - + bool is_lefth = record.print_obj()->is_left_handed(); if (!modelslices.empty()) { ClipperPolygons v = get_all_polygons(modelslices, po->instances(), is_lefth); @@ -1276,7 +1286,7 @@ void SLAPrint::process() } const ExPolygons &supportslices = record.get_slice(soSupport); - + if (!supportslices.empty()) { ClipperPolygons v = get_all_polygons(supportslices, po->instances(), is_lefth); for(ClipperPolygon& p_tmp : v) supports_polygons.emplace_back(std::move(p_tmp)); @@ -1369,8 +1379,8 @@ void SLAPrint::process() { // create a raster printer for the current print parameters double layerh = m_default_object_config.layer_height.getFloat(); - m_printer.reset(new SLAPrinter(m_printer_config, - m_material_config, + m_printer.reset(new SLAPrinter(m_printer_config, + m_material_config, layerh)); } @@ -1429,7 +1439,7 @@ void SLAPrint::process() if(canceled()) return; // Sequential version (for testing) - // for(unsigned l = 0; l < lvlcnt; ++l) process_level(l); + // for(unsigned l = 0; l < lvlcnt; ++l) lvlfn(l); // Print all the layers in parallel tbb::parallel_for(0, lvlcnt, lvlfn); @@ -1446,44 +1456,48 @@ void SLAPrint::process() using slaposFn = std::function; using slapsFn = std::function; - std::array pobj_program = + slaposFn pobj_program[] = { - slice_model, - support_points, - support_tree, - base_pool, - slice_supports + slice_model, support_points, support_tree, base_pool, slice_supports }; - std::array print_program = - { - merge_slices_and_eval_stats, - rasterize + // We want to first process all objects... + std::vector level1_obj_steps = { + slaposObjectSlice, slaposSupportPoints, slaposSupportTree, slaposBasePool }; + // and then slice all supports to allow preview to be displayed ASAP + std::vector level2_obj_steps = { + slaposSliceSupports + }; + + slapsFn print_program[] = { merge_slices_and_eval_stats, rasterize }; + SLAPrintStep print_steps[] = { slapsMergeSlicesAndEval, slapsRasterize }; + double st = min_objstatus; - unsigned incr = 0; BOOST_LOG_TRIVIAL(info) << "Start slicing process."; - // TODO: this loop could run in parallel but should not exhaust all the CPU - // power available - // Calculate the support structures first before slicing the supports, - // so that the preview will get displayed ASAP for all objects. - std::vector step_ranges = {slaposObjectSlice, - slaposSliceSupports, - slaposCount}; +#ifdef SLAPRINT_DO_BENCHMARK + Benchmark bench; +#else + struct { + void start() {} void stop() {} double getElapsedSec() { return .0; } + } bench; +#endif - for (size_t idx_range = 0; idx_range + 1 < step_ranges.size(); ++idx_range) { + std::array step_times {}; + + auto apply_steps_on_objects = + [this, &st, ostepd, &pobj_program, &step_times, &bench] + (const std::vector &steps) + { + unsigned incr = 0; for (SLAPrintObject *po : m_objects) { - BOOST_LOG_TRIVIAL(info) - << "Slicing object " << po->model_object()->name; + for (SLAPrintObjectStep currentstep : steps) { - for (int s = int(step_ranges[idx_range]); - s < int(step_ranges[idx_range + 1]); - ++s) { - auto currentstep = static_cast(s); + Benchmark bench; // Cancellation checking. Each step will check for // cancellation on its own and return earlier gracefully. @@ -1493,12 +1507,12 @@ void SLAPrint::process() st += incr * ostepd; - if (po->m_stepmask[currentstep] - && po->set_started(currentstep)) { - m_report_status(*this, - st, - OBJ_STEP_LABELS(currentstep)); + if (po->m_stepmask[currentstep] && po->set_started(currentstep)) { + m_report_status(*this, st, OBJ_STEP_LABELS(currentstep)); + bench.start(); pobj_program[currentstep](*po); + bench.stop(); + step_times[currentstep] += bench.getElapsedSec(); throw_if_canceled(); po->set_done(currentstep); } @@ -1506,26 +1520,27 @@ void SLAPrint::process() incr = OBJ_STEP_LEVELS[currentstep]; } } - } - - std::array printsteps = { - slapsMergeSlicesAndEval, slapsRasterize }; + apply_steps_on_objects(level1_obj_steps); + apply_steps_on_objects(level2_obj_steps); + + SLAPrintStep printsteps[] = { slapsMergeSlicesAndEval, slapsRasterize }; + // this would disable the rasterization step - // m_stepmask[slapsRasterize] = false; + // std::fill(m_stepmask.begin(), m_stepmask.end(), false); double pstd = (100 - max_objstatus) / 100.0; st = max_objstatus; - for(size_t s = 0; s < print_program.size(); ++s) { - auto currentstep = printsteps[s]; - + for(SLAPrintStep currentstep : printsteps) { throw_if_canceled(); - if(m_stepmask[currentstep] && set_started(currentstep)) - { + if (m_stepmask[currentstep] && set_started(currentstep)) { m_report_status(*this, st, PRINT_STEP_LABELS(currentstep)); + bench.start(); print_program[currentstep](); + bench.stop(); + step_times[slaposCount + currentstep] += bench.getElapsedSec(); throw_if_canceled(); set_done(currentstep); } @@ -1535,6 +1550,21 @@ void SLAPrint::process() // If everything vent well m_report_status(*this, 100, L("Slicing done")); + +#ifdef SLAPRINT_DO_BENCHMARK + std::string csvbenchstr; + for (size_t i = 0; i < size_t(slaposCount); ++i) + csvbenchstr += OBJ_STEP_LABELS(i) + ";"; + + for (size_t i = 0; i < size_t(slapsCount); ++i) + csvbenchstr += PRINT_STEP_LABELS(i) + ";"; + + csvbenchstr += "\n"; + for (double t : step_times) csvbenchstr += std::to_string(t) + ";"; + + std::cout << "Performance stats: \n" << csvbenchstr << std::endl; +#endif + } bool SLAPrint::invalidate_state_by_config_options(const std::vector &opt_keys, bool &invalidate_all_model_objects) @@ -1756,7 +1786,7 @@ Vec3d SLAPrint::relative_correction() const corr(X) = printer_config().relative_correction.values[0]; corr(Y) = printer_config().relative_correction.values[0]; corr(Z) = printer_config().relative_correction.values.back(); - } + } if(material_config().material_correction.values.size() >= 2) { corr(X) *= material_config().material_correction.values[0]; @@ -1925,7 +1955,7 @@ void SLAPrint::StatusReporter::operator()(SLAPrint & p, BOOST_LOG_TRIVIAL(info) << st << "% " << msg << (logmsg.empty() ? "" : ": ") << logmsg << log_memory_info(); - + p.set_status(int(std::round(st)), msg, flags); } diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 2a8d8fccf..aef089634 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -11,13 +11,14 @@ #include #include #include +#include #include #include #include namespace Slic3r { - enum class ModelVolumeType : int; + enum class ModelVolumeType : int; }; typedef double coordf_t; @@ -36,11 +37,11 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const std::function cb, const std::string& icon = "", wxEvtHandler* event_handler = nullptr, std::function const cb_condition = []() { return true; }, wxWindow* parent = nullptr); -wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description, +wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description, const std::string& icon = "", std::function const cb_condition = []() { return true; }, wxWindow* parent = nullptr); -wxMenuItem* append_menu_radio_item(wxMenu* menu, int id, const wxString& string, const wxString& description, +wxMenuItem* append_menu_radio_item(wxMenu* menu, int id, const wxString& string, const wxString& description, std::function cb, wxEvtHandler* event_handler); class wxDialog; @@ -48,7 +49,7 @@ void edit_tooltip(wxString& tooltip); void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector& btn_ids); int em_unit(wxWindow* win); -wxBitmap create_scaled_bitmap(wxWindow *win, const std::string& bmp_name, +wxBitmap create_scaled_bitmap(wxWindow *win, const std::string& bmp_name, const int px_cnt = 16, const bool is_horizontal = false, const bool grayscale = false); class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup @@ -92,23 +93,23 @@ public: class wxDataViewTreeCtrlComboPopup: public wxDataViewTreeCtrl, public wxComboPopup { - static const unsigned int DefaultWidth; - static const unsigned int DefaultHeight; - static const unsigned int DefaultItemHeight; + static const unsigned int DefaultWidth; + static const unsigned int DefaultHeight; + static const unsigned int DefaultItemHeight; - wxString m_text; - int m_cnt_open_items{0}; + wxString m_text; + int m_cnt_open_items{0}; public: - virtual bool Create(wxWindow* parent); - virtual wxWindow* GetControl() { return this; } - virtual void SetStringValue(const wxString& value) { m_text = value; } - virtual wxString GetStringValue() const { return m_text; } + virtual bool Create(wxWindow* parent); + virtual wxWindow* GetControl() { return this; } + virtual void SetStringValue(const wxString& value) { m_text = value; } + virtual wxString GetStringValue() const { return m_text; } // virtual wxSize GetAdjustedSize(int minWidth, int prefHeight, int maxHeight); - virtual void OnKeyEvent(wxKeyEvent& evt); - void OnDataViewTreeCtrlSelection(wxCommandEvent& evt); - void SetItemsCnt(int cnt) { m_cnt_open_items = cnt; } + virtual void OnKeyEvent(wxKeyEvent& evt); + void OnDataViewTreeCtrlSelection(wxCommandEvent& evt); + void SetItemsCnt(int cnt) { m_cnt_open_items = cnt; } }; @@ -121,7 +122,7 @@ class DataViewBitmapText : public wxObject public: DataViewBitmapText( const wxString &text = wxEmptyString, const wxBitmap& bmp = wxNullBitmap) : - m_text(text), + m_text(text), m_bmp(bmp) { } @@ -177,8 +178,8 @@ WX_DEFINE_ARRAY_PTR(ObjectDataViewModelNode*, MyObjectTreeModelNodePtrArray); class ObjectDataViewModelNode { - ObjectDataViewModelNode* m_parent; - MyObjectTreeModelNodePtrArray m_children; + ObjectDataViewModelNode* m_parent; + MyObjectTreeModelNodePtrArray m_children; wxBitmap m_empty_bmp; size_t m_volumes_cnt = 0; std::vector< std::string > m_opt_categories; @@ -196,7 +197,7 @@ class ObjectDataViewModelNode Slic3r::ModelVolumeType m_volume_type; public: - ObjectDataViewModelNode(const wxString &name, + ObjectDataViewModelNode(const wxString &name, const wxString& extruder): m_parent(NULL), m_name(name), @@ -211,20 +212,20 @@ public: #endif //__WXGTK__ set_action_icon(); - } + } - ObjectDataViewModelNode(ObjectDataViewModelNode* parent, - const wxString& sub_obj_name, - const wxBitmap& bmp, - const wxString& extruder, + ObjectDataViewModelNode(ObjectDataViewModelNode* parent, + const wxString& sub_obj_name, + const wxBitmap& bmp, + const wxString& extruder, const int idx = -1 ) : m_parent (parent), - m_name (sub_obj_name), - m_type (itVolume), + m_name (sub_obj_name), + m_type (itVolume), m_idx (idx), m_extruder (extruder) { - m_bmp = bmp; + m_bmp = bmp; #ifdef __WXGTK__ // it's necessary on GTK because of control have to know if this item will be container // in another case you couldn't to add subitem for this item @@ -235,125 +236,125 @@ public: set_action_icon(); } - ObjectDataViewModelNode(ObjectDataViewModelNode* parent, - const t_layer_height_range& layer_range, + ObjectDataViewModelNode(ObjectDataViewModelNode* parent, + const t_layer_height_range& layer_range, const int idx = -1, const wxString& extruder = wxEmptyString ); ObjectDataViewModelNode(ObjectDataViewModelNode* parent, const ItemType type); - ~ObjectDataViewModelNode() - { - // free all our children nodes - size_t count = m_children.GetCount(); - for (size_t i = 0; i < count; i++) - { - ObjectDataViewModelNode *child = m_children[i]; - delete child; - } + ~ObjectDataViewModelNode() + { + // free all our children nodes + size_t count = m_children.GetCount(); + for (size_t i = 0; i < count; i++) + { + ObjectDataViewModelNode *child = m_children[i]; + delete child; + } #ifndef NDEBUG - // Indicate that the object was deleted. - m_idx = -2; + // Indicate that the object was deleted. + m_idx = -2; #endif /* NDEBUG */ - } + } - bool IsContainer() const - { - return m_container; - } + bool IsContainer() const + { + return m_container; + } - ObjectDataViewModelNode* GetParent() - { - assert(m_parent == nullptr || m_parent->valid()); - return m_parent; - } - MyObjectTreeModelNodePtrArray& GetChildren() - { - return m_children; - } - ObjectDataViewModelNode* GetNthChild(unsigned int n) - { - return m_children.Item(n); - } - void Insert(ObjectDataViewModelNode* child, unsigned int n) - { - if (!m_container) - m_container = true; - m_children.Insert(child, n); - } - void Append(ObjectDataViewModelNode* child) - { - if (!m_container) - m_container = true; - m_children.Add(child); - } - void RemoveAllChildren() - { - if (GetChildCount() == 0) - return; - for (int id = int(GetChildCount()) - 1; id >= 0; --id) - { - if (m_children.Item(id)->GetChildCount() > 0) - m_children[id]->RemoveAllChildren(); - auto node = m_children[id]; - m_children.RemoveAt(id); - delete node; - } - } + ObjectDataViewModelNode* GetParent() + { + assert(m_parent == nullptr || m_parent->valid()); + return m_parent; + } + MyObjectTreeModelNodePtrArray& GetChildren() + { + return m_children; + } + ObjectDataViewModelNode* GetNthChild(unsigned int n) + { + return m_children.Item(n); + } + void Insert(ObjectDataViewModelNode* child, unsigned int n) + { + if (!m_container) + m_container = true; + m_children.Insert(child, n); + } + void Append(ObjectDataViewModelNode* child) + { + if (!m_container) + m_container = true; + m_children.Add(child); + } + void RemoveAllChildren() + { + if (GetChildCount() == 0) + return; + for (int id = int(GetChildCount()) - 1; id >= 0; --id) + { + if (m_children.Item(id)->GetChildCount() > 0) + m_children[id]->RemoveAllChildren(); + auto node = m_children[id]; + m_children.RemoveAt(id); + delete node; + } + } - size_t GetChildCount() const - { - return m_children.GetCount(); - } + size_t GetChildCount() const + { + return m_children.GetCount(); + } - bool SetValue(const wxVariant &variant, unsigned int col); + bool SetValue(const wxVariant &variant, unsigned int col); - void SetBitmap(const wxBitmap &icon) { m_bmp = icon; } + void SetBitmap(const wxBitmap &icon) { m_bmp = icon; } const wxBitmap& GetBitmap() const { return m_bmp; } const wxString& GetName() const { return m_name; } ItemType GetType() const { return m_type; } - void SetIdx(const int& idx); - int GetIdx() const { return m_idx; } - t_layer_height_range GetLayerRange() const { return m_layer_range; } + void SetIdx(const int& idx); + int GetIdx() const { return m_idx; } + t_layer_height_range GetLayerRange() const { return m_layer_range; } - // use this function only for childrens - void AssignAllVal(ObjectDataViewModelNode& from_node) - { - // ! Don't overwrite other values because of equality of this values for all children -- - m_name = from_node.m_name; + // use this function only for childrens + void AssignAllVal(ObjectDataViewModelNode& from_node) + { + // ! Don't overwrite other values because of equality of this values for all children -- + m_name = from_node.m_name; m_bmp = from_node.m_bmp; m_idx = from_node.m_idx; m_extruder = from_node.m_extruder; m_type = from_node.m_type; - } + } - bool SwapChildrens(int frst_id, int scnd_id) { - if (GetChildCount() < 2 || - frst_id < 0 || (size_t)frst_id >= GetChildCount() || - scnd_id < 0 || (size_t)scnd_id >= GetChildCount()) - return false; + bool SwapChildrens(int frst_id, int scnd_id) { + if (GetChildCount() < 2 || + frst_id < 0 || (size_t)frst_id >= GetChildCount() || + scnd_id < 0 || (size_t)scnd_id >= GetChildCount()) + return false; - ObjectDataViewModelNode new_scnd = *GetNthChild(frst_id); - ObjectDataViewModelNode new_frst = *GetNthChild(scnd_id); + ObjectDataViewModelNode new_scnd = *GetNthChild(frst_id); + ObjectDataViewModelNode new_frst = *GetNthChild(scnd_id); new_scnd.m_idx = m_children.Item(scnd_id)->m_idx; new_frst.m_idx = m_children.Item(frst_id)->m_idx; - m_children.Item(frst_id)->AssignAllVal(new_frst); - m_children.Item(scnd_id)->AssignAllVal(new_scnd); - return true; - } + m_children.Item(frst_id)->AssignAllVal(new_frst); + m_children.Item(scnd_id)->AssignAllVal(new_scnd); + return true; + } - // Set action icons for node + // Set action icons for node void set_action_icon(); void update_settings_digest_bitmaps(); - bool update_settings_digest(const std::vector& categories); + bool update_settings_digest(const std::vector& categories); int volume_type() const { return int(m_volume_type); } void msw_rescale(); #ifndef NDEBUG - bool valid(); + bool valid(); #endif /* NDEBUG */ private: @@ -369,7 +370,7 @@ wxDECLARE_EVENT(wxCUSTOMEVT_LAST_VOLUME_IS_DELETED, wxCommandEvent); class ObjectDataViewModel :public wxDataViewModel { - std::vector m_objects; + std::vector m_objects; std::vector m_volume_bmps; wxBitmap* m_warning_bmp; @@ -379,7 +380,7 @@ public: ObjectDataViewModel(); ~ObjectDataViewModel(); - wxDataViewItem Add( const wxString &name, + wxDataViewItem Add( const wxString &name, const int extruder, const bool has_errors = false); wxDataViewItem AddVolumeChild( const wxDataViewItem &parent_item, @@ -391,24 +392,24 @@ public: wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item); wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num); wxDataViewItem AddLayersRoot(const wxDataViewItem &parent_item); - wxDataViewItem AddLayersChild( const wxDataViewItem &parent_item, + wxDataViewItem AddLayersChild( const wxDataViewItem &parent_item, const t_layer_height_range& layer_range, - const int extruder = 0, + const int extruder = 0, const int index = -1); - wxDataViewItem Delete(const wxDataViewItem &item); - wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num); - void DeleteAll(); + wxDataViewItem Delete(const wxDataViewItem &item); + wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num); + void DeleteAll(); void DeleteChildren(wxDataViewItem& parent); void DeleteVolumeChildren(wxDataViewItem& parent); void DeleteSettings(const wxDataViewItem& parent); - wxDataViewItem GetItemById(int obj_idx); + wxDataViewItem GetItemById(int obj_idx); wxDataViewItem GetItemById(const int obj_idx, const int sub_obj_idx, const ItemType parent_type); - wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx); - wxDataViewItem GetItemByInstanceId(int obj_idx, int inst_idx); + wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx); + wxDataViewItem GetItemByInstanceId(int obj_idx, int inst_idx); wxDataViewItem GetItemByLayerId(int obj_idx, int layer_idx); wxDataViewItem GetItemByLayerRange(const int obj_idx, const t_layer_height_range& layer_range); int GetItemIdByLayerRange(const int obj_idx, const t_layer_height_range& layer_range); - int GetIdByItem(const wxDataViewItem& item) const; + int GetIdByItem(const wxDataViewItem& item) const; int GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const; int GetObjectIdByItem(const wxDataViewItem& item) const; int GetVolumeIdByItem(const wxDataViewItem& item) const; @@ -418,53 +419,53 @@ public: int GetRowByItem(const wxDataViewItem& item) const; bool IsEmpty() { return m_objects.empty(); } - // helper method for wxLog + // helper method for wxLog - wxString GetName(const wxDataViewItem &item) const; + wxString GetName(const wxDataViewItem &item) const; wxBitmap& GetBitmap(const wxDataViewItem &item) const; - // helper methods to change the model + // helper methods to change the model - virtual unsigned int GetColumnCount() const override { return 3;} - virtual wxString GetColumnType(unsigned int col) const override{ return wxT("string"); } + virtual unsigned int GetColumnCount() const override { return 3;} + virtual wxString GetColumnType(unsigned int col) const override{ return wxT("string"); } - virtual void GetValue( wxVariant &variant, - const wxDataViewItem &item, + virtual void GetValue( wxVariant &variant, + const wxDataViewItem &item, unsigned int col) const override; - virtual bool SetValue( const wxVariant &variant, - const wxDataViewItem &item, + virtual bool SetValue( const wxVariant &variant, + const wxDataViewItem &item, unsigned int col) override; - bool SetValue( const wxVariant &variant, - const int item_idx, + bool SetValue( const wxVariant &variant, + const int item_idx, unsigned int col); - // For parent move child from cur_volume_id place to new_volume_id + // For parent move child from cur_volume_id place to new_volume_id // Remaining items will moved up/down accordingly - wxDataViewItem ReorganizeChildren( const int cur_volume_id, + wxDataViewItem ReorganizeChildren( const int cur_volume_id, const int new_volume_id, const wxDataViewItem &parent); - virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const override; + virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const override; - virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override; + virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override; // get object item wxDataViewItem GetTopParent(const wxDataViewItem &item) const; - virtual bool IsContainer(const wxDataViewItem &item) const override; - virtual unsigned int GetChildren(const wxDataViewItem &parent, - wxDataViewItemArray &array) const override; + virtual bool IsContainer(const wxDataViewItem &item) const override; + virtual unsigned int GetChildren(const wxDataViewItem &parent, + wxDataViewItemArray &array) const override; void GetAllChildren(const wxDataViewItem &parent,wxDataViewItemArray &array) const; - // Is the container just a header or an item with all columns - // In our case it is an item with all columns - virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; } + // Is the container just a header or an item with all columns + // In our case it is an item with all columns + virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; } ItemType GetItemType(const wxDataViewItem &item) const ; - wxDataViewItem GetItemByType( const wxDataViewItem &parent_item, + wxDataViewItem GetItemByType( const wxDataViewItem &parent_item, ItemType type) const; wxDataViewItem GetSettingsItem(const wxDataViewItem &item) const; wxDataViewItem GetInstanceRootItem(const wxDataViewItem &item) const; wxDataViewItem GetLayerRootItem(const wxDataViewItem &item) const; bool IsSettingsItem(const wxDataViewItem &item) const; - void UpdateSettingsDigest( const wxDataViewItem &item, + void UpdateSettingsDigest( const wxDataViewItem &item, const std::vector& categories); void SetVolumeBitmaps(const std::vector& volume_bmps) { m_volume_bmps = volume_bmps; } @@ -475,7 +476,7 @@ public: // Rescale bitmaps for existing Items void Rescale(); - wxBitmap GetVolumeIcon(const Slic3r::ModelVolumeType vol_type, + wxBitmap GetVolumeIcon(const Slic3r::ModelVolumeType vol_type, const bool is_marked = false); void DeleteWarningIcon(const wxDataViewItem& item, const bool unmark_object = false); t_layer_height_range GetLayerRangeByItem(const wxDataViewItem& item) const; @@ -520,12 +521,12 @@ public: return false; #else return true; -#endif +#endif } - wxWindow* CreateEditorCtrl(wxWindow* parent, - wxRect labelRect, + wxWindow* CreateEditorCtrl(wxWindow* parent, + wxRect labelRect, const wxVariant& value) override; - bool GetValueFromEditorCtrl( wxWindow* ctrl, + bool GetValueFromEditorCtrl( wxWindow* ctrl, wxVariant& value) override; bool WasCanceled() const { return m_was_unusable_symbol; } @@ -542,88 +543,88 @@ private: class MyCustomRenderer : public wxDataViewCustomRenderer { public: - // This renderer can be either activatable or editable, for demonstration - // purposes. In real programs, you should select whether the user should be - // able to activate or edit the cell and it doesn't make sense to switch - // between the two -- but this is just an example, so it doesn't stop us. - explicit MyCustomRenderer(wxDataViewCellMode mode) - : wxDataViewCustomRenderer("string", mode, wxALIGN_CENTER) - { } + // This renderer can be either activatable or editable, for demonstration + // purposes. In real programs, you should select whether the user should be + // able to activate or edit the cell and it doesn't make sense to switch + // between the two -- but this is just an example, so it doesn't stop us. + explicit MyCustomRenderer(wxDataViewCellMode mode) + : wxDataViewCustomRenderer("string", mode, wxALIGN_CENTER) + { } - virtual bool Render(wxRect rect, wxDC *dc, int state) override/*wxOVERRIDE*/ - { - dc->SetBrush(*wxLIGHT_GREY_BRUSH); - dc->SetPen(*wxTRANSPARENT_PEN); + virtual bool Render(wxRect rect, wxDC *dc, int state) override/*wxOVERRIDE*/ + { + dc->SetBrush(*wxLIGHT_GREY_BRUSH); + dc->SetPen(*wxTRANSPARENT_PEN); - rect.Deflate(2); - dc->DrawRoundedRectangle(rect, 5); + rect.Deflate(2); + dc->DrawRoundedRectangle(rect, 5); - RenderText(m_value, - 0, // no offset - wxRect(dc->GetTextExtent(m_value)).CentreIn(rect), - dc, - state); - return true; - } + RenderText(m_value, + 0, // no offset + wxRect(dc->GetTextExtent(m_value)).CentreIn(rect), + dc, + state); + return true; + } - virtual bool ActivateCell(const wxRect& WXUNUSED(cell), - wxDataViewModel *WXUNUSED(model), - const wxDataViewItem &WXUNUSED(item), - unsigned int WXUNUSED(col), - const wxMouseEvent *mouseEvent) override/*wxOVERRIDE*/ - { - wxString position; - if (mouseEvent) - position = wxString::Format("via mouse at %d, %d", mouseEvent->m_x, mouseEvent->m_y); - else - position = "from keyboard"; + virtual bool ActivateCell(const wxRect& WXUNUSED(cell), + wxDataViewModel *WXUNUSED(model), + const wxDataViewItem &WXUNUSED(item), + unsigned int WXUNUSED(col), + const wxMouseEvent *mouseEvent) override/*wxOVERRIDE*/ + { + wxString position; + if (mouseEvent) + position = wxString::Format("via mouse at %d, %d", mouseEvent->m_x, mouseEvent->m_y); + else + position = "from keyboard"; // wxLogMessage("MyCustomRenderer ActivateCell() %s", position); - return false; - } + return false; + } - virtual wxSize GetSize() const override/*wxOVERRIDE*/ - { - return wxSize(60, 20); - } + virtual wxSize GetSize() const override/*wxOVERRIDE*/ + { + return wxSize(60, 20); + } - virtual bool SetValue(const wxVariant &value) override/*wxOVERRIDE*/ - { - m_value = value.GetString(); - return true; - } + virtual bool SetValue(const wxVariant &value) override/*wxOVERRIDE*/ + { + m_value = value.GetString(); + return true; + } - virtual bool GetValue(wxVariant &WXUNUSED(value)) const override/*wxOVERRIDE*/{ return true; } + virtual bool GetValue(wxVariant &WXUNUSED(value)) const override/*wxOVERRIDE*/{ return true; } - virtual bool HasEditorCtrl() const override/*wxOVERRIDE*/{ return true; } + virtual bool HasEditorCtrl() const override/*wxOVERRIDE*/{ return true; } - virtual wxWindow* - CreateEditorCtrl(wxWindow* parent, - wxRect labelRect, - const wxVariant& value) override/*wxOVERRIDE*/ - { - wxTextCtrl* text = new wxTextCtrl(parent, wxID_ANY, value, - labelRect.GetPosition(), - labelRect.GetSize(), - wxTE_PROCESS_ENTER); - text->SetInsertionPointEnd(); + virtual wxWindow* + CreateEditorCtrl(wxWindow* parent, + wxRect labelRect, + const wxVariant& value) override/*wxOVERRIDE*/ + { + wxTextCtrl* text = new wxTextCtrl(parent, wxID_ANY, value, + labelRect.GetPosition(), + labelRect.GetSize(), + wxTE_PROCESS_ENTER); + text->SetInsertionPointEnd(); - return text; - } + return text; + } - virtual bool - GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value) override/*wxOVERRIDE*/ - { - wxTextCtrl* text = wxDynamicCast(ctrl, wxTextCtrl); - if (!text) - return false; + virtual bool + GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value) override/*wxOVERRIDE*/ + { + wxTextCtrl* text = wxDynamicCast(ctrl, wxTextCtrl); + if (!text) + return false; - value = text->GetValue(); + value = text->GetValue(); - return true; - } + return true; + } private: - wxString m_value; + wxString m_value; }; @@ -635,7 +636,7 @@ class ScalableBitmap { public: ScalableBitmap() {}; - ScalableBitmap( wxWindow *parent, + ScalableBitmap( wxWindow *parent, const std::string& icon_name = "", const int px_cnt = 16, const bool is_horizontal = false); @@ -681,9 +682,9 @@ public: DoubleSlider( wxWindow *parent, wxWindowID id, - int lowerValue, - int higherValue, - int minValue, + int lowerValue, + int higherValue, + int minValue, int maxValue, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, @@ -726,8 +727,8 @@ public: EnableTickManipulation(false); } - bool is_horizontal() const { return m_style == wxSL_HORIZONTAL; } - bool is_one_layer() const { return m_is_one_layer; } + bool is_horizontal() const { return m_style == wxSL_HORIZONTAL; } + bool is_one_layer() const { return m_is_one_layer; } bool is_lower_at_min() const { return m_lower_value == m_min_value; } bool is_higher_at_max() const { return m_higher_value == m_max_value; } bool is_full_span() const { return this->is_lower_at_min() && this->is_higher_at_max(); } @@ -746,7 +747,7 @@ public: void OnRightUp(wxMouseEvent& event); protected: - + void render(); void draw_focus_rect(); void draw_action_icon(wxDC& dc, const wxPoint pt_beg, const wxPoint pt_end); diff --git a/src/slic3r/Utils/Time.hpp b/src/slic3r/Utils/Time.hpp index 7b670bd3e..6a1aefa18 100644 --- a/src/slic3r/Utils/Time.hpp +++ b/src/slic3r/Utils/Time.hpp @@ -2,7 +2,7 @@ #define slic3r_Utils_Time_hpp_ #include -#include +#include namespace Slic3r { namespace Utils {