Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions resources/images/plate_hidden.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions resources/images/plate_hidden_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions resources/images/plate_hidden_hover.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions resources/images/plate_hidden_hover_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions resources/images/plate_visible.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions resources/images/plate_visible_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions resources/images/plate_visible_hover.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions resources/images/plate_visible_hover_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions resources/images/toolbar_plate_visibility.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions resources/images/toolbar_plate_visibility_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
123 changes: 123 additions & 0 deletions src/slic3r/GUI/GLCanvas3D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2034,6 +2034,39 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject
_set_warning_notification(EWarning::SomethingNotShown, false);
}

void GLCanvas3D::update_plate_volumes_visibility(PartPlateList& plate_list)
{
// Build a set of (object_id, instance_id) pairs that belong to hidden plates
std::set<std::pair<int,int>> hidden_instances;
for (int i = 0; i < plate_list.get_plate_count(); i++) {
const PartPlate* plate = plate_list.get_plate(i);
if (plate && !plate->is_visible()) {
for (const auto& pair : plate->get_instance_set())
hidden_instances.insert(pair);
}
}

for (GLVolume* vol : m_volumes.volumes) {
int obj_id = vol->composite_id.object_id;
int inst_id = vol->composite_id.instance_id;
bool in_hidden;
if (vol->is_wipe_tower) {
int wt_plate_id = obj_id - 1000;
const PartPlate* wt_plate = plate_list.get_plate(wt_plate_id);
in_hidden = wt_plate && !wt_plate->is_visible();
} else if (obj_id < 0 || obj_id >= 1000) {
continue;
} else {
in_hidden = hidden_instances.count({obj_id, inst_id}) > 0;
}
if (in_hidden)
vol->is_active = false;
else if (!vol->is_active) {
vol->is_active = true;
}
}
}

void GLCanvas3D::update_instance_printable_state_for_object(const size_t obj_idx)
{
ModelObject* model_object = m_model->objects[obj_idx];
Expand Down Expand Up @@ -3744,6 +3777,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
#endif
}
wxGetApp().plater()->get_partplate_list().reset_thumbnail_assembly_view_data(); // reload scene
// Re-apply per-plate visibility (newly loaded wipe towers default to active).
update_plate_volumes_visibility(wxGetApp().plater()->get_partplate_list());
// and force this canvas to be redrawn.
m_dirty = true;
}
Expand Down Expand Up @@ -7410,6 +7445,94 @@ bool GLCanvas3D::_init_main_toolbar()
if (!p_main_toolbar->add_item(item))
return false;
}

{
GLToolbarItem::Data item;
item.name = "plate_visibility";
item.icon_filename_callback = [](bool is_dark_mode)->std::string {
return is_dark_mode ? "toolbar_plate_visibility_dark.svg" : "toolbar_plate_visibility.svg";
};
item.tooltip = _utf8(L("Show/Hide Plates"));
item.sprite_id = sprite_id++;
item.left.toggable = false;
item.left.action_callback = [this]() {
if (m_canvas == nullptr) return;
PartPlateList& list = wxGetApp().plater()->get_partplate_list();
if (list.get_plate_count() <= 1) return;
wxMenu menu;

auto do_refresh = [this, &list]() {
list.update_unselected_plate_trans(list.get_plate_count());
update_plate_volumes_visibility(list);
wxGetApp().obj_list()->reload_all_plates();
wxGetApp().plater()->update();
};

// Show All
wxMenuItem* show_all = menu.Append(wxID_ANY, _L("Show All Plates"));
menu.Bind(wxEVT_MENU, [this, &list, do_refresh](wxCommandEvent&) {
for (int i = 0; i < list.get_plate_count(); i++) {
PartPlate* p = list.get_plate(i);
if (p && !p->is_visible()) p->set_visible(true);
}
do_refresh();
}, show_all->GetId());

// Hide Other Plates — disabled if current plate is hidden or no others are visible
int curr_idx = list.get_curr_plate_index();
PartPlate* curr_plate = list.get_plate(curr_idx);
bool curr_is_visible = curr_plate && curr_plate->is_visible();
wxMenuItem* hide_others = menu.Append(wxID_ANY, _L("Hide Other Plates"));
bool any_other_visible = false;
for (int i = 0; i < list.get_plate_count(); i++)
if (i != curr_idx && list.get_plate(i) && list.get_plate(i)->is_visible())
any_other_visible = true;
if (!any_other_visible || !curr_is_visible) hide_others->Enable(false);
menu.Bind(wxEVT_MENU, [this, &list, curr_idx, do_refresh](wxCommandEvent&) {
PartPlate* curr = list.get_plate(curr_idx);
if (!curr || !curr->is_visible()) return;
for (int i = 0; i < list.get_plate_count(); i++) {
PartPlate* p = list.get_plate(i);
if (p && i != curr_idx && p->is_visible()) p->set_visible(false);
}
do_refresh();
}, hide_others->GetId());

menu.AppendSeparator();

// Per-plate toggles
for (int i = 0; i < list.get_plate_count(); i++) {
PartPlate* plate = list.get_plate(i);
if (!plate) continue;
wxString name = from_u8(plate->get_plate_name());
if (name.empty())
name = wxString::Format(_L("Plate %d"), i + 1);
else
name = wxString::Format("%s (%d)", name, i + 1);
wxMenuItem* mi = menu.AppendCheckItem(wxID_ANY, name);
mi->Check(plate->is_visible());
if (plate->is_visible() && list.get_visible_plate_count() <= 1)
mi->Enable(false);
menu.Bind(wxEVT_MENU, [this, i, &list, do_refresh](wxCommandEvent&) {
PartPlate* p = list.get_plate(i);
if (!p) return;
if (p->is_visible() && list.get_visible_plate_count() <= 1) return;
p->set_visible(!p->is_visible());
do_refresh();
}, mi->GetId());
}
m_canvas->PopupMenu(&menu);
};
item.left.render_callback = GLToolbarItem::Default_Render_Callback;
item.visible = true;
item.visibility_callback = [this]()->bool {
return wxGetApp().plater()->get_partplate_list().get_plate_count() > 1;
};
item.enabling_callback = []()->bool { return true; };
item.b_collapsible = false;
if (!p_main_toolbar->add_item(item))
return false;
}
}

p_main_toolbar->update_items_state();
Expand Down
1 change: 1 addition & 0 deletions src/slic3r/GUI/GLCanvas3D.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,7 @@ class GLCanvas3D
void toggle_selected_volume_visibility(bool selected_visible);
void toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1);
void toggle_model_objects_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1, const ModelVolume* mv = nullptr);
void update_plate_volumes_visibility(PartPlateList& plate_list);
void update_instance_printable_state_for_object(size_t obj_idx);
void update_instance_printable_state_for_objects(const std::vector<size_t>& object_idxs);

Expand Down
73 changes: 73 additions & 0 deletions src/slic3r/GUI/GUI_Factories.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1844,6 +1844,7 @@ wxMenu *MenuFactory::filament_action_menu(int active_filament_menu_id) {
wxMenu* MenuFactory::plate_menu()
{
append_menu_item_locked(&m_plate_menu);
append_menu_item_plate_visibility(&m_plate_menu);
append_menu_item_plate_name(&m_plate_menu);
{
NetworkAgent* agent = GUI::wxGetApp().getAgent();
Expand Down Expand Up @@ -2433,6 +2434,78 @@ void MenuFactory::append_menu_item_locked(wxMenu* menu)
}, item->GetId());
}

void MenuFactory::append_menu_item_plate_visibility(wxMenu* menu)
{
const std::vector<wxString> names = {
_L("Show Plate"), _L("Hide Plate"),
_L("Show All Plates"), _L("Hide Other Plates")
};
for (const wxString& name : names) {
int item_id;
while ((item_id = menu->FindItem(name)) != wxNOT_FOUND)
menu->Destroy(item_id);
}

PartPlateList& list = plater()->get_partplate_list();
if (list.get_plate_count() <= 1)
return;

PartPlate* plate = list.get_selected_plate();
if (!plate) return;

auto do_refresh = []() {
PartPlateList& list = plater()->get_partplate_list();
list.update_unselected_plate_trans(list.get_plate_count());
plater()->get_view3D_canvas3D()->update_plate_volumes_visibility(list);
wxGetApp().obj_list()->reload_all_plates();
plater()->update();
};

// Show All
auto show_all = append_menu_item(menu, wxID_ANY, _L("Show All Plates"), "",
[do_refresh](wxCommandEvent&) {
PartPlateList& list = plater()->get_partplate_list();
for (int i = 0; i < list.get_plate_count(); i++) {
PartPlate* p = list.get_plate(i);
if (p && !p->is_visible()) p->set_visible(true);
}
do_refresh();
}, "", nullptr, nullptr, nullptr);

// Hide Other Plates — disabled if current plate is hidden (would leave 0 visible) or no others are visible
int curr_idx = list.get_curr_plate_index();
bool curr_is_visible = plate->is_visible();
bool any_other_visible = false;
for (int i = 0; i < list.get_plate_count(); i++)
if (i != curr_idx && list.get_plate(i) && list.get_plate(i)->is_visible())
any_other_visible = true;
auto hide_others = append_menu_item(menu, wxID_ANY, _L("Hide Other Plates"), "",
[do_refresh, curr_idx](wxCommandEvent&) {
PartPlateList& list = plater()->get_partplate_list();
PartPlate* curr = list.get_plate(curr_idx);
if (!curr || !curr->is_visible()) return;
for (int i = 0; i < list.get_plate_count(); i++) {
PartPlate* p = list.get_plate(i);
if (p && i != curr_idx && p->is_visible()) p->set_visible(false);
}
do_refresh();
}, "", nullptr, nullptr, nullptr);
if (!any_other_visible || !curr_is_visible) hide_others->Enable(false);

// Single plate toggle (only if not the last visible)
bool is_last_visible = plate->is_visible() && list.get_visible_plate_count() <= 1;
if (!is_last_visible) {
wxString vis_text = plate->is_visible() ? names[1] : names[0];
append_menu_item(menu, wxID_ANY, vis_text, "",
[plate, do_refresh](wxCommandEvent&) {
PartPlateList& list = plater()->get_partplate_list();
if (plate->is_visible() && list.get_visible_plate_count() <= 1) return;
plate->set_visible(!plate->is_visible());
do_refresh();
}, "", nullptr, nullptr, nullptr);
}
}

void MenuFactory::append_menu_item_fill_bed(wxMenu *menu)
{
append_menu_item(
Expand Down
1 change: 1 addition & 0 deletions src/slic3r/GUI/GUI_Factories.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ class MenuFactory
void append_menu_item_change_filament(wxMenu* menu);
void append_menu_item_set_printable(wxMenu* menu);
void append_menu_item_locked(wxMenu* menu);
void append_menu_item_plate_visibility(wxMenu* menu);
void append_menu_item_fill_bed(wxMenu *menu);
void append_menu_item_plate_name(wxMenu *menu);
void append_menu_item_align_distribute(wxMenu *menu);
Expand Down
Loading
Loading