removableDriveManager bug fixes
This commit is contained in:
parent
b8aa12486e
commit
1fa464af96
36 changed files with 620 additions and 469 deletions
6
deps/CGAL/CGAL.cmake
vendored
6
deps/CGAL/CGAL.cmake
vendored
|
@ -7,3 +7,9 @@ prusaslicer_add_cmake_project(
|
||||||
# URL_HASH SHA256=bd9327be903ab7ee379a8a7a0609eba0962f5078d2497cf8e13e8e1598584154
|
# URL_HASH SHA256=bd9327be903ab7ee379a8a7a0609eba0962f5078d2497cf8e13e8e1598584154
|
||||||
DEPENDS dep_boost dep_GMP dep_MPFR
|
DEPENDS dep_boost dep_GMP dep_MPFR
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ExternalProject_Add_Step(dep_CGAL dep_CGAL_relocation_fix
|
||||||
|
DEPENDEES install
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E remove CGALConfig-installation-dirs.cmake
|
||||||
|
WORKING_DIRECTORY "${DESTDIR}/usr/local/lib/cmake/CGAL"
|
||||||
|
)
|
2
deps/GMP/GMP.cmake
vendored
2
deps/GMP/GMP.cmake
vendored
|
@ -20,7 +20,7 @@ else ()
|
||||||
ExternalProject_Add(dep_GMP
|
ExternalProject_Add(dep_GMP
|
||||||
URL https://gmplib.org/download/gmp/gmp-6.1.2.tar.bz2
|
URL https://gmplib.org/download/gmp/gmp-6.1.2.tar.bz2
|
||||||
BUILD_IN_SOURCE ON
|
BUILD_IN_SOURCE ON
|
||||||
CONFIGURE_COMMAND ./configure --enable-shared=no --enable-static=yes "--prefix=${DESTDIR}/usr/local" --with-pic
|
CONFIGURE_COMMAND ./configure --enable-shared=no --enable-cxx=yes --enable-static=yes "--prefix=${DESTDIR}/usr/local" --with-pic
|
||||||
BUILD_COMMAND make -j
|
BUILD_COMMAND make -j
|
||||||
INSTALL_COMMAND make install
|
INSTALL_COMMAND make install
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||||
<g id="hex_x5F_plus">
|
<g id="hex_x5F_plus">
|
||||||
<g>
|
<g>
|
||||||
<polygon fill="#ED6B21" points="2,8 2,11 8,15 14,11 14,8 "/>
|
<polygon fill="#ED6B21" points="1,8 1,11 8,16 15,11 15,8 " style="stroke:white;stroke-width:1"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 446 B After Width: | Height: | Size: 482 B |
|
@ -4,7 +4,7 @@
|
||||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||||
<g id="hex_x5F_plus">
|
<g id="hex_x5F_plus">
|
||||||
<g>
|
<g>
|
||||||
<polygon fill="#ED6B21" points="8,1 2,5 2,7 2,8 14,8 14,7 14,5 "/>
|
<polygon fill="#ED6B21" points="8,0 1,5 1,7 1,8 15,8 15,7 15,5" style="stroke:white;stroke-width:1"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 454 B After Width: | Height: | Size: 487 B |
|
@ -15,5 +15,5 @@ add_library(hidapi STATIC ${HIDAPI_IMPL})
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
# Don't link the udev library, as there are two versions out there (libudev.so.0, libudev.so.1), so they are linked explicitely.
|
# Don't link the udev library, as there are two versions out there (libudev.so.0, libudev.so.1), so they are linked explicitely.
|
||||||
# target_link_libraries(hidapi udev)
|
# target_link_libraries(hidapi udev)
|
||||||
target_link_libraries(hidapi)
|
target_link_libraries(hidapi dl)
|
||||||
endif()
|
endif()
|
||||||
|
|
5
src/hidapi/README.md
Normal file
5
src/hidapi/README.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
** hidapi is a c++ library for communicating with USB and Bluetooth HID devices on Linux, Mac and Windows.**
|
||||||
|
|
||||||
|
For more information go to https://github.com/libusb/hidapi
|
||||||
|
|
||||||
|
THIS DIRECTORY CONTAINS THE hidapi-0.9.0 7da5cc9 SOURCE DISTRIBUTION.
|
|
@ -51,7 +51,7 @@ const std::string MODEL_CONFIG_FILE = "Metadata/Slic3r_PE_model.config";
|
||||||
const std::string LAYER_HEIGHTS_PROFILE_FILE = "Metadata/Slic3r_PE_layer_heights_profile.txt";
|
const std::string LAYER_HEIGHTS_PROFILE_FILE = "Metadata/Slic3r_PE_layer_heights_profile.txt";
|
||||||
const std::string LAYER_CONFIG_RANGES_FILE = "Metadata/Prusa_Slicer_layer_config_ranges.xml";
|
const std::string LAYER_CONFIG_RANGES_FILE = "Metadata/Prusa_Slicer_layer_config_ranges.xml";
|
||||||
const std::string SLA_SUPPORT_POINTS_FILE = "Metadata/Slic3r_PE_sla_support_points.txt";
|
const std::string SLA_SUPPORT_POINTS_FILE = "Metadata/Slic3r_PE_sla_support_points.txt";
|
||||||
const std::string CUSTOM_GCODE_PER_HEIGHT_FILE = "Metadata/Prusa_Slicer_custom_gcode_per_height.xml";
|
const std::string CUSTOM_GCODE_PER_PRINT_Z_FILE = "Metadata/Prusa_Slicer_custom_gcode_per_print_z.xml";
|
||||||
|
|
||||||
const char* MODEL_TAG = "model";
|
const char* MODEL_TAG = "model";
|
||||||
const char* RESOURCES_TAG = "resources";
|
const char* RESOURCES_TAG = "resources";
|
||||||
|
@ -418,7 +418,7 @@ namespace Slic3r {
|
||||||
void _extract_layer_config_ranges_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
void _extract_layer_config_ranges_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
||||||
void _extract_sla_support_points_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
void _extract_sla_support_points_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
||||||
|
|
||||||
void _extract_custom_gcode_per_height_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
void _extract_custom_gcode_per_print_z_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
||||||
|
|
||||||
void _extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, DynamicPrintConfig& config, const std::string& archive_filename);
|
void _extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, DynamicPrintConfig& config, const std::string& archive_filename);
|
||||||
bool _extract_model_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, Model& model);
|
bool _extract_model_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, Model& model);
|
||||||
|
@ -629,10 +629,10 @@ namespace Slic3r {
|
||||||
// extract slic3r print config file
|
// extract slic3r print config file
|
||||||
_extract_print_config_from_archive(archive, stat, config, filename);
|
_extract_print_config_from_archive(archive, stat, config, filename);
|
||||||
}
|
}
|
||||||
if (boost::algorithm::iequals(name, CUSTOM_GCODE_PER_HEIGHT_FILE))
|
if (boost::algorithm::iequals(name, CUSTOM_GCODE_PER_PRINT_Z_FILE))
|
||||||
{
|
{
|
||||||
// extract slic3r layer config ranges file
|
// extract slic3r layer config ranges file
|
||||||
_extract_custom_gcode_per_height_from_archive(archive, stat);
|
_extract_custom_gcode_per_print_z_from_archive(archive, stat);
|
||||||
}
|
}
|
||||||
else if (boost::algorithm::iequals(name, MODEL_CONFIG_FILE))
|
else if (boost::algorithm::iequals(name, MODEL_CONFIG_FILE))
|
||||||
{
|
{
|
||||||
|
@ -1064,7 +1064,7 @@ namespace Slic3r {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _3MF_Importer::_extract_custom_gcode_per_height_from_archive(::mz_zip_archive &archive, const mz_zip_archive_file_stat &stat)
|
void _3MF_Importer::_extract_custom_gcode_per_print_z_from_archive(::mz_zip_archive &archive, const mz_zip_archive_file_stat &stat)
|
||||||
{
|
{
|
||||||
if (stat.m_uncomp_size > 0)
|
if (stat.m_uncomp_size > 0)
|
||||||
{
|
{
|
||||||
|
@ -1079,24 +1079,23 @@ namespace Slic3r {
|
||||||
pt::ptree main_tree;
|
pt::ptree main_tree;
|
||||||
pt::read_xml(iss, main_tree);
|
pt::read_xml(iss, main_tree);
|
||||||
|
|
||||||
if (main_tree.front().first != "custom_gcodes_per_height")
|
if (main_tree.front().first != "custom_gcodes_per_print_z")
|
||||||
return;
|
return;
|
||||||
pt::ptree code_tree = main_tree.front().second;
|
pt::ptree code_tree = main_tree.front().second;
|
||||||
|
|
||||||
if (!m_model->custom_gcode_per_height.empty())
|
m_model->custom_gcode_per_print_z.clear();
|
||||||
m_model->custom_gcode_per_height.clear();
|
|
||||||
|
|
||||||
for (const auto& code : code_tree)
|
for (const auto& code : code_tree)
|
||||||
{
|
{
|
||||||
if (code.first != "code")
|
if (code.first != "code")
|
||||||
continue;
|
continue;
|
||||||
pt::ptree tree = code.second;
|
pt::ptree tree = code.second;
|
||||||
double height = tree.get<double>("<xmlattr>.height");
|
double print_z = tree.get<double> ("<xmlattr>.print_z" );
|
||||||
std::string gcode = tree.get<std::string>("<xmlattr>.gcode");
|
std::string gcode = tree.get<std::string> ("<xmlattr>.gcode" );
|
||||||
int extruder = tree.get<int>("<xmlattr>.extruder");
|
int extruder = tree.get<int> ("<xmlattr>.extruder" );
|
||||||
std::string color = tree.get<std::string>("<xmlattr>.color");
|
std::string color = tree.get<std::string> ("<xmlattr>.color" );
|
||||||
|
|
||||||
m_model->custom_gcode_per_height.push_back(Model::CustomGCode(height, gcode, extruder, color)) ;
|
m_model->custom_gcode_per_print_z.push_back(Model::CustomGCode{print_z, gcode, extruder, color}) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1885,7 +1884,7 @@ namespace Slic3r {
|
||||||
bool _add_sla_support_points_file_to_archive(mz_zip_archive& archive, Model& model);
|
bool _add_sla_support_points_file_to_archive(mz_zip_archive& archive, Model& model);
|
||||||
bool _add_print_config_file_to_archive(mz_zip_archive& archive, const DynamicPrintConfig &config);
|
bool _add_print_config_file_to_archive(mz_zip_archive& archive, const DynamicPrintConfig &config);
|
||||||
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data);
|
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data);
|
||||||
bool _add_custom_gcode_per_height_file_to_archive(mz_zip_archive& archive, Model& model);
|
bool _add_custom_gcode_per_print_z_file_to_archive(mz_zip_archive& archive, Model& model);
|
||||||
};
|
};
|
||||||
|
|
||||||
#if ENABLE_THUMBNAIL_GENERATOR
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
@ -1988,9 +1987,9 @@ namespace Slic3r {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds custom gcode per height file ("Metadata/Prusa_Slicer_custom_gcode_per_height.xml").
|
// Adds custom gcode per height file ("Metadata/Prusa_Slicer_custom_gcode_per_print_z.xml").
|
||||||
// All custom gcode per height of whole Model are stored here
|
// All custom gcode per height of whole Model are stored here
|
||||||
if (!_add_custom_gcode_per_height_file_to_archive(archive, model))
|
if (!_add_custom_gcode_per_print_z_file_to_archive(archive, model))
|
||||||
{
|
{
|
||||||
close_zip_writer(&archive);
|
close_zip_writer(&archive);
|
||||||
boost::filesystem::remove(filename);
|
boost::filesystem::remove(filename);
|
||||||
|
@ -2567,20 +2566,20 @@ namespace Slic3r {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _3MF_Exporter::_add_custom_gcode_per_height_file_to_archive( mz_zip_archive& archive, Model& model)
|
bool _3MF_Exporter::_add_custom_gcode_per_print_z_file_to_archive( mz_zip_archive& archive, Model& model)
|
||||||
{
|
{
|
||||||
std::string out = "";
|
std::string out = "";
|
||||||
|
|
||||||
if (!model.custom_gcode_per_height.empty())
|
if (!model.custom_gcode_per_print_z.empty())
|
||||||
{
|
{
|
||||||
pt::ptree tree;
|
pt::ptree tree;
|
||||||
pt::ptree& main_tree = tree.add("custom_gcodes_per_height", "");
|
pt::ptree& main_tree = tree.add("custom_gcodes_per_print_z", "");
|
||||||
|
|
||||||
for (const Model::CustomGCode& code : model.custom_gcode_per_height)
|
for (const Model::CustomGCode& code : model.custom_gcode_per_print_z)
|
||||||
{
|
{
|
||||||
pt::ptree& code_tree = main_tree.add("code", "");
|
pt::ptree& code_tree = main_tree.add("code", "");
|
||||||
// store minX and maxZ
|
// store minX and maxZ
|
||||||
code_tree.put("<xmlattr>.height" , code.height );
|
code_tree.put("<xmlattr>.print_z" , code.print_z );
|
||||||
code_tree.put("<xmlattr>.gcode" , code.gcode );
|
code_tree.put("<xmlattr>.gcode" , code.gcode );
|
||||||
code_tree.put("<xmlattr>.extruder" , code.extruder );
|
code_tree.put("<xmlattr>.extruder" , code.extruder );
|
||||||
code_tree.put("<xmlattr>.color" , code.color );
|
code_tree.put("<xmlattr>.color" , code.color );
|
||||||
|
@ -2599,9 +2598,9 @@ bool _3MF_Exporter::_add_custom_gcode_per_height_file_to_archive( mz_zip_archive
|
||||||
|
|
||||||
if (!out.empty())
|
if (!out.empty())
|
||||||
{
|
{
|
||||||
if (!mz_zip_writer_add_mem(&archive, CUSTOM_GCODE_PER_HEIGHT_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION))
|
if (!mz_zip_writer_add_mem(&archive, CUSTOM_GCODE_PER_PRINT_Z_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION))
|
||||||
{
|
{
|
||||||
add_error("Unable to add custom Gcodes per height file to archive");
|
add_error("Unable to add custom Gcodes per print_z file to archive");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -637,7 +637,7 @@ void AMFParserContext::endElement(const char * /* name */)
|
||||||
int extruder = atoi(m_value[2].c_str());
|
int extruder = atoi(m_value[2].c_str());
|
||||||
const std::string& color = m_value[3];
|
const std::string& color = m_value[3];
|
||||||
|
|
||||||
m_model.custom_gcode_per_height.push_back(Model::CustomGCode(height, gcode, extruder, color));
|
m_model.custom_gcode_per_print_z.push_back(Model::CustomGCode{height, gcode, extruder, color});
|
||||||
|
|
||||||
for (std::string& val: m_value)
|
for (std::string& val: m_value)
|
||||||
val.clear();
|
val.clear();
|
||||||
|
@ -1221,21 +1221,21 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
||||||
stream << " </constellation>\n";
|
stream << " </constellation>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!model->custom_gcode_per_height.empty())
|
if (!model->custom_gcode_per_print_z.empty())
|
||||||
{
|
{
|
||||||
std::string out = "";
|
std::string out = "";
|
||||||
pt::ptree tree;
|
pt::ptree tree;
|
||||||
|
|
||||||
pt::ptree& main_tree = tree.add("custom_gcodes_per_height", "");
|
pt::ptree& main_tree = tree.add("custom_gcodes_per_height", "");
|
||||||
|
|
||||||
for (const Model::CustomGCode& code : model->custom_gcode_per_height)
|
for (const Model::CustomGCode& code : model->custom_gcode_per_print_z)
|
||||||
{
|
{
|
||||||
pt::ptree& code_tree = main_tree.add("code", "");
|
pt::ptree& code_tree = main_tree.add("code", "");
|
||||||
// store minX and maxZ
|
// store minX and maxZ
|
||||||
code_tree.put("<xmlattr>.height", code.height);
|
code_tree.put("<xmlattr>.print_z" , code.print_z );
|
||||||
code_tree.put("<xmlattr>.gcode", code.gcode);
|
code_tree.put("<xmlattr>.gcode" , code.gcode );
|
||||||
code_tree.put("<xmlattr>.extruder", code.extruder);
|
code_tree.put("<xmlattr>.extruder" , code.extruder );
|
||||||
code_tree.put("<xmlattr>.color", code.color);
|
code_tree.put("<xmlattr>.color" , code.color );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tree.empty())
|
if (!tree.empty())
|
||||||
|
|
|
@ -936,7 +936,7 @@ void GCode::_do_export(Print& print, FILE* file)
|
||||||
|
|
||||||
// Initialize custom gcode
|
// Initialize custom gcode
|
||||||
Model* model = print.get_object(0)->model_object()->get_model();
|
Model* model = print.get_object(0)->model_object()->get_model();
|
||||||
m_custom_g_code_heights = model->custom_gcode_per_height;
|
m_custom_gcode_per_print_z = model->custom_gcode_per_print_z;
|
||||||
|
|
||||||
// Initialize autospeed.
|
// Initialize autospeed.
|
||||||
{
|
{
|
||||||
|
@ -1124,20 +1124,22 @@ void GCode::_do_export(Print& print, FILE* file)
|
||||||
}
|
}
|
||||||
print.throw_if_canceled();
|
print.throw_if_canceled();
|
||||||
|
|
||||||
|
// #ys_FIXME_no_exported_codes
|
||||||
|
/*
|
||||||
/* To avoid change filament for non-used extruder for Multi-material,
|
/* To avoid change filament for non-used extruder for Multi-material,
|
||||||
* check model->custom_gcode_per_height using tool_ordering values
|
* check model->custom_gcode_per_print_z using tool_ordering values
|
||||||
* */
|
* /
|
||||||
if (!m_custom_g_code_heights. empty())
|
if (!m_custom_gcode_per_print_z. empty())
|
||||||
{
|
{
|
||||||
bool delete_executed = false;
|
bool delete_executed = false;
|
||||||
auto it = m_custom_g_code_heights.end();
|
auto it = m_custom_gcode_per_print_z.end();
|
||||||
while (it != m_custom_g_code_heights.begin())
|
while (it != m_custom_gcode_per_print_z.begin())
|
||||||
{
|
{
|
||||||
--it;
|
--it;
|
||||||
if (it->gcode != ColorChangeCode)
|
if (it->gcode != ColorChangeCode)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto it_layer_tools = std::lower_bound(tool_ordering.begin(), tool_ordering.end(), LayerTools(it->height));
|
auto it_layer_tools = std::lower_bound(tool_ordering.begin(), tool_ordering.end(), LayerTools(it->print_z));
|
||||||
|
|
||||||
bool used_extruder = false;
|
bool used_extruder = false;
|
||||||
for (; it_layer_tools != tool_ordering.end(); it_layer_tools++)
|
for (; it_layer_tools != tool_ordering.end(); it_layer_tools++)
|
||||||
|
@ -1154,16 +1156,16 @@ void GCode::_do_export(Print& print, FILE* file)
|
||||||
|
|
||||||
/* If we are there, current extruder wouldn't be used,
|
/* If we are there, current extruder wouldn't be used,
|
||||||
* so this color change is a redundant move.
|
* so this color change is a redundant move.
|
||||||
* Delete this item from m_custom_g_code_heights
|
* Delete this item from m_custom_gcode_per_print_z
|
||||||
* */
|
* /
|
||||||
it = m_custom_g_code_heights.erase(it);
|
it = m_custom_gcode_per_print_z.erase(it);
|
||||||
delete_executed = true;
|
delete_executed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delete_executed)
|
if (delete_executed)
|
||||||
model->custom_gcode_per_height = m_custom_g_code_heights;
|
model->custom_gcode_per_print_z = m_custom_gcode_per_print_z;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
m_cooling_buffer->set_current_extruder(initial_extruder_id);
|
m_cooling_buffer->set_current_extruder(initial_extruder_id);
|
||||||
|
|
||||||
|
@ -1461,7 +1463,7 @@ void GCode::_do_export(Print& print, FILE* file)
|
||||||
dst.first += buf;
|
dst.first += buf;
|
||||||
++ dst.second;
|
++ dst.second;
|
||||||
};
|
};
|
||||||
print.m_print_statistics.filament_stats.insert(std::pair<size_t, float>(extruder.id(), (float)used_filament));
|
print.m_print_statistics.filament_stats.insert(std::pair<size_t, float>{extruder.id(), (float)used_filament});
|
||||||
append(out_filament_used_mm, "%.1lf", used_filament);
|
append(out_filament_used_mm, "%.1lf", used_filament);
|
||||||
append(out_filament_used_cm3, "%.1lf", extruded_volume * 0.001);
|
append(out_filament_used_cm3, "%.1lf", extruded_volume * 0.001);
|
||||||
if (filament_weight > 0.) {
|
if (filament_weight > 0.) {
|
||||||
|
@ -1835,15 +1837,15 @@ void GCode::process_layer(
|
||||||
std::string custom_code = "";
|
std::string custom_code = "";
|
||||||
std::string pause_print_msg = "";
|
std::string pause_print_msg = "";
|
||||||
int m600_before_extruder = -1;
|
int m600_before_extruder = -1;
|
||||||
while (!m_custom_g_code_heights.empty() && m_custom_g_code_heights.front().height-EPSILON < layer.print_z) {
|
while (!m_custom_gcode_per_print_z.empty() && m_custom_gcode_per_print_z.front().print_z - EPSILON < layer.print_z) {
|
||||||
custom_code = m_custom_g_code_heights.front().gcode;
|
custom_code = m_custom_gcode_per_print_z.front().gcode;
|
||||||
|
|
||||||
if (custom_code == ColorChangeCode && m_custom_g_code_heights.front().extruder > 0)
|
if (custom_code == ColorChangeCode && m_custom_gcode_per_print_z.front().extruder > 0)
|
||||||
m600_before_extruder = m_custom_g_code_heights.front().extruder - 1;
|
m600_before_extruder = m_custom_gcode_per_print_z.front().extruder - 1;
|
||||||
if (custom_code == PausePrintCode)
|
if (custom_code == PausePrintCode)
|
||||||
pause_print_msg = m_custom_g_code_heights.front().color;
|
pause_print_msg = m_custom_gcode_per_print_z.front().color;
|
||||||
|
|
||||||
m_custom_g_code_heights.erase(m_custom_g_code_heights.begin());
|
m_custom_gcode_per_print_z.erase(m_custom_gcode_per_print_z.begin());
|
||||||
colorprint_change = true;
|
colorprint_change = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -367,7 +367,7 @@ protected:
|
||||||
* Updated before the export and erased during the process,
|
* Updated before the export and erased during the process,
|
||||||
* so no toolchange occurs twice.
|
* so no toolchange occurs twice.
|
||||||
* */
|
* */
|
||||||
std::vector<Model::CustomGCode> m_custom_g_code_heights;
|
std::vector<Model::CustomGCode> m_custom_gcode_per_print_z;
|
||||||
|
|
||||||
// Time estimators
|
// Time estimators
|
||||||
GCodeTimeEstimator m_normal_time_estimator;
|
GCodeTimeEstimator m_normal_time_estimator;
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
// Additional Codes which can be set by user using DoubleSlider
|
||||||
|
static constexpr char ColorChangeCode[] = "M600";
|
||||||
|
static constexpr char PausePrintCode[] = "M601";
|
||||||
|
static constexpr char ExtruderChangeCode[] = "tool_change";
|
||||||
|
|
||||||
class GCodeWriter {
|
class GCodeWriter {
|
||||||
public:
|
public:
|
||||||
GCodeConfig config;
|
GCodeConfig config;
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
#include "SVG.hpp"
|
#include "SVG.hpp"
|
||||||
#include <Eigen/Dense>
|
#include <Eigen/Dense>
|
||||||
|
#include "GCodeWriter.hpp"
|
||||||
|
#include "GCode/PreviewData.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
@ -43,7 +45,7 @@ Model& Model::assign_copy(const Model &rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy custom code per height
|
// copy custom code per height
|
||||||
this->custom_gcode_per_height = rhs.custom_gcode_per_height;
|
this->custom_gcode_per_print_z = rhs.custom_gcode_per_print_z;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +66,7 @@ Model& Model::assign_copy(Model &&rhs)
|
||||||
rhs.objects.clear();
|
rhs.objects.clear();
|
||||||
|
|
||||||
// copy custom code per height
|
// copy custom code per height
|
||||||
this->custom_gcode_per_height = rhs.custom_gcode_per_height;
|
this->custom_gcode_per_print_z = rhs.custom_gcode_per_print_z;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,6 +126,8 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
|
||||||
if (add_default_instances)
|
if (add_default_instances)
|
||||||
model.add_default_instances();
|
model.add_default_instances();
|
||||||
|
|
||||||
|
update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, config);
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,6 +163,8 @@ Model Model::read_from_archive(const std::string& input_file, DynamicPrintConfig
|
||||||
if (add_default_instances)
|
if (add_default_instances)
|
||||||
model.add_default_instances();
|
model.add_default_instances();
|
||||||
|
|
||||||
|
update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, config);
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,16 +601,15 @@ std::string Model::propose_export_file_name_and_path(const std::string &new_exte
|
||||||
std::vector<std::pair<double, DynamicPrintConfig>> Model::get_custom_tool_changes(double default_layer_height, size_t num_extruders) const
|
std::vector<std::pair<double, DynamicPrintConfig>> Model::get_custom_tool_changes(double default_layer_height, size_t num_extruders) const
|
||||||
{
|
{
|
||||||
std::vector<std::pair<double, DynamicPrintConfig>> custom_tool_changes;
|
std::vector<std::pair<double, DynamicPrintConfig>> custom_tool_changes;
|
||||||
if (!custom_gcode_per_height.empty()) {
|
for (const CustomGCode& custom_gcode : custom_gcode_per_print_z)
|
||||||
for (const CustomGCode& custom_gcode : custom_gcode_per_height)
|
|
||||||
if (custom_gcode.gcode == ExtruderChangeCode) {
|
if (custom_gcode.gcode == ExtruderChangeCode) {
|
||||||
DynamicPrintConfig config;
|
DynamicPrintConfig config;
|
||||||
// If extruder count in PrinterSettings was changed, use default (0) extruder for extruders, more than num_extruders
|
// If extruder count in PrinterSettings was changed, use default (0) extruder for extruders, more than num_extruders
|
||||||
config.set_key_value("extruder", new ConfigOptionInt(custom_gcode.extruder > num_extruders ? 0 : custom_gcode.extruder));
|
config.set_key_value("extruder", new ConfigOptionInt(custom_gcode.extruder > num_extruders ? 0 : custom_gcode.extruder));
|
||||||
// For correct extruders(tools) changing, we should decrease custom_gcode.height value by one default layer height
|
// For correct extruders(tools) changing, we should decrease custom_gcode.height value by one default layer height
|
||||||
custom_tool_changes.push_back({ custom_gcode.height - default_layer_height, config });
|
custom_tool_changes.push_back({ custom_gcode.print_z - default_layer_height, config });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return custom_tool_changes;
|
return custom_tool_changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1933,6 +1938,30 @@ extern bool model_has_advanced_features(const Model &model)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void update_custom_gcode_per_print_z_from_config(std::vector<Model::CustomGCode>& custom_gcode_per_print_z, DynamicPrintConfig* config)
|
||||||
|
{
|
||||||
|
if (!config->has("colorprint_heights"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const std::vector<std::string>& colors = GCodePreviewData::ColorPrintColors();
|
||||||
|
|
||||||
|
const auto& colorprint_values = config->option<ConfigOptionFloats>("colorprint_heights")->values;
|
||||||
|
|
||||||
|
if (!colorprint_values.empty())
|
||||||
|
{
|
||||||
|
custom_gcode_per_print_z.clear();
|
||||||
|
custom_gcode_per_print_z.reserve(colorprint_values.size());
|
||||||
|
int i = 0;
|
||||||
|
for (auto val : colorprint_values)
|
||||||
|
custom_gcode_per_print_z.emplace_back(Model::CustomGCode{ val, ColorChangeCode, 1, colors[(++i)%7] });
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There is one and only place this configuration option is used now.
|
||||||
|
* It wouldn't be used in the future, so erase it.
|
||||||
|
* */
|
||||||
|
config->erase("colorprint_heights");
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique.
|
// Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique.
|
||||||
void check_model_ids_validity(const Model &model)
|
void check_model_ids_validity(const Model &model)
|
||||||
|
|
|
@ -749,33 +749,30 @@ public:
|
||||||
// Extensions for color print
|
// Extensions for color print
|
||||||
struct CustomGCode
|
struct CustomGCode
|
||||||
{
|
{
|
||||||
CustomGCode(double height, const std::string& code, int extruder, const std::string& color) :
|
bool operator<(const CustomGCode& other) const { return other.print_z > this->print_z; }
|
||||||
height(height), gcode(code), extruder(extruder), color(color) {}
|
|
||||||
|
|
||||||
bool operator<(const CustomGCode& other) const { return other.height > this->height; }
|
|
||||||
bool operator==(const CustomGCode& other) const
|
bool operator==(const CustomGCode& other) const
|
||||||
{
|
{
|
||||||
return (other.height == this->height) &&
|
return (other.print_z == this->print_z ) &&
|
||||||
(other.gcode == this->gcode) &&
|
(other.gcode == this->gcode ) &&
|
||||||
(other.extruder == this->extruder )&&
|
(other.extruder == this->extruder ) &&
|
||||||
(other.color == this->color );
|
(other.color == this->color );
|
||||||
}
|
}
|
||||||
bool operator!=(const CustomGCode& other) const
|
bool operator!=(const CustomGCode& other) const
|
||||||
{
|
{
|
||||||
return (other.height != this->height) ||
|
return (other.print_z != this->print_z ) ||
|
||||||
(other.gcode != this->gcode) ||
|
(other.gcode != this->gcode ) ||
|
||||||
(other.extruder != this->extruder )||
|
(other.extruder != this->extruder ) ||
|
||||||
(other.color != this->color );
|
(other.color != this->color );
|
||||||
}
|
}
|
||||||
|
|
||||||
double height;
|
double print_z;
|
||||||
std::string gcode;
|
std::string gcode;
|
||||||
int extruder; // 0 - "gcode" will be applied for whole print
|
int extruder; // 0 - "gcode" will be applied for whole print
|
||||||
// else - "gcode" will be applied only for "extruder" print
|
// else - "gcode" will be applied only for "extruder" print
|
||||||
std::string color; // if gcode is equal to PausePrintCode,
|
std::string color; // if gcode is equal to PausePrintCode,
|
||||||
// this field is used for save a short message shown on Printer display
|
// this field is used for save a short message shown on Printer display
|
||||||
};
|
};
|
||||||
std::vector<CustomGCode> custom_gcode_per_height;
|
std::vector<CustomGCode> custom_gcode_per_print_z;
|
||||||
|
|
||||||
// Default constructor assigns a new ID to the model.
|
// Default constructor assigns a new ID to the model.
|
||||||
Model() { assert(this->id().valid()); }
|
Model() { assert(this->id().valid()); }
|
||||||
|
@ -841,7 +838,7 @@ public:
|
||||||
// Propose an output path, replace extension. The new_extension shall contain the initial dot.
|
// Propose an output path, replace extension. The new_extension shall contain the initial dot.
|
||||||
std::string propose_export_file_name_and_path(const std::string &new_extension) const;
|
std::string propose_export_file_name_and_path(const std::string &new_extension) const;
|
||||||
|
|
||||||
// from custom_gcode_per_height get just tool_change codes
|
// from custom_gcode_per_print_z get just tool_change codes
|
||||||
std::vector<std::pair<double, DynamicPrintConfig>> get_custom_tool_changes(double default_layer_height, size_t num_extruders) const;
|
std::vector<std::pair<double, DynamicPrintConfig>> get_custom_tool_changes(double default_layer_height, size_t num_extruders) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -877,6 +874,10 @@ extern bool model_volume_list_changed(const ModelObject &model_object_old, const
|
||||||
extern bool model_has_multi_part_objects(const Model &model);
|
extern bool model_has_multi_part_objects(const Model &model);
|
||||||
// If the model has advanced features, then it cannot be processed in simple mode.
|
// If the model has advanced features, then it cannot be processed in simple mode.
|
||||||
extern bool model_has_advanced_features(const Model &model);
|
extern bool model_has_advanced_features(const Model &model);
|
||||||
|
/* If loaded configuration has a "colorprint_heights" option (if it was imported from older Slicer),
|
||||||
|
* then model.custom_gcode_per_print_z should be updated considering this option
|
||||||
|
* */
|
||||||
|
extern void update_custom_gcode_per_print_z_from_config(std::vector<Model::CustomGCode>& custom_gcode_per_print_z, DynamicPrintConfig* config);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique.
|
// Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique.
|
||||||
|
|
|
@ -739,10 +739,10 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||||
model_object_status.emplace(model_object->id(), ModelObjectStatus::Old);
|
model_object_status.emplace(model_object->id(), ModelObjectStatus::Old);
|
||||||
|
|
||||||
// But if custom gcode per layer height was changed
|
// But if custom gcode per layer height was changed
|
||||||
if (m_model.custom_gcode_per_height != model.custom_gcode_per_height) {
|
if (m_model.custom_gcode_per_print_z != model.custom_gcode_per_print_z) {
|
||||||
// we should stop background processing
|
// we should stop background processing
|
||||||
update_apply_status(this->invalidate_step(psGCodeExport));
|
update_apply_status(this->invalidate_step(psGCodeExport));
|
||||||
m_model.custom_gcode_per_height = model.custom_gcode_per_height;
|
m_model.custom_gcode_per_print_z = model.custom_gcode_per_print_z;
|
||||||
}
|
}
|
||||||
} else if (model_object_list_extended(m_model, model)) {
|
} else if (model_object_list_extended(m_model, model)) {
|
||||||
// Add new objects. Their volumes and configs will be synchronized later.
|
// Add new objects. Their volumes and configs will be synchronized later.
|
||||||
|
|
|
@ -71,12 +71,6 @@ enum SLAPillarConnectionMode {
|
||||||
slapcmDynamic
|
slapcmDynamic
|
||||||
};
|
};
|
||||||
|
|
||||||
// ys_FIXME ! may be, it's not a best place
|
|
||||||
// Additional Codes which can be set by user using DoubleSlider
|
|
||||||
static const std::string ColorChangeCode = "M600";
|
|
||||||
static const std::string PausePrintCode = "M601";
|
|
||||||
static const std::string ExtruderChangeCode = "tool_change";
|
|
||||||
|
|
||||||
template<> inline const t_config_enum_values& ConfigOptionEnum<PrinterTechnology>::get_enum_values() {
|
template<> inline const t_config_enum_values& ConfigOptionEnum<PrinterTechnology>::get_enum_values() {
|
||||||
static t_config_enum_values keys_map;
|
static t_config_enum_values keys_map;
|
||||||
if (keys_map.empty()) {
|
if (keys_map.empty()) {
|
||||||
|
|
|
@ -43,6 +43,7 @@ std::vector<std::pair<size_t, bool>> chain_segments_closest_point(std::vector<En
|
||||||
assert(next_idx < end_points.size());
|
assert(next_idx < end_points.size());
|
||||||
EndPointType &end_point = end_points[next_idx];
|
EndPointType &end_point = end_points[next_idx];
|
||||||
end_point.chain_id = 1;
|
end_point.chain_id = 1;
|
||||||
|
out.emplace_back(next_idx / 2, (next_idx & 1) != 0);
|
||||||
this_idx = next_idx ^ 1;
|
this_idx = next_idx ^ 1;
|
||||||
}
|
}
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@ -72,7 +73,7 @@ std::vector<std::pair<size_t, bool>> chain_segments_greedy_constrained_reversals
|
||||||
else if (num_segments == 1)
|
else if (num_segments == 1)
|
||||||
{
|
{
|
||||||
// Just sort the end points so that the first point visited is closest to start_near.
|
// Just sort the end points so that the first point visited is closest to start_near.
|
||||||
out.emplace_back(0, start_near != nullptr &&
|
out.emplace_back(0, could_reverse_func(0) && start_near != nullptr &&
|
||||||
(end_point_func(0, true) - *start_near).template cast<double>().squaredNorm() < (end_point_func(0, false) - *start_near).template cast<double>().squaredNorm());
|
(end_point_func(0, true) - *start_near).template cast<double>().squaredNorm() < (end_point_func(0, false) - *start_near).template cast<double>().squaredNorm());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -999,13 +1000,13 @@ std::vector<std::pair<size_t, bool>> chain_extrusion_entities(std::vector<Extrus
|
||||||
auto segment_end_point = [&entities](size_t idx, bool first_point) -> const Point& { return first_point ? entities[idx]->first_point() : entities[idx]->last_point(); };
|
auto segment_end_point = [&entities](size_t idx, bool first_point) -> const Point& { return first_point ? entities[idx]->first_point() : entities[idx]->last_point(); };
|
||||||
auto could_reverse = [&entities](size_t idx) { const ExtrusionEntity *ee = entities[idx]; return ee->is_loop() || ee->can_reverse(); };
|
auto could_reverse = [&entities](size_t idx) { const ExtrusionEntity *ee = entities[idx]; return ee->is_loop() || ee->can_reverse(); };
|
||||||
std::vector<std::pair<size_t, bool>> out = chain_segments_greedy_constrained_reversals<Point, decltype(segment_end_point), decltype(could_reverse)>(segment_end_point, could_reverse, entities.size(), start_near);
|
std::vector<std::pair<size_t, bool>> out = chain_segments_greedy_constrained_reversals<Point, decltype(segment_end_point), decltype(could_reverse)>(segment_end_point, could_reverse, entities.size(), start_near);
|
||||||
for (size_t i = 0; i < entities.size(); ++ i) {
|
for (std::pair<size_t, bool> &segment : out) {
|
||||||
ExtrusionEntity *ee = entities[i];
|
ExtrusionEntity *ee = entities[segment.first];
|
||||||
if (ee->is_loop())
|
if (ee->is_loop())
|
||||||
// Ignore reversals for loops, as the start point equals the end point.
|
// Ignore reversals for loops, as the start point equals the end point.
|
||||||
out[i].second = false;
|
segment.second = false;
|
||||||
// Is can_reverse() respected by the reversals?
|
// Is can_reverse() respected by the reversals?
|
||||||
assert(entities[i]->can_reverse() || ! out[i].second);
|
assert(ee->can_reverse() || ! segment.second);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,38 +224,14 @@ std::vector<coordf_t> layer_height_profile_from_ranges(
|
||||||
|
|
||||||
// Based on the work of @platsch
|
// Based on the work of @platsch
|
||||||
// Fill layer_height_profile by heights ensuring a prescribed maximum cusp height.
|
// Fill layer_height_profile by heights ensuring a prescribed maximum cusp height.
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
std::vector<double> layer_height_profile_adaptive(const SlicingParameters& slicing_params, const ModelObject& object, float quality_factor)
|
||||||
std::vector<double> layer_height_profile_adaptive(const SlicingParameters& slicing_params,
|
|
||||||
const ModelObject& object, float cusp_value)
|
|
||||||
#else
|
|
||||||
std::vector<coordf_t> layer_height_profile_adaptive(
|
|
||||||
const SlicingParameters &slicing_params,
|
|
||||||
const t_layer_config_ranges & /* layer_config_ranges */,
|
|
||||||
const ModelVolumePtrs &volumes)
|
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
{
|
{
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
// 1) Initialize the SlicingAdaptive class with the object meshes.
|
// 1) Initialize the SlicingAdaptive class with the object meshes.
|
||||||
SlicingAdaptive as;
|
SlicingAdaptive as;
|
||||||
as.set_slicing_parameters(slicing_params);
|
as.set_slicing_parameters(slicing_params);
|
||||||
as.set_object(object);
|
as.prepare(object);
|
||||||
#else
|
|
||||||
// 1) Initialize the SlicingAdaptive class with the object meshes.
|
|
||||||
SlicingAdaptive as;
|
|
||||||
as.set_slicing_parameters(slicing_params);
|
|
||||||
for (const ModelVolume* volume : volumes)
|
|
||||||
if (volume->is_model_part())
|
|
||||||
as.add_mesh(&volume->mesh());
|
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
|
|
||||||
as.prepare();
|
|
||||||
|
|
||||||
// 2) Generate layers using the algorithm of @platsch
|
// 2) Generate layers using the algorithm of @platsch
|
||||||
// loop until we have at least one layer and the max slice_z reaches the object height
|
|
||||||
#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
double cusp_value = 0.2;
|
|
||||||
#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
|
|
||||||
std::vector<double> layer_height_profile;
|
std::vector<double> layer_height_profile;
|
||||||
layer_height_profile.push_back(0.0);
|
layer_height_profile.push_back(0.0);
|
||||||
layer_height_profile.push_back(slicing_params.first_object_layer_height);
|
layer_height_profile.push_back(slicing_params.first_object_layer_height);
|
||||||
|
@ -263,39 +239,41 @@ std::vector<coordf_t> layer_height_profile_adaptive(
|
||||||
layer_height_profile.push_back(slicing_params.first_object_layer_height);
|
layer_height_profile.push_back(slicing_params.first_object_layer_height);
|
||||||
layer_height_profile.push_back(slicing_params.first_object_layer_height);
|
layer_height_profile.push_back(slicing_params.first_object_layer_height);
|
||||||
}
|
}
|
||||||
double slice_z = slicing_params.first_object_layer_height;
|
double print_z = slicing_params.first_object_layer_height;
|
||||||
int current_facet = 0;
|
// last facet visited by the as.next_layer_height() function, where the facets are sorted by their increasing Z span.
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
size_t current_facet = 0;
|
||||||
while (slice_z <= slicing_params.object_print_z_height()) {
|
// loop until we have at least one layer and the max slice_z reaches the object height
|
||||||
double height = slicing_params.max_layer_height;
|
while (print_z + EPSILON < slicing_params.object_print_z_height()) {
|
||||||
#else
|
float height = slicing_params.max_layer_height;
|
||||||
double height = slicing_params.first_object_layer_height;
|
|
||||||
while ((slice_z - height) <= slicing_params.object_print_z_height()) {
|
|
||||||
height = 999.0;
|
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
// Slic3r::debugf "\n Slice layer: %d\n", $id;
|
// Slic3r::debugf "\n Slice layer: %d\n", $id;
|
||||||
// determine next layer height
|
// determine next layer height
|
||||||
double cusp_height = as.cusp_height((float)slice_z, cusp_value, current_facet);
|
float cusp_height = as.next_layer_height(float(print_z), quality_factor, current_facet);
|
||||||
|
|
||||||
|
#if 0
|
||||||
// check for horizontal features and object size
|
// check for horizontal features and object size
|
||||||
/*
|
if (this->config.match_horizontal_surfaces.value) {
|
||||||
if($self->config->get_value('match_horizontal_surfaces')) {
|
coordf_t horizontal_dist = as.horizontal_facet_distance(print_z + height, min_layer_height);
|
||||||
my $horizontal_dist = $adaptive_slicing[$region_id]->horizontal_facet_distance(scale $slice_z+$cusp_height, $min_height);
|
if ((horizontal_dist < min_layer_height) && (horizontal_dist > 0)) {
|
||||||
if(($horizontal_dist < $min_height) && ($horizontal_dist > 0)) {
|
#ifdef SLIC3R_DEBUG
|
||||||
Slic3r::debugf "Horizontal feature ahead, distance: %f\n", $horizontal_dist;
|
std::cout << "Horizontal feature ahead, distance: " << horizontal_dist << std::endl;
|
||||||
# can we shrink the current layer a bit?
|
#endif
|
||||||
if($cusp_height-($min_height-$horizontal_dist) > $min_height) {
|
// can we shrink the current layer a bit?
|
||||||
# yes we can
|
if (height-(min_layer_height - horizontal_dist) > min_layer_height) {
|
||||||
$cusp_height = $cusp_height-($min_height-$horizontal_dist);
|
// yes we can
|
||||||
Slic3r::debugf "Shrink layer height to %f\n", $cusp_height;
|
height -= (min_layer_height - horizontal_dist);
|
||||||
}else{
|
#ifdef SLIC3R_DEBUG
|
||||||
# no, current layer would become too thin
|
std::cout << "Shrink layer height to " << height << std::endl;
|
||||||
$cusp_height = $cusp_height+$horizontal_dist;
|
#endif
|
||||||
Slic3r::debugf "Widen layer height to %f\n", $cusp_height;
|
} else {
|
||||||
|
// no, current layer would become too thin
|
||||||
|
height += horizontal_dist;
|
||||||
|
#ifdef SLIC3R_DEBUG
|
||||||
|
std::cout << "Widen layer height to " << height << std::endl;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
#endif
|
||||||
height = std::min(cusp_height, height);
|
height = std::min(cusp_height, height);
|
||||||
|
|
||||||
// apply z-gradation
|
// apply z-gradation
|
||||||
|
@ -308,22 +286,22 @@ std::vector<coordf_t> layer_height_profile_adaptive(
|
||||||
|
|
||||||
// look for an applicable custom range
|
// look for an applicable custom range
|
||||||
/*
|
/*
|
||||||
if (my $range = first { $_->[0] <= $slice_z && $_->[1] > $slice_z } @{$self->layer_height_ranges}) {
|
if (my $range = first { $_->[0] <= $print_z && $_->[1] > $print_z } @{$self->layer_height_ranges}) {
|
||||||
$height = $range->[2];
|
$height = $range->[2];
|
||||||
|
|
||||||
# if user set custom height to zero we should just skip the range and resume slicing over it
|
# if user set custom height to zero we should just skip the range and resume slicing over it
|
||||||
if ($height == 0) {
|
if ($height == 0) {
|
||||||
$slice_z += $range->[1] - $range->[0];
|
$print_z += $range->[1] - $range->[0];
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
layer_height_profile.push_back(slice_z);
|
layer_height_profile.push_back(print_z);
|
||||||
layer_height_profile.push_back(height);
|
layer_height_profile.push_back(height);
|
||||||
slice_z += height;
|
print_z += height;
|
||||||
#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
||||||
layer_height_profile.push_back(slice_z);
|
layer_height_profile.push_back(print_z);
|
||||||
layer_height_profile.push_back(height);
|
layer_height_profile.push_back(height);
|
||||||
#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
||||||
}
|
}
|
||||||
|
@ -722,11 +700,7 @@ int generate_layer_height_texture(
|
||||||
const Vec3crd &color1 = palette_raw[idx1];
|
const Vec3crd &color1 = palette_raw[idx1];
|
||||||
const Vec3crd &color2 = palette_raw[idx2];
|
const Vec3crd &color2 = palette_raw[idx2];
|
||||||
coordf_t z = cell_to_z * coordf_t(cell);
|
coordf_t z = cell_to_z * coordf_t(cell);
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
assert(lo - EPSILON <= z && z <= hi + EPSILON);
|
||||||
assert((lo - EPSILON <= z) && (z <= hi + EPSILON));
|
|
||||||
#else
|
|
||||||
assert(z >= lo && z <= hi);
|
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
// Intensity profile to visualize the layers.
|
// Intensity profile to visualize the layers.
|
||||||
coordf_t intensity = cos(M_PI * 0.7 * (mid - z) / h);
|
coordf_t intensity = cos(M_PI * 0.7 * (mid - z) / h);
|
||||||
// Color mapping from layer height to RGB.
|
// Color mapping from layer height to RGB.
|
||||||
|
|
|
@ -18,12 +18,7 @@ namespace Slic3r
|
||||||
|
|
||||||
class PrintConfig;
|
class PrintConfig;
|
||||||
class PrintObjectConfig;
|
class PrintObjectConfig;
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
class ModelObject;
|
class ModelObject;
|
||||||
#else
|
|
||||||
class ModelVolume;
|
|
||||||
typedef std::vector<ModelVolume*> ModelVolumePtrs;
|
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
|
|
||||||
// Parameters to guide object slicing and support generation.
|
// Parameters to guide object slicing and support generation.
|
||||||
// The slicing parameters account for a raft and whether the 1st object layer is printed with a normal or a bridging flow
|
// The slicing parameters account for a raft and whether the 1st object layer is printed with a normal or a bridging flow
|
||||||
|
@ -142,10 +137,9 @@ extern std::vector<coordf_t> layer_height_profile_from_ranges(
|
||||||
const SlicingParameters &slicing_params,
|
const SlicingParameters &slicing_params,
|
||||||
const t_layer_config_ranges &layer_config_ranges);
|
const t_layer_config_ranges &layer_config_ranges);
|
||||||
|
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
extern std::vector<double> layer_height_profile_adaptive(
|
extern std::vector<double> layer_height_profile_adaptive(
|
||||||
const SlicingParameters& slicing_params,
|
const SlicingParameters& slicing_params,
|
||||||
const ModelObject& object, float cusp_value);
|
const ModelObject& object, float quality_factor);
|
||||||
|
|
||||||
struct HeightProfileSmoothingParams
|
struct HeightProfileSmoothingParams
|
||||||
{
|
{
|
||||||
|
@ -159,12 +153,6 @@ struct HeightProfileSmoothingParams
|
||||||
extern std::vector<double> smooth_height_profile(
|
extern std::vector<double> smooth_height_profile(
|
||||||
const std::vector<double>& profile, const SlicingParameters& slicing_params,
|
const std::vector<double>& profile, const SlicingParameters& slicing_params,
|
||||||
const HeightProfileSmoothingParams& smoothing_params);
|
const HeightProfileSmoothingParams& smoothing_params);
|
||||||
#else
|
|
||||||
extern std::vector<coordf_t> layer_height_profile_adaptive(
|
|
||||||
const SlicingParameters &slicing_params,
|
|
||||||
const t_layer_config_ranges &layer_config_ranges,
|
|
||||||
const ModelVolumePtrs &volumes);
|
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
|
|
||||||
enum LayerHeightEditActionType : unsigned int {
|
enum LayerHeightEditActionType : unsigned int {
|
||||||
LAYER_HEIGHT_EDIT_ACTION_INCREASE = 0,
|
LAYER_HEIGHT_EDIT_ACTION_INCREASE = 0,
|
||||||
|
|
|
@ -1,95 +1,151 @@
|
||||||
#include "libslic3r.h"
|
#include "libslic3r.h"
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
#include "Model.hpp"
|
#include "Model.hpp"
|
||||||
#else
|
|
||||||
#include "TriangleMesh.hpp"
|
#include "TriangleMesh.hpp"
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
#include "SlicingAdaptive.hpp"
|
#include "SlicingAdaptive.hpp"
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
|
// Based on the work of Florens Waserfall (@platch on github)
|
||||||
|
// and his paper
|
||||||
|
// Florens Wasserfall, Norman Hendrich, Jianwei Zhang:
|
||||||
|
// Adaptive Slicing for the FDM Process Revisited
|
||||||
|
// 13th IEEE Conference on Automation Science and Engineering (CASE-2017), August 20-23, Xi'an, China. DOI: 10.1109/COASE.2017.8256074
|
||||||
|
// https://tams.informatik.uni-hamburg.de/publications/2017/Adaptive%20Slicing%20for%20the%20FDM%20Process%20Revisited.pdf
|
||||||
|
|
||||||
|
// Vojtech believes that there is a bug in @platch's derivation of the triangle area error metric.
|
||||||
|
// Following Octave code paints graphs of recommended layer height versus surface slope angle.
|
||||||
|
#if 0
|
||||||
|
adeg=0:1:85;
|
||||||
|
a=adeg*pi/180;
|
||||||
|
t=tan(a);
|
||||||
|
tsqr=sqrt(tan(a));
|
||||||
|
lerr=1./cos(a);
|
||||||
|
lerr2=1./(0.3+cos(a));
|
||||||
|
plot(adeg, t, 'b', adeg, sqrt(t), 'g', adeg, 0.5 * lerr, 'm', adeg, 0.5 * lerr2, 'r')
|
||||||
|
xlabel("angle(deg), 0 - horizontal wall, 90 - vertical wall");
|
||||||
|
ylabel("layer height");
|
||||||
|
legend("tan(a) as cura - topographic lines distance limit", "sqrt(tan(a)) as PrusaSlicer - error triangle area limit", "old slic3r - max distance metric", "new slic3r - Waserfall paper");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#define ADAPTIVE_LAYER_HEIGHT_DEBUG
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
namespace Slic3r
|
namespace Slic3r
|
||||||
{
|
{
|
||||||
|
|
||||||
#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
static inline std::pair<float, float> face_z_span(const stl_facet &f)
|
||||||
void SlicingAdaptive::clear()
|
|
||||||
{
|
|
||||||
m_meshes.clear();
|
|
||||||
m_faces.clear();
|
|
||||||
m_face_normal_z.clear();
|
|
||||||
}
|
|
||||||
#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
|
|
||||||
std::pair<float, float> face_z_span(const stl_facet *f)
|
|
||||||
{
|
{
|
||||||
return std::pair<float, float>(
|
return std::pair<float, float>(
|
||||||
std::min(std::min(f->vertex[0](2), f->vertex[1](2)), f->vertex[2](2)),
|
std::min(std::min(f.vertex[0](2), f.vertex[1](2)), f.vertex[2](2)),
|
||||||
std::max(std::max(f->vertex[0](2), f->vertex[1](2)), f->vertex[2](2)));
|
std::max(std::max(f.vertex[0](2), f.vertex[1](2)), f.vertex[2](2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SlicingAdaptive::prepare()
|
// By Florens Waserfall aka @platch:
|
||||||
|
// This constant essentially describes the volumetric error at the surface which is induced
|
||||||
|
// by stacking "elliptic" extrusion threads. It is empirically determined by
|
||||||
|
// 1. measuring the surface profile of printed parts to find
|
||||||
|
// the ratio between layer height and profile height and then
|
||||||
|
// 2. computing the geometric difference between the model-surface and the elliptic profile.
|
||||||
|
//
|
||||||
|
// The definition of the roughness formula is in
|
||||||
|
// https://tams.informatik.uni-hamburg.de/publications/2017/Adaptive%20Slicing%20for%20the%20FDM%20Process%20Revisited.pdf
|
||||||
|
// (page 51, formula (8))
|
||||||
|
// Currenty @platch's error metric formula is not used.
|
||||||
|
static constexpr double SURFACE_CONST = 0.18403;
|
||||||
|
|
||||||
|
// for a given facet, compute maximum height within the allowed surface roughness / stairstepping deviation
|
||||||
|
static inline float layer_height_from_slope(const SlicingAdaptive::FaceZ &face, float max_surface_deviation)
|
||||||
{
|
{
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
// @platch's formula, see his paper "Adaptive Slicing for the FDM Process Revisited".
|
||||||
if (m_object == nullptr)
|
// return float(max_surface_deviation / (SURFACE_CONST + 0.5 * std::abs(normal_z)));
|
||||||
return;
|
|
||||||
|
|
||||||
|
// Constant stepping in horizontal direction, as used by Cura.
|
||||||
|
// return (face.n_cos > 1e-5) ? float(max_surface_deviation * face.n_sin / face.n_cos) : FLT_MAX;
|
||||||
|
|
||||||
|
// Constant error measured as an area of the surface error triangle, Vojtech's formula.
|
||||||
|
// return (face.n_cos > 1e-5) ? float(1.44 * max_surface_deviation * sqrt(face.n_sin / face.n_cos)) : FLT_MAX;
|
||||||
|
|
||||||
|
// Constant error measured as an area of the surface error triangle, Vojtech's formula with clamping to roughness at 90 degrees.
|
||||||
|
return std::min(max_surface_deviation / 0.184f, (face.n_cos > 1e-5) ? float(1.44 * max_surface_deviation * sqrt(face.n_sin / face.n_cos)) : FLT_MAX);
|
||||||
|
|
||||||
|
// Constant stepping along the surface, equivalent to the "surface roughness" metric by Perez and later Pandey et all, see @platch's paper for references.
|
||||||
|
// return float(max_surface_deviation * face.n_sin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlicingAdaptive::clear()
|
||||||
|
{
|
||||||
m_faces.clear();
|
m_faces.clear();
|
||||||
m_face_normal_z.clear();
|
}
|
||||||
|
|
||||||
m_mesh = m_object->raw_mesh();
|
void SlicingAdaptive::prepare(const ModelObject &object)
|
||||||
const ModelInstance* first_instance = m_object->instances.front();
|
{
|
||||||
m_mesh.transform(first_instance->get_matrix(), first_instance->is_left_handed());
|
this->clear();
|
||||||
|
|
||||||
|
TriangleMesh mesh = object.raw_mesh();
|
||||||
|
const ModelInstance &first_instance = *object.instances.front();
|
||||||
|
mesh.transform(first_instance.get_matrix(), first_instance.is_left_handed());
|
||||||
|
|
||||||
// 1) Collect faces from mesh.
|
// 1) Collect faces from mesh.
|
||||||
m_faces.reserve(m_mesh.stl.stats.number_of_facets);
|
m_faces.reserve(mesh.stl.stats.number_of_facets);
|
||||||
for (stl_facet& face : m_mesh.stl.facet_start)
|
for (const stl_facet &face : mesh.stl.facet_start) {
|
||||||
{
|
Vec3f n = face.normal.normalized();
|
||||||
face.normal.normalize();
|
m_faces.emplace_back(FaceZ({ face_z_span(face), std::abs(n.z()), std::sqrt(n.x() * n.x() + n.y() * n.y()) }));
|
||||||
m_faces.emplace_back(&face);
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
// 1) Collect faces of all meshes.
|
|
||||||
int nfaces_total = 0;
|
|
||||||
for (std::vector<const TriangleMesh*>::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh)
|
|
||||||
nfaces_total += (*it_mesh)->stl.stats.number_of_facets;
|
|
||||||
m_faces.reserve(nfaces_total);
|
|
||||||
for (std::vector<const TriangleMesh*>::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh)
|
|
||||||
for (const stl_facet& face : (*it_mesh)->stl.facet_start)
|
|
||||||
m_faces.emplace_back(&face);
|
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
|
|
||||||
// 2) Sort faces lexicographically by their Z span.
|
// 2) Sort faces lexicographically by their Z span.
|
||||||
std::sort(m_faces.begin(), m_faces.end(), [](const stl_facet *f1, const stl_facet *f2) { return face_z_span(f1) < face_z_span(f2); });
|
std::sort(m_faces.begin(), m_faces.end(), [](const FaceZ &f1, const FaceZ &f2) { return f1.z_span < f2.z_span; });
|
||||||
|
|
||||||
// 3) Generate Z components of the facet normals.
|
|
||||||
m_face_normal_z.assign(m_faces.size(), 0.0f);
|
|
||||||
for (size_t iface = 0; iface < m_faces.size(); ++ iface)
|
|
||||||
m_face_normal_z[iface] = m_faces[iface]->normal(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float SlicingAdaptive::cusp_height(float z, float cusp_value, int ¤t_facet)
|
// current_facet is in/out parameter, rememebers the index of the last face of m_faces visited,
|
||||||
|
// where this function will start from.
|
||||||
|
// print_z - the top print surface of the previous layer.
|
||||||
|
// returns height of the next layer.
|
||||||
|
float SlicingAdaptive::next_layer_height(const float print_z, float quality_factor, size_t ¤t_facet)
|
||||||
{
|
{
|
||||||
float height = (float)m_slicing_params.max_layer_height;
|
float height = (float)m_slicing_params.max_layer_height;
|
||||||
bool first_hit = false;
|
|
||||||
|
float max_surface_deviation;
|
||||||
|
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
// @platch's formula for quality:
|
||||||
|
double delta_min = SURFACE_CONST * m_slicing_params.min_layer_height;
|
||||||
|
double delta_mid = (SURFACE_CONST + 0.5) * m_slicing_params.layer_height;
|
||||||
|
double delta_max = (SURFACE_CONST + 0.5) * m_slicing_params.max_layer_height;
|
||||||
|
#else
|
||||||
|
// Vojtech's formula for triangle area error metric.
|
||||||
|
double delta_min = m_slicing_params.min_layer_height;
|
||||||
|
double delta_mid = m_slicing_params.layer_height;
|
||||||
|
double delta_max = m_slicing_params.max_layer_height;
|
||||||
|
#endif
|
||||||
|
max_surface_deviation = (quality_factor < 0.5f) ?
|
||||||
|
lerp(delta_min, delta_mid, 2. * quality_factor) :
|
||||||
|
lerp(delta_max, delta_mid, 2. * (1. - quality_factor));
|
||||||
|
}
|
||||||
|
|
||||||
// find all facets intersecting the slice-layer
|
// find all facets intersecting the slice-layer
|
||||||
int ordered_id = current_facet;
|
size_t ordered_id = current_facet;
|
||||||
for (; ordered_id < int(m_faces.size()); ++ ordered_id) {
|
{
|
||||||
std::pair<float, float> zspan = face_z_span(m_faces[ordered_id]);
|
bool first_hit = false;
|
||||||
|
for (; ordered_id < m_faces.size(); ++ ordered_id) {
|
||||||
|
const std::pair<float, float> &zspan = m_faces[ordered_id].z_span;
|
||||||
// facet's minimum is higher than slice_z -> end loop
|
// facet's minimum is higher than slice_z -> end loop
|
||||||
if (zspan.first >= z)
|
if (zspan.first >= print_z)
|
||||||
break;
|
break;
|
||||||
// facet's maximum is higher than slice_z -> store the first event for next cusp_height call to begin at this point
|
// facet's maximum is higher than slice_z -> store the first event for next cusp_height call to begin at this point
|
||||||
if (zspan.second > z) {
|
if (zspan.second > print_z) {
|
||||||
// first event?
|
// first event?
|
||||||
if (! first_hit) {
|
if (! first_hit) {
|
||||||
first_hit = true;
|
first_hit = true;
|
||||||
current_facet = ordered_id;
|
current_facet = ordered_id;
|
||||||
}
|
}
|
||||||
// skip touching facets which could otherwise cause small cusp values
|
// skip touching facets which could otherwise cause small cusp values
|
||||||
if (zspan.second <= z + EPSILON)
|
if (zspan.second < print_z + EPSILON)
|
||||||
continue;
|
continue;
|
||||||
// compute cusp-height for this facet and store minimum of all heights
|
// compute cusp-height for this facet and store minimum of all heights
|
||||||
float normal_z = m_face_normal_z[ordered_id];
|
height = std::min(height, layer_height_from_slope(m_faces[ordered_id], max_surface_deviation));
|
||||||
height = std::min(height, (normal_z == 0.0f) ? (float)m_slicing_params.max_layer_height : std::abs(cusp_value / normal_z));
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,60 +153,59 @@ float SlicingAdaptive::cusp_height(float z, float cusp_value, int ¤t_facet
|
||||||
height = std::max(height, float(m_slicing_params.min_layer_height));
|
height = std::max(height, float(m_slicing_params.min_layer_height));
|
||||||
|
|
||||||
// check for sloped facets inside the determined layer and correct height if necessary
|
// check for sloped facets inside the determined layer and correct height if necessary
|
||||||
if (height > m_slicing_params.min_layer_height) {
|
if (height > float(m_slicing_params.min_layer_height)) {
|
||||||
for (; ordered_id < int(m_faces.size()); ++ ordered_id) {
|
for (; ordered_id < m_faces.size(); ++ ordered_id) {
|
||||||
std::pair<float, float> zspan = face_z_span(m_faces[ordered_id]);
|
const std::pair<float, float> &zspan = m_faces[ordered_id].z_span;
|
||||||
// facet's minimum is higher than slice_z + height -> end loop
|
// facet's minimum is higher than slice_z + height -> end loop
|
||||||
if (zspan.first >= z + height)
|
if (zspan.first >= print_z + height)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// skip touching facets which could otherwise cause small cusp values
|
// skip touching facets which could otherwise cause small cusp values
|
||||||
if (zspan.second <= z + EPSILON)
|
if (zspan.second < print_z + EPSILON)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Compute cusp-height for this facet and check against height.
|
// Compute cusp-height for this facet and check against height.
|
||||||
float normal_z = m_face_normal_z[ordered_id];
|
float reduced_height = layer_height_from_slope(m_faces[ordered_id], max_surface_deviation);
|
||||||
float cusp = (normal_z == 0.0f) ? (float)m_slicing_params.max_layer_height : std::abs(cusp_value / normal_z);
|
|
||||||
|
|
||||||
float z_diff = zspan.first - z;
|
float z_diff = zspan.first - print_z;
|
||||||
|
if (reduced_height < z_diff) {
|
||||||
// handle horizontal facets
|
assert(z_diff < height + EPSILON);
|
||||||
if (normal_z > 0.999f) {
|
// The currently visited triangle's slope limits the next layer height so much, that
|
||||||
// Slic3r::debugf "cusp computation, height is reduced from %f", $height;
|
// the lowest point of the currently visible triangle is already above the newly proposed layer height.
|
||||||
|
// This means, that we need to limit the layer height so that the offending newly visited triangle
|
||||||
|
// is just above of the new layer.
|
||||||
|
#ifdef ADAPTIVE_LAYER_HEIGHT_DEBUG
|
||||||
|
BOOST_LOG_TRIVIAL(trace) << "cusp computation, height is reduced from " << height << "to " << z_diff << " due to z-diff";
|
||||||
|
#endif /* ADAPTIVE_LAYER_HEIGHT_DEBUG */
|
||||||
height = z_diff;
|
height = z_diff;
|
||||||
// Slic3r::debugf "to %f due to near horizontal facet\n", $height;
|
} else if (reduced_height < height) {
|
||||||
} else if (cusp > z_diff) {
|
#ifdef ADAPTIVE_LAYER_HEIGHT_DEBUG
|
||||||
if (cusp < height) {
|
BOOST_LOG_TRIVIAL(trace) << "adaptive layer computation: height is reduced from " << height << "to " << reduced_height << " due to higher facet";
|
||||||
// Slic3r::debugf "cusp computation, height is reduced from %f", $height;
|
#endif /* ADAPTIVE_LAYER_HEIGHT_DEBUG */
|
||||||
height = cusp;
|
height = reduced_height;
|
||||||
// Slic3r::debugf "to %f due to new cusp height\n", $height;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Slic3r::debugf "cusp computation, height is reduced from %f", $height;
|
|
||||||
height = z_diff;
|
|
||||||
// Slic3r::debugf "to z-diff: %f\n", $height;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// lower height limit due to printer capabilities again
|
// lower height limit due to printer capabilities again
|
||||||
height = std::max(height, float(m_slicing_params.min_layer_height));
|
height = std::max(height, float(m_slicing_params.min_layer_height));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slic3r::debugf "cusp computation, layer-bottom at z:%f, cusp_value:%f, resulting layer height:%f\n", unscale $z, $cusp_value, $height;
|
#ifdef ADAPTIVE_LAYER_HEIGHT_DEBUG
|
||||||
|
BOOST_LOG_TRIVIAL(trace) << "adaptive layer computation, layer-bottom at z:" << print_z << ", quality_factor:" << quality_factor << ", resulting layer height:" << height;
|
||||||
|
#endif /* ADAPTIVE_LAYER_HEIGHT_DEBUG */
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
// Returns the distance to the next horizontal facet in Z-dir
|
// Returns the distance to the next horizontal facet in Z-dir
|
||||||
// to consider horizontal object features in slice thickness
|
// to consider horizontal object features in slice thickness
|
||||||
float SlicingAdaptive::horizontal_facet_distance(float z)
|
float SlicingAdaptive::horizontal_facet_distance(float z)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < m_faces.size(); ++ i) {
|
for (size_t i = 0; i < m_faces.size(); ++ i) {
|
||||||
std::pair<float, float> zspan = face_z_span(m_faces[i]);
|
std::pair<float, float> zspan = m_faces[i].z_span;
|
||||||
// facet's minimum is higher than max forward distance -> end loop
|
// facet's minimum is higher than max forward distance -> end loop
|
||||||
if (zspan.first > z + m_slicing_params.max_layer_height)
|
if (zspan.first > z + m_slicing_params.max_layer_height)
|
||||||
break;
|
break;
|
||||||
// min_z == max_z -> horizontal facet
|
// min_z == max_z -> horizontal facet
|
||||||
if ((zspan.first > z) && (zspan.first == zspan.second))
|
if (zspan.first > z && zspan.first == zspan.second)
|
||||||
return zspan.first - z;
|
return zspan.first - z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +213,5 @@ float SlicingAdaptive::horizontal_facet_distance(float z)
|
||||||
return (z + (float)m_slicing_params.max_layer_height > (float)m_slicing_params.object_print_z_height()) ?
|
return (z + (float)m_slicing_params.max_layer_height > (float)m_slicing_params.object_print_z_height()) ?
|
||||||
std::max((float)m_slicing_params.object_print_z_height() - z, 0.f) : (float)m_slicing_params.max_layer_height;
|
std::max((float)m_slicing_params.object_print_z_height() - z, 0.f) : (float)m_slicing_params.max_layer_height;
|
||||||
}
|
}
|
||||||
#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
|
|
||||||
}; // namespace Slic3r
|
}; // namespace Slic3r
|
||||||
|
|
|
@ -5,50 +5,36 @@
|
||||||
|
|
||||||
#include "Slicing.hpp"
|
#include "Slicing.hpp"
|
||||||
#include "admesh/stl.h"
|
#include "admesh/stl.h"
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
#include "TriangleMesh.hpp"
|
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
|
|
||||||
namespace Slic3r
|
namespace Slic3r
|
||||||
{
|
{
|
||||||
|
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
class ModelVolume;
|
class ModelVolume;
|
||||||
#else
|
|
||||||
class TriangleMesh;
|
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
|
|
||||||
class SlicingAdaptive
|
class SlicingAdaptive
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
void clear();
|
void clear();
|
||||||
#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
void set_slicing_parameters(SlicingParameters params) { m_slicing_params = params; }
|
void set_slicing_parameters(SlicingParameters params) { m_slicing_params = params; }
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
void prepare(const ModelObject &object);
|
||||||
void set_object(const ModelObject& object) { m_object = &object; }
|
// Return next layer height starting from the last print_z, using a quality measure
|
||||||
#else
|
// (quality in range from 0 to 1, 0 - highest quality at low layer heights, 1 - lowest print quality at high layer heights).
|
||||||
void add_mesh(const TriangleMesh* mesh) { m_meshes.push_back(mesh); }
|
// The layer height curve shall be centered roughly around the default profile's layer height for quality 0.5.
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
float next_layer_height(const float print_z, float quality, size_t ¤t_facet);
|
||||||
void prepare();
|
|
||||||
float cusp_height(float z, float cusp_value, int ¤t_facet);
|
|
||||||
#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
float horizontal_facet_distance(float z);
|
float horizontal_facet_distance(float z);
|
||||||
#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
|
struct FaceZ {
|
||||||
|
std::pair<float, float> z_span;
|
||||||
|
// Cosine of the normal vector towards the Z axis.
|
||||||
|
float n_cos;
|
||||||
|
// Sine of the normal vector towards the Z axis.
|
||||||
|
float n_sin;
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SlicingParameters m_slicing_params;
|
SlicingParameters m_slicing_params;
|
||||||
|
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
std::vector<FaceZ> m_faces;
|
||||||
const ModelObject* m_object;
|
|
||||||
TriangleMesh m_mesh;
|
|
||||||
#else
|
|
||||||
std::vector<const TriangleMesh*> m_meshes;
|
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
// Collected faces of all meshes, sorted by raising Z of the bottom most face.
|
|
||||||
std::vector<const stl_facet*> m_faces;
|
|
||||||
// Z component of face normals, normalized.
|
|
||||||
std::vector<float> m_face_normal_z;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace Slic3r
|
}; // namespace Slic3r
|
||||||
|
|
|
@ -53,4 +53,7 @@
|
||||||
// Enable selection for missing files in reload from disk command
|
// Enable selection for missing files in reload from disk command
|
||||||
#define ENABLE_RELOAD_FROM_DISK_MISSING_SELECTION (1 && ENABLE_2_2_0_ALPHA1)
|
#define ENABLE_RELOAD_FROM_DISK_MISSING_SELECTION (1 && ENABLE_2_2_0_ALPHA1)
|
||||||
|
|
||||||
|
// Enable closing 3Dconnextion imgui settings dialog by clicking on [X] and [Close] buttons
|
||||||
|
#define ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG (1 && ENABLE_2_2_0_ALPHA1)
|
||||||
|
|
||||||
#endif // _technologies_h_
|
#endif // _technologies_h_
|
||||||
|
|
|
@ -94,12 +94,13 @@ void BackgroundSlicingProcess::process_fff()
|
||||||
m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data);
|
m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data);
|
||||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
if (m_fff_print->model().custom_gcode_per_height != GUI::wxGetApp().model().custom_gcode_per_height) {
|
/* #ys_FIXME_no_exported_codes
|
||||||
GUI::wxGetApp().model().custom_gcode_per_height = m_fff_print->model().custom_gcode_per_height;
|
if (m_fff_print->model().custom_gcode_per_print_z != GUI::wxGetApp().model().custom_gcode_per_print_z) {
|
||||||
// #ys_FIXME : controll text
|
GUI::wxGetApp().model().custom_gcode_per_print_z = m_fff_print->model().custom_gcode_per_print_z;
|
||||||
GUI::show_info(nullptr, _(L("To except of redundant tool manipulation, \n"
|
GUI::show_info(nullptr, _(L("To except of redundant tool manipulation, \n"
|
||||||
"Color change(s) for unused extruder(s) was(were) deleted")), _(L("Info")));
|
"Color change(s) for unused extruder(s) was(were) deleted")), _(L("Info")));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (this->set_step_started(bspsGCodeFinalize)) {
|
if (this->set_step_started(bspsGCodeFinalize)) {
|
||||||
if (! m_export_path.empty()) {
|
if (! m_export_path.empty()) {
|
||||||
|
|
|
@ -133,7 +133,7 @@ GLCanvas3D::LayersEditing::LayersEditing()
|
||||||
, m_slicing_parameters(nullptr)
|
, m_slicing_parameters(nullptr)
|
||||||
, m_layer_height_profile_modified(false)
|
, m_layer_height_profile_modified(false)
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
||||||
, m_adaptive_cusp(0.0f)
|
, m_adaptive_quality(0.5f)
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
||||||
, state(Unknown)
|
, state(Unknown)
|
||||||
, band_width(2.0f)
|
, band_width(2.0f)
|
||||||
|
@ -268,24 +268,24 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (imgui.button(_(L("Adaptive"))))
|
if (imgui.button(_(L("Adaptive"))))
|
||||||
wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), Event<float>(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, m_adaptive_cusp));
|
wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), Event<float>(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, m_adaptive_quality));
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
float text_align = ImGui::GetCursorPosX();
|
float text_align = ImGui::GetCursorPosX();
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
imgui.text(_(L("Cusp (mm)")));
|
imgui.text(_(L("Quality / Speed")));
|
||||||
if (ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
{
|
{
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
ImGui::TextUnformatted(_(L("I am a tooltip")));
|
ImGui::TextUnformatted(_(L("Higher print quality versus higher print speed.")));
|
||||||
ImGui::EndTooltip();
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
float widget_align = ImGui::GetCursorPosX();
|
float widget_align = ImGui::GetCursorPosX();
|
||||||
ImGui::PushItemWidth(imgui.get_style_scaling() * 120.0f);
|
ImGui::PushItemWidth(imgui.get_style_scaling() * 120.0f);
|
||||||
m_adaptive_cusp = clamp(0.0f, 0.5f * (float)m_slicing_parameters->layer_height, m_adaptive_cusp);
|
m_adaptive_quality = clamp(0.0f, 1.f, m_adaptive_quality);
|
||||||
ImGui::SliderFloat("", &m_adaptive_cusp, 0.0f, 0.5f * (float)m_slicing_parameters->layer_height, "%.3f");
|
ImGui::SliderFloat("", &m_adaptive_quality, 0.0f, 1.f, "%.2f");
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (imgui.button(_(L("Smooth"))))
|
if (imgui.button(_(L("Smooth"))))
|
||||||
|
@ -645,10 +645,10 @@ void GLCanvas3D::LayersEditing::reset_layer_height_profile(GLCanvas3D& canvas)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
||||||
void GLCanvas3D::LayersEditing::adaptive_layer_height_profile(GLCanvas3D& canvas, float cusp)
|
void GLCanvas3D::LayersEditing::adaptive_layer_height_profile(GLCanvas3D& canvas, float quality_factor)
|
||||||
{
|
{
|
||||||
this->update_slicing_parameters();
|
this->update_slicing_parameters();
|
||||||
m_layer_height_profile = layer_height_profile_adaptive(*m_slicing_parameters, *m_model_object, cusp);
|
m_layer_height_profile = layer_height_profile_adaptive(*m_slicing_parameters, *m_model_object, quality_factor);
|
||||||
const_cast<ModelObject*>(m_model_object)->layer_height_profile = m_layer_height_profile;
|
const_cast<ModelObject*>(m_model_object)->layer_height_profile = m_layer_height_profile;
|
||||||
m_layers_texture.valid = false;
|
m_layers_texture.valid = false;
|
||||||
canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
||||||
|
@ -712,11 +712,6 @@ void GLCanvas3D::LayersEditing::update_slicing_parameters()
|
||||||
m_slicing_parameters = new SlicingParameters();
|
m_slicing_parameters = new SlicingParameters();
|
||||||
*m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object, m_object_max_z);
|
*m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object, m_object_max_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
if (m_adaptive_cusp == 0.0f)
|
|
||||||
m_adaptive_cusp = 0.25f * m_slicing_parameters->layer_height;
|
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float GLCanvas3D::LayersEditing::thickness_bar_width(const GLCanvas3D &canvas)
|
float GLCanvas3D::LayersEditing::thickness_bar_width(const GLCanvas3D &canvas)
|
||||||
|
@ -1016,24 +1011,25 @@ void GLCanvas3D::LegendTexture::fill_color_print_legend_items( const GLCanvas3D
|
||||||
std::vector<float>& colors,
|
std::vector<float>& colors,
|
||||||
std::vector<std::string>& cp_legend_items)
|
std::vector<std::string>& cp_legend_items)
|
||||||
{
|
{
|
||||||
std::vector<Model::CustomGCode> custom_gcode_per_height = wxGetApp().plater()->model().custom_gcode_per_height;
|
std::vector<Model::CustomGCode> custom_gcode_per_print_z = wxGetApp().plater()->model().custom_gcode_per_print_z;
|
||||||
|
|
||||||
const int extruders_cnt = wxGetApp().extruders_edited_cnt();
|
const int extruders_cnt = wxGetApp().extruders_edited_cnt();
|
||||||
if (extruders_cnt == 1)
|
if (extruders_cnt == 1)
|
||||||
{
|
{
|
||||||
if (custom_gcode_per_height.empty()) {
|
if (custom_gcode_per_print_z.empty()) {
|
||||||
cp_legend_items.push_back(I18N::translate_utf8(L("Default print color")));
|
cp_legend_items.emplace_back(I18N::translate_utf8(L("Default print color")));
|
||||||
colors = colors_in;
|
colors = colors_in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::vector<std::pair<double, double>> cp_values;
|
std::vector<std::pair<double, double>> cp_values;
|
||||||
|
cp_values.reserve(custom_gcode_per_print_z.size());
|
||||||
|
|
||||||
std::vector<double> print_zs = canvas.get_current_print_zs(true);
|
std::vector<double> print_zs = canvas.get_current_print_zs(true);
|
||||||
for (auto custom_code : custom_gcode_per_height)
|
for (auto custom_code : custom_gcode_per_print_z)
|
||||||
{
|
{
|
||||||
if (custom_code.gcode != ColorChangeCode)
|
if (custom_code.gcode != ColorChangeCode)
|
||||||
continue;
|
continue;
|
||||||
auto lower_b = std::lower_bound(print_zs.begin(), print_zs.end(), custom_code.height - DoubleSlider::epsilon());
|
auto lower_b = std::lower_bound(print_zs.begin(), print_zs.end(), custom_code.print_z - DoubleSlider::epsilon());
|
||||||
|
|
||||||
if (lower_b == print_zs.end())
|
if (lower_b == print_zs.end())
|
||||||
continue;
|
continue;
|
||||||
|
@ -1044,14 +1040,14 @@ void GLCanvas3D::LegendTexture::fill_color_print_legend_items( const GLCanvas3D
|
||||||
// to avoid duplicate values, check adding values
|
// to avoid duplicate values, check adding values
|
||||||
if (cp_values.empty() ||
|
if (cp_values.empty() ||
|
||||||
!(cp_values.back().first == previous_z && cp_values.back().second == current_z))
|
!(cp_values.back().first == previous_z && cp_values.back().second == current_z))
|
||||||
cp_values.push_back(std::pair<double, double>(previous_z, current_z));
|
cp_values.emplace_back(std::pair<double, double>(previous_z, current_z));
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto items_cnt = (int)cp_values.size();
|
const auto items_cnt = (int)cp_values.size();
|
||||||
if (items_cnt == 0) // There is no one color change, but there is/are some pause print or custom Gcode
|
if (items_cnt == 0) // There is no one color change, but there is/are some pause print or custom Gcode
|
||||||
{
|
{
|
||||||
cp_legend_items.push_back(I18N::translate_utf8(L("Default print color")));
|
cp_legend_items.emplace_back(I18N::translate_utf8(L("Default print color")));
|
||||||
cp_legend_items.push_back(I18N::translate_utf8(L("Pause print or custom G-code")));
|
cp_legend_items.emplace_back(I18N::translate_utf8(L("Pause print or custom G-code")));
|
||||||
colors = colors_in;
|
colors = colors_in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1060,7 +1056,7 @@ void GLCanvas3D::LegendTexture::fill_color_print_legend_items( const GLCanvas3D
|
||||||
colors.resize(colors_in.size(), 0.0);
|
colors.resize(colors_in.size(), 0.0);
|
||||||
|
|
||||||
::memcpy((void*)(colors.data()), (const void*)(colors_in.data() + (color_cnt - 1) * 4), 4 * sizeof(float));
|
::memcpy((void*)(colors.data()), (const void*)(colors_in.data() + (color_cnt - 1) * 4), 4 * sizeof(float));
|
||||||
cp_legend_items.push_back(I18N::translate_utf8(L("Pause print or custom G-code")));
|
cp_legend_items.emplace_back(I18N::translate_utf8(L("Pause print or custom G-code")));
|
||||||
size_t color_pos = 4;
|
size_t color_pos = 4;
|
||||||
|
|
||||||
for (int i = items_cnt; i >= 0; --i, color_pos+=4)
|
for (int i = items_cnt; i >= 0; --i, color_pos+=4)
|
||||||
|
@ -1072,15 +1068,15 @@ void GLCanvas3D::LegendTexture::fill_color_print_legend_items( const GLCanvas3D
|
||||||
std::string id_str = std::to_string(i + 1) + ": ";
|
std::string id_str = std::to_string(i + 1) + ": ";
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
cp_legend_items.push_back(id_str + (boost::format(I18N::translate_utf8(L("up to %.2f mm"))) % cp_values[0].first).str());
|
cp_legend_items.emplace_back(id_str + (boost::format(I18N::translate_utf8(L("up to %.2f mm"))) % cp_values[0].first).str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i == items_cnt) {
|
if (i == items_cnt) {
|
||||||
cp_legend_items.push_back(id_str + (boost::format(I18N::translate_utf8(L("above %.2f mm"))) % cp_values[i - 1].second).str());
|
cp_legend_items.emplace_back(id_str + (boost::format(I18N::translate_utf8(L("above %.2f mm"))) % cp_values[i - 1].second).str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cp_legend_items.push_back(id_str + (boost::format(I18N::translate_utf8(L("%.2f - %.2f mm"))) % cp_values[i - 1].second % cp_values[i].first).str());
|
cp_legend_items.emplace_back(id_str + (boost::format(I18N::translate_utf8(L("%.2f - %.2f mm"))) % cp_values[i - 1].second % cp_values[i].first).str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1094,20 +1090,20 @@ void GLCanvas3D::LegendTexture::fill_color_print_legend_items( const GLCanvas3D
|
||||||
size_t color_in_pos = 4 * (color_cnt - 1);
|
size_t color_in_pos = 4 * (color_cnt - 1);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < (unsigned int)extruders_cnt; ++i)
|
for (unsigned int i = 0; i < (unsigned int)extruders_cnt; ++i)
|
||||||
cp_legend_items.push_back((boost::format(I18N::translate_utf8(L("Extruder %d"))) % (i + 1)).str());
|
cp_legend_items.emplace_back((boost::format(I18N::translate_utf8(L("Extruder %d"))) % (i + 1)).str());
|
||||||
|
|
||||||
::memcpy((void*)(colors.data() + color_pos), (const void*)(colors_in.data() + color_in_pos), 4 * sizeof(float));
|
::memcpy((void*)(colors.data() + color_pos), (const void*)(colors_in.data() + color_in_pos), 4 * sizeof(float));
|
||||||
color_pos += 4;
|
color_pos += 4;
|
||||||
color_in_pos -= 4;
|
color_in_pos -= 4;
|
||||||
cp_legend_items.push_back(I18N::translate_utf8(L("Pause print or custom G-code")));
|
cp_legend_items.emplace_back(I18N::translate_utf8(L("Pause print or custom G-code")));
|
||||||
|
|
||||||
int cnt = custom_gcode_per_height.size();
|
int cnt = custom_gcode_per_print_z.size();
|
||||||
for (int i = cnt-1; i >= 0; --i)
|
for (int i = cnt-1; i >= 0; --i)
|
||||||
if (custom_gcode_per_height[i].gcode == ColorChangeCode) {
|
if (custom_gcode_per_print_z[i].gcode == ColorChangeCode) {
|
||||||
::memcpy((void*)(colors.data() + color_pos), (const void*)(colors_in.data() + color_in_pos), 4 * sizeof(float));
|
::memcpy((void*)(colors.data() + color_pos), (const void*)(colors_in.data() + color_in_pos), 4 * sizeof(float));
|
||||||
color_pos += 4;
|
color_pos += 4;
|
||||||
color_in_pos -= 4;
|
color_in_pos -= 4;
|
||||||
cp_legend_items.push_back((boost::format(I18N::translate_utf8(L("Color change for Extruder %d at %.2f mm"))) % custom_gcode_per_height[i].extruder % custom_gcode_per_height[i].height).str());
|
cp_legend_items.emplace_back((boost::format(I18N::translate_utf8(L("Color change for Extruder %d at %.2f mm"))) % custom_gcode_per_print_z[i].extruder % custom_gcode_per_print_z[i].print_z).str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1688,10 +1684,10 @@ void GLCanvas3D::reset_layer_height_profile()
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCanvas3D::adaptive_layer_height_profile(float cusp)
|
void GLCanvas3D::adaptive_layer_height_profile(float quality_factor)
|
||||||
{
|
{
|
||||||
wxGetApp().plater()->take_snapshot(_(L("Variable layer height - Adaptive")));
|
wxGetApp().plater()->take_snapshot(_(L("Variable layer height - Adaptive")));
|
||||||
m_layers_editing.adaptive_layer_height_profile(*this, cusp);
|
m_layers_editing.adaptive_layer_height_profile(*this, quality_factor);
|
||||||
m_layers_editing.state = LayersEditing::Completed;
|
m_layers_editing.state = LayersEditing::Completed;
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
|
@ -1925,7 +1921,11 @@ void GLCanvas3D::render()
|
||||||
m_camera.debug_render();
|
m_camera.debug_render();
|
||||||
#endif // ENABLE_CAMERA_STATISTICS
|
#endif // ENABLE_CAMERA_STATISTICS
|
||||||
|
|
||||||
|
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
wxGetApp().plater()->get_mouse3d_controller().render_settings_dialog(*this);
|
||||||
|
#else
|
||||||
wxGetApp().plater()->get_mouse3d_controller().render_settings_dialog((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height());
|
wxGetApp().plater()->get_mouse3d_controller().render_settings_dialog((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height());
|
||||||
|
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
|
||||||
wxGetApp().imgui()->render();
|
wxGetApp().imgui()->render();
|
||||||
|
|
||||||
|
@ -2633,8 +2633,8 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
|
||||||
if (m_extra_frame_requested || mouse3d_controller_applied)
|
if (m_extra_frame_requested || mouse3d_controller_applied)
|
||||||
{
|
{
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
evt.RequestMore();
|
|
||||||
m_extra_frame_requested = false;
|
m_extra_frame_requested = false;
|
||||||
|
evt.RequestMore();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_dirty = false;
|
m_dirty = false;
|
||||||
|
@ -5390,7 +5390,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||||
// For coloring by a color_print(M600), return a parsed color.
|
// For coloring by a color_print(M600), return a parsed color.
|
||||||
bool color_by_color_print() const { return color_print_values!=nullptr; }
|
bool color_by_color_print() const { return color_print_values!=nullptr; }
|
||||||
const size_t color_print_color_idx_by_layer_idx(const size_t layer_idx) const {
|
const size_t color_print_color_idx_by_layer_idx(const size_t layer_idx) const {
|
||||||
const Model::CustomGCode value(layers[layer_idx]->print_z + EPSILON, "", 0, "");
|
const Model::CustomGCode value{layers[layer_idx]->print_z + EPSILON, "", 0, ""};
|
||||||
auto it = std::lower_bound(color_print_values->begin(), color_print_values->end(), value);
|
auto it = std::lower_bound(color_print_values->begin(), color_print_values->end(), value);
|
||||||
return (it - color_print_values->begin()) % number_tools();
|
return (it - color_print_values->begin()) % number_tools();
|
||||||
}
|
}
|
||||||
|
@ -5401,7 +5401,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||||
|
|
||||||
auto it = std::find_if(color_print_values->begin(), color_print_values->end(),
|
auto it = std::find_if(color_print_values->begin(), color_print_values->end(),
|
||||||
[print_z](const Model::CustomGCode& code)
|
[print_z](const Model::CustomGCode& code)
|
||||||
{ return fabs(code.height - print_z) < EPSILON; });
|
{ return fabs(code.print_z - print_z) < EPSILON; });
|
||||||
if (it != color_print_values->end())
|
if (it != color_print_values->end())
|
||||||
{
|
{
|
||||||
const std::string& code = it->gcode;
|
const std::string& code = it->gcode;
|
||||||
|
@ -5421,7 +5421,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Model::CustomGCode value(print_z + EPSILON, "", 0, "");
|
const Model::CustomGCode value{print_z + EPSILON, "", 0, ""};
|
||||||
it = std::lower_bound(color_print_values->begin(), color_print_values->end(), value);
|
it = std::lower_bound(color_print_values->begin(), color_print_values->end(), value);
|
||||||
while (it != color_print_values->begin())
|
while (it != color_print_values->begin())
|
||||||
{
|
{
|
||||||
|
|
|
@ -185,7 +185,7 @@ private:
|
||||||
bool m_layer_height_profile_modified;
|
bool m_layer_height_profile_modified;
|
||||||
|
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
||||||
mutable float m_adaptive_cusp;
|
mutable float m_adaptive_quality;
|
||||||
mutable HeightProfileSmoothingParams m_smooth_params;
|
mutable HeightProfileSmoothingParams m_smooth_params;
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
||||||
|
|
||||||
|
@ -236,8 +236,8 @@ private:
|
||||||
void accept_changes(GLCanvas3D& canvas);
|
void accept_changes(GLCanvas3D& canvas);
|
||||||
void reset_layer_height_profile(GLCanvas3D& canvas);
|
void reset_layer_height_profile(GLCanvas3D& canvas);
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
||||||
void adaptive_layer_height_profile(GLCanvas3D& canvas, float cusp);
|
void adaptive_layer_height_profile(GLCanvas3D& canvas, float quality_factor);
|
||||||
void smooth_layer_height_profile(GLCanvas3D& canvas, const HeightProfileSmoothingParams& smoothing_paramsn);
|
void smooth_layer_height_profile(GLCanvas3D& canvas, const HeightProfileSmoothingParams& smoothing_params);
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
||||||
|
|
||||||
static float get_cursor_z_relative(const GLCanvas3D& canvas);
|
static float get_cursor_z_relative(const GLCanvas3D& canvas);
|
||||||
|
@ -541,7 +541,7 @@ public:
|
||||||
|
|
||||||
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
||||||
void reset_layer_height_profile();
|
void reset_layer_height_profile();
|
||||||
void adaptive_layer_height_profile(float cusp);
|
void adaptive_layer_height_profile(float quality_factor);
|
||||||
void smooth_layer_height_profile(const HeightProfileSmoothingParams& smoothing_params);
|
void smooth_layer_height_profile(const HeightProfileSmoothingParams& smoothing_params);
|
||||||
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
|
||||||
|
|
||||||
|
|
|
@ -569,7 +569,7 @@ void Preview::update_view_type(bool slice_completed)
|
||||||
{
|
{
|
||||||
const DynamicPrintConfig& config = wxGetApp().preset_bundle->project_config;
|
const DynamicPrintConfig& config = wxGetApp().preset_bundle->project_config;
|
||||||
|
|
||||||
const wxString& choice = !wxGetApp().plater()->model().custom_gcode_per_height.empty() /*&&
|
const wxString& choice = !wxGetApp().plater()->model().custom_gcode_per_print_z.empty() /*&&
|
||||||
(wxGetApp().extruders_edited_cnt()==1 || !slice_completed) */?
|
(wxGetApp().extruders_edited_cnt()==1 || !slice_completed) */?
|
||||||
_(L("Color Print")) :
|
_(L("Color Print")) :
|
||||||
config.option<ConfigOptionFloats>("wiping_volumes_matrix")->values.size() > 1 ?
|
config.option<ConfigOptionFloats>("wiping_volumes_matrix")->values.size() > 1 ?
|
||||||
|
@ -600,7 +600,7 @@ void Preview::create_double_slider()
|
||||||
|
|
||||||
Bind(wxCUSTOMEVT_TICKSCHANGED, [this](wxEvent&) {
|
Bind(wxCUSTOMEVT_TICKSCHANGED, [this](wxEvent&) {
|
||||||
Model& model = wxGetApp().plater()->model();
|
Model& model = wxGetApp().plater()->model();
|
||||||
model.custom_gcode_per_height = m_slider->GetTicksValues();
|
model.custom_gcode_per_print_z = m_slider->GetTicksValues();
|
||||||
m_schedule_background_process();
|
m_schedule_background_process();
|
||||||
|
|
||||||
update_view_type(false);
|
update_view_type(false);
|
||||||
|
@ -646,7 +646,7 @@ void Preview::check_slider_values(std::vector<Model::CustomGCode>& ticks_from_mo
|
||||||
ticks_from_model.erase(std::remove_if(ticks_from_model.begin(), ticks_from_model.end(),
|
ticks_from_model.erase(std::remove_if(ticks_from_model.begin(), ticks_from_model.end(),
|
||||||
[layers_z](Model::CustomGCode val)
|
[layers_z](Model::CustomGCode val)
|
||||||
{
|
{
|
||||||
auto it = std::lower_bound(layers_z.begin(), layers_z.end(), val.height - DoubleSlider::epsilon());
|
auto it = std::lower_bound(layers_z.begin(), layers_z.end(), val.print_z - DoubleSlider::epsilon());
|
||||||
return it == layers_z.end();
|
return it == layers_z.end();
|
||||||
}),
|
}),
|
||||||
ticks_from_model.end());
|
ticks_from_model.end());
|
||||||
|
@ -669,7 +669,7 @@ void Preview::update_double_slider(const std::vector<double>& layers_z, bool kee
|
||||||
bool snap_to_min = force_sliders_full_range || m_slider->is_lower_at_min();
|
bool snap_to_min = force_sliders_full_range || m_slider->is_lower_at_min();
|
||||||
bool snap_to_max = force_sliders_full_range || m_slider->is_higher_at_max();
|
bool snap_to_max = force_sliders_full_range || m_slider->is_higher_at_max();
|
||||||
|
|
||||||
std::vector<Model::CustomGCode> &ticks_from_model = wxGetApp().plater()->model().custom_gcode_per_height;
|
std::vector<Model::CustomGCode> &ticks_from_model = wxGetApp().plater()->model().custom_gcode_per_print_z;
|
||||||
check_slider_values(ticks_from_model, layers_z);
|
check_slider_values(ticks_from_model, layers_z);
|
||||||
|
|
||||||
m_slider->SetSliderValues(layers_z);
|
m_slider->SetSliderValues(layers_z);
|
||||||
|
@ -789,7 +789,7 @@ void Preview::load_print_as_fff(bool keep_z_range)
|
||||||
colors.push_back("#808080"); // gray color for pause print or custom G-code
|
colors.push_back("#808080"); // gray color for pause print or custom G-code
|
||||||
|
|
||||||
if (!gcode_preview_data_valid)
|
if (!gcode_preview_data_valid)
|
||||||
color_print_values = wxGetApp().plater()->model().custom_gcode_per_height;
|
color_print_values = wxGetApp().plater()->model().custom_gcode_per_print_z;
|
||||||
}
|
}
|
||||||
else if (gcode_preview_data_valid || (m_gcode_preview_data->extrusion.view_type == GCodePreviewData::Extrusion::Tool) )
|
else if (gcode_preview_data_valid || (m_gcode_preview_data->extrusion.view_type == GCodePreviewData::Extrusion::Tool) )
|
||||||
{
|
{
|
||||||
|
|
|
@ -254,6 +254,16 @@ bool ImGuiWrapper::begin(const wxString &name, int flags)
|
||||||
return begin(into_u8(name), flags);
|
return begin(into_u8(name), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ImGuiWrapper::begin(const std::string& name, bool* close, int flags)
|
||||||
|
{
|
||||||
|
return ImGui::Begin(name.c_str(), close, (ImGuiWindowFlags)flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGuiWrapper::begin(const wxString& name, bool* close, int flags)
|
||||||
|
{
|
||||||
|
return begin(into_u8(name), close, flags);
|
||||||
|
}
|
||||||
|
|
||||||
void ImGuiWrapper::end()
|
void ImGuiWrapper::end()
|
||||||
{
|
{
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
|
@ -56,6 +56,8 @@ public:
|
||||||
|
|
||||||
bool begin(const std::string &name, int flags = 0);
|
bool begin(const std::string &name, int flags = 0);
|
||||||
bool begin(const wxString &name, int flags = 0);
|
bool begin(const wxString &name, int flags = 0);
|
||||||
|
bool begin(const std::string& name, bool* close, int flags = 0);
|
||||||
|
bool begin(const wxString& name, bool* close, int flags = 0);
|
||||||
void end();
|
void end();
|
||||||
|
|
||||||
bool button(const wxString &label);
|
bool button(const wxString &label);
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
#include "PresetBundle.hpp"
|
#include "PresetBundle.hpp"
|
||||||
#include "AppConfig.hpp"
|
#include "AppConfig.hpp"
|
||||||
|
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
#include "GLCanvas3D.hpp"
|
||||||
|
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
|
||||||
#include <wx/glcanvas.h>
|
#include <wx/glcanvas.h>
|
||||||
|
|
||||||
|
@ -184,7 +187,10 @@ Mouse3DController::Mouse3DController()
|
||||||
, m_device(nullptr)
|
, m_device(nullptr)
|
||||||
, m_device_str("")
|
, m_device_str("")
|
||||||
, m_running(false)
|
, m_running(false)
|
||||||
, m_settings_dialog(false)
|
, m_show_settings_dialog(false)
|
||||||
|
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
, m_settings_dialog_closed_by_user(false)
|
||||||
|
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
{
|
{
|
||||||
m_last_time = std::chrono::high_resolution_clock::now();
|
m_last_time = std::chrono::high_resolution_clock::now();
|
||||||
}
|
}
|
||||||
|
@ -229,8 +235,11 @@ bool Mouse3DController::apply(Camera& camera)
|
||||||
if (!m_running && is_device_connected())
|
if (!m_running && is_device_connected())
|
||||||
{
|
{
|
||||||
disconnect_device();
|
disconnect_device();
|
||||||
// hides the settings dialog if the user re-plug the device
|
// hides the settings dialog if the user un-plug the device
|
||||||
m_settings_dialog = false;
|
m_show_settings_dialog = false;
|
||||||
|
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
m_settings_dialog_closed_by_user = false;
|
||||||
|
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the user plugged the device
|
// check if the user plugged the device
|
||||||
|
@ -240,16 +249,54 @@ bool Mouse3DController::apply(Camera& camera)
|
||||||
return is_device_connected() ? m_state.apply(camera) : false;
|
return is_device_connected() ? m_state.apply(camera) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
void Mouse3DController::render_settings_dialog(GLCanvas3D& canvas) const
|
||||||
|
#else
|
||||||
void Mouse3DController::render_settings_dialog(unsigned int canvas_width, unsigned int canvas_height) const
|
void Mouse3DController::render_settings_dialog(unsigned int canvas_width, unsigned int canvas_height) const
|
||||||
|
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
{
|
{
|
||||||
if (!m_running || !m_settings_dialog)
|
if (!m_running || !m_show_settings_dialog)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
// when the user clicks on [X] or [Close] button we need to trigger
|
||||||
|
// an extra frame to let the dialog disappear
|
||||||
|
if (m_settings_dialog_closed_by_user)
|
||||||
|
{
|
||||||
|
m_show_settings_dialog = false;
|
||||||
|
m_settings_dialog_closed_by_user = false;
|
||||||
|
canvas.request_extra_frame();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size cnv_size = canvas.get_canvas_size();
|
||||||
|
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
|
||||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||||
|
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
imgui.set_next_window_pos(0.5f * (float)cnv_size.get_width(), 0.5f * (float)cnv_size.get_height(), ImGuiCond_Always, 0.5f, 0.5f);
|
||||||
|
#else
|
||||||
imgui.set_next_window_pos(0.5f * (float)canvas_width, 0.5f * (float)canvas_height, ImGuiCond_Always, 0.5f, 0.5f);
|
imgui.set_next_window_pos(0.5f * (float)canvas_width, 0.5f * (float)canvas_height, ImGuiCond_Always, 0.5f, 0.5f);
|
||||||
|
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
|
||||||
|
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
static ImVec2 last_win_size(0.0f, 0.0f);
|
||||||
|
bool shown = true;
|
||||||
|
if (imgui.begin(_(L("3Dconnexion settings")), &shown, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse))
|
||||||
|
{
|
||||||
|
if (shown)
|
||||||
|
{
|
||||||
|
ImVec2 win_size = ImGui::GetWindowSize();
|
||||||
|
if ((last_win_size.x != win_size.x) || (last_win_size.y != win_size.y))
|
||||||
|
{
|
||||||
|
// when the user clicks on [X] button, the next time the dialog is shown
|
||||||
|
// has a dummy size, so we trigger an extra frame to let it have the correct size
|
||||||
|
last_win_size = win_size;
|
||||||
|
canvas.request_extra_frame();
|
||||||
|
}
|
||||||
|
#else
|
||||||
imgui.begin(_(L("3Dconnexion settings")), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse);
|
imgui.begin(_(L("3Dconnexion settings")), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse);
|
||||||
|
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
|
||||||
const ImVec4& color = ImGui::GetStyleColorVec4(ImGuiCol_Separator);
|
const ImVec4& color = ImGui::GetStyleColorVec4(ImGuiCol_Separator);
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
||||||
|
@ -322,6 +369,24 @@ void Mouse3DController::render_settings_dialog(unsigned int canvas_width, unsign
|
||||||
Vec3f target = wxGetApp().plater()->get_camera().get_target().cast<float>();
|
Vec3f target = wxGetApp().plater()->get_camera().get_target().cast<float>();
|
||||||
ImGui::InputFloat3("Target", target.data(), "%.3f", ImGuiInputTextFlags_ReadOnly);
|
ImGui::InputFloat3("Target", target.data(), "%.3f", ImGuiInputTextFlags_ReadOnly);
|
||||||
#endif // ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
|
#endif // ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
|
||||||
|
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
if (imgui.button(_(L("Close"))))
|
||||||
|
{
|
||||||
|
// the user clicked on the [Close] button
|
||||||
|
m_settings_dialog_closed_by_user = true;
|
||||||
|
canvas.set_as_dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// the user clicked on the [X] button
|
||||||
|
m_settings_dialog_closed_by_user = true;
|
||||||
|
canvas.set_as_dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
|
||||||
imgui.end();
|
imgui.end();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,9 @@ namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
struct Camera;
|
struct Camera;
|
||||||
|
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
class GLCanvas3D;
|
||||||
|
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
|
||||||
class Mouse3DController
|
class Mouse3DController
|
||||||
{
|
{
|
||||||
|
@ -130,7 +133,13 @@ class Mouse3DController
|
||||||
hid_device* m_device;
|
hid_device* m_device;
|
||||||
std::string m_device_str;
|
std::string m_device_str;
|
||||||
bool m_running;
|
bool m_running;
|
||||||
bool m_settings_dialog;
|
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
mutable bool m_show_settings_dialog;
|
||||||
|
// set to true when ther user closes the dialog by clicking on [X] or [Close] buttons
|
||||||
|
mutable bool m_settings_dialog_closed_by_user;
|
||||||
|
#else
|
||||||
|
bool m_show_settings_dialog;
|
||||||
|
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
std::chrono::time_point<std::chrono::high_resolution_clock> m_last_time;
|
std::chrono::time_point<std::chrono::high_resolution_clock> m_last_time;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -146,9 +155,13 @@ public:
|
||||||
|
|
||||||
bool apply(Camera& camera);
|
bool apply(Camera& camera);
|
||||||
|
|
||||||
bool is_settings_dialog_shown() const { return m_settings_dialog; }
|
bool is_settings_dialog_shown() const { return m_show_settings_dialog; }
|
||||||
void show_settings_dialog(bool show) { m_settings_dialog = show && is_running(); }
|
void show_settings_dialog(bool show) { m_show_settings_dialog = show && is_running(); }
|
||||||
|
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
void render_settings_dialog(GLCanvas3D& canvas) const;
|
||||||
|
#else
|
||||||
void render_settings_dialog(unsigned int canvas_width, unsigned int canvas_height) const;
|
void render_settings_dialog(unsigned int canvas_width, unsigned int canvas_height) const;
|
||||||
|
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool connect_device();
|
bool connect_device();
|
||||||
|
|
|
@ -2370,7 +2370,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||||
config += std::move(config_loaded);
|
config += std::move(config_loaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->model.custom_gcode_per_height = model.custom_gcode_per_height;
|
this->model.custom_gcode_per_print_z = model.custom_gcode_per_print_z;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (load_config)
|
if (load_config)
|
||||||
|
@ -2789,7 +2789,7 @@ void Plater::priv::reset()
|
||||||
// The hiding of the slicing results, if shown, is not taken care by the background process, so we do it here
|
// The hiding of the slicing results, if shown, is not taken care by the background process, so we do it here
|
||||||
this->sidebar->show_sliced_info_sizer(false);
|
this->sidebar->show_sliced_info_sizer(false);
|
||||||
|
|
||||||
model.custom_gcode_per_height.clear();
|
model.custom_gcode_per_print_z.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::priv::mirror(Axis axis)
|
void Plater::priv::mirror(Axis axis)
|
||||||
|
@ -3282,22 +3282,30 @@ void Plater::priv::reload_from_disk()
|
||||||
input_paths.push_back(sel_filename_path);
|
input_paths.push_back(sel_filename_path);
|
||||||
missing_input_paths.pop_back();
|
missing_input_paths.pop_back();
|
||||||
|
|
||||||
std::string sel_path = fs::path(sel_filename_path).remove_filename().string();
|
fs::path sel_path = fs::path(sel_filename_path).remove_filename().string();
|
||||||
|
|
||||||
std::vector<fs::path>::iterator it = missing_input_paths.begin();
|
std::vector<fs::path>::iterator it = missing_input_paths.begin();
|
||||||
while (it != missing_input_paths.end())
|
while (it != missing_input_paths.end())
|
||||||
{
|
{
|
||||||
// try to use the path of the selected file with all remaining missing files
|
// try to use the path of the selected file with all remaining missing files
|
||||||
std::string repathed_filename = sel_path + "/" + it->filename().string();
|
fs::path repathed_filename = sel_path;
|
||||||
|
repathed_filename /= it->filename();
|
||||||
if (fs::exists(repathed_filename))
|
if (fs::exists(repathed_filename))
|
||||||
{
|
{
|
||||||
input_paths.push_back(repathed_filename);
|
input_paths.push_back(repathed_filename.string());
|
||||||
it = missing_input_paths.erase(it);
|
it = missing_input_paths.erase(it);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxString message = _(L("It is not allowed to change the file to reload")) + " (" + from_u8(fs::path(search).filename().string())+ ").\n" + _(L("Do you want to retry")) + " ?";
|
||||||
|
wxMessageDialog dlg(q, message, wxMessageBoxCaptionStr, wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION);
|
||||||
|
if (dlg.ShowModal() != wxID_YES)
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // ENABLE_RELOAD_FROM_DISK_MISSING_SELECTION
|
#endif // ENABLE_RELOAD_FROM_DISK_MISSING_SELECTION
|
||||||
|
|
||||||
|
@ -5042,6 +5050,7 @@ void Plater::drive_ejected_callback()
|
||||||
{
|
{
|
||||||
if (RemovableDriveManager::get_instance().get_did_eject())
|
if (RemovableDriveManager::get_instance().get_did_eject())
|
||||||
{
|
{
|
||||||
|
RemovableDriveManager::get_instance().set_did_eject(false);
|
||||||
wxString message = "Unmounting succesesful. The device " + RemovableDriveManager::get_instance().get_last_save_name() + "(" + RemovableDriveManager::get_instance().get_last_save_path() + ")" + " can now be safely removed from the computer.";
|
wxString message = "Unmounting succesesful. The device " + RemovableDriveManager::get_instance().get_last_save_name() + "(" + RemovableDriveManager::get_instance().get_last_save_path() + ")" + " can now be safely removed from the computer.";
|
||||||
wxMessageBox(message);
|
wxMessageBox(message);
|
||||||
}
|
}
|
||||||
|
@ -5260,6 +5269,7 @@ const DynamicPrintConfig* Plater::get_plater_config() const
|
||||||
return p->config;
|
return p->config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get vector of extruder colors considering filament color, if extruder color is undefined.
|
||||||
std::vector<std::string> Plater::get_extruder_colors_from_plater_config() const
|
std::vector<std::string> Plater::get_extruder_colors_from_plater_config() const
|
||||||
{
|
{
|
||||||
const Slic3r::DynamicPrintConfig* config = &wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
const Slic3r::DynamicPrintConfig* config = &wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||||
|
@ -5279,13 +5289,17 @@ std::vector<std::string> Plater::get_extruder_colors_from_plater_config() const
|
||||||
return extruder_colors;
|
return extruder_colors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get vector of colors used for rendering of a Preview scene in "Color print" mode
|
||||||
|
* It consists of extruder colors and colors, saved in model.custom_gcode_per_print_z
|
||||||
|
*/
|
||||||
std::vector<std::string> Plater::get_colors_for_color_print() const
|
std::vector<std::string> Plater::get_colors_for_color_print() const
|
||||||
{
|
{
|
||||||
std::vector<std::string> colors = get_extruder_colors_from_plater_config();
|
std::vector<std::string> colors = get_extruder_colors_from_plater_config();
|
||||||
|
colors.reserve(colors.size() + p->model.custom_gcode_per_print_z.size());
|
||||||
|
|
||||||
for (const Model::CustomGCode& code : p->model.custom_gcode_per_height)
|
for (const Model::CustomGCode& code : p->model.custom_gcode_per_print_z)
|
||||||
if (code.gcode == ColorChangeCode)
|
if (code.gcode == ColorChangeCode)
|
||||||
colors.push_back(code.color);
|
colors.emplace_back(code.color);
|
||||||
|
|
||||||
return colors;
|
return colors;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
#include "libslic3r/libslic3r.h"
|
#include "libslic3r/libslic3r.h"
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
|
#include "GUI_App.hpp"
|
||||||
|
|
||||||
// Store the print/filament/printer presets into a "presets" subdirectory of the Slic3rPE config dir.
|
// Store the print/filament/printer presets into a "presets" subdirectory of the Slic3rPE config dir.
|
||||||
// This breaks compatibility with the upstream Slic3r if the --datadir is used to switch between the two versions.
|
// This breaks compatibility with the upstream Slic3r if the --datadir is used to switch between the two versions.
|
||||||
|
@ -868,6 +869,9 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
||||||
}
|
}
|
||||||
// 4) Load the project config values (the per extruder wipe matrix etc).
|
// 4) Load the project config values (the per extruder wipe matrix etc).
|
||||||
this->project_config.apply_only(config, s_project_options);
|
this->project_config.apply_only(config, s_project_options);
|
||||||
|
|
||||||
|
update_custom_gcode_per_print_z_from_config(GUI::wxGetApp().plater()->model().custom_gcode_per_print_z, &this->project_config);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ptSLA:
|
case ptSLA:
|
||||||
|
|
|
@ -505,6 +505,7 @@ void RemovableDriveManager::erase_callbacks()
|
||||||
}
|
}
|
||||||
void RemovableDriveManager::set_last_save_path(const std::string& path)
|
void RemovableDriveManager::set_last_save_path(const std::string& path)
|
||||||
{
|
{
|
||||||
|
m_last_save_path_verified = false;
|
||||||
m_last_save_path = path;
|
m_last_save_path = path;
|
||||||
}
|
}
|
||||||
void RemovableDriveManager::verify_last_save_path()
|
void RemovableDriveManager::verify_last_save_path()
|
||||||
|
@ -571,4 +572,8 @@ bool RemovableDriveManager::get_did_eject()
|
||||||
{
|
{
|
||||||
return m_did_eject;
|
return m_did_eject;
|
||||||
}
|
}
|
||||||
|
void RemovableDriveManager::set_did_eject(const bool b)
|
||||||
|
{
|
||||||
|
m_did_eject = b;
|
||||||
|
}
|
||||||
}}//namespace Slicer::Gui
|
}}//namespace Slicer::Gui
|
||||||
|
|
|
@ -56,6 +56,7 @@ public:
|
||||||
void set_is_writing(const bool b);
|
void set_is_writing(const bool b);
|
||||||
bool get_is_writing();
|
bool get_is_writing();
|
||||||
bool get_did_eject();
|
bool get_did_eject();
|
||||||
|
void set_did_eject(const bool b);
|
||||||
std::string get_drive_name(const std::string& path);
|
std::string get_drive_name(const std::string& path);
|
||||||
private:
|
private:
|
||||||
RemovableDriveManager();
|
RemovableDriveManager();
|
||||||
|
|
|
@ -2538,7 +2538,7 @@ std::vector<t_custom_code> DoubleSlider::GetTicksValues() const
|
||||||
for (const TICK_CODE& tick : m_ticks_) {
|
for (const TICK_CODE& tick : m_ticks_) {
|
||||||
if (tick.tick > val_size)
|
if (tick.tick > val_size)
|
||||||
break;
|
break;
|
||||||
values.push_back(t_custom_code(m_values[tick.tick], tick.gcode, tick.extruder, tick.color));
|
values.emplace_back(t_custom_code{m_values[tick.tick], tick.gcode, tick.extruder, tick.color});
|
||||||
}
|
}
|
||||||
|
|
||||||
return values;
|
return values;
|
||||||
|
@ -2553,12 +2553,12 @@ void DoubleSlider::SetTicksValues(const std::vector<t_custom_code>& heights)
|
||||||
|
|
||||||
m_ticks_.clear();
|
m_ticks_.clear();
|
||||||
for (auto h : heights) {
|
for (auto h : heights) {
|
||||||
auto it = std::lower_bound(m_values.begin(), m_values.end(), h.height - epsilon());
|
auto it = std::lower_bound(m_values.begin(), m_values.end(), h.print_z - epsilon());
|
||||||
|
|
||||||
if (it == m_values.end())
|
if (it == m_values.end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
m_ticks_.insert(TICK_CODE(it-m_values.begin(), h.gcode, h.extruder, h.color));
|
m_ticks_.emplace(TICK_CODE{int(it-m_values.begin()), h.gcode, h.extruder, h.color});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!was_empty && m_ticks_.empty())
|
if (!was_empty && m_ticks_.empty())
|
||||||
|
@ -2642,7 +2642,7 @@ void DoubleSlider::draw_action_icon(wxDC& dc, const wxPoint pt_beg, const wxPoin
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wxBitmap* icon = m_is_action_icon_focesed ? &m_bmp_add_tick_off.bmp() : &m_bmp_add_tick_on.bmp();
|
wxBitmap* icon = m_is_action_icon_focesed ? &m_bmp_add_tick_off.bmp() : &m_bmp_add_tick_on.bmp();
|
||||||
if (m_ticks_.find(tick) != m_ticks_.end())
|
if (m_ticks_.find(TICK_CODE{tick}) != m_ticks_.end())
|
||||||
icon = m_is_action_icon_focesed ? &m_bmp_del_tick_off.bmp() : &m_bmp_del_tick_on.bmp();
|
icon = m_is_action_icon_focesed ? &m_bmp_del_tick_off.bmp() : &m_bmp_del_tick_on.bmp();
|
||||||
|
|
||||||
wxCoord x_draw, y_draw;
|
wxCoord x_draw, y_draw;
|
||||||
|
@ -3081,7 +3081,7 @@ wxString DoubleSlider::get_tooltip(IconFocus icon_focus)
|
||||||
else if (m_is_action_icon_focesed)
|
else if (m_is_action_icon_focesed)
|
||||||
{
|
{
|
||||||
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
|
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
|
||||||
const auto tick_code_it = m_ticks_.find(tick);
|
const auto tick_code_it = m_ticks_.find(TICK_CODE{tick});
|
||||||
tooltip = tick_code_it == m_ticks_.end() ? (m_state == msSingleExtruder ?
|
tooltip = tick_code_it == m_ticks_.end() ? (m_state == msSingleExtruder ?
|
||||||
_(L("For add color change use left mouse button click")) :
|
_(L("For add color change use left mouse button click")) :
|
||||||
_(L("For add change extruder use left mouse button click"))) + "\n" +
|
_(L("For add change extruder use left mouse button click"))) + "\n" +
|
||||||
|
@ -3240,13 +3240,13 @@ void DoubleSlider::action_tick(const TicksAction action)
|
||||||
|
|
||||||
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
|
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
|
||||||
|
|
||||||
const auto it = m_ticks_.find(tick);
|
const auto it = m_ticks_.find(TICK_CODE{tick});
|
||||||
|
|
||||||
if (it != m_ticks_.end()) // erase this tick
|
if (it != m_ticks_.end()) // erase this tick
|
||||||
{
|
{
|
||||||
if (action == taAdd)
|
if (action == taAdd)
|
||||||
return;
|
return;
|
||||||
m_ticks_.erase(TICK_CODE(tick));
|
m_ticks_.erase(TICK_CODE{tick});
|
||||||
|
|
||||||
wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED));
|
wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED));
|
||||||
Refresh();
|
Refresh();
|
||||||
|
@ -3350,7 +3350,7 @@ void DoubleSlider::OnRightDown(wxMouseEvent& event)
|
||||||
{
|
{
|
||||||
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
|
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
|
||||||
// if on this Z doesn't exist tick
|
// if on this Z doesn't exist tick
|
||||||
auto it = m_ticks_.find(tick);
|
auto it = m_ticks_.find(TICK_CODE{ tick });
|
||||||
if (it == m_ticks_.end())
|
if (it == m_ticks_.end())
|
||||||
{
|
{
|
||||||
// show context menu on OnRightUp()
|
// show context menu on OnRightUp()
|
||||||
|
@ -3387,7 +3387,7 @@ int DoubleSlider::get_extruder_for_tick(int tick)
|
||||||
if (m_ticks_.empty())
|
if (m_ticks_.empty())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
auto it = m_ticks_.lower_bound(tick);
|
auto it = m_ticks_.lower_bound(TICK_CODE{tick});
|
||||||
while (it != m_ticks_.begin()) {
|
while (it != m_ticks_.begin()) {
|
||||||
--it;
|
--it;
|
||||||
if(it->gcode == Slic3r::ExtruderChangeCode)
|
if(it->gcode == Slic3r::ExtruderChangeCode)
|
||||||
|
@ -3454,7 +3454,7 @@ void DoubleSlider::OnRightUp(wxMouseEvent& event)
|
||||||
else if (m_show_edit_menu) {
|
else if (m_show_edit_menu) {
|
||||||
wxMenu menu;
|
wxMenu menu;
|
||||||
|
|
||||||
std::set<TICK_CODE>::iterator it = m_ticks_.find(m_selection == ssLower ? m_lower_value : m_higher_value);
|
std::set<TICK_CODE>::iterator it = m_ticks_.find(TICK_CODE{ m_selection == ssLower ? m_lower_value : m_higher_value });
|
||||||
const bool is_color_change = it->gcode == Slic3r::ColorChangeCode;
|
const bool is_color_change = it->gcode == Slic3r::ColorChangeCode;
|
||||||
|
|
||||||
append_menu_item(&menu, wxID_ANY, it->gcode == Slic3r::ColorChangeCode ? _(L("Edit color")) :
|
append_menu_item(&menu, wxID_ANY, it->gcode == Slic3r::ColorChangeCode ? _(L("Edit color")) :
|
||||||
|
@ -3526,7 +3526,7 @@ void DoubleSlider::add_code(std::string code, int selected_extruder/* = -1*/)
|
||||||
{
|
{
|
||||||
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
|
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
|
||||||
// if on this Z doesn't exist tick
|
// if on this Z doesn't exist tick
|
||||||
auto it = m_ticks_.find(tick);
|
auto it = m_ticks_.find(TICK_CODE{ tick });
|
||||||
if (it == m_ticks_.end())
|
if (it == m_ticks_.end())
|
||||||
{
|
{
|
||||||
std::string color = "";
|
std::string color = "";
|
||||||
|
@ -3535,7 +3535,7 @@ void DoubleSlider::add_code(std::string code, int selected_extruder/* = -1*/)
|
||||||
std::vector<std::string> colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
std::vector<std::string> colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
||||||
|
|
||||||
if (m_state == msSingleExtruder && !m_ticks_.empty()) {
|
if (m_state == msSingleExtruder && !m_ticks_.empty()) {
|
||||||
auto before_tick_it = std::lower_bound(m_ticks_.begin(), m_ticks_.end(), tick);
|
auto before_tick_it = std::lower_bound(m_ticks_.begin(), m_ticks_.end(), TICK_CODE{ tick });
|
||||||
while (before_tick_it != m_ticks_.begin()) {
|
while (before_tick_it != m_ticks_.begin()) {
|
||||||
--before_tick_it;
|
--before_tick_it;
|
||||||
if (before_tick_it->gcode == Slic3r::ColorChangeCode) {
|
if (before_tick_it->gcode == Slic3r::ColorChangeCode) {
|
||||||
|
@ -3580,7 +3580,7 @@ void DoubleSlider::add_code(std::string code, int selected_extruder/* = -1*/)
|
||||||
extruder = get_extruder_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value);
|
extruder = get_extruder_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ticks_.insert(TICK_CODE(tick, code, extruder, color));
|
m_ticks_.emplace(TICK_CODE{tick, code, extruder, color});
|
||||||
|
|
||||||
wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED));
|
wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED));
|
||||||
Refresh();
|
Refresh();
|
||||||
|
@ -3592,7 +3592,7 @@ void DoubleSlider::edit_tick()
|
||||||
{
|
{
|
||||||
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
|
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
|
||||||
// if on this Z exists tick
|
// if on this Z exists tick
|
||||||
std::set<TICK_CODE>::iterator it = m_ticks_.find(tick);
|
std::set<TICK_CODE>::iterator it = m_ticks_.find(TICK_CODE{ tick });
|
||||||
if (it != m_ticks_.end())
|
if (it != m_ticks_.end())
|
||||||
{
|
{
|
||||||
std::string edited_value;
|
std::string edited_value;
|
||||||
|
@ -3619,7 +3619,7 @@ void DoubleSlider::edit_tick()
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ticks_.erase(it);
|
m_ticks_.erase(it);
|
||||||
m_ticks_.insert(changed_tick);
|
m_ticks_.emplace(changed_tick);
|
||||||
|
|
||||||
wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED));
|
wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED));
|
||||||
}
|
}
|
||||||
|
@ -3632,9 +3632,9 @@ void DoubleSlider::change_extruder(int extruder)
|
||||||
std::vector<std::string> colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
std::vector<std::string> colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
||||||
|
|
||||||
// if on this Y doesn't exist tick
|
// if on this Y doesn't exist tick
|
||||||
if (m_ticks_.find(tick) == m_ticks_.end())
|
if (m_ticks_.find(TICK_CODE{tick}) == m_ticks_.end())
|
||||||
{
|
{
|
||||||
m_ticks_.insert(TICK_CODE(tick, Slic3r::ExtruderChangeCode, extruder, extruder == 0 ? "" : colors[extruder-1]));
|
m_ticks_.emplace(TICK_CODE{tick, Slic3r::ExtruderChangeCode, extruder, extruder == 0 ? "" : colors[extruder-1]});
|
||||||
|
|
||||||
wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED));
|
wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED));
|
||||||
Refresh();
|
Refresh();
|
||||||
|
@ -3672,7 +3672,7 @@ void DoubleSlider::edit_extruder_sequence()
|
||||||
while (tick <= m_max_value)
|
while (tick <= m_max_value)
|
||||||
{
|
{
|
||||||
int cur_extruder = m_extruders_sequence.extruders[extruder];
|
int cur_extruder = m_extruders_sequence.extruders[extruder];
|
||||||
m_ticks_.insert(TICK_CODE(tick, Slic3r::ExtruderChangeCode, cur_extruder + 1, colors[cur_extruder]));
|
m_ticks_.emplace(TICK_CODE{tick, Slic3r::ExtruderChangeCode, cur_extruder + 1, colors[cur_extruder]});
|
||||||
|
|
||||||
extruder++;
|
extruder++;
|
||||||
if (extruder == extr_cnt)
|
if (extruder == extr_cnt)
|
||||||
|
@ -3680,12 +3680,12 @@ void DoubleSlider::edit_extruder_sequence()
|
||||||
if (m_extruders_sequence.is_mm_intervals)
|
if (m_extruders_sequence.is_mm_intervals)
|
||||||
{
|
{
|
||||||
value += m_extruders_sequence.interval_by_mm;
|
value += m_extruders_sequence.interval_by_mm;
|
||||||
auto it = std::lower_bound(m_values.begin(), m_values.end(), value - epsilon());
|
auto val_it = std::lower_bound(m_values.begin(), m_values.end(), value - epsilon());
|
||||||
|
|
||||||
if (it == m_values.end())
|
if (val_it == m_values.end())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
tick = it - m_values.begin();
|
tick = val_it - m_values.begin();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tick += m_extruders_sequence.interval_by_layers;
|
tick += m_extruders_sequence.interval_by_layers;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
|
#include "libslic3r/GCodeWriter.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
enum class ModelVolumeType : int;
|
enum class ModelVolumeType : int;
|
||||||
|
@ -961,24 +962,12 @@ private:
|
||||||
|
|
||||||
struct TICK_CODE
|
struct TICK_CODE
|
||||||
{
|
{
|
||||||
TICK_CODE(int tick):tick(tick), gcode(Slic3r::ColorChangeCode), extruder(0), color("") {}
|
|
||||||
TICK_CODE(int tick, const std::string& code) :
|
|
||||||
tick(tick), gcode(code), extruder(0) {}
|
|
||||||
TICK_CODE(int tick, int extruder) :
|
|
||||||
tick(tick), gcode(Slic3r::ColorChangeCode), extruder(extruder) {}
|
|
||||||
TICK_CODE(int tick, const std::string& code, int extruder, const std::string& color) :
|
|
||||||
tick(tick), gcode(code), extruder(extruder), color(color) {}
|
|
||||||
|
|
||||||
bool operator<(const TICK_CODE& other) const { return other.tick > this->tick; }
|
bool operator<(const TICK_CODE& other) const { return other.tick > this->tick; }
|
||||||
bool operator>(const TICK_CODE& other) const { return other.tick < this->tick; }
|
bool operator>(const TICK_CODE& other) const { return other.tick < this->tick; }
|
||||||
TICK_CODE operator=(const TICK_CODE& other) const {
|
|
||||||
TICK_CODE ret_val(other.tick, other.gcode, other.extruder, other.color);
|
|
||||||
return ret_val;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tick;
|
int tick;
|
||||||
std::string gcode;
|
std::string gcode = Slic3r::ColorChangeCode;
|
||||||
int extruder;
|
int extruder = 0;
|
||||||
std::string color;
|
std::string color;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
set(SLIC3R_APP_NAME "PrusaSlicer")
|
set(SLIC3R_APP_NAME "PrusaSlicer")
|
||||||
set(SLIC3R_APP_KEY "PrusaSlicer")
|
set(SLIC3R_APP_KEY "PrusaSlicer")
|
||||||
set(SLIC3R_VERSION "2.1.0")
|
set(SLIC3R_VERSION "2.2.0-alpha0")
|
||||||
set(SLIC3R_BUILD_ID "PrusaSlicer-${SLIC3R_VERSION}+UNKNOWN")
|
set(SLIC3R_BUILD_ID "PrusaSlicer-${SLIC3R_VERSION}+UNKNOWN")
|
||||||
set(SLIC3R_RC_VERSION "2,1,0,0")
|
set(SLIC3R_RC_VERSION "2,2,0,0")
|
||||||
set(SLIC3R_RC_VERSION_DOTS "2.1.0.0")
|
set(SLIC3R_RC_VERSION_DOTS "2.2.0.0")
|
||||||
|
|
Loading…
Reference in a new issue