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;