diff --git a/doc/How to build - Windows.md b/doc/How to build - Windows.md index c2dc31ce3..cd5227daf 100644 --- a/doc/How to build - Windows.md +++ b/doc/How to build - Windows.md @@ -125,11 +125,11 @@ intermediate files, which are not handled correctly by either `b2.exe` or possib # Noob guide (step by step) Install Visual Studio Community 2019 from -visualstudio.microsoft.com/vs/ +[visualstudio.microsoft.com/vs/](https://visualstudio.microsoft.com/vs/) Select all workload options for C++ Install git for Windows from -gitforwindows.org +[gitforwindows.org](https://gitforwindows.org/) download and run the exe accepting all defaults download PrusaSlicer-master.zip from github diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 28b28b405..d683e55b8 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -1414,6 +1414,8 @@ public: bool multiline = false; // For text input: If true, the GUI text box spans the complete page width. bool full_width = false; + // For text input: If true, the GUI formats text as code (fixed-width) + bool is_code = false; // Not editable. Currently only used for the display of the number of threads. bool readonly = false; // Height of a multiline GUI text box. diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 436a2b29f..a4fd228fc 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -1899,9 +1899,9 @@ namespace Slic3r { assert(index < geometry.custom_supports.size()); assert(index < geometry.custom_seam.size()); if (! geometry.custom_supports[index].empty()) - volume->m_supported_facets.set_triangle_from_string(i, geometry.custom_supports[index]); + volume->supported_facets.set_triangle_from_string(i, geometry.custom_supports[index]); if (! geometry.custom_seam[index].empty()) - volume->m_seam_facets.set_triangle_from_string(i, geometry.custom_seam[index]); + volume->seam_facets.set_triangle_from_string(i, geometry.custom_seam[index]); } @@ -2417,11 +2417,11 @@ namespace Slic3r { stream << "v" << j + 1 << "=\"" << its.indices[i][j] + volume_it->second.first_vertex_id << "\" "; } - std::string custom_supports_data_string = volume->m_supported_facets.get_triangle_as_string(i); + std::string custom_supports_data_string = volume->supported_facets.get_triangle_as_string(i); if (! custom_supports_data_string.empty()) stream << CUSTOM_SUPPORTS_ATTR << "=\"" << custom_supports_data_string << "\" "; - std::string custom_seam_data_string = volume->m_seam_facets.get_triangle_as_string(i); + std::string custom_seam_data_string = volume->seam_facets.get_triangle_as_string(i); if (! custom_seam_data_string.empty()) stream << CUSTOM_SEAM_ATTR << "=\"" << custom_seam_data_string << "\" "; diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index a4541eeec..2ea55e010 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -608,6 +608,7 @@ void ModelObject::assign_new_unique_ids_recursive() model_volume->assign_new_unique_ids_recursive(); for (ModelInstance *model_instance : this->instances) model_instance->assign_new_unique_ids_recursive(); + this->layer_height_profile.set_new_unique_id(); } // Clone this ModelObject including its volumes and instances, keep the IDs of the copies equal to the original. @@ -1041,8 +1042,8 @@ void ModelObject::convert_units(ModelObjectPtrs& new_objects, bool from_imperial int vol_idx = 0; for (ModelVolume* volume : volumes) { - volume->m_supported_facets.clear(); - volume->m_seam_facets.clear(); + volume->supported_facets.clear(); + volume->seam_facets.clear(); if (!volume->mesh().empty()) { TriangleMesh mesh(volume->mesh()); mesh.require_shared_vertices(); @@ -1147,8 +1148,8 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b for (ModelVolume *volume : volumes) { const auto volume_matrix = volume->get_matrix(); - volume->m_supported_facets.clear(); - volume->m_seam_facets.clear(); + volume->supported_facets.clear(); + volume->seam_facets.clear(); if (! volume->is_model_part()) { // Modifiers are not cut, but we still need to add the instance transformation @@ -1727,6 +1728,14 @@ void ModelObject::scale_to_fit(const Vec3d &size) */ } +void ModelVolume::assign_new_unique_ids_recursive() +{ + ObjectBase::set_new_unique_id(); + config.set_new_unique_id(); + supported_facets.set_new_unique_id(); + seam_facets.set_new_unique_id(); +} + void ModelVolume::rotate(double angle, Axis axis) { switch (axis) @@ -2011,7 +2020,7 @@ bool model_custom_supports_data_changed(const ModelObject& mo, const ModelObject assert(! model_volume_list_changed(mo, mo_new, ModelVolumeType::MODEL_PART)); assert(mo.volumes.size() == mo_new.volumes.size()); for (size_t i=0; im_supported_facets.timestamp_matches(mo.volumes[i]->m_supported_facets)) + if (! mo_new.volumes[i]->supported_facets.timestamp_matches(mo.volumes[i]->supported_facets)) return true; } return false; @@ -2021,7 +2030,7 @@ bool model_custom_seam_data_changed(const ModelObject& mo, const ModelObject& mo assert(! model_volume_list_changed(mo, mo_new, ModelVolumeType::MODEL_PART)); assert(mo.volumes.size() == mo_new.volumes.size()); for (size_t i=0; im_seam_facets.timestamp_matches(mo.volumes[i]->m_seam_facets)) + if (! mo_new.volumes[i]->seam_facets.timestamp_matches(mo.volumes[i]->seam_facets)) return true; } return false; diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 003c4ed0f..7786ee4d8 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -191,6 +191,9 @@ public: private: std::vector m_data; + + // to access set_new_unique_id() when copy / pasting an object + friend class ModelObject; }; // A printable object, possibly having multiple print volumes (each with its own set of parameters and materials), @@ -446,6 +449,9 @@ private: } std::map> m_data; + + // To access set_new_unique_id() when copy / pasting a ModelVolume. + friend class ModelVolume; }; // An object STL, or a modifier volume, over which a different set of parameters shall be applied. @@ -483,10 +489,10 @@ public: ModelConfigObject config; // List of mesh facets to be supported/unsupported. - FacetsAnnotation m_supported_facets; + FacetsAnnotation supported_facets; // List of seam enforcers/blockers. - FacetsAnnotation m_seam_facets; + FacetsAnnotation seam_facets; // A parent object owning this modifier volume. ModelObject* get_object() const { return this->object; } @@ -579,7 +585,7 @@ protected: // Copies IDs of both the ModelVolume and its config. explicit ModelVolume(const ModelVolume &rhs) = default; void set_model_object(ModelObject *model_object) { object = model_object; } - void assign_new_unique_ids_recursive() override { ObjectBase::set_new_unique_id(); config.set_new_unique_id(); } + void assign_new_unique_ids_recursive() override; void transform_this_mesh(const Transform3d& t, bool fix_left_handed); void transform_this_mesh(const Matrix3d& m, bool fix_left_handed); @@ -617,7 +623,7 @@ private: ObjectBase(other), name(other.name), source(other.source), m_mesh(other.m_mesh), m_convex_hull(other.m_convex_hull), config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation), - m_supported_facets(other.m_supported_facets), m_seam_facets(other.m_seam_facets) + supported_facets(other.supported_facets), seam_facets(other.seam_facets) { assert(this->id().valid()); assert(this->config.id().valid()); assert(this->id() != this->config.id()); assert(this->id() == other.id() && this->config.id() == other.config.id()); @@ -635,8 +641,8 @@ private: calculate_convex_hull(); assert(this->config.id().valid()); assert(this->config.id() != other.config.id()); assert(this->id() != this->config.id()); - m_supported_facets.clear(); - m_seam_facets.clear(); + supported_facets.clear(); + seam_facets.clear(); } ModelVolume& operator=(ModelVolume &rhs) = delete; @@ -650,8 +656,8 @@ private: template void load(Archive &ar) { bool has_convex_hull; ar(name, source, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull); - cereal::load_by_value(ar, m_supported_facets); - cereal::load_by_value(ar, m_seam_facets); + cereal::load_by_value(ar, supported_facets); + cereal::load_by_value(ar, seam_facets); cereal::load_by_value(ar, config); assert(m_mesh); if (has_convex_hull) { @@ -665,8 +671,8 @@ private: template void save(Archive &ar) const { bool has_convex_hull = m_convex_hull.get() != nullptr; ar(name, source, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull); - cereal::save_by_value(ar, m_supported_facets); - cereal::save_by_value(ar, m_seam_facets); + cereal::save_by_value(ar, supported_facets); + cereal::save_by_value(ar, seam_facets); cereal::save_by_value(ar, config); if (has_convex_hull) cereal::save_optional(ar, m_convex_hull); diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 34a3d8b23..01e46d227 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -404,10 +404,10 @@ static inline void model_volume_list_copy_configs(ModelObject &model_object_dst, // Copy the ModelVolume data. mv_dst.name = mv_src.name; mv_dst.config.assign_config(mv_src.config); - if (! mv_dst.m_supported_facets.timestamp_matches(mv_src.m_supported_facets)) - mv_dst.m_supported_facets = mv_src.m_supported_facets; - if (! mv_dst.m_seam_facets.timestamp_matches(mv_src.m_seam_facets)) - mv_dst.m_seam_facets = mv_src.m_seam_facets; + if (! mv_dst.supported_facets.timestamp_matches(mv_src.supported_facets)) + mv_dst.supported_facets = mv_src.supported_facets; + if (! mv_dst.seam_facets.timestamp_matches(mv_src.seam_facets)) + mv_dst.seam_facets = mv_src.seam_facets; //FIXME what to do with the materials? // mv_dst.m_material_id = mv_src.m_material_id; ++ i_src; diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 6f0372ef4..d08ea6161 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -2748,8 +2748,8 @@ void PrintObject::project_and_append_custom_facets( { for (const ModelVolume* mv : this->model_object()->volumes) { const indexed_triangle_set custom_facets = seam - ? mv->m_seam_facets.get_facets(*mv, type) - : mv->m_supported_facets.get_facets(*mv, type); + ? mv->seam_facets.get_facets(*mv, type) + : mv->supported_facets.get_facets(*mv, type); if (! mv->is_model_part() || custom_facets.indices.empty()) continue; diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 689cc4944..88a4525b8 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -40,7 +40,7 @@ #define ENABLE_2_3_0_ALPHA1 1 // Enable rendering of objects using environment map -#define ENABLE_ENVIRONMENT_MAP (1 && ENABLE_2_3_0_ALPHA1) +#define ENABLE_ENVIRONMENT_MAP (0 && ENABLE_2_3_0_ALPHA1) // Enable smoothing of objects normals #define ENABLE_SMOOTH_NORMALS (0 && ENABLE_2_3_0_ALPHA1) diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 5392deec9..95fd13577 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -387,7 +387,9 @@ void TextCtrl::BUILD() { const long style = m_opt.multiline ? wxTE_MULTILINE : wxTE_PROCESS_ENTER/*0*/; auto temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, style); - temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + temp->SetFont(m_opt.is_code ? + Slic3r::GUI::wxGetApp().code_font(): + Slic3r::GUI::wxGetApp().normal_font()); if (! m_opt.multiline && !wxOSX) // Only disable background refresh for single line input fields, as they are completely painted over by the edit control. diff --git a/src/slic3r/GUI/FirmwareDialog.cpp b/src/slic3r/GUI/FirmwareDialog.cpp index 5441c84ed..879e7fe34 100644 --- a/src/slic3r/GUI/FirmwareDialog.cpp +++ b/src/slic3r/GUI/FirmwareDialog.cpp @@ -790,7 +790,7 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) : SetFont(font); wxFont status_font = font;//wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); status_font.MakeBold(); - wxFont mono_font(wxFontInfo().Family(wxFONTFAMILY_TELETYPE)); + wxFont mono_font = GUI::wxGetApp().code_font(); mono_font.MakeSmaller(); // Create GUI components and layout diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 34d2331b6..3b78a6223 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -325,6 +325,7 @@ bool GCodeViewer::init() set_toolpath_move_type_visible(EMoveType::Extrude, true); m_sequential_view.marker.init(); + m_sequential_view.skip_invisible_moves = true; std::array point_sizes; ::glGetIntegerv(GL_ALIASED_POINT_SIZE_RANGE, point_sizes.data()); @@ -515,18 +516,20 @@ void GCodeViewer::update_sequential_view_current(unsigned int first, unsigned in unsigned int new_first = first; unsigned int new_last = last; - while (!is_visible(new_first)) { - if (first_diff > 0) - ++new_first; - else - --new_first; - } + if (m_sequential_view.skip_invisible_moves) { + while (!is_visible(new_first)) { + if (first_diff > 0) + ++new_first; + else + --new_first; + } - while (!is_visible(new_last)) { - if (last_diff > 0) - ++new_last; - else - --new_last; + while (!is_visible(new_last)) { + if (last_diff > 0) + ++new_last; + else + --new_last; + } } m_sequential_view.current.first = new_first; diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 2953346a2..783020925 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -342,7 +342,7 @@ public: Vec3f m_world_position; Transform3f m_world_transform; float m_z_offset{ 0.5f }; - std::array m_color{ 1.0f, 1.0f, 1.0f, 1.0f }; + std::array m_color{ 1.0f, 1.0f, 1.0f, 0.5f }; bool m_visible{ false }; public: @@ -365,6 +365,7 @@ public: size_t last{ 0 }; }; + bool skip_invisible_moves{ false }; Endpoints endpoints; Endpoints current; Endpoints last_current; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 6e6778883..0eac01749 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -979,6 +979,11 @@ void GUI_App::init_fonts() m_small_font.SetPointSize(11); m_bold_font.SetPointSize(13); #endif /*__WXMAC__*/ + + // wxSYS_OEM_FIXED_FONT and wxSYS_ANSI_FIXED_FONT use the same as + // DEFAULT in wxGtk. Use the TELETYPE family as a work-around + m_code_font = wxFont(wxFontInfo().Family(wxFONTFAMILY_TELETYPE)); + m_code_font.SetPointSize(m_normal_font.GetPointSize()); } void GUI_App::update_fonts(const MainFrame *main_frame) @@ -994,6 +999,7 @@ void GUI_App::update_fonts(const MainFrame *main_frame) m_small_font = m_normal_font; m_bold_font = main_frame->normal_font().Bold(); m_em_unit = main_frame->em_unit(); + m_code_font.SetPointSize(m_normal_font.GetPointSize()); } void GUI_App::set_label_clr_modified(const wxColour& clr) { diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 74496ca54..4e95e854f 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -121,6 +121,7 @@ private: wxFont m_small_font; wxFont m_bold_font; wxFont m_normal_font; + wxFont m_code_font; int m_em_unit; // width of a "m"-symbol in pixels for current system font // Note: for 100% Scale m_em_unit = 10 -> it's a good enough coefficient for a size setting of controls @@ -212,6 +213,7 @@ public: const wxFont& small_font() { return m_small_font; } const wxFont& bold_font() { return m_bold_font; } const wxFont& normal_font() { return m_normal_font; } + const wxFont& code_font() { return m_code_font; } int em_unit() const { return m_em_unit; } wxSize get_min_size() const; float toolbar_icon_scale(const bool is_limited = false) const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index f11e6041a..3384804b4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -50,6 +50,8 @@ bool GLGizmoFdmSupports::on_init() m_desc["remove_caption"] = _L("Shift + Left mouse button") + ": "; m_desc["remove"] = _L("Remove selection"); m_desc["remove_all"] = _L("Remove all selection"); + m_desc["circle"] = _L("Circle"); + m_desc["sphere"] = _L("Sphere"); return true; } @@ -86,18 +88,15 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l if (! m_setting_angle) { m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); - std::vector cursor_types; - cursor_types.push_back(_L("Circle").ToUTF8().data()); - cursor_types.push_back(_L("Sphere").ToUTF8().data()); - // First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that: const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x, m_imgui->calc_text_size(m_desc.at("reset_direction")).x) + m_imgui->scaled(1.5f); const float cursor_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f); - const float cursor_type_combo_left = m_imgui->calc_text_size(m_desc.at("cursor_type")).x + m_imgui->scaled(1.f); - const float cursor_type_combo_width = std::max(m_imgui->calc_text_size(wxString::FromUTF8(cursor_types[0].c_str())).x, - m_imgui->calc_text_size(wxString::FromUTF8(cursor_types[1].c_str())).x) + const float cursor_type_radio_left = m_imgui->calc_text_size(m_desc.at("cursor_type")).x + m_imgui->scaled(1.f); + const float cursor_type_radio_width1 = m_imgui->calc_text_size(m_desc["circle"]).x + + m_imgui->scaled(2.5f); + const float cursor_type_radio_width2 = m_imgui->calc_text_size(m_desc["sphere"]).x + m_imgui->scaled(2.5f); const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f); const float minimal_slider_width = m_imgui->scaled(4.f); @@ -114,7 +113,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l float window_width = minimal_slider_width + std::max(cursor_slider_left, clipping_slider_left); window_width = std::max(window_width, total_text_max); window_width = std::max(window_width, button_width); - window_width = std::max(window_width, cursor_type_combo_left + cursor_type_combo_width); + window_width = std::max(window_width, cursor_type_radio_left + cursor_type_radio_width1 + cursor_type_radio_width2); auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) { m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, caption); @@ -166,20 +165,41 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("cursor_type")); - ImGui::SameLine(window_width - cursor_type_combo_width - m_imgui->scaled(0.5f)); - ImGui::PushItemWidth(cursor_type_combo_width); - int selection = int(m_cursor_type); - m_imgui->combo("", cursor_types, selection); - m_cursor_type = TriangleSelector::CursorType(selection); + ImGui::SameLine(cursor_type_radio_left + m_imgui->scaled(0.f)); + ImGui::PushItemWidth(cursor_type_radio_width1); + + bool sphere_sel = m_cursor_type == TriangleSelector::CursorType::SPHERE; + if (m_imgui->radio_button(m_desc["sphere"], sphere_sel)) + sphere_sel = true; + if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(max_tooltip_width); - ImGui::TextUnformatted(_L("Sphere paints all facets inside, regardless of their orientation.\n\n" - "Circle ignores facets facing away from the camera.").ToUTF8().data()); + ImGui::TextUnformatted(_L("Paints all facets inside, regardless of their orientation.").ToUTF8().data()); ImGui::PopTextWrapPos(); ImGui::EndTooltip(); } + ImGui::SameLine(cursor_type_radio_left + cursor_type_radio_width2 + m_imgui->scaled(0.f)); + ImGui::PushItemWidth(cursor_type_radio_width2); + + if (m_imgui->radio_button(m_desc["circle"], ! sphere_sel)) + sphere_sel = false; + + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(max_tooltip_width); + ImGui::TextUnformatted(_L("Ignores facets facing away from the camera.").ToUTF8().data()); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + + m_cursor_type = sphere_sel + ? TriangleSelector::CursorType::SPHERE + : TriangleSelector::CursorType::CIRCLE; + + + ImGui::Separator(); if (m_c->object_clipper()->get_position() == 0.f) { @@ -287,7 +307,7 @@ void GLGizmoFdmSupports::update_model_object() const if (! mv->is_model_part()) continue; ++idx; - updated |= mv->m_supported_facets.set(*m_triangle_selectors[idx].get()); + updated |= mv->supported_facets.set(*m_triangle_selectors[idx].get()); } if (updated) @@ -314,7 +334,7 @@ void GLGizmoFdmSupports::update_from_model_object() const TriangleMesh* mesh = &mv->mesh(); m_triangle_selectors.emplace_back(std::make_unique(*mesh)); - m_triangle_selectors.back()->deserialize(mv->m_supported_facets.get_data()); + m_triangle_selectors.back()->deserialize(mv->supported_facets.get_data()); } } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp index ed4f2809c..f76cb42b6 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp @@ -33,6 +33,8 @@ bool GLGizmoSeam::on_init() m_desc["remove_caption"] = _L("Shift + Left mouse button") + ": "; m_desc["remove"] = _L("Remove selection"); m_desc["remove_all"] = _L("Remove all selection"); + m_desc["circle"] = _L("Circle"); + m_desc["sphere"] = _L("Sphere"); return true; } @@ -71,12 +73,6 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) const float approx_height = m_imgui->scaled(14.0f); y = std::min(y, bottom_limit - approx_height); m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); - - std::vector cursor_types; - cursor_types.push_back(_L("Circle").ToUTF8().data()); - cursor_types.push_back(_L("Sphere").ToUTF8().data()); - - m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); // First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that: @@ -84,9 +80,10 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) m_imgui->calc_text_size(m_desc.at("reset_direction")).x) + m_imgui->scaled(1.5f); const float cursor_size_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f); - const float cursor_type_combo_left = m_imgui->calc_text_size(m_desc.at("cursor_type")).x + m_imgui->scaled(1.f); - const float cursor_type_combo_width = std::max(m_imgui->calc_text_size(wxString::FromUTF8(cursor_types[0].c_str())).x, - m_imgui->calc_text_size(wxString::FromUTF8(cursor_types[1].c_str())).x) + const float cursor_type_radio_left = m_imgui->calc_text_size(m_desc.at("cursor_type")).x + m_imgui->scaled(1.f); + const float cursor_type_radio_width1 = m_imgui->calc_text_size(m_desc["circle"]).x + + m_imgui->scaled(2.5f); + const float cursor_type_radio_width2 = m_imgui->calc_text_size(m_desc["sphere"]).x + m_imgui->scaled(2.5f); const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f); const float minimal_slider_width = m_imgui->scaled(4.f); @@ -103,7 +100,7 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) float window_width = minimal_slider_width + std::max(cursor_size_slider_left, clipping_slider_left); window_width = std::max(window_width, total_text_max); window_width = std::max(window_width, button_width); - window_width = std::max(window_width, cursor_type_combo_left + cursor_type_combo_width); + window_width = std::max(window_width, cursor_type_radio_left + cursor_type_radio_width1 + cursor_type_radio_width2); auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) { static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f); @@ -147,21 +144,41 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) } + ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("cursor_type")); - ImGui::SameLine(window_width - cursor_type_combo_width - m_imgui->scaled(0.5f)); - ImGui::PushItemWidth(cursor_type_combo_width); - int selection = int(m_cursor_type); - m_imgui->combo("", cursor_types, selection); - m_cursor_type = TriangleSelector::CursorType(selection); + ImGui::SameLine(cursor_type_radio_left + m_imgui->scaled(0.f)); + ImGui::PushItemWidth(cursor_type_radio_width1); + + bool sphere_sel = m_cursor_type == TriangleSelector::CursorType::SPHERE; + if (m_imgui->radio_button(m_desc["sphere"], sphere_sel)) + sphere_sel = true; + if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(max_tooltip_width); - ImGui::TextUnformatted(_L("Sphere paints all facets inside, regardless of their orientation.\n\n" - "Circle ignores facets facing away from the camera.").ToUTF8().data()); + ImGui::TextUnformatted(_L("Paints all facets inside, regardless of their orientation.").ToUTF8().data()); ImGui::PopTextWrapPos(); ImGui::EndTooltip(); } + ImGui::SameLine(cursor_type_radio_left + cursor_type_radio_width2 + m_imgui->scaled(0.f)); + ImGui::PushItemWidth(cursor_type_radio_width2); + + if (m_imgui->radio_button(m_desc["circle"], ! sphere_sel)) + sphere_sel = false; + + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(max_tooltip_width); + ImGui::TextUnformatted(_L("Ignores facets facing away from the camera.").ToUTF8().data()); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + + m_cursor_type = sphere_sel + ? TriangleSelector::CursorType::SPHERE + : TriangleSelector::CursorType::CIRCLE; + ImGui::Separator(); @@ -202,7 +219,7 @@ void GLGizmoSeam::update_model_object() const if (! mv->is_model_part()) continue; ++idx; - updated |= mv->m_seam_facets.set(*m_triangle_selectors[idx].get()); + updated |= mv->seam_facets.set(*m_triangle_selectors[idx].get()); } if (updated) @@ -229,7 +246,7 @@ void GLGizmoSeam::update_from_model_object() const TriangleMesh* mesh = &mv->mesh(); m_triangle_selectors.emplace_back(std::make_unique(*mesh)); - m_triangle_selectors.back()->deserialize(mv->m_seam_facets.get_data()); + m_triangle_selectors.back()->deserialize(mv->seam_facets.get_data()); } } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 6c4d0a71d..586828029 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1872,12 +1872,14 @@ void TabFilament::build() optgroup = page->new_optgroup(L("Start G-code"), 0); option = optgroup->get_option("start_filament_gcode"); option.opt.full_width = true; + option.opt.is_code = true; option.opt.height = gcode_field_height;// 150; optgroup->append_single_option_line(option); optgroup = page->new_optgroup(L("End G-code"), 0); option = optgroup->get_option("end_filament_gcode"); option.opt.full_width = true; + option.opt.is_code = true; option.opt.height = gcode_field_height;// 150; optgroup->append_single_option_line(option); @@ -2135,51 +2137,60 @@ void TabPrinter::build_fff() optgroup = page->new_optgroup(L("Start G-code"), 0); option = optgroup->get_option("start_gcode"); option.opt.full_width = true; + option.opt.is_code = true; option.opt.height = gcode_field_height;//150; optgroup->append_single_option_line(option); optgroup = page->new_optgroup(L("End G-code"), 0); option = optgroup->get_option("end_gcode"); option.opt.full_width = true; + option.opt.is_code = true; option.opt.height = gcode_field_height;//150; optgroup->append_single_option_line(option); optgroup = page->new_optgroup(L("Before layer change G-code"), 0); option = optgroup->get_option("before_layer_gcode"); option.opt.full_width = true; + option.opt.is_code = true; option.opt.height = gcode_field_height;//150; optgroup->append_single_option_line(option); optgroup = page->new_optgroup(L("After layer change G-code"), 0); option = optgroup->get_option("layer_gcode"); option.opt.full_width = true; + option.opt.is_code = true; option.opt.height = gcode_field_height;//150; optgroup->append_single_option_line(option); optgroup = page->new_optgroup(L("Tool change G-code"), 0); option = optgroup->get_option("toolchange_gcode"); option.opt.full_width = true; + option.opt.is_code = true; option.opt.height = gcode_field_height;//150; optgroup->append_single_option_line(option); optgroup = page->new_optgroup(L("Between objects G-code (for sequential printing)"), 0); option = optgroup->get_option("between_objects_gcode"); option.opt.full_width = true; + option.opt.is_code = true; option.opt.height = gcode_field_height;//150; optgroup->append_single_option_line(option); optgroup = page->new_optgroup(L("Color Change G-code"), 0); option = optgroup->get_option("color_change_gcode"); + option.opt.is_code = true; option.opt.height = gcode_field_height;//150; optgroup->append_single_option_line(option); optgroup = page->new_optgroup(L("Pause Print G-code"), 0); option = optgroup->get_option("pause_print_gcode"); + option.opt.is_code = true; option.opt.height = gcode_field_height;//150; optgroup->append_single_option_line(option); optgroup = page->new_optgroup(L("Template Custom G-code"), 0); option = optgroup->get_option("template_custom_gcode"); + option.opt.is_code = true; option.opt.height = gcode_field_height;//150; optgroup->append_single_option_line(option);