diff --git a/src/slic3r.cpp b/src/slic3r.cpp index 5198eeaa3..958b66305 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -361,6 +361,14 @@ int CLI::run(int argc, char **argv) std::string outfile = m_config.opt_string("output"); Print fff_print; SLAPrint sla_print; + + sla_print.set_status_callback( + [](const PrintBase::SlicingStatus& s) + { + if(s.percent >= 0) // FIXME: is this sufficient? + printf("%3d%s %s\n", s.percent, "% =>", s.text.c_str()); + }); + PrintBase *print = (printer_technology == ptFFF) ? static_cast(&fff_print) : static_cast(&sla_print); if (! m_config.opt_bool("dont_arrange")) { //FIXME make the min_object_distance configurable. diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 4178dcb43..31c3717ff 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4403,11 +4403,13 @@ void GLCanvas3D::_resize(unsigned int w, unsigned int h) if ((m_canvas == nullptr) && (m_context == nullptr)) return; - wxGetApp().imgui()->set_display_size((float)w, (float)h); + auto *imgui = wxGetApp().imgui(); + imgui->set_display_size((float)w, (float)h); + imgui->set_font_size(m_canvas->GetFont().GetPixelSize().y); #if ENABLE_RETINA_GL - wxGetApp().imgui()->set_style_scaling(m_retina_helper->get_scale_factor()); + imgui->set_style_scaling(m_retina_helper->get_scale_factor()); #else - wxGetApp().imgui()->set_style_scaling(m_canvas->GetContentScaleFactor()); + imgui->set_style_scaling(m_canvas->GetContentScaleFactor()); #endif // ensures that this canvas is current diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index fdb8968d3..f1a7d9263 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -81,7 +81,7 @@ IMPLEMENT_APP(GUI_App) GUI_App::GUI_App() : wxApp() , m_em_unit(10) - , m_imgui(nullptr) + , m_imgui(new ImGuiWrapper()) {} bool GUI_App::OnInit() @@ -138,7 +138,6 @@ bool GUI_App::OnInit() // initialize label colors and fonts init_label_colours(); init_fonts(); - m_imgui.reset(new ImGuiWrapper(m_normal_font.GetPixelSize().y)); load_language(); diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index f626fa7f5..001e0b33f 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -25,9 +25,9 @@ namespace Slic3r { namespace GUI { -ImGuiWrapper::ImGuiWrapper(float font_size) +ImGuiWrapper::ImGuiWrapper() : m_glyph_ranges(nullptr) - , m_font_size(font_size) + , m_font_size(18.0) , m_font_texture(0) , m_style_scaling(1.0) , m_mouse_buttons(0) @@ -36,7 +36,6 @@ ImGuiWrapper::ImGuiWrapper(float font_size) { ImGui::CreateContext(); - init_default_font(); init_input(); init_style(); @@ -45,7 +44,7 @@ ImGuiWrapper::ImGuiWrapper(float font_size) ImGuiWrapper::~ImGuiWrapper() { - destroy_device_objects(); + destroy_font(); ImGui::DestroyContext(); } @@ -82,7 +81,7 @@ void ImGuiWrapper::set_language(const std::string &language) if (ranges != m_glyph_ranges) { m_glyph_ranges = ranges; - init_default_font(); + destroy_font(); } } @@ -93,12 +92,20 @@ void ImGuiWrapper::set_display_size(float w, float h) io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f); } +void ImGuiWrapper::set_font_size(float font_size) +{ + if (m_font_size != font_size) { + m_font_size = font_size; + destroy_font(); + } +} + void ImGuiWrapper::set_style_scaling(float scaling) { if (!std::isnan(scaling) && !std::isinf(scaling) && scaling != m_style_scaling) { ImGui::GetStyle().ScaleAllSizes(scaling / m_style_scaling); m_style_scaling = scaling; - init_default_font(); + destroy_font(); } } @@ -156,12 +163,15 @@ bool ImGuiWrapper::update_key_data(wxKeyEvent &evt) void ImGuiWrapper::new_frame() { + printf("ImGuiWrapper: new_frame()\n"); + if (m_new_frame_open) { return; } - if (m_font_texture == 0) - create_device_objects(); + if (m_font_texture == 0) { + init_font(); + } ImGui::NewFrame(); m_new_frame_open = true; @@ -254,7 +264,8 @@ void ImGuiWrapper::text(const std::string &label) void ImGuiWrapper::text(const wxString &label) { - this->text(into_u8(label).c_str()); + auto label_utf8 = into_u8(label); + this->text(label_utf8.c_str()); } bool ImGuiWrapper::combo(const wxString& label, const std::vector& options, int& selection) @@ -282,6 +293,12 @@ bool ImGuiWrapper::combo(const wxString& label, const std::vector& return res; } +ImVec2 ImGuiWrapper::calc_text_size(const wxString &text) +{ + auto text_utf8 = into_u8(text); + return ImGui::CalcTextSize(text_utf8.c_str()); +} + void ImGuiWrapper::disabled_begin(bool disabled) { wxCHECK_RET(!m_disabled, "ImGUI: Unbalanced disabled_begin() call"); @@ -323,11 +340,13 @@ bool ImGuiWrapper::want_any_input() const return io.WantCaptureMouse || io.WantCaptureKeyboard || io.WantTextInput; } -void ImGuiWrapper::init_default_font() +void ImGuiWrapper::init_font() { + printf("ImGuiWrapper: init_font()\n"); + const float font_size = m_font_size * m_style_scaling; - destroy_fonts_texture(); + destroy_font(); ImGuiIO& io = ImGui::GetIO(); io.Fonts->Clear(); @@ -338,17 +357,8 @@ void ImGuiWrapper::init_default_font() throw std::runtime_error("ImGui: Could not load deafult font"); } } -} -void ImGuiWrapper::create_device_objects() -{ - create_fonts_texture(); -} - -void ImGuiWrapper::create_fonts_texture() -{ // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. @@ -554,14 +564,9 @@ bool ImGuiWrapper::display_initialized() const return io.DisplaySize.x >= 0.0f && io.DisplaySize.y >= 0.0f; } -void ImGuiWrapper::destroy_device_objects() +void ImGuiWrapper::destroy_font() { - destroy_fonts_texture(); -} - -void ImGuiWrapper::destroy_fonts_texture() -{ - if (m_font_texture) { + if (m_font_texture != 0) { ImGuiIO& io = ImGui::GetIO(); io.Fonts->TexID = 0; glDeleteTextures(1, &m_font_texture); diff --git a/src/slic3r/GUI/ImGuiWrapper.hpp b/src/slic3r/GUI/ImGuiWrapper.hpp index 7e022532a..476379da2 100644 --- a/src/slic3r/GUI/ImGuiWrapper.hpp +++ b/src/slic3r/GUI/ImGuiWrapper.hpp @@ -18,9 +18,6 @@ namespace GUI { class ImGuiWrapper { - typedef std::map FontsMap; - - FontsMap m_fonts; const ImWchar *m_glyph_ranges; float m_font_size; unsigned m_font_texture; @@ -31,22 +28,27 @@ class ImGuiWrapper std::string m_clipboard_text; public: - ImGuiWrapper(float font_size); + ImGuiWrapper(); ~ImGuiWrapper(); void read_glsl_version(); void set_language(const std::string &language); void set_display_size(float w, float h); + void set_font_size(float font_size); void set_style_scaling(float scaling); bool update_mouse_data(wxMouseEvent &evt); bool update_key_data(wxKeyEvent &evt); + float get_font_size() const { return m_font_size; } float get_style_scaling() const { return m_style_scaling; } void new_frame(); void render(); + float scaled(float x) const { return x * m_font_size * m_style_scaling; } + ImVec2 scaled_vec(float x, float y) const { return ImVec2(x * m_font_size * m_style_scaling, y * m_font_size * m_style_scaling); } + void set_next_window_pos(float x, float y, int flag); void set_next_window_bg_alpha(float alpha); @@ -64,6 +66,8 @@ public: void text(const wxString &label); bool combo(const wxString& label, const std::vector& options, int& selection); // Use -1 to not mark any option as selected + ImVec2 calc_text_size(const wxString &text); + void disabled_begin(bool disabled); void disabled_end(); @@ -73,15 +77,12 @@ public: bool want_any_input() const; private: - void init_default_font(); - void create_device_objects(); - void create_fonts_texture(); + void init_font(); void init_input(); void init_style(); void render_draw_data(ImDrawData *draw_data); bool display_initialized() const; - void destroy_device_objects(); - void destroy_fonts_texture(); + void destroy_font(); static const char* clipboard_get(void* user_data); static void clipboard_set(void* user_data, const char* text); diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 5d286846b..34b5f4067 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -118,17 +118,17 @@ void Selection::add(unsigned int volume_idx, bool as_single_selection) if (needs_reset) clear(); - if (volume->is_modifier) - m_mode = Volume; - else if (!contains_volume(volume_idx)) - m_mode = Instance; - // else -> keep current mode + if (!contains_volume(volume_idx)) + m_mode = volume->is_modifier ? Volume : Instance; + else + // keep current mode + return; switch (m_mode) { case Volume: { - if (volume->volume_idx() >= 0 && (is_empty() || (volume->instance_idx() == get_instance_idx()))) + if ((volume->volume_idx() >= 0) && (is_empty() || (volume->instance_idx() == get_instance_idx()))) _add_volume(volume_idx); break; @@ -439,6 +439,8 @@ void Selection::translate(const Vec3d& displacement, bool local) if (!m_valid) return; + EMode translation_type = m_mode; + for (unsigned int i : m_list) { if ((m_mode == Volume) || (*m_volumes)[i]->is_wipe_tower) @@ -452,13 +454,22 @@ void Selection::translate(const Vec3d& displacement, bool local) } } else if (m_mode == Instance) - (*m_volumes)[i]->set_instance_offset(m_cache.volumes_data[i].get_instance_position() + displacement); + { + if (_is_from_fully_selected_instance(i)) + (*m_volumes)[i]->set_instance_offset(m_cache.volumes_data[i].get_instance_position() + displacement); + else + { + Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement; + (*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement); + translation_type = Volume; + } + } } #if !DISABLE_INSTANCES_SYNCH - if (m_mode == Instance) + if (translation_type == Instance) _synchronize_unselected_instances(SYNC_ROTATION_NONE); - else if (m_mode == Volume) + else if (translation_type == Volume) _synchronize_unselected_volumes(); #endif // !DISABLE_INSTANCES_SYNCH @@ -1683,5 +1694,29 @@ void Selection::_ensure_on_bed() } } +bool Selection::_is_from_fully_selected_instance(unsigned int volume_idx) const +{ + struct SameInstance + { + int obj_idx; + int inst_idx; + GLVolumePtrs& volumes; + + SameInstance(int obj_idx, int inst_idx, GLVolumePtrs& volumes) : obj_idx(obj_idx), inst_idx(inst_idx), volumes(volumes) {} + bool operator () (unsigned int i) { return (volumes[i]->object_idx() == obj_idx) && (volumes[i]->instance_idx() == inst_idx); } + }; + + if ((unsigned int)m_volumes->size() <= volume_idx) + return false; + + GLVolume* volume = (*m_volumes)[volume_idx]; + int object_idx = volume->object_idx(); + if ((int)m_model->objects.size() <= object_idx) + return false; + + unsigned int count = (unsigned int)std::count_if(m_list.begin(), m_list.end(), SameInstance(object_idx, volume->instance_idx(), *m_volumes)); + return count == (unsigned int)m_model->objects[object_idx]->volumes.size(); +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 200f239c1..4b2a72d7c 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -297,6 +297,7 @@ private: void _synchronize_unselected_instances(SyncRotationType sync_rotation_type); void _synchronize_unselected_volumes(); void _ensure_on_bed(); + bool _is_from_fully_selected_instance(unsigned int volume_idx) const; }; } // namespace GUI