diff --git a/resources/images/im_all_plates_stats.svg b/resources/images/im_all_plates_stats.svg
new file mode 100644
index 000000000..e0ac402c3
--- /dev/null
+++ b/resources/images/im_all_plates_stats.svg
@@ -0,0 +1,7 @@
+
diff --git a/resources/images/im_all_plates_stats_transparent.svg b/resources/images/im_all_plates_stats_transparent.svg
new file mode 100644
index 000000000..b60c5d362
--- /dev/null
+++ b/resources/images/im_all_plates_stats_transparent.svg
@@ -0,0 +1,7 @@
+
diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp
index c7c4f1480..f1f1c8ad1 100644
--- a/src/slic3r/GUI/GCodeViewer.cpp
+++ b/src/slic3r/GUI/GCodeViewer.cpp
@@ -4118,6 +4118,210 @@ void GCodeViewer::render_shells()
// glsafe(::glDepthMask(GL_TRUE));
}
+//BBS
+void GCodeViewer::render_all_plates_stats(const std::vector& gcode_result_list, bool show /*= true*/) const {
+ if (!show)
+ return;
+ ImGuiWrapper& imgui = *wxGetApp().imgui();
+
+ ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
+ ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0, 10.0 * m_scale));
+ ImGui::PushStyleColor(ImGuiCol_Separator, ImVec4(1.0f, 1.0f, 1.0f, 0.6f));
+ ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
+ ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
+ ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, ImVec4(0.42f, 0.42f, 0.42f, 1.00f));
+ ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, ImVec4(0.93f, 0.93f, 0.93f, 1.00f));
+ ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, ImVec4(0.93f, 0.93f, 0.93f, 1.00f));
+ ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(340.f * m_scale * imgui.scaled(1.0f / 15.0f), 0));
+
+ ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), 0, ImVec2(0.5f, 0.5f));
+ ImGui::Begin(_L("Statistics of All Plates").c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
+ ImDrawList* draw_list = ImGui::GetWindowDrawList();
+
+ std::vector filament_diameters = gcode_result_list.front()->filament_diameters;
+ std::vector filament_densities = gcode_result_list.front()->filament_densities;
+ std::vector filament_colors = decode_colors(wxGetApp().plater()->get_extruder_colors_from_plater_config(gcode_result_list.back()));
+
+ bool imperial_units = wxGetApp().app_config->get("use_inches") == "1";
+ float window_padding = 4.0f * m_scale;
+ const float icon_size = ImGui::GetTextLineHeight() * 0.7;
+ std::vector offsets;
+ std::map volume_of_extruders_all_plates; // map
+ std::map flushed_volume_of_extruders_all_plates; // map
+ std::vector model_used_filaments_m_all_plates;
+ std::vector model_used_filaments_g_all_plates;
+ std::vector flushed_filaments_m_all_plates;
+ std::vector flushed_filaments_g_all_plates;
+ float total_time_all_plates = 0.0f;
+ bool show_detailed_statistics_page = false;
+
+ auto max_width = [](const std::vector& items, const std::string& title, float extra_size = 0.0f) {
+ float ret = ImGui::CalcTextSize(title.c_str()).x;
+ for (const std::string& item : items) {
+ ret = std::max(ret, extra_size + ImGui::CalcTextSize(item.c_str()).x);
+ }
+ return ret;
+ };
+ auto calculate_offsets = [max_width, window_padding](const std::vector>>& title_columns, float extra_size = 0.0f) {
+ const ImGuiStyle& style = ImGui::GetStyle();
+ std::vector offsets;
+ offsets.push_back(max_width(title_columns[0].second, title_columns[0].first, extra_size) + 3.0f * style.ItemSpacing.x + style.WindowPadding.x);
+ for (size_t i = 1; i < title_columns.size() - 1; i++)
+ offsets.push_back(offsets.back() + max_width(title_columns[i].second, title_columns[i].first) + style.ItemSpacing.x);
+ if (title_columns.back().first == _u8L("Display"))
+ offsets.back() = ImGui::GetWindowWidth() - ImGui::CalcTextSize(_u8L("Display").c_str()).x - ImGui::GetFrameHeight() / 2 - 2 * window_padding;
+
+ float average_col_width = ImGui::GetWindowWidth() / static_cast(title_columns.size());
+ std::vector ret;
+ ret.push_back(0);
+ for (size_t i = 1; i < title_columns.size(); i++) {
+ ret.push_back(std::max(offsets[i - 1], i * average_col_width));
+ }
+
+ return ret;
+ };
+ auto append_item = [icon_size, &imgui, imperial_units, &window_padding, &draw_list, this](const Color& color, const std::vector>& columns_offsets)
+ {
+ // render icon
+ ImVec2 pos = ImVec2(ImGui::GetCursorScreenPos().x + window_padding * 3, ImGui::GetCursorScreenPos().y);
+
+ draw_list->AddRectFilled({ pos.x + 1.0f * m_scale, pos.y + 3.0f * m_scale }, { pos.x + icon_size - 1.0f * m_scale, pos.y + icon_size + 1.0f * m_scale },
+ ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }));
+
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(20.0 * m_scale, 6.0 * m_scale));
+
+ // render selectable
+ ImGui::Dummy({ 0.0, 0.0 });
+ ImGui::SameLine();
+
+ // render column item
+ {
+ float dummy_size = ImGui::GetStyle().ItemSpacing.x + icon_size;
+ ImGui::SameLine(dummy_size);
+ imgui.text(columns_offsets[0].first);
+
+ for (auto i = 1; i < columns_offsets.size(); i++) {
+ ImGui::SameLine(columns_offsets[i].second);
+ imgui.text(columns_offsets[i].first);
+ }
+ }
+
+ ImGui::PopStyleVar(1);
+ };
+ auto append_headers = [&imgui](const std::vector>& title_offsets) {
+ for (size_t i = 0; i < title_offsets.size(); i++) {
+ ImGui::SameLine(title_offsets[i].second);
+ imgui.bold_text(title_offsets[i].first);
+ }
+ ImGui::Separator();
+ };
+ auto get_used_filament_from_volume = [this, imperial_units, &filament_diameters, &filament_densities](double volume, int extruder_id) {
+ double koef = imperial_units ? 1.0 / GizmoObjectManipulation::in_to_mm : 0.001;
+ std::pair ret = { koef * volume / (PI * sqr(0.5 * filament_diameters[extruder_id])),
+ volume * filament_densities[extruder_id] * 0.001 };
+ return ret;
+ };
+
+ ImGui::Dummy({ window_padding, window_padding });
+ ImGui::SameLine();
+ // title and item data
+ {
+ PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
+ for (auto plate : plate_list.get_nonempty_plate_list())
+ {
+ auto plate_print_statistics = plate->get_slice_result()->print_statistics;
+ auto plate_extruders = plate->get_extruders(true);
+ for (size_t extruder_id : plate_extruders) {
+ extruder_id -= 1;
+ if (plate_print_statistics.volumes_per_extruder.find(extruder_id) == plate_print_statistics.volumes_per_extruder.end())
+ continue;
+ double volume = plate_print_statistics.volumes_per_extruder.at(extruder_id);
+ volume_of_extruders_all_plates[extruder_id] += volume;
+ if (plate_print_statistics.flush_per_filament.find(extruder_id) == plate_print_statistics.flush_per_filament.end())
+ flushed_volume_of_extruders_all_plates[extruder_id] = 0;
+ else {
+ double flushed_volume = plate_print_statistics.flush_per_filament.at(extruder_id);
+ flushed_volume_of_extruders_all_plates[extruder_id] += flushed_volume;
+ }
+ }
+ const PrintEstimatedStatistics::Mode& plate_time_mode = plate_print_statistics.modes[static_cast(m_time_estimate_mode)];
+ total_time_all_plates += plate_time_mode.time;
+ }
+
+ for (auto it = volume_of_extruders_all_plates.begin(); it != volume_of_extruders_all_plates.end(); it++) {
+ auto [model_used_filament_m, model_used_filament_g] = get_used_filament_from_volume(it->second, it->first);
+ model_used_filaments_m_all_plates.push_back(model_used_filament_m);
+ model_used_filaments_g_all_plates.push_back(model_used_filament_g);
+ }
+ for (auto it = flushed_volume_of_extruders_all_plates.begin(); it != flushed_volume_of_extruders_all_plates.end(); it++) {
+ auto [flushed_filament_m, flushed_filament_g] = get_used_filament_from_volume(it->second, it->first);
+ if (flushed_filament_m != 0.0 || flushed_filament_g != 0.0)
+ show_detailed_statistics_page = true;
+ flushed_filaments_m_all_plates.push_back(flushed_filament_m);
+ flushed_filaments_g_all_plates.push_back(flushed_filament_g);
+ }
+
+ char buff[64];
+ double longest_str = 0.0;
+ for (auto i : model_used_filaments_g_all_plates) {
+ if (i > longest_str)
+ longest_str = i;
+ }
+ ::sprintf(buff, "%.2f", longest_str);
+ offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), {buff}}, {_u8L("Flushed"), {buff}}, /*{_u8L("Tower"), total_filaments},*/ {_u8L("Total"), {buff}} }, icon_size);
+
+ if (!show_detailed_statistics_page)
+ append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[2]} });
+ else
+ append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, /*{_u8L("Tower"), offsets[3]},*/ {_u8L("Total"), offsets[3]} });// to add Tower
+ }
+
+ // item
+ {
+ size_t i = 0;
+ for (auto it = volume_of_extruders_all_plates.begin(); it != volume_of_extruders_all_plates.end(); it++) {
+ if (i < model_used_filaments_m_all_plates.size() && i < model_used_filaments_g_all_plates.size()) {
+ std::vector> columns_offsets;
+ columns_offsets.push_back({ std::to_string(it->first + 1), offsets[0] });
+
+ char buf[64];
+ if (show_detailed_statistics_page) {
+ ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i]);
+ columns_offsets.push_back({ buf, offsets[1] });
+
+ ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m_all_plates[i], flushed_filaments_g_all_plates[i]);
+ columns_offsets.push_back({ buf, offsets[2] });
+
+ ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i] + flushed_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] + flushed_filaments_g_all_plates[i]);
+ columns_offsets.push_back({ buf, offsets[3] });
+ }
+ else {
+ ::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i]);
+ columns_offsets.push_back({ buf, offsets[2] });
+ }
+
+ append_item(filament_colors[it->first], columns_offsets);
+ }
+ i++;
+ }
+
+ ImGui::Dummy(ImVec2(0.0f, ImGui::GetFontSize() * 0.1));
+ ImGui::Dummy({ window_padding, window_padding });
+ ImGui::SameLine();
+ imgui.title(_u8L("Total Time Estimation"));
+
+ ImGui::Dummy({ window_padding, window_padding });
+ ImGui::SameLine();
+ imgui.text(_u8L("Total time") + ":");
+ ImGui::SameLine();
+ imgui.text(short_time(get_time_dhms(total_time_all_plates)));
+ }
+ ImGui::End();
+ ImGui::PopStyleColor(6);
+ ImGui::PopStyleVar(3);
+ return;
+}
+
void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canvas_height, int right_margin)
{
if (!m_legend_enabled)
@@ -4381,6 +4585,14 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
return std::make_pair(it->second.first * koef, it->second.second);
};
+ // get used filament (meters and grams) from used volume in respect to the active extruder
+ auto get_used_filament_from_volume = [this, imperial_units](double volume, int extruder_id) {
+ double koef = imperial_units ? 1.0 / GizmoObjectManipulation::in_to_mm : 0.001;
+ std::pair ret = { koef * volume / (PI * sqr(0.5 * m_filament_diameters[extruder_id])),
+ volume * m_filament_densities[extruder_id] * 0.001 };
+ return ret;
+ };
+
//BBS display Color Scheme
ImGui::Dummy({ window_padding, window_padding });
ImGui::Dummy({ window_padding, window_padding });
@@ -4460,13 +4672,6 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
double koef = imperial_units ? GizmoObjectManipulation::in_to_mm : 1000.0;
double unit_conver = imperial_units ? GizmoObjectManipulation::oz_to_g : 1;
- // get used filament (meters and grams) from used volume in respect to the active extruder
- auto get_used_filament_from_volume = [this, imperial_units](double volume, int extruder_id) {
- double koef = imperial_units ? 1.0 / GizmoObjectManipulation::in_to_mm : 0.001;
- std::pair ret = { koef * volume / (PI * sqr(0.5 * m_filament_diameters[extruder_id])),
- volume * m_filament_densities[extruder_id] * 0.001 };
- return ret;
- };
// extrusion paths section -> title
ImGui::Dummy({ window_padding, window_padding });
@@ -4746,13 +4951,13 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
char buf[64];
if (show_flushed_filaments) {
- ::sprintf(buf, imperial_units ? "%.2f in\n%.2f g" : "%.2f m\n%.2f g", model_used_filaments_m[i], model_used_filaments_g[i]);
+ ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m[i], model_used_filaments_g[i]);
columns_offsets.push_back({ buf, offsets[1] });
- ::sprintf(buf, imperial_units ? "%.2f in\n%.2f g" : "%.2f m\n%.2f g", flushed_filaments_m[i], flushed_filaments_g[i]);
+ ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m[i], flushed_filaments_g[i]);
columns_offsets.push_back({ buf, offsets[2] });
- ::sprintf(buf, imperial_units ? "%.2f in\n%.2f g" : "%.2f m\n%.2f g", model_used_filaments_m[i] + flushed_filaments_m[i], model_used_filaments_g[i] + flushed_filaments_g[i]);
+ ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m[i] + flushed_filaments_m[i], model_used_filaments_g[i] + flushed_filaments_g[i]);
columns_offsets.push_back({ buf, offsets[3] });
}
else {
@@ -5289,16 +5494,16 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
}
default : { assert(false); break; }
}
+ }
- if (m_view_type == EViewType::ColorPrint) {
- ImGui::Spacing();
- ImGui::Dummy({ window_padding, window_padding });
- ImGui::SameLine();
- offsets = calculate_offsets({ { _u8L("Options"), { ""}}, { _u8L("Display"), {""}} }, icon_size);
- append_headers({ {_u8L("Options"), offsets[0] }, { _u8L("Display"), offsets[1]} });
- for (auto item : options_items)
- append_option_item(item, offsets);
- }
+ if (m_view_type == EViewType::ColorPrint) {
+ ImGui::Spacing();
+ ImGui::Dummy({ window_padding, window_padding });
+ ImGui::SameLine();
+ offsets = calculate_offsets({ { _u8L("Options"), { ""}}, { _u8L("Display"), {""}} }, icon_size);
+ append_headers({ {_u8L("Options"), offsets[0] }, { _u8L("Display"), offsets[1]} });
+ for (auto item : options_items)
+ append_option_item(item, offsets);
}
legend_height = ImGui::GetCurrentWindow()->Size.y;
diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp
index 465b3a6ec..05cca2039 100644
--- a/src/slic3r/GUI/GCodeViewer.hpp
+++ b/src/slic3r/GUI/GCodeViewer.hpp
@@ -805,6 +805,8 @@ public:
void reset_shell();
void load_shells(const Print& print, bool initialized, bool force_previewing = false);
void set_shells_on_preview(bool is_previewing) { m_shells.previewing = is_previewing; }
+ //BBS: add all plates filament statistics
+ void render_all_plates_stats(const std::vector& gcode_result_list, bool show = true) const;
//BBS: GUI refactor: add canvas width and height
void render(int canvas_width, int canvas_height, int right_margin);
//BBS
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index c3aaed90c..8d09ef48b 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -1145,6 +1145,7 @@ GLCanvas3D::~GLCanvas3D()
reset_volumes();
m_sel_plate_toolbar.del_all_item();
+ m_sel_plate_toolbar.del_stats_item();
}
void GLCanvas3D::post_event(wxEvent &&event)
@@ -1593,6 +1594,11 @@ void GLCanvas3D::enable_main_toolbar(bool enable)
m_main_toolbar.set_enabled(enable);
}
+void GLCanvas3D::reset_select_plate_toolbar_selection() {
+ if (m_sel_plate_toolbar.m_all_plates_stats_item)
+ m_sel_plate_toolbar.m_all_plates_stats_item->selected = false;
+}
+
void GLCanvas3D::enable_select_plate_toolbar(bool enable)
{
m_sel_plate_toolbar.set_enabled(enable);
@@ -1832,7 +1838,7 @@ void GLCanvas3D::render(bool only_init)
_render_platelist(!camera.is_looking_downward(), only_current, only_body, hover_id);
}
/* preview render */
- else if (m_canvas_type == ECanvasType::CanvasPreview) {
+ else if (m_canvas_type == ECanvasType::CanvasPreview && m_render_preview) {
//BBS: add outline logic
_render_objects(GLVolumeCollection::ERenderType::Opaque, !m_gizmos.is_running());
//BBS: GUI refactor: add canvas size as parameters
@@ -5802,6 +5808,9 @@ bool GLCanvas3D::_init_toolbars()
if (!_init_separator_toolbar())
return false;
+ if (!_init_select_plate_toolbar())
+ return false;
+
#if 0
if (!_init_view_toolbar())
return false;
@@ -5967,7 +5976,24 @@ bool GLCanvas3D::_init_main_toolbar()
//BBS: GUI refactor: GLToolbar
bool GLCanvas3D::_init_select_plate_toolbar()
{
- return true;
+ std::string path = resources_dir() + "/images/";
+ IMToolbarItem* item = new IMToolbarItem();
+ bool result = item->image_texture.load_from_svg_file(path + "im_all_plates_stats.svg", false, false, false, 128);
+ result = result && item->image_texture_transparent.load_from_svg_file(path + "im_all_plates_stats_transparent.svg", false, false, false, 128);
+ m_sel_plate_toolbar.m_all_plates_stats_item = item;
+
+ return result;
+}
+
+void GLCanvas3D::_update_select_plate_toolbar_stats_item(bool force_selected) {
+ PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
+ if (plate_list.get_nonempty_plate_list().size() > 1)
+ m_sel_plate_toolbar.show_stats_item = true;
+ else
+ m_sel_plate_toolbar.show_stats_item = false;
+
+ if (force_selected && m_sel_plate_toolbar.show_stats_item)
+ m_sel_plate_toolbar.m_all_plates_stats_item->selected = true;
}
bool GLCanvas3D::_update_imgui_select_plate_toolbar()
@@ -5975,6 +6001,8 @@ bool GLCanvas3D::_update_imgui_select_plate_toolbar()
bool result = true;
if (!m_sel_plate_toolbar.is_enabled()) return false;
+ _update_select_plate_toolbar_stats_item();
+
m_sel_plate_toolbar.del_all_item();
PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
@@ -5990,6 +6018,7 @@ bool GLCanvas3D::_update_imgui_select_plate_toolbar()
}
m_sel_plate_toolbar.m_items.push_back(item);
}
+
m_sel_plate_toolbar.is_display_scrollbar = false;
return result;
}
@@ -7080,20 +7109,23 @@ void GLCanvas3D::_render_main_toolbar()
//BBS: GUI refactor: GLToolbar adjust
//when rendering, {0, 0} is at the center, {-0.5, 0.5} at the left-up
-void GLCanvas3D::_render_imgui_select_plate_toolbar() const
+void GLCanvas3D::_render_imgui_select_plate_toolbar()
{
if (!m_sel_plate_toolbar.is_enabled())
return;
+ IMToolbarItem* all_plates_stats_item = m_sel_plate_toolbar.m_all_plates_stats_item;
+
PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
for (int i = 0; i < plate_list.get_plate_count(); i++) {
if (i < m_sel_plate_toolbar.m_items.size()) {
- if (i == plate_list.get_curr_plate_index())
+ if (i == plate_list.get_curr_plate_index() && !all_plates_stats_item->selected)
m_sel_plate_toolbar.m_items[i]->selected = true;
else
m_sel_plate_toolbar.m_items[i]->selected = false;
m_sel_plate_toolbar.m_items[i]->percent = plate_list.get_plate(i)->get_slicing_percent();
+
if (plate_list.get_plate(i)->is_slice_result_valid()) {
if (plate_list.get_plate(i)->is_slice_result_ready_for_print())
m_sel_plate_toolbar.m_items[i]->slice_state = IMToolbarItem::SliceState::SLICED;
@@ -7107,6 +7139,39 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() const
m_sel_plate_toolbar.m_items[i]->slice_state = IMToolbarItem::SliceState::SLICING;
}
}
+ if (m_sel_plate_toolbar.show_stats_item) {
+ all_plates_stats_item->percent = 0.0f;
+
+ size_t sliced_plates_cnt = 0;
+ bool slice_failed = false;
+ for (auto plate : plate_list.get_nonempty_plate_list()) {
+ if (plate->is_slice_result_valid() && plate->is_slice_result_ready_for_print())
+ sliced_plates_cnt++;
+ if (plate->is_slice_result_valid() && !plate->is_slice_result_ready_for_print())
+ slice_failed = true;
+ }
+ all_plates_stats_item->percent = (float)(sliced_plates_cnt) / (float)(plate_list.get_nonempty_plate_list().size()) * 100.0f;
+
+ if (all_plates_stats_item->percent == 0.0f)
+ all_plates_stats_item->slice_state = IMToolbarItem::SliceState::UNSLICED;
+ else if (sliced_plates_cnt == plate_list.get_nonempty_plate_list().size())
+ all_plates_stats_item->slice_state = IMToolbarItem::SliceState::SLICED;
+ else if (all_plates_stats_item->percent < 100.0f)
+ all_plates_stats_item->slice_state = IMToolbarItem::SliceState::SLICING;
+
+ if (slice_failed)
+ all_plates_stats_item->slice_state = IMToolbarItem::SliceState::SLICE_FAILED;
+
+ if (all_plates_stats_item->selected && all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICED) {
+ m_gcode_viewer.render_all_plates_stats(plate_list.get_nonempty_plates_slice_results());
+ m_render_preview = false;
+ }
+ else{
+ m_gcode_viewer.render_all_plates_stats(plate_list.get_nonempty_plates_slice_results(), false);
+ m_render_preview = true;
+ }
+ }else
+ m_render_preview = true;
// places the toolbar on the top_left corner of the 3d scene
#if ENABLE_RETINA_GL
@@ -7130,7 +7195,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() const
float button_margin = frame_padding;
ImGuiWrapper& imgui = *wxGetApp().imgui();
- int item_count = m_sel_plate_toolbar.m_items.size();
+ int item_count = m_sel_plate_toolbar.m_items.size() + (m_sel_plate_toolbar.show_stats_item ? 1 : 0);
bool show_scroll = item_count * (button_height + frame_padding * 2.0f + button_margin) - button_margin + 22.0f * f_scale > canvas_h ? true: false;
show_scroll = m_sel_plate_toolbar.is_display_scrollbar && show_scroll;
float window_height = std::min(item_count * (button_height + (frame_padding + margin_size) * 2.0f + button_margin) - button_margin + 28.0f * f_scale, canvas_h);
@@ -7171,7 +7236,89 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() const
ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
ImVec2 margin = ImVec2(margin_size, margin_size);
- for (int i = 0; i < item_count; i++) {
+ if(m_sel_plate_toolbar.show_stats_item)
+ {
+ // draw image
+ ImVec2 button_start_pos = ImGui::GetCursorScreenPos();
+
+ if (all_plates_stats_item->selected) {
+ ImGui::PushStyleColor(ImGuiCol_Button, button_active);
+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_active);
+ ImGui::PushStyleColor(ImGuiCol_ButtonActive, button_active);
+ }
+ else {
+ ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(128.0f, 128.0f, 128.0f, 0.0f));
+ if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICE_FAILED) {
+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetStyleColorVec4(ImGuiCol_Button));
+ ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_Button));
+ }
+ else {
+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_hover);
+ ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.42f, 0.42f, 0.42f, 1.0f));
+ }
+ }
+
+ ImVec4 text_clr;
+ ImTextureID btn_texture_id;
+ if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::UNSLICED || all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICING || all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICE_FAILED)
+ {
+ text_clr = ImVec4(0, 174.0f / 255.0f, 66.0f / 255.0f, 0.2f);
+ btn_texture_id = (ImTextureID)(intptr_t)(all_plates_stats_item->image_texture_transparent.get_id());
+ }
+ else
+ {
+ text_clr = ImVec4(0, 174.0f / 255.0f, 66.0f / 255.0f, 1);
+ btn_texture_id = (ImTextureID)(intptr_t)(all_plates_stats_item->image_texture.get_id());
+ }
+
+ if (ImGui::ImageButton2(btn_texture_id, size, {0,0}, {1,1}, frame_padding, bg_col, tint_col, margin)) {
+ if (all_plates_stats_item->slice_state != IMToolbarItem::SliceState::SLICE_FAILED) {
+ if (m_process && !m_process->running()) {
+ for (int i = 0; i < m_sel_plate_toolbar.m_items.size(); i++) {
+ m_sel_plate_toolbar.m_items[i]->selected = false;
+ }
+ all_plates_stats_item->selected = true;
+ wxCommandEvent evt = wxCommandEvent(EVT_GLTOOLBAR_SLICE_ALL);
+ wxPostEvent(wxGetApp().plater(), evt);
+ }
+ }
+ }
+
+ ImGui::PopStyleColor(3);
+
+ ImVec2 start_pos = ImVec2(button_start_pos.x + frame_padding + margin.x, button_start_pos.y + frame_padding + margin.y);
+ if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::UNSLICED) {
+ ImVec2 size = ImVec2(button_width, button_height);
+ ImVec2 end_pos = ImVec2(start_pos.x + size.x, start_pos.y + size.y);
+ ImGui::GetForegroundDrawList()->AddRectFilled(start_pos, end_pos, IM_COL32(0, 0, 0, 80));
+ }
+ else if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICING) {
+ ImVec2 size = ImVec2(button_width, button_height * all_plates_stats_item->percent / 100.0f);
+ ImVec2 rect_start_pos = ImVec2(start_pos.x, start_pos.y + size.y);
+ ImVec2 rect_end_pos = ImVec2(start_pos.x + button_width, start_pos.y + button_height);
+ ImGui::GetForegroundDrawList()->AddRectFilled(rect_start_pos, rect_end_pos, IM_COL32(0, 0, 0, 80));
+ }
+ else if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICE_FAILED) {
+ ImVec2 size = ImVec2(button_width, button_height);
+ ImVec2 end_pos = ImVec2(start_pos.x + size.x, start_pos.y + size.y);
+ ImGui::GetForegroundDrawList()->AddRectFilled(start_pos, end_pos, IM_COL32(40, 1, 1, 64));
+ ImGui::GetForegroundDrawList()->AddRect(start_pos, end_pos, IM_COL32(208, 27, 27, 255), 0.0f, 0, 1.0f);
+ }
+
+ // draw text
+ GImGui->FontSize = 15.0f;
+ ImGui::PushStyleColor(ImGuiCol_Text, text_clr);
+ ImVec2 text_size = ImGui::CalcTextSize(_L("All Plates").c_str());
+ ImVec2 text_start_pos = ImVec2(start_pos.x + (button_width - text_size.x) / 2, start_pos.y + 3.0f * button_height / 5.0f);
+ ImGui::RenderText(text_start_pos, _L("All Plates").c_str());
+ text_size = ImGui::CalcTextSize(_L("Stats").c_str());
+ text_start_pos = ImVec2(start_pos.x + (button_width - text_size.x) / 2, text_start_pos.y + ImGui::GetTextLineHeight());
+ ImGui::RenderText(text_start_pos, _L("Stats").c_str());
+ ImGui::PopStyleColor();
+ ImGui::SetWindowFontScale(1.2f);
+ }
+
+ for (int i = 0; i < m_sel_plate_toolbar.m_items.size(); i++) {
IMToolbarItem* item = m_sel_plate_toolbar.m_items[i];
// draw image
@@ -7183,11 +7330,16 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() const
if (item->selected) {
ImGui::PushStyleColor(ImGuiCol_Button, button_active);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_active);
- } else
+ }
+ else {
+ ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(128.0f, 128.0f, 128.0f, 0.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.42f, 0.42f, 0.42f, 1.0f));
+ }
if (ImGui::ImageButton2(item->texture_id, size, uv0, uv1, frame_padding, bg_col, tint_col, margin)) {
if (m_process && !m_process->running()) {
+ all_plates_stats_item->selected = false;
+ item->selected = true;
// begin to slicing plate
wxCommandEvent* evt = new wxCommandEvent(EVT_GLTOOLBAR_SELECT_SLICED_PLATE);
evt->SetInt(i);
@@ -7195,10 +7347,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() const
}
}
- if (item->selected)
- ImGui::PopStyleColor(2);
- else
- ImGui::PopStyleColor(1);
+ ImGui::PopStyleColor(2);
ImVec2 start_pos = ImVec2(button_start_pos.x + frame_padding + margin.x, button_start_pos.y + frame_padding + margin.y);
if (item->slice_state == IMToolbarItem::SliceState::UNSLICED) {
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index 82a20b2d1..e1b0787e3 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -543,6 +543,7 @@ private:
bool m_dirty;
bool m_initialized;
//BBS: add flag to controll rendering
+ bool m_render_preview{ true };
bool m_enable_render { true };
bool m_apply_zoom_to_volumes_filter;
bool m_picking_enabled;
@@ -785,6 +786,8 @@ public:
void enable_selection(bool enable);
void enable_main_toolbar(bool enable);
//BBS: GUI refactor: GLToolbar
+ void _update_select_plate_toolbar_stats_item(bool force_selected = false);
+ void reset_select_plate_toolbar_selection();
void enable_select_plate_toolbar(bool enable);
void enable_assemble_view_toolbar(bool enable);
void enable_return_toolbar(bool enable);
@@ -1097,7 +1100,7 @@ private:
void _render_current_gizmo() const;
void _render_gizmos_overlay();
void _render_main_toolbar();
- void _render_imgui_select_plate_toolbar() const;
+ void _render_imgui_select_plate_toolbar();
void _render_assemble_view_toolbar() const;
void _render_return_toolbar() const;
void _render_separator_toolbar_right() const;
diff --git a/src/slic3r/GUI/IMToolbar.cpp b/src/slic3r/GUI/IMToolbar.cpp
index f1d3481f3..e14cdb2ff 100644
--- a/src/slic3r/GUI/IMToolbar.cpp
+++ b/src/slic3r/GUI/IMToolbar.cpp
@@ -52,6 +52,11 @@ void IMToolbar::del_all_item()
m_items.clear();
}
+void IMToolbar::del_stats_item()
+{
+ delete m_all_plates_stats_item;
+ m_all_plates_stats_item = nullptr;
+}
bool IMReturnToolbar::init()
{
diff --git a/src/slic3r/GUI/IMToolbar.hpp b/src/slic3r/GUI/IMToolbar.hpp
index c30b2e6ef..681045fdb 100644
--- a/src/slic3r/GUI/IMToolbar.hpp
+++ b/src/slic3r/GUI/IMToolbar.hpp
@@ -27,10 +27,11 @@ public:
bool selected{ false };
float percent;
- ImTextureID texture_id { 0 };
GLTexture image_texture;
+ GLTexture image_texture_transparent;
SliceState slice_state;
+ ImTextureID texture_id { 0 };
std::vector image_data;
unsigned int image_width;
unsigned int image_height;
@@ -47,6 +48,7 @@ public:
float icon_width;
float icon_height;
bool is_display_scrollbar;
+ bool show_stats_item{ false };
IMToolbar() {
icon_width = DEFAULT_TOOLBAR_BUTTON_WIDTH;
@@ -54,7 +56,9 @@ public:
}
void del_all_item();
+ void del_stats_item();
+ IMToolbarItem* m_all_plates_stats_item = nullptr;
std::vector m_items;
float fontScale;
diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp
index c2b18f3e9..cf86833ec 100644
--- a/src/slic3r/GUI/PartPlate.cpp
+++ b/src/slic3r/GUI/PartPlate.cpp
@@ -3105,6 +3105,25 @@ PartPlate* PartPlateList::get_selected_plate()
return m_plate_list[m_current_plate];
}
+std::vector PartPlateList::get_nonempty_plate_list()
+{
+ std::vector nonempty_plate_list;
+ for (auto plate : m_plate_list){
+ if (plate->get_extruders().size() != 0) {
+ nonempty_plate_list.push_back(plate);
+ }
+ }
+ return nonempty_plate_list;
+}
+
+std::vector PartPlateList::get_nonempty_plates_slice_results() {
+ std::vector nonempty_plates_slice_result;
+ for (auto plate : get_nonempty_plate_list()) {
+ nonempty_plates_slice_result.push_back(plate->get_slice_result());
+ }
+ return nonempty_plates_slice_result;
+}
+
//select plate
int PartPlateList::select_plate(int index)
{
diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp
index f2d76262c..78305e299 100644
--- a/src/slic3r/GUI/PartPlate.hpp
+++ b/src/slic3r/GUI/PartPlate.hpp
@@ -626,6 +626,10 @@ public:
PartPlate* get_selected_plate();
+ std::vector get_nonempty_plate_list();
+
+ std::vector get_nonempty_plates_slice_results();
+
Vec3d get_current_plate_origin() { return compute_origin(m_current_plate, m_plate_cols); }
Vec2d get_current_shape_position() { return compute_shape_position(m_current_plate, m_plate_cols); }
Pointfs get_exclude_area() { return m_exclude_areas; }
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 38d744680..e14f031c8 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -1688,6 +1688,8 @@ struct Plater::priv
bool m_is_slicing {false};
bool m_is_publishing {false};
int m_cur_slice_plate;
+ //BBS: m_slice_all in .gcode.3mf file case, set true when slice all
+ bool m_slice_all_only_has_gcode{ false };
bool m_need_update{false};
//BBS: add popup object table logic
@@ -5310,6 +5312,9 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice)
return;
}
+ //BBS: wish to reset all plates stats item selected state when back to View3D Tab
+ preview->get_canvas3d()->reset_select_plate_toolbar_selection();
+
wxPanel* old_panel = current_panel;
//#if BBL_HAS_FIRST_PAGE
if (!old_panel) {
@@ -5810,6 +5815,20 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
//BBS: add project slice logic
bool is_finished = !m_slice_all || (m_cur_slice_plate == (partplate_list.get_plate_count() - 1));
+ //BBS: slice .gcode.3mf file related logic, assign is_finished again
+ bool only_has_gcode_need_preview = false;
+ auto plate_list = this->partplate_list.get_plate_list();
+ bool has_print_instances = false;
+ for (auto plate : plate_list)
+ has_print_instances = has_print_instances || plate->has_printable_instances();
+ if (this->model.objects.empty() && !has_print_instances)
+ only_has_gcode_need_preview = true;
+ if (only_has_gcode_need_preview && m_slice_all_only_has_gcode) {
+ is_finished = (m_cur_slice_plate == (partplate_list.get_plate_count() - 1));
+ if (is_finished)
+ m_slice_all_only_has_gcode = false;
+ }
+
// Stop the background task, wait until the thread goes into the "Idle" state.
// At this point of time the thread should be either finished or canceled,
// so the following call just confirms, that the produced data were consumed.
@@ -6058,12 +6077,15 @@ void Plater::priv::on_action_slice_all(SimpleEvent&)
Plater::setExtruderParams(Slic3r::Model::extruderParamsMap);
Plater::setPrintSpeedTable(Slic3r::Model::printSpeedMap);
m_slice_all = true;
+ m_slice_all_only_has_gcode = true;
m_cur_slice_plate = 0;
//select plate
q->select_plate(m_cur_slice_plate);
q->reslice();
if (!m_is_publishing)
q->select_view_3D("Preview");
+ //BBS: wish to select all plates stats item
+ preview->get_canvas3d()->_update_select_plate_toolbar_stats_item(true);
}
}
@@ -8090,7 +8112,13 @@ void Plater::force_update_all_plate_thumbnails()
}
// BBS: backup
-std::vector Plater::load_files(const std::vector& input_files, LoadStrategy strategy, bool ask_multi) { return p->load_files(input_files, strategy, ask_multi); }
+std::vector Plater::load_files(const std::vector& input_files, LoadStrategy strategy, bool ask_multi) {
+ //BBS: wish to reset state when load a new file
+ p->m_slice_all_only_has_gcode = false;
+ //BBS: wish to reset all plates stats item selected state when load a new file
+ p->preview->get_canvas3d()->reset_select_plate_toolbar_selection();
+ return p->load_files(input_files, strategy, ask_multi);
+}
// To be called when providing a list of files to the GUI slic3r on command line.
std::vector Plater::load_files(const std::vector& input_files, LoadStrategy strategy, bool ask_multi)