From 447e58254d147e8ad8edb2ab95423b6eb9f670d8 Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Mon, 4 Apr 2022 09:57:19 +0200 Subject: [PATCH] Fix 3mf trmat - wrong reload --- src/libslic3r/Format/3mf.cpp | 186 +++++++++++++----------- src/libslic3r/TextConfiguration.hpp | 7 + src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp | 73 +++++++++- src/slic3r/Utils/RaycastManager.hpp | 11 ++ 4 files changed, 187 insertions(+), 90 deletions(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index b8a665c044..b82d616375 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -145,9 +145,6 @@ static constexpr const char* MESH_STAT_FACETS_REMOVED = "facets_removed"; static constexpr const char* MESH_STAT_FACETS_RESERVED = "facets_reversed"; static constexpr const char* MESH_STAT_BACKWARDS_EDGES = "backwards_edges"; -// fix for unbake volume transformation -static constexpr const char *FIX_TRANSFORMATION_TAG = "fix_tr_mat"; - // Store / load of TextConfiguration static constexpr const char *TEXT_TAG = "emboss"; static constexpr const char *TEXT_DATA_ATTR = "text"; @@ -422,8 +419,6 @@ namespace Slic3r { MetadataList metadata; RepairedMeshErrors mesh_stats; std::optional text_configuration; - // fix for baked transformation matrix - std::optional fix_tr_mat; VolumeMetadata(unsigned int first_triangle_id, unsigned int last_triangle_id) : first_triangle_id(first_triangle_id) , last_triangle_id(last_triangle_id) @@ -561,7 +556,6 @@ namespace Slic3r { bool _handle_end_metadata(); bool _handle_start_text_configuration(const char** attributes, unsigned int num_attributes); - bool _handle_start_fix_transformation(const char** attributes, unsigned int num_attributes); bool _create_object_instance(int object_id, const Transform3d& transform, const bool printable, unsigned int recur_counter); @@ -1462,8 +1456,6 @@ namespace Slic3r { res = _handle_start_config_metadata(attributes, num_attributes); else if (::strcmp(TEXT_TAG, name) == 0) res = _handle_start_text_configuration(attributes, num_attributes); - else if (::strcmp(FIX_TRANSFORMATION_TAG, name) == 0) - res = _handle_start_fix_transformation(attributes, num_attributes); if (!res) _stop_xml_parser(); @@ -1853,23 +1845,6 @@ namespace Slic3r { return volume.text_configuration.has_value(); } - bool _3MF_Importer::_handle_start_fix_transformation(const char **attributes, unsigned int num_attributes) - { - IdToMetadataMap::iterator object = m_objects_metadata.find(m_curr_config.object_id); - if (object == m_objects_metadata.end()) { - add_error("Cannot assign volume mesh to a valid object"); - return false; - } - if (object->second.volumes.empty()) { - add_error("Cannot assign mesh to a valid volume"); - return false; - } - ObjectMetadata::VolumeMetadata& volume = object->second.volumes.back(); - volume.fix_tr_mat = get_transform_from_3mf_specs_string( - get_attribute_value_string(attributes, num_attributes, TRANSFORM_ATTR)); - return volume.fix_tr_mat.has_value(); - } - bool _3MF_Importer::_create_object_instance(int object_id, const Transform3d& transform, const bool printable, unsigned int recur_counter) { static const unsigned int MAX_RECURSIONS = 10; @@ -2111,11 +2086,8 @@ namespace Slic3r { // Remove the vertices, that are not referenced by any face. its_compactify_vertices(its, true); - // fix: undo baked volume rotation - if (volume_data.fix_tr_mat.has_value()) - its_transform(its, volume_data.fix_tr_mat->inverse()); - TriangleMesh triangle_mesh(std::move(its), volume_data.mesh_stats); + if (m_version == 0) { // if the 3mf was not produced by PrusaSlicer and there is only one instance, // bake the transformation into the geometry to allow the reload from disk command @@ -2153,10 +2125,22 @@ namespace Slic3r { volume->supported_facets.shrink_to_fit(); volume->seam_facets.shrink_to_fit(); volume->mmu_segmentation_facets.shrink_to_fit(); - volume->text_configuration = std::move(volume_data.text_configuration); + auto &tc = volume_data.text_configuration; + if (tc.has_value()) { + volume->text_configuration = tc; - if (volume_data.fix_tr_mat.has_value()) - volume->set_transformation(*volume_data.fix_tr_mat); + // Transformation before store to 3mf + const Transform3d &pre_trmat = *tc->fix_3mf_tr; + // Cannot use source tranformation + // When store transformed againg to 3mf it is not modified !!! + // const Transform3d &pre_trmat = volume->source.transform.get_matrix(); + + // create fix transformation + assert(tc->fix_3mf_tr.has_value()); + volume->text_configuration->fix_3mf_tr = + pre_trmat.inverse() * + volume->get_transformation().get_matrix(); + } // apply the remaining volume's metadata for (const Metadata& metadata : volume_data.metadata) { @@ -2288,7 +2272,7 @@ namespace Slic3r { public: bool save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config, bool fullpath_sources, const ThumbnailData* thumbnail_data, bool zip64); - + static void add_transformation(std::stringstream &stream, const Transform3d &tr); private: bool _save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config, const ThumbnailData* thumbnail_data); bool _add_content_types_file_to_archive(mz_zip_archive& archive); @@ -2296,8 +2280,7 @@ namespace Slic3r { bool _add_relationships_file_to_archive(mz_zip_archive& archive); bool _add_model_file_to_archive(const std::string& filename, mz_zip_archive& archive, const Model& model, IdToObjectDataMap& objects_data); bool _add_object_to_model_stream(mz_zip_writer_staged_context &context, unsigned int& object_id, ModelObject& object, BuildItemsList& build_items, VolumeToOffsetsMap& volumes_offsets); - bool _add_mesh_to_object_stream(mz_zip_writer_staged_context &context, ModelObject& object, VolumeToOffsetsMap& volumes_offsets); - void _add_transformation(std::stringstream &stream, const Transform3d &tr); + bool _add_mesh_to_object_stream(mz_zip_writer_staged_context &context, ModelObject& object, VolumeToOffsetsMap& volumes_offsets); bool _add_build_to_model_stream(std::stringstream& stream, const BuildItemsList& build_items); bool _add_layer_height_profile_file_to_archive(mz_zip_archive& archive, Model& model); bool _add_layer_config_ranges_file_to_archive(mz_zip_archive& archive, Model& model); @@ -2306,7 +2289,6 @@ namespace Slic3r { bool _add_print_config_file_to_archive(mz_zip_archive& archive, const DynamicPrintConfig &config); bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data); bool _add_custom_gcode_per_print_z_file_to_archive(mz_zip_archive& archive, Model& model, const DynamicPrintConfig* config); - void _add_fix_transformation(std::stringstream& stream, const Transform3d &transformation); }; bool _3MF_Exporter::save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config, bool fullpath_sources, const ThumbnailData* thumbnail_data, bool zip64) @@ -2736,9 +2718,8 @@ namespace Slic3r { vertices_count += (int)its.vertices.size(); const Transform3d& matrix = volume->get_matrix(); - - for (size_t i = 0; i < its.vertices.size(); ++i) { - Vec3f v = (matrix * its.vertices[i].cast()).cast(); + for (const auto& vertex: its.vertices) { + Vec3f v = (matrix * vertex.cast()).cast(); char *ptr = buf; boost::spirit::karma::generate(ptr, boost::spirit::lit(" <") << VERTEX_TAG << " x=\""); ptr = format_coordinate(v.x(), ptr); @@ -2835,7 +2816,7 @@ namespace Slic3r { return flush(true); } - void _3MF_Exporter::_add_transformation(std::stringstream &stream, const Transform3d &tr) + void _3MF_Exporter::add_transformation(std::stringstream &stream, const Transform3d &tr) { for (unsigned c = 0; c < 4; ++c) { for (unsigned r = 0; r < 3; ++r) { @@ -2857,7 +2838,7 @@ namespace Slic3r { for (const BuildItem& item : build_items) { stream << " <" << ITEM_TAG << " " << OBJECTID_ATTR << "=\"" << item.id << "\" " << TRANSFORM_ATTR << "=\""; - _add_transformation(stream, item.transform); + add_transformation(stream, item.transform); stream << "\" " << PRINTABLE_ATTR << "=\"" << item.printable << "\"/>\n"; } @@ -3126,40 +3107,43 @@ namespace Slic3r { // stores volume's type (overrides the modifier field above) add_metadata(stream, 3, MetadataType::volume, VOLUME_TYPE_KEY, ModelVolume::type_to_string(volume->type())); - // stores volume's local matrix - stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << MATRIX_KEY << "\" " << VALUE_ATTR << "=\""; - const Transform3d matrix = volume->get_matrix() * volume->source.transform.get_matrix(); - for (int r = 0; r < 4; ++r) { - for (int c = 0; c < 4; ++c) { - stream << matrix(r, c); - if (r != 3 || c != 3) - stream << " "; - } - } - stream << "\"/>\n"; + // stores volume's local matrix + stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << MATRIX_KEY << "\" " << VALUE_ATTR << "=\""; + const Transform3d matrix = volume->get_matrix() * volume->source.transform.get_matrix(); + for (int r = 0; r < 4; ++r) { + for (int c = 0; c < 4; ++c) { + stream << matrix(r, c); + if (r != 3 || c != 3) + stream << " "; + } + } + stream << "\"/>\n"; - // stores volume's source data - { - std::string input_file = xml_escape(m_fullpath_sources ? volume->source.input_file : boost::filesystem::path(volume->source.input_file).filename().string()); - std::string prefix = std::string(" <") + METADATA_TAG + " " + TYPE_ATTR + "=\"" + VOLUME_TYPE + "\" " + KEY_ATTR + "=\""; - if (! volume->source.input_file.empty()) { - stream << prefix << SOURCE_FILE_KEY << "\" " << VALUE_ATTR << "=\"" << input_file << "\"/>\n"; - stream << prefix << SOURCE_OBJECT_ID_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.object_idx << "\"/>\n"; - stream << prefix << SOURCE_VOLUME_ID_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.volume_idx << "\"/>\n"; - stream << prefix << SOURCE_OFFSET_X_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(0) << "\"/>\n"; - stream << prefix << SOURCE_OFFSET_Y_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(1) << "\"/>\n"; - stream << prefix << SOURCE_OFFSET_Z_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(2) << "\"/>\n"; - } - assert(! volume->source.is_converted_from_inches || ! volume->source.is_converted_from_meters); - if (volume->source.is_converted_from_inches) - stream << prefix << SOURCE_IN_INCHES_KEY << "\" " << VALUE_ATTR << "=\"1\"/>\n"; - else if (volume->source.is_converted_from_meters) - stream << prefix << SOURCE_IN_METERS_KEY << "\" " << VALUE_ATTR << "=\"1\"/>\n"; + if (volume->text_configuration.has_value()) { + int j = 42; + } + // stores volume's source data + { + std::string input_file = xml_escape(m_fullpath_sources ? volume->source.input_file : boost::filesystem::path(volume->source.input_file).filename().string()); + std::string prefix = std::string(" <") + METADATA_TAG + " " + TYPE_ATTR + "=\"" + VOLUME_TYPE + "\" " + KEY_ATTR + "=\""; + if (! volume->source.input_file.empty()) { + stream << prefix << SOURCE_FILE_KEY << "\" " << VALUE_ATTR << "=\"" << input_file << "\"/>\n"; + stream << prefix << SOURCE_OBJECT_ID_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.object_idx << "\"/>\n"; + stream << prefix << SOURCE_VOLUME_ID_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.volume_idx << "\"/>\n"; + stream << prefix << SOURCE_OFFSET_X_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(0) << "\"/>\n"; + stream << prefix << SOURCE_OFFSET_Y_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(1) << "\"/>\n"; + stream << prefix << SOURCE_OFFSET_Z_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(2) << "\"/>\n"; + } + assert(! volume->source.is_converted_from_inches || ! volume->source.is_converted_from_meters); + if (volume->source.is_converted_from_inches) + stream << prefix << SOURCE_IN_INCHES_KEY << "\" " << VALUE_ATTR << "=\"1\"/>\n"; + else if (volume->source.is_converted_from_meters) + stream << prefix << SOURCE_IN_METERS_KEY << "\" " << VALUE_ATTR << "=\"1\"/>\n"; #if ENABLE_RELOAD_FROM_DISK_REWORK - if (volume->source.is_from_builtin_objects) - stream << prefix << SOURCE_IS_BUILTIN_VOLUME_KEY << "\" " << VALUE_ATTR << "=\"1\"/>\n"; + if (volume->source.is_from_builtin_objects) + stream << prefix << SOURCE_IS_BUILTIN_VOLUME_KEY << "\" " << VALUE_ATTR << "=\"1\"/>\n"; #endif // ENABLE_RELOAD_FROM_DISK_REWORK - } + } // stores volume's config data for (const std::string& key : volume->config.keys()) { @@ -3169,8 +3153,38 @@ namespace Slic3r { // stores volume's text data const auto &tc = volume->text_configuration; if (tc.has_value()) { - TextConfigurationSerialization::to_xml(stream, *tc); - _add_fix_transformation(stream, volume->get_transformation().get_matrix()); + const Transform3d &actual_trmat = + volume->get_transformation().get_matrix(); + + if (!tc->fix_3mf_tr.has_value()) { + TextConfiguration tc2 = *tc; // copy + tc2.fix_3mf_tr = actual_trmat; + + // transformation after store to .3mf + Vec3d min, max; + for (const Vec3f& v: volume->mesh().its.vertices){ + Vec3d vd = actual_trmat * v.cast(); + for (size_t i = 0; i < 3; ++i) { + if (min[i] > vd[i]) min[i] = vd[i]; + if (max[i] < vd[i]) max[i] = vd[i]; + } + } + Vec3d center = max-min; + Transform3d post_trmat = Transform3d::Identity(); + post_trmat.translate(center); + + TextConfigurationSerialization::to_xml(stream, tc2); + } else { + // fix_3mf_tr is change immediatery after load + // to keep valid fix transformation + // but I need to store original transformation + // if (!tc->fix_3mf_tr->isApprox(actual_trmat, 1e-10)) + Transform3d original_trmat = + ((*tc->fix_3mf_tr) * actual_trmat.inverse()).inverse(); + // fix already stored transformation + TextConfiguration tc2 = *tc; // copy + tc2.fix_3mf_tr = original_trmat; + } } // stores mesh's statistics @@ -3252,14 +3266,6 @@ bool _3MF_Exporter::_add_custom_gcode_per_print_z_file_to_archive( mz_zip_archiv return true; } -void _3MF_Exporter::_add_fix_transformation(std::stringstream &stream, - const Transform3d &transformation) -{ - stream << " <" << FIX_TRANSFORMATION_TAG << " " << TRANSFORM_ATTR << "=\""; - _add_transformation(stream, transformation); - stream << "\" />\n"; // end TEXT_TAG -} - // Perform conversions based on the config values available. //FIXME provide a version of PrusaSlicer that stored the project file (3MF). static void handle_legacy_project_loaded(unsigned int version_project_file, DynamicPrintConfig& config) @@ -3382,6 +3388,13 @@ void TextConfigurationSerialization::to_xml(std::stringstream &stream, const Tex stream << FONT_STYLE_ATTR << "=\"" << *fp.style << "\" "; if (fp.weight.has_value()) stream << FONT_WEIGHT_ATTR << "=\"" << *fp.weight << "\" "; + + // FIX of baked transformation + assert(tc.fix_3mf_tr.has_value()); + stream << TRANSFORM_ATTR << "=\""; + _3MF_Exporter::add_transformation(stream, *tc.fix_3mf_tr); + stream << "\" "; + stream << "/>\n"; // end TEXT_TAG } @@ -3426,7 +3439,14 @@ std::optional TextConfigurationSerialization::read(const char FontItem fi{ style_name, std::move(font_descriptor), type, std::move(fp) }; std::string text = get_attribute_value_string(attributes, num_attributes, TEXT_DATA_ATTR); - return TextConfiguration{std::move(fi), std::move(text)}; + + std::optional fix_tr_mat; + std::string fix_tr_mat_str = get_attribute_value_string(attributes, num_attributes, TRANSFORM_ATTR); + if (!fix_tr_mat_str.empty()) { + fix_tr_mat = get_transform_from_3mf_specs_string(fix_tr_mat_str); + } + + return TextConfiguration{std::move(fi), std::move(text), std::move(fix_tr_mat)}; } diff --git a/src/libslic3r/TextConfiguration.hpp b/src/libslic3r/TextConfiguration.hpp index 4aea831f3e..9e44f7a0d0 100644 --- a/src/libslic3r/TextConfiguration.hpp +++ b/src/libslic3r/TextConfiguration.hpp @@ -4,6 +4,7 @@ #include #include #include +#include "Point.hpp" // Transform3d namespace Slic3r { @@ -179,6 +180,12 @@ struct TextConfiguration // Embossed text value std::string text = "None"; + // !!! Volume stored in .3mf has transformed vertices. + // (baked transformation into vertices position) + // Only place for fill this is when load from .3mf + // This is correct volume transformation + std::optional fix_3mf_tr; + // undo / redo stack recovery //template void serialize(Archive &ar){ ar(text, font_item); } }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index 9a86f0db93..4e2764a751 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -44,6 +44,7 @@ #define SHOW_WX_FONT_DESCRIPTOR // OS specific descriptor | file path --> in edit style #define SHOW_FONT_FILE_PROPERTY // ascent, descent, line gap, cache --> in advanced #define SHOW_FONT_COUNT // count of enumerated font --> in font combo box +#define SHOW_CONTAIN_3MF_FIX // when contain fix matrix --> show gray '3mf' next to close button #define SHOW_IMGUI_ATLAS #define SHOW_ICONS_TEXTURE #define SHOW_FINE_POSITION @@ -55,6 +56,7 @@ #define SHOW_WX_FONT_DESCRIPTOR #define SHOW_FONT_FILE_PROPERTY #define SHOW_FONT_COUNT +#define SHOW_CONTAIN_3MF_FIX #define ALLOW_ADD_FONT_BY_FILE #define ALLOW_ADD_FONT_BY_OS_SELECTOR #define ALLOW_REVERT_ALL_STYLES @@ -246,13 +248,23 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event) // hovered object must be actual text volume if (m_volume != act_model_volume) return false; - RaycastManager::SkipVolume skip(m_volume->id().id); + const ModelVolumePtrs &volumes = m_volume->get_object()->volumes; + std::vector allowed_volumes_id; + if (volumes.size() > 1) { + allowed_volumes_id.reserve(volumes.size() - 1); + for (auto &v : volumes) { + if (v->id() == m_volume->id()) continue; + allowed_volumes_id.emplace_back(v->id().id); + } + } + RaycastManager::AllowVolumes condition(std::move(allowed_volumes_id)); + // detect start text dragging if (mouse_event.LeftDown()) { // initialize raycasters // IMPROVE: move to job, for big scene it slows down ModelObject *act_model_object = act_model_volume->get_object(); - m_raycast_manager.actualize(act_model_object, &skip); + m_raycast_manager.actualize(act_model_object, &condition); return false; } @@ -260,7 +272,7 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event) Vec2i mouse_coord(mouse_event.GetX(), mouse_event.GetY()); Vec2d mouse_pos = mouse_coord.cast(); const Camera &camera = wxGetApp().plater()->get_camera(); - auto hit = m_raycast_manager.unproject(mouse_pos, camera, &skip); + auto hit = m_raycast_manager.unproject(mouse_pos, camera, &condition); if (!hit.has_value()) { // there is no hit // show common translation of object @@ -270,14 +282,21 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event) } if (mouse_event.Dragging()) { + TextConfiguration &tc = *m_volume->text_configuration; // hide common dragging of object m_parent.toggle_model_objects_visibility(false, m_volume->get_object(), gl_volume->instance_idx(), m_volume); // Calculate temporary position Transform3d object_trmat = m_raycast_manager.get_transformation(hit->tr_key); Transform3d trmat = Emboss::create_transformation_onto_surface(hit->position, hit->normal); - const FontProp& font_prop = m_volume->text_configuration->font_item.prop; + const FontProp& font_prop = tc.font_item.prop; Emboss::apply_transformation(font_prop, trmat); + + // fix baked transformation from .3mf store process + if (tc.fix_3mf_tr.has_value()) + trmat = trmat * (*tc.fix_3mf_tr); + + // temp is in wolrld coors m_temp_transformation = object_trmat * trmat; } else if (mouse_event.LeftUp()) { // TODO: Disable apply common transformation after draggig @@ -769,8 +788,21 @@ bool GLGizmoEmboss::process() m_update_job_cancel = std::make_shared >(false); EmbossDataUpdate data{font, create_configuration(), create_volume_name(), m_volume->id(), m_update_job_cancel}; + /* queue_job(worker, std::make_unique(std::move(data))); - + /*/ + // Run Job on main thread (blocking) + EmbossUpdateJob j(std::move(data)); + struct MyCtl:public Job::Ctl{ + void update_status(int st, const std::string &msg = "") override{}; + bool was_canceled() const override { return false; } + std::future call_on_main_thread(std::function fn) override{return std::future{};} + } ctl; + j.process(ctl); + std::exception_ptr e_ptr = nullptr; + j.finalize(false, e_ptr); + // */ + // notification is removed befor object is changed by job remove_notification_not_valid_font(); return true; @@ -862,6 +894,33 @@ void GLGizmoEmboss::draw_window() } m_imgui->disabled_end(); +#ifdef SHOW_CONTAIN_3MF_FIX + bool is_loaded_from_3mf = m_volume != nullptr && + m_volume->text_configuration.has_value() && + !m_volume->source.input_file.empty(); + if (is_loaded_from_3mf) { + ImGui::SameLine(); + m_imgui->text_colored(ImGuiWrapper::COL_GREY_DARK, m_volume->source.input_file); + } + + if (m_volume!=nullptr && + m_volume->text_configuration.has_value() && + m_volume->text_configuration->fix_3mf_tr.has_value()) { + + ImGui::SameLine(); + m_imgui->text_colored(ImGuiWrapper::COL_GREY_DARK, "3mf"); + if (ImGui::IsItemHovered()) { + Transform3d &fix = *m_volume->text_configuration->fix_3mf_tr; + std::stringstream ss; + ss << fix.matrix(); + ImGui::SetTooltip("Text configuation contain \n" + "Fix Transformation Matrix \n" + "%s\n" + "loaded from 3mf file.", + ss.str().c_str()); + } + } +#endif // SHOW_CONTAIN_3MF_FIX #ifdef SHOW_ICONS_TEXTURE auto &t = m_icons_texture; ImGui::Image((void *) t.get_id(), ImVec2(t.get_width(), t.get_height())); @@ -928,11 +987,11 @@ void GLGizmoEmboss::draw_text_input() } float imgui_size = FontManager::get_imgui_font_size(prop, *m_font_manager.get_font_file()); if (imgui_size > FontManager::max_imgui_font_size) { - append_warning(_u8L("Tall"), + append_warning(_u8L("To tall"), _u8L("Diminished font height inside text input.")); } if (imgui_size < FontManager::min_imgui_font_size) { - append_warning(_u8L("Tiny"), + append_warning(_u8L("To small"), _u8L("Enlarged font height inside text input.")); } if (!who.empty()) { diff --git a/src/slic3r/Utils/RaycastManager.hpp b/src/slic3r/Utils/RaycastManager.hpp index ba0736258d..5cc7de7629 100644 --- a/src/slic3r/Utils/RaycastManager.hpp +++ b/src/slic3r/Utils/RaycastManager.hpp @@ -86,6 +86,17 @@ public: bool skip(const size_t &model_volume_id) const override { return model_volume_id == volume_id; } }; + class AllowVolumes: public ISkip + { + std::vector allowed_id; + public: + AllowVolumes(std::vector allowed_id) : allowed_id(allowed_id) {} + bool skip(const size_t &model_volume_id) const override { + auto it = std::find(allowed_id.begin(), allowed_id.end(), model_volume_id); + return it == allowed_id.end(); + } + }; + /// /// Unproject on mesh by Mesh raycasters /// Note: Function use current camera position from wxGetApp()