diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 133a8aa84..74dea387a 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,5 +1,5 @@ ### Version -_Version of Slic3r used goes here_ +_Version of Slic3r Prusa Edition used goes here_ _Use `About->About Slic3r` for release versions_ @@ -7,6 +7,10 @@ _For -dev versions, use `git describe --tag` or get the hash value for the versi ### Operating system type + version _What OS are you using, and state any version #s_ +_In case of 3D rendering issues, please attach the content of menu Help -> System Info dialog_ + +### 3D printer brand / version + firmware version (if known) +_What 3D printer brand / version are you printing on, is it a stock model or did you modify the printer, what firmware is running on your printer, version of the firmware #s_ ### Behavior * _Describe the problem_ @@ -18,5 +22,5 @@ _What OS are you using, and state any version #s_ _Is this a new feature request?_ -#### STL/Config (.ZIP) where problem occurs -_Upload a zipped copy of an STL and your config (`File -> Export Config`)_ +#### Project File (.3MF) where problem occurs +_Upload a Slic3r PE Project File (.3MF) (`Plater -> Export plate as 3MF` for Slic3r PE 1.41.2 and older, `File -> Save` / `Save Project` for Slic3r PE 1.42.0-alpha and newer)_ diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e42e24e9..90ebd1e5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,9 +86,8 @@ set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) if(NOT WIN32) - # Add DEBUG flags for the debug builds in a way the Visual Studio adds these flags. + # Add DEBUG flags to debug builds. add_compile_options("$<$:-DDEBUG>") - add_compile_options("$<$:-D_DEBUG>") endif() # To be able to link libslic3r with the Perl XS module. diff --git a/deps/deps-windows.cmake b/deps/deps-windows.cmake index 44a1843bb..7276277e6 100644 --- a/deps/deps-windows.cmake +++ b/deps/deps-windows.cmake @@ -1,8 +1,21 @@ +if (MSVC_VERSION EQUAL 1800) + set(DEP_VS_VER "12") + set(DEP_BOOST_TOOLSET "msvc-12.0") +elseif (MSVC_VERSION EQUAL 1900) + set(DEP_VS_VER "14") + set(DEP_BOOST_TOOLSET "msvc-14.0") +elseif (MSVC_VERSION GREATER 1900) + set(DEP_VS_VER "15") + set(DEP_BOOST_TOOLSET "msvc-14.1") +else () + message(FATAL_ERROR "Unsupported MSVC version") +endif () + if (${DEPS_BITS} EQUAL 32) - set(DEP_MSVC_GEN "Visual Studio 12") + set(DEP_MSVC_GEN "Visual Studio ${DEP_VS_VER}") else () - set(DEP_MSVC_GEN "Visual Studio 12 Win64") + set(DEP_MSVC_GEN "Visual Studio ${DEP_VS_VER} Win64") endif () @@ -29,7 +42,7 @@ ExternalProject_Add(dep_boost --with-regex "--prefix=${DESTDIR}/usr/local" "address-model=${DEPS_BITS}" - toolset=msvc-12.0 + "toolset=${DEP_BOOST_TOOLSET}" link=static variant=release threading=multi @@ -204,7 +217,7 @@ ExternalProject_Add(dep_libcurl URL_HASH SHA256=cc245bf9a1a42a45df491501d97d5593392a03f7b4f07b952793518d97666115 BUILD_IN_SOURCE 1 CONFIGURE_COMMAND "" - BUILD_COMMAND cd winbuild && nmake /f Makefile.vc mode=static VC=12 GEN_PDB=yes DEBUG=no "MACHINE=${DEP_LIBCURL_TARGET}" + BUILD_COMMAND cd winbuild && nmake /f Makefile.vc mode=static "VC=${DEP_VS_VER}" GEN_PDB=yes DEBUG=no "MACHINE=${DEP_LIBCURL_TARGET}" INSTALL_COMMAND cd builds\\libcurl-*-release-*-winssl && "${CMAKE_COMMAND}" -E copy_directory include "${DESTDIR}\\usr\\local\\include" && "${CMAKE_COMMAND}" -E copy_directory lib "${DESTDIR}\\usr\\local\\lib" @@ -214,7 +227,7 @@ if (${DEP_DEBUG}) ExternalProject_Add_Step(dep_libcurl build_debug DEPENDEES build DEPENDERS install - COMMAND cd winbuild && nmake /f Makefile.vc mode=static VC=12 GEN_PDB=yes DEBUG=yes "MACHINE=${DEP_LIBCURL_TARGET}" + COMMAND cd winbuild && nmake /f Makefile.vc mode=static "VC=${DEP_VS_VER}" GEN_PDB=yes DEBUG=yes "MACHINE=${DEP_LIBCURL_TARGET}" WORKING_DIRECTORY "${SOURCE_DIR}" ) ExternalProject_Add_Step(dep_libcurl install_debug diff --git a/src/avrdude/windows/unistd.h b/src/avrdude/windows/unistd.h index b1bc6bf7f..95ba79a34 100644 --- a/src/avrdude/windows/unistd.h +++ b/src/avrdude/windows/unistd.h @@ -45,7 +45,9 @@ extern "C" { #define chdir _chdir #define isatty _isatty #define lseek _lseek +#if _MSC_VER < 1900 #define snprintf _snprintf +#endif #define strncasecmp _strnicmp #define strcasecmp _stricmp #define stat _stat diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index baf860bd4..270905fce 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -71,8 +71,8 @@ add_library(libslic3r STATIC GCode/CoolingBuffer.hpp GCode/PostProcessor.cpp GCode/PostProcessor.hpp - GCode/PressureEqualizer.cpp - GCode/PressureEqualizer.hpp +# GCode/PressureEqualizer.cpp +# GCode/PressureEqualizer.hpp GCode/PreviewData.cpp GCode/PreviewData.hpp GCode/PrintExtents.cpp diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 67264b16f..66698d4ad 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -662,10 +662,14 @@ void GCode::_do_export(Print &print, FILE *file) m_cooling_buffer = make_unique(*this); if (print.config().spiral_vase.value) m_spiral_vase = make_unique(print.config()); +#ifdef HAS_PRESSURE_EQUALIZER if (print.config().max_volumetric_extrusion_rate_slope_positive.value > 0 || print.config().max_volumetric_extrusion_rate_slope_negative.value > 0) m_pressure_equalizer = make_unique(&print.config()); m_enable_extrusion_role_markers = (bool)m_pressure_equalizer; +#else /* HAS_PRESSURE_EQUALIZER */ + m_enable_extrusion_role_markers = false; +#endif /* HAS_PRESSURE_EQUALIZER */ // Write information on the generator. _write_format(file, "; %s\n\n", Slic3r::header_slic3r_generated().c_str()); @@ -860,7 +864,7 @@ void GCode::_do_export(Print &print, FILE *file) if (! (has_wipe_tower && print.config().single_extruder_multi_material_priming)) { // Set initial extruder only after custom start G-code. // Ugly hack: Do not set the initial extruder if the extruder is primed using the MMU priming towers at the edge of the print bed. - _write(file, this->set_extruder(initial_extruder_id)); + _write(file, this->set_extruder(initial_extruder_id, 0.)); } // Do all objects for each layer. @@ -918,8 +922,10 @@ void GCode::_do_export(Print &print, FILE *file) this->process_layer(file, print, lrs, tool_ordering.tools_for_layer(ltp.print_z()), © - object.copies().data()); print.throw_if_canceled(); } +#ifdef HAS_PRESSURE_EQUALIZER if (m_pressure_equalizer) _write(file, m_pressure_equalizer->process("", true)); +#endif /* HAS_PRESSURE_EQUALIZER */ ++ finished_objects; // Flag indicating whether the nozzle temperature changes from 1st to 2nd layer were performed. // Reset it when starting another object from 1st layer. @@ -974,8 +980,10 @@ void GCode::_do_export(Print &print, FILE *file) this->process_layer(file, print, layer.second, layer_tools, size_t(-1)); print.throw_if_canceled(); } +#ifdef HAS_PRESSURE_EQUALIZER if (m_pressure_equalizer) _write(file, m_pressure_equalizer->process("", true)); +#endif /* HAS_PRESSURE_EQUALIZER */ if (m_wipe_tower) // Purge the extruder, pull out the active filament. _write(file, m_wipe_tower->finalize(*this)); @@ -1533,15 +1541,13 @@ void GCode::process_layer( } } // for objects - - // Extrude the skirt, brim, support, perimeters, infill ordered by the extruders. std::vector> lower_layer_edge_grids(layers.size()); for (unsigned int extruder_id : layer_tools.extruders) { gcode += (layer_tools.has_wipe_tower && m_wipe_tower) ? m_wipe_tower->tool_change(*this, extruder_id, extruder_id == layer_tools.extruders.back()) : - this->set_extruder(extruder_id); + this->set_extruder(extruder_id, print_z); // let analyzer tag generator aware of a role type change if (m_enable_analyzer && layer_tools.has_wipe_tower && m_wipe_tower) @@ -1658,11 +1664,13 @@ void GCode::process_layer( if (m_cooling_buffer) gcode = m_cooling_buffer->process_layer(gcode, layer.id()); +#ifdef HAS_PRESSURE_EQUALIZER // Apply pressure equalization if enabled; // printf("G-code before filter:\n%s\n", gcode.c_str()); if (m_pressure_equalizer) gcode = m_pressure_equalizer->process(gcode.c_str(), false); // printf("G-code after filter:\n%s\n", out.c_str()); +#endif /* HAS_PRESSURE_EQUALIZER */ _write(file, gcode); BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z << @@ -2643,7 +2651,7 @@ std::string GCode::retract(bool toolchange) return gcode; } -std::string GCode::set_extruder(unsigned int extruder_id) +std::string GCode::set_extruder(unsigned int extruder_id, double print_z) { if (!m_writer.need_toolchange(extruder_id)) return ""; @@ -2677,6 +2685,8 @@ std::string GCode::set_extruder(unsigned int extruder_id) DynamicConfig config; config.set_key_value("previous_extruder", new ConfigOptionInt((int)m_writer.extruder()->id())); config.set_key_value("next_extruder", new ConfigOptionInt((int)extruder_id)); + config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index)); + config.set_key_value("layer_z", new ConfigOptionFloat(print_z)); gcode += placeholder_parser_process("toolchange_gcode", m_config.toolchange_gcode.value, extruder_id, &config); check_add_eol(gcode); } diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 86a6cacee..21957d32c 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -11,7 +11,6 @@ #include "Print.hpp" #include "PrintConfig.hpp" #include "GCode/CoolingBuffer.hpp" -#include "GCode/PressureEqualizer.hpp" #include "GCode/SpiralVase.hpp" #include "GCode/ToolOrdering.hpp" #include "GCode/WipeTower.hpp" @@ -22,6 +21,10 @@ #include #include +#ifdef HAS_PRESSURE_EQUALIZER +#include "GCode/PressureEqualizer.hpp" +#endif /* HAS_PRESSURE_EQUALIZER */ + namespace Slic3r { // Forward declarations. @@ -257,12 +260,12 @@ protected: bool needs_retraction(const Polyline &travel, ExtrusionRole role = erNone); std::string retract(bool toolchange = false); std::string unretract() { return m_writer.unlift() + m_writer.unretract(); } - std::string set_extruder(unsigned int extruder_id); + std::string set_extruder(unsigned int extruder_id, double print_z); /* Origin of print coordinates expressed in unscaled G-code coordinates. This affects the input arguments supplied to the extrude*() and travel_to() methods. */ - Vec2d m_origin; + Vec2d m_origin; FullPrintConfig m_config; GCodeWriter m_writer; PlaceholderParser m_placeholder_parser; @@ -306,7 +309,9 @@ protected: std::unique_ptr m_cooling_buffer; std::unique_ptr m_spiral_vase; +#ifdef HAS_PRESSURE_EQUALIZER std::unique_ptr m_pressure_equalizer; +#endif /* HAS_PRESSURE_EQUALIZER */ std::unique_ptr m_wipe_tower; // Heights at which the skirt has already been extruded. diff --git a/src/libslic3r/GCode/PreviewData.cpp b/src/libslic3r/GCode/PreviewData.cpp index e99eeac02..8eba6801e 100644 --- a/src/libslic3r/GCode/PreviewData.cpp +++ b/src/libslic3r/GCode/PreviewData.cpp @@ -479,14 +479,14 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std:: } case Extrusion::ColorPrint: { - const auto color_print_cnt = cp_values.size(); + const int color_cnt = (int)tool_colors.size()/4; + + const auto color_print_cnt = (int)cp_values.size(); for (int i = color_print_cnt; i >= 0 ; --i) { - int val = i; - while (val >= GCodePreviewData::Range::Colors_Count) - val -= GCodePreviewData::Range::Colors_Count; - GCodePreviewData::Color color = Range::Default_Colors[val]; - + GCodePreviewData::Color color; + ::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + (i % color_cnt) * 4), 4 * sizeof(float)); + if (color_print_cnt == 0) { items.emplace_back(Slic3r::I18N::translate(L("Default print color")), color); break; @@ -521,6 +521,12 @@ size_t GCodePreviewData::memory_used() const sizeof(shell) + sizeof(ranges); } +const std::vector& GCodePreviewData::ColorPrintColors() +{ + static std::vector color_print = {"#C0392B", "#E67E22", "#F1C40F", "#27AE60", "#1ABC9C", "#2980B9", "#9B59B6"}; + return color_print; +} + GCodePreviewData::Color operator + (const GCodePreviewData::Color& c1, const GCodePreviewData::Color& c2) { return GCodePreviewData::Color(clamp(0.0f, 1.0f, c1.rgba[0] + c2.rgba[0]), diff --git a/src/libslic3r/GCode/PreviewData.hpp b/src/libslic3r/GCode/PreviewData.hpp index 4ca579d9a..e934dc80a 100644 --- a/src/libslic3r/GCode/PreviewData.hpp +++ b/src/libslic3r/GCode/PreviewData.hpp @@ -216,6 +216,8 @@ public: // Return an estimate of the memory consumed by the time estimator. size_t memory_used() const; + + static const std::vector& ColorPrintColors(); }; GCodePreviewData::Color operator + (const GCodePreviewData::Color& c1, const GCodePreviewData::Color& c2); diff --git a/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index f87969505..031fd9a28 100644 --- a/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -381,22 +381,7 @@ public: Writer& comment_material(WipeTowerPrusaMM::material_type material) { m_gcode += "; material : "; - switch (material) - { - case WipeTowerPrusaMM::PVA: - m_gcode += "#8 (PVA)"; - break; - case WipeTowerPrusaMM::SCAFF: - m_gcode += "#5 (Scaffold)"; - break; - case WipeTowerPrusaMM::FLEX: - m_gcode += "#4 (Flex)"; - break; - default: - m_gcode += "DEFAULT (PLA)"; - break; - } - m_gcode += "\n"; + m_gcode += WipeTowerPrusaMM::to_string(material) + "\n"; return *this; }; @@ -487,6 +472,23 @@ WipeTowerPrusaMM::material_type WipeTowerPrusaMM::parse_material(const char *nam return INVALID; } +std::string WipeTowerPrusaMM::to_string(material_type material) +{ + switch (material) { + case PLA: return "PLA"; + case ABS: return "ABS"; + case PET: return "PET"; + case HIPS: return "HIPS"; + case FLEX: return "FLEX"; + case SCAFF: return "SCAFF"; + case EDGE: return "EDGE"; + case NGEN: return "NGEN"; + case PVA: return "PVA"; + case INVALID: + default: return "INVALID"; + } +} + // Returns gcode to prime the nozzles at the front edge of the print bed. WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( // print_z of the first layer. diff --git a/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 70c9526e6..3f904a483 100644 --- a/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -38,6 +38,7 @@ public: // Parse material name into material_type. static material_type parse_material(const char *name); + static std::string to_string(material_type material); // x -- x coordinates of wipe tower in mm ( left bottom corner ) // y -- y coordinates of wipe tower in mm ( left bottom corner ) diff --git a/src/libslic3r/Int128.hpp b/src/libslic3r/Int128.hpp index d54b75342..56dc5f461 100644 --- a/src/libslic3r/Int128.hpp +++ b/src/libslic3r/Int128.hpp @@ -53,6 +53,11 @@ #define HAS_INTRINSIC_128_TYPE #endif +#if defined(_MSC_VER) && defined(_WIN64) + #include + #pragma intrinsic(_mul128) +#endif + //------------------------------------------------------------------------------ // Int128 class (enables safe math on signed 64bit integers) // eg Int128 val1((int64_t)9223372036854775807); //ie 2^63 -1 diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index d86a180b8..a88bdd991 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -489,6 +489,9 @@ void Model::convert_multipart_object(unsigned int max_extruders) { new_v->name = o->name; new_v->config.set_deserialize("extruder", get_auto_extruder_id_as_string(max_extruders)); +#if ENABLE_VOLUMES_CENTERING_FIXES + new_v->translate(-o->origin_translation); +#endif // ENABLE_VOLUMES_CENTERING_FIXES } } @@ -549,7 +552,7 @@ std::string Model::propose_export_file_name() const for (const ModelObject *model_object : this->objects) for (ModelInstance *model_instance : model_object->instances) if (model_instance->is_printable()) - return model_object->input_file; + return model_object->name.empty() ? model_object->input_file : model_object->name; return std::string(); } @@ -1683,7 +1686,7 @@ bool model_volume_list_changed(const ModelObject &model_object_old, const ModelO return false; } -#ifdef _DEBUG +#ifndef NDEBUG // Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique. void check_model_ids_validity(const Model &model) { @@ -1729,6 +1732,6 @@ void check_model_ids_equal(const Model &model1, const Model &model2) } } } -#endif /* _DEBUG */ +#endif /* NDEBUG */ } diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 0ae238510..ba109246a 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -629,11 +629,11 @@ extern bool model_object_list_extended(const Model &model_old, const Model &mode // than the old ModelObject. extern bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const ModelVolume::Type type); -#ifdef _DEBUG +#ifndef NDEBUG // 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_equal(const Model &model1, const Model &model2); -#endif /* _DEBUG */ +#endif /* NDEBUG */ } diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 1ef6c7b84..3efb18599 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -135,8 +135,10 @@ bool Print::invalidate_state_by_config_options(const std::vectortotal_used_filament)); + config.set_key_value("used_filament", new ConfigOptionFloat (this->total_used_filament / 1000.)); config.set_key_value("extruded_volume", new ConfigOptionFloat (this->total_extruded_volume)); config.set_key_value("total_cost", new ConfigOptionFloat (this->total_cost)); config.set_key_value("total_weight", new ConfigOptionFloat (this->total_weight)); @@ -1924,7 +1926,7 @@ DynamicConfig PrintStatistics::placeholders() "print_time", "normal_print_time", "silent_print_time", "used_filament", "extruded_volume", "total_cost", "total_weight", "total_wipe_tower_cost", "total_wipe_tower_filament"}) - config.set_key_value(key, new ConfigOptionString(std::string("{") + key + "}")); + config.set_key_value(key, new ConfigOptionString(std::string("{") + key + "}")); return config; } diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 85dcb5d40..a51bd32f1 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1208,6 +1208,7 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); +#ifdef HAS_PRESSURE_EQUALIZER def = this->add("max_volumetric_extrusion_rate_slope_positive", coFloat); def->label = L("Max volumetric slope positive"); def->tooltip = L("This experimental setting is used to limit the speed of change in extrusion rate. " @@ -1231,6 +1232,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); +#endif /* HAS_PRESSURE_EQUALIZER */ def = this->add("min_fan_speed", coInts); def->label = L("Min"); @@ -2740,6 +2742,9 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va "start_perimeters_at_concave_points", "start_perimeters_at_non_overhang", "randomize_start", "seal_position", "vibration_limit", "bed_size", "print_center", "g0", "threads", "pressure_advance", "wipe_tower_per_color_wipe" +#ifndef HAS_PRESSURE_EQUALIZER + , "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative" +#endif /* HAS_PRESSURE_EQUALIZER */ }; if (ignore.find(opt_key) != ignore.end()) { diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 4842156d6..1b218a192 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -20,6 +20,8 @@ #include "libslic3r.h" #include "Config.hpp" +// #define HAS_PRESSURE_EQUALIZER + namespace Slic3r { enum PrinterTechnology @@ -620,8 +622,10 @@ public: ConfigOptionString layer_gcode; ConfigOptionFloat max_print_speed; ConfigOptionFloat max_volumetric_speed; +#ifdef HAS_PRESSURE_EQUALIZER ConfigOptionFloat max_volumetric_extrusion_rate_slope_positive; ConfigOptionFloat max_volumetric_extrusion_rate_slope_negative; +#endif ConfigOptionPercents retract_before_wipe; ConfigOptionFloats retract_length; ConfigOptionFloats retract_length_toolchange; @@ -689,8 +693,10 @@ protected: OPT_PTR(layer_gcode); OPT_PTR(max_print_speed); OPT_PTR(max_volumetric_speed); +#ifdef HAS_PRESSURE_EQUALIZER OPT_PTR(max_volumetric_extrusion_rate_slope_positive); OPT_PTR(max_volumetric_extrusion_rate_slope_negative); +#endif /* HAS_PRESSURE_EQUALIZER */ OPT_PTR(retract_before_wipe); OPT_PTR(retract_length); OPT_PTR(retract_length_toolchange); diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index d10d9e0eb..fd1645c9e 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -35,6 +35,27 @@ #include "GUI.hpp" +#ifdef HAS_GLSAFE +void glAssertRecentCallImpl() +{ + GLenum err = glGetError(); + if (err == GL_NO_ERROR) + return; + const char *sErr = 0; + switch (err) { + case GL_INVALID_ENUM: sErr = "Invalid Enum"; break; + case GL_INVALID_VALUE: sErr = "Invalid Value"; break; + case GL_INVALID_OPERATION: sErr = "Invalid Operation"; break; + case GL_STACK_OVERFLOW: sErr = "Stack Overflow"; break; + case GL_STACK_UNDERFLOW: sErr = "Stack Underflow"; break; + case GL_OUT_OF_MEMORY: sErr = "Out Of Memory"; break; + default: sErr = "Unknown"; break; + } + BOOST_LOG_TRIVIAL(error) << "OpenGL error " << (int)err << ": " << sErr; + assert(false); +} +#endif + namespace Slic3r { void GLIndexedVertexArray::load_mesh_flat_shading(const TriangleMesh &mesh) @@ -81,25 +102,25 @@ void GLIndexedVertexArray::finalize_geometry(bool use_VBOs) if (use_VBOs) { if (! empty()) { - glGenBuffers(1, &this->vertices_and_normals_interleaved_VBO_id); - glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id); - glBufferData(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved.size() * 4, this->vertices_and_normals_interleaved.data(), GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glsafe(glGenBuffers(1, &this->vertices_and_normals_interleaved_VBO_id)); + glsafe(glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id)); + glsafe(glBufferData(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved.size() * 4, this->vertices_and_normals_interleaved.data(), GL_STATIC_DRAW)); + glsafe(glBindBuffer(GL_ARRAY_BUFFER, 0)); this->vertices_and_normals_interleaved.clear(); } if (! this->triangle_indices.empty()) { - glGenBuffers(1, &this->triangle_indices_VBO_id); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices.size() * 4, this->triangle_indices.data(), GL_STATIC_DRAW); + glsafe(glGenBuffers(1, &this->triangle_indices_VBO_id)); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id)); + glsafe(glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices.size() * 4, this->triangle_indices.data(), GL_STATIC_DRAW)); this->triangle_indices.clear(); } if (! this->quad_indices.empty()) { - glGenBuffers(1, &this->quad_indices_VBO_id); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices.size() * 4, this->quad_indices.data(), GL_STATIC_DRAW); + glsafe(glGenBuffers(1, &this->quad_indices_VBO_id)); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id)); + glsafe(glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices.size() * 4, this->quad_indices.data(), GL_STATIC_DRAW)); this->quad_indices.clear(); } - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } this->shrink_to_fit(); } @@ -107,15 +128,15 @@ void GLIndexedVertexArray::finalize_geometry(bool use_VBOs) void GLIndexedVertexArray::release_geometry() { if (this->vertices_and_normals_interleaved_VBO_id) { - glDeleteBuffers(1, &this->vertices_and_normals_interleaved_VBO_id); + glsafe(glDeleteBuffers(1, &this->vertices_and_normals_interleaved_VBO_id)); this->vertices_and_normals_interleaved_VBO_id = 0; } if (this->triangle_indices_VBO_id) { - glDeleteBuffers(1, &this->triangle_indices_VBO_id); + glsafe(glDeleteBuffers(1, &this->triangle_indices_VBO_id)); this->triangle_indices_VBO_id = 0; } if (this->quad_indices_VBO_id) { - glDeleteBuffers(1, &this->quad_indices_VBO_id); + glsafe(glDeleteBuffers(1, &this->quad_indices_VBO_id)); this->quad_indices_VBO_id = 0; } this->clear(); @@ -125,42 +146,42 @@ void GLIndexedVertexArray::release_geometry() void GLIndexedVertexArray::render() const { if (this->vertices_and_normals_interleaved_VBO_id) { - glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id); - glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))); - glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr); + glsafe(glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id)); + glsafe(glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)))); + glsafe(glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr)); } else { - glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3); - glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data()); + glsafe(glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3)); + glsafe(glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data())); } - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); + glsafe(glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(glEnableClientState(GL_NORMAL_ARRAY)); if (this->indexed()) { if (this->vertices_and_normals_interleaved_VBO_id) { // Render using the Vertex Buffer Objects. if (this->triangle_indices_size > 0) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id); - glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, nullptr); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id)); + glsafe(glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, nullptr)); } if (this->quad_indices_size > 0) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id); - glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, nullptr); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id)); + glsafe(glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, nullptr)); } - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } else { // Render in an immediate mode. if (! this->triangle_indices.empty()) - glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, this->triangle_indices.data()); + glsafe(glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, this->triangle_indices.data())); if (! this->quad_indices.empty()) - glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, this->quad_indices.data()); + glsafe(glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, this->quad_indices.data())); } } else - glDrawArrays(GL_TRIANGLES, 0, GLsizei(this->vertices_and_normals_interleaved_size / 6)); + glsafe(glDrawArrays(GL_TRIANGLES, 0, GLsizei(this->vertices_and_normals_interleaved_size / 6))); if (this->vertices_and_normals_interleaved_VBO_id) - glBindBuffer(GL_ARRAY_BUFFER, 0); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); + glsafe(glBindBuffer(GL_ARRAY_BUFFER, 0)); + glsafe(glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(glDisableClientState(GL_NORMAL_ARRAY)); } void GLIndexedVertexArray::render( @@ -173,35 +194,35 @@ void GLIndexedVertexArray::render( if (this->vertices_and_normals_interleaved_VBO_id) { // Render using the Vertex Buffer Objects. - glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id); - glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))); - glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); + glsafe(glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id)); + glsafe(glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)))); + glsafe(glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr)); + glsafe(glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(glEnableClientState(GL_NORMAL_ARRAY)); if (this->triangle_indices_size > 0) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id); - glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4)); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id)); + glsafe(glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4))); } if (this->quad_indices_size > 0) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id); - glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4)); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id)); + glsafe(glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4))); } - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glsafe(glBindBuffer(GL_ARRAY_BUFFER, 0)); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } else { // Render in an immediate mode. - glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3); - glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data()); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); + glsafe(glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3)); + glsafe(glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data())); + glsafe(glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(glEnableClientState(GL_NORMAL_ARRAY)); if (! this->triangle_indices.empty()) - glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->triangle_indices.data() + tverts_range.first)); + glsafe(glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->triangle_indices.data() + tverts_range.first))); if (! this->quad_indices.empty()) - glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->quad_indices.data() + qverts_range.first)); + glsafe(glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->quad_indices.data() + qverts_range.first))); } - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); + glsafe(glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(glDisableClientState(GL_NORMAL_ARRAY)); } const float GLVolume::SELECTED_COLOR[4] = { 0.0f, 1.0f, 0.0f, 1.0f }; @@ -375,15 +396,15 @@ void GLVolume::render() const if (!is_active) return; - ::glCullFace(GL_BACK); - ::glPushMatrix(); + glsafe(::glCullFace(GL_BACK)); + glsafe(::glPushMatrix()); - ::glMultMatrixd(world_matrix().data()); + glsafe(::glMultMatrixd(world_matrix().data())); if (this->indexed_vertex_array.indexed()) this->indexed_vertex_array.render(this->tverts_range, this->qverts_range); else this->indexed_vertex_array.render(); - ::glPopMatrix(); + glsafe(::glPopMatrix()); } void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) const @@ -398,63 +419,63 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c GLsizei n_quads = GLsizei(std::min(indexed_vertex_array.quad_indices_size, qverts_range.second - qverts_range.first)); if (n_triangles + n_quads == 0) { - ::glDisableClientState(GL_VERTEX_ARRAY); - ::glDisableClientState(GL_NORMAL_ARRAY); + glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); if (color_id >= 0) { float color[4]; ::memcpy((void*)color, (const void*)render_color, 4 * sizeof(float)); - ::glUniform4fv(color_id, 1, (const GLfloat*)color); + glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)color)); } else - ::glColor4fv(render_color); + glsafe(::glColor4fv(render_color)); if (detection_id != -1) - ::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0); + glsafe(::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0)); if (worldmatrix_id != -1) - ::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast().data()); + glsafe(::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast().data())); render(); - ::glEnableClientState(GL_VERTEX_ARRAY); - ::glEnableClientState(GL_NORMAL_ARRAY); + glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); return; } if (color_id >= 0) - ::glUniform4fv(color_id, 1, (const GLfloat*)render_color); + glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)render_color)); else - ::glColor4fv(render_color); + glsafe(::glColor4fv(render_color)); if (detection_id != -1) - ::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0); + glsafe(::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0)); if (worldmatrix_id != -1) - ::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast().data()); + glsafe(::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast().data())); - ::glBindBuffer(GL_ARRAY_BUFFER, indexed_vertex_array.vertices_and_normals_interleaved_VBO_id); - ::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))); - ::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, indexed_vertex_array.vertices_and_normals_interleaved_VBO_id)); + glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)))); + glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr)); - ::glPushMatrix(); + glsafe(::glPushMatrix()); - ::glMultMatrixd(world_matrix().data()); + glsafe(::glMultMatrixd(world_matrix().data())); if (n_triangles > 0) { - ::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexed_vertex_array.triangle_indices_VBO_id); - ::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexed_vertex_array.triangle_indices_VBO_id)); + glsafe(::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4))); } if (n_quads > 0) { - ::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexed_vertex_array.quad_indices_VBO_id); - ::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexed_vertex_array.quad_indices_VBO_id)); + glsafe(::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4))); } - ::glPopMatrix(); + glsafe(::glPopMatrix()); } void GLVolume::render_legacy() const @@ -467,33 +488,33 @@ void GLVolume::render_legacy() const GLsizei n_quads = GLsizei(std::min(indexed_vertex_array.quad_indices_size, qverts_range.second - qverts_range.first)); if (n_triangles + n_quads == 0) { - ::glDisableClientState(GL_VERTEX_ARRAY); - ::glDisableClientState(GL_NORMAL_ARRAY); + glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); - ::glColor4fv(render_color); + glsafe(::glColor4fv(render_color)); render(); - ::glEnableClientState(GL_VERTEX_ARRAY); - ::glEnableClientState(GL_NORMAL_ARRAY); + glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); return; } - ::glColor4fv(render_color); - ::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data() + 3); - ::glNormalPointer(GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data()); + glsafe(::glColor4fv(render_color)); + glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data() + 3)); + glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data())); - ::glPushMatrix(); + glsafe(::glPushMatrix()); - ::glMultMatrixd(world_matrix().data()); + glsafe(::glMultMatrixd(world_matrix().data())); if (n_triangles > 0) - ::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, indexed_vertex_array.triangle_indices.data() + tverts_range.first); + glsafe(::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, indexed_vertex_array.triangle_indices.data() + tverts_range.first)); if (n_quads > 0) - ::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, indexed_vertex_array.quad_indices.data() + qverts_range.first); + glsafe(::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, indexed_vertex_array.quad_indices.data() + qverts_range.first)); - ::glPopMatrix(); + glsafe(::glPopMatrix()); } std::vector GLVolumeCollection::load_object( @@ -705,7 +726,7 @@ static GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolum if ((type == GLVolumeCollection::Transparent) && (list.size() > 1)) { Transform3d modelview_matrix; - ::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data()); + glsafe(::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data())); for (GLVolumeWithZ& volume : list) { @@ -722,18 +743,18 @@ static GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolum void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool disable_cullface, std::function filter_func) const { - ::glEnable(GL_BLEND); - ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glsafe(::glEnable(GL_BLEND)); + glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - ::glCullFace(GL_BACK); + glsafe(::glCullFace(GL_BACK)); if (disable_cullface) - ::glDisable(GL_CULL_FACE); + glsafe(::glDisable(GL_CULL_FACE)); - ::glEnableClientState(GL_VERTEX_ARRAY); - ::glEnableClientState(GL_NORMAL_ARRAY); + glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); GLint current_program_id; - ::glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id); + glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id)); GLint color_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "uniform_color") : -1; GLint z_range_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "z_range") : -1; GLint print_box_min_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.min") : -1; @@ -742,13 +763,13 @@ void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool GLint print_box_worldmatrix_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.volume_world_matrix") : -1; if (print_box_min_id != -1) - ::glUniform3fv(print_box_min_id, 1, (const GLfloat*)print_box_min); + glsafe(::glUniform3fv(print_box_min_id, 1, (const GLfloat*)print_box_min)); if (print_box_max_id != -1) - ::glUniform3fv(print_box_max_id, 1, (const GLfloat*)print_box_max); + glsafe(::glUniform3fv(print_box_max_id, 1, (const GLfloat*)print_box_max)); if (z_range_id != -1) - ::glUniform2fv(z_range_id, 1, (const GLfloat*)z_range); + glsafe(::glUniform2fv(z_range_id, 1, (const GLfloat*)z_range)); GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, filter_func); for (GLVolumeWithZ& volume : to_render) { @@ -756,29 +777,29 @@ void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool volume.first->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id); } - ::glBindBuffer(GL_ARRAY_BUFFER, 0); - ::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); - ::glDisableClientState(GL_VERTEX_ARRAY); - ::glDisableClientState(GL_NORMAL_ARRAY); + glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); if (disable_cullface) - ::glEnable(GL_CULL_FACE); + glsafe(::glEnable(GL_CULL_FACE)); - ::glDisable(GL_BLEND); + glsafe(::glDisable(GL_BLEND)); } void GLVolumeCollection::render_legacy(ERenderType type, bool disable_cullface) const { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glsafe(glEnable(GL_BLEND)); + glsafe(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - glCullFace(GL_BACK); + glsafe(glCullFace(GL_BACK)); if (disable_cullface) - ::glDisable(GL_CULL_FACE); + glsafe(::glDisable(GL_CULL_FACE)); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); + glsafe(glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(glEnableClientState(GL_NORMAL_ARRAY)); GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, std::function()); for (GLVolumeWithZ& volume : to_render) @@ -787,13 +808,13 @@ void GLVolumeCollection::render_legacy(ERenderType type, bool disable_cullface) volume.first->render_legacy(); } - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); + glsafe(glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(glDisableClientState(GL_NORMAL_ARRAY)); if (disable_cullface) - ::glEnable(GL_CULL_FACE); + glsafe(::glEnable(GL_CULL_FACE)); - glDisable(GL_BLEND); + glsafe(glDisable(GL_BLEND)); } bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, ModelInstance::EPrintVolumeState* out_state) @@ -1718,44 +1739,44 @@ void GLModel::render() const void GLModel::render_VBOs() const { - ::glEnable(GL_BLEND); - ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glsafe(::glEnable(GL_BLEND)); + glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - ::glCullFace(GL_BACK); - ::glEnableClientState(GL_VERTEX_ARRAY); - ::glEnableClientState(GL_NORMAL_ARRAY); + glsafe(::glCullFace(GL_BACK)); + glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); GLint current_program_id; - ::glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id); + glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id)); GLint color_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "uniform_color") : -1; m_volume.render_VBOs(color_id, -1, -1); - ::glBindBuffer(GL_ARRAY_BUFFER, 0); - ::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); - ::glDisableClientState(GL_VERTEX_ARRAY); - ::glDisableClientState(GL_NORMAL_ARRAY); + glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); - ::glDisable(GL_BLEND); + glsafe(::glDisable(GL_BLEND)); } void GLModel::render_legacy() const { - ::glEnable(GL_LIGHTING); - ::glEnable(GL_BLEND); - ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glsafe(::glEnable(GL_LIGHTING)); + glsafe(::glEnable(GL_BLEND)); + glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - ::glCullFace(GL_BACK); - ::glEnableClientState(GL_VERTEX_ARRAY); - ::glEnableClientState(GL_NORMAL_ARRAY); + glsafe(::glCullFace(GL_BACK)); + glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); m_volume.render_legacy(); - ::glDisableClientState(GL_VERTEX_ARRAY); - ::glDisableClientState(GL_NORMAL_ARRAY); + glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); - ::glDisable(GL_BLEND); - ::glDisable(GL_LIGHTING); + glsafe(::glDisable(GL_BLEND)); + glsafe(::glDisable(GL_LIGHTING)); } bool GLArrow::on_init(bool useVBOs) diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index e9340bd6e..7430ff4aa 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -11,6 +11,19 @@ #include +#ifndef NDEBUG +#define HAS_GLSAFE +#endif + +#ifdef HAS_GLSAFE +extern void glAssertRecentCallImpl(); +inline void glAssertRecentCall() { glAssertRecentCallImpl(); } +#define glsafe(cmd) do { cmd; glAssertRecentCallImpl(); } while (false) +#else +inline void glAssertRecentCall() { } +#define glsafe(cmd) cmd +#endif + namespace Slic3r { class Print; diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 3dd160432..862f1b107 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -143,9 +143,11 @@ void Field::get_value_by_opt_type(wxString& str) break; } double val; + // Replace the first occurence of comma in decimal number. + str.Replace(",", ".", false); if(!str.ToCDouble(&val)) { - show_error(m_parent, _(L("Input value contains incorrect symbol(s).\nUse, please, only digits"))); + show_error(m_parent, _(L("Invalid numeric input."))); set_value(double_to_string(val), true); } if (m_opt.min > val || val > m_opt.max) @@ -163,10 +165,12 @@ void Field::get_value_by_opt_type(wxString& str) if (m_opt.type == coFloatOrPercent && !str.IsEmpty() && str.Last() != '%') { double val; + // Replace the first occurence of comma in decimal number. + str.Replace(",", ".", false); if (!str.ToCDouble(&val)) { - show_error(m_parent, _(L("Input value contains incorrect symbol(s).\nUse, please, only digits"))); - set_value(double_to_string(val), true); + show_error(m_parent, _(L("Invalid numeric input."))); + set_value(double_to_string(val), true); } else if (m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max || m_opt.sidetext.rfind("mm ") != std::string::npos && val > 1) @@ -334,6 +338,7 @@ void TextCtrl::propagate_value() boost::any& TextCtrl::get_value() { wxString ret_str = static_cast(window)->GetValue(); + // modifies ret_string! get_value_by_opt_type(ret_str); return m_value; @@ -727,11 +732,13 @@ boost::any& Choice::get_value() else if (m_opt.gui_type == "f_enum_open") { const int ret_enum = static_cast(window)->GetSelection(); if (ret_enum < 0 || m_opt.enum_values.empty() || m_opt.type == coStrings) + // modifies ret_string! get_value_by_opt_type(ret_str); else m_value = atof(m_opt.enum_values[ret_enum].c_str()); } else + // modifies ret_string! get_value_by_opt_type(ret_str); return m_value; diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp index 3273f84c9..8391a111b 100644 --- a/src/slic3r/GUI/Field.hpp +++ b/src/slic3r/GUI/Field.hpp @@ -115,7 +115,7 @@ public: /// subclasses should overload with a specific version /// Postcondition: Method does not fire the on_change event. virtual void set_value(const boost::any& value, bool change_event) = 0; - + /// Gets a boost::any representing this control. /// subclasses should overload with a specific version virtual boost::any& get_value() = 0; @@ -128,6 +128,8 @@ public: virtual wxString get_tooltip_text(const wxString& default_string); + void field_changed() { on_change_field(); } + // set icon to "UndoToSystemValue" button according to an inheritance of preset // void set_nonsys_btn_icon(const wxBitmap& icon); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 7366516d1..0a6dd52c0 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1793,12 +1793,12 @@ static double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to)); Vec3d axis = angle_axis.axis(); double angle = angle_axis.angle(); -#ifdef _DEBUG +#ifndef NDEBUG if (std::abs(angle) > 1e-8) { assert(std::abs(axis.x()) < 1e-8); assert(std::abs(axis.y()) < 1e-8); } -#endif /* _DEBUG */ +#endif /* NDEBUG */ return (axis.z() < 0) ? -angle : angle; } @@ -2786,7 +2786,7 @@ void GLCanvas3D::Selection::_render_sidebar_size_hint(Axis axis, double length) { } -#ifdef _DEBUG +#ifndef NDEBUG static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to) { Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to)); @@ -2820,7 +2820,7 @@ static void verify_instances_rotation_synchronized(const Model &model, const GLV } } } -#endif /* _DEBUG */ +#endif /* NDEBUG */ void GLCanvas3D::Selection::_synchronize_unselected_instances(SyncRotationType sync_rotation_type) { @@ -2880,9 +2880,9 @@ void GLCanvas3D::Selection::_synchronize_unselected_instances(SyncRotationType s } } -#ifdef _DEBUG +#ifndef NDEBUG verify_instances_rotation_synchronized(*m_model, *m_volumes); -#endif /* _DEBUG */ +#endif /* NDEBUG */ } void GLCanvas3D::Selection::_synchronize_unselected_volumes() @@ -3250,6 +3250,7 @@ bool GLCanvas3D::Gizmos::handle_shortcut(int key, const Selection& selection) if (!m_enabled || selection.is_empty()) return false; + EType old_current = m_current; bool handled = false; for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) { @@ -3273,7 +3274,12 @@ bool GLCanvas3D::Gizmos::handle_shortcut(int key, const Selection& selection) handled = true; } } - else + } + + if (handled && (old_current != Undefined) && (old_current != m_current)) + { + GizmosMap::const_iterator it = m_gizmos.find(old_current); + if (it != m_gizmos.end()) it->second->set_state(GLGizmoBase::Off); } @@ -3742,17 +3748,12 @@ GLCanvas3D::LegendTexture::LegendTexture() { } -bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, const std::vector& tool_colors, const GLCanvas3D& canvas, bool use_error_colors) +void GLCanvas3D::LegendTexture::fill_color_print_legend_values(const GCodePreviewData& preview_data, const GLCanvas3D& canvas, + std::vector>& cp_legend_values) { - reset(); - - // collects items to render - auto title = _(preview_data.get_legend_title()); - - std::vector> cp_legend_values; if (preview_data.extrusion.view_type == GCodePreviewData::Extrusion::ColorPrint) { - const auto& config = wxGetApp().preset_bundle->full_config(); + auto& config = wxGetApp().preset_bundle->project_config; const std::vector& color_print_values = config.option("colorprint_heights")->values; const int values_cnt = color_print_values.size(); if (values_cnt > 0) { @@ -3773,7 +3774,19 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c } } } - const GCodePreviewData::LegendItemsList& items = preview_data.get_legend_items(tool_colors, /*color_print_values*/cp_legend_values); +} + +bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, const std::vector& tool_colors, const GLCanvas3D& canvas, bool use_error_colors) +{ + reset(); + + // collects items to render + auto title = _(preview_data.get_legend_title()); + + std::vector> cp_legend_values; + fill_color_print_legend_values(preview_data, canvas, cp_legend_values); + + const GCodePreviewData::LegendItemsList& items = preview_data.get_legend_items(tool_colors, cp_legend_values); unsigned int items_count = (unsigned int)items.size(); if (items_count == 0) @@ -4160,6 +4173,8 @@ unsigned int GLCanvas3D::get_volumes_count() const void GLCanvas3D::reset_volumes() { + _set_current(); + if (!m_volumes.empty()) { m_selection.clear(); @@ -4614,6 +4629,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re if ((m_canvas == nullptr) || (m_config == nullptr) || (m_model == nullptr)) return; + _set_current(); + struct ModelVolumeState { ModelVolumeState(const GLVolume *volume) : model_volume(nullptr), geometry_id(volume->geometry_id), volume_idx(-1) {} @@ -4668,10 +4685,10 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re } if (printer_technology == ptSLA) { const SLAPrint *sla_print = this->sla_print(); - #ifdef _DEBUG + #ifndef NDEBUG // Verify that the SLAPrint object is synchronized with m_model. check_model_ids_equal(*m_model, sla_print->model()); - #endif /* _DEBUG */ + #endif /* NDEBUG */ sla_support_state.reserve(sla_print->objects().size()); for (const SLAPrintObject *print_object : sla_print->objects()) { SLASupportState state; @@ -4920,6 +4937,8 @@ void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const const Print *print = this->fff_print(); if ((m_canvas != nullptr) && (print != nullptr)) { + _set_current(); + std::vector tool_colors = _parse_colors(str_tool_colors); if (m_volumes.empty()) @@ -4957,22 +4976,25 @@ void GLCanvas3D::load_sla_preview() const SLAPrint* print = this->sla_print(); if ((m_canvas != nullptr) && (print != nullptr)) { + _set_current(); _load_shells_sla(); } } -void GLCanvas3D::load_preview(const std::vector& str_tool_colors) +void GLCanvas3D::load_preview(const std::vector& str_tool_colors, const std::vector& color_print_values) { const Print *print = this->fff_print(); if (print == nullptr) return; + _set_current(); + _load_print_toolpaths(); _load_wipe_tower_toolpaths(str_tool_colors); for (const PrintObject* object : print->objects()) { if (object != nullptr) - _load_print_object_toolpaths(*object, str_tool_colors); + _load_print_object_toolpaths(*object, str_tool_colors, color_print_values); } for (GLVolume* volume : m_volumes.volumes) @@ -4982,7 +5004,14 @@ void GLCanvas3D::load_preview(const std::vector& str_tool_colors) _update_toolpath_volumes_outside_state(); _show_warning_texture_if_needed(); - reset_legend_texture(); + if (color_print_values.empty()) + reset_legend_texture(); + else { + auto preview_data = GCodePreviewData(); + preview_data.extrusion.view_type = GCodePreviewData::Extrusion::ColorPrint; + const std::vector tool_colors = _parse_colors(str_tool_colors); + _generate_legend_texture(preview_data, tool_colors); + } } void GLCanvas3D::bind_event_handlers() @@ -5630,7 +5659,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) void GLCanvas3D::on_paint(wxPaintEvent& evt) { - render(); + if (m_initialized) + m_dirty = true; + else + // Call render directly, so it gets initialized immediately, not from On Idle handler. + this->render(); } void GLCanvas3D::on_key_down(wxKeyEvent& evt) @@ -5681,6 +5714,7 @@ Point GLCanvas3D::get_local_mouse_position() const void GLCanvas3D::reset_legend_texture() { + _set_current(); m_legend_texture.reset(); } @@ -5951,6 +5985,9 @@ void GLCanvas3D::set_camera_zoom(float zoom) if (zoom_min > 0.0f) zoom = std::max(zoom, zoom_min * 0.7f); + // Don't allow to zoom too close to the scene. + zoom = std::min(zoom, 100.0f); + m_camera.zoom = zoom; viewport_changed(); _refresh_if_shown_on_screen(); @@ -7235,7 +7272,7 @@ void GLCanvas3D::_load_print_toolpaths() volume.indexed_vertex_array.finalize_geometry(m_use_VBOs && m_initialized); } -void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, const std::vector& str_tool_colors) +void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, const std::vector& str_tool_colors, const std::vector& color_print_values) { std::vector tool_colors = _parse_colors(str_tool_colors); @@ -7247,6 +7284,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c bool has_infill; bool has_support; const std::vector* tool_colors; + const std::vector* color_print_values; // Number of vertices (each vertex is 6x4=24 bytes long) static const size_t alloc_size_max() { return 131072; } // 3.15MB @@ -7264,7 +7302,15 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c const float* color_tool(size_t tool) const { return tool_colors->data() + tool * 4; } int volume_idx(int extruder, int feature) const { - return this->color_by_tool() ? std::min(this->number_tools() - 1, std::max(extruder - 1, 0)) : feature; + return this->color_by_color_print() ? 0 : this->color_by_tool() ? std::min(this->number_tools() - 1, std::max(extruder - 1, 0)) : feature; + } + + // For coloring by a color_print(M600), return a parsed color. + bool color_by_color_print() const { return color_print_values!=nullptr; } + const float* color_print_by_layer_idx(const size_t layer_idx) const + { + auto it = std::lower_bound(color_print_values->begin(), color_print_values->end(), layers[layer_idx]->print_z + EPSILON); + return color_tool((it - color_print_values->begin()) % number_tools()); } } ctxt; @@ -7272,6 +7318,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c ctxt.has_infill = print_object.is_step_done(posInfill); ctxt.has_support = print_object.is_step_done(posSupportMaterial); ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors; + ctxt.color_print_values = color_print_values.empty() ? nullptr : &color_print_values; ctxt.shifted_copies = &print_object.copies(); @@ -7296,7 +7343,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - start"; //FIXME Improve the heuristics for a grain size. - size_t grain_size = std::max(ctxt.layers.size() / 16, size_t(1)); + size_t grain_size = ctxt.color_by_color_print() ? size_t(1) : std::max(ctxt.layers.size() / 16, size_t(1)); tbb::spin_mutex new_volume_mutex; auto new_volume = [this, &new_volume_mutex](const float *color) -> GLVolume* { auto *volume = new GLVolume(color); @@ -7311,7 +7358,9 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c tbb::blocked_range(0, ctxt.layers.size(), grain_size), [&ctxt, &new_volume](const tbb::blocked_range& range) { GLVolumePtrs vols; - if (ctxt.color_by_tool()) { + if (ctxt.color_by_color_print()) + vols.emplace_back(new_volume(ctxt.color_print_by_layer_idx(range.begin()))); + else if (ctxt.color_by_tool()) { for (size_t i = 0; i < ctxt.number_tools(); ++i) vols.emplace_back(new_volume(ctxt.color_tool(i))); } @@ -7629,11 +7678,15 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat } case GCodePreviewData::Extrusion::ColorPrint: { + const size_t color_cnt = tool_colors.size() / 4; + int val = int(value); - while (val >= GCodePreviewData::Range::Colors_Count) - val -= GCodePreviewData::Range::Colors_Count; + while (val >= color_cnt) + val -= color_cnt; - GCodePreviewData::Color color = GCodePreviewData::Range::Default_Colors[val]; + GCodePreviewData::Color color; + ::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + val * 4), 4 * sizeof(float)); + return color; } default: @@ -8284,6 +8337,8 @@ void GLCanvas3D::_update_toolpath_volumes_outside_state() void GLCanvas3D::_show_warning_texture_if_needed() { + _set_current(); + if (_is_any_volume_outside()) { enable_warning_texture(true); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 8bdbf89b0..7d38e5128 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -857,6 +857,8 @@ private: public: LegendTexture(); + void fill_color_print_legend_values(const GCodePreviewData& preview_data, const GLCanvas3D& canvas, + std::vector>& cp_legend_values); bool generate(const GCodePreviewData& preview_data, const std::vector& tool_colors, const GLCanvas3D& canvas, bool use_error_colors); @@ -1027,8 +1029,7 @@ public: void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector& str_tool_colors); void load_sla_preview(); - void load_preview(const std::vector& str_tool_colors); - + void load_preview(const std::vector& str_tool_colors, const std::vector& color_print_values); void bind_event_handlers(); void unbind_event_handlers(); @@ -1133,7 +1134,8 @@ private: // Create 3D thick extrusion lines for object forming extrusions. // Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes, // one for perimeters, one for infill and one for supports. - void _load_print_object_toolpaths(const PrintObject& print_object, const std::vector& str_tool_colors); + void _load_print_object_toolpaths(const PrintObject& print_object, const std::vector& str_tool_colors, + const std::vector& color_print_values); // Create 3D thick extrusion lines for wipe tower extrusions void _load_wipe_tower_toolpaths(const std::vector& str_tool_colors); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 00b074f7d..57c01a447 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -64,12 +64,6 @@ ObjectList::ObjectList(wxWindow* parent) : init_icons(); - // create popup menus for object and part - create_object_popupmenu(&m_menu_object); - create_part_popupmenu(&m_menu_part); - create_sla_object_popupmenu(&m_menu_sla_object); - create_instance_popupmenu(&m_menu_instance); - // describe control behavior Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxEvent& event) { selection_changed(); @@ -106,8 +100,6 @@ ObjectList::ObjectList(wxWindow* parent) : ObjectList::~ObjectList() { - if (m_default_config) - delete m_default_config; } void ObjectList::create_objects_ctrl() @@ -141,6 +133,15 @@ void ObjectList::create_objects_ctrl() wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); } +void ObjectList::create_popup_menus() +{ + // create popup menus for object and part + create_object_popupmenu(&m_menu_object); + create_part_popupmenu(&m_menu_part); + create_sla_object_popupmenu(&m_menu_sla_object); + create_instance_popupmenu(&m_menu_instance); +} + void ObjectList::set_tooltip_for_item(const wxPoint& pt) { wxDataViewItem item; @@ -310,7 +311,7 @@ void ObjectList::update_extruder_in_config(const wxDataViewItem& item) wxGetApp().plater()->update(); } -void ObjectList::update_name_in_model(const wxDataViewItem& item) +void ObjectList::update_name_in_model(const wxDataViewItem& item) const { const int obj_idx = m_objects_model->GetObjectIdByItem(item); if (obj_idx < 0) return; @@ -421,9 +422,6 @@ void ObjectList::show_context_menu() if (multiple_selection() && selected_instances_of_same_object()) { wxGetApp().plater()->PopupMenu(&m_menu_instance); - - wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { - evt.Enable(can_split_instances()); }, m_menu_item_split_instances->GetId()); return; } @@ -442,12 +440,6 @@ void ObjectList::show_context_menu() append_menu_item_settings(menu); wxGetApp().plater()->PopupMenu(menu); - - wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { - evt.Enable(is_splittable()); }, m_menu_item_split->GetId()); - - wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { - evt.Enable(is_splittable()); }, m_menu_item_split_part->GetId()); } } @@ -755,10 +747,8 @@ void ObjectList::get_settings_choice(const wxString& category_name) const ConfigOption* option = from_config.option(opt_key); if (!option) { // if current option doesn't exist in prints.get_edited_preset(), - // get it from m_default_config - if (m_default_config) delete m_default_config; - m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(false)); - option = m_default_config->option(opt_key); + // get it from default config values + option = DynamicPrintConfig::new_from_defaults_keys({ opt_key })->option(opt_key); } m_config->set_key_value(opt_key, option->clone()); } @@ -782,10 +772,8 @@ void ObjectList::get_freq_settings_choice(const wxString& bundle_name) const ConfigOption* option = from_config.option(opt_key); if (!option) { // if current option doesn't exist in prints.get_edited_preset(), - // get it from m_default_config - if (m_default_config) delete m_default_config; - m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(false)); - option = m_default_config->option(opt_key); + // get it from default config values + option = DynamicPrintConfig::new_from_defaults_keys({ opt_key })->option(opt_key); } m_config->set_key_value(opt_key, option->clone()); } @@ -964,8 +952,30 @@ wxMenuItem* ObjectList::append_menu_item_instance_to_object(wxMenu* menu) [this](wxCommandEvent&) { split_instances(); }, "", menu); } +void ObjectList::append_menu_item_rename(wxMenu* menu) +{ + append_menu_item(menu, wxID_ANY, _(L("Rename")), "", + [this](wxCommandEvent&) { rename_item(); }, "", menu); + menu->AppendSeparator(); +} + +void ObjectList::append_menu_item_fix_through_netfabb(wxMenu* menu) +{ + if (!is_windows10()) + return; + append_menu_item(menu, wxID_ANY, _(L("Fix through the Netfabb")), "", + [this](wxCommandEvent&) { fix_through_netfabb(); }, "", menu); + menu->AppendSeparator(); +} + void ObjectList::create_object_popupmenu(wxMenu *menu) { +#ifdef __WXOSX__ + append_menu_item_rename(menu); +#endif // __WXOSX__ + + append_menu_item_fix_through_netfabb(menu); + // Split object to parts m_menu_item_split = append_menu_item_split(menu); menu->AppendSeparator(); @@ -973,16 +983,30 @@ void ObjectList::create_object_popupmenu(wxMenu *menu) // rest of a object_menu will be added later in: // - append_menu_items_add_volume() -> for "Add (volumes)" // - append_menu_item_settings() -> for "Add (settings)" + + wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { + evt.Enable(is_splittable()); }, m_menu_item_split->GetId()); } void ObjectList::create_sla_object_popupmenu(wxMenu *menu) { +#ifdef __WXOSX__ + append_menu_item_rename(menu); +#endif // __WXOSX__ + + append_menu_item_fix_through_netfabb(menu); // rest of a object_sla_menu will be added later in: // - append_menu_item_settings() -> for "Add (settings)" } void ObjectList::create_part_popupmenu(wxMenu *menu) { +#ifdef __WXOSX__ + append_menu_item_rename(menu); +#endif // __WXOSX__ + + append_menu_item_fix_through_netfabb(menu); + m_menu_item_split_part = append_menu_item_split(menu); // Append change part type @@ -991,11 +1015,17 @@ void ObjectList::create_part_popupmenu(wxMenu *menu) // rest of a object_sla_menu will be added later in: // - append_menu_item_settings() -> for "Add (settings)" + + wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { + evt.Enable(is_splittable()); }, m_menu_item_split_part->GetId()); } void ObjectList::create_instance_popupmenu(wxMenu*menu) { m_menu_item_split_instances = append_menu_item_instance_to_object(menu); + + wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { + evt.Enable(can_split_instances()); }, m_menu_item_split_instances->GetId()); } wxMenu* ObjectList::create_settings_popupmenu(wxMenu *parent_menu) @@ -2052,6 +2082,66 @@ void ObjectList::split_instances() instances_to_separated_object(obj_idx, inst_idxs); } +void ObjectList::rename_item() +{ + const wxDataViewItem item = GetSelection(); + if (!item || !(m_objects_model->GetItemType(item) & (itVolume | itObject))) + return ; + + const wxString new_name = wxGetTextFromUser(_(L("Enter new name"))+":", _(L("Renaming")), + m_objects_model->GetName(item), this); + + if (new_name.IsEmpty()) + return; + + bool is_unusable_symbol = false; + std::string chosen_name = Slic3r::normalize_utf8_nfc(new_name.ToUTF8()); + const char* unusable_symbols = "<>:/\\|?*\""; + for (size_t i = 0; i < std::strlen(unusable_symbols); i++) { + if (chosen_name.find_first_of(unusable_symbols[i]) != std::string::npos) { + is_unusable_symbol = true; + } + } + + if (is_unusable_symbol) { + show_error(this, _(L("The supplied name is not valid;")) + "\n" + + _(L("the following characters are not allowed:")) + " <>:/\\|?*\""); + return; + } + + // The icon can't be edited so get its old value and reuse it. + wxVariant valueOld; + m_objects_model->GetValue(valueOld, item, 0); + + PrusaDataViewBitmapText bmpText; + bmpText << valueOld; + + // But replace the text with the value entered by user. + bmpText.SetText(new_name); + + wxVariant value; + value << bmpText; + m_objects_model->SetValue(value, item, 0); + m_objects_model->ItemChanged(item); + + update_name_in_model(item); +} + +void ObjectList::fix_through_netfabb() const +{ + const wxDataViewItem item = GetSelection(); + if (!item) + return; + + ItemType type = m_objects_model->GetItemType(item); + + if (type & itObject) + wxGetApp().plater()->fix_through_netfabb(m_objects_model->GetIdByItem(item)); + else if (type & itVolume) + wxGetApp().plater()->fix_through_netfabb(m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item)), + m_objects_model->GetVolumeIdByItem(item)); +} + void ObjectList::ItemValueChanged(wxDataViewEvent &event) { if (event.GetColumn() == 0) diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 93a3ba60f..e572bec82 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -97,9 +97,6 @@ class ObjectList : public wxDataViewCtrl } m_dragged_data; wxBoxSizer *m_sizer {nullptr}; - - DynamicPrintConfig *m_default_config {nullptr}; - wxWindow *m_parent {nullptr}; wxBitmap m_bmp_modifiermesh; @@ -153,6 +150,7 @@ public: void create_objects_ctrl(); + void create_popup_menus(); wxDataViewColumn* create_objects_list_extruder_column(int extruders_count); void update_objects_list_extruder_column(int extruders_count); // show/hide "Extruder" column for Objects List @@ -160,7 +158,7 @@ public: // update extruder in current config void update_extruder_in_config(const wxDataViewItem& item); // update changed name in the object model - void update_name_in_model(const wxDataViewItem& item); + void update_name_in_model(const wxDataViewItem& item) const; void update_extruder_values_for_items(const int max_extruder); void init_icons(); @@ -181,6 +179,8 @@ public: wxMenuItem* append_menu_item_settings(wxMenu* menu); wxMenuItem* append_menu_item_change_type(wxMenu* menu); wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu); + void append_menu_item_rename(wxMenu* menu); + void append_menu_item_fix_through_netfabb(wxMenu* menu); void create_object_popupmenu(wxMenu *menu); void create_sla_object_popupmenu(wxMenu*menu); void create_part_popupmenu(wxMenu*menu); @@ -262,7 +262,8 @@ public: void instances_to_separated_object(const int obj_idx, const std::set& inst_idx); void split_instances(); - + void rename_item(); + void fix_through_netfabb() const; private: void OnChar(wxKeyEvent& event); void OnContextMenu(wxDataViewEvent &event); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 53ca52cb6..b594d0fef 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -558,6 +558,7 @@ void Preview::create_double_slider() m_gcode_preview_data->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)type; m_preferred_color_mode = "feature"; } + reload_print(); }); } @@ -728,10 +729,22 @@ void Preview::load_print_as_fff() m_preferred_color_mode = "tool_or_feature"; } + bool gcode_preview_data_valid = print->is_step_done(psGCodeExport) && ! m_gcode_preview_data->empty(); // Collect colors per extruder. std::vector colors; - bool gcode_preview_data_valid = print->is_step_done(psGCodeExport) && ! m_gcode_preview_data->empty(); - if (gcode_preview_data_valid || (m_gcode_preview_data->extrusion.view_type == GCodePreviewData::Extrusion::Tool)) + std::vector color_print_values = {}; + // set color print values, if it si selected "ColorPrint" view type + if (m_gcode_preview_data->extrusion.view_type == GCodePreviewData::Extrusion::ColorPrint) + { + colors = GCodePreviewData::ColorPrintColors(); + if (! gcode_preview_data_valid) { + //FIXME accessing full_config() is pretty expensive. + // Only initialize color_print_values for the initial preview, not for the full preview where the color_print_values is extracted from the G-code. + const auto& config = wxGetApp().preset_bundle->project_config; + color_print_values = config.option("colorprint_heights")->values; + } + } + else if (gcode_preview_data_valid || (m_gcode_preview_data->extrusion.view_type == GCodePreviewData::Extrusion::Tool) ) { const ConfigOptionStrings* extruders_opt = dynamic_cast(m_config->option("extruder_colour")); const ConfigOptionStrings* filamemts_opt = dynamic_cast(m_config->option("filament_colour")); @@ -748,8 +761,9 @@ void Preview::load_print_as_fff() color = "#FFFFFF"; } - colors.push_back(color); + colors.emplace_back(color); } + color_print_values.clear(); } if (IsShown()) @@ -759,7 +773,7 @@ void Preview::load_print_as_fff() m_canvas->load_gcode_preview(*m_gcode_preview_data, colors); else // Load the initial preview based on slices, not the final G-code. - m_canvas->load_preview(colors); + m_canvas->load_preview(colors, color_print_values); show_hide_ui_elements(gcode_preview_data_valid ? "full" : "simple"); // recalculates zs and update sliders accordingly std::vector zs = m_canvas->get_current_print_zs(true); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 2df3429fe..947dd59bd 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -22,6 +22,7 @@ #include "AppConfig.hpp" #include "PrintHostDialogs.hpp" #include "wxExtensions.hpp" +#include "GUI_ObjectList.hpp" #include "I18N.hpp" #include @@ -132,6 +133,8 @@ void MainFrame::init_tabpanel() wxGetApp().plater_ = m_plater; m_tabpanel->AddPage(m_plater, _(L("Plater"))); + wxGetApp().obj_list()->create_popup_menus(); + // The following event is emited by Tab implementation on config value change. Bind(EVT_TAB_VALUE_CHANGED, &MainFrame::on_value_changed, this); @@ -236,11 +239,11 @@ void MainFrame::init_menubar() // File menu wxMenu* fileMenu = new wxMenu; { - wxMenuItem* item_open = append_menu_item(fileMenu, wxID_ANY, _(L("&Open")) + dots + "\tCtrl+O", _(L("Open a project file")), + wxMenuItem* item_open = append_menu_item(fileMenu, wxID_ANY, _(L("&Open Project")) + dots + "\tCtrl+O", _(L("Open a project file")), [this](wxCommandEvent&) { if (m_plater) m_plater->load_project(); }, "brick_add.png"); - wxMenuItem* item_save = append_menu_item(fileMenu, wxID_ANY, _(L("&Save")) + "\tCtrl+S", _(L("Save current project file")), + wxMenuItem* item_save = append_menu_item(fileMenu, wxID_ANY, _(L("&Save Project")) + "\tCtrl+S", _(L("Save current project file")), [this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(into_path(m_plater->get_project_filename())); }, "disk.png"); - wxMenuItem* item_save_as = append_menu_item(fileMenu, wxID_ANY, _(L("Save &as")) + dots + "\tCtrl+Alt+S", _(L("Save current project file as")), + wxMenuItem* item_save_as = append_menu_item(fileMenu, wxID_ANY, _(L("Save Project &as")) + dots + "\tCtrl+Alt+S", _(L("Save current project file as")), [this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(); }, "disk.png"); fileMenu->AppendSeparator(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 42e404106..4902cf1c9 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1031,7 +1031,7 @@ struct Plater::priv void update_restart_background_process(bool force_scene_update, bool force_preview_update); void export_gcode(fs::path output_path, PrintHostJob upload_job); void reload_from_disk(); - void fix_through_netfabb(const int obj_idx); + void fix_through_netfabb(const int obj_idx, const int vol_idx = -1); void set_current_panel(wxPanel* panel); @@ -1717,6 +1717,8 @@ void Plater::priv::reset() object_list_changed(); update(); + // 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); auto& config = wxGetApp().preset_bundle->project_config; config.option("colorprint_heights")->values.clear(); @@ -2104,7 +2106,7 @@ void Plater::priv::reload_from_disk() remove(obj_orig_idx); } -void Plater::priv::fix_through_netfabb(const int obj_idx) +void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/) { if (obj_idx < 0) return; @@ -2438,6 +2440,8 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/ } menu->AppendSeparator(); + sidebar->obj_list()->append_menu_item_fix_through_netfabb(menu); + wxMenu* mirror_menu = new wxMenu(); if (mirror_menu == nullptr) return false; @@ -3148,7 +3152,7 @@ void Plater::changed_object(int obj_idx) this->p->schedule_background_process(); } -void Plater::fix_through_netfabb(const int obj_idx) { p->fix_through_netfabb(obj_idx); } +void Plater::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/) { p->fix_through_netfabb(obj_idx, vol_idx); } void Plater::update_object_menu() { p->update_object_menu(); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 7b19d6f31..09b7348d5 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -147,7 +147,7 @@ public: void export_3mf(const boost::filesystem::path& output_path = boost::filesystem::path()); void reslice(); void changed_object(int obj_idx); - void fix_through_netfabb(const int obj_idx); + void fix_through_netfabb(const int obj_idx, const int vol_idx = -1); void send_gcode(); void on_extruders_change(int extruders_count); diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index d4ee9cf5f..ef1caf035 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -323,7 +323,10 @@ const std::vector& Preset::print_options() "seam_position", "external_perimeters_first", "fill_density", "fill_pattern", "external_fill_pattern", "infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle", "solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first", "max_print_speed", - "max_volumetric_speed", "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative", + "max_volumetric_speed", +#ifdef HAS_PRESSURE_EQUALIZER + "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative", +#endif /* HAS_PRESSURE_EQUALIZER */ "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "infill_speed", "solid_infill_speed", "top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed", "bridge_speed", "gap_fill_speed", "travel_speed", "first_layer_speed", "perimeter_acceleration", "infill_acceleration", @@ -531,6 +534,9 @@ void PresetCollection::load_presets(const std::string &dir_path, const std::stri boost::filesystem::path dir = boost::filesystem::canonical(boost::filesystem::path(dir_path) / subdir).make_preferred(); m_dir_path = dir.string(); std::string errors_cummulative; + // Store the loaded presets into a new vector, otherwise the binary search for already existing presets would be broken. + // (see the "Preset already present, not loading" message). + std::deque presets_loaded; for (auto &dir_entry : boost::filesystem::directory_iterator(dir)) if (boost::filesystem::is_regular_file(dir_entry.status()) && boost::algorithm::iends_with(dir_entry.path().filename().string(), ".ini") && // Ignore system and hidden files, which may be created by the DropBox synchronisation process. @@ -568,12 +574,13 @@ void PresetCollection::load_presets(const std::string &dir_path, const std::stri } catch (const std::runtime_error &err) { throw std::runtime_error(std::string("Failed loading the preset file: ") + preset.file + "\n\tReason: " + err.what()); } - m_presets.emplace_back(preset); + presets_loaded.emplace_back(preset); } catch (const std::runtime_error &err) { errors_cummulative += err.what(); errors_cummulative += "\n"; } } + m_presets.insert(m_presets.end(), std::make_move_iterator(presets_loaded.begin()), std::make_move_iterator(presets_loaded.end())); std::sort(m_presets.begin() + m_num_default_presets, m_presets.end()); this->select_preset(first_visible_idx()); if (! errors_cummulative.empty()) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 79952f184..3f76b4f78 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1028,8 +1028,10 @@ void TabPrint::build() optgroup = page->new_optgroup(_(L("Autospeed (advanced)"))); optgroup->append_single_option_line("max_print_speed"); optgroup->append_single_option_line("max_volumetric_speed"); +#ifdef HAS_PRESSURE_EQUALIZER optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_positive"); optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_negative"); +#endif /* HAS_PRESSURE_EQUALIZER */ page = add_options_page(_(L("Multiple Extruders")), "funnel.png"); optgroup = page->new_optgroup(_(L("Extruders"))); @@ -1587,11 +1589,11 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup) auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(btn); - btn->Bind(wxEVT_BUTTON, [this, parent, optgroup](wxCommandEvent e) { + btn->Bind(wxEVT_BUTTON, [this, parent, optgroup](wxCommandEvent &e) { BonjourDialog dialog(parent); if (dialog.show_and_lookup()) { optgroup->set_value("print_host", std::move(dialog.get_selected()), true); - // FIXME: emit killfocus on the edit widget + optgroup->get_field("print_host")->field_changed(); } }); @@ -1605,7 +1607,7 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup) auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(btn); - btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent e) { + btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) { std::unique_ptr host(PrintHost::get_print_host(m_config)); if (! host) { const auto text = wxString::Format("%s", @@ -1646,6 +1648,7 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup) wxFileDialog openFileDialog(this, _(L("Open CA certificate file")), "", "", filemasks, wxFD_OPEN | wxFD_FILE_MUST_EXIST); if (openFileDialog.ShowModal() != wxID_CANCEL) { optgroup->set_value("printhost_cafile", std::move(openFileDialog.GetPath()), true); + optgroup->get_field("printhost_cafile")->field_changed(); } }); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 827dcc696..d24db63ea 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -1867,8 +1867,10 @@ void PrusaDoubleSlider::draw_colored_band(wxDC& dc) return; } - const std::vector& clr_bytes = Slic3r::GCodePreviewData::Range::Default_Colors[0].as_bytes(); - wxColour clr = wxColour(clr_bytes[0], clr_bytes[1], clr_bytes[2], clr_bytes[3]); + const std::vector& colors = Slic3r::GCodePreviewData::ColorPrintColors(); + const size_t colors_cnt = colors.size(); + + wxColour clr(colors[0]); dc.SetPen(clr); dc.SetBrush(clr); dc.DrawRectangle(main_band); @@ -1876,15 +1878,13 @@ void PrusaDoubleSlider::draw_colored_band(wxDC& dc) int i = 1; for (auto tick : m_ticks) { - if (i == Slic3r::GCodePreviewData::Range::Colors_Count) + if (i == colors_cnt) i = 0; const wxCoord pos = get_position_from_value(tick); is_horizontal() ? main_band.SetLeft(SLIDER_MARGIN + pos) : main_band.SetBottom(pos-1); - const std::vector& clr_b = Slic3r::GCodePreviewData::Range::Default_Colors[i].as_bytes(); - - clr = wxColour(clr_b[0], clr_b[1], clr_b[2], clr_b[3]); + clr = wxColour(colors[i]); dc.SetPen(clr); dc.SetBrush(clr); dc.DrawRectangle(main_band);