post changes after merging BS1.7.4

Remove tracking etc..
This commit is contained in:
SoftFever 2023-08-26 18:24:13 +08:00
parent e65b11a831
commit 2a478ab4f9
615 changed files with 46215 additions and 54844 deletions

View file

@ -3,14 +3,11 @@
#include <string>
#include <sstream>
#include <iostream>
#include <mutex>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/log/trivial.hpp>
#include <boost/format.hpp>
#define slic3r_Semver_hpp_
#define _libslic3r_h_
#include <libslic3r/Utils.hpp>
#include <mutex>
static std::string g_log_folder;
static std::atomic<int> g_crash_log_count = 0;
@ -108,127 +105,127 @@ void CBaseException::ShowExceptionResoult(DWORD dwExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
{
//OutputString(_T("ACCESS_VIOLATION(%s)\r\n"), _T("读写非法内存"));
//OutputString(_T("ACCESS_VIOLATION(%s)\r\n"), _T("<EFBFBD><EFBFBD>д<EFBFBD>Ƿ<EFBFBD><EFBFBD>ڴ<EFBFBD>"));
OutputString(_T("ACCESS_VIOLATION\r\n"));
}
return ;
case EXCEPTION_DATATYPE_MISALIGNMENT:
{
//OutputString(_T("DATATYPE_MISALIGNMENT(%s)\r\n"), _T("线程视图在不支持对齐的硬件上读写未对齐的数据"));
//OutputString(_T("DATATYPE_MISALIGNMENT(%s)\r\n"), _T("<EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD>ڲ<EFBFBD>֧<EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD>дδ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
OutputString(_T("DATATYPE_MISALIGNMENT\r\n"));
}
return ;
case EXCEPTION_BREAKPOINT:
{
//OutputString(_T("BREAKPOINT(%s)\r\n"), _T("遇到一个断点"));
//OutputString(_T("BREAKPOINT(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>"));
OutputString(_T("BREAKPOINT\r\n"));
}
return ;
case EXCEPTION_SINGLE_STEP:
{
//OutputString(_T("SINGLE_STEP(%s)\r\n"), _T("单步")); //一般是发生在调试事件中
//OutputString(_T("SINGLE_STEP(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>")); //һ<><D2BB><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>
OutputString(_T("SINGLE_STEP\r\n"));
}
return ;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
{
//OutputString(_T("ARRAY_BOUNDS_EXCEEDED(%s)\r\n"), _T("数组访问越界"));
//OutputString(_T("ARRAY_BOUNDS_EXCEEDED(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><EFBFBD>"));
OutputString(_T("ARRAY_BOUNDS_EXCEEDED\r\n"));
}
return ;
case EXCEPTION_FLT_DENORMAL_OPERAND:
{
//OutputString(_T("FLT_DENORMAL_OPERAND(%s)\r\n"), _T("浮点操作的一个操作数不正规,给定的浮点数无法表示")); //操作数的问题
//OutputString(_T("FLT_DENORMAL_OPERAND(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD><EFBFBD><EFBFBD>ʾ")); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
OutputString(_T("FLT_DENORMAL_OPERAND\r\n"));
}
return ;
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
{
//OutputString(_T("FLT_DIVIDE_BY_ZERO(%s)\r\n"), _T("浮点数除0操作"));
//OutputString(_T("FLT_DIVIDE_BY_ZERO(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
OutputString(_T("FLT_DIVIDE_BY_ZERO\r\n"));
}
return ;
case EXCEPTION_FLT_INEXACT_RESULT:
{
//OutputString(_T("FLT_INEXACT_RESULT(%s)\r\n"), _T("浮点数操作的结果无法表示")); //无法表示一般是数据太小,超过浮点数表示的范围, 计算之后产生的结果异常
//OutputString(_T("FLT_INEXACT_RESULT(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD><EFBFBD><EFBFBD>ʾ")); //<2F>޷<EFBFBD><DEB7><EFBFBD>ʾһ<CABE><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̫С<CCAB><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>ķ<EFBFBD>Χ, <20><><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><C4BD><EFBFBD>
OutputString(_T("FLT_INEXACT_RESULT\r\n"));
}
return ;
case EXCEPTION_FLT_INVALID_OPERATION:
{
//OutputString(_T("FLT_INVALID_OPERATION(%s)\r\n"), _T("其他浮点数异常"));
//OutputString(_T("FLT_INVALID_OPERATION(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
OutputString(_T("FLT_INVALID_OPERATION\r\n"));
}
return ;
case EXCEPTION_FLT_OVERFLOW:
{
//OutputString(_T("FLT_OVERFLOW(%s)\r\n"), _T("浮点操作的指数超过了相应类型的最大值"));
//OutputString(_T("FLT_OVERFLOW(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ"));
OutputString(_T("FLT_OVERFLOW\r\n"));
}
return ;
case EXCEPTION_FLT_STACK_CHECK:
{
//OutputString(_T("STACK_CHECK(%s)\r\n"), _T("栈越界或者栈向下溢出"));
//OutputString(_T("STACK_CHECK(%s)\r\n"), _T("ջԽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
OutputString(_T("STACK_CHECK\r\n"));
}
return ;
case EXCEPTION_INT_DIVIDE_BY_ZERO:
{
//OutputString(_T("INT_DIVIDE_BY_ZERO(%s)\r\n"), _T("整数除0异常"));
//OutputString(_T("INT_DIVIDE_BY_ZERO(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0<EFBFBD>"));
OutputString(_T("INT_DIVIDE_BY_ZERO\r\n"));
}
return ;
case EXCEPTION_INVALID_HANDLE:
{
//OutputString(_T("INVALID_HANDLE(%s)\r\n"), _T("句柄无效"));
//OutputString(_T("INVALID_HANDLE(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч"));
OutputString(_T("INVALID_HANDLE\r\n"));
}
return ;
case EXCEPTION_PRIV_INSTRUCTION:
{
//OutputString(_T("PRIV_INSTRUCTION(%s)\r\n"), _T("线程试图执行当前机器模式不支持的指令"));
//OutputString(_T("PRIV_INSTRUCTION(%s)\r\n"), _T("<EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD>ͼִ<EFBFBD>е<EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD>֧<EFBFBD>ֵ<EFBFBD>ָ<EFBFBD><EFBFBD>"));
OutputString(_T("PRIV_INSTRUCTION\r\n"));
}
return ;
case EXCEPTION_IN_PAGE_ERROR:
{
//OutputString(_T("IN_PAGE_ERROR(%s)\r\n"), _T("线程视图访问未加载的虚拟内存页或者不能加载的虚拟内存页"));
//OutputString(_T("IN_PAGE_ERROR(%s)\r\n"), _T("<EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD>߲<EFBFBD><EFBFBD>ܼ<EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ҳ"));
OutputString(_T("IN_PAGE_ERROR\r\n"));
}
return ;
case EXCEPTION_ILLEGAL_INSTRUCTION:
{
//OutputString(_T("ILLEGAL_INSTRUCTION(%s)\r\n"), _T("线程视图执行无效指令"));
//OutputString(_T("ILLEGAL_INSTRUCTION(%s)\r\n"), _T("<EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD>ͼִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Чָ<EFBFBD><EFBFBD>"));
OutputString(_T("ILLEGAL_INSTRUCTION\r\n"));
}
return ;
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
{
//OutputString(_T("NONCONTINUABLE_EXCEPTION(%s)\r\n"), _T("线程试图在一个不可继续执行的异常发生后继续执行"));
//OutputString(_T("NONCONTINUABLE_EXCEPTION(%s)\r\n"), _T("<EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɼ<EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD>"));
OutputString(_T("NONCONTINUABLE_EXCEPTION\r\n"));
}
return ;
case EXCEPTION_STACK_OVERFLOW:
{
//OutputString(_T("STACK_OVERFLOW(%s)\r\n"), _T("栈溢出"));
//OutputString(_T("STACK_OVERFLOW(%s)\r\n"), _T("ջ<EFBFBD><EFBFBD><EFBFBD>"));
OutputString(_T("STACK_OVERFLOW\r\n"));
}
return ;
case EXCEPTION_INVALID_DISPOSITION:
{
//OutputString(_T("INVALID_DISPOSITION(%s)\r\n"), _T("异常处理程序给异常调度器返回了一个无效配置")); //使用高级语言编写的程序永远不会遇到这个异常
//OutputString(_T("INVALID_DISPOSITION(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD><EFBFBD>")); //ʹ<>ø߼<C3B8><DFBC><EFBFBD><EFBFBD>Ա<EFBFBD>д<EFBFBD>ij<EFBFBD><C4B3><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
OutputString(_T("INVALID_DISPOSITION\r\n"));
}
return ;
case EXCEPTION_FLT_UNDERFLOW:
{
//OutputString(_T("FLT_UNDERFLOW(%s)\r\n"), _T("浮点数操作的指数小于相应类型的最小值"));
//OutputString(_T("FLT_UNDERFLOW(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD>Сֵ"));
OutputString(_T("FLT_UNDERFLOW\r\n"));
}
return ;
case EXCEPTION_INT_OVERFLOW:
{
//OutputString(_T("INT_OVERFLOW(%s)\r\n"), _T("整数操作越界"));
//OutputString(_T("INT_OVERFLOW(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><EFBFBD>"));
OutputString(_T("INT_OVERFLOW\r\n"));
}
return ;
@ -257,7 +254,6 @@ LONG WINAPI CBaseException::UnhandledExceptionFilter(PEXCEPTION_POINTERS pExcept
//BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": got an ExceptionCode %1%, skip it!") % pExceptionInfo->ExceptionRecord->ExceptionCode;
return EXCEPTION_CONTINUE_SEARCH;
}
Slic3r::flush_logs();
g_dump_mutex.lock();
CBaseException base(GetCurrentProcess(), GetCurrentProcessId(), NULL, pExceptionInfo);
base.ShowExceptionInformation();
@ -296,7 +292,7 @@ BOOL CBaseException::GetLogicalAddress(
DWORD rva = (DWORD)addr - hMod;
//计算当前地址在第几个节
//<EFBFBD><EFBFBD><EFBFBD>㵱ǰ<EFBFBD><EFBFBD>ַ<EFBFBD>ڵڼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (unsigned i = 0; i < pNtHdr->FileHeader.NumberOfSections; i++, pSection++ )
{
DWORD sectionStart = pSection->VirtualAddress;

View file

@ -248,12 +248,6 @@ else ()
COMMAND ln -sfn "${SLIC3R_RESOURCES_DIR}" "${BIN_RESOURCES_DIR}"
COMMENT "Symlinking the resources directory into the build tree"
VERBATIM)
if (UNIX AND NOT APPLE)
add_custom_command(TARGET BambuStudio POST_BUILD
COMMAND ln -sfn "zh_cn" "${BIN_RESOURCES_DIR}/i18n/zh_CN"
COMMENT "Symlinking zh_CN language setting to zh_cn"
VERBATIM)
endif()
endif ()
# Slic3r binary install target. Default build type is release in case no CMAKE_BUILD_TYPE is provided.

File diff suppressed because it is too large Load diff

View file

@ -46,7 +46,6 @@ private:
bool has_print_action() const { return m_config.opt_bool("export_gcode") || m_config.opt_bool("export_sla"); }
std::string output_filepath(const Model &model, IO::ExportFormat format) const;
std::string output_filepath(const ModelObject &object, unsigned int index, IO::ExportFormat format) const;
};
}

View file

@ -38,7 +38,7 @@ CStackWalker::~CStackWalker(void)
BOOL CStackWalker::LoadSymbol()
{
//USES_CONVERSION;
//只加载一次
//只加载一次
if(m_bSymbolLoaded)
{
return m_bSymbolLoaded;
@ -51,11 +51,11 @@ BOOL CStackWalker::LoadSymbol()
return m_bSymbolLoaded;
}
//添加当前程序路径
//添加当前程序路径
TCHAR szSymbolPath[MAX_SYMBOL_PATH] = _T("");
StringCchCopy(szSymbolPath, MAX_SYMBOL_PATH, _T(".;"));
//添加程序所在目录
//添加程序所在目录
TCHAR szTemp[MAX_PATH] = _T("");
if (GetCurrentDirectory(MAX_PATH, szTemp) > 0)
{
@ -63,7 +63,7 @@ BOOL CStackWalker::LoadSymbol()
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T(";"));
}
//添加程序主模块所在路径
//添加程序主模块所在路径
ZeroMemory(szTemp, MAX_PATH * sizeof(TCHAR));
if (GetModuleFileName(NULL, szTemp, MAX_PATH) > 0)
{
@ -131,7 +131,7 @@ BOOL CStackWalker::LoadSymbol()
if (NULL != m_lpszSymbolPath)
{
m_bSymbolLoaded = SymInitialize(m_hProcess, textconv_helper::T2A_(m_lpszSymbolPath), TRUE); //这里设置为TRUE让它在初始化符号表的同时加载符号表
m_bSymbolLoaded = SymInitialize(m_hProcess, textconv_helper::T2A_(m_lpszSymbolPath), TRUE); //这里设置为TRUE让它在初始化符号表的同时加载符号表
}
DWORD symOptions = SymGetOptions();
@ -167,7 +167,7 @@ void CStackWalker::FreeModuleInformations(LPMODULE_INFO pmi)
LPMODULE_INFO CStackWalker::GetModulesTH32()
{
//这里为了防止加载Toolhelp.dll 影响最终结果,所以采用动态加载的方式
//这里为了防止加载Toolhelp.dll 影响最终结果,所以采用动态加载的方式
LPMODULE_INFO pHead = NULL;
LPMODULE_INFO pTail = pHead;
@ -391,13 +391,13 @@ void CStackWalker::GetModuleInformation(LPMODULE_INFO pmi)
LPSTACKINFO CStackWalker::StackWalker(HANDLE hThread, const CONTEXT* context)
{
//USES_CONVERSION;
//加载符号表
//加载符号表
LoadSymbol();
LPSTACKINFO pHead = NULL;
LPSTACKINFO pTail = pHead;
//获取当前线程的上下文环境
//获取当前线程的上下文环境
CONTEXT c = {0};
if (context == NULL)
{
@ -411,7 +411,7 @@ LPSTACKINFO CStackWalker::StackWalker(HANDLE hThread, const CONTEXT* context)
}
else
{
//如果不是当前线程,需要停止目标线程,以便取出正确的堆栈信息
//如果不是当前线程,需要停止目标线程,以便取出正确的堆栈信息
SuspendThread(hThread);
memset(&c, 0, sizeof(CONTEXT));
c.ContextFlags = CONTEXT_FULL;
@ -446,7 +446,7 @@ LPSTACKINFO CStackWalker::StackWalker(HANDLE hThread, const CONTEXT* context)
sf.AddrFrame.Mode = AddrModeFlat;
sf.AddrStack.Offset = c.Rsp;
sf.AddrStack.Mode = AddrModeFlat;
////intel Itanium(安腾)
////intel Itanium(安腾)
#elif _M_IA64
imageType = IMAGE_FILE_MACHINE_IA64;
sf.AddrPC.Offset = c.StIIP;
@ -490,7 +490,7 @@ LPSTACKINFO CStackWalker::StackWalker(HANDLE hThread, const CONTEXT* context)
StringCchCopy(pCallStack->undName, STACKWALK_MAX_NAMELEN, textconv_helper::A2T_(szName));
}else
{
//调用错误一般是487(地址无效或者没有访问的权限、在符号表中未找到指定地址的相关信息)
//调用错误一般是487(地址无效或者没有访问的权限、在符号表中未找到指定地址的相关信息)
this->OutputString(_T("Call SymGetSymFromAddr64 ,Address %08x Error:%08x\r\n"), sf.AddrPC.Offset, GetLastError());
continue;
}
@ -505,7 +505,7 @@ LPSTACKINFO CStackWalker::StackWalker(HANDLE hThread, const CONTEXT* context)
continue;
}
//这里为了将获取函数信息失败的情况与正常的情况一起输出,防止用户在查看时出现误解
//这里为了将获取函数信息失败的情况与正常的情况一起输出,防止用户在查看时出现误解
this->OutputString(_T("%08llx:%s [%s][%ld]\r\n"), pCallStack->szFncAddr, pCallStack->undFullName, pCallStack->szFileName, pCallStack->uFileNum);
if (NULL == pHead)
{

View file

@ -84,7 +84,6 @@ public:
//BBS: virtual object to mark unprintable region on heatbed
bool is_virt_object{ false };
bool is_wipe_tower{ false };
bool has_tried_with_excluded{ false };
/// The type of the shape which was handed over as the template argument.
using ShapeType = RawShape;
@ -663,21 +662,9 @@ public:
/// Get the packed items.
inline ItemGroup getItems() { return impl_.getItems(); }
inline int getPackedSize()
{
int size = 0;
auto items = getItems();
for (const auto &itm : items) {
if (itm.get().isFixed() == false) { size++; }
}
return size;
}
/// Clear the packed items so a new session can be started.
inline void clearItems() { impl_.clearItems(); }
inline void clearItems(const std::function<bool(const Item &itm)> &func) { impl_.clearItems(func); }
inline double filledArea() const { return impl_.filledArea(); }
inline double score() const { return impl_.score(); }

View file

@ -555,13 +555,6 @@ public:
Base::clearItems();
}
//clearFunc: itm will be cleared if return ture
inline void clearItems(const std::function<bool(const Item &itm)> &clearFunc)
{
finalAlign(bin_);
Base::clearItems(clearFunc);
}
void preload(const ItemGroup& packeditems) {
Base::preload(packeditems);
if (config_.on_preload)

View file

@ -96,17 +96,6 @@ public:
farea_valid_ = false;
}
//clearFunc: will be cleared if return true
inline void clearItems(const std::function<bool(const Item &itm)> &clearFunc)
{
ItemGroup newGroup;
for (auto &i : items_) {
if (clearFunc(i.get()) == false) { newGroup.push_back(i); }
}
std::swap(newGroup, items_);
farea_valid_ = false;
}
inline double filledArea() const {
if(farea_valid_) return farea_;
else {

View file

@ -161,24 +161,6 @@ public:
makeProgress(placers[j], j);
}
if (was_packed && it->get().has_tried_with_excluded) {
placers[j].clearItems([](const Item &itm) { return itm.isFixed() && !itm.is_wipe_tower; });
placers[j].preload(fixed_bins[placers.size() - 1]);
}
bool placer_not_packed = !was_packed && !placers.empty() && j == placers.size() && placers[j - 1].getPackedSize() == 0; // large item is not placed into the bin
if (placer_not_packed) {
if (it->get().has_tried_with_excluded == false) {
it->get().has_tried_with_excluded = true;
placers[j - 1].clearItems([](const Item &itm) { return itm.isFixed()&&!itm.is_wipe_tower; });
placers[j - 1].preload(pconfig.m_excluded_items);
j = j - 1;
continue;
} else {
placers[j - 1].clearItems([](const Item &itm) { return itm.isFixed() && !itm.is_wipe_tower; });
placers[j - 1].preload(fixed_bins[placers.size() - 1]);
}
}
if(!was_packed){
if (this->unfitindicator_ && !placers.empty())
this->unfitindicator_(it->get().name + ", height=" +std::to_string(it->get().height)

View file

@ -37,7 +37,7 @@ protected:
// then it should be removed from the list
Placer p{ bin };
p.configure(pcfg);
p.preload(pcfg.m_excluded_items);
//p.preload(pcfg.m_excluded_items);
auto it = c.begin();
while (it != c.end() && !stopcond_()) {

View file

@ -38,7 +38,7 @@ using namespace nlohmann;
namespace Slic3r {
static const std::string VERSION_CHECK_URL = "";
static const std::string VERSION_CHECK_URL = "https://api.github.com/repos/softfever/OrcaSlicer/releases";
static const std::string MODELS_STR = "models";
const std::string AppConfig::SECTION_FILAMENTS = "filaments";
@ -65,19 +65,19 @@ std::string AppConfig::get_hms_host()
{
std::string sel = get("iot_environment");
std::string host = "";
#if !BBL_RELEASE_TO_PUBLIC
if (sel == ENV_DEV_HOST)
host = "e-dev.bambu-lab.com";
else if (sel == ENV_QAT_HOST)
host = "e-qa.bambu-lab.com";
else if (sel == ENV_PRE_HOST)
host = "e-pre.bambu-lab.com";
else if (sel == ENV_PRODUCT_HOST)
host = "e.bambulab.com";
return host;
#else
// #if !BBL_RELEASE_TO_PUBLIC
// if (sel == ENV_DEV_HOST)
// host = "e-dev.bambu-lab.com";
// else if (sel == ENV_QAT_HOST)
// host = "e-qa.bambu-lab.com";
// else if (sel == ENV_PRE_HOST)
// host = "e-pre.bambu-lab.com";
// else if (sel == ENV_PRODUCT_HOST)
// host = "e.bambulab.com";
// return host;
// #else
return "e.bambulab.com";
#endif
// #endif
}
void AppConfig::reset()
@ -178,6 +178,9 @@ void AppConfig::set_defaults()
set_bool("show_hints", true);
//#endif
if (get("show_gcode_window").empty())
set_bool("show_gcode_window", true);
#ifdef _WIN32
@ -226,6 +229,10 @@ void AppConfig::set_defaults()
set("slicer_uuid", to_string(uuid));
}
// Orca
if (get("stealth_mode").empty()) {
set_bool("stealth_mode", false);
}
if (get("show_model_mesh").empty()) {
set_bool("show_model_mesh", false);
}
@ -318,15 +325,19 @@ void AppConfig::set_defaults()
set("curr_bed_type", "1");
}
#if BBL_RELEASE_TO_PUBLIC
// #if BBL_RELEASE_TO_PUBLIC
if (get("iot_environment").empty()) {
set("iot_environment", "3");
}
#else
if (get("iot_environment").empty()) {
set("iot_environment", "1");
// #else
// if (get("iot_environment").empty()) {
// set("iot_environment", "1");
// }
// #endif
if (get("presets", "filament_colors").empty()) {
set_str("presets", "filament_colors", "#F2754E");
}
#endif
if (get("print", "bed_leveling").empty()) {
set_str("print", "bed_leveling", "1");
@ -531,6 +542,10 @@ std::string AppConfig::load()
}
m_printer_cali_infos.emplace_back(cali_info);
}
} else if (it.key() == "orca_presets") {
for (auto& j_model : it.value()) {
m_printer_settings[j_model["machine"].get<std::string>()] = j_model;
}
} else {
if (it.value().is_object()) {
for (auto iter = it.value().begin(); iter != it.value().end(); iter++) {
@ -702,6 +717,10 @@ void AppConfig::save()
}
}
// write machine settings
for (const auto& preset : m_printer_settings) {
j["orca_presets"].push_back(preset.second);
}
boost::nowide::ofstream c;
c.open(path_pid, std::ios::out | std::ios::trunc);
c << std::setw(4) << j << std::endl;
@ -1128,29 +1147,29 @@ void AppConfig::update_last_backup_dir(const std::string& dir)
std::string AppConfig::get_region()
{
#if BBL_RELEASE_TO_PUBLIC
// #if BBL_RELEASE_TO_PUBLIC
return this->get("region");
#else
std::string sel = get("iot_environment");
std::string region;
if (sel == ENV_DEV_HOST)
region = "ENV_CN_DEV";
else if (sel == ENV_QAT_HOST)
region = "ENV_CN_QA";
else if (sel == ENV_PRE_HOST)
region = "ENV_CN_PRE";
if (region.empty())
return this->get("region");
return region;
#endif
// #else
// std::string sel = get("iot_environment");
// std::string region;
// if (sel == ENV_DEV_HOST)
// region = "ENV_CN_DEV";
// else if (sel == ENV_QAT_HOST)
// region = "ENV_CN_QA";
// else if (sel == ENV_PRE_HOST)
// region = "ENV_CN_PRE";
// if (region.empty())
// return this->get("region");
// return region;
// #endif
}
std::string AppConfig::get_country_code()
{
std::string region = get_region();
#if !BBL_RELEASE_TO_PUBLIC
if (is_engineering_region()) { return region; }
#endif
// #if !BBL_RELEASE_TO_PUBLIC
// if (is_engineering_region()) { return region; }
// #endif
if (region == "CHN" || region == "China")
return "CN";
else if (region == "USA")

View file

@ -9,7 +9,7 @@
#include "libslic3r/Config.hpp"
#include "libslic3r/Semver.hpp"
#include "Calib.hpp"
#include "calib.hpp"
using namespace nlohmann;
@ -194,6 +194,7 @@ public:
m_dirty = true;
}
const std::vector<std::string> &get_filament_presets() const { return m_filament_presets; }
void set_filament_presets(const std::vector<std::string> &filament_presets){
m_filament_presets = filament_presets;

View file

@ -70,14 +70,23 @@ public:
return ! (this->max(0) < other.min(0) || this->min(0) > other.max(0) ||
this->max(1) < other.min(1) || this->min(1) > other.max(1));
}
PointClass operator[](size_t idx) const
{
PointClass operator[](size_t idx) const {
switch (idx) {
case 0: return min; break;
case 1: return PointClass(max(0), min(1)); break;
case 2: return max; break;
case 3: return PointClass(min(0), max(1)); break;
default: return PointClass(); break;
case 0:
return min;
break;
case 1:
return PointClass(max(0), min(1));
break;
case 2:
return max;
break;
case 3:
return PointClass(min(0), max(1));
break;
default:
return PointClass();
break;
}
return PointClass();
}

View file

@ -23,8 +23,8 @@ void make_brim(const Print& print, PrintTryCancel try_cancel,
std::vector<unsigned int>& printExtruders);
// BBS: automatically make brim
ExtrusionEntityCollection make_brim_auto(const Print &print, PrintTryCancel try_cancel, Polygons &islands_area);
ExtrusionEntityCollection make_brim_auto(const Print &print, PrintTryCancel try_cancel, Polygons &islands_area);
} // Slic3r
#endif // slic3r_Brim_hpp_

View file

@ -37,8 +37,6 @@ set(lisbslic3r_sources
Brim.hpp
BuildVolume.cpp
BuildVolume.hpp
Calib.cpp
Calib.hpp
Circle.cpp
Circle.hpp
clipper.cpp

View file

@ -1,748 +0,0 @@
#include "Calib.hpp"
#include "Config.hpp"
#include "Model.hpp"
#include "GCode.hpp"
#include <cmath>
namespace Slic3r {
float CalibPressureAdvance::find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height, int filament_idx)
{
const double general_suggested_min_speed = 100.0;
double filament_max_volumetric_speed = config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->get_at(0);
Flow pattern_line = Flow(line_width, layer_height, config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0));
auto pa_speed = std::min(std::max(general_suggested_min_speed, config.option<ConfigOptionFloat>("outer_wall_speed")->value),
filament_max_volumetric_speed / pattern_line.mm3_per_mm());
return std::floor(pa_speed);
}
std::string CalibPressureAdvance::move_to(Vec2d pt, GCodeWriter &writer, std::string comment)
{
std::stringstream gcode;
gcode << writer.retract();
gcode << writer.travel_to_xy(pt, comment);
gcode << writer.unretract();
m_last_pos = Vec3d(pt.x(), pt.y(), 0);
return gcode.str();
}
double CalibPressureAdvance::e_per_mm(double line_width, double layer_height, float nozzle_diameter, float filament_diameter, float print_flow_ratio) const
{
const Flow line_flow = Flow(line_width, layer_height, nozzle_diameter);
const double filament_area = M_PI * std::pow(filament_diameter / 2, 2);
return line_flow.mm3_per_mm() / filament_area * print_flow_ratio;
}
std::string CalibPressureAdvance::convert_number_to_string(double num) const
{
auto sNumber = std::to_string(num);
sNumber.erase(sNumber.find_last_not_of('0') + 1, std::string::npos);
sNumber.erase(sNumber.find_last_not_of('.') + 1, std::string::npos);
return sNumber;
}
std::string CalibPressureAdvance::draw_digit(
double startx, double starty, char c, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, GCodeWriter &writer)
{
const double len = m_digit_segment_len;
const double gap = line_width / 2.0;
const auto dE = e_per_mm * len;
const auto two_dE = dE * 2;
Vec2d p0, p1, p2, p3, p4, p5;
Vec2d p0_5, p4_5;
Vec2d gap_p0_toward_p3, gap_p2_toward_p3;
Vec2d dot_direction;
if (mode == CalibPressureAdvance::DrawDigitMode::Bottom_To_Top) {
// 1-------2-------5
// | | |
// | | |
// 0-------3-------4
p0 = Vec2d(startx, starty);
p0_5 = Vec2d(startx, starty + len / 2);
p1 = Vec2d(startx, starty + len);
p2 = Vec2d(startx + len, starty + len);
p3 = Vec2d(startx + len, starty);
p4 = Vec2d(startx + len * 2, starty);
p4_5 = Vec2d(startx + len * 2, starty + len / 2);
p5 = Vec2d(startx + len * 2, starty + len);
gap_p0_toward_p3 = p0 + Vec2d(gap, 0);
gap_p2_toward_p3 = p2 + Vec2d(0, gap);
dot_direction = Vec2d(-len / 2, 0);
} else {
// 0-------1
// | |
// 3-------2
// | |
// 4-------5
p0 = Vec2d(startx, starty);
p0_5 = Vec2d(startx + len / 2, starty);
p1 = Vec2d(startx + len, starty);
p2 = Vec2d(startx + len, starty - len);
p3 = Vec2d(startx, starty - len);
p4 = Vec2d(startx, starty - len * 2);
p4_5 = Vec2d(startx + len / 2, starty - len * 2);
p5 = Vec2d(startx + len, starty - len * 2);
gap_p0_toward_p3 = p0 - Vec2d(0, gap);
gap_p2_toward_p3 = p2 - Vec2d(gap, 0);
dot_direction = Vec2d(0, len / 2);
}
std::stringstream gcode;
switch (c) {
case '0':
gcode << move_to(p0, writer, "Glyph: 0");
gcode << writer.extrude_to_xy(p1, dE);
gcode << writer.extrude_to_xy(p5, two_dE);
gcode << writer.extrude_to_xy(p4, dE);
gcode << writer.extrude_to_xy(gap_p0_toward_p3, two_dE);
break;
case '1':
gcode << move_to(p0_5, writer, "Glyph: 1");
gcode << writer.extrude_to_xy(p4_5, two_dE);
break;
case '2':
gcode << move_to(p0, writer, "Glyph: 2");
gcode << writer.extrude_to_xy(p1, dE);
gcode << writer.extrude_to_xy(p2, dE);
gcode << writer.extrude_to_xy(p3, dE);
gcode << writer.extrude_to_xy(p4, dE);
gcode << writer.extrude_to_xy(p5, dE);
break;
case '3':
gcode << move_to(p0, writer, "Glyph: 3");
gcode << writer.extrude_to_xy(p1, dE);
gcode << writer.extrude_to_xy(p5, two_dE);
gcode << writer.extrude_to_xy(p4, dE);
gcode << move_to(gap_p2_toward_p3, writer);
gcode << writer.extrude_to_xy(p3, dE);
break;
case '4':
gcode << move_to(p0, writer, "Glyph: 4");
gcode << writer.extrude_to_xy(p3, dE);
gcode << writer.extrude_to_xy(p2, dE);
gcode << move_to(p1, writer);
gcode << writer.extrude_to_xy(p5, two_dE);
break;
case '5':
gcode << move_to(p1, writer, "Glyph: 5");
gcode << writer.extrude_to_xy(p0, dE);
gcode << writer.extrude_to_xy(p3, dE);
gcode << writer.extrude_to_xy(p2, dE);
gcode << writer.extrude_to_xy(p5, dE);
gcode << writer.extrude_to_xy(p4, dE);
break;
case '6':
gcode << move_to(p1, writer, "Glyph: 6");
gcode << writer.extrude_to_xy(p0, dE);
gcode << writer.extrude_to_xy(p4, two_dE);
gcode << writer.extrude_to_xy(p5, dE);
gcode << writer.extrude_to_xy(p2, dE);
gcode << writer.extrude_to_xy(p3, dE);
break;
case '7':
gcode << move_to(p0, writer, "Glyph: 7");
gcode << writer.extrude_to_xy(p1, dE);
gcode << writer.extrude_to_xy(p5, two_dE);
break;
case '8':
gcode << move_to(p2, writer, "Glyph: 8");
gcode << writer.extrude_to_xy(p3, dE);
gcode << writer.extrude_to_xy(p4, dE);
gcode << writer.extrude_to_xy(p5, dE);
gcode << writer.extrude_to_xy(p1, two_dE);
gcode << writer.extrude_to_xy(p0, dE);
gcode << writer.extrude_to_xy(p3, dE);
break;
case '9':
gcode << move_to(p5, writer, "Glyph: 9");
gcode << writer.extrude_to_xy(p1, two_dE);
gcode << writer.extrude_to_xy(p0, dE);
gcode << writer.extrude_to_xy(p3, dE);
gcode << writer.extrude_to_xy(p2, dE);
break;
case '.':
gcode << move_to(p4_5, writer, "Glyph: .");
gcode << writer.extrude_to_xy(p4_5 + dot_direction, dE);
break;
default: break;
}
return gcode.str();
}
std::string CalibPressureAdvance::draw_number(
double startx, double starty, double value, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, double speed, GCodeWriter &writer)
{
auto sNumber = convert_number_to_string(value);
std::stringstream gcode;
gcode << writer.set_speed(speed);
for (std::string::size_type i = 0; i < sNumber.length(); ++i) {
if (i > m_max_number_len) { break; }
switch (mode) {
case DrawDigitMode::Bottom_To_Top: gcode << draw_digit(startx, starty + i * number_spacing(), sNumber[i], mode, line_width, e_per_mm, writer); break;
default: gcode << draw_digit(startx + i * number_spacing(), starty, sNumber[i], mode, line_width, e_per_mm, writer);
}
}
return gcode.str();
}
CalibPressureAdvanceLine::CalibPressureAdvanceLine(GCode *gcodegen)
: mp_gcodegen(gcodegen)
, m_nozzle_diameter(gcodegen->config().nozzle_diameter.get_at(0))
{
}
std::string CalibPressureAdvanceLine::generate_test(double start_pa /*= 0*/, double step_pa /*= 0.002*/, int count /*= 10*/)
{
BoundingBoxf bed_ext = get_extents(mp_gcodegen->config().printable_area.values);
if (is_delta()) { CalibPressureAdvanceLine::delta_scale_bed_ext(bed_ext); }
auto bed_sizes = mp_gcodegen->config().printable_area.values;
const auto &w = bed_ext.size().x();
const auto &h = bed_ext.size().y();
count = std::min(count, int((h - 10) / m_space_y));
m_length_long = 40 + std::min(w - 120.0, 0.0);
auto startx = (w - m_length_short * 2 - m_length_long - 20) / 2;
auto starty = (h - count * m_space_y) / 2;
if (is_delta()) { CalibPressureAdvanceLine::delta_modify_start(startx, starty, count); }
return print_pa_lines(startx, starty, start_pa, step_pa, count);
}
bool CalibPressureAdvanceLine::is_delta() const { return mp_gcodegen->config().printable_area.values.size() > 4; }
std::string CalibPressureAdvanceLine::print_pa_lines(double start_x, double start_y, double start_pa, double step_pa, int num)
{
auto & writer = mp_gcodegen->writer();
const auto &config = mp_gcodegen->config();
const auto filament_diameter = config.filament_diameter.get_at(0);
const auto print_flow_ratio = config.print_flow_ratio;
const double e_per_mm = CalibPressureAdvance::e_per_mm(m_line_width, m_height_layer, m_nozzle_diameter, filament_diameter, print_flow_ratio);
const double thin_e_per_mm = CalibPressureAdvance::e_per_mm(m_thin_line_width, m_height_layer, m_nozzle_diameter, filament_diameter, print_flow_ratio);
const double number_e_per_mm = CalibPressureAdvance::e_per_mm(m_number_line_width, m_height_layer, m_nozzle_diameter, filament_diameter, print_flow_ratio);
const double fast = CalibPressureAdvance::speed_adjust(m_fast_speed);
const double slow = CalibPressureAdvance::speed_adjust(m_slow_speed);
std::stringstream gcode;
gcode << mp_gcodegen->writer().travel_to_z(m_height_layer);
double y_pos = start_y;
// prime line
auto prime_x = start_x - 2;
gcode << move_to(Vec2d(prime_x, y_pos + (num - 4) * m_space_y), writer);
gcode << writer.set_speed(slow);
gcode << writer.extrude_to_xy(Vec2d(prime_x, y_pos + 3 * m_space_y), e_per_mm * m_space_y * num * 1.1);
for (int i = 0; i < num; ++i) {
gcode << writer.set_pressure_advance(start_pa + i * step_pa);
gcode << move_to(Vec2d(start_x, y_pos + i * m_space_y), writer);
gcode << writer.set_speed(slow);
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short, y_pos + i * m_space_y), e_per_mm * m_length_short);
gcode << writer.set_speed(fast);
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long, y_pos + i * m_space_y), e_per_mm * m_length_long);
gcode << writer.set_speed(slow);
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long + m_length_short, y_pos + i * m_space_y), e_per_mm * m_length_short);
}
gcode << writer.set_pressure_advance(0.0);
if (m_draw_numbers) {
// draw indicator lines
gcode << writer.set_speed(fast);
gcode << move_to(Vec2d(start_x + m_length_short, y_pos + (num - 1) * m_space_y + 2), writer);
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short, y_pos + (num - 1) * m_space_y + 7), thin_e_per_mm * 7);
gcode << move_to(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * m_space_y + 7), writer);
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * m_space_y + 2), thin_e_per_mm * 7);
for (int i = 0; i < num; i += 2) {
gcode << draw_number(start_x + m_length_short + m_length_long + m_length_short + 3, y_pos + i * m_space_y + m_space_y / 2, start_pa + i * step_pa, m_draw_digit_mode,
m_number_line_width, number_e_per_mm, 3600, writer);
}
}
return gcode.str();
}
void CalibPressureAdvanceLine::delta_modify_start(double &startx, double &starty, int count)
{
startx = -startx;
starty = -(count * m_space_y) / 2;
}
CalibPressureAdvancePattern::CalibPressureAdvancePattern(const Calib_Params &params, const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin)
: m_params(params)
{
this->m_draw_digit_mode = DrawDigitMode::Bottom_To_Top;
refresh_setup(config, is_bbl_machine, model, origin);
};
void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin)
{
std::stringstream gcode;
gcode << "; start pressure advance pattern for layer\n";
refresh_setup(config, is_bbl_machine, model, origin);
gcode << move_to(Vec2d(m_starting_point.x(), m_starting_point.y()), m_writer, "Move to start XY position");
gcode << m_writer.travel_to_z(height_first_layer(), "Move to start Z position");
gcode << m_writer.set_pressure_advance(m_params.start);
const DrawBoxOptArgs default_box_opt_args(*this);
// create anchoring frame
gcode << draw_box(m_starting_point.x(), m_starting_point.y(), print_size_x(), frame_size_y(), default_box_opt_args);
// create tab for numbers
DrawBoxOptArgs draw_box_opt_args = default_box_opt_args;
draw_box_opt_args.is_filled = true;
draw_box_opt_args.num_perimeters = wall_count();
gcode << draw_box(m_starting_point.x(), m_starting_point.y() + frame_size_y() + line_spacing_first_layer(), glyph_tab_max_x() - m_starting_point.x(),
max_numbering_height() + line_spacing_first_layer() + m_glyph_padding_vertical * 2, draw_box_opt_args);
std::vector<CustomGCode::Item> gcode_items;
const DrawLineOptArgs default_line_opt_args(*this);
const int num_patterns = get_num_patterns(); // "cache" for use in loops
// draw pressure advance pattern
for (int i = 0; i < m_num_layers; ++i) {
if (i > 0) {
gcode << "; end pressure advance pattern for layer\n";
CustomGCode::Item item;
item.print_z = height_first_layer() + (i - 1) * height_layer();
item.type = CustomGCode::Type::Custom;
item.extra = gcode.str();
gcode_items.push_back(item);
gcode = std::stringstream(); // reset for next layer contents
gcode << "; start pressure advance pattern for layer\n";
const double layer_height = height_first_layer() + (i * height_layer());
gcode << m_writer.travel_to_z(layer_height, "Move to layer height");
}
// line numbering
if (i == 1) {
gcode << m_writer.set_pressure_advance(m_params.start);
double number_e_per_mm = e_per_mm(line_width(), height_layer(), m_config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_flow_ratio")->get_at(0));
// glyph on every other line
for (int j = 0; j < num_patterns; j += 2) {
gcode << draw_number(glyph_start_x(j), m_starting_point.y() + frame_size_y() + m_glyph_padding_vertical + line_width(), m_params.start + (j * m_params.step),
m_draw_digit_mode, line_width(), number_e_per_mm, speed_first_layer(), m_writer);
}
}
DrawLineOptArgs draw_line_opt_args = default_line_opt_args;
double to_x = m_starting_point.x() + pattern_shift();
double to_y = m_starting_point.y();
double side_length = m_wall_side_length;
// shrink first layer to fit inside frame
if (i == 0) {
double shrink = (line_spacing_first_layer() * (wall_count() - 1) + (line_width_first_layer() * (1 - m_encroachment))) / std::sin(to_radians(m_corner_angle) / 2);
side_length = m_wall_side_length - shrink;
to_x += shrink * std::sin(to_radians(90) - to_radians(m_corner_angle) / 2);
to_y += line_spacing_first_layer() * (wall_count() - 1) + (line_width_first_layer() * (1 - m_encroachment));
}
double initial_x = to_x;
double initial_y = to_y;
gcode << move_to(Vec2d(to_x, to_y), m_writer, "Move to pattern start");
for (int j = 0; j < num_patterns; ++j) {
// increment pressure advance
gcode << m_writer.set_pressure_advance(m_params.start + (j * m_params.step));
for (int k = 0; k < wall_count(); ++k) {
to_x += std::cos(to_radians(m_corner_angle) / 2) * side_length;
to_y += std::sin(to_radians(m_corner_angle) / 2) * side_length;
draw_line_opt_args = default_line_opt_args;
draw_line_opt_args.height = i == 0 ? height_first_layer() : height_layer();
draw_line_opt_args.line_width = line_width(); // don't use line_width_first_layer so results are consistent across all layers
draw_line_opt_args.speed = i == 0 ? speed_adjust(speed_first_layer()) : speed_adjust(speed_perimeter());
draw_line_opt_args.comment = "Print pattern wall";
gcode << draw_line(Vec2d(to_x, to_y), draw_line_opt_args);
to_x -= std::cos(to_radians(m_corner_angle) / 2) * side_length;
to_y += std::sin(to_radians(m_corner_angle) / 2) * side_length;
gcode << draw_line(Vec2d(to_x, to_y), draw_line_opt_args);
to_y = initial_y;
if (k != wall_count() - 1) {
// perimeters not done yet. move to next perimeter
to_x += line_spacing_angle();
gcode << move_to(Vec2d(to_x, to_y), m_writer, "Move to start next pattern wall");
} else if (j != num_patterns - 1) {
// patterns not done yet. move to next pattern
to_x += m_pattern_spacing + line_width();
gcode << move_to(Vec2d(to_x, to_y), m_writer, "Move to next pattern");
} else if (i != m_num_layers - 1) {
// layers not done yet. move back to start
to_x = initial_x;
gcode << move_to(Vec2d(to_x, to_y), m_writer, "Move back to start position");
} else {
// everything done
}
}
}
}
gcode << m_writer.set_pressure_advance(m_params.start);
gcode << "; end pressure advance pattern for layer\n";
CustomGCode::Item item;
item.print_z = max_layer_z();
item.type = CustomGCode::Type::Custom;
item.extra = gcode.str();
gcode_items.push_back(item);
CustomGCode::Info info;
info.mode = CustomGCode::Mode::SingleExtruder;
info.gcodes = gcode_items;
model.plates_custom_gcodes[model.curr_plate_index] = info;
}
void CalibPressureAdvancePattern::refresh_setup(const DynamicPrintConfig &config, bool is_bbl_machine, const Model &model, const Vec3d &origin)
{
m_config = config;
m_config.apply(model.objects.front()->config.get(), true);
m_config.apply(model.objects.front()->volumes.front()->config.get(), true);
m_is_delta = (m_config.option<ConfigOptionPoints>("printable_area")->values.size() > 4);
_refresh_starting_point(model);
_refresh_writer(is_bbl_machine, model, origin);
}
void CalibPressureAdvancePattern::_refresh_starting_point(const Model &model)
{
ModelObject * obj = model.objects.front();
BoundingBoxf3 bbox = obj->instance_bounding_box(*obj->instances.front(), false);
m_starting_point = Vec3d(bbox.min.x(), bbox.max.y(), 0);
m_starting_point.y() += m_handle_spacing;
if (m_is_delta) {
m_starting_point.x() *= -1;
m_starting_point.y() -= (frame_size_y() / 2);
}
}
void CalibPressureAdvancePattern::_refresh_writer(bool is_bbl_machine, const Model &model, const Vec3d &origin)
{
PrintConfig print_config;
print_config.apply(m_config, true);
m_writer.apply_print_config(print_config);
m_writer.set_xy_offset(origin(0), origin(1));
//m_writer.set_is_bbl_machine(is_bbl_machine);
const unsigned int extruder_id = model.objects.front()->volumes.front()->extruder_id();
m_writer.set_extruders({extruder_id});
m_writer.set_extruder(extruder_id);
}
std::string CalibPressureAdvancePattern::draw_line(Vec2d to_pt, DrawLineOptArgs opt_args)
{
const double e_per_mm = CalibPressureAdvance::e_per_mm(opt_args.line_width, opt_args.height, m_config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_flow_ratio")->get_at(0));
const double length = get_distance(Vec2d(m_last_pos.x(), m_last_pos.y()), to_pt);
auto dE = e_per_mm * length;
std::stringstream gcode;
gcode << m_writer.set_speed(opt_args.speed);
gcode << m_writer.extrude_to_xy(to_pt, dE, opt_args.comment);
m_last_pos = Vec3d(to_pt.x(), to_pt.y(), 0);
return gcode.str();
}
std::string CalibPressureAdvancePattern::draw_box(double min_x, double min_y, double size_x, double size_y, DrawBoxOptArgs opt_args)
{
std::stringstream gcode;
double x = min_x;
double y = min_y;
const double max_x = min_x + size_x;
const double max_y = min_y + size_y;
const double spacing = opt_args.line_width - opt_args.height * (1 - M_PI / 4);
// if number of perims exceeds size of box, reduce it to max
const int max_perimeters = std::min(
// this is the equivalent of number of perims for concentric fill
std::floor(size_x * std::sin(to_radians(45))) / (spacing / std::sin(to_radians(45))),
std::floor(size_y * std::sin(to_radians(45))) / (spacing / std::sin(to_radians(45))));
opt_args.num_perimeters = std::min(opt_args.num_perimeters, max_perimeters);
gcode << move_to(Vec2d(min_x, min_y), m_writer, "Move to box start");
DrawLineOptArgs line_opt_args(*this);
line_opt_args.height = opt_args.height;
line_opt_args.line_width = opt_args.line_width;
line_opt_args.speed = opt_args.speed;
for (int i = 0; i < opt_args.num_perimeters; ++i) {
if (i != 0) { // after first perimeter, step inwards to start next perimeter
x += spacing;
y += spacing;
gcode << move_to(Vec2d(x, y), m_writer, "Step inwards to print next perimeter");
}
y += size_y - i * spacing * 2;
line_opt_args.comment = "Draw perimeter (up)";
gcode << draw_line(Vec2d(x, y), line_opt_args);
x += size_x - i * spacing * 2;
line_opt_args.comment = "Draw perimeter (right)";
gcode << draw_line(Vec2d(x, y), line_opt_args);
y -= size_y - i * spacing * 2;
line_opt_args.comment = "Draw perimeter (down)";
gcode << draw_line(Vec2d(x, y), line_opt_args);
x -= size_x - i * spacing * 2;
line_opt_args.comment = "Draw perimeter (left)";
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
if (!opt_args.is_filled) { return gcode.str(); }
// create box infill
const double spacing_45 = spacing / std::sin(to_radians(45));
const double bound_modifier = (spacing * (opt_args.num_perimeters - 1)) + (opt_args.line_width * (1 - m_encroachment));
const double x_min_bound = min_x + bound_modifier;
const double x_max_bound = max_x - bound_modifier;
const double y_min_bound = min_y + bound_modifier;
const double y_max_bound = max_y - bound_modifier;
const int x_count = std::floor((x_max_bound - x_min_bound) / spacing_45);
const int y_count = std::floor((y_max_bound - y_min_bound) / spacing_45);
double x_remainder = std::fmod((x_max_bound - x_min_bound), spacing_45);
double y_remainder = std::fmod((y_max_bound - y_min_bound), spacing_45);
x = x_min_bound;
y = y_min_bound;
gcode << move_to(Vec2d(x, y), m_writer, "Move to fill start");
for (int i = 0; i < x_count + y_count + (x_remainder + y_remainder >= spacing_45 ? 1 : 0);
++i) { // this isn't the most robust way, but less expensive than finding line intersections
if (i < std::min(x_count, y_count)) {
if (i % 2 == 0) {
x += spacing_45;
y = y_min_bound;
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right");
y += x - x_min_bound;
x = x_min_bound;
line_opt_args.comment = "Fill: Print up/left";
gcode << draw_line(Vec2d(x, y), line_opt_args);
} else {
y += spacing_45;
x = x_min_bound;
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step up");
x += y - y_min_bound;
y = y_min_bound;
line_opt_args.comment = "Fill: Print down/right";
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
} else if (i < std::max(x_count, y_count)) {
if (x_count > y_count) {
// box is wider than tall
if (i % 2 == 0) {
x += spacing_45;
y = y_min_bound;
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right");
x -= y_max_bound - y_min_bound;
y = y_max_bound;
line_opt_args.comment = "Fill: Print up/left";
gcode << draw_line(Vec2d(x, y), line_opt_args);
} else {
if (i == y_count) {
x += spacing_45 - y_remainder;
y_remainder = 0;
} else {
x += spacing_45;
}
y = y_max_bound;
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right");
x += y_max_bound - y_min_bound;
y = y_min_bound;
line_opt_args.comment = "Fill: Print down/right";
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
} else {
// box is taller than wide
if (i % 2 == 0) {
x = x_max_bound;
if (i == x_count) {
y += spacing_45 - x_remainder;
x_remainder = 0;
} else {
y += spacing_45;
}
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step up");
x = x_min_bound;
y += x_max_bound - x_min_bound;
line_opt_args.comment = "Fill: Print up/left";
gcode << draw_line(Vec2d(x, y), line_opt_args);
} else {
x = x_min_bound;
y += spacing_45;
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step up");
x = x_max_bound;
y -= x_max_bound - x_min_bound;
line_opt_args.comment = "Fill: Print down/right";
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
}
} else {
if (i % 2 == 0) {
x = x_max_bound;
if (i == x_count) {
y += spacing_45 - x_remainder;
} else {
y += spacing_45;
}
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step up");
x -= y_max_bound - y;
y = y_max_bound;
line_opt_args.comment = "Fill: Print up/left";
gcode << draw_line(Vec2d(x, y), line_opt_args);
} else {
if (i == y_count) {
x += spacing_45 - y_remainder;
} else {
x += spacing_45;
}
y = y_max_bound;
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right");
y -= x_max_bound - x;
x = x_max_bound;
line_opt_args.comment = "Fill: Print down/right";
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
}
}
return gcode.str();
}
double CalibPressureAdvancePattern::get_distance(Vec2d from, Vec2d to) const { return std::hypot((to.x() - from.x()), (to.y() - from.y())); }
double CalibPressureAdvancePattern::object_size_x() const
{
return get_num_patterns() * ((wall_count() - 1) * line_spacing_angle()) + (get_num_patterns() - 1) * (m_pattern_spacing + line_width()) +
std::cos(to_radians(m_corner_angle) / 2) * m_wall_side_length + line_spacing_first_layer() * wall_count();
}
double CalibPressureAdvancePattern::object_size_y() const
{
return 2 * (std::sin(to_radians(m_corner_angle) / 2) * m_wall_side_length) + max_numbering_height() + m_glyph_padding_vertical * 2 + line_width_first_layer();
}
double CalibPressureAdvancePattern::glyph_start_x(int pattern_i) const
{
// note that pattern_i is zero-based!
// align glyph's start with first perimeter of specified pattern
double x =
// starting offset
m_starting_point.x() + pattern_shift() +
// width of pattern extrusions
pattern_i * (wall_count() - 1) * line_spacing_angle() + // center to center distance of extrusions
pattern_i * line_width() + // endcaps. center to end on either side = 1 line width
// space between each pattern
pattern_i * m_pattern_spacing;
// align to middle of pattern walls
x += wall_count() * line_spacing_angle() / 2;
// shift so glyph is centered on pattern
// m_digit_segment_len = half of X length of glyph
x -= (glyph_length_x() / 2);
return x;
}
double CalibPressureAdvancePattern::glyph_length_x() const
{
// half of line_width sticks out on each side
return line_width() + (2 * m_digit_segment_len);
}
double CalibPressureAdvancePattern::glyph_tab_max_x() const
{
// only every other glyph is shown, starting with 1
int num = get_num_patterns();
int max_num = (num % 2 == 0) ? num - 1 : num;
// padding at end should be same as padding at start
double padding = glyph_start_x(0) - m_starting_point.x();
return glyph_start_x(max_num - 1) + // glyph_start_x is zero-based
(glyph_length_x() - line_width() / 2) + padding;
}
double CalibPressureAdvancePattern::max_numbering_height() const
{
std::string::size_type most_characters = 0;
const int num_patterns = get_num_patterns();
// note: only every other number is printed
for (std::string::size_type i = 0; i < num_patterns; i += 2) {
std::string sNumber = convert_number_to_string(m_params.start + (i * m_params.step));
if (sNumber.length() > most_characters) { most_characters = sNumber.length(); }
}
most_characters = std::min(most_characters, m_max_number_len);
return (most_characters * m_digit_segment_len) + ((most_characters - 1) * m_digit_gap_len);
}
double CalibPressureAdvancePattern::pattern_shift() const { return (wall_count() - 1) * line_spacing_first_layer() + line_width_first_layer() + m_glyph_padding_horizontal; }
} // namespace Slic3r

View file

@ -1,307 +0,0 @@
#pragma once
#include "GCodeWriter.hpp"
#include "PrintConfig.hpp"
#include "BoundingBox.hpp"
namespace Slic3r {
class GCode;
class Model;
enum class CalibMode : int {
Calib_None = 0,
Calib_PA_Line,
Calib_PA_Pattern,
Calib_PA_Tower,
Calib_Flow_Rate,
Calib_Temp_Tower,
Calib_Vol_speed_Tower,
Calib_VFA_Tower,
Calib_Retraction_tower
};
enum class CalibState {
Start = 0,
Preset,
Calibration,
CoarseSave,
FineCalibration,
Save,
Finish
};
struct Calib_Params
{
Calib_Params() : mode(CalibMode::Calib_None){}
double start, end, step;
bool print_numbers;
CalibMode mode;
};
class X1CCalibInfos
{
public:
struct X1CCalibInfo
{
int tray_id;
int bed_temp;
int nozzle_temp;
float nozzle_diameter;
std::string filament_id;
std::string setting_id;
float max_volumetric_speed;
float flow_rate = 0.98f; // for flow ratio
};
std::vector<X1CCalibInfo> calib_datas;
};
class CaliPresetInfo
{
public:
int tray_id;
float nozzle_diameter;
std::string filament_id;
std::string setting_id;
std::string name;
CaliPresetInfo &operator=(const CaliPresetInfo &other)
{
this->tray_id = other.tray_id;
this->nozzle_diameter = other.nozzle_diameter;
this->filament_id = other.filament_id;
this->setting_id = other.setting_id;
this->name = other.name;
return *this;
}
};
struct PrinterCaliInfo
{
std::string dev_id;
bool cali_finished = true;
float cache_flow_ratio;
std::vector<CaliPresetInfo> selected_presets;
};
class PACalibResult
{
public:
enum CalibResult {
CALI_RESULT_SUCCESS = 0,
CALI_RESULT_PROBLEM = 1,
CALI_RESULT_FAILED = 2,
};
int tray_id;
int cali_idx = -1;
float nozzle_diameter;
std::string filament_id;
std::string setting_id;
std::string name;
float k_value = 0.0;
float n_coef = 0.0;
int confidence = -1; // 0: success 1: uncertain 2: failed
};
struct PACalibIndexInfo
{
int tray_id;
int cali_idx;
float nozzle_diameter;
std::string filament_id;
};
class FlowRatioCalibResult
{
public:
int tray_id;
float nozzle_diameter;
std::string filament_id;
std::string setting_id;
float flow_ratio;
int confidence; // 0: success 1: uncertain 2: failed
};
class CalibPressureAdvance
{
public:
static float find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height, int filament_idx = 0);
protected:
CalibPressureAdvance() = default;
~CalibPressureAdvance() = default;
enum class DrawDigitMode { Left_To_Right, Bottom_To_Top };
void delta_scale_bed_ext(BoundingBoxf &bed_ext) const { bed_ext.scale(1.0f / 1.41421f); }
std::string move_to(Vec2d pt, GCodeWriter &writer, std::string comment = std::string());
double e_per_mm(double line_width, double layer_height, float nozzle_diameter, float filament_diameter, float print_flow_ratio) const;
double speed_adjust(int speed) const { return speed * 60; };
std::string convert_number_to_string(double num) const;
double number_spacing() const { return m_digit_segment_len + m_digit_gap_len; };
std::string draw_digit(double startx, double starty, char c, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, GCodeWriter &writer);
std::string draw_number(
double startx, double starty, double value, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, double speed, GCodeWriter &writer);
Vec3d m_last_pos;
DrawDigitMode m_draw_digit_mode{DrawDigitMode::Left_To_Right};
const double m_digit_segment_len{2};
const double m_digit_gap_len{1};
const std::string::size_type m_max_number_len{5};
};
class CalibPressureAdvanceLine : public CalibPressureAdvance
{
public:
CalibPressureAdvanceLine(GCode *gcodegen);
~CalibPressureAdvanceLine(){};
std::string generate_test(double start_pa = 0, double step_pa = 0.002, int count = 50);
void set_speed(double fast = 100.0, double slow = 20.0)
{
m_slow_speed = slow;
m_fast_speed = fast;
}
const double &line_width() { return m_line_width; };
bool is_delta() const;
bool & draw_numbers() { return m_draw_numbers; }
private:
std::string print_pa_lines(double start_x, double start_y, double start_pa, double step_pa, int num);
void delta_modify_start(double &startx, double &starty, int count);
GCode *mp_gcodegen;
double m_nozzle_diameter;
double m_slow_speed, m_fast_speed;
const double m_height_layer{0.2};
const double m_line_width{0.6};
const double m_thin_line_width{0.44};
const double m_number_line_width{0.48};
const double m_space_y{3.5};
double m_length_short{20.0}, m_length_long{40.0};
bool m_draw_numbers{true};
};
struct SuggestedConfigCalibPAPattern
{
const std::vector<std::pair<std::string, double>> float_pairs{{"initial_layer_print_height", 0.25}, {"layer_height", 0.2}, {"initial_layer_speed", 30}};
const std::vector<std::pair<std::string, double>> nozzle_ratio_pairs{{"line_width", 112.5}, {"initial_layer_line_width", 140}};
const std::vector<std::pair<std::string, int>> int_pairs{{"skirt_loops", 0}, {"wall_loops", 3}};
const std::pair<std::string, BrimType> brim_pair{"brim_type", BrimType::btNoBrim};
};
class CalibPressureAdvancePattern : public CalibPressureAdvance
{
friend struct DrawLineOptArgs;
friend struct DrawBoxOptArgs;
public:
CalibPressureAdvancePattern(const Calib_Params &params, const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin);
double handle_xy_size() const { return m_handle_xy_size; };
double handle_spacing() const { return m_handle_spacing; };
double print_size_x() const { return object_size_x() + pattern_shift(); };
double print_size_y() const { return object_size_y(); };
double max_layer_z() const { return height_first_layer() + ((m_num_layers - 1) * height_layer()); };
void generate_custom_gcodes(const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin);
protected:
double speed_first_layer() const { return m_config.option<ConfigOptionFloat>("initial_layer_speed")->value; };
double speed_perimeter() const { return m_config.option<ConfigOptionFloat>("outer_wall_speed")->value; };
double line_width_first_layer() const { return m_config.get_abs_value("initial_layer_line_width"); };
double line_width() const { return m_config.get_abs_value("line_width"); };
int wall_count() const { return m_config.option<ConfigOptionInt>("wall_loops")->value; };
private:
struct DrawLineOptArgs
{
DrawLineOptArgs(const CalibPressureAdvancePattern &p) : height{p.height_layer()}, line_width{p.line_width()}, speed{p.speed_adjust(p.speed_perimeter())} {};
double height;
double line_width;
double speed;
std::string comment{"Print line"};
};
struct DrawBoxOptArgs
{
DrawBoxOptArgs(const CalibPressureAdvancePattern &p)
: num_perimeters{p.wall_count()}, height{p.height_first_layer()}, line_width{p.line_width_first_layer()}, speed{p.speed_adjust(p.speed_first_layer())} {};
bool is_filled{false};
int num_perimeters;
double height;
double line_width;
double speed;
};
void refresh_setup(const DynamicPrintConfig &config, bool is_bbl_machine, const Model &model, const Vec3d &origin);
void _refresh_starting_point(const Model &model);
void _refresh_writer(bool is_bbl_machine, const Model &model, const Vec3d &origin);
double height_first_layer() const { return m_config.option<ConfigOptionFloat>("initial_layer_print_height")->value; };
double height_layer() const { return m_config.option<ConfigOptionFloat>("layer_height")->value; };
const int get_num_patterns() const { return std::ceil((m_params.end - m_params.start) / m_params.step + 1); }
std::string draw_line(Vec2d to_pt, DrawLineOptArgs opt_args);
std::string draw_box(double min_x, double min_y, double size_x, double size_y, DrawBoxOptArgs opt_args);
double to_radians(double degrees) const { return degrees * M_PI / 180; };
double get_distance(Vec2d from, Vec2d to) const;
/*
from slic3r documentation: spacing = extrusion_width - layer_height * (1 - PI/4)
"spacing" = center-to-center distance of adjacent extrusions, which partially overlap
https://manual.slic3r.org/advanced/flow-math
https://ellis3dp.com/Print-Tuning-Guide/articles/misconceptions.html#two-04mm-perimeters--08mm
*/
double line_spacing() const { return line_width() - height_layer() * (1 - M_PI / 4); };
double line_spacing_first_layer() const { return line_width_first_layer() - height_first_layer() * (1 - M_PI / 4); };
double line_spacing_angle() const { return line_spacing() / std::sin(to_radians(m_corner_angle) / 2); };
double object_size_x() const;
double object_size_y() const;
double frame_size_y() const { return std::sin(to_radians(double(m_corner_angle) / 2)) * m_wall_side_length * 2; };
double glyph_start_x(int pattern_i = 0) const;
double glyph_length_x() const;
double glyph_tab_max_x() const;
double max_numbering_height() const;
double pattern_shift() const;
const Calib_Params &m_params;
DynamicPrintConfig m_config;
GCodeWriter m_writer;
bool m_is_delta;
Vec3d m_starting_point;
const double m_handle_xy_size{5};
const double m_handle_spacing{2};
const int m_num_layers{4};
const double m_wall_side_length{30.0};
const int m_corner_angle{90};
const int m_pattern_spacing{2};
const double m_encroachment{1. / 3.};
const double m_glyph_padding_horizontal{1};
const double m_glyph_padding_vertical{1};
};
} // namespace Slic3r

View file

@ -1660,7 +1660,7 @@ public:
ConfigOptionEnumsGenericTempl& operator= (const ConfigOption* opt) { this->set(opt); return *this; }
bool operator< (const ConfigOptionInts& rhs) const throw() { return this->values < rhs.values; }
bool operator==(const ConfigOptionInts& rhs) const
bool operator==(const ConfigOptionInts& rhs) const throw()
{
if (rhs.type() != this->type())
throw ConfigurationError("ConfigOptionEnumsGeneric: Comparing incompatible types");

View file

@ -183,10 +183,10 @@ bool overlaps(const ExPolygons& expolys1, const ExPolygons& expolys2)
}
}
return false;
}
Point projection_onto(const ExPolygons& polygons, const Point& from)
{
}
Point projection_onto(const ExPolygons& polygons, const Point& from)
{
Point projected_pt;
double min_dist = std::numeric_limits<double>::max();

View file

@ -56,6 +56,8 @@ public:
double retract_length_toolchange() const;
double retract_restart_extra_toolchange() const;
bool use_firmware_retraction() const;
private:
// Private constructor to create a key for a search in std::set.
Extruder(unsigned int id) : m_id(id) {}
@ -64,7 +66,7 @@ private:
GCodeConfig *m_config;
// Print-wide global ID of this extruder.
unsigned int m_id;
// Current state of the extruder axis, may be resetted if use_relative_e_distance.
// Current state of the extruder axis, may be resetted if use_relative_e_distances.
double m_E;
// Current state of the extruder tachometer, used to output the extruded_volume() and used_filament() statistics.
double m_absolute_E;

View file

@ -95,7 +95,7 @@ struct SurfaceFillParams
this->overlap == rhs.overlap &&
this->angle == rhs.angle &&
this->bridge == rhs.bridge &&
// this->bridge_angle == rhs.bridge_angle &&
this->bridge_angle == rhs.bridge_angle &&
this->density == rhs.density &&
// this->dont_adjust == rhs.dont_adjust &&
this->anchor_length == rhs.anchor_length &&
@ -154,26 +154,42 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
//BBS
params.with_loop = surface.surface_type == stInternalWithLoop;
if (surface.is_solid()) {
if (surface.is_solid()) {
params.density = 100.f;
//FIXME for non-thick bridges, shall we allow a bottom surface pattern?
if (surface.is_solid_infill())
params.pattern = region_config.internal_solid_infill_pattern.value;
else if (surface.is_external() && !is_bridge)
params.pattern = surface.is_top() ? region_config.top_surface_pattern.value : region_config.bottom_surface_pattern.value;
else
params.pattern = region_config.top_surface_pattern == ipMonotonic ? ipMonotonic : ipRectilinear;
else if (surface.is_external() && ! is_bridge) {
if(surface.is_top())
params.pattern = region_config.top_surface_pattern.value;
else
params.pattern = region_config.bottom_surface_pattern.value;
}
else {
if(region_config.top_surface_pattern == ipMonotonic || region_config.top_surface_pattern == ipMonotonicLine)
params.pattern = ipMonotonic;
else
params.pattern = ipRectilinear;
}
} else if (params.density <= 0)
continue;
params.extrusion_role =
is_bridge ?
erBridgeInfill :
(surface.is_solid() ?
(surface.is_top() ? erTopSolidInfill : (surface.is_bottom()? erBottomSurface : erSolidInfill)) :
erInternalInfill);
params.bridge_angle = float(surface.bridge_angle);
params.extrusion_role = erInternalInfill;
if (is_bridge) {
if (surface.is_internal_bridge())
params.extrusion_role = erInternalBridgeInfill;
else
params.extrusion_role = erBridgeInfill;
} else if (surface.is_solid()) {
if (surface.is_top()) {
params.extrusion_role = erTopSolidInfill;
} else if (surface.is_bottom()) {
params.extrusion_role = erBottomSurface;
} else {
params.extrusion_role = erSolidInfill;
}
}
params.bridge_angle = float(surface.bridge_angle);
params.angle = float(Geometry::deg2rad(region_config.infill_direction.value));
// Calculate the actual flow we'll be using for this infill.
@ -194,11 +210,11 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
// so that internall infill will be aligned over all layers of the current region.
params.spacing = layerm.region().flow(*layer.object(), frInfill, layer.object()->config().layer_height, false).spacing();
// Anchor a sparse infill to inner perimeters with the following anchor length:
params.anchor_length = float(region_config.sparse_infill_anchor);
if (region_config.sparse_infill_anchor.percent)
params.anchor_length = float(region_config.infill_anchor);
if (region_config.infill_anchor.percent)
params.anchor_length = float(params.anchor_length * 0.01 * params.spacing);
params.anchor_length_max = float(region_config.sparse_infill_anchor_max);
if (region_config.sparse_infill_anchor_max.percent)
params.anchor_length_max = float(region_config.infill_anchor_max);
if (region_config.infill_anchor_max.percent)
params.anchor_length_max = float(params.anchor_length_max * 0.01 * params.spacing);
params.anchor_length = std::min(params.anchor_length, params.anchor_length_max);
}
@ -315,7 +331,11 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
if (internal_solid_fill == nullptr) {
// Produce another solid fill.
params.extruder = layerm.region().extruder(frSolidInfill);
params.pattern = layerm.region().config().top_surface_pattern == ipMonotonic ? ipMonotonic : ipRectilinear;
const auto top_pattern = layerm.region().config().top_surface_pattern;
if(top_pattern == ipMonotonic || top_pattern == ipMonotonicLine)
params.pattern = top_pattern;
else
params.pattern = ipRectilinear;
params.density = 100.f;
params.extrusion_role = erInternalInfill;
params.angle = float(Geometry::deg2rad(layerm.region().config().infill_direction.value));
@ -459,10 +479,12 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
#endif
}
LayerRegion* layerm = this->m_regions[surface_fill.region_id];
// Maximum length of the perimeter segment linking two infill lines.
f->link_max_length = (coord_t)scale_(link_max_length);
// Used by the concentric infill pattern to clip the loops to create extrusion paths.
f->loop_clipping = coord_t(scale_(surface_fill.params.flow.nozzle_diameter()) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER);
f->loop_clipping = coord_t(scale_(layerm->region().config().seam_gap.get_abs_value(surface_fill.params.flow.nozzle_diameter())));
// apply half spacing using this flow's own spacing and generate infill
FillParams params;
@ -480,14 +502,19 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
params.using_internal_flow = using_internal_flow;
params.no_extrusion_overlap = surface_fill.params.overlap;
params.with_loop = surface_fill.params.with_loop;
params.config = &layerm->region().config();
if (surface_fill.params.pattern == ipGrid)
params.can_reverse = false;
LayerRegion* layerm = this->m_regions[surface_fill.region_id];
for (ExPolygon& expoly : surface_fill.expolygons) {
f->no_overlap_expolygons = intersection_ex(surface_fill.no_overlap_expolygons, ExPolygons() = {expoly}, ApplySafetyOffset::Yes);
// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
f->spacing = surface_fill.params.spacing;
surface_fill.surface.expolygon = std::move(expoly);
if(surface_fill.params.bridge && surface_fill.surface.is_external() && surface_fill.params.density > 99.0){
params.density = layerm->region().config().bridge_density.get_abs_value(1.0);
params.dont_adjust = true;
}
// BBS: make fill
f->fill_surface_extrusion(&surface_fill.surface,
params,

View file

@ -28,6 +28,11 @@
namespace Slic3r {
//BBS: 0% of sparse_infill_line_width, no anchor at the start of sparse infill
float Fill::infill_anchor = 400;
//BBS: 20mm
float Fill::infill_anchor_max = 20;
Fill* Fill::new_from_type(const InfillPattern type)
{
switch (type) {

View file

@ -40,7 +40,7 @@ struct FillParams
bool full_infill() const { return density > 0.9999f; }
// Don't connect the fill lines around the inner perimeter.
bool dont_connect() const { return anchor_length_max < 0.05f; }
double filter_out_gap_fill { 0.0 };
// Fill density, fraction in <0, 1>
float density { 0.f };
@ -110,6 +110,9 @@ public:
// BBS: all no overlap expolygons in same layer
ExPolygons no_overlap_expolygons;
static float infill_anchor;
static float infill_anchor_max;
public:
virtual ~Fill() {}
virtual Fill* clone() const = 0;

View file

@ -3179,11 +3179,6 @@ void FillMonotonicLineWGapFill::fill_surface_extrusion(const Surface* surface, c
}), polylines.end());
ExtrusionEntityCollection gap_fill;
// OrcaSlicer: filter out tiny gap fills
polylines.erase(std::remove_if(polylines.begin(), polylines.end(), [&](const ThickPolyline &p) {
return p.length() < scale_(params.filter_out_gap_fill);
}), polylines.end());
variable_width(polylines, erGapFill, params.flow, gap_fill.entities);
coll_nosort->append(std::move(gap_fill.entities));

View file

@ -277,7 +277,7 @@ static constexpr const char* OBJECT_ID_ATTR = "object_id";
static constexpr const char* INSTANCEID_ATTR = "instance_id";
static constexpr const char* IDENTIFYID_ATTR = "identify_id";
static constexpr const char* PLATERID_ATTR = "plater_id";
static constexpr const char* PLATER_NAME_ATTR = "plater_name";
static constexpr const char* PLATER_NAME_ATTR = "plater_name";
static constexpr const char* PLATE_IDX_ATTR = "index";
static constexpr const char* SLICE_PREDICTION_ATTR = "prediction";
static constexpr const char* SLICE_WEIGHT_ATTR = "weight";
@ -910,7 +910,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
bool m_load_restore = false;
std::string m_backup_path;
std::string m_origin_file;
// Semantic version of Bambu Studio, that generated this 3MF.
// Semantic version of Orca Slicer, that generated this 3MF.
boost::optional<Semver> m_bambuslicer_generator_version;
unsigned int m_fdm_supports_painting_version = 0;
unsigned int m_seam_painting_version = 0;
@ -1769,7 +1769,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
lock.close();
if (!m_is_bbl_3mf) {
// if the 3mf was not produced by BambuStudio and there is more than one instance,
// if the 3mf was not produced by OrcaSlicer and there is more than one instance,
// split the object in as many objects as instances
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", found 3mf from other vendor, split as instance");
for (const IdToModelObjectMap::value_type& object : m_objects) {
@ -2046,7 +2046,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
}
plate_data_list[it->first-1]->locked = it->second->locked;
plate_data_list[it->first-1]->plate_index = it->second->plate_index-1;
plate_data_list[it->first-1]->plate_name = it->second->plate_name;
plate_data_list[it->first-1]->plate_name = it->second->plate_name;
plate_data_list[it->first-1]->obj_inst_map = it->second->obj_inst_map;
plate_data_list[it->first-1]->gcode_file = (m_load_restore || it->second->gcode_file.empty()) ? it->second->gcode_file : m_backup_path + "/" + it->second->gcode_file;
plate_data_list[it->first-1]->gcode_prediction = it->second->gcode_prediction;
@ -2616,7 +2616,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
}
}
}
void _BBS_3MF_Importer::_extract_layer_config_ranges_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, ConfigSubstitutionContext& config_substitutions)
{
if (stat.m_uncomp_size > 0) {
@ -3121,7 +3121,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
}
if (!m_is_bbl_3mf) {
// if the 3mf was not produced by BambuStudio and there is only one object,
// if the 3mf was not produced by OrcaSlicer and there is only one object,
// set the object name to match the filename
if (m_model->objects.size() == 1)
m_model->objects.front()->name = m_name;
@ -3522,19 +3522,23 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
m_is_bbl_3mf = true;
m_bambuslicer_generator_version = Semver::parse(m_curr_characters.substr(12));
}
else if (boost::starts_with(m_curr_characters, "OrcaSlicer-")) {
m_is_bbl_3mf = true;
m_bambuslicer_generator_version = Semver::parse(m_curr_characters.substr(11));
}
//TODO: currently use version 0, no need to load&&save this string
/*} else if (m_curr_metadata_name == BBS_FDM_SUPPORTS_PAINTING_VERSION) {
m_fdm_supports_painting_version = (unsigned int) atoi(m_curr_characters.c_str());
check_painting_version(m_fdm_supports_painting_version, FDM_SUPPORTS_PAINTING_VERSION,
_(L("The selected 3MF contains FDM supports painted object using a newer version of BambuStudio and is not compatible.")));
_(L("The selected 3MF contains FDM supports painted object using a newer version of OrcaSlicer and is not compatible.")));
} else if (m_curr_metadata_name == BBS_SEAM_PAINTING_VERSION) {
m_seam_painting_version = (unsigned int) atoi(m_curr_characters.c_str());
check_painting_version(m_seam_painting_version, SEAM_PAINTING_VERSION,
_(L("The selected 3MF contains seam painted object using a newer version of BambuStudio and is not compatible.")));
_(L("The selected 3MF contains seam painted object using a newer version of OrcaSlicer and is not compatible.")));
} else if (m_curr_metadata_name == BBS_MM_PAINTING_VERSION) {
m_mm_painting_version = (unsigned int) atoi(m_curr_characters.c_str());
check_painting_version(m_mm_painting_version, MM_PAINTING_VERSION,
_(L("The selected 3MF contains multi-material painted object using a newer version of BambuStudio and is not compatible.")));*/
_(L("The selected 3MF contains multi-material painted object using a newer version of OrcaSlicer and is not compatible.")));*/
} else if (m_curr_metadata_name == BBL_MODEL_ID_TAG) {
m_model_id = xml_unescape(m_curr_characters);
} else if (m_curr_metadata_name == BBL_MODEL_NAME_TAG) {
@ -4543,7 +4547,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
TriangleMesh triangle_mesh(std::move(its), volume_data.mesh_stats);
if (!m_is_bbl_3mf) {
// if the 3mf was not produced by BambuStudio and there is only one instance,
// if the 3mf was not produced by OrcaSlicer and there is only one instance,
// bake the transformation into the geometry to allow the reload from disk command
// to work properly
if (object.instances.size() == 1) {
@ -5414,7 +5418,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
}
// Adds content types file ("[Content_Types].xml";).
// The content of this file is the same for each BambuStudio 3mf.
// The content of this file is the same for each OrcaSlicer 3mf.
if (!_add_content_types_file_to_archive(archive)) {
return false;
}
@ -5769,7 +5773,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
}
// Adds relationships file ("_rels/.rels").
// The content of this file is the same for each BambuStudio 3mf.
// The content of this file is the same for each OrcaSlicer 3mf.
// The relationshis file contains a reference to the geometry file "3D/3dmodel.model", the name was chosen to be compatible with CURA.
if (!_add_relationships_file_to_archive(archive, {}, {}, {}, temp_data, export_plate_idx)) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" <<__LINE__ << boost::format(", _add_relationships_file_to_archive failed\n");
@ -5934,7 +5938,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
int i = 0;
for (auto & path : targets) {
for (auto & type : types)
stream << " <Relationship Target=\"/" << xml_escape(path) << "\" Id=\"rel-" << boost::to_string(++i) << "\" Type=\"" << type << "\"/>\n";
stream << " <Relationship Target=\"/" << xml_escape(path) << "\" Id=\"rel-" << std::to_string(++i) << "\" Type=\"" << type << "\"/>\n";
}
}
stream << "</Relationships>";
@ -6069,7 +6073,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
date = date.substr(0, 10);
metadata_item_map[BBL_CREATION_DATE_TAG] = date;
metadata_item_map[BBL_MODIFICATION_TAG] = date;
metadata_item_map[BBL_APPLICATION_TAG] = (boost::format("%1%-%2%") % SLIC3R_APP_KEY % SLIC3R_VERSION).str();
//SoftFever: write BambuStudio tag to keep it compatible
metadata_item_map[BBL_APPLICATION_TAG] = (boost::format("%1%-%2%") % "BambuStudio" % SLIC3R_VERSION).str();
}
metadata_item_map[BBS_3MF_VERSION] = std::to_string(VERSION_BBS_3MF);

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,7 @@
#include "PrintConfig.hpp"
#include "GCode/AvoidCrossingPerimeters.hpp"
#include "GCode/CoolingBuffer.hpp"
#include "GCode/FanMover.hpp"
#include "GCode/RetractWhenCrossingPerimeters.hpp"
#include "GCode/SpiralVase.hpp"
#include "GCode/ToolOrdering.hpp"
@ -19,6 +20,7 @@
#include "EdgeGrid.hpp"
#include "GCode/ThumbnailData.hpp"
#include "libslic3r/ObjectID.hpp"
#include "GCode/ExtrusionProcessor.hpp"
#include <memory>
#include <map>
@ -179,6 +181,7 @@ public:
const Point& last_pos() const { return m_last_pos; }
Vec2d point_to_gcode(const Point &point) const;
Point gcode_to_point(const Vec2d &point) const;
Vec2d point_to_gcode_quantized(const Point& point) const;
const FullPrintConfig &config() const { return m_config; }
const Layer* layer() const { return m_layer; }
GCodeWriter& writer() { return m_writer; }
@ -195,19 +198,19 @@ public:
void set_layer_count(unsigned int value) { m_layer_count = value; }
void apply_print_config(const PrintConfig &print_config);
// OrcaSlicer
std::string travel_to(const Point& point, ExtrusionRole role, std::string comment);
bool needs_retraction(const Polyline& travel, ExtrusionRole role, LiftType& lift_type);
std::string retract(bool toolchange = false, bool is_last_retraction = false, LiftType lift_type = LiftType::SpiralLift);
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
std::string set_extruder(unsigned int extruder_id, double print_z);
bool is_BBL_Printer();
// SoftFever
std::string set_object_info(Print* print);
// append full config to the given string
static void append_full_config(const Print& print, std::string& str);
// BBS: detect lift type in needs_retraction
bool needs_retraction(const Polyline &travel, ExtrusionRole role, LiftType &lift_type);
std::string retract(bool toolchange = false, bool is_last_retraction = false, LiftType lift_type = LiftType::SpiralLift);
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
//BBS
bool is_BBL_Printer();
// Object and support extrusions of the same PrintObject at the same print_z.
// public, so that it could be accessed by free helper functions from GCode.cpp
struct LayerToPrint
@ -403,20 +406,21 @@ private:
// For sequential print, the instance of the object to be printing has to be defined.
const size_t single_object_instance_idx);
std::string extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region);
std::string extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, bool ironing);
std::string extrude_support(const ExtrusionEntityCollection &support_fills);
std::string extrude_perimeters(const Print& print, const std::vector<ObjectByExtruder::Island::Region>& by_region);
std::string extrude_infill(const Print& print, const std::vector<ObjectByExtruder::Island::Region>& by_region, bool ironing);
std::string extrude_support(const ExtrusionEntityCollection& support_fills);
std::string travel_to(const Point &point, ExtrusionRole role, std::string comment);
// BBS
LiftType to_lift_type(ZHopType z_hop_types);
std::string set_extruder(unsigned int extruder_id, double print_z);
std::set<ObjectID> m_objsWithBrim; // indicates the objs with brim
std::set<ObjectID> m_objSupportsWithBrim; // indicates the objs' supports with brim
// Cache for custom seam enforcers/blockers for each layer.
SeamPlacer m_seam_placer;
ExtrusionQualityEstimator m_extrusion_quality_estimator;
/* Origin of print coordinates expressed in unscaled G-code coordinates.
This affects the input arguments supplied to the extrude*() and travel_to()
methods. */
@ -440,6 +444,13 @@ private:
// of the G-code lines: _EXTRUDE_SET_SPEED, _WIPE, _OVERHANG_FAN_START, _OVERHANG_FAN_END
// Those comments are received and consumed (removed from the G-code) by the CoolingBuffer.pm Perl module.
bool m_enable_cooling_markers;
bool m_enable_exclude_object;
std::vector<size_t> m_label_objects_ids;
std::string _encode_label_ids_to_base64(std::vector<size_t> ids);
// Orca
bool m_is_overhang_fan_on;
bool m_is_supp_interface_fan_on;
// Markers for the Pressure Equalizer to recognize the extrusion type.
// The Pressure Equalizer removes the markers from the final G-code.
bool m_enable_extrusion_role_markers;
@ -458,6 +469,8 @@ private:
//double m_volumetric_speed;
// Support for the extrusion role markers. Which marker is active?
ExtrusionRole m_last_extrusion_role;
// To ignore gapfill role for retract_lift_enforce
ExtrusionRole m_last_notgapfill_extrusion_role;
// Support for G-Code Processor
float m_last_height{ 0.0f };
float m_last_layer_z{ 0.0f };
@ -485,16 +498,15 @@ private:
bool m_second_layer_things_done;
// Index of a last object copy extruded.
std::pair<const PrintObject*, Point> m_last_obj_copy;
//BBS
bool m_enable_label_object;
std::vector<size_t> m_label_objects_ids;
std::string _encode_label_ids_to_base64(std::vector<size_t> ids);
bool m_silent_time_estimator_enabled;
// Processor
GCodeProcessor m_processor;
//some post-processing on the file, with their data class
std::unique_ptr<FanMover> m_fan_mover;
// BBS
Print* m_curr_print = nullptr;
unsigned int m_toolchange_count;
@ -511,7 +523,12 @@ private:
void _print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
// On the first printing layer. This flag triggers first layer speeds.
//BBS
bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0 && abs(m_layer->bottom_z()) < EPSILON; }
bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0 && abs(m_layer->bottom_z()) < EPSILON; }
int layer_id() const {
if (m_layer == nullptr)
return -1;
return m_layer->id();
}
// To control print speed of 1st object layer over raft interface.
bool object_layer_over_raft() const { return m_object_layer_over_raft; }

View file

@ -5,6 +5,7 @@
#include <boost/log/trivial.hpp>
#include <iostream>
#include <float.h>
#include <unordered_map>
#if 0
#define DEBUG
@ -61,7 +62,8 @@ struct CoolingLine
TYPE_G2 = 1 << 12,
TYPE_G3 = 1 << 13,
TYPE_FORCE_RESUME_FAN = 1 << 14,
TYPE_SET_FAN_CHANGING_LAYER = 1 << 15,
TYPE_SUPPORT_INTERFACE_FAN_START = 1 << 15,
TYPE_SUPPORT_INTERFACE_FAN_END = 1 << 16,
};
CoolingLine(unsigned int type, size_t line_start, size_t line_end) :
@ -480,6 +482,10 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
line.type = CoolingLine::TYPE_OVERHANG_FAN_START;
} else if (boost::starts_with(sline, ";_OVERHANG_FAN_END")) {
line.type = CoolingLine::TYPE_OVERHANG_FAN_END;
} else if (boost::starts_with(sline, ";_SUPP_INTERFACE_FAN_START")) {
line.type = CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START;
} else if (boost::starts_with(sline, ";_SUPP_INTERFACE_FAN_END")) {
line.type = CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_END;
} else if (boost::starts_with(sline, "G4 ")) {
// Parse the wait time.
line.type = CoolingLine::TYPE_G4;
@ -491,8 +497,6 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
(pos_P > 0) ? atof(sline.c_str() + pos_P + 1) * 0.001 : 0.);
} else if (boost::starts_with(sline, ";_FORCE_RESUME_FAN_SPEED")) {
line.type = CoolingLine::TYPE_FORCE_RESUME_FAN;
} else if (boost::starts_with(sline, ";_SET_FAN_SPEED_CHANGING_LAYER")) {
line.type = CoolingLine::TYPE_SET_FAN_CHANGING_LAYER;
}
if (line.type != 0)
adjustment->lines.emplace_back(std::move(line));
@ -725,14 +729,9 @@ std::string CoolingBuffer::apply_layer_cooldown(
new_gcode.reserve(gcode.size() * 2);
bool overhang_fan_control= false;
int overhang_fan_speed = 0;
enum class SetFanType {
sfChangingLayer = 0,
sfChangingFilament,
sfImmediatelyApply
};
auto change_extruder_set_fan = [ this, layer_id, layer_time, &new_gcode, &overhang_fan_control, &overhang_fan_speed](SetFanType type) {
bool supp_interface_fan_control= false;
int supp_interface_fan_speed = 0;
auto change_extruder_set_fan = [ this, layer_id, layer_time, &new_gcode, &overhang_fan_control, &overhang_fan_speed, &supp_interface_fan_control, &supp_interface_fan_speed](bool immediately_apply) {
#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder)
int fan_min_speed = EXTRUDER_CONFIG(fan_min_speed);
int fan_speed_new = EXTRUDER_CONFIG(reduce_fan_stop_start_freq) ? fan_min_speed : 0;
@ -741,6 +740,8 @@ std::string CoolingBuffer::apply_layer_cooldown(
int close_fan_the_first_x_layers = EXTRUDER_CONFIG(close_fan_the_first_x_layers);
// Is the fan speed ramp enabled?
int full_fan_speed_layer = EXTRUDER_CONFIG(full_fan_speed_layer);
supp_interface_fan_speed = EXTRUDER_CONFIG(support_material_interface_fan_speed);
if (close_fan_the_first_x_layers <= 0 && full_fan_speed_layer > 0) {
// When ramping up fan speed from close_fan_the_first_x_layers to full_fan_speed_layer, force close_fan_the_first_x_layers above zero,
// so there will be a zero fan speed at least at the 1st layer.
@ -769,6 +770,9 @@ std::string CoolingBuffer::apply_layer_cooldown(
fan_speed_new = std::clamp(int(float(fan_speed_new) * factor + 0.5f), 0, 255);
overhang_fan_speed = std::clamp(int(float(overhang_fan_speed) * factor + 0.5f), 0, 255);
}
supp_interface_fan_speed = EXTRUDER_CONFIG(support_material_interface_fan_speed);
supp_interface_fan_control = supp_interface_fan_speed >= 0;
#undef EXTRUDER_CONFIG
overhang_fan_control= overhang_fan_speed > fan_speed_new;
} else {
@ -776,34 +780,34 @@ std::string CoolingBuffer::apply_layer_cooldown(
overhang_fan_speed = 0;
fan_speed_new = 0;
additional_fan_speed_new = 0;
supp_interface_fan_control= false;
supp_interface_fan_speed = 0;
}
if (fan_speed_new != m_fan_speed) {
m_fan_speed = fan_speed_new;
//BBS
m_current_fan_speed = fan_speed_new;
if (type == SetFanType::sfImmediatelyApply)
if (immediately_apply)
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_fan_speed);
else if (type == SetFanType::sfChangingLayer)
this->m_set_fan_changing_layer = true;
//BBS: don't need to handle change filament, because we are always force to resume fan speed when filament change is finished
}
//BBS
if (additional_fan_speed_new != m_additional_fan_speed) {
m_additional_fan_speed = additional_fan_speed_new;
if (type == SetFanType::sfImmediatelyApply)
if (immediately_apply && m_config.auxiliary_fan.value)
new_gcode += GCodeWriter::set_additional_fan(m_additional_fan_speed);
else if (type == SetFanType::sfChangingLayer)
this->m_set_addition_fan_changing_layer = true;
//BBS: don't need to handle change filament, because we are always force to resume fan speed when filament change is finished
}
};
const char *pos = gcode.c_str();
int current_feedrate = 0;
//BBS
m_set_fan_changing_layer = false;
m_set_addition_fan_changing_layer = false;
change_extruder_set_fan(SetFanType::sfChangingLayer);
change_extruder_set_fan(true);
// Reduce set fan commands by deferring the GCodeWriter::set_fan calls. Inspired by SuperSlicer
// define fan_speed_change_requests and initialize it with all possible types fan speed change requests
std::unordered_map<int, bool> fan_speed_change_requests = {{CoolingLine::TYPE_OVERHANG_FAN_START, false},
{CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START, false},
{CoolingLine::TYPE_FORCE_RESUME_FAN, false}};
bool need_set_fan = false;
for (const CoolingLine *line : lines) {
const char *line_start = gcode.c_str() + line->line_start;
const char *line_end = gcode.c_str() + line->line_end;
@ -813,37 +817,37 @@ std::string CoolingBuffer::apply_layer_cooldown(
unsigned int new_extruder = (unsigned int)atoi(line_start + m_toolchange_prefix.size());
if (new_extruder != m_current_extruder) {
m_current_extruder = new_extruder;
change_extruder_set_fan(SetFanType::sfChangingFilament); //BBS: will force to resume fan speed when filament change is finished
change_extruder_set_fan(false); //BBS: will force to resume fan speed when filament change is finished
}
new_gcode.append(line_start, line_end - line_start);
} else if (line->type & CoolingLine::TYPE_OVERHANG_FAN_START) {
if (overhang_fan_control) {
//BBS
m_current_fan_speed = overhang_fan_speed;
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, overhang_fan_speed);
}
if (overhang_fan_control && !fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START]) {
need_set_fan = true;
fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START] = true;
}
} else if (line->type & CoolingLine::TYPE_OVERHANG_FAN_END) {
if (overhang_fan_control) {
//BBS
m_current_fan_speed = m_fan_speed;
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_fan_speed);
if (overhang_fan_control && fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START]) {
fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START] = false;
}
need_set_fan = true;
} else if (line->type & CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START) {
if (supp_interface_fan_control && !fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START]) {
fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START] = true;
need_set_fan = true;
}
} else if (line->type & CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_END && fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START]) {
if (supp_interface_fan_control) {
fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START] = false;
}
need_set_fan = true;
} else if (line->type & CoolingLine::TYPE_FORCE_RESUME_FAN) {
//BBS: force to write a fan speed command again
if (m_current_fan_speed != -1)
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_current_fan_speed);
if (m_additional_fan_speed != -1)
new_gcode += GCodeWriter::set_additional_fan(m_additional_fan_speed);
} else if (line->type & CoolingLine::TYPE_SET_FAN_CHANGING_LAYER) {
//BBS: check whether fan speed need to changed when change layer
if (m_current_fan_speed != -1 && m_set_fan_changing_layer) {
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_current_fan_speed);
m_set_fan_changing_layer = false;
// check if any fan speed change request is active
if (m_fan_speed != -1 && !std::any_of(fan_speed_change_requests.begin(), fan_speed_change_requests.end(), [](const std::pair<int, bool>& p) { return p.second; })){
fan_speed_change_requests[CoolingLine::TYPE_FORCE_RESUME_FAN] = true;
need_set_fan = true;
}
if (m_additional_fan_speed != -1 && m_set_addition_fan_changing_layer) {
if (m_additional_fan_speed != -1 && m_config.auxiliary_fan.value)
new_gcode += GCodeWriter::set_additional_fan(m_additional_fan_speed);
m_set_addition_fan_changing_layer = false;
}
}
else if (line->type & CoolingLine::TYPE_EXTRUDE_END) {
// Just remove this comment.
@ -929,6 +933,24 @@ std::string CoolingBuffer::apply_layer_cooldown(
} else {
new_gcode.append(line_start, line_end - line_start);
}
if (need_set_fan) {
if (fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START]){
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, overhang_fan_speed);
m_current_fan_speed = overhang_fan_speed;
}
else if (fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START]){
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, supp_interface_fan_speed);
m_current_fan_speed = supp_interface_fan_speed;
}
else if(fan_speed_change_requests[CoolingLine::TYPE_FORCE_RESUME_FAN] && m_current_fan_speed != -1){
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_current_fan_speed);
fan_speed_change_requests[CoolingLine::TYPE_FORCE_RESUME_FAN] = false;
}
else
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_fan_speed);
need_set_fan = false;
}
pos = line_end;
}
const char *gcode_end = gcode.c_str() + gcode.size();

View file

@ -59,9 +59,6 @@ private:
bool m_cooling_logic_proportional = false;
//BBS: current fan speed
int m_current_fan_speed;
//BBS:
bool m_set_fan_changing_layer = false;
bool m_set_addition_fan_changing_layer = false;
};
}

View file

@ -1,3 +1,4 @@
#include "ExtrusionEntity.hpp"
#include "libslic3r/libslic3r.h"
#include "libslic3r/Utils.hpp"
#include "libslic3r/Print.hpp"
@ -16,6 +17,7 @@
#include <float.h>
#include <assert.h>
#include <regex>
#if __has_include(<charconv>)
#include <charconv>
@ -60,6 +62,23 @@ const std::vector<std::string> GCodeProcessor::Reserved_Tags = {
"_GP_TOTAL_LAYER_NUMBER_PLACEHOLDER"
};
const std::vector<std::string> GCodeProcessor::Reserved_Tags_compatible = {
"TYPE:",
"WIPE_START",
"WIPE_END",
"HEIGHT:",
"WIDTH:",
"LAYER_CHANGE",
"COLOR_CHANGE",
"PAUSE_PRINT",
"CUSTOM_GCODE",
"_GP_FIRST_LINE_M73_PLACEHOLDER",
"_GP_LAST_LINE_M73_PLACEHOLDER",
"_GP_ESTIMATED_PRINTING_TIME_PLACEHOLDER",
"_GP_TOTAL_LAYER_NUMBER_PLACEHOLDER"
};
const std::string GCodeProcessor::Flush_Start_Tag = " FLUSH_START";
const std::string GCodeProcessor::Flush_End_Tag = " FLUSH_END";
@ -73,6 +92,8 @@ const std::map<NozzleType,int> GCodeProcessor::Nozzle_Type_To_HRC={
const float GCodeProcessor::Wipe_Width = 0.05f;
const float GCodeProcessor::Wipe_Height = 0.05f;
bool GCodeProcessor::s_IsBBLPrinter = true;
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
const std::string GCodeProcessor::Mm3_Per_Mm_Tag = "MM3_PER_MM:";
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
@ -101,16 +122,16 @@ static float intersection_distance(float initial_rate, float final_rate, float a
static float speed_from_distance(float initial_feedrate, float distance, float acceleration)
{
// to avoid invalid negative numbers due to numerical errors
// to avoid invalid negative numbers due to numerical errors
float value = std::max(0.0f, sqr(initial_feedrate) + 2.0f * acceleration * distance);
return ::sqrt(value);
}
// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the
// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the
// acceleration within the allotted distance.
static float max_allowable_speed(float acceleration, float target_velocity, float distance)
{
// to avoid invalid negative numbers due to numerical errors
// to avoid invalid negative numbers due to numerical errors
float value = std::max(0.0f, sqr(target_velocity) - 2.0f * acceleration * distance);
return std::sqrt(value);
}
@ -161,7 +182,7 @@ void GCodeProcessor::TimeBlock::calculate_trapezoid()
float cruise_distance = distance - accelerate_distance - decelerate_distance;
// Not enough space to reach the nominal feedrate.
// This means no cruising, and we'll have to use intersection_distance() to calculate when to abort acceleration
// This means no cruising, and we'll have to use intersection_distance() to calculate when to abort acceleration
// and start braking in order to reach the exit_feedrate exactly at the end of this block.
if (cruise_distance < 0.0f) {
accelerate_distance = std::clamp(intersection_distance(feedrate_profile.entry, feedrate_profile.exit, acceleration, distance), 0.0f, distance);
@ -470,12 +491,17 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
PrintEstimatedStatistics::ETimeMode mode = static_cast<PrintEstimatedStatistics::ETimeMode>(i);
if (mode == PrintEstimatedStatistics::ETimeMode::Normal || machine.enabled) {
char buf[128];
if(!s_IsBBLPrinter)
// SoftFever: compatibility with klipper_estimator
sprintf(buf, "; estimated printing time (normal mode) = %s\n", get_time_dhms(machine.time).c_str());
else {
//sprintf(buf, "; estimated printing time (%s mode) = %s\n",
// (mode == PrintEstimatedStatistics::ETimeMode::Normal) ? "normal" : "silent",
// get_time_dhms(machine.time).c_str());
sprintf(buf, "; model printing time: %s; total estimated time: %s\n",
get_time_dhms(machine.time - machine.prepare_time).c_str(),
get_time_dhms(machine.time).c_str());
}
ret += buf;
}
}
@ -636,7 +662,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
if (processed && lines_added_count > 0)
offsets.push_back({ line_id, lines_added_count });
if (! processed && ! is_temporary_decoration(gcode_line) &&
(GCodeReader::GCodeLine::cmd_is(gcode_line, "G1") ||
(GCodeReader::GCodeLine::cmd_is(gcode_line, "G1") ||
GCodeReader::GCodeLine::cmd_is(gcode_line, "G2") ||
GCodeReader::GCodeLine::cmd_is(gcode_line, "G3"))) {
// remove temporary lines, add lines M73 where needed
@ -651,7 +677,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
gcode_line.clear();
}
// Skip EOL.
it = it_end;
it = it_end;
if (it != it_bufend && *it == '\r')
++ it;
if (it != it_bufend && *it == '\n')
@ -822,10 +848,12 @@ void GCodeProcessorResult::reset() {
#endif // ENABLE_GCODE_VIEWER_STATISTICS
const std::vector<std::pair<GCodeProcessor::EProducer, std::string>> GCodeProcessor::Producers = {
//BBS: BambuStudio is also "bambu". Otherwise the time estimation didn't work.
//BBS: OrcaSlicer is also "bambu". Otherwise the time estimation didn't work.
//FIXME: Workaround and should be handled when do removing-bambu
{ EProducer::BambuStudio, SLIC3R_APP_NAME },
{ EProducer::BambuStudio, "generated by BambuStudio" }
{ EProducer::OrcaSlicer, SLIC3R_APP_NAME },
{ EProducer::OrcaSlicer, "generated by OrcaSlicer" },
{ EProducer::OrcaSlicer, "generated by BambuStudio" },
{ EProducer::OrcaSlicer, "BambuStudio" }
//{ EProducer::Slic3rPE, "generated by Slic3r Bambu Edition" },
//{ EProducer::Slic3r, "generated by Slic3r" },
//{ EProducer::SuperSlicer, "generated by SuperSlicer" },
@ -843,11 +871,12 @@ bool GCodeProcessor::contains_reserved_tag(const std::string& gcode, std::string
bool ret = false;
GCodeReader parser;
parser.parse_buffer(gcode, [&ret, &found_tag](GCodeReader& parser, const GCodeReader::GCodeLine& line) {
auto& _tags = s_IsBBLPrinter ? Reserved_Tags : Reserved_Tags_compatible;
parser.parse_buffer(gcode, [&ret, &found_tag, _tags](GCodeReader& parser, const GCodeReader::GCodeLine& line) {
std::string comment = line.raw();
if (comment.length() > 2 && comment.front() == ';') {
comment = comment.substr(1);
for (const std::string& s : Reserved_Tags) {
for (const std::string& s : _tags) {
if (boost::starts_with(comment, s)) {
ret = true;
found_tag = comment;
@ -870,11 +899,12 @@ bool GCodeProcessor::contains_reserved_tags(const std::string& gcode, unsigned i
CNumericLocalesSetter locales_setter;
GCodeReader parser;
parser.parse_buffer(gcode, [&ret, &found_tag, max_count](GCodeReader& parser, const GCodeReader::GCodeLine& line) {
auto& _tags = s_IsBBLPrinter ? Reserved_Tags : Reserved_Tags_compatible;
parser.parse_buffer(gcode, [&ret, &found_tag, max_count, _tags](GCodeReader& parser, const GCodeReader::GCodeLine& line) {
std::string comment = line.raw();
if (comment.length() > 2 && comment.front() == ';') {
comment = comment.substr(1);
for (const std::string& s : Reserved_Tags) {
for (const std::string& s : _tags) {
if (boost::starts_with(comment, s)) {
ret = true;
found_tag.push_back(comment);
@ -917,6 +947,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
m_result.filament_densities.resize(extruders_count);
m_result.filament_vitrification_temperature.resize(extruders_count);
m_extruder_temps.resize(extruders_count);
m_result.nozzle_hrc = static_cast<int>(config.nozzle_hrc.getInt());
m_result.nozzle_type = config.nozzle_type;
for (size_t i = 0; i < extruders_count; ++ i) {
m_extruder_offsets[i] = to_3d(config.extruder_offset.get_at(i).cast<float>().eval(), 0.f);
@ -927,12 +958,17 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
m_result.filament_vitrification_temperature[i] = static_cast<float>(config.temperature_vitrification.get_at(i));
}
if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfKlipper) {
if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfKlipper || m_flavor == gcfRepRapFirmware) {
m_time_processor.machine_limits = reinterpret_cast<const MachineEnvelopeConfig&>(config);
if (m_flavor == gcfMarlinLegacy) {
// Legacy Marlin does not have separate travel acceleration, it uses the 'extruding' value instead.
m_time_processor.machine_limits.machine_max_acceleration_travel = m_time_processor.machine_limits.machine_max_acceleration_extruding;
}
if (m_flavor == gcfRepRapFirmware) {
// RRF does not support setting min feedrates. Set them to zero.
m_time_processor.machine_limits.machine_min_travel_rate.values.assign(m_time_processor.machine_limits.machine_min_travel_rate.size(), 0.);
m_time_processor.machine_limits.machine_min_extruding_rate.values.assign(m_time_processor.machine_limits.machine_min_extruding_rate.size(), 0.);
}
}
// Filament load / unload times are not specific to a firmware flavor. Let anybody use it if they find it useful.
@ -973,6 +1009,9 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
if (nozzle_volume != nullptr)
m_nozzle_volume = nozzle_volume->value;
const ConfigOptionInt *nozzle_HRC = config.option<ConfigOptionInt>("nozzle_hrc");
if (nozzle_HRC != nullptr) m_result.nozzle_hrc = nozzle_HRC->value;
const ConfigOptionEnum<NozzleType>* nozzle_type = config.option<ConfigOptionEnum<NozzleType>>("nozzle_type");
if (nozzle_type != nullptr)
m_result.nozzle_type=nozzle_type->value;
@ -1080,7 +1119,7 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
}
}
}
if (m_extruder_offsets.size() < m_result.extruders_count) {
for (size_t i = m_extruder_offsets.size(); i < m_result.extruders_count; ++i) {
m_extruder_offsets.emplace_back(DEFAULT_EXTRUDER_OFFSET);
@ -1355,12 +1394,12 @@ void GCodeProcessor::process_file(const std::string& filename, std::function<voi
});
m_parser.reset();
// if the gcode was produced by BambuStudio,
// if the gcode was produced by OrcaSlicer,
// extract the config from it
if (m_producer == EProducer::BambuStudio || m_producer == EProducer::Slic3rPE || m_producer == EProducer::Slic3r) {
if (m_producer == EProducer::OrcaSlicer || m_producer == EProducer::Slic3rPE || m_producer == EProducer::Slic3r) {
DynamicPrintConfig config;
config.apply(FullPrintConfig::defaults());
// Silently substitute unknown values by new ones for loading configurations from BambuStudio's own G-code.
// Silently substitute unknown values by new ones for loading configurations from OrcaSlicer's own G-code.
// Showing substitution log or errors may make sense, but we are not really reading many values from the G-code config,
// thus a probability of incorrect substitution is low and the G-code viewer is a consumer-only anyways.
config.load_from_gcode_file(filename, ForwardCompatibilitySubstitutionRule::EnableSilent);
@ -1410,7 +1449,7 @@ void GCodeProcessor::initialize(const std::string& filename)
void GCodeProcessor::process_buffer(const std::string &buffer)
{
//FIXME maybe cache GCodeLine gline to be over multiple parse_buffer() invocations.
m_parser.parse_buffer(buffer, [this](GCodeReader&, const GCodeReader::GCodeLine& line) {
m_parser.parse_buffer(buffer, [this](GCodeReader&, const GCodeReader::GCodeLine& line) {
this->process_gcode_line(line, false);
});
}
@ -1452,7 +1491,7 @@ void GCodeProcessor::finalize(bool post_process)
else
m_result.moves[i].layer_duration = 0;
}
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
std::cout << "\n";
m_mm3_per_mm_compare.output();
@ -1608,7 +1647,7 @@ void GCodeProcessor::apply_config_simplify3d(const std::string& filename)
}
return false;
};
begin = skip_whitespaces(begin, end);
end = remove_eols(begin, end);
if (begin != end) {
@ -1666,7 +1705,6 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool
m_start_position = m_end_position;
const std::string_view cmd = line.cmd();
//OrcaSlicer
if (m_flavor == gcfKlipper)
{
if (boost::iequals(cmd, "SET_VELOCITY_LIMIT"))
@ -1690,7 +1728,7 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool
case '2':
case '3': { process_G2_G3(line); break; } // Move
//BBS
case '4': { process_G4(line); break; } // Delay
case 4: { process_G4(line); break; } // Delay
default: break;
}
break;
@ -1890,7 +1928,7 @@ template<typename T>
auto str_end = sv.data() + sv.size();
auto [end_ptr, error_code] = std::from_chars(sv.data(), str_end, out);
return error_code == std::errc() && end_ptr == str_end;
}
}
else
#endif
{
@ -2043,7 +2081,7 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
return;
}
if (!producers_enabled || m_producer == EProducer::BambuStudio) {
if (!producers_enabled || m_producer == EProducer::OrcaSlicer) {
// height tag
if (boost::starts_with(comment, reserved_tag(ETags::Height))) {
if (!parse_number(comment.substr(reserved_tag(ETags::Height).size()), m_forced_height))
@ -2181,9 +2219,9 @@ bool GCodeProcessor::process_producers_tags(const std::string_view comment)
switch (m_producer)
{
case EProducer::Slic3rPE:
case EProducer::Slic3r:
case EProducer::Slic3r:
case EProducer::SuperSlicer:
case EProducer::BambuStudio: { return process_bambuslicer_tags(comment); }
case EProducer::OrcaSlicer: { return process_bambuslicer_tags(comment); }
case EProducer::Cura: { return process_cura_tags(comment); }
case EProducer::Simplify3D: { return process_simplify3d_tags(comment); }
case EProducer::CraftWare: { return process_craftware_tags(comment); }
@ -2288,7 +2326,7 @@ bool GCodeProcessor::process_simplify3d_tags(const std::string_view comment)
set_extrusion_role(erSkirt);
return true;
}
// ; outer perimeter
pos = cmt.find(" outer perimeter");
if (pos == 0) {
@ -2332,6 +2370,13 @@ bool GCodeProcessor::process_simplify3d_tags(const std::string_view comment)
return true;
}
// ; internal bridge
pos = cmt.find(" internal bridge");
if (pos == 0) {
set_extrusion_role(erInternalBridgeInfill);
return true;
}
// ; support
pos = cmt.find(" support");
if (pos == 0) {
@ -2483,6 +2528,8 @@ bool GCodeProcessor::process_ideamaker_tags(const std::string_view comment)
set_extrusion_role(erInternalInfill);
else if (type == "BRIDGE")
set_extrusion_role(erBridgeInfill);
else if (type == "INTERNAL BRIDGE")
set_extrusion_role(erInternalBridgeInfill);
else if (type == "SUPPORT")
set_extrusion_role(erSupportMaterial);
else {
@ -2682,7 +2729,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
type = (delta_pos[Z] == 0.0f) ? EMoveType::Unretract : EMoveType::Travel;
else if (delta_pos[X] != 0.0f || delta_pos[Y] != 0.0f)
type = EMoveType::Extrude;
}
}
else if (delta_pos[X] != 0.0f || delta_pos[Y] != 0.0f || delta_pos[Z] != 0.0f)
type = EMoveType::Travel;
@ -2755,7 +2802,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
else if (m_extrusion_role == erExternalPerimeter)
// cross section: rectangle
m_width = delta_pos[E] * static_cast<float>(M_PI * sqr(1.05f * filament_radius)) / (delta_xyz * m_height);
else if (m_extrusion_role == erBridgeInfill || m_extrusion_role == erNone)
else if (m_extrusion_role == erBridgeInfill || m_extrusion_role == erInternalBridgeInfill || m_extrusion_role == erNone)
// cross section: circle
m_width = static_cast<float>(m_result.filament_diameters[m_extruder_id]) * std::sqrt(delta_pos[E] / delta_xyz);
else
@ -2880,7 +2927,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
}
// calculates block acceleration
float acceleration =
float acceleration =
(type == EMoveType::Travel) ? get_travel_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)) :
(is_extrusion_only_move(delta_pos) ?
get_retract_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)) :
@ -3212,7 +3259,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line)
else if (m_extrusion_role == erExternalPerimeter)
//BBS: cross section: rectangle
m_width = delta_pos[E] * static_cast<float>(M_PI * sqr(1.05f * filament_radius)) / (delta_xyz * m_height);
else if (m_extrusion_role == erBridgeInfill || m_extrusion_role == erNone)
else if (m_extrusion_role == erBridgeInfill || m_extrusion_role == erInternalBridgeInfill || m_extrusion_role == erNone)
//BBS: cross section: circle
m_width = static_cast<float>(m_result.filament_diameters[m_extruder_id]) * std::sqrt(delta_pos[E] / delta_xyz);
else
@ -3355,7 +3402,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line)
}
else if (a == Y || a == Z) {
continue;
}
}
else {
float v_exit = prev.axis_feedrate[a];
float v_entry = curr.axis_feedrate[a];
@ -3578,7 +3625,7 @@ void GCodeProcessor::process_G92(const GCodeReader::GCodeLine& line)
simulate_st_synchronize();
if (!any_found && !line.has_unknown_axis()) {
// The G92 may be called for axes that PrusaSlicer does not recognize, for example see GH issue #3510,
// The G92 may be called for axes that PrusaSlicer does not recognize, for example see GH issue #3510,
// where G92 A0 B0 is called although the extruder axis is till E.
for (unsigned char a = X; a <= E; ++a) {
m_origin[a] = m_end_position[a];
@ -3826,7 +3873,7 @@ void GCodeProcessor::process_SET_VELOCITY_LIMIT(const GCodeReader::GCodeLine& li
{
_jerk = std::stof(matches[1]);
}
catch (...) {}
catch (...){}
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
set_option_value(m_time_processor.machine_limits.machine_max_jerk_x, i, _jerk);
set_option_value(m_time_processor.machine_limits.machine_max_jerk_y, i, _jerk);
@ -3856,8 +3903,8 @@ void GCodeProcessor::process_SET_VELOCITY_LIMIT(const GCodeReader::GCodeLine& li
}
catch (...) {}
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
set_option_value(m_time_processor.machine_limits.machine_max_speed_x, i, _speed);
set_option_value(m_time_processor.machine_limits.machine_max_speed_y, i, _speed);
set_option_value(m_time_processor.machine_limits.machine_max_speed_x, i, _speed);
set_option_value(m_time_processor.machine_limits.machine_max_speed_y, i, _speed);
}
}
@ -4289,7 +4336,9 @@ void GCodeProcessor::update_slice_warnings()
warning.params.clear();
warning.level=1;
int nozzle_hrc = Nozzle_Type_To_HRC.find(m_result.nozzle_type)->second;
int nozzle_hrc = m_result.nozzle_hrc;
if(nozzle_hrc <= 0)
nozzle_hrc = Nozzle_Type_To_HRC.find(m_result.nozzle_type)->second;
if (nozzle_hrc!=0) {
for (size_t i = 0; i < used_extruders.size(); i++) {
int HRC=0;
@ -4310,4 +4359,3 @@ void GCodeProcessor::update_slice_warnings()
}
} /* namespace Slic3r */

View file

@ -97,11 +97,11 @@ namespace Slic3r {
{
std::string _objName1;
std::string _objName2;
float _height;
double _height;
const void *_obj1; // nullptr means wipe tower
const void *_obj2;
int layer = -1;
ConflictResult(const std::string &objName1, const std::string &objName2, float height, const void *obj1, const void *obj2)
ConflictResult(const std::string &objName1, const std::string &objName2, double height, const void *obj1, const void *obj2)
: _objName1(objName1), _objName2(objName2), _height(height), _obj1(obj1), _obj2(obj2)
{}
ConflictResult() = default;
@ -192,6 +192,7 @@ namespace Slic3r {
std::vector<std::pair<float, std::pair<size_t, size_t>>> spiral_vase_layers;
//BBS
std::vector<SliceWarning> warnings;
int nozzle_hrc;
NozzleType nozzle_type;
BedType bed_type = BedType::btCount;
#if ENABLE_GCODE_VIEWER_STATISTICS
@ -235,6 +236,7 @@ namespace Slic3r {
class GCodeProcessor
{
static const std::vector<std::string> Reserved_Tags;
static const std::vector<std::string> Reserved_Tags_compatible;
static const std::string Flush_Start_Tag;
static const std::string Flush_End_Tag;
static const std::map<NozzleType, int>Nozzle_Type_To_HRC;
@ -256,8 +258,8 @@ namespace Slic3r {
Total_Layer_Number_Placeholder
};
static const std::string& reserved_tag(ETags tag) { return Reserved_Tags[static_cast<unsigned char>(tag)]; }
// checks the given gcode for reserved tags and returns true when finding the 1st (which is returned into found_tag)
static const std::string& reserved_tag(ETags tag) { return s_IsBBLPrinter ? Reserved_Tags[static_cast<unsigned char>(tag)] : Reserved_Tags_compatible[static_cast<unsigned char>(tag)]; }
// checks the given gcode for reserved tags and returns true when finding the 1st (which is returned into found_tag)
static bool contains_reserved_tag(const std::string& gcode, std::string& found_tag);
// checks the given gcode for reserved tags and returns true when finding any
// (the first max_count found tags are returned into found_tag)
@ -269,6 +271,8 @@ namespace Slic3r {
static const float Wipe_Width;
static const float Wipe_Height;
static bool s_IsBBLPrinter;
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
static const std::string Mm3_Per_Mm_Tag;
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
@ -365,7 +369,7 @@ namespace Slic3r {
AxisCoords axis_feedrate; // mm/s
AxisCoords abs_axis_feedrate; // mm/s
//BBS: unit vector of enter speed and exit speed in x-y-z space.
//BBS: unit vector of enter speed and exit speed in x-y-z space.
//For line move, there are same. For arc move, there are different.
Vec3f enter_direction;
Vec3f exit_direction;
@ -669,7 +673,7 @@ namespace Slic3r {
enum class EProducer
{
Unknown,
BambuStudio,
OrcaSlicer,
Slic3rPE,
Slic3r,
SuperSlicer,

View file

@ -128,9 +128,9 @@ public:
}
WipeTowerWriter& disable_linear_advance() {
if (m_gcode_flavor == gcfKlipper)
if(m_gcode_flavor == gcfKlipper)
m_gcode += "SET_PRESSURE_ADVANCE ADVANCE=0\n";
else if (m_gcode_flavor == gcfRepRapFirmware)
else if(m_gcode_flavor == gcfRepRapFirmware)
m_gcode += std::string("M572 D") + std::to_string(m_current_tool) + " S0\n";
else
m_gcode += "M900 K0\n";

View file

@ -15,18 +15,21 @@
namespace Slic3r {
const bool GCodeWriter::full_gcode_comment = false;
bool GCodeWriter::full_gcode_comment = true;
const double GCodeWriter::slope_threshold = 3 * PI / 180;
void GCodeWriter::apply_print_config(const PrintConfig &print_config)
{
this->config.apply(print_config, true);
m_single_extruder_multi_material = print_config.single_extruder_multi_material.value;
bool is_marlin = print_config.gcode_flavor.value == gcfMarlinLegacy
|| print_config.gcode_flavor.value == gcfMarlinFirmware
|| print_config.gcode_flavor.value == gcfKlipper;
m_max_acceleration = std::lrint(is_marlin ? print_config.machine_max_acceleration_extruding.values.front() : 0);
m_max_jerk = std::lrint(is_marlin ? std::min(print_config.machine_max_jerk_x.values.front(), print_config.machine_max_jerk_y.values.front()) : 0);
bool use_mach_limits = print_config.gcode_flavor.value == gcfMarlinLegacy ||
print_config.gcode_flavor.value == gcfMarlinFirmware ||
print_config.gcode_flavor.value == gcfKlipper ||
print_config.gcode_flavor.value == gcfRepRapFirmware;
m_max_acceleration = std::lrint(use_mach_limits ? print_config.machine_max_acceleration_extruding.values.front() : 0);
m_max_jerk = std::lrint(use_mach_limits ? std::min(print_config.machine_max_jerk_x.values.front(), print_config.machine_max_jerk_y.values.front()) : 0);
m_max_jerk_z = print_config.machine_max_jerk_z.values.front();
m_max_jerk_e = print_config.machine_max_jerk_e.values.front();
}
void GCodeWriter::set_extruders(std::vector<unsigned int> extruder_ids)
@ -173,15 +176,16 @@ std::string GCodeWriter::set_acceleration(unsigned int acceleration)
// This is new MarlinFirmware with separated print/retraction/travel acceleration.
// Use M204 P, we don't want to override travel acc by M204 S (which is deprecated anyway).
gcode << "M204 P" << acceleration;
} else if (FLAVOR_IS(gcfKlipper) && this->config.accel_to_decel_enable) {
gcode << "SET_VELOCITY_LIMIT ACCEL_TO_DECEL=" << acceleration * this->config.accel_to_decel_factor / 100;
if (GCodeWriter::full_gcode_comment) gcode << " ; adjust ACCEL_TO_DECEL";
gcode << "\nM204 S" << acceleration;
// Set max accel to decel to half of acceleration
} else {
// M204: Set default acceleration
} else if (FLAVOR_IS(gcfKlipper)) {
gcode << "SET_VELOCITY_LIMIT ACCEL=" << acceleration;
if (this->config.accel_to_decel_enable) {
gcode << " ACCEL_TO_DECEL=" << acceleration * this->config.accel_to_decel_factor / 100;
if (GCodeWriter::full_gcode_comment)
gcode << " ; adjust ACCEL_TO_DECEL";
}
} else
gcode << "M204 S" << acceleration;
}
//BBS
if (GCodeWriter::full_gcode_comment) gcode << " ; adjust acceleration";
gcode << "\n";
@ -189,45 +193,55 @@ std::string GCodeWriter::set_acceleration(unsigned int acceleration)
return gcode.str();
}
std::string GCodeWriter::set_pressure_advance(double pa) const
{
std::ostringstream gcode;
if (pa < 0) return gcode.str();
if (false) { // todo: bbl printer
// OrcaSlicer: set L1000 to use linear model
gcode << "M900 K" << std::setprecision(4) << pa << " L1000 M10 ; Override pressure advance value\n";
} else {
if (this->config.gcode_flavor == gcfKlipper)
gcode << "SET_PRESSURE_ADVANCE ADVANCE=" << std::setprecision(4) << pa << "; Override pressure advance value\n";
else if (this->config.gcode_flavor == gcfRepRapFirmware)
gcode << ("M572 D0 S") << std::setprecision(4) << pa << "; Override pressure advance value\n";
else
gcode << "M900 K" << std::setprecision(4) << pa << "; Override pressure advance value\n";
}
return gcode.str();
}
std::string GCodeWriter::set_jerk_xy(double jerk)
{
// Clamp the jerk to the allowed maximum.
if (m_max_jerk > 0 && jerk > m_max_jerk) jerk = m_max_jerk;
if (jerk < 0.01 || is_approx(jerk, m_last_jerk)) return std::string();
if (m_max_jerk > 0 && jerk > m_max_jerk)
jerk = m_max_jerk;
if (jerk < 0.01 || is_approx(jerk, m_last_jerk))
return std::string();
m_last_jerk = jerk;
std::ostringstream gcode;
if (FLAVOR_IS(gcfKlipper))
if(FLAVOR_IS(gcfKlipper))
gcode << "SET_VELOCITY_LIMIT SQUARE_CORNER_VELOCITY=" << jerk;
else
gcode << "M205 X" << jerk << " Y" << jerk;
if (m_is_bbl_printers)
gcode << std::setprecision(2) << " Z" << m_max_jerk_z << " E" << m_max_jerk_e;
if (GCodeWriter::full_gcode_comment) gcode << " ; adjust jerk";
gcode << "\n";
return gcode.str();
}
std::string GCodeWriter::set_pressure_advance(double pa) const
{
std::ostringstream gcode;
if (pa < 0)
return gcode.str();
if(m_is_bbl_printers){
//SoftFever: set L1000 to use linear model
gcode << "M900 K" <<std::setprecision(4)<< pa << " L1000 M10 ; Override pressure advance value\n";
}
else{
if (FLAVOR_IS(gcfKlipper))
gcode << "SET_PRESSURE_ADVANCE ADVANCE=" << std::setprecision(4) << pa << "; Override pressure advance value\n";
else if(FLAVOR_IS(gcfRepRapFirmware))
gcode << ("M572 D0 S") << std::setprecision(4) << pa << "; Override pressure advance value\n";
else
gcode << "M900 K" <<std::setprecision(4)<< pa << "; Override pressure advance value\n";
}
return gcode.str();
}
std::string GCodeWriter::reset_e(bool force)
{
if (FLAVOR_IS(gcfMach3)
@ -241,7 +255,7 @@ std::string GCodeWriter::reset_e(bool force)
m_extruder->reset_E();
}
if (!this->config.use_relative_e_distances) {
if (! this->config.use_relative_e_distances) {
std::ostringstream gcode;
gcode << "G92 E0";
//BBS
@ -296,11 +310,12 @@ std::string GCodeWriter::toolchange(unsigned int extruder_id)
return gcode.str();
}
std::string GCodeWriter::set_speed(double F, const std::string &comment, const std::string &cooling_marker) const
std::string GCodeWriter::set_speed(double F, const std::string &comment, const std::string &cooling_marker)
{
assert(F > 0.);
assert(F < 100000.);
m_current_speed = F;
GCodeG1Formatter w;
w.emit_f(F);
//BBS
@ -320,7 +335,9 @@ std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &com
GCodeG1Formatter w;
w.emit_xy(point_on_plate);
w.emit_f(this->config.travel_speed.value * 60.0);
auto speed = m_is_first_layer
? this->config.get_abs_value("initial_layer_travel_speed") : this->config.travel_speed.value;
w.emit_f(speed * 60.0);
//BBS
w.emit_comment(GCodeWriter::full_gcode_comment, comment);
return w.string();
@ -339,6 +356,8 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
used for unlift. */
// BBS
Vec3d dest_point = point;
auto travel_speed =
m_is_first_layer ? this->config.get_abs_value("initial_layer_travel_speed") : this->config.travel_speed.value;
//BBS: a z_hop need to be handle when travel
if (std::abs(m_to_lift) > EPSILON) {
assert(std::abs(m_lifted) < EPSILON);
@ -380,9 +399,9 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
Vec3d slope_top_point = Vec3d(temp(0), temp(1), delta(2)) + source;
GCodeG1Formatter w0;
w0.emit_xyz(slope_top_point);
w0.emit_f(this->config.travel_speed.value * 60.0);
w0.emit_f(travel_speed * 60.0);
//BBS
w0.emit_comment(GCodeWriter::full_gcode_comment, "slope lift Z");
w0.emit_comment(GCodeWriter::full_gcode_comment, comment);
slop_move = w0.string();
}
else if (m_to_lift_type == LiftType::NormalLift) {
@ -395,13 +414,13 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
GCodeG1Formatter w0;
if (this->is_current_position_clear()) {
w0.emit_xyz(target);
w0.emit_f(this->config.travel_speed.value * 60.0);
w0.emit_f(travel_speed * 60.0);
w0.emit_comment(GCodeWriter::full_gcode_comment, comment);
xy_z_move = w0.string();
}
else {
w0.emit_xy(Vec2d(target.x(), target.y()));
w0.emit_f(this->config.travel_speed.value * 60.0);
w0.emit_f(travel_speed * 60.0);
w0.emit_comment(GCodeWriter::full_gcode_comment, comment);
xy_z_move = w0.string() + _travel_to_z(target.z(), comment);
}
@ -475,8 +494,10 @@ std::string GCodeWriter::_travel_to_z(double z, const std::string &comment)
m_pos(2) = z;
double speed = this->config.travel_speed_z.value;
if (speed == 0.)
speed = this->config.travel_speed.value;
if (speed == 0.) {
speed = m_is_first_layer ? this->config.get_abs_value("initial_layer_travel_speed")
: this->config.travel_speed.value;
}
GCodeG1Formatter w;
w.emit_z(z);
@ -491,8 +512,10 @@ std::string GCodeWriter::_spiral_travel_to_z(double z, const Vec2d &ij_offset, c
m_pos(2) = z;
double speed = this->config.travel_speed_z.value;
if (speed == 0.)
speed = this->config.travel_speed.value;
if (speed == 0.) {
speed = m_is_first_layer ? this->config.get_abs_value("initial_layer_travel_speed")
: this->config.travel_speed.value;
}
std::string output = "G17\n";
GCodeG2G3Formatter w(true);
@ -525,6 +548,9 @@ std::string GCodeWriter::extrude_to_xy(const Vec2d &point, double dE, const std:
{
m_pos(0) = point(0);
m_pos(1) = point(1);
if(std::abs(dE) <= std::numeric_limits<double>::epsilon())
force_no_extrusion = true;
if (!force_no_extrusion)
m_extruder->extrude(dE);
@ -605,15 +631,26 @@ std::string GCodeWriter::retract_for_toolchange(bool before_wipe)
std::string GCodeWriter::_retract(double length, double restart_extra, const std::string &comment)
{
/* If firmware retraction is enabled, we use a fake value of 1
since we ignore the actual configured retract_length which
might be 0, in which case the retraction logic gets skipped. */
if (this->config.use_firmware_retraction)
length = 1;
std::string gcode;
if (double dE = m_extruder->retract(length, restart_extra); dE != 0) {
//BBS
GCodeG1Formatter w;
w.emit_e(m_extruder->E());
w.emit_f(m_extruder->retract_speed() * 60.);
//BBS
w.emit_comment(GCodeWriter::full_gcode_comment, comment);
gcode = w.string();
if (this->config.use_firmware_retraction) {
gcode = FLAVOR_IS(gcfMachinekit) ? "G22 ; retract\n" : "G10 ; retract\n";
}
else {
// BBS
GCodeG1Formatter w;
w.emit_e(m_extruder->E());
w.emit_f(m_extruder->retract_speed() * 60.);
// BBS
w.emit_comment(GCodeWriter::full_gcode_comment, comment);
gcode = w.string();
}
}
if (FLAVOR_IS(gcfMakerWare))
@ -630,14 +667,20 @@ std::string GCodeWriter::unretract()
gcode = "M101 ; extruder on\n";
if (double dE = m_extruder->unretract(); dE != 0) {
//BBS
// use G1 instead of G0 because G0 will blend the restart with the previous travel move
GCodeG1Formatter w;
w.emit_e(m_extruder->E());
w.emit_f(m_extruder->deretract_speed() * 60.);
//BBS
w.emit_comment(GCodeWriter::full_gcode_comment, " ; unretract");
gcode += w.string();
if (this->config.use_firmware_retraction) {
gcode += FLAVOR_IS(gcfMachinekit) ? "G23 ; unretract\n" : "G11 ; unretract\n";
gcode += this->reset_e();
}
else {
//BBS
// use G1 instead of G0 because G0 will blend the restart with the previous travel move
GCodeG1Formatter w;
w.emit_e(m_extruder->E());
w.emit_f(m_extruder->deretract_speed() * 60.);
//BBS
w.emit_comment(GCodeWriter::full_gcode_comment, " ; unretract");
gcode += w.string();
}
}
return gcode;
@ -651,8 +694,10 @@ std::string GCodeWriter::lift(LiftType lift_type, bool spiral_vase)
// check whether the above/below conditions are met
double target_lift = 0;
{
//BBS
target_lift = this->config.z_hop.get_at(m_extruder->id());
double above = this->config.retract_lift_above.get_at(m_extruder->id());
double below = this->config.retract_lift_below.get_at(m_extruder->id());
if (m_pos(2) >= above && (below == 0 || m_pos(2) <= below))
target_lift = this->config.z_hop.get_at(m_extruder->id());
}
// BBS
if (m_lifted == 0 && m_to_lift == 0 && target_lift > 0) {
@ -702,9 +747,9 @@ std::string GCodeWriter::set_fan(const GCodeFlavor gcode_flavor, unsigned int sp
gcode << "M126"; break;
case gcfMach3:
case gcfMachinekit:
gcode << "M106 P" << 255.0 * speed / 100.0; break;
gcode << "M106 P" << static_cast<unsigned int>(255.5 * speed / 100.0); break;
default:
gcode << "M106 S" << 255.0 * speed / 100.0; break;
gcode << "M106 S" << static_cast<unsigned int>(255.5 * speed / 100.0); break;
}
if (GCodeWriter::full_gcode_comment)
gcode << " ; enable fan";
@ -748,6 +793,11 @@ void GCodeWriter::add_object_end_labels(std::string& gcode)
if (!m_gcode_label_objects_end.empty()) {
gcode += m_gcode_label_objects_end;
m_gcode_label_objects_end = "";
// Orca: reset E so that e value remain correct after skipping the object
// ref to: https://github.com/SoftFever/OrcaSlicer/pull/205/commits/7f1fe0bd544077626080aa1a9a0576aa735da1a4#r1083470162
if (!this->config.use_relative_e_distances)
gcode += reset_e(true);
}
}

View file

@ -11,12 +11,6 @@
namespace Slic3r {
enum class LiftType {
NormalLift,
LazyLift,
SpiralLift
};
class GCodeWriter {
public:
GCodeConfig config;
@ -30,7 +24,8 @@ public:
/*m_last_bed_temperature(0), */m_last_bed_temperature_reached(true),
m_lifted(0),
m_to_lift(0),
m_to_lift_type(LiftType::NormalLift)
m_to_lift_type(LiftType::NormalLift),
m_current_speed(3600), m_is_first_layer(true)
{}
Extruder* extruder() { return m_extruder; }
const Extruder* extruder() const { return m_extruder; }
@ -51,8 +46,8 @@ public:
std::string set_temperature(unsigned int temperature, bool wait = false, int tool = -1) const;
std::string set_bed_temperature(int temperature, bool wait = false);
std::string set_acceleration(unsigned int acceleration);
std::string set_pressure_advance(double pa) const;
std::string set_jerk_xy(double jerk);
std::string set_pressure_advance(double pa) const;
std::string reset_e(bool force = false);
std::string update_progress(unsigned int num, unsigned int tot, bool allow_100 = false) const;
// return false if this extruder was already selected
@ -64,7 +59,9 @@ public:
// printed with the same extruder.
std::string toolchange_prefix() const;
std::string toolchange(unsigned int extruder_id);
std::string set_speed(double F, const std::string &comment = std::string(), const std::string &cooling_marker = std::string()) const;
std::string set_speed(double F, const std::string &comment = std::string(), const std::string &cooling_marker = std::string());
// SoftFever NOTE: the returned speed is mm/minute
double get_current_speed() const { return m_current_speed;}
std::string travel_to_xy(const Vec2d &point, const std::string &comment = std::string());
std::string travel_to_xyz(const Vec3d &point, const std::string &comment = std::string());
std::string travel_to_z(double z, const std::string &comment = std::string());
@ -93,22 +90,26 @@ public:
static std::string set_additional_fan(unsigned int speed);
//BBS
void set_object_start_str(std::string start_string) { m_gcode_label_objects_start = start_string; }
bool empty_object_start_str() { return m_gcode_label_objects_start.empty(); }
bool is_object_start_str_empty() { return m_gcode_label_objects_start.empty(); }
void set_object_end_str(std::string end_string) { m_gcode_label_objects_end = end_string; }
bool empty_object_end_str() { return m_gcode_label_objects_end.empty(); }
void add_object_start_labels(std::string& gcode);
void add_object_end_labels(std::string& gcode);
bool is_object_end_str_empty() { return m_gcode_label_objects_end.empty(); }
void add_object_start_labels(std::string &gcode);
void add_object_end_labels(std::string &gcode);
void add_object_change_labels(std::string& gcode);
//BBS:
void set_current_position_clear(bool clear) { m_is_current_pos_clear = clear; };
bool is_current_position_clear() const { return m_is_current_pos_clear; };
//BBS:
static const bool full_gcode_comment;
static bool full_gcode_comment;
//Radian threshold of slope for lazy lift and spiral lift;
static const double slope_threshold;
//SoftFever
void set_is_bbl_machine(bool bval) {m_is_bbl_printers = bval;}
const bool is_bbl_printers() const {return m_is_bbl_printers;}
void set_is_first_layer(bool bval) { m_is_first_layer = bval; }
private:
private:
// Extruders are sorted by their ID, so that binary search is possible.
std::vector<Extruder> m_extruders;
bool m_single_extruder_multi_material;
@ -117,8 +118,15 @@ private:
// Limit for setting the acceleration, to respect the machine limits set for the Marlin firmware.
// If set to zero, the limit is not in action.
unsigned int m_max_acceleration;
double m_last_jerk;
double m_max_jerk;
double m_last_jerk;
double m_max_jerk_z;
double m_max_jerk_e;
unsigned int m_travel_acceleration;
unsigned int m_travel_jerk;
//BBS
unsigned int m_last_additional_fan_speed;
int m_last_bed_temperature;
@ -136,10 +144,15 @@ private:
//BBS: x, y offset for gcode generated
double m_x_offset{ 0 };
double m_y_offset{ 0 };
std::string m_gcode_label_objects_start;
std::string m_gcode_label_objects_end;
//SoftFever
bool m_is_bbl_printers = false;
double m_current_speed;
bool m_is_first_layer = true;
std::string _travel_to_z(double z, const std::string &comment);
std::string _spiral_travel_to_z(double z, const Vec2d &ij_offset, const std::string &comment);
std::string _retract(double length, double restart_extra, const std::string &comment);
@ -171,6 +184,13 @@ public:
// static constexpr const int XYZF_EXPORT_DIGITS = 6;
// static constexpr const int E_EXPORT_DIGITS = 9;
#endif
static constexpr const std::array<double, 10> pow_10 { 1., 10., 100., 1000., 10000., 100000., 1000000., 10000000., 100000000., 1000000000. };
static constexpr const std::array<double, 10> pow_10_inv { 1. / 1., 1. / 10., 1. / 100., 1. / 1000., 1. / 10000., 1. / 100000., 1. / 1000000., 1. / 10000000., 1. / 100000000., 1. / 1000000000. };
// Quantize doubles to a resolution of the G-code.
static double quantize(double v, size_t ndigits) { return std::round(v * pow_10[ndigits]) * pow_10_inv[ndigits]; }
static double quantize_xyzf(double v) { return quantize(v, XYZF_EXPORT_DIGITS); }
static double quantize_e(double v) { return quantize(v, E_EXPORT_DIGITS); }
void emit_axis(const char axis, const double v, size_t digits);

View file

@ -174,7 +174,6 @@ void Layer::make_perimeters()
&& config.gap_infill_speed.value == other_config.gap_infill_speed.value
&& config.filter_out_gap_fill.value == other_config.filter_out_gap_fill.value
&& config.detect_overhang_wall == other_config.detect_overhang_wall
&& config.filter_out_gap_fill.value == other_config.filter_out_gap_fill.value
&& config.opt_serialize("inner_wall_line_width") == other_config.opt_serialize("inner_wall_line_width")
&& config.opt_serialize("outer_wall_line_width") == other_config.opt_serialize("outer_wall_line_width")
&& config.detect_thin_wall == other_config.detect_thin_wall

View file

@ -5,7 +5,7 @@
#include "Flow.hpp"
#include "SurfaceCollection.hpp"
#include "ExtrusionEntityCollection.hpp"
#include "BoundingBox.hpp"
namespace Slic3r {
class ExPolygon;

View file

@ -71,9 +71,12 @@ Model& Model::assign_copy(const Model &rhs)
// BBS
this->plates_custom_gcodes = rhs.plates_custom_gcodes;
this->curr_plate_index = rhs.curr_plate_index;
this->calib_pa_pattern.reset();
if (rhs.calib_pa_pattern) {
this->calib_pa_pattern = std::make_unique<CalibPressureAdvancePattern>(CalibPressureAdvancePattern(*rhs.calib_pa_pattern));
this->calib_pa_pattern = std::make_unique<CalibPressureAdvancePattern>(
CalibPressureAdvancePattern(*rhs.calib_pa_pattern)
);
}
// BBS: for design info
@ -104,7 +107,8 @@ Model& Model::assign_copy(Model &&rhs)
// BBS
this->plates_custom_gcodes = std::move(rhs.plates_custom_gcodes);
this->curr_plate_index = rhs.curr_plate_index;
this->calib_pa_pattern = std::move(rhs.calib_pa_pattern);
this->calib_pa_pattern.reset();
this->calib_pa_pattern.swap(rhs.calib_pa_pattern);
//BBS: add auxiliary path logic
// BBS: backup, all in one temp dir
@ -810,7 +814,7 @@ std::string Model::get_backup_path()
std::time_t t = std::time(0);
std::tm* now_time = std::localtime(&t);
std::stringstream buf;
buf << "/bamboo_model/";
buf << "/orcaslicer_model/";
buf << std::put_time(now_time, "%a_%b_%d/%H_%M_%S#");
buf << pid << "#";
buf << this->id().id;
@ -1378,19 +1382,11 @@ const BoundingBoxf3& ModelObject::raw_bounding_box() const
}
// This returns an accurate snug bounding box of the transformed object instance, without the translation applied.
BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_translate) const
{
BoundingBoxf3 bb;
const Transform3d& inst_matrix = this->instances[instance_idx]->get_transformation().get_matrix(dont_translate);
for (ModelVolume *v : this->volumes)
{
if (v->is_model_part())
bb.merge(v->mesh().transformed_bounding_box(inst_matrix * v->get_matrix()));
}
return bb;
BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_translate) const {
return instance_bounding_box(*this->instances[instance_idx], dont_translate);
}
BoundingBoxf3 ModelObject::instance_bounding_box(const ModelInstance& instance, bool dont_translate) const {
BoundingBoxf3 ModelObject::instance_bounding_box(const ModelInstance &instance, bool dont_translate) const {
BoundingBoxf3 bbox;
const auto& inst_mat = instance.get_transformation().get_matrix(dont_translate);
for (auto vol : this->volumes) {
@ -1400,6 +1396,7 @@ BoundingBoxf3 ModelObject::instance_bounding_box(const ModelInstance& instance,
return bbox;
}
//BBS: add convex bounding box
BoundingBoxf3 ModelObject::instance_convex_hull_bounding_box(size_t instance_idx, bool dont_translate) const
{
@ -2461,7 +2458,6 @@ void ModelObject::bake_xy_rotation_into_meshes(size_t instance_idx)
assert(instance_idx < this->instances.size());
const Geometry::Transformation reference_trafo = this->instances[instance_idx]->get_transformation();
if (Geometry::is_rotation_ninety_degrees(reference_trafo.get_rotation()))
// nothing to do, scaling in the world coordinate space is possible in the representation of Geometry::Transformation.
return;
@ -3250,6 +3246,7 @@ double Model::findMaxSpeed(const ModelObject* object) {
double solidInfillSpeedObj = Model::printSpeedMap.solidInfillSpeed;
double topSolidInfillSpeedObj = Model::printSpeedMap.topSolidInfillSpeed;
double supportSpeedObj = Model::printSpeedMap.supportSpeed;
double smallPerimeterSpeedObj = Model::printSpeedMap.smallPerimeterSpeed;
for (std::string objectKey : objectKeys) {
if (objectKey == "inner_wall_speed"){
perimeterSpeedObj = object->config.opt_float(objectKey);
@ -3265,8 +3262,10 @@ double Model::findMaxSpeed(const ModelObject* object) {
supportSpeedObj = object->config.opt_float(objectKey);
if (objectKey == "outer_wall_speed")
externalPerimeterSpeedObj = object->config.opt_float(objectKey);
if (objectKey == "small_perimeter_speed")
smallPerimeterSpeedObj = object->config.opt_float(objectKey);
}
objMaxSpeed = std::max(perimeterSpeedObj, std::max(externalPerimeterSpeedObj, std::max(infillSpeedObj, std::max(solidInfillSpeedObj, std::max(topSolidInfillSpeedObj, std::max(supportSpeedObj, objMaxSpeed))))));
objMaxSpeed = std::max(perimeterSpeedObj, std::max(externalPerimeterSpeedObj, std::max(infillSpeedObj, std::max(solidInfillSpeedObj, std::max(topSolidInfillSpeedObj, std::max(supportSpeedObj, std::max(smallPerimeterSpeedObj, objMaxSpeed)))))));
if (objMaxSpeed <= 0) objMaxSpeed = 250.;
return objMaxSpeed;
}

View file

@ -22,8 +22,6 @@
//BBS: add stl
#include "Format/STL.hpp"
#include "Calib.hpp"
#include <map>
#include <memory>
#include <string>

View file

@ -1,5 +1,6 @@
#include "PerimeterGenerator.hpp"
#include "ClipperUtils.hpp"
#include "ExtrusionEntity.hpp"
#include "ExtrusionEntityCollection.hpp"
#include "ShortestPath.hpp"
#include "VariableWidth.hpp"
@ -275,7 +276,7 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
Polylines remain_polines;
//BBS: don't calculate overhang degree when enable fuzzy skin. It's unmeaning
if (perimeter_generator.config->enable_overhang_speed && perimeter_generator.config->fuzzy_skin == FuzzySkinType::None) {
if (perimeter_generator.config->overhang_speed_classic && perimeter_generator.config->enable_overhang_speed && perimeter_generator.config->fuzzy_skin == FuzzySkinType::None) {
for (auto it = lower_polygons_series->begin();
it != lower_polygons_series->end(); it++)
{
@ -322,31 +323,12 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
// outside the grown lower slices (thus where the distance between
// the loop centerline and original lower slices is >= half nozzle diameter
if (remain_polines.size() != 0) {
if (!((perimeter_generator.object_config->enable_support || perimeter_generator.object_config->enforce_support_layers > 0)
&& perimeter_generator.object_config->support_top_z_distance.value == 0)) {
extrusion_paths_append(
paths,
std::move(remain_polines),
overhang_sampling_number - 1,
int(0),
erOverhangPerimeter,
perimeter_generator.mm3_per_mm_overhang(),
perimeter_generator.overhang_flow.width(),
perimeter_generator.overhang_flow.height());
} else {
extrusion_paths_append(
paths,
std::move(remain_polines),
overhang_sampling_number - 1,
int(0),
role,
extrusion_mm3_per_mm,
extrusion_width,
(float)perimeter_generator.layer_height);
}
extrusion_paths_append(paths, std::move(remain_polines), overhang_sampling_number - 1, int(0),
erOverhangPerimeter, perimeter_generator.mm3_per_mm_overhang(),
perimeter_generator.overhang_flow.width(),
perimeter_generator.overhang_flow.height());
}
// Reapply the nearest point search for starting point.
// We allow polyline reversal because Clipper may have randomly reversed polylines during clipping.
chain_and_reorder_extrusion_paths(paths, &paths.front().first_point());
@ -413,38 +395,22 @@ static ClipperLib_Z::Paths clip_extrusion(const ClipperLib_Z::Path& subject, con
ClipperLib_Z::Clipper clipper;
clipper.ZFillFunction([](const ClipperLib_Z::IntPoint& e1bot, const ClipperLib_Z::IntPoint& e1top, const ClipperLib_Z::IntPoint& e2bot,
const ClipperLib_Z::IntPoint& e2top, ClipperLib_Z::IntPoint& pt) {
// The clipping contour may be simplified by clipping it with a bounding box of "subject" path.
// The clipping function used may produce self intersections outside of the "subject" bounding box. Such self intersections are
// harmless to the result of the clipping operation,
// Both ends of each edge belong to the same source: Either they are from subject or from clipping path.
assert(e1bot.z() >= 0 && e1top.z() >= 0);
assert(e2bot.z() >= 0 && e2top.z() >= 0);
assert((e1bot.z() == 0) == (e1top.z() == 0));
assert((e2bot.z() == 0) == (e2top.z() == 0));
// Start & end points of the clipped polyline (extrusion path with a non-zero width).
ClipperLib_Z::IntPoint start = e1bot;
ClipperLib_Z::IntPoint end = e1top;
if (start.z() <= 0 && end.z() <= 0) {
start = e2bot;
end = e2top;
}
if (start.z() <= 0 && end.z() <= 0) {
// Self intersection on the source contour.
assert(start.z() == 0 && end.z() == 0);
pt.z() = 0;
}
else {
// Interpolate extrusion line width.
assert(start.z() > 0 && end.z() > 0);
assert(start.z() > 0 && end.z() > 0);
double length_sqr = (end - start).cast<double>().squaredNorm();
double dist_sqr = (pt - start).cast<double>().squaredNorm();
double t = std::sqrt(dist_sqr / length_sqr);
// Interpolate extrusion line width.
double length_sqr = (end - start).cast<double>().squaredNorm();
double dist_sqr = (pt - start).cast<double>().squaredNorm();
double t = std::sqrt(dist_sqr / length_sqr);
pt.z() = start.z() + coord_t((end.z() - start.z()) * t);
}
pt.z() = start.z() + coord_t((end.z() - start.z()) * t);
});
clipper.AddPath(subject, ClipperLib_Z::ptSubject, false);
@ -611,9 +577,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p
ExtrusionPaths paths;
// detect overhanging/bridging perimeters
if (perimeter_generator.config->detect_overhang_wall && perimeter_generator.layer_id > perimeter_generator.object_config->raft_layers
&& !((perimeter_generator.object_config->enable_support || perimeter_generator.object_config->enforce_support_layers > 0) &&
perimeter_generator.object_config->support_top_z_distance.value == 0)) {
if (perimeter_generator.config->detect_overhang_wall && perimeter_generator.layer_id > perimeter_generator.object_config->raft_layers) {
ClipperLib_Z::Path extrusion_path;
extrusion_path.reserve(extrusion->size());
BoundingBox extrusion_path_bbox;
@ -645,7 +609,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p
extrusion_paths_append(temp_paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctIntersection), role,
is_external ? perimeter_generator.ext_perimeter_flow : perimeter_generator.perimeter_flow);
if (perimeter_generator.config->enable_overhang_speed && perimeter_generator.config->fuzzy_skin == FuzzySkinType::None) {
if (perimeter_generator.config->overhang_speed_classic && perimeter_generator.config->enable_overhang_speed && perimeter_generator.config->fuzzy_skin == FuzzySkinType::None) {
Flow flow = is_external ? perimeter_generator.ext_perimeter_flow : perimeter_generator.perimeter_flow;
std::map<double, std::vector<Polygons>> clipper_serise;
@ -795,7 +759,100 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p
return extrusion_coll;
}
void PerimeterGenerator::split_top_surfaces(const ExPolygons &orig_polygons, ExPolygons &top_fills,
ExPolygons &non_top_polygons, ExPolygons &fill_clip) const {
// other perimeters
coord_t perimeter_width = this->perimeter_flow.scaled_width();
coord_t perimeter_spacing = this->perimeter_flow.scaled_spacing();
// external perimeters
coord_t ext_perimeter_width = this->ext_perimeter_flow.scaled_width();
coord_t ext_perimeter_spacing = this->ext_perimeter_flow.scaled_spacing();
bool has_gap_fill = this->config->gap_infill_speed.value > 0;
// split the polygons with top/not_top
// get the offset from solid surface anchor
coord_t offset_top_surface =
scale_(1.5 * (config->wall_loops.value == 0
? 0.
: unscaled(double(ext_perimeter_width +
perimeter_spacing * int(int(config->wall_loops.value) - int(1))))));
// if possible, try to not push the extra perimeters inside the sparse infill
if (offset_top_surface >
0.9 * (config->wall_loops.value <= 1 ? 0. : (perimeter_spacing * (config->wall_loops.value - 1))))
offset_top_surface -=
coord_t(0.9 * (config->wall_loops.value <= 1 ? 0. : (perimeter_spacing * (config->wall_loops.value - 1))));
else
offset_top_surface = 0;
// don't takes into account too thin areas
// skip if the exposed area is smaller than "min_width_top_surface"
double min_width_top_surface = std::max(double(ext_perimeter_spacing / 2 + 10), config->min_width_top_surface.get_abs_value(perimeter_width));
Polygons grown_upper_slices = offset(*this->upper_slices, min_width_top_surface);
// get boungding box of last
BoundingBox last_box = get_extents(orig_polygons);
last_box.offset(SCALED_EPSILON);
// get the Polygons upper the polygon this layer
Polygons upper_polygons_series_clipped =
ClipperUtils::clip_clipper_polygons_with_subject_bbox(grown_upper_slices, last_box);
// set the clip to a virtual "second perimeter"
fill_clip = offset_ex(orig_polygons, -double(ext_perimeter_spacing));
// get the real top surface
ExPolygons grown_lower_slices;
ExPolygons bridge_checker;
auto nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->wall_filament - 1);
// Check whether surface be bridge or not
if (this->lower_slices != NULL) {
// BBS: get the Polygons below the polygon this layer
Polygons lower_polygons_series_clipped =
ClipperUtils::clip_clipper_polygons_with_subject_bbox(*this->lower_slices, last_box);
double bridge_offset = std::max(double(ext_perimeter_spacing), (double(perimeter_width)));
// SoftFever: improve bridging
const float bridge_margin =
std::min(float(scale_(BRIDGE_INFILL_MARGIN)), float(scale_(nozzle_diameter * BRIDGE_INFILL_MARGIN / 0.4)));
bridge_checker = offset_ex(diff_ex(orig_polygons, lower_polygons_series_clipped, ApplySafetyOffset::Yes),
1.5 * bridge_offset + bridge_margin + perimeter_spacing / 2);
}
ExPolygons delete_bridge = diff_ex(orig_polygons, bridge_checker, ApplySafetyOffset::Yes);
ExPolygons top_polygons = diff_ex(delete_bridge, upper_polygons_series_clipped, ApplySafetyOffset::Yes);
// get the not-top surface, from the "real top" but enlarged by external_infill_margin (and the
// min_width_top_surface we removed a bit before)
ExPolygons temp_gap = diff_ex(top_polygons, fill_clip);
ExPolygons inner_polygons =
diff_ex(orig_polygons,
offset_ex(top_polygons, offset_top_surface + min_width_top_surface - double(ext_perimeter_spacing / 2)),
ApplySafetyOffset::Yes);
// get the enlarged top surface, by using inner_polygons instead of upper_slices, and clip it for it to be exactly
// the polygons to fill.
top_polygons = diff_ex(fill_clip, inner_polygons, ApplySafetyOffset::Yes);
// increase by half peri the inner space to fill the frontier between last and stored.
top_fills = union_ex(top_fills, top_polygons);
//set the clip to the external wall but go back inside by infill_extrusion_width/2 to be sure the extrusion won't go outside even with a 100% overlap.
double infill_spacing_unscaled = this->config->sparse_infill_line_width.get_abs_value(nozzle_diameter);
if (infill_spacing_unscaled == 0) infill_spacing_unscaled = Flow::auto_extrusion_width(frInfill, nozzle_diameter);
fill_clip = offset_ex(orig_polygons, double(ext_perimeter_spacing / 2) - scale_(infill_spacing_unscaled / 2));
// ExPolygons oldLast = last;
non_top_polygons = intersection_ex(inner_polygons, orig_polygons);
if (has_gap_fill)
non_top_polygons = union_ex(non_top_polygons, temp_gap);
//{
// std::stringstream stri;
// stri << this->layer_id << "_1_"<< i <<"_only_one_peri"<< ".svg";
// SVG svg(stri.str());
// svg.draw(to_polylines(top_fills), "green");
// svg.draw(to_polylines(inner_polygons), "yellow");
// svg.draw(to_polylines(top_polygons), "cyan");
// svg.draw(to_polylines(oldLast), "orange");
// svg.draw(to_polylines(last), "red");
// svg.Close();
//}
}
void PerimeterGenerator::process_classic()
{
@ -803,12 +860,17 @@ void PerimeterGenerator::process_classic()
m_mm3_per_mm = this->perimeter_flow.mm3_per_mm();
coord_t perimeter_width = this->perimeter_flow.scaled_width();
coord_t perimeter_spacing = this->perimeter_flow.scaled_spacing();
// external perimeters
m_ext_mm3_per_mm = this->ext_perimeter_flow.mm3_per_mm();
coord_t ext_perimeter_width = this->ext_perimeter_flow.scaled_width();
coord_t ext_perimeter_spacing = this->ext_perimeter_flow.scaled_spacing();
coord_t ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.spacing() + this->perimeter_flow.spacing()));
coord_t ext_perimeter_spacing2;
if(config->precise_outer_wall)
ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.width() + this->perimeter_flow.width()));
else
ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.spacing() + this->perimeter_flow.spacing()));
// overhang perimeters
m_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm();
@ -851,17 +913,13 @@ void PerimeterGenerator::process_classic()
// BBS: don't simplify too much which influence arc fitting when export gcode if arc_fitting is enabled
double surface_simplify_resolution = (print_config->enable_arc_fitting && this->config->fuzzy_skin == FuzzySkinType::None) ? 0.2 * m_scaled_resolution : m_scaled_resolution;
//BBS: reorder the surface to reduce the travel time
ExPolygons surface_exp;
for (const Surface &surface : this->slices->surfaces)
surface_exp.push_back(surface.expolygon);
std::vector<size_t> surface_order = chain_expolygons(surface_exp);
for (size_t order_idx = 0; order_idx < surface_order.size(); order_idx++) {
const Surface &surface = this->slices->surfaces[surface_order[order_idx]];
for (const Surface &surface : this->slices->surfaces) {
// detect how many perimeters must be generated for this island
int loop_number = this->config->wall_loops + surface.extra_perimeters - 1; // 0-indexed loops
//BBS: set the topmost and bottom most layer to be one wall
if (loop_number > 0 && ((this->object_config->top_one_wall_type != TopOneWallType::None && this->upper_slices == nullptr) || (this->object_config->only_one_wall_first_layer && layer_id == 0)))
if (this->layer_id == 0 && this->config->only_one_wall_first_layer)
loop_number = 0;
//BBS: set the topmost layer to be one wall
if (loop_number > 0 && config->only_one_wall_top && this->upper_slices == nullptr)
loop_number = 0;
ExPolygons last = union_ex(surface.expolygon.simplify_p(surface_simplify_resolution));
@ -1008,68 +1066,8 @@ void PerimeterGenerator::process_classic()
//BBS: refer to superslicer
//store surface for top infill if only_one_wall_top
if (i == 0 && i != loop_number && this->object_config->top_one_wall_type == TopOneWallType::Alltop && this->upper_slices != NULL) {
//split the polygons with top/not_top
//get the offset from solid surface anchor
coord_t offset_top_surface = scale_(1.5 * (config->wall_loops.value == 0 ? 0. : unscaled(double(ext_perimeter_width + perimeter_spacing * int(int(config->wall_loops.value) - int(1))))));
// if possible, try to not push the extra perimeters inside the sparse infill
if (offset_top_surface > 0.9 * (config->wall_loops.value <= 1 ? 0. : (perimeter_spacing * (config->wall_loops.value - 1))))
offset_top_surface -= coord_t(0.9 * (config->wall_loops.value <= 1 ? 0. : (perimeter_spacing * (config->wall_loops.value - 1))));
else
offset_top_surface = 0;
//don't takes into account too thin areas
double min_width_top_surface = std::max(double(ext_perimeter_spacing / 2 + 10), 1.0 * (double(perimeter_width)));
//BBS: get boungding box of last
BoundingBox last_box = get_extents(last);
last_box.offset(SCALED_EPSILON);
// BBS: get the Polygons upper the polygon this layer
Polygons upper_polygons_series_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*this->upper_slices, last_box);
upper_polygons_series_clipped = offset(upper_polygons_series_clipped, min_width_top_surface);
//set the clip to a virtual "second perimeter"
fill_clip = offset_ex(last, -double(ext_perimeter_spacing));
// get the real top surface
ExPolygons grown_lower_slices;
ExPolygons bridge_checker;
// BBS: check whether surface be bridge or not
if (this->lower_slices != NULL) {
// BBS: get the Polygons below the polygon this layer
Polygons lower_polygons_series_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*this->lower_slices, last_box);
double bridge_offset = std::max(double(ext_perimeter_spacing), (double(perimeter_width)));
bridge_checker = offset_ex(diff_ex(last, lower_polygons_series_clipped, ApplySafetyOffset::Yes), 1.5 * bridge_offset);
}
ExPolygons delete_bridge = diff_ex(last, bridge_checker, ApplySafetyOffset::Yes);
ExPolygons top_polygons = diff_ex(delete_bridge, upper_polygons_series_clipped, ApplySafetyOffset::Yes);
//get the not-top surface, from the "real top" but enlarged by external_infill_margin (and the min_width_top_surface we removed a bit before)
ExPolygons temp_gap = diff_ex(top_polygons, fill_clip);
ExPolygons inner_polygons = diff_ex(last,
offset_ex(top_polygons, offset_top_surface + min_width_top_surface - double(ext_perimeter_spacing / 2)),
ApplySafetyOffset::Yes);
// get the enlarged top surface, by using inner_polygons instead of upper_slices, and clip it for it to be exactly the polygons to fill.
top_polygons = diff_ex(fill_clip, inner_polygons, ApplySafetyOffset::Yes);
// increase by half peri the inner space to fill the frontier between last and stored.
top_fills = union_ex(top_fills, top_polygons);
//set the clip to the external wall but go back inside by infill_extrusion_width/2 to be sure the extrusion won't go outside even with a 100% overlap.
double infill_spacing_unscaled = this->config->sparse_infill_line_width.value;
fill_clip = offset_ex(last, double(ext_perimeter_spacing / 2) - scale_(infill_spacing_unscaled / 2));
last = intersection_ex(inner_polygons, last);
if (has_gap_fill)
last = union_ex(last,temp_gap);
//{
// std::stringstream stri;
// stri << this->layer->id() << "_1_"<< i <<"_only_one_peri"<< ".svg";
// SVG svg(stri.str());
// svg.draw(to_polylines(top_fills), "green");
// svg.draw(to_polylines(inner_polygons), "yellow");
// svg.draw(to_polylines(top_polygons), "cyan");
// svg.draw(to_polylines(oldLast), "orange");
// svg.draw(to_polylines(last), "red");
// svg.Close();
//}
if (i == 0 && i!=loop_number && config->only_one_wall_top && this->upper_slices != NULL) {
this->split_top_surfaces(last, top_fills, last, fill_clip);
}
if (i == loop_number && (! has_gap_fill || this->config->sparse_infill_density.value == 0)) {
@ -1135,20 +1133,21 @@ void PerimeterGenerator::process_classic()
}
// at this point, all loops should be in contours[0]
ExtrusionEntityCollection entities = traverse_loops(*this, contours.front(), thin_walls);
// if brim will be printed, reverse the order of perimeters so that
// we continue inwards after having finished the brim
// TODO: add test for perimeter order
bool is_outer_wall_first =
this->print_config->wall_infill_order == WallInfillOrder::OuterInnerInfill ||
this->print_config->wall_infill_order == WallInfillOrder::InfillOuterInner;
bool is_outer_wall_first =
this->config->wall_infill_order == WallInfillOrder::OuterInnerInfill ||
this->config->wall_infill_order == WallInfillOrder::InfillOuterInner;
if (is_outer_wall_first ||
//BBS: always print outer wall first when there indeed has brim.
(this->layer_id == 0 &&
this->object_config->brim_type == BrimType::btOuterOnly &&
this->object_config->brim_width.value > 0))
this->object_config->brim_type == BrimType::btOuterOnly &&
this->object_config->brim_width.value > 0))
entities.reverse();
//BBS. adjust wall generate seq
else if (this->print_config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill)
// SoftFever: sandwich mode
else if (this->config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill)
if (entities.entities.size() > 1){
int last_outer=0;
int outer = 0;
@ -1161,6 +1160,7 @@ void PerimeterGenerator::process_classic()
// append perimeters for this slice as a collection
if (! entities.empty())
this->loops->append(entities);
} // for each loop of an island
// fill gaps
@ -1194,10 +1194,12 @@ void PerimeterGenerator::process_classic()
++ irun;
}
#endif
// OrcaSlicer: filter out tiny gap fills
polylines.erase(std::remove_if(polylines.begin(), polylines.end(), [&](const ThickPolyline &p) {
return p.length()< scale_(this->config->filter_out_gap_fill.value);
}), polylines.end());
// SoftFever: filter out tiny gap fills
polylines.erase(std::remove_if(polylines.begin(), polylines.end(),
[&](const ThickPolyline& p) {
return p.length() < scale_(config->filter_out_gap_fill.value);
}), polylines.end());
if (! polylines.empty()) {
ExtrusionEntityCollection gap_fill;
@ -1211,7 +1213,8 @@ void PerimeterGenerator::process_classic()
//FIXME Vojtech: This grows by a rounded extrusion width, not by line spacing,
// therefore it may cover the area, but no the volume.
last = diff_ex(last, gap_fill.polygons_covered_by_width(10.f));
this->gap_fill->append(std::move(gap_fill.entities));
this->gap_fill->append(std::move(gap_fill.entities));
}
}
@ -1272,39 +1275,6 @@ void PerimeterGenerator::process_classic()
} // for each island
}
//BBS:
void PerimeterGenerator::add_infill_contour_for_arachne( ExPolygons infill_contour,
int loops,
coord_t ext_perimeter_spacing,
coord_t perimeter_spacing,
coord_t min_perimeter_infill_spacing,
coord_t spacing,
bool is_inner_part)
{
if( offset_ex(infill_contour, -float(spacing / 2.)).empty() )
{
infill_contour.clear(); // Infill region is too small, so let's filter it out.
}
// create one more offset to be used as boundary for fill
// we offset by half the perimeter spacing (to get to the actual infill boundary)
// and then we offset back and forth by half the infill spacing to only consider the
// non-collapsing regions
coord_t insert = (loops < 0) ? 0: ext_perimeter_spacing;
if (is_inner_part || loops > 0)
insert = perimeter_spacing;
insert = coord_t(scale_(this->config->infill_wall_overlap.get_abs_value(unscale<double>(insert))));
Polygons inner_pp;
for (ExPolygon &ex : infill_contour)
ex.simplify_p(m_scaled_resolution, &inner_pp);
this->fill_surfaces->append(offset2_ex(union_ex(inner_pp), float(-min_perimeter_infill_spacing / 2.), float(insert + min_perimeter_infill_spacing / 2.)), stInternal);
append(*this->fill_no_overlap, offset2_ex(union_ex(inner_pp), float(-min_perimeter_infill_spacing / 2.), float(+min_perimeter_infill_spacing / 2.)));
}
// Thanks, Cura developers, for implementing an algorithm for generating perimeters with variable width (Arachne) that is based on the paper
// "A framework for adaptive width control of dense contour-parallel toolpaths in fused deposition modeling"
void PerimeterGenerator::process_arachne()
@ -1318,7 +1288,6 @@ void PerimeterGenerator::process_arachne()
coord_t ext_perimeter_width = this->ext_perimeter_flow.scaled_width();
coord_t ext_perimeter_spacing = this->ext_perimeter_flow.scaled_spacing();
coord_t ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.spacing() + this->perimeter_flow.spacing()));
// overhang perimeters
m_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm();
@ -1340,15 +1309,20 @@ void PerimeterGenerator::process_arachne()
// we need to process each island separately because we might have different
// extra perimeters for each one
for (const Surface& surface : this->slices->surfaces) {
coord_t bead_width_0 = ext_perimeter_spacing;
if (config->precise_outer_wall)
bead_width_0 = ext_perimeter_width + this->perimeter_flow.scaled_width() - perimeter_spacing;
// detect how many perimeters must be generated for this island
int loop_number = this->config->wall_loops + surface.extra_perimeters - 1; // 0-indexed loops
if (loop_number > 0 && this->object_config->only_one_wall_first_layer && layer_id == 0 ||
(this->object_config->top_one_wall_type == TopOneWallType::Topmost && this->upper_slices == nullptr))
int loop_number = this->config->wall_loops + surface.extra_perimeters - 1; // 0-indexed loops
if (this->layer_id == 0 && this->config->only_one_wall_first_layer)
loop_number = 0;
ExPolygons last = offset_ex(surface.expolygon.simplify_p(surface_simplify_resolution), -float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.));
Polygons last_p = to_polygons(last);
// BBS: set the topmost layer to be one wall
if (loop_number > 0 && config->only_one_wall_top && this->upper_slices == nullptr)
loop_number = 0;
ExPolygons last = offset_ex(surface.expolygon.simplify_p(surface_simplify_resolution),
config->precise_outer_wall ? -float(ext_perimeter_width / 2. - bead_width_0 / 2.)
: -float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.));
double min_nozzle_diameter = *std::min_element(print_config->nozzle_diameter.values.begin(), print_config->nozzle_diameter.values.end());
Arachne::WallToolPathsParams input_params;
{
@ -1367,76 +1341,67 @@ void PerimeterGenerator::process_arachne()
input_params.wall_transition_angle = this->object_config->wall_transition_angle.value;
input_params.wall_distribution_count = this->object_config->wall_distribution_count.value;
}
coord_t wall_0_inset = 0;
//if (config->precise_outer_wall)
// wall_0_inset = 0.5 * (ext_perimeter_width + this->perimeter_flow.scaled_width() - ext_perimeter_spacing -
// perimeter_spacing);
int remain_loops = -1;
if (this->object_config->top_one_wall_type == TopOneWallType::Alltop) {
if (this->upper_slices != nullptr)
remain_loops = loop_number - 1;
std::vector<Arachne::VariableWidthLines> out_shell;
ExPolygons top_fills;
ExPolygons fill_clip;
if (loop_number > 0 && config->only_one_wall_top && this->upper_slices != nullptr) {
// Check if current layer has surfaces that are not covered by upper layer (i.e., top surfaces)
ExPolygons non_top_polygons;
this->split_top_surfaces(last, top_fills, non_top_polygons, fill_clip);
loop_number = 0;
if (top_fills.empty()) {
// No top surfaces, no special handling needed
} else {
// First we slice the outer shell
Polygons last_p = to_polygons(last);
Arachne::WallToolPaths wallToolPaths(last_p, bead_width_0, perimeter_spacing, coord_t(1),
wall_0_inset, layer_height, input_params);
out_shell = wallToolPaths.getToolPaths();
// Make sure infill not overlap with wall
top_fills = intersection_ex(top_fills, wallToolPaths.getInnerContour());
if (!top_fills.empty()) {
// Then get the inner part that needs more walls
last = intersection_ex(non_top_polygons, wallToolPaths.getInnerContour());
loop_number--;
} else {
// Give up the outer shell because we don't have any meaningful top surface
out_shell.clear();
}
}
}
Arachne::WallToolPaths wallToolPaths(last_p, ext_perimeter_spacing, perimeter_spacing, coord_t(loop_number + 1), 0, layer_height, input_params);
Polygons last_p = to_polygons(last);
Arachne::WallToolPaths wallToolPaths(last_p, bead_width_0, perimeter_spacing, coord_t(loop_number + 1),
wall_0_inset, layer_height, input_params);
std::vector<Arachne::VariableWidthLines> perimeters = wallToolPaths.getToolPaths();
loop_number = int(perimeters.size()) - 1;
//BBS: top one wall for arachne
ExPolygons infill_contour = union_ex(wallToolPaths.getInnerContour());
ExPolygons inner_infill_contour;
if( remain_loops >= 0 )
{
ExPolygons the_layer_surface = infill_contour;
// BBS: get boungding box of last
BoundingBox infill_contour_box = get_extents(infill_contour);
infill_contour_box.offset(SCALED_EPSILON);
// BBS: get the Polygons upper the polygon this layer
Polygons upper_polygons_series_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*this->upper_slices, infill_contour_box);
infill_contour = diff_ex(infill_contour, upper_polygons_series_clipped);
coord_t perimeter_width = this->perimeter_flow.scaled_width();
//BBS: add bridge area
if (this->lower_slices != nullptr) {
BoundingBox infill_contour_box = get_extents(infill_contour);
infill_contour_box.offset(SCALED_EPSILON);
// BBS: get the Polygons below the polygon this layer
Polygons lower_polygons_series_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*this->lower_slices, infill_contour_box);
ExPolygons bridge_area = offset_ex(diff_ex(infill_contour, lower_polygons_series_clipped), std::max(ext_perimeter_spacing, perimeter_width));
infill_contour = diff_ex(infill_contour, bridge_area);
}
//BBS: filter small area and extend top surface a bit to hide the wall line
double min_width_top_surface = std::max(double(ext_perimeter_spacing / 4 + 10), double(perimeter_width / 4));
infill_contour = offset2_ex(infill_contour, -min_width_top_surface, min_width_top_surface + perimeter_width);
//BBS: get the inner surface that not export to top
ExPolygons surface_not_export_to_top = diff_ex(the_layer_surface, infill_contour);
//BBS: get real top surface
infill_contour = intersection_ex(infill_contour, the_layer_surface);
Polygons surface_not_export_to_top_p = to_polygons(surface_not_export_to_top);
Arachne::WallToolPaths innerWallToolPaths(surface_not_export_to_top_p, ext_perimeter_spacing, perimeter_spacing, coord_t(remain_loops + 1), 0, layer_height, input_params);
std::vector<Arachne::VariableWidthLines> perimeters_inner = innerWallToolPaths.getToolPaths();
remain_loops = int(perimeters_inner.size()) - 1;
//BBS: set wall's perporsity
if (!perimeters.empty()) {
for (int perimeter_idx = 0; perimeter_idx < perimeters_inner.size(); perimeter_idx++) {
if (perimeters_inner[perimeter_idx].empty()) continue;
for (Arachne::ExtrusionLine &wall : perimeters_inner[perimeter_idx]) {
// BBS: 0 means outer wall
wall.inset_idx++;
if (!out_shell.empty()) {
// Combine outer shells
size_t inset_offset = 0;
for (auto &p : out_shell) {
for (auto &l : p) {
if (l.inset_idx + 1 > inset_offset) {
inset_offset = l.inset_idx + 1;
}
}
}
perimeters.insert(perimeters.end(), perimeters_inner.begin(), perimeters_inner.end());
for (auto &p : perimeters) {
for (auto &l : p) {
l.inset_idx += inset_offset;
}
}
inner_infill_contour = union_ex(innerWallToolPaths.getInnerContour());
perimeters.insert(perimeters.begin(), out_shell.begin(), out_shell.end());
}
loop_number = int(perimeters.size()) - 1;
#ifdef ARACHNE_DEBUG
{
@ -1461,8 +1426,9 @@ void PerimeterGenerator::process_arachne()
int direction = -1;
bool is_outer_wall_first =
this->print_config->wall_infill_order == WallInfillOrder::OuterInnerInfill ||
this->print_config->wall_infill_order == WallInfillOrder::InfillOuterInner;
this->config->wall_infill_order == WallInfillOrder::OuterInnerInfill ||
this->config->wall_infill_order == WallInfillOrder::InfillOuterInner ||
this->config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill;
if (is_outer_wall_first) {
start_perimeter = 0;
end_perimeter = int(perimeters.size());
@ -1588,32 +1554,102 @@ void PerimeterGenerator::process_arachne()
}
}
}
// BBS. adjust wall generate seq
if (this->print_config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill)
if (ordered_extrusions.size() > 1) {
int last_outer = 0;
int outer = 0;
for (; outer < ordered_extrusions.size(); ++outer)
if (ordered_extrusions[outer].extrusion->inset_idx == 0 && outer - last_outer > 1) {
std::swap(ordered_extrusions[outer], ordered_extrusions[outer - 1]);
last_outer = outer;
}
}
if (this->config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill) {
if (ordered_extrusions.size() > 2) { // 3 walls minimum needed to do inner outer inner ordering
int position = 0; // index to run the re-ordering for multiple external perimeters in a single island.
int arr_i = 0; // index to run through the walls
int outer, first_internal, second_internal; // allocate index values
// run the re-ordering for all wall loops in the same island
while (position < ordered_extrusions.size()) {
outer = first_internal = second_internal = -1; // initialise all index values to -1
// run through the walls to get the index values that need re-ordering until the first one for each
// is found. Start at "position" index to enable the for loop to iterate for multiple external
// perimeters in a single island
for (arr_i = position; arr_i < ordered_extrusions.size(); ++arr_i) {
switch (ordered_extrusions[arr_i].extrusion->inset_idx) {
case 0: // external perimeter
if (outer == -1)
outer = arr_i;
break;
case 1: // first internal wall
if (first_internal == -1 && arr_i > outer)
first_internal = arr_i;
break;
case 2: // second internal wall
if (ordered_extrusions[arr_i].extrusion->inset_idx == 2 && second_internal == -1 &&
arr_i > first_internal)
second_internal = arr_i;
break;
}
if (second_internal != -1)
break; // found all three perimeters to re-order
}
if (outer > -1 && first_internal > -1 && second_internal > -1) { // found perimeters to re-order?
const auto temp = ordered_extrusions[second_internal];
ordered_extrusions[second_internal] = ordered_extrusions[first_internal];
ordered_extrusions[first_internal] = ordered_extrusions[outer];
ordered_extrusions[outer] = temp;
} else
break; // did not find any more candidates to re-order, so stop the while loop early
// go to the next perimeter to continue scanning for external walls in the same island
position = arr_i + 1;
}
}
}
if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(*this, ordered_extrusions); !extrusion_coll.empty())
this->loops->append(extrusion_coll);
ExPolygons infill_contour = union_ex(wallToolPaths.getInnerContour());
const coord_t spacing = (perimeters.size() == 1) ? ext_perimeter_spacing2 : perimeter_spacing;
if (offset_ex(infill_contour, -float(spacing / 2.)).empty())
infill_contour.clear(); // Infill region is too small, so let's filter it out.
// create one more offset to be used as boundary for fill
// we offset by half the perimeter spacing (to get to the actual infill boundary)
// and then we offset back and forth by half the infill spacing to only consider the
// non-collapsing regions
coord_t inset =
(loop_number < 0) ? 0 :
(loop_number == 0) ?
// one loop
ext_perimeter_spacing :
// two or more loops?
perimeter_spacing;
inset = coord_t(scale_(this->config->infill_wall_overlap.get_abs_value(unscale<double>(inset))));
// simplify infill contours according to resolution
Polygons pp;
for (ExPolygon& ex : infill_contour)
ex.simplify_p(m_scaled_resolution, &pp);
ExPolygons not_filled_exp = union_ex(pp);
// collapse too narrow infill areas
const auto min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
ExPolygons infill_exp = offset2_ex(
not_filled_exp,
float(-min_perimeter_infill_spacing / 2.),
float(inset + min_perimeter_infill_spacing / 2.));
// append infill areas to fill_surfaces
add_infill_contour_for_arachne(infill_contour, loop_number, ext_perimeter_spacing, perimeter_spacing, min_perimeter_infill_spacing, spacing, false);
//BBS: add infill_contour of top one wall part
if( !inner_infill_contour.empty() )
add_infill_contour_for_arachne(inner_infill_contour, remain_loops, ext_perimeter_spacing, perimeter_spacing, min_perimeter_infill_spacing, spacing, true);
if (!top_fills.empty()) {
infill_exp = union_ex(infill_exp, offset_ex(top_fills, double(inset)));
}
this->fill_surfaces->append(infill_exp, stInternal);
// BBS: get the no-overlap infill expolygons
{
ExPolygons polyWithoutOverlap;
polyWithoutOverlap = offset2_ex(
not_filled_exp,
float(-min_perimeter_infill_spacing / 2.),
float(+min_perimeter_infill_spacing / 2.));
if (!top_fills.empty())
polyWithoutOverlap = union_ex(polyWithoutOverlap, top_fills);
this->fill_no_overlap->insert(this->fill_no_overlap->end(), polyWithoutOverlap.begin(), polyWithoutOverlap.end());
}
}
}
@ -1644,6 +1680,7 @@ std::map<int, Polygons> PerimeterGenerator::generate_lower_polygons_series(float
// BBS: increase start_offset a little to avoid to calculate 90 degree as overhang
offset_series[0] = start_offset + 0.5 * (end_offset - start_offset) / (overhang_sampling_number - 1);
offset_series[overhang_sampling_number - 2] = end_offset;
offset_series.back() = 0.1 * nozzle_diameter;
std::map<int, Polygons> lower_polygons_series;
if (this->lower_slices == NULL) {

View file

@ -69,8 +69,6 @@ public:
void process_classic();
void process_arachne();
void add_infill_contour_for_arachne( ExPolygons infill_contour, int loops, coord_t ext_perimeter_spacing, coord_t perimeter_spacing, coord_t min_perimeter_infill_spacing, coord_t spacing, bool is_inner_part );
double ext_mm3_per_mm() const { return m_ext_mm3_per_mm; }
double mm3_per_mm() const { return m_mm3_per_mm; }
double mm3_per_mm_overhang() const { return m_mm3_per_mm_overhang; }

View file

@ -1,5 +1,6 @@
#include <cassert>
#include "Config.hpp"
#include "Exception.hpp"
#include "Preset.hpp"
#include "PresetBundle.hpp"
@ -677,25 +678,6 @@ std::string Preset::get_current_printer_type(PresetBundle *preset_bundle)
return "";
}
bool Preset::has_lidar(PresetBundle *preset_bundle)
{
bool has_lidar = false;
if (preset_bundle) {
auto config = &preset_bundle->printers.get_edited_preset().config;
std::string vendor_name;
for (auto vendor_profile : preset_bundle->vendors) {
for (auto vendor_model : vendor_profile.second.models)
if (vendor_model.name == config->opt_string("printer_model")) {
vendor_name = vendor_profile.first;
break;
}
}
if (!vendor_name.empty())
has_lidar = vendor_name.compare("BBL") == 0 ? true : false;
}
return has_lidar;
}
bool Preset::is_custom_defined()
{
if (custom_defined == "1")
@ -703,9 +685,9 @@ bool Preset::is_custom_defined()
return false;
}
bool Preset::is_bbl_vendor_preset(PresetBundle *preset_bundle)
bool Preset::has_lidar(PresetBundle *preset_bundle)
{
bool is_bbl_vendor_preset = true;
bool has_lidar = false;
if (preset_bundle) {
auto config = &preset_bundle->printers.get_edited_preset().config;
std::string vendor_name;
@ -718,9 +700,9 @@ bool Preset::is_bbl_vendor_preset(PresetBundle *preset_bundle)
}
}
if (!vendor_name.empty())
is_bbl_vendor_preset = vendor_name.compare("BBL") == 0 ? true : false;
has_lidar = vendor_name.compare("BBL") == 0 ? true : false;
}
return is_bbl_vendor_preset;
return has_lidar;
}
BedType Preset::get_default_bed_type(PresetBundle* preset_bundle)
@ -757,10 +739,10 @@ static std::vector<std::string> s_Preset_print_options {
"layer_height", "initial_layer_print_height", "wall_loops", "slice_closing_radius", "spiral_mode", "slicing_mode",
"top_shell_layers", "top_shell_thickness", "bottom_shell_layers", "bottom_shell_thickness",
"ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall",
"seam_position", "wall_infill_order", "sparse_infill_density", "sparse_infill_pattern", "sparse_infill_anchor", "sparse_infill_anchor_max",
"top_surface_pattern", "bottom_surface_pattern", "internal_solid_infill_pattern", "infill_direction", "bridge_angle",
"minimum_sparse_infill_area", "reduce_infill_retraction", "ironing_pattern", "ironing_type",
"ironing_flow", "ironing_speed", "ironing_spacing",
"seam_position", "staggered_inner_seams", "wall_infill_order", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern",
"infill_direction",
"minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern",
"ironing_type", "ironing_pattern", "ironing_flow", "ironing_speed", "ironing_spacing",
"max_travel_detour_distance",
"fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_distance",
#ifdef HAS_PRESSURE_EQUALIZER
@ -768,19 +750,15 @@ static std::vector<std::string> s_Preset_print_options {
#endif /* HAS_PRESSURE_EQUALIZER */
"inner_wall_speed", "outer_wall_speed", "sparse_infill_speed", "internal_solid_infill_speed",
"top_surface_speed", "support_speed", "support_object_xy_distance", "support_interface_speed",
"bridge_speed", "gap_infill_speed", "travel_speed", "travel_speed_z", "initial_layer_speed", "outer_wall_acceleration",
"initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "inner_wall_acceleration", "sparse_infill_acceleration",
"accel_to_decel_enable", "accel_to_decel_factor", "skirt_loops", "skirt_distance",
"skirt_height", "draft_shield",
"brim_width", "brim_object_gap", "brim_type", "enable_support", "support_type", "support_threshold_angle", "enforce_support_layers",
"bridge_speed", "internal_bridge_speed", "gap_infill_speed", "travel_speed", "travel_speed_z", "initial_layer_speed",
"outer_wall_acceleration", "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "skirt_loops", "skirt_speed", "skirt_distance", "skirt_height", "draft_shield",
"brim_width", "brim_object_gap", "brim_type", "brim_ears_max_angle", "brim_ears_detection_length", "enable_support", "support_type", "support_threshold_angle", "enforce_support_layers",
"raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion",
"support_base_pattern", "support_base_pattern_spacing", "support_expansion", "support_style",
// BBS
"independent_support_layer_height",
"support_angle", "support_interface_top_layers", "support_interface_bottom_layers",
"support_interface_pattern", "support_interface_spacing", "support_interface_loop_pattern",
"support_top_z_distance", "support_on_build_plate_only","support_critical_regions_only", "support_remove_small_overhang",
"bridge_no_support", "thick_bridges", "max_bridge_length", "print_sequence",
"support_top_z_distance", "support_on_build_plate_only","support_critical_regions_only", "bridge_no_support", "thick_bridges", "max_bridge_length", "print_sequence", "support_remove_small_overhang",
"filename_format", "wall_filament", "support_bottom_z_distance",
"sparse_infill_filament", "solid_infill_filament", "support_filament", "support_interface_filament",
"ooze_prevention", "standby_temperature_delta", "interface_shells", "line_width", "initial_layer_line_width",
@ -790,23 +768,25 @@ static std::vector<std::string> s_Preset_print_options {
"prime_tower_width", "prime_tower_brim_width", "prime_volume",
"wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits",
"flush_into_infill", "flush_into_objects", "flush_into_support",
// BBS
"tree_support_branch_angle", "tree_support_wall_count", "tree_support_branch_distance",
"tree_support_branch_diameter","tree_support_brim_width",
"tree_support_branch_diameter",
"detect_narrow_internal_solid_infill",
"gcode_add_line_number", "enable_arc_fitting", "infill_combination", /*"adaptive_layer_height",*/
"support_bottom_interface_spacing", "enable_overhang_speed", "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed",
"initial_layer_infill_speed", "top_one_wall_type", "only_one_wall_first_layer",
"initial_layer_infill_speed", "only_one_wall_top",
"timelapse_type", "internal_bridge_support_thickness",
"wall_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle",
"wall_distribution_count", "min_feature_size", "min_bead_width", "post_process",
"seam_gap", "wipe_speed", "top_solid_infill_flow_ratio", "initial_layer_flow_ratio",
"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk", "travel_jerk",
"filter_out_gap_fill",
// calib
"print_flow_ratio",
//Orca
"exclude_object"
"small_perimeter_speed", "small_perimeter_threshold","bridge_angle", "filter_out_gap_fill", "travel_acceleration","inner_wall_acceleration", "min_width_top_surface",
"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk","travel_jerk",
"top_solid_infill_flow_ratio","bottom_solid_infill_flow_ratio","only_one_wall_first_layer", "print_flow_ratio", "seam_gap",
"role_based_wipe_speed", "wipe_speed", "accel_to_decel_enable", "accel_to_decel_factor", "wipe_on_loops",
"bridge_density", "precise_outer_wall", "overhang_speed_classic", "bridge_acceleration",
"sparse_infill_acceleration", "internal_solid_infill_acceleration", "tree_support_adaptive_layer_height", "tree_support_auto_brim",
"tree_support_brim_width", "gcode_comments", "gcode_label_objects",
"initial_layer_travel_speed", "exclude_object", "slow_down_layers", "infill_anchor", "infill_anchor_max",
"make_overhang_printable", "make_overhang_printable_angle", "make_overhang_printable_hole_size"
};
static std::vector<std::string> s_Preset_filament_options {
@ -822,15 +802,15 @@ static std::vector<std::string> s_Preset_filament_options {
"fan_max_speed", "enable_overhang_bridge_fan", "overhang_fan_speed", "overhang_fan_threshold", "close_fan_the_first_x_layers", "full_fan_speed_layer", "fan_cooling_layer_time", "slow_down_layer_time", "slow_down_min_speed",
"filament_start_gcode", "filament_end_gcode",
// Retract overrides
"filament_retraction_length", "filament_z_hop", "filament_z_hop_types", "filament_retraction_speed", "filament_deretraction_speed", "filament_retract_restart_extra", "filament_retraction_minimum_travel",
"filament_retraction_length", "filament_z_hop", "filament_z_hop_types", "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_lift_enforce", "filament_retraction_speed", "filament_deretraction_speed", "filament_retract_restart_extra", "filament_retraction_minimum_travel",
"filament_retract_when_changing_layer", "filament_wipe", "filament_retract_before_wipe",
// Profile compatibility
"filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits",
//BBS
"filament_wipe_distance", "additional_cooling_fan_speed",
"bed_temperature_difference", "nozzle_temperature_range_low", "nozzle_temperature_range_high",
//OrcaSlicer
"enable_pressure_advance", "pressure_advance", "chamber_temperatures"
//SoftFever
"enable_pressure_advance", "pressure_advance","chamber_temperature", "filament_shrink", "support_material_interface_fan_speed" /*,"filament_seam_gap"*/
};
static std::vector<std::string> s_Preset_machine_limits_options {
@ -844,20 +824,20 @@ static std::vector<std::string> s_Preset_machine_limits_options {
static std::vector<std::string> s_Preset_printer_options {
"printer_technology",
"printable_area", "bed_exclude_area","bed_custom_texture", "bed_custom_model", "gcode_flavor",
"fan_kickstart", "fan_speedup_time", "fan_speedup_overhangs",
"single_extruder_multi_material", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "layer_change_gcode", "change_filament_gcode",
"printer_model", "printer_variant", "printable_height", "extruder_clearance_radius", "extruder_clearance_max_radius","extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
"printer_model", "printer_variant", "printable_height", "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
"default_print_profile", "inherits",
"silent_mode",
// BBS
"scan_first_layer", "machine_load_filament_time", "machine_unload_filament_time", "machine_pause_gcode", "template_custom_gcode",
"nozzle_type","auxiliary_fan", "nozzle_volume","upward_compatible_machine", "z_hop_types",
//OrcaSlicer
"nozzle_type", "nozzle_hrc","auxiliary_fan", "nozzle_volume","upward_compatible_machine", "z_hop_types", "retract_lift_enforce",
//SoftFever
"host_type", "print_host", "printhost_apikey",
"print_host_webui",
"printhost_cafile","printhost_port","printhost_authorization_type",
"printhost_user", "printhost_password", "printhost_ssl_ignore_revoke",
"use_relative_e_distances", "extruder_type"
};
"printhost_user", "printhost_password", "printhost_ssl_ignore_revoke", "thumbnails",
"use_firmware_retraction", "use_relative_e_distances"};
static std::vector<std::string> s_Preset_sla_print_options {
"layer_height",
@ -1745,12 +1725,14 @@ std::pair<Preset*, bool> PresetCollection::load_external_preset(
{
// Load the preset over a default preset, so that the missing fields are filled in from the default preset.
DynamicPrintConfig cfg(this->default_preset_for(combined_config).config);
// OrcaSlicer: ignore print connection info from project
cfg.erase("print_host");
cfg.erase("print_host_webui");
cfg.erase("printhost_apikey");
cfg.erase("printhost_cafile");
const auto &keys = cfg.keys();
// SoftFever: ignore print connection info from project
auto keys = cfg.keys();
keys.erase(std::remove_if(keys.begin(), keys.end(),
[](std::string &val) {
return val == "print_host" || val == "print_host_webui" || val == "printhost_apikey" ||
val == "printhost_cafile";
}),
keys.end());
cfg.apply_only(combined_config, keys, true);
std::string &inherits = Preset::inherits(cfg);
@ -2363,7 +2345,7 @@ inline t_config_option_keys deep_diff(const ConfigBase &config_this, const Confi
if (this_opt != nullptr && other_opt != nullptr && *this_opt != *other_opt)
{
//BBS: add bed_exclude_area
if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "compatible_prints" || opt_key == "compatible_printers") {
if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "thumbnails") {
// Scalar variable, or a vector variable, which is independent from number of extruders,
// thus the vector is presented to the user as a single input.
diff.emplace_back(opt_key);
@ -2685,6 +2667,7 @@ static std::vector<std::string> s_PhysicalPrinter_opts {
"printer_technology",
"host_type",
"print_host",
"print_host_webui",
"printhost_apikey",
"printhost_cafile",
"printhost_port",
@ -2856,6 +2839,8 @@ void PhysicalPrinterCollection::load_printers(
// see https://github.com/prusa3d/PrusaSlicer/issues/732
boost::filesystem::path dir = boost::filesystem::absolute(boost::filesystem::path(dir_path) / subdir).make_preferred();
m_dir_path = dir.string();
if(!boost::filesystem::exists(dir))
return;
std::string errors_cummulative;
// Store the loaded printers into a new vector, otherwise the binary search for already existing presets would be broken.
std::deque<PhysicalPrinter> printers_loaded;
@ -3235,6 +3220,9 @@ namespace PresetUtils {
if (!boost::filesystem::exists(boost::filesystem::path(out)))
out = Slic3r::resources_dir() + "/profiles/" + preset.vendor->id + "/" + pm->hotend_model;
}
if (out.empty() ||!boost::filesystem::exists(boost::filesystem::path(out)))
out = Slic3r::resources_dir() + "/profiles/hotend.stl";
return out;
}
} // namespace PresetUtils

View file

@ -300,11 +300,9 @@ public:
std::string get_filament_type(std::string &display_filament_type);
std::string get_printer_type(PresetBundle *preset_bundle); // get edited preset type
std::string get_current_printer_type(PresetBundle *preset_bundle); // get current preset type
bool has_lidar(PresetBundle *preset_bundle);
bool is_custom_defined();
bool is_bbl_vendor_preset(PresetBundle *preset_bundle);
bool has_lidar(PresetBundle *preset_bundle);
BedType get_default_bed_type(PresetBundle *preset_bundle);
bool has_cali_lines(PresetBundle* preset_bundle);

View file

@ -42,10 +42,10 @@ static std::vector<std::string> s_project_options {
};
//BBS: add BBL as default
const char *PresetBundle::BBL_BUNDLE = "BBL";
const char *PresetBundle::BBL_DEFAULT_PRINTER_MODEL = "Bambu Lab X1 Carbon";
const char *PresetBundle::BBL_BUNDLE = "Custom";
const char *PresetBundle::BBL_DEFAULT_PRINTER_MODEL = "MyKlipper 0.4 nozzle";
const char *PresetBundle::BBL_DEFAULT_PRINTER_VARIANT = "0.4";
const char *PresetBundle::BBL_DEFAULT_FILAMENT = "Generic PLA";
const char *PresetBundle::BBL_DEFAULT_FILAMENT = "My Generic PLA";
PresetBundle::PresetBundle()
: prints(Preset::TYPE_PRINT, Preset::print_options(), static_cast<const PrintRegionConfig &>(FullPrintConfig::defaults()))
@ -88,7 +88,7 @@ PresetBundle::PresetBundle()
for (size_t i = 0; i < 1; ++i) {
// The following ugly switch is to avoid printers.preset(0) to return the edited instance, as the 0th default is the current one.
Preset &preset = this->printers.default_preset(i);
for (const char *key : {"printer_settings_id", "printer_model", "printer_variant"}) preset.config.optptr(key, true);
for (const char *key : {"printer_settings_id", "printer_model", "printer_variant", "thumbnails"}) preset.config.optptr(key, true);
//if (i == 0) {
preset.config.optptr("default_print_profile", true);
preset.config.option<ConfigOptionStrings>("default_filament_profile", true);
@ -512,6 +512,9 @@ std::string PresetBundle::get_hotend_model_for_printer_model(std::string model_n
out = Slic3r::resources_dir() + "/profiles/" + vendor_name + "/" + hotend_stl;
}
if (out.empty() ||!boost::filesystem::exists(boost::filesystem::path(out)))
out = Slic3r::resources_dir() + "/profiles/hotend.stl";
return out;
}
@ -1264,6 +1267,72 @@ void PresetBundle::load_installed_sla_materials(AppConfig &config)
preset.set_visible_from_appconfig(config);
}
void PresetBundle::update_selections(AppConfig &config)
{
std::string initial_printer_profile_name = printers.get_selected_preset_name();
// Orca: load from orca_presets
std::string initial_print_profile_name = config.get_printer_setting(initial_printer_profile_name, PRESET_PRINT_NAME);
std::string initial_filament_profile_name = config.get_printer_setting(initial_printer_profile_name, PRESET_FILAMENT_NAME);
// Selects the profiles, which were selected at the last application close.
prints.select_preset_by_name_strict(initial_print_profile_name);
filaments.select_preset_by_name_strict(initial_filament_profile_name);
// Load the names of the other filament profiles selected for a multi-material printer.
// Load it even if the current printer technology is SLA.
// The possibly excessive filament names will be later removed with this->update_multi_material_filament_presets()
// once the FFF technology gets selected.
this->filament_presets = { filaments.get_selected_preset_name() };
for (unsigned int i = 1; i < 1000; ++ i) {
char name[64];
sprintf(name, "filament_%02u", i);
auto f_name = config.get_printer_setting(initial_printer_profile_name, name);
if (f_name.empty())
break;
this->filament_presets.emplace_back(remove_ini_suffix(f_name));
}
std::vector<std::string> filament_colors;
auto f_colors = config.get_printer_setting(initial_printer_profile_name, "filament_colors");
if (!f_colors.empty()) {
boost::algorithm::split(filament_colors, f_colors, boost::algorithm::is_any_of(","));
}
filament_colors.resize(filament_presets.size(), "#FF8040");
project_config.option<ConfigOptionStrings>("filament_colour")->values = filament_colors;
std::vector<std::string> matrix;
if (config.has_printer_setting(initial_printer_profile_name, "flush_volumes_matrix")) {
boost::algorithm::split(matrix, config.get_printer_setting(initial_printer_profile_name, "flush_volumes_matrix"), boost::algorithm::is_any_of("|"));
auto flush_volumes_matrix = matrix | boost::adaptors::transformed(boost::lexical_cast<double, std::string>);
project_config.option<ConfigOptionFloats>("flush_volumes_matrix")->values = std::vector<double>(flush_volumes_matrix.begin(), flush_volumes_matrix.end());
}
if (config.has_printer_setting(initial_printer_profile_name, "flush_volumes_vector")) {
boost::algorithm::split(matrix, config.get_printer_setting(initial_printer_profile_name, "flush_volumes_vector"), boost::algorithm::is_any_of("|"));
auto flush_volumes_vector = matrix | boost::adaptors::transformed(boost::lexical_cast<double, std::string>);
project_config.option<ConfigOptionFloats>("flush_volumes_vector")->values = std::vector<double>(flush_volumes_vector.begin(), flush_volumes_vector.end());
}
if (config.has("app", "flush_multiplier")) {
std::string str_flush_multiplier = config.get("app", "flush_multiplier");
if (!str_flush_multiplier.empty())
project_config.option<ConfigOptionFloat>("flush_multiplier")->set(new ConfigOptionFloat(std::stof(str_flush_multiplier)));
}
// Update visibility of presets based on their compatibility with the active printer.
// Always try to select a compatible print and filament preset to the current printer preset,
// as the application may have been closed with an active "external" preset, which does not
// exist.
this->update_compatible(PresetSelectCompatibleType::Always);
this->update_multi_material_filament_presets();
std::string first_visible_filament_name;
for (auto & fp : filament_presets) {
if (auto it = filaments.find_preset_internal(fp); it == filaments.end() || !it->is_visible || !it->is_compatible) {
if (first_visible_filament_name.empty())
first_visible_filament_name = filaments.first_compatible().name;
fp = first_visible_filament_name;
}
}
}
// Load selections (current print, current filaments, current printer) from config.ini
// This is done on application start up or after updates are applied.
void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& preferred_selection/* = PresetPreferences()*/)
@ -1277,10 +1346,8 @@ void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& p
this->load_installed_sla_materials(config);
// Parse the initial print / filament / printer profile names.
std::string initial_print_profile_name = remove_ini_suffix(config.get("presets", PRESET_PRINT_NAME));
std::string initial_sla_print_profile_name = remove_ini_suffix(config.get("presets", PRESET_SLA_PRINT_NAME));
std::string initial_filament_profile_name = remove_ini_suffix(config.get("presets", PRESET_FILAMENT_NAME));
std::string initial_sla_material_profile_name = remove_ini_suffix(config.get("presets", PRESET_SLA_MATERIALS_NAME));
// std::string initial_sla_print_profile_name = remove_ini_suffix(config.get("presets", PRESET_SLA_PRINT_NAME));
// std::string initial_sla_material_profile_name = remove_ini_suffix(config.get("presets", PRESET_SLA_MATERIALS_NAME));
std::string initial_printer_profile_name = remove_ini_suffix(config.get("presets", PRESET_PRINTER_NAME));
// Activate print / filament / printer profiles from either the config,
@ -1294,6 +1361,11 @@ void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& p
const Preset *preferred_printer = printers.find_system_preset_by_model_and_variant(preferred_selection.printer_model_id, preferred_selection.printer_variant);
printers.select_preset_by_name(preferred_printer ? preferred_printer->name : initial_printer_profile_name, true);
// Orca: load from orca_presets
// const auto os_presets = config.get_machine_settings(initial_printer_profile_name);
std::string initial_print_profile_name = config.get_printer_setting(initial_printer_profile_name, PRESET_PRINT_NAME);
std::string initial_filament_profile_name = config.get_printer_setting(initial_printer_profile_name, PRESET_FILAMENT_NAME);
//BBS: set default print/filament profiles to BBL's default setting
if (preferred_printer)
{
@ -1309,8 +1381,8 @@ void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& p
// Selects the profile, leaves it to -1 if the initial profile name is empty or if it was not found.
prints.select_preset_by_name_strict(initial_print_profile_name);
filaments.select_preset_by_name_strict(initial_filament_profile_name);
sla_prints.select_preset_by_name_strict(initial_sla_print_profile_name);
sla_materials.select_preset_by_name_strict(initial_sla_material_profile_name);
// sla_prints.select_preset_by_name_strict(initial_sla_print_profile_name);
// sla_materials.select_preset_by_name_strict(initial_sla_material_profile_name);
// Load the names of the other filament profiles selected for a multi-material printer.
// Load it even if the current printer technology is SLA.
@ -1320,24 +1392,26 @@ void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& p
for (unsigned int i = 1; i < 1000; ++ i) {
char name[64];
sprintf(name, "filament_%02u", i);
if (! config.has("presets", name))
auto f_name = config.get_printer_setting(initial_printer_profile_name, name);
if (f_name.empty())
break;
this->filament_presets.emplace_back(remove_ini_suffix(config.get("presets", name)));
this->filament_presets.emplace_back(remove_ini_suffix(f_name));
}
std::vector<std::string> filament_colors;
if (config.has("presets", "filament_colors")) {
boost::algorithm::split(filament_colors, config.get("presets", "filament_colors"), boost::algorithm::is_any_of(","));
auto f_colors = config.get_printer_setting(initial_printer_profile_name, "filament_colors");
if (!f_colors.empty()) {
boost::algorithm::split(filament_colors, f_colors, boost::algorithm::is_any_of(","));
}
filament_colors.resize(filament_presets.size(), "#00AE42");
filament_colors.resize(filament_presets.size(), "#FF8040");
project_config.option<ConfigOptionStrings>("filament_colour")->values = filament_colors;
std::vector<std::string> matrix;
if (config.has("presets", "flush_volumes_matrix")) {
boost::algorithm::split(matrix, config.get("presets", "flush_volumes_matrix"), boost::algorithm::is_any_of("|"));
if (config.has_printer_setting(initial_printer_profile_name, "flush_volumes_matrix")) {
boost::algorithm::split(matrix, config.get_printer_setting(initial_printer_profile_name, "flush_volumes_matrix"), boost::algorithm::is_any_of("|"));
auto flush_volumes_matrix = matrix | boost::adaptors::transformed(boost::lexical_cast<double, std::string>);
project_config.option<ConfigOptionFloats>("flush_volumes_matrix")->values = std::vector<double>(flush_volumes_matrix.begin(), flush_volumes_matrix.end());
}
if (config.has("presets", "flush_volumes_vector")) {
boost::algorithm::split(matrix, config.get("presets", "flush_volumes_vector"), boost::algorithm::is_any_of("|"));
if (config.has_printer_setting(initial_printer_profile_name, "flush_volumes_vector")) {
boost::algorithm::split(matrix, config.get_printer_setting(initial_printer_profile_name, "flush_volumes_vector"), boost::algorithm::is_any_of("|"));
auto flush_volumes_vector = matrix | boost::adaptors::transformed(boost::lexical_cast<double, std::string>);
project_config.option<ConfigOptionFloats>("flush_volumes_vector")->values = std::vector<double>(flush_volumes_vector.begin(), flush_volumes_vector.end());
}
@ -1399,27 +1473,32 @@ void PresetBundle::export_selections(AppConfig &config)
assert(this->printers.get_edited_preset().printer_technology() != ptFFF || filament_presets.size() >= 1);
//assert(this->printers.get_edited_preset().printer_technology() != ptFFF || filament_presets.size() > 1 || filaments.get_selected_preset_name() == filament_presets.front());
config.clear_section("presets");
config.set("presets", PRESET_PRINT_NAME, prints.get_selected_preset_name());
config.set("presets", PRESET_FILAMENT_NAME, filament_presets.front());
auto printer_name = printers.get_selected_preset_name();
config.set("presets", PRESET_PRINTER_NAME, printer_name);
config.clear_printer_settings(printer_name);
config.set_printer_setting(printer_name, PRESET_PRINTER_NAME, printer_name);
config.set_printer_setting(printer_name, PRESET_PRINT_NAME, prints.get_selected_preset_name());
config.set_printer_setting(printer_name, PRESET_FILAMENT_NAME, filament_presets.front());
config.set_printer_setting(printer_name, "curr_bed_type", config.get("curr_bed_type"));
for (unsigned i = 1; i < filament_presets.size(); ++i) {
char name[64];
assert(!filament_presets[i].empty());
sprintf(name, "filament_%02u", i);
config.set("presets", name, filament_presets[i]);
config.set_printer_setting(printer_name, name, filament_presets[i]);
}
CNumericLocalesSetter locales_setter;
std::string filament_colors = boost::algorithm::join(project_config.option<ConfigOptionStrings>("filament_colour")->values, ",");
config.set("presets", "filament_colors", filament_colors);
config.set_printer_setting(printer_name, "filament_colors", filament_colors);
std::string flush_volumes_matrix = boost::algorithm::join(project_config.option<ConfigOptionFloats>("flush_volumes_matrix")->values |
boost::adaptors::transformed(static_cast<std::string (*)(double)>(std::to_string)),
"|");
config.set("presets", "flush_volumes_matrix", flush_volumes_matrix);
config.set_printer_setting(printer_name, "flush_volumes_matrix", flush_volumes_matrix);
std::string flush_volumes_vector = boost::algorithm::join(project_config.option<ConfigOptionFloats>("flush_volumes_vector")->values |
boost::adaptors::transformed(static_cast<std::string (*)(double)>(std::to_string)),
"|");
config.set("presets", "flush_volumes_vector", flush_volumes_vector);
config.set_printer_setting(printer_name, "flush_volumes_vector", flush_volumes_vector);
config.set("presets", PRESET_PRINTER_NAME, printers.get_selected_preset_name());
auto flush_multi_opt = project_config.option<ConfigOptionFloat>("flush_multiplier");
config.set("flush_multiplier", std::to_string(flush_multi_opt ? flush_multi_opt->getFloat() : 1.0f));
@ -1563,11 +1642,11 @@ DynamicPrintConfig PresetBundle::full_config() const
DynamicPrintConfig PresetBundle::full_config_secure() const
{
DynamicPrintConfig config = this->full_config();
//BBS example: config.erase("print_host");
//FIXME legacy, the keys should not be there after conversion to a Physical Printer profile.
config.erase("print_host");
config.erase("print_host_webui");
config.erase("printhost_apikey");
config.erase("printhost_cafile");
return config;
config.erase("printhost_cafile"); return config;
}
const std::set<std::string> ignore_settings_list ={
@ -3571,9 +3650,9 @@ std::vector<std::string> PresetBundle::export_current_configs(const std::string
if (overwrite == 0) overwrite = 1;
if (boost::filesystem::exists(file) && overwrite < 2) {
overwrite = override_confirm(preset->name);
if (overwrite == 0 || overwrite == 2)
continue;
}
if (overwrite == 0 || overwrite == 2)
continue;
preset->config.save_to_json(file, preset->name, "", preset->version.to_string());
result.push_back(file);
}

View file

@ -86,6 +86,8 @@ public:
//BBS: check whether this is the only edited filament
bool is_the_only_edited_filament(unsigned int filament_index);
// Orca: update selected filament and print
void update_selections(AppConfig &config);
void set_calibrate_printer(std::string name);
PresetCollection prints;

View file

@ -23,6 +23,7 @@
#include <boost/filesystem/path.hpp>
#include <boost/format.hpp>
#include <boost/log/trivial.hpp>
#include <boost/regex.hpp>
//BBS: add json support
#include "nlohmann/json.hpp"
@ -79,7 +80,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"before_layer_change_gcode",
"enable_pressure_advance",
"pressure_advance",
"enable_overhang_bridge_fan"
"enable_overhang_bridge_fan",
"overhang_fan_speed",
"overhang_fan_threshold",
"slow_down_for_layer_cooling",
@ -92,23 +93,28 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"extruder_clearance_height_to_rod",
"extruder_clearance_height_to_lid",
"extruder_clearance_radius",
"extruder_clearance_max_radius",
"extruder_colour",
"extruder_offset",
"filament_flow_ratio",
"reduce_fan_stop_start_freq",
"fan_cooling_layer_time",
"full_fan_speed_layer",
"fan_kickstart",
"fan_speedup_overhangs",
"fan_speedup_time",
"filament_colour",
"default_filament_colour",
"filament_diameter",
"filament_density",
"filament_cost",
"initial_layer_acceleration",
"outer_wall_acceleration",
"inner_wall_acceleration",
"initial_layer_acceleration",
"top_surface_acceleration",
"accel_to_decel_enable",
"accel_to_decel_factor",
"bridge_acceleration",
"travel_acceleration",
"sparse_infill_acceleration",
"internal_solid_infill_acceleration"
// BBS
"cool_plate_temp_initial_layer",
"eng_plate_temp_initial_layer",
@ -131,10 +137,14 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"retract_when_changing_layer",
"retraction_length",
"retract_length_toolchange",
"z_hop",
"z_hop",
"retract_lift_above",
"retract_lift_below",
"retract_lift_enforce",
"retract_restart_extra",
"retract_restart_extra_toolchange",
"retraction_speed",
"use_firmware_retraction",
"slow_down_layer_time",
"standby_temperature_delta",
"machine_start_gcode",
@ -145,23 +155,23 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"wipe_distance",
"curr_bed_type",
"nozzle_volume",
"chamber_temperatures",
"chamber_temperature",
"thumbnails",
"nozzle_hrc",
"required_nozzle_HRC",
"upward_compatible_machine",
//OrcaSlicer
// SoftFever
"seam_gap",
"wipe_speed"
"default_jerk",
"outer_wall_jerk",
"inner_wall_jerk",
"infill_jerk",
"top_surface_jerk",
"initial_layer_jerk",
"travel_jerk",
"inner_wall_acceleration",
"sparse_infill_acceleration",
"role_based_wipe_speed",
"wipe_speed",
"use_relative_e_distances",
"accel_to_decel_enable",
"accel_to_decel_factor",
"wipe_on_loops",
"gcode_comments",
"gcode_label_objects",
"exclude_object",
"use_relative_e_distances"
"support_material_interface_fan_speed"
};
static std::unordered_set<std::string> steps_ignore;
@ -179,6 +189,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
// These steps have no influence on the G-code whatsoever. Just ignore them.
} else if (
opt_key == "skirt_loops"
|| opt_key == "skirt_speed"
|| opt_key == "skirt_height"
|| opt_key == "draft_shield"
|| opt_key == "skirt_distance"
@ -190,6 +201,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
} else if (
opt_key == "initial_layer_print_height"
|| opt_key == "nozzle_diameter"
|| opt_key == "filament_shrink"
|| opt_key == "resolution"
// Spiral Vase forces different kind of slicing than the normal model:
// In Spiral Vase mode, holes are closed and only the largest area contour is kept at each layer.
@ -198,8 +210,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
osteps.emplace_back(posSlice);
} else if (
opt_key == "print_sequence"
|| opt_key == "chamber_temperatures"
|| opt_key == "filament_type"
|| opt_key == "chamber_temperature"
|| opt_key == "nozzle_temperature_initial_layer"
|| opt_key == "filament_minimal_purge_on_wipe_tower"
|| opt_key == "filament_max_volumetric_speed"
@ -224,7 +236,9 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "initial_layer_infill_speed"
|| opt_key == "travel_speed"
|| opt_key == "travel_speed_z"
|| opt_key == "initial_layer_speed") {
|| opt_key == "initial_layer_speed"
|| opt_key == "initial_layer_travel_speed"
|| opt_key == "slow_down_layers") {
//|| opt_key == "z_offset") {
steps.emplace_back(psWipeTower);
steps.emplace_back(psSkirtBrim);
@ -248,7 +262,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
osteps.emplace_back(posPerimeters);
osteps.emplace_back(posInfill);
osteps.emplace_back(posSupportMaterial);
osteps.emplace_back(posSimplifyWall);
osteps.emplace_back(posSimplifyPath);
osteps.emplace_back(posSimplifyInfill);
osteps.emplace_back(posSimplifySupportPath);
steps.emplace_back(psSkirtBrim);
@ -274,9 +288,9 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
return invalidated;
}
void Print::set_calib_params(const Calib_Params &params)
{
m_calib_params = params;
void Print::set_calib_params(const Calib_Params& params) {
m_calib_params = params;
m_calib_params.mode = params.mode;
}
bool Print::invalidate_step(PrintStep step)
@ -527,7 +541,7 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
auto tmp = offset(convex_hull_no_offset,
// Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects
// exactly by satisfying the extruder_clearance_radius, this test will not trigger collision.
float(scale_(0.5 * print.config().extruder_clearance_max_radius.value - EPSILON)),
float(scale_(0.5 * print.config().extruder_clearance_radius.value - EPSILON)),
jtRound, scale_(0.1));
if (!tmp.empty()) { // tmp may be empty due to clipper's bug, see STUDIO-2452
convex_hull = tmp.front();
@ -940,6 +954,10 @@ StringObjectException Print::check_multi_filament_valid(const Print& print)
return {std::string()};
}
// Orca: this g92e0 regex is used copied from PrusaSlicer
// Matches "G92 E0" with various forms of writing the zero and with an optional comment.
boost::regex regex_g92e0 { "^[ \\t]*[gG]92[ \\t]*[eE](0(\\.0*)?|\\.0+)[ \\t]*(;.*)?$" };
// Precondition: Print::validate() requires the Print::apply() to be called its invocation.
//BBS: refine seq-print validation logic
StringObjectException Print::validate(StringObjectException *warning, Polygons* collison_polygons, std::vector<std::pair<Polygon, float>>* height_polygons) const
@ -1120,19 +1138,15 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
return ("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 {
// This may change in the future, if we switch to "extrusion width wrt. nozzle diameter"
// instead of currently used logic "extrusion width wrt. layer height", see GH issues #1923 #2829.
// 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);
double extrusion_width_min = config.get_abs_value(opt_key);
double extrusion_width_max = config.get_abs_value(opt_key);
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 = L("Too small line width");
return false;
} else if (extrusion_width_max >= max_nozzle_diameter * 2.5) {
} else if (extrusion_width_max > max_nozzle_diameter * 5) {
err_msg = L("Too large line width");
return false;
}
@ -1218,33 +1232,56 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
}
}
// Orca: G92 E0 is not supported when using absolute extruder addressing
// This check is copied from PrusaSlicer, the original author is Vojtech Bubnik
{
bool before_layer_gcode_resets_extruder =
boost::regex_search(m_config.before_layer_change_gcode.value, regex_g92e0);
bool layer_gcode_resets_extruder = boost::regex_search(m_config.layer_change_gcode.value, regex_g92e0);
if (m_config.use_relative_e_distances) {
// See GH issues #6336 #5073
if ((m_config.gcode_flavor == gcfMarlinLegacy || m_config.gcode_flavor == gcfMarlinFirmware) &&
!before_layer_gcode_resets_extruder && !layer_gcode_resets_extruder)
return {L("Relative extruder addressing requires resetting the extruder position at each layer to "
"prevent loss of floating point accuracy. Add \"G92 E0\" to layer_gcode."),
nullptr, "before_layer_change_gcode"};
} else if (before_layer_gcode_resets_extruder)
return {L("\"G92 E0\" was found in before_layer_gcode, which is incompatible with absolute extruder "
"addressing."),
nullptr, "before_layer_change_gcode"};
else if (layer_gcode_resets_extruder)
return {L("\"G92 E0\" was found in layer_gcode, which is incompatible with absolute extruder addressing."),
nullptr, "layer_change_gcode"};
}
const ConfigOptionDef* bed_type_def = print_config_def.get("curr_bed_type");
assert(bed_type_def != nullptr);
const t_config_enum_values* bed_type_keys_map = bed_type_def->enum_keys_map;
for (unsigned int extruder_id : extruders) {
const ConfigOptionInts* bed_temp_opt = m_config.option<ConfigOptionInts>(get_bed_temp_key(m_config.curr_bed_type));
for (unsigned int extruder_id : extruders) {
int curr_bed_temp = bed_temp_opt->get_at(extruder_id);
if (curr_bed_temp == 0 && bed_type_keys_map != nullptr) {
std::string bed_type_name;
for (auto item : *bed_type_keys_map) {
if (item.second == m_config.curr_bed_type) {
bed_type_name = item.first;
break;
}
}
if (is_BBL_printer()) {
const t_config_enum_values* bed_type_keys_map = bed_type_def->enum_keys_map;
for (unsigned int extruder_id : extruders) {
const ConfigOptionInts* bed_temp_opt = m_config.option<ConfigOptionInts>(get_bed_temp_key(m_config.curr_bed_type));
for (unsigned int extruder_id : extruders) {
int curr_bed_temp = bed_temp_opt->get_at(extruder_id);
if (curr_bed_temp == 0 && bed_type_keys_map != nullptr) {
std::string bed_type_name;
for (auto item : *bed_type_keys_map) {
if (item.second == m_config.curr_bed_type) {
bed_type_name = item.first;
break;
}
}
StringObjectException except;
except.string = format(L("Plate %d: %s does not support filament %s"), this->get_plate_index() + 1, L(bed_type_name), extruder_id + 1);
except.string += "\n";
except.type = STRING_EXCEPT_FILAMENT_NOT_MATCH_BED_TYPE;
except.params.push_back(std::to_string(this->get_plate_index() + 1));
except.params.push_back(L(bed_type_name));
except.params.push_back(std::to_string(extruder_id+1));
except.object = nullptr;
return except;
StringObjectException except;
except.string = format(L("Plate %d: %s does not support filament %s"), this->get_plate_index() + 1, L(bed_type_name), extruder_id + 1);
except.string += "\n";
except.type = STRING_EXCEPT_FILAMENT_NOT_MATCH_BED_TYPE;
except.params.push_back(std::to_string(this->get_plate_index() + 1));
except.params.push_back(L(bed_type_name));
except.params.push_back(std::to_string(extruder_id+1));
except.object = nullptr;
return except;
}
}
}
}
@ -1316,10 +1353,10 @@ double Print::skirt_first_layer_height() const
Flow Print::brim_flow() const
{
ConfigOptionFloat width = m_config.initial_layer_line_width;
if (width.value == 0)
ConfigOptionFloatOrPercent width = m_config.initial_layer_line_width;
if (width.value <= 0)
width = m_print_regions.front()->config().inner_wall_line_width;
if (width.value == 0)
if (width.value <= 0)
width = m_objects.front()->config().line_width;
/* We currently use a random region's perimeter extruder.
@ -1329,6 +1366,7 @@ Flow Print::brim_flow() const
generation as well. */
return Flow::new_from_config_width(
frPerimeter,
// Flow::new_from_config_width takes care of the percent to value substitution
width,
(float)m_config.nozzle_diameter.get_at(m_print_regions.front()->config().wall_filament-1),
(float)this->skirt_first_layer_height());
@ -1336,8 +1374,8 @@ Flow Print::brim_flow() const
Flow Print::skirt_flow() const
{
ConfigOptionFloat width = m_config.initial_layer_line_width;
if (width.value == 0)
ConfigOptionFloatOrPercent width = m_config.initial_layer_line_width;
if (width.value <= 0)
width = m_objects.front()->config().line_width;
/* We currently use a random object's support material extruder.
@ -1347,6 +1385,7 @@ Flow Print::skirt_flow() const
generation as well. */
return Flow::new_from_config_width(
frPerimeter,
// Flow::new_from_config_width takes care of the percent to value substitution
width,
(float)m_config.nozzle_diameter.get_at(m_objects.front()->config().support_filament-1),
(float)this->skirt_first_layer_height());
@ -1737,7 +1776,7 @@ void Print::process(bool use_cache)
// BBS: m_brimMap and m_supportBrimMap are used instead of m_brim to generate brim of objs and supports seperately
m_brimMap.clear();
m_supportBrimMap.clear();
m_first_layer_convex_hull.points.clear(); // BBS: plate offset is contained in this convexhull
m_first_layer_convex_hull.points.clear();
if (this->has_brim()) {
Polygons islands_area;
make_brim(*this, this->make_try_cancel(), islands_area, m_brimMap,
@ -1766,8 +1805,8 @@ void Print::process(bool use_cache)
obj->simplify_extrusion_path();
}
else {
if (obj->set_started(posSimplifyWall))
obj->set_done(posSimplifyWall);
if (obj->set_started(posSimplifyPath))
obj->set_done(posSimplifyPath);
if (obj->set_started(posSimplifyInfill))
obj->set_done(posSimplifyInfill);
if (obj->set_started(posSimplifySupportPath))
@ -2070,16 +2109,15 @@ std::vector<Point> Print::first_layer_wipe_tower_corners(bool check_wipe_tower_e
return corners;
}
//OrcaSlicer
Vec2d Print::translate_to_print_space(const Vec2d& point) const {
//SoftFever
Vec2d Print::translate_to_print_space(const Vec2d &point) const {
//const BoundingBoxf bed_bbox(config().printable_area.values);
return Vec2d(point(0) - m_origin(0), point(1) - m_origin(1));
}
Vec2d Print::translate_to_print_space(const Point& point) const {
Vec2d Print::translate_to_print_space(const Point &point) const {
return Vec2d(unscaled(point.x()) - m_origin(0), unscaled(point.y()) - m_origin(1));
}
void Print::finalize_first_layer_convex_hull()
{
append(m_first_layer_convex_hull.points, m_skirt_convex_hull);

View file

@ -14,14 +14,14 @@
#include "GCode/ThumbnailData.hpp"
#include "GCode/GCodeProcessor.hpp"
#include "MultiMaterialSegmentation.hpp"
#include "libslic3r.h"
#include <Eigen/Geometry>
#include <functional>
#include <set>
#include "Calib.hpp"
#include "calib.hpp"
namespace Slic3r {
@ -87,9 +87,9 @@ enum PrintStep {
enum PrintObjectStep {
posSlice, posPerimeters, posPrepareInfill,
posInfill, posIroning, posSupportMaterial,
posInfill, posIroning, posSupportMaterial, posSimplifyPath, posSimplifySupportPath,
// BBS
posSimplifyWall, posSimplifyInfill, posSimplifySupportPath,
posSimplifyInfill,
posDetectOverhangsForLift,
posCount,
};
@ -194,11 +194,11 @@ struct PrintInstance
const ModelInstance *model_instance;
// Shift of this instance's center into the world coordinates.
Point shift;
BoundingBoxf3 get_bounding_box();
Polygon get_convex_hull_2d();
// OrcaSlicer
//
// SoftFever
//
// instance id
size_t id;
@ -305,7 +305,7 @@ public:
Transform3d trafo_centered() const
{ Transform3d t = this->trafo(); t.pretranslate(Vec3d(- unscale<double>(m_center_offset.x()), - unscale<double>(m_center_offset.y()), 0)); return t; }
const PrintInstances& instances() const { return m_instances; }
PrintInstances& instances() { return m_instances; }
PrintInstances &instances() { return m_instances; }
// Whoever will get a non-const pointer to PrintObject will be able to modify its layers.
LayerPtrs& layers() { return m_layers; }
@ -434,11 +434,11 @@ public:
// BBS: Boundingbox of the first layer
BoundingBox firstLayerObjectBrimBoundingBox;
// OrcaSlicer
size_t get_klipper_object_id() const { return m_klipper_object_id; }
void set_klipper_object_id(size_t id) { m_klipper_object_id = id; }
// SoftFever
size_t get_id() const { return m_id; }
void set_id(size_t id) { m_id = id; }
private:
private:
// to be called from Print only.
friend class Print;
@ -522,10 +522,12 @@ private:
PrintObject* m_shared_object{ nullptr };
// OrcaSlicer
//
// object id for klipper firmware only
size_t m_klipper_object_id;
// SoftFever
//
// object id
size_t m_id;
void apply_conical_overhang();
public:
//BBS: When printing multi-material objects, this settings will make slicer to clip the overlapping object parts one by the other.
@ -737,7 +739,7 @@ public:
const PrintConfig& config() const { return m_config; }
const PrintObjectConfig& default_object_config() const { return m_default_object_config; }
const PrintRegionConfig& default_region_config() const { return m_default_region_config; }
const PrintRegionConfig& default_region_config() const { return m_default_region_config; }
ConstPrintObjectPtrsAdaptor objects() const { return ConstPrintObjectPtrsAdaptor(&m_objects); }
PrintObject* get_object(size_t idx) { return const_cast<PrintObject*>(m_objects[idx]); }
const PrintObject* get_object(size_t idx) const { return m_objects[idx]; }
@ -795,8 +797,6 @@ public:
int get_modified_count() const {return m_modified_count;}
//BBS: add status for whether support used
bool is_support_used() const {return m_support_used;}
bool is_BBL_Printer() const { return m_isBBLPrinter;}
void set_BBL_Printer(const bool isBBL) { m_isBBLPrinter = isBBL;}
std::string get_conflict_string() const
{
std::string result;
@ -806,23 +806,28 @@ public:
return result;
}
//BBS
static StringObjectException sequential_print_clearance_valid(const Print &print, Polygons *polygons = nullptr, std::vector<std::pair<Polygon, float>>* height_polygons = nullptr);
ConflictResultOpt get_conflict_result() const { return m_conflict_result; }
// Return 4 wipe tower corners in the world coordinates (shifted and rotated), including the wipe tower brim.
std::vector<Point> first_layer_wipe_tower_corners(bool check_wipe_tower_existance=true) const;
//OrcaSlicer
CalibMode & calib_mode() { return m_calib_params.mode; }
const CalibMode& calib_mode() const { return m_calib_params.mode; }
void set_calib_params(const Calib_Params &params);
//SoftFever
bool &is_BBL_printer() { return m_isBBLPrinter; }
const bool is_BBL_printer() const { return m_isBBLPrinter; }
CalibMode& calib_mode() { return m_calib_params.mode; }
const CalibMode calib_mode() const { return m_calib_params.mode; }
void set_calib_params(const Calib_Params& params);
const Calib_Params& calib_params() const { return m_calib_params; }
Vec2d translate_to_print_space(const Vec2d& point) const;
Vec2d translate_to_print_space(const Vec2d &point) const;
// scaled point
Vec2d translate_to_print_space(const Point& point) const;
Vec2d translate_to_print_space(const Point &point) const;
static bool check_multi_filaments_compatibility(const std::vector<std::string>& filament_types);
protected:
protected:
// Invalidates the step, and its depending steps in Print.
bool invalidate_step(PrintStep step);
@ -844,8 +849,10 @@ private:
PrintRegionConfig m_default_region_config;
PrintObjectPtrs m_objects;
PrintRegionPtrs m_print_regions;
//BBS.
bool m_isBBLPrinter = false;
//SoftFever
bool m_isBBLPrinter;
// Ordered collections of extrusion paths to build skirt loops and brim.
ExtrusionEntityCollection m_skirt;
// BBS: collecting extrusion paths to build brim by objs
@ -874,8 +881,8 @@ private:
//BBS
ConflictResultOpt m_conflict_result;
FakeWipeTower m_fake_wipe_tower;
// OrcaSlicer: calibration
//SoftFever: calibration
Calib_Params m_calib_params;
// To allow GCode to set the Print's GCodeExport step status.

View file

@ -516,9 +516,9 @@ public:
bool get_no_check_flag() const { return m_no_check; }
void set_no_check_flag(bool no_check) { m_no_check = no_check; }
//SoftFever plate name
std::string get_plate_name() const { return m_plate_name; }
void set_plate_name(const std::string &name) { m_plate_name = name; }
void set_plate_name(const std::string& name) { m_plate_name = name; }
protected:
friend class PrintObjectBase;
friend class BackgroundSlicingProcess;
@ -554,8 +554,9 @@ protected:
int m_plate_index{ 0 };
bool m_no_check = false;
// current plate name
std::string m_plate_name; // utf8 string
// SoftFever: current plate name
std::string m_plate_name;
// Callback to be evoked regularly to update state of the UI thread.
status_callback_type m_status_callback;

File diff suppressed because it is too large Load diff

View file

@ -32,7 +32,7 @@
namespace Slic3r {
enum GCodeFlavor : unsigned char {
gcfMarlinLegacy, gcfKlipper, gcfRepRapSprinter, gcfRepRapFirmware, gcfRepetier, gcfTeacup, gcfMakerWare, gcfMarlinFirmware, gcfSailfish, gcfMach3, gcfMachinekit,
gcfMarlinLegacy, gcfKlipper, gcfRepRapFirmware, gcfRepRapSprinter, gcfRepetier, gcfTeacup, gcfMakerWare, gcfMarlinFirmware, gcfSailfish, gcfMach3, gcfMachinekit,
gcfSmoothie, gcfNoExtrusion
};
@ -129,6 +129,12 @@ enum SeamPosition {
spNearest, spAligned, spRear, spRandom
};
enum LiftType {
NormalLift,
SpiralLift,
LazyLift
};
enum SLAMaterial {
slamTough,
slamFlex,
@ -150,6 +156,7 @@ enum SLAPillarConnectionMode {
enum BrimType {
btAutoBrim, // BBS
btEar, // Orca
btOuterOnly,
btInnerOnly,
btOuterAndInner,
@ -174,13 +181,6 @@ enum class PerimeterGeneratorType
Arachne
};
enum class TopOneWallType
{
None,
Alltop,
Topmost
};
// BBS
enum OverhangFanThreshold {
Overhang_threshold_none = 0,
@ -219,10 +219,11 @@ enum ZHopType {
zhtCount
};
// BBS
enum ExtruderType {
etDirectDrive = 0,
etBowden
enum RetractLiftEnforceType {
rletAllSurfaces = 0,
rletTopOnly,
rletBottomOnly,
rletTopAndBottom
};
static std::string bed_type_to_gcode_string(const BedType type)
@ -311,7 +312,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(ForwardCompatibilitySubstitutionRule)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PrintHostType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(AuthorizationType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PerimeterGeneratorType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(TopOneWallType)
#undef CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS
// Defines each and every confiuration option of Slic3r, including the properties of the GUI dialogs.
@ -640,10 +641,12 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, brim_object_gap))
((ConfigOptionEnum<BrimType>, brim_type))
((ConfigOptionFloat, brim_width))
((ConfigOptionFloat, brim_ears_detection_length))
((ConfigOptionFloat, brim_ears_max_angle))
((ConfigOptionBool, bridge_no_support))
((ConfigOptionFloat, elefant_foot_compensation))
((ConfigOptionFloat, max_bridge_length))
((ConfigOptionFloat, line_width))
((ConfigOptionFloatOrPercent, line_width))
// Force the generation of solid shells between adjacent materials/volumes.
((ConfigOptionBool, interface_shells))
((ConfigOptionFloat, layer_height))
@ -653,6 +656,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, raft_first_layer_expansion))
((ConfigOptionInt, raft_layers))
((ConfigOptionEnum<SeamPosition>, seam_position))
((ConfigOptionBool, staggered_inner_seams))
((ConfigOptionFloat, slice_closing_radius))
((ConfigOptionEnum<SlicingMode>, slicing_mode))
((ConfigOptionBool, enable_support))
@ -667,7 +671,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, support_bottom_z_distance))
((ConfigOptionInt, enforce_support_layers))
((ConfigOptionInt, support_filament))
((ConfigOptionFloat, support_line_width))
((ConfigOptionFloatOrPercent, support_line_width))
((ConfigOptionBool, support_interface_loop_pattern))
((ConfigOptionInt, support_interface_filament))
((ConfigOptionInt, support_interface_top_layers))
@ -699,6 +703,8 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, tree_support_branch_diameter))
((ConfigOptionFloat, tree_support_branch_angle))
((ConfigOptionInt, tree_support_wall_count))
((ConfigOptionBool, tree_support_adaptive_layer_height))
((ConfigOptionBool, tree_support_auto_brim))
((ConfigOptionFloat, tree_support_brim_width))
((ConfigOptionBool, detect_narrow_internal_solid_infill))
// ((ConfigOptionBool, adaptive_layer_height))
@ -711,39 +717,39 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionInt, wall_distribution_count))
((ConfigOptionPercent, min_feature_size))
((ConfigOptionPercent, min_bead_width))
((ConfigOptionEnum<TopOneWallType>, top_one_wall_type))
((ConfigOptionBool, only_one_wall_first_layer))
// OrcaSlicer
((ConfigOptionPercent, seam_gap))
((ConfigOptionPercent, wipe_speed))
// Orca
((ConfigOptionFloat, make_overhang_printable_angle))
((ConfigOptionFloat, make_overhang_printable_hole_size))
)
// This object is mapped to Perl as Slic3r::Config::PrintRegion.
PRINT_CONFIG_CLASS_DEFINE(
PrintRegionConfig,
((ConfigOptionInt, bottom_shell_layers))
((ConfigOptionFloat, bottom_shell_thickness))
((ConfigOptionFloat, bridge_angle))
((ConfigOptionFloat, bridge_flow))
((ConfigOptionFloat, bridge_speed))
((ConfigOptionBool, ensure_vertical_shell_thickness))
((ConfigOptionEnum<InfillPattern>, top_surface_pattern))
((ConfigOptionEnum<InfillPattern>, bottom_surface_pattern))
((ConfigOptionInt, bottom_shell_layers))
((ConfigOptionFloat, bottom_shell_thickness))
((ConfigOptionFloat, bridge_angle))
((ConfigOptionFloat, bridge_flow))
((ConfigOptionFloat, bridge_speed))
((ConfigOptionFloatOrPercent, internal_bridge_speed))
((ConfigOptionBool, ensure_vertical_shell_thickness))
((ConfigOptionEnum<InfillPattern>, top_surface_pattern))
((ConfigOptionEnum<InfillPattern>, bottom_surface_pattern))
((ConfigOptionEnum<InfillPattern>, internal_solid_infill_pattern))
((ConfigOptionFloat, outer_wall_line_width))
((ConfigOptionFloat, outer_wall_speed))
((ConfigOptionFloat, infill_direction))
((ConfigOptionPercent, sparse_infill_density))
((ConfigOptionEnum<InfillPattern>, sparse_infill_pattern))
((ConfigOptionEnum<FuzzySkinType>, fuzzy_skin))
((ConfigOptionFloat, fuzzy_skin_thickness))
((ConfigOptionFloat, fuzzy_skin_point_distance))
((ConfigOptionFloat, gap_infill_speed))
((ConfigOptionInt, sparse_infill_filament))
((ConfigOptionFloat, sparse_infill_line_width))
((ConfigOptionPercent, infill_wall_overlap))
((ConfigOptionFloat, sparse_infill_speed))
((ConfigOptionFloatOrPercent, outer_wall_line_width))
((ConfigOptionFloat, outer_wall_speed))
((ConfigOptionFloat, infill_direction))
((ConfigOptionPercent, sparse_infill_density))
((ConfigOptionEnum<InfillPattern>, sparse_infill_pattern))
((ConfigOptionEnum<FuzzySkinType>, fuzzy_skin))
((ConfigOptionFloat, fuzzy_skin_thickness))
((ConfigOptionFloat, fuzzy_skin_point_distance))
((ConfigOptionFloat, gap_infill_speed))
((ConfigOptionInt, sparse_infill_filament))
((ConfigOptionFloatOrPercent, sparse_infill_line_width))
((ConfigOptionPercent, infill_wall_overlap))
((ConfigOptionFloat, sparse_infill_speed))
//BBS
((ConfigOptionBool, infill_combination))
// Ironing options
@ -755,34 +761,51 @@ PRINT_CONFIG_CLASS_DEFINE(
// Detect bridging perimeters
((ConfigOptionBool, detect_overhang_wall))
((ConfigOptionInt, wall_filament))
((ConfigOptionFloat, inner_wall_line_width))
((ConfigOptionFloatOrPercent, inner_wall_line_width))
((ConfigOptionFloat, inner_wall_speed))
// Total number of perimeters.
((ConfigOptionInt, wall_loops))
((ConfigOptionFloat, minimum_sparse_infill_area))
((ConfigOptionInt, solid_infill_filament))
((ConfigOptionFloat, internal_solid_infill_line_width))
((ConfigOptionFloatOrPercent, internal_solid_infill_line_width))
((ConfigOptionFloat, internal_solid_infill_speed))
// Detect thin walls.
((ConfigOptionBool, detect_thin_wall))
((ConfigOptionFloat, top_surface_line_width))
((ConfigOptionFloatOrPercent, top_surface_line_width))
((ConfigOptionInt, top_shell_layers))
((ConfigOptionFloat, top_shell_thickness))
((ConfigOptionFloat, top_surface_speed))
//BBS
((ConfigOptionBool, enable_overhang_speed))
((ConfigOptionFloat, overhang_1_4_speed))
((ConfigOptionFloat, overhang_2_4_speed))
((ConfigOptionFloat, overhang_3_4_speed))
((ConfigOptionFloat, overhang_4_4_speed))
((ConfigOptionFloatOrPercent, sparse_infill_anchor))
((ConfigOptionFloatOrPercent, sparse_infill_anchor_max))
//OrcaSlicer
((ConfigOptionFloat, top_solid_infill_flow_ratio))
((ConfigOptionFloat, initial_layer_flow_ratio))
((ConfigOptionFloat, filter_out_gap_fill))
//calib
((ConfigOptionFloat, print_flow_ratio)))
((ConfigOptionBool, enable_overhang_speed))
((ConfigOptionFloatOrPercent, overhang_1_4_speed))
((ConfigOptionFloatOrPercent, overhang_2_4_speed))
((ConfigOptionFloatOrPercent, overhang_3_4_speed))
((ConfigOptionFloatOrPercent, overhang_4_4_speed))
((ConfigOptionBool, only_one_wall_top))
//SoftFever
((ConfigOptionFloatOrPercent, min_width_top_surface))
((ConfigOptionBool, only_one_wall_first_layer))
((ConfigOptionFloat, print_flow_ratio))
((ConfigOptionFloatOrPercent, seam_gap))
((ConfigOptionBool, role_based_wipe_speed))
((ConfigOptionFloatOrPercent, wipe_speed))
((ConfigOptionBool, wipe_on_loops))
((ConfigOptionEnum<WallInfillOrder>, wall_infill_order))
((ConfigOptionBool, precise_outer_wall))
((ConfigOptionBool, overhang_speed_classic))
((ConfigOptionPercent, bridge_density))
((ConfigOptionFloat, filter_out_gap_fill))
((ConfigOptionFloatOrPercent, small_perimeter_speed))
((ConfigOptionFloat, small_perimeter_threshold))
((ConfigOptionFloat, top_solid_infill_flow_ratio))
((ConfigOptionFloat, bottom_solid_infill_flow_ratio))
((ConfigOptionFloatOrPercent, infill_anchor))
((ConfigOptionFloatOrPercent, infill_anchor_max))
// Orca
((ConfigOptionBool, make_overhang_printable))
)
PRINT_CONFIG_CLASS_DEFINE(
MachineEnvelopeConfig,
@ -827,6 +850,9 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloats, filament_flow_ratio))
((ConfigOptionBools, enable_pressure_advance))
((ConfigOptionFloats, pressure_advance))
((ConfigOptionFloat, fan_kickstart))
((ConfigOptionBool, fan_speedup_overhangs))
((ConfigOptionFloat, fan_speedup_time))
((ConfigOptionFloats, filament_diameter))
((ConfigOptionFloats, filament_density))
((ConfigOptionStrings, filament_type))
@ -846,6 +872,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, gcode_add_line_number))
((ConfigOptionBool, bbl_bed_temperature_gcode))
((ConfigOptionEnum<GCodeFlavor>, gcode_flavor))
((ConfigOptionString, layer_change_gcode))
//#ifdef HAS_PRESSURE_EQUALIZER
// ((ConfigOptionFloat, max_volumetric_extrusion_rate_slope_positive))
@ -857,6 +884,9 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloats, z_hop))
// BBS
((ConfigOptionEnumsGeneric, z_hop_types))
((ConfigOptionFloats, retract_lift_above))
((ConfigOptionFloats, retract_lift_below))
((ConfigOptionEnumsGeneric, retract_lift_enforce))
((ConfigOptionFloats, retract_restart_extra))
((ConfigOptionFloats, retract_restart_extra_toolchange))
((ConfigOptionFloats, retraction_speed))
@ -867,16 +897,21 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionString, change_filament_gcode))
((ConfigOptionFloat, travel_speed))
((ConfigOptionFloat, travel_speed_z))
((ConfigOptionBool, use_relative_e_distances))
((ConfigOptionBool, silent_mode))
((ConfigOptionString, machine_pause_gcode))
((ConfigOptionString, template_custom_gcode))
//BBS
((ConfigOptionEnum<NozzleType>, nozzle_type))
((ConfigOptionInt, nozzle_hrc))
((ConfigOptionBool, auxiliary_fan))
// SoftFever
((ConfigOptionBool, use_firmware_retraction))
((ConfigOptionBool, use_relative_e_distances))
((ConfigOptionBool, accel_to_decel_enable))
((ConfigOptionPercent, accel_to_decel_factor))
((ConfigOptionEnumsGeneric, extruder_type))
((ConfigOptionFloatOrPercent, initial_layer_travel_speed))
((ConfigOptionBool, bbl_calib_mark_logo))
)
// This object is mapped to Perl as Slic3r::Config::Print.
@ -908,30 +943,39 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionInts, first_layer_print_sequence))
((ConfigOptionBools, slow_down_for_layer_cooling))
((ConfigOptionFloat, default_acceleration))
((ConfigOptionFloat, inner_wall_acceleration))
((ConfigOptionFloatOrPercent, sparse_infill_acceleration))
((ConfigOptionInts, close_fan_the_first_x_layers))
((ConfigOptionEnum<DraftShield>, draft_shield))
((ConfigOptionFloat, extruder_clearance_height_to_rod))//BBs
((ConfigOptionFloat, extruder_clearance_height_to_lid))//BBS
((ConfigOptionFloat, extruder_clearance_radius))
((ConfigOptionFloat, extruder_clearance_max_radius))
((ConfigOptionStrings, extruder_colour))
((ConfigOptionPoints, extruder_offset))
((ConfigOptionBools, reduce_fan_stop_start_freq))
((ConfigOptionInts, fan_cooling_layer_time))
((ConfigOptionFloats, fan_cooling_layer_time))
((ConfigOptionStrings, filament_colour))
((ConfigOptionFloat, top_surface_acceleration))
((ConfigOptionFloat, outer_wall_acceleration))
((ConfigOptionFloat, inner_wall_acceleration))
((ConfigOptionFloat, top_surface_acceleration))
((ConfigOptionFloat, initial_layer_acceleration))
((ConfigOptionFloat, initial_layer_line_width))
((ConfigOptionFloatOrPercent, bridge_acceleration))
((ConfigOptionFloat, travel_acceleration))
((ConfigOptionFloatOrPercent, sparse_infill_acceleration))
((ConfigOptionFloatOrPercent, internal_solid_infill_acceleration))
((ConfigOptionFloatOrPercent, initial_layer_line_width))
((ConfigOptionFloat, initial_layer_print_height))
((ConfigOptionFloat, initial_layer_speed))
((ConfigOptionFloat, default_jerk))
((ConfigOptionFloat, outer_wall_jerk))
((ConfigOptionFloat, inner_wall_jerk))
((ConfigOptionFloat, infill_jerk))
((ConfigOptionFloat, top_surface_jerk))
((ConfigOptionFloat, initial_layer_jerk))
((ConfigOptionFloat, travel_jerk))
//BBS
((ConfigOptionFloat, initial_layer_infill_speed))
((ConfigOptionInts, nozzle_temperature_initial_layer))
((ConfigOptionInts, full_fan_speed_layer))
((ConfigOptionEnum<WallInfillOrder>,wall_infill_order))
((ConfigOptionInts, fan_max_speed))
((ConfigOptionFloats, max_layer_height))
((ConfigOptionInts, fan_min_speed))
@ -950,11 +994,12 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionFloat, skirt_distance))
((ConfigOptionInt, skirt_height))
((ConfigOptionInt, skirt_loops))
((ConfigOptionInts, slow_down_layer_time))
((ConfigOptionFloat, skirt_speed))
((ConfigOptionFloats, slow_down_layer_time))
((ConfigOptionBool, spiral_mode))
((ConfigOptionInt, standby_temperature_delta))
((ConfigOptionInts, nozzle_temperature))
((ConfigOptionInts, chamber_temperatures))
((ConfigOptionInts , chamber_temperature))
((ConfigOptionBools, wipe))
// BBS
((ConfigOptionInts, bed_temperature_difference))
@ -983,17 +1028,18 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionFloat, nozzle_volume))
((ConfigOptionPoints, start_end_points))
((ConfigOptionEnum<TimelapseType>, timelapse_type))
((ConfigOptionFloat, default_jerk))
((ConfigOptionFloat, outer_wall_jerk))
((ConfigOptionFloat, inner_wall_jerk))
((ConfigOptionFloat, infill_jerk))
((ConfigOptionFloat, top_surface_jerk))
((ConfigOptionFloat, initial_layer_jerk))
((ConfigOptionFloat, travel_jerk))
((ConfigOptionPoints, thumbnails))
// BBS: move from PrintObjectConfig
((ConfigOptionBool, independent_support_layer_height))
((ConfigOptionBool, exclude_object))
((ConfigOptionBool, independent_support_layer_height))
// SoftFever
((ConfigOptionPercents, filament_shrink))
((ConfigOptionBool, gcode_label_objects))
((ConfigOptionBool, exclude_object))
((ConfigOptionBool, gcode_comments))
((ConfigOptionInt, slow_down_layers))
((ConfigOptionInts, support_material_interface_fan_speed))
)
// This object is mapped to Perl as Slic3r::Config::Full.
@ -1362,7 +1408,12 @@ public:
const ConfigOption* option(const t_config_option_key &opt_key) const { return m_data.option(opt_key); }
int opt_int(const t_config_option_key &opt_key) const { return m_data.opt_int(opt_key); }
int extruder() const { return opt_int("extruder"); }
double opt_float(const t_config_option_key &opt_key) const { return m_data.opt_float(opt_key); }
double opt_float(const t_config_option_key &opt_key) const {
return m_data.opt_float(opt_key);
}
double get_abs_value(const t_config_option_key &opt_key) const {
return m_data.get_abs_value(opt_key);
}
std::string opt_serialize(const t_config_option_key &opt_key) const { return m_data.opt_serialize(opt_key); }
// Return an optional timestamp of this object.

View file

@ -423,7 +423,10 @@ static const float g_min_overhang_percent_for_lift = 0.3f;
void PrintObject::detect_overhangs_for_lift()
{
if (this->set_started(posDetectOverhangsForLift)) {
const float min_overlap = m_config.line_width * g_min_overhang_percent_for_lift;
const double nozzle_diameter = m_print->config().nozzle_diameter.get_at(0);
const coordf_t line_width = this->config().get_abs_value("line_width", nozzle_diameter);
const float min_overlap = line_width * g_min_overhang_percent_for_lift;
size_t num_layers = this->layer_count();
size_t num_raft_layers = m_slicing_params.raft_layers();
@ -433,17 +436,18 @@ void PrintObject::detect_overhangs_for_lift()
tbb::spin_mutex layer_storage_mutex;
tbb::parallel_for(tbb::blocked_range<size_t>(num_raft_layers + 1, num_layers),
[this, min_overlap](const tbb::blocked_range<size_t>& range)
[this, min_overlap, line_width](const tbb::blocked_range<size_t>& range)
{
for (size_t layer_id = range.begin(); layer_id < range.end(); ++layer_id) {
Layer& layer = *m_layers[layer_id];
Layer& lower_layer = *layer.lower_layer;
ExPolygons overhangs = diff_ex(layer.lslices, offset_ex(lower_layer.lslices, scale_(min_overlap)));
layer.loverhangs = std::move(offset2_ex(overhangs, -0.1f * scale_(m_config.line_width), 0.1f * scale_(m_config.line_width)));
layer.loverhangs = std::move(offset2_ex(overhangs, -0.1f * scale_(line_width), 0.1f * scale_(line_width)));
layer.loverhangs_bbox = get_extents(layer.loverhangs);
}
});
this->set_done(posDetectOverhangsForLift);
}
}
@ -495,10 +499,10 @@ void PrintObject::generate_support_material()
void PrintObject::simplify_extrusion_path()
{
if (this->set_started(posSimplifyWall)) {
if (this->set_started(posSimplifyPath)) {
m_print->set_status(75, L("Optimizing toolpath"));
BOOST_LOG_TRIVIAL(debug) << "Simplify wall extrusion path of object in parallel - start";
//BBS: walls
BOOST_LOG_TRIVIAL(debug) << "Simplify extrusion path of object in parallel - start";
//BBS: infill and walls
tbb::parallel_for(
tbb::blocked_range<size_t>(0, m_layers.size()),
[this](const tbb::blocked_range<size_t>& range) {
@ -510,7 +514,7 @@ void PrintObject::simplify_extrusion_path()
);
m_print->throw_if_canceled();
BOOST_LOG_TRIVIAL(debug) << "Simplify wall extrusion path of object in parallel - end";
this->set_done(posSimplifyWall);
this->set_done(posSimplifyPath);
}
if (this->set_started(posSimplifyInfill)) {
@ -690,8 +694,12 @@ bool PrintObject::invalidate_state_by_config_options(
if ( opt_key == "brim_width"
|| opt_key == "brim_object_gap"
|| opt_key == "brim_type"
|| opt_key == "brim_ears_max_angle"
|| opt_key == "brim_ears_detection_length"
// BBS: brim generation depends on printing speed
|| opt_key == "outer_wall_speed"
|| opt_key == "small_perimeter_speed"
|| opt_key == "small_perimeter_threshold"
|| opt_key == "sparse_infill_speed"
|| opt_key == "inner_wall_speed"
|| opt_key == "support_speed"
@ -709,13 +717,18 @@ bool PrintObject::invalidate_state_by_config_options(
}
} else if (
opt_key == "wall_loops"
|| opt_key == "top_one_wall_type"
|| opt_key == "only_one_wall_top"
|| opt_key == "only_one_wall_first_layer"
|| opt_key == "initial_layer_line_width"
|| opt_key == "inner_wall_line_width"
|| opt_key == "infill_wall_overlap") {
|| opt_key == "infill_wall_overlap"
|| opt_key == "seam_gap"
|| opt_key == "role_based_wipe_speed"
|| opt_key == "wipe_on_loops"
|| opt_key == "wipe_speed") {
steps.emplace_back(posPerimeters);
} else if (opt_key == "gap_infill_speed" || opt_key == "filter_out_gap_fill") {
} else if (opt_key == "gap_infill_speed"
|| opt_key == "filter_out_gap_fill" ) {
// Return true if gap-fill speed has changed from zero value to non-zero or from non-zero value to zero.
auto is_gap_fill_changed_state_due_to_speed = [&opt_key, &old_config, &new_config]() -> bool {
if (opt_key == "gap_infill_speed") {
@ -729,9 +742,9 @@ bool PrintObject::invalidate_state_by_config_options(
};
// Filtering of unprintable regions in multi-material segmentation depends on if gap-fill is enabled or not.
// So step posSlice is invalidated when gap-fill was enabled/disabled by option "gap_fill_enabled" or by
// So step posSlice is invalidated when gap-fill was enabled/disabled by option "filter_out_gap_fill" or by
// changing "gap_infill_speed" to force recomputation of the multi-material segmentation.
if (this->is_mm_painted() && ((opt_key == "gap_infill_speed" || opt_key == "filter_out_gap_fill") && is_gap_fill_changed_state_due_to_speed()))
if (this->is_mm_painted() && (opt_key == "filter_out_gap_fill" && (opt_key == "gap_infill_speed" && is_gap_fill_changed_state_due_to_speed())))
steps.emplace_back(posSlice);
steps.emplace_back(posPerimeters);
} else if (
@ -739,14 +752,24 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "raft_layers"
|| opt_key == "raft_contact_distance"
|| opt_key == "slice_closing_radius"
|| opt_key == "slicing_mode") {
|| opt_key == "slicing_mode"
|| opt_key == "make_overhang_printable"
|| opt_key == "make_overhang_printable_angle"
|| opt_key == "make_overhang_printable_hole_size") {
steps.emplace_back(posSlice);
} else if (
opt_key == "elefant_foot_compensation"
|| opt_key == "support_top_z_distance"
|| opt_key == "support_bottom_z_distance"
|| opt_key == "xy_hole_compensation"
|| opt_key == "xy_contour_compensation") {
|| opt_key == "xy_contour_compensation"
//BBS: [Arthur] the following params affect bottomBridge surface type detection
|| opt_key == "support_type"
|| opt_key == "bridge_no_support"
|| opt_key == "max_bridge_length"
|| opt_key == "support_interface_top_layers"
|| opt_key == "support_critical_regions_only"
) {
steps.emplace_back(posSlice);
} else if (opt_key == "enable_support") {
steps.emplace_back(posSupportMaterial);
@ -786,10 +809,12 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "bridge_no_support"
|| opt_key == "max_bridge_length"
|| opt_key == "initial_layer_line_width"
|| opt_key == "tree_support_adaptive_layer_height"
|| opt_key == "tree_support_auto_brim"
|| opt_key == "tree_support_brim_width"
|| opt_key == "tree_support_branch_distance"
|| opt_key == "tree_support_branch_diameter"
|| opt_key == "tree_support_branch_angle"
|| opt_key == "tree_support_brim_width"
|| opt_key == "tree_support_wall_count") {
steps.emplace_back(posSupportMaterial);
} else if (
@ -822,19 +847,21 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "sparse_infill_filament"
|| opt_key == "solid_infill_filament"
|| opt_key == "sparse_infill_line_width"
|| opt_key == "infill_direction"
|| opt_key == "ensure_vertical_shell_thickness"
|| opt_key == "bridge_angle"
//BBS
|| opt_key == "internal_bridge_support_thickness") {
|| opt_key == "internal_bridge_support_thickness"
|| opt_key == "bridge_density") {
steps.emplace_back(posPrepareInfill);
} else if (
opt_key == "top_surface_pattern"
|| opt_key == "bottom_surface_pattern"
|| opt_key == "internal_solid_infill_pattern"
|| opt_key == "external_fill_link_max_length"
|| opt_key == "infill_direction"
|| opt_key == "sparse_infill_anchor"
|| opt_key == "sparse_infill_anchor_max"
|| opt_key == "sparse_infill_pattern"
|| opt_key == "infill_anchor"
|| opt_key == "infill_anchor_max"
|| opt_key == "top_surface_line_width"
|| opt_key == "initial_layer_line_width") {
steps.emplace_back(posInfill);
@ -871,7 +898,9 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "detect_overhang_wall"
//BBS
|| opt_key == "enable_overhang_speed"
|| opt_key == "detect_thin_wall") {
|| opt_key == "detect_thin_wall"
|| opt_key == "precise_outer_wall"
|| opt_key == "overhang_speed_classic") {
steps.emplace_back(posPerimeters);
steps.emplace_back(posSupportMaterial);
} else if (opt_key == "bridge_flow") {
@ -893,8 +922,6 @@ bool PrintObject::invalidate_state_by_config_options(
steps.emplace_back(posSlice);
} else if (
opt_key == "seam_position"
|| opt_key == "seam_gap"
|| opt_key == "wipe_speed"
|| opt_key == "support_speed"
|| opt_key == "support_interface_speed"
|| opt_key == "overhang_1_4_speed"
@ -902,7 +929,10 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "overhang_3_4_speed"
|| opt_key == "overhang_4_4_speed"
|| opt_key == "bridge_speed"
|| opt_key == "internal_bridge_speed"
|| opt_key == "outer_wall_speed"
|| opt_key == "small_perimeter_speed"
|| opt_key == "small_perimeter_threshold"
|| opt_key == "sparse_infill_speed"
|| opt_key == "inner_wall_speed"
|| opt_key == "internal_solid_infill_speed"
@ -933,15 +963,15 @@ bool PrintObject::invalidate_step(PrintObjectStep step)
// propagate to dependent steps
if (step == posPerimeters) {
invalidated |= this->invalidate_steps({ posPrepareInfill, posInfill, posIroning, posSimplifyWall, posSimplifyInfill });
invalidated |= this->invalidate_steps({ posPrepareInfill, posInfill, posIroning, posSimplifyPath, posSimplifyInfill });
invalidated |= m_print->invalidate_steps({ psSkirtBrim });
} else if (step == posPrepareInfill) {
invalidated |= this->invalidate_steps({ posInfill, posIroning, posSimplifyWall, posSimplifyInfill });
invalidated |= this->invalidate_steps({ posInfill, posIroning, posSimplifyPath, posSimplifyInfill });
} else if (step == posInfill) {
invalidated |= this->invalidate_steps({ posIroning, posSimplifyInfill });
invalidated |= m_print->invalidate_steps({ psSkirtBrim });
} else if (step == posSlice) {
invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posIroning, posSupportMaterial, posSimplifyWall, posSimplifyInfill });
invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posIroning, posSupportMaterial, posSimplifyPath, posSimplifyInfill });
invalidated |= m_print->invalidate_steps({ psSkirtBrim });
m_slicing_params.valid = false;
} else if (step == posSupportMaterial) {
@ -2616,6 +2646,7 @@ SupportNecessaryType PrintObject::is_support_necessary()
#if 0
double threshold_rad = (m_config.support_threshold_angle.value < EPSILON ? 30 : m_config.support_threshold_angle.value + 1) * M_PI / 180.;
int enforce_support_layers = m_config.enforce_support_layers;
// not fixing in extrusion width % PR b/c never called
const coordf_t extrusion_width = m_config.line_width.value;
const coordf_t extrusion_width_scaled = scale_(extrusion_width);
float max_bridge_length = scale_(m_config.max_bridge_length.value);

View file

@ -164,27 +164,27 @@ SlicingParameters SlicingParameters::create_from_config(
// Convert layer_config_ranges to layer_height_profile. Both are referenced to z=0, meaning the raft layers are not accounted for
// in the height profile and the printed object may be lifted by the raft thickness at the time of the G-code generation.
std::vector<coordf_t> layer_height_profile_from_ranges(
const SlicingParameters& slicing_params,
const t_layer_config_ranges& layer_config_ranges)
const SlicingParameters &slicing_params,
const t_layer_config_ranges &layer_config_ranges)
{
// 1) If there are any height ranges, trim one by the other to make them non-overlapping. Insert the 1st layer if fixed.
std::vector<std::pair<t_layer_height_range, coordf_t>> ranges_non_overlapping;
std::vector<std::pair<t_layer_height_range,coordf_t>> ranges_non_overlapping;
ranges_non_overlapping.reserve(layer_config_ranges.size() * 4);
if (slicing_params.first_object_layer_height_fixed())
ranges_non_overlapping.push_back(std::pair<t_layer_height_range, coordf_t>(
t_layer_height_range(0., slicing_params.first_object_layer_height),
ranges_non_overlapping.push_back(std::pair<t_layer_height_range,coordf_t>(
t_layer_height_range(0., slicing_params.first_object_layer_height),
slicing_params.first_object_layer_height));
// The height ranges are sorted lexicographically by low / high layer boundaries.
for (t_layer_config_ranges::const_iterator it_range = layer_config_ranges.begin(); it_range != layer_config_ranges.end(); ++it_range) {
for (t_layer_config_ranges::const_iterator it_range = layer_config_ranges.begin(); it_range != layer_config_ranges.end(); ++ it_range) {
coordf_t lo = it_range->first.first;
coordf_t hi = std::min(it_range->first.second, slicing_params.object_print_z_height());
coordf_t height = it_range->second.option("layer_height")->getFloat();
if (!ranges_non_overlapping.empty())
if (! ranges_non_overlapping.empty())
// Trim current low with the last high.
lo = std::max(lo, ranges_non_overlapping.back().first.second);
if (lo + EPSILON < hi)
// Ignore too narrow ranges.
ranges_non_overlapping.push_back(std::pair<t_layer_height_range, coordf_t>(t_layer_height_range(lo, hi), height));
ranges_non_overlapping.push_back(std::pair<t_layer_height_range,coordf_t>(t_layer_height_range(lo, hi), height));
}
// 2) Convert the trimmed ranges to a height profile, fill in the undefined intervals between z=0 and z=slicing_params.object_print_z_max()
@ -233,7 +233,7 @@ std::vector<coordf_t> layer_height_profile_from_ranges(
lh_append(slicing_params.object_print_z_height(), slicing_params.layer_height);
}
return layer_height_profile;
return layer_height_profile;
}
// Based on the work of @platsch

View file

@ -25,7 +25,7 @@
#define TAU (2.0 * M_PI)
#define NO_INDEX (std::numeric_limits<unsigned int>::max())
//#define SUPPORT_TREE_DEBUG_TO_SVG
// #define SUPPORT_TREE_DEBUG_TO_SVG
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
#include "nlohmann/json.hpp"
@ -687,12 +687,12 @@ TreeSupport::TreeSupport(PrintObject& object, const SlicingParameters &slicing_p
m_object_config->support_interface_pattern == smipConcentric ?
ipConcentric :
(m_support_params.interface_density > 0.95 ? ipRectilinear : ipSupportBase);
m_support_params.support_extrusion_width = m_object_config->support_line_width.value > 0 ? m_object_config->support_line_width : m_object_config->line_width;
// Check if set to zero, use default if so.
if (m_support_params.support_extrusion_width <= 0.0) {
const auto nozzle_diameter = object.print()->config().nozzle_diameter.get_at(object.config().support_interface_filament - 1);
m_support_params.support_extrusion_width = Flow::auto_extrusion_width(FlowRole::frSupportMaterial, (float)nozzle_diameter);
}
const auto nozzle_diameter = object.print()->config().nozzle_diameter.get_at(object.config().support_interface_filament-1);
const coordf_t extrusion_width = m_object_config->line_width.get_abs_value(nozzle_diameter);
const coordf_t support_extrusion_width = m_object_config->support_line_width.get_abs_value(nozzle_diameter);
m_support_params.support_extrusion_width = support_extrusion_width > 0 ? support_extrusion_width : extrusion_width;
is_slim = is_tree_slim(support_type, support_style);
is_strong = is_tree(support_type) && support_style == smsTreeStrong;
MAX_BRANCH_RADIUS = 10.0;
@ -726,7 +726,8 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
const PrintObjectConfig& config = m_object->config();
SupportType stype = support_type;
const coordf_t radius_sample_resolution = g_config_tree_support_collision_resolution;
const coordf_t extrusion_width = config.line_width.value;
const double nozzle_diameter = m_object->print()->config().nozzle_diameter.get_at(0);
const coordf_t extrusion_width = config.get_abs_value("line_width", nozzle_diameter);
const coordf_t extrusion_width_scaled = scale_(extrusion_width);
const coordf_t max_bridge_length = scale_(config.max_bridge_length.value);
const bool bridge_no_support = max_bridge_length > 0;
@ -1404,6 +1405,10 @@ void TreeSupport::generate_toolpaths()
coordf_t layer_height = object_config.layer_height.value;
const size_t wall_count = object_config.tree_support_wall_count.value;
// Check if set to zero, use default if so.
if (support_extrusion_width <= 0.0)
support_extrusion_width = Flow::auto_extrusion_width(FlowRole::frSupportMaterial, (float)nozzle_diameter);
// coconut: use same intensity settings as SupportMaterial.cpp
auto m_support_material_interface_flow = support_material_interface_flow(m_object, float(m_slicing_params.layer_height));
coordf_t interface_spacing = object_config.support_interface_spacing.value + m_support_material_interface_flow.spacing();
@ -1903,10 +1908,10 @@ void TreeSupport::generate()
smooth_nodes(contact_nodes);
#if !USE_PLAN_LAYER_HEIGHTS
// Adjust support layer heights
adjust_layer_heights(contact_nodes);
#endif
if (!m_object->config().tree_support_adaptive_layer_height)
// Adjust support layer heights
adjust_layer_heights(contact_nodes);
//Generate support areas.
profiler.stage_start(STAGE_DRAW_CIRCLES);
@ -2111,11 +2116,13 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
const size_t top_interface_layers = config.support_interface_top_layers.value;
const size_t bottom_interface_layers = config.support_interface_bottom_layers.value;
const double diameter_angle_scale_factor = tan(tree_support_branch_diameter_angle * M_PI / 180.);// * layer_height / branch_radius; //Scale factor per layer to produce the desired angle.
const double nozzle_diameter = m_object->print()->config().nozzle_diameter.get_at(0);
const coordf_t line_width = config.get_abs_value("support_line_width", nozzle_diameter);
const coordf_t line_width_scaled = scale_(line_width);
const bool with_lightning_infill = m_support_params.base_fill_pattern == ipLightning;
coordf_t support_extrusion_width = m_support_params.support_extrusion_width;
const coordf_t line_width_scaled = scale_(support_extrusion_width);
const float tree_brim_width = config.tree_support_brim_width.value;
const size_t wall_count = config.tree_support_wall_count.value;
const PrintObjectConfig& object_config = m_object->config();
BOOST_LOG_TRIVIAL(info) << "draw_circles for object: " << m_object->model_object()->name;
@ -2205,7 +2212,11 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
}
}
if (layer_nr == 0 && m_raft_layers == 0) {
double brim_width = tree_brim_width > 0 ? tree_brim_width : layers_to_top * layer_height / (scale * branch_radius) * 0.5;
double brim_width =
config.tree_support_auto_brim
? layers_to_top * layer_height /
(scale * branch_radius) * 0.5
: config.tree_support_brim_width;
circle = offset(circle, scale_(brim_width))[0];
}
area.emplace_back(ExPolygon(circle));
@ -2290,7 +2301,7 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
if (SQUARE_SUPPORT) {
// simplify support contours
ExPolygons base_areas_simplified;
for (auto &area : base_areas) { area.simplify(scale_(support_extrusion_width / 2), &base_areas_simplified); }
for (auto &area : base_areas) { area.simplify(scale_(line_width / 2), &base_areas_simplified); }
base_areas = std::move(base_areas_simplified);
}
//Subtract support floors. We can only compute floor_areas here instead of with roof_areas,
@ -2569,12 +2580,14 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
const size_t bottom_interface_layers = config.support_interface_bottom_layers.value;
const size_t top_interface_layers = config.support_interface_top_layers.value;
float DO_NOT_MOVER_UNDER_MM = is_slim ? 0 : 5; // do not move contact points under 5mm
const auto nozzle_diameter = m_object->print()->config().nozzle_diameter.get_at(m_object->config().support_interface_filament-1);
const auto support_line_width = config.support_line_width.get_abs_value(nozzle_diameter);
auto get_branch_angle = [this,&config](coordf_t radius) {
if (config.tree_support_branch_angle.value < 30.0) return config.tree_support_branch_angle.value;
return (radius - MIN_BRANCH_RADIUS) / (MAX_BRANCH_RADIUS - MIN_BRANCH_RADIUS) * (config.tree_support_branch_angle.value - 30.0) + 30.0;
};
auto get_max_move_dist = [this, &config, branch_radius, tip_layers, diameter_angle_scale_factor, wall_count, support_extrusion_width](const Node *node, int power = 1) {
auto get_max_move_dist = [this, &config, branch_radius, tip_layers, diameter_angle_scale_factor, wall_count, support_extrusion_width, support_line_width](const Node *node, int power = 1) {
double move_dist = node->max_move_dist;
if (node->max_move_dist == 0) {
if (node->radius == 0) node->radius = calc_branch_radius(branch_radius, node->dist_mm_to_top, diameter_angle_scale_factor);
@ -2582,7 +2595,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
if (angle > 30.0 && node->radius > MIN_BRANCH_RADIUS)
angle = (node->radius - MIN_BRANCH_RADIUS) / (MAX_BRANCH_RADIUS - MIN_BRANCH_RADIUS) * (config.tree_support_branch_angle.value - 30.0) + 30.0;
double tan_angle = tan(angle * M_PI / 180);
int wall_count_ = node->radius > 2 * support_extrusion_width ? wall_count : 1;
int wall_count_ = node->radius > 2 * support_line_width ? wall_count : 1;
node->max_move_dist = (angle < 90) ? (coordf_t) (tan_angle * node->height) * wall_count_ : std::numeric_limits<coordf_t>::max();
node->max_move_dist = std::min(node->max_move_dist, support_extrusion_width);
move_dist = node->max_move_dist;
@ -3062,7 +3075,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
}
}
}
BOOST_LOG_TRIVIAL(debug) << "after m_avoidance_cache.size()=" << m_ts_data->m_avoidance_cache.size();
for (Node *node : to_free_node_set)
@ -3269,7 +3282,7 @@ std::vector<LayerHeightData> TreeSupport::plan_layer_heights(std::vector<std::ve
std::vector<LayerHeightData> layer_heights(contact_nodes.size());
std::vector<int> bounds;
if (!USE_PLAN_LAYER_HEIGHTS || layer_height == max_layer_height || !print_config.independent_support_layer_height) {
if (!config.tree_support_adaptive_layer_height || layer_height == max_layer_height || !print_config.independent_support_layer_height) {
for (int layer_nr = 0; layer_nr < contact_nodes.size(); layer_nr++) {
layer_heights[layer_nr] = {m_object->get_layer(layer_nr)->print_z, m_object->get_layer(layer_nr)->height, layer_nr > 0 ? size_t(layer_nr - 1) : 0};
}

View file

@ -9,6 +9,10 @@
#include <boost/system/error_code.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/date_time.hpp>
#include "boost/date_time/posix_time/ptime.hpp"
#include <openssl/md5.h>
#include "libslic3r.h"
@ -554,6 +558,21 @@ inline std::string get_bbl_monitor_time_dhm(float time_in_secs)
return buffer;
}
inline std::string get_bbl_monitor_end_time_dhm(float time_in_secs)
{
if (time_in_secs == 0.0f)
return {};
std::stringstream stream;
boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
auto endTime = now + boost::posix_time::seconds(static_cast<int>(time_in_secs));
auto facet = new boost::posix_time::time_facet("%H:%M");//%Y-%m-%d %H:%M:%S
stream.imbue(std::locale(std::locale::classic(), facet));
stream << endTime;
return stream.str();
}
inline std::string get_bbl_remain_time_dhms(float time_in_secs)
{
int days = (int) (time_in_secs / 86400.0f);
@ -591,6 +610,9 @@ inline std::string filter_characters(const std::string& str, const std::string&
return filteredStr;
}
void copy_directory_recursively(const boost::filesystem::path &source, const boost::filesystem::path &target);
} // namespace Slic3r
#if WIN32

View file

@ -1,23 +1,23 @@
#include "Calib.hpp"
#include "calib.hpp"
#include "BoundingBox.hpp"
#include "Config.hpp"
#include "Model.hpp"
#include "GCode.hpp"
#include <cmath>
namespace Slic3r {
float CalibPressureAdvance::find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height, int filament_idx)
{
const double general_suggested_min_speed = 100.0;
double filament_max_volumetric_speed = config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->get_at(0);
Flow pattern_line = Flow(line_width, layer_height, config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0));
auto pa_speed = std::min(std::max(general_suggested_min_speed, config.option<ConfigOptionFloat>("outer_wall_speed")->value),
filament_max_volumetric_speed / pattern_line.mm3_per_mm());
// Calculate the optimal Pressure Advance speed
float CalibPressureAdvance::find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height,
int filament_idx) {
const double general_suggested_min_speed = 100.0;
double filament_max_volumetric_speed = config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->get_at(0);
Flow pattern_line = Flow(line_width, layer_height, config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0));
auto pa_speed = std::min(std::max(general_suggested_min_speed,config.option<ConfigOptionFloat>("outer_wall_speed")->value), filament_max_volumetric_speed / pattern_line.mm3_per_mm());
return std::floor(pa_speed);
}
std::string CalibPressureAdvance::move_to(Vec2d pt, GCodeWriter &writer, std::string comment)
std::string CalibPressureAdvance::move_to(Vec2d pt, GCodeWriter& writer, std::string comment)
{
std::stringstream gcode;
@ -27,12 +27,18 @@ std::string CalibPressureAdvance::move_to(Vec2d pt, GCodeWriter &writer, std::st
m_last_pos = Vec3d(pt.x(), pt.y(), 0);
return gcode.str();
return gcode.str();
}
double CalibPressureAdvance::e_per_mm(double line_width, double layer_height, float nozzle_diameter, float filament_diameter, float print_flow_ratio) const
double CalibPressureAdvance::e_per_mm(
double line_width,
double layer_height,
float nozzle_diameter,
float filament_diameter,
float print_flow_ratio
) const
{
const Flow line_flow = Flow(line_width, layer_height, nozzle_diameter);
const Flow line_flow = Flow(line_width, layer_height, nozzle_diameter);
const double filament_area = M_PI * std::pow(filament_diameter / 2, 2);
return line_flow.mm3_per_mm() / filament_area * print_flow_ratio;
@ -48,12 +54,19 @@ std::string CalibPressureAdvance::convert_number_to_string(double num) const
}
std::string CalibPressureAdvance::draw_digit(
double startx, double starty, char c, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, GCodeWriter &writer)
double startx,
double starty,
char c,
CalibPressureAdvance::DrawDigitMode mode,
double line_width,
double e_per_mm,
GCodeWriter& writer
)
{
const double len = m_digit_segment_len;
const double gap = line_width / 2.0;
const auto dE = e_per_mm * len;
const auto dE = e_per_mm * len;
const auto two_dE = dE * 2;
Vec2d p0, p1, p2, p3, p4, p5;
@ -66,33 +79,33 @@ std::string CalibPressureAdvance::draw_digit(
// | | |
// | | |
// 0-------3-------4
p0 = Vec2d(startx, starty);
p0 = Vec2d(startx, starty);
p0_5 = Vec2d(startx, starty + len / 2);
p1 = Vec2d(startx, starty + len);
p2 = Vec2d(startx + len, starty + len);
p3 = Vec2d(startx + len, starty);
p4 = Vec2d(startx + len * 2, starty);
p1 = Vec2d(startx, starty + len);
p2 = Vec2d(startx + len, starty + len);
p3 = Vec2d(startx + len, starty);
p4 = Vec2d(startx + len * 2, starty);
p4_5 = Vec2d(startx + len * 2, starty + len / 2);
p5 = Vec2d(startx + len * 2, starty + len);
p5 = Vec2d(startx + len * 2, starty + len);
gap_p0_toward_p3 = p0 + Vec2d(gap, 0);
gap_p2_toward_p3 = p2 + Vec2d(0, gap);
dot_direction = Vec2d(-len / 2, 0);
} else {
// 0-------1
// 0-------1
// | |
// 3-------2
// | |
// 4-------5
p0 = Vec2d(startx, starty);
p0 = Vec2d(startx, starty);
p0_5 = Vec2d(startx + len / 2, starty);
p1 = Vec2d(startx + len, starty);
p2 = Vec2d(startx + len, starty - len);
p3 = Vec2d(startx, starty - len);
p4 = Vec2d(startx, starty - len * 2);
p1 = Vec2d(startx + len, starty);
p2 = Vec2d(startx + len, starty - len);
p3 = Vec2d(startx, starty - len);
p4 = Vec2d(startx, starty - len * 2);
p4_5 = Vec2d(startx + len / 2, starty - len * 2);
p5 = Vec2d(startx + len, starty - len * 2);
p5 = Vec2d(startx + len, starty - len * 2);
gap_p0_toward_p3 = p0 - Vec2d(0, gap);
gap_p2_toward_p3 = p2 - Vec2d(gap, 0);
@ -178,71 +191,120 @@ std::string CalibPressureAdvance::draw_digit(
gcode << move_to(p4_5, writer, "Glyph: .");
gcode << writer.extrude_to_xy(p4_5 + dot_direction, dE);
break;
default: break;
default:
break;
}
return gcode.str();
}
std::string CalibPressureAdvance::draw_number(
double startx, double starty, double value, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, double speed, GCodeWriter &writer)
double startx,
double starty,
double value,
CalibPressureAdvance::DrawDigitMode mode,
double line_width,
double e_per_mm,
double speed,
GCodeWriter& writer
)
{
auto sNumber = convert_number_to_string(value);
auto sNumber = convert_number_to_string(value);
std::stringstream gcode;
gcode << writer.set_speed(speed);
for (std::string::size_type i = 0; i < sNumber.length(); ++i) {
if (i > m_max_number_len) { break; }
if (i > m_max_number_len) {
break;
}
switch (mode) {
case DrawDigitMode::Bottom_To_Top: gcode << draw_digit(startx, starty + i * number_spacing(), sNumber[i], mode, line_width, e_per_mm, writer); break;
default: gcode << draw_digit(startx + i * number_spacing(), starty, sNumber[i], mode, line_width, e_per_mm, writer);
case DrawDigitMode::Bottom_To_Top:
gcode << draw_digit(
startx,
starty + i * number_spacing(),
sNumber[i],
mode,
line_width,
e_per_mm,
writer
);
break;
default:
gcode << draw_digit(
startx + i * number_spacing(),
starty,
sNumber[i],
mode,
line_width,
e_per_mm,
writer
);
}
}
return gcode.str();
}
CalibPressureAdvanceLine::CalibPressureAdvanceLine(GCode *gcodegen)
: mp_gcodegen(gcodegen)
, m_nozzle_diameter(gcodegen->config().nozzle_diameter.get_at(0))
{
}
std::string CalibPressureAdvanceLine::generate_test(double start_pa /*= 0*/, double step_pa /*= 0.002*/, int count /*= 10*/)
{
BoundingBoxf bed_ext = get_extents(mp_gcodegen->config().printable_area.values);
if (is_delta()) { CalibPressureAdvanceLine::delta_scale_bed_ext(bed_ext); }
if (is_delta()) {
CalibPressureAdvanceLine::delta_scale_bed_ext(bed_ext);
}
auto bed_sizes = mp_gcodegen->config().printable_area.values;
const auto &w = bed_ext.size().x();
const auto &h = bed_ext.size().y();
count = std::min(count, int((h - 10) / m_space_y));
auto bed_sizes = mp_gcodegen->config().printable_area.values;
const auto &w = bed_ext.size().x();
const auto &h = bed_ext.size().y();
count = std::min(count, int((h - 10) / m_space_y));
m_length_long = 40 + std::min(w - 120.0, 0.0);
auto startx = (w - m_length_short * 2 - m_length_long - 20) / 2;
auto starty = (h - count * m_space_y) / 2;
if (is_delta()) { CalibPressureAdvanceLine::delta_modify_start(startx, starty, count); }
if (is_delta()) {
CalibPressureAdvanceLine::delta_modify_start(startx, starty, count);
}
return print_pa_lines(startx, starty, start_pa, step_pa, count);
}
bool CalibPressureAdvanceLine::is_delta() const { return mp_gcodegen->config().printable_area.values.size() > 4; }
bool CalibPressureAdvanceLine::is_delta() const
{
return mp_gcodegen->config().printable_area.values.size() > 4;
}
std::string CalibPressureAdvanceLine::print_pa_lines(double start_x, double start_y, double start_pa, double step_pa, int num)
{
auto & writer = mp_gcodegen->writer();
const auto &config = mp_gcodegen->config();
auto& writer = mp_gcodegen->writer();
const auto& config = mp_gcodegen->config();
const auto filament_diameter = config.filament_diameter.get_at(0);
const auto print_flow_ratio = config.print_flow_ratio;
const auto print_flow_ratio = config.print_flow_ratio;
const double e_per_mm = CalibPressureAdvance::e_per_mm(m_line_width, m_height_layer, m_nozzle_diameter, filament_diameter, print_flow_ratio);
const double thin_e_per_mm = CalibPressureAdvance::e_per_mm(m_thin_line_width, m_height_layer, m_nozzle_diameter, filament_diameter, print_flow_ratio);
const double number_e_per_mm = CalibPressureAdvance::e_per_mm(m_number_line_width, m_height_layer, m_nozzle_diameter, filament_diameter, print_flow_ratio);
const double e_per_mm = CalibPressureAdvance::e_per_mm(
m_line_width,
m_height_layer,
m_nozzle_diameter,
filament_diameter,
print_flow_ratio
);
const double thin_e_per_mm = CalibPressureAdvance::e_per_mm(
m_thin_line_width,
m_height_layer,
m_nozzle_diameter,
filament_diameter,
print_flow_ratio
);
const double number_e_per_mm = CalibPressureAdvance::e_per_mm(
m_number_line_width,
m_height_layer,
m_nozzle_diameter,
filament_diameter,
print_flow_ratio
);
const double fast = CalibPressureAdvance::speed_adjust(m_fast_speed);
const double slow = CalibPressureAdvance::speed_adjust(m_slow_speed);
const double fast = CalibPressureAdvance::speed_adjust(m_fast_speed);
const double slow = CalibPressureAdvance::speed_adjust(m_slow_speed);
std::stringstream gcode;
gcode << mp_gcodegen->writer().travel_to_z(m_height_layer);
double y_pos = start_y;
@ -274,28 +336,47 @@ std::string CalibPressureAdvanceLine::print_pa_lines(double start_x, double star
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * m_space_y + 2), thin_e_per_mm * 7);
for (int i = 0; i < num; i += 2) {
gcode << draw_number(start_x + m_length_short + m_length_long + m_length_short + 3, y_pos + i * m_space_y + m_space_y / 2, start_pa + i * step_pa, m_draw_digit_mode,
m_number_line_width, number_e_per_mm, 3600, writer);
gcode << draw_number(
start_x + m_length_short + m_length_long + m_length_short + 3,
y_pos + i * m_space_y + m_space_y / 2,
start_pa + i * step_pa,
m_draw_digit_mode,
m_number_line_width,
number_e_per_mm,
3600,
writer
);
}
}
return gcode.str();
}
void CalibPressureAdvanceLine::delta_modify_start(double &startx, double &starty, int count)
void CalibPressureAdvanceLine::delta_modify_start(double& startx, double& starty, int count)
{
startx = -startx;
starty = -(count * m_space_y) / 2;
}
CalibPressureAdvancePattern::CalibPressureAdvancePattern(const Calib_Params &params, const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin)
: m_params(params)
CalibPressureAdvancePattern::CalibPressureAdvancePattern(
const Calib_Params& params,
const DynamicPrintConfig& config,
bool is_bbl_machine,
Model& model,
const Vec3d& origin
) :
m_params(params)
{
this->m_draw_digit_mode = DrawDigitMode::Bottom_To_Top;
refresh_setup(config, is_bbl_machine, model, origin);
};
void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin)
void CalibPressureAdvancePattern::generate_custom_gcodes(
const DynamicPrintConfig& config,
bool is_bbl_machine,
Model& model,
const Vec3d& origin
)
{
std::stringstream gcode;
gcode << "; start pressure advance pattern for layer\n";
@ -309,18 +390,29 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfi
const DrawBoxOptArgs default_box_opt_args(*this);
// create anchoring frame
gcode << draw_box(m_starting_point.x(), m_starting_point.y(), print_size_x(), frame_size_y(), default_box_opt_args);
gcode << draw_box(
m_starting_point.x(),
m_starting_point.y(),
print_size_x(),
frame_size_y(),
default_box_opt_args
);
// create tab for numbers
DrawBoxOptArgs draw_box_opt_args = default_box_opt_args;
draw_box_opt_args.is_filled = true;
draw_box_opt_args.is_filled = true;
draw_box_opt_args.num_perimeters = wall_count();
gcode << draw_box(m_starting_point.x(), m_starting_point.y() + frame_size_y() + line_spacing_first_layer(), glyph_tab_max_x() - m_starting_point.x(),
max_numbering_height() + line_spacing_first_layer() + m_glyph_padding_vertical * 2, draw_box_opt_args);
gcode << draw_box(
m_starting_point.x(),
m_starting_point.y() + frame_size_y() + line_spacing_first_layer(),
glyph_tab_max_x() - m_starting_point.x(),
max_numbering_height() + line_spacing_first_layer() + m_glyph_padding_vertical * 2,
draw_box_opt_args
);
std::vector<CustomGCode::Item> gcode_items;
const DrawLineOptArgs default_line_opt_args(*this);
const int num_patterns = get_num_patterns(); // "cache" for use in loops
const DrawLineOptArgs default_line_opt_args(*this);
const int num_patterns = get_num_patterns(); // "cache" for use in loops
// draw pressure advance pattern
for (int i = 0; i < m_num_layers; ++i) {
@ -328,13 +420,13 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfi
gcode << "; end pressure advance pattern for layer\n";
CustomGCode::Item item;
item.print_z = height_first_layer() + (i - 1) * height_layer();
item.type = CustomGCode::Type::Custom;
item.extra = gcode.str();
item.type = CustomGCode::Type::Custom;
item.extra = gcode.str();
gcode_items.push_back(item);
gcode = std::stringstream(); // reset for next layer contents
gcode << "; start pressure advance pattern for layer\n";
const double layer_height = height_first_layer() + (i * height_layer());
gcode << m_writer.travel_to_z(layer_height, "Move to layer height");
}
@ -343,29 +435,49 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfi
if (i == 1) {
gcode << m_writer.set_pressure_advance(m_params.start);
double number_e_per_mm = e_per_mm(line_width(), height_layer(), m_config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_flow_ratio")->get_at(0));
double number_e_per_mm = e_per_mm(
line_width(),
height_layer(),
m_config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_flow_ratio")->get_at(0)
);
// glyph on every other line
for (int j = 0; j < num_patterns; j += 2) {
gcode << draw_number(glyph_start_x(j), m_starting_point.y() + frame_size_y() + m_glyph_padding_vertical + line_width(), m_params.start + (j * m_params.step),
m_draw_digit_mode, line_width(), number_e_per_mm, speed_first_layer(), m_writer);
gcode << draw_number(
glyph_start_x(j),
m_starting_point.y() + frame_size_y() + m_glyph_padding_vertical + line_width(),
m_params.start + (j * m_params.step),
m_draw_digit_mode,
line_width(),
number_e_per_mm,
speed_first_layer(),
m_writer
);
}
}
DrawLineOptArgs draw_line_opt_args = default_line_opt_args;
double to_x = m_starting_point.x() + pattern_shift();
double to_y = m_starting_point.y();
double to_x = m_starting_point.x() + pattern_shift();
double to_y = m_starting_point.y();
double side_length = m_wall_side_length;
// shrink first layer to fit inside frame
if (i == 0) {
double shrink = (line_spacing_first_layer() * (wall_count() - 1) + (line_width_first_layer() * (1 - m_encroachment))) / std::sin(to_radians(m_corner_angle) / 2);
side_length = m_wall_side_length - shrink;
double shrink =
(
line_spacing_first_layer() * (wall_count() - 1) +
(line_width_first_layer() * (1 - m_encroachment))
) / std::sin(to_radians(m_corner_angle) / 2)
;
side_length = m_wall_side_length - shrink;
to_x += shrink * std::sin(to_radians(90) - to_radians(m_corner_angle) / 2);
to_y += line_spacing_first_layer() * (wall_count() - 1) + (line_width_first_layer() * (1 - m_encroachment));
to_y +=
line_spacing_first_layer() * (wall_count() - 1) +
(line_width_first_layer() * (1 - m_encroachment))
;
}
double initial_x = to_x;
@ -380,12 +492,12 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfi
for (int k = 0; k < wall_count(); ++k) {
to_x += std::cos(to_radians(m_corner_angle) / 2) * side_length;
to_y += std::sin(to_radians(m_corner_angle) / 2) * side_length;
draw_line_opt_args = default_line_opt_args;
draw_line_opt_args.height = i == 0 ? height_first_layer() : height_layer();
draw_line_opt_args.line_width = line_width(); // don't use line_width_first_layer so results are consistent across all layers
draw_line_opt_args.speed = i == 0 ? speed_adjust(speed_first_layer()) : speed_adjust(speed_perimeter());
draw_line_opt_args.comment = "Print pattern wall";
draw_line_opt_args = default_line_opt_args;
draw_line_opt_args.height = i == 0 ? height_first_layer() : height_layer();
draw_line_opt_args.line_width = line_width(); // don't use line_width_first_layer so results are consistent across all layers
draw_line_opt_args.speed = i == 0 ? speed_adjust(speed_first_layer()) : speed_adjust(speed_perimeter());
draw_line_opt_args.comment = "Print pattern wall";
gcode << draw_line(Vec2d(to_x, to_y), draw_line_opt_args);
to_x -= std::cos(to_radians(m_corner_angle) / 2) * side_length;
@ -418,18 +530,23 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfi
CustomGCode::Item item;
item.print_z = max_layer_z();
item.type = CustomGCode::Type::Custom;
item.extra = gcode.str();
item.type = CustomGCode::Type::Custom;
item.extra = gcode.str();
gcode_items.push_back(item);
CustomGCode::Info info;
info.mode = CustomGCode::Mode::SingleExtruder;
info.mode = CustomGCode::Mode::SingleExtruder;
info.gcodes = gcode_items;
model.plates_custom_gcodes[model.curr_plate_index] = info;
}
void CalibPressureAdvancePattern::refresh_setup(const DynamicPrintConfig &config, bool is_bbl_machine, const Model &model, const Vec3d &origin)
void CalibPressureAdvancePattern::refresh_setup(
const DynamicPrintConfig& config,
bool is_bbl_machine,
const Model& model,
const Vec3d& origin
)
{
m_config = config;
m_config.apply(model.objects.front()->config.get(), true);
@ -441,10 +558,15 @@ void CalibPressureAdvancePattern::refresh_setup(const DynamicPrintConfig &config
_refresh_writer(is_bbl_machine, model, origin);
}
void CalibPressureAdvancePattern::_refresh_starting_point(const Model &model)
void CalibPressureAdvancePattern::_refresh_starting_point(const Model& model)
{
ModelObject * obj = model.objects.front();
BoundingBoxf3 bbox = obj->instance_bounding_box(*obj->instances.front(), false);
ModelObject* obj = model.objects.front();
BoundingBoxf3 bbox =
obj->instance_bounding_box(
*obj->instances.front(),
false
)
;
m_starting_point = Vec3d(bbox.min.x(), bbox.max.y(), 0);
m_starting_point.y() += m_handle_spacing;
@ -455,28 +577,39 @@ void CalibPressureAdvancePattern::_refresh_starting_point(const Model &model)
}
}
void CalibPressureAdvancePattern::_refresh_writer(bool is_bbl_machine, const Model &model, const Vec3d &origin)
void CalibPressureAdvancePattern::_refresh_writer(
bool is_bbl_machine,
const Model& model,
const Vec3d& origin
)
{
PrintConfig print_config;
print_config.apply(m_config, true);
m_writer.apply_print_config(print_config);
m_writer.set_xy_offset(origin(0), origin(1));
//m_writer.set_is_bbl_machine(is_bbl_machine);
m_writer.set_is_bbl_machine(is_bbl_machine);
const unsigned int extruder_id = model.objects.front()->volumes.front()->extruder_id();
m_writer.set_extruders({extruder_id});
m_writer.set_extruders({ extruder_id });
m_writer.set_extruder(extruder_id);
}
std::string CalibPressureAdvancePattern::draw_line(Vec2d to_pt, DrawLineOptArgs opt_args)
std::string CalibPressureAdvancePattern::draw_line(
Vec2d to_pt,
DrawLineOptArgs opt_args
)
{
const double e_per_mm = CalibPressureAdvance::e_per_mm(opt_args.line_width, opt_args.height, m_config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_flow_ratio")->get_at(0));
const double e_per_mm = CalibPressureAdvance::e_per_mm(
opt_args.line_width,
opt_args.height,
m_config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_flow_ratio")->get_at(0)
);
const double length = get_distance(Vec2d(m_last_pos.x(), m_last_pos.y()), to_pt);
auto dE = e_per_mm * length;
auto dE = e_per_mm * length;
std::stringstream gcode;
@ -488,31 +621,40 @@ std::string CalibPressureAdvancePattern::draw_line(Vec2d to_pt, DrawLineOptArgs
return gcode.str();
}
std::string CalibPressureAdvancePattern::draw_box(double min_x, double min_y, double size_x, double size_y, DrawBoxOptArgs opt_args)
std::string CalibPressureAdvancePattern::draw_box(
double min_x,
double min_y,
double size_x,
double size_y,
DrawBoxOptArgs opt_args
)
{
std::stringstream gcode;
double x = min_x;
double y = min_y;
double x = min_x;
double y = min_y;
const double max_x = min_x + size_x;
const double max_y = min_y + size_y;
const double spacing = opt_args.line_width - opt_args.height * (1 - M_PI / 4);
// if number of perims exceeds size of box, reduce it to max
const int max_perimeters = std::min(
// this is the equivalent of number of perims for concentric fill
std::floor(size_x * std::sin(to_radians(45))) / (spacing / std::sin(to_radians(45))),
std::floor(size_y * std::sin(to_radians(45))) / (spacing / std::sin(to_radians(45))));
const int max_perimeters =
std::min(
// this is the equivalent of number of perims for concentric fill
std::floor(size_x * std::sin(to_radians(45))) / (spacing / std::sin(to_radians(45))),
std::floor(size_y * std::sin(to_radians(45))) / (spacing / std::sin(to_radians(45)))
)
;
opt_args.num_perimeters = std::min(opt_args.num_perimeters, max_perimeters);
gcode << move_to(Vec2d(min_x, min_y), m_writer, "Move to box start");
DrawLineOptArgs line_opt_args(*this);
line_opt_args.height = opt_args.height;
line_opt_args.height = opt_args.height;
line_opt_args.line_width = opt_args.line_width;
line_opt_args.speed = opt_args.speed;
line_opt_args.speed = opt_args.speed;
for (int i = 0; i < opt_args.num_perimeters; ++i) {
if (i != 0) { // after first perimeter, step inwards to start next perimeter
@ -538,18 +680,23 @@ std::string CalibPressureAdvancePattern::draw_box(double min_x, double min_y, do
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
if (!opt_args.is_filled) { return gcode.str(); }
if (!opt_args.is_filled) {
return gcode.str();
}
// create box infill
const double spacing_45 = spacing / std::sin(to_radians(45));
const double bound_modifier = (spacing * (opt_args.num_perimeters - 1)) + (opt_args.line_width * (1 - m_encroachment));
const double x_min_bound = min_x + bound_modifier;
const double x_max_bound = max_x - bound_modifier;
const double y_min_bound = min_y + bound_modifier;
const double y_max_bound = max_y - bound_modifier;
const int x_count = std::floor((x_max_bound - x_min_bound) / spacing_45);
const int y_count = std::floor((y_max_bound - y_min_bound) / spacing_45);
const double bound_modifier =
(spacing * (opt_args.num_perimeters - 1)) +
(opt_args.line_width * (1 - m_encroachment))
;
const double x_min_bound = min_x + bound_modifier;
const double x_max_bound = max_x - bound_modifier;
const double y_min_bound = min_y + bound_modifier;
const double y_max_bound = max_y - bound_modifier;
const int x_count = std::floor((x_max_bound - x_min_bound) / spacing_45);
const int y_count = std::floor((y_max_bound - y_min_bound) / spacing_45);
double x_remainder = std::fmod((x_max_bound - x_min_bound), spacing_45);
double y_remainder = std::fmod((y_max_bound - y_min_bound), spacing_45);
@ -559,8 +706,7 @@ std::string CalibPressureAdvancePattern::draw_box(double min_x, double min_y, do
gcode << move_to(Vec2d(x, y), m_writer, "Move to fill start");
for (int i = 0; i < x_count + y_count + (x_remainder + y_remainder >= spacing_45 ? 1 : 0);
++i) { // this isn't the most robust way, but less expensive than finding line intersections
for (int i = 0; i < x_count + y_count + (x_remainder + y_remainder >= spacing_45 ? 1 : 0); ++i) { // this isn't the most robust way, but less expensive than finding line intersections
if (i < std::min(x_count, y_count)) {
if (i % 2 == 0) {
x += spacing_45;
@ -568,7 +714,7 @@ std::string CalibPressureAdvancePattern::draw_box(double min_x, double min_y, do
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right");
y += x - x_min_bound;
x = x_min_bound;
x = x_min_bound;
line_opt_args.comment = "Fill: Print up/left";
gcode << draw_line(Vec2d(x, y), line_opt_args);
} else {
@ -577,7 +723,7 @@ std::string CalibPressureAdvancePattern::draw_box(double min_x, double min_y, do
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step up");
x += y - y_min_bound;
y = y_min_bound;
y = y_min_bound;
line_opt_args.comment = "Fill: Print down/right";
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
@ -590,7 +736,7 @@ std::string CalibPressureAdvancePattern::draw_box(double min_x, double min_y, do
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right");
x -= y_max_bound - y_min_bound;
y = y_max_bound;
y = y_max_bound;
line_opt_args.comment = "Fill: Print up/left";
gcode << draw_line(Vec2d(x, y), line_opt_args);
} else {
@ -602,9 +748,9 @@ std::string CalibPressureAdvancePattern::draw_box(double min_x, double min_y, do
}
y = y_max_bound;
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right");
x += y_max_bound - y_min_bound;
y = y_min_bound;
y = y_min_bound;
line_opt_args.comment = "Fill: Print down/right";
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
@ -646,7 +792,7 @@ std::string CalibPressureAdvancePattern::draw_box(double min_x, double min_y, do
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step up");
x -= y_max_bound - y;
y = y_max_bound;
y = y_max_bound;
line_opt_args.comment = "Fill: Print up/left";
gcode << draw_line(Vec2d(x, y), line_opt_args);
} else {
@ -659,7 +805,7 @@ std::string CalibPressureAdvancePattern::draw_box(double min_x, double min_y, do
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right");
y -= x_max_bound - x;
x = x_max_bound;
x = x_max_bound;
line_opt_args.comment = "Fill: Print down/right";
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
@ -669,17 +815,26 @@ std::string CalibPressureAdvancePattern::draw_box(double min_x, double min_y, do
return gcode.str();
}
double CalibPressureAdvancePattern::get_distance(Vec2d from, Vec2d to) const { return std::hypot((to.x() - from.x()), (to.y() - from.y())); }
double CalibPressureAdvancePattern::get_distance(Vec2d from, Vec2d to) const
{
return std::hypot((to.x() - from.x()), (to.y() - from.y()));
}
double CalibPressureAdvancePattern::object_size_x() const
{
return get_num_patterns() * ((wall_count() - 1) * line_spacing_angle()) + (get_num_patterns() - 1) * (m_pattern_spacing + line_width()) +
std::cos(to_radians(m_corner_angle) / 2) * m_wall_side_length + line_spacing_first_layer() * wall_count();
return get_num_patterns() * ((wall_count() - 1) * line_spacing_angle()) +
(get_num_patterns() - 1) * (m_pattern_spacing + line_width()) +
std::cos(to_radians(m_corner_angle) / 2) * m_wall_side_length +
line_spacing_first_layer() * wall_count()
;
}
double CalibPressureAdvancePattern::object_size_y() const
{
return 2 * (std::sin(to_radians(m_corner_angle) / 2) * m_wall_side_length) + max_numbering_height() + m_glyph_padding_vertical * 2 + line_width_first_layer();
return 2 * (std::sin(to_radians(m_corner_angle) / 2) * m_wall_side_length) +
max_numbering_height() +
m_glyph_padding_vertical * 2 +
line_width_first_layer();
}
double CalibPressureAdvancePattern::glyph_start_x(int pattern_i) const
@ -688,14 +843,16 @@ double CalibPressureAdvancePattern::glyph_start_x(int pattern_i) const
// align glyph's start with first perimeter of specified pattern
double x =
// starting offset
m_starting_point.x() + pattern_shift() +
m_starting_point.x() +
pattern_shift() +
// width of pattern extrusions
pattern_i * (wall_count() - 1) * line_spacing_angle() + // center to center distance of extrusions
pattern_i * line_width() + // endcaps. center to end on either side = 1 line width
pattern_i * line_width() + // endcaps. center to end on either side = 1 line width
// space between each pattern
pattern_i * m_pattern_spacing;
pattern_i * m_pattern_spacing
;
// align to middle of pattern walls
x += wall_count() * line_spacing_angle() / 2;
@ -716,26 +873,35 @@ double CalibPressureAdvancePattern::glyph_length_x() const
double CalibPressureAdvancePattern::glyph_tab_max_x() const
{
// only every other glyph is shown, starting with 1
int num = get_num_patterns();
int max_num = (num % 2 == 0) ? num - 1 : num;
int num = get_num_patterns();
int max_num =
(num % 2 == 0)
? num - 1
: num
;
// padding at end should be same as padding at start
double padding = glyph_start_x(0) - m_starting_point.x();
return glyph_start_x(max_num - 1) + // glyph_start_x is zero-based
(glyph_length_x() - line_width() / 2) + padding;
return
glyph_start_x(max_num - 1) + // glyph_start_x is zero-based
(glyph_length_x() - line_width() / 2) +
padding
;
}
double CalibPressureAdvancePattern::max_numbering_height() const
{
std::string::size_type most_characters = 0;
const int num_patterns = get_num_patterns();
const int num_patterns = get_num_patterns();
// note: only every other number is printed
for (std::string::size_type i = 0; i < num_patterns; i += 2) {
std::string sNumber = convert_number_to_string(m_params.start + (i * m_params.step));
if (sNumber.length() > most_characters) { most_characters = sNumber.length(); }
if (sNumber.length() > most_characters) {
most_characters = sNumber.length();
}
}
most_characters = std::min(most_characters, m_max_number_len);
@ -743,6 +909,12 @@ double CalibPressureAdvancePattern::max_numbering_height() const
return (most_characters * m_digit_segment_len) + ((most_characters - 1) * m_digit_gap_len);
}
double CalibPressureAdvancePattern::pattern_shift() const { return (wall_count() - 1) * line_spacing_first_layer() + line_width_first_layer() + m_glyph_padding_horizontal; }
double CalibPressureAdvancePattern::pattern_shift() const
{
return
(wall_count() - 1) * line_spacing_first_layer() +
line_width_first_layer() +
m_glyph_padding_horizontal
;
}
} // namespace Slic3r

View file

@ -1,5 +1,7 @@
#pragma once
#define calib_pressure_advance_dd
#include "GCode.hpp"
#include "GCodeWriter.hpp"
#include "PrintConfig.hpp"
#include "BoundingBox.hpp"
@ -31,14 +33,14 @@ enum class CalibState {
Finish
};
struct Calib_Params
{
Calib_Params() : mode(CalibMode::Calib_None){}
struct Calib_Params {
Calib_Params() : mode(CalibMode::Calib_None) { };
double start, end, step;
bool print_numbers;
CalibMode mode;
};
class X1CCalibInfos
{
public:
@ -123,93 +125,133 @@ public:
int confidence; // 0: success 1: uncertain 2: failed
};
class CalibPressureAdvance
{
public:
static float find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height, int filament_idx = 0);
class CalibPressureAdvance {
public:
static float find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height,
int filament_idx = 0);
protected:
CalibPressureAdvance() = default;
~CalibPressureAdvance() = default;
protected:
CalibPressureAdvance() =default;
~CalibPressureAdvance() =default;
enum class DrawDigitMode { Left_To_Right, Bottom_To_Top };
enum class DrawDigitMode {
Left_To_Right,
Bottom_To_Top
};
void delta_scale_bed_ext(BoundingBoxf &bed_ext) const { bed_ext.scale(1.0f / 1.41421f); }
void delta_scale_bed_ext(BoundingBoxf& bed_ext) const { bed_ext.scale(1.0f / 1.41421f); }
std::string move_to(Vec2d pt, GCodeWriter &writer, std::string comment = std::string());
double e_per_mm(double line_width, double layer_height, float nozzle_diameter, float filament_diameter, float print_flow_ratio) const;
std::string move_to(Vec2d pt, GCodeWriter& writer, std::string comment = std::string());
double e_per_mm(
double line_width,
double layer_height,
float nozzle_diameter,
float filament_diameter,
float print_flow_ratio
) const;
double speed_adjust(int speed) const { return speed * 60; };
std::string convert_number_to_string(double num) const;
double number_spacing() const { return m_digit_segment_len + m_digit_gap_len; };
std::string draw_digit(double startx, double starty, char c, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, GCodeWriter &writer);
std::string draw_digit(
double startx,
double starty,
char c,
CalibPressureAdvance::DrawDigitMode mode,
double line_width,
double e_per_mm,
GCodeWriter& writer
);
std::string draw_number(
double startx, double starty, double value, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, double speed, GCodeWriter &writer);
double startx,
double starty,
double value,
CalibPressureAdvance::DrawDigitMode mode,
double line_width,
double e_per_mm,
double speed,
GCodeWriter& writer
);
Vec3d m_last_pos;
DrawDigitMode m_draw_digit_mode{DrawDigitMode::Left_To_Right};
const double m_digit_segment_len{2};
const double m_digit_gap_len{1};
const std::string::size_type m_max_number_len{5};
DrawDigitMode m_draw_digit_mode {DrawDigitMode::Left_To_Right};
const double m_digit_segment_len {2};
const double m_digit_gap_len {1};
const std::string::size_type m_max_number_len {5};
};
class CalibPressureAdvanceLine : public CalibPressureAdvance
{
class CalibPressureAdvanceLine : public CalibPressureAdvance {
public:
CalibPressureAdvanceLine(GCode *gcodegen);
~CalibPressureAdvanceLine(){};
CalibPressureAdvanceLine(GCode* gcodegen) :
mp_gcodegen(gcodegen),
m_nozzle_diameter(gcodegen->config().nozzle_diameter.get_at(0))
{ };
~CalibPressureAdvanceLine() { };
std::string generate_test(double start_pa = 0, double step_pa = 0.002, int count = 50);
void set_speed(double fast = 100.0, double slow = 20.0)
{
void set_speed(double fast = 100.0, double slow = 20.0) {
m_slow_speed = slow;
m_fast_speed = fast;
}
const double &line_width() { return m_line_width; };
bool is_delta() const;
bool & draw_numbers() { return m_draw_numbers; }
const double& line_width() { return m_line_width; };
bool is_delta() const;
bool& draw_numbers() { return m_draw_numbers; }
private:
std::string print_pa_lines(double start_x, double start_y, double start_pa, double step_pa, int num);
void delta_modify_start(double& startx, double& starty, int count);
void delta_modify_start(double &startx, double &starty, int count);
GCode *mp_gcodegen;
GCode* mp_gcodegen;
double m_nozzle_diameter;
double m_slow_speed, m_fast_speed;
const double m_height_layer {0.2};
const double m_line_width {0.6};
const double m_thin_line_width {0.44};
const double m_number_line_width {0.48};
const double m_space_y {3.5};
const double m_height_layer{0.2};
const double m_line_width{0.6};
const double m_thin_line_width{0.44};
const double m_number_line_width{0.48};
const double m_space_y{3.5};
double m_length_short{20.0}, m_length_long{40.0};
bool m_draw_numbers{true};
double m_length_short {20.0}, m_length_long {40.0};
bool m_draw_numbers {true};
};
struct SuggestedConfigCalibPAPattern
{
const std::vector<std::pair<std::string, double>> float_pairs{{"initial_layer_print_height", 0.25}, {"layer_height", 0.2}, {"initial_layer_speed", 30}};
struct SuggestedConfigCalibPAPattern {
const std::vector<std::pair<std::string, double>> float_pairs {
{"initial_layer_print_height", 0.25},
{"layer_height", 0.2},
{"initial_layer_speed", 30}
};
const std::vector<std::pair<std::string, double>> nozzle_ratio_pairs{{"line_width", 112.5}, {"initial_layer_line_width", 140}};
const std::vector<std::pair<std::string, double>> nozzle_ratio_pairs {
{"line_width", 112.5},
{"initial_layer_line_width", 140}
};
const std::vector<std::pair<std::string, int>> int_pairs{{"skirt_loops", 0}, {"wall_loops", 3}};
const std::vector<std::pair<std::string, int>> int_pairs {
{"skirt_loops", 0},
{"wall_loops", 3}
};
const std::pair<std::string, BrimType> brim_pair{"brim_type", BrimType::btNoBrim};
const std::pair<std::string, BrimType> brim_pair {"brim_type", BrimType::btNoBrim};
};
class CalibPressureAdvancePattern : public CalibPressureAdvance
{
friend struct DrawLineOptArgs;
friend struct DrawBoxOptArgs;
class CalibPressureAdvancePattern : public CalibPressureAdvance {
friend struct DrawLineOptArgs;
friend struct DrawBoxOptArgs;
public:
CalibPressureAdvancePattern(const Calib_Params &params, const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin);
CalibPressureAdvancePattern(
const Calib_Params& params,
const DynamicPrintConfig& config,
bool is_bbl_machine,
Model& model,
const Vec3d& origin
);
double handle_xy_size() const { return m_handle_xy_size; };
double handle_spacing() const { return m_handle_spacing; };
@ -217,53 +259,85 @@ public:
double print_size_y() const { return object_size_y(); };
double max_layer_z() const { return height_first_layer() + ((m_num_layers - 1) * height_layer()); };
void generate_custom_gcodes(const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin);
void generate_custom_gcodes(
const DynamicPrintConfig& config,
bool is_bbl_machine,
Model& model,
const Vec3d& origin
);
protected:
double speed_first_layer() const { return m_config.option<ConfigOptionFloat>("initial_layer_speed")->value; };
double speed_perimeter() const { return m_config.option<ConfigOptionFloat>("outer_wall_speed")->value; };
double line_width_first_layer() const { return m_config.get_abs_value("initial_layer_line_width"); };
double line_width() const { return m_config.get_abs_value("line_width"); };
int wall_count() const { return m_config.option<ConfigOptionInt>("wall_loops")->value; };
int wall_count() const { return m_config.option<ConfigOptionInt>("wall_loops")->value; };
private:
struct DrawLineOptArgs
{
DrawLineOptArgs(const CalibPressureAdvancePattern &p) : height{p.height_layer()}, line_width{p.line_width()}, speed{p.speed_adjust(p.speed_perimeter())} {};
struct DrawLineOptArgs {
DrawLineOptArgs(const CalibPressureAdvancePattern& p) :
height {p.height_layer()},
line_width {p.line_width()},
speed {p.speed_adjust(p.speed_perimeter())}
{ };
double height;
double line_width;
double speed;
std::string comment{"Print line"};
double height;
double line_width;
double speed;
std::string comment {"Print line"};
};
struct DrawBoxOptArgs
{
DrawBoxOptArgs(const CalibPressureAdvancePattern &p)
: num_perimeters{p.wall_count()}, height{p.height_first_layer()}, line_width{p.line_width_first_layer()}, speed{p.speed_adjust(p.speed_first_layer())} {};
struct DrawBoxOptArgs {
DrawBoxOptArgs(const CalibPressureAdvancePattern& p) :
num_perimeters {p.wall_count()},
height {p.height_first_layer()},
line_width {p.line_width_first_layer()},
speed {p.speed_adjust(p.speed_first_layer())}
{ };
bool is_filled{false};
int num_perimeters;
bool is_filled {false};
int num_perimeters;
double height;
double line_width;
double speed;
};
void refresh_setup(const DynamicPrintConfig &config, bool is_bbl_machine, const Model &model, const Vec3d &origin);
void _refresh_starting_point(const Model &model);
void _refresh_writer(bool is_bbl_machine, const Model &model, const Vec3d &origin);
void refresh_setup(
const DynamicPrintConfig& config,
bool is_bbl_machine,
const Model& model,
const Vec3d& origin
);
void _refresh_starting_point(const Model& model);
void _refresh_writer(
bool is_bbl_machine,
const Model& model,
const Vec3d& origin
);
double height_first_layer() const { return m_config.option<ConfigOptionFloat>("initial_layer_print_height")->value; };
double height_layer() const { return m_config.option<ConfigOptionFloat>("layer_height")->value; };
const int get_num_patterns() const { return std::ceil((m_params.end - m_params.start) / m_params.step + 1); }
double height_first_layer() const { return m_config.option<ConfigOptionFloat>("initial_layer_print_height")->value; };
double height_layer() const { return m_config.option<ConfigOptionFloat>("layer_height")->value; };
const int get_num_patterns() const
{
return std::ceil((m_params.end - m_params.start) / m_params.step + 1);
}
std::string draw_line(Vec2d to_pt, DrawLineOptArgs opt_args);
std::string draw_box(double min_x, double min_y, double size_x, double size_y, DrawBoxOptArgs opt_args);
std::string draw_line(
Vec2d to_pt,
DrawLineOptArgs opt_args
);
std::string draw_box(
double min_x,
double min_y,
double size_x,
double size_y,
DrawBoxOptArgs opt_args
);
double to_radians(double degrees) const { return degrees * M_PI / 180; };
double get_distance(Vec2d from, Vec2d to) const;
/*
/*
from slic3r documentation: spacing = extrusion_width - layer_height * (1 - PI/4)
"spacing" = center-to-center distance of adjacent extrusions, which partially overlap
https://manual.slic3r.org/advanced/flow-math
@ -284,24 +358,23 @@ private:
double pattern_shift() const;
const Calib_Params &m_params;
const Calib_Params& m_params;
DynamicPrintConfig m_config;
GCodeWriter m_writer;
bool m_is_delta;
Vec3d m_starting_point;
GCodeWriter m_writer;
bool m_is_delta;
Vec3d m_starting_point;
const double m_handle_xy_size{5};
const double m_handle_spacing{2};
const int m_num_layers{4};
const double m_handle_xy_size {5};
const double m_handle_spacing {2};
const int m_num_layers {4};
const double m_wall_side_length {30.0};
const int m_corner_angle {90};
const int m_pattern_spacing {2};
const double m_encroachment {1. / 3.};
const double m_wall_side_length{30.0};
const int m_corner_angle{90};
const int m_pattern_spacing{2};
const double m_encroachment{1. / 3.};
const double m_glyph_padding_horizontal{1};
const double m_glyph_padding_vertical{1};
const double m_glyph_padding_horizontal {1};
const double m_glyph_padding_vertical {1};
};
} // namespace Slic3r

View file

@ -89,6 +89,7 @@ static constexpr double BRIDGE_INFILL_MARGIN = 1;
//BBS: some global const config which user can not change, but developer can
static constexpr bool g_config_support_sharp_tails = true;
static constexpr bool g_config_remove_small_overhangs = true;
static constexpr float g_config_tree_support_collision_resolution = 0.2;
// Write slices as SVG images into out directory during the 2D processing of the slices.

View file

@ -297,88 +297,88 @@ endif()
# TODO: package documentation files
if(MCUT_BUILD_AS_SHARED_LIB)
#
# dynamic libs
#
# if(MCUT_BUILD_AS_SHARED_LIB)
# #
# # dynamic libs
# #
install(TARGETS ${mpn_shared_lib_name}
LIBRARY
DESTINATION lib/shared
COMPONENT dynamic_libraries)
else()
#
# static libs
#
# install(TARGETS ${mpn_shared_lib_name}
# LIBRARY
# DESTINATION lib/shared
# COMPONENT dynamic_libraries)
# else()
# #
# # static libs
# #
install(TARGETS ${mpn_static_lib_name}
ARCHIVE
DESTINATION lib/static
COMPONENT static_libraries)
endif()
# install(TARGETS ${mpn_static_lib_name}
# ARCHIVE
# DESTINATION lib/static
# COMPONENT static_libraries)
# endif()
#
# headers
#
install(FILES ${MCUT_INCLUDE_DIR}/mcut/mcut.h ${MCUT_INCLUDE_DIR}/mcut/platform.h
DESTINATION include/mcut
COMPONENT headers)
# install(FILES ${MCUT_INCLUDE_DIR}/mcut/mcut.h ${MCUT_INCLUDE_DIR}/mcut/platform.h
# DESTINATION include/mcut
# COMPONENT headers)
install(FILES
${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt
${CMAKE_CURRENT_SOURCE_DIR}/README.md
DESTINATION ./
COMPONENT text_files)
# install(FILES
# ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt
# ${CMAKE_CURRENT_SOURCE_DIR}/README.md
# DESTINATION ./
# COMPONENT text_files)
#
# notify CPack of the names of all of the components in the project
#
set(CPACK_COMPONENTS_ALL static_libraries dynamic_libraries headers text_files) # applications
# set(CPACK_COMPONENTS_ALL static_libraries dynamic_libraries headers text_files) # applications
set(CPACK_COMPONENT_APPLICATIONS_DISPLAY_NAME "MCUT Application")
set(CPACK_COMPONENT_STATIC_LIBRARIES_DISPLAY_NAME "Static Libraries")
set(CPACK_COMPONENT_DYNAMIC_LIBRARIES_DISPLAY_NAME "Dynamics Libraries")
set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C++ Headers")
# set(CPACK_COMPONENT_APPLICATIONS_DISPLAY_NAME "MCUT Application")
# set(CPACK_COMPONENT_STATIC_LIBRARIES_DISPLAY_NAME "Static Libraries")
# set(CPACK_COMPONENT_DYNAMIC_LIBRARIES_DISPLAY_NAME "Dynamics Libraries")
# set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C++ Headers")
set(CPACK_COMPONENT_APPLICATIONS_DESCRIPTION
"A simple application using MCUT")
set(CPACK_COMPONENT_STATIC_LIBRARIES_DESCRIPTION
"Static libraries used to build programs with MCUT")
set(CPACK_COMPONENT_DYNAMIC_LIBRARIES_DESCRIPTION
"Dynamic libraries used to build programs with MCUT")
set(CPACK_COMPONENT_HEADERS_DESCRIPTION
"C/C++ header files for use with MCUT")
# set(CPACK_COMPONENT_APPLICATIONS_DESCRIPTION
# "A simple application using MCUT")
# set(CPACK_COMPONENT_STATIC_LIBRARIES_DESCRIPTION
# "Static libraries used to build programs with MCUT")
# set(CPACK_COMPONENT_DYNAMIC_LIBRARIES_DESCRIPTION
# "Dynamic libraries used to build programs with MCUT")
# set(CPACK_COMPONENT_HEADERS_DESCRIPTION
# "C/C++ header files for use with MCUT")
#
# component dependencies
#
set(CPACK_COMPONENT_HEADERS_DEPENDS static_libraries dynamic_libraries)
# #
# # component dependencies
# #
# set(CPACK_COMPONENT_HEADERS_DEPENDS static_libraries dynamic_libraries)
set(CPACK_COMPONENT_APPLICATIONS_GROUP "Runtime")
set(CPACK_COMPONENT_STATIC_LIBRARIES_GROUP "Development")
set(CPACK_COMPONENT_DYNAMIC_LIBRARIES_GROUP "Development")
set(CPACK_COMPONENT_HEADERS_GROUP "Development")
# set(CPACK_COMPONENT_APPLICATIONS_GROUP "Runtime")
# set(CPACK_COMPONENT_STATIC_LIBRARIES_GROUP "Development")
# set(CPACK_COMPONENT_DYNAMIC_LIBRARIES_GROUP "Development")
# set(CPACK_COMPONENT_HEADERS_GROUP "Development")
set(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION
"All of the tools you'll ever need to develop software")
# set(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION
# "All of the tools you'll ever need to develop software")
set (CPACK_PACKAGE_NAME "MCUT")
set (CPACK_PACKAGE_VENDOR "Floyd M. Chitalu")
set (CPACK_PACKAGE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
set (CPACK_PACKAGE_VERSION_MAJOR "${MCUT_MAJOR}")
set (CPACK_PACKAGE_VERSION_MINOR "${MCUT_MINOR}")
set (CPACK_PACKAGE_VERSION_PATCH "${MCUT_PATCH}")
#set (CPACK_PACKAGE_DESCRIPTION "MCUT (pronounced emcut) is a tool for cutting meshes.")
#set (CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/DESCRIPTION.txt)
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "MCUT is a library for cutting meshes to perform tasks like boolean operations and more.")
set (CPACK_PACKAGE_HOMEPAGE_URL "https://cutdigital.github.io/mcut.site/")
set (CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
# set (CPACK_PACKAGE_ICON )
set (CPACK_PACKAGE_CHECKSUM SHA256)
#set (CPACK_PROJECT_CONFIG_FILE )
set (CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt) # must also include in install command
set (CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_SOURCE_DIR}/README.md)
#set (CPACK_RESOURCE_FILE_WELCOME ${CMAKE_CURRENT_SOURCE_DIR}/WELCOME.txt)
# set (CPACK_PACKAGE_NAME "MCUT")
# set (CPACK_PACKAGE_VENDOR "Floyd M. Chitalu")
# set (CPACK_PACKAGE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
# set (CPACK_PACKAGE_VERSION_MAJOR "${MCUT_MAJOR}")
# set (CPACK_PACKAGE_VERSION_MINOR "${MCUT_MINOR}")
# set (CPACK_PACKAGE_VERSION_PATCH "${MCUT_PATCH}")
# #set (CPACK_PACKAGE_DESCRIPTION "MCUT (pronounced emcut) is a tool for cutting meshes.")
# #set (CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/DESCRIPTION.txt)
# set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "MCUT is a library for cutting meshes to perform tasks like boolean operations and more.")
# set (CPACK_PACKAGE_HOMEPAGE_URL "https://cutdigital.github.io/mcut.site/")
# set (CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
# # set (CPACK_PACKAGE_ICON )
# set (CPACK_PACKAGE_CHECKSUM SHA256)
# #set (CPACK_PROJECT_CONFIG_FILE )
# set (CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt) # must also include in install command
# set (CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_SOURCE_DIR}/README.md)
# #set (CPACK_RESOURCE_FILE_WELCOME ${CMAKE_CURRENT_SOURCE_DIR}/WELCOME.txt)
if (WIN32)
if (USE_WIX_TOOLSET)
@ -394,7 +394,7 @@ endif ()
#set (CPACK_OUTPUT_CONFIG_FILE ) # Defaults to CPackConfig.cmake.
#set (CPACK_PACKAGE_EXECUTABLES )
set (CPACK_STRIP_FILES TRUE)
# set (CPACK_STRIP_FILES TRUE)
# set (CPACK_VERBATIM_VARIABLES )
# set (CPACK_SOURCE_PACKAGE_FILE_NAME )
# set (CPACK_SOURCE_STRIP_FILES )
@ -412,6 +412,6 @@ set (CPACK_STRIP_FILES TRUE)
# set ( )
include(CPack)
# include(CPack)
# eof

View file

@ -22,17 +22,6 @@
<string>????</string>
<key>CFBundleVersion</key>
<string>@SLIC3R_BUILD_ID@</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>bambustudioopen url</string>
<key>CFBundleURLSchemes</key>
<array>
<string>bambustudioopen</string>
</array>
</dict>
</array>
<key>CFBundleDocumentTypes</key>
<array>
<dict>

View file

@ -179,8 +179,6 @@ set(SLIC3R_GUI_SOURCES
GUI/MainFrame.hpp
GUI/BBLTopbar.cpp
GUI/BBLTopbar.hpp
GUI/BedShapeDialog.cpp
GUI/BedShapeDialog.hpp
GUI/Plater.cpp
GUI/Plater.hpp
GUI/PartPlate.cpp
@ -193,6 +191,10 @@ set(SLIC3R_GUI_SOURCES
GUI/SavePresetDialog.cpp
GUI/GUI_Colors.hpp
GUI/GUI_Colors.cpp
GUI/PhysicalPrinterDialog.hpp
GUI/PhysicalPrinterDialog.cpp
GUI/PrintHostDialogs.cpp
GUI/PrintHostDialogs.hpp
GUI/GUI_Factories.cpp
GUI/GUI_Factories.hpp
GUI/GUI_ObjectList.cpp
@ -410,12 +412,14 @@ set(SLIC3R_GUI_SOURCES
GUI/CalibrationWizardCaliPage.hpp
GUI/CalibrationWizardSavePage.cpp
GUI/CalibrationWizardSavePage.hpp
GUI/calib_dlg.cpp
GUI/calib_dlg.hpp
GUI/Calibration.hpp
GUI/Calibration.cpp
GUI/PrintOptionsDialog.hpp
GUI/PrintOptionsDialog.cpp
GUI/BonjourDialog.hpp
GUI/BonjourDialog.cpp
GUI/BedShapeDialog.hpp
GUI/BedShapeDialog.cpp
Utils/json_diff.hpp
Utils/json_diff.cpp
GUI/KBShortcutsDialog.hpp
@ -447,6 +451,12 @@ set(SLIC3R_GUI_SOURCES
Utils/PrintHost.cpp
Utils/NetworkAgent.cpp
Utils/NetworkAgent.hpp
Utils/OctoPrint.cpp
Utils/OctoPrint.hpp
Utils/PrintHost.cpp
Utils/PrintHost.hpp
Utils/Serial.cpp
Utils/Serial.hpp
Utils/MKS.hpp
Utils/MKS.cpp
Utils/Duet.cpp
@ -457,7 +467,8 @@ set(SLIC3R_GUI_SOURCES
Utils/AstroBox.hpp
Utils/Repetier.cpp
Utils/Repetier.hpp
GUI/calib_dlg.hpp
GUI/calib_dlg.cpp
Utils/CalibUtils.cpp
Utils/CalibUtils.hpp
)
@ -509,7 +520,7 @@ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SLIC3R_GUI_SOURCES})
encoding_check(libslic3r_gui)
target_link_libraries(libslic3r_gui libslic3r cereal imgui minilzo GLEW::GLEW OpenGL::GL hidapi ${wxWidgets_LIBRARIES} glfw libcurl OpenSSL::SSL OpenSSL::Crypto)
target_link_libraries(libslic3r_gui libslic3r cereal::cereal imgui minilzo GLEW::GLEW OpenGL::GL hidapi ${wxWidgets_LIBRARIES} glfw libcurl OpenSSL::SSL OpenSSL::Crypto)
#target_link_libraries(libslic3r_gui libslic3r cereal imgui minilzo GLEW::GLEW OpenGL::GL hidapi libcurl OpenSSL::SSL OpenSSL::Crypto ${wxWidgets_LIBRARIES} glfw)
if (MSVC)
@ -537,6 +548,10 @@ if (SLIC3R_STATIC)
target_compile_definitions(libslic3r_gui PUBLIC -DwxDEBUG_LEVEL=0)
endif()
if (HAVE_SPNAV)
target_link_libraries(libslic3r_gui spnav)
endif()
if (SLIC3R_STATIC AND NOT SLIC3R_STATIC_EXCLUDE_CURL AND UNIX AND NOT APPLE)
target_compile_definitions(libslic3r_gui PRIVATE OPENSSL_CERT_OVERRIDE)
endif ()
@ -561,4 +576,4 @@ if (UNIX AND NOT APPLE)
endif ()
# Add a definition so that we can tell we are compiling slic3r.
target_compile_definitions(libslic3r_gui PRIVATE SLIC3R_CURRENTLY_COMPILING_GUI_MODULE)
target_compile_definitions(libslic3r_gui PRIVATE SLIC3R_CURRENTLY_COMPILING_GUI_MODULE)

View file

@ -18,7 +18,12 @@
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/log/trivial.hpp>
#if BOOST_VERSION >= 107800
#include <boost/timer/timer.hpp>
#else
#include <boost/timer.hpp>
#endif
static const float GROUND_Z = -0.04f;
static const std::array<float, 4> DEFAULT_MODEL_COLOR = { 0.3255f, 0.337f, 0.337f, 1.0f };
@ -338,7 +343,6 @@ void Bed3D::render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor,
if (show_axes)
render_axes();
glsafe(::glEnable(GL_DEPTH_TEST));
m_model.set_color(-1, m_is_dark ? DEFAULT_MODEL_COLOR_DARK : DEFAULT_MODEL_COLOR);
@ -604,7 +608,7 @@ void Bed3D::render_system(GLCanvas3D& canvas, bool bottom) const
void Bed3D::update_model_offset() const
{
// move the model so that its origin (0.0, 0.0, 0.0) goes into the bed shape center and a bit down to avoid z-fighting with the texture quad
Vec3d shift = m_build_volume.bounding_volume().center();
Vec3d shift = m_extended_bounding_box.center();
shift(2) = -0.03;
Vec3d* model_offset_ptr = const_cast<Vec3d*>(&m_model_offset);
*model_offset_ptr = shift;
@ -613,8 +617,8 @@ void Bed3D::update_model_offset() const
{
(*model_offset_ptr)(0) -= m_bed_shape[2].x() / 2.0f;
(*model_offset_ptr)(1) -= m_bed_shape[2].y() / 2.0f;
(*model_offset_ptr)(2) = -0.41 + GROUND_Z;
}
(*model_offset_ptr)(2) = -0.41 + GROUND_Z;
// update extended bounding box
const_cast<BoundingBoxf3&>(m_extended_bounding_box) = calc_extended_bounding_box();
@ -631,9 +635,9 @@ GeometryBuffer Bed3D::update_bed_triangles() const
BoundingBoxf3 build_volume;
if (!m_build_volume.valid()) return new_triangles;
(*model_offset_ptr)(0) = m_build_volume.bounding_volume2d().min.x();
(*model_offset_ptr)(1) = m_build_volume.bounding_volume2d().min.y();
auto bed_ext = get_extents(m_bed_shape);
(*model_offset_ptr)(0) = m_build_volume.bounding_volume2d().min.x() - bed_ext.min.x();
(*model_offset_ptr)(1) = m_build_volume.bounding_volume2d().min.y() - bed_ext.min.y();
(*model_offset_ptr)(2) = -0.41 + GROUND_Z;
std::vector<Vec2d> new_bed_shape;

View file

@ -34,10 +34,10 @@ void AMSMaterialsSetting::create()
m_sizer_button->Add(0, 0, 1, wxEXPAND, 0);
m_button_confirm = new Button(this, _L("Confirm"));
m_btn_bg_green = StateColor(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
m_btn_bg_green = StateColor(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed), std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
m_button_confirm->SetBackgroundColor(m_btn_bg_green);
m_button_confirm->SetBorderColor(wxColour(0, 174, 66));
m_button_confirm->SetBorderColor(wxColour(0, 150, 136));
m_button_confirm->SetTextColor(wxColour("#FFFFFE"));
m_button_confirm->SetMinSize(AMS_MATERIALS_SETTING_BUTTON_SIZE);
m_button_confirm->SetCornerRadius(FromDIP(12));
@ -138,7 +138,7 @@ void AMSMaterialsSetting::create_panel_normal(wxWindow* parent)
m_sizer_filament->Add(m_comboBox_filament, 1, wxALIGN_CENTER, 0);
m_readonly_filament = new TextInput(parent, wxEmptyString, "", "", wxDefaultPosition, AMS_MATERIALS_SETTING_COMBOX_WIDTH, wxTE_READONLY | wxRIGHT);
m_readonly_filament->SetBorderColor(StateColor(std::make_pair(0xDBDBDB, (int)StateColor::Focused), std::make_pair(0x00AE42, (int)StateColor::Hovered),
m_readonly_filament->SetBorderColor(StateColor(std::make_pair(0xDBDBDB, (int)StateColor::Focused), std::make_pair(0x009688, (int)StateColor::Hovered),
std::make_pair(0xDBDBDB, (int)StateColor::Normal)));
m_readonly_filament->SetFont(::Label::Body_14);
m_readonly_filament->SetLabelColor(AMS_MATERIALS_SETTING_GREY800);
@ -984,7 +984,7 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
}
else {
m_button_confirm->SetBackgroundColor(m_btn_bg_green);
m_button_confirm->SetBorderColor(wxColour(0, 174, 66));
m_button_confirm->SetBorderColor(wxColour(0, 150, 136));
m_button_confirm->SetTextColor(wxColour("#FFFFFE"));
m_button_confirm->Enable(true);
}

View file

@ -869,7 +869,7 @@ AmsHumidityTipPopup::AmsHumidityTipPopup(wxWindow* parent)
main_sizer->Add(m_staticText_note, 0, wxALL | wxLEFT | wxRIGHT, 22);
m_button_confirm = new Button(this, _L("OK"));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Pressed), std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
m_button_confirm->SetBackgroundColor(btn_bg_green);
m_button_confirm->SetBorderColor(wxColour(0, 150, 136));
m_button_confirm->SetTextColor(wxColour(0xFFFFFE));
@ -1189,7 +1189,7 @@ void AmsReplaceMaterialDialog::create()
auto label_title = new Label(this, _L("Auto Refill"));
label_title->SetFont(Label::Head_14);
label_title->SetForegroundColour(0x00AE42);
label_title->SetForegroundColour(0x009688);
label_txt = new Label(this, _L("When the current material run out, the printer will continue to print in the following order."));
label_txt->SetFont(Label::Body_13);
label_txt->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#323A3C")));
@ -1224,7 +1224,7 @@ void AmsReplaceMaterialDialog::create()
std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed), std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
m_button_sizer->Add( 0, 0, 1, wxEXPAND, 0 );
m_main_sizer->Add(0,0,0, wxTOP, FromDIP(12));

View file

@ -403,12 +403,6 @@ void BBLTopbar::OnPublishClicked(wxAuiToolBarEvent& event)
return;
}
// record
json j;
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent)
agent->track_event("enter_model_mall", j.dump());
//no more check
//if (GUI::wxGetApp().plater()->model().objects.empty()) return;

View file

@ -120,7 +120,7 @@ public:
// Get the current print. It is either m_fff_print or m_sla_print.
const PrintBase* current_print() const { return m_print; }
const Print* fff_print() const { return m_fff_print; }
Print * fff_print() { return m_fff_print; }
Print* fff_print() { return m_fff_print; }
const SLAPrint* sla_print() const { return m_sla_print; }
// Take the project path (if provided), extract the name of the project, run it through the macro processor and save it next to the project file.
// If the project_path is empty, just run output_filepath().

View file

@ -59,7 +59,7 @@ wxString get_fail_reason(int code)
SetDoubleBuffered(true);
#endif //__WINDOWS__
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str();
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str();
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
SetBackgroundColour(*wxWHITE);
@ -183,7 +183,7 @@ wxString get_fail_reason(int code)
m_link_Terms_title->SetFont(Label::Head_13);
m_link_Terms_title->SetMaxSize(wxSize(FromDIP(450), -1));
m_link_Terms_title->Wrap(FromDIP(450));
m_link_Terms_title->SetForegroundColour(wxColour(0x00AE42));
m_link_Terms_title->SetForegroundColour(wxColour(0x009688));
m_link_Terms_title->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
wxString txt = _L("Thank you for purchasing a Bambu Lab device.Before using your Bambu Lab device, please read the termsand conditions.By clicking to agree to use your Bambu Lab device, you agree to abide by the Privacy Policyand Terms of Use(collectively, the \"Terms\"). If you do not comply with or agree to the Bambu Lab Privacy Policy, please do not use Bambu Lab equipment and services.");
ConfirmBeforeSendDialog confirm_dlg(this, wxID_ANY, _L("Terms and Conditions"), ConfirmBeforeSendDialog::ButtonStyle::ONLY_CONFIRM);
@ -202,7 +202,7 @@ wxString get_fail_reason(int code)
m_link_privacy_title->SetFont(Label::Head_13);
m_link_privacy_title->SetMaxSize(wxSize(FromDIP(450), -1));
m_link_privacy_title->Wrap(FromDIP(450));
m_link_privacy_title->SetForegroundColour(wxColour(0x00AE42));
m_link_privacy_title->SetForegroundColour(wxColour(0x009688));
m_link_privacy_title->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
std::string url;
std::string country_code = Slic3r::GUI::wxGetApp().app_config->get_country_code();
@ -242,7 +242,7 @@ wxString get_fail_reason(int code)
m_link_notice_title->SetFont(Label::Head_13);
m_link_notice_title->SetMaxSize(wxSize(FromDIP(450), -1));
m_link_notice_title->Wrap(FromDIP(450));
m_link_notice_title->SetForegroundColour(wxColour(0x00AE42));
m_link_notice_title->SetForegroundColour(wxColour(0x009688));
m_link_notice_title->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_HAND); });
m_link_notice_title->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_ARROW); });
m_link_notice_title->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
@ -297,7 +297,7 @@ wxString get_fail_reason(int code)
m_sw_bind_failed_info->SetSizer( m_sizer_bind_failed_info );
m_link_network_state = new Label(m_sw_bind_failed_info, _L("Check the status of current system services"));
m_link_network_state->SetForegroundColour(0x00AE42);
m_link_network_state->SetForegroundColour(0x009688);
m_link_network_state->SetFont(::Label::Body_12);
m_link_network_state->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {wxGetApp().link_to_network_check(); });
m_link_network_state->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {m_link_network_state->SetCursor(wxCURSOR_HAND); });
@ -380,9 +380,9 @@ wxString get_fail_reason(int code)
m_button_bind = new Button(button_panel, _L("Confirm"));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
m_button_bind->SetBackgroundColor(btn_bg_green);
m_button_bind->SetBorderColor(*wxWHITE);
m_button_bind->SetTextColor(wxColour("#FFFFFE"));
@ -667,7 +667,7 @@ void BindMachineDialog::on_show(wxShowEvent &event)
UnBindMachineDialog::UnBindMachineDialog(Plater *plater /*= nullptr*/)
: DPIDialog(static_cast<wxWindow *>(wxGetApp().mainframe), wxID_ANY, _L("Log out printer"), wxDefaultPosition, wxDefaultSize, wxCAPTION)
{
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str();
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str();
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
SetBackgroundColour(*wxWHITE);
@ -740,10 +740,10 @@ UnBindMachineDialog::UnBindMachineDialog(Plater *plater /*= nullptr*/)
m_sizer_button->Add(0, 0, 1, wxEXPAND, 5);
m_button_unbind = new Button(this, _L("Confirm"));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
m_button_unbind->SetBackgroundColor(btn_bg_green);
m_button_unbind->SetBorderColor(wxColour(0, 174, 66));
m_button_unbind->SetBorderColor(wxColour(0, 150, 136));
m_button_unbind->SetTextColor(wxColour("#FFFFFE"));
m_button_unbind->SetSize(BIND_DIALOG_BUTTON_SIZE);
m_button_unbind->SetMinSize(BIND_DIALOG_BUTTON_SIZE);

View file

@ -322,7 +322,7 @@ wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned target_
// map of color replaces
std::map<std::string, std::string> replaces;
replaces["\"#00AE42\""] = "\"#009688\"";
replaces["\"#0x00AE42\""] = "\"#009688\"";
replaces["\"#00FF00\""] = "\"#52c7b8\"";
if (dark_mode) {
replaces["\"#262E30\""] = "\"#EFEFF0\"";

View file

@ -84,7 +84,7 @@ BonjourDialog::BonjourDialog(wxWindow *parent, Slic3r::PrinterTechnology tech)
auto button_sizer = new wxBoxSizer(wxHORIZONTAL);
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed), std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
StateColor btn_bg_white(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed), std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered),

View file

@ -273,12 +273,12 @@ void HistoryWindow::sync_history_data() {
});
auto edit_button = new Button(m_history_data_panel, _L("Edit"));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
edit_button->SetBackgroundColour(*wxWHITE);
edit_button->SetBackgroundColor(btn_bg_green);
edit_button->SetBorderColor(wxColour(0, 174, 66));
edit_button->SetBorderColor(wxColour(0, 150, 136));
edit_button->SetTextColor(wxColour("#FFFFFE"));
edit_button->SetMinSize(wxSize(-1, FromDIP(24)));
edit_button->SetCornerRadius(FromDIP(12));
@ -407,12 +407,12 @@ EditCalibrationHistoryDialog::EditCalibrationHistoryDialog(wxWindow* parent, con
auto btn_sizer = new wxBoxSizer(wxHORIZONTAL);
Button* save_btn = new Button(top_panel, _L("Save"));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
save_btn->SetBackgroundColour(*wxWHITE);
save_btn->SetBackgroundColor(btn_bg_green);
save_btn->SetBorderColor(wxColour(0, 174, 66));
save_btn->SetBorderColor(wxColour(0, 150, 136));
save_btn->SetTextColor(wxColour("#FFFFFE"));
save_btn->SetMinSize(wxSize(-1, FromDIP(24)));
save_btn->SetCornerRadius(FromDIP(12));

View file

@ -599,23 +599,6 @@ void CalibrationPanel::show_status(int status)
{
if (!m_initialized) return;
if (last_status == status)return;
if (last_status & (int)MonitorStatus::MONITOR_CONNECTING != 0) {
NetworkAgent* agent = wxGetApp().getAgent();
json j;
j["dev_id"] = obj ? obj->dev_id : "obj_nullptr";
if (status & (int)MonitorStatus::MONITOR_DISCONNECTED != 0) {
j["result"] = "failed";
if (agent) {
agent->track_event("connect_dev", j.dump());
}
}
else if (status & (int)MonitorStatus::MONITOR_NORMAL != 0) {
j["result"] = "success";
if (agent) {
agent->track_event("connect_dev", j.dump());
}
}
}
last_status = status;
BOOST_LOG_TRIVIAL(info) << "monitor: show_status = " << status;

View file

@ -10,7 +10,7 @@ namespace Slic3r { namespace GUI {
#define SELECT_MACHINE_GREY900 wxColour(38, 46, 48)
#define SELECT_MACHINE_GREY600 wxColour(144,144,144)
#define SELECT_MACHINE_GREY400 wxColour(206, 206, 206)
#define SELECT_MACHINE_BRAND wxColour(0, 174, 66)
#define SELECT_MACHINE_BRAND wxColour(0, 150, 136)
#define SELECT_MACHINE_REMIND wxColour(255,111,0)
#define SELECT_MACHINE_LIGHT_GREEN wxColour(219, 253, 231)

View file

@ -3,7 +3,7 @@
#include "GUI_App.hpp"
#include "MsgDialog.hpp"
#include "CalibrationWizardPage.hpp"
#include "../../libslic3r/Calib.hpp"
#include "../../libslic3r/calib.hpp"
#include "Tabbook.hpp"
#include "CaliHistoryDialog.hpp"

View file

@ -142,9 +142,9 @@ CaliPageButton::CaliPageButton(wxWindow* parent, CaliPageActionType type, wxStri
Button(parent, text)
{
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
StateColor btn_bg_white(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed),
@ -152,7 +152,7 @@ CaliPageButton::CaliPageButton(wxWindow* parent, CaliPageActionType type, wxStri
std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Normal));
StateColor btn_bd_green(std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Enabled));
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Enabled));
StateColor btn_bd_white(std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));

View file

@ -11,7 +11,7 @@
#include "PresetComboBoxes.hpp"
#include "../slic3r/Utils/CalibUtils.hpp"
#include "../../libslic3r/Calib.hpp"
#include "../../libslic3r/calib.hpp"
namespace Slic3r { namespace GUI {

View file

@ -86,7 +86,7 @@ void Camera::set_zoom(double zoom)
void Camera::select_view(const std::string& direction)
{
if (direction == "iso")
set_iso_orientation();
set_default_orientation();
else if (direction == "left")
look_at(m_target - m_distance * Vec3d::UnitX(), m_target, Vec3d::UnitZ());
else if (direction == "right")
@ -574,19 +574,6 @@ void Camera::set_default_orientation()
m_view_matrix.fromPositionOrientationScale(m_view_rotation * (-camera_pos), m_view_rotation, Vec3d::Ones());
}
void Camera::set_iso_orientation()
{
m_zenit = 45.0f;
const double theta_rad = Geometry::deg2rad(-(double)m_zenit);
const double phi_rad = Geometry::deg2rad(45.0);
const double sin_theta = ::sin(theta_rad);
const Vec3d camera_pos = m_target + m_distance * Vec3d(sin_theta * ::sin(phi_rad), sin_theta * ::cos(phi_rad), ::cos(theta_rad));
m_view_rotation = Eigen::AngleAxisd(theta_rad, Vec3d::UnitX()) * Eigen::AngleAxisd(phi_rad, Vec3d::UnitZ());
m_view_rotation.normalize();
m_view_matrix.fromPositionOrientationScale(m_view_rotation * (-camera_pos), m_view_rotation, Vec3d::Ones());
}
Vec3d Camera::validate_target(const Vec3d& target) const
{
BoundingBoxf3 test_box = m_scene_box;
@ -604,15 +591,15 @@ Vec3d Camera::validate_target(const Vec3d& target) const
void Camera::update_zenit()
{
m_zenit = Geometry::rad2deg(0.5 * M_PI - std::acos(std::clamp(-get_dir_forward().dot(Vec3d::UnitZ()), -1.0, 1.0))); }
m_zenit = Geometry::rad2deg(0.5 * M_PI - std::acos(std::clamp(-get_dir_forward().dot(Vec3d::UnitZ()), -1.0, 1.0)));
}
void Camera::update_target() {
Vec3d temptarget = get_position() + m_distance * get_dir_forward();
if (!(temptarget-m_target).isApprox(Vec3d::Zero())){
m_target = temptarget;
}
}
}
} // GUI
} // Slic3r

View file

@ -163,7 +163,6 @@ private:
void set_distance(double distance);
void set_default_orientation();
void set_iso_orientation();
Vec3d validate_target(const Vec3d& target) const;
void update_zenit();
void update_target();

View file

@ -173,10 +173,11 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
return;
// layer_height shouldn't be equal to zero
auto gpreset = GUI::wxGetApp().preset_bundle->printers.get_edited_preset();
if (config->opt_float("layer_height") < EPSILON)
{
const wxString msg_text = _(L("Too small layer height.\nReset to 0.2"));
MessageDialog dialog(m_msg_dlg_parent, msg_text,"", wxICON_WARNING | wxOK);
MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxOK);
DynamicPrintConfig new_conf = *config;
is_msg_dlg_already_exist = true;
dialog.ShowModal();
@ -186,14 +187,15 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
}
//BBS: limite the max layer_herght
if (config->opt_float("layer_height") > 0.6 + EPSILON)
auto max_lh = gpreset.config.opt_float("max_layer_height",0);
if (max_lh > 0.2 && config->opt_float("layer_height") > max_lh+ EPSILON)
{
const wxString msg_text = _(L("Too large layer height.\nReset to 0.2"));
const wxString msg_text = wxString::Format(L"Too large layer height.\nReset to %0.3f", max_lh);
MessageDialog dialog(nullptr, msg_text, "", 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.2));
new_conf.set_key_value("layer_height", new ConfigOptionFloat(max_lh));
apply(config, &new_conf);
is_msg_dlg_already_exist = false;
}
@ -319,37 +321,6 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
is_msg_dlg_already_exist = false;
}
//BBS
//if (config->opt_enum<PerimeterGeneratorType>("wall_generator") == PerimeterGeneratorType::Arachne &&
// config->opt_bool("enable_overhang_speed"))
//{
// wxString msg_text = _(L("Arachne engine only works when overhang slowing down is disabled.\n"
// "This may cause decline in the quality of overhang surface when print fastly")) + "\n";
// if (is_global_config)
// msg_text += "\n" + _(L("Disable overhang slowing down automatically? \n"
// "Yes - Enable arachne and disable overhang slowing down\n"
// "No - Give up using arachne this time"));
// MessageDialog dialog(m_msg_dlg_parent, msg_text, "",
// wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK));
// DynamicPrintConfig new_conf = *config;
// is_msg_dlg_already_exist = true;
// auto answer = dialog.ShowModal();
// bool enable_overhang_slow_down = true;
// if (!is_global_config || answer == wxID_YES) {
// new_conf.set_key_value("enable_overhang_speed", new ConfigOptionBool(false));
// enable_overhang_slow_down = false;
// }
// else {
// new_conf.set_key_value("wall_generator", new ConfigOptionEnum<PerimeterGeneratorType>(PerimeterGeneratorType::Classic));
// }
// apply(config, &new_conf);
// if (cb_value_change) {
// if (!enable_overhang_slow_down)
// cb_value_change("enable_overhang_speed", false);
// }
// is_msg_dlg_already_exist = false;
//}
// BBS
int filament_cnt = wxGetApp().preset_bundle->filament_presets.size();
#if 0
@ -508,7 +479,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
void ConfigManipulation::apply_null_fff_config(DynamicPrintConfig *config, std::vector<std::string> const &keys, std::map<ObjectBase *, ModelConfig *> const &configs)
{
for (auto &k : keys) {
if (/*k == "adaptive_layer_height" || */k == "independent_support_layer_height" || k == "enable_support" || k == "detect_thin_wall")
if (/*k == "adaptive_layer_height" || */ k == "independent_support_layer_height" || k == "enable_support" ||
k == "detect_thin_wall" || k == "tree_support_adaptive_layer_height")
config->set_key_value(k, new ConfigOptionBool(true));
else if (k == "wall_loops")
config->set_key_value(k, new ConfigOptionInt(0));
@ -531,20 +503,25 @@ void ConfigManipulation::apply_null_fff_config(DynamicPrintConfig *config, std::
void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, const bool is_global_config)
{
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
//SoftFever
auto gcflavor = preset_bundle->printers.get_edited_preset().config.option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value;
bool have_perimeters = config->opt_int("wall_loops") > 0;
for (auto el : { "ensure_vertical_shell_thickness", "detect_thin_wall", "detect_overhang_wall",
"seam_position","seam_gap","wipe_speed", "wall_infill_order", "outer_wall_line_width",
"inner_wall_speed", "outer_wall_speed" })
"seam_position", "staggered_inner_seams", "wall_infill_order", "outer_wall_line_width",
"inner_wall_speed", "outer_wall_speed", "small_perimeter_speed", "small_perimeter_threshold" })
toggle_field(el, have_perimeters);
bool have_infill = config->option<ConfigOptionPercent>("sparse_infill_density")->value > 0;
// sparse_infill_filament uses the same logic as in Print::extruders()
for (auto el : { "sparse_infill_pattern", "sparse_infill_anchor_max", "infill_combination",
"minimum_sparse_infill_area", "sparse_infill_filament"})
for (auto el : { "sparse_infill_pattern", "infill_combination",
"minimum_sparse_infill_area", "sparse_infill_filament", "infill_anchor_max"})
toggle_line(el, have_infill);
// Only allow configuration of open anchors if the anchoring is enabled.
bool has_infill_anchors = have_infill && config->option<ConfigOptionFloatOrPercent>("sparse_infill_anchor_max")->value > 0;
toggle_line("sparse_infill_anchor", has_infill_anchors);
bool has_infill_anchors = have_infill && config->option<ConfigOptionFloatOrPercent>("infill_anchor_max")->value > 0;
toggle_field("infill_anchor", has_infill_anchors);
bool has_spiral_vase = config->opt_bool("spiral_mode");
bool has_top_solid_infill = config->opt_int("top_shell_layers") > 0;
@ -554,8 +531,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
for (auto el : { "top_surface_pattern", "bottom_surface_pattern", "internal_solid_infill_pattern", "solid_infill_filament"})
toggle_field(el, has_solid_infill);
for (auto el : { "infill_direction", "sparse_infill_line_width", "bridge_angle",
"sparse_infill_speed", "bridge_speed" })
for (auto el : { "infill_direction", "sparse_infill_line_width",
"sparse_infill_speed", "bridge_speed", "internal_bridge_speed", "bridge_angle" })
toggle_field(el, have_infill || has_solid_infill);
toggle_field("top_shell_thickness", ! has_spiral_vase && has_top_solid_infill);
@ -569,19 +546,14 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
bool have_default_acceleration = config->opt_float("default_acceleration") > 0;
//BBS
for (auto el : { "initial_layer_acceleration", "outer_wall_acceleration", "top_surface_acceleration", "inner_wall_acceleration", "sparse_infill_acceleration" })
for (auto el : {"outer_wall_acceleration", "inner_wall_acceleration", "initial_layer_acceleration",
"top_surface_acceleration", "travel_acceleration", "bridge_acceleration", "sparse_infill_acceleration", "internal_solid_infill_acceleration"})
toggle_field(el, have_default_acceleration);
if (is_BBL_Printer) {
for (auto el : {"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk", "travel_jerk"})
toggle_line(el, false);
} else {
for (auto el : {"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk", "travel_jerk"})
toggle_line(el, true);
bool quality_default_jerk = config->opt_float("default_jerk") > 0;
for (auto el : {"outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk", "travel_jerk"})
toggle_field(el, quality_default_jerk);
}
bool have_default_jerk = config->opt_float("default_jerk") > 0;
for (auto el : { "outer_wall_jerk", "inner_wall_jerk", "initial_layer_jerk", "top_surface_jerk","travel_jerk", "infill_jerk"})
toggle_field(el, have_default_jerk);
bool have_skirt = config->opt_int("skirt_loops") > 0;
toggle_field("skirt_height", have_skirt && config->opt_enum<DraftShield>("draft_shield") != dsEnabled);
@ -595,6 +567,15 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
// wall_filament uses the same logic as in Print::extruders()
toggle_field("wall_filament", have_perimeters || have_brim);
bool have_brim_ear = (config->opt_enum<BrimType>("brim_type") == btEar);
const auto brim_width = config->opt_float("brim_width");
// disable brim_ears_max_angle and brim_ears_detection_length if brim_width is 0
toggle_field("brim_ears_max_angle", brim_width > 0.0f);
toggle_field("brim_ears_detection_length", brim_width > 0.0f);
// hide brim_ears_max_angle and brim_ears_detection_length if brim_ear is not selected
toggle_line("brim_ears_max_angle", have_brim_ear);
toggle_line("brim_ears_detection_length", have_brim_ear);
bool have_raft = config->opt_int("raft_layers") > 0;
bool have_support_material = config->opt_bool("enable_support") || have_raft;
// BBS
@ -607,22 +588,23 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
"support_interface_pattern", "support_interface_top_layers", "support_interface_bottom_layers",
"bridge_no_support", "max_bridge_length", "support_top_z_distance", "support_bottom_z_distance",
//BBS: add more support params to dependent of enable_support
"support_type", "support_on_build_plate_only",
"support_remove_small_overhang",
"support_type", "support_on_build_plate_only", "support_critical_regions_only",
"support_object_xy_distance"/*, "independent_support_layer_height"*/})
toggle_field(el, have_support_material);
toggle_field("support_threshold_angle", have_support_material && is_auto(support_type));
//toggle_field("support_closing_radius", have_support_material && support_style == smsSnug);
bool support_is_tree = config->opt_bool("enable_support") && is_tree(support_type);
for (auto el : {"tree_support_branch_angle", "tree_support_wall_count", "tree_support_branch_distance", "tree_support_branch_diameter","tree_support_brim_width"})
for (auto el : {"tree_support_branch_angle", "tree_support_wall_count", "tree_support_branch_distance",
"tree_support_branch_diameter", "tree_support_adaptive_layer_height", "tree_support_auto_brim", "tree_support_brim_width"})
toggle_field(el, support_is_tree);
// hide tree support settings when normal is selected
for (auto el : {"tree_support_branch_angle", "tree_support_wall_count", "tree_support_branch_distance", "tree_support_branch_diameter", "max_bridge_length","tree_support_brim_width" })
for (auto el : {"tree_support_branch_angle", "tree_support_wall_count", "tree_support_branch_distance",
"tree_support_branch_diameter", "max_bridge_length", "tree_support_adaptive_layer_height", "tree_support_auto_brim", "tree_support_brim_width"})
toggle_line(el, support_is_tree);
toggle_line("support_critical_regions_only", is_auto(support_type) && support_is_tree);
toggle_field("tree_support_brim_width", support_is_tree && !config->opt_bool("tree_support_auto_brim"));
// tree support use max_bridge_length instead of bridge_no_support
toggle_line("bridge_no_support", !support_is_tree);
@ -647,7 +629,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
toggle_line(el, have_raft);
bool has_ironing = (config->opt_enum<IroningType>("ironing_type") != IroningType::NoIroning);
for (auto el : {"ironing_pattern", "ironing_flow", "ironing_spacing", "ironing_speed"})
for (auto el : { "ironing_flow", "ironing_spacing", "ironing_speed" })
toggle_line(el, has_ironing);
// bool have_sequential_printing = (config->opt_enum<PrintSequence>("print_sequence") == PrintSequence::ByObject);
@ -664,11 +646,16 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
for (auto el : {"flush_into_infill", "flush_into_support", "flush_into_objects"})
toggle_field(el, have_prime_tower);
// BBS: MusangKing - Hide "Independent support layer height" option
toggle_line("independent_support_layer_height", have_support_material && !have_prime_tower);
bool have_avoid_crossing_perimeters = config->opt_bool("reduce_crossing_wall");
toggle_line("max_travel_detour_distance", have_avoid_crossing_perimeters);
bool has_overhang_speed = config->opt_bool("enable_overhang_speed");
for (auto el : { "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed"})
for (auto el :
{"overhang_speed_classic", "overhang_1_4_speed",
"overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed"})
toggle_line(el, has_overhang_speed);
toggle_line("flush_into_objects", !is_global_config);
@ -682,22 +669,24 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
"min_feature_size", "min_bead_width", "wall_distribution_count" })
toggle_line(el, have_arachne);
toggle_field("detect_thin_wall", !have_arachne);
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
// OrcaSlicer
auto gcflavor = preset_bundle->printers.get_edited_preset().config.option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value;
if( gcflavor != gcfKlipper )
{
for (auto el : {"accel_to_decel_enable", "accel_to_decel_factor"})
toggle_line(el, false);
}
else {
for (auto el : {"accel_to_decel_enable", "accel_to_decel_factor"})
toggle_line(el, true);
// Orca
auto is_role_based_wipe_speed = config->opt_bool("role_based_wipe_speed");
toggle_field("wipe_speed",!is_role_based_wipe_speed);
for (auto el : {"accel_to_decel_enable", "accel_to_decel_factor"})
toggle_line(el, gcflavor == gcfKlipper);
if(gcflavor == gcfKlipper)
toggle_field("accel_to_decel_factor", config->opt_bool("accel_to_decel_enable"));
}
bool have_make_overhang_printable = config->opt_bool("make_overhang_printable");
toggle_line("make_overhang_printable_angle", have_make_overhang_printable);
toggle_line("make_overhang_printable_hole_size", have_make_overhang_printable);
toggle_line("exclude_object", gcflavor == gcfKlipper);
toggle_line("min_width_top_surface",config->opt_bool("only_one_wall_top"));
}
void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/)

View file

@ -1620,29 +1620,12 @@ int MachineObject::command_go_home()
int MachineObject::command_control_fan(FanType fan_type, bool on_off)
{
std::string gcode = (boost::format("M106 P%1% S%2% \n") % (int)fan_type % (on_off ? 255 : 0)).str();
try {
json j;
j["fan_control"] = "fan_control";
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_event("printer_control", j.dump());
}
catch (...) {}
return this->publish_gcode(gcode);
}
int MachineObject::command_control_fan_val(FanType fan_type, int val)
{
std::string gcode = (boost::format("M106 P%1% S%2% \n") % (int)fan_type % (val)).str();
try {
json j;
j["fan_control"] = "fan_control_val";
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_event("printer_control", j.dump());
}
catch (...) {}
return this->publish_gcode(gcode);
}
@ -1680,29 +1663,12 @@ int MachineObject::command_task_resume()
int MachineObject::command_set_bed(int temp)
{
std::string gcode_str = (boost::format("M140 S%1%\n") % temp).str();
try {
json j;
j["temp_control"] = "bed_temp";
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_event("printer_control", j.dump());
}
catch (...) {}
return this->publish_gcode(gcode_str);
}
int MachineObject::command_set_nozzle(int temp)
{
std::string gcode_str = (boost::format("M104 S%1%\n") % temp).str();
try {
json j;
j["temp_control"] = "nozzle_temp";
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_event("printer_control", j.dump());
}
catch (...) {}
return this->publish_gcode(gcode_str);
}
@ -1971,7 +1937,6 @@ int MachineObject::command_axis_control(std::string axis, double unit, double va
j["axis_control"] = axis;
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_event("printer_control", j.dump());
}
catch (...) {}
@ -3759,12 +3724,6 @@ int MachineObject::parse_json(std::string payload)
} else if (jj["command"].get<std::string>() == "gcode_line") {
//ack of gcode_line
BOOST_LOG_TRIVIAL(debug) << "parse_json, ack of gcode_line = " << j.dump(4);
if (m_agent && is_studio_cmd(sequence_id)) {
json t;
t["dev_id"] = this->dev_id;
t["signal"] = this->wifi_signal;
m_agent->track_event("ack_cmd_gcode_line", t.dump());
}
} else if (jj["command"].get<std::string>() == "project_file") {
//ack of project file
BOOST_LOG_TRIVIAL(debug) << "parse_json, ack of project_file = " << j.dump(4);
@ -3773,7 +3732,6 @@ int MachineObject::parse_json(std::string payload)
json t;
t["dev_id"] = this->dev_id;
t["signal"] = this->wifi_signal;
m_agent->track_event("ack_cmd_project_file", t.dump());
}
std::string result;
@ -4262,13 +4220,6 @@ int MachineObject::publish_gcode(std::string gcode_str)
j["print"]["param"] = gcode_str;
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
if (m_agent) {
j["print"]["user_id"] = m_agent->get_user_id();
json t;
t["dev_id"] = this->dev_id;
t["signal"] = this->wifi_signal;
m_agent->track_event("cmd_gcode_line", t.dump());
}
return publish_json(j.dump());
}

View file

@ -12,7 +12,7 @@
#include "slic3r/Utils/json_diff.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "CameraPopup.hpp"
#include "libslic3r/Calib.hpp"
#include "libslic3r/calib.hpp"
#define USE_LOCAL_SOCKET_BIND 0

View file

@ -49,9 +49,9 @@ DownloadProgressDialog::DownloadProgressDialog(wxString title)
m_simplebook_status = new wxSimplebook(this);
m_simplebook_status->SetSize(wxSize(FromDIP(400), -1));
m_simplebook_status->SetMinSize(wxSize(FromDIP(400), -1));
m_simplebook_status->SetMaxSize(wxSize(FromDIP(400), -1));
m_simplebook_status->SetSize(wxSize(FromDIP(400), FromDIP(70)));
m_simplebook_status->SetMinSize(wxSize(FromDIP(400), FromDIP(70)));
m_simplebook_status->SetMaxSize(wxSize(FromDIP(400), FromDIP(70)));
//mode normal
m_status_bar = std::make_shared<BBLStatusBarSend>(m_simplebook_status);

View file

@ -169,7 +169,7 @@ void ExtrusionCalibration::create()
m_error_text->Hide();
m_button_cali = new Button(m_step_1_panel, _L("Start calibration"));
m_btn_bg_green = StateColor(std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Disabled), std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
m_btn_bg_green = StateColor(std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Disabled), std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed), std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
m_button_cali->SetBackgroundColor(m_btn_bg_green);
m_button_cali->SetFont(Label::Body_13);
@ -180,7 +180,7 @@ void ExtrusionCalibration::create()
m_button_cali->Bind(wxEVT_BUTTON, &ExtrusionCalibration::on_click_cali, this);
m_cali_cancel = new Button(m_step_1_panel, _L("Cancel"));
m_btn_bg_green = StateColor(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
m_btn_bg_green = StateColor(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed), std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
m_cali_cancel->SetBackgroundColor(m_btn_bg_green);
m_cali_cancel->SetBorderColor(wxColour(0, 150, 136));
@ -255,7 +255,7 @@ void ExtrusionCalibration::create()
// save button
m_button_save_result = new Button(m_step_2_panel, _L("Save"));
m_btn_bg_green = StateColor(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
m_btn_bg_green = StateColor(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed), std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
m_button_save_result->SetBackgroundColor(m_btn_bg_green);
m_button_save_result->SetFont(Label::Body_13);

View file

@ -385,7 +385,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
wxString y_str = thumbnail.GetNextToken();
if (y_str.ToDouble(&y) && !thumbnail.HasMoreTokens()) {
if (m_opt_id == "bed_exclude_area") {
if (0 <= x && x <= 256 && 0 <= y && y <= 256) {
if (0 <= x && 0 <= y) {
out_values.push_back(Vec2d(x, y));
continue;
}
@ -511,7 +511,7 @@ void TextCtrl::BUILD() {
m_combine_side_text = !m_opt.multiline;
if (parent_is_custom_ctrl && m_opt.height < 0)
opt_height = (double) text_ctrl->GetSize().GetHeight() / m_em_unit;
if (m_opt.is_code) // BBS
if (m_opt.is_code)
temp->SetFont(Slic3r::GUI::wxGetApp().normal_font());
@ -1383,8 +1383,7 @@ boost::any& Choice::get_value()
{
if (m_opt.nullable && field->GetSelection() == -1)
m_value = ConfigOptionEnumsGenericNullable::nil_value();
else if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "internal_solid_infill_pattern" || m_opt_id == "sparse_infill_pattern" ||
m_opt_id == "support_style") {
else if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "internal_solid_infill_pattern" || m_opt_id == "sparse_infill_pattern" || m_opt_id == "support_style") {
const std::string& key = m_opt.enum_values[field->GetSelection()];
m_value = int(m_opt.enum_keys_map->at(key));
}

View file

@ -327,7 +327,7 @@ void GCodeViewer::SequentialRangeCap::reset() {
void GCodeViewer::SequentialView::Marker::init(std::string filename)
{
if (filename.empty()) {
m_model.init_from(stilized_arrow(16, 1.5f, 3.0f, 0.8f, 3.0f));
//m_model.init_from(stilized_arrow(16, 1.5f, 3.0f, 0.8f, 3.0f));
} else {
m_model.init_from_file(filename);
}
@ -1160,9 +1160,6 @@ void GCodeViewer::refresh(const GCodeProcessorResult& gcode_result, const std::v
for (auto item : m_tools.m_tool_visibles) item = true;
}
for (int i = 0; i < m_tools.m_tool_colors.size(); i++) {
m_tools.m_tool_colors[i] = adjust_color_for_rendering(m_tools.m_tool_colors[i]);
}
// ensure there are enough colors defined
while (m_tools.m_tool_colors.size() < std::max(size_t(1), gcode_result.extruders_count)) {
m_tools.m_tool_colors.push_back(decode_color("#FF8000"));
@ -1188,7 +1185,7 @@ void GCodeViewer::refresh(const GCodeProcessorResult& gcode_result, const std::v
m_extrusions.ranges.temperature.update_from(curr.temperature);
if (curr.extrusion_role != erCustom || is_visible(erCustom))
m_extrusions.ranges.volumetric_rate.update_from(round_to_bin(curr.volumetric_rate()));
if (curr.layer_duration > 0.f) {
m_extrusions.ranges.layer_duration.update_from(curr.layer_duration);
m_extrusions.ranges.layer_duration_log.update_from(curr.layer_duration);
@ -1226,7 +1223,7 @@ void GCodeViewer::refresh_render_paths()
void GCodeViewer::update_shells_color_by_extruder(const DynamicPrintConfig* config)
{
if (config != nullptr)
m_shells.volumes.update_colors_by_extruder(config,false);
m_shells.volumes.update_colors_by_extruder(config);
}
//BBS: always load shell at preview
@ -3842,7 +3839,7 @@ void GCodeViewer::render_toolpaths()
#if ENABLE_GCODE_VIEWER_STATISTICS
this
#endif // ENABLE_GCODE_VIEWER_STATISTICS
](std::vector<RenderPath>::reverse_iterator it_path, std::vector<RenderPath>::reverse_iterator it_end, GLShaderProgram& shader, int uniform_color) {
](std::vector<RenderPath>::iterator it_path, std::vector<RenderPath>::iterator it_end, GLShaderProgram& shader, int uniform_color) {
glsafe(::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE));
glsafe(::glEnable(GL_POINT_SPRITE));
@ -3869,7 +3866,7 @@ void GCodeViewer::render_toolpaths()
#if ENABLE_GCODE_VIEWER_STATISTICS
this
#endif // ENABLE_GCODE_VIEWER_STATISTICS
](std::vector<RenderPath>::reverse_iterator it_path, std::vector<RenderPath>::reverse_iterator it_end, GLShaderProgram& shader, int uniform_color) {
](std::vector<RenderPath>::iterator it_path, std::vector<RenderPath>::iterator it_end, GLShaderProgram& shader, int uniform_color) {
for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) {
const RenderPath& path = *it;
// Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415.
@ -3887,7 +3884,7 @@ void GCodeViewer::render_toolpaths()
#if ENABLE_GCODE_VIEWER_STATISTICS
this
#endif // ENABLE_GCODE_VIEWER_STATISTICS
](std::vector<RenderPath>::reverse_iterator it_path, std::vector<RenderPath>::reverse_iterator it_end, GLShaderProgram& shader, int uniform_color) {
](std::vector<RenderPath>::iterator it_path, std::vector<RenderPath>::iterator it_end, GLShaderProgram& shader, int uniform_color) {
for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) {
const RenderPath& path = *it;
// Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415.
@ -4017,15 +4014,13 @@ void GCodeViewer::render_toolpaths()
default: break;
}
int uniform_color = shader->get_uniform_location("uniform_color");
auto it_path = buffer.render_paths.rbegin();
auto it_path = buffer.render_paths.begin();
//BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":buffer indices size %1%, render_path size %2% ")%buffer.indices.size() %buffer.render_paths.size();
unsigned int indices_count = static_cast<unsigned int>(buffer.indices.size());
for (unsigned int index = 0; index < indices_count; ++index) {
unsigned int ibuffer_id = indices_count - index - 1;
for (unsigned int ibuffer_id = 0; ibuffer_id < static_cast<unsigned int>(buffer.indices.size()); ++ibuffer_id) {
const IBuffer& i_buffer = buffer.indices[ibuffer_id];
// Skip all paths with ibuffer_id < ibuffer_id.
for (; it_path != buffer.render_paths.rend() && it_path->ibuffer_id > ibuffer_id; ++ it_path) ;
if (it_path == buffer.render_paths.rend() || it_path->ibuffer_id < ibuffer_id)
for (; it_path != buffer.render_paths.end() && it_path->ibuffer_id < ibuffer_id; ++ it_path) ;
if (it_path == buffer.render_paths.end() || it_path->ibuffer_id > ibuffer_id)
// Not found. This shall not happen.
continue;
@ -4044,16 +4039,16 @@ void GCodeViewer::render_toolpaths()
switch (buffer.render_primitive_type)
{
case TBuffer::ERenderPrimitiveType::Point: {
render_as_points(it_path, buffer.render_paths.rend(), *shader, uniform_color);
render_as_points(it_path, buffer.render_paths.end(), *shader, uniform_color);
break;
}
case TBuffer::ERenderPrimitiveType::Line: {
glsafe(::glLineWidth(static_cast<GLfloat>(line_width(zoom))));
render_as_lines(it_path, buffer.render_paths.rend(), *shader, uniform_color);
render_as_lines(it_path, buffer.render_paths.end(), *shader, uniform_color);
break;
}
case TBuffer::ERenderPrimitiveType::Triangle: {
render_as_triangles(it_path, buffer.render_paths.rend(), *shader, uniform_color);
render_as_triangles(it_path, buffer.render_paths.end(), *shader, uniform_color);
break;
}
default: { break; }
@ -4176,10 +4171,6 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
std::vector<float> filament_densities = gcode_result_list.front()->filament_densities;
std::vector<Color> filament_colors = decode_colors(wxGetApp().plater()->get_extruder_colors_from_plater_config(gcode_result_list.back()));
for (int i = 0; i < filament_colors.size(); i++) {
filament_colors[i] = adjust_color_for_rendering(filament_colors[i]);
}
bool imperial_units = wxGetApp().app_config->get("use_inches") == "1";
float window_padding = 4.0f * m_scale;
const float icon_size = ImGui::GetTextLineHeight() * 0.7;
@ -4323,20 +4314,18 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
columns_offsets.push_back({ std::to_string(it->first + 1), offsets[0] });
char buf[64];
double unit_conver = imperial_units ? GizmoObjectManipulation::oz_to_g : 1.0;
if (show_detailed_statistics_page) {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i]);
columns_offsets.push_back({ buf, offsets[1] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m_all_plates[i], flushed_filaments_g_all_plates[i] / unit_conver);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m_all_plates[i], flushed_filaments_g_all_plates[i]);
columns_offsets.push_back({ buf, offsets[2] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", (model_used_filaments_m_all_plates[i] + flushed_filaments_m_all_plates[i]),
(model_used_filaments_g_all_plates[i] + flushed_filaments_g_all_plates[i]) / unit_conver);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i] + flushed_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] + flushed_filaments_g_all_plates[i]);
columns_offsets.push_back({ buf, offsets[3] });
}
else {
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver);
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i]);
columns_offsets.push_back({ buf, offsets[2] });
}
@ -4430,21 +4419,21 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
default:
case EItemType::Rect: {
draw_list->AddRectFilled({ pos.x + 1.0f * m_scale, pos.y + 3.0f * m_scale }, { pos.x + icon_size - 1.0f * m_scale, pos.y + icon_size + 1.0f * m_scale },
ImGui::GetColorU32({color[0], color[1], color[2], color[3]}));
ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }));
break;
}
case EItemType::Circle: {
ImVec2 center(0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size + 5.0f));
draw_list->AddCircleFilled(center, 0.5f * icon_size, ImGui::GetColorU32({color[0], color[1], color[2], color[3]}), 16);
draw_list->AddCircleFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16);
break;
}
case EItemType::Hexagon: {
ImVec2 center(0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size + 5.0f));
draw_list->AddNgonFilled(center, 0.5f * icon_size, ImGui::GetColorU32({color[0], color[1], color[2], color[3]}), 6);
draw_list->AddNgonFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 6);
break;
}
case EItemType::Line: {
draw_list->AddLine({pos.x + 1, pos.y + icon_size + 2}, {pos.x + icon_size - 1, pos.y + 4}, ImGui::GetColorU32({color[0], color[1], color[2], color[3]}), 3.0f);
draw_list->AddLine({ pos.x + 1, pos.y + icon_size + 2 }, { pos.x + icon_size - 1, pos.y + 4 }, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 3.0f);
break;
case EItemType::None:
break;
@ -4959,7 +4948,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
columns_offsets.push_back({ std::to_string(extruder_idx + 1), offsets[0] });
char buf[64];
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m[0], model_used_filaments_g[0] / unit_conver);
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m[0] , model_used_filaments_g[0]);
columns_offsets.push_back({ buf, offsets[2] });
append_item(EItemType::Rect, m_tools.m_tool_colors[extruder_idx], columns_offsets, false);
@ -4993,20 +4982,19 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
char buf[64];
if (show_flushed_filaments) {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m[i], model_used_filaments_g[i] / unit_conver);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m[i], model_used_filaments_g[i]);
columns_offsets.push_back({ buf, offsets[1] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m[i], flushed_filaments_g[i] / unit_conver);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m[i], flushed_filaments_g[i]);
columns_offsets.push_back({ buf, offsets[2] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", (model_used_filaments_m[i] + flushed_filaments_m[i]),
(model_used_filaments_g[i] + flushed_filaments_g[i]) / unit_conver);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m[i] + flushed_filaments_m[i], model_used_filaments_g[i] + flushed_filaments_g[i]);
columns_offsets.push_back({ buf, offsets[3] });
}
else {
char buf[64];
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m[i], model_used_filaments_g[i] / unit_conver);
columns_offsets.push_back({buf, offsets[2]});
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m[i], model_used_filaments_g[i]);
columns_offsets.push_back({ buf, offsets[2] });
}
append_item(EItemType::Rect, m_tools.m_tool_colors[extruder_idx], columns_offsets, false, filament_visible, [this, extruder_idx]() {
@ -5055,20 +5043,20 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
std::vector<std::pair<std::string, float>> columns_offsets;
columns_offsets.push_back({ _u8L("Total"), offsets[0] });
if (!show_flushed_filaments) {
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", total_model_used_filament_m, total_model_used_filament_g / unit_conver);
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", total_model_used_filament_m, total_model_used_filament_g);
columns_offsets.push_back({ buf, offsets[2] });
append_item(EItemType::None, m_tools.m_tool_colors[0], columns_offsets);
}
else {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m, total_model_used_filament_g / unit_conver);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m, total_model_used_filament_g);
columns_offsets.push_back({ buf, offsets[1] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_flushed_filament_m, total_flushed_filament_g / unit_conver);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_flushed_filament_m, total_flushed_filament_g);
columns_offsets.push_back({ buf, offsets[2] });
bool imperial_units = wxGetApp().app_config->get("use_inches") == "1";
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m + total_flushed_filament_m, (total_model_used_filament_g + total_flushed_filament_g) / unit_conver);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", (total_model_used_filament_m + total_flushed_filament_m) * 1000 / /*1000*/koef, (total_model_used_filament_g + total_flushed_filament_g) / unit_conver);
columns_offsets.push_back({ buf, offsets[3] });
append_item(EItemType::None, m_tools.m_tool_colors[0], columns_offsets);

View file

@ -492,7 +492,7 @@ class GCodeViewer
std::vector<Endpoints>& get_endpoints() { return m_endpoints; }
double get_z_at(unsigned int id) const { return (id < m_zs.size()) ? m_zs[id] : 0.0; }
Endpoints get_endpoints_at(unsigned int id) const { return (id < m_endpoints.size()) ? m_endpoints[id] : Endpoints(); }
int get_l_at(float z) const
int get_l_at(double z) const
{
auto iter = std::upper_bound(m_zs.begin(), m_zs.end(), z);
return std::distance(m_zs.begin(), iter);
@ -737,6 +737,7 @@ public:
//BBS
ConflictResultOpt m_conflict_result;
private:
std::vector<int> m_plater_extruder;
bool m_gl_data_initialized{ false };

View file

@ -119,7 +119,7 @@ RetinaHelper::~RetinaHelper() {}
float RetinaHelper::get_scale_factor() { return float(m_window->GetContentScaleFactor()); }
#endif // __WXGTK3__
// Fixed the collision between BuildVolume::Type::Convex and macro Convex defined inside /usr/include/X11/X.h that is included by WxWidgets 3.0.
// Fixed the collision between BuildVolume_Type::Convex and macro Convex defined inside /usr/include/X11/X.h that is included by WxWidgets 3.0.
#if defined(__linux__) && defined(Convex)
#undef Convex
#endif
@ -287,7 +287,7 @@ void GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(const GLCanv
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 0.00f));
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 0.00f));
ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImVec4(0.81f, 0.81f, 0.81f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_SliderGrabActive, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_SliderGrabActive, ImVec4(0.00f, 0.59f, 0.53f, 1.00f));
if(ImGui::BBLSliderScalar("##radius_slider", ImGuiDataType_S32, &radius, &v_min, &v_max)){
radius = std::clamp(radius, 1, 10);
m_smooth_params.radius = (unsigned int)radius;
@ -298,9 +298,9 @@ void GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(const GLCanv
input_align = std::max(input_align, ImGui::GetCursorPosX());
ImGui::SetCursorPosX(input_align);
ImGui::PushItemWidth(input_box_width);
ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0.00f, 0.68f, 0.26f, 0.00f));
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(0.00f, 0.68f, 0.26f, 0.00f));
ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.00f, 0.59f, 0.53f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0.00f, 0.59f, 0.53f, 0.00f));
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(0.00f, 0.59f, 0.53f, 0.00f));
ImGui::BBLDragScalar("##radius_input", ImGuiDataType_S32, &radius, 1, &v_min, &v_max);
ImGui::PopStyleColor(3);
@ -1047,22 +1047,30 @@ const double GLCanvas3D::DefaultCameraZoomToPlateMarginFactor = 1.25;
void GLCanvas3D::load_arrange_settings()
{
std::string dist_fff_str =
wxGetApp().app_config->get("arrange", "min_object_distance");
wxGetApp().app_config->get("arrange", "min_object_distance_fff");
std::string dist_fff_seq_print_str =
wxGetApp().app_config->get("arrange", "min_object_distance_seq_print");
wxGetApp().app_config->get("arrange", "min_object_distance_seq_print_fff");
std::string dist_sla_str =
wxGetApp().app_config->get("arrange", "min_object_distance_sla");
std::string en_rot_fff_str =
wxGetApp().app_config->get("arrange", "enable_rotation");
wxGetApp().app_config->get("arrange", "enable_rotation_fff");
std::string en_rot_fff_seqp_str =
wxGetApp().app_config->get("arrange", "enable_rotation_seq_print");
std::string en_rot_sla_str =
wxGetApp().app_config->get("arrange", "enable_rotation_sla");
std::string en_allow_multiple_materials_str =
wxGetApp().app_config->get("arrange", "allow_multi_materials_on_same_plate");
std::string en_avoid_region_str =
wxGetApp().app_config->get("arrange", "avoid_extrusion_cali_region");
if (!dist_fff_str.empty())
m_arrange_settings_fff.distance = std::stof(dist_fff_str);
@ -1074,13 +1082,20 @@ void GLCanvas3D::load_arrange_settings()
m_arrange_settings_sla.distance = std::stof(dist_sla_str);
if (!en_rot_fff_str.empty())
m_arrange_settings_fff.enable_rotation = (en_rot_fff_str == "1" || en_rot_fff_str == "yes");
m_arrange_settings_fff.enable_rotation = (en_rot_fff_str == "1" || en_rot_fff_str == "true");
if (!en_allow_multiple_materials_str.empty())
m_arrange_settings_fff.allow_multi_materials_on_same_plate = (en_allow_multiple_materials_str == "1" || en_allow_multiple_materials_str == "true");
if (!en_rot_fff_seqp_str.empty())
m_arrange_settings_fff_seq_print.enable_rotation = (en_rot_fff_seqp_str == "1" || en_rot_fff_seqp_str == "yes");
m_arrange_settings_fff_seq_print.enable_rotation = (en_rot_fff_seqp_str == "1" || en_rot_fff_seqp_str == "true");
if(!en_avoid_region_str.empty())
m_arrange_settings_fff.avoid_extrusion_cali_region = (en_avoid_region_str == "1" || en_avoid_region_str == "true");
if (!en_rot_sla_str.empty())
m_arrange_settings_sla.enable_rotation = (en_rot_sla_str == "1" || en_rot_sla_str == "yes");
m_arrange_settings_sla.enable_rotation = (en_rot_sla_str == "1" || en_rot_sla_str == "true");
//BBS: add specific arrange settings
m_arrange_settings_fff_seq_print.is_seq_print = true;
@ -3118,12 +3133,15 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
case WXK_BACK: { post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE)); break; }
#endif
case WXK_ESCAPE: { deselect_all(); break; }
//case WXK_F5: {
// if ((wxGetApp().is_editor() && !wxGetApp().plater()->model().objects.empty()) ||
// (wxGetApp().is_gcode_viewer() && !wxGetApp().plater()->get_last_loaded_gcode().empty()))
// post_event(SimpleEvent(EVT_GLCANVAS_RELOAD_FROM_DISK));
// break;
//}
case WXK_F5: {
if (wxGetApp().mainframe->is_printer_view())
wxGetApp().mainframe->load_printer_url();
//if ((wxGetApp().is_editor() && !wxGetApp().plater()->model().objects.empty()) ||
// (wxGetApp().is_gcode_viewer() && !wxGetApp().plater()->get_last_loaded_gcode().empty()))
// post_event(SimpleEvent(EVT_GLCANVAS_RELOAD_FROM_DISK));
break;
}
// BBS: use keypad to change extruder
case '1':
@ -3175,10 +3193,8 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
}
//case 'B':
//case 'b': { zoom_to_bed(); break; }
#if !BBL_RELEASE_TO_PUBLIC
case 'C':
case 'c': { m_gcode_viewer.toggle_gcode_window_visibility(); m_dirty = true; request_extra_frame(); break; }
#endif
//case 'G':
//case 'g': {
// if ((evt.GetModifiers() & shiftMask) != 0) {
@ -3376,7 +3392,11 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
else if (m_tab_down && keyCode == WXK_TAB && !evt.HasAnyModifiers()) {
// Enable switching between 3D and Preview with Tab
// m_canvas->HandleAsNavigationKey(evt); // XXX: Doesn't work in some cases / on Linux
//post_event(SimpleEvent(EVT_GLCANVAS_TAB));
post_event(SimpleEvent(EVT_GLCANVAS_TAB));
}
else if (keyCode == WXK_TAB && evt.ShiftDown() && !evt.ControlDown() && ! wxGetApp().is_gcode_viewer()) {
// Collapse side-panel with Shift+Tab
post_event(SimpleEvent(EVT_GLCANVAS_COLLAPSE_SIDEBAR));
}
else if (keyCode == WXK_SHIFT) {
translationProcessor.process(evt);
@ -5044,7 +5064,7 @@ void GLCanvas3D::update_sequential_clearance()
// the results are then cached for following displacements
if (m_sequential_print_clearance_first_displacement) {
m_sequential_print_clearance.m_hull_2d_cache.clear();
float shrink_factor = static_cast<float>(scale_(0.5 * fff_print()->config().extruder_clearance_max_radius.value - EPSILON));
float shrink_factor = static_cast<float>(scale_(0.5 * fff_print()->config().extruder_clearance_radius.value - EPSILON));
double mitter_limit = scale_(0.1);
m_sequential_print_clearance.m_hull_2d_cache.reserve(m_model->objects.size());
for (size_t i = 0; i < m_model->objects.size(); ++i) {
@ -5395,20 +5415,22 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
ImGui::Separator();
if (imgui->bbl_checkbox(_L("Auto rotate for arrangement"), settings.enable_rotation)) {
settings_out.enable_rotation = settings.enable_rotation;
appcfg->set("arrange", rot_key.c_str(), settings_out.enable_rotation? "1" : "0");
appcfg->set("arrange", rot_key.c_str(), settings_out.enable_rotation);
settings_changed = true;
}
if (imgui->bbl_checkbox(_L("Allow multiple materials on same plate"), settings.allow_multi_materials_on_same_plate)) {
settings_out.allow_multi_materials_on_same_plate = settings.allow_multi_materials_on_same_plate;
appcfg->set("arrange", multi_material_key.c_str(), settings_out.allow_multi_materials_on_same_plate ? "1" : "0");
appcfg->set("arrange", multi_material_key.c_str(), settings_out.allow_multi_materials_on_same_plate );
settings_changed = true;
}
// only show this option if the printer has micro Lidar and can do first layer scan
DynamicPrintConfig &current_config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
const bool has_lidar = preset_bundle->printers.get_edited_preset().has_lidar(preset_bundle);
auto op = current_config.option("scan_first_layer");
if (op && op->getBool()) {
if (has_lidar && op && op->getBool()) {
if (imgui->bbl_checkbox(_L("Avoid extrusion calibration region"), settings.avoid_extrusion_cali_region)) {
settings_out.avoid_extrusion_cali_region = settings.avoid_extrusion_cali_region;
appcfg->set("arrange", avoid_extrusion_key.c_str(), settings_out.avoid_extrusion_cali_region ? "1" : "0");
@ -5567,25 +5589,19 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
//camera.select_view("top");
}
else {
//camera.zoom_to_box(volumes_box);
//const Vec3d& target = camera.get_target();
//double distance = camera.get_distance();
//camera.look_at(target - 0.707 * distance * Vec3d::UnitY() + 0.3 * distance * Vec3d::UnitZ(), target, Vec3d::UnitY() + Vec3d::UnitZ());
//BBS: use original iso view for thumbnail
camera.select_view("iso");
camera.zoom_to_box(volumes_box);
const Vec3d& target = camera.get_target();
double distance = camera.get_distance();
camera.select_view("iso");
camera.apply_view_matrix();
camera.apply_projection(plate_build_volume);
}
camera.apply_view_matrix();
camera.apply_projection(plate_build_volume);
//double near_z = -1.0;
//double far_z = -1.0;
//camera.apply_projection(volumes_box, near_z, far_z);
//GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
if (!for_picking && (shader == nullptr)) {
BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail with no picking: shader is null, return directly");
@ -5593,17 +5609,8 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
}
//if (thumbnail_params.transparent_background)
if (for_picking)
glsafe(::glClearColor(0.f, 0.f, 0.f, 0.f));
else {
//glsafe(::glClearColor(0.906f, 0.906f, 0.906f, 1.0f));
//glsafe(::glClearColor(0.50f, 0.5f, 0.5f, 1.0f));
//glsafe(::glClearColor(0.121568f, 0.121568f, 0.121568f, 1.0f));
//glsafe(::glClearColor(0.17647f, 0.17647f, 0.17647f, 1.0f));
//glsafe(::glClearColor(0.906f, 0.906f, 0.906f, 1.0f));
//glsafe(::glClearColor(0.37647f, 0.37647f, 0.37647f, 0.5f)); too lite
glsafe(::glClearColor(0.0f, 0.0f, 0.0f, 0.0f));
}
glsafe(::glClearColor(0.f, 0.f, 0.f, 0.f));
glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
glsafe(::glEnable(GL_DEPTH_TEST));
@ -6105,12 +6112,7 @@ bool GLCanvas3D::_init_main_toolbar()
item.icon_filename = m_is_dark ? "toolbar_arrange_dark.svg" : "toolbar_arrange.svg";
item.tooltip = _utf8(L("Arrange all objects")) + " [A]\n" + _utf8(L("Arrange objects on selected plates")) + " [Shift+A]";
item.sprite_id++;
item.left.action_callback = [this]() {
if (m_canvas != nullptr) {
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_update_property("auto_arrange", std::to_string(++auto_arrange_count));
}
};
item.left.action_callback = []() {};
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_arrange(); };
item.left.toggable = true;
//BBS: GUI refactor: adjust the main toolbar position
@ -6135,13 +6137,7 @@ bool GLCanvas3D::_init_main_toolbar()
item.tooltip = _utf8(L("Split to objects"));
item.sprite_id++;
item.left.render_callback = nullptr;
item.left.action_callback = [this]() {
if (m_canvas != nullptr) {
wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS));
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_update_property("split_to_objects", std::to_string(++split_to_objects_count));
}
};
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS)); };
item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); };
if (!m_main_toolbar.add_item(item))
@ -6151,13 +6147,7 @@ bool GLCanvas3D::_init_main_toolbar()
item.icon_filename = m_is_dark ? "split_parts_dark.svg" : "split_parts.svg";
item.tooltip = _utf8(L("Split to parts"));
item.sprite_id++;
item.left.action_callback = [this]() {
if (m_canvas != nullptr) {
wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_VOLUMES));
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_update_property("split_to_part", std::to_string(++split_to_part_count));
}
};
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_VOLUMES)); };
item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_split_to_volumes(); };
if (!m_main_toolbar.add_item(item))
@ -6167,13 +6157,7 @@ bool GLCanvas3D::_init_main_toolbar()
item.icon_filename = m_is_dark ? "toolbar_variable_layer_height_dark.svg" : "toolbar_variable_layer_height.svg";
item.tooltip = _utf8(L("Variable layer height"));
item.sprite_id++;
item.left.action_callback = [this]() {
if (m_canvas != nullptr) {
wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING));
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_update_property("custom_height", std::to_string(++custom_height_count));
}
};
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING)); };
item.visibility_callback = [this]()->bool {
bool res = current_printer_technology() == ptFFF;
// turns off if changing printer technology
@ -6197,6 +6181,7 @@ bool GLCanvas3D::_init_select_plate_toolbar()
bool result = item->image_texture.load_from_svg_file(path + "im_all_plates_stats.svg", false, false, false, 128);
result = result && item->image_texture_transparent.load_from_svg_file(path + "im_all_plates_stats_transparent.svg", false, false, false, 128);
m_sel_plate_toolbar.m_all_plates_stats_item = item;
return result;
}
@ -6276,13 +6261,7 @@ bool GLCanvas3D::_init_assemble_view_toolbar()
item.tooltip = _utf8(L("Assembly View"));
item.sprite_id = 1;
item.left.toggable = false;
item.left.action_callback = [this]() {
if (m_canvas != nullptr) {
wxPostEvent(m_canvas, SimpleEvent(EVT_GLVIEWTOOLBAR_ASSEMBLE)); m_gizmos.reset_all_states(); wxGetApp().plater()->get_assmeble_canvas3D()->get_gizmos_manager().reset_all_states();
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_update_property("custom_painting", std::to_string(++custom_painting_count));
}
};
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLVIEWTOOLBAR_ASSEMBLE)); };
item.left.render_callback = GLToolbarItem::Default_Render_Callback;
item.visible = true;
item.visibility_callback = [this]()->bool { return true; };
@ -6751,22 +6730,22 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
if (const BuildVolume &build_volume = m_bed.build_volume(); build_volume.valid()) {
switch (build_volume.type()) {
case BuildVolume::Type::Rectangle: {
case BuildVolume_Type::Rectangle: {
const BoundingBox3Base<Vec3d> bed_bb = build_volume.bounding_volume().inflated(BuildVolume::SceneEpsilon);
m_volumes.set_print_volume({ 0, // Rectangle
{ float(bed_bb.min.x()), float(bed_bb.min.y()), float(bed_bb.max.x()), float(bed_bb.max.y()) },
{ 0.0f, float(build_volume.printable_height()) } });
break;
}
case BuildVolume::Type::Circle: {
case BuildVolume_Type::Circle: {
m_volumes.set_print_volume({ 1, // Circle
{ unscaled<float>(build_volume.circle().center.x()), unscaled<float>(build_volume.circle().center.y()), unscaled<float>(build_volume.circle().radius + BuildVolume::SceneEpsilon), 0.0f },
{ 0.0f, float(build_volume.printable_height() + BuildVolume::SceneEpsilon) } });
break;
}
default:
case BuildVolume::Type::Convex:
case BuildVolume::Type::Custom: {
case BuildVolume_Type::Convex:
case BuildVolume_Type::Custom: {
m_volumes.set_print_volume({ static_cast<int>(type),
{ -FLT_MAX, -FLT_MAX, FLT_MAX, FLT_MAX },
{ -FLT_MAX, FLT_MAX } }
@ -8999,8 +8978,8 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
std::string objName2 = m_gcode_viewer.m_conflict_result.value()._objName2;
double height = m_gcode_viewer.m_conflict_result.value()._height;
int layer = m_gcode_viewer.m_conflict_result.value().layer;
text = (boost::format(_u8L("Conflicts of gcode paths have been found at layer %d. Please separate the conflicted objects farther (%s <-> %s).")) % (layer + 1) %
objName1 % objName2)
text = (boost::format(_u8L("Conflicts of gcode paths have been found at layer %d, z = %.2lf mm. Please separate the conflicted objects farther (%s <-> %s).")) % layer %
height % objName1 % objName2)
.str();
prevConflictText = text;
const PrintObject *obj2 = reinterpret_cast<const PrintObject *>(m_gcode_viewer.m_conflict_result.value()._obj2);

View file

@ -414,7 +414,6 @@ class GLCanvas3D
void render(const std::vector<const ModelInstance*>& sorted_instances) const;
};
class Tooltip
{
std::string m_text;
@ -597,7 +596,6 @@ private:
Labels m_labels;
Tooltip m_tooltip;
bool m_tooltip_enabled{ true };
Slope m_slope;
OrientSettings m_orient_settings_fff, m_orient_settings_sla;

View file

@ -516,9 +516,11 @@ bool GLTexture::generate_from_text(const std::string &text_str, wxFont &font, wx
// prepare buffer
std::vector<unsigned char> data(4 * m_width * m_height, 0);
const unsigned char* src = image.GetData();
//for debug use
//image.SaveFile(text_str+"_test.png", wxBITMAP_TYPE_PNG);
/* for debug use
std::ofstream fout;
fout.open(text_str+std::to_string(m_width)+"_"+std::to_string(m_height)+".rgb", std::ios::out);
fout.write((const char*)src, 3 * m_width * m_height);
fout.close();*/
for (int h = 0; h < m_height; ++h) {
unsigned char* dst = data.data() + 4 * h * m_width;
for (int w = 0; w < m_width; ++w) {

View file

@ -32,7 +32,6 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_PRINT_SELECT, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER_ALL, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent);

View file

@ -32,7 +32,6 @@ wxDECLARE_EVENT(EVT_GLTOOLBAR_PRINT_SELECT, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER_ALL, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent);

View file

@ -554,7 +554,7 @@ void desktop_open_any_folder( const std::string path )
#elif __APPLE__
openFolderForFile(from_u8(path));
#else
const char *argv[] = {"nautilus", path.data(), nullptr};
const char *argv[] = {"xdg-open", path.data(), nullptr};
// Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars,
// because they may mess up the environment expected by the file manager.

View file

@ -188,7 +188,7 @@ bool is_associate_files(std::wstring extend)
wchar_t app_path[MAX_PATH];
::GetModuleFileNameW(nullptr, app_path, sizeof(app_path));
std::wstring prog_id = L" Bambu.Studio.1";
std::wstring prog_id = L" Orca.Slicer.1";
std::wstring reg_base = L"Software\\Classes";
std::wstring reg_extension = reg_base + L"\\." + extend;
@ -298,14 +298,13 @@ public:
memDc.SetTextForeground(StateColor::darkModeColorFor(wxColor(134, 134, 134)));
memDc.DrawLabel(m_constant_text.version, version_rect, wxALIGN_LEFT | wxALIGN_BOTTOM);
#if BBL_INTERNAL_TESTING
wxSize text_rect = memDc.GetTextExtent("Internal Version");
int start_x = (title_rect.GetLeft() + version_rect.GetRight()) / 2 - text_rect.GetWidth();
auto bs_version = wxString::Format("Based on BambuStudio and PrusaSlicer").ToStdString();
memDc.SetFont(Label::Body_12);
wxSize text_rect = memDc.GetTextExtent(bs_version);
int start_x = (title_rect.GetLeft() + version_rect.GetRight()) / 2 - text_rect.GetWidth()/2;
int start_y = version_rect.GetBottom() + 10;
wxRect internal_sign_rect(wxPoint(start_x, start_y), wxSize(text_rect));
memDc.SetFont(m_constant_text.title_font);
memDc.DrawLabel("Internal Version", internal_sign_rect, wxALIGN_TOP | wxALIGN_LEFT);
#endif
memDc.DrawLabel(bs_version, internal_sign_rect, wxALIGN_RIGHT);
// load bitmap for logo
BitmapCache bmp_cache;
@ -573,12 +572,11 @@ private:
title = wxGetApp().is_editor() ? SLIC3R_APP_FULL_NAME : GCODEVIEWER_APP_NAME;
// dynamically get the version to display
auto version_text = GUI_App::format_display_version();
#if BBL_INTERNAL_TESTING
version = _L("Internal Version") + " " + std::string(version_text);
#else
version = _L("Version") + " " + std::string(version_text);
#endif
// #if BBL_INTERNAL_TESTING
// version = _L("Internal Version") + " " + std::string(SLIC3R_VERSION);
// #else
// version = _L("") + " " + std::string(SoftFever_VERSION);
// #endif
// credits infornation
credits = title;
@ -738,7 +736,7 @@ static const FileWildcards file_wildcards_by_type[FT_SIZE] = {
/* FT_OBJ */ { "OBJ files"sv, { ".obj"sv } },
/* FT_AMF */ { "AMF files"sv, { ".amf"sv, ".zip.amf"sv, ".xml"sv } },
/* FT_3MF */ { "3MF files"sv, { ".3mf"sv } },
/* FT_GCODE */ { "G-code files"sv, { ".gcode"sv } },
/* FT_GCODE */ { "G-code files"sv, { ".gcode"sv, ".3mf"sv } },
/* FT_MODEL */ {"Supported files"sv, {".3mf"sv, ".stl"sv, ".stp"sv, ".step"sv, ".svg"sv, ".amf"sv, ".obj"sv }},
/* FT_PROJECT */ { "Project files"sv, { ".3mf"sv} },
/* FT_GALLERY */ { "Known files"sv, { ".stl"sv, ".obj"sv } },
@ -962,22 +960,22 @@ static void generic_exception_handle()
// and terminate the app so it is at least certain to happen now.
BOOST_LOG_TRIVIAL(error) << boost::format("std::bad_alloc exception: %1%") % ex.what();
flush_logs();
wxString errmsg = wxString::Format(_L("BambuStudio will terminate because of running out of memory."
wxString errmsg = wxString::Format(_L("OrcaSlicer will terminate because of running out of memory."
"It may be a bug. It will be appreciated if you report the issue to our team."));
wxMessageBox(errmsg + "\n\n" + wxString(ex.what()), _L("Fatal error"), wxOK | wxICON_ERROR);
std::terminate();
//throw;
} catch (const boost::io::bad_format_string& ex) {
BOOST_LOG_TRIVIAL(error) << boost::format("Uncaught exception: %1%") % ex.what();
flush_logs();
wxString errmsg = _L("BambuStudio will terminate because of a localization error. "
BOOST_LOG_TRIVIAL(error) << boost::format("Uncaught exception: %1%") % ex.what();
flush_logs();
wxString errmsg = _L("OrcaSlicer will terminate because of a localization error. "
"It will be appreciated if you report the specific scenario this issue happened.");
wxMessageBox(errmsg + "\n\n" + wxString(ex.what()), _L("Critical error"), wxOK | wxICON_ERROR);
std::terminate();
//throw;
} catch (const std::exception& ex) {
wxLogError(format_wxstr(_L("BambuStudio got an unhandled exception: %1%"), ex.what()));
wxLogError(format_wxstr(_L("OrcaSlicer got an unhandled exception: %1%"), ex.what()));
BOOST_LOG_TRIVIAL(error) << boost::format("Uncaught exception: %1%") % ex.what();
flush_logs();
throw;
@ -1014,29 +1012,26 @@ void GUI_App::post_init()
bool switch_to_3d = false;
if (!this->init_params->input_files.empty()) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", init with input files, size %1%, input_gcode %2%")
%this->init_params->input_files.size() %this->init_params->input_gcode;
if (this->init_params->input_files.size() == 1 &&
boost::starts_with(this->init_params->input_files.front(), "bambustudio://open")) {
std::string download_params_url = url_decode(this->init_params->input_files.front());
auto input_str_arr = split_str(download_params_url, "file=");
std::string download_url;
for (auto input_str : input_str_arr) {
if ( boost::starts_with(input_str, "http://") || boost::starts_with(input_str, "https://")) {
download_url = input_str;
}
boost::starts_with(this->init_params->input_files.front(), "orcaslicer://open")) {
auto input_str_arr = split_str(this->init_params->input_files.front(), "orcaslicer://open/?file=");
std::string download_origin_url;
for (auto input_str:input_str_arr) {
if (!input_str.empty()) download_origin_url = input_str;
}
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("download_url %1%") % download_url;
if (!download_url.empty()) {
m_download_file_url = from_u8(download_url).ToStdString();
std::string download_file_url = url_decode(download_origin_url);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << download_file_url;
if (!download_file_url.empty() && ( boost::starts_with(download_file_url, "http://") || boost::starts_with(download_file_url, "https://")) ) {
request_model_download(download_origin_url);
}
}
else {
switch_to_3d = true;
@ -1048,12 +1043,19 @@ void GUI_App::post_init()
else {
mainframe->select_tab(size_t(MainFrame::tp3DEditor));
plater_->select_view_3D("3D");
wxArrayString input_files;
for (auto & file : this->init_params->input_files) {
input_files.push_back(wxString::FromUTF8(file));
Plater::TakeSnapshot snapshot(this->plater(), "Load Project", UndoRedo::SnapshotType::ProjectSeparator);
const std::vector<size_t> res = this->plater()->load_files(this->init_params->input_files);
if (!res.empty()) {
if (this->init_params->input_files.size() == 1) {
// Update application titlebar when opening a project file
const std::string& filename = this->init_params->input_files.front();
this->plater()->up_to_date(true, false);
this->plater()->up_to_date(true, true);
//BBS: remove amf logic as project
if (boost::algorithm::iends_with(filename, ".3mf"))
this->plater()->set_project_filename(from_u8(filename));
}
}
this->plater()->set_project_filename(_L("Untitled"));
this->plater()->load_files(input_files);
}
}
}
@ -1153,39 +1155,10 @@ void GUI_App::post_init()
}
#endif
//BBS: check crash log
auto log_dir_path = boost::filesystem::path(data_dir()) / "log";
if (boost::filesystem::exists(log_dir_path))
{
boost::filesystem::directory_iterator end_iter;
for (boost::filesystem::directory_iterator iter(log_dir_path); iter != end_iter; ++iter)
{
std::string file_name = iter->path().stem().string();
if (boost::starts_with(file_name, "crash")) {
if (file_name.find("done") == std::string::npos) {
std::ifstream ifs(iter->path().string(), ios::in);
std::stringstream data;
data << ifs.rdbuf();
ifs.close();
NetworkAgent* agent = wxGetApp().getAgent();
json j;
j["time"] = file_name.substr(file_name.find("crash") + strlen("crash") + 1);
j["verion"] = std::string(SLIC3R_VERSION);
j["content"] = decode_path(data.str().c_str());
try {
if (agent) {
agent->track_event("studio_crash", j.dump());
}
}
catch (...) {}
std::string new_file_name = file_name.append("_done");
boost::filesystem::rename(iter->path(), iter->path().parent_path() / boost::filesystem::path(new_file_name + iter->path().extension().string()));
}
}
}
}
if (app_config->get("stealth_mode") == "false")
hms_query = new HMSQuery();
m_show_gcode_window = app_config->get("show_gcode_window") == "true";
if (m_networking_need_update) {
//updating networking
int ret = updating_bambu_networking();
@ -1215,17 +1188,17 @@ void GUI_App::post_init()
bool sys_preset = app_config->get("sync_system_preset") == "true";
this->preset_updater->sync(http_url, language, network_ver, sys_preset ? preset_bundle : nullptr);
//BBS: check new version
this->check_new_version();
//BBS: check privacy version
if (is_user_login()) {
this->check_privacy_version(0);
this->check_track_enable();
this->check_new_version_sf();
if (is_user_login() && app_config->get("stealth_mode") == "false") {
// this->check_privacy_version(0);
request_user_handle(0);
}
});
}
if (is_user_login())
request_user_handle(0);
if(!m_networking_need_update && m_agent) {
m_agent->set_on_ssdp_msg_fn(
[this](std::string json_str) {
@ -1316,11 +1289,10 @@ GUI_App::GUI_App()
, m_app_mode(EAppMode::Editor)
, m_em_unit(10)
, m_imgui(new ImGuiWrapper())
, hms_query(new HMSQuery())
, m_removable_drive_manager(std::make_unique<RemovableDriveManager>())
//, m_other_instance_message_handler(std::make_unique<OtherInstanceMessageHandler>())
{
//app config initializes early becasuse it is used in instance checking in BambuStudio.cpp
//app config initializes early becasuse it is used in instance checking in OrcaSlicer.cpp
this->init_app_config();
this->init_download_path();
@ -1454,9 +1426,6 @@ int GUI_App::download_plugin(std::string name, std::string package_name, Install
if (!app_config) {
j["result"] = "failed";
j["error_msg"] = "app_config is nullptr";
if (m_agent) {
m_agent->track_event("networkplugin_download", j.dump());
}
return -1;
}
@ -1528,9 +1497,6 @@ int GUI_App::download_plugin(std::string name, std::string package_name, Install
if (result < 0) {
j["result"] = "failed";
j["error_msg"] = err_msg;
if (m_agent) {
m_agent->track_event("networkplugin_download", j.dump());
}
if (pro_fn) pro_fn(InstallStatusDownloadFailed, 0, cancel);
return result;
}
@ -1541,9 +1507,6 @@ int GUI_App::download_plugin(std::string name, std::string package_name, Install
if (pro_fn) pro_fn(InstallStatusDownloadFailed, 0, cancel);
j["result"] = "failed";
j["error_msg"] = "[download_plugin 1]: no available plugin found for this app version: " + std::string(SLIC3R_VERSION);
if (m_agent) {
m_agent->track_event("networkplugin_download", j.dump());
}
return -1;
}
else if (pro_fn) {
@ -1554,9 +1517,6 @@ int GUI_App::download_plugin(std::string name, std::string package_name, Install
BOOST_LOG_TRIVIAL(info) << boost::format("[download_plugin 1]: %1%, cancelled by user") % __LINE__;
j["result"] = "failed";
j["error_msg"] = (boost::format("[download_plugin 1]: %1%, cancelled by user") % __LINE__).str();
if (m_agent) {
m_agent->track_event("networkplugin_download", j.dump());
}
return -1;
}
BOOST_LOG_TRIVIAL(info) << "[download_plugin] get_url = " << download_url;
@ -1605,9 +1565,6 @@ int GUI_App::download_plugin(std::string name, std::string package_name, Install
http.perform_sync();
j["result"] = result < 0 ? "failed" : "success";
j["error_msg"] = err_msg;
if (m_agent) {
m_agent->track_event("networkplugin_download", j.dump());
}
return result;
}
@ -2057,9 +2014,12 @@ static boost::optional<Semver> parse_semver_from_ini(std::string path)
std::stringstream buffer;
buffer << stream.rdbuf();
std::string body = buffer.str();
size_t start = body.find("BambuStudio ");
if (start == std::string::npos)
return boost::none;
size_t start = body.find("OrcaSlicer ");
if (start == std::string::npos) {
start = body.find("OrcaSlicer ");
if (start == std::string::npos)
return boost::none;
}
body = body.substr(start + 12);
size_t end = body.find_first_of(" \n");
if (end < body.size())
@ -2099,12 +2059,11 @@ void GUI_App::init_app_config()
// Mac : "~/Library/Application Support/Slic3r"
if (data_dir().empty()) {
boost::filesystem::path data_dir_path;
#ifndef __linux__
std::string data_dir = wxStandardPaths::Get().GetUserDataDir().ToUTF8().data();
//BBS create folder if not exists
boost::filesystem::path data_dir_path(data_dir);
if (!boost::filesystem::exists(data_dir_path))
boost::filesystem::create_directory(data_dir_path);
data_dir_path = boost::filesystem::path(data_dir);
set_data_dir(data_dir);
#else
// Since version 2.3, config dir on Linux is in ${XDG_CONFIG_HOME}.
@ -2113,10 +2072,19 @@ void GUI_App::init_app_config()
if (! wxGetEnv(wxS("XDG_CONFIG_HOME"), &dir) || dir.empty() )
dir = wxFileName::GetHomeDir() + wxS("/.config");
set_data_dir((dir + "/" + GetAppName()).ToUTF8().data());
boost::filesystem::path data_dir_path(data_dir());
if (!boost::filesystem::exists(data_dir_path))
boost::filesystem::create_directory(data_dir_path);
data_dir_path = boost::filesystem::path(data_dir());
#endif
if (!boost::filesystem::exists(data_dir_path)){
auto older_data_dir = data_dir_path.parent_path() / "BambuStudio-SoftFever";
if(boost::filesystem::exists(older_data_dir)){
copy_directory_recursively(older_data_dir,data_dir_path);
boost::system::error_code ec;
boost::filesystem::rename(data_dir_path / "BambuStudio.conf", data_dir_path / "OrcaSlicer.conf", ec);
boost::filesystem::rename(data_dir_path / "BambuStudio.conf.bak", data_dir_path / "OrcaSlicer.conf.bak", ec);
}
else
boost::filesystem::create_directory(data_dir_path);
}
} else {
m_datadir_redefined = true;
}
@ -2146,7 +2114,7 @@ void GUI_App::init_app_config()
if (!error.empty()) {
// Error while parsing config file. We'll customize the error message and rethrow to be displayed.
throw Slic3r::RuntimeError(
_u8L("BambuStudio configuration file may be corrupted and is not abled to be parsed."
_u8L("OrcaSlicer configuration file may be corrupted and is not abled to be parsed."
"Please delete the file and try again.") +
"\n\n" + app_config->config_path() + "\n\n" + error);
}
@ -2366,7 +2334,7 @@ bool GUI_App::on_init_inner()
RichMessageDialog
dlg(nullptr,
wxString::Format(_L("%s\nDo you want to continue?"), msg),
"BambuStudio", wxICON_QUESTION | wxYES_NO);
"OrcaSlicer", wxICON_QUESTION | wxYES_NO);
dlg.ShowCheckBox(_L("Remember my choice"));
if (dlg.ShowModal() != wxID_YES) return false;
@ -2440,8 +2408,9 @@ bool GUI_App::on_init_inner()
}
}
app_config->set("version", SLIC3R_VERSION);
app_config->save();
if(app_config->get("version") != SLIC3R_VERSION) {
app_config->set("version", SLIC3R_VERSION);
}
BBLSplashScreen * scrn = nullptr;
const bool show_splash_screen = true;
@ -2500,7 +2469,7 @@ bool GUI_App::on_init_inner()
/* wxString tips = wxString::Format(_L("Click to download new version in default browser: %s"), version_info.version_str);
DownloadDialog dialog(this->mainframe,
tips,
_L("New version of Bambu Studio"),
_L("New version of Orca Slicer"),
false,
wxCENTER | wxICON_INFORMATION);
@ -2548,7 +2517,7 @@ bool GUI_App::on_init_inner()
wxString tips = wxString::Format(_L("Click to download new version in default browser: %s"), version_str);
DownloadDialog dialog(this->mainframe,
tips,
_L("The Bambu Studio needs an upgrade"),
_L("The Orca Slicer needs an upgrade"),
false,
wxCENTER | wxICON_INFORMATION);
dialog.SetExtendedMessage(description_text);
@ -2721,14 +2690,12 @@ bool GUI_App::on_init_inner()
if (m_agent) {
json j = json::object();
m_agent->start_subscribe("app");
m_agent->track_event("mqtt_active", j.dump());
}
} else {
BOOST_LOG_TRIVIAL(info) << "studio is inactive, stop to subscribe";
if (m_agent) {
json j = json::object();
m_agent->stop_subscribe("app");
m_agent->track_event("mqtt_inactive", j.dump());
}
}
m_studio_active = curr_studio_active;
@ -2738,9 +2705,6 @@ bool GUI_App::on_init_inner()
if (! plater_)
return;
if (app_config->dirty())
app_config->save();
// BBS
//this->obj_manipul()->update_if_dirty();
@ -2764,10 +2728,11 @@ bool GUI_App::on_init_inner()
request_model_download(m_download_file_url);
m_download_file_url = "";
}
update_publish_status();
}
if (m_post_initialized && app_config->dirty())
app_config->save();
});
m_initialized = true;
@ -3089,7 +3054,7 @@ void GUI_App::UpdateDarkUI(wxWindow* window, bool highlited/* = false*/, bool ju
/*if (m_is_dark_mode != dark_mode() )
m_is_dark_mode = dark_mode();*/
if (m_is_dark_mode) {
auto original_col = window->GetBackgroundColour();
@ -3218,7 +3183,7 @@ void GUI_App::init_fonts()
// wxSYS_OEM_FIXED_FONT and wxSYS_ANSI_FIXED_FONT use the same as
// DEFAULT in wxGtk. Use the TELETYPE family as a work-around
m_code_font = wxFont(wxFontInfo().Family(wxFONTFAMILY_TELETYPE));
m_code_font.SetPointSize(m_normal_font.GetPointSize());
m_code_font.SetPointSize(m_small_font.GetPointSize());
}
void GUI_App::update_fonts(const MainFrame *main_frame)
@ -3235,7 +3200,7 @@ void GUI_App::update_fonts(const MainFrame *main_frame)
m_bold_font = m_normal_font.Bold();
m_link_font = m_bold_font.Underlined();
m_em_unit = main_frame->em_unit();
m_code_font.SetPointSize(m_normal_font.GetPointSize());
m_code_font.SetPointSize(m_small_font.GetPointSize());
}
void GUI_App::set_label_clr_modified(const wxColour& clr)
@ -3653,7 +3618,7 @@ void GUI_App::load_gcode(wxWindow* parent, wxString& input_file) const
{
input_file.Clear();
wxFileDialog dialog(parent ? parent : GetTopWindow(),
_L("Choose one file (gcode/.gco/.g/.ngc/ngc):"),
_L("Choose one file (gcode/3mf):"),
app_config->get_last_dir(), "",
file_wildcards(FT_GCODE), wxFD_OPEN | wxFD_FILE_MUST_EXIST);
@ -4037,32 +4002,21 @@ void GUI_App::on_http_error(wxCommandEvent &evt)
wxString result;
if (status >= 400 && status < 500) {
try {
wxString body_str = evt.GetString();
bool found_json = false;
for (int i = 0; i < body_str.size(); i++) {
if (body_str[i] == '{') {
found_json = true;
break;
}
}
if (found_json) {
json j = json::parse(body_str);
if (j.contains("code")) {
if (!j["code"].is_null())
code = j["code"].get<int>();
}
if (j.contains("error")) {
if (!j["error"].is_null())
error = j["error"].get<std::string>();
}
}
json j = json::parse(evt.GetString());
if (j.contains("code")) {
if (!j["code"].is_null())
code = j["code"].get<int>();
}
if (j.contains("error"))
if (!j["error"].is_null())
error = j["error"].get<std::string>();
}
catch (...) {}
}
// Version limit
if (code == HttpErrorVersionLimited) {
MessageDialog msg_dlg(nullptr, _L("The version of Bambu studio is too low and needs to be updated to the latest version before it can be used normally"), "", wxAPPLY | wxOK);
MessageDialog msg_dlg(nullptr, _L("The version of Orca Slicer is too low and needs to be updated to the latest version before it can be used normally"), "", wxAPPLY | wxOK);
if (msg_dlg.ShowModal() == wxOK) {
return;
}
@ -4134,6 +4088,8 @@ void GUI_App::on_user_login_handle(wxCommandEvent &evt)
void GUI_App::check_track_enable()
{
// Orca: alaways disable track event
return;
if (app_config && app_config->get("firstguide", "privacyuse") == "true") {
//enable track event
json header_json;
@ -4150,9 +4106,6 @@ void GUI_App::check_track_enable()
/* record studio start event */
json j;
j["user_mode"] = this->get_mode_str();
if (m_agent) {
m_agent->track_event("studio_launch", j.dump());
}
}
}
@ -4268,6 +4221,108 @@ void GUI_App::check_new_version(bool show_tips, int by_user)
}).perform();
}
//parse the string, if it doesn't contain a valid version string, return invalid version.
Semver get_version(const std::string& str, const std::regex& regexp) {
std::smatch match;
if (std::regex_match(str, match, regexp)) {
std::string version_cleaned = match[0];
const boost::optional<Semver> version = Semver::parse(version_cleaned);
if (version.has_value()) {
return *version;
}
}
return Semver::invalid();
}
void GUI_App::check_new_version_sf(bool show_tips, int by_user)
{
AppConfig* app_config = wxGetApp().app_config;
auto version_check_url = app_config->version_check_url();
Http::get(version_check_url)
.on_error([&](std::string body, std::string error, unsigned http_status) {
(void)body;
BOOST_LOG_TRIVIAL(error) << format("Error getting: `%1%`: HTTP %2%, %3%", "check_new_version_sf", http_status,
error);
})
.timeout_connect(1)
.on_complete([&](std::string body, unsigned http_status) {
// Http response OK
if (http_status != 200)
return;
try {
boost::trim(body);
// SoftFever: parse github release, ported from SS
boost::property_tree::ptree root;
std::stringstream json_stream(body);
boost::property_tree::read_json(json_stream, root);
bool i_am_pre = false;
// at least two number, use '.' as separator. can be followed by -Az23 for prereleased and +Az42 for
// metadata
std::regex matcher("[0-9]+\\.[0-9]+(\\.[0-9]+)*(-[A-Za-z0-9]+)?(\\+[A-Za-z0-9]+)?");
Semver current_version = get_version(SoftFever_VERSION, matcher);
Semver best_pre(1, 0, 0);
Semver best_release(1, 0, 0);
std::string best_pre_url;
std::string best_release_url;
std::string best_release_content;
std::string best_pre_content;
const std::regex reg_num("([0-9]+)");
for (auto json_version : root) {
std::string tag = json_version.second.get<std::string>("tag_name");
if (tag[0] == 'v')
tag.erase(0, 1);
for (std::regex_iterator it = std::sregex_iterator(tag.begin(), tag.end(), reg_num);
it != std::sregex_iterator(); ++it) {
}
Semver tag_version = get_version(tag, matcher);
if (current_version == tag_version)
i_am_pre = json_version.second.get<bool>("prerelease");
if (json_version.second.get<bool>("prerelease")) {
if (best_pre < tag_version) {
best_pre = tag_version;
best_pre_url = json_version.second.get<std::string>("html_url");
best_pre_content = json_version.second.get<std::string>("body");
best_pre.set_prerelease("Preview");
}
} else {
if (best_release < tag_version) {
best_release = tag_version;
best_release_url = json_version.second.get<std::string>("html_url");
best_release_content = json_version.second.get<std::string>("body");
}
}
}
// if release is more recent than beta, use release anyway
if (best_pre < best_release) {
best_pre = best_release;
best_pre_url = best_release_url;
best_pre_content = best_release_content;
}
// if we're the most recent, don't do anything
if ((i_am_pre ? best_pre : best_release) <= current_version)
return;
// BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...",
// SLIC3R_APP_NAME, i_am_pre ? best_pre.to_string(): best_release.to_string());
version_info.url = i_am_pre ? best_pre_url : best_release_url;
version_info.version_str = i_am_pre ? best_pre.to_string() : best_release.to_string_sf();
version_info.description = i_am_pre ? best_pre_content : best_release_content;
version_info.force_upgrade = false;
wxCommandEvent *evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
evt->SetString((i_am_pre ? best_pre : best_release).to_string());
GUI::wxGetApp().QueueEvent(evt);
} catch (...) {
}
})
.perform();
}
//BBS pop up a dialog and download files
void GUI_App::request_new_version(int by_user)
@ -4301,12 +4356,10 @@ void GUI_App::show_check_privacy_dlg(wxCommandEvent& evt)
privacy_dlg.Bind(EVT_PRIVACY_UPDATE_CONFIRM, [this, online_login](wxCommandEvent &e) {
app_config->set("privacy_version", privacy_version_info.version_str);
app_config->set_bool("privacy_update_checked", true);
app_config->save();
request_user_handle(online_login);
});
privacy_dlg.Bind(EVT_PRIVACY_UPDATE_CANCEL, [this](wxCommandEvent &e) {
app_config->set_bool("privacy_update_checked", false);
app_config->save();
if (m_agent) {
m_agent->user_logout();
}
@ -4861,7 +4914,6 @@ bool GUI_App::select_language()
// m_wxLocale->GetCanonicalName()
// 3) new_language_info->CanonicalName is a safe bet. It points to a valid dictionary name.
app_config->set("language", new_language_info->CanonicalName.ToUTF8().data());
app_config->save();
return true;
}
}
@ -4937,7 +4989,7 @@ bool GUI_App::load_language(wxString language, bool initial)
}
if (language_info != nullptr && language_info->LayoutDirection == wxLayout_RightToLeft) {
BOOST_LOG_TRIVIAL(info) << boost::format("The following language code requires right to left layout, which is not supported by BambuStudio: %1%") % language_info->CanonicalName.ToUTF8().data();
BOOST_LOG_TRIVIAL(trace) << boost::format("The following language code requires right to left layout, which is not supported by OrcaSlicer: %1%") % language_info->CanonicalName.ToUTF8().data();
language_info = nullptr;
}
@ -4951,7 +5003,7 @@ bool GUI_App::load_language(wxString language, bool initial)
language_info = wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH_US);
}
BOOST_LOG_TRIVIAL(info) << boost::format("Switching wxLocales to %1%") % language_info->CanonicalName.ToUTF8().data();
BOOST_LOG_TRIVIAL(trace) << boost::format("Switching wxLocales to %1%") % language_info->CanonicalName.ToUTF8().data();
// Select language for locales. This language may be different from the language of the dictionary.
//if (language_info == m_language_info_best || language_info == m_language_info_system) {
@ -5022,14 +5074,14 @@ bool GUI_App::load_language(wxString language, bool initial)
if (! wxLocale::IsAvailable(language_info->Language)) {
// Loading the language dictionary failed.
wxString message = "Switching Bambu Studio to language " + language_info->CanonicalName + " failed.";
wxString message = "Switching Orca Slicer to language " + language_info->CanonicalName + " failed.";
#if !defined(_WIN32) && !defined(__APPLE__)
// likely some linux system
message += "\nYou may need to reconfigure the missing locales, likely by running the \"locale-gen\" and \"dpkg-reconfigure locales\" commands.\n";
#endif
if (initial)
message + "\n\nApplication will close.";
wxMessageBox(message, "Bambu Studio - Switching language failed", wxOK | wxICON_ERROR);
wxMessageBox(message, "Orca Slicer - Switching language failed", wxOK | wxICON_ERROR);
if (initial)
std::exit(EXIT_FAILURE);
else
@ -5096,7 +5148,6 @@ void GUI_App::save_mode(const /*ConfigOptionMode*/int mode)
mode == comSimple ? "simple" :
mode == comDevelop ? "develop" : "simple";
app_config->set("user_mode", mode_str);
app_config->save();
update_mode();
}
@ -5110,6 +5161,7 @@ void GUI_App::update_mode()
mainframe->m_param_panel->update_mode();
if (mainframe->m_param_dialog)
mainframe->m_param_dialog->panel()->update_mode();
mainframe->m_webview->update_mode();
#ifdef _MSW_DARK_MODE
if (!wxGetApp().tabs_as_menu())
@ -5682,7 +5734,7 @@ void GUI_App::OSXStoreOpenFiles(const wxArrayString &fileNames)
if (is_gcode_file(into_u8(filename)))
++ num_gcodes;
if (fileNames.size() == num_gcodes) {
// Opening PrusaSlicer by drag & dropping a G-Code onto BambuStudio icon in Finder,
// Opening PrusaSlicer by drag & dropping a G-Code onto OrcaSlicer icon in Finder,
// just G-codes were passed. Switch to G-code viewer mode.
m_app_mode = EAppMode::GCodeViewer;
unlock_lockfile(get_instance_hash_string() + ".lock", data_dir() + "/cache/");
@ -5698,8 +5750,8 @@ void GUI_App::MacOpenURL(const wxString& url)
{
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "get mac url " << url;
if (!url.empty() && boost::starts_with(url, "bambustudioopen://")) {
auto input_str_arr = split_str(url.ToStdString(), "bambustudioopen://");
if (!url.empty() && boost::starts_with(url, "orcasliceropen://")) {
auto input_str_arr = split_str(url.ToStdString(), "orcasliceropen://");
std::string download_origin_url;
for (auto input_str : input_str_arr) {
@ -6343,8 +6395,8 @@ void GUI_App::associate_files(std::wstring extend)
::GetModuleFileNameW(nullptr, app_path, sizeof(app_path));
std::wstring prog_path = L"\"" + std::wstring(app_path) + L"\"";
std::wstring prog_id = L" Bambu.Studio.1";
std::wstring prog_desc = L"BambuStudio";
std::wstring prog_id = L" Orca.Slicer.1";
std::wstring prog_desc = L"OrcaSlicer";
std::wstring prog_command = prog_path + L" \"%1\"";
std::wstring reg_base = L"Software\\Classes";
std::wstring reg_extension = reg_base + L"\\." + extend;
@ -6366,8 +6418,8 @@ void GUI_App::disassociate_files(std::wstring extend)
::GetModuleFileNameW(nullptr, app_path, sizeof(app_path));
std::wstring prog_path = L"\"" + std::wstring(app_path) + L"\"";
std::wstring prog_id = L" Bambu.Studio.1";
std::wstring prog_desc = L"BambuStudio";
std::wstring prog_id = L" Orca.Slicer.1";
std::wstring prog_desc = L"OrcaSlicer";
std::wstring prog_command = prog_path + L" \"%1\"";
std::wstring reg_base = L"Software\\Classes";
std::wstring reg_extension = reg_base + L"\\." + extend;

View file

@ -115,9 +115,9 @@ enum ConfigMenuIDs {
ConfigMenuCnt,
};
enum BambuStudioMenuIDs {
BambuStudioMenuAbout,
BambuStudioMenuPreferences,
enum OrcaSlicerMenuIDs {
OrcaSlicerMenuAbout,
OrcaSlicerMenuPreferences,
};
enum CameraMenuIDs {
@ -294,10 +294,10 @@ private:
bool m_side_popup_status{false};
wxString m_info_dialog_content;
HttpServer m_http_server;
bool m_show_gcode_window{true};
boost::thread m_check_network_thread;
public:
//try again when subscription fails
public:
//try again when subscription fails
void on_start_subscribe_again(std::string dev_id);
void check_filaments_in_blacklist(std::string tag_supplier, std::string tag_material, bool& in_blacklist, std::string& action, std::string& info);
std::string get_local_models_path();
@ -311,7 +311,6 @@ public:
//explicit GUI_App(EAppMode mode = EAppMode::Editor);
~GUI_App() override;
void show_message_box(std::string msg) { wxMessageBox(msg); }
EAppMode get_app_mode() const { return m_app_mode; }
Slic3r::DeviceManager* getDeviceManager() { return m_device_manager; }
@ -320,7 +319,12 @@ public:
bool is_editor() const { return m_app_mode == EAppMode::Editor; }
bool is_gcode_viewer() const { return m_app_mode == EAppMode::GCodeViewer; }
bool is_recreating_gui() const { return m_is_recreating_gui; }
std::string logo_name() const { return is_editor() ? "BambuStudio" : "BambuStudio-gcodeviewer"; }
std::string logo_name() const { return is_editor() ? "OrcaSlicer" : "OrcaSlicer-gcodeviewer"; }
// SoftFever
bool show_gcode_window() const { return m_show_gcode_window; }
void set_show_gcode_window(bool val) { m_show_gcode_window = val; }
wxString get_inf_dialog_contect () {return m_info_dialog_content;};
std::vector<std::string> split_str(std::string src, std::string separator);
@ -440,6 +444,7 @@ public:
void check_update(bool show_tips, int by_user);
void check_new_version(bool show_tips = false, int by_user = 0);
void check_new_version_sf(bool show_tips = false, int by_user = 0);
void request_new_version(int by_user);
void enter_force_upgrade();
void set_skip_version(bool skip = true);

View file

@ -74,9 +74,10 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::OBJECT_C
{
{ L("Quality"), {{"layer_height", "",1},
//{"initial_layer_print_height", "",2},
{"seam_position", "",2}, {"seam_gap", "",3}, {"wipe_speed", "",4},
{"slice_closing_radius", "",5}, {"resolution", "",6},
{"xy_hole_compensation", "",7}, {"xy_contour_compensation", "",8}, {"elefant_foot_compensation", "",9}
{"seam_position", "",2},
{"slice_closing_radius", "",3}, {"resolution", "",4},
{"xy_hole_compensation", "",5}, {"xy_contour_compensation", "",6}, {"elefant_foot_compensation", "",7},
{"make_overhang_printable_angle","", 8},{"make_overhang_printable_hole_size","",9}
}},
{ L("Support"), {{"brim_type", "",1},{"brim_width", "",2},{"brim_object_gap", "",3},
{"enable_support", "",4},{"support_type", "",5},{"support_threshold_angle", "",6},{"support_on_build_plate_only", "",7},
@ -92,16 +93,16 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::OBJECT_C
std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::PART_CATEGORY_SETTINGS=
{
{ L("Quality"), {{"ironing_type", "",8},{"ironing_flow", "",9},{"ironing_spacing", "",10},{"bridge_flow", "",11}
{ L("Quality"), {{"ironing_type", "",8},{"ironing_flow", "",9},{"ironing_spacing", "",10},{"bridge_flow", "",11},{"make_overhang_printable", "",11},{"bridge_density", "", 1}
}},
{ L("Strength"), {{"wall_loops", "",1},{"top_shell_layers", "",1},{"top_shell_thickness", "",1},
{"bottom_shell_layers", "",1}, {"bottom_shell_thickness", "",1}, {"sparse_infill_density", "",1},
{"sparse_infill_pattern", "",1},{"sparse_infill_anchor", "",1},{"sparse_infill_anchor_max", "",1}, {"top_surface_pattern", "",1},{"bottom_surface_pattern", "",1}, {"internal_solid_infill_pattern", "",1},
{"infill_combination", "",1}, {"infill_wall_overlap", "",1}, {"infill_direction", "",1}, {"bridge_angle", "",1},{"minimum_sparse_infill_area", "",1}
{ L("Strength"), {{"wall_loops", "",1},{"top_shell_layers", L("Top Solid Layers"),1},{"top_shell_thickness", L("Top Minimum Shell Thickness"),1},
{"bottom_shell_layers", L("Bottom Solid Layers"),1}, {"bottom_shell_thickness", L("Bottom Minimum Shell Thickness"),1},
{"sparse_infill_density", "",1},{"sparse_infill_pattern", "",1},{"infill_anchor", "",1},{"infill_anchor_max", "",1},{"top_surface_pattern", "",1},{"bottom_surface_pattern", "",1}, {"internal_solid_infill_pattern", "",1},
{"infill_combination", "",1}, {"infill_wall_overlap", "",1}, {"infill_direction", "",1}, {"bridge_angle", "",1}, {"minimum_sparse_infill_area", "",1}
}},
{ L("Speed"), {{"outer_wall_speed", "",1},{"inner_wall_speed", "",2},{"sparse_infill_speed", "",3},{"top_surface_speed", "",4}, {"internal_solid_infill_speed", "",5},
{"enable_overhang_speed", "",6}, {"overhang_1_4_speed", "",7}, {"overhang_2_4_speed", "",8}, {"overhang_3_4_speed", "",9}, {"overhang_4_4_speed", "",10},
{"bridge_speed", "",11}, {"gap_infill_speed", "",12}
{"enable_overhang_speed", "",6}, {"overhang_speed_classic", "",6}, {"overhang_1_4_speed", "",7}, {"overhang_2_4_speed", "",8}, {"overhang_3_4_speed", "",9}, {"overhang_4_4_speed", "",10},
{"bridge_speed", "",11}, {"gap_infill_speed", "",12}, {"internal_bridge_speed", "", 13}
}}
};
@ -141,7 +142,7 @@ std::vector<SimpleSettingData> SettingsFactory::get_visible_options(const std::s
//Quality
"layer_height", "initial_layer_print_height", "adaptive_layer_height", "seam_position", "xy_hole_compensation", "xy_contour_compensation", "elefant_foot_compensation", "support_line_width",
//Support
"enable_support", "support_type", "support_threshold_angle", "support_on_build_plate_only", "support_critical_regions_only", "enforce_support_layers","support_remove_small_overhang",
"enable_support", "support_type", "support_threshold_angle", "support_on_build_plate_only", "support_critical_regions_only", "enforce_support_layers",
//tree support
"tree_support_wall_count",
//support
@ -484,18 +485,38 @@ wxMenu* MenuFactory::append_submenu_add_generic(wxMenu* menu, ModelVolumeType ty
sub_menu->AppendSeparator();
}
for (auto &item : {L("Cube"), L("Cylinder"), L("Sphere"), L("Cone")})
{
append_menu_item(sub_menu, wxID_ANY, _(item), "",
[type, item](wxCommandEvent&) { obj_list()->load_generic_subobject(item, type); }, "", menu);
for (auto &item : {L("Orca Cube"), L("3DBenchy"), L("Autodesk FDM Test"),
L("Voron Cube")}) {
append_menu_item(
sub_menu, wxID_ANY, _(item), "",
[type, item](wxCommandEvent &) {
std::vector<boost::filesystem::path> input_files;
std::string file_name = item;
if (file_name == L("Orca Cube"))
file_name = "OrcaCube_v2.3mf";
else if (file_name == L("3DBenchy"))
file_name = "3DBenchy.stl";
else if (file_name == L("Autodesk FDM Test"))
file_name = "ksr_fdmtest_v4.stl";
else if (file_name == L("Voron Cube"))
file_name = "Voron_Design_Cube_v7.stl";
else
return;
input_files.push_back(
(boost::filesystem::path(Slic3r::resources_dir()) /
"handy_models" / file_name));
plater()->load_files(input_files, LoadStrategy::LoadModel);
},
"", menu);
}
if (type == ModelVolumeType::INVALID) {
sub_menu->AppendSeparator();
for (auto &item : {L("Bambu Cube"), L("Bambu Cube V2"), L("3DBenchy"), L("ksr FDMTest")}) {
append_menu_item(
sub_menu, wxID_ANY, _(item), "", [type, item](wxCommandEvent &) { obj_list()->load_generic_subobject(item, type); }, "", menu);
}
sub_menu->AppendSeparator();
for (auto &item : {L("Cube"), L("Cylinder"), L("Sphere"), L("Cone")}) {
append_menu_item(
sub_menu, wxID_ANY, _(item), "",
[type, item](wxCommandEvent &) {
obj_list()->load_generic_subobject(item, type);
},
"", menu);
}
return sub_menu;
@ -636,6 +657,13 @@ wxMenuItem* MenuFactory::append_menu_item_instance_to_object(wxMenu* menu)
return menu_item;
}
void MenuFactory::append_menu_item_fill_bed(wxMenu *menu)
{
append_menu_item(
menu, wxID_ANY, _L("Fill bed with copies"), _L("Fill the remaining area of bed with copies of the selected object"),
[](wxCommandEvent &) { plater()->fill_bed_with_instances(); }, "", nullptr, []() { return plater()->can_increase_instances(); }, m_parent);
}
wxMenuItem* MenuFactory::append_menu_item_printable(wxMenu* menu)
{
// BBS: to be checked
@ -1041,7 +1069,7 @@ void MenuFactory::create_object_menu()
// "Add (volumes)" popupmenu will be added later in append_menu_items_add_volume()
}
void MenuFactory::create_bbl_object_menu()
void MenuFactory::create_extra_object_menu()
{
append_menu_item_fill_bed(&m_object_menu);
// Object Clone
@ -1266,7 +1294,7 @@ void MenuFactory::init(wxWindow* parent)
create_sla_object_menu();
//create_part_menu();
create_bbl_object_menu();
create_extra_object_menu();
create_bbl_part_menu();
create_bbl_assemble_object_menu();
create_bbl_assemble_part_menu();
@ -1383,6 +1411,8 @@ wxMenu* MenuFactory::multi_selection_menu()
append_submenu(menu, split_menu, wxID_ANY, _L("Split"), _L("Split the selected object"), "",
[]() { return plater()->can_split(true); }, m_parent);
}
menu->AppendSeparator();
append_menu_item_change_filament(menu);
}
return menu;
}
@ -1658,12 +1688,6 @@ void MenuFactory::append_menu_item_locked(wxMenu* menu)
}, item->GetId());
}
void MenuFactory::append_menu_item_fill_bed(wxMenu *menu)
{
append_menu_item(
menu, wxID_ANY, _L("Fill bed with copies"), _L("Fill the remaining area of bed with copies of the selected object"),
[](wxCommandEvent &) { plater()->fill_bed_with_instances(); }, "", nullptr, []() { return plater()->can_increase_instances(); }, m_parent);
}
void MenuFactory::append_menu_item_plate_name(wxMenu *menu)
{
wxString name= _L("Edit Plate Name");

View file

@ -108,7 +108,7 @@ private:
//BBS: add part plate related logic
void create_plate_menu();
//BBS: add bbl object menu
void create_bbl_object_menu();
void create_extra_object_menu();
void create_bbl_part_menu();
void create_bbl_assemble_object_menu();
void create_bbl_assemble_part_menu();

View file

@ -1272,7 +1272,7 @@ void ObjectList::show_context_menu(const bool evt_context_menu)
const auto item = GetSelection();
if (item)
{
const ItemType type = m_objects_model->GetItemType(item);
const ItemType type = m_objects_model->GetItemType(item);
if (!(type & (itPlate | itObject | itVolume | itInstance)))
return;
@ -2020,32 +2020,24 @@ static TriangleMesh create_mesh(const std::string& type_name, const BoundingBoxf
{
const double side = wxGetApp().plater()->canvas3D()->get_size_proportional_to_max_bed_size(0.1);
TriangleMesh mesh;
indexed_triangle_set mesh;
if (type_name == "Cube")
// Sitting on the print bed, left front front corner at (0, 0).
mesh = TriangleMesh(its_make_cube(side, side, side));
mesh = its_make_cube(side, side, side);
else if (type_name == "Cylinder")
// Centered around 0, sitting on the print bed.
// The cylinder has the same volume as the box above.
mesh = TriangleMesh(its_make_cylinder(0.5 * side, side));
mesh = its_make_cylinder(0.5 * side, side);
else if (type_name == "Sphere")
// Centered around 0, half the sphere below the print bed, half above.
// The sphere has the same volume as the box above.
mesh = TriangleMesh(its_make_sphere(0.5 * side, PI / 18));
mesh = its_make_sphere(0.5 * side, PI / 18);
else if (type_name == "Slab")
// Sitting on the print bed, left front front corner at (0, 0).
mesh = TriangleMesh(its_make_cube(bb.size().x() * 1.5, bb.size().y() * 1.5, bb.size().z() * 0.5));
mesh = its_make_cube(bb.size().x() * 1.5, bb.size().y() * 1.5, bb.size().z() * 0.5);
else if (type_name == "Cone")
mesh = TriangleMesh(its_make_cone(0.5 * side, side));
else if (type_name == "Bambu Cube")
mesh.ReadSTLFile((Slic3r::resources_dir() + "/model/Bambu_Cube.stl").c_str(), true, nullptr);
else if (type_name == "Bambu Cube V2")
mesh.ReadSTLFile((Slic3r::resources_dir() + "/model/Bambu_Cube_V2.stl").c_str(), true, nullptr);
else if (type_name == "3DBenchy")
mesh.ReadSTLFile((Slic3r::resources_dir() + "/model/3DBenchy.stl").c_str(), true, nullptr);
else if (type_name == "ksr FDMTest")
mesh.ReadSTLFile((Slic3r::resources_dir() + "/model/ksr_FDMTest.stl").c_str(), true, nullptr);
return mesh;
mesh = its_make_cone(0.5 * side, side);
return TriangleMesh(mesh);
}
void ObjectList::load_generic_subobject(const std::string& type_name, const ModelVolumeType type)
@ -3611,7 +3603,6 @@ void ObjectList::update_info_items(size_t obj_idx, wxDataViewItemArray* selectio
}
}
void ObjectList::add_objects_to_list(std::vector<size_t> obj_idxs, bool call_selection_changed, bool notify_partplate, bool do_info_update)
{
#ifdef __WXOSX__
@ -3625,6 +3616,7 @@ void ObjectList::add_objects_to_list(std::vector<size_t> obj_idxs, bool call_sel
#endif
}
void ObjectList::add_object_to_list(size_t obj_idx, bool call_selection_changed, bool notify_partplate, bool do_info_update)
{
auto model_object = (*m_objects)[obj_idx];

View file

@ -358,7 +358,7 @@ void ObjectSettings::update_config_values(ModelConfig* config)
ConfigManipulation config_manipulation(load_config, toggle_field, nullptr, nullptr, &(config->get()));
// BBS: whether the preset is Bambu Lab printer
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
bool is_BBL_printer = preset_bundle.printers.get_edited_preset().is_bbl_vendor_preset(&preset_bundle);
bool is_BBL_printer = preset_bundle.printers.get_edited_preset().has_lidar(&preset_bundle);
config_manipulation.set_is_BBL_Printer(is_BBL_printer);
if (!is_object_settings)

View file

@ -1874,6 +1874,7 @@ void ObjectGridTable::init_cols(ObjectGrid *object_grid)
col = new ObjectGridCol(coBool, "support_reset", L("Support"), true, true, false, false, wxALIGN_CENTRE);
m_col_data.push_back(col);
// orca merge todo:
//Bed Adhesion
col = new ObjectGridCol(coEnum, "brim_type", L("Support"), true, false, true, true, wxALIGN_LEFT);
col->size = object_grid->GetTextExtent(L("Auto Brim")).x + 8; //add 8 for border

View file

@ -298,7 +298,8 @@ bool ObjectTableSettings::update_settings_list(bool is_object, bool is_multiple_
ConfigManipulation config_manipulation(nullptr, toggle_field, toggle_line, nullptr, &m_current_config);
// BBS: whether the preset is Bambu Lab printer
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
bool is_BBL_printer = preset_bundle.printers.get_edited_preset().is_bbl_vendor_preset(&preset_bundle);
bool is_BBL_printer = preset_bundle.printers.get_edited_preset().has_lidar(&preset_bundle);
// orca merge todo:
config_manipulation.set_is_BBL_Printer(is_BBL_printer);
printer_technology == ptFFF ? config_manipulation.toggle_print_fff_options(&m_current_config) :
@ -403,7 +404,7 @@ void ObjectTableSettings::update_config_values(bool is_object, ModelObject* obje
ConfigManipulation config_manipulation(nullptr, toggle_field, toggle_line, nullptr, &m_current_config);
// BBS: whether the preset is Bambu Lab printer
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
bool is_BBL_printer = preset_bundle.printers.get_edited_preset().is_bbl_vendor_preset(&preset_bundle);
bool is_BBL_printer = preset_bundle.printers.get_edited_preset().has_lidar(&preset_bundle);
config_manipulation.set_is_BBL_Printer(is_BBL_printer);
printer_technology == ptFFF ? config_manipulation.update_print_fff_config(&main_config) :

View file

@ -132,7 +132,7 @@ void GLGizmoMeshBoolean::on_render()
}
float src_color[3] = { 1.0f, 1.0f, 1.0f };
float tool_color[3] = { 0.0f, 174.0f / 255.0f, 66.0f / 255.0f };
float tool_color[3] = { 0.0f, 150.0f / 255.0f, 136.0f / 255.0f };
m_parent.get_selection().render_bounding_box(src_bb, src_color, m_parent.get_scale());
m_parent.get_selection().render_bounding_box(tool_bb, tool_color, m_parent.get_scale());
}
@ -179,12 +179,17 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l
GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always, 0.0f, 0.0f);
GizmoImguiBegin("MeshBoolean", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
const int max_tab_length = 2 * ImGui::GetStyle().FramePadding.x + std::max(ImGui::CalcTextSize(_L("Union").c_str()).x,
std::max(ImGui::CalcTextSize(_L("Difference").c_str()).x, ImGui::CalcTextSize(_L("Intersection").c_str()).x));
const int max_cap_length = ImGui::GetStyle().WindowPadding.x + ImGui::GetStyle().ItemSpacing.x + std::max(ImGui::CalcTextSize(_L("Source Volume").c_str()).x, ImGui::CalcTextSize(_L("Tool Volume").c_str()).x);
const int select_btn_length = 2 * ImGui::GetStyle().FramePadding.x + std::max(ImGui::CalcTextSize(("1 " + _L("selected")).c_str()).x, ImGui::CalcTextSize(_L("Select").c_str()).x);
const int max_tab_length = 2 * ImGui::GetStyle().FramePadding.x + std::max(ImGui::CalcTextSize(_u8L("Union").c_str()).x,
std::max(ImGui::CalcTextSize(_u8L("Difference").c_str()).x, ImGui::CalcTextSize(_u8L("Intersection").c_str()).x));
const int max_cap_length = ImGui::GetStyle().WindowPadding.x + ImGui::GetStyle().ItemSpacing.x +
std::max({ImGui::CalcTextSize(_u8L("Source Volume").c_str()).x,
ImGui::CalcTextSize(_u8L("Tool Volume").c_str()).x,
ImGui::CalcTextSize(_u8L("Subtract from").c_str()).x,
ImGui::CalcTextSize(_u8L("Subtract with").c_str()).x});
auto selectable = [this](const wxString& label, bool selected, const ImVec2& size_arg) {
const int select_btn_length = 2 * ImGui::GetStyle().FramePadding.x + std::max(ImGui::CalcTextSize(("1 " + _u8L("selected")).c_str()).x, ImGui::CalcTextSize(_u8L("Select").c_str()).x);
auto selectable = [this](const std::string& label, bool selected, const ImVec2& size_arg) {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0,0 });
ImGuiWindow* window = ImGui::GetCurrentWindow();
@ -195,13 +200,13 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l
if (selected || hovered) {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Button, { 0, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_Button, { 0, 150.0f / 255.0f, 136.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0, 150.0f / 255.0f, 136.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0, 150.0f / 255.0f, 136.0f / 255.0f, 1.0f });
}
else {
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0, 150.0f / 255.0f, 136.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0, 150.0f / 255.0f, 136.0f / 255.0f, 1.0f });
}
bool res = ImGui::Button(label.c_str(), size_arg);
@ -240,15 +245,15 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l
};
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0);
if (selectable(_L("Union").c_str(), m_operation_mode == MeshBooleanOperation::Union, ImVec2(max_tab_length, 0.0f))) {
if (selectable(_u8L("Union"), m_operation_mode == MeshBooleanOperation::Union, ImVec2(max_tab_length, 0.0f))) {
m_operation_mode = MeshBooleanOperation::Union;
}
ImGui::SameLine(0, 0);
if (selectable(_L("Difference").c_str(), m_operation_mode == MeshBooleanOperation::Difference, ImVec2(max_tab_length, 0.0f))) {
if (selectable(_u8L("Difference"), m_operation_mode == MeshBooleanOperation::Difference, ImVec2(max_tab_length, 0.0f))) {
m_operation_mode = MeshBooleanOperation::Difference;
}
ImGui::SameLine(0, 0);
if (selectable(_L("Intersection").c_str(), m_operation_mode == MeshBooleanOperation::Intersection, ImVec2(max_tab_length, 0.0f))) {
if (selectable(_u8L("Intersection"), m_operation_mode == MeshBooleanOperation::Intersection, ImVec2(max_tab_length, 0.0f))) {
m_operation_mode = MeshBooleanOperation::Intersection;
}
ImGui::PopStyleVar();
@ -257,10 +262,10 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l
std::string cap_str1 = m_operation_mode != MeshBooleanOperation::Difference ? _u8L("Part 1") : _u8L("Subtract from");
m_imgui->text(cap_str1);
ImGui::SameLine(max_cap_length);
wxString select_src_str = m_src.mv ? "1 " + _L("selected") : _L("Select");
select_src_str << "##select_source_volume";
std::string select_src_str = m_src.mv ? "1 " + _u8L("selected") : _u8L("Select");
select_src_str += "##select_source_volume";
ImGui::PushItemWidth(select_btn_length);
if (selectable(select_src_str.c_str(), m_selecting_state == MeshBooleanSelectingState::SelectSource, ImVec2(select_btn_length, 0)))
if (selectable(select_src_str, m_selecting_state == MeshBooleanSelectingState::SelectSource, ImVec2(select_btn_length, 0)))
m_selecting_state = MeshBooleanSelectingState::SelectSource;
ImGui::PopItemWidth();
if (m_src.mv) {
@ -285,10 +290,10 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l
std::string cap_str2 = m_operation_mode != MeshBooleanOperation::Difference ? _u8L("Part 2") : _u8L("Subtract with");
m_imgui->text(cap_str2);
ImGui::SameLine(max_cap_length);
wxString select_tool_str = m_tool.mv ? "1 " + _L("selected") : _L("Select");
select_tool_str << "##select_tool_volume";
std::string select_tool_str = m_tool.mv ? "1 " + _u8L("selected") : _u8L("Select");
select_tool_str += "##select_tool_volume";
ImGui::PushItemWidth(select_btn_length);
if (selectable(select_tool_str.c_str(), m_selecting_state == MeshBooleanSelectingState::SelectTool, ImVec2(select_btn_length, 0)))
if (selectable(select_tool_str, m_selecting_state == MeshBooleanSelectingState::SelectTool, ImVec2(select_btn_length, 0)))
m_selecting_state = MeshBooleanSelectingState::SelectTool;
ImGui::PopItemWidth();
if (m_tool.mv) {

View file

@ -498,7 +498,9 @@ void ArrangeJob::process()
auto& print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
const Slic3r::DynamicPrintConfig& global_config = wxGetApp().preset_bundle->full_config();
if (params.avoid_extrusion_cali_region && global_config.opt_bool("scan_first_layer"))
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
const bool has_lidar = preset_bundle->printers.get_edited_preset().has_lidar(preset_bundle);
if (has_lidar && params.avoid_extrusion_cali_region && global_config.opt_bool("scan_first_layer"))
partplate_list.preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES);
update_arrange_params(params, *m_plater, m_selected);
@ -736,7 +738,7 @@ arrangement::ArrangeParams init_arrange_params(Plater *p)
params.clearance_height_to_rod = print.config().extruder_clearance_height_to_rod.value;
params.clearance_height_to_lid = print.config().extruder_clearance_height_to_lid.value;
params.cleareance_radius = print.config().extruder_clearance_max_radius.value;
params.cleareance_radius = print.config().extruder_clearance_radius.value;
params.printable_height = print.config().printable_height.value;
params.allow_rotations = settings.enable_rotation;
params.allow_multi_materials_on_same_plate = settings.allow_multi_materials_on_same_plate;

View file

@ -211,7 +211,9 @@ void FillBedJob::process()
auto &partplate_list = m_plater->get_partplate_list();
auto &print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
const Slic3r::DynamicPrintConfig& global_config = wxGetApp().preset_bundle->full_config();
if (params.avoid_extrusion_cali_region && global_config.opt_bool("scan_first_layer"))
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
const bool has_lidar = preset_bundle->printers.get_edited_preset().has_lidar(preset_bundle);
if (has_lidar && params.avoid_extrusion_cali_region && global_config.opt_bool("scan_first_layer"))
partplate_list.preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES);
update_selected_items_inflation(m_selected, *m_plater, params);
@ -231,7 +233,7 @@ void FillBedJob::process()
do_stop = ap.bed_idx > 0 && ap.priority == 0;
};
// final align用的是凸包在有fixed item的情况下可能找到的参考点位置是错的这里就不做了。见STUDIO-3265
params.do_final_align = false;
params.do_final_align = !has_lidar;
arrangement::arrange(m_selected, m_unselected, m_bedpts, params);

Some files were not shown because too many files have changed in this diff Show more