mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-04 00:50:40 +08:00
Multiple beds: Fixed behaviour with empty beds and non-printable instances
This commit is contained in:
parent
4f7366045e
commit
1a608da2ae
@ -1661,7 +1661,7 @@ unsigned int ModelObject::update_instances_print_volume_state(const BuildVolume
|
|||||||
if (inside_outside == INSIDE)
|
if (inside_outside == INSIDE)
|
||||||
++num_printable;
|
++num_printable;
|
||||||
if (bed_idx != -1)
|
if (bed_idx != -1)
|
||||||
s_multiple_beds.set_instance_bed(model_instance->id(), bed_idx);
|
s_multiple_beds.set_instance_bed(model_instance->id(), model_instance->printable, bed_idx);
|
||||||
}
|
}
|
||||||
return num_printable;
|
return num_printable;
|
||||||
}
|
}
|
||||||
|
@ -115,12 +115,16 @@ Vec3d MultipleBeds::get_bed_translation(int id) const
|
|||||||
void MultipleBeds::clear_inst_map()
|
void MultipleBeds::clear_inst_map()
|
||||||
{
|
{
|
||||||
m_inst_to_bed.clear();
|
m_inst_to_bed.clear();
|
||||||
|
m_occupied_beds_cache.fill(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultipleBeds::set_instance_bed(ObjectID id, int bed_idx)
|
void MultipleBeds::set_instance_bed(ObjectID id, bool printable, int bed_idx)
|
||||||
{
|
{
|
||||||
assert(bed_idx < get_max_beds());
|
assert(bed_idx < get_max_beds());
|
||||||
m_inst_to_bed[id] = bed_idx;
|
m_inst_to_bed[id] = bed_idx;
|
||||||
|
|
||||||
|
if (printable)
|
||||||
|
m_occupied_beds_cache[bed_idx] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultipleBeds::inst_map_updated()
|
void MultipleBeds::inst_map_updated()
|
||||||
@ -298,6 +302,11 @@ Vec2d MultipleBeds::bed_gap() const
|
|||||||
return Vec2d::Ones() * gap;
|
return Vec2d::Ones() * gap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MultipleBeds::is_bed_occupied(int i) const
|
||||||
|
{
|
||||||
|
return m_occupied_beds_cache[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Vec2crd MultipleBeds::get_bed_gap() const {
|
Vec2crd MultipleBeds::get_bed_gap() const {
|
||||||
return scaled(Vec2d{bed_gap() / 2.0});
|
return scaled(Vec2d{bed_gap() / 2.0});
|
||||||
|
@ -32,9 +32,10 @@ public:
|
|||||||
Vec3d get_bed_translation(int id) const;
|
Vec3d get_bed_translation(int id) const;
|
||||||
|
|
||||||
void clear_inst_map();
|
void clear_inst_map();
|
||||||
void set_instance_bed(ObjectID id, int bed_idx);
|
void set_instance_bed(ObjectID id, bool printable, int bed_idx);
|
||||||
void inst_map_updated();
|
void inst_map_updated();
|
||||||
const std::map<ObjectID, int> &get_inst_map() const { return m_inst_to_bed; }
|
const std::map<ObjectID, int> &get_inst_map() const { return m_inst_to_bed; }
|
||||||
|
bool is_bed_occupied(int bed_idx) const;
|
||||||
|
|
||||||
int get_number_of_beds() const { return m_number_of_beds; }
|
int get_number_of_beds() const { return m_number_of_beds; }
|
||||||
bool should_show_next_bed() const { return m_show_next_bed; }
|
bool should_show_next_bed() const { return m_show_next_bed; }
|
||||||
@ -78,6 +79,7 @@ private:
|
|||||||
bool m_show_next_bed = false;
|
bool m_show_next_bed = false;
|
||||||
std::map<ObjectID, int> m_inst_to_bed;
|
std::map<ObjectID, int> m_inst_to_bed;
|
||||||
std::map<PrintBase*, size_t> m_printbase_to_texture;
|
std::map<PrintBase*, size_t> m_printbase_to_texture;
|
||||||
|
std::array<int, MAX_NUMBER_OF_BEDS> m_occupied_beds_cache;
|
||||||
int m_last_hovered_bed = -1;
|
int m_last_hovered_bed = -1;
|
||||||
BoundingBoxf m_build_volume_bb;
|
BoundingBoxf m_build_volume_bb;
|
||||||
bool m_legacy_layout = false;
|
bool m_legacy_layout = false;
|
||||||
|
@ -139,6 +139,7 @@ void GLCanvas3D::select_bed(int i, bool triggered_by_user)
|
|||||||
wxGetApp().plater()->get_camera().translate_world(s_multiple_beds.get_bed_translation(i) - s_multiple_beds.get_bed_translation(old_bed));
|
wxGetApp().plater()->get_camera().translate_world(s_multiple_beds.get_bed_translation(i) - s_multiple_beds.get_bed_translation(old_bed));
|
||||||
}
|
}
|
||||||
wxGetApp().plater()->schedule_background_process();
|
wxGetApp().plater()->schedule_background_process();
|
||||||
|
wxGetApp().plater()->object_list_changed(); // Updates Slice Now / Export buttons.
|
||||||
if (s_multiple_beds.is_autoslicing() && triggered_by_user)
|
if (s_multiple_beds.is_autoslicing() && triggered_by_user)
|
||||||
s_multiple_beds.stop_autoslice(false);
|
s_multiple_beds.stop_autoslice(false);
|
||||||
});
|
});
|
||||||
@ -6314,7 +6315,7 @@ void GLCanvas3D::_render_overlays()
|
|||||||
void Slic3r::GUI::GLCanvas3D::_render_bed_selector()
|
void Slic3r::GUI::GLCanvas3D::_render_bed_selector()
|
||||||
{
|
{
|
||||||
static float btn_side = 80.f;
|
static float btn_side = 80.f;
|
||||||
static float btn_border = 4.f;
|
static float btn_border = 2.f;
|
||||||
static bool hide_title = true;
|
static bool hide_title = true;
|
||||||
|
|
||||||
ImVec2 btn_size = ImVec2(btn_side, btn_side);
|
ImVec2 btn_size = ImVec2(btn_side, btn_side);
|
||||||
@ -6325,27 +6326,38 @@ void Slic3r::GUI::GLCanvas3D::_render_bed_selector()
|
|||||||
//ImGui::Text("%d", i);
|
//ImGui::Text("%d", i);
|
||||||
//ImGui::SameLine();
|
//ImGui::SameLine();
|
||||||
|
|
||||||
|
bool empty = ! s_multiple_beds.is_bed_occupied(i);
|
||||||
bool inactive = i != s_multiple_beds.get_active_bed() || s_multiple_beds.is_autoslicing();
|
bool inactive = i != s_multiple_beds.get_active_bed() || s_multiple_beds.is_autoslicing();
|
||||||
if (inactive)
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0., 0., 0., .5));
|
ImGui::PushStyleColor(ImGuiCol_Button, ImGuiPureWrap::COL_GREY_DARK);
|
||||||
if (bool clicked = (i >= int(s_th_tex_id.size()))
|
ImGui::PushStyleColor(ImGuiCol_Border, inactive ? ImGuiPureWrap::COL_GREY_DARK : ImGuiPureWrap::COL_BUTTON_ACTIVE);
|
||||||
? ImGui::Button(std::to_string(i).c_str(), btn_size)
|
|
||||||
: ImGui::ImageButton((void*)(int64_t)s_th_tex_id[i], btn_size, ImVec2(0, 1), ImVec2(1, 0));
|
if (empty)
|
||||||
clicked)
|
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
|
||||||
|
|
||||||
|
bool clicked = false;
|
||||||
|
ImVec2 btn_padding = ImVec2(btn_border, btn_border);
|
||||||
|
if (i >= int(s_th_tex_id.size()) || empty)
|
||||||
|
clicked = ImGui::Button(empty ? "empty" : std::to_string(i + 1).c_str(), btn_size + btn_padding);
|
||||||
|
else
|
||||||
|
clicked = ImGui::ImageButton((void*)(int64_t)s_th_tex_id[i], btn_size - btn_padding, ImVec2(0, 1), ImVec2(1, 0), btn_border);
|
||||||
|
|
||||||
|
if (clicked && ! empty)
|
||||||
select_bed(i, true);
|
select_bed(i, true);
|
||||||
|
|
||||||
if (inactive)
|
ImGui::PopStyleColor(2);
|
||||||
ImGui::PopStyleColor();
|
if (empty)
|
||||||
|
ImGui::PopItemFlag();
|
||||||
|
|
||||||
std::string status_text;
|
//std::string status_text;
|
||||||
if (wxGetApp().plater()->get_fff_prints()[i]->finished())
|
//if (wxGetApp().plater()->get_fff_prints()[i]->finished())
|
||||||
status_text = "Finished";
|
// status_text = "Finished";
|
||||||
else if (m_process->fff_print() == wxGetApp().plater()->get_fff_prints()[i].get() && m_process->running())
|
//else if (m_process->fff_print() == wxGetApp().plater()->get_fff_prints()[i].get() && m_process->running())
|
||||||
status_text = "Running";
|
// status_text = "Running";
|
||||||
else
|
//else
|
||||||
status_text = "Idle";
|
// status_text = "Idle";
|
||||||
if (ImGui::IsItemHovered())
|
//if (ImGui::IsItemHovered())
|
||||||
ImGui::SetTooltip(status_text.c_str());
|
// ImGui::SetTooltip(status_text.c_str());
|
||||||
};
|
};
|
||||||
|
|
||||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||||
@ -6365,9 +6377,8 @@ void Slic3r::GUI::GLCanvas3D::_render_bed_selector()
|
|||||||
#endif
|
#endif
|
||||||
ImGui::Begin("Bed selector", 0, ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar);
|
ImGui::Begin("Bed selector", 0, ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar);
|
||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.f);
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, ImVec2());
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, ImVec2());
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(btn_border, btn_border));
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2());
|
||||||
|
|
||||||
// Disable for now.
|
// Disable for now.
|
||||||
//if (imgui.image_button(ImGui::SliceAllBtnIcon, "Slice All")) {
|
//if (imgui.image_button(ImGui::SliceAllBtnIcon, "Slice All")) {
|
||||||
@ -6386,7 +6397,7 @@ void Slic3r::GUI::GLCanvas3D::_render_bed_selector()
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::PopStyleVar(4);
|
ImGui::PopStyleVar(3);
|
||||||
|
|
||||||
#if use_scrolling
|
#if use_scrolling
|
||||||
bool extra_frame{ false };
|
bool extra_frame{ false };
|
||||||
|
@ -1874,7 +1874,7 @@ void Plater::priv::object_list_changed()
|
|||||||
// XXX: is this right?
|
// XXX: is this right?
|
||||||
const bool model_fits = view3D->get_canvas3d()->check_volumes_outside_state() == ModelInstancePVS_Inside;
|
const bool model_fits = view3D->get_canvas3d()->check_volumes_outside_state() == ModelInstancePVS_Inside;
|
||||||
|
|
||||||
sidebar->enable_buttons(!model.objects.empty() && !export_in_progress && model_fits);
|
sidebar->enable_buttons(s_multiple_beds.is_bed_occupied(s_multiple_beds.get_active_bed()) && !model.objects.empty() && !export_in_progress && model_fits);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::priv::select_all()
|
void Plater::priv::select_all()
|
||||||
@ -2979,13 +2979,17 @@ void Plater::priv::set_current_panel(wxPanel* panel)
|
|||||||
// FIXME: it may be better to have a single function making this check and let it be called wherever needed
|
// FIXME: it may be better to have a single function making this check and let it be called wherever needed
|
||||||
bool export_in_progress = this->background_process.is_export_scheduled();
|
bool export_in_progress = this->background_process.is_export_scheduled();
|
||||||
bool model_fits = view3D->get_canvas3d()->check_volumes_outside_state() != ModelInstancePVS_Partly_Outside;
|
bool model_fits = view3D->get_canvas3d()->check_volumes_outside_state() != ModelInstancePVS_Partly_Outside;
|
||||||
if (!model.objects.empty() && !export_in_progress && model_fits) {
|
if (s_multiple_beds.is_bed_occupied(s_multiple_beds.get_active_bed()) && !model.objects.empty() && !export_in_progress && model_fits) {
|
||||||
preview->get_canvas3d()->init_gcode_viewer();
|
preview->get_canvas3d()->init_gcode_viewer();
|
||||||
preview->load_gcode_shells();
|
preview->load_gcode_shells();
|
||||||
q->reslice();
|
q->reslice();
|
||||||
}
|
}
|
||||||
// keeps current gcode preview, if any
|
// keeps current gcode preview, if any
|
||||||
preview->reload_print();
|
preview->reload_print();
|
||||||
|
|
||||||
|
if (! s_multiple_beds.is_bed_occupied(s_multiple_beds.get_active_bed()))
|
||||||
|
preview->get_canvas3d()->reset_gcode_toolpaths();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
preview->set_as_dirty();
|
preview->set_as_dirty();
|
||||||
@ -4564,6 +4568,11 @@ void Plater::reload_print()
|
|||||||
p->preview->reload_print();
|
p->preview->reload_print();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Plater::object_list_changed()
|
||||||
|
{
|
||||||
|
p->object_list_changed();
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<size_t> Plater::load_files(const std::vector<fs::path>& input_files, bool load_model, bool load_config, bool imperial_units /*= false*/) { return p->load_files(input_files, load_model, load_config, imperial_units); }
|
std::vector<size_t> Plater::load_files(const std::vector<fs::path>& input_files, bool load_model, bool load_config, bool imperial_units /*= false*/) { return p->load_files(input_files, load_model, load_config, imperial_units); }
|
||||||
|
|
||||||
// To be called when providing a list of files to the GUI slic3r on command line.
|
// To be called when providing a list of files to the GUI slic3r on command line.
|
||||||
@ -5535,8 +5544,9 @@ void Plater::apply_cut_object_to_model(size_t obj_idx, const ModelObjectPtrs& ne
|
|||||||
size_t last_id = p->model.objects.size() - 1;
|
size_t last_id = p->model.objects.size() - 1;
|
||||||
for (size_t i = 0; i < new_objects.size(); ++i) {
|
for (size_t i = 0; i < new_objects.size(); ++i) {
|
||||||
selection.add_object((unsigned int)(last_id - i), i == 0);
|
selection.add_object((unsigned int)(last_id - i), i == 0);
|
||||||
const ObjectID instance_id{p->model.objects[last_id - i]->instances.front()->id().id};
|
const ModelInstance* mi = p->model.objects[last_id - i]->instances.front();
|
||||||
s_multiple_beds.set_instance_bed(instance_id, s_multiple_beds.get_active_bed());
|
const ObjectID instance_id{mi->id().id};
|
||||||
|
s_multiple_beds.set_instance_bed(instance_id, mi->printable, s_multiple_beds.get_active_bed());
|
||||||
}
|
}
|
||||||
|
|
||||||
UIThreadWorker w;
|
UIThreadWorker w;
|
||||||
|
@ -117,6 +117,7 @@ public:
|
|||||||
void convert_gcode_to_ascii();
|
void convert_gcode_to_ascii();
|
||||||
void convert_gcode_to_binary();
|
void convert_gcode_to_binary();
|
||||||
void reload_print();
|
void reload_print();
|
||||||
|
void object_list_changed();
|
||||||
|
|
||||||
std::vector<size_t> load_files(const std::vector<boost::filesystem::path>& input_files, bool load_model = true, bool load_config = true, bool imperial_units = false);
|
std::vector<size_t> load_files(const std::vector<boost::filesystem::path>& input_files, bool load_model = true, bool load_config = true, bool imperial_units = false);
|
||||||
// To be called when providing a list of files to the GUI slic3r on command line.
|
// To be called when providing a list of files to the GUI slic3r on command line.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user