Merge commit '85d9a165636617c76d30be54a1cd99bd4e5663b0'
@ -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 Slic3r with static libraries (Boost, TBB, glew)" ${SLIC3R_STATIC_INITIAL})
|
||||
@ -52,9 +52,21 @@ if (SLIC3R_GUI)
|
||||
add_definitions(-DSLIC3R_GUI)
|
||||
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)
|
||||
add_compile_options(/MP)
|
||||
if (SLIC3R_MSVC_COMPILE_PARALLEL AND NOT IS_CLANG_CL)
|
||||
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
|
||||
@ -62,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 "")
|
||||
@ -101,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)
|
||||
@ -148,8 +164,10 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUXX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fext-numeric-literals" )
|
||||
endif()
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" )
|
||||
if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
|
||||
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.
|
||||
@ -168,7 +186,6 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATC
|
||||
add_compile_options(-Wno-unknown-pragmas)
|
||||
endif()
|
||||
|
||||
|
||||
if (SLIC3R_ASAN)
|
||||
add_compile_options(-fsanitize=address -fno-omit-frame-pointer)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
||||
@ -196,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)
|
||||
|
||||
@ -229,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")
|
||||
@ -251,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
|
||||
|
@ -105,6 +105,9 @@ function(add_precompiled_header _target _input)
|
||||
cmake_parse_arguments(_PCH "FORCEINCLUDE" "SOURCE_CXX;SOURCE_C" "" ${ARGN})
|
||||
|
||||
get_filename_component(_input_we ${_input} NAME_WE)
|
||||
get_filename_component(_input_full ${_input} ABSOLUTE)
|
||||
file(TO_NATIVE_PATH "${_input_full}" _input_fullpath)
|
||||
|
||||
if(NOT _PCH_SOURCE_CXX)
|
||||
set(_PCH_SOURCE_CXX "${_input_we}.cpp")
|
||||
endif()
|
||||
@ -138,16 +141,16 @@ function(add_precompiled_header _target _input)
|
||||
set_source_files_properties("${_source}" PROPERTIES OBJECT_OUTPUTS "${_pch_c_pch}")
|
||||
else()
|
||||
if(_source MATCHES \\.\(cpp|cxx|cc\)$)
|
||||
set(_pch_compile_flags "${_pch_compile_flags} \"/Fp${_pch_cxx_pch}\" \"/Yu${_input}\"")
|
||||
set(_pch_compile_flags "${_pch_compile_flags} \"/Fp${_pch_cxx_pch}\" \"/Yu${_input_fullpath}\"")
|
||||
set(_pch_source_cxx_needed TRUE)
|
||||
set_source_files_properties("${_source}" PROPERTIES OBJECT_DEPENDS "${_pch_cxx_pch}")
|
||||
else()
|
||||
set(_pch_compile_flags "${_pch_compile_flags} \"/Fp${_pch_c_pch}\" \"/Yu${_input}\"")
|
||||
set(_pch_compile_flags "${_pch_compile_flags} \"/Fp${_pch_c_pch}\" \"/Yu${_input_fullpath}\"")
|
||||
set(_pch_source_c_needed TRUE)
|
||||
set_source_files_properties("${_source}" PROPERTIES OBJECT_DEPENDS "${_pch_c_pch}")
|
||||
endif()
|
||||
if(_PCH_FORCEINCLUDE)
|
||||
set(_pch_compile_flags "${_pch_compile_flags} /FI${_input}")
|
||||
set(_pch_compile_flags "${_pch_compile_flags} /FI${_input_fullpath}")
|
||||
endif(_PCH_FORCEINCLUDE)
|
||||
endif()
|
||||
|
||||
|
5
deps/CMakeLists.txt
vendored
@ -75,7 +75,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()
|
||||
|
||||
|
76
deps/deps-mingw.cmake
vendored
Normal file
@ -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}
|
||||
)
|
7
deps/deps-unix-common.cmake
vendored
@ -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}
|
||||
)
|
||||
|
4
deps/deps-windows.cmake
vendored
@ -19,6 +19,10 @@ else ()
|
||||
message(FATAL_ERROR "Unsupported MSVC version")
|
||||
endif ()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
||||
set(DEP_BOOST_TOOLSET "clang-win")
|
||||
endif ()
|
||||
|
||||
if (${DEPS_BITS} EQUAL 32)
|
||||
set(DEP_MSVC_GEN "Visual Studio ${DEP_VS_VER}")
|
||||
# set(DEP_PLATFORM "Win32")
|
||||
|
@ -3,39 +3,23 @@
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="edit_x5F_layers_x5F_all">
|
||||
<path fill="#808080" d="M15,2.5H1C0.72,2.5,0.5,2.28,0.5,2S0.72,1.5,1,1.5h14c0.28,0,0.5,0.22,0.5,0.5S15.28,2.5,15,2.5z"/>
|
||||
<path fill="#808080" d="M15,4.5H1C0.72,4.5,0.5,4.28,0.5,4S0.72,3.5,1,3.5h14c0.28,0,0.5,0.22,0.5,0.5S15.28,4.5,15,4.5z"/>
|
||||
<path fill="#808080" d="M15,12.5H1c-0.28,0-0.5-0.22-0.5-0.5s0.22-0.5,0.5-0.5h14c0.28,0,0.5,0.22,0.5,0.5S15.28,12.5,15,12.5z"/>
|
||||
<path fill="#808080" d="M15,14.5H1c-0.28,0-0.5-0.22-0.5-0.5s0.22-0.5,0.5-0.5h14c0.28,0,0.5,0.22,0.5,0.5S15.28,14.5,15,14.5z"/>
|
||||
<g>
|
||||
<path fill="#808080" d="M5.86,10.36c-0.01,0.04-0.13-0.14-0.2-0.22l-0.2-0.02C5.16,10.1,4.85,9.89,4.73,9.6L4.69,9.5H1
|
||||
c-0.28,0-0.5,0.22-0.5,0.5s0.22,0.5,0.5,0.5h4.87L5.86,10.36z"/>
|
||||
<path fill="#808080" d="M15,9.5h-3.69l-0.04,0.1c-0.12,0.29-0.42,0.5-0.73,0.53l-0.18,0.01c0.04,0.01-0.13,0.13-0.21,0.2
|
||||
l-0.02,0.16H15c0.28,0,0.5-0.22,0.5-0.5S15.28,9.5,15,9.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M4.7,8.29l0.11-0.13c-0.03,0.02,0-0.19,0.01-0.3L4.7,7.71C4.65,7.65,4.61,7.58,4.58,7.5H1
|
||||
C0.72,7.5,0.5,7.72,0.5,8S0.72,8.5,1,8.5h3.58C4.61,8.42,4.65,8.35,4.7,8.29z"/>
|
||||
<path fill="#808080" d="M15,7.5h-3.58c-0.03,0.08-0.08,0.15-0.13,0.21l-0.11,0.13l-0.01,0.02c0.01,0.12,0.04,0.32,0.06,0.38
|
||||
l0.06,0.05c0.05,0.06,0.1,0.13,0.13,0.21H15c0.28,0,0.5-0.22,0.5-0.5S15.28,7.5,15,7.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M4.74,6.4c0.12-0.29,0.42-0.5,0.73-0.52l0.17-0.01C5.6,5.86,5.77,5.73,5.85,5.66L5.87,5.5H1
|
||||
C0.72,5.5,0.5,5.72,0.5,6S0.72,6.5,1,6.5h3.69L4.74,6.4z"/>
|
||||
<path fill="#808080" d="M15,5.5h-4.87l0.01,0.14c0-0.03,0.13,0.13,0.2,0.21l0.2,0.02c0.31,0.02,0.61,0.24,0.73,0.53l0.04,0.1H15
|
||||
c0.28,0,0.5-0.22,0.5-0.5S15.28,5.5,15,5.5z"/>
|
||||
</g>
|
||||
<path fill="#ED6B21" d="M10.67,7.89c-0.01-0.12,0.05-0.29,0.13-0.38l0.11-0.13c0.08-0.09,0.11-0.26,0.06-0.37L10.8,6.59
|
||||
c-0.05-0.11-0.18-0.21-0.3-0.22l-0.17-0.01c-0.12-0.01-0.28-0.09-0.36-0.18C9.89,6.1,9.65,5.79,9.64,5.67L9.63,5.5
|
||||
C9.62,5.38,9.52,5.24,9.41,5.2L8.99,5.02C8.88,4.98,8.71,5,8.62,5.08L8.49,5.2C8.4,5.28,8.22,5.33,8.11,5.33
|
||||
C7.99,5.32,7.6,5.27,7.51,5.2L7.38,5.08C7.29,5,7.13,4.98,7.01,5.02L6.59,5.2C6.48,5.24,6.38,5.38,6.37,5.5L6.36,5.67
|
||||
C6.35,5.79,6.27,5.95,6.19,6.03S5.79,6.35,5.67,6.36L5.5,6.37C5.38,6.38,5.24,6.48,5.2,6.59L5.02,7.01C4.98,7.12,5,7.29,5.08,7.38
|
||||
L5.2,7.51C5.28,7.6,5.33,7.78,5.33,7.89C5.32,8.01,5.27,8.4,5.2,8.49L5.08,8.62C5,8.71,4.98,8.87,5.02,8.99L5.2,9.41
|
||||
c0.05,0.11,0.18,0.21,0.3,0.22l0.17,0.01c0.12,0.01,0.28,0.09,0.36,0.18c0.08,0.09,0.32,0.39,0.33,0.51l0.01,0.17
|
||||
c0.01,0.12,0.11,0.26,0.22,0.3l0.42,0.17c0.11,0.05,0.28,0.02,0.37-0.06l0.13-0.11c0.09-0.08,0.26-0.14,0.38-0.13
|
||||
c0.12,0.01,0.5,0.05,0.59,0.13l0.13,0.11c0.09,0.08,0.26,0.11,0.37,0.06l0.42-0.17c0.11-0.05,0.21-0.18,0.22-0.3l0.01-0.17
|
||||
c0.01-0.12,0.09-0.28,0.18-0.36c0.09-0.08,0.39-0.32,0.51-0.33l0.17-0.01c0.12-0.01,0.26-0.11,0.3-0.22l0.17-0.42
|
||||
c0.05-0.11,0.02-0.28-0.06-0.37L10.8,8.49C10.72,8.4,10.68,8.01,10.67,7.89z M8,9.8c-0.99,0-1.8-0.8-1.8-1.8S7.01,6.2,8,6.2
|
||||
S9.8,7.01,9.8,8S8.99,9.8,8,9.8z"/>
|
||||
<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="2" x2="6" y2="2"/>
|
||||
<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="6" x2="6" y2="6"/>
|
||||
|
||||
<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="10" x2="14" y2="10"/>
|
||||
|
||||
<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="14" x2="14" y2="14"/>
|
||||
<path fill="#ED6B21" d="M14.62,4.37c-0.01-0.14,0.06-0.34,0.15-0.44l0.13-0.15c0.09-0.11,0.12-0.3,0.07-0.43l-0.2-0.49
|
||||
c-0.05-0.13-0.21-0.24-0.35-0.25l-0.2-0.01c-0.14-0.01-0.33-0.1-0.42-0.21c-0.09-0.1-0.37-0.46-0.38-0.6l-0.01-0.2
|
||||
c-0.01-0.14-0.12-0.3-0.25-0.35l-0.49-0.2C12.52,0.97,12.33,1,12.22,1.1l-0.15,0.13c-0.11,0.09-0.31,0.16-0.44,0.15
|
||||
c-0.14-0.01-0.59-0.06-0.69-0.15L10.78,1.1c-0.11-0.09-0.3-0.12-0.43-0.07l-0.49,0.2C9.73,1.28,9.61,1.44,9.6,1.58l-0.01,0.2
|
||||
C9.58,1.92,9.49,2.11,9.38,2.2c-0.1,0.09-0.46,0.37-0.6,0.38L8.58,2.6c-0.14,0.01-0.3,0.12-0.35,0.25l-0.2,0.49
|
||||
C7.97,3.48,8,3.67,8.1,3.78l0.13,0.15c0.09,0.11,0.16,0.31,0.15,0.44C8.37,4.52,8.32,4.96,8.23,5.07L8.1,5.22
|
||||
C8,5.33,7.97,5.52,8.03,5.65l0.2,0.49C8.28,6.27,8.44,6.39,8.58,6.4l0.2,0.01c0.14,0.01,0.33,0.1,0.42,0.21
|
||||
c0.09,0.1,0.37,0.46,0.38,0.6l0.01,0.2c0.01,0.14,0.12,0.3,0.25,0.35l0.49,0.2C10.48,8.03,10.67,8,10.78,7.9l0.15-0.13
|
||||
c0.11-0.09,0.31-0.16,0.44-0.15c0.14,0.01,0.59,0.06,0.69,0.15l0.15,0.13c0.11,0.09,0.3,0.12,0.43,0.07l0.49-0.2
|
||||
c0.13-0.05,0.24-0.21,0.25-0.35l0.01-0.2c0.01-0.14,0.1-0.33,0.21-0.42s0.46-0.37,0.6-0.38l0.2-0.01c0.14-0.01,0.3-0.12,0.35-0.25
|
||||
l0.2-0.49C15.03,5.52,15,5.33,14.9,5.22l-0.13-0.15C14.68,4.96,14.63,4.51,14.62,4.37z M11.5,6.6c-1.16,0-2.1-0.94-2.1-2.1
|
||||
s0.94-2.1,2.1-2.1s2.1,0.94,2.1,2.1S12.66,6.6,11.5,6.6z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 2.2 KiB |
@ -2,68 +2,13 @@
|
||||
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="edit_x5F_layers_x5F_some">
|
||||
<g>
|
||||
<path fill="#808080" d="M15,2.5H1C0.72,2.5,0.5,2.28,0.5,2S0.72,1.5,1,1.5h14c0.28,0,0.5,0.22,0.5,0.5S15.28,2.5,15,2.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#808080" d="M15,4.5h-2.5C12.22,4.5,12,4.28,12,4s0.22-0.5,0.5-0.5H15c0.28,0,0.5,0.22,0.5,0.5S15.28,4.5,15,4.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M9.5,4.5h-3C6.22,4.5,6,4.28,6,4s0.22-0.5,0.5-0.5h3C9.78,3.5,10,3.72,10,4S9.78,4.5,9.5,4.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M3.5,4.5H1C0.72,4.5,0.5,4.28,0.5,4S0.72,3.5,1,3.5h2.5C3.78,3.5,4,3.72,4,4S3.78,4.5,3.5,4.5z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#808080" d="M15,8.5h-2.5C12.22,8.5,12,8.28,12,8s0.22-0.5,0.5-0.5H15c0.28,0,0.5,0.22,0.5,0.5S15.28,8.5,15,8.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M3.5,8.5H1C0.72,8.5,0.5,8.28,0.5,8S0.72,7.5,1,7.5h2.5C3.78,7.5,4,7.72,4,8S3.78,8.5,3.5,8.5z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#808080" d="M15,12.5h-2.5c-0.28,0-0.5-0.22-0.5-0.5s0.22-0.5,0.5-0.5H15c0.28,0,0.5,0.22,0.5,0.5S15.28,12.5,15,12.5
|
||||
z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M9.5,12.5h-3C6.22,12.5,6,12.28,6,12s0.22-0.5,0.5-0.5h3c0.28,0,0.5,0.22,0.5,0.5S9.78,12.5,9.5,12.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M3.5,12.5H1c-0.28,0-0.5-0.22-0.5-0.5s0.22-0.5,0.5-0.5h2.5C3.78,11.5,4,11.72,4,12S3.78,12.5,3.5,12.5z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M15,14.5H1c-0.28,0-0.5-0.22-0.5-0.5s0.22-0.5,0.5-0.5h14c0.28,0,0.5,0.22,0.5,0.5S15.28,14.5,15,14.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M15,9.5h-3.69l-0.04,0.1c-0.12,0.29-0.42,0.5-0.73,0.53l-0.18,0.01c0.04,0.01-0.13,0.13-0.21,0.2
|
||||
l-0.02,0.16H15c0.28,0,0.5-0.22,0.5-0.5S15.28,9.5,15,9.5z"/>
|
||||
<path fill="#808080" d="M5.86,10.36c-0.01,0.04-0.13-0.14-0.2-0.22l-0.2-0.02C5.16,10.1,4.85,9.89,4.73,9.6L4.69,9.5H1
|
||||
c-0.28,0-0.5,0.22-0.5,0.5s0.22,0.5,0.5,0.5h4.87L5.86,10.36z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M4.74,6.4c0.12-0.29,0.42-0.5,0.73-0.52l0.17-0.01C5.6,5.86,5.77,5.73,5.85,5.66L5.87,5.5H1
|
||||
C0.72,5.5,0.5,5.72,0.5,6S0.72,6.5,1,6.5h3.69L4.74,6.4z"/>
|
||||
<path fill="#808080" d="M15,5.5h-4.87l0.01,0.14c0-0.03,0.13,0.13,0.2,0.21l0.2,0.02c0.31,0.02,0.61,0.24,0.73,0.53l0.04,0.1H15
|
||||
c0.28,0,0.5-0.22,0.5-0.5S15.28,5.5,15,5.5z"/>
|
||||
</g>
|
||||
<path fill="#ED6B21" d="M10.67,7.89c-0.01-0.12,0.05-0.29,0.13-0.38l0.11-0.13c0.08-0.09,0.11-0.26,0.06-0.37L10.8,6.59
|
||||
c-0.05-0.11-0.18-0.21-0.3-0.22l-0.17-0.01c-0.12-0.01-0.28-0.09-0.36-0.18C9.89,6.1,9.65,5.79,9.64,5.67L9.63,5.5
|
||||
C9.62,5.38,9.52,5.24,9.41,5.2L8.99,5.02C8.88,4.98,8.71,5,8.62,5.08L8.49,5.2C8.4,5.28,8.22,5.33,8.11,5.33
|
||||
C7.99,5.32,7.6,5.27,7.51,5.2L7.38,5.08C7.29,5,7.13,4.98,7.01,5.02L6.59,5.2C6.48,5.24,6.38,5.38,6.37,5.5L6.36,5.67
|
||||
C6.35,5.79,6.27,5.95,6.19,6.03S5.79,6.35,5.67,6.36L5.5,6.37C5.38,6.38,5.24,6.48,5.2,6.59L5.02,7.01C4.98,7.12,5,7.29,5.08,7.38
|
||||
L5.2,7.51C5.28,7.6,5.33,7.78,5.33,7.89C5.32,8.01,5.27,8.4,5.2,8.49L5.08,8.62C5,8.71,4.98,8.87,5.02,8.99L5.2,9.41
|
||||
c0.05,0.11,0.18,0.21,0.3,0.22l0.17,0.01c0.12,0.01,0.28,0.09,0.36,0.18c0.08,0.09,0.32,0.39,0.33,0.51l0.01,0.17
|
||||
c0.01,0.12,0.11,0.26,0.22,0.3l0.42,0.17c0.11,0.05,0.28,0.02,0.37-0.06l0.13-0.11c0.09-0.08,0.26-0.14,0.38-0.13
|
||||
c0.12,0.01,0.5,0.05,0.59,0.13l0.13,0.11c0.09,0.08,0.26,0.11,0.37,0.06l0.42-0.17c0.11-0.05,0.21-0.18,0.22-0.3l0.01-0.17
|
||||
c0.01-0.12,0.09-0.28,0.18-0.36c0.09-0.08,0.39-0.32,0.51-0.33l0.17-0.01c0.12-0.01,0.26-0.11,0.3-0.22l0.17-0.42
|
||||
c0.05-0.11,0.02-0.28-0.06-0.37L10.8,8.49C10.72,8.4,10.68,8.01,10.67,7.89z M8,9.8c-0.99,0-1.8-0.8-1.8-1.8S7.01,6.2,8,6.2
|
||||
S9.8,7.01,9.8,8S8.99,9.8,8,9.8z"/>
|
||||
<g id="edit_x5F_layers_x5F_some_1_">
|
||||
|
||||
<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="11" x2="14" y2="11"/>
|
||||
|
||||
<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="14" x2="14" y2="14"/>
|
||||
<path fill="#ED6B21" d="M7.68,8.87c0.18,0.18,0.47,0.18,0.64,0L11.19,6c0.18-0.18,0.12-0.32-0.13-0.32H9.62
|
||||
c-0.25,0-0.45-0.2-0.45-0.45V1.45C9.17,1.2,8.97,1,8.71,1H7.29C7.03,1,6.83,1.2,6.83,1.45v3.77c0,0.25-0.2,0.45-0.45,0.45H4.95
|
||||
C4.7,5.68,4.64,5.82,4.81,6L7.68,8.87z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 931 B |
13
resources/icons/eye_closed.svg
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="eye_x5F_close">
|
||||
<path fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
|
||||
M2,8c0,0,2,4,6,4s6-4,6-4s-2-4-6-4S2,8,2,8z"/>
|
||||
|
||||
<circle fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" cx="8" cy="8" r="1"/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="2" y1="14" x2="14" y2="2"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 856 B |
11
resources/icons/eye_open.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="eye_x5F_open">
|
||||
<path fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
|
||||
M2,8c0,0,2,4,6,4s6-4,6-4s-2-4-6-4S2,8,2,8z"/>
|
||||
|
||||
<circle fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" cx="8" cy="8" r="1"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 697 B |
10
resources/icons/lock_closed_f.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="lock_x5F_closed">
|
||||
<path fill="none" stroke="#808080" stroke-width="3" stroke-miterlimit="9" d="M4,8V4c0,0,0-2,2-2c1,0,3,0,4,0c2,0,2,2,2,2v4"/>
|
||||
<path fill="#808080" d="M13,8H3C2.45,8,2,8.45,2,9v5c0,0.55,0.45,1,1,1h10c0.55,0,1-0.45,1-1V9C14,8.45,13.55,8,13,8z M10,12H8.91
|
||||
c-0.21,0.58-0.76,1-1.41,1C6.67,13,6,12.33,6,11.5S6.67,10,7.5,10c0.65,0,1.2,0.42,1.41,1H10V12z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 728 B |
11
resources/icons/lock_open_f.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="lock_x5F_open">
|
||||
<path fill="none" stroke="#ED6B21" stroke-width="3" stroke-linecap="round" stroke-miterlimit="10" d="M4,8V4c0,0,0-2,2-2
|
||||
c1,0,3,0,4,0c2,0,2,2,2,2v1"/>
|
||||
<path fill="#ED6B21" d="M13,8H3C2.45,8,2,8.45,2,9v5c0,0.55,0.45,1,1,1h10c0.55,0,1-0.45,1-1V9C14,8.45,13.55,8,13,8z M10,12H8.91
|
||||
c-0.21,0.58-0.76,1-1.41,1C6.67,13,6,12.33,6,11.5S6.67,10,7.5,10c0.65,0,1.2,0.42,1.41,1H10V12z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 753 B |
@ -4,19 +4,19 @@
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="mirror_x5F_off">
|
||||
<g>
|
||||
<path fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" d="M10,3.01l4,0c0.55,0,1,0.45,1,1v8
|
||||
c0,0.55-0.45,1-1,1h-4"/>
|
||||
<path fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
|
||||
M10,3.01l3,0c0.55,0,1,0.45,1,1v8c0,0.55-0.45,1-1,1h-3"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" d="M6,3.01L2,3C1.45,3,1,3.45,1,4v8
|
||||
c0,0.55,0.45,1,1,1h4"/>
|
||||
<path fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
|
||||
M6,3.01L3,3C2.45,3,2,3.45,2,4v8c0,0.55,0.45,1,1,1h3"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="1" x2="8" y2="3.5"/>
|
||||
<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="1" x2="8" y2="3.5"/>
|
||||
|
||||
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,3" x1="8" y1="6.5" x2="8" y2="11"/>
|
||||
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="12.5" x2="8" y2="15"/>
|
||||
<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,3" x1="8" y1="6.5" x2="8" y2="11"/>
|
||||
<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="12.5" x2="8" y2="15"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@ -2,21 +2,21 @@
|
||||
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="mirror_x5F_off_1_">
|
||||
<g id="mirror_x5F_on">
|
||||
<g>
|
||||
<path fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" d="M10,3.01l4,0c0.55,0,1,0.45,1,1v8
|
||||
c0,0.55-0.45,1-1,1h-4"/>
|
||||
<path fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" d="M10,3.01l3,0
|
||||
c0.55,0,1,0.45,1,1v8c0,0.55-0.45,1-1,1h-3"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-miterlimit="10" d="M6,3.01L2,3C1.45,3,1,3.45,1,4v8
|
||||
c0,0.55,0.45,1,1,1h4"/>
|
||||
<path fill="none" stroke="#ED6B21" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" d="M6,3.01L3,3
|
||||
C2.45,3,2,3.45,2,4v8c0,0.55,0.45,1,1,1h3"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="1" x2="8" y2="3.5"/>
|
||||
<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="1" x2="8" y2="3.5"/>
|
||||
|
||||
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,3" x1="8" y1="6.5" x2="8" y2="11"/>
|
||||
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="12.5" x2="8" y2="15"/>
|
||||
<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,3" x1="8" y1="6.5" x2="8" y2="11"/>
|
||||
<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="12.5" x2="8" y2="15"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@ -1,3 +1,7 @@
|
||||
min_slic3r_version = 2.1.0-alpha0
|
||||
1.0.0-beta1 Updated color for the ASA filaments to differ from the other filaments. Single extruder printers now have no extruder color assigned, obects and toolpaths will be colored with the color of the active filament.
|
||||
1.0.0-beta0 Printer model checks in start G-codes, ASA filament profiles, limits on min / max SL1 exposition times
|
||||
1.0.0-alpha0 Filament specific retract for PET and similar copolymers, and for FLEX
|
||||
min_slic3r_version = 1.42.0-alpha6
|
||||
0.8.3 FW version and SL1 materials update
|
||||
0.8.2 FFF and SL1 settings update
|
||||
|
@ -8,7 +8,7 @@ technologies = FFF; SLA
|
||||
|
||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
||||
# This means, the server may force the PrusaSlicer configuration to be downgraded.
|
||||
config_version = 0.8.3
|
||||
config_version = 1.0.0-beta1
|
||||
# Where to get the updates from?
|
||||
config_update_url = http://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaResearch/
|
||||
changelog_url = http://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||
@ -821,7 +821,7 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and
|
||||
# MK2 MMU #
|
||||
[print:0.35mm FAST sol full 0.6 nozzle]
|
||||
inherits = *0.35mm*; *0.6nozzle*; *soluble_support*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.6 and num_extruders>1
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_model=="MK2SMM" and nozzle_diameter[0]==0.6 and num_extruders>1
|
||||
external_perimeter_extrusion_width = 0.6
|
||||
external_perimeter_speed = 30
|
||||
notes = Set your solluble extruder in Multiple Extruders > Support material/raft interface extruder
|
||||
@ -886,8 +886,8 @@ solid_infill_speed = 70
|
||||
top_solid_infill_speed = 45
|
||||
external_perimeter_extrusion_width = 0.7
|
||||
perimeter_extrusion_width = 0.7
|
||||
infill_extrusion_width = 0.72
|
||||
solid_infill_extrusion_width = 0.72
|
||||
infill_extrusion_width = 0.7
|
||||
solid_infill_extrusion_width = 0.7
|
||||
|
||||
# XXXXXXXXXXXXXXXXXXXXXX
|
||||
# XXX----- MK2.5 ----XXX
|
||||
@ -1019,12 +1019,22 @@ max_fan_speed = 50
|
||||
min_fan_speed = 30
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}24{else}45{endif} ; Filament gcode"
|
||||
temperature = 240
|
||||
filament_retract_length = 1.4
|
||||
filament_retract_lift = 0.2
|
||||
compatible_printers_condition = printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
|
||||
[filament:*PET06*]
|
||||
inherits = *PET*
|
||||
compatible_printers_condition = nozzle_diameter[0]==0.6 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
compatible_printers_condition = nozzle_diameter[0]==0.6 and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
filament_max_volumetric_speed = 15
|
||||
|
||||
[filament:*PETMMU1*]
|
||||
inherits = *PET*
|
||||
filament_retract_length = nil
|
||||
filament_retract_speed = nil
|
||||
filament_retract_lift = 0.2
|
||||
compatible_printers_condition = printer_model=="MK2SMM"
|
||||
|
||||
[filament:*ABS*]
|
||||
inherits = *common*
|
||||
bed_temperature = 110
|
||||
@ -1049,7 +1059,7 @@ inherits = *common*
|
||||
bed_temperature = 50
|
||||
bridge_fan_speed = 100
|
||||
# For now, all but selected filaments are disabled for the MMU 2.0
|
||||
compatible_printers_condition = nozzle_diameter[0]>0.35 and num_extruders==1 && ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material)
|
||||
compatible_printers_condition = nozzle_diameter[0]>0.35 and printer_model!="MK2SMM" and num_extruders==1 && ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material)
|
||||
cooling = 0
|
||||
disable_fan_first_layers = 1
|
||||
extrusion_multiplier = 1.2
|
||||
@ -1062,8 +1072,10 @@ first_layer_bed_temperature = 50
|
||||
first_layer_temperature = 240
|
||||
max_fan_speed = 90
|
||||
min_fan_speed = 70
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode"
|
||||
start_filament_gcode = "M900 K0"; Filament gcode"
|
||||
temperature = 240
|
||||
filament_retract_length = 0.4
|
||||
filament_retract_lift = 0
|
||||
|
||||
[filament:ColorFabb Brass Bronze]
|
||||
inherits = *PLA*
|
||||
@ -1134,7 +1146,7 @@ temperature = 270
|
||||
|
||||
[filament:ColorFabb XT-CF20]
|
||||
inherits = *PET*
|
||||
compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
compatible_printers_condition = nozzle_diameter[0]>0.35 and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
extrusion_multiplier = 1.2
|
||||
filament_cost = 80.65
|
||||
filament_density = 1.35
|
||||
@ -1144,6 +1156,8 @@ first_layer_bed_temperature = 90
|
||||
first_layer_temperature = 260
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode"
|
||||
temperature = 260
|
||||
filament_retract_length = nil
|
||||
filament_retract_lift = 0.2
|
||||
|
||||
[filament:ColorFabb nGen]
|
||||
inherits = *PET*
|
||||
@ -1173,13 +1187,15 @@ first_layer_temperature = 260
|
||||
max_fan_speed = 35
|
||||
min_fan_speed = 20
|
||||
temperature = 260
|
||||
filament_retract_length = nil
|
||||
filament_retract_lift = 0
|
||||
compatible_printers_condition = nozzle_diameter[0]>0.35 and num_extruders==1 && ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material)
|
||||
|
||||
[filament:E3D Edge]
|
||||
inherits = *PET*
|
||||
filament_cost = 56.9
|
||||
filament_density = 1.26
|
||||
filament_type = EDGE
|
||||
filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
|
||||
|
||||
[filament:E3D PC-ABS]
|
||||
inherits = *ABS*
|
||||
@ -1199,17 +1215,31 @@ temperature = 240
|
||||
[filament:Fillamentum ASA]
|
||||
inherits = *ABS*
|
||||
filament_cost = 38.7
|
||||
filament_density = 1.04
|
||||
filament_density = 1.07
|
||||
fan_always_on = 1
|
||||
first_layer_temperature = 265
|
||||
temperature = 265
|
||||
filament_type = ASA
|
||||
|
||||
[filament:Fillamentum CPE HG100 HM100]
|
||||
[filament:Prusament ASA]
|
||||
inherits = *ABS*
|
||||
filament_cost = 35.28
|
||||
filament_density = 1.07
|
||||
fan_always_on = 1
|
||||
first_layer_temperature = 260
|
||||
first_layer_bed_temperature = 105
|
||||
temperature = 260
|
||||
bed_temperature = 110
|
||||
min_fan_speed = 20
|
||||
disable_fan_first_layers = 4
|
||||
filament_type = ASA
|
||||
filament_colour = #FFF2EC
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}12{else}20{endif} ; Filament gcode"
|
||||
|
||||
[filament:Fillamentum CPE]
|
||||
inherits = *PET*
|
||||
filament_cost = 54.1
|
||||
filament_density = 1.25
|
||||
filament_notes = "CPE HG100 , CPE HM100"
|
||||
filament_type = CPE
|
||||
first_layer_bed_temperature = 90
|
||||
first_layer_temperature = 275
|
||||
@ -1248,6 +1278,15 @@ filament_cost = 25.4
|
||||
filament_density = 1.24
|
||||
filament_notes = "List of materials tested with standard PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH"
|
||||
|
||||
[filament:Generic FLEX]
|
||||
inherits = *FLEX*
|
||||
filament_cost = 82
|
||||
filament_density = 1.22
|
||||
filament_max_volumetric_speed = 1.2
|
||||
filament_retract_length = 0
|
||||
filament_retract_speed = nil
|
||||
filament_retract_lift = nil
|
||||
|
||||
[filament:Polymaker PC-Max]
|
||||
inherits = *ABS*
|
||||
filament_cost = 77.3
|
||||
@ -1297,6 +1336,24 @@ filament_unloading_speed = 20
|
||||
[filament:Generic ABS MMU2]
|
||||
inherits = *ABS MMU2*
|
||||
|
||||
[filament:Prusament ASA MMU2]
|
||||
inherits = *ABS MMU2*
|
||||
filament_cost = 35.28
|
||||
filament_density = 1.07
|
||||
fan_always_on = 1
|
||||
first_layer_temperature = 260
|
||||
first_layer_bed_temperature = 105
|
||||
temperature = 260
|
||||
bed_temperature = 110
|
||||
min_fan_speed = 20
|
||||
disable_fan_first_layers = 4
|
||||
filament_cooling_final_speed = 2
|
||||
filament_cooling_initial_speed = 3
|
||||
filament_cooling_moves = 1
|
||||
filament_type = ASA
|
||||
filament_colour = #FFF2EC
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}12{else}20{endif} ; Filament gcode"
|
||||
|
||||
[filament:Prusa ABS MMU2]
|
||||
inherits = *ABS MMU2*
|
||||
|
||||
@ -1323,7 +1380,7 @@ inherits = *PET*
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.27
|
||||
filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nPlasty Mladec PETG"
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.6 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.6 and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
|
||||
[filament:Prusament PETG]
|
||||
inherits = *PET*
|
||||
@ -1332,7 +1389,7 @@ temperature = 250
|
||||
filament_cost = 24.99
|
||||
filament_density = 1.27
|
||||
filament_type = PETG
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.6 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.6 and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
|
||||
[filament:Prusa PET 0.6 nozzle]
|
||||
inherits = *PET06*
|
||||
@ -1350,7 +1407,7 @@ filament_type = PETG
|
||||
|
||||
[filament:*PET MMU2*]
|
||||
inherits = Prusa PET
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.6 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
temperature = 230
|
||||
first_layer_temperature = 230
|
||||
filament_cooling_final_speed = 1
|
||||
@ -1364,6 +1421,13 @@ filament_unload_time = 12
|
||||
filament_unloading_speed = 20
|
||||
filament_unloading_speed_start = 120
|
||||
filament_loading_speed_start = 19
|
||||
filament_retract_length = 1.4
|
||||
filament_retract_lift = 0.2
|
||||
|
||||
[filament:*PET MMU2 06*]
|
||||
inherits = *PET MMU2*
|
||||
compatible_printers_condition = nozzle_diameter[0]==0.6 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
filament_max_volumetric_speed = 13
|
||||
|
||||
[filament:Generic PET MMU2]
|
||||
inherits = *PET MMU2*
|
||||
@ -1375,6 +1439,16 @@ inherits = *PET MMU2*
|
||||
inherits = *PET MMU2*
|
||||
filament_type = PETG
|
||||
|
||||
[filament:Generic PET MMU2 0.6 nozzle]
|
||||
inherits = *PET MMU2 06*
|
||||
|
||||
[filament:Prusa PET MMU2 0.6 nozzle]
|
||||
inherits = *PET MMU2 06*
|
||||
|
||||
[filament:Prusament PETG MMU2 0.6 nozzle]
|
||||
inherits = *PET MMU2 06*
|
||||
filament_type = PETG
|
||||
|
||||
[filament:Prusa PLA]
|
||||
inherits = *PLA*
|
||||
filament_cost = 25.4
|
||||
@ -1417,6 +1491,7 @@ inherits = *PLA MMU2*
|
||||
inherits = *FLEX*
|
||||
filament_cost = 82
|
||||
filament_density = 1.22
|
||||
filament_max_volumetric_speed = 1.35
|
||||
|
||||
[filament:Taulman Bridge]
|
||||
inherits = *common*
|
||||
@ -1554,6 +1629,130 @@ min_fan_speed = 100
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode"
|
||||
temperature = 220
|
||||
|
||||
## Filaments MMU1
|
||||
|
||||
[filament:ColorFabb HT MMU1]
|
||||
inherits = *PETMMU1*
|
||||
bed_temperature = 110
|
||||
bridge_fan_speed = 30
|
||||
cooling = 1
|
||||
disable_fan_first_layers = 3
|
||||
fan_always_on = 0
|
||||
fan_below_layer_time = 10
|
||||
filament_cost = 58.66
|
||||
filament_density = 1.18
|
||||
first_layer_bed_temperature = 105
|
||||
first_layer_temperature = 270
|
||||
max_fan_speed = 20
|
||||
min_fan_speed = 10
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}45{endif}; Filament gcode"
|
||||
temperature = 270
|
||||
|
||||
[filament:ColorFabb XT MMU1]
|
||||
inherits = *PETMMU1*
|
||||
filament_type = PET
|
||||
filament_cost = 62.9
|
||||
filament_density = 1.27
|
||||
first_layer_bed_temperature = 90
|
||||
first_layer_temperature = 260
|
||||
temperature = 270
|
||||
|
||||
[filament:ColorFabb XT-CF20 MMU1]
|
||||
inherits = *PETMMU1*
|
||||
compatible_printers_condition = nozzle_diameter[0]>0.35 and printer_model=="MK2SMM"
|
||||
extrusion_multiplier = 1.2
|
||||
filament_cost = 80.65
|
||||
filament_density = 1.35
|
||||
filament_colour = #804040
|
||||
filament_max_volumetric_speed = 1
|
||||
first_layer_bed_temperature = 90
|
||||
first_layer_temperature = 260
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode"
|
||||
temperature = 260
|
||||
|
||||
[filament:ColorFabb nGen MMU1]
|
||||
inherits = *PETMMU1*
|
||||
filament_cost = 21.2
|
||||
filament_density = 1.2
|
||||
bridge_fan_speed = 40
|
||||
fan_always_on = 0
|
||||
fan_below_layer_time = 10
|
||||
filament_type = NGEN
|
||||
first_layer_temperature = 240
|
||||
max_fan_speed = 35
|
||||
min_fan_speed = 20
|
||||
|
||||
[filament:E3D Edge MMU1]
|
||||
inherits = *PETMMU1*
|
||||
filament_cost = 56.9
|
||||
filament_density = 1.26
|
||||
filament_type = EDGE
|
||||
filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
|
||||
|
||||
[filament:Fillamentum CPE MMU1]
|
||||
inherits = *PETMMU1*
|
||||
filament_cost = 54.1
|
||||
filament_density = 1.25
|
||||
filament_type = CPE
|
||||
first_layer_bed_temperature = 90
|
||||
first_layer_temperature = 275
|
||||
max_fan_speed = 50
|
||||
min_fan_speed = 50
|
||||
temperature = 275
|
||||
|
||||
[filament:Generic PET MMU1]
|
||||
inherits = *PETMMU1*
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.27
|
||||
filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
|
||||
|
||||
[filament:Prusa PET MMU1]
|
||||
inherits = *PETMMU1*
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.27
|
||||
filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nPlasty Mladec PETG"
|
||||
|
||||
[filament:Prusament PETG MMU1]
|
||||
inherits = *PETMMU1*
|
||||
first_layer_temperature = 240
|
||||
temperature = 250
|
||||
filament_cost = 24.99
|
||||
filament_density = 1.27
|
||||
filament_type = PETG
|
||||
|
||||
[filament:Taulman T-Glase MMU1]
|
||||
inherits = *PETMMU1*
|
||||
filament_cost = 40
|
||||
filament_density = 1.27
|
||||
bridge_fan_speed = 40
|
||||
cooling = 0
|
||||
fan_always_on = 0
|
||||
first_layer_bed_temperature = 90
|
||||
first_layer_temperature = 240
|
||||
max_fan_speed = 5
|
||||
min_fan_speed = 0
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode"
|
||||
|
||||
[filament:SemiFlex or Flexfill 98A MMU1]
|
||||
inherits = *FLEX*
|
||||
filament_cost = 82
|
||||
filament_density = 1.22
|
||||
filament_max_volumetric_speed = 1.35
|
||||
filament_retract_length = nil
|
||||
filament_retract_speed = nil
|
||||
filament_retract_lift = nil
|
||||
compatible_printers_condition = printer_model=="MK2SMM"
|
||||
|
||||
[filament:Generic FLEX MMU1]
|
||||
inherits = *FLEX*
|
||||
filament_cost = 82
|
||||
filament_density = 1.22
|
||||
filament_max_volumetric_speed = 1.2
|
||||
filament_retract_length = 0
|
||||
filament_retract_speed = nil
|
||||
filament_retract_lift = nil
|
||||
compatible_printers_condition = printer_model=="MK2SMM"
|
||||
|
||||
[sla_print:*common*]
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_SL1.*/
|
||||
layer_height = 0.05
|
||||
@ -1658,37 +1857,37 @@ initial_exposure_time = 100
|
||||
[sla_material:Prusa Orange Tough 0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 6
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa Grey Tough 0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 7
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa Azure Blue Tough 0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 7
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa Maroon Tough 0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 6
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa Beige Tough 0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 6
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa Pink Tough 0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 7
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa White Tough 0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 6.5
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa Transparent Tough 0.025]
|
||||
inherits = *common 0.025*
|
||||
@ -1703,7 +1902,7 @@ initial_exposure_time = 35
|
||||
## [sla_material:Prusa Transparent Green Tough 0.025]
|
||||
## inherits = *common 0.025*
|
||||
## exposure_time = 5
|
||||
## initial_exposure_time = 30
|
||||
## initial_exposure_time = 35
|
||||
|
||||
########### Materials 0.05
|
||||
|
||||
@ -1822,42 +2021,42 @@ initial_exposure_time = 30
|
||||
[sla_material:Prusa Beige Tough 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa Orange Tough 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7.5
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa Grey Tough 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 8.5
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa Black Tough 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 6
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
## [sla_material:Prusa Beige Super Low Odor 0.05]
|
||||
## inherits = *common 0.05*
|
||||
## exposure_time = 7.5
|
||||
## initial_exposure_time = 30
|
||||
## initial_exposure_time = 35
|
||||
|
||||
## [sla_material:Prusa White Super Low Odor 0.05]
|
||||
## inherits = *common 0.05*
|
||||
## exposure_time = 6.5
|
||||
## initial_exposure_time = 30
|
||||
## initial_exposure_time = 35
|
||||
|
||||
## [sla_material:Prusa Grey Super Low Odor 0.05]
|
||||
## inherits = *common 0.05*
|
||||
## exposure_time = 6.5
|
||||
## initial_exposure_time = 30
|
||||
## initial_exposure_time = 35
|
||||
|
||||
## [sla_material:Prusa Black High Tenacity 0.05]
|
||||
## inherits = *common 0.05*
|
||||
## exposure_time = 7
|
||||
## initial_exposure_time = 30
|
||||
## initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa Green Casting 0.05]
|
||||
inherits = *common 0.05*
|
||||
@ -1867,37 +2066,37 @@ initial_exposure_time = 40
|
||||
## [sla_material:Prusa Yellow Solid 0.05]
|
||||
## inherits = *common 0.05*
|
||||
## exposure_time = 7
|
||||
## initial_exposure_time = 30
|
||||
## initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa White Tough 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7.5
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
## [sla_material:Prusa Transparent Green Tough 0.05]
|
||||
## inherits = *common 0.05*
|
||||
## exposure_time = 6
|
||||
## initial_exposure_time = 30
|
||||
## initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa Transparent Red Tough 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 6
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa Maroon Tough 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7.5
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa Pink Tough 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 8
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa Azure Blue Tough 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 8
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa Transparent Tough 0.05]
|
||||
inherits = *common 0.05*
|
||||
@ -1907,7 +2106,7 @@ initial_exposure_time = 15
|
||||
## [sla_material:Prusa Yellow Flexible 0.05]
|
||||
## inherits = *common 0.05*
|
||||
## exposure_time = 9
|
||||
## initial_exposure_time = 30
|
||||
## initial_exposure_time = 35
|
||||
|
||||
## [sla_material:Prusa Clear Flexible 0.05]
|
||||
## inherits = *common 0.05*
|
||||
@ -1917,29 +2116,29 @@ initial_exposure_time = 15
|
||||
## [sla_material:Prusa White Flexible 0.05]
|
||||
## inherits = *common 0.05*
|
||||
## exposure_time = 9
|
||||
## initial_exposure_time = 30
|
||||
## initial_exposure_time = 35
|
||||
|
||||
## [sla_material:Prusa Blue Flexible 0.05]
|
||||
## inherits = *common 0.05*
|
||||
## exposure_time = 9
|
||||
## initial_exposure_time = 30
|
||||
## initial_exposure_time = 35
|
||||
|
||||
## [sla_material:Prusa Black Flexible 0.05]
|
||||
## inherits = *common 0.05*
|
||||
## exposure_time = 9
|
||||
## initial_exposure_time = 30
|
||||
## initial_exposure_time = 35
|
||||
|
||||
## [sla_material:Prusa Red Flexible 0.05]
|
||||
## inherits = *common 0.05*
|
||||
## exposure_time = 9
|
||||
## initial_exposure_time = 30
|
||||
## initial_exposure_time = 35
|
||||
|
||||
########### Materials 0.035
|
||||
|
||||
[sla_material:Prusa Orange Tough 0.035]
|
||||
inherits = *common 0.035*
|
||||
exposure_time = 6
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
########### Materials 0.1
|
||||
|
||||
@ -1981,7 +2180,7 @@ initial_exposure_time = 55
|
||||
[sla_material:Prusa Transparent Tough 0.1]
|
||||
inherits = *common 0.1*
|
||||
exposure_time = 8
|
||||
initial_exposure_time = 30
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:Prusa Green Casting 0.1]
|
||||
inherits = *common 0.1*
|
||||
@ -1995,7 +2194,6 @@ before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0.0\n;[layer_z]\n\n
|
||||
between_objects_gcode =
|
||||
deretract_speed = 0
|
||||
end_gcode = G4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
|
||||
extruder_colour = #FFFF00
|
||||
extruder_offset = 0x0
|
||||
gcode_flavor = marlin
|
||||
silent_mode = 0
|
||||
@ -2039,7 +2237,7 @@ retract_speed = 35
|
||||
serial_port =
|
||||
serial_speed = 250000
|
||||
single_extruder_multi_material = 0
|
||||
start_gcode = M115 U3.2.3 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.2.3 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
toolchange_gcode =
|
||||
use_firmware_retraction = 0
|
||||
use_relative_e_distances = 1
|
||||
@ -2076,7 +2274,7 @@ printer_model = MK2SMM
|
||||
inherits = *multimaterial*
|
||||
end_gcode = G1 E-4 F2100.00000\nG91\nG1 Z1 F7200.000\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7 \nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3 \nG1 E-15.0000 F5000\nG1 E-50.0000 F5400\nG1 E-15.0000 F3000\nG1 E-12.0000 F2000\nG1 F1600\nG1 X0 Y1 E3.0000\nG1 X50 Y1 E-5.0000\nG1 F2000\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-3.0000\nG4 S0\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM84 ; disable motors\n\n
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN
|
||||
start_gcode = M115 U3.2.3 ; tell printer latest fw version\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\n; Start G-Code sequence START\nT?\nM104 S[first_layer_temperature]\nM140 S[first_layer_bed_temperature]\nM109 S[first_layer_temperature]\nM190 S[first_layer_bed_temperature]\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100\nM92 E140\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\nG92 E0.0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.2.3 ; tell printer latest fw version\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\n; Start G-Code sequence START\nT?\nM104 S[first_layer_temperature]\nM140 S[first_layer_bed_temperature]\nM109 S[first_layer_temperature]\nM190 S[first_layer_bed_temperature]\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100\nM92 E140\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\nG92 E0.0
|
||||
default_print_profile = 0.15mm OPTIMAL
|
||||
|
||||
[printer:*mm-multi*]
|
||||
@ -2086,7 +2284,7 @@ end_gcode = {if not has_wipe_tower}\n; Pull the filament into the cooling tubes.
|
||||
extruder_colour = #FFAA55;#E37BA0;#4ECDD3;#FB7259
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN
|
||||
start_gcode = M115 U3.2.3 ; tell printer latest fw version\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\n; Start G-Code sequence START\nT[initial_tool]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100 ; set max feedrate\nM92 E140 ; E-steps per filament milimeter\n{if not has_single_extruder_multi_material_priming}\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\n{endif}\nG92 E0.0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.2.3 ; tell printer latest fw version\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\n; Start G-Code sequence START\nT[initial_tool]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100 ; set max feedrate\nM92 E140 ; E-steps per filament milimeter\n{if not has_single_extruder_multi_material_priming}\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\n{endif}\nG92 E0.0
|
||||
default_print_profile = 0.15mm OPTIMAL
|
||||
|
||||
# XXXXXXXXXXXXXXXXX
|
||||
@ -2154,19 +2352,19 @@ min_layer_height = 0.1
|
||||
inherits = Original Prusa i3 MK2S
|
||||
printer_model = MK2.5
|
||||
remaining_times = 1
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 0.25 nozzle]
|
||||
inherits = Original Prusa i3 MK2S 0.25 nozzle
|
||||
printer_model = MK2.5
|
||||
remaining_times = 1
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK2S 0.6 nozzle
|
||||
printer_model = MK2.5
|
||||
remaining_times = 1
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 MMU2 Single]
|
||||
inherits = Original Prusa i3 MK2.5; *mm2*
|
||||
@ -2195,7 +2393,7 @@ machine_min_travel_rate = 0
|
||||
default_print_profile = 0.15mm OPTIMAL MK2.5
|
||||
default_filament_profile = Prusament PLA
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2.5\n
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\n; select extruder\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; load to nozzle\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\n; select extruder\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; load to nozzle\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n
|
||||
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 MMU2 Single 0.6 nozzle]
|
||||
@ -2237,23 +2435,23 @@ single_extruder_multi_material = 1
|
||||
# to be defined explicitely.
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n
|
||||
end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors\n
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S]
|
||||
inherits = Original Prusa i3 MK2.5
|
||||
printer_model = MK2.5S
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S 0.25 nozzle]
|
||||
inherits = Original Prusa i3 MK2.5 0.25 nozzle
|
||||
printer_model = MK2.5S
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK2.5 0.6 nozzle
|
||||
printer_model = MK2.5S
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S MMU2S Single]
|
||||
inherits = Original Prusa i3 MK2.5; *mm2s*
|
||||
@ -2282,7 +2480,7 @@ machine_min_travel_rate = 0
|
||||
default_print_profile = 0.15mm OPTIMAL MK2.5
|
||||
default_filament_profile = Prusament PLA
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2.5\n
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n
|
||||
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S MMU2S Single 0.6 nozzle]
|
||||
@ -2302,7 +2500,7 @@ min_layer_height = 0.05
|
||||
nozzle_diameter = 0.25
|
||||
printer_variant = 0.25
|
||||
default_print_profile = 0.10mm DETAIL 0.25 nozzle
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S MMU2S]
|
||||
inherits = Original Prusa i3 MK2.5; *mm2s*
|
||||
@ -2335,9 +2533,24 @@ single_extruder_multi_material = 1
|
||||
# to be defined explicitely.
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n
|
||||
end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors\n
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S MMU2S 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK2.5S MMU2S
|
||||
nozzle_diameter = 0.6,0.6,0.6,0.6,0.6
|
||||
max_layer_height = 0.40
|
||||
min_layer_height = 0.15
|
||||
printer_variant = 0.6
|
||||
default_print_profile = 0.20mm NORMAL 0.6 nozzle
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 MMU2 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK2.5 MMU2
|
||||
nozzle_diameter = 0.6,0.6,0.6,0.6,0.6
|
||||
max_layer_height = 0.40
|
||||
min_layer_height = 0.15
|
||||
printer_variant = 0.6
|
||||
default_print_profile = 0.20mm NORMAL 0.6 nozzle
|
||||
|
||||
# XXXXXXXXXXXXXXXXX
|
||||
# XXX--- MK3 ---XXX
|
||||
@ -2367,7 +2580,7 @@ remaining_times = 1
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n
|
||||
retract_lift_below = 209
|
||||
max_print_height = 210
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
printer_model = MK3
|
||||
default_print_profile = 0.15mm QUALITY MK3
|
||||
|
||||
@ -2377,7 +2590,7 @@ nozzle_diameter = 0.25
|
||||
max_layer_height = 0.15
|
||||
min_layer_height = 0.05
|
||||
printer_variant = 0.25
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
default_print_profile = 0.10mm DETAIL 0.25 nozzle MK3
|
||||
|
||||
[printer:Original Prusa i3 MK3 0.6 nozzle]
|
||||
@ -2391,17 +2604,17 @@ default_print_profile = 0.30mm QUALITY 0.6 nozzle MK3
|
||||
[printer:Original Prusa i3 MK3S]
|
||||
inherits = Original Prusa i3 MK3
|
||||
printer_model = MK3S
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
|
||||
[printer:Original Prusa i3 MK3S 0.25 nozzle]
|
||||
inherits = Original Prusa i3 MK3 0.25 nozzle
|
||||
printer_model = MK3S
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
|
||||
[printer:Original Prusa i3 MK3S 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK3 0.6 nozzle
|
||||
printer_model = MK3S
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
|
||||
[printer:*mm2*]
|
||||
inherits = Original Prusa i3 MK3
|
||||
@ -2431,7 +2644,7 @@ default_filament_profile = Prusament PLA MMU2
|
||||
inherits = *mm2*
|
||||
single_extruder_multi_material = 0
|
||||
default_filament_profile = Prusament PLA
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
|
||||
|
||||
[printer:Original Prusa i3 MK3 MMU2 Single 0.6 nozzle]
|
||||
@ -2450,7 +2663,7 @@ nozzle_diameter = 0.25
|
||||
max_layer_height = 0.15
|
||||
min_layer_height = 0.05
|
||||
printer_variant = 0.25
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F1000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F1000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
default_print_profile = 0.10mm DETAIL 0.25 nozzle MK3
|
||||
|
||||
[printer:Original Prusa i3 MK3 MMU2]
|
||||
@ -2461,14 +2674,14 @@ inherits = *mm2*
|
||||
machine_max_acceleration_e = 8000,8000
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors\n
|
||||
|
||||
[printer:Original Prusa i3 MK3S MMU2S Single]
|
||||
inherits = *mm2s*
|
||||
single_extruder_multi_material = 0
|
||||
default_filament_profile = Prusament PLA
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
|
||||
|
||||
[printer:Original Prusa i3 MK3S MMU2S Single 0.6 nozzle]
|
||||
@ -2487,7 +2700,7 @@ nozzle_diameter = 0.25
|
||||
max_layer_height = 0.15
|
||||
min_layer_height = 0.05
|
||||
printer_variant = 0.25
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
default_print_profile = 0.10mm DETAIL 0.25 nozzle MK3
|
||||
|
||||
[printer:Original Prusa i3 MK3S MMU2S]
|
||||
@ -2495,18 +2708,26 @@ inherits = *mm2s*
|
||||
machine_max_acceleration_e = 8000,8000
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F
|
||||
start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors\n
|
||||
|
||||
# 0.6 nozzle MMU printer profile - only for single mode for now
|
||||
## 0.6mm nozzle MMU2/S printer profiles
|
||||
|
||||
# [printer:Original Prusa i3 MK3S MMU2S 0.6 nozzle]
|
||||
# inherits = Original Prusa i3 MK3S MMU2S
|
||||
# nozzle_diameter = 0.6,0.6,0.6,0.6,0.6
|
||||
# max_layer_height = 0.40
|
||||
# min_layer_height = 0.15
|
||||
# printer_variant = 0.6
|
||||
# default_print_profile = 0.30mm QUALITY 0.6 nozzle MK3
|
||||
[printer:Original Prusa i3 MK3S MMU2S 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK3S MMU2S
|
||||
nozzle_diameter = 0.6,0.6,0.6,0.6,0.6
|
||||
max_layer_height = 0.40
|
||||
min_layer_height = 0.15
|
||||
printer_variant = 0.6
|
||||
default_print_profile = 0.30mm QUALITY 0.6 nozzle MK3
|
||||
|
||||
[printer:Original Prusa i3 MK3 MMU2 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK3 MMU2
|
||||
nozzle_diameter = 0.6,0.6,0.6,0.6,0.6
|
||||
max_layer_height = 0.40
|
||||
min_layer_height = 0.15
|
||||
printer_variant = 0.6
|
||||
default_print_profile = 0.30mm QUALITY 0.6 nozzle MK3
|
||||
|
||||
[printer:Original Prusa SL1]
|
||||
printer_technology = SLA
|
||||
@ -2514,13 +2735,17 @@ printer_model = SL1
|
||||
printer_variant = default
|
||||
default_sla_material_profile = Prusa Orange Tough 0.05
|
||||
default_sla_print_profile = 0.05 Normal
|
||||
bed_shape = 0.98x1.02,119.98x1.02,119.98x67.02,0.98x67.02
|
||||
bed_shape = 1.48x1.02,119.48x1.02,119.48x67.02,1.48x67.02
|
||||
display_height = 68.04
|
||||
display_orientation = portrait
|
||||
display_pixels_x = 2560
|
||||
display_pixels_y = 1440
|
||||
display_width = 120.96
|
||||
max_print_height = 150
|
||||
min_exposure_time = 1
|
||||
max_exposure_time = 120
|
||||
min_initial_exposure_time = 1
|
||||
max_initial_exposure_time = 300
|
||||
printer_correction = 1,1,1
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_SL1\n
|
||||
|
||||
|
@ -1 +1,2 @@
|
||||
add_subdirectory(slabasebed)
|
||||
add_subdirectory(slasupporttree)
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <libslic3r/libslic3r.h>
|
||||
#include <libslic3r/TriangleMesh.hpp>
|
||||
#include <libslic3r/Tesselate.hpp>
|
||||
#include <libslic3r/ClipperUtils.hpp>
|
||||
#include <libslic3r/SLA/SLABasePool.hpp>
|
||||
#include <libslic3r/SLA/SLABoilerPlate.hpp>
|
||||
#include <libnest2d/tools/benchmark.h>
|
||||
@ -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);
|
||||
|
2
sandboxes/slasupporttree/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
add_executable(slasupporttree slasupporttree.cpp)
|
||||
target_link_libraries(slasupporttree libslic3r ${Boost_LIBRARIES} ${TBB_LIBRARIES} ${Boost_LIBRARIES} ${CMAKE_DL_LIBS})
|
42
sandboxes/slasupporttree/slasupporttree.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include <libslic3r/libslic3r.h>
|
||||
#include <libslic3r/Model.hpp>
|
||||
#include <libslic3r/Tesselate.hpp>
|
||||
#include <libslic3r/ClipperUtils.hpp>
|
||||
#include <libslic3r/SLA/SLAAutoSupports.hpp>
|
||||
#include <libslic3r/SLA/SLASupportTree.hpp>
|
||||
#include <libslic3r/SLAPrint.hpp>
|
||||
#include <libslic3r/MTUtils.hpp>
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/mutex.h>
|
||||
#include <future>
|
||||
|
||||
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;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
project(Slic3r-native)
|
||||
|
||||
add_subdirectory(build-utils)
|
||||
add_subdirectory(admesh)
|
||||
add_subdirectory(avrdude)
|
||||
# boost/nowide
|
||||
@ -48,7 +49,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)
|
||||
@ -57,6 +58,9 @@ if (SLIC3R_GUI)
|
||||
|
||||
include(${wxWidgets_USE_FILE})
|
||||
|
||||
# list(REMOVE_ITEM wxWidgets_LIBRARIES oleacc)
|
||||
message(STATUS "wx libs: ${wxWidgets_LIBRARIES}")
|
||||
|
||||
add_subdirectory(slic3r)
|
||||
endif()
|
||||
|
||||
@ -66,13 +70,20 @@ endif()
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/msw/PrusaSlicer.rc.in ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/msw/PrusaSlicer.manifest.in ${CMAKE_CURRENT_BINARY_DIR}/slic3r.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(slic3r SHARED PrusaSlicer.cpp PrusaSlicer.hpp)
|
||||
else ()
|
||||
add_executable(slic3r PrusaSlicer.cpp PrusaSlicer.hpp)
|
||||
endif ()
|
||||
|
||||
add_library(slic3r_lib STATIC PrusaSlicer.cpp PrusaSlicer.hpp)
|
||||
if (NOT MSVC)
|
||||
|
||||
if (MINGW)
|
||||
target_link_options(slic3r PUBLIC "-Wl,-allow-multiple-definition")
|
||||
set_target_properties(slic3r PROPERTIES PREFIX "")
|
||||
endif (MINGW)
|
||||
|
||||
if (NOT WIN32)
|
||||
# Binary name on unix like systems (OSX, Linux)
|
||||
set_target_properties(slic3r PROPERTIES OUTPUT_NAME "slic3r++")
|
||||
endif ()
|
||||
@ -101,7 +112,7 @@ if (SLIC3R_GUI)
|
||||
|
||||
# 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()
|
||||
@ -135,7 +146,7 @@ if (SLIC3R_GUI)
|
||||
target_link_libraries(slic3r user32.lib Setupapi.lib OpenGL32.Lib GlU32.Lib)
|
||||
target_link_libraries(slic3r_lib user32.lib Setupapi.lib OpenGL32.Lib GlU32.Lib)
|
||||
elseif (MINGW)
|
||||
target_link_libraries(slic3r -lopengl32)
|
||||
target_link_libraries(slic3r opengl32 ws2_32 uxtheme setupapi)
|
||||
target_link_libraries(slic3r_lib -lopengl32)
|
||||
elseif (APPLE)
|
||||
target_link_libraries(slic3r "-framework OpenGL")
|
||||
@ -148,27 +159,34 @@ 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(slic3r_app_gui WIN32 PrusaSlicer_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc)
|
||||
# Generate debug symbols even in release mode.
|
||||
#target_link_options(slic3r_app_gui PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>")
|
||||
if(MSVC)
|
||||
target_link_options(slic3r_app_gui PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>")
|
||||
endif()
|
||||
target_compile_definitions(slic3r_app_gui PRIVATE -DSLIC3R_WRAPPER_NOCONSOLE)
|
||||
add_dependencies(slic3r_app_gui slic3r)
|
||||
set_target_properties(slic3r_app_gui PROPERTIES OUTPUT_NAME "slic3r++")
|
||||
add_dependencies(slic3r_app_gui PrusaSlicer)
|
||||
set_target_properties(slic3r_app_gui PROPERTIES OUTPUT_NAME "prusa-slicer")
|
||||
target_link_libraries(slic3r_app_gui PRIVATE boost_headeronly)
|
||||
|
||||
add_executable(slic3r_app_console PrusaSlicer_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc)
|
||||
# Generate debug symbols even in release mode.
|
||||
#target_link_options(slic3r_app_console PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>")
|
||||
if (MSVC)
|
||||
target_link_options(slic3r_app_console PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>")
|
||||
endif ()
|
||||
target_compile_definitions(slic3r_app_console PRIVATE -DSLIC3R_WRAPPER_CONSOLE)
|
||||
add_dependencies(slic3r_app_console slic3r)
|
||||
set_target_properties(slic3r_app_console PROPERTIES OUTPUT_NAME "slic3r++_console")
|
||||
add_dependencies(slic3r_app_console PrusaSlicer)
|
||||
set_target_properties(slic3r_app_console PROPERTIES OUTPUT_NAME "prusa-slicer-console")
|
||||
target_link_libraries(slic3r_app_console PRIVATE boost_headeronly)
|
||||
|
||||
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)
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <boost/nowide/args.hpp>
|
||||
#include <boost/nowide/cenv.hpp>
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
#include <boost/nowide/integration/filesystem.hpp>
|
||||
|
||||
#include "unix/fhs.hpp" // Generated by CMake from ../platform/unix/fhs.hpp.in
|
||||
|
||||
@ -47,6 +48,7 @@
|
||||
#ifdef SLIC3R_GUI
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
#endif /* SLIC3R_GUI */
|
||||
|
||||
using namespace Slic3r;
|
||||
@ -59,6 +61,26 @@ PrinterTechnology get_printer_technology(const DynamicConfig &config)
|
||||
|
||||
int CLI::run(int argc, char **argv)
|
||||
{
|
||||
// Switch boost::filesystem to utf8.
|
||||
try {
|
||||
boost::nowide::nowide_filesystem();
|
||||
} catch (const std::runtime_error& ex) {
|
||||
std::string caption = std::string(SLIC3R_APP_NAME) + " Error";
|
||||
std::string text = std::string("An error occured while setting up locale.\n") + (
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
// likely some linux system
|
||||
"You may need to reconfigure the missing locales, likely by running the \"locale-gen\" and \"dpkg-reconfigure locales\" commands.\n"
|
||||
#endif
|
||||
SLIC3R_APP_NAME " will now terminate.\n\n") + ex.what();
|
||||
#if defined(_WIN32) && defined(SLIC3R_GUI)
|
||||
if (m_actions.empty())
|
||||
// Empty actions means Slicer is executed in the GUI mode. Show a GUI message.
|
||||
MessageBoxA(NULL, text.c_str(), caption.c_str(), MB_OK | MB_ICONERROR);
|
||||
#endif
|
||||
boost::nowide::cerr << text.c_str() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (! this->setup(argc, argv))
|
||||
return 1;
|
||||
|
||||
@ -409,7 +431,7 @@ int CLI::run(int argc, char **argv)
|
||||
outfile_final = sla_print.print_statistics().finalize_output_path(outfile);
|
||||
sla_print.export_raster(outfile_final);
|
||||
}
|
||||
if (outfile != outfile_final && Slic3r::rename_file(outfile, outfile_final) != 0) {
|
||||
if (outfile != outfile_final && Slic3r::rename_file(outfile, outfile_final)) {
|
||||
boost::nowide::cerr << "Renaming file " << outfile << " to " << outfile_final << " failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
@ -484,7 +506,10 @@ int CLI::run(int argc, char **argv)
|
||||
if (! m_extra_config.empty())
|
||||
gui->mainframe->load_config(m_extra_config);
|
||||
});
|
||||
return wxEntry(argc, argv);
|
||||
int result = wxEntry(argc, argv);
|
||||
//FIXME this is a workaround for the PrusaSlicer 2.1 release.
|
||||
_3DScene::destroy();
|
||||
return result;
|
||||
#else /* SLIC3R_GUI */
|
||||
// No GUI support. Just print out a help.
|
||||
this->print_help(false);
|
||||
@ -499,6 +524,7 @@ int CLI::run(int argc, char **argv)
|
||||
bool CLI::setup(int argc, char **argv)
|
||||
{
|
||||
{
|
||||
Slic3r::set_logging_level(1);
|
||||
const char *loglevel = boost::nowide::getenv("SLIC3R_LOGLEVEL");
|
||||
if (loglevel != nullptr) {
|
||||
if (loglevel[0] >= '0' && loglevel[0] <= '9' && loglevel[1] == 0)
|
||||
@ -651,7 +677,7 @@ 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)
|
||||
{
|
||||
|
@ -205,6 +205,8 @@ extern "C" {
|
||||
Slic3rMainFunc slic3r_main = nullptr;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
#ifdef SLIC3R_WRAPPER_NOCONSOLE
|
||||
int APIENTRY wWinMain(HINSTANCE /* hInstance */, HINSTANCE /* hPrevInstance */, PWSTR /* lpCmdLine */, int /* nCmdShow */)
|
||||
{
|
||||
@ -298,3 +300,4 @@ int wmain(int argc, wchar_t **argv)
|
||||
// argc minus the trailing nullptr of the argv
|
||||
return slic3r_main((int)argv_extended.size() - 1, argv_extended.data());
|
||||
}
|
||||
}
|
||||
|
@ -162,23 +162,23 @@ static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first)
|
||||
// Read a single facet from an ASCII .STL file
|
||||
// skip solid/endsolid
|
||||
// (in this order, otherwise it won't work when they are paired in the middle of a file)
|
||||
fscanf(fp, "endsolid%*[^\n]\n");
|
||||
fscanf(fp, "solid%*[^\n]\n"); // name might contain spaces so %*s doesn't work and it also can be empty (just "solid")
|
||||
fscanf(fp, "endsolid %*[^\n]\n");
|
||||
fscanf(fp, "solid %*[^\n]\n"); // name might contain spaces so %*s doesn't work and it also can be empty (just "solid")
|
||||
// Leading space in the fscanf format skips all leading white spaces including numerous new lines and tabs.
|
||||
int res_normal = fscanf(fp, " facet normal %31s %31s %31s", normal_buf[0], normal_buf[1], normal_buf[2]);
|
||||
int res_normal = fscanf(fp, " facet normal %31s %31s %31s ", normal_buf[0], normal_buf[1], normal_buf[2]);
|
||||
assert(res_normal == 3);
|
||||
int res_outer_loop = fscanf(fp, " outer loop");
|
||||
int res_outer_loop = fscanf(fp, " outer loop ");
|
||||
assert(res_outer_loop == 0);
|
||||
int res_vertex1 = fscanf(fp, " vertex %f %f %f", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2));
|
||||
int res_vertex1 = fscanf(fp, " vertex %f %f %f ", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2));
|
||||
assert(res_vertex1 == 3);
|
||||
int res_vertex2 = fscanf(fp, " vertex %f %f %f", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2));
|
||||
int res_vertex2 = fscanf(fp, " vertex %f %f %f ", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2));
|
||||
assert(res_vertex2 == 3);
|
||||
int res_vertex3 = fscanf(fp, " vertex %f %f %f", &facet.vertex[2](0), &facet.vertex[2](1), &facet.vertex[2](2));
|
||||
int res_vertex3 = fscanf(fp, " vertex %f %f %f ", &facet.vertex[2](0), &facet.vertex[2](1), &facet.vertex[2](2));
|
||||
assert(res_vertex3 == 3);
|
||||
int res_endloop = fscanf(fp, " endloop");
|
||||
int res_endloop = fscanf(fp, " endloop %*[^\n]\n");
|
||||
assert(res_endloop == 0);
|
||||
// There is a leading and trailing white space around endfacet to eat up all leading and trailing white spaces including numerous tabs and new lines.
|
||||
int res_endfacet = fscanf(fp, " endfacet ");
|
||||
int res_endfacet = fscanf(fp, " endfacet %*[^\n]\n");
|
||||
if (res_normal != 3 || res_outer_loop != 0 || res_vertex1 != 3 || res_vertex2 != 3 || res_vertex3 != 3 || res_endloop != 0 || res_endfacet != 0) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Something is syntactically very wrong with this ASCII STL! ";
|
||||
return false;
|
||||
|
@ -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)
|
||||
@ -81,13 +85,13 @@ add_executable(avrdude-conf-gen conf-generate.cpp)
|
||||
# Config file embedding
|
||||
add_custom_command(
|
||||
DEPENDS avrdude-conf-gen ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf
|
||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf.h
|
||||
COMMAND $<TARGET_FILE:avrdude-conf-gen> avrdude-slic3r.conf avrdude_slic3r_conf > avrdude-slic3r.conf.h
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/avrdude-slic3r.conf.h
|
||||
COMMAND $<TARGET_FILE:avrdude-conf-gen> avrdude-slic3r.conf avrdude_slic3r_conf ${CMAKE_CURRENT_BINARY_DIR}/avrdude-slic3r.conf.h
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
add_custom_target(gen_conf_h
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf.h
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/avrdude-slic3r.conf.h
|
||||
)
|
||||
|
||||
add_library(avrdude STATIC ${AVRDUDE_SOURCES})
|
||||
@ -96,7 +100,15 @@ add_dependencies(avrdude gen_conf_h)
|
||||
add_executable(avrdude-slic3r main-standalone.cpp)
|
||||
target_link_libraries(avrdude-slic3r avrdude)
|
||||
|
||||
encoding_check(avrdude)
|
||||
encoding_check(avrdude-slic3r)
|
||||
|
||||
# Make avrdude-slic3r.conf.h includable:
|
||||
target_include_directories(avrdude SYSTEM PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
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()
|
||||
|
@ -6,36 +6,42 @@
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
if (argc != 3) {
|
||||
std::cerr << "Usage: " << argv[0] << " <file> <symbol name>" << std::endl;
|
||||
if (argc != 4) {
|
||||
std::cerr << "Usage: " << argv[0] << " <file> <symbol name> <output file>" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* filename = argv[1];
|
||||
const char* filename_in = argv[1];
|
||||
const char* symbol = argv[2];
|
||||
const char* filename_out = argv[3];
|
||||
|
||||
size_t size = 0;
|
||||
std::fstream file(filename);
|
||||
std::fstream file(filename_in, std::ios::in | std::ios::binary);
|
||||
if (!file.good()) {
|
||||
std::cerr << "Cannot read file: " << filename << std::endl;
|
||||
std::cerr << "Cannot read file: " << filename_in << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "/* WARN: This file is auto-generated from `" << filename << "` */" << std::endl;
|
||||
std::cout << "const unsigned char " << symbol << "[] = {";
|
||||
std::fstream output(filename_out, std::ios::out | std::ios::trunc);
|
||||
if (!output.good()) {
|
||||
std::cerr << "Cannot open output file: " << filename_out << std::endl;
|
||||
}
|
||||
|
||||
output << "/* WARN: This file is auto-generated from `" << filename_in << "` */" << std::endl;
|
||||
output << "const unsigned char " << symbol << "[] = {";
|
||||
|
||||
char c;
|
||||
std::cout << std::hex;
|
||||
std::cout.fill('0');
|
||||
output << std::hex;
|
||||
output.fill('0');
|
||||
for (file.get(c); !file.eof(); size++, file.get(c)) {
|
||||
if (size % 12 == 0) { std::cout << "\n "; }
|
||||
std::cout << "0x" << std::setw(2) << (unsigned)c << ", ";
|
||||
if (size % 12 == 0) { output << "\n "; }
|
||||
output << "0x" << std::setw(2) << (unsigned)c << ", ";
|
||||
}
|
||||
|
||||
std::cout << "\n 0, 0\n};\n";
|
||||
output << "\n 0, 0\n};\n";
|
||||
|
||||
std::cout << std::dec;
|
||||
std::cout << "const size_t " << symbol << "_size = " << size << ";" << std::endl;
|
||||
std::cout << "const size_t " << symbol << "_size_yy = " << size + 2 << ";" << std::endl;
|
||||
output << std::dec;
|
||||
output << "const size_t " << symbol << "_size = " << size << ";" << std::endl;
|
||||
output << "const size_t " << symbol << "_size_yy = " << size + 2 << ";" << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
/* C99 systems have <inttypes.h>. 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.
|
||||
|
@ -38,6 +38,10 @@ struct ArgvUtf8 : std::vector<char*>
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
int wmain(int argc_w, wchar_t *argv_w[])
|
||||
{
|
||||
ArgvUtf8 argv_utf8(argc_w, argv_w);
|
||||
|
@ -63,10 +63,15 @@ extern "C" {
|
||||
#define STDOUT_FILENO 1
|
||||
#define STDERR_FILENO 2
|
||||
|
||||
#if defined(_MSC_VER) && defined(__clang__)
|
||||
#include <stdint.h>
|
||||
struct timezone;
|
||||
struct timeval;
|
||||
#else
|
||||
#ifndef __cplusplus
|
||||
/* should be in some equivalent to <sys/types.h> */
|
||||
typedef __int8 int8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
@ -74,6 +79,7 @@ typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
int usleep(unsigned usec);
|
||||
|
39
src/build-utils/CMakeLists.txt
Normal file
@ -0,0 +1,39 @@
|
||||
|
||||
add_executable(encoding-check encoding-check.cpp)
|
||||
|
||||
# A global no-op target which depends on all encodings checks,
|
||||
# and on which in turn all checked targets depend.
|
||||
# This is done to make encoding checks the first thing to be
|
||||
# performed before actually compiling any sources of the checked targets
|
||||
# to make the check fail as early as possible.
|
||||
add_custom_target(global-encoding-check
|
||||
ALL
|
||||
DEPENDS encoding-check
|
||||
)
|
||||
|
||||
# Function that adds source file encoding check to a target
|
||||
# using the above encoding-check binary
|
||||
|
||||
function(encoding_check TARGET)
|
||||
# Obtain target source files
|
||||
get_target_property(T_SOURCES ${TARGET} SOURCES)
|
||||
|
||||
# Define top-level encoding check target for this ${TARGET}
|
||||
add_custom_target(encoding-check-${TARGET}
|
||||
DEPENDS encoding-check ${T_SOURCES}
|
||||
COMMENT "Checking source files encodings for target ${TARGET}"
|
||||
)
|
||||
|
||||
# Add checking of each source file as a subcommand of encoding-check-${TARGET}
|
||||
foreach(file ${T_SOURCES})
|
||||
add_custom_command(TARGET encoding-check-${TARGET}
|
||||
COMMAND $<TARGET_FILE:encoding-check> ${TARGET} ${file}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# This adds dependency on encoding-check-${TARGET} to ${TARET}
|
||||
# via the global-encoding-check
|
||||
add_dependencies(global-encoding-check encoding-check-${TARGET})
|
||||
add_dependencies(${TARGET} global-encoding-check)
|
||||
endfunction()
|
119
src/build-utils/encoding-check.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
/*
|
||||
* The utf8_check() function scans the '\0'-terminated string starting
|
||||
* at s. It returns a pointer to the first byte of the first malformed
|
||||
* or overlong UTF-8 sequence found, or NULL if the string contains
|
||||
* only correct UTF-8. It also spots UTF-8 sequences that could cause
|
||||
* trouble if converted to UTF-16, namely surrogate characters
|
||||
* (U+D800..U+DFFF) and non-Unicode positions (U+FFFE..U+FFFF). This
|
||||
* routine is very likely to find a malformed sequence if the input
|
||||
* uses any other encoding than UTF-8. It therefore can be used as a
|
||||
* very effective heuristic for distinguishing between UTF-8 and other
|
||||
* encodings.
|
||||
*
|
||||
* I wrote this code mainly as a specification of functionality; there
|
||||
* are no doubt performance optimizations possible for certain CPUs.
|
||||
*
|
||||
* Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/> -- 2005-03-30
|
||||
* License: http://www.cl.cam.ac.uk/~mgk25/short-license.html
|
||||
*/
|
||||
|
||||
unsigned char *utf8_check(unsigned char *s)
|
||||
{
|
||||
while (*s) {
|
||||
if (*s < 0x80) {
|
||||
// 0xxxxxxx
|
||||
s++;
|
||||
} else if ((s[0] & 0xe0) == 0xc0) {
|
||||
// 110xxxxx 10xxxxxx
|
||||
if ((s[1] & 0xc0) != 0x80 ||
|
||||
(s[0] & 0xfe) == 0xc0) { // overlong?
|
||||
return s;
|
||||
} else {
|
||||
s += 2;
|
||||
}
|
||||
} else if ((s[0] & 0xf0) == 0xe0) {
|
||||
// 1110xxxx 10xxxxxx 10xxxxxx
|
||||
if ((s[1] & 0xc0) != 0x80 ||
|
||||
(s[2] & 0xc0) != 0x80 ||
|
||||
(s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || // overlong?
|
||||
(s[0] == 0xed && (s[1] & 0xe0) == 0xa0) || // surrogate?
|
||||
(s[0] == 0xef && s[1] == 0xbf &&
|
||||
(s[2] & 0xfe) == 0xbe)) { // U+FFFE or U+FFFF?
|
||||
return s;
|
||||
} else {
|
||||
s += 3;
|
||||
}
|
||||
} else if ((s[0] & 0xf8) == 0xf0) {
|
||||
// 11110xxX 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
if ((s[1] & 0xc0) != 0x80 ||
|
||||
(s[2] & 0xc0) != 0x80 ||
|
||||
(s[3] & 0xc0) != 0x80 ||
|
||||
(s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) || // overlong?
|
||||
(s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) { // > U+10FFFF?
|
||||
return s;
|
||||
} else {
|
||||
s += 4;
|
||||
}
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
if (argc != 3) {
|
||||
std::cerr << "Usage: " << argv[0] << " <program/library> <file>" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* target = argv[1];
|
||||
const char* filename = argv[2];
|
||||
|
||||
const auto error_exit = [=](const char* error) {
|
||||
std::cerr << "\n\tError: " << error << ": " << filename << "\n"
|
||||
<< "\tTarget: " << target << "\n"
|
||||
<< std::endl;
|
||||
std::exit(-2);
|
||||
};
|
||||
|
||||
std::ifstream file(filename, std::ios::binary | std::ios::ate);
|
||||
const auto size = file.tellg();
|
||||
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
file.seekg(0, std::ios::beg);
|
||||
std::vector<char> buffer(size);
|
||||
|
||||
if (file.read(buffer.data(), size)) {
|
||||
buffer.push_back('\0');
|
||||
|
||||
// Check UTF-8 validity
|
||||
if (utf8_check(reinterpret_cast<unsigned char*>(buffer.data())) != nullptr) {
|
||||
error_exit("Source file does not contain (valid) UTF-8");
|
||||
}
|
||||
|
||||
// Check against a BOM mark
|
||||
if (buffer.size() >= 3
|
||||
&& buffer[0] == '\xef'
|
||||
&& buffer[1] == '\xbb'
|
||||
&& buffer[2] == '\xbf') {
|
||||
error_exit("Source file is valid UTF-8 but contains a BOM mark");
|
||||
}
|
||||
} else {
|
||||
error_exit("Could not read source file");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// 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 <typename T>
|
||||
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<T> & THIS = *this;
|
||||
// Templates:
|
||||
// T should be a matrix that implements .size(), and operator(int i)
|
||||
template <typename T>
|
||||
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;i<minc;i++)
|
||||
{
|
||||
if(THIS.data(i) == that.data(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return THIS.data(i) < that.data(i);
|
||||
if(this->data(i) == that.data(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return this->data(i) < that.data(i);
|
||||
}
|
||||
// All characters the same, comes done to length
|
||||
return THIS.data.size()<that.data.size();
|
||||
};
|
||||
bool operator==(const SortableRow & that) const
|
||||
{
|
||||
// Get reference so that I can use parenthesis
|
||||
const SortableRow<T> & THIS = *this;
|
||||
if(THIS.data.size() != that.data.size())
|
||||
return this->data.size()<that.data.size();
|
||||
};
|
||||
bool operator==(const SortableRow & that) const
|
||||
{
|
||||
if(this->data.size() != that.data.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for(int i = 0;i<THIS.data.size();i++)
|
||||
{
|
||||
if(THIS.data(i) != that.data(i))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for(int i = 0;i<this->data.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
|
||||
|
@ -1,12 +1,12 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// 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/.
|
||||
#include "ray_box_intersect.h"
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
template <
|
||||
typename Derivedsource,
|
||||
@ -27,7 +27,7 @@ IGL_INLINE bool igl::ray_box_intersect(
|
||||
const Eigen::Vector3f& rayo,
|
||||
const Eigen::Vector3f& rayd,
|
||||
const Eigen::Vector3f& bmin,
|
||||
const Eigen::Vector3f& bmax,
|
||||
const Eigen::Vector3f& bmax,
|
||||
float & tnear,
|
||||
float & tfar
|
||||
)->bool
|
||||
@ -35,12 +35,12 @@ IGL_INLINE bool igl::ray_box_intersect(
|
||||
Eigen::Vector3f bnear;
|
||||
Eigen::Vector3f bfar;
|
||||
// Checks for intersection testing on each direction coordinate
|
||||
// Computes
|
||||
// Computes
|
||||
float t1, t2;
|
||||
tnear = -1e+6f, tfar = 1e+6f; //, tCube;
|
||||
bool intersectFlag = true;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
// std::cout << "coordinate " << i << ": bmin " << bmin(i) << ", bmax " << bmax(i) << std::endl;
|
||||
// std::cout << "coordinate " << i << ": bmin " << bmin(i) << ", bmax " << bmax(i) << std::endl;
|
||||
assert(bmin(i) <= bmax(i));
|
||||
if (::fabs(rayd(i)) < 1e-6) { // Ray parallel to axis i-th
|
||||
if (rayo(i) < bmin(i) || rayo(i) > bmax(i)) {
|
||||
@ -59,12 +59,12 @@ IGL_INLINE bool igl::ray_box_intersect(
|
||||
}
|
||||
// std::cout << " bnear " << bnear(i) << ", bfar " << bfar(i) << std::endl;
|
||||
// Finds the distance parameters t1 and t2 of the two ray-box intersections:
|
||||
// t1 must be the closest to the ray origin rayo.
|
||||
// t1 must be the closest to the ray origin rayo.
|
||||
t1 = (bnear(i) - rayo(i)) / rayd(i);
|
||||
t2 = (bfar(i) - rayo(i)) / rayd(i);
|
||||
if (t1 > t2) {
|
||||
std::swap(t1,t2);
|
||||
}
|
||||
}
|
||||
// The two intersection values are used to saturate tnear and tfar
|
||||
if (t1 > tnear) {
|
||||
tnear = t1;
|
||||
@ -72,7 +72,7 @@ IGL_INLINE bool igl::ray_box_intersect(
|
||||
if (t2 < tfar) {
|
||||
tfar = t2;
|
||||
}
|
||||
// std::cout << " t1 " << t1 << ", t2 " << t2 << ", tnear " << tnear << ", tfar " << tfar
|
||||
// std::cout << " t1 " << t1 << ", t2 " << t2 << ", tnear " << tnear << ", tfar " << tfar
|
||||
// << " tnear > tfar? " << (tnear > tfar) << ", tfar < 0? " << (tfar < 0) << std::endl;
|
||||
if(tnear > tfar) {
|
||||
intersectFlag = false;
|
||||
@ -101,11 +101,11 @@ IGL_INLINE bool igl::ray_box_intersect(
|
||||
// This should be precomputed and provided as input
|
||||
typedef Matrix<Scalar,1,3> RowVector3S;
|
||||
const RowVector3S inv_dir( 1./dir(0),1./dir(1),1./dir(2));
|
||||
const std::vector<bool> sign = { inv_dir(0)<0, inv_dir(1)<0, inv_dir(2)<0};
|
||||
const std::array<bool, 3> sign = { inv_dir(0)<0, inv_dir(1)<0, inv_dir(2)<0};
|
||||
// http://people.csail.mit.edu/amy/papers/box-jgt.pdf
|
||||
// "An Efficient and Robust Ray–Box Intersection Algorithm"
|
||||
Scalar tymin, tymax, tzmin, tzmax;
|
||||
std::vector<RowVector3S> bounds = {box.min(),box.max()};
|
||||
std::array<RowVector3S, 2> bounds = {box.min(),box.max()};
|
||||
tmin = ( bounds[sign[0]](0) - origin(0)) * inv_dir(0);
|
||||
tmax = ( bounds[1-sign[0]](0) - origin(0)) * inv_dir(0);
|
||||
tymin = (bounds[sign[1]](1) - origin(1)) * inv_dir(1);
|
||||
@ -146,4 +146,4 @@ IGL_INLINE bool igl::ray_box_intersect(
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
template bool igl::ray_box_intersect<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, double>(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::AlignedBox<double, 3> const&, double const&, double const&, double&, double&);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -29,7 +29,9 @@ IGL_INLINE bool igl::ray_mesh_intersect(
|
||||
// Should be but can't be const
|
||||
Vector3d s_d = s.template cast<double>();
|
||||
Vector3d dir_d = dir.template cast<double>();
|
||||
hits.clear();
|
||||
hits.clear();
|
||||
hits.reserve(F.rows());
|
||||
|
||||
// loop over all triangles
|
||||
for(int f = 0;f<F.rows();f++)
|
||||
{
|
||||
|
@ -337,7 +337,15 @@ merge(const TMultiShape<PolygonImpl>& 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 <libnest2d/utils/boost_alg.hpp>
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // CLIPPER_BACKEND_HPP
|
||||
|
@ -7,6 +7,10 @@
|
||||
#include "../tools/svgtools.hpp"
|
||||
#include <libnest2d/utils/rotcalipers.hpp>
|
||||
|
||||
#if defined(_MSC_VER) && defined(__clang__)
|
||||
#define BOOST_NO_CXX17_HDR_STRING_VIEW
|
||||
#endif
|
||||
|
||||
#include "boost/multiprecision/integer.hpp"
|
||||
#include "boost/rational.hpp"
|
||||
|
||||
|
@ -12,6 +12,11 @@
|
||||
#include <ClipperUtils.hpp>
|
||||
|
||||
#include <boost/geometry/index/rtree.hpp>
|
||||
|
||||
#if defined(_MSC_VER) && defined(__clang__)
|
||||
#define BOOST_NO_CXX17_HDR_STRING_VIEW
|
||||
#endif
|
||||
|
||||
#include <boost/multiprecision/integer.hpp>
|
||||
#include <boost/rational.hpp>
|
||||
|
||||
@ -128,13 +133,24 @@ 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.
|
||||
ItemGroup m_remaining; // Remaining items (m_items at the beginning)
|
||||
ItemGroup m_items; // The items to be packed
|
||||
ItemGroup m_remaining; // Remaining items
|
||||
ItemGroup m_items; // allready packed items
|
||||
size_t m_item_count = 0; // Number of all items to be packed
|
||||
|
||||
template<class T> ArithmeticOnly<T, double> norm(T val)
|
||||
{
|
||||
@ -152,7 +168,6 @@ protected:
|
||||
const double bin_area = m_bin_area;
|
||||
const SpatIndex& spatindex = m_rtree;
|
||||
const SpatIndex& smalls_spatindex = m_smallsrtree;
|
||||
const ItemGroup& remaining = m_remaining;
|
||||
|
||||
// We will treat big items (compared to the print bed) differently
|
||||
auto isBig = [bin_area](double a) {
|
||||
@ -194,8 +209,8 @@ protected:
|
||||
} compute_case;
|
||||
|
||||
bool bigitems = isBig(item.area()) || spatindex.empty();
|
||||
if(bigitems && !remaining.empty()) compute_case = BIG_ITEM;
|
||||
else if (bigitems && remaining.empty()) compute_case = LAST_BIG_ITEM;
|
||||
if(bigitems && !m_remaining.empty()) compute_case = BIG_ITEM;
|
||||
else if (bigitems && m_remaining.empty()) compute_case = LAST_BIG_ITEM;
|
||||
else compute_case = SMALL_ITEM;
|
||||
|
||||
switch (compute_case) {
|
||||
@ -220,7 +235,7 @@ protected:
|
||||
// The smalles distance from the arranged pile center:
|
||||
double dist = norm(*(std::min_element(dists.begin(), dists.end())));
|
||||
double bindist = norm(pl::distance(ibb.center(), bincenter));
|
||||
dist = 0.8 * dist + 0.2*bindist;
|
||||
dist = 0.8 * dist + 0.2 * bindist;
|
||||
|
||||
// Prepare a variable for the alignment score.
|
||||
// This will indicate: how well is the candidate item
|
||||
@ -252,29 +267,24 @@ protected:
|
||||
if(ascore < alignment_score) alignment_score = ascore;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
density = std::sqrt(norm(fullbb.width()) * norm(fullbb.height()));
|
||||
|
||||
double R = double(m_remaining.size()) / m_item_count;
|
||||
|
||||
// The final mix of the score is the balance between the
|
||||
// distance from the full pile center, the pack density and
|
||||
// the alignment with the neighbors
|
||||
if (result.empty())
|
||||
score = 0.5 * dist + 0.5 * density;
|
||||
score = 0.50 * dist + 0.50 * density;
|
||||
else
|
||||
score = 0.40 * dist + 0.40 * density + 0.2 * alignment_score;
|
||||
score = R * 0.60 * dist +
|
||||
(1.0 - R) * 0.20 * density +
|
||||
0.20 * alignment_score;
|
||||
|
||||
break;
|
||||
}
|
||||
case LAST_BIG_ITEM: {
|
||||
auto mp = m_merged_pile;
|
||||
mp.emplace_back(item.transformedShape());
|
||||
auto chull = sl::convexHull(mp);
|
||||
|
||||
placers::EdgeCache<clppr::Polygon> ec(chull);
|
||||
|
||||
double circ = norm(ec.circumference());
|
||||
double bcirc = 2.0 * norm(fullbb.width() + fullbb.height());
|
||||
score = 0.5 * circ + 0.5 * bcirc;
|
||||
score = norm(pl::distance(ibb.center(), m_pilebb.center()));
|
||||
break;
|
||||
}
|
||||
case SMALL_ITEM: {
|
||||
@ -340,9 +350,11 @@ public:
|
||||
m_pck.configure(m_pconf);
|
||||
}
|
||||
|
||||
template<class...Args> inline void operator()(Args&&...args) {
|
||||
m_rtree.clear(); /*m_preload_idx.clear();*/
|
||||
m_pck.execute(std::forward<Args>(args)...);
|
||||
template<class It> inline void operator()(It from, It to) {
|
||||
m_rtree.clear();
|
||||
m_item_count += size_t(to - from);
|
||||
m_pck.execute(from, to);
|
||||
m_item_count = 0;
|
||||
}
|
||||
|
||||
inline void preload(std::vector<Item>& fixeditems) {
|
||||
@ -361,6 +373,7 @@ public:
|
||||
}
|
||||
|
||||
m_pck.configure(m_pconf);
|
||||
m_item_count += fixeditems.size();
|
||||
}
|
||||
};
|
||||
|
||||
@ -424,6 +437,18 @@ inline Circle to_lnCircle(const CircleBed& circ) {
|
||||
}
|
||||
|
||||
// Get the type of bed geometry from a simple vector of points.
|
||||
void BedShapeHint::reset(BedShapes type)
|
||||
{
|
||||
if (m_type != type) {
|
||||
if (m_type == bsIrregular)
|
||||
m_bed.polygon.Slic3r::Polyline::~Polyline();
|
||||
else if (type == bsIrregular)
|
||||
::new (&m_bed.polygon) Polyline();
|
||||
}
|
||||
|
||||
m_type = type;
|
||||
}
|
||||
|
||||
BedShapeHint::BedShapeHint(const Polyline &bed) {
|
||||
auto x = [](const Point& p) { return p(X); };
|
||||
auto y = [](const Point& p) { return p(Y); };
|
||||
@ -492,19 +517,50 @@ BedShapeHint::BedShapeHint(const Polyline &bed) {
|
||||
m_type = BedShapes::bsCircle;
|
||||
m_bed.circ = c;
|
||||
} else {
|
||||
assert(m_type != BedShapes::bsIrregular);
|
||||
m_type = BedShapes::bsIrregular;
|
||||
m_bed.polygon = bed;
|
||||
::new (&m_bed.polygon) Polyline(bed);
|
||||
}
|
||||
}
|
||||
|
||||
BedShapeHint &BedShapeHint::operator=(BedShapeHint &&cpy)
|
||||
{
|
||||
reset(cpy.m_type);
|
||||
|
||||
switch(m_type) {
|
||||
case bsBox: m_bed.box = std::move(cpy.m_bed.box); break;
|
||||
case bsCircle: m_bed.circ = std::move(cpy.m_bed.circ); break;
|
||||
case bsIrregular: m_bed.polygon = std::move(cpy.m_bed.polygon); break;
|
||||
case bsInfinite: m_bed.infbed = std::move(cpy.m_bed.infbed); break;
|
||||
case bsUnknown: break;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BedShapeHint &BedShapeHint::operator=(const BedShapeHint &cpy)
|
||||
{
|
||||
reset(cpy.m_type);
|
||||
|
||||
switch(m_type) {
|
||||
case bsBox: m_bed.box = cpy.m_bed.box; break;
|
||||
case bsCircle: m_bed.circ = cpy.m_bed.circ; break;
|
||||
case bsIrregular: m_bed.polygon = cpy.m_bed.polygon; break;
|
||||
case bsInfinite: m_bed.infbed = cpy.m_bed.infbed; break;
|
||||
case bsUnknown: break;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class BinT> // Arrange for arbitrary bin type
|
||||
void _arrange(
|
||||
std::vector<Item> & shapes,
|
||||
std::vector<Item> & excludes,
|
||||
const BinT & bin,
|
||||
coord_t minobjd,
|
||||
std::function<void(unsigned)> prind,
|
||||
std::function<bool()> stopfn)
|
||||
std::vector<Item> & shapes,
|
||||
std::vector<Item> & excludes,
|
||||
const BinT & bin,
|
||||
coord_t minobjd,
|
||||
std::function<void(unsigned)> prind,
|
||||
std::function<bool()> stopfn)
|
||||
{
|
||||
// Integer ceiling the min distance from the bed perimeters
|
||||
coord_t md = minobjd - 2 * scaled(0.1 + EPSILON);
|
||||
|
@ -39,18 +39,24 @@ enum BedShapes {
|
||||
class BedShapeHint {
|
||||
BedShapes m_type = BedShapes::bsInfinite;
|
||||
|
||||
// The union neither calls constructors nor destructors of its members.
|
||||
// The only member with non-trivial constructor / destructor is the polygon,
|
||||
// a placement new / delete needs to be called over it.
|
||||
union BedShape_u { // TODO: use variant from cpp17?
|
||||
CircleBed circ;
|
||||
BoundingBox box;
|
||||
Polyline polygon;
|
||||
InfiniteBed infbed{};
|
||||
~BedShape_u() {}
|
||||
BedShape_u() {};
|
||||
BedShape_u() {}
|
||||
} m_bed;
|
||||
|
||||
// Reset the type, allocate m_bed properly
|
||||
void reset(BedShapes type);
|
||||
|
||||
public:
|
||||
|
||||
BedShapeHint(){};
|
||||
BedShapeHint(){}
|
||||
|
||||
/// Get a bed shape hint for arrange() from a naked Polyline.
|
||||
explicit BedShapeHint(const Polyline &polyl);
|
||||
@ -73,38 +79,13 @@ public:
|
||||
{
|
||||
if (m_type == BedShapes::bsIrregular)
|
||||
m_bed.polygon.Slic3r::Polyline::~Polyline();
|
||||
};
|
||||
}
|
||||
|
||||
BedShapeHint(const BedShapeHint &cpy) { *this = cpy; }
|
||||
BedShapeHint(BedShapeHint &&cpy) { *this = std::move(cpy); }
|
||||
|
||||
BedShapeHint &operator=(const BedShapeHint &cpy)
|
||||
{
|
||||
m_type = cpy.m_type;
|
||||
switch(m_type) {
|
||||
case bsBox: m_bed.box = cpy.m_bed.box; break;
|
||||
case bsCircle: m_bed.circ = cpy.m_bed.circ; break;
|
||||
case bsIrregular: m_bed.polygon = cpy.m_bed.polygon; break;
|
||||
case bsInfinite: m_bed.infbed = cpy.m_bed.infbed; break;
|
||||
case bsUnknown: break;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BedShapeHint& operator=(BedShapeHint &&cpy)
|
||||
{
|
||||
m_type = cpy.m_type;
|
||||
switch(m_type) {
|
||||
case bsBox: m_bed.box = std::move(cpy.m_bed.box); break;
|
||||
case bsCircle: m_bed.circ = std::move(cpy.m_bed.circ); break;
|
||||
case bsIrregular: m_bed.polygon = std::move(cpy.m_bed.polygon); break;
|
||||
case bsInfinite: m_bed.infbed = std::move(cpy.m_bed.infbed); break;
|
||||
case bsUnknown: break;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
BedShapeHint &operator=(const BedShapeHint &cpy);
|
||||
BedShapeHint& operator=(BedShapeHint &&cpy);
|
||||
|
||||
BedShapes get_type() const { return m_type; }
|
||||
|
||||
|
@ -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
|
||||
@ -72,7 +76,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
|
||||
@ -127,6 +131,8 @@ add_library(libslic3r STATIC
|
||||
Point.hpp
|
||||
Polygon.cpp
|
||||
Polygon.hpp
|
||||
PolygonTrimmer.cpp
|
||||
PolygonTrimmer.hpp
|
||||
Polyline.cpp
|
||||
Polyline.hpp
|
||||
PolylineCollection.cpp
|
||||
@ -139,6 +145,7 @@ add_library(libslic3r STATIC
|
||||
PrintConfig.hpp
|
||||
PrintObject.cpp
|
||||
PrintRegion.cpp
|
||||
Semver.cpp
|
||||
SLAPrint.cpp
|
||||
SLAPrint.hpp
|
||||
SLA/SLAAutoSupports.hpp
|
||||
@ -186,6 +193,8 @@ add_library(libslic3r STATIC
|
||||
SLA/SLARasterWriter.cpp
|
||||
)
|
||||
|
||||
encoding_check(libslic3r)
|
||||
|
||||
if (SLIC3R_PCH AND NOT SLIC3R_SYNTAXONLY)
|
||||
add_precompiled_header(libslic3r pchheader.hpp FORCEINCLUDE)
|
||||
endif ()
|
||||
|
@ -396,7 +396,7 @@ public:
|
||||
this->values[i] = rhs_vec->values[i];
|
||||
modified = true;
|
||||
}
|
||||
return false;
|
||||
return modified;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "libslic3r.h"
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "EdgeGrid.hpp"
|
||||
#include "Geometry.hpp"
|
||||
#include "SVG.hpp"
|
||||
|
||||
#if 0
|
||||
@ -275,136 +276,27 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution)
|
||||
// 6) Finally fill in m_cell_data by rasterizing the lines once again.
|
||||
for (size_t i = 0; i < m_cells.size(); ++i)
|
||||
m_cells[i].end = m_cells[i].begin;
|
||||
for (size_t i = 0; i < m_contours.size(); ++i) {
|
||||
const Slic3r::Points &pts = *m_contours[i];
|
||||
for (size_t j = 0; j < pts.size(); ++j) {
|
||||
// End points of the line segment.
|
||||
Slic3r::Point p1(pts[j]);
|
||||
Slic3r::Point p2 = pts[(j + 1 == pts.size()) ? 0 : j + 1];
|
||||
p1(0) -= m_bbox.min(0);
|
||||
p1(1) -= m_bbox.min(1);
|
||||
p2(0) -= m_bbox.min(0);
|
||||
p2(1) -= m_bbox.min(1);
|
||||
// Get the cells of the end points.
|
||||
coord_t ix = p1(0) / m_resolution;
|
||||
coord_t iy = p1(1) / m_resolution;
|
||||
coord_t ixb = p2(0) / m_resolution;
|
||||
coord_t iyb = p2(1) / m_resolution;
|
||||
assert(ix >= 0 && size_t(ix) < m_cols);
|
||||
assert(iy >= 0 && size_t(iy) < m_rows);
|
||||
assert(ixb >= 0 && size_t(ixb) < m_cols);
|
||||
assert(iyb >= 0 && size_t(iyb) < m_rows);
|
||||
// Account for the end points.
|
||||
m_cell_data[m_cells[iy*m_cols + ix].end++] = std::pair<size_t, size_t>(i, j);
|
||||
if (ix == ixb && iy == iyb)
|
||||
// Both ends fall into the same cell.
|
||||
continue;
|
||||
// Raster the centeral part of the line.
|
||||
coord_t dx = std::abs(p2(0) - p1(0));
|
||||
coord_t dy = std::abs(p2(1) - p1(1));
|
||||
if (p1(0) < p2(0)) {
|
||||
int64_t ex = int64_t((ix + 1)*m_resolution - p1(0)) * int64_t(dy);
|
||||
if (p1(1) < p2(1)) {
|
||||
// x positive, y positive
|
||||
int64_t ey = int64_t((iy + 1)*m_resolution - p1(1)) * int64_t(dx);
|
||||
do {
|
||||
assert(ix <= ixb && iy <= iyb);
|
||||
if (ex < ey) {
|
||||
ey -= ex;
|
||||
ex = int64_t(dy) * m_resolution;
|
||||
ix += 1;
|
||||
|
||||
struct Visitor {
|
||||
Visitor(std::vector<std::pair<size_t, size_t>> &cell_data, std::vector<Cell> &cells, size_t cols) :
|
||||
cell_data(cell_data), cells(cells), cols(cols), i(0), j(0) {}
|
||||
|
||||
void operator()(coord_t iy, coord_t ix) { cell_data[cells[iy*cols + ix].end++] = std::pair<size_t, size_t>(i, j); }
|
||||
|
||||
std::vector<std::pair<size_t, size_t>> &cell_data;
|
||||
std::vector<Cell> &cells;
|
||||
size_t cols;
|
||||
size_t i;
|
||||
size_t j;
|
||||
} visitor(m_cell_data, m_cells, m_cols);
|
||||
|
||||
assert(visitor.i == 0);
|
||||
for (; visitor.i < m_contours.size(); ++ visitor.i) {
|
||||
const Slic3r::Points &pts = *m_contours[visitor.i];
|
||||
for (visitor.j = 0; visitor.j < pts.size(); ++ visitor.j)
|
||||
this->visit_cells_intersecting_line(pts[visitor.j], pts[(visitor.j + 1 == pts.size()) ? 0 : visitor.j + 1], visitor);
|
||||
}
|
||||
else if (ex == ey) {
|
||||
ex = int64_t(dy) * m_resolution;
|
||||
ey = int64_t(dx) * m_resolution;
|
||||
ix += 1;
|
||||
iy += 1;
|
||||
}
|
||||
else {
|
||||
assert(ex > ey);
|
||||
ex -= ey;
|
||||
ey = int64_t(dx) * m_resolution;
|
||||
iy += 1;
|
||||
}
|
||||
m_cell_data[m_cells[iy*m_cols + ix].end++] = std::pair<size_t, size_t>(i, j);
|
||||
} while (ix != ixb || iy != iyb);
|
||||
}
|
||||
else {
|
||||
// x positive, y non positive
|
||||
int64_t ey = int64_t(p1(1) - iy*m_resolution) * int64_t(dx);
|
||||
do {
|
||||
assert(ix <= ixb && iy >= iyb);
|
||||
if (ex <= ey) {
|
||||
ey -= ex;
|
||||
ex = int64_t(dy) * m_resolution;
|
||||
ix += 1;
|
||||
}
|
||||
else {
|
||||
ex -= ey;
|
||||
ey = int64_t(dx) * m_resolution;
|
||||
iy -= 1;
|
||||
}
|
||||
m_cell_data[m_cells[iy*m_cols + ix].end++] = std::pair<size_t, size_t>(i, j);
|
||||
} while (ix != ixb || iy != iyb);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int64_t ex = int64_t(p1(0) - ix*m_resolution) * int64_t(dy);
|
||||
if (p1(1) < p2(1)) {
|
||||
// x non positive, y positive
|
||||
int64_t ey = int64_t((iy + 1)*m_resolution - p1(1)) * int64_t(dx);
|
||||
do {
|
||||
assert(ix >= ixb && iy <= iyb);
|
||||
if (ex < ey) {
|
||||
ey -= ex;
|
||||
ex = int64_t(dy) * m_resolution;
|
||||
ix -= 1;
|
||||
}
|
||||
else {
|
||||
assert(ex >= ey);
|
||||
ex -= ey;
|
||||
ey = int64_t(dx) * m_resolution;
|
||||
iy += 1;
|
||||
}
|
||||
m_cell_data[m_cells[iy*m_cols + ix].end++] = std::pair<size_t, size_t>(i, j);
|
||||
} while (ix != ixb || iy != iyb);
|
||||
}
|
||||
else {
|
||||
// x non positive, y non positive
|
||||
int64_t ey = int64_t(p1(1) - iy*m_resolution) * int64_t(dx);
|
||||
do {
|
||||
assert(ix >= ixb && iy >= iyb);
|
||||
if (ex < ey) {
|
||||
ey -= ex;
|
||||
ex = int64_t(dy) * m_resolution;
|
||||
ix -= 1;
|
||||
}
|
||||
else if (ex == ey) {
|
||||
// The lower edge of a grid cell belongs to the cell.
|
||||
// Handle the case where the ray may cross the lower left corner of a cell in a general case,
|
||||
// or a left or lower edge in a degenerate case (horizontal or vertical line).
|
||||
if (dx > 0) {
|
||||
ex = int64_t(dy) * m_resolution;
|
||||
ix -= 1;
|
||||
}
|
||||
if (dy > 0) {
|
||||
ey = int64_t(dx) * m_resolution;
|
||||
iy -= 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(ex > ey);
|
||||
ex -= ey;
|
||||
ey = int64_t(dx) * m_resolution;
|
||||
iy -= 1;
|
||||
}
|
||||
m_cell_data[m_cells[iy*m_cols + ix].end++] = std::pair<size_t, size_t>(i, j);
|
||||
} while (ix != ixb || iy != iyb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Divide, round to a grid coordinate.
|
||||
@ -1360,28 +1252,6 @@ Polygons EdgeGrid::Grid::contours_simplified(coord_t offset, bool fill_holes) co
|
||||
return out;
|
||||
}
|
||||
|
||||
inline int segments_could_intersect(
|
||||
const Slic3r::Point &ip1, const Slic3r::Point &ip2,
|
||||
const Slic3r::Point &jp1, const Slic3r::Point &jp2)
|
||||
{
|
||||
Vec2crd iv = (ip2 - ip1);
|
||||
Vec2crd vij1 = (jp1 - ip1);
|
||||
Vec2crd vij2 = (jp2 - ip1);
|
||||
int64_t tij1 = cross2(iv, vij1);
|
||||
int64_t tij2 = cross2(iv, vij2);
|
||||
int sij1 = (tij1 > 0) ? 1 : ((tij1 < 0) ? -1 : 0); // signum
|
||||
int sij2 = (tij2 > 0) ? 1 : ((tij2 < 0) ? -1 : 0);
|
||||
return sij1 * sij2;
|
||||
}
|
||||
|
||||
inline bool segments_intersect(
|
||||
const Slic3r::Point &ip1, const Slic3r::Point &ip2,
|
||||
const Slic3r::Point &jp1, const Slic3r::Point &jp2)
|
||||
{
|
||||
return segments_could_intersect(ip1, ip2, jp1, jp2) <= 0 &&
|
||||
segments_could_intersect(jp1, jp2, ip1, ip2) <= 0;
|
||||
}
|
||||
|
||||
std::vector<std::pair<EdgeGrid::Grid::ContourEdge, EdgeGrid::Grid::ContourEdge>> EdgeGrid::Grid::intersecting_edges() const
|
||||
{
|
||||
std::vector<std::pair<ContourEdge, ContourEdge>> out;
|
||||
@ -1405,7 +1275,7 @@ std::vector<std::pair<EdgeGrid::Grid::ContourEdge, EdgeGrid::Grid::ContourEdge>>
|
||||
if (&ipts == &jpts && (&ip1 == &jp2 || &jp1 == &ip2))
|
||||
// Segments of the same contour share a common vertex.
|
||||
continue;
|
||||
if (segments_intersect(ip1, ip2, jp1, jp2)) {
|
||||
if (Geometry::segments_intersect(ip1, ip2, jp1, jp2)) {
|
||||
// The two segments intersect. Add them to the output.
|
||||
int jfirst = (&jpts < &ipts) || (&jpts == &ipts && jpt < ipt);
|
||||
out.emplace_back(jfirst ?
|
||||
@ -1440,7 +1310,7 @@ bool EdgeGrid::Grid::has_intersecting_edges() const
|
||||
const Slic3r::Point &jp1 = jpts[jpt];
|
||||
const Slic3r::Point &jp2 = jpts[(jpt + 1 == jpts.size()) ? 0 : jpt + 1];
|
||||
if (! (&ipts == &jpts && (&ip1 == &jp2 || &jp1 == &ip2)) &&
|
||||
segments_intersect(ip1, ip2, jp1, jp2))
|
||||
Geometry::segments_intersect(ip1, ip2, jp1, jp2))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,145 @@ public:
|
||||
std::vector<std::pair<ContourEdge, ContourEdge>> intersecting_edges() const;
|
||||
bool has_intersecting_edges() const;
|
||||
|
||||
template<typename FUNCTION> void visit_cells_intersecting_line(Slic3r::Point p1, Slic3r::Point p2, FUNCTION func) const
|
||||
{
|
||||
// End points of the line segment.
|
||||
p1(0) -= m_bbox.min(0);
|
||||
p1(1) -= m_bbox.min(1);
|
||||
p2(0) -= m_bbox.min(0);
|
||||
p2(1) -= m_bbox.min(1);
|
||||
// Get the cells of the end points.
|
||||
coord_t ix = p1(0) / m_resolution;
|
||||
coord_t iy = p1(1) / m_resolution;
|
||||
coord_t ixb = p2(0) / m_resolution;
|
||||
coord_t iyb = p2(1) / m_resolution;
|
||||
assert(ix >= 0 && size_t(ix) < m_cols);
|
||||
assert(iy >= 0 && size_t(iy) < m_rows);
|
||||
assert(ixb >= 0 && size_t(ixb) < m_cols);
|
||||
assert(iyb >= 0 && size_t(iyb) < m_rows);
|
||||
// Account for the end points.
|
||||
func(iy, ix);
|
||||
if (ix == ixb && iy == iyb)
|
||||
// Both ends fall into the same cell.
|
||||
return;
|
||||
// Raster the centeral part of the line.
|
||||
coord_t dx = std::abs(p2(0) - p1(0));
|
||||
coord_t dy = std::abs(p2(1) - p1(1));
|
||||
if (p1(0) < p2(0)) {
|
||||
int64_t ex = int64_t((ix + 1)*m_resolution - p1(0)) * int64_t(dy);
|
||||
if (p1(1) < p2(1)) {
|
||||
// x positive, y positive
|
||||
int64_t ey = int64_t((iy + 1)*m_resolution - p1(1)) * int64_t(dx);
|
||||
do {
|
||||
assert(ix <= ixb && iy <= iyb);
|
||||
if (ex < ey) {
|
||||
ey -= ex;
|
||||
ex = int64_t(dy) * m_resolution;
|
||||
ix += 1;
|
||||
}
|
||||
else if (ex == ey) {
|
||||
ex = int64_t(dy) * m_resolution;
|
||||
ey = int64_t(dx) * m_resolution;
|
||||
ix += 1;
|
||||
iy += 1;
|
||||
}
|
||||
else {
|
||||
assert(ex > ey);
|
||||
ex -= ey;
|
||||
ey = int64_t(dx) * m_resolution;
|
||||
iy += 1;
|
||||
}
|
||||
func(iy, ix);
|
||||
} while (ix != ixb || iy != iyb);
|
||||
}
|
||||
else {
|
||||
// x positive, y non positive
|
||||
int64_t ey = int64_t(p1(1) - iy*m_resolution) * int64_t(dx);
|
||||
do {
|
||||
assert(ix <= ixb && iy >= iyb);
|
||||
if (ex <= ey) {
|
||||
ey -= ex;
|
||||
ex = int64_t(dy) * m_resolution;
|
||||
ix += 1;
|
||||
}
|
||||
else {
|
||||
ex -= ey;
|
||||
ey = int64_t(dx) * m_resolution;
|
||||
iy -= 1;
|
||||
}
|
||||
func(iy, ix);
|
||||
} while (ix != ixb || iy != iyb);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int64_t ex = int64_t(p1(0) - ix*m_resolution) * int64_t(dy);
|
||||
if (p1(1) < p2(1)) {
|
||||
// x non positive, y positive
|
||||
int64_t ey = int64_t((iy + 1)*m_resolution - p1(1)) * int64_t(dx);
|
||||
do {
|
||||
assert(ix >= ixb && iy <= iyb);
|
||||
if (ex < ey) {
|
||||
ey -= ex;
|
||||
ex = int64_t(dy) * m_resolution;
|
||||
ix -= 1;
|
||||
}
|
||||
else {
|
||||
assert(ex >= ey);
|
||||
ex -= ey;
|
||||
ey = int64_t(dx) * m_resolution;
|
||||
iy += 1;
|
||||
}
|
||||
func(iy, ix);
|
||||
} while (ix != ixb || iy != iyb);
|
||||
}
|
||||
else {
|
||||
// x non positive, y non positive
|
||||
int64_t ey = int64_t(p1(1) - iy*m_resolution) * int64_t(dx);
|
||||
do {
|
||||
assert(ix >= ixb && iy >= iyb);
|
||||
if (ex < ey) {
|
||||
ey -= ex;
|
||||
ex = int64_t(dy) * m_resolution;
|
||||
ix -= 1;
|
||||
}
|
||||
else if (ex == ey) {
|
||||
// The lower edge of a grid cell belongs to the cell.
|
||||
// Handle the case where the ray may cross the lower left corner of a cell in a general case,
|
||||
// or a left or lower edge in a degenerate case (horizontal or vertical line).
|
||||
if (dx > 0) {
|
||||
ex = int64_t(dy) * m_resolution;
|
||||
ix -= 1;
|
||||
}
|
||||
if (dy > 0) {
|
||||
ey = int64_t(dx) * m_resolution;
|
||||
iy -= 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(ex > ey);
|
||||
ex -= ey;
|
||||
ey = int64_t(dx) * m_resolution;
|
||||
iy -= 1;
|
||||
}
|
||||
func(iy, ix);
|
||||
} while (ix != ixb || iy != iyb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<std::vector<std::pair<size_t, size_t>>::const_iterator, std::vector<std::pair<size_t, size_t>>::const_iterator> cell_data_range(coord_t row, coord_t col) const
|
||||
{
|
||||
const EdgeGrid::Grid::Cell &cell = m_cells[row * m_cols + col];
|
||||
return std::make_pair(m_cell_data.begin() + cell.begin, m_cell_data.begin() + cell.end);
|
||||
}
|
||||
|
||||
std::pair<const Slic3r::Point&, const Slic3r::Point&> segment(const std::pair<size_t, size_t> &contour_and_segment_idx) const
|
||||
{
|
||||
const Slic3r::Points &ipts = *m_contours[contour_and_segment_idx.first];
|
||||
size_t ipt = contour_and_segment_idx.second;
|
||||
return std::pair<const Slic3r::Point&, const Slic3r::Point&>(ipts[ipt], ipts[(ipt + 1 == ipts.size()) ? 0 : ipt + 1]);
|
||||
}
|
||||
|
||||
protected:
|
||||
struct Cell {
|
||||
Cell() : begin(0), end(0) {}
|
||||
|
@ -76,10 +76,14 @@ float Flow::spacing() const
|
||||
return this->width + BRIDGE_EXTRA_SPACING;
|
||||
// rectangle with semicircles at the ends
|
||||
float min_flow_spacing = this->width - this->height * (1. - 0.25 * PI);
|
||||
return this->width - PERIMETER_LINE_OVERLAP_FACTOR * (this->width - min_flow_spacing);
|
||||
float res = this->width - PERIMETER_LINE_OVERLAP_FACTOR * (this->width - min_flow_spacing);
|
||||
#else
|
||||
return float(this->bridge ? (this->width + BRIDGE_EXTRA_SPACING) : (this->width - this->height * (1. - 0.25 * PI)));
|
||||
float res = float(this->bridge ? (this->width + BRIDGE_EXTRA_SPACING) : (this->width - this->height * (1. - 0.25 * PI)));
|
||||
#endif
|
||||
// assert(res > 0.f);
|
||||
if (res <= 0.f)
|
||||
throw std::runtime_error("Flow::spacing() produced negative spacing. Did you set some extrusion width too small?");
|
||||
return res;
|
||||
}
|
||||
|
||||
// This method returns the centerline spacing between an extrusion using this
|
||||
@ -89,20 +93,26 @@ float Flow::spacing(const Flow &other) const
|
||||
{
|
||||
assert(this->height == other.height);
|
||||
assert(this->bridge == other.bridge);
|
||||
return float(this->bridge ?
|
||||
float res = float(this->bridge ?
|
||||
0.5 * this->width + 0.5 * other.width + BRIDGE_EXTRA_SPACING :
|
||||
0.5 * this->spacing() + 0.5 * other.spacing());
|
||||
// assert(res > 0.f);
|
||||
if (res <= 0.f)
|
||||
throw std::runtime_error("Flow::spacing() produced negative spacing. Did you set some extrusion width too small?");
|
||||
return res;
|
||||
}
|
||||
|
||||
// This method returns extrusion volume per head move unit.
|
||||
double Flow::mm3_per_mm() const
|
||||
{
|
||||
double res = this->bridge ?
|
||||
float res = this->bridge ?
|
||||
// Area of a circle with dmr of this->width.
|
||||
(this->width * this->width) * 0.25 * PI :
|
||||
// Rectangle with semicircles at the ends. ~ h (w - 0.215 h)
|
||||
this->height * (this->width - this->height * (1. - 0.25 * PI));
|
||||
assert(res > 0.);
|
||||
//assert(res > 0.);
|
||||
if (res <= 0.)
|
||||
throw std::runtime_error("Flow::mm3_per_mm() produced negative flow. Did you set some extrusion width too small?");
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include "../GCode.hpp"
|
||||
#include "../Geometry.hpp"
|
||||
|
||||
#include "../I18N.hpp"
|
||||
|
||||
#include "3mf.hpp"
|
||||
|
||||
#include <limits>
|
||||
@ -71,6 +73,7 @@ const char* V2_ATTR = "v2";
|
||||
const char* V3_ATTR = "v3";
|
||||
const char* OBJECTID_ATTR = "objectid";
|
||||
const char* TRANSFORM_ATTR = "transform";
|
||||
const char* PRINTABLE_ATTR = "printable";
|
||||
|
||||
const char* KEY_ATTR = "key";
|
||||
const char* VALUE_ATTR = "value";
|
||||
@ -131,6 +134,12 @@ int get_attribute_value_int(const char** attributes, unsigned int attributes_siz
|
||||
return (text != nullptr) ? ::atoi(text) : 0;
|
||||
}
|
||||
|
||||
bool get_attribute_value_bool(const char** attributes, unsigned int attributes_size, const char* attribute_key)
|
||||
{
|
||||
const char* text = get_attribute_value_charptr(attributes, attributes_size, attribute_key);
|
||||
return (text != nullptr) ? (bool)::atoi(text) : true;
|
||||
}
|
||||
|
||||
Slic3r::Transform3d get_transform_from_string(const std::string& mat_str)
|
||||
{
|
||||
if (mat_str.empty())
|
||||
@ -195,6 +204,11 @@ bool is_valid_object_type(const std::string& type)
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
//! macro used to mark string used at localization,
|
||||
//! return same string
|
||||
#define L(s) (s)
|
||||
#define _(s) Slic3r::I18N::translate(s)
|
||||
|
||||
// Base class with error messages management
|
||||
class _3MF_Base
|
||||
{
|
||||
@ -343,6 +357,7 @@ namespace Slic3r {
|
||||
|
||||
// Version of the 3mf file
|
||||
unsigned int m_version;
|
||||
bool m_check_version;
|
||||
|
||||
XML_Parser m_xml_parser;
|
||||
Model* m_model;
|
||||
@ -365,7 +380,7 @@ namespace Slic3r {
|
||||
_3MF_Importer();
|
||||
~_3MF_Importer();
|
||||
|
||||
bool load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config);
|
||||
bool load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config, bool check_version);
|
||||
|
||||
private:
|
||||
void _destroy_xml_parser();
|
||||
@ -428,7 +443,7 @@ namespace Slic3r {
|
||||
bool _handle_start_metadata(const char** attributes, unsigned int num_attributes);
|
||||
bool _handle_end_metadata();
|
||||
|
||||
bool _create_object_instance(int object_id, const Transform3d& transform, unsigned int recur_counter);
|
||||
bool _create_object_instance(int object_id, const Transform3d& transform, const bool printable, unsigned int recur_counter);
|
||||
|
||||
void _apply_transform(ModelInstance& instance, const Transform3d& transform);
|
||||
|
||||
@ -458,6 +473,7 @@ namespace Slic3r {
|
||||
|
||||
_3MF_Importer::_3MF_Importer()
|
||||
: m_version(0)
|
||||
, m_check_version(false)
|
||||
, m_xml_parser(nullptr)
|
||||
, m_model(nullptr)
|
||||
, m_unit_factor(1.0f)
|
||||
@ -472,9 +488,10 @@ namespace Slic3r {
|
||||
_destroy_xml_parser();
|
||||
}
|
||||
|
||||
bool _3MF_Importer::load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config)
|
||||
bool _3MF_Importer::load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config, bool check_version)
|
||||
{
|
||||
m_version = 0;
|
||||
m_check_version = check_version;
|
||||
m_model = &model;
|
||||
m_unit_factor = 1.0f;
|
||||
m_curr_object.reset();
|
||||
@ -536,12 +553,21 @@ namespace Slic3r {
|
||||
|
||||
if (boost::algorithm::istarts_with(name, MODEL_FOLDER) && boost::algorithm::iends_with(name, MODEL_EXTENSION))
|
||||
{
|
||||
// valid model name -> extract model
|
||||
if (!_extract_model_from_archive(archive, stat))
|
||||
try
|
||||
{
|
||||
// valid model name -> extract model
|
||||
if (!_extract_model_from_archive(archive, stat))
|
||||
{
|
||||
close_zip_reader(&archive);
|
||||
add_error("Archive does not contain a valid model");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
// ensure the zip archive is closed and rethrow the exception
|
||||
close_zip_reader(&archive);
|
||||
add_error("Archive does not contain a valid model");
|
||||
return false;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1367,8 +1393,9 @@ namespace Slic3r {
|
||||
|
||||
int object_id = get_attribute_value_int(attributes, num_attributes, OBJECTID_ATTR);
|
||||
Transform3d transform = get_transform_from_string(get_attribute_value_string(attributes, num_attributes, TRANSFORM_ATTR));
|
||||
int printable = get_attribute_value_bool(attributes, num_attributes, PRINTABLE_ATTR);
|
||||
|
||||
return _create_object_instance(object_id, transform, 1);
|
||||
return _create_object_instance(object_id, transform, printable, 1);
|
||||
}
|
||||
|
||||
bool _3MF_Importer::_handle_end_item()
|
||||
@ -1391,12 +1418,20 @@ namespace Slic3r {
|
||||
bool _3MF_Importer::_handle_end_metadata()
|
||||
{
|
||||
if (m_curr_metadata_name == SLIC3RPE_3MF_VERSION)
|
||||
{
|
||||
m_version = (unsigned int)atoi(m_curr_characters.c_str());
|
||||
|
||||
if (m_check_version && (m_version > VERSION_3MF))
|
||||
{
|
||||
std::string msg = _(L("The selected 3mf file has been saved with a newer version of " + std::string(SLIC3R_APP_NAME) + " and is not compatibile."));
|
||||
throw std::runtime_error(msg.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _3MF_Importer::_create_object_instance(int object_id, const Transform3d& transform, unsigned int recur_counter)
|
||||
bool _3MF_Importer::_create_object_instance(int object_id, const Transform3d& transform, const bool printable, unsigned int recur_counter)
|
||||
{
|
||||
static const unsigned int MAX_RECURSIONS = 10;
|
||||
|
||||
@ -1432,6 +1467,7 @@ namespace Slic3r {
|
||||
add_error("Unable to add object instance");
|
||||
return false;
|
||||
}
|
||||
instance->printable = printable;
|
||||
|
||||
m_instances.emplace_back(instance, transform);
|
||||
}
|
||||
@ -1441,7 +1477,7 @@ namespace Slic3r {
|
||||
// recursively process nested components
|
||||
for (const Component& component : it->second)
|
||||
{
|
||||
if (!_create_object_instance(component.object_id, transform * component.transform, recur_counter + 1))
|
||||
if (!_create_object_instance(component.object_id, transform * component.transform, printable, recur_counter + 1))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1655,10 +1691,12 @@ namespace Slic3r {
|
||||
{
|
||||
unsigned int id;
|
||||
Transform3d transform;
|
||||
bool printable;
|
||||
|
||||
BuildItem(unsigned int id, const Transform3d& transform)
|
||||
BuildItem(unsigned int id, const Transform3d& transform, const bool printable)
|
||||
: id(id)
|
||||
, transform(transform)
|
||||
, printable(printable)
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -1951,7 +1989,7 @@ namespace Slic3r {
|
||||
Transform3d t = instance->get_matrix();
|
||||
// instance_id is just a 1 indexed index in build_items.
|
||||
assert(instance_id == build_items.size() + 1);
|
||||
build_items.emplace_back(instance_id, t);
|
||||
build_items.emplace_back(instance_id, t, instance->printable);
|
||||
|
||||
stream << " </" << OBJECT_TAG << ">\n";
|
||||
|
||||
@ -2059,7 +2097,7 @@ namespace Slic3r {
|
||||
stream << " ";
|
||||
}
|
||||
}
|
||||
stream << "\" />\n";
|
||||
stream << "\" printable =\"" << item.printable << "\" />\n";
|
||||
}
|
||||
|
||||
stream << " </" << BUILD_TAG << ">\n";
|
||||
@ -2305,13 +2343,13 @@ namespace Slic3r {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool load_3mf(const char* path, DynamicPrintConfig* config, Model* model)
|
||||
bool load_3mf(const char* path, DynamicPrintConfig* config, Model* model, bool check_version)
|
||||
{
|
||||
if ((path == nullptr) || (config == nullptr) || (model == nullptr))
|
||||
return false;
|
||||
|
||||
_3MF_Importer importer;
|
||||
bool res = importer.load_model_from_file(path, *model, *config);
|
||||
bool res = importer.load_model_from_file(path, *model, *config, check_version);
|
||||
importer.log_errors();
|
||||
return res;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ namespace Slic3r {
|
||||
class DynamicPrintConfig;
|
||||
|
||||
// Load the content of a 3mf file into the given model and preset bundle.
|
||||
extern bool load_3mf(const char* path, DynamicPrintConfig* config, Model* model);
|
||||
extern bool load_3mf(const char* path, DynamicPrintConfig* config, Model* model, bool check_version);
|
||||
|
||||
// Save the given model and the config data contained in the given Print into a 3mf file.
|
||||
// The model could be modified during the export process if meshes are not repaired or have no shared vertices
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "../GCode.hpp"
|
||||
#include "../PrintConfig.hpp"
|
||||
#include "../Utils.hpp"
|
||||
#include "../I18N.hpp"
|
||||
|
||||
#include "AMF.hpp"
|
||||
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
@ -42,9 +44,14 @@ const char* SLIC3R_CONFIG_TYPE = "slic3rpe_config";
|
||||
namespace Slic3r
|
||||
{
|
||||
|
||||
//! macro used to mark string used at localization,
|
||||
//! return same string
|
||||
#define L(s) (s)
|
||||
#define _(s) Slic3r::I18N::translate(s)
|
||||
|
||||
struct AMFParserContext
|
||||
{
|
||||
AMFParserContext(XML_Parser parser, DynamicPrintConfig *config, Model *model) :
|
||||
AMFParserContext(XML_Parser parser, DynamicPrintConfig* config, Model* model) :
|
||||
m_version(0),
|
||||
m_parser(parser),
|
||||
m_model(*model),
|
||||
@ -137,6 +144,7 @@ struct AMFParserContext
|
||||
NODE_TYPE_MIRRORX, // amf/constellation/instance/mirrorx
|
||||
NODE_TYPE_MIRRORY, // amf/constellation/instance/mirrory
|
||||
NODE_TYPE_MIRRORZ, // amf/constellation/instance/mirrorz
|
||||
NODE_TYPE_PRINTABLE, // amf/constellation/instance/mirrorz
|
||||
NODE_TYPE_METADATA, // anywhere under amf/*/metadata
|
||||
};
|
||||
|
||||
@ -145,7 +153,8 @@ struct AMFParserContext
|
||||
: deltax_set(false), deltay_set(false), deltaz_set(false)
|
||||
, rx_set(false), ry_set(false), rz_set(false)
|
||||
, scalex_set(false), scaley_set(false), scalez_set(false)
|
||||
, mirrorx_set(false), mirrory_set(false), mirrorz_set(false) {}
|
||||
, mirrorx_set(false), mirrory_set(false), mirrorz_set(false)
|
||||
, printable(true) {}
|
||||
// Shift in the X axis.
|
||||
float deltax;
|
||||
bool deltax_set;
|
||||
@ -178,6 +187,8 @@ struct AMFParserContext
|
||||
bool mirrory_set;
|
||||
float mirrorz;
|
||||
bool mirrorz_set;
|
||||
// printable property
|
||||
bool printable;
|
||||
|
||||
bool anything_set() const { return deltax_set || deltay_set || deltaz_set ||
|
||||
rx_set || ry_set || rz_set ||
|
||||
@ -321,6 +332,8 @@ void AMFParserContext::startElement(const char *name, const char **atts)
|
||||
node_type_new = NODE_TYPE_MIRRORY;
|
||||
else if (strcmp(name, "mirrorz") == 0)
|
||||
node_type_new = NODE_TYPE_MIRRORZ;
|
||||
else if (strcmp(name, "printable") == 0)
|
||||
node_type_new = NODE_TYPE_PRINTABLE;
|
||||
}
|
||||
else if (m_path[2] == NODE_TYPE_LAYER_CONFIG && strcmp(name, "range") == 0) {
|
||||
assert(m_object);
|
||||
@ -397,7 +410,8 @@ void AMFParserContext::characters(const XML_Char *s, int len)
|
||||
m_path.back() == NODE_TYPE_SCALE ||
|
||||
m_path.back() == NODE_TYPE_MIRRORX ||
|
||||
m_path.back() == NODE_TYPE_MIRRORY ||
|
||||
m_path.back() == NODE_TYPE_MIRRORZ)
|
||||
m_path.back() == NODE_TYPE_MIRRORZ ||
|
||||
m_path.back() == NODE_TYPE_PRINTABLE)
|
||||
m_value[0].append(s, len);
|
||||
break;
|
||||
case 6:
|
||||
@ -507,6 +521,11 @@ void AMFParserContext::endElement(const char * /* name */)
|
||||
m_instance->mirrorz_set = true;
|
||||
m_value[0].clear();
|
||||
break;
|
||||
case NODE_TYPE_PRINTABLE:
|
||||
assert(m_instance);
|
||||
m_instance->printable = bool(atoi(m_value[0].c_str()));
|
||||
m_value[0].clear();
|
||||
break;
|
||||
|
||||
// Object vertices:
|
||||
case NODE_TYPE_VERTEX:
|
||||
@ -685,6 +704,7 @@ void AMFParserContext::endDocument()
|
||||
mi->set_rotation(Vec3d(instance.rx_set ? (double)instance.rx : 0.0, instance.ry_set ? (double)instance.ry : 0.0, instance.rz_set ? (double)instance.rz : 0.0));
|
||||
mi->set_scaling_factor(Vec3d(instance.scalex_set ? (double)instance.scalex : 1.0, instance.scaley_set ? (double)instance.scaley : 1.0, instance.scalez_set ? (double)instance.scalez : 1.0));
|
||||
mi->set_mirror(Vec3d(instance.mirrorx_set ? (double)instance.mirrorx : 1.0, instance.mirrory_set ? (double)instance.mirrory : 1.0, instance.mirrorz_set ? (double)instance.mirrorz : 1.0));
|
||||
mi->printable = instance.printable;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -742,7 +762,7 @@ bool load_amf_file(const char *path, DynamicPrintConfig *config, Model *model)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, DynamicPrintConfig* config, Model* model, unsigned int& version)
|
||||
bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, DynamicPrintConfig* config, Model* model, bool check_version)
|
||||
{
|
||||
if (stat.m_uncomp_size == 0)
|
||||
{
|
||||
@ -788,19 +808,21 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi
|
||||
|
||||
ctx.endDocument();
|
||||
|
||||
version = ctx.m_version;
|
||||
if (check_version && (ctx.m_version > VERSION_AMF))
|
||||
{
|
||||
std::string msg = _(L("The selected amf file has been saved with a newer version of " + std::string(SLIC3R_APP_NAME) + " and is not compatibile."));
|
||||
throw std::runtime_error(msg.c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Load an AMF archive into a provided model.
|
||||
bool load_amf_archive(const char *path, DynamicPrintConfig *config, Model *model)
|
||||
bool load_amf_archive(const char* path, DynamicPrintConfig* config, Model* model, bool check_version)
|
||||
{
|
||||
if ((path == nullptr) || (model == nullptr))
|
||||
return false;
|
||||
|
||||
unsigned int version = 0;
|
||||
|
||||
mz_zip_archive archive;
|
||||
mz_zip_zero_struct(&archive);
|
||||
|
||||
@ -820,11 +842,20 @@ bool load_amf_archive(const char *path, DynamicPrintConfig *config, Model *model
|
||||
{
|
||||
if (boost::iends_with(stat.m_filename, ".amf"))
|
||||
{
|
||||
if (!extract_model_from_archive(archive, stat, config, model, version))
|
||||
try
|
||||
{
|
||||
if (!extract_model_from_archive(archive, stat, config, model, check_version))
|
||||
{
|
||||
close_zip_reader(&archive);
|
||||
printf("Archive does not contain a valid model");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
// ensure the zip archive is closed and rethrow the exception
|
||||
close_zip_reader(&archive);
|
||||
printf("Archive does not contain a valid model");
|
||||
return false;
|
||||
throw e;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -849,7 +880,7 @@ bool load_amf_archive(const char *path, DynamicPrintConfig *config, Model *model
|
||||
|
||||
// Load an AMF file into a provided model.
|
||||
// If config is not a null pointer, updates it if the amf file/archive contains config data
|
||||
bool load_amf(const char *path, DynamicPrintConfig *config, Model *model)
|
||||
bool load_amf(const char* path, DynamicPrintConfig* config, Model* model, bool check_version)
|
||||
{
|
||||
if (boost::iends_with(path, ".amf.xml"))
|
||||
// backward compatibility with older slic3r output
|
||||
@ -864,7 +895,7 @@ bool load_amf(const char *path, DynamicPrintConfig *config, Model *model)
|
||||
file.read(const_cast<char*>(zip_mask.data()), 2);
|
||||
file.close();
|
||||
|
||||
return (zip_mask == "PK") ? load_amf_archive(path, config, model) : load_amf_file(path, config, model);
|
||||
return (zip_mask == "PK") ? load_amf_archive(path, config, model, check_version) : load_amf_file(path, config, model);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
@ -1036,6 +1067,7 @@ bool store_amf(std::string &path, Model *model, const DynamicPrintConfig *config
|
||||
" <mirrorx>%lf</mirrorx>\n"
|
||||
" <mirrory>%lf</mirrory>\n"
|
||||
" <mirrorz>%lf</mirrorz>\n"
|
||||
" <printable>%d</printable>\n"
|
||||
" </instance>\n",
|
||||
object_id,
|
||||
instance->get_offset(X),
|
||||
@ -1049,7 +1081,8 @@ bool store_amf(std::string &path, Model *model, const DynamicPrintConfig *config
|
||||
instance->get_scaling_factor(Z),
|
||||
instance->get_mirror(X),
|
||||
instance->get_mirror(Y),
|
||||
instance->get_mirror(Z));
|
||||
instance->get_mirror(Z),
|
||||
instance->printable);
|
||||
|
||||
//FIXME missing instance->scaling_factor
|
||||
instances.append(buf);
|
||||
|
@ -7,7 +7,7 @@ class Model;
|
||||
class DynamicPrintConfig;
|
||||
|
||||
// Load the content of an amf file into the given model and configuration.
|
||||
extern bool load_amf(const char *path, DynamicPrintConfig *config, Model *model);
|
||||
extern bool load_amf(const char* path, DynamicPrintConfig* config, Model* model, bool check_version);
|
||||
|
||||
// Save the given model and the config data into an amf file.
|
||||
// The model could be modified during the export process if meshes are not repaired or have no shared vertices
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "libslic3r.h"
|
||||
#include "I18N.hpp"
|
||||
#include "GCode.hpp"
|
||||
#include "ExtrusionEntity.hpp"
|
||||
#include "EdgeGrid.hpp"
|
||||
@ -23,6 +24,8 @@
|
||||
|
||||
#include "SVG.hpp"
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
|
||||
#include <Shiny/Shiny.h>
|
||||
|
||||
#if 0
|
||||
@ -36,6 +39,11 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
//! macro used to mark string used at localization,
|
||||
//! return same string
|
||||
#define L(s) (s)
|
||||
#define _(s) Slic3r::I18N::translate(s)
|
||||
|
||||
// Only add a newline in case the current G-code does not end with a newline.
|
||||
static inline void check_add_eol(std::string &gcode)
|
||||
{
|
||||
@ -43,6 +51,11 @@ static inline void check_add_eol(std::string &gcode)
|
||||
gcode += '\n';
|
||||
}
|
||||
|
||||
void AvoidCrossingPerimeters::init_external_mp(const Print &print)
|
||||
{
|
||||
m_external_mp = Slic3r::make_unique<MotionPlanner>(union_ex(this->collect_contours_all_layers(print.objects())));
|
||||
}
|
||||
|
||||
// Plan a travel move while minimizing the number of perimeter crossings.
|
||||
// point is in unscaled coordinates, in the coordinate system of the current active object
|
||||
// (set by gcodegen.set_origin()).
|
||||
@ -59,6 +72,72 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point &
|
||||
return result;
|
||||
}
|
||||
|
||||
// Collect outer contours of all objects over all layers.
|
||||
// Discard objects only containing thin walls (offset would fail on an empty polygon).
|
||||
// Used by avoid crossing perimeters feature.
|
||||
Polygons AvoidCrossingPerimeters::collect_contours_all_layers(const PrintObjectPtrs& objects)
|
||||
{
|
||||
Polygons islands;
|
||||
for (const PrintObject *object : objects) {
|
||||
// Reducing all the object slices into the Z projection in a logarithimc fashion.
|
||||
// First reduce to half the number of layers.
|
||||
std::vector<Polygons> polygons_per_layer((object->layers().size() + 1) / 2);
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, object->layers().size() / 2),
|
||||
[&object, &polygons_per_layer](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t i = range.begin(); i < range.end(); ++ i) {
|
||||
const Layer* layer1 = object->layers()[i * 2];
|
||||
const Layer* layer2 = object->layers()[i * 2 + 1];
|
||||
Polygons polys;
|
||||
polys.reserve(layer1->slices.expolygons.size() + layer2->slices.expolygons.size());
|
||||
for (const ExPolygon &expoly : layer1->slices.expolygons)
|
||||
//FIXME no holes?
|
||||
polys.emplace_back(expoly.contour);
|
||||
for (const ExPolygon &expoly : layer2->slices.expolygons)
|
||||
//FIXME no holes?
|
||||
polys.emplace_back(expoly.contour);
|
||||
polygons_per_layer[i] = union_(polys);
|
||||
}
|
||||
});
|
||||
if (object->layers().size() & 1) {
|
||||
const Layer *layer = object->layers().back();
|
||||
Polygons polys;
|
||||
polys.reserve(layer->slices.expolygons.size());
|
||||
for (const ExPolygon &expoly : layer->slices.expolygons)
|
||||
//FIXME no holes?
|
||||
polys.emplace_back(expoly.contour);
|
||||
polygons_per_layer.back() = union_(polys);
|
||||
}
|
||||
// Now reduce down to a single layer.
|
||||
size_t cnt = polygons_per_layer.size();
|
||||
while (cnt > 1) {
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, cnt / 2),
|
||||
[&polygons_per_layer](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t i = range.begin(); i < range.end(); ++ i) {
|
||||
Polygons polys;
|
||||
polys.reserve(polygons_per_layer[i * 2].size() + polygons_per_layer[i * 2 + 1].size());
|
||||
polygons_append(polys, polygons_per_layer[i * 2]);
|
||||
polygons_append(polys, polygons_per_layer[i * 2 + 1]);
|
||||
polygons_per_layer[i * 2] = union_(polys);
|
||||
}
|
||||
});
|
||||
for (size_t i = 0; i < cnt / 2; ++ i)
|
||||
polygons_per_layer[i] = std::move(polygons_per_layer[i * 2]);
|
||||
if (cnt & 1)
|
||||
polygons_per_layer[cnt / 2] = std::move(polygons_per_layer[cnt - 1]);
|
||||
cnt = (cnt + 1) / 2;
|
||||
}
|
||||
// And collect copies of the objects.
|
||||
for (const Point © : object->copies()) {
|
||||
// All the layers were reduced to the 1st item of polygons_per_layer.
|
||||
size_t i = islands.size();
|
||||
polygons_append(islands, polygons_per_layer.front());
|
||||
for (; i < islands.size(); ++ i)
|
||||
islands[i].translate(copy);
|
||||
}
|
||||
}
|
||||
return islands;
|
||||
}
|
||||
|
||||
std::string OozePrevention::pre_toolchange(GCode &gcodegen)
|
||||
{
|
||||
std::string gcode;
|
||||
@ -191,9 +270,6 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
|
||||
|
||||
std::string tcr_rotated_gcode = post_process_wipe_tower_moves(tcr, wipe_tower_offset, wipe_tower_rotation);
|
||||
|
||||
// Disable linear advance for the wipe tower operations.
|
||||
gcode += (gcodegen.config().gcode_flavor == gcfRepRap ? std::string("M572 D0 S0\n") : std::string("M900 K0\n"));
|
||||
|
||||
if (!tcr.priming) {
|
||||
// Move over the wipe tower.
|
||||
// Retract for a tool change, using the toolchange retract value and setting the priming extra length.
|
||||
@ -362,7 +438,6 @@ std::string WipeTowerIntegration::post_process_wipe_tower_moves(const WipeTower:
|
||||
|
||||
std::string WipeTowerIntegration::prime(GCode &gcodegen)
|
||||
{
|
||||
//assert(m_layer_idx == 0);
|
||||
std::string gcode;
|
||||
|
||||
if (&m_priming != nullptr) {
|
||||
@ -405,7 +480,8 @@ std::string WipeTowerIntegration::tool_change(GCode &gcodegen, int extruder_id,
|
||||
assert(m_layer_idx >= 0 && size_t(m_layer_idx) <= m_tool_changes.size());
|
||||
if (! m_brim_done || gcodegen.writer().need_toolchange(extruder_id) || finish_layer) {
|
||||
if (m_layer_idx < (int)m_tool_changes.size()) {
|
||||
assert(size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size());
|
||||
if (! (size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size()))
|
||||
throw std::runtime_error("Wipe tower generation failed, possibly due to empty first layer.");
|
||||
gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][m_tool_change_idx++], extruder_id);
|
||||
}
|
||||
m_brim_done = true;
|
||||
@ -435,6 +511,7 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
|
||||
// Pair the object layers with the support layers by z.
|
||||
size_t idx_object_layer = 0;
|
||||
size_t idx_support_layer = 0;
|
||||
const LayerToPrint* last_extrusion_layer = nullptr;
|
||||
while (idx_object_layer < object.layers().size() || idx_support_layer < object.support_layers().size()) {
|
||||
LayerToPrint layer_to_print;
|
||||
layer_to_print.object_layer = (idx_object_layer < object.layers().size()) ? object.layers()[idx_object_layer ++] : nullptr;
|
||||
@ -448,7 +525,31 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
|
||||
-- idx_object_layer;
|
||||
}
|
||||
}
|
||||
|
||||
layers_to_print.emplace_back(layer_to_print);
|
||||
|
||||
// In case there are extrusions on this layer, check there is a layer to lay it on.
|
||||
if ((layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions())
|
||||
|| (layer_to_print.support_layer && layer_to_print.support_layer->has_extrusions())) {
|
||||
double support_contact_z = (last_extrusion_layer && last_extrusion_layer->support_layer)
|
||||
? object.config().support_material_contact_distance
|
||||
: 0.;
|
||||
double maximal_print_z = (last_extrusion_layer ? last_extrusion_layer->print_z() : 0.)
|
||||
+ layer_to_print.layer()->height
|
||||
+ std::max(0., support_contact_z);
|
||||
// Negative support_contact_z is not taken into account, it can result in false positives in cases
|
||||
// where previous layer has object extrusions too (https://github.com/prusa3d/PrusaSlicer/issues/2752)
|
||||
|
||||
|
||||
if (layer_to_print.print_z() > maximal_print_z + EPSILON)
|
||||
throw std::runtime_error(_(L("Empty layers detected, the output would not be printable.")) + "\n\n" +
|
||||
_(L("Object name: ")) + object.model_object()->name + "\n" + _(L("Print z: ")) +
|
||||
std::to_string(layers_to_print.back().print_z()) + "\n\n" + _(L("This is "
|
||||
"usually caused by negligibly small extrusions or by a faulty model. Try to repair "
|
||||
" the model or change its orientation on the bed.")));
|
||||
// Remember last layer with extrusions.
|
||||
last_extrusion_layer = &layers_to_print.back();
|
||||
}
|
||||
}
|
||||
|
||||
return layers_to_print;
|
||||
@ -561,11 +662,11 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
|
||||
}
|
||||
|
||||
if (print->config().remaining_times.value) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for normal mode";
|
||||
BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for normal mode" << log_memory_info();
|
||||
m_normal_time_estimator.post_process_remaining_times(path_tmp, 60.0f);
|
||||
m_normal_time_estimator.reset();
|
||||
if (m_silent_time_estimator_enabled) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for silent mode";
|
||||
BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for silent mode" << log_memory_info();
|
||||
m_silent_time_estimator.post_process_remaining_times(path_tmp, 60.0f);
|
||||
m_silent_time_estimator.reset();
|
||||
}
|
||||
@ -573,12 +674,12 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
|
||||
|
||||
// starts analyzer calculations
|
||||
if (m_enable_analyzer) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Preparing G-code preview data";
|
||||
BOOST_LOG_TRIVIAL(debug) << "Preparing G-code preview data" << log_memory_info();
|
||||
m_analyzer.calc_gcode_preview_data(*preview_data, [print]() { print->throw_if_canceled(); });
|
||||
m_analyzer.reset();
|
||||
}
|
||||
|
||||
if (rename_file(path_tmp, path) != 0)
|
||||
if (rename_file(path_tmp, path))
|
||||
throw std::runtime_error(
|
||||
std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + path + '\n' +
|
||||
"Is " + path_tmp + " locked?" + '\n');
|
||||
@ -748,7 +849,7 @@ void GCode::_do_export(Print &print, FILE *file)
|
||||
mm3_per_mm.erase(std::remove_if(mm3_per_mm.begin(), mm3_per_mm.end(), [](double v) { return v < 0.000001; }), mm3_per_mm.end());
|
||||
if (! mm3_per_mm.empty()) {
|
||||
// In order to honor max_print_speed we need to find a target volumetric
|
||||
// speed that we can use throughout the print. So we define this target
|
||||
// speed that we can use throughout the print. So we define this target
|
||||
// volumetric speed as the volumetric speed produced by printing the
|
||||
// smallest cross-section at the maximum speed: any larger cross-section
|
||||
// will need slower feedrates.
|
||||
@ -836,7 +937,7 @@ void GCode::_do_export(Print &print, FILE *file)
|
||||
_writeln(file, GCodeTimeEstimator::Silent_First_M73_Output_Placeholder_Tag);
|
||||
}
|
||||
|
||||
// Prepare the helper object for replacing placeholders in custom G-code and output filename.
|
||||
// Prepare the helper object for replacing placeholders in custom G-code and output filename.
|
||||
m_placeholder_parser = print.placeholder_parser();
|
||||
m_placeholder_parser.update_timestamp();
|
||||
print.update_object_placeholders(m_placeholder_parser.config_writable(), ".gcode");
|
||||
@ -931,19 +1032,9 @@ void GCode::_do_export(Print &print, FILE *file)
|
||||
_write(file, this->preamble());
|
||||
|
||||
// Initialize a motion planner for object-to-object travel moves.
|
||||
m_avoid_crossing_perimeters.reset();
|
||||
if (print.config().avoid_crossing_perimeters.value) {
|
||||
// Collect outer contours of all objects over all layers.
|
||||
// Discard objects only containing thin walls (offset would fail on an empty polygon).
|
||||
Polygons islands;
|
||||
for (const PrintObject *object : print.objects())
|
||||
for (const Layer *layer : object->layers())
|
||||
for (const ExPolygon &expoly : layer->slices.expolygons)
|
||||
for (const Point © : object->copies()) {
|
||||
islands.emplace_back(expoly.contour);
|
||||
islands.back().translate(copy);
|
||||
}
|
||||
//FIXME Mege the islands in parallel.
|
||||
m_avoid_crossing_perimeters.init_external_mp(union_ex(islands));
|
||||
m_avoid_crossing_perimeters.init_external_mp(print);
|
||||
print.throw_if_canceled();
|
||||
}
|
||||
|
||||
@ -1159,9 +1250,9 @@ void GCode::_do_export(Print &print, FILE *file)
|
||||
print.m_print_statistics.clear();
|
||||
print.m_print_statistics.estimated_normal_print_time = m_normal_time_estimator.get_time_dhms();
|
||||
print.m_print_statistics.estimated_silent_print_time = m_silent_time_estimator_enabled ? m_silent_time_estimator.get_time_dhms() : "N/A";
|
||||
print.m_print_statistics.estimated_normal_color_print_times = m_normal_time_estimator.get_color_times_dhms();
|
||||
print.m_print_statistics.estimated_normal_color_print_times = m_normal_time_estimator.get_color_times_dhms(true);
|
||||
if (m_silent_time_estimator_enabled)
|
||||
print.m_print_statistics.estimated_silent_color_print_times = m_silent_time_estimator.get_color_times_dhms();
|
||||
print.m_print_statistics.estimated_silent_color_print_times = m_silent_time_estimator.get_color_times_dhms(true);
|
||||
|
||||
std::vector<Extruder> extruders = m_writer.extruders();
|
||||
if (! extruders.empty()) {
|
||||
@ -1514,7 +1605,13 @@ void GCode::process_layer(
|
||||
|
||||
// we should add or not colorprint_change in respect to nozzle_diameter count instead of really used extruders count
|
||||
if (colorprint_change && print./*extruders()*/config().nozzle_diameter.size()==1)
|
||||
{
|
||||
// add tag for analyzer
|
||||
gcode += "; " + GCodeAnalyzer::Color_Change_Tag + "\n";
|
||||
// add tag for time estimator
|
||||
gcode += "; " + GCodeTimeEstimator::Color_Change_Tag + "\n";
|
||||
gcode += "M600\n";
|
||||
}
|
||||
|
||||
|
||||
// Extrude skirt at the print_z of the raft layers and normal object layers
|
||||
@ -1870,7 +1967,8 @@ void GCode::process_layer(
|
||||
", time estimator memory: " <<
|
||||
format_memsize_MB(m_normal_time_estimator.memory_used() + m_silent_time_estimator_enabled ? m_silent_time_estimator.memory_used() : 0) <<
|
||||
", analyzer memory: " <<
|
||||
format_memsize_MB(m_analyzer.memory_used());
|
||||
format_memsize_MB(m_analyzer.memory_used()) <<
|
||||
log_memory_info();
|
||||
}
|
||||
|
||||
void GCode::apply_print_config(const PrintConfig &print_config)
|
||||
@ -2789,7 +2887,7 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
|
||||
EXTRUDER_CONFIG(filament_max_volumetric_speed) / path.mm3_per_mm
|
||||
);
|
||||
}
|
||||
double F = speed * 60; // convert mm/sec to mm/min
|
||||
double F = speed * 60; // convert mm/sec to mm/min
|
||||
|
||||
// extrude arc or line
|
||||
if (m_enable_extrusion_role_markers) {
|
||||
@ -3049,7 +3147,7 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
|
||||
|
||||
// Set the temperature if the wipe tower didn't (not needed for non-single extruder MM)
|
||||
if (m_config.single_extruder_multi_material && !m_config.wipe_tower) {
|
||||
int temp = (m_layer_index == 0 ? m_config.first_layer_temperature.get_at(extruder_id) :
|
||||
int temp = (m_layer_index <= 0 ? m_config.first_layer_temperature.get_at(extruder_id) :
|
||||
m_config.temperature.get_at(extruder_id));
|
||||
|
||||
gcode += m_writer.set_temperature(temp, false);
|
||||
|
@ -45,13 +45,17 @@ public:
|
||||
AvoidCrossingPerimeters() : use_external_mp(false), use_external_mp_once(false), disable_once(true) {}
|
||||
~AvoidCrossingPerimeters() {}
|
||||
|
||||
void init_external_mp(const ExPolygons &islands) { m_external_mp = Slic3r::make_unique<MotionPlanner>(islands); }
|
||||
void reset() { m_external_mp.reset(); m_layer_mp.reset(); }
|
||||
void init_external_mp(const Print &print);
|
||||
void init_layer_mp(const ExPolygons &islands) { m_layer_mp = Slic3r::make_unique<MotionPlanner>(islands); }
|
||||
|
||||
Polyline travel_to(const GCode &gcodegen, const Point &point);
|
||||
|
||||
bool is_init() { return (use_external_mp || use_external_mp_once) ? m_external_mp.get() != nullptr : m_layer_mp.get() != nullptr; }
|
||||
private:
|
||||
// For initializing the regions to avoid.
|
||||
static Polygons collect_contours_all_layers(const PrintObjectPtrs& objects);
|
||||
|
||||
std::unique_ptr<MotionPlanner> m_external_mp;
|
||||
std::unique_ptr<MotionPlanner> m_layer_mp;
|
||||
};
|
||||
|
@ -25,6 +25,7 @@ const std::string GCodeAnalyzer::Extrusion_Role_Tag = "_ANALYZER_EXTR_ROLE:";
|
||||
const std::string GCodeAnalyzer::Mm3_Per_Mm_Tag = "_ANALYZER_MM3_PER_MM:";
|
||||
const std::string GCodeAnalyzer::Width_Tag = "_ANALYZER_WIDTH:";
|
||||
const std::string GCodeAnalyzer::Height_Tag = "_ANALYZER_HEIGHT:";
|
||||
const std::string GCodeAnalyzer::Color_Change_Tag = "_ANALYZER_COLOR_CHANGE";
|
||||
|
||||
const double GCodeAnalyzer::Default_mm3_per_mm = 0.0;
|
||||
const float GCodeAnalyzer::Default_Width = 0.0f;
|
||||
@ -240,11 +241,6 @@ void GCodeAnalyzer::_process_gcode_line(GCodeReader&, const GCodeReader::GCodeLi
|
||||
{
|
||||
switch (::atoi(&cmd[1]))
|
||||
{
|
||||
case 600: // Set color change
|
||||
{
|
||||
_processM600(line);
|
||||
break;
|
||||
}
|
||||
case 82: // Set extruder to absolute mode
|
||||
{
|
||||
_processM82(line);
|
||||
@ -517,12 +513,6 @@ void GCodeAnalyzer::_reset_cached_position()
|
||||
}
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_processM600(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
m_state.cur_cp_color_id++;
|
||||
_set_cp_color_id(m_state.cur_cp_color_id);
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_processT(const std::string& cmd)
|
||||
{
|
||||
if (cmd.length() > 1)
|
||||
@ -579,6 +569,14 @@ bool GCodeAnalyzer::_process_tags(const GCodeReader::GCodeLine& line)
|
||||
return true;
|
||||
}
|
||||
|
||||
// color change tag
|
||||
pos = comment.find(Color_Change_Tag);
|
||||
if (pos != comment.npos)
|
||||
{
|
||||
_process_color_change_tag();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -608,6 +606,12 @@ void GCodeAnalyzer::_process_height_tag(const std::string& comment, size_t pos)
|
||||
_set_height((float)::strtod(comment.substr(pos + Height_Tag.length()).c_str(), nullptr));
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_process_color_change_tag()
|
||||
{
|
||||
m_state.cur_cp_color_id++;
|
||||
_set_cp_color_id(m_state.cur_cp_color_id);
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_set_units(GCodeAnalyzer::EUnits units)
|
||||
{
|
||||
m_state.units = units;
|
||||
@ -945,12 +949,12 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data, s
|
||||
polyline = Polyline3();
|
||||
|
||||
// add both vertices of the move
|
||||
polyline.append(Vec3crd(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z())));
|
||||
polyline.append(Vec3crd(scale_(move.end_position.x()), scale_(move.end_position.y()), scale_(move.end_position.z())));
|
||||
polyline.append(Vec3crd((int)scale_(move.start_position.x()), (int)scale_(move.start_position.y()), (int)scale_(move.start_position.z())));
|
||||
polyline.append(Vec3crd((int)scale_(move.end_position.x()), (int)scale_(move.end_position.y()), (int)scale_(move.end_position.z())));
|
||||
}
|
||||
else
|
||||
// append end vertex of the move to current polyline
|
||||
polyline.append(Vec3crd(scale_(move.end_position.x()), scale_(move.end_position.y()), scale_(move.end_position.z())));
|
||||
polyline.append(Vec3crd((int)scale_(move.end_position.x()), (int)scale_(move.end_position.y()), (int)scale_(move.end_position.z())));
|
||||
|
||||
// update current values
|
||||
position = move.end_position;
|
||||
@ -994,7 +998,7 @@ void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_da
|
||||
cancel_callback();
|
||||
|
||||
// store position
|
||||
Vec3crd position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()));
|
||||
Vec3crd position((int)scale_(move.start_position.x()), (int)scale_(move.start_position.y()), (int)scale_(move.start_position.z()));
|
||||
preview_data.retraction.positions.emplace_back(position, move.data.width, move.data.height);
|
||||
}
|
||||
|
||||
@ -1021,7 +1025,7 @@ void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_
|
||||
cancel_callback();
|
||||
|
||||
// store position
|
||||
Vec3crd position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()));
|
||||
Vec3crd position((int)scale_(move.start_position.x()), (int)scale_(move.start_position.y()), (int)scale_(move.start_position.z()));
|
||||
preview_data.unretraction.positions.emplace_back(position, move.data.width, move.data.height);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ public:
|
||||
static const std::string Mm3_Per_Mm_Tag;
|
||||
static const std::string Width_Tag;
|
||||
static const std::string Height_Tag;
|
||||
static const std::string Color_Change_Tag;
|
||||
|
||||
static const double Default_mm3_per_mm;
|
||||
static const float Default_Width;
|
||||
@ -178,9 +179,6 @@ private:
|
||||
// Repetier: Go to stored position
|
||||
void _processM402(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Set color change
|
||||
void _processM600(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Processes T line (Select Tool)
|
||||
void _processT(const std::string& command);
|
||||
void _processT(const GCodeReader::GCodeLine& line);
|
||||
@ -201,6 +199,9 @@ private:
|
||||
// Processes height tag
|
||||
void _process_height_tag(const std::string& comment, size_t pos);
|
||||
|
||||
// Processes color change tag
|
||||
void _process_color_change_tag();
|
||||
|
||||
void _set_units(EUnits units);
|
||||
EUnits _get_units() const;
|
||||
|
||||
|
@ -78,8 +78,13 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
|
||||
zs.emplace_back(layer->print_z);
|
||||
for (auto layer : object->support_layers())
|
||||
zs.emplace_back(layer->print_z);
|
||||
if (! object->layers().empty())
|
||||
object_bottom_z = object->layers().front()->print_z - object->layers().front()->height;
|
||||
|
||||
// Find first object layer that is not empty and save its print_z
|
||||
for (const Layer* layer : object->layers())
|
||||
if (layer->has_extrusions()) {
|
||||
object_bottom_z = layer->print_z - layer->height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->initialize_layers(zs);
|
||||
}
|
||||
@ -96,23 +101,6 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
|
||||
this->collect_extruder_statistics(prime_multi_material);
|
||||
}
|
||||
|
||||
|
||||
LayerTools& ToolOrdering::tools_for_layer(coordf_t print_z)
|
||||
{
|
||||
auto it_layer_tools = std::lower_bound(m_layer_tools.begin(), m_layer_tools.end(), LayerTools(print_z - EPSILON));
|
||||
assert(it_layer_tools != m_layer_tools.end());
|
||||
coordf_t dist_min = std::abs(it_layer_tools->print_z - print_z);
|
||||
for (++ it_layer_tools; it_layer_tools != 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;
|
||||
}
|
||||
|
||||
void ToolOrdering::initialize_layers(std::vector<coordf_t> &zs)
|
||||
{
|
||||
sort_remove_duplicates(zs);
|
||||
@ -151,7 +139,7 @@ void ToolOrdering::collect_extruders(const PrintObject &object)
|
||||
LayerTools &layer_tools = this->tools_for_layer(layer->print_z);
|
||||
// What extruders are required to print this object layer?
|
||||
for (size_t region_id = 0; region_id < object.region_volumes.size(); ++ region_id) {
|
||||
const LayerRegion *layerm = (region_id < layer->regions().size()) ? layer->regions()[region_id] : nullptr;
|
||||
const LayerRegion *layerm = (region_id < layer->regions().size()) ? layer->regions()[region_id] : nullptr;
|
||||
if (layerm == nullptr)
|
||||
continue;
|
||||
const PrintRegion ®ion = *object.print()->regions()[region_id];
|
||||
@ -324,16 +312,17 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_
|
||||
m_layer_tools[j].has_wipe_tower = true;
|
||||
} else {
|
||||
LayerTools <_extra = *m_layer_tools.insert(m_layer_tools.begin() + j, lt_new);
|
||||
//LayerTools <_prev = m_layer_tools[j];
|
||||
LayerTools <_next = m_layer_tools[j + 1];
|
||||
assert(! m_layer_tools[j - 1].extruders.empty() && ! lt_next.extruders.empty());
|
||||
// FIXME: Following assert tripped when running combine_infill.t. I decided to comment it out for now.
|
||||
// If it is a bug, it's likely not critical, because this code is unchanged for a long time. It might
|
||||
// still be worth looking into it more and decide if it is a bug or an obsolete assert.
|
||||
//assert(lt_prev.extruders.back() == lt_next.extruders.front());
|
||||
lt_extra.has_wipe_tower = true;
|
||||
lt_extra.has_wipe_tower = true;
|
||||
lt_extra.extruders.push_back(lt_next.extruders.front());
|
||||
lt_extra.wipe_tower_partitions = lt_next.wipe_tower_partitions;
|
||||
}
|
||||
lt_extra.wipe_tower_partitions = lt_next.wipe_tower_partitions;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -375,7 +364,7 @@ void ToolOrdering::collect_extruder_statistics(bool prime_multi_material)
|
||||
// Reorder m_all_printing_extruders in the sequence they will be primed, the last one will be m_first_printing_extruder.
|
||||
// Then set m_first_printing_extruder to the 1st extruder primed.
|
||||
m_all_printing_extruders.erase(
|
||||
std::remove_if(m_all_printing_extruders.begin(), m_all_printing_extruders.end(),
|
||||
std::remove_if(m_all_printing_extruders.begin(), m_all_printing_extruders.end(),
|
||||
[ this ](const unsigned int eid) { return eid == m_first_printing_extruder; }),
|
||||
m_all_printing_extruders.end());
|
||||
m_all_printing_extruders.emplace_back(m_first_printing_extruder);
|
||||
@ -623,6 +612,6 @@ const std::vector<int>* WipingExtrusions::get_extruder_overrides(const Extrusion
|
||||
|
||||
return &(entity_map_it->second);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Slic3r
|
||||
|
@ -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<unsigned int>& 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<unsigned int>& 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 LayerTools*>(&const_cast<const ToolOrdering*>(this)->tools_for_layer(print_z)); }
|
||||
template<class Self> 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<LayerTools>::const_iterator begin() const { return m_layer_tools.begin(); }
|
||||
std::vector<LayerTools>::const_iterator end() const { return m_layer_tools.end(); }
|
||||
bool empty() const { return m_layer_tools.empty(); }
|
||||
std::vector<LayerTools>& 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<LayerTools>::const_iterator begin() const { return m_layer_tools.begin(); }
|
||||
std::vector<LayerTools>::const_iterator end() const { return m_layer_tools.end(); }
|
||||
bool empty() const { return m_layer_tools.empty(); }
|
||||
std::vector<LayerTools>& 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<coordf_t> &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<coordf_t> &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<LayerTools> m_layer_tools;
|
||||
|
@ -22,6 +22,7 @@ TODO LIST
|
||||
#include <numeric>
|
||||
|
||||
#include "Analyzer.hpp"
|
||||
#include "BoundingBox.hpp"
|
||||
|
||||
#if defined(__linux) || defined(__GNUC__ )
|
||||
#include <strings.h>
|
||||
@ -113,6 +114,11 @@ public:
|
||||
return (*this);
|
||||
}
|
||||
|
||||
WipeTowerWriter& disable_linear_advance() {
|
||||
m_gcode += (m_gcode_flavor == gcfRepRap ? std::string("M572 D0 S0\n") : std::string("M900 K0\n"));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Suppress / resume G-code preview in Slic3r. Slic3r will have difficulty to differentiate the various
|
||||
// filament loading and cooling moves from normal extrusion moves. Therefore the writer
|
||||
// is asked to suppres output of some lines, which look like extrusions.
|
||||
@ -470,6 +476,83 @@ private:
|
||||
|
||||
|
||||
|
||||
WipeTower::WipeTower(const PrintConfig& config, const std::vector<std::vector<float>>& wiping_matrix, size_t initial_tool) :
|
||||
m_semm(config.single_extruder_multi_material.value),
|
||||
m_wipe_tower_pos(config.wipe_tower_x, config.wipe_tower_y),
|
||||
m_wipe_tower_width(config.wipe_tower_width),
|
||||
m_wipe_tower_rotation_angle(config.wipe_tower_rotation_angle),
|
||||
m_y_shift(0.f),
|
||||
m_z_pos(0.f),
|
||||
m_is_first_layer(false),
|
||||
m_bridging(config.wipe_tower_bridging),
|
||||
m_gcode_flavor(config.gcode_flavor),
|
||||
m_current_tool(initial_tool),
|
||||
wipe_volumes(wiping_matrix)
|
||||
{
|
||||
// If this is a single extruder MM printer, we will use all the SE-specific config values.
|
||||
// Otherwise, the defaults will be used to turn off the SE stuff.
|
||||
if (m_semm) {
|
||||
m_cooling_tube_retraction = config.cooling_tube_retraction;
|
||||
m_cooling_tube_length = config.cooling_tube_length;
|
||||
m_parking_pos_retraction = config.parking_pos_retraction;
|
||||
m_extra_loading_move = config.extra_loading_move;
|
||||
m_set_extruder_trimpot = config.high_current_on_filament_swap;
|
||||
}
|
||||
// Calculate where the priming lines should be - very naive test not detecting parallelograms or custom shapes
|
||||
const std::vector<Vec2d>& bed_points = config.bed_shape.values;
|
||||
m_bed_shape = (bed_points.size() == 4 ? RectangularBed : CircularBed);
|
||||
m_bed_width = BoundingBoxf(bed_points).size().x();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void WipeTower::set_extruder(size_t idx, const PrintConfig& config)
|
||||
{
|
||||
//while (m_filpar.size() < idx+1) // makes sure the required element is in the vector
|
||||
m_filpar.push_back(FilamentParameters());
|
||||
|
||||
m_filpar[idx].material = config.filament_type.get_at(idx);
|
||||
m_filpar[idx].temperature = config.temperature.get_at(idx);
|
||||
m_filpar[idx].first_layer_temperature = config.first_layer_temperature.get_at(idx);
|
||||
|
||||
// If this is a single extruder MM printer, we will use all the SE-specific config values.
|
||||
// Otherwise, the defaults will be used to turn off the SE stuff.
|
||||
if (m_semm) {
|
||||
m_filpar[idx].loading_speed = config.filament_loading_speed.get_at(idx);
|
||||
m_filpar[idx].loading_speed_start = config.filament_loading_speed_start.get_at(idx);
|
||||
m_filpar[idx].unloading_speed = config.filament_unloading_speed.get_at(idx);
|
||||
m_filpar[idx].unloading_speed_start = config.filament_unloading_speed_start.get_at(idx);
|
||||
m_filpar[idx].delay = config.filament_toolchange_delay.get_at(idx);
|
||||
m_filpar[idx].cooling_moves = config.filament_cooling_moves.get_at(idx);
|
||||
m_filpar[idx].cooling_initial_speed = config.filament_cooling_initial_speed.get_at(idx);
|
||||
m_filpar[idx].cooling_final_speed = config.filament_cooling_final_speed.get_at(idx);
|
||||
}
|
||||
|
||||
m_filpar[idx].filament_area = float((M_PI/4.f) * pow(config.filament_diameter.get_at(idx), 2)); // all extruders are assumed to have the same filament diameter at this point
|
||||
float nozzle_diameter = config.nozzle_diameter.get_at(idx);
|
||||
m_filpar[idx].nozzle_diameter = nozzle_diameter; // to be used in future with (non-single) multiextruder MM
|
||||
|
||||
float max_vol_speed = config.filament_max_volumetric_speed.get_at(idx);
|
||||
if (max_vol_speed!= 0.f)
|
||||
m_filpar[idx].max_e_speed = (max_vol_speed / filament_area());
|
||||
|
||||
m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter
|
||||
|
||||
if (m_semm) {
|
||||
std::istringstream stream{config.filament_ramming_parameters.get_at(idx)};
|
||||
float speed = 0.f;
|
||||
stream >> m_filpar[idx].ramming_line_width_multiplicator >> m_filpar[idx].ramming_step_multiplicator;
|
||||
m_filpar[idx].ramming_line_width_multiplicator /= 100;
|
||||
m_filpar[idx].ramming_step_multiplicator /= 100;
|
||||
while (stream >> speed)
|
||||
m_filpar[idx].ramming_speed.push_back(speed);
|
||||
}
|
||||
|
||||
m_used_filament_length.resize(std::max(m_used_filament_length.size(), idx + 1)); // makes sure that the vector is big enough so we don't have to check later
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Returns gcode to prime the nozzles at the front edge of the print bed.
|
||||
std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
|
||||
// print_z of the first layer.
|
||||
@ -488,9 +571,11 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
|
||||
// therefore the homing position is shifted inside the bed by 0.2 in the firmware to [0.2, -2.0].
|
||||
// box_coordinates cleaning_box(xy(0.5f, - 1.5f), m_wipe_tower_width, wipe_area);
|
||||
|
||||
const float prime_section_width = std::min(240.f / tools.size(), 60.f);
|
||||
box_coordinates cleaning_box(Vec2f(5.f, 0.01f + m_perimeter_width/2.f), prime_section_width, 100.f);
|
||||
|
||||
float prime_section_width = std::min(0.9f * m_bed_width / tools.size(), 60.f);
|
||||
box_coordinates cleaning_box(Vec2f(0.02f * m_bed_width, 0.01f + m_perimeter_width/2.f), prime_section_width, 100.f);
|
||||
// In case of a circular bed, place it so it goes across the diameter and hope it will fit
|
||||
if (m_bed_shape == CircularBed)
|
||||
cleaning_box.translate(-m_bed_width/2 + m_bed_width * 0.03f, -m_bed_width * 0.12f);
|
||||
|
||||
std::vector<ToolChangeResult> results;
|
||||
|
||||
@ -818,6 +903,8 @@ void WipeTower::toolchange_Unload(
|
||||
}
|
||||
}
|
||||
|
||||
writer.disable_linear_advance();
|
||||
|
||||
// now the ramming itself:
|
||||
while (i < m_filpar[m_current_tool].ramming_speed.size())
|
||||
{
|
||||
@ -1242,6 +1329,8 @@ void WipeTower::generate(std::vector<std::vector<WipeTower::ToolChangeResult>> &
|
||||
for (auto& used : m_used_filament_length) // reset used filament stats
|
||||
used = 0.f;
|
||||
|
||||
m_old_temperature = -1; // reset last temperature written in the gcode
|
||||
|
||||
std::vector<WipeTower::ToolChangeResult> layer_result;
|
||||
for (auto layer : m_plan)
|
||||
{
|
||||
|
@ -78,105 +78,11 @@ public:
|
||||
// y -- y coordinates of wipe tower in mm ( left bottom corner )
|
||||
// width -- width of wipe tower in mm ( default 60 mm - leave as it is )
|
||||
// wipe_area -- space available for one toolchange in mm
|
||||
//WipeTower(bool semm, float x, float y, float width, float rotation_angle, float cooling_tube_retraction,
|
||||
// float cooling_tube_length, float parking_pos_retraction, float extra_loading_move,
|
||||
// float bridging, bool set_extruder_trimpot, GCodeFlavor flavor,
|
||||
// const std::vector<std::vector<float>>& wiping_matrix, unsigned int initial_tool) :
|
||||
// m_semm(semm),
|
||||
// m_wipe_tower_pos(x, y),
|
||||
// m_wipe_tower_width(width),
|
||||
// m_wipe_tower_rotation_angle(rotation_angle),
|
||||
// m_y_shift(0.f),
|
||||
// m_z_pos(0.f),
|
||||
// m_is_first_layer(false),
|
||||
// m_gcode_flavor(flavor),
|
||||
// m_bridging(bridging),
|
||||
// m_current_tool(initial_tool),
|
||||
// wipe_volumes(wiping_matrix)
|
||||
// {
|
||||
// // If this is a single extruder MM printer, we will use all the SE-specific config values.
|
||||
// // Otherwise, the defaults will be used to turn off the SE stuff.
|
||||
// if (m_semm) {
|
||||
// m_cooling_tube_retraction = cooling_tube_retraction;
|
||||
// m_cooling_tube_length = cooling_tube_length;
|
||||
// m_parking_pos_retraction = parking_pos_retraction;
|
||||
// m_extra_loading_move = extra_loading_move;
|
||||
// m_set_extruder_trimpot = set_extruder_trimpot;
|
||||
// }
|
||||
// }
|
||||
|
||||
WipeTower(PrintConfig &config, const std::vector<std::vector<float>>& wiping_matrix, unsigned int initial_tool, float first_layer_width) :
|
||||
m_semm(config.single_extruder_multi_material.value),
|
||||
m_wipe_tower_pos(float(config.wipe_tower_x.value), float(config.wipe_tower_y.value)),
|
||||
m_wipe_tower_width(float(config.wipe_tower_width.value)),
|
||||
m_wipe_tower_rotation_angle(float(config.wipe_tower_rotation_angle.value)),
|
||||
m_y_shift(0.f),
|
||||
m_z_pos(0.f),
|
||||
m_is_first_layer(false),
|
||||
m_bridging(float(config.wipe_tower_bridging)),
|
||||
m_gcode_flavor(config.gcode_flavor),
|
||||
m_current_tool(initial_tool),
|
||||
wipe_volumes(wiping_matrix),
|
||||
m_brim_width(first_layer_width),
|
||||
m_config(&config)
|
||||
{
|
||||
// If this is a single extruder MM printer, we will use all the SE-specific config values.
|
||||
// Otherwise, the defaults will be used to turn off the SE stuff.
|
||||
if (config.single_extruder_multi_material.value) {
|
||||
m_cooling_tube_retraction = (float(config.cooling_tube_retraction.value));
|
||||
m_cooling_tube_length = (float(config.cooling_tube_length.value));
|
||||
m_parking_pos_retraction = (float(config.parking_pos_retraction.value));
|
||||
m_extra_loading_move = (float(config.extra_loading_move.value));
|
||||
m_set_extruder_trimpot = (config.high_current_on_filament_swap.value);
|
||||
}
|
||||
}
|
||||
|
||||
WipeTower(const PrintConfig& config, const std::vector<std::vector<float>>& wiping_matrix, size_t initial_tool);
|
||||
virtual ~WipeTower() {}
|
||||
|
||||
// Set the extruder properties.
|
||||
void set_extruder(size_t idx)
|
||||
{
|
||||
//while (m_filpar.size() < idx+1) // makes sure the required element is in the vector
|
||||
m_filpar.push_back(FilamentParameters());
|
||||
|
||||
m_filpar[idx].material = m_config->filament_type.get_at(idx);
|
||||
m_filpar[idx].temperature = (float)m_config->temperature.get_at(idx);
|
||||
m_filpar[idx].first_layer_temperature = m_config->first_layer_temperature.get_at(idx);
|
||||
|
||||
// If this is a single extruder MM printer, we will use all the SE-specific config values.
|
||||
// Otherwise, the defaults will be used to turn off the SE stuff.
|
||||
if (m_semm) {
|
||||
m_filpar[idx].loading_speed = (float)m_config->filament_loading_speed.get_at(idx);
|
||||
m_filpar[idx].loading_speed_start = (float)m_config->filament_loading_speed_start.get_at(idx);
|
||||
m_filpar[idx].unloading_speed = (float)m_config->filament_unloading_speed.get_at(idx);
|
||||
m_filpar[idx].unloading_speed_start = (float)m_config->filament_unloading_speed_start.get_at(idx);
|
||||
m_filpar[idx].delay = (float)m_config->filament_toolchange_delay.get_at(idx);
|
||||
m_filpar[idx].cooling_moves = (float)m_config->filament_cooling_moves.get_at(idx);
|
||||
m_filpar[idx].cooling_initial_speed = (float)m_config->filament_cooling_initial_speed.get_at(idx);
|
||||
m_filpar[idx].cooling_final_speed = (float)m_config->filament_cooling_final_speed.get_at(idx);
|
||||
}
|
||||
|
||||
m_filpar[idx].filament_area = (M_PI/4.f) * pow((float)m_config->filament_diameter.get_at(idx), 2); // all extruders are assumed to have the same filament diameter at this point
|
||||
m_filpar[idx].nozzle_diameter = (float)m_config->nozzle_diameter.get_at(idx); // to be used in future with (non-single) multiextruder MM
|
||||
|
||||
if ((float)m_config->filament_max_volumetric_speed.get_at(idx) != 0.f)
|
||||
m_filpar[idx].max_e_speed = ((float)m_config->filament_max_volumetric_speed.get_at(idx) / filament_area());
|
||||
|
||||
m_perimeter_width = m_filpar[idx].nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter
|
||||
|
||||
if (m_semm) {
|
||||
std::stringstream stream{ m_config->filament_ramming_parameters.get_at(idx) };
|
||||
float speed = 0.f;
|
||||
stream >> m_filpar[idx].ramming_line_width_multiplicator >> m_filpar[idx].ramming_step_multiplicator;
|
||||
m_filpar[idx].ramming_line_width_multiplicator /= 100;
|
||||
m_filpar[idx].ramming_step_multiplicator /= 100;
|
||||
while (stream >> speed)
|
||||
m_filpar[idx].ramming_speed.push_back(speed);
|
||||
}
|
||||
|
||||
m_used_filament_length.resize(std::max(m_used_filament_length.size(), idx + 1)); // makes sure that the vector is big enough so we don't have to check later
|
||||
}
|
||||
|
||||
void set_extruder(size_t idx, const PrintConfig& config);
|
||||
|
||||
// Appends into internal structure m_plan containing info about the future wipe tower
|
||||
// to be used before building begins. The entries must be added ordered in z.
|
||||
@ -285,7 +191,6 @@ private:
|
||||
SHAPE_REVERSED = -1
|
||||
};
|
||||
|
||||
|
||||
const bool m_peters_wipe_tower = false; // sparse wipe tower inspired by Peter's post processor - not finished yet
|
||||
const float Width_To_Nozzle_Ratio = 1.25f; // desired line width (oval) in multiples of nozzle diameter - may not be actually neccessary to adjust
|
||||
const float WT_EPSILON = 1e-3f;
|
||||
@ -293,7 +198,6 @@ private:
|
||||
return m_filpar[0].filament_area; // all extruders are assumed to have the same filament diameter at this point
|
||||
}
|
||||
|
||||
PrintConfig *m_config = NULL;
|
||||
|
||||
bool m_semm = true; // Are we using a single extruder multimaterial printer?
|
||||
Vec2f m_wipe_tower_pos; // Left front corner of the wipe tower in mm.
|
||||
@ -318,6 +222,12 @@ private:
|
||||
bool m_adhesion = true;
|
||||
GCodeFlavor m_gcode_flavor;
|
||||
|
||||
// Bed properties
|
||||
enum {
|
||||
RectangularBed,
|
||||
CircularBed
|
||||
} m_bed_shape;
|
||||
float m_bed_width; // width of the bed bounding box
|
||||
|
||||
float m_perimeter_width = 0.4f * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill.
|
||||
float m_brim_width = 0.4 * Width_To_Nozzle_Ratio * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill.
|
||||
|
@ -168,10 +168,14 @@ namespace Slic3r {
|
||||
}
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
|
||||
const std::string GCodeTimeEstimator::Normal_First_M73_Output_Placeholder_Tag = "; NORMAL_FIRST_M73_OUTPUT_PLACEHOLDER";
|
||||
const std::string GCodeTimeEstimator::Silent_First_M73_Output_Placeholder_Tag = "; SILENT_FIRST_M73_OUTPUT_PLACEHOLDER";
|
||||
const std::string GCodeTimeEstimator::Normal_Last_M73_Output_Placeholder_Tag = "; NORMAL_LAST_M73_OUTPUT_PLACEHOLDER";
|
||||
const std::string GCodeTimeEstimator::Silent_Last_M73_Output_Placeholder_Tag = "; SILENT_LAST_M73_OUTPUT_PLACEHOLDER";
|
||||
const std::string GCodeTimeEstimator::Normal_First_M73_Output_Placeholder_Tag = "; _TE_NORMAL_FIRST_M73_OUTPUT_PLACEHOLDER";
|
||||
const std::string GCodeTimeEstimator::Silent_First_M73_Output_Placeholder_Tag = "; _TE_SILENT_FIRST_M73_OUTPUT_PLACEHOLDER";
|
||||
const std::string GCodeTimeEstimator::Normal_Last_M73_Output_Placeholder_Tag = "; _TE_NORMAL_LAST_M73_OUTPUT_PLACEHOLDER";
|
||||
const std::string GCodeTimeEstimator::Silent_Last_M73_Output_Placeholder_Tag = "; _TE_SILENT_LAST_M73_OUTPUT_PLACEHOLDER";
|
||||
|
||||
// temporary human readable form to use until not removed from gcode by the new post-process method
|
||||
const std::string GCodeTimeEstimator::Color_Change_Tag = "PRINT_COLOR_CHANGE";
|
||||
// const std::string GCodeTimeEstimator::Color_Change_Tag = "_TE_COLOR_CHANGE";
|
||||
|
||||
GCodeTimeEstimator::GCodeTimeEstimator(EMode mode)
|
||||
: m_mode(mode)
|
||||
@ -390,7 +394,7 @@ namespace Slic3r {
|
||||
fclose(out);
|
||||
in.close();
|
||||
|
||||
if (rename_file(path_tmp, filename) != 0)
|
||||
if (rename_file(path_tmp, filename))
|
||||
throw std::runtime_error(std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + filename + '\n' +
|
||||
"Is " + path_tmp + " locked?" + '\n');
|
||||
|
||||
@ -694,22 +698,39 @@ namespace Slic3r {
|
||||
return m_color_times;
|
||||
}
|
||||
|
||||
std::vector<std::string> GCodeTimeEstimator::get_color_times_dhms() const
|
||||
std::vector<std::string> GCodeTimeEstimator::get_color_times_dhms(bool include_remaining) const
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
float total_time = 0.0f;
|
||||
for (float t : m_color_times)
|
||||
{
|
||||
ret.push_back(_get_time_dhms(t));
|
||||
std::string time = _get_time_dhms(t);
|
||||
if (include_remaining)
|
||||
{
|
||||
time += " (";
|
||||
time += _get_time_dhms(m_time - total_time);
|
||||
time += ")";
|
||||
}
|
||||
total_time += t;
|
||||
ret.push_back(time);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::string> GCodeTimeEstimator::get_color_times_minutes() const
|
||||
std::vector<std::string> GCodeTimeEstimator::get_color_times_minutes(bool include_remaining) const
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
float total_time = 0.0f;
|
||||
for (float t : m_color_times)
|
||||
{
|
||||
ret.push_back(_get_time_minutes(t));
|
||||
std::string time = _get_time_minutes(t);
|
||||
if (include_remaining)
|
||||
{
|
||||
time += " (";
|
||||
time += _get_time_minutes(m_time - total_time);
|
||||
time += ")";
|
||||
}
|
||||
total_time += t;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -797,6 +818,11 @@ namespace Slic3r {
|
||||
void GCodeTimeEstimator::_process_gcode_line(GCodeReader&, const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
PROFILE_FUNC();
|
||||
|
||||
// processes 'special' comments contained in line
|
||||
if (_process_tags(line))
|
||||
return;
|
||||
|
||||
std::string cmd = line.cmd();
|
||||
if (cmd.length() > 1)
|
||||
{
|
||||
@ -904,11 +930,6 @@ namespace Slic3r {
|
||||
_processM566(line);
|
||||
break;
|
||||
}
|
||||
case 600: // Set color change
|
||||
{
|
||||
_processM600(line);
|
||||
break;
|
||||
}
|
||||
case 702: // MK3 MMU2: Process the final filament unload.
|
||||
{
|
||||
_processM702(line);
|
||||
@ -1379,18 +1400,6 @@ namespace Slic3r {
|
||||
set_axis_max_jerk(E, line.e() * MMMIN_TO_MMSEC);
|
||||
}
|
||||
|
||||
void GCodeTimeEstimator::_processM600(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
PROFILE_FUNC();
|
||||
m_needs_color_times = true;
|
||||
_calculate_time();
|
||||
if (m_color_time_cache != 0.0f)
|
||||
{
|
||||
m_color_times.push_back(m_color_time_cache);
|
||||
m_color_time_cache = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void GCodeTimeEstimator::_processM702(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
PROFILE_FUNC();
|
||||
@ -1422,6 +1431,33 @@ namespace Slic3r {
|
||||
}
|
||||
}
|
||||
|
||||
bool GCodeTimeEstimator::_process_tags(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
std::string comment = line.comment();
|
||||
|
||||
// color change tag
|
||||
size_t pos = comment.find(Color_Change_Tag);
|
||||
if (pos != comment.npos)
|
||||
{
|
||||
_process_color_change_tag();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GCodeTimeEstimator::_process_color_change_tag()
|
||||
{
|
||||
PROFILE_FUNC();
|
||||
m_needs_color_times = true;
|
||||
_calculate_time();
|
||||
if (m_color_time_cache != 0.0f)
|
||||
{
|
||||
m_color_times.push_back(m_color_time_cache);
|
||||
m_color_time_cache = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void GCodeTimeEstimator::_simulate_st_synchronize()
|
||||
{
|
||||
PROFILE_FUNC();
|
||||
|
@ -22,6 +22,8 @@ namespace Slic3r {
|
||||
static const std::string Normal_Last_M73_Output_Placeholder_Tag;
|
||||
static const std::string Silent_Last_M73_Output_Placeholder_Tag;
|
||||
|
||||
static const std::string Color_Change_Tag;
|
||||
|
||||
enum EMode : unsigned char
|
||||
{
|
||||
Normal,
|
||||
@ -346,14 +348,16 @@ namespace Slic3r {
|
||||
// Returns the estimated time, in minutes (integer)
|
||||
std::string get_time_minutes() const;
|
||||
|
||||
// Returns the estimated time, in seconds, for each color
|
||||
// Returns the estimated time, in seconds, for each color
|
||||
std::vector<float> get_color_times() const;
|
||||
|
||||
// Returns the estimated time, in format DDd HHh MMm SSs, for each color
|
||||
std::vector<std::string> get_color_times_dhms() const;
|
||||
// If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)"
|
||||
std::vector<std::string> get_color_times_dhms(bool include_remaining) const;
|
||||
|
||||
// Returns the estimated time, in minutes (integer), for each color
|
||||
std::vector<std::string> get_color_times_minutes() const;
|
||||
// If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)"
|
||||
std::vector<std::string> get_color_times_minutes(bool include_remaining) const;
|
||||
|
||||
// Return an estimate of the memory consumed by the time estimator.
|
||||
size_t memory_used() const;
|
||||
@ -423,15 +427,19 @@ namespace Slic3r {
|
||||
// Set allowable instantaneous speed change
|
||||
void _processM566(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Set color change
|
||||
void _processM600(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Unload the current filament into the MK3 MMU2 unit at the end of print.
|
||||
void _processM702(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Processes T line (Select Tool)
|
||||
void _processT(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Processes the tags
|
||||
// Returns true if any tag has been processed
|
||||
bool _process_tags(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Processes color change tag
|
||||
void _process_color_change_tag();
|
||||
|
||||
// Simulates firmware st_synchronize() call
|
||||
void _simulate_st_synchronize();
|
||||
|
||||
|
@ -122,6 +122,29 @@ inline bool segment_segment_intersection(const Vec2d &p1, const Vec2d &v1, const
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline int segments_could_intersect(
|
||||
const Slic3r::Point &ip1, const Slic3r::Point &ip2,
|
||||
const Slic3r::Point &jp1, const Slic3r::Point &jp2)
|
||||
{
|
||||
Vec2i64 iv = (ip2 - ip1).cast<int64_t>();
|
||||
Vec2i64 vij1 = (jp1 - ip1).cast<int64_t>();
|
||||
Vec2i64 vij2 = (jp2 - ip1).cast<int64_t>();
|
||||
int64_t tij1 = cross2(iv, vij1);
|
||||
int64_t tij2 = cross2(iv, vij2);
|
||||
int sij1 = (tij1 > 0) ? 1 : ((tij1 < 0) ? -1 : 0); // signum
|
||||
int sij2 = (tij2 > 0) ? 1 : ((tij2 < 0) ? -1 : 0);
|
||||
return sij1 * sij2;
|
||||
}
|
||||
|
||||
inline bool segments_intersect(
|
||||
const Slic3r::Point &ip1, const Slic3r::Point &ip2,
|
||||
const Slic3r::Point &jp1, const Slic3r::Point &jp2)
|
||||
{
|
||||
return segments_could_intersect(ip1, ip2, jp1, jp2) <= 0 &&
|
||||
segments_could_intersect(jp1, jp2, ip1, ip2) <= 0;
|
||||
}
|
||||
|
||||
Pointf3s convex_hull(Pointf3s points);
|
||||
Polygon convex_hull(Points points);
|
||||
Polygon convex_hull(const Polygons &polygons);
|
||||
|
@ -1,6 +1,11 @@
|
||||
#include "MinAreaBoundingBox.hpp"
|
||||
|
||||
#include <libslic3r/ExPolygon.hpp>
|
||||
|
||||
#if defined(_MSC_VER) && defined(__clang__)
|
||||
#define BOOST_NO_CXX17_HDR_STRING_VIEW
|
||||
#endif
|
||||
|
||||
#include <boost/rational.hpp>
|
||||
|
||||
#include <libslic3r/Int128.hpp>
|
||||
|
@ -21,8 +21,6 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
unsigned int Model::s_auto_extruder_id = 1;
|
||||
|
||||
Model& Model::assign_copy(const Model &rhs)
|
||||
{
|
||||
this->copy_id(rhs);
|
||||
@ -86,7 +84,7 @@ void Model::update_links_bottom_up_recursive()
|
||||
}
|
||||
}
|
||||
|
||||
Model Model::read_from_file(const std::string &input_file, DynamicPrintConfig *config, bool add_default_instances)
|
||||
Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* config, bool add_default_instances, bool check_version)
|
||||
{
|
||||
Model model;
|
||||
|
||||
@ -99,11 +97,10 @@ Model Model::read_from_file(const std::string &input_file, DynamicPrintConfig *c
|
||||
result = load_stl(input_file.c_str(), &model);
|
||||
else if (boost::algorithm::iends_with(input_file, ".obj"))
|
||||
result = load_obj(input_file.c_str(), &model);
|
||||
else if (!boost::algorithm::iends_with(input_file, ".zip.amf") && (boost::algorithm::iends_with(input_file, ".amf") ||
|
||||
boost::algorithm::iends_with(input_file, ".amf.xml")))
|
||||
result = load_amf(input_file.c_str(), config, &model);
|
||||
else if (boost::algorithm::iends_with(input_file, ".amf") || boost::algorithm::iends_with(input_file, ".amf.xml"))
|
||||
result = load_amf(input_file.c_str(), config, &model, check_version);
|
||||
else if (boost::algorithm::iends_with(input_file, ".3mf"))
|
||||
result = load_3mf(input_file.c_str(), config, &model);
|
||||
result = load_3mf(input_file.c_str(), config, &model, false);
|
||||
else if (boost::algorithm::iends_with(input_file, ".prusa"))
|
||||
result = load_prus(input_file.c_str(), &model);
|
||||
else
|
||||
@ -124,15 +121,15 @@ Model Model::read_from_file(const std::string &input_file, DynamicPrintConfig *c
|
||||
return model;
|
||||
}
|
||||
|
||||
Model Model::read_from_archive(const std::string &input_file, DynamicPrintConfig *config, bool add_default_instances)
|
||||
Model Model::read_from_archive(const std::string& input_file, DynamicPrintConfig* config, bool add_default_instances, bool check_version)
|
||||
{
|
||||
Model model;
|
||||
|
||||
bool result = false;
|
||||
if (boost::algorithm::iends_with(input_file, ".3mf"))
|
||||
result = load_3mf(input_file.c_str(), config, &model);
|
||||
result = load_3mf(input_file.c_str(), config, &model, check_version);
|
||||
else if (boost::algorithm::iends_with(input_file, ".zip.amf"))
|
||||
result = load_amf(input_file.c_str(), config, &model);
|
||||
result = load_amf(input_file.c_str(), config, &model, check_version);
|
||||
else
|
||||
throw std::runtime_error("Unknown file format. Input file must have .3mf or .zip.amf extension.");
|
||||
|
||||
@ -486,9 +483,20 @@ bool Model::looks_like_multipart_object() const
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate next extruder ID string, in the range of (1, max_extruders).
|
||||
static inline std::string auto_extruder_id(unsigned int max_extruders, unsigned int &cntr)
|
||||
{
|
||||
char str_extruder[64];
|
||||
sprintf(str_extruder, "%ud", cntr + 1);
|
||||
if (++ cntr == max_extruders)
|
||||
cntr = 0;
|
||||
return str_extruder;
|
||||
}
|
||||
|
||||
void Model::convert_multipart_object(unsigned int max_extruders)
|
||||
{
|
||||
if (this->objects.empty())
|
||||
assert(this->objects.size() >= 2);
|
||||
if (this->objects.size() < 2)
|
||||
return;
|
||||
|
||||
ModelObject* object = new ModelObject(this);
|
||||
@ -496,60 +504,33 @@ void Model::convert_multipart_object(unsigned int max_extruders)
|
||||
object->name = this->objects.front()->name;
|
||||
//FIXME copy the config etc?
|
||||
|
||||
reset_auto_extruder_id();
|
||||
|
||||
//supermerill: note: the new codepath indroduced in fab363493140a93c1786c7898424a73dd1ed2a2e
|
||||
// doesn't work for my fork for a reason, deactivating it for now.
|
||||
bool is_single_object = true; // (this->objects.size() == 1);
|
||||
|
||||
unsigned int extruder_counter = 0;
|
||||
for (const ModelObject* o : this->objects)
|
||||
{
|
||||
for (const ModelVolume* v : o->volumes)
|
||||
{
|
||||
if (is_single_object)
|
||||
{
|
||||
// If there is only one object, just copy the volumes
|
||||
ModelVolume* new_v = object->add_volume(*v);
|
||||
if (new_v != nullptr)
|
||||
{
|
||||
new_v->name = o->name;
|
||||
new_v->config.set_deserialize("extruder", get_auto_extruder_id_as_string(max_extruders));
|
||||
new_v->translate(-o->origin_translation);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const ModelVolume* v : o->volumes) {
|
||||
// If there are more than one object, put all volumes together
|
||||
// Each object may contain any number of volumes and instances
|
||||
// The volumes transformations are relative to the object containing them...
|
||||
Geometry::Transformation trafo_volume = v->get_transformation();
|
||||
// Revert the centering operation.
|
||||
trafo_volume.set_offset(trafo_volume.get_offset() - o->origin_translation);
|
||||
int counter = 1;
|
||||
auto copy_volume = [o, max_extruders, &counter, &extruder_counter](ModelVolume *new_v) {
|
||||
assert(new_v != nullptr);
|
||||
new_v->name = o->name + "_" + std::to_string(counter++);
|
||||
new_v->config.set_deserialize("extruder", auto_extruder_id(max_extruders, extruder_counter));
|
||||
return new_v;
|
||||
};
|
||||
if (o->instances.empty()) {
|
||||
copy_volume(object->add_volume(*v))->set_transformation(trafo_volume);
|
||||
} else {
|
||||
for (const ModelInstance* i : o->instances)
|
||||
{
|
||||
ModelVolume* new_v = object->add_volume(*v);
|
||||
if (new_v != nullptr)
|
||||
{
|
||||
new_v->name = o->name + "_" + std::to_string(counter++);
|
||||
new_v->config.set_deserialize("extruder", get_auto_extruder_id_as_string(max_extruders));
|
||||
new_v->translate(-o->origin_translation);
|
||||
// ...so, transform everything to a common reference system (world)
|
||||
new_v->set_transformation(i->get_transformation() * v->get_transformation());
|
||||
copy_volume(object->add_volume(*v))->set_transformation(i->get_transformation() * trafo_volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_single_object)
|
||||
{
|
||||
// If there is only one object, keep its instances
|
||||
for (const ModelInstance* i : this->objects.front()->instances)
|
||||
{
|
||||
object->add_instance(*i);
|
||||
}
|
||||
}
|
||||
else
|
||||
// If there are more than one object, create a single instance
|
||||
object->add_instance();
|
||||
object->instances[0]->set_offset(object->raw_mesh_bounding_box().center());
|
||||
|
||||
this->clear_objects();
|
||||
this->objects.push_back(object);
|
||||
@ -574,32 +555,6 @@ void Model::adjust_min_z()
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Model::get_auto_extruder_id(unsigned int max_extruders)
|
||||
{
|
||||
unsigned int id = s_auto_extruder_id;
|
||||
if (id > max_extruders) {
|
||||
// The current counter is invalid, likely due to switching the printer profiles
|
||||
// to a profile with a lower number of extruders.
|
||||
reset_auto_extruder_id();
|
||||
id = s_auto_extruder_id;
|
||||
} else if (++ s_auto_extruder_id > max_extruders) {
|
||||
reset_auto_extruder_id();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
std::string Model::get_auto_extruder_id_as_string(unsigned int max_extruders)
|
||||
{
|
||||
char str_extruder[64];
|
||||
sprintf(str_extruder, "%ud", get_auto_extruder_id(max_extruders));
|
||||
return str_extruder;
|
||||
}
|
||||
|
||||
void Model::reset_auto_extruder_id()
|
||||
{
|
||||
s_auto_extruder_id = 1;
|
||||
}
|
||||
|
||||
// Propose a filename including path derived from the ModelObject's input path.
|
||||
// If object's name is filled in, use the object name, otherwise use the input name.
|
||||
std::string Model::propose_export_file_name_and_path() const
|
||||
@ -646,6 +601,7 @@ ModelObject& ModelObject::assign_copy(const ModelObject &rhs)
|
||||
this->sla_points_status = rhs.sla_points_status;
|
||||
this->layer_config_ranges = rhs.layer_config_ranges; // #ys_FIXME_experiment
|
||||
this->layer_height_profile = rhs.layer_height_profile;
|
||||
this->printable = rhs.printable;
|
||||
this->origin_translation = rhs.origin_translation;
|
||||
m_bounding_box = rhs.m_bounding_box;
|
||||
m_bounding_box_valid = rhs.m_bounding_box_valid;
|
||||
@ -1664,7 +1620,7 @@ size_t ModelVolume::split(unsigned int max_extruders)
|
||||
size_t ivolume = std::find(this->object->volumes.begin(), this->object->volumes.end(), this) - this->object->volumes.begin();
|
||||
std::string name = this->name;
|
||||
|
||||
Model::reset_auto_extruder_id();
|
||||
unsigned int extruder_counter = 0;
|
||||
Vec3d offset = this->get_offset();
|
||||
|
||||
for (TriangleMesh *mesh : meshptrs) {
|
||||
@ -1683,7 +1639,7 @@ size_t ModelVolume::split(unsigned int max_extruders)
|
||||
this->object->volumes[ivolume]->center_geometry_after_creation();
|
||||
this->object->volumes[ivolume]->translate(offset);
|
||||
this->object->volumes[ivolume]->name = name + "_" + std::to_string(idx + 1);
|
||||
this->object->volumes[ivolume]->config.set_deserialize("extruder", Model::get_auto_extruder_id_as_string(max_extruders));
|
||||
this->object->volumes[ivolume]->config.set_deserialize("extruder", auto_extruder_id(max_extruders, extruder_counter));
|
||||
delete mesh;
|
||||
++ idx;
|
||||
}
|
||||
|
@ -192,6 +192,8 @@ public:
|
||||
// Profile of increasing z to a layer height, to be linearly interpolated when calculating the layers.
|
||||
// The pairs of <z, layer_height> are packed into a 1D array.
|
||||
std::vector<coordf_t> layer_height_profile;
|
||||
// Whether or not this object is printable
|
||||
bool printable;
|
||||
|
||||
// This vector holds position of selected support points for SLA. The data are
|
||||
// saved in mesh coordinates to allow using them for several instances.
|
||||
@ -304,11 +306,11 @@ public:
|
||||
private:
|
||||
friend class Model;
|
||||
// This constructor assigns new ID to this ModelObject and its config.
|
||||
explicit ModelObject(Model *model) : m_model(model), origin_translation(Vec3d::Zero()),
|
||||
explicit ModelObject(Model* model) : m_model(model), printable(true), origin_translation(Vec3d::Zero()),
|
||||
m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false)
|
||||
{ assert(this->id().valid()); }
|
||||
explicit ModelObject(int) : ObjectBase(-1), config(-1), m_model(nullptr), origin_translation(Vec3d::Zero()), m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false)
|
||||
{ assert(this->id().invalid()); assert(this->config.id().invalid()); }
|
||||
{ assert(this->id().valid()); }
|
||||
explicit ModelObject(int) : ObjectBase(-1), config(-1), m_model(nullptr), printable(true), origin_translation(Vec3d::Zero()), m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false)
|
||||
{ assert(this->id().invalid()); assert(this->config.id().invalid()); }
|
||||
~ModelObject();
|
||||
void assign_new_unique_ids_recursive() override;
|
||||
|
||||
@ -370,8 +372,8 @@ private:
|
||||
template<class Archive> void serialize(Archive &ar) {
|
||||
ar(cereal::base_class<ObjectBase>(this));
|
||||
Internal::StaticSerializationWrapper<ModelConfig> config_wrapper(config);
|
||||
ar(name, input_file, instances, volumes, config_wrapper, layer_config_ranges, layer_height_profile, sla_support_points, sla_points_status, origin_translation,
|
||||
m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid);
|
||||
ar(name, input_file, instances, volumes, config_wrapper, layer_config_ranges, layer_height_profile, sla_support_points, sla_points_status, printable, origin_translation,
|
||||
m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid);
|
||||
}
|
||||
};
|
||||
|
||||
@ -595,6 +597,8 @@ private:
|
||||
public:
|
||||
// flag showing the position of this instance with respect to the print volume (set by Print::validate() using ModelObject::check_instances_print_volume_state())
|
||||
EPrintVolumeState print_volume_state;
|
||||
// Whether or not this instance is printable
|
||||
bool printable;
|
||||
|
||||
ModelObject* get_object() const { return this->object; }
|
||||
|
||||
@ -639,8 +643,8 @@ public:
|
||||
|
||||
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); }
|
||||
|
||||
bool is_printable() const { return print_volume_state == PVS_Inside; }
|
||||
|
||||
bool is_printable() const { return object->printable && printable && (print_volume_state == PVS_Inside); }
|
||||
|
||||
// Getting the input polygon for arrange
|
||||
arrangement::ArrangePolygon get_arrange_polygon() const;
|
||||
|
||||
@ -667,10 +671,10 @@ private:
|
||||
ModelObject* object;
|
||||
|
||||
// Constructor, which assigns a new unique ID.
|
||||
explicit ModelInstance(ModelObject *object) : print_volume_state(PVS_Inside), object(object) { assert(this->id().valid()); }
|
||||
explicit ModelInstance(ModelObject* object) : print_volume_state(PVS_Inside), printable(true), object(object) { assert(this->id().valid()); }
|
||||
// Constructor, which assigns a new unique ID.
|
||||
explicit ModelInstance(ModelObject *object, const ModelInstance &other) :
|
||||
m_transformation(other.m_transformation), print_volume_state(PVS_Inside), object(object) { assert(this->id().valid() && this->id() != other.id()); }
|
||||
m_transformation(other.m_transformation), print_volume_state(PVS_Inside), printable(true), object(object) {assert(this->id().valid() && this->id() != other.id());}
|
||||
|
||||
explicit ModelInstance(ModelInstance &&rhs) = delete;
|
||||
ModelInstance& operator=(const ModelInstance &rhs) = delete;
|
||||
@ -681,8 +685,8 @@ private:
|
||||
// Used for deserialization, therefore no IDs are allocated.
|
||||
ModelInstance() : ObjectBase(-1), object(nullptr) { assert(this->id().invalid()); }
|
||||
template<class Archive> void serialize(Archive &ar) {
|
||||
ar(m_transformation, print_volume_state);
|
||||
}
|
||||
ar(m_transformation, print_volume_state, printable);
|
||||
}
|
||||
};
|
||||
|
||||
class ModelWipeTower final : public ObjectBase
|
||||
@ -721,8 +725,6 @@ private:
|
||||
// all objects may share mutliple materials.
|
||||
class Model final : public ObjectBase
|
||||
{
|
||||
static unsigned int s_auto_extruder_id;
|
||||
|
||||
public:
|
||||
// Materials are owned by a model and referenced by objects through t_model_material_id.
|
||||
// Single material may be shared by multiple models.
|
||||
@ -745,8 +747,8 @@ public:
|
||||
|
||||
OBJECTBASE_DERIVED_COPY_MOVE_CLONE(Model)
|
||||
|
||||
static Model read_from_file(const std::string &input_file, DynamicPrintConfig *config = nullptr, bool add_default_instances = true);
|
||||
static Model read_from_archive(const std::string &input_file, DynamicPrintConfig *config, bool add_default_instances = true);
|
||||
static Model read_from_file(const std::string& input_file, DynamicPrintConfig* config = nullptr, bool add_default_instances = true, bool check_version = false);
|
||||
static Model read_from_archive(const std::string& input_file, DynamicPrintConfig* config, bool add_default_instances = true, bool check_version = false);
|
||||
|
||||
// Add a new ModelObject to this Model, generate a new ID for this ModelObject.
|
||||
ModelObject* add_object();
|
||||
@ -791,14 +793,10 @@ public:
|
||||
|
||||
void print_info() const { for (const ModelObject *o : this->objects) o->print_info(); }
|
||||
|
||||
static unsigned int get_auto_extruder_id(unsigned int max_extruders);
|
||||
static std::string get_auto_extruder_id_as_string(unsigned int max_extruders);
|
||||
static void reset_auto_extruder_id();
|
||||
|
||||
// Propose an output file name & path based on the first printable object's name and source input file's path.
|
||||
std::string propose_export_file_name_and_path() const;
|
||||
std::string propose_export_file_name_and_path() const;
|
||||
// Propose an output path, replace extension. The new_extension shall contain the initial dot.
|
||||
std::string propose_export_file_name_and_path(const std::string &new_extension) const;
|
||||
std::string propose_export_file_name_and_path(const std::string &new_extension) const;
|
||||
|
||||
private:
|
||||
explicit Model(int) : ObjectBase(-1) { assert(this->id().invalid()); };
|
||||
|
@ -175,6 +175,11 @@ void PlaceholderParser::apply_env_variables()
|
||||
}
|
||||
|
||||
namespace spirit = boost::spirit;
|
||||
// Using an encoding, which accepts unsigned chars.
|
||||
// Don't use boost::spirit::ascii, as it crashes internally due to indexing with negative char values for UTF8 characters into some 7bit character classification tables.
|
||||
//namespace spirit_encoding = boost::spirit::ascii;
|
||||
//FIXME iso8859_1 is just a workaround for the problem above. Replace it with UTF8 support!
|
||||
namespace spirit_encoding = boost::spirit::iso8859_1;
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace px = boost::phoenix;
|
||||
|
||||
@ -931,7 +936,7 @@ namespace client
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Inspired by the C grammar rules https://www.lysator.liu.se/c/ANSI-C-grammar-y.html
|
||||
template <typename Iterator>
|
||||
struct macro_processor : qi::grammar<Iterator, std::string(const MyContext*), qi::locals<bool>, spirit::ascii::space_type>
|
||||
struct macro_processor : qi::grammar<Iterator, std::string(const MyContext*), qi::locals<bool>, spirit_encoding::space_type>
|
||||
{
|
||||
macro_processor() : macro_processor::base_type(start)
|
||||
{
|
||||
@ -944,12 +949,12 @@ namespace client
|
||||
qi::lexeme_type lexeme;
|
||||
qi::no_skip_type no_skip;
|
||||
qi::real_parser<double, strict_real_policies_without_nan_inf> strict_double;
|
||||
spirit::ascii::char_type char_;
|
||||
spirit_encoding::char_type char_;
|
||||
utf8_char_skipper_parser utf8char;
|
||||
spirit::bool_type bool_;
|
||||
spirit::int_type int_;
|
||||
spirit::double_type double_;
|
||||
spirit::ascii::string_type string;
|
||||
spirit_encoding::string_type string;
|
||||
spirit::eoi_type eoi;
|
||||
spirit::repository::qi::iter_pos_type iter_pos;
|
||||
auto kw = spirit::repository::qi::distinct(qi::copy(alnum | '_'));
|
||||
@ -1178,20 +1183,20 @@ namespace client
|
||||
}
|
||||
|
||||
// Generic expression over expr<Iterator>.
|
||||
typedef qi::rule<Iterator, expr<Iterator>(const MyContext*), spirit::ascii::space_type> RuleExpression;
|
||||
typedef qi::rule<Iterator, expr<Iterator>(const MyContext*), spirit_encoding::space_type> RuleExpression;
|
||||
|
||||
// The start of the grammar.
|
||||
qi::rule<Iterator, std::string(const MyContext*), qi::locals<bool>, spirit::ascii::space_type> start;
|
||||
qi::rule<Iterator, std::string(const MyContext*), qi::locals<bool>, spirit_encoding::space_type> start;
|
||||
// A free-form text.
|
||||
qi::rule<Iterator, std::string(), spirit::ascii::space_type> text;
|
||||
qi::rule<Iterator, std::string(), spirit_encoding::space_type> text;
|
||||
// A free-form text, possibly empty, possibly containing macro expansions.
|
||||
qi::rule<Iterator, std::string(const MyContext*), spirit::ascii::space_type> text_block;
|
||||
qi::rule<Iterator, std::string(const MyContext*), spirit_encoding::space_type> text_block;
|
||||
// Statements enclosed in curely braces {}
|
||||
qi::rule<Iterator, std::string(const MyContext*), spirit::ascii::space_type> macro;
|
||||
qi::rule<Iterator, std::string(const MyContext*), spirit_encoding::space_type> macro;
|
||||
// Legacy variable expansion of the original Slic3r, in the form of [scalar_variable] or [vector_variable_index].
|
||||
qi::rule<Iterator, std::string(const MyContext*), spirit::ascii::space_type> legacy_variable_expansion;
|
||||
qi::rule<Iterator, std::string(const MyContext*), spirit_encoding::space_type> legacy_variable_expansion;
|
||||
// Parsed identifier name.
|
||||
qi::rule<Iterator, boost::iterator_range<Iterator>(), spirit::ascii::space_type> identifier;
|
||||
qi::rule<Iterator, boost::iterator_range<Iterator>(), spirit_encoding::space_type> identifier;
|
||||
// Ternary operator (?:) over logical_or_expression.
|
||||
RuleExpression conditional_expression;
|
||||
// Logical or over logical_and_expressions.
|
||||
@ -1209,16 +1214,16 @@ namespace client
|
||||
// Number literals, functions, braced expressions, variable references, variable indexing references.
|
||||
RuleExpression unary_expression;
|
||||
// Rule to capture a regular expression enclosed in //.
|
||||
qi::rule<Iterator, boost::iterator_range<Iterator>(), spirit::ascii::space_type> regular_expression;
|
||||
qi::rule<Iterator, boost::iterator_range<Iterator>(), spirit_encoding::space_type> regular_expression;
|
||||
// Evaluate boolean expression into bool.
|
||||
qi::rule<Iterator, bool(const MyContext*), spirit::ascii::space_type> bool_expr_eval;
|
||||
qi::rule<Iterator, bool(const MyContext*), spirit_encoding::space_type> bool_expr_eval;
|
||||
// Reference of a scalar variable, or reference to a field of a vector variable.
|
||||
qi::rule<Iterator, expr<Iterator>(const MyContext*), qi::locals<OptWithPos<Iterator>, int>, spirit::ascii::space_type> scalar_variable_reference;
|
||||
qi::rule<Iterator, expr<Iterator>(const MyContext*), qi::locals<OptWithPos<Iterator>, int>, spirit_encoding::space_type> scalar_variable_reference;
|
||||
// Rule to translate an identifier to a ConfigOption, or to fail.
|
||||
qi::rule<Iterator, OptWithPos<Iterator>(const MyContext*), spirit::ascii::space_type> variable_reference;
|
||||
qi::rule<Iterator, OptWithPos<Iterator>(const MyContext*), spirit_encoding::space_type> variable_reference;
|
||||
|
||||
qi::rule<Iterator, std::string(const MyContext*), qi::locals<bool, bool>, spirit::ascii::space_type> if_else_output;
|
||||
// qi::rule<Iterator, std::string(const MyContext*), qi::locals<expr<Iterator>, bool, std::string>, spirit::ascii::space_type> switch_output;
|
||||
qi::rule<Iterator, std::string(const MyContext*), qi::locals<bool, bool>, spirit_encoding::space_type> if_else_output;
|
||||
// qi::rule<Iterator, std::string(const MyContext*), qi::locals<expr<Iterator>, bool, std::string>, spirit_encoding::space_type> switch_output;
|
||||
|
||||
qi::symbols<char> keywords;
|
||||
};
|
||||
@ -1230,7 +1235,7 @@ static std::string process_macro(const std::string &templ, client::MyContext &co
|
||||
typedef client::macro_processor<iterator_type> macro_processor;
|
||||
|
||||
// Our whitespace skipper.
|
||||
spirit::ascii::space_type space;
|
||||
spirit_encoding::space_type space;
|
||||
// Our grammar, statically allocated inside the method, meaning it will be allocated the first time
|
||||
// PlaceholderParser::process() runs.
|
||||
//FIXME this kind of initialization is not thread safe!
|
||||
|
56
src/libslic3r/PolygonTrimmer.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
#include "PolygonTrimmer.hpp"
|
||||
#include "EdgeGrid.hpp"
|
||||
#include "Geometry.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
TrimmedLoop trim_loop(const Polygon &loop, const EdgeGrid::Grid &grid)
|
||||
{
|
||||
assert(! loop.empty());
|
||||
assert(loop.size() >= 2);
|
||||
|
||||
TrimmedLoop out;
|
||||
|
||||
if (loop.size() >= 2) {
|
||||
size_t cnt = loop.points.size();
|
||||
|
||||
struct Visitor {
|
||||
Visitor(const EdgeGrid::Grid &grid, const Slic3r::Point *pt_prev, const Slic3r::Point *pt_this) : grid(grid), pt_prev(pt_prev), pt_this(pt_this) {}
|
||||
|
||||
void operator()(coord_t iy, coord_t ix) {
|
||||
// Called with a row and colum of the grid cell, which is intersected by a line.
|
||||
auto cell_data_range = grid.cell_data_range(iy, ix);
|
||||
for (auto it_contour_and_segment = cell_data_range.first; it_contour_and_segment != cell_data_range.second; ++ it_contour_and_segment) {
|
||||
// End points of the line segment and their vector.
|
||||
auto segment = grid.segment(*it_contour_and_segment);
|
||||
if (Geometry::segments_intersect(segment.first, segment.second, *pt_prev, *pt_this)) {
|
||||
// The two segments intersect. Add them to the output.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const EdgeGrid::Grid &grid;
|
||||
const Slic3r::Point *pt_this;
|
||||
const Slic3r::Point *pt_prev;
|
||||
} visitor(grid, &loop.points.back(), nullptr);
|
||||
|
||||
for (const Point &pt_this : loop.points) {
|
||||
visitor.pt_this = &pt_this;
|
||||
grid.visit_cells_intersecting_line(*visitor.pt_prev, pt_this, visitor);
|
||||
visitor.pt_prev = &pt_this;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::vector<TrimmedLoop> trim_loops(const Polygons &loops, const EdgeGrid::Grid &grid)
|
||||
{
|
||||
std::vector<TrimmedLoop> out;
|
||||
out.reserve(loops.size());
|
||||
for (const Polygon &loop : loops)
|
||||
out.emplace_back(trim_loop(loop, grid));
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
32
src/libslic3r/PolygonTrimmer.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef slic3r_PolygonTrimmer_hpp_
|
||||
#define slic3r_PolygonTrimmer_hpp_
|
||||
|
||||
#include "libslic3r.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "Line.hpp"
|
||||
#include "MultiPoint.hpp"
|
||||
#include "Polyline.hpp"
|
||||
#include "Polygon.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace EdgeGrid {
|
||||
class Grid;
|
||||
}
|
||||
|
||||
struct TrimmedLoop
|
||||
{
|
||||
std::vector<Point> points;
|
||||
// Number of points per segment. Empty if the loop is
|
||||
std::vector<unsigned int> segments;
|
||||
|
||||
bool is_trimmed() const { return ! segments.empty(); }
|
||||
};
|
||||
|
||||
TrimmedLoop trim_loop(const Polygon &loop, const EdgeGrid::Grid &grid);
|
||||
std::vector<TrimmedLoop> trim_loops(const Polygons &loops, const EdgeGrid::Grid &grid);
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif /* slic3r_PolygonTrimmer_hpp_ */
|
@ -19,6 +19,7 @@
|
||||
#include <limits>
|
||||
#include <unordered_set>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
//! macro used to mark string used at localization,
|
||||
@ -270,8 +271,14 @@ std::vector<unsigned int> Print::object_extruders() const
|
||||
{
|
||||
std::vector<unsigned int> extruders;
|
||||
extruders.reserve(m_regions.size() * 3);
|
||||
for (const PrintRegion *region : m_regions)
|
||||
region->collect_object_printing_extruders(extruders);
|
||||
std::vector<unsigned char> region_used(m_regions.size(), false);
|
||||
for (const PrintObject *object : m_objects)
|
||||
for (const std::vector<std::pair<t_layer_height_range, int>> &volumes_per_region : object->region_volumes)
|
||||
if (! volumes_per_region.empty())
|
||||
region_used[&volumes_per_region - &object->region_volumes.front()] = true;
|
||||
for (size_t idx_region = 0; idx_region < m_regions.size(); ++ idx_region)
|
||||
if (region_used[idx_region])
|
||||
m_regions[idx_region]->collect_object_printing_extruders(extruders);
|
||||
sort_remove_duplicates(extruders);
|
||||
return extruders;
|
||||
}
|
||||
@ -281,19 +288,26 @@ std::vector<unsigned int> Print::support_material_extruders() const
|
||||
{
|
||||
std::vector<unsigned int> extruders;
|
||||
bool support_uses_current_extruder = false;
|
||||
auto num_extruders = (unsigned int)m_config.nozzle_diameter.size();
|
||||
|
||||
for (PrintObject *object : m_objects) {
|
||||
if (object->has_support_material()) {
|
||||
assert(object->config().support_material_extruder >= 0);
|
||||
if (object->config().support_material_extruder == 0)
|
||||
support_uses_current_extruder = true;
|
||||
else
|
||||
extruders.push_back(object->config().support_material_extruder - 1);
|
||||
else {
|
||||
unsigned int i = (unsigned int)object->config().support_material_extruder - 1;
|
||||
extruders.emplace_back((i >= num_extruders) ? 0 : i);
|
||||
}
|
||||
assert(object->config().support_material_interface_extruder >= 0);
|
||||
if (object->config().support_material_interface_extruder == 0)
|
||||
support_uses_current_extruder = true;
|
||||
else
|
||||
extruders.push_back(object->config().support_material_interface_extruder - 1);
|
||||
else {
|
||||
unsigned int i = (unsigned int)object->config().support_material_interface_extruder - 1;
|
||||
extruders.emplace_back((i >= num_extruders) ? 0 : i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (support_uses_current_extruder)
|
||||
// Add all object extruders to the support extruders as it is not know which one will be used to print supports.
|
||||
@ -585,6 +599,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
|
||||
// Apply variables to placeholder parser. The placeholder parser is used by G-code export,
|
||||
// which should be stopped if print_diff is not empty.
|
||||
size_t num_extruders = m_config.nozzle_diameter.size();
|
||||
bool num_extruders_changed = false;
|
||||
if (! full_config_diff.empty() || ! placeholder_parser_overrides.empty()) {
|
||||
update_apply_status(this->invalidate_step(psGCodeExport));
|
||||
m_placeholder_parser.apply_config(std::move(placeholder_parser_overrides));
|
||||
@ -600,6 +616,10 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
// Handle changes to regions config defaults
|
||||
m_default_region_config.apply_only(new_full_config, region_diff, true);
|
||||
m_full_print_config = std::move(new_full_config);
|
||||
if (num_extruders != m_config.nozzle_diameter.size()) {
|
||||
num_extruders = m_config.nozzle_diameter.size();
|
||||
num_extruders_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
class LayerRanges
|
||||
@ -776,7 +796,6 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
print_object_status.emplace(PrintObjectStatus(print_object));
|
||||
|
||||
// 3) Synchronize ModelObjects & PrintObjects.
|
||||
size_t num_extruders = m_config.nozzle_diameter.size();
|
||||
for (size_t idx_model_object = 0; idx_model_object < model.objects.size(); ++ idx_model_object) {
|
||||
ModelObject &model_object = *m_model.objects[idx_model_object];
|
||||
auto it_status = model_object_status.find(ModelObjectStatus(model_object.id()));
|
||||
@ -823,7 +842,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
bool object_config_changed = model_object.config != model_object_new.config;
|
||||
if (object_config_changed)
|
||||
static_cast<DynamicPrintConfig&>(model_object.config) = static_cast<const DynamicPrintConfig&>(model_object_new.config);
|
||||
if (! object_diff.empty() || object_config_changed) {
|
||||
if (! object_diff.empty() || object_config_changed || num_extruders_changed) {
|
||||
PrintObjectConfig new_config = PrintObject::object_config_from_model_object(m_default_object_config, model_object, num_extruders);
|
||||
auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id()));
|
||||
for (auto it = range.first; it != range.second; ++ it) {
|
||||
@ -1152,16 +1171,27 @@ std::string Print::validate() const
|
||||
// #4043
|
||||
if (total_copies_count > 1 && ! m_config.complete_objects.value)
|
||||
return L("The Spiral Vase option can only be used when printing a single object.");
|
||||
if (m_regions.size() > 1)
|
||||
assert(m_objects.size() == 1);
|
||||
size_t num_regions = 0;
|
||||
for (const std::vector<std::pair<t_layer_height_range, int>> &volumes_per_region : m_objects.front()->region_volumes)
|
||||
if (! volumes_per_region.empty())
|
||||
++ num_regions;
|
||||
if (num_regions > 1)
|
||||
return L("The Spiral Vase option can only be used when printing single material objects.");
|
||||
}
|
||||
|
||||
if (this->has_wipe_tower() && ! m_objects.empty()) {
|
||||
// make sure all extruders use same diameter filament and have the same nozzle diameter
|
||||
// Make sure all extruders use same diameter filament and have the same nozzle diameter
|
||||
// EPSILON comparison is used for nozzles and 10 % tolerance is used for filaments
|
||||
double first_nozzle_diam = m_config.nozzle_diameter.get_at(extruders().front());
|
||||
double first_filament_diam = m_config.filament_diameter.get_at(extruders().front());
|
||||
for (const auto& extruder_idx : extruders()) {
|
||||
if (m_config.nozzle_diameter.get_at(extruder_idx) != m_config.nozzle_diameter.get_at(extruders().front())
|
||||
|| m_config.filament_diameter.get_at(extruder_idx) != m_config.filament_diameter.get_at(extruders().front()))
|
||||
return L("The wipe tower is only supported if all extruders have the same nozzle diameter and use filaments of the same diameter.");
|
||||
double nozzle_diam = m_config.nozzle_diameter.get_at(extruder_idx);
|
||||
double filament_diam = m_config.filament_diameter.get_at(extruder_idx);
|
||||
if (nozzle_diam - EPSILON > first_nozzle_diam || nozzle_diam + EPSILON < first_nozzle_diam
|
||||
|| std::abs((filament_diam-first_filament_diam)/first_filament_diam) > 0.1)
|
||||
return L("The wipe tower is only supported if all extruders have the same nozzle diameter "
|
||||
"and use filaments of the same diameter.");
|
||||
}
|
||||
|
||||
if (m_config.gcode_flavor != gcfRepRap && m_config.gcode_flavor != gcfRepetier && m_config.gcode_flavor != gcfMarlin)
|
||||
@ -1169,15 +1199,11 @@ std::string Print::validate() const
|
||||
if (! m_config.use_relative_e_distances)
|
||||
return L("The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1).");
|
||||
|
||||
for (size_t i=1; i<m_config.nozzle_diameter.values.size(); ++i)
|
||||
if (m_config.nozzle_diameter.values[i] != m_config.nozzle_diameter.values[i-1])
|
||||
return L("All extruders must have the same diameter for the Wipe Tower.");
|
||||
|
||||
if (m_objects.size() > 1) {
|
||||
bool has_custom_layering = false;
|
||||
std::vector<std::vector<coordf_t>> layer_height_profiles;
|
||||
for (const PrintObject *object : m_objects) {
|
||||
has_custom_layering = ! object->model_object()->layer_config_ranges.empty() || ! object->model_object()->layer_height_profile.empty(); // #ys_FIXME_experiment
|
||||
has_custom_layering = ! object->model_object()->layer_config_ranges.empty() || ! object->model_object()->layer_height_profile.empty();
|
||||
if (has_custom_layering) {
|
||||
layer_height_profiles.assign(m_objects.size(), std::vector<coordf_t>());
|
||||
break;
|
||||
@ -1258,6 +1284,20 @@ std::string Print::validate() const
|
||||
return L("One or more object were assigned an extruder that the printer does not have.");
|
||||
#endif
|
||||
|
||||
auto validate_extrusion_width = [min_nozzle_diameter, max_nozzle_diameter](const ConfigBase &config, const char *opt_key, double layer_height, std::string &err_msg) -> bool {
|
||||
double extrusion_width_min = config.get_abs_value(opt_key, min_nozzle_diameter);
|
||||
double extrusion_width_max = config.get_abs_value(opt_key, max_nozzle_diameter);
|
||||
if (extrusion_width_min == 0) {
|
||||
// Default "auto-generated" extrusion width is always valid.
|
||||
} else if (extrusion_width_min <= layer_height) {
|
||||
err_msg = (boost::format(L("%1%=%2% mm is too low to be printable at a layer height %3% mm")) % opt_key % extrusion_width_min % layer_height).str();
|
||||
return false;
|
||||
} else if (extrusion_width_max >= max_nozzle_diameter * 3.) {
|
||||
err_msg = (boost::format(L("Excessive %1%=%2% mm to be printable with a nozzle diameter %3% mm")) % opt_key % extrusion_width_max % max_nozzle_diameter).str();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
for (PrintObject *object : m_objects) {
|
||||
if (object->config().raft_layers > 0 || object->config().support_material.value) {
|
||||
if ((object->config().support_material_extruder == 0 || object->config().support_material_interface_extruder == 0) && max_nozzle_diameter - min_nozzle_diameter > EPSILON) {
|
||||
@ -1301,8 +1341,20 @@ std::string Print::validate() const
|
||||
return L("First layer height can't be greater than nozzle diameter");
|
||||
|
||||
// validate layer_height
|
||||
if (object->config().layer_height.value > min_nozzle_diameter)
|
||||
double layer_height = object->config().layer_height.value;
|
||||
if (layer_height > min_nozzle_diameter)
|
||||
return L("Layer height can't be greater than nozzle diameter");
|
||||
|
||||
// Validate extrusion widths.
|
||||
std::string err_msg;
|
||||
if (! validate_extrusion_width(object->config(), "extrusion_width", layer_height, err_msg))
|
||||
return err_msg;
|
||||
if ((object->config().support_material || object->config().raft_layers > 0) && ! validate_extrusion_width(object->config(), "support_material_extrusion_width", layer_height, err_msg))
|
||||
return err_msg;
|
||||
for (const char *opt_key : { "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", "top_infill_extrusion_width" })
|
||||
for (size_t i = 0; i < object->region_volumes.size(); ++ i)
|
||||
if (! object->region_volumes[i].empty() && ! validate_extrusion_width(this->get_region(i)->config(), opt_key, layer_height, err_msg))
|
||||
return err_msg;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1912,7 +1964,7 @@ void Print::_make_wipe_tower()
|
||||
break;
|
||||
lt.has_support = true;
|
||||
// Insert the new support layer.
|
||||
double height = lt.print_z - m_wipe_tower_data.tool_ordering.layer_tools()[i-1].print_z;
|
||||
double height = lt.print_z - (i == 0 ? 0. : m_wipe_tower_data.tool_ordering.layer_tools()[i-1].print_z);
|
||||
//FIXME the support layer ID is set to -1, as Vojtech hopes it is not being used anyway.
|
||||
it_layer = m_objects.front()->insert_support_layer(it_layer, -1, height, lt.print_z, lt.print_z - 0.5 * height);
|
||||
++ it_layer;
|
||||
@ -1922,16 +1974,7 @@ void Print::_make_wipe_tower()
|
||||
this->throw_if_canceled();
|
||||
|
||||
// Initialize the wipe tower.
|
||||
WipeTower wipe_tower(m_config
|
||||
//m_config.single_extruder_multi_material.value,
|
||||
//float(m_config.wipe_tower_x.value), float(m_config.wipe_tower_y.value),
|
||||
//float(m_config.wipe_tower_width.value),
|
||||
//float(m_config.wipe_tower_rotation_angle.value), float(m_config.cooling_tube_retraction.value),
|
||||
//float(m_config.cooling_tube_length.value), float(m_config.parking_pos_retraction.value),
|
||||
//float(m_config.extra_loading_move.value), float(m_config.wipe_tower_bridging),
|
||||
//m_config.high_current_on_filament_swap.value
|
||||
, wipe_volumes,
|
||||
m_wipe_tower_data.tool_ordering.first_extruder(), this->brim_flow().width);
|
||||
WipeTower wipe_tower(m_config, wipe_volumes, m_wipe_tower_data.tool_ordering.first_extruder());
|
||||
|
||||
|
||||
//wipe_tower.set_retract();
|
||||
@ -1939,7 +1982,9 @@ void Print::_make_wipe_tower()
|
||||
|
||||
// Set the extruder & material properties at the wipe tower object.
|
||||
for (size_t i = 0; i < number_of_extruders; ++i)
|
||||
wipe_tower.set_extruder(i);
|
||||
|
||||
wipe_tower.set_extruder(i, m_config);
|
||||
|
||||
m_wipe_tower_data.priming = Slic3r::make_unique<std::vector<WipeTower::ToolChangeResult>>(
|
||||
wipe_tower.prime((float)this->skirt_first_layer_height(), m_wipe_tower_data.tool_ordering.all_extruders(), false));
|
||||
|
||||
|
@ -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)
|
||||
@ -27,7 +27,7 @@ static void assign_printer_technology_to_unknown(t_optiondef_map &options, Print
|
||||
PrintConfigDef::PrintConfigDef()
|
||||
{
|
||||
this->init_common_params();
|
||||
//assign params that are not already allocated to FFF+SLA (default from slic3rPE)
|
||||
//assign params that are not already allocated to FFF+SLA (default from slic3rPE)
|
||||
assign_printer_technology_to_unknown(this->options, ptFFF | ptSLA);
|
||||
this->init_fff_params();
|
||||
this->init_extruder_retract_keys();
|
||||
@ -52,7 +52,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;
|
||||
@ -87,8 +87,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");
|
||||
@ -103,7 +103,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. "
|
||||
@ -216,7 +216,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->min = 0;
|
||||
def->max = 2;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(1));
|
||||
def->set_default_value(new ConfigOptionFloat(1));
|
||||
|
||||
def = this->add("over_bridge_flow_ratio", coFloat);
|
||||
def->label = L("Above the bridges");
|
||||
@ -484,6 +484,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->tooltip = L("Fill pattern for bottom infill. This only affects the bottom visible layer, and not its adjacent solid shells.");
|
||||
def->cli = "bottom-fill-pattern|external-fill-pattern=s";
|
||||
def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values();
|
||||
|
||||
def->enum_values.push_back("rectilinear");
|
||||
def->enum_values.push_back("rectilineargapfill");
|
||||
def->enum_values.push_back("concentric");
|
||||
@ -703,7 +704,7 @@ void PrintConfigDef::init_fff_params()
|
||||
"check filament diameter and your firmware E steps.");
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionFloats { 1. });
|
||||
|
||||
|
||||
def = this->add("extrusion_width", coFloatOrPercent);
|
||||
def->label = L("Default extrusion width");
|
||||
def->category = L("Extrusion Width");
|
||||
@ -861,7 +862,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");
|
||||
@ -938,7 +939,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;
|
||||
@ -1375,7 +1376,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("silent_mode", coBool);
|
||||
def = this->add("silent_mode", coBool);
|
||||
def->label = L("Supports stealth mode");
|
||||
def->category = L("Firmware");
|
||||
def->tooltip = L("The firmware supports stealth mode");
|
||||
@ -1391,79 +1392,79 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
const int machine_limits_opt_width = 70;
|
||||
{
|
||||
struct AxisDefault {
|
||||
std::string name;
|
||||
std::vector<double> max_feedrate;
|
||||
std::vector<double> max_acceleration;
|
||||
std::vector<double> max_jerk;
|
||||
};
|
||||
std::vector<AxisDefault> 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<std::string>(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 = 70;
|
||||
{
|
||||
struct AxisDefault {
|
||||
std::string name;
|
||||
std::vector<double> max_feedrate;
|
||||
std::vector<double> max_acceleration;
|
||||
std::vector<double> max_jerk;
|
||||
};
|
||||
std::vector<AxisDefault> 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<std::string>(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);
|
||||
@ -1474,7 +1475,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->min = 0;
|
||||
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);
|
||||
@ -1485,7 +1486,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->min = 0;
|
||||
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);
|
||||
@ -1704,7 +1705,7 @@ void PrintConfigDef::init_fff_params()
|
||||
"\n * Keep only bridges: remove the unsupported perimeter, kep only bridges that end in solid area."
|
||||
"\n * Keep bridges and overhangs: remove the unsupported perimeter, keep only bridges that end in solid area, fill the rest with overhang perimeters+bridges."
|
||||
"\n * Fill the voids with bridges: remove the unsupported perimeter, draw bridges over the whole hole. !! can lead to problems with overhangs shape like /\\, consider carefully before using this option!"
|
||||
"\n!!Computationally intensive!!. ");
|
||||
"\n!!Computationally intensive!!. ");
|
||||
def->enum_keys_map = &ConfigOptionEnum<NoPerimeterUnsupportedAlgo>::get_enum_values();
|
||||
def->enum_values.push_back("none");
|
||||
def->enum_values.push_back("noperi");
|
||||
@ -1803,9 +1804,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");
|
||||
@ -1837,7 +1838,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;
|
||||
@ -1885,7 +1886,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.");
|
||||
@ -1947,7 +1948,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->category = L("Support material");
|
||||
def->tooltip = L("Select this option to not use the z-lift on a top surface.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBools { false });
|
||||
def->set_default_value(new ConfigOptionBools { false });
|
||||
|
||||
def = this->add("retract_restart_extra", coFloats);
|
||||
def->label = L("Extra length on restart");
|
||||
@ -2079,7 +2080,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->min = 0;
|
||||
def->mode = comSimple;
|
||||
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 "
|
||||
@ -2289,7 +2290,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 = comAdvanced;
|
||||
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");
|
||||
@ -2372,8 +2373,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->aliases = { "support_material_contact_distance" };
|
||||
def->set_default_value(new ConfigOptionFloatOrPercent(0.2, false));
|
||||
@ -2562,7 +2563,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("");
|
||||
def->full_label = L("Thin walls");
|
||||
@ -2604,7 +2605,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 "
|
||||
@ -2863,45 +2864,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<const ConfigOptionFloats* >(it_opt->second.default_value.get())->values)); break;
|
||||
case coPercents : def->set_default_value(new ConfigOptionPercentsNullable(static_cast<const ConfigOptionPercents*>(it_opt->second.default_value.get())->values)); break;
|
||||
case coBools : def->set_default_value(new ConfigOptionBoolsNullable (static_cast<const ConfigOptionBools* >(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<const ConfigOptionFloats* >(it_opt->second.default_value.get())->values)); break;
|
||||
case coPercents : def->set_default_value(new ConfigOptionPercentsNullable(static_cast<const ConfigOptionPercents*>(it_opt->second.default_value.get())->values)); break;
|
||||
case coBools : def->set_default_value(new ConfigOptionBoolsNullable (static_cast<const ConfigOptionBools* >(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()
|
||||
@ -3003,7 +3004,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");
|
||||
@ -3014,7 +3015,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);
|
||||
@ -3032,6 +3033,22 @@ void PrintConfigDef::init_sla_params()
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionInt(10));
|
||||
|
||||
def = this->add("min_exposure_time", coFloat);
|
||||
def->label = L("Minimum exposure time");
|
||||
def->tooltip = L("Minimum exposure time");
|
||||
def->sidetext = L("s");
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("max_exposure_time", coFloat);
|
||||
def->label = L("Maximum exposure time");
|
||||
def->tooltip = L("Maximum exposure time");
|
||||
def->sidetext = L("s");
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionFloat(100));
|
||||
|
||||
def = this->add("exposure_time", coFloat);
|
||||
def->label = L("Exposure time");
|
||||
def->tooltip = L("Exposure time");
|
||||
@ -3039,6 +3056,22 @@ void PrintConfigDef::init_sla_params()
|
||||
def->min = 0;
|
||||
def->set_default_value(new ConfigOptionFloat(10));
|
||||
|
||||
def = this->add("min_initial_exposure_time", coFloat);
|
||||
def->label = L("Minimum initial exposure time");
|
||||
def->tooltip = L("Minimum initial exposure time");
|
||||
def->sidetext = L("s");
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("max_initial_exposure_time", coFloat);
|
||||
def->label = L("Maximum initial exposure time");
|
||||
def->tooltip = L("Maximum initial exposure time");
|
||||
def->sidetext = L("s");
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionFloat(150));
|
||||
|
||||
def = this->add("initial_exposure_time", coFloat);
|
||||
def->label = L("Initial exposure time");
|
||||
def->tooltip = L("Initial exposure time");
|
||||
@ -3181,7 +3214,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");
|
||||
@ -3296,14 +3329,14 @@ void PrintConfigDef::init_sla_params()
|
||||
def->set_default_value(new ConfigOptionFloat(50.0));
|
||||
|
||||
// This is disabled on the UI. I hope it will never be enabled.
|
||||
def = this->add("pad_edge_radius", coFloat);
|
||||
def->label = L("Pad edge radius");
|
||||
def->category = L("Pad");
|
||||
// def->tooltip = L("");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(1.0));
|
||||
// def = this->add("pad_edge_radius", coFloat);
|
||||
// def->label = L("Pad edge radius");
|
||||
// def->category = L("Pad");
|
||||
//// def->tooltip = L("");
|
||||
// def->sidetext = L("mm");
|
||||
// def->min = 0;
|
||||
// def->mode = comAdvanced;
|
||||
// def->set_default_value(new ConfigOptionFloat(1.0));
|
||||
|
||||
def = this->add("pad_wall_slope", coFloat);
|
||||
def->label = L("Pad wall slope");
|
||||
@ -3315,7 +3348,14 @@ void PrintConfigDef::init_sla_params()
|
||||
def->max = 90;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(45.0));
|
||||
|
||||
|
||||
def = this->add("pad_zero_elevation", coBool);
|
||||
def->label = L("Pad around object");
|
||||
def->category = L("Pad");
|
||||
def->tooltip = L("Create pad around object and ignore the support elevation");
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("pad_object_gap", coFloat);
|
||||
def->label = L("Pad object gap");
|
||||
def->category = L("Pad");
|
||||
@ -3326,7 +3366,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");
|
||||
@ -3336,7 +3376,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");
|
||||
@ -3346,7 +3386,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");
|
||||
@ -3367,7 +3407,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<float>(value);
|
||||
if (v != 0)
|
||||
if (v != 0)
|
||||
value = boost::lexical_cast<std::string>(v*100) + "%";
|
||||
} catch (boost::bad_lexical_cast &) {
|
||||
value = "0";
|
||||
@ -3407,14 +3447,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<std::string> 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"
|
||||
@ -3425,7 +3465,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;
|
||||
@ -3465,10 +3505,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<ConfigOptionBool>("spiral_vase", true)->value) {
|
||||
{
|
||||
// this should be actually done only on the spiral layers instead of all
|
||||
@ -3541,7 +3581,6 @@ double PrintConfig::min_object_distance(const ConfigBase *config)
|
||||
}
|
||||
}
|
||||
return base_dist;
|
||||
}
|
||||
|
||||
//FIXME localize this function.
|
||||
std::string FullPrintConfig::validate()
|
||||
@ -3565,7 +3604,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";
|
||||
@ -3575,8 +3614,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 &&
|
||||
@ -3588,11 +3627,11 @@ 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";
|
||||
@ -3615,7 +3654,7 @@ std::string FullPrintConfig::validate()
|
||||
|| ! print_config_def.get("bottom_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";
|
||||
@ -3623,7 +3662,7 @@ 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";
|
||||
@ -3667,7 +3706,7 @@ std::string FullPrintConfig::validate()
|
||||
if (this->extra_perimeters)
|
||||
return "Can't make more than one perimeter when spiral vase mode is enabled";
|
||||
}
|
||||
|
||||
|
||||
// extrusion widths
|
||||
{
|
||||
double max_nozzle_diameter = 0.;
|
||||
@ -3724,7 +3763,7 @@ std::string FullPrintConfig::validate()
|
||||
if (out_of_range)
|
||||
return std::string("Value out of range: " + opt_key);
|
||||
}
|
||||
|
||||
|
||||
// The configuration is valid.
|
||||
return "";
|
||||
}
|
||||
@ -3747,13 +3786,13 @@ StaticPrintConfig::StaticCache<class Slic3r::SLAFullPrintConfig> 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");
|
||||
@ -3761,7 +3800,7 @@ CLIActionsConfigDef::CLIActionsConfigDef()
|
||||
def->set_default_value(new ConfigOptionBool(false);
|
||||
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.");
|
||||
@ -3810,12 +3849,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.");
|
||||
@ -3825,38 +3864,38 @@ 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->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->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->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.");
|
||||
@ -3865,12 +3904,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.");
|
||||
@ -3883,22 +3922,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.");
|
||||
@ -3907,7 +3946,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.");
|
||||
@ -3917,26 +3956,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.");
|
||||
@ -3946,7 +3985,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.");
|
||||
@ -3962,15 +4001,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/types/polymorphic.hpp>
|
||||
CEREAL_REGISTER_TYPE(Slic3r::DynamicPrintConfig)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::DynamicConfig, Slic3r::DynamicPrintConfig)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::DynamicConfig, Slic3r::DynamicPrintConfig)
|
||||
|
@ -891,7 +891,7 @@ protected:
|
||||
class PrintConfig : public MachineEnvelopeConfig, public GCodeConfig
|
||||
{
|
||||
STATIC_PRINT_CONFIG_CACHE_DERIVED(PrintConfig)
|
||||
PrintConfig() : MachineEnvelopeConfig(0), GCodeConfig(0) { initialize_cache(); *this = s_cache_PrintConfig.defaults(); }
|
||||
PrintConfig() : MachineEnvelopeConfig(0), GCodeConfig(0) { initialize_cache(); *this = s_cache_PrintConfig.defaults(); }
|
||||
public:
|
||||
double min_object_distance() const;
|
||||
static double min_object_distance(const ConfigBase *config);
|
||||
@ -967,7 +967,7 @@ public:
|
||||
ConfigOptionFloat z_offset;
|
||||
|
||||
protected:
|
||||
PrintConfig(int) : MachineEnvelopeConfig(1), GCodeConfig(1) {}
|
||||
PrintConfig(int) : MachineEnvelopeConfig(1), GCodeConfig(1) {}
|
||||
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
||||
{
|
||||
this->MachineEnvelopeConfig::initialize(cache, base_ptr);
|
||||
@ -1150,7 +1150,7 @@ public:
|
||||
|
||||
// The height of the pillar base cone in mm.
|
||||
ConfigOptionFloat support_base_height /*= 1.0*/;
|
||||
|
||||
|
||||
// The minimum distance of the pillar base from the model in mm.
|
||||
ConfigOptionFloat support_base_safety_distance; /*= 1.0*/;
|
||||
|
||||
@ -1166,7 +1166,7 @@ public:
|
||||
// The elevation in Z direction upwards. This is the space between the pad
|
||||
// and the model object's bounding box bottom. Units in mm.
|
||||
ConfigOptionFloat support_object_elevation /*= 5.0*/;
|
||||
|
||||
|
||||
/////// Following options influence automatic support points placement:
|
||||
ConfigOptionInt support_points_density_relative;
|
||||
ConfigOptionFloat support_points_minimal_distance;
|
||||
@ -1187,11 +1187,11 @@ public:
|
||||
ConfigOptionFloat pad_max_merge_distance /*= 50*/;
|
||||
|
||||
// The smoothing radius of the pad edges
|
||||
ConfigOptionFloat pad_edge_radius /*= 1*/;
|
||||
// ConfigOptionFloat pad_edge_radius /*= 1*/;
|
||||
|
||||
// The slope of the pad wall...
|
||||
ConfigOptionFloat pad_wall_slope;
|
||||
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
// Zero elevation mode parameters:
|
||||
// - The object pad will be derived from the the model geometry.
|
||||
@ -1199,16 +1199,19 @@ public:
|
||||
// according to the support_base_safety_distance parameter.
|
||||
// - The two pads will be connected with tiny connector sticks
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Disable the elevation (ignore its value) and use the zero elevation mode
|
||||
ConfigOptionBool pad_zero_elevation;
|
||||
|
||||
// This is the gap between the object bottom and the generated pad
|
||||
ConfigOptionFloat pad_object_gap;
|
||||
|
||||
|
||||
// How far to place the connector sticks on the object pad perimeter
|
||||
ConfigOptionFloat pad_object_connector_stride;
|
||||
|
||||
|
||||
// The width of the connectors sticks
|
||||
ConfigOptionFloat pad_object_connector_width;
|
||||
|
||||
|
||||
// How much should the tiny connectors penetrate into the model body
|
||||
ConfigOptionFloat pad_object_connector_penetration;
|
||||
|
||||
@ -1239,8 +1242,9 @@ protected:
|
||||
OPT_PTR(pad_wall_thickness);
|
||||
OPT_PTR(pad_wall_height);
|
||||
OPT_PTR(pad_max_merge_distance);
|
||||
OPT_PTR(pad_edge_radius);
|
||||
// OPT_PTR(pad_edge_radius);
|
||||
OPT_PTR(pad_wall_slope);
|
||||
OPT_PTR(pad_zero_elevation);
|
||||
OPT_PTR(pad_object_gap);
|
||||
OPT_PTR(pad_object_connector_stride);
|
||||
OPT_PTR(pad_object_connector_width);
|
||||
@ -1286,6 +1290,10 @@ public:
|
||||
ConfigOptionFloat fast_tilt_time;
|
||||
ConfigOptionFloat slow_tilt_time;
|
||||
ConfigOptionFloat area_fill;
|
||||
ConfigOptionFloat min_exposure_time;
|
||||
ConfigOptionFloat max_exposure_time;
|
||||
ConfigOptionFloat min_initial_exposure_time;
|
||||
ConfigOptionFloat max_initial_exposure_time;
|
||||
protected:
|
||||
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
||||
{
|
||||
@ -1305,6 +1313,10 @@ protected:
|
||||
OPT_PTR(fast_tilt_time);
|
||||
OPT_PTR(slow_tilt_time);
|
||||
OPT_PTR(area_fill);
|
||||
OPT_PTR(min_exposure_time);
|
||||
OPT_PTR(max_exposure_time);
|
||||
OPT_PTR(min_initial_exposure_time);
|
||||
OPT_PTR(max_initial_exposure_time);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1364,8 +1376,8 @@ extern const CLIMiscConfigDef cli_misc_config_def;
|
||||
class DynamicPrintAndCLIConfig : public DynamicPrintConfig
|
||||
{
|
||||
public:
|
||||
DynamicPrintAndCLIConfig() {}
|
||||
DynamicPrintAndCLIConfig(const DynamicPrintAndCLIConfig &other) : DynamicPrintConfig(other) {}
|
||||
DynamicPrintAndCLIConfig() {}
|
||||
DynamicPrintAndCLIConfig(const DynamicPrintAndCLIConfig &other) : DynamicPrintConfig(other) {}
|
||||
|
||||
// Overrides ConfigBase::def(). Static configuration definition. Any value stored into this ConfigBase shall have its definition here.
|
||||
const ConfigDef* def() const override { return &s_def; }
|
||||
@ -1386,7 +1398,7 @@ private:
|
||||
this->options.insert(cli_transform_config_def.options.begin(), cli_transform_config_def.options.end());
|
||||
this->options.insert(cli_misc_config_def.options.begin(), cli_misc_config_def.options.end());
|
||||
for (const auto &kvp : this->options)
|
||||
this->by_serialization_key_ordinal[kvp.second.serialization_key_ordinal] = &kvp.second;
|
||||
this->by_serialization_key_ordinal[kvp.second.serialization_key_ordinal] = &kvp.second;
|
||||
}
|
||||
// Do not release the default values, they are handled by print_config_def & cli_actions_config_def / cli_transform_config_def / cli_misc_config_def.
|
||||
~PrintAndCLIConfigDef() { this->options.clear(); }
|
||||
@ -1398,36 +1410,36 @@ private:
|
||||
|
||||
// Serialization through the Cereal library
|
||||
namespace cereal {
|
||||
// Let cereal know that there are load / save non-member functions declared for DynamicPrintConfig, ignore serialize / load / save from parent class DynamicConfig.
|
||||
template <class Archive> struct specialize<Archive, Slic3r::DynamicPrintConfig, cereal::specialization::non_member_load_save> {};
|
||||
// Let cereal know that there are load / save non-member functions declared for DynamicPrintConfig, ignore serialize / load / save from parent class DynamicConfig.
|
||||
template <class Archive> struct specialize<Archive, Slic3r::DynamicPrintConfig, cereal::specialization::non_member_load_save> {};
|
||||
|
||||
template<class Archive> void load(Archive& archive, Slic3r::DynamicPrintConfig &config)
|
||||
{
|
||||
size_t cnt;
|
||||
archive(cnt);
|
||||
config.clear();
|
||||
for (size_t i = 0; i < cnt; ++ i) {
|
||||
size_t serialization_key_ordinal;
|
||||
archive(serialization_key_ordinal);
|
||||
assert(serialization_key_ordinal > 0);
|
||||
auto it = Slic3r::print_config_def.by_serialization_key_ordinal.find(serialization_key_ordinal);
|
||||
assert(it != Slic3r::print_config_def.by_serialization_key_ordinal.end());
|
||||
config.set_key_value(it->second->opt_key, it->second->load_option_from_archive(archive));
|
||||
}
|
||||
}
|
||||
template<class Archive> void load(Archive& archive, Slic3r::DynamicPrintConfig &config)
|
||||
{
|
||||
size_t cnt;
|
||||
archive(cnt);
|
||||
config.clear();
|
||||
for (size_t i = 0; i < cnt; ++ i) {
|
||||
size_t serialization_key_ordinal;
|
||||
archive(serialization_key_ordinal);
|
||||
assert(serialization_key_ordinal > 0);
|
||||
auto it = Slic3r::print_config_def.by_serialization_key_ordinal.find(serialization_key_ordinal);
|
||||
assert(it != Slic3r::print_config_def.by_serialization_key_ordinal.end());
|
||||
config.set_key_value(it->second->opt_key, it->second->load_option_from_archive(archive));
|
||||
}
|
||||
}
|
||||
|
||||
template<class Archive> void save(Archive& archive, const Slic3r::DynamicPrintConfig &config)
|
||||
{
|
||||
size_t cnt = config.size();
|
||||
archive(cnt);
|
||||
for (auto it = config.cbegin(); it != config.cend(); ++it) {
|
||||
const Slic3r::ConfigOptionDef* optdef = Slic3r::print_config_def.get(it->first);
|
||||
assert(optdef != nullptr);
|
||||
assert(optdef->serialization_key_ordinal > 0);
|
||||
archive(optdef->serialization_key_ordinal);
|
||||
optdef->save_option_to_archive(archive, it->second.get());
|
||||
}
|
||||
}
|
||||
template<class Archive> void save(Archive& archive, const Slic3r::DynamicPrintConfig &config)
|
||||
{
|
||||
size_t cnt = config.size();
|
||||
archive(cnt);
|
||||
for (auto it = config.cbegin(); it != config.cend(); ++it) {
|
||||
const Slic3r::ConfigOptionDef* optdef = Slic3r::print_config_def.get(it->first);
|
||||
assert(optdef != nullptr);
|
||||
assert(optdef->serialization_key_ordinal > 0);
|
||||
archive(optdef->serialization_key_ordinal);
|
||||
optdef->save_option_to_archive(archive, it->second.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -162,7 +162,7 @@ void PrintObject::make_perimeters()
|
||||
const PrintRegion ®ion = *m_print->regions()[region_id];
|
||||
if (! region.config().extra_perimeters || region.config().perimeters == 0 || region.config().fill_density == 0 || this->layer_count() < 2)
|
||||
continue;
|
||||
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Generating extra perimeters for region " << region_id << " in parallel - start";
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, m_layers.size() - 1),
|
||||
@ -2863,7 +2863,7 @@ void PrintObject::discover_horizontal_shells()
|
||||
if (new_internal_solid.empty()) {
|
||||
// No internal solid needed on this layer. In order to decide whether to continue
|
||||
// searching on the next neighbor (thus enforcing the configured number of solid
|
||||
// layers, use different strategies according to configured infill density:
|
||||
// layers, use different strategies according to configured infill density:
|
||||
if (region_config.fill_density.value == 0) {
|
||||
// If user expects the object to be void (for example a hollow sloping vase),
|
||||
// don't continue the search. In this case, we only generate the external solid
|
||||
|
@ -46,7 +46,7 @@ Flow PrintRegion::flow(FlowRole role, double layer_height, bool bridge, bool fir
|
||||
}
|
||||
double nozzle_diameter = m_print->config().nozzle_diameter.get_at(extruder-1);
|
||||
|
||||
return Flow::new_from_config_width(role, config_width, nozzle_diameter, layer_height, bridge ? (float)m_config.bridge_flow_ratio : 0.0);
|
||||
return Flow::new_from_config_width(role, config_width, (float)nozzle_diameter, (float)layer_height, bridge ? (float)m_config.bridge_flow_ratio : 0.0f);
|
||||
}
|
||||
|
||||
coordf_t PrintRegion::nozzle_dmr_avg(const PrintConfig &print_config) const
|
||||
@ -64,16 +64,27 @@ coordf_t PrintRegion::bridging_height_avg(const PrintConfig &print_config) const
|
||||
void PrintRegion::collect_object_printing_extruders(const PrintConfig &print_config, const PrintRegionConfig ®ion_config, std::vector<unsigned int> &object_extruders)
|
||||
{
|
||||
// These checks reflect the same logic used in the GUI for enabling/disabling extruder selection fields.
|
||||
auto num_extruders = (int)print_config.nozzle_diameter.size();
|
||||
auto emplace_extruder = [num_extruders, &object_extruders](int extruder_id) {
|
||||
int i = std::max(0, extruder_id - 1);
|
||||
object_extruders.emplace_back((i >= num_extruders) ? 0 : i);
|
||||
};
|
||||
if (region_config.perimeters.value > 0 || print_config.brim_width.value > 0)
|
||||
object_extruders.emplace_back(region_config.perimeter_extruder - 1);
|
||||
emplace_extruder(region_config.perimeter_extruder);
|
||||
if (region_config.fill_density.value > 0)
|
||||
object_extruders.emplace_back(region_config.infill_extruder - 1);
|
||||
emplace_extruder(region_config.infill_extruder);
|
||||
if (region_config.top_solid_layers.value > 0 || region_config.bottom_solid_layers.value > 0)
|
||||
object_extruders.emplace_back(region_config.solid_infill_extruder - 1);
|
||||
emplace_extruder(region_config.solid_infill_extruder);
|
||||
}
|
||||
|
||||
void PrintRegion::collect_object_printing_extruders(std::vector<unsigned int> &object_extruders) const
|
||||
{
|
||||
auto num_extruders = (int)print()->config().nozzle_diameter.size();
|
||||
// PrintRegion, if used by some PrintObject, shall have all the extruders set to an existing printer extruder.
|
||||
// If not, then there must be something wrong with the Print::apply() function.
|
||||
assert(this->config().perimeter_extruder <= num_extruders);
|
||||
assert(this->config().infill_extruder <= num_extruders);
|
||||
assert(this->config().solid_infill_extruder <= num_extruders);
|
||||
collect_object_printing_extruders(print()->config(), this->config(), object_extruders);
|
||||
}
|
||||
|
||||
|
@ -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 <tbb/parallel_for.h>
|
||||
|
||||
|
@ -85,7 +85,7 @@ using Portion = std::tuple<double, double>;
|
||||
|
||||
// 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<bool> struct _ccr {};
|
||||
|
||||
@ -713,7 +713,7 @@ struct Pad {
|
||||
}
|
||||
|
||||
tmesh.translate(0, 0, float(zlevel));
|
||||
tmesh.require_shared_vertices();
|
||||
if (!tmesh.empty()) tmesh.require_shared_vertices();
|
||||
}
|
||||
|
||||
bool empty() const { return tmesh.facets_count() == 0; }
|
||||
@ -1194,7 +1194,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)
|
||||
{
|
||||
@ -1297,7 +1297,7 @@ class SLASupportTree::Algorithm {
|
||||
// Hit results
|
||||
std::array<HitResult, SAMPLES> 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)
|
||||
{
|
||||
@ -2588,7 +2588,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 {
|
||||
@ -2597,41 +2597,53 @@ void SLASupportTree::merged_mesh_with_pad(TriangleMesh &outmesh) const {
|
||||
}
|
||||
|
||||
std::vector<ExPolygons> SLASupportTree::slice(
|
||||
const std::vector<float> &heights, float cr) const
|
||||
const std::vector<float> &grid, float cr) const
|
||||
{
|
||||
const TriangleMesh &sup_mesh = m_impl->merged_mesh();
|
||||
const TriangleMesh &pad_mesh = get_pad();
|
||||
|
||||
std::vector<ExPolygons> sup_slices;
|
||||
using Slices = std::vector<ExPolygons>;
|
||||
auto slices = reserve_vector<Slices>(2);
|
||||
|
||||
if (!sup_mesh.empty()) {
|
||||
slices.emplace_back();
|
||||
|
||||
TriangleMeshSlicer sup_slicer(&sup_mesh);
|
||||
sup_slicer.closing_radius = cr;
|
||||
sup_slicer.slice(heights, &sup_slices, m_impl->ctl().cancelfn);
|
||||
sup_slicer.slice(grid, &slices.back(), m_impl->ctl().cancelfn);
|
||||
}
|
||||
|
||||
if (!pad_mesh.empty()) {
|
||||
slices.emplace_back();
|
||||
|
||||
auto bb = pad_mesh.bounding_box();
|
||||
auto maxzit = std::upper_bound(heights.begin(), heights.end(), bb.max.z());
|
||||
auto maxzit = std::upper_bound(grid.begin(), grid.end(), bb.max.z());
|
||||
|
||||
auto padgrid = reserve_vector<float>(heights.end() - maxzit);
|
||||
std::copy(heights.begin(), maxzit, std::back_inserter(padgrid));
|
||||
auto padgrid = reserve_vector<float>(grid.end() - maxzit);
|
||||
std::copy(grid.begin(), maxzit, std::back_inserter(padgrid));
|
||||
|
||||
std::vector<ExPolygons> pad_slices;
|
||||
if (!pad_mesh.empty()) {
|
||||
TriangleMeshSlicer pad_slicer(&pad_mesh);
|
||||
pad_slicer.closing_radius = cr;
|
||||
pad_slicer.slice(padgrid, &pad_slices, m_impl->ctl().cancelfn);
|
||||
pad_slicer.slice(padgrid, &slices.back(), m_impl->ctl().cancelfn);
|
||||
}
|
||||
|
||||
size_t len = std::min(heights.size(), pad_slices.size());
|
||||
len = std::min(len, sup_slices.size());
|
||||
size_t len = grid.size();
|
||||
for (const Slices &slv : slices) { len = std::min(len, slv.size()); }
|
||||
|
||||
// Either the support or the pad or both has to be non empty
|
||||
if (slices.empty()) return {};
|
||||
|
||||
Slices &mrg = slices.front();
|
||||
|
||||
for (auto it = std::next(slices.begin()); it != slices.end(); ++it) {
|
||||
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] = {};
|
||||
Slices &slv = *it;
|
||||
std::copy(slv[i].begin(), slv[i].end(), std::back_inserter(mrg[i]));
|
||||
slv[i] = {}; // clear and delete
|
||||
}
|
||||
}
|
||||
|
||||
return sup_slices;
|
||||
return mrg;
|
||||
}
|
||||
|
||||
const TriangleMesh &SLASupportTree::add_pad(const ExPolygons& modelbase,
|
||||
|
@ -148,9 +148,9 @@ std::vector<BoxIndexEl> BoxIndex::query(const BoundingBox &qrbb,
|
||||
BoxIndex::QueryType qt)
|
||||
{
|
||||
namespace bgi = boost::geometry::index;
|
||||
|
||||
|
||||
std::vector<BoxIndexEl> 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<BoxIndexEl> 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<double>();
|
||||
V.block<1, 3>(3 * i + 1, 0) = facet.vertex[1].cast<double>();
|
||||
V.block<1, 3>(3 * i + 2, 0) = facet.vertex[2].cast<double>();
|
||||
V.block<1, 3>(3 * i + 0, 0) = facet.vertex[0].cast<double>();
|
||||
V.block<1, 3>(3 * i + 1, 0) = facet.vertex[1].cast<double>();
|
||||
V.block<1, 3>(3 * i + 2, 0) = facet.vertex[2].cast<double>();
|
||||
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)
|
||||
{
|
||||
|
@ -16,6 +16,12 @@
|
||||
// For geometry algorithms with native Clipper types (no copies and conversions)
|
||||
#include <libnest2d/backends/clipper/geometries.hpp>
|
||||
|
||||
// #define SLAPRINT_DO_BENCHMARK
|
||||
|
||||
#ifdef SLAPRINT_DO_BENCHMARK
|
||||
#include <libnest2d/tools/benchmark.h>
|
||||
#endif
|
||||
|
||||
//#include <tbb/spin_mutex.h>//#include "tbb/mutex.h"
|
||||
|
||||
#include "I18N.hpp"
|
||||
@ -569,6 +575,16 @@ std::string SLAPrint::output_filename(const std::string &filename_base) const
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool is_zero_elevation(const SLAPrintObjectConfig &c) {
|
||||
bool en_implicit = c.support_object_elevation.getFloat() <= EPSILON &&
|
||||
c.pad_enable.getBool() && c.supports_enable.getBool();
|
||||
bool en_explicit = c.pad_zero_elevation.getBool() &&
|
||||
c.supports_enable.getBool();
|
||||
|
||||
return en_implicit || en_explicit;
|
||||
}
|
||||
|
||||
// Compile the argument for support creation from the static print config.
|
||||
sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c) {
|
||||
sla::SupportConfig scfg;
|
||||
@ -577,7 +593,8 @@ sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c) {
|
||||
scfg.head_back_radius_mm = 0.5*c.support_pillar_diameter.getFloat();
|
||||
scfg.head_penetration_mm = c.support_head_penetration.getFloat();
|
||||
scfg.head_width_mm = c.support_head_width.getFloat();
|
||||
scfg.object_elevation_mm = c.support_object_elevation.getFloat();
|
||||
scfg.object_elevation_mm = is_zero_elevation(c) ?
|
||||
0. : c.support_object_elevation.getFloat();
|
||||
scfg.bridge_slope = c.support_critical_angle.getFloat() * PI / 180.0 ;
|
||||
scfg.max_bridge_length_mm = c.support_max_bridge_length.getFloat();
|
||||
scfg.max_pillar_link_distance_mm = c.support_max_pillar_link_distance.getFloat();
|
||||
@ -603,8 +620,7 @@ sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c) {
|
||||
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();
|
||||
ret.enabled = is_zero_elevation(c);
|
||||
|
||||
if(ret.enabled) {
|
||||
ret.object_gap_mm = c.pad_object_gap.getFloat();
|
||||
@ -661,7 +677,9 @@ std::string SLAPrint::validate() const
|
||||
double elv = cfg.object_elevation_mm;
|
||||
|
||||
if(supports_en && elv > EPSILON && elv < pinhead_width )
|
||||
return L("Elevation is too low for object.");
|
||||
return L(
|
||||
"Elevation is too low for object. Use the \"Pad around "
|
||||
"obect\" feature to print the object without elevation.");
|
||||
|
||||
sla::PoolConfig::EmbedObject builtinpad = builtin_pad_cfg(po->config());
|
||||
if(supports_en && builtinpad.enabled &&
|
||||
@ -674,6 +692,20 @@ std::string SLAPrint::validate() const
|
||||
}
|
||||
}
|
||||
|
||||
double expt_max = m_printer_config.max_exposure_time.getFloat();
|
||||
double expt_min = m_printer_config.min_exposure_time.getFloat();
|
||||
double expt_cur = m_material_config.exposure_time.getFloat();
|
||||
|
||||
if (expt_cur < expt_min || expt_cur > expt_max)
|
||||
return L("Exposition time is out of printer profile bounds.");
|
||||
|
||||
double iexpt_max = m_printer_config.max_initial_exposure_time.getFloat();
|
||||
double iexpt_min = m_printer_config.min_initial_exposure_time.getFloat();
|
||||
double iexpt_cur = m_material_config.initial_exposure_time.getFloat();
|
||||
|
||||
if (iexpt_cur < iexpt_min || iexpt_cur > iexpt_max)
|
||||
return L("Initial exposition time is out of printer profile bounds.");
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@ -749,7 +781,7 @@ void SLAPrint::process()
|
||||
for(coord_t h = minZs + ilhs + lhs; h <= maxZs; h += lhs)
|
||||
po.m_slice_index.emplace_back(h, unscale<float>(h) - lh / 2.f, lh);
|
||||
|
||||
// Just get the first record that is form the model:
|
||||
// Just get the first record that is from the model:
|
||||
auto slindex_it =
|
||||
po.closest_slice_record(po.m_slice_index, float(bb3d.min(Z)));
|
||||
|
||||
@ -879,7 +911,7 @@ void SLAPrint::process()
|
||||
|
||||
// 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) {
|
||||
if (is_zero_elevation(po.config())) {
|
||||
double gnd = po.m_supportdata->emesh.ground_level();
|
||||
auto & pts = po.m_supportdata->support_points;
|
||||
double tolerance = po.config().pad_enable.getBool()
|
||||
@ -1429,7 +1461,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<unsigned, decltype(lvlfn)>(0, lvlcnt, lvlfn);
|
||||
@ -1446,44 +1478,45 @@ void SLAPrint::process()
|
||||
using slaposFn = std::function<void(SLAPrintObject&)>;
|
||||
using slapsFn = std::function<void(void)>;
|
||||
|
||||
std::array<slaposFn, slaposCount> 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<slapsFn, slapsCount> print_program =
|
||||
{
|
||||
merge_slices_and_eval_stats,
|
||||
rasterize
|
||||
// We want to first process all objects...
|
||||
std::vector<SLAPrintObjectStep> level1_obj_steps = {
|
||||
slaposObjectSlice, slaposSupportPoints, slaposSupportTree, slaposBasePool
|
||||
};
|
||||
|
||||
// and then slice all supports to allow preview to be displayed ASAP
|
||||
std::vector<SLAPrintObjectStep> 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<SLAPrintObjectStep> 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<double, slaposCount + slapsCount> step_times {};
|
||||
|
||||
auto apply_steps_on_objects =
|
||||
[this, &st, ostepd, &pobj_program, &step_times, &bench]
|
||||
(const std::vector<SLAPrintObjectStep> &steps)
|
||||
{
|
||||
unsigned incr = 0;
|
||||
for (SLAPrintObject *po : m_objects) {
|
||||
|
||||
BOOST_LOG_TRIVIAL(info)
|
||||
<< "Slicing object " << po->model_object()->name;
|
||||
|
||||
for (int s = int(step_ranges[idx_range]);
|
||||
s < int(step_ranges[idx_range + 1]);
|
||||
++s) {
|
||||
auto currentstep = static_cast<SLAPrintObjectStep>(s);
|
||||
for (SLAPrintObjectStep step : steps) {
|
||||
|
||||
// Cancellation checking. Each step will check for
|
||||
// cancellation on its own and return earlier gracefully.
|
||||
@ -1493,39 +1526,38 @@ void SLAPrint::process()
|
||||
|
||||
st += incr * ostepd;
|
||||
|
||||
if (po->m_stepmask[currentstep]
|
||||
&& po->set_started(currentstep)) {
|
||||
m_report_status(*this,
|
||||
st,
|
||||
OBJ_STEP_LABELS(currentstep));
|
||||
pobj_program[currentstep](*po);
|
||||
if (po->m_stepmask[step] && po->set_started(step)) {
|
||||
m_report_status(*this, st, OBJ_STEP_LABELS(step));
|
||||
bench.start();
|
||||
pobj_program[step](*po);
|
||||
bench.stop();
|
||||
step_times[step] += bench.getElapsedSec();
|
||||
throw_if_canceled();
|
||||
po->set_done(currentstep);
|
||||
po->set_done(step);
|
||||
}
|
||||
|
||||
incr = OBJ_STEP_LEVELS[currentstep];
|
||||
incr = OBJ_STEP_LEVELS[step];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::array<SLAPrintStep, slapsCount> printsteps = {
|
||||
slapsMergeSlicesAndEval, slapsRasterize
|
||||
};
|
||||
|
||||
apply_steps_on_objects(level1_obj_steps);
|
||||
apply_steps_on_objects(level2_obj_steps);
|
||||
|
||||
// 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 : print_steps) {
|
||||
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 +1567,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<t_config_option_key> &opt_keys, bool &invalidate_all_model_objects)
|
||||
@ -1553,7 +1600,11 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt
|
||||
// Cache the plenty of parameters, which influence the final rasterization only,
|
||||
// or they are only notes not influencing the rasterization step.
|
||||
static std::unordered_set<std::string> steps_rasterize = {
|
||||
"min_exposure_time",
|
||||
"max_exposure_time",
|
||||
"exposure_time",
|
||||
"min_initial_exposure_time",
|
||||
"max_initial_exposure_time",
|
||||
"initial_exposure_time",
|
||||
"display_width",
|
||||
"display_height",
|
||||
@ -1647,6 +1698,7 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|
||||
|| opt_key == "pad_wall_thickness"
|
||||
|| opt_key == "supports_enable"
|
||||
|| opt_key == "support_object_elevation"
|
||||
|| opt_key == "pad_zero_elevation"
|
||||
|| opt_key == "slice_closing_radius") {
|
||||
steps.emplace_back(slaposObjectSlice);
|
||||
} else if (
|
||||
@ -1719,7 +1771,10 @@ bool SLAPrintObject::invalidate_all_steps()
|
||||
}
|
||||
|
||||
double SLAPrintObject::get_elevation() const {
|
||||
if (is_zero_elevation(m_config)) return 0.;
|
||||
|
||||
bool en = m_config.supports_enable.getBool();
|
||||
|
||||
double ret = en ? m_config.support_object_elevation.getFloat() : 0.;
|
||||
|
||||
if(m_config.pad_enable.getBool()) {
|
||||
@ -1736,6 +1791,8 @@ double SLAPrintObject::get_elevation() const {
|
||||
|
||||
double SLAPrintObject::get_current_elevation() const
|
||||
{
|
||||
if (is_zero_elevation(m_config)) return 0.;
|
||||
|
||||
bool has_supports = is_step_done(slaposSupportTree);
|
||||
bool has_pad = is_step_done(slaposBasePool);
|
||||
|
||||
|
7
src/libslic3r/Semver.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
#include "libslic3r.h"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
Semver SEMVER { SLIC3R_VERSION };
|
||||
|
||||
}
|
@ -18,8 +18,9 @@ extern void trace(unsigned int level, const char *message);
|
||||
// Format memory allocated, separate thousands by comma.
|
||||
extern std::string format_memsize_MB(size_t n);
|
||||
// Return string to be added to the boost::log output to inform about the current process memory allocation.
|
||||
// The string is non-empty only if the loglevel >= info (3).
|
||||
extern std::string log_memory_info();
|
||||
// The string is non-empty if the loglevel >= info (3) or ignore_loglevel==true.
|
||||
// Latter is used to get the memory info from SysInfoDialog.
|
||||
extern std::string log_memory_info(bool ignore_loglevel = false);
|
||||
extern void disable_multi_threading();
|
||||
// Returns the size of physical memory (RAM) in bytes.
|
||||
extern size_t total_physical_memory();
|
||||
@ -60,7 +61,7 @@ extern std::string normalize_utf8_nfc(const char *src);
|
||||
// Safely rename a file even if the target exists.
|
||||
// On Windows, the file explorer (or anti-virus or whatever else) often locks the file
|
||||
// for a short while, so the file may not be movable. Retry while we see recoverable errors.
|
||||
extern int rename_file(const std::string &from, const std::string &to);
|
||||
extern std::error_code rename_file(const std::string &from, const std::string &to);
|
||||
|
||||
// Copy a file, adjust the access attributes, so that the target is writable.
|
||||
extern int copy_file(const std::string &from, const std::string &to);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <cmath>
|
||||
|
||||
#include "Technologies.hpp"
|
||||
#include "Semver.hpp"
|
||||
|
||||
typedef int64_t coord_t;
|
||||
typedef double coordf_t;
|
||||
@ -91,6 +92,8 @@ inline std::string debug_out_path(const char *name, ...)
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
extern Semver SEMVER;
|
||||
|
||||
template<typename T, typename Q>
|
||||
inline T unscale(Q v) { return T(v) * T(SCALING_FACTOR); }
|
||||
|
||||
|
@ -13,9 +13,13 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/resource.h>
|
||||
#ifdef BSD
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
#include <mach/mach.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <boost/log/core.hpp>
|
||||
@ -29,7 +33,6 @@
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/nowide/integration/filesystem.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
|
||||
@ -89,10 +92,10 @@ unsigned get_logging_level()
|
||||
}
|
||||
|
||||
// Force set_logging_level(<=error) after loading of the DLL.
|
||||
// Switch boost::filesystem to utf8.
|
||||
// This is currently only needed if libslic3r is loaded as a shared library into Perl interpreter
|
||||
// to perform unit and integration tests.
|
||||
static struct RunOnInit {
|
||||
RunOnInit() {
|
||||
boost::nowide::nowide_filesystem();
|
||||
set_logging_level(1);
|
||||
}
|
||||
} g_RunOnInit;
|
||||
@ -170,67 +173,247 @@ const std::string& data_dir()
|
||||
return g_data_dir;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// The following helpers are borrowed from the LLVM project https://github.com/llvm
|
||||
namespace WindowsSupport
|
||||
{
|
||||
template <typename HandleTraits>
|
||||
class ScopedHandle {
|
||||
typedef typename HandleTraits::handle_type handle_type;
|
||||
handle_type Handle;
|
||||
ScopedHandle(const ScopedHandle &other) = delete;
|
||||
void operator=(const ScopedHandle &other) = delete;
|
||||
public:
|
||||
ScopedHandle() : Handle(HandleTraits::GetInvalid()) {}
|
||||
explicit ScopedHandle(handle_type h) : Handle(h) {}
|
||||
~ScopedHandle() { if (HandleTraits::IsValid(Handle)) HandleTraits::Close(Handle); }
|
||||
handle_type take() {
|
||||
handle_type t = Handle;
|
||||
Handle = HandleTraits::GetInvalid();
|
||||
return t;
|
||||
}
|
||||
ScopedHandle &operator=(handle_type h) {
|
||||
if (HandleTraits::IsValid(Handle))
|
||||
HandleTraits::Close(Handle);
|
||||
Handle = h;
|
||||
return *this;
|
||||
}
|
||||
// True if Handle is valid.
|
||||
explicit operator bool() const { return HandleTraits::IsValid(Handle) ? true : false; }
|
||||
operator handle_type() const { return Handle; }
|
||||
};
|
||||
|
||||
struct CommonHandleTraits {
|
||||
typedef HANDLE handle_type;
|
||||
static handle_type GetInvalid() { return INVALID_HANDLE_VALUE; }
|
||||
static void Close(handle_type h) { ::CloseHandle(h); }
|
||||
static bool IsValid(handle_type h) { return h != GetInvalid(); }
|
||||
};
|
||||
|
||||
typedef ScopedHandle<CommonHandleTraits> ScopedFileHandle;
|
||||
|
||||
std::error_code map_windows_error(unsigned windows_error_code)
|
||||
{
|
||||
#define MAP_ERR_TO_COND(x, y) case x: return std::make_error_code(std::errc::y)
|
||||
switch (windows_error_code) {
|
||||
MAP_ERR_TO_COND(ERROR_ACCESS_DENIED, permission_denied);
|
||||
MAP_ERR_TO_COND(ERROR_ALREADY_EXISTS, file_exists);
|
||||
MAP_ERR_TO_COND(ERROR_BAD_UNIT, no_such_device);
|
||||
MAP_ERR_TO_COND(ERROR_BUFFER_OVERFLOW, filename_too_long);
|
||||
MAP_ERR_TO_COND(ERROR_BUSY, device_or_resource_busy);
|
||||
MAP_ERR_TO_COND(ERROR_BUSY_DRIVE, device_or_resource_busy);
|
||||
MAP_ERR_TO_COND(ERROR_CANNOT_MAKE, permission_denied);
|
||||
MAP_ERR_TO_COND(ERROR_CANTOPEN, io_error);
|
||||
MAP_ERR_TO_COND(ERROR_CANTREAD, io_error);
|
||||
MAP_ERR_TO_COND(ERROR_CANTWRITE, io_error);
|
||||
MAP_ERR_TO_COND(ERROR_CURRENT_DIRECTORY, permission_denied);
|
||||
MAP_ERR_TO_COND(ERROR_DEV_NOT_EXIST, no_such_device);
|
||||
MAP_ERR_TO_COND(ERROR_DEVICE_IN_USE, device_or_resource_busy);
|
||||
MAP_ERR_TO_COND(ERROR_DIR_NOT_EMPTY, directory_not_empty);
|
||||
MAP_ERR_TO_COND(ERROR_DIRECTORY, invalid_argument);
|
||||
MAP_ERR_TO_COND(ERROR_DISK_FULL, no_space_on_device);
|
||||
MAP_ERR_TO_COND(ERROR_FILE_EXISTS, file_exists);
|
||||
MAP_ERR_TO_COND(ERROR_FILE_NOT_FOUND, no_such_file_or_directory);
|
||||
MAP_ERR_TO_COND(ERROR_HANDLE_DISK_FULL, no_space_on_device);
|
||||
MAP_ERR_TO_COND(ERROR_INVALID_ACCESS, permission_denied);
|
||||
MAP_ERR_TO_COND(ERROR_INVALID_DRIVE, no_such_device);
|
||||
MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION, function_not_supported);
|
||||
MAP_ERR_TO_COND(ERROR_INVALID_HANDLE, invalid_argument);
|
||||
MAP_ERR_TO_COND(ERROR_INVALID_NAME, invalid_argument);
|
||||
MAP_ERR_TO_COND(ERROR_LOCK_VIOLATION, no_lock_available);
|
||||
MAP_ERR_TO_COND(ERROR_LOCKED, no_lock_available);
|
||||
MAP_ERR_TO_COND(ERROR_NEGATIVE_SEEK, invalid_argument);
|
||||
MAP_ERR_TO_COND(ERROR_NOACCESS, permission_denied);
|
||||
MAP_ERR_TO_COND(ERROR_NOT_ENOUGH_MEMORY, not_enough_memory);
|
||||
MAP_ERR_TO_COND(ERROR_NOT_READY, resource_unavailable_try_again);
|
||||
MAP_ERR_TO_COND(ERROR_OPEN_FAILED, io_error);
|
||||
MAP_ERR_TO_COND(ERROR_OPEN_FILES, device_or_resource_busy);
|
||||
MAP_ERR_TO_COND(ERROR_OUTOFMEMORY, not_enough_memory);
|
||||
MAP_ERR_TO_COND(ERROR_PATH_NOT_FOUND, no_such_file_or_directory);
|
||||
MAP_ERR_TO_COND(ERROR_BAD_NETPATH, no_such_file_or_directory);
|
||||
MAP_ERR_TO_COND(ERROR_READ_FAULT, io_error);
|
||||
MAP_ERR_TO_COND(ERROR_RETRY, resource_unavailable_try_again);
|
||||
MAP_ERR_TO_COND(ERROR_SEEK, io_error);
|
||||
MAP_ERR_TO_COND(ERROR_SHARING_VIOLATION, permission_denied);
|
||||
MAP_ERR_TO_COND(ERROR_TOO_MANY_OPEN_FILES, too_many_files_open);
|
||||
MAP_ERR_TO_COND(ERROR_WRITE_FAULT, io_error);
|
||||
MAP_ERR_TO_COND(ERROR_WRITE_PROTECT, permission_denied);
|
||||
MAP_ERR_TO_COND(WSAEACCES, permission_denied);
|
||||
MAP_ERR_TO_COND(WSAEBADF, bad_file_descriptor);
|
||||
MAP_ERR_TO_COND(WSAEFAULT, bad_address);
|
||||
MAP_ERR_TO_COND(WSAEINTR, interrupted);
|
||||
MAP_ERR_TO_COND(WSAEINVAL, invalid_argument);
|
||||
MAP_ERR_TO_COND(WSAEMFILE, too_many_files_open);
|
||||
MAP_ERR_TO_COND(WSAENAMETOOLONG, filename_too_long);
|
||||
default:
|
||||
return std::error_code(windows_error_code, std::system_category());
|
||||
}
|
||||
#undef MAP_ERR_TO_COND
|
||||
}
|
||||
|
||||
static std::error_code rename_internal(HANDLE from_handle, const std::wstring &wide_to, bool replace_if_exists)
|
||||
{
|
||||
std::vector<char> rename_info_buf(sizeof(FILE_RENAME_INFO) - sizeof(wchar_t) + (wide_to.size() * sizeof(wchar_t)));
|
||||
FILE_RENAME_INFO &rename_info = *reinterpret_cast<FILE_RENAME_INFO*>(rename_info_buf.data());
|
||||
rename_info.ReplaceIfExists = replace_if_exists;
|
||||
rename_info.RootDirectory = 0;
|
||||
rename_info.FileNameLength = DWORD(wide_to.size() * sizeof(wchar_t));
|
||||
std::copy(wide_to.begin(), wide_to.end(), &rename_info.FileName[0]);
|
||||
|
||||
::SetLastError(ERROR_SUCCESS);
|
||||
if (! ::SetFileInformationByHandle(from_handle, FileRenameInfo, &rename_info, (DWORD)rename_info_buf.size())) {
|
||||
unsigned Error = GetLastError();
|
||||
if (Error == ERROR_SUCCESS)
|
||||
Error = ERROR_CALL_NOT_IMPLEMENTED; // Wine doesn't always set error code.
|
||||
return map_windows_error(Error);
|
||||
}
|
||||
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
static std::error_code real_path_from_handle(HANDLE H, std::wstring &buffer)
|
||||
{
|
||||
buffer.resize(MAX_PATH + 1);
|
||||
DWORD CountChars = ::GetFinalPathNameByHandleW(H, (LPWSTR)buffer.data(), (DWORD)buffer.size() - 1, FILE_NAME_NORMALIZED);
|
||||
if (CountChars > buffer.size()) {
|
||||
// The buffer wasn't big enough, try again. In this case the return value *does* indicate the size of the null terminator.
|
||||
buffer.resize((size_t)CountChars);
|
||||
CountChars = ::GetFinalPathNameByHandleW(H, (LPWSTR)buffer.data(), (DWORD)buffer.size() - 1, FILE_NAME_NORMALIZED);
|
||||
}
|
||||
if (CountChars == 0)
|
||||
return map_windows_error(GetLastError());
|
||||
buffer.resize(CountChars);
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
std::error_code rename(const std::string &from, const std::string &to)
|
||||
{
|
||||
// Convert to utf-16.
|
||||
std::wstring wide_from = boost::nowide::widen(from);
|
||||
std::wstring wide_to = boost::nowide::widen(to);
|
||||
|
||||
ScopedFileHandle from_handle;
|
||||
// Retry this a few times to defeat badly behaved file system scanners.
|
||||
for (unsigned retry = 0; retry != 200; ++ retry) {
|
||||
if (retry != 0)
|
||||
::Sleep(10);
|
||||
from_handle = ::CreateFileW((LPWSTR)wide_from.data(), GENERIC_READ | DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (from_handle)
|
||||
break;
|
||||
}
|
||||
if (! from_handle)
|
||||
return map_windows_error(GetLastError());
|
||||
|
||||
// We normally expect this loop to succeed after a few iterations. If it
|
||||
// requires more than 200 tries, it's more likely that the failures are due to
|
||||
// a true error, so stop trying.
|
||||
for (unsigned retry = 0; retry != 200; ++ retry) {
|
||||
auto errcode = rename_internal(from_handle, wide_to, true);
|
||||
|
||||
if (errcode == std::error_code(ERROR_CALL_NOT_IMPLEMENTED, std::system_category())) {
|
||||
// Wine doesn't support SetFileInformationByHandle in rename_internal.
|
||||
// Fall back to MoveFileEx.
|
||||
if (std::error_code errcode2 = real_path_from_handle(from_handle, wide_from))
|
||||
return errcode2;
|
||||
if (::MoveFileExW((LPCWSTR)wide_from.data(), (LPCWSTR)wide_to.data(), MOVEFILE_REPLACE_EXISTING))
|
||||
return std::error_code();
|
||||
return map_windows_error(GetLastError());
|
||||
}
|
||||
|
||||
if (! errcode || errcode != std::errc::permission_denied)
|
||||
return errcode;
|
||||
|
||||
// The destination file probably exists and is currently open in another
|
||||
// process, either because the file was opened without FILE_SHARE_DELETE or
|
||||
// it is mapped into memory (e.g. using MemoryBuffer). Rename it in order to
|
||||
// move it out of the way of the source file. Use FILE_FLAG_DELETE_ON_CLOSE
|
||||
// to arrange for the destination file to be deleted when the other process
|
||||
// closes it.
|
||||
ScopedFileHandle to_handle(::CreateFileW((LPCWSTR)wide_to.data(), GENERIC_READ | DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL));
|
||||
if (! to_handle) {
|
||||
auto errcode = map_windows_error(GetLastError());
|
||||
// Another process might have raced with us and moved the existing file
|
||||
// out of the way before we had a chance to open it. If that happens, try
|
||||
// to rename the source file again.
|
||||
if (errcode == std::errc::no_such_file_or_directory)
|
||||
continue;
|
||||
return errcode;
|
||||
}
|
||||
|
||||
BY_HANDLE_FILE_INFORMATION FI;
|
||||
if (! ::GetFileInformationByHandle(to_handle, &FI))
|
||||
return map_windows_error(GetLastError());
|
||||
|
||||
// Try to find a unique new name for the destination file.
|
||||
for (unsigned unique_id = 0; unique_id != 200; ++ unique_id) {
|
||||
std::wstring tmp_filename = wide_to + L".tmp" + std::to_wstring(unique_id);
|
||||
std::error_code errcode = rename_internal(to_handle, tmp_filename, false);
|
||||
if (errcode) {
|
||||
if (errcode == std::make_error_code(std::errc::file_exists) || errcode == std::make_error_code(std::errc::permission_denied)) {
|
||||
// Again, another process might have raced with us and moved the file
|
||||
// before we could move it. Check whether this is the case, as it
|
||||
// might have caused the permission denied error. If that was the
|
||||
// case, we don't need to move it ourselves.
|
||||
ScopedFileHandle to_handle2(::CreateFileW((LPCWSTR)wide_to.data(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
|
||||
if (! to_handle2) {
|
||||
auto errcode = map_windows_error(GetLastError());
|
||||
if (errcode == std::errc::no_such_file_or_directory)
|
||||
break;
|
||||
return errcode;
|
||||
}
|
||||
BY_HANDLE_FILE_INFORMATION FI2;
|
||||
if (! ::GetFileInformationByHandle(to_handle2, &FI2))
|
||||
return map_windows_error(GetLastError());
|
||||
if (FI.nFileIndexHigh != FI2.nFileIndexHigh || FI.nFileIndexLow != FI2.nFileIndexLow || FI.dwVolumeSerialNumber != FI2.dwVolumeSerialNumber)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
return errcode;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Okay, the old destination file has probably been moved out of the way at
|
||||
// this point, so try to rename the source file again. Still, another
|
||||
// process might have raced with us to create and open the destination
|
||||
// file, so we need to keep doing this until we succeed.
|
||||
}
|
||||
|
||||
// The most likely root cause.
|
||||
return std::make_error_code(std::errc::permission_denied);
|
||||
}
|
||||
} // namespace WindowsSupport
|
||||
#endif /* _WIN32 */
|
||||
|
||||
// borrowed from LVVM lib/Support/Windows/Path.inc
|
||||
int rename_file(const std::string &from, const std::string &to)
|
||||
std::error_code rename_file(const std::string &from, const std::string &to)
|
||||
{
|
||||
int ec = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// Convert to utf-16.
|
||||
std::wstring wide_from = boost::nowide::widen(from);
|
||||
std::wstring wide_to = boost::nowide::widen(to);
|
||||
|
||||
// Retry while we see recoverable errors.
|
||||
// System scanners (eg. indexer) might open the source file when it is written
|
||||
// and closed.
|
||||
bool TryReplace = true;
|
||||
|
||||
// This loop may take more than 2000 x 1ms to finish.
|
||||
for (int i = 0; i < 2000; ++ i) {
|
||||
if (i > 0)
|
||||
// Sleep 1ms
|
||||
::Sleep(1);
|
||||
if (TryReplace) {
|
||||
// Try ReplaceFile first, as it is able to associate a new data stream
|
||||
// with the destination even if the destination file is currently open.
|
||||
if (::ReplaceFileW(wide_to.data(), wide_from.data(), NULL, 0, NULL, NULL))
|
||||
return 0;
|
||||
DWORD ReplaceError = ::GetLastError();
|
||||
ec = -1; // ReplaceError
|
||||
// If ReplaceFileW returned ERROR_UNABLE_TO_MOVE_REPLACEMENT or
|
||||
// ERROR_UNABLE_TO_MOVE_REPLACEMENT_2, retry but only use MoveFileExW().
|
||||
if (ReplaceError == ERROR_UNABLE_TO_MOVE_REPLACEMENT ||
|
||||
ReplaceError == ERROR_UNABLE_TO_MOVE_REPLACEMENT_2) {
|
||||
TryReplace = false;
|
||||
continue;
|
||||
}
|
||||
// If ReplaceFileW returned ERROR_UNABLE_TO_REMOVE_REPLACED, retry
|
||||
// using ReplaceFileW().
|
||||
if (ReplaceError == ERROR_UNABLE_TO_REMOVE_REPLACED)
|
||||
continue;
|
||||
// We get ERROR_FILE_NOT_FOUND if the destination file is missing.
|
||||
// MoveFileEx can handle this case.
|
||||
if (ReplaceError != ERROR_ACCESS_DENIED && ReplaceError != ERROR_FILE_NOT_FOUND && ReplaceError != ERROR_SHARING_VIOLATION)
|
||||
break;
|
||||
}
|
||||
if (::MoveFileExW(wide_from.c_str(), wide_to.c_str(), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))
|
||||
return 0;
|
||||
DWORD MoveError = ::GetLastError();
|
||||
ec = -1; // MoveError
|
||||
if (MoveError != ERROR_ACCESS_DENIED && MoveError != ERROR_SHARING_VIOLATION)
|
||||
break;
|
||||
}
|
||||
|
||||
return WindowsSupport::rename(from, to);
|
||||
#else
|
||||
|
||||
boost::nowide::remove(to.c_str());
|
||||
ec = boost::nowide::rename(from.c_str(), to.c_str());
|
||||
|
||||
return std::make_error_code(static_cast<std::errc>(boost::nowide::rename(from.c_str(), to.c_str())));
|
||||
#endif
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
int copy_file(const std::string &from, const std::string &to)
|
||||
@ -431,47 +614,82 @@ std::string format_memsize_MB(size_t n)
|
||||
return out + "MB";
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#ifndef PROCESS_MEMORY_COUNTERS_EX
|
||||
// MingW32 doesn't have this struct in psapi.h
|
||||
typedef struct _PROCESS_MEMORY_COUNTERS_EX {
|
||||
DWORD cb;
|
||||
DWORD PageFaultCount;
|
||||
SIZE_T PeakWorkingSetSize;
|
||||
SIZE_T WorkingSetSize;
|
||||
SIZE_T QuotaPeakPagedPoolUsage;
|
||||
SIZE_T QuotaPagedPoolUsage;
|
||||
SIZE_T QuotaPeakNonPagedPoolUsage;
|
||||
SIZE_T QuotaNonPagedPoolUsage;
|
||||
SIZE_T PagefileUsage;
|
||||
SIZE_T PeakPagefileUsage;
|
||||
SIZE_T PrivateUsage;
|
||||
} PROCESS_MEMORY_COUNTERS_EX, *PPROCESS_MEMORY_COUNTERS_EX;
|
||||
#endif /* PROCESS_MEMORY_COUNTERS_EX */
|
||||
|
||||
std::string log_memory_info()
|
||||
// Returns platform-specific string to be used as log output or parsed in SysInfoDialog.
|
||||
// The latter parses the string with (semi)colons as separators, it should look about as
|
||||
// "desc1: value1; desc2: value2" or similar (spaces should not matter).
|
||||
std::string log_memory_info(bool ignore_loglevel)
|
||||
{
|
||||
std::string out;
|
||||
if (logSeverity <= boost::log::trivial::info) {
|
||||
if (ignore_loglevel || logSeverity <= boost::log::trivial::info) {
|
||||
#ifdef WIN32
|
||||
#ifndef PROCESS_MEMORY_COUNTERS_EX
|
||||
// MingW32 doesn't have this struct in psapi.h
|
||||
typedef struct _PROCESS_MEMORY_COUNTERS_EX {
|
||||
DWORD cb;
|
||||
DWORD PageFaultCount;
|
||||
SIZE_T PeakWorkingSetSize;
|
||||
SIZE_T WorkingSetSize;
|
||||
SIZE_T QuotaPeakPagedPoolUsage;
|
||||
SIZE_T QuotaPagedPoolUsage;
|
||||
SIZE_T QuotaPeakNonPagedPoolUsage;
|
||||
SIZE_T QuotaNonPagedPoolUsage;
|
||||
SIZE_T PagefileUsage;
|
||||
SIZE_T PeakPagefileUsage;
|
||||
SIZE_T PrivateUsage;
|
||||
} PROCESS_MEMORY_COUNTERS_EX, *PPROCESS_MEMORY_COUNTERS_EX;
|
||||
#endif /* PROCESS_MEMORY_COUNTERS_EX */
|
||||
|
||||
|
||||
HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ::GetCurrentProcessId());
|
||||
if (hProcess != nullptr) {
|
||||
PROCESS_MEMORY_COUNTERS_EX pmc;
|
||||
if (GetProcessMemoryInfo(hProcess, (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc)))
|
||||
out = " WorkingSet: " + format_memsize_MB(pmc.WorkingSetSize) + " PrivateBytes: " + format_memsize_MB(pmc.PrivateUsage) + " Pagefile(peak): " + format_memsize_MB(pmc.PagefileUsage) + "(" + format_memsize_MB(pmc.PeakPagefileUsage) + ")";
|
||||
out = " WorkingSet: " + format_memsize_MB(pmc.WorkingSetSize) + "; PrivateBytes: " + format_memsize_MB(pmc.PrivateUsage) + "; Pagefile(peak): " + format_memsize_MB(pmc.PagefileUsage) + "(" + format_memsize_MB(pmc.PeakPagefileUsage) + ")";
|
||||
else
|
||||
out += " Used memory: N/A";
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
#elif defined(__linux__) or defined(__APPLE__)
|
||||
// Get current memory usage.
|
||||
#ifdef __APPLE__
|
||||
struct mach_task_basic_info info;
|
||||
mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
|
||||
out += " Resident memory: ";
|
||||
if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount ) == KERN_SUCCESS )
|
||||
out += format_memsize_MB((size_t)info.resident_size);
|
||||
else
|
||||
out += "N/A";
|
||||
#else // i.e. __linux__
|
||||
size_t tSize = 0, resident = 0, share = 0;
|
||||
std::ifstream buffer("/proc/self/statm");
|
||||
if (buffer && (buffer >> tSize >> resident >> share)) {
|
||||
size_t page_size = (size_t)sysconf(_SC_PAGE_SIZE); // in case x86-64 is configured to use 2MB pages
|
||||
size_t rss = resident * page_size;
|
||||
out += " Resident memory: " + format_memsize_MB(rss);
|
||||
out += "; Shared memory: " + format_memsize_MB(share * page_size);
|
||||
out += "; Private memory: " + format_memsize_MB(rss - share * page_size);
|
||||
}
|
||||
else
|
||||
out += " Used memory: N/A";
|
||||
#endif
|
||||
// Now get peak memory usage.
|
||||
out += "; Peak memory usage: ";
|
||||
rusage memory_info;
|
||||
if (getrusage(RUSAGE_SELF, &memory_info) == 0)
|
||||
{
|
||||
size_t peak_mem_usage = (size_t)memory_info.ru_maxrss;
|
||||
#ifdef __linux__
|
||||
peak_mem_usage *= 1024;// getrusage returns the value in kB on linux
|
||||
#endif
|
||||
out += format_memsize_MB(peak_mem_usage);
|
||||
}
|
||||
else
|
||||
out += "N/A";
|
||||
#endif
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
#else
|
||||
std::string log_memory_info()
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Returns the size of physical memory (RAM) in bytes.
|
||||
// http://nadeausoftware.com/articles/2012/09/c_c_tip_how_get_physical_memory_size_system
|
||||
size_t total_physical_memory()
|
||||
|
@ -5,3 +5,5 @@ add_library(semver STATIC
|
||||
semver.c
|
||||
semver.h
|
||||
)
|
||||
|
||||
encoding_check(semver)
|
||||
|
@ -87,6 +87,8 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/LambdaObjectDialog.hpp
|
||||
GUI/Tab.cpp
|
||||
GUI/Tab.hpp
|
||||
GUI/ConfigManipulation.cpp
|
||||
GUI/ConfigManipulation.hpp
|
||||
GUI/Field.cpp
|
||||
GUI/Field.hpp
|
||||
GUI/OptionsGroup.cpp
|
||||
@ -163,6 +165,8 @@ endif ()
|
||||
|
||||
add_library(libslic3r_gui STATIC ${SLIC3R_GUI_SOURCES})
|
||||
|
||||
encoding_check(libslic3r_gui)
|
||||
|
||||
target_link_libraries(libslic3r_gui libslic3r avrdude cereal imgui ${GLEW_LIBRARIES})
|
||||
if (SLIC3R_PCH AND NOT SLIC3R_SYNTAXONLY)
|
||||
add_precompiled_header(libslic3r_gui pchheader.hpp FORCEINCLUDE)
|
||||
|
@ -366,7 +366,7 @@ const Snapshot& SnapshotDB::take_snapshot(const AppConfig &app_config, Snapshot:
|
||||
// Snapshot header.
|
||||
snapshot.time_captured = Slic3r::Utils::get_current_time_utc();
|
||||
snapshot.id = Slic3r::Utils::format_time_ISO8601Z(snapshot.time_captured);
|
||||
snapshot.slic3r_version_captured = *Semver::parse(SLIC3R_VERSION); // XXX: have Semver Slic3r version
|
||||
snapshot.slic3r_version_captured = Slic3r::SEMVER;
|
||||
snapshot.comment = comment;
|
||||
snapshot.reason = reason;
|
||||
// Active presets at the time of the snapshot.
|
||||
|
@ -8,8 +8,8 @@
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "libslic3r/Semver.hpp"
|
||||
#include "Version.hpp"
|
||||
#include "../Utils/Semver.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
@ -15,7 +15,6 @@ namespace Slic3r {
|
||||
namespace GUI {
|
||||
namespace Config {
|
||||
|
||||
static const Semver s_current_slic3r_semver(SLIC3R_VERSION);
|
||||
|
||||
// Optimized lexicographic compare of two pre-release versions, ignoring the numeric suffix.
|
||||
static int compare_prerelease(const char *p1, const char *p2)
|
||||
@ -64,7 +63,7 @@ bool Version::is_slic3r_supported(const Semver &slic3r_version) const
|
||||
|
||||
bool Version::is_current_slic3r_supported() const
|
||||
{
|
||||
return this->is_slic3r_supported(s_current_slic3r_semver);
|
||||
return this->is_slic3r_supported(Slic3r::SEMVER);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "libslic3r/FileParserError.hpp"
|
||||
#include "../Utils/Semver.hpp"
|
||||
#include "libslic3r/Semver.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
@ -609,10 +609,12 @@ void Bed3D::render_default(bool bottom) const
|
||||
if (!has_model && !bottom)
|
||||
{
|
||||
// draw background
|
||||
glsafe(::glDepthMask(GL_FALSE));
|
||||
glsafe(::glColor4f(0.35f, 0.35f, 0.35f, 0.4f));
|
||||
glsafe(::glNormal3d(0.0f, 0.0f, 1.0f));
|
||||
glsafe(::glVertexPointer(3, GL_FLOAT, m_triangles.get_vertex_data_size(), (GLvoid*)m_triangles.get_vertices_data()));
|
||||
glsafe(::glDrawArrays(GL_TRIANGLES, 0, (GLsizei)triangles_vcount));
|
||||
glsafe(::glDepthMask(GL_TRUE));
|
||||
}
|
||||
|
||||
// draw grid
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "libslic3r/GCode/Analyzer.hpp"
|
||||
#include "slic3r/GUI/PresetBundle.hpp"
|
||||
#include "libslic3r/Format/STL.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -24,6 +25,8 @@
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/spin_mutex.h>
|
||||
|
||||
@ -74,15 +77,19 @@ void GLIndexedVertexArray::load_mesh_full_shading(const TriangleMesh &mesh)
|
||||
}
|
||||
}
|
||||
|
||||
void GLIndexedVertexArray::finalize_geometry() const
|
||||
void GLIndexedVertexArray::finalize_geometry(bool opengl_initialized)
|
||||
{
|
||||
assert(this->vertices_and_normals_interleaved_VBO_id == 0);
|
||||
assert(this->triangle_indices_VBO_id == 0);
|
||||
assert(this->quad_indices_VBO_id == 0);
|
||||
|
||||
this->shrink_to_fit();
|
||||
if (! opengl_initialized) {
|
||||
// Shrink the data vectors to conserve memory in case the data cannot be transfered to the OpenGL driver yet.
|
||||
this->shrink_to_fit();
|
||||
return;
|
||||
}
|
||||
|
||||
if (! empty()) {
|
||||
if (! this->vertices_and_normals_interleaved.empty()) {
|
||||
glsafe(::glGenBuffers(1, &this->vertices_and_normals_interleaved_VBO_id));
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
|
||||
glsafe(::glBufferData(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved.size() * 4, this->vertices_and_normals_interleaved.data(), GL_STATIC_DRAW));
|
||||
@ -124,13 +131,8 @@ void GLIndexedVertexArray::release_geometry()
|
||||
|
||||
void GLIndexedVertexArray::render() const
|
||||
{
|
||||
if (this->vertices_and_normals_interleaved_VBO_id == 0)
|
||||
{
|
||||
// sends data to gpu, if not done yet
|
||||
finalize_geometry();
|
||||
if (this->vertices_and_normals_interleaved_VBO_id == 0)
|
||||
return;
|
||||
}
|
||||
assert(this->vertices_and_normals_interleaved_VBO_id != 0);
|
||||
assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0);
|
||||
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
|
||||
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
|
||||
@ -161,13 +163,8 @@ void GLIndexedVertexArray::render(
|
||||
const std::pair<size_t, size_t>& tverts_range,
|
||||
const std::pair<size_t, size_t>& qverts_range) const
|
||||
{
|
||||
if (this->vertices_and_normals_interleaved_VBO_id == 0)
|
||||
{
|
||||
// sends data to gpu, if not done yet
|
||||
finalize_geometry();
|
||||
if (this->vertices_and_normals_interleaved_VBO_id == 0)
|
||||
return;
|
||||
}
|
||||
assert(this->vertices_and_normals_interleaved_VBO_id != 0);
|
||||
assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0);
|
||||
|
||||
// Render using the Vertex Buffer Objects.
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
|
||||
@ -218,6 +215,7 @@ GLVolume::GLVolume(float r, float g, float b, float a)
|
||||
, extruder_id(0)
|
||||
, selected(false)
|
||||
, disabled(false)
|
||||
, printable(true)
|
||||
, is_active(true)
|
||||
, zoom_to_volumes(true)
|
||||
, shader_outside_printer_detection_enabled(false)
|
||||
@ -275,6 +273,13 @@ void GLVolume::set_render_color()
|
||||
set_render_color(color, 4);
|
||||
}
|
||||
|
||||
if (!printable)
|
||||
{
|
||||
render_color[0] /= 4;
|
||||
render_color[1] /= 4;
|
||||
render_color[2] /= 4;
|
||||
}
|
||||
|
||||
if (force_transparent)
|
||||
render_color[3] = color[3];
|
||||
}
|
||||
@ -415,30 +420,32 @@ bool GLVolume::is_sla_support() const { return this->composite_id.volume_id == -
|
||||
bool GLVolume::is_sla_pad() const { return this->composite_id.volume_id == -int(slaposBasePool); }
|
||||
|
||||
std::vector<int> GLVolumeCollection::load_object(
|
||||
const ModelObject* model_object,
|
||||
const ModelObject *model_object,
|
||||
int obj_idx,
|
||||
const std::vector<int>& instance_idxs,
|
||||
const std::string& color_by)
|
||||
const std::vector<int> &instance_idxs,
|
||||
const std::string &color_by,
|
||||
bool opengl_initialized)
|
||||
{
|
||||
std::vector<int> volumes_idx;
|
||||
for (int volume_idx = 0; volume_idx < int(model_object->volumes.size()); ++volume_idx)
|
||||
for (int instance_idx : instance_idxs)
|
||||
volumes_idx.emplace_back(this->GLVolumeCollection::load_object_volume(model_object, obj_idx, volume_idx, instance_idx, color_by));
|
||||
volumes_idx.emplace_back(this->GLVolumeCollection::load_object_volume(model_object, obj_idx, volume_idx, instance_idx, color_by, opengl_initialized));
|
||||
return volumes_idx;
|
||||
}
|
||||
|
||||
int GLVolumeCollection::load_object_volume(
|
||||
const ModelObject* model_object,
|
||||
int obj_idx,
|
||||
int volume_idx,
|
||||
int instance_idx,
|
||||
const std::string& color_by)
|
||||
const ModelObject *model_object,
|
||||
int obj_idx,
|
||||
int volume_idx,
|
||||
int instance_idx,
|
||||
const std::string &color_by,
|
||||
bool opengl_initialized)
|
||||
{
|
||||
const ModelVolume* model_volume = model_object->volumes[volume_idx];
|
||||
const int extruder_id = model_volume->extruder_id();
|
||||
const ModelInstance* instance = model_object->instances[instance_idx];
|
||||
const TriangleMesh& mesh = model_volume->mesh();
|
||||
float color[4];
|
||||
const ModelVolume *model_volume = model_object->volumes[volume_idx];
|
||||
const int extruder_id = model_volume->extruder_id();
|
||||
const ModelInstance *instance = model_object->instances[instance_idx];
|
||||
const TriangleMesh &mesh = model_volume->mesh();
|
||||
float color[4];
|
||||
memcpy(color, GLVolume::MODEL_COLOR[((color_by == "volume") ? volume_idx : obj_idx) % 4], sizeof(float) * 3);
|
||||
/* if (model_volume->is_support_blocker()) {
|
||||
color[0] = 1.0f;
|
||||
@ -455,6 +462,7 @@ int GLVolumeCollection::load_object_volume(
|
||||
GLVolume& v = *this->volumes.back();
|
||||
v.set_color_from_model_volume(model_volume);
|
||||
v.indexed_vertex_array.load_mesh(mesh);
|
||||
v.indexed_vertex_array.finalize_geometry(opengl_initialized);
|
||||
v.composite_id = GLVolume::CompositeID(obj_idx, volume_idx, instance_idx);
|
||||
if (model_volume->is_model_part())
|
||||
{
|
||||
@ -475,13 +483,14 @@ int GLVolumeCollection::load_object_volume(
|
||||
// This function produces volumes for multiple instances in a single shot,
|
||||
// as some object specific mesh conversions may be expensive.
|
||||
void GLVolumeCollection::load_object_auxiliary(
|
||||
const SLAPrintObject* print_object,
|
||||
const SLAPrintObject *print_object,
|
||||
int obj_idx,
|
||||
// pairs of <instance_idx, print_instance_idx>
|
||||
const std::vector<std::pair<size_t, size_t>>& instances,
|
||||
SLAPrintObjectStep milestone,
|
||||
// Timestamp of the last change of the milestone
|
||||
size_t timestamp)
|
||||
size_t timestamp,
|
||||
bool opengl_initialized)
|
||||
{
|
||||
assert(print_object->is_step_done(milestone));
|
||||
Transform3d mesh_trafo_inv = print_object->trafo().inverse();
|
||||
@ -495,6 +504,7 @@ void GLVolumeCollection::load_object_auxiliary(
|
||||
this->volumes.emplace_back(new GLVolume((milestone == slaposBasePool) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR));
|
||||
GLVolume& v = *this->volumes.back();
|
||||
v.indexed_vertex_array.load_mesh(mesh);
|
||||
v.indexed_vertex_array.finalize_geometry(opengl_initialized);
|
||||
v.composite_id = GLVolume::CompositeID(obj_idx, -int(milestone), (int)instance_idx.first);
|
||||
v.geometry_id = std::pair<size_t, size_t>(timestamp, model_instance.id().id);
|
||||
// Create a copy of the convex hull mesh for each instance. Use a move operator on the last instance.
|
||||
@ -511,7 +521,7 @@ void GLVolumeCollection::load_object_auxiliary(
|
||||
}
|
||||
|
||||
int GLVolumeCollection::load_wipe_tower_preview(
|
||||
int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width)
|
||||
int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, bool opengl_initialized)
|
||||
{
|
||||
if (depth < 0.01f)
|
||||
return int(this->volumes.size() - 1);
|
||||
@ -564,6 +574,7 @@ int GLVolumeCollection::load_wipe_tower_preview(
|
||||
this->volumes.emplace_back(new GLVolume(color));
|
||||
GLVolume& v = *this->volumes.back();
|
||||
v.indexed_vertex_array.load_mesh(mesh);
|
||||
v.indexed_vertex_array.finalize_geometry(opengl_initialized);
|
||||
v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0));
|
||||
v.set_volume_rotation(Vec3d(0., 0., (M_PI / 180.) * rotation_angle));
|
||||
v.composite_id = GLVolume::CompositeID(obj_idx, 0, 0);
|
||||
@ -574,6 +585,23 @@ int GLVolumeCollection::load_wipe_tower_preview(
|
||||
return int(this->volumes.size() - 1);
|
||||
}
|
||||
|
||||
GLVolume* GLVolumeCollection::new_toolpath_volume(const float *rgba, size_t reserve_vbo_floats)
|
||||
{
|
||||
GLVolume *out = new_nontoolpath_volume(rgba, reserve_vbo_floats);
|
||||
out->is_extrusion_path = true;
|
||||
return out;
|
||||
}
|
||||
|
||||
GLVolume* GLVolumeCollection::new_nontoolpath_volume(const float *rgba, size_t reserve_vbo_floats)
|
||||
{
|
||||
GLVolume *out = new GLVolume(rgba);
|
||||
out->is_extrusion_path = false;
|
||||
// Reserving number of vertices (3x position + 3x color)
|
||||
out->indexed_vertex_array.reserve(reserve_vbo_floats / 6);
|
||||
this->volumes.emplace_back(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func)
|
||||
{
|
||||
GLVolumeWithIdAndZList list;
|
||||
@ -823,6 +851,230 @@ std::vector<double> GLVolumeCollection::get_current_print_zs(bool active_only) c
|
||||
return print_zs;
|
||||
}
|
||||
|
||||
size_t GLVolumeCollection::cpu_memory_used() const
|
||||
{
|
||||
size_t memsize = sizeof(*this) + this->volumes.capacity() * sizeof(GLVolume);
|
||||
for (const GLVolume *volume : this->volumes)
|
||||
memsize += volume->cpu_memory_used();
|
||||
return memsize;
|
||||
}
|
||||
|
||||
size_t GLVolumeCollection::gpu_memory_used() const
|
||||
{
|
||||
size_t memsize = 0;
|
||||
for (const GLVolume *volume : this->volumes)
|
||||
memsize += volume->gpu_memory_used();
|
||||
return memsize;
|
||||
}
|
||||
|
||||
std::string GLVolumeCollection::log_memory_info() const
|
||||
{
|
||||
return " (GLVolumeCollection RAM: " + format_memsize_MB(this->cpu_memory_used()) + " GPU: " + format_memsize_MB(this->gpu_memory_used()) + " Both: " + format_memsize_MB(this->gpu_memory_used()) + ")";
|
||||
}
|
||||
|
||||
bool can_export_to_obj(const GLVolume& volume)
|
||||
{
|
||||
if (!volume.is_active || !volume.is_extrusion_path)
|
||||
return false;
|
||||
|
||||
if (volume.indexed_vertex_array.triangle_indices.empty() && (std::min(volume.indexed_vertex_array.triangle_indices_size, volume.tverts_range.second - volume.tverts_range.first) == 0))
|
||||
return false;
|
||||
|
||||
if (volume.indexed_vertex_array.quad_indices.empty() && (std::min(volume.indexed_vertex_array.quad_indices_size, volume.qverts_range.second - volume.qverts_range.first) == 0))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GLVolumeCollection::has_toolpaths_to_export() const
|
||||
{
|
||||
for (const GLVolume* volume : this->volumes)
|
||||
{
|
||||
if (can_export_to_obj(*volume))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GLVolumeCollection::export_toolpaths_to_obj(const char* filename) const
|
||||
{
|
||||
if (filename == nullptr)
|
||||
return;
|
||||
|
||||
if (!has_toolpaths_to_export())
|
||||
return;
|
||||
|
||||
// collect color information to generate materials
|
||||
std::set<std::array<float, 4>> colors;
|
||||
for (const GLVolume* volume : this->volumes)
|
||||
{
|
||||
if (!can_export_to_obj(*volume))
|
||||
continue;
|
||||
|
||||
std::array<float, 4> color;
|
||||
::memcpy((void*)color.data(), (const void*)volume->color, 4 * sizeof(float));
|
||||
colors.insert(color);
|
||||
}
|
||||
|
||||
// save materials file
|
||||
boost::filesystem::path mat_filename(filename);
|
||||
mat_filename.replace_extension("mtl");
|
||||
FILE* fp = boost::nowide::fopen(mat_filename.string().c_str(), "w");
|
||||
if (fp == nullptr) {
|
||||
BOOST_LOG_TRIVIAL(error) << "GLVolumeCollection::export_toolpaths_to_obj: Couldn't open " << mat_filename.string().c_str() << " for writing";
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(fp, "# G-Code Toolpaths Materials\n");
|
||||
fprintf(fp, "# Generated by %s based on Slic3r\n", SLIC3R_BUILD_ID);
|
||||
|
||||
unsigned int colors_count = 1;
|
||||
for (const std::array<float, 4>& color : colors)
|
||||
{
|
||||
fprintf(fp, "\nnewmtl material_%d\n", colors_count++);
|
||||
fprintf(fp, "Ka 1 1 1\n");
|
||||
fprintf(fp, "Kd %f %f %f\n", color[0], color[1], color[2]);
|
||||
fprintf(fp, "Ks 0 0 0\n");
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
// save geometry file
|
||||
fp = boost::nowide::fopen(filename, "w");
|
||||
if (fp == nullptr) {
|
||||
BOOST_LOG_TRIVIAL(error) << "GLVolumeCollection::export_toolpaths_to_obj: Couldn't open " << filename << " for writing";
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(fp, "# G-Code Toolpaths\n");
|
||||
fprintf(fp, "# Generated by %s based on Slic3r\n", SLIC3R_BUILD_ID);
|
||||
fprintf(fp, "\nmtllib ./%s\n", mat_filename.filename().string().c_str());
|
||||
|
||||
unsigned int vertices_count = 0;
|
||||
unsigned int volumes_count = 0;
|
||||
|
||||
for (const GLVolume* volume : this->volumes)
|
||||
{
|
||||
if (!can_export_to_obj(*volume))
|
||||
continue;
|
||||
|
||||
std::vector<float> vertices_and_normals_interleaved;
|
||||
std::vector<int> triangle_indices;
|
||||
std::vector<int> quad_indices;
|
||||
|
||||
if (!volume->indexed_vertex_array.vertices_and_normals_interleaved.empty())
|
||||
// data are in CPU memory
|
||||
vertices_and_normals_interleaved = volume->indexed_vertex_array.vertices_and_normals_interleaved;
|
||||
else if ((volume->indexed_vertex_array.vertices_and_normals_interleaved_VBO_id != 0) && (volume->indexed_vertex_array.vertices_and_normals_interleaved_size != 0))
|
||||
{
|
||||
// data are in GPU memory
|
||||
vertices_and_normals_interleaved = std::vector<float>(volume->indexed_vertex_array.vertices_and_normals_interleaved_size, 0.0f);
|
||||
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, volume->indexed_vertex_array.vertices_and_normals_interleaved_VBO_id));
|
||||
glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, 0, vertices_and_normals_interleaved.size() * sizeof(float), vertices_and_normals_interleaved.data()));
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
if (!volume->indexed_vertex_array.triangle_indices.empty())
|
||||
{
|
||||
// data are in CPU memory
|
||||
size_t size = std::min(volume->indexed_vertex_array.triangle_indices.size(), volume->tverts_range.second - volume->tverts_range.first);
|
||||
if (size != 0)
|
||||
{
|
||||
std::vector<int>::const_iterator it_begin = volume->indexed_vertex_array.triangle_indices.begin() + volume->tverts_range.first;
|
||||
std::vector<int>::const_iterator it_end = volume->indexed_vertex_array.triangle_indices.begin() + volume->tverts_range.first + size;
|
||||
std::copy(it_begin, it_end, std::back_inserter(triangle_indices));
|
||||
}
|
||||
}
|
||||
else if ((volume->indexed_vertex_array.triangle_indices_VBO_id != 0) && (volume->indexed_vertex_array.triangle_indices_size != 0))
|
||||
{
|
||||
// data are in GPU memory
|
||||
size_t size = std::min(volume->indexed_vertex_array.triangle_indices_size, volume->tverts_range.second - volume->tverts_range.first);
|
||||
if (size != 0)
|
||||
{
|
||||
triangle_indices = std::vector<int>(size, 0);
|
||||
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, volume->indexed_vertex_array.triangle_indices_VBO_id));
|
||||
glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, volume->tverts_range.first * sizeof(int), size * sizeof(int), triangle_indices.data()));
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (!volume->indexed_vertex_array.quad_indices.empty())
|
||||
{
|
||||
// data are in CPU memory
|
||||
size_t size = std::min(volume->indexed_vertex_array.quad_indices.size(), volume->qverts_range.second - volume->qverts_range.first);
|
||||
if (size != 0)
|
||||
{
|
||||
std::vector<int>::const_iterator it_begin = volume->indexed_vertex_array.quad_indices.begin() + volume->qverts_range.first;
|
||||
std::vector<int>::const_iterator it_end = volume->indexed_vertex_array.quad_indices.begin() + volume->qverts_range.first + size;
|
||||
std::copy(it_begin, it_end, std::back_inserter(quad_indices));
|
||||
}
|
||||
}
|
||||
else if ((volume->indexed_vertex_array.quad_indices_VBO_id != 0) && (volume->indexed_vertex_array.quad_indices_size != 0))
|
||||
{
|
||||
// data are in GPU memory
|
||||
size_t size = std::min(volume->indexed_vertex_array.quad_indices_size, volume->qverts_range.second - volume->qverts_range.first);
|
||||
if (size != 0)
|
||||
{
|
||||
quad_indices = std::vector<int>(size, 0);
|
||||
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, volume->indexed_vertex_array.quad_indices_VBO_id));
|
||||
glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, volume->qverts_range.first * sizeof(int), size * sizeof(int), quad_indices.data()));
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (triangle_indices.empty() && quad_indices.empty())
|
||||
continue;
|
||||
|
||||
fprintf(fp, "\n# vertices volume %d\n", volumes_count);
|
||||
for (unsigned int i = 0; i < vertices_and_normals_interleaved.size(); i += 6)
|
||||
{
|
||||
fprintf(fp, "v %f %f %f\n", vertices_and_normals_interleaved[i + 3], vertices_and_normals_interleaved[i + 4], vertices_and_normals_interleaved[i + 5]);
|
||||
}
|
||||
|
||||
fprintf(fp, "\n# normals volume %d\n", volumes_count);
|
||||
for (unsigned int i = 0; i < vertices_and_normals_interleaved.size(); i += 6)
|
||||
{
|
||||
fprintf(fp, "vn %f %f %f\n", vertices_and_normals_interleaved[i + 0], vertices_and_normals_interleaved[i + 1], vertices_and_normals_interleaved[i + 2]);
|
||||
}
|
||||
|
||||
std::array<float, 4> color;
|
||||
::memcpy((void*)color.data(), (const void*)volume->color, 4 * sizeof(float));
|
||||
colors.insert(color);
|
||||
fprintf(fp, "\n# material volume %d\n", volumes_count);
|
||||
fprintf(fp, "usemtl material_%lld\n", 1 + std::distance(colors.begin(), colors.find(color)));
|
||||
|
||||
fprintf(fp, "\n# triangular facets volume %d\n", volumes_count);
|
||||
for (unsigned int i = 0; i < triangle_indices.size(); i += 3)
|
||||
{
|
||||
int id_v1 = vertices_count + 1 + triangle_indices[i + 0];
|
||||
int id_v2 = vertices_count + 1 + triangle_indices[i + 1];
|
||||
int id_v3 = vertices_count + 1 + triangle_indices[i + 2];
|
||||
fprintf(fp, "f %d//%d %d//%d %d//%d\n", id_v1, id_v1, id_v2, id_v2, id_v3, id_v3);
|
||||
}
|
||||
|
||||
fprintf(fp, "\n# quadrangular facets volume %d\n", volumes_count);
|
||||
for (unsigned int i = 0; i < quad_indices.size(); i += 4)
|
||||
{
|
||||
int id_v1 = vertices_count + 1 + quad_indices[i + 0];
|
||||
int id_v2 = vertices_count + 1 + quad_indices[i + 1];
|
||||
int id_v3 = vertices_count + 1 + quad_indices[i + 2];
|
||||
int id_v4 = vertices_count + 1 + quad_indices[i + 3];
|
||||
fprintf(fp, "f %d//%d %d//%d %d//%d %d//%d\n", id_v1, id_v1, id_v2, id_v2, id_v3, id_v3, id_v4, id_v4);
|
||||
}
|
||||
|
||||
++volumes_count;
|
||||
vertices_count += vertices_and_normals_interleaved.size() / 6;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
// caller is responsible for supplying NO lines with zero length
|
||||
static void thick_lines_to_indexed_vertex_array(
|
||||
const Lines &lines,
|
||||
@ -1594,6 +1846,7 @@ bool GLArrow::on_init()
|
||||
triangles.emplace_back(7, 13, 6);
|
||||
|
||||
m_volume.indexed_vertex_array.load_mesh(TriangleMesh(vertices, triangles));
|
||||
m_volume.indexed_vertex_array.finalize_geometry(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1707,6 +1960,7 @@ bool GLCurvedArrow::on_init()
|
||||
triangles.emplace_back(vertices_per_level, 2 * vertices_per_level + 1, vertices_per_level + 1);
|
||||
|
||||
m_volume.indexed_vertex_array.load_mesh(TriangleMesh(vertices, triangles));
|
||||
m_volume.indexed_vertex_array.finalize_geometry(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1733,6 +1987,7 @@ bool GLBed::on_init_from_file(const std::string& filename)
|
||||
m_filename = filename;
|
||||
|
||||
m_volume.indexed_vertex_array.load_mesh(model.mesh());
|
||||
m_volume.indexed_vertex_array.finalize_geometry(true);
|
||||
|
||||
float color[4] = { 0.235f, 0.235f, 0.235f, 1.0f };
|
||||
set_color(color, 4);
|
||||
@ -1765,6 +2020,11 @@ bool _3DScene::init(wxGLCanvas* canvas)
|
||||
return s_canvas_mgr.init(canvas);
|
||||
}
|
||||
|
||||
void _3DScene::destroy()
|
||||
{
|
||||
s_canvas_mgr.destroy();
|
||||
}
|
||||
|
||||
GUI::GLCanvas3D* _3DScene::get_canvas(wxGLCanvas* canvas)
|
||||
{
|
||||
return s_canvas_mgr.get_canvas(canvas);
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
vertices_and_normals_interleaved_VBO_id(0),
|
||||
triangle_indices_VBO_id(0),
|
||||
quad_indices_VBO_id(0)
|
||||
{}
|
||||
{ assert(! rhs.has_VBOs()); }
|
||||
GLIndexedVertexArray(GLIndexedVertexArray &&rhs) :
|
||||
vertices_and_normals_interleaved(std::move(rhs.vertices_and_normals_interleaved)),
|
||||
triangle_indices(std::move(rhs.triangle_indices)),
|
||||
@ -73,7 +73,7 @@ public:
|
||||
vertices_and_normals_interleaved_VBO_id(0),
|
||||
triangle_indices_VBO_id(0),
|
||||
quad_indices_VBO_id(0)
|
||||
{}
|
||||
{ assert(! rhs.has_VBOs()); }
|
||||
|
||||
~GLIndexedVertexArray() { release_geometry(); }
|
||||
|
||||
@ -81,14 +81,17 @@ public:
|
||||
{
|
||||
assert(vertices_and_normals_interleaved_VBO_id == 0);
|
||||
assert(triangle_indices_VBO_id == 0);
|
||||
assert(triangle_indices_VBO_id == 0);
|
||||
this->vertices_and_normals_interleaved = rhs.vertices_and_normals_interleaved;
|
||||
this->triangle_indices = rhs.triangle_indices;
|
||||
this->quad_indices = rhs.quad_indices;
|
||||
this->m_bounding_box = rhs.m_bounding_box;
|
||||
vertices_and_normals_interleaved_size = rhs.vertices_and_normals_interleaved_size;
|
||||
triangle_indices_size = rhs.triangle_indices_size;
|
||||
quad_indices_size = rhs.quad_indices_size;
|
||||
assert(quad_indices_VBO_id == 0);
|
||||
assert(rhs.vertices_and_normals_interleaved_VBO_id == 0);
|
||||
assert(rhs.triangle_indices_VBO_id == 0);
|
||||
assert(rhs.quad_indices_VBO_id == 0);
|
||||
this->vertices_and_normals_interleaved = rhs.vertices_and_normals_interleaved;
|
||||
this->triangle_indices = rhs.triangle_indices;
|
||||
this->quad_indices = rhs.quad_indices;
|
||||
this->m_bounding_box = rhs.m_bounding_box;
|
||||
this->vertices_and_normals_interleaved_size = rhs.vertices_and_normals_interleaved_size;
|
||||
this->triangle_indices_size = rhs.triangle_indices_size;
|
||||
this->quad_indices_size = rhs.quad_indices_size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -96,21 +99,24 @@ public:
|
||||
{
|
||||
assert(vertices_and_normals_interleaved_VBO_id == 0);
|
||||
assert(triangle_indices_VBO_id == 0);
|
||||
assert(triangle_indices_VBO_id == 0);
|
||||
this->vertices_and_normals_interleaved = std::move(rhs.vertices_and_normals_interleaved);
|
||||
this->triangle_indices = std::move(rhs.triangle_indices);
|
||||
this->quad_indices = std::move(rhs.quad_indices);
|
||||
this->m_bounding_box = std::move(rhs.m_bounding_box);
|
||||
vertices_and_normals_interleaved_size = rhs.vertices_and_normals_interleaved_size;
|
||||
triangle_indices_size = rhs.triangle_indices_size;
|
||||
quad_indices_size = rhs.quad_indices_size;
|
||||
assert(quad_indices_VBO_id == 0);
|
||||
assert(rhs.vertices_and_normals_interleaved_VBO_id == 0);
|
||||
assert(rhs.triangle_indices_VBO_id == 0);
|
||||
assert(rhs.quad_indices_VBO_id == 0);
|
||||
this->vertices_and_normals_interleaved = std::move(rhs.vertices_and_normals_interleaved);
|
||||
this->triangle_indices = std::move(rhs.triangle_indices);
|
||||
this->quad_indices = std::move(rhs.quad_indices);
|
||||
this->m_bounding_box = std::move(rhs.m_bounding_box);
|
||||
this->vertices_and_normals_interleaved_size = rhs.vertices_and_normals_interleaved_size;
|
||||
this->triangle_indices_size = rhs.triangle_indices_size;
|
||||
this->quad_indices_size = rhs.quad_indices_size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Vertices and their normals, interleaved to be used by void glInterleavedArrays(GL_N3F_V3F, 0, x)
|
||||
mutable std::vector<float> vertices_and_normals_interleaved;
|
||||
mutable std::vector<int> triangle_indices;
|
||||
mutable std::vector<int> quad_indices;
|
||||
std::vector<float> vertices_and_normals_interleaved;
|
||||
std::vector<int> triangle_indices;
|
||||
std::vector<int> quad_indices;
|
||||
|
||||
// When the geometry data is loaded into the graphics card as Vertex Buffer Objects,
|
||||
// the above mentioned std::vectors are cleared and the following variables keep their original length.
|
||||
@ -120,9 +126,9 @@ public:
|
||||
|
||||
// IDs of the Vertex Array Objects, into which the geometry has been loaded.
|
||||
// Zero if the VBOs are not sent to GPU yet.
|
||||
mutable unsigned int vertices_and_normals_interleaved_VBO_id{ 0 };
|
||||
mutable unsigned int triangle_indices_VBO_id{ 0 };
|
||||
mutable unsigned int quad_indices_VBO_id{ 0 };
|
||||
unsigned int vertices_and_normals_interleaved_VBO_id{ 0 };
|
||||
unsigned int triangle_indices_VBO_id{ 0 };
|
||||
unsigned int quad_indices_VBO_id{ 0 };
|
||||
|
||||
void load_mesh_full_shading(const TriangleMesh &mesh);
|
||||
void load_mesh(const TriangleMesh& mesh) { this->load_mesh_full_shading(mesh); }
|
||||
@ -142,12 +148,12 @@ public:
|
||||
|
||||
if (this->vertices_and_normals_interleaved.size() + 6 > this->vertices_and_normals_interleaved.capacity())
|
||||
this->vertices_and_normals_interleaved.reserve(next_highest_power_of_2(this->vertices_and_normals_interleaved.size() + 6));
|
||||
this->vertices_and_normals_interleaved.push_back(nx);
|
||||
this->vertices_and_normals_interleaved.push_back(ny);
|
||||
this->vertices_and_normals_interleaved.push_back(nz);
|
||||
this->vertices_and_normals_interleaved.push_back(x);
|
||||
this->vertices_and_normals_interleaved.push_back(y);
|
||||
this->vertices_and_normals_interleaved.push_back(z);
|
||||
this->vertices_and_normals_interleaved.emplace_back(nx);
|
||||
this->vertices_and_normals_interleaved.emplace_back(ny);
|
||||
this->vertices_and_normals_interleaved.emplace_back(nz);
|
||||
this->vertices_and_normals_interleaved.emplace_back(x);
|
||||
this->vertices_and_normals_interleaved.emplace_back(y);
|
||||
this->vertices_and_normals_interleaved.emplace_back(z);
|
||||
|
||||
this->vertices_and_normals_interleaved_size = this->vertices_and_normals_interleaved.size();
|
||||
m_bounding_box.merge(Vec3f(x, y, z).cast<double>());
|
||||
@ -168,9 +174,9 @@ public:
|
||||
|
||||
if (this->triangle_indices.size() + 3 > this->vertices_and_normals_interleaved.capacity())
|
||||
this->triangle_indices.reserve(next_highest_power_of_2(this->triangle_indices.size() + 3));
|
||||
this->triangle_indices.push_back(idx1);
|
||||
this->triangle_indices.push_back(idx2);
|
||||
this->triangle_indices.push_back(idx3);
|
||||
this->triangle_indices.emplace_back(idx1);
|
||||
this->triangle_indices.emplace_back(idx2);
|
||||
this->triangle_indices.emplace_back(idx3);
|
||||
this->triangle_indices_size = this->triangle_indices.size();
|
||||
};
|
||||
|
||||
@ -181,17 +187,17 @@ public:
|
||||
|
||||
if (this->quad_indices.size() + 4 > this->vertices_and_normals_interleaved.capacity())
|
||||
this->quad_indices.reserve(next_highest_power_of_2(this->quad_indices.size() + 4));
|
||||
this->quad_indices.push_back(idx1);
|
||||
this->quad_indices.push_back(idx2);
|
||||
this->quad_indices.push_back(idx3);
|
||||
this->quad_indices.push_back(idx4);
|
||||
this->quad_indices.emplace_back(idx1);
|
||||
this->quad_indices.emplace_back(idx2);
|
||||
this->quad_indices.emplace_back(idx3);
|
||||
this->quad_indices.emplace_back(idx4);
|
||||
this->quad_indices_size = this->quad_indices.size();
|
||||
};
|
||||
|
||||
// Finalize the initialization of the geometry & indices,
|
||||
// upload the geometry and indices to OpenGL VBO objects
|
||||
// and shrink the allocated data, possibly relasing it if it has been loaded into the VBOs.
|
||||
void finalize_geometry() const;
|
||||
void finalize_geometry(bool opengl_initialized);
|
||||
// Release the geometry data, release OpenGL VBOs.
|
||||
void release_geometry();
|
||||
|
||||
@ -212,7 +218,7 @@ public:
|
||||
}
|
||||
|
||||
// Shrink the internal storage to tighly fit the data stored.
|
||||
void shrink_to_fit() const {
|
||||
void shrink_to_fit() {
|
||||
this->vertices_and_normals_interleaved.shrink_to_fit();
|
||||
this->triangle_indices.shrink_to_fit();
|
||||
this->quad_indices.shrink_to_fit();
|
||||
@ -220,6 +226,22 @@ public:
|
||||
|
||||
const BoundingBoxf3& bounding_box() const { return m_bounding_box; }
|
||||
|
||||
// Return an estimate of the memory consumed by this class.
|
||||
size_t cpu_memory_used() const { return sizeof(*this) + vertices_and_normals_interleaved.capacity() * sizeof(float) + triangle_indices.capacity() * sizeof(int) + quad_indices.capacity() * sizeof(int); }
|
||||
// Return an estimate of the memory held by GPU vertex buffers.
|
||||
size_t gpu_memory_used() const
|
||||
{
|
||||
size_t memsize = 0;
|
||||
if (this->vertices_and_normals_interleaved_VBO_id != 0)
|
||||
memsize += this->vertices_and_normals_interleaved_size * 4;
|
||||
if (this->triangle_indices_VBO_id != 0)
|
||||
memsize += this->triangle_indices_size * 4;
|
||||
if (this->quad_indices_VBO_id != 0)
|
||||
memsize += this->quad_indices_size * 4;
|
||||
return memsize;
|
||||
}
|
||||
size_t total_memory_used() const { return this->cpu_memory_used() + this->gpu_memory_used(); }
|
||||
|
||||
private:
|
||||
BoundingBoxf3 m_bounding_box;
|
||||
};
|
||||
@ -251,7 +273,7 @@ private:
|
||||
Geometry::Transformation m_volume_transformation;
|
||||
|
||||
// Shift in z required by sla supports+pad
|
||||
double m_sla_shift_z;
|
||||
double m_sla_shift_z;
|
||||
// Bounding box of this volume, in unscaled coordinates.
|
||||
mutable BoundingBoxf3 m_transformed_bounding_box;
|
||||
// Whether or not is needed to recalculate the transformed bounding box.
|
||||
@ -295,6 +317,8 @@ public:
|
||||
bool selected;
|
||||
// Is this object disabled from selection?
|
||||
bool disabled;
|
||||
// Is this object printable?
|
||||
bool printable;
|
||||
// Whether or not this volume is active for rendering
|
||||
bool is_active;
|
||||
// Whether or not to use this volume when applying zoom_to_volumes()
|
||||
@ -416,18 +440,27 @@ public:
|
||||
|
||||
bool empty() const { return this->indexed_vertex_array.empty(); }
|
||||
|
||||
void set_range(coordf_t low, coordf_t high);
|
||||
void set_range(double low, double high);
|
||||
|
||||
void render() const;
|
||||
void render(int color_id, int detection_id, int worldmatrix_id) const;
|
||||
|
||||
void finalize_geometry() { this->indexed_vertex_array.finalize_geometry(); }
|
||||
void finalize_geometry(bool opengl_initialized) { this->indexed_vertex_array.finalize_geometry(opengl_initialized); }
|
||||
void release_geometry() { this->indexed_vertex_array.release_geometry(); }
|
||||
|
||||
void set_bounding_boxes_as_dirty() { m_transformed_bounding_box_dirty = true; m_transformed_convex_hull_bounding_box_dirty = true; }
|
||||
|
||||
bool is_sla_support() const;
|
||||
bool is_sla_pad() const;
|
||||
|
||||
// Return an estimate of the memory consumed by this class.
|
||||
size_t cpu_memory_used() const {
|
||||
//FIXME what to do wih m_convex_hull?
|
||||
return sizeof(*this) - sizeof(this->indexed_vertex_array) + this->indexed_vertex_array.cpu_memory_used() + this->print_zs.capacity() * sizeof(coordf_t) + this->offsets.capacity() * sizeof(size_t);
|
||||
}
|
||||
// Return an estimate of the memory held by GPU vertex buffers.
|
||||
size_t gpu_memory_used() const { return this->indexed_vertex_array.gpu_memory_used(); }
|
||||
size_t total_memory_used() const { return this->cpu_memory_used() + this->gpu_memory_used(); }
|
||||
};
|
||||
|
||||
typedef std::vector<GLVolume*> GLVolumePtrs;
|
||||
@ -462,30 +495,36 @@ public:
|
||||
~GLVolumeCollection() { clear(); };
|
||||
|
||||
std::vector<int> load_object(
|
||||
const ModelObject* model_object,
|
||||
const ModelObject *model_object,
|
||||
int obj_idx,
|
||||
const std::vector<int>& instance_idxs,
|
||||
const std::string& color_by);
|
||||
const std::vector<int> &instance_idxs,
|
||||
const std::string &color_by,
|
||||
bool opengl_initialized);
|
||||
|
||||
int load_object_volume(
|
||||
const ModelObject* model_object,
|
||||
int obj_idx,
|
||||
int volume_idx,
|
||||
int instance_idx,
|
||||
const std::string& color_by);
|
||||
const ModelObject *model_object,
|
||||
int obj_idx,
|
||||
int volume_idx,
|
||||
int instance_idx,
|
||||
const std::string &color_by,
|
||||
bool opengl_initialized);
|
||||
|
||||
// Load SLA auxiliary GLVolumes (for support trees or pad).
|
||||
void load_object_auxiliary(
|
||||
const SLAPrintObject* print_object,
|
||||
const SLAPrintObject *print_object,
|
||||
int obj_idx,
|
||||
// pairs of <instance_idx, print_instance_idx>
|
||||
const std::vector<std::pair<size_t, size_t>>& instances,
|
||||
SLAPrintObjectStep milestone,
|
||||
// Timestamp of the last change of the milestone
|
||||
size_t timestamp);
|
||||
size_t timestamp,
|
||||
bool opengl_initialized);
|
||||
|
||||
int load_wipe_tower_preview(
|
||||
int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width);
|
||||
int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, bool opengl_initialized);
|
||||
|
||||
GLVolume* new_toolpath_volume(const float *rgba, size_t reserve_vbo_floats = 0);
|
||||
GLVolume* new_nontoolpath_volume(const float *rgba, size_t reserve_vbo_floats = 0);
|
||||
|
||||
// Render the volumes by OpenGL.
|
||||
void render(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func = std::function<bool(const GLVolume&)>()) const;
|
||||
@ -493,7 +532,7 @@ public:
|
||||
// Finalize the initialization of the geometry & indices,
|
||||
// upload the geometry and indices to OpenGL VBO objects
|
||||
// and shrink the allocated data, possibly relasing it if it has been loaded into the VBOs.
|
||||
void finalize_geometry() { for (auto* v : volumes) v->finalize_geometry(); }
|
||||
void finalize_geometry(bool opengl_initialized) { for (auto* v : volumes) v->finalize_geometry(opengl_initialized); }
|
||||
// Release the geometry data assigned to the volumes.
|
||||
// If OpenGL VBOs were allocated, an OpenGL context has to be active to release them.
|
||||
void release_geometry() { for (auto *v : volumes) v->release_geometry(); }
|
||||
@ -521,6 +560,18 @@ public:
|
||||
// Returns a vector containing the sorted list of all the print_zs of the volumes contained in this collection
|
||||
std::vector<double> get_current_print_zs(bool active_only) const;
|
||||
|
||||
// Return an estimate of the memory consumed by this class.
|
||||
size_t cpu_memory_used() const;
|
||||
// Return an estimate of the memory held by GPU vertex buffers.
|
||||
size_t gpu_memory_used() const;
|
||||
size_t total_memory_used() const { return this->cpu_memory_used() + this->gpu_memory_used(); }
|
||||
// Return CPU, GPU and total memory log line.
|
||||
std::string log_memory_info() const;
|
||||
|
||||
bool has_toolpaths_to_export() const;
|
||||
// Export the geometry of the GLVolumes toolpaths of this collection into the file with the given path, in obj format
|
||||
void export_toolpaths_to_obj(const char* filename) const;
|
||||
|
||||
private:
|
||||
GLVolumeCollection(const GLVolumeCollection &other);
|
||||
GLVolumeCollection& operator=(const GLVolumeCollection &);
|
||||
@ -538,6 +589,7 @@ public:
|
||||
GLModel();
|
||||
virtual ~GLModel();
|
||||
|
||||
// init() / init_from_file() shall be called with the OpenGL context active!
|
||||
bool init() { return on_init(); }
|
||||
bool init_from_file(const std::string& filename) { return on_init_from_file(filename); }
|
||||
|
||||
@ -567,7 +619,7 @@ protected:
|
||||
class GLArrow : public GLModel
|
||||
{
|
||||
protected:
|
||||
virtual bool on_init();
|
||||
bool on_init() override;
|
||||
};
|
||||
|
||||
class GLCurvedArrow : public GLModel
|
||||
@ -578,13 +630,13 @@ public:
|
||||
explicit GLCurvedArrow(unsigned int resolution);
|
||||
|
||||
protected:
|
||||
virtual bool on_init();
|
||||
bool on_init() override;
|
||||
};
|
||||
|
||||
class GLBed : public GLModel
|
||||
{
|
||||
protected:
|
||||
virtual bool on_init_from_file(const std::string& filename);
|
||||
bool on_init_from_file(const std::string& filename) override;
|
||||
};
|
||||
|
||||
class _3DScene
|
||||
@ -599,6 +651,7 @@ public:
|
||||
static void remove_all_canvases();
|
||||
|
||||
static bool init(wxGLCanvas* canvas);
|
||||
static void destroy();
|
||||
|
||||
static GUI::GLCanvas3D* get_canvas(wxGLCanvas* canvas);
|
||||
|
||||
|
@ -76,9 +76,9 @@ void CopyrightsDialog::fill_entries()
|
||||
{
|
||||
m_entries = {
|
||||
{ "wxWidgets" , "2019 wxWidgets" , "https://www.wxwidgets.org/" },
|
||||
{ "OpenGL" , "1997-2019 The Khronos™ Group Inc" , "https://www.opengl.org/" },
|
||||
{ "OpenGL" , "1997-2019 The Khronos™ Group Inc" , "https://www.opengl.org/" },
|
||||
{ "GNU gettext" , "1998, 2019 Free Software Foundation, Inc." , "https://www.gnu.org/software/gettext/" },
|
||||
{ "PoEdit" , "2019 Václav Slavík" , "https://poedit.net/" },
|
||||
{ "PoEdit" , "2019 Václav Slavík" , "https://poedit.net/" },
|
||||
{ "ImGUI" , "2014-2019 Omar Cornut" , "https://github.com/ocornut/imgui" },
|
||||
{ "Eigen" , "" , "http://eigen.tuxfamily.org" },
|
||||
{ "ADMesh" , "1995, 1996 Anthony D. Martin; "
|
||||
@ -106,8 +106,13 @@ void CopyrightsDialog::fill_entries()
|
||||
"2001-2016 Expat maintainers" , "http://www.libexpat.org/" },
|
||||
{ "AVRDUDE" , "2018 Free Software Foundation, Inc." , "http://savannah.nongnu.org/projects/avrdude" },
|
||||
{ "Shinyprofiler" , "2007-2010 Aidin Abedi" , "http://code.google.com/p/shinyprofiler/" },
|
||||
{ "Real-Time DXT1/DXT5 C compression library"
|
||||
, "Based on original by fabian \"ryg\" giesen v1.04. "
|
||||
"Custom version, modified by Yann Collet" , "https://github.com/Cyan4973/RygsDXTc" },
|
||||
{ "Icons for STL and GCODE files."
|
||||
, "Akira Yasuda" , "http://3dp0.com/icons-for-stl-and-gcode/" }
|
||||
, "Akira Yasuda" , "http://3dp0.com/icons-for-stl-and-gcode/" },
|
||||
{ "AppImage packaging for Linux using AppImageKit"
|
||||
, "2004-2019 Simon Peter and contributors" , "https://appimage.org/" }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -15,9 +15,13 @@
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/exceptions.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include <wx/string.h>
|
||||
#include "I18N.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
static const std::string VENDOR_PREFIX = "vendor:";
|
||||
@ -58,7 +62,7 @@ void AppConfig::set_defaults()
|
||||
if (!get("use_legacy_opengl").empty())
|
||||
erase("", "use_legacy_opengl");
|
||||
|
||||
#if __APPLE__
|
||||
#ifdef __APPLE__
|
||||
if (get("use_retina_opengl").empty())
|
||||
set("use_retina_opengl", "1");
|
||||
#endif
|
||||
@ -90,7 +94,15 @@ void AppConfig::load()
|
||||
namespace pt = boost::property_tree;
|
||||
pt::ptree tree;
|
||||
boost::nowide::ifstream ifs(AppConfig::config_path());
|
||||
pt::read_ini(ifs, tree);
|
||||
try {
|
||||
pt::read_ini(ifs, tree);
|
||||
} catch (pt::ptree_error& ex) {
|
||||
// Error while parsing config file. We'll customize the error message and rethrow to be displayed.
|
||||
throw std::runtime_error(
|
||||
_utf8(L("Error parsing PrusaSlicer config file, it is probably corrupted. "
|
||||
"Try to manualy delete the file to recover from the error. Your user profiles will not be affected.")) +
|
||||
"\n\n" + AppConfig::config_path() + "\n\n" + ex.what());
|
||||
}
|
||||
|
||||
// 2) Parse the property_tree, extract the sections and key / value pairs.
|
||||
for (const auto §ion : tree) {
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "libslic3r/Config.hpp"
|
||||
#include "slic3r/Utils/Semver.hpp"
|
||||
#include "libslic3r/Semver.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
@ -153,7 +153,12 @@ void BackgroundSlicingProcess::thread_proc()
|
||||
} catch (CanceledException & /* ex */) {
|
||||
// Canceled, this is all right.
|
||||
assert(m_print->canceled());
|
||||
} catch (std::exception &ex) {
|
||||
} catch (const std::bad_alloc& ex) {
|
||||
wxString errmsg = wxString::Format(_(L("%s has encountered an error. It was likely caused by running out of memory. "
|
||||
"If you are sure you have enough RAM on your system, this may also be a bug and we would "
|
||||
"be glad if you reported it.")), SLIC3R_APP_NAME);
|
||||
error = errmsg.ToStdString() + "\n\n" + std::string(ex.what());
|
||||
} catch (std::exception &ex) {
|
||||
error = ex.what();
|
||||
} catch (...) {
|
||||
error = "Unknown C++ exception.";
|
||||
|
@ -212,7 +212,7 @@ wxPanel* BedShapePanel::init_texture_panel()
|
||||
wxStaticText* lbl = dynamic_cast<wxStaticText*>(e.GetEventObject());
|
||||
if (lbl != nullptr)
|
||||
{
|
||||
wxString tooltip_text = (m_custom_texture == NONE) ? _(L("")) : _(m_custom_texture);
|
||||
wxString tooltip_text = (m_custom_texture == NONE) ? "" : _(m_custom_texture);
|
||||
wxToolTip* tooltip = lbl->GetToolTip();
|
||||
if ((tooltip == nullptr) || (tooltip->GetTip() != tooltip_text))
|
||||
lbl->SetToolTip(tooltip_text);
|
||||
@ -280,7 +280,7 @@ wxPanel* BedShapePanel::init_model_panel()
|
||||
wxStaticText* lbl = dynamic_cast<wxStaticText*>(e.GetEventObject());
|
||||
if (lbl != nullptr)
|
||||
{
|
||||
wxString tooltip_text = (m_custom_model == NONE) ? _(L("")) : _(m_custom_model);
|
||||
wxString tooltip_text = (m_custom_model == NONE) ? "" : _(m_custom_model);
|
||||
wxToolTip* tooltip = lbl->GetToolTip();
|
||||
if ((tooltip == nullptr) || (tooltip->GetTip() != tooltip_text))
|
||||
lbl->SetToolTip(tooltip_text);
|
||||
|
@ -22,10 +22,10 @@ namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
const double Camera::DefaultDistance = 1000.0;
|
||||
double Camera::FrustrumMinZSize = 50.0;
|
||||
double Camera::FrustrumMinZRange = 50.0;
|
||||
double Camera::FrustrumMinNearZ = 100.0;
|
||||
double Camera::FrustrumZMargin = 10.0;
|
||||
double Camera::FovMinDeg = 0.5;
|
||||
double Camera::FovMaxDeg = 75.0;
|
||||
double Camera::MaxFovDeg = 60.0;
|
||||
|
||||
Camera::Camera()
|
||||
: phi(45.0f)
|
||||
@ -186,7 +186,8 @@ void Camera::apply_view_matrix() const
|
||||
|
||||
void Camera::apply_projection(const BoundingBoxf3& box) const
|
||||
{
|
||||
m_distance = DefaultDistance;
|
||||
set_distance(DefaultDistance);
|
||||
|
||||
double w = 0.0;
|
||||
double h = 0.0;
|
||||
|
||||
@ -194,15 +195,14 @@ void Camera::apply_projection(const BoundingBoxf3& box) const
|
||||
{
|
||||
m_frustrum_zs = calc_tight_frustrum_zs_around(box);
|
||||
|
||||
w = (double)m_viewport[2];
|
||||
h = (double)m_viewport[3];
|
||||
w = 0.5 * (double)m_viewport[2];
|
||||
h = 0.5 * (double)m_viewport[3];
|
||||
|
||||
double two_zoom = 2.0 * m_zoom;
|
||||
if (two_zoom != 0.0)
|
||||
if (m_zoom != 0.0)
|
||||
{
|
||||
double inv_two_zoom = 1.0 / two_zoom;
|
||||
w *= inv_two_zoom;
|
||||
h *= inv_two_zoom;
|
||||
double inv_zoom = 1.0 / m_zoom;
|
||||
w *= inv_zoom;
|
||||
h *= inv_zoom;
|
||||
}
|
||||
|
||||
switch (m_type)
|
||||
@ -226,21 +226,16 @@ void Camera::apply_projection(const BoundingBoxf3& box) const
|
||||
|
||||
if (m_type == Perspective)
|
||||
{
|
||||
double fov_rad = 2.0 * std::atan(h / m_frustrum_zs.first);
|
||||
double fov_deg = Geometry::rad2deg(fov_rad);
|
||||
double fov_deg = Geometry::rad2deg(2.0 * std::atan(h / m_frustrum_zs.first));
|
||||
|
||||
// adjust camera distance to keep fov in a limited range
|
||||
if (fov_deg > FovMaxDeg + 0.001)
|
||||
if (fov_deg > MaxFovDeg)
|
||||
{
|
||||
double new_near_z = h / ::tan(0.5 * Geometry::deg2rad(FovMaxDeg));
|
||||
m_distance += (new_near_z - m_frustrum_zs.first);
|
||||
apply_view_matrix();
|
||||
}
|
||||
else if (fov_deg < FovMinDeg - 0.001)
|
||||
{
|
||||
double new_near_z = h / ::tan(0.5 * Geometry::deg2rad(FovMinDeg));
|
||||
m_distance += (new_near_z - m_frustrum_zs.first);
|
||||
apply_view_matrix();
|
||||
double delta_z = h / ::tan(0.5 * Geometry::deg2rad(MaxFovDeg)) - m_frustrum_zs.first;
|
||||
if (delta_z > 0.001)
|
||||
set_distance(m_distance + delta_z);
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
@ -328,42 +323,50 @@ void Camera::debug_render() const
|
||||
|
||||
std::pair<double, double> Camera::calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const
|
||||
{
|
||||
std::pair<double, double> ret = std::make_pair(DBL_MAX, -DBL_MAX);
|
||||
std::pair<double, double> ret;
|
||||
|
||||
Vec3d bb_min = box.min;
|
||||
Vec3d bb_max = box.max;
|
||||
|
||||
// box vertices in world space
|
||||
std::vector<Vec3d> vertices;
|
||||
vertices.reserve(8);
|
||||
vertices.push_back(bb_min);
|
||||
vertices.emplace_back(bb_max(0), bb_min(1), bb_min(2));
|
||||
vertices.emplace_back(bb_max(0), bb_max(1), bb_min(2));
|
||||
vertices.emplace_back(bb_min(0), bb_max(1), bb_min(2));
|
||||
vertices.emplace_back(bb_min(0), bb_min(1), bb_max(2));
|
||||
vertices.emplace_back(bb_max(0), bb_min(1), bb_max(2));
|
||||
vertices.push_back(bb_max);
|
||||
vertices.emplace_back(bb_min(0), bb_max(1), bb_max(2));
|
||||
|
||||
// set the Z range in eye coordinates (negative Zs are in front of the camera)
|
||||
for (const Vec3d& v : vertices)
|
||||
while (true)
|
||||
{
|
||||
double z = -(m_view_matrix * v)(2);
|
||||
ret.first = std::min(ret.first, z);
|
||||
ret.second = std::max(ret.second, z);
|
||||
}
|
||||
ret = std::make_pair(DBL_MAX, -DBL_MAX);
|
||||
|
||||
// apply margin
|
||||
ret.first -= FrustrumZMargin;
|
||||
ret.second += FrustrumZMargin;
|
||||
// box vertices in world space
|
||||
std::vector<Vec3d> vertices;
|
||||
vertices.reserve(8);
|
||||
vertices.push_back(box.min);
|
||||
vertices.emplace_back(box.max(0), box.min(1), box.min(2));
|
||||
vertices.emplace_back(box.max(0), box.max(1), box.min(2));
|
||||
vertices.emplace_back(box.min(0), box.max(1), box.min(2));
|
||||
vertices.emplace_back(box.min(0), box.min(1), box.max(2));
|
||||
vertices.emplace_back(box.max(0), box.min(1), box.max(2));
|
||||
vertices.push_back(box.max);
|
||||
vertices.emplace_back(box.min(0), box.max(1), box.max(2));
|
||||
|
||||
// ensure min size
|
||||
if (ret.second - ret.first < FrustrumMinZSize)
|
||||
{
|
||||
double mid_z = 0.5 * (ret.first + ret.second);
|
||||
double half_size = 0.5 * FrustrumMinZSize;
|
||||
ret.first = mid_z - half_size;
|
||||
ret.second = mid_z + half_size;
|
||||
// set the Z range in eye coordinates (negative Zs are in front of the camera)
|
||||
for (const Vec3d& v : vertices)
|
||||
{
|
||||
double z = -(m_view_matrix * v)(2);
|
||||
ret.first = std::min(ret.first, z);
|
||||
ret.second = std::max(ret.second, z);
|
||||
}
|
||||
|
||||
// apply margin
|
||||
ret.first -= FrustrumZMargin;
|
||||
ret.second += FrustrumZMargin;
|
||||
|
||||
// ensure min size
|
||||
if (ret.second - ret.first < FrustrumMinZRange)
|
||||
{
|
||||
double mid_z = 0.5 * (ret.first + ret.second);
|
||||
double half_size = 0.5 * FrustrumMinZRange;
|
||||
ret.first = mid_z - half_size;
|
||||
ret.second = mid_z + half_size;
|
||||
}
|
||||
|
||||
if (ret.first >= FrustrumMinNearZ)
|
||||
break;
|
||||
|
||||
// ensure min Near Z
|
||||
set_distance(m_distance + FrustrumMinNearZ - ret.first);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -385,21 +388,19 @@ double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int ca
|
||||
Vec3d up = get_dir_up();
|
||||
Vec3d forward = get_dir_forward();
|
||||
|
||||
Vec3d bb_min = box.min;
|
||||
Vec3d bb_max = box.max;
|
||||
Vec3d bb_center = box.center();
|
||||
|
||||
// box vertices in world space
|
||||
std::vector<Vec3d> vertices;
|
||||
vertices.reserve(8);
|
||||
vertices.push_back(bb_min);
|
||||
vertices.emplace_back(bb_max(0), bb_min(1), bb_min(2));
|
||||
vertices.emplace_back(bb_max(0), bb_max(1), bb_min(2));
|
||||
vertices.emplace_back(bb_min(0), bb_max(1), bb_min(2));
|
||||
vertices.emplace_back(bb_min(0), bb_min(1), bb_max(2));
|
||||
vertices.emplace_back(bb_max(0), bb_min(1), bb_max(2));
|
||||
vertices.push_back(bb_max);
|
||||
vertices.emplace_back(bb_min(0), bb_max(1), bb_max(2));
|
||||
vertices.push_back(box.min);
|
||||
vertices.emplace_back(box.max(0), box.min(1), box.min(2));
|
||||
vertices.emplace_back(box.max(0), box.max(1), box.min(2));
|
||||
vertices.emplace_back(box.min(0), box.max(1), box.min(2));
|
||||
vertices.emplace_back(box.min(0), box.min(1), box.max(2));
|
||||
vertices.emplace_back(box.max(0), box.min(1), box.max(2));
|
||||
vertices.push_back(box.max);
|
||||
vertices.emplace_back(box.min(0), box.max(1), box.max(2));
|
||||
|
||||
double max_x = 0.0;
|
||||
double max_y = 0.0;
|
||||
@ -430,6 +431,12 @@ double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int ca
|
||||
return std::min((double)canvas_w / (2.0 * max_x), (double)canvas_h / (2.0 * max_y));
|
||||
}
|
||||
|
||||
void Camera::set_distance(double distance) const
|
||||
{
|
||||
m_distance = distance;
|
||||
apply_view_matrix();
|
||||
}
|
||||
|
||||
} // GUI
|
||||
} // Slic3r
|
||||
|
||||
|
@ -10,10 +10,10 @@ namespace GUI {
|
||||
struct Camera
|
||||
{
|
||||
static const double DefaultDistance;
|
||||
static double FrustrumMinZSize;
|
||||
static double FrustrumMinZRange;
|
||||
static double FrustrumMinNearZ;
|
||||
static double FrustrumZMargin;
|
||||
static double FovMinDeg;
|
||||
static double FovMaxDeg;
|
||||
static double MaxFovDeg;
|
||||
|
||||
enum EType : unsigned char
|
||||
{
|
||||
@ -101,6 +101,7 @@ private:
|
||||
// the camera MUST be outside of the bounding box in eye coordinate of the given box
|
||||
std::pair<double, double> calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const;
|
||||
double calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h) const;
|
||||
void set_distance(double distance) const;
|
||||
};
|
||||
|
||||
} // GUI
|
||||
|
373
src/slic3r/GUI/ConfigManipulation.cpp
Normal file
@ -0,0 +1,373 @@
|
||||
// #include "libslic3r/GCodeSender.hpp"
|
||||
#include "ConfigManipulation.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
|
||||
#include <wx/msgdlg.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
void ConfigManipulation::apply(DynamicPrintConfig* config, DynamicPrintConfig* new_config)
|
||||
{
|
||||
bool modified = false;
|
||||
for (auto opt_key : config->diff(*new_config)) {
|
||||
config->set_key_value(opt_key, new_config->option(opt_key)->clone());
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (modified && load_config != nullptr)
|
||||
load_config();
|
||||
}
|
||||
|
||||
void ConfigManipulation::toggle_field(const std::string& opt_key, const bool toggle, int opt_index/* = -1*/)
|
||||
{
|
||||
if (local_config) {
|
||||
if (local_config->option(opt_key) == nullptr)
|
||||
return;
|
||||
}
|
||||
Field* field = get_field(opt_key, opt_index);
|
||||
if (field==nullptr) return;
|
||||
field->toggle(toggle);
|
||||
}
|
||||
|
||||
void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, const bool is_global_config)
|
||||
{
|
||||
// #ys_FIXME_to_delete
|
||||
//! Temporary workaround for the correct updates of the TextCtrl (like "layer_height"):
|
||||
// KillFocus() for the wxSpinCtrl use CallAfter function. So,
|
||||
// to except the duplicate call of the update() after dialog->ShowModal(),
|
||||
// let check if this process is already started.
|
||||
if (is_msg_dlg_already_exist)
|
||||
return;
|
||||
|
||||
// layer_height shouldn't be equal to zero
|
||||
if (config->opt_float("layer_height") < EPSILON)
|
||||
{
|
||||
const wxString msg_text = _(L("Zero layer height is not valid.\n\nThe layer height will be reset to 0.01."));
|
||||
auto dialog = new wxMessageDialog(nullptr, msg_text, _(L("Layer height")), wxICON_WARNING | wxOK);
|
||||
DynamicPrintConfig new_conf = *config;
|
||||
is_msg_dlg_already_exist = true;
|
||||
dialog->ShowModal();
|
||||
new_conf.set_key_value("layer_height", new ConfigOptionFloat(0.01));
|
||||
apply(config, &new_conf);
|
||||
is_msg_dlg_already_exist = false;
|
||||
}
|
||||
|
||||
if (fabs(config->option<ConfigOptionFloatOrPercent>("first_layer_height")->value - 0) < EPSILON)
|
||||
{
|
||||
const wxString msg_text = _(L("Zero first layer height is not valid.\n\nThe first layer height will be reset to 0.01."));
|
||||
auto dialog = new wxMessageDialog(nullptr, msg_text, _(L("First layer height")), wxICON_WARNING | wxOK);
|
||||
DynamicPrintConfig new_conf = *config;
|
||||
is_msg_dlg_already_exist = true;
|
||||
dialog->ShowModal();
|
||||
new_conf.set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(0.01, false));
|
||||
apply(config, &new_conf);
|
||||
is_msg_dlg_already_exist = false;
|
||||
}
|
||||
|
||||
double fill_density = config->option<ConfigOptionPercent>("fill_density")->value;
|
||||
|
||||
if (config->opt_bool("spiral_vase") &&
|
||||
!(config->opt_int("perimeters") == 1 && config->opt_int("top_solid_layers") == 0 &&
|
||||
fill_density == 0)) {
|
||||
wxString msg_text = _(L("The Spiral Vase mode requires:\n"
|
||||
"- one perimeter\n"
|
||||
"- no top solid layers\n"
|
||||
"- 0% fill density\n"
|
||||
"- no support material\n"
|
||||
"- no ensure_vertical_shell_thickness"));
|
||||
if (is_global_config)
|
||||
msg_text += "\n\n" + _(L("Shall I adjust those settings in order to enable Spiral Vase?"));
|
||||
auto dialog = new wxMessageDialog(nullptr, msg_text, _(L("Spiral Vase")),
|
||||
wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK));
|
||||
DynamicPrintConfig new_conf = *config;
|
||||
auto answer = dialog->ShowModal();
|
||||
if (!is_global_config || answer == wxID_YES) {
|
||||
new_conf.set_key_value("perimeters", new ConfigOptionInt(1));
|
||||
new_conf.set_key_value("top_solid_layers", new ConfigOptionInt(0));
|
||||
new_conf.set_key_value("fill_density", new ConfigOptionPercent(0));
|
||||
new_conf.set_key_value("support_material", new ConfigOptionBool(false));
|
||||
new_conf.set_key_value("support_material_enforce_layers", new ConfigOptionInt(0));
|
||||
new_conf.set_key_value("ensure_vertical_shell_thickness", new ConfigOptionBool(false));
|
||||
fill_density = 0;
|
||||
}
|
||||
else {
|
||||
new_conf.set_key_value("spiral_vase", new ConfigOptionBool(false));
|
||||
}
|
||||
apply(config, &new_conf);
|
||||
if (cb_value_change)
|
||||
cb_value_change("fill_density", fill_density);
|
||||
}
|
||||
|
||||
if (config->opt_bool("wipe_tower") && config->opt_bool("support_material") &&
|
||||
config->opt_float("support_material_contact_distance") > 0. &&
|
||||
(config->opt_int("support_material_extruder") != 0 || config->opt_int("support_material_interface_extruder") != 0)) {
|
||||
wxString msg_text = _(L("The Wipe Tower currently supports the non-soluble supports only\n"
|
||||
"if they are printed with the current extruder without triggering a tool change.\n"
|
||||
"(both support_material_extruder and support_material_interface_extruder need to be set to 0)."));
|
||||
if (is_global_config)
|
||||
msg_text += "\n\n" + _(L("Shall I adjust those settings in order to enable the Wipe Tower?"));
|
||||
auto dialog = new wxMessageDialog(nullptr, msg_text, _(L("Wipe Tower")),
|
||||
wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK));
|
||||
DynamicPrintConfig new_conf = *config;
|
||||
auto answer = dialog->ShowModal();
|
||||
if (!is_global_config || answer == wxID_YES) {
|
||||
new_conf.set_key_value("support_material_extruder", new ConfigOptionInt(0));
|
||||
new_conf.set_key_value("support_material_interface_extruder", new ConfigOptionInt(0));
|
||||
}
|
||||
else
|
||||
new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false));
|
||||
apply(config, &new_conf);
|
||||
}
|
||||
|
||||
if (config->opt_bool("wipe_tower") && config->opt_bool("support_material") &&
|
||||
config->opt_float("support_material_contact_distance") == 0 &&
|
||||
!config->opt_bool("support_material_synchronize_layers")) {
|
||||
wxString msg_text = _(L("For the Wipe Tower to work with the soluble supports, the support layers\n"
|
||||
"need to be synchronized with the object layers."));
|
||||
if (is_global_config)
|
||||
msg_text += "\n\n" + _(L("Shall I synchronize support layers in order to enable the Wipe Tower?"));
|
||||
auto dialog = new wxMessageDialog(nullptr, msg_text, _(L("Wipe Tower")),
|
||||
wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK));
|
||||
DynamicPrintConfig new_conf = *config;
|
||||
auto answer = dialog->ShowModal();
|
||||
if (!is_global_config || answer == wxID_YES) {
|
||||
new_conf.set_key_value("support_material_synchronize_layers", new ConfigOptionBool(true));
|
||||
}
|
||||
else
|
||||
new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false));
|
||||
apply(config, &new_conf);
|
||||
}
|
||||
|
||||
if (config->opt_bool("support_material")) {
|
||||
// Ask only once.
|
||||
if (!support_material_overhangs_queried) {
|
||||
support_material_overhangs_queried = true;
|
||||
if (!config->opt_bool("overhangs")/* != 1*/) {
|
||||
wxString msg_text = _(L("Supports work better, if the following feature is enabled:\n"
|
||||
"- Detect bridging perimeters"));
|
||||
if (is_global_config)
|
||||
msg_text += "\n\n" + _(L("Shall I adjust those settings for supports?"));
|
||||
auto dialog = new wxMessageDialog(nullptr, msg_text, _(L("Support Generator")),
|
||||
wxICON_WARNING | (is_global_config ? wxYES | wxNO | wxCANCEL : wxOK));
|
||||
DynamicPrintConfig new_conf = *config;
|
||||
auto answer = dialog->ShowModal();
|
||||
if (!is_global_config || answer == wxID_YES) {
|
||||
// Enable "detect bridging perimeters".
|
||||
new_conf.set_key_value("overhangs", new ConfigOptionBool(true));
|
||||
}
|
||||
else if (answer == wxID_NO) {
|
||||
// Do nothing, leave supports on and "detect bridging perimeters" off.
|
||||
}
|
||||
else if (answer == wxID_CANCEL) {
|
||||
// Disable supports.
|
||||
new_conf.set_key_value("support_material", new ConfigOptionBool(false));
|
||||
support_material_overhangs_queried = false;
|
||||
}
|
||||
apply(config, &new_conf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
support_material_overhangs_queried = false;
|
||||
}
|
||||
|
||||
if (config->option<ConfigOptionPercent>("fill_density")->value == 100) {
|
||||
auto fill_pattern = config->option<ConfigOptionEnum<InfillPattern>>("fill_pattern")->value;
|
||||
std::string str_fill_pattern = "";
|
||||
t_config_enum_values map_names = config->option<ConfigOptionEnum<InfillPattern>>("fill_pattern")->get_enum_values();
|
||||
for (auto it : map_names) {
|
||||
if (fill_pattern == it.second) {
|
||||
str_fill_pattern = it.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!str_fill_pattern.empty()) {
|
||||
const std::vector<std::string>& external_fill_pattern = config->def()->get("top_fill_pattern")->enum_values;
|
||||
bool correct_100p_fill = false;
|
||||
for (const std::string& fill : external_fill_pattern)
|
||||
{
|
||||
if (str_fill_pattern == fill)
|
||||
correct_100p_fill = true;
|
||||
}
|
||||
// get fill_pattern name from enum_labels for using this one at dialog_msg
|
||||
str_fill_pattern = _utf8(config->def()->get("fill_pattern")->enum_labels[fill_pattern]);
|
||||
if (!correct_100p_fill) {
|
||||
wxString msg_text = GUI::from_u8((boost::format(_utf8(L("The %1% infill pattern is not supposed to work at 100%% density."))) % str_fill_pattern).str());
|
||||
if (is_global_config)
|
||||
msg_text += "\n\n" + _(L("Shall I switch to rectilinear fill pattern?"));
|
||||
auto dialog = new wxMessageDialog(nullptr, msg_text, _(L("Infill")),
|
||||
wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK) );
|
||||
DynamicPrintConfig new_conf = *config;
|
||||
auto answer = dialog->ShowModal();
|
||||
if (!is_global_config || answer == wxID_YES) {
|
||||
new_conf.set_key_value("fill_pattern", new ConfigOptionEnum<InfillPattern>(ipRectilinear));
|
||||
fill_density = 100;
|
||||
}
|
||||
else
|
||||
fill_density = wxGetApp().preset_bundle->prints.get_selected_preset().config.option<ConfigOptionPercent>("fill_density")->value;
|
||||
new_conf.set_key_value("fill_density", new ConfigOptionPercent(fill_density));
|
||||
apply(config, &new_conf);
|
||||
if (cb_value_change)
|
||||
cb_value_change("fill_density", fill_density);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
|
||||
{
|
||||
bool have_perimeters = config->opt_int("perimeters") > 0;
|
||||
for (auto el : { "extra_perimeters", "ensure_vertical_shell_thickness", "thin_walls", "overhangs",
|
||||
"seam_position", "external_perimeters_first", "external_perimeter_extrusion_width",
|
||||
"perimeter_speed", "small_perimeter_speed", "external_perimeter_speed" })
|
||||
toggle_field(el, have_perimeters);
|
||||
|
||||
bool have_infill = config->option<ConfigOptionPercent>("fill_density")->value > 0;
|
||||
// infill_extruder uses the same logic as in Print::extruders()
|
||||
for (auto el : { "fill_pattern", "infill_every_layers", "infill_only_where_needed",
|
||||
"solid_infill_every_layers", "solid_infill_below_area", "infill_extruder" })
|
||||
toggle_field(el, have_infill);
|
||||
|
||||
bool have_solid_infill = config->opt_int("top_solid_layers") > 0 || config->opt_int("bottom_solid_layers") > 0;
|
||||
// solid_infill_extruder uses the same logic as in Print::extruders()
|
||||
for (auto el : { "top_fill_pattern", "bottom_fill_pattern", "infill_first", "solid_infill_extruder",
|
||||
"solid_infill_extrusion_width", "solid_infill_speed" })
|
||||
toggle_field(el, have_solid_infill);
|
||||
|
||||
for (auto el : { "fill_angle", "bridge_angle", "infill_extrusion_width",
|
||||
"infill_speed", "bridge_speed" })
|
||||
toggle_field(el, have_infill || have_solid_infill);
|
||||
|
||||
toggle_field("gap_fill_speed", have_perimeters && have_infill);
|
||||
|
||||
bool have_top_solid_infill = config->opt_int("top_solid_layers") > 0;
|
||||
for (auto el : { "top_infill_extrusion_width", "top_solid_infill_speed" })
|
||||
toggle_field(el, have_top_solid_infill);
|
||||
|
||||
bool have_default_acceleration = config->opt_float("default_acceleration") > 0;
|
||||
for (auto el : { "perimeter_acceleration", "infill_acceleration",
|
||||
"bridge_acceleration", "first_layer_acceleration" })
|
||||
toggle_field(el, have_default_acceleration);
|
||||
|
||||
bool have_skirt = config->opt_int("skirts") > 0 || config->opt_float("min_skirt_length") > 0;
|
||||
for (auto el : { "skirt_distance", "skirt_height" })
|
||||
toggle_field(el, have_skirt);
|
||||
|
||||
bool have_brim = config->opt_float("brim_width") > 0;
|
||||
// perimeter_extruder uses the same logic as in Print::extruders()
|
||||
toggle_field("perimeter_extruder", have_perimeters || have_brim);
|
||||
|
||||
bool have_raft = config->opt_int("raft_layers") > 0;
|
||||
bool have_support_material = config->opt_bool("support_material") || have_raft;
|
||||
bool have_support_material_auto = have_support_material && config->opt_bool("support_material_auto");
|
||||
bool have_support_interface = config->opt_int("support_material_interface_layers") > 0;
|
||||
bool have_support_soluble = have_support_material && config->opt_float("support_material_contact_distance") == 0;
|
||||
for (auto el : { "support_material_pattern", "support_material_with_sheath",
|
||||
"support_material_spacing", "support_material_angle", "support_material_interface_layers",
|
||||
"dont_support_bridges", "support_material_extrusion_width", "support_material_contact_distance",
|
||||
"support_material_xy_spacing" })
|
||||
toggle_field(el, have_support_material);
|
||||
toggle_field("support_material_threshold", have_support_material_auto);
|
||||
|
||||
for (auto el : { "support_material_interface_spacing", "support_material_interface_extruder",
|
||||
"support_material_interface_speed", "support_material_interface_contact_loops" })
|
||||
toggle_field(el, have_support_material && have_support_interface);
|
||||
toggle_field("support_material_synchronize_layers", have_support_soluble);
|
||||
|
||||
toggle_field("perimeter_extrusion_width", have_perimeters || have_skirt || have_brim);
|
||||
toggle_field("support_material_extruder", have_support_material || have_skirt);
|
||||
toggle_field("support_material_speed", have_support_material || have_brim || have_skirt);
|
||||
|
||||
bool have_sequential_printing = config->opt_bool("complete_objects");
|
||||
for (auto el : { "extruder_clearance_radius", "extruder_clearance_height" })
|
||||
toggle_field(el, have_sequential_printing);
|
||||
|
||||
bool have_ooze_prevention = config->opt_bool("ooze_prevention");
|
||||
toggle_field("standby_temperature_delta", have_ooze_prevention);
|
||||
|
||||
bool have_wipe_tower = config->opt_bool("wipe_tower");
|
||||
for (auto el : { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging" })
|
||||
toggle_field(el, have_wipe_tower);
|
||||
}
|
||||
|
||||
void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/)
|
||||
{
|
||||
double head_penetration = config->opt_float("support_head_penetration");
|
||||
double head_width = config->opt_float("support_head_width");
|
||||
if (head_penetration > head_width) {
|
||||
wxString msg_text = _(L("Head penetration should not be greater than the head width."));
|
||||
|
||||
auto dialog = new wxMessageDialog(nullptr,
|
||||
msg_text,
|
||||
_(L("Invalid Head penetration")),
|
||||
wxICON_WARNING | wxOK);
|
||||
|
||||
DynamicPrintConfig new_conf = *config;
|
||||
if (dialog->ShowModal() == wxID_OK) {
|
||||
new_conf.set_key_value("support_head_penetration", new ConfigOptionFloat(head_width));
|
||||
apply(config, &new_conf);
|
||||
}
|
||||
}
|
||||
|
||||
double pinhead_d = config->opt_float("support_head_front_diameter");
|
||||
double pillar_d = config->opt_float("support_pillar_diameter");
|
||||
if (pinhead_d > pillar_d) {
|
||||
wxString msg_text = _(L("Pinhead diameter should be smaller than the pillar diameter."));
|
||||
|
||||
auto dialog = new wxMessageDialog(nullptr,
|
||||
msg_text,
|
||||
_(L("Invalid pinhead diameter")),
|
||||
wxICON_WARNING | wxOK);
|
||||
|
||||
DynamicPrintConfig new_conf = *config;
|
||||
if (dialog->ShowModal() == wxID_OK) {
|
||||
new_conf.set_key_value("support_head_front_diameter", new ConfigOptionFloat(pillar_d / 2.0));
|
||||
apply(config, &new_conf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigManipulation::toggle_print_sla_options(DynamicPrintConfig* config)
|
||||
{
|
||||
bool supports_en = config->opt_bool("supports_enable");
|
||||
|
||||
toggle_field("support_head_front_diameter", supports_en);
|
||||
toggle_field("support_head_penetration", supports_en);
|
||||
toggle_field("support_head_width", supports_en);
|
||||
toggle_field("support_pillar_diameter", supports_en);
|
||||
toggle_field("support_pillar_connection_mode", supports_en);
|
||||
toggle_field("support_buildplate_only", supports_en);
|
||||
toggle_field("support_base_diameter", supports_en);
|
||||
toggle_field("support_base_height", supports_en);
|
||||
toggle_field("support_base_safety_distance", supports_en);
|
||||
toggle_field("support_critical_angle", supports_en);
|
||||
toggle_field("support_max_bridge_length", supports_en);
|
||||
toggle_field("support_max_pillar_link_distance", supports_en);
|
||||
toggle_field("support_points_density_relative", supports_en);
|
||||
toggle_field("support_points_minimal_distance", supports_en);
|
||||
|
||||
bool pad_en = config->opt_bool("pad_enable");
|
||||
|
||||
toggle_field("pad_wall_thickness", pad_en);
|
||||
toggle_field("pad_wall_height", pad_en);
|
||||
toggle_field("pad_max_merge_distance", pad_en);
|
||||
// toggle_field("pad_edge_radius", supports_en);
|
||||
toggle_field("pad_wall_slope", pad_en);
|
||||
toggle_field("pad_zero_elevation", pad_en);
|
||||
|
||||
bool has_suppad = pad_en && supports_en;
|
||||
bool zero_elev = config->opt_bool("pad_zero_elevation") && has_suppad;
|
||||
|
||||
toggle_field("support_object_elevation", supports_en && !zero_elev);
|
||||
toggle_field("pad_object_gap", zero_elev);
|
||||
toggle_field("pad_object_connector_stride", zero_elev);
|
||||
toggle_field("pad_object_connector_width", zero_elev);
|
||||
toggle_field("pad_object_connector_penetration", zero_elev);
|
||||
}
|
||||
|
||||
|
||||
} // GUI
|
||||
} // Slic3r
|
62
src/slic3r/GUI/ConfigManipulation.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
#ifndef slic3r_ConfigManipulation_hpp_
|
||||
#define slic3r_ConfigManipulation_hpp_
|
||||
|
||||
/* Class for validation config options
|
||||
* and update (enable/disable) IU components
|
||||
*
|
||||
* Used for config validation for global config (Print Settings Tab)
|
||||
* and local config (overrides options on sidebar)
|
||||
* */
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "Field.hpp"
|
||||
//#include <boost-1_70/boost/any.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class ConfigManipulation
|
||||
{
|
||||
bool is_msg_dlg_already_exist{ false };
|
||||
bool support_material_overhangs_queried{ false };
|
||||
|
||||
// function to loading of changed configuration
|
||||
std::function<void()> load_config = nullptr;
|
||||
std::function<Field* (const std::string&, int opt_index)> get_field = nullptr;
|
||||
// callback to propagation of changed value, if needed
|
||||
std::function<void(const std::string&, const boost::any&)> cb_value_change = nullptr;
|
||||
DynamicPrintConfig* local_config = nullptr;
|
||||
|
||||
public:
|
||||
ConfigManipulation(std::function<void()> load_config,
|
||||
std::function<Field* (const std::string&, int opt_index)> get_field,
|
||||
std::function<void(const std::string&, const boost::any&)> cb_value_change,
|
||||
DynamicPrintConfig* local_config = nullptr) :
|
||||
load_config(load_config),
|
||||
get_field(get_field),
|
||||
cb_value_change(cb_value_change),
|
||||
local_config(local_config) {}
|
||||
ConfigManipulation() {}
|
||||
|
||||
~ConfigManipulation() {
|
||||
load_config = nullptr;
|
||||
get_field = nullptr;
|
||||
cb_value_change = nullptr;
|
||||
}
|
||||
|
||||
void apply(DynamicPrintConfig* config, DynamicPrintConfig* new_config);
|
||||
void toggle_field(const std::string& field_key, const bool toggle, int opt_index = -1);
|
||||
|
||||
// FFF print
|
||||
void update_print_fff_config(DynamicPrintConfig* config, const bool is_global_config = false);
|
||||
void toggle_print_fff_options(DynamicPrintConfig* config);
|
||||
|
||||
// SLA print
|
||||
void update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config = false);
|
||||
void toggle_print_sla_options(DynamicPrintConfig* config);
|
||||
};
|
||||
|
||||
} // GUI
|
||||
} // Slic3r
|
||||
|
||||
#endif /* slic3r_ConfigManipulation_hpp_ */
|
@ -25,6 +25,7 @@
|
||||
#include "PresetBundle.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "slic3r/Config/Snapshot.hpp"
|
||||
#include "slic3r/Utils/PresetUpdater.hpp"
|
||||
|
||||
|
||||
@ -33,6 +34,10 @@ namespace GUI {
|
||||
|
||||
#define MAIN_VENDOR "None"
|
||||
|
||||
using Config::Snapshot;
|
||||
using Config::SnapshotDB;
|
||||
|
||||
|
||||
// Printer model picker GUI control
|
||||
|
||||
struct PrinterPickerEvent : public wxEvent
|
||||
@ -1001,15 +1006,33 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
||||
|
||||
// Decide whether to create snapshot based on run_reason and the reset profile checkbox
|
||||
bool snapshot = true;
|
||||
Snapshot::Reason snapshot_reason = Snapshot::SNAPSHOT_UPGRADE;
|
||||
switch (run_reason) {
|
||||
case ConfigWizard::RR_DATA_EMPTY: snapshot = false; break;
|
||||
case ConfigWizard::RR_DATA_LEGACY: snapshot = true; break;
|
||||
case ConfigWizard::RR_DATA_INCOMPAT: snapshot = false; break; // In this case snapshot is done by PresetUpdater with the appropriate reason
|
||||
case ConfigWizard::RR_USER: snapshot = page_welcome->reset_user_profile(); break;
|
||||
case ConfigWizard::RR_DATA_EMPTY:
|
||||
snapshot = false;
|
||||
break;
|
||||
case ConfigWizard::RR_DATA_LEGACY:
|
||||
snapshot = true;
|
||||
break;
|
||||
case ConfigWizard::RR_DATA_INCOMPAT:
|
||||
// In this case snapshot has already been taken by
|
||||
// PresetUpdater with the appropriate reason
|
||||
snapshot = false;
|
||||
break;
|
||||
case ConfigWizard::RR_USER:
|
||||
snapshot = page_welcome->reset_user_profile();
|
||||
snapshot_reason = Snapshot::SNAPSHOT_USER;
|
||||
break;
|
||||
}
|
||||
|
||||
if (snapshot) {
|
||||
SnapshotDB::singleton().take_snapshot(*app_config, snapshot_reason);
|
||||
}
|
||||
|
||||
if (install_bundles.size() > 0) {
|
||||
// Install bundles from resources.
|
||||
updater->install_bundles_rsrc(std::move(install_bundles), snapshot);
|
||||
// Don't create snapshot - we've already done that above if applicable.
|
||||
updater->install_bundles_rsrc(std::move(install_bundles), false);
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << "No bundles need to be installed from resources";
|
||||
}
|
||||
|
@ -206,8 +206,8 @@ void Field::get_value_by_opt_type(wxString& str)
|
||||
const wxString msg_text = wxString::Format(_(L("Do you mean %s%% instead of %s %s?\n"
|
||||
"Select YES if you want to change this value to %s%%, \n"
|
||||
"or NO if you are sure that %s %s is a correct value.")), stVal, stVal, sidetext, stVal, stVal, sidetext);
|
||||
auto dialog = new wxMessageDialog(m_parent, msg_text, _(L("Parameter validation")), wxICON_WARNING | wxYES | wxNO);
|
||||
if (dialog->ShowModal() == wxID_YES) {
|
||||
wxMessageDialog dialog(m_parent, msg_text, _(L("Parameter validation")), wxICON_WARNING | wxYES | wxNO);
|
||||
if (dialog.ShowModal() == wxID_YES) {
|
||||
set_value(wxString::Format("%s%%", stVal), false/*true*/);
|
||||
str += "%%";
|
||||
}
|
||||
@ -393,6 +393,12 @@ void TextCtrl::set_value(const boost::any& value, bool change_event/* = false*/)
|
||||
else
|
||||
dynamic_cast<wxTextCtrl*>(window)->SetValue(boost::any_cast<wxString>(value));
|
||||
m_disable_change_event = false;
|
||||
|
||||
if (!change_event) {
|
||||
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue();
|
||||
// update m_value to correct work of next value_was_changed()
|
||||
get_value_by_opt_type(ret_str);
|
||||
}
|
||||
}
|
||||
|
||||
void TextCtrl::set_last_meaningful_value()
|
||||
@ -410,7 +416,7 @@ void TextCtrl::set_na_value()
|
||||
boost::any& TextCtrl::get_value()
|
||||
{
|
||||
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue();
|
||||
// modifies ret_string!
|
||||
// update m_value
|
||||
get_value_by_opt_type(ret_str);
|
||||
|
||||
return m_value;
|
||||
@ -553,7 +559,16 @@ void SpinCtrl::BUILD() {
|
||||
break;
|
||||
}
|
||||
|
||||
const int min_val = m_opt.min == INT_MIN ? 0: m_opt.min;
|
||||
const int min_val = m_opt.min == INT_MIN
|
||||
#ifdef __WXOSX__
|
||||
// We will forcibly set the input value for SpinControl, since the value
|
||||
// inserted from the keyboard is not updated under OSX.
|
||||
// So, we can't set min control value bigger then 0.
|
||||
// Otherwise, it couldn't be possible to input from keyboard value
|
||||
// less then min_val.
|
||||
|| m_opt.min > 0
|
||||
#endif
|
||||
? 0 : m_opt.min;
|
||||
const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647;
|
||||
|
||||
auto temp = new wxSpinCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size,
|
||||
@ -622,11 +637,24 @@ void SpinCtrl::BUILD() {
|
||||
|
||||
void SpinCtrl::propagate_value()
|
||||
{
|
||||
if (suppress_propagation)
|
||||
return;
|
||||
|
||||
suppress_propagation = true;
|
||||
if (tmp_value == UNDEF_VALUE) {
|
||||
on_kill_focus();
|
||||
} else {
|
||||
#ifdef __WXOSX__
|
||||
// check input value for minimum
|
||||
if (m_opt.min > 0 && tmp_value < m_opt.min) {
|
||||
wxSpinCtrl* spin = static_cast<wxSpinCtrl*>(window);
|
||||
spin->SetValue(m_opt.min);
|
||||
spin->GetText()->SetInsertionPointEnd();
|
||||
}
|
||||
#endif
|
||||
on_change_field();
|
||||
}
|
||||
suppress_propagation = false;
|
||||
}
|
||||
|
||||
void SpinCtrl::msw_rescale()
|
||||
@ -946,7 +974,7 @@ boost::any& Choice::get_value()
|
||||
wxString ret_str = field->GetValue();
|
||||
|
||||
// options from right panel
|
||||
std::vector <std::string> right_panel_options{ "support", "scale_unit" };
|
||||
std::vector <std::string> right_panel_options{ "support", "pad", "scale_unit" };
|
||||
for (auto rp_option: right_panel_options)
|
||||
if (m_opt_id == rp_option)
|
||||
return m_value = boost::any(ret_str);
|
||||
@ -1050,11 +1078,12 @@ void ColourPicker::BUILD()
|
||||
// Validate the color
|
||||
wxString clr_str(m_opt.get_default_value<ConfigOptionStrings>()->get_at(m_opt_idx));
|
||||
wxColour clr(clr_str);
|
||||
if (! clr.IsOk()) {
|
||||
if (clr_str.IsEmpty() || !clr.IsOk()) {
|
||||
clr = wxTransparentColour;
|
||||
}
|
||||
|
||||
auto temp = new wxColourPickerCtrl(m_parent, wxID_ANY, clr, wxDefaultPosition, size);
|
||||
temp->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
temp->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
|
||||
// // recast as a wxWindow to fit the calling convention
|
||||
@ -1065,17 +1094,60 @@ void ColourPicker::BUILD()
|
||||
temp->SetToolTip(get_tooltip_text(clr_str));
|
||||
}
|
||||
|
||||
void ColourPicker::set_undef_value(wxColourPickerCtrl* field)
|
||||
{
|
||||
field->SetColour(wxTransparentColour);
|
||||
|
||||
wxButton* btn = dynamic_cast<wxButton*>(field->GetPickerCtrl());
|
||||
wxBitmap bmp = btn->GetBitmap();
|
||||
wxMemoryDC dc(bmp);
|
||||
if (!dc.IsOk()) return;
|
||||
dc.SetTextForeground(*wxWHITE);
|
||||
dc.SetFont(wxGetApp().normal_font());
|
||||
|
||||
const wxRect rect = wxRect(0, 0, bmp.GetWidth(), bmp.GetHeight());
|
||||
dc.DrawLabel("undef", rect, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
btn->SetBitmapLabel(bmp);
|
||||
}
|
||||
|
||||
void ColourPicker::set_value(const boost::any& value, bool change_event)
|
||||
{
|
||||
m_disable_change_event = !change_event;
|
||||
const wxString clr_str(boost::any_cast<wxString>(value));
|
||||
auto field = dynamic_cast<wxColourPickerCtrl*>(window);
|
||||
|
||||
wxColour clr(clr_str);
|
||||
if (clr_str.IsEmpty() || !clr.IsOk())
|
||||
set_undef_value(field);
|
||||
else
|
||||
field->SetColour(clr);
|
||||
|
||||
m_disable_change_event = false;
|
||||
}
|
||||
|
||||
boost::any& ColourPicker::get_value()
|
||||
{
|
||||
// boost::any m_value;
|
||||
|
||||
auto colour = static_cast<wxColourPickerCtrl*>(window)->GetColour();
|
||||
auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), colour.Red(), colour.Green(), colour.Blue());
|
||||
m_value = clr_str.ToStdString();
|
||||
|
||||
if (colour == wxTransparentColour)
|
||||
m_value = std::string("");
|
||||
else {
|
||||
auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), colour.Red(), colour.Green(), colour.Blue());
|
||||
m_value = clr_str.ToStdString();
|
||||
}
|
||||
return m_value;
|
||||
}
|
||||
|
||||
void ColourPicker::msw_rescale()
|
||||
{
|
||||
Field::msw_rescale();
|
||||
|
||||
wxColourPickerCtrl* field = dynamic_cast<wxColourPickerCtrl*>(window);
|
||||
if (field->GetColour() == wxTransparentColour)
|
||||
set_undef_value(field);
|
||||
}
|
||||
|
||||
void PointCtrl::BUILD()
|
||||
{
|
||||
auto temp = new wxBoxSizer(wxHORIZONTAL);
|
||||
|