diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp index 1ee4b0d347..c5bbccb245 100644 --- a/src/PrusaSlicer.cpp +++ b/src/PrusaSlicer.cpp @@ -72,6 +72,8 @@ int CLI::run(int argc, char **argv) { // Mark the main thread for the debugger and for runtime checks. set_current_thread_name("slic3r_main"); + // Save the thread ID of the main thread. + save_main_thread_id(); #ifdef __WXGTK__ // On Linux, wxGTK has no support for Wayland, and the app crashes on diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index 48f0d3ab20..3c3a4d18d3 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -417,12 +417,8 @@ std::string AppConfig::load() void AppConfig::save() { - { - // Returns "undefined" if the thread naming functionality is not supported by the operating system. - std::optional current_thread_name = get_current_thread_name(); - if (current_thread_name && *current_thread_name != "slic3r_main") - throw CriticalException("Calling AppConfig::save() from a worker thread!"); - } + if (! is_main_thread_active()) + throw CriticalException("Calling AppConfig::save() from a worker thread!"); // The config is first written to a file with a PID suffix and then moved // to avoid race conditions with multiple instances of Slic3r diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 3f865601a9..f766d5db8d 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2946,10 +2946,10 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de prev = p; } } else { - std::string comment; + std::string marked_comment; if (m_config.gcode_comments) { - comment = description; - comment += description_bridge; + marked_comment = description; + marked_comment += description_bridge; } double last_set_speed = new_points[0].speed * 60.0; gcode += m_writer.set_speed(last_set_speed, "", comment); @@ -2958,7 +2958,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de const ProcessedPoint& processed_point = new_points[i]; Vec2d p = this->point_to_gcode_quantized(processed_point.p); const double line_length = (p - prev).norm(); - gcode += m_writer.extrude_to_xy(p, e_per_mm * line_length, comment); + gcode += m_writer.extrude_to_xy(p, e_per_mm * line_length, marked_comment); prev = p; double new_speed = processed_point.speed * 60.0; if (last_set_speed != new_speed) { diff --git a/src/libslic3r/GCode/ExtrusionProcessor.hpp b/src/libslic3r/GCode/ExtrusionProcessor.hpp index 1525624dae..7ce7a77f69 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.hpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.hpp @@ -264,10 +264,11 @@ public: float original_speed) { size_t speed_sections_count = std::min(overlaps.values.size(), speeds.values.size()); + float speed_base = ext_perimeter_speed > 0 ? ext_perimeter_speed : original_speed; std::vector> speed_sections; for (size_t i = 0; i < speed_sections_count; i++) { float distance = path.width * (1.0 - (overlaps.get_at(i) / 100.0)); - float speed = speeds.get_at(i).percent ? (ext_perimeter_speed * speeds.get_at(i).value / 100.0) : speeds.get_at(i).value; + float speed = speeds.get_at(i).percent ? (speed_base * speeds.get_at(i).value / 100.0) : speeds.get_at(i).value; speed_sections.push_back({distance, speed}); } std::sort(speed_sections.begin(), speed_sections.end(), diff --git a/src/libslic3r/Thread.cpp b/src/libslic3r/Thread.cpp index 22d4cb4197..aa710aaefc 100644 --- a/src/libslic3r/Thread.cpp +++ b/src/libslic3r/Thread.cpp @@ -191,6 +191,26 @@ std::optional get_current_thread_name() #endif // _WIN32 +// To be called at the start of the application to save the current thread ID as the main (UI) thread ID. +static boost::thread::id g_main_thread_id; + +void save_main_thread_id() +{ + g_main_thread_id = boost::this_thread::get_id(); +} + +// Retrieve the cached main (UI) thread ID. +boost::thread::id get_main_thread_id() +{ + return g_main_thread_id; +} + +// Checks whether the main (UI) thread is active. +bool is_main_thread_active() +{ + return get_main_thread_id() == boost::this_thread::get_id(); +} + // Spawn (n - 1) worker threads on Intel TBB thread pool and name them by an index and a system thread ID. // Also it sets locale of the worker threads to "C" for the G-code generator to produce "." as a decimal separator. void name_tbb_thread_pool_threads_set_locale() diff --git a/src/libslic3r/Thread.hpp b/src/libslic3r/Thread.hpp index 252116ea79..19ad29801c 100644 --- a/src/libslic3r/Thread.hpp +++ b/src/libslic3r/Thread.hpp @@ -29,6 +29,13 @@ inline bool set_thread_name(boost::thread &thread, const std::string &thread_nam bool set_current_thread_name(const char *thread_name); inline bool set_current_thread_name(const std::string &thread_name) { return set_current_thread_name(thread_name.c_str()); } +// To be called at the start of the application to save the current thread ID as the main (UI) thread ID. +void save_main_thread_id(); +// Retrieve the cached main (UI) thread ID. +boost::thread::id get_main_thread_id(); +// Checks whether the main (UI) thread is active. +bool is_main_thread_active(); + // OSX specific: Set Quality of Service to "user initiated", so that the threads will be scheduled to high performance // cores if available. void set_current_thread_qos(); diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 185ebb743e..0a07cb6f99 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -385,8 +385,10 @@ void GLVolume::render() GLShaderProgram* shader = GUI::wxGetApp().get_current_shader(); if (shader == nullptr) return; + + const bool is_left_handed = this->is_left_handed(); - if (this->is_left_handed()) + if (is_left_handed) glsafe(::glFrontFace(GL_CW)); glsafe(::glCullFace(GL_BACK)); @@ -395,7 +397,7 @@ void GLVolume::render() else model.render(this->tverts_range); - if (this->is_left_handed()) + if (is_left_handed) glsafe(::glFrontFace(GL_CCW)); } @@ -793,6 +795,7 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab glsafe(::glDisable(GL_CULL_FACE)); for (GLVolumeWithIdAndZ& volume : to_render) { + const Transform3d& world_matrix = volume.first->world_matrix(); volume.first->set_render_color(true); // render sinking contours of non-hovered volumes @@ -814,9 +817,9 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab shader->set_uniform("print_volume.type", static_cast(m_print_volume.type)); shader->set_uniform("print_volume.xy_data", m_print_volume.data); shader->set_uniform("print_volume.z_data", m_print_volume.zs); - shader->set_uniform("volume_world_matrix", volume.first->world_matrix()); + shader->set_uniform("volume_world_matrix", world_matrix); shader->set_uniform("slope.actived", m_slope.active && !volume.first->is_modifier && !volume.first->is_wipe_tower); - shader->set_uniform("slope.volume_world_normal_matrix", static_cast(volume.first->world_matrix().matrix().block(0, 0, 3, 3).inverse().transpose().cast())); + shader->set_uniform("slope.volume_world_normal_matrix", static_cast(world_matrix.matrix().block(0, 0, 3, 3).inverse().transpose().cast())); shader->set_uniform("slope.normal_z", m_slope.normal_z); #if ENABLE_ENVIRONMENT_MAP @@ -829,7 +832,7 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab glcheck(); volume.first->model.set_color(volume.first->render_color); - const Transform3d model_matrix = volume.first->world_matrix(); + const Transform3d model_matrix = world_matrix; shader->set_uniform("view_model_matrix", view_matrix * model_matrix); shader->set_uniform("projection_matrix", projection_matrix); const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 82b6d3c951..8809624343 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -818,8 +818,11 @@ static float get_cursor_height() void GLCanvas3D::Tooltip::set_text(const std::string& text) { // If the mouse is inside an ImGUI dialog, then the tooltip is suppressed. - m_text = m_in_imgui ? std::string() : text; - m_cursor_height = get_cursor_height(); + const std::string& new_text = m_in_imgui ? std::string() : text; + if (m_text != new_text) { // To avoid calling the expensive call to get_cursor_height. + m_text = new_text; + m_cursor_height = get_cursor_height(); + } } void GLCanvas3D::Tooltip::render(const Vec2d& mouse_position, GLCanvas3D& canvas)