diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 5e6d28b587..aeb078172c 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -59,7 +59,7 @@ function(prusaslicer_add_cmake_project projectname) set(_gen "") set(_build_j "-j${NPROC}") if (MSVC) - set(_gen CMAKE_GENERATOR "${DEP_MSVC_GEN}") + set(_gen CMAKE_GENERATOR "${DEP_MSVC_GEN}" CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}") set(_build_j "/m") endif () diff --git a/src/platform/osx/Info.plist.in b/src/platform/osx/Info.plist.in index d09f015b9c..f4e298180b 100644 --- a/src/platform/osx/Info.plist.in +++ b/src/platform/osx/Info.plist.in @@ -116,7 +116,5 @@ NSApplication NSHighResolutionCapable - NSRequiresAquaSystemAppearance - diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index dce7c4c996..a0f842d26e 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -191,7 +191,6 @@ Bed3D::Bed3D() : m_type(Custom) , m_custom_texture("") , m_custom_model("") - , m_requires_canvas_update(false) , m_vbo_id(0) , m_scale_factor(1.0f) { @@ -438,6 +437,7 @@ void Bed3D::render_texture(const std::string& filename, bool bottom, GLCanvas3D& render_default(bottom); return; } + canvas.request_extra_frame(); } // starts generating the main texture, compression will run asynchronously @@ -457,6 +457,7 @@ void Bed3D::render_texture(const std::string& filename, bool bottom, GLCanvas3D& render_default(bottom); return; } + canvas.request_extra_frame(); } // starts generating the main texture, compression will run asynchronously @@ -481,13 +482,9 @@ void Bed3D::render_texture(const std::string& filename, bool bottom, GLCanvas3D& if (m_temp_texture.get_id() != 0) m_temp_texture.reset(); - m_requires_canvas_update = true; - } - else if (m_requires_canvas_update && m_texture.all_compressed_data_sent_to_gpu()) - m_requires_canvas_update = false; + canvas.request_extra_frame(); - if (m_texture.all_compressed_data_sent_to_gpu() && canvas.is_keeping_dirty()) - canvas.stop_keeping_dirty(); + } if (m_triangles.get_vertices_count() > 0) { diff --git a/src/slic3r/GUI/3DBed.hpp b/src/slic3r/GUI/3DBed.hpp index 19ecddc0a6..cd2de862e7 100644 --- a/src/slic3r/GUI/3DBed.hpp +++ b/src/slic3r/GUI/3DBed.hpp @@ -86,8 +86,6 @@ private: mutable GLTexture m_texture; // temporary texture shown until the main texture has still no levels compressed mutable GLTexture m_temp_texture; - // used to trigger 3D scene update once all compressed textures have been sent to GPU - mutable bool m_requires_canvas_update; mutable Shader m_shader; mutable unsigned int m_vbo_id; mutable GLBed m_model; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 012127aede..8e922398a4 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1393,7 +1393,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar , m_gizmos(*this) , m_use_clipping_planes(false) , m_sidebar_field("") - , m_keep_dirty(false) + , m_extra_frame_requested(false) , m_config(nullptr) , m_process(nullptr) , m_model(nullptr) @@ -1631,8 +1631,6 @@ void GLCanvas3D::bed_shape_changed() refresh_camera_scene_box(); m_camera.requires_zoom_to_bed = true; m_dirty = true; - if (m_bed.is_prusa()) - start_keeping_dirty(); } void GLCanvas3D::set_color_by(const std::string& value) @@ -2627,10 +2625,11 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt) _refresh_if_shown_on_screen(); - if (m_keep_dirty || mouse3d_controller_applied) + if (m_extra_frame_requested || mouse3d_controller_applied) { m_dirty = true; evt.RequestMore(); + m_extra_frame_requested = false; } else m_dirty = false; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 547a9d8857..e07ccd7fdd 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -436,7 +436,9 @@ private: bool m_use_clipping_planes; mutable SlaCap m_sla_caps[2]; std::string m_sidebar_field; - bool m_keep_dirty; + // when true renders an extra frame by not resetting m_dirty to false + // see request_extra_frame() + bool m_extra_frame_requested; mutable GLVolumeCollection m_volumes; Selection m_selection; @@ -664,9 +666,7 @@ public: void set_cursor(ECursorType type); void msw_rescale(); - bool is_keeping_dirty() const { return m_keep_dirty; } - void start_keeping_dirty() { m_keep_dirty = true; } - void stop_keeping_dirty() { m_keep_dirty = false; } + void request_extra_frame() { m_extra_frame_requested = true; } int get_main_toolbar_item_id(const std::string& name) const { return m_main_toolbar.get_item_id(name); } void force_main_toolbar_left_action(int item_id) { m_main_toolbar.force_left_action(item_id, *this); } diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index a1f06de314..c0520cb9a9 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1192,7 +1192,13 @@ void ObjectList::get_settings_choice(const wxString& category_name) { wxArrayString names; wxArrayInt selections; - wxDataViewItem item = GetSelection(); + + /* If we try to add settings for object/part from 3Dscene, + * for the second try there is selected ItemSettings in ObjectList. + * So, check if selected item isn't SettingsItem. And get a SettingsItem's parent item, if yes + */ + const wxDataViewItem selected_item = GetSelection(); + wxDataViewItem item = m_objects_model->GetItemType(selected_item) & itSettings ? m_objects_model->GetParent(selected_item) : selected_item; const ItemType item_type = m_objects_model->GetItemType(item); @@ -1318,11 +1324,17 @@ void ObjectList::get_freq_settings_choice(const wxString& bundle_name) { std::vector options = get_options_for_bundle(bundle_name); const Selection& selection = scene_selection(); - wxDataViewItem item = GetSelectedItemsCount() > 1 && selection.is_single_full_object() ? - m_objects_model->GetItemById(selection.get_object_idx()) : - GetSelection(); + const wxDataViewItem sel_item = // when all instances in object are selected + GetSelectedItemsCount() > 1 && selection.is_single_full_object() ? + m_objects_model->GetItemById(selection.get_object_idx()) : + GetSelection(); - ItemType item_type = m_objects_model->GetItemType(item); + /* If we try to add settings for object/part from 3Dscene, + * for the second try there is selected ItemSettings in ObjectList. + * So, check if selected item isn't SettingsItem. And get a SettingsItem's parent item, if yes + */ + wxDataViewItem item = m_objects_model->GetItemType(sel_item) & itSettings ? m_objects_model->GetParent(sel_item) : sel_item; + const ItemType item_type = m_objects_model->GetItemType(item); /* Because of we couldn't edited layer_height for ItVolume from settings list, * correct options according to the selected item type : @@ -1546,17 +1558,21 @@ wxMenuItem* ObjectList::append_menu_item_change_type(wxMenu* menu) wxMenuItem* ObjectList::append_menu_item_instance_to_object(wxMenu* menu, wxWindow* parent) { wxMenuItem* menu_item = append_menu_item(menu, wxID_ANY, _(L("Set as a Separated Object")), "", - [this](wxCommandEvent&) { split_instances(); }, "", menu, [](){return wxGetApp().plater()->can_set_instance_to_object(); }, parent); + [this](wxCommandEvent&) { split_instances(); }, "", menu); /* New behavior logic: * 1. Split Object to several separated object, if ALL instances are selected * 2. Separate selected instances from the initial object to the separated object, * if some (not all) instances are selected */ - parent->Bind(wxEVT_UPDATE_UI, [](wxUpdateUIEvent& evt) { - evt.SetText(wxGetApp().plater()->canvas3D()->get_selection().is_single_full_object() ? - _(L("Set as a Separated Objects")) : _(L("Set as a Separated Object"))); - }, menu_item->GetId()); + parent->Bind(wxEVT_UPDATE_UI, [](wxUpdateUIEvent& evt) + { + const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); + evt.SetText(selection.is_single_full_object() ? + _(L("Set as a Separated Objects")) : _(L("Set as a Separated Object"))); + + evt.Enable(wxGetApp().plater()->can_set_instance_to_object()); + }, menu_item->GetId()); return menu_item; } @@ -1726,7 +1742,15 @@ wxMenu* ObjectList::create_settings_popupmenu(wxMenu *parent_menu) wxMenu *menu = new wxMenu; settings_menu_hierarchy settings_menu; - const bool is_part = !(m_objects_model->GetItemType(GetSelection()) == itObject || scene_selection().is_single_full_object()); + + /* If we try to add settings for object/part from 3Dscene, + * for the second try there is selected ItemSettings in ObjectList. + * So, check if selected item isn't SettingsItem. And get a SettingsItem's parent item, if yes + */ + const wxDataViewItem selected_item = GetSelection(); + wxDataViewItem item = m_objects_model->GetItemType(selected_item) & itSettings ? m_objects_model->GetParent(selected_item) : selected_item; + + const bool is_part = !(m_objects_model->GetItemType(item) == itObject || scene_selection().is_single_full_object()); get_options_menu(settings_menu, is_part); for (auto cat : settings_menu) { @@ -3005,7 +3029,8 @@ void ObjectList::update_selections() else if (selection.is_single_full_object() || selection.is_multiple_full_object()) { const Selection::ObjectIdxsToInstanceIdxsMap& objects_content = selection.get_content(); - if (m_selection_mode & (smSettings | smLayer | smLayerRoot)) + // it's impossible to select Settings, Layer or LayerRoot for several objects + if (!selection.is_multiple_full_object() && (m_selection_mode & (smSettings | smLayer | smLayerRoot))) { auto obj_idx = objects_content.begin()->first; wxDataViewItem obj_item = m_objects_model->GetItemById(obj_idx); @@ -3938,8 +3963,15 @@ void ObjectList::update_after_undo_redo() Plater::SuppressSnapshots suppress(wxGetApp().plater()); // Unselect all objects before deleting them, so that no change of selection is emitted during deletion. - unselect_objects();//this->UnselectAll(); + + /* To avoid execution of selection_changed() + * from wxEVT_DATAVIEW_SELECTION_CHANGED emitted from DeleteAll(), + * wrap this two functions into m_prevent_list_events * + * */ + m_prevent_list_events = true; + this->UnselectAll(); m_objects_model->DeleteAll(); + m_prevent_list_events = false; size_t obj_idx = 0; std::vector obj_idxs; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 4406b1bf5c..e98446749f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -136,12 +136,25 @@ void GLGizmoCut::on_render_for_picking() const void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit) { - const float approx_height = m_imgui->scaled(11.0f); - y = std::min(y, bottom_limit - approx_height); - m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); + static float last_y = 0.0f; + static float last_h = 0.0f; m_imgui->begin(_(L("Cut")), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); + // adjust window position to avoid overlap the view toolbar + float win_h = ImGui::GetWindowHeight(); + y = std::min(y, bottom_limit - win_h); + ImGui::SetWindowPos(ImVec2(x, y), ImGuiCond_Always); + if ((last_h != win_h) || (last_y != y)) + { + // ask canvas for another frame to render the window in the correct position + m_parent.request_extra_frame(); + if (last_h != win_h) + last_h = win_h; + if (last_y != y) + last_y = y; + } + ImGui::AlignTextToFramePadding(); m_imgui->text("Z"); ImGui::SameLine(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 8499774644..a0e84d4903 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -686,6 +686,9 @@ void GLGizmoSlaSupports::make_line_segments() const void GLGizmoSlaSupports::on_render_input_window(float x, float y, float bottom_limit) { + static float last_y = 0.0f; + static float last_h = 0.0f; + if (!m_model_object) return; @@ -697,11 +700,22 @@ RENDER_AGAIN: //ImGui::SetNextWindowPos(ImVec2(x, y - std::max(0.f, y+window_size.y-bottom_limit) )); //ImGui::SetNextWindowSize(ImVec2(window_size)); - const float approx_height = m_imgui->scaled(18.0f); - y = std::min(y, bottom_limit - approx_height); - m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); + // adjust window position to avoid overlap the view toolbar + float win_h = ImGui::GetWindowHeight(); + y = std::min(y, bottom_limit - win_h); + ImGui::SetWindowPos(ImVec2(x, y), ImGuiCond_Always); + if ((last_h != win_h) || (last_y != y)) + { + // ask canvas for another frame to render the window in the correct position + m_parent.request_extra_frame(); + if (last_h != win_h) + last_h = win_h; + if (last_y != y) + last_y = y; + } + // 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 settings_sliders_left = std::max(m_imgui->calc_text_size(m_desc.at("minimal_distance")).x, m_imgui->calc_text_size(m_desc.at("points_density")).x) + m_imgui->scaled(1.f); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index d0d58cb2b7..c8267331d3 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3234,7 +3234,7 @@ void Plater::priv::reload_from_disk() { // ask user to select the missing file std::string search = missing_input_paths.back().string(); - wxFileDialog dialog(q, _(L("Please select the file to reload:")), "", search, file_wildcards(FT_MODEL), wxFD_OPEN | wxFD_FILE_MUST_EXIST); + wxFileDialog dialog(q, _(L("Please select the file to reload:")), "", from_u8(fs::path(search).filename().string()), file_wildcards(FT_MODEL), wxFD_OPEN | wxFD_FILE_MUST_EXIST); if (dialog.ShowModal() != wxID_OK) return;