From 44d31f9bf22b15eb12c6e0795af5184f21e6b1a8 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 13 Jul 2021 11:57:19 +0200 Subject: [PATCH] Follow-up of d6fdf2d5c2d7508bfa429b9d77a6f6c44988ead1 -> Automatic generation of missing thumbnails --- src/slic3r/GUI/Camera.cpp | 26 ++++----- src/slic3r/GUI/Camera.hpp | 6 +-- src/slic3r/GUI/GCodeViewer.cpp | 2 +- src/slic3r/GUI/GLCanvas3D.cpp | 58 ++++++++++---------- src/slic3r/GUI/GLCanvas3D.hpp | 14 ++--- src/slic3r/GUI/GalleryDialog.cpp | 90 ++++++++++++++++++++++++++------ src/slic3r/GUI/Plater.cpp | 17 +++--- 7 files changed, 140 insertions(+), 73 deletions(-) diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index 8271a81ba..44b0cd84a 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -25,19 +25,19 @@ std::string Camera::get_type_as_string() const { switch (m_type) { - case Unknown: return "unknown"; - case Perspective: return "perspective"; + case EType::Unknown: return "unknown"; + case EType::Perspective: return "perspective"; default: - case Ortho: return "orthographic"; + case EType::Ortho: return "orthographic"; }; } void Camera::set_type(EType type) { - if (m_type != type) { + if (m_type != type && (type == EType::Ortho || type == EType::Perspective)) { m_type = type; if (m_update_config_on_type_change_enabled) { - wxGetApp().app_config->set("use_perspective_camera", (m_type == Perspective) ? "1" : "0"); + wxGetApp().app_config->set("use_perspective_camera", (m_type == EType::Perspective) ? "1" : "0"); wxGetApp().app_config->save(); } } @@ -46,7 +46,7 @@ void Camera::set_type(EType type) void Camera::select_next_type() { unsigned char next = (unsigned char)m_type + 1; - if (next == (unsigned char)Num_types) + if (next == (unsigned char)EType::Num_types) next = 1; set_type((EType)next); @@ -95,10 +95,10 @@ double Camera::get_fov() const { switch (m_type) { - case Perspective: + case EType::Perspective: return 2.0 * Geometry::rad2deg(std::atan(1.0 / m_projection_matrix.matrix()(1, 1))); default: - case Ortho: + case EType::Ortho: return 0.0; }; } @@ -143,12 +143,12 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa switch (m_type) { default: - case Ortho: + case EType::Ortho: { m_gui_scale = 1.0; break; } - case Perspective: + case EType::Perspective: { // scale near plane to keep w and h constant on the plane at z = m_distance const double scale = m_frustrum_zs.first / m_distance; @@ -165,12 +165,12 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa switch (m_type) { default: - case Ortho: + case EType::Ortho: { glsafe(::glOrtho(-w, w, -h, h, m_frustrum_zs.first, m_frustrum_zs.second)); break; } - case Perspective: + case EType::Perspective: { glsafe(::glFrustum(-w, w, -h, h, m_frustrum_zs.first, m_frustrum_zs.second)); break; @@ -501,7 +501,7 @@ void Camera::set_default_orientation() const Vec3d camera_pos = m_target + m_distance * Vec3d(sin_theta * ::sin(phi_rad), sin_theta * ::cos(phi_rad), ::cos(theta_rad)); m_view_rotation = Eigen::AngleAxisd(theta_rad, Vec3d::UnitX()) * Eigen::AngleAxisd(phi_rad, Vec3d::UnitZ()); m_view_rotation.normalize(); - m_view_matrix.fromPositionOrientationScale(m_view_rotation * (- camera_pos), m_view_rotation, Vec3d(1., 1., 1.)); + m_view_matrix.fromPositionOrientationScale(m_view_rotation * (-camera_pos), m_view_rotation, Vec3d::Ones()); } Vec3d Camera::validate_target(const Vec3d& target) const diff --git a/src/slic3r/GUI/Camera.hpp b/src/slic3r/GUI/Camera.hpp index 1788ab545..a61eb44ec 100644 --- a/src/slic3r/GUI/Camera.hpp +++ b/src/slic3r/GUI/Camera.hpp @@ -18,7 +18,7 @@ struct Camera static double FrustrumZMargin; static double MaxFovDeg; - enum EType : unsigned char + enum class EType : unsigned char { Unknown, Ortho, @@ -29,7 +29,7 @@ struct Camera bool requires_zoom_to_bed{ false }; private: - EType m_type{ Perspective }; + EType m_type{ EType::Perspective }; bool m_update_config_on_type_change_enabled{ false }; Vec3d m_target{ Vec3d::Zero() }; float m_zenit{ 45.0f }; @@ -54,7 +54,7 @@ public: std::string get_type_as_string() const; void set_type(EType type); // valid values for type: "0" -> ortho, "1" -> perspective - void set_type(const std::string& type) { set_type((type == "1") ? Perspective : Ortho); } + void set_type(const std::string& type) { set_type((type == "1") ? EType::Perspective : EType::Ortho); } void select_next_type(); void enable_update_config_on_type_change(bool enable) { m_update_config_on_type_change_enabled = enable; } diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index b18a9a0e0..610259a8b 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2417,7 +2417,7 @@ void GCodeViewer::render_toolpaths() const const Camera& camera = wxGetApp().plater()->get_camera(); double zoom = camera.get_zoom(); const std::array& viewport = camera.get_viewport(); - float near_plane_height = camera.get_type() == Camera::Perspective ? static_cast(viewport[3]) / (2.0f * static_cast(2.0 * std::tan(0.5 * Geometry::deg2rad(camera.get_fov())))) : + float near_plane_height = camera.get_type() == Camera::EType::Perspective ? static_cast(viewport[3]) / (2.0f * static_cast(2.0 * std::tan(0.5 * Geometry::deg2rad(camera.get_fov())))) : static_cast(viewport[3]) * 0.0005; auto set_uniform_color = [](const std::array& color, GLShaderProgram& shader) { diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 8cf19a9ea..a1e9ed30a 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -21,7 +21,6 @@ #include "slic3r/GUI/GUI_Preview.hpp" #include "slic3r/GUI/OpenGLManager.hpp" #include "slic3r/GUI/3DBed.hpp" -#include "slic3r/GUI/Camera.hpp" #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/MainFrame.hpp" @@ -697,7 +696,7 @@ void GLCanvas3D::Labels::render(const std::vector& sorted_ Vec3d screen_box_center = world_to_screen * owner.world_box.center(); float x = 0.0f; float y = 0.0f; - if (camera.get_type() == Camera::Perspective) { + if (camera.get_type() == Camera::EType::Perspective) { x = (0.5f + 0.001f * 0.5f * (float)screen_box_center(0)) * viewport[2]; y = (0.5f - 0.001f * 0.5f * (float)screen_box_center(1)) * viewport[3]; } else { @@ -1589,13 +1588,18 @@ void GLCanvas3D::render() #endif // ENABLE_RENDER_STATISTICS } -void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) +void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type) +{ + render_thumbnail(thumbnail_data, w, h, thumbnail_params, m_volumes, camera_type); +} + +void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type) { switch (OpenGLManager::get_framebuffers_type()) { - case OpenGLManager::EFramebufferType::Arb: { _render_thumbnail_framebuffer(thumbnail_data, w, h, printable_only, parts_only, show_bed, transparent_background); break; } - case OpenGLManager::EFramebufferType::Ext: { _render_thumbnail_framebuffer_ext(thumbnail_data, w, h, printable_only, parts_only, show_bed, transparent_background); break; } - default: { _render_thumbnail_legacy(thumbnail_data, w, h, printable_only, parts_only, show_bed, transparent_background); break; } + case OpenGLManager::EFramebufferType::Arb: { _render_thumbnail_framebuffer(thumbnail_data, w, h, thumbnail_params, volumes, camera_type); break; } + case OpenGLManager::EFramebufferType::Ext: { _render_thumbnail_framebuffer_ext(thumbnail_data, w, h, thumbnail_params, volumes, camera_type); break; } + default: { _render_thumbnail_legacy(thumbnail_data, w, h, thumbnail_params, volumes, camera_type); break; } } } @@ -4086,7 +4090,7 @@ static void debug_output_thumbnail(const ThumbnailData& thumbnail_data) } #endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT -void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) +void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type) { auto is_visible = [](const GLVolume& v) { bool ret = v.printable; @@ -4099,9 +4103,9 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool GLVolumePtrs visible_volumes; - for (GLVolume* vol : m_volumes.volumes) { - if (!vol->is_modifier && !vol->is_wipe_tower && (!parts_only || (vol->composite_id.volume_id >= 0))) { - if (!printable_only || is_visible(*vol)) + for (GLVolume* vol : volumes.volumes) { + if (!vol->is_modifier && !vol->is_wipe_tower && (!thumbnail_params.parts_only || vol->composite_id.volume_id >= 0)) { + if (!thumbnail_params.printable_only || is_visible(*vol)) visible_volumes.emplace_back(vol); } } @@ -4109,37 +4113,37 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool if (visible_volumes.empty()) return; - BoundingBoxf3 box; + BoundingBoxf3 volumes_box; for (const GLVolume* vol : visible_volumes) { - box.merge(vol->transformed_bounding_box()); + volumes_box.merge(vol->transformed_bounding_box()); } Camera camera; - camera.set_type(Camera::Ortho); + camera.set_type(camera_type); camera.set_scene_box(scene_bounding_box()); camera.apply_viewport(0, 0, thumbnail_data.width, thumbnail_data.height); - camera.zoom_to_volumes(visible_volumes); + camera.zoom_to_box(volumes_box); camera.apply_view_matrix(); double near_z = -1.0; double far_z = -1.0; - if (show_bed) { + if (thumbnail_params.show_bed) { // extends the near and far z of the frustrum to avoid the bed being clipped // box in eye space BoundingBoxf3 t_bed_box = wxGetApp().plater()->get_bed().get_bounding_box(true).transformed(camera.get_view_matrix()); - near_z = -t_bed_box.max(2); - far_z = -t_bed_box.min(2); + near_z = -t_bed_box.max.z(); + far_z = -t_bed_box.min.z(); } - camera.apply_projection(box, near_z, far_z); + camera.apply_projection(volumes_box, near_z, far_z); GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); if (shader == nullptr) return; - if (transparent_background) + if (thumbnail_params.transparent_background) glsafe(::glClearColor(0.0f, 0.0f, 0.0f, 0.0f)); glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); @@ -4161,15 +4165,15 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool glsafe(::glDisable(GL_DEPTH_TEST)); - if (show_bed) + if (thumbnail_params.show_bed) _render_bed(!camera.is_looking_downward(), false); // restore background color - if (transparent_background) + if (thumbnail_params.transparent_background) glsafe(::glClearColor(1.0f, 1.0f, 1.0f, 1.0f)); } -void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) +void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type) { thumbnail_data.set(w, h); if (!thumbnail_data.is_valid()) @@ -4219,7 +4223,7 @@ void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, un glsafe(::glDrawBuffers(1, drawBufs)); if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) { - _render_thumbnail_internal(thumbnail_data, printable_only, parts_only, show_bed, transparent_background); + _render_thumbnail_internal(thumbnail_data, thumbnail_params, volumes, camera_type); if (multisample) { GLuint resolve_fbo; @@ -4268,7 +4272,7 @@ void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, un glsafe(::glDisable(GL_MULTISAMPLE)); } -void GLCanvas3D::_render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) +void GLCanvas3D::_render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type) { thumbnail_data.set(w, h); if (!thumbnail_data.is_valid()) @@ -4318,7 +4322,7 @@ void GLCanvas3D::_render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data glsafe(::glDrawBuffers(1, drawBufs)); if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT) { - _render_thumbnail_internal(thumbnail_data, printable_only, parts_only, show_bed, transparent_background); + _render_thumbnail_internal(thumbnail_data, thumbnail_params, volumes, camera_type); if (multisample) { GLuint resolve_fbo; @@ -4367,7 +4371,7 @@ void GLCanvas3D::_render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data glsafe(::glDisable(GL_MULTISAMPLE)); } -void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) +void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type) { // check that thumbnail size does not exceed the default framebuffer size const Size& cnv_size = get_canvas_size(); @@ -4383,7 +4387,7 @@ void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigne if (!thumbnail_data.is_valid()) return; - _render_thumbnail_internal(thumbnail_data, printable_only, parts_only, show_bed, transparent_background); + _render_thumbnail_internal(thumbnail_data, thumbnail_params, volumes, camera_type); glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data())); #if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 94630b0f7..2c2489b96 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -15,6 +15,7 @@ #include "MeshUtils.hpp" #include "libslic3r/GCode/GCodeProcessor.hpp" #include "GCodeViewer.hpp" +#include "Camera.hpp" #include "libslic3r/Slicing.hpp" @@ -37,9 +38,9 @@ class wxGLContext; namespace Slic3r { -struct Camera; class BackgroundSlicingProcess; struct ThumbnailData; +struct ThumbnailsParams; class ModelObject; class ModelInstance; class PrintObject; @@ -622,7 +623,8 @@ public: void render(); // printable_only == false -> render also non printable volumes as grayed // parts_only == false -> render also sla support and pad - void render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background); + void render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type); + void render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type); void select_all(); void deselect_all(); @@ -846,13 +848,13 @@ private: bool _render_undo_redo_stack(const bool is_undo, float pos_x); bool _render_search_list(float pos_x); bool _render_arrange_menu(float pos_x); - void _render_thumbnail_internal(ThumbnailData& thumbnail_data, bool printable_only, bool parts_only, bool show_bed, bool transparent_background); + void _render_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type); // render thumbnail using an off-screen framebuffer - void _render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background); + void _render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type); // render thumbnail using an off-screen framebuffer when GLEW_EXT_framebuffer_object is supported - void _render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background); + void _render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type); // render thumbnail using the default framebuffer - void _render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background); + void _render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type); void _update_volumes_hover_state(); diff --git a/src/slic3r/GUI/GalleryDialog.cpp b/src/slic3r/GUI/GalleryDialog.cpp index ab0b0b683..8551c5771 100644 --- a/src/slic3r/GUI/GalleryDialog.cpp +++ b/src/slic3r/GUI/GalleryDialog.cpp @@ -3,7 +3,9 @@ #include #include #include + #include +#include #include #include @@ -11,16 +13,22 @@ #include #include #include +#include #include "GUI.hpp" #include "GUI_App.hpp" #include "format.hpp" #include "wxExtensions.hpp" #include "I18N.hpp" +#include "Notebook.hpp" +#include "3DScene.hpp" +#include "GLCanvas3D.hpp" +#include "Plater.hpp" +#include "3DBed.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/AppConfig.hpp" -#include -#include "Notebook.hpp" +#include "libslic3r/Model.hpp" +#include "libslic3r/GCode/ThumbnailData.hpp" namespace Slic3r { namespace GUI { @@ -209,7 +217,7 @@ static void add_lock(wxImage& image) // add_border(image); } -static void add_def_img(wxImageList* img_list, bool is_system, std::string stl_path) +static void add_default_image(wxImageList* img_list, bool is_system, std::string stl_path) { wxBitmap bmp = create_scaled_bitmap("cog", nullptr, IMG_PX_CNT, true); @@ -243,11 +251,63 @@ static std::string get_dir_path(bool sys_dir) #endif } -static std::string name_from_path(fs::path path) +static void generate_thumbnail_from_stl(const std::string& filename) { - std::string filename = path.filename().string(); - filename.erase(filename.size() - 4); // Remove the extention suffix. - return filename; + if (!boost::algorithm::iends_with(filename, ".stl")) { + BOOST_LOG_TRIVIAL(error) << "Found invalid file type in generate_thumbnail_from_stl() [" << filename << "]"; + return; + } + + Model model; + try { + model = Model::read_from_file(filename); + } + catch (std::exception&) { + BOOST_LOG_TRIVIAL(error) << "Error loading model from " << filename << " in generate_thumbnail_from_stl()"; + return; + } + + assert(model.objects.size() == 1); + assert(model.objects[0]->volumes.size() == 1); + assert(model.objects[0]->instances.size() == 1); + + model.objects[0]->center_around_origin(false); + model.objects[0]->ensure_on_bed(false); + + const Vec3d bed_center_3d = wxGetApp().plater()->get_bed().get_bounding_box(false).center(); + const Vec2d bed_center_2d = { bed_center_3d.x(), bed_center_3d.y()}; + model.center_instances_around_point(bed_center_2d); + + GLVolumeCollection volumes; + volumes.volumes.push_back(new GLVolume()); + GLVolume* volume = volumes.volumes[0]; + volume->indexed_vertex_array.load_mesh(model.mesh()); + volume->indexed_vertex_array.finalize_geometry(true); + volume->set_instance_transformation(model.objects[0]->instances[0]->get_transformation()); + volume->set_volume_transformation(model.objects[0]->volumes[0]->get_transformation()); + + ThumbnailData thumbnail_data; + const ThumbnailsParams thumbnail_params = { {}, false, false, false, true }; + wxGetApp().plater()->canvas3D()->render_thumbnail(thumbnail_data, 256, 256, thumbnail_params, volumes, Camera::EType::Perspective); + + if (thumbnail_data.width == 0 || thumbnail_data.height == 0) + return; + + wxImage image(thumbnail_data.width, thumbnail_data.height); + image.InitAlpha(); + + for (unsigned int r = 0; r < thumbnail_data.height; ++r) { + unsigned int rr = (thumbnail_data.height - 1 - r) * thumbnail_data.width; + for (unsigned int c = 0; c < thumbnail_data.width; ++c) { + unsigned char* px = (unsigned char*)thumbnail_data.pixels.data() + 4 * (rr + c); + image.SetRGB((int)c, (int)r, px[0], px[1], px[2]); + image.SetAlpha((int)c, (int)r, px[3]); + } + } + + fs::path out_path = fs::path(filename); + out_path.replace_extension("png"); + image.SaveFile(out_path.string(), wxBITMAP_TYPE_PNG); } void GalleryDialog::load_label_icon_list() @@ -260,12 +320,14 @@ void GalleryDialog::load_label_icon_list() for (auto& dir_entry : fs::directory_iterator(dir)) if (is_stl_file(dir_entry)) { - std::string name = name_from_path(dir_entry.path()); + std::string name = dir_entry.path().stem().string(); Item item = Item{ name, sys_dir }; items.push_back(item); } }; + wxBusyCursor busy; + std::string m_sys_dir_path, m_cust_dir_path; std::vector list_items; add_files_from_gallery(list_items, true, m_sys_dir_path); @@ -282,15 +344,13 @@ void GalleryDialog::load_label_icon_list() for (const auto& item : list_items) { std::string img_name = (item.is_system ? m_sys_dir_path : m_cust_dir_path) + item.name + ext; std::string stl_name = (item.is_system ? m_sys_dir_path : m_cust_dir_path) + item.name + ".stl"; - if (!fs::exists(img_name)) { - add_def_img(m_image_list, item.is_system, stl_name); - continue; - } + if (!fs::exists(img_name)) + generate_thumbnail_from_stl(stl_name); wxImage image; if (!image.LoadFile(from_u8(img_name), wxBITMAP_TYPE_PNG) || image.GetWidth() == 0 || image.GetHeight() == 0) { - add_def_img(m_image_list, item.is_system, stl_name); + add_default_image(m_image_list, item.is_system, stl_name); continue; } image.Rescale(px_cnt, px_cnt, wxIMAGE_QUALITY_BILINEAR); @@ -435,12 +495,12 @@ bool GalleryDialog::load_files(const wxArrayString& input_files) if (!fs::exists(dest_dir / current.filename())) fs::copy_file(current, dest_dir / current.filename()); else { - std::string filename = name_from_path(current); + std::string filename = current.stem().string(); int file_idx = 0; for (auto& dir_entry : fs::directory_iterator(dest_dir)) if (is_stl_file(dir_entry)) { - std::string name = name_from_path(dir_entry.path()); + std::string name = dir_entry.path().stem().string(); if (filename == name) { if (file_idx == 0) file_idx++; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 49c0359bf..a82baf9b8 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1788,8 +1788,8 @@ struct Plater::priv bool can_replace_with_stl() const; bool can_split(bool to_objects) const; - void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background); - ThumbnailsList generate_thumbnails(const ThumbnailsParams& params); + void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type); + ThumbnailsList generate_thumbnails(const ThumbnailsParams& params, Camera::EType camera_type); void bring_instance_forward() const; @@ -1865,7 +1865,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) background_process.set_fff_print(&fff_print); background_process.set_sla_print(&sla_print); background_process.set_gcode_result(&gcode_result); - background_process.set_thumbnail_cb([this](const ThumbnailsParams& params) { return this->generate_thumbnails(params); }); + background_process.set_thumbnail_cb([this](const ThumbnailsParams& params) { return this->generate_thumbnails(params, Camera::EType::Ortho); }); background_process.set_slicing_completed_event(EVT_SLICING_COMPLETED); background_process.set_finished_event(EVT_PROCESS_COMPLETED); background_process.set_export_began_event(EVT_EXPORT_BEGAN); @@ -4074,18 +4074,18 @@ void Plater::priv::on_3dcanvas_mouse_dragging_finished(SimpleEvent&) } } -void Plater::priv::generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) +void Plater::priv::generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type) { - view3D->get_canvas3d()->render_thumbnail(data, w, h, printable_only, parts_only, show_bed, transparent_background); + view3D->get_canvas3d()->render_thumbnail(data, w, h, thumbnail_params, camera_type); } -ThumbnailsList Plater::priv::generate_thumbnails(const ThumbnailsParams& params) +ThumbnailsList Plater::priv::generate_thumbnails(const ThumbnailsParams& params, Camera::EType camera_type) { ThumbnailsList thumbnails; for (const Vec2d& size : params.sizes) { thumbnails.push_back(ThumbnailData()); Point isize(size); // round to ints - generate_thumbnail(thumbnails.back(), isize.x(), isize.y(), params.printable_only, params.parts_only, params.show_bed, params.transparent_background); + generate_thumbnail(thumbnails.back(), isize.x(), isize.y(), params, camera_type); if (!thumbnails.back().is_valid()) thumbnails.pop_back(); } @@ -5630,7 +5630,8 @@ void Plater::export_3mf(const boost::filesystem::path& output_path) wxBusyCursor wait; bool full_pathnames = wxGetApp().app_config->get("export_sources_full_pathnames") == "1"; ThumbnailData thumbnail_data; - p->generate_thumbnail(thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second, false, true, true, true); + ThumbnailsParams thumbnail_params = { {}, false, true, true, true }; + p->generate_thumbnail(thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second, thumbnail_params, Camera::EType::Ortho); #if ENABLE_PROJECT_DIRTY_STATE bool ret = Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, full_pathnames, &thumbnail_data); if (ret) {