mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-24 09:23:27 +00:00
mixed filament re-ordering
This commit is contained in:
@@ -113,6 +113,30 @@ float RetinaHelper::get_scale_factor() { return float(m_window->GetContentScaleF
|
||||
#undef Convex
|
||||
#endif
|
||||
|
||||
static std::vector<unsigned int> get_ui_ordered_filament_ids(Plater *plater, size_t total_filaments)
|
||||
{
|
||||
std::vector<unsigned int> ordered_ids;
|
||||
if (plater != nullptr)
|
||||
ordered_ids = plater->sidebar().get_ui_ordered_filament_ids();
|
||||
|
||||
std::vector<unsigned int> sanitized_ids;
|
||||
sanitized_ids.reserve(total_filaments);
|
||||
std::vector<bool> used(total_filaments + 1, false);
|
||||
for (const unsigned int filament_id : ordered_ids) {
|
||||
if (filament_id == 0 || filament_id > total_filaments || used[filament_id])
|
||||
continue;
|
||||
used[filament_id] = true;
|
||||
sanitized_ids.emplace_back(filament_id);
|
||||
}
|
||||
|
||||
for (unsigned int filament_id = 1; filament_id <= total_filaments; ++filament_id) {
|
||||
if (!used[filament_id])
|
||||
sanitized_ids.emplace_back(filament_id);
|
||||
}
|
||||
|
||||
return sanitized_ids;
|
||||
}
|
||||
|
||||
GLCanvas3D::LayersEditing::~LayersEditing()
|
||||
{
|
||||
if (m_z_texture_id != 0) {
|
||||
@@ -3304,8 +3328,16 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
||||
if (keyCode < '7') keyCode += 10;
|
||||
m_timer_set_color.Stop();
|
||||
}
|
||||
if (m_gizmos.get_current_type() != GLGizmosManager::MmSegmentation)
|
||||
obj_list->set_extruder_for_selected_items(keyCode - '0');
|
||||
if (m_gizmos.get_current_type() != GLGizmosManager::MmSegmentation) {
|
||||
const int display_filament_id = keyCode - '0';
|
||||
const size_t total_filaments = wxGetApp().plater()->get_extruder_colors_from_plater_config().size();
|
||||
const std::vector<unsigned int> ordered_filament_ids =
|
||||
get_ui_ordered_filament_ids(wxGetApp().plater(), total_filaments);
|
||||
if (display_filament_id >= 1 && size_t(display_filament_id) <= ordered_filament_ids.size())
|
||||
obj_list->set_extruder_for_selected_items(int(ordered_filament_ids[size_t(display_filament_id - 1)]));
|
||||
else
|
||||
obj_list->set_extruder_for_selected_items(display_filament_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3847,8 +3879,11 @@ void GLCanvas3D::on_render_timer(wxTimerEvent& evt)
|
||||
void GLCanvas3D::on_set_color_timer(wxTimerEvent& evt)
|
||||
{
|
||||
auto obj_list = wxGetApp().obj_list();
|
||||
if (m_gizmos.get_current_type() != GLGizmosManager::MmSegmentation)
|
||||
obj_list->set_extruder_for_selected_items(1);
|
||||
if (m_gizmos.get_current_type() != GLGizmosManager::MmSegmentation) {
|
||||
const std::vector<unsigned int> ordered_filament_ids =
|
||||
get_ui_ordered_filament_ids(wxGetApp().plater(), wxGetApp().plater()->get_extruder_colors_from_plater_config().size());
|
||||
obj_list->set_extruder_for_selected_items(ordered_filament_ids.empty() ? 1 : int(ordered_filament_ids.front()));
|
||||
}
|
||||
m_timer_set_color.Stop();
|
||||
}
|
||||
|
||||
@@ -8354,28 +8389,52 @@ void GLCanvas3D::_render_paint_toolbar() const
|
||||
#endif
|
||||
int em_unit = wxGetApp().em_unit() / 10;
|
||||
|
||||
std::vector<std::string> colors = wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
||||
int extruder_num = colors.size();
|
||||
const std::vector<std::string> actual_colors = wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
||||
const std::vector<unsigned int> display_filament_ids =
|
||||
get_ui_ordered_filament_ids(wxGetApp().plater(), actual_colors.size());
|
||||
std::vector<std::string> colors;
|
||||
colors.reserve(display_filament_ids.size());
|
||||
for (const unsigned int filament_id : display_filament_ids) {
|
||||
if (filament_id >= 1 && filament_id <= actual_colors.size())
|
||||
colors.emplace_back(actual_colors[filament_id - 1]);
|
||||
}
|
||||
|
||||
const int extruder_num = int(colors.size());
|
||||
std::vector<std::string> filament_text_first_line;
|
||||
std::vector<std::string> filament_text_second_line;
|
||||
{
|
||||
auto preset_bundle = wxGetApp().preset_bundle;
|
||||
for (auto filament_name : preset_bundle->filament_presets) {
|
||||
for (auto iter = preset_bundle->filaments.lbegin(); iter != preset_bundle->filaments.end(); iter++) {
|
||||
if (filament_name.compare(iter->name) == 0) {
|
||||
const size_t physical_count = preset_bundle ? preset_bundle->filament_presets.size() : 0;
|
||||
filament_text_first_line.reserve(colors.size());
|
||||
filament_text_second_line.reserve(colors.size());
|
||||
for (size_t display_idx = 0; display_idx < display_filament_ids.size(); ++display_idx) {
|
||||
const unsigned int actual_filament_id = display_filament_ids[display_idx];
|
||||
bool label_found = false;
|
||||
if (preset_bundle != nullptr && actual_filament_id >= 1 && actual_filament_id <= physical_count) {
|
||||
const std::string &filament_name = preset_bundle->filament_presets[size_t(actual_filament_id - 1)];
|
||||
for (auto iter = preset_bundle->filaments.lbegin(); iter != preset_bundle->filaments.end(); ++iter) {
|
||||
if (filament_name.compare(iter->name) != 0)
|
||||
continue;
|
||||
|
||||
std::string display_filament_type;
|
||||
iter->config.get_filament_type(display_filament_type);
|
||||
auto pos = display_filament_type.find(' ');
|
||||
if (pos != std::string::npos) {
|
||||
filament_text_first_line.push_back(display_filament_type.substr(0, pos));
|
||||
filament_text_second_line.push_back(display_filament_type.substr(pos + 1));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
filament_text_first_line.push_back(display_filament_type);
|
||||
filament_text_second_line.push_back("");
|
||||
}
|
||||
label_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!label_found) {
|
||||
filament_text_first_line.push_back("Mixed");
|
||||
filament_text_second_line.push_back("Filament");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8417,8 +8476,11 @@ void GLCanvas3D::_render_paint_toolbar() const
|
||||
if (disabled)
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
|
||||
if (ImGui::Button(("##filament_button" + std::to_string(i)).c_str(), button_size)) {
|
||||
if (!ImGui::IsMouseHoveringRect(left_arrow_button.Min, left_arrow_button.Max) && !ImGui::IsMouseHoveringRect(right_arrow_button.Min, right_arrow_button.Max))
|
||||
wxPostEvent(m_canvas, IntEvent(EVT_GLTOOLBAR_FILLCOLOR, i + 1));
|
||||
if (!ImGui::IsMouseHoveringRect(left_arrow_button.Min, left_arrow_button.Max) && !ImGui::IsMouseHoveringRect(right_arrow_button.Min, right_arrow_button.Max)) {
|
||||
const int actual_filament_id =
|
||||
i < int(display_filament_ids.size()) ? int(display_filament_ids[size_t(i)]) : i + 1;
|
||||
wxPostEvent(m_canvas, IntEvent(EVT_GLTOOLBAR_FILLCOLOR, actual_filament_id));
|
||||
}
|
||||
}
|
||||
if (ImGui::IsItemHovered() && i < 9) {
|
||||
if (!ImGui::IsMouseHoveringRect(left_arrow_button.Min, left_arrow_button.Max) && !ImGui::IsMouseHoveringRect(right_arrow_button.Min, right_arrow_button.Max)) {
|
||||
|
||||
@@ -50,7 +50,14 @@ static int filaments_count()
|
||||
return static_cast<int>(mixed_mgr.total_filaments(size_t(physical)));
|
||||
}
|
||||
|
||||
static wxString filament_menu_item_name(const int filament_id_1based)
|
||||
static std::vector<unsigned int> ui_ordered_filament_ids()
|
||||
{
|
||||
if (wxGetApp().plater() == nullptr)
|
||||
return {};
|
||||
return wxGetApp().plater()->sidebar().get_ui_ordered_filament_ids();
|
||||
}
|
||||
|
||||
static wxString filament_menu_item_name(const int filament_id_1based, const int display_filament_id_1based)
|
||||
{
|
||||
if (filament_id_1based <= 0)
|
||||
return _L("Default");
|
||||
@@ -70,7 +77,7 @@ static wxString filament_menu_item_name(const int filament_id_1based)
|
||||
return wxString::Format(_L("Filament %d"), filament_id_1based);
|
||||
}
|
||||
|
||||
return wxString::Format(_L("Mixed Filament %d"), filament_id_1based);
|
||||
return wxString::Format(_L("Mixed Filament %d"), display_filament_id_1based);
|
||||
}
|
||||
|
||||
static bool is_improper_category(const std::string& category, const int filaments_cnt, const bool is_object_settings = true)
|
||||
@@ -912,8 +919,8 @@ void MenuFactory::append_menu_item_change_extruder(wxMenu* menu)
|
||||
menu->Destroy(item_id);
|
||||
}
|
||||
|
||||
const int filaments_cnt = filaments_count();
|
||||
if (filaments_cnt <= 1)
|
||||
const std::vector<unsigned int> ordered_filament_ids = ui_ordered_filament_ids();
|
||||
if (ordered_filament_ids.size() <= 1)
|
||||
return;
|
||||
|
||||
wxDataViewItemArray sels;
|
||||
@@ -932,12 +939,13 @@ void MenuFactory::append_menu_item_change_extruder(wxMenu* menu)
|
||||
initial_extruder = config.has("extruder") ? config.extruder() : 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i <= filaments_cnt; i++)
|
||||
for (size_t display_idx = 0; display_idx <= ordered_filament_ids.size(); ++display_idx)
|
||||
{
|
||||
bool is_active_extruder = i == initial_extruder;
|
||||
int icon_idx = i == 0 ? 0 : i - 1;
|
||||
const int actual_filament_id = display_idx == 0 ? 0 : int(ordered_filament_ids[display_idx - 1]);
|
||||
const bool is_active_extruder = actual_filament_id == initial_extruder;
|
||||
const int icon_idx = actual_filament_id == 0 ? 0 : actual_filament_id - 1;
|
||||
|
||||
wxString item_name = filament_menu_item_name(i);
|
||||
wxString item_name = filament_menu_item_name(actual_filament_id, int(display_idx));
|
||||
|
||||
if (is_active_extruder) {
|
||||
item_name << " (" + _L("current") + ")";
|
||||
@@ -945,11 +953,13 @@ void MenuFactory::append_menu_item_change_extruder(wxMenu* menu)
|
||||
|
||||
if (icon_idx >= 0 && icon_idx < icons.size()) {
|
||||
append_menu_item(
|
||||
extruder_selection_menu, wxID_ANY, item_name, "", [i](wxCommandEvent &) { obj_list()->set_extruder_for_selected_items(i); }, *icons[icon_idx], menu,
|
||||
extruder_selection_menu, wxID_ANY, item_name, "",
|
||||
[actual_filament_id](wxCommandEvent &) { obj_list()->set_extruder_for_selected_items(actual_filament_id); }, *icons[icon_idx], menu,
|
||||
[is_active_extruder]() { return !is_active_extruder; }, m_parent);
|
||||
} else {
|
||||
append_menu_item(
|
||||
extruder_selection_menu, wxID_ANY, item_name, "", [i](wxCommandEvent &) { obj_list()->set_extruder_for_selected_items(i); }, "", menu,
|
||||
extruder_selection_menu, wxID_ANY, item_name, "",
|
||||
[actual_filament_id](wxCommandEvent &) { obj_list()->set_extruder_for_selected_items(actual_filament_id); }, "", menu,
|
||||
[is_active_extruder]() { return !is_active_extruder; }, m_parent);
|
||||
}
|
||||
}
|
||||
@@ -1965,8 +1975,8 @@ void MenuFactory::append_menu_item_change_filament(wxMenu* menu)
|
||||
menu->Destroy(item_id);
|
||||
}
|
||||
|
||||
int filaments_cnt = filaments_count();
|
||||
if (filaments_cnt <= 1)
|
||||
const std::vector<unsigned int> ordered_filament_ids = ui_ordered_filament_ids();
|
||||
if (ordered_filament_ids.size() <= 1)
|
||||
return;
|
||||
|
||||
wxDataViewItemArray sels;
|
||||
@@ -1981,12 +1991,10 @@ void MenuFactory::append_menu_item_change_filament(wxMenu* menu)
|
||||
}
|
||||
|
||||
std::vector<wxBitmap*> icons = get_extruder_color_icons(true);
|
||||
if (icons.size() < filaments_cnt) {
|
||||
BOOST_LOG_TRIVIAL(warning) << boost::format("Warning: icons size %1%, filaments_cnt=%2%")%icons.size()%filaments_cnt;
|
||||
if (icons.size() < ordered_filament_ids.size()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << boost::format("Warning: icons size %1%, filaments_cnt=%2%") % icons.size() % ordered_filament_ids.size();
|
||||
if (icons.size() <= 1)
|
||||
return;
|
||||
else
|
||||
filaments_cnt = icons.size();
|
||||
}
|
||||
wxMenu* extruder_selection_menu = new wxMenu();
|
||||
const wxString& name = sels.Count() == 1 ? names[0] : names[1];
|
||||
@@ -2002,29 +2010,20 @@ void MenuFactory::append_menu_item_change_filament(wxMenu* menu)
|
||||
initial_extruder = config.has("extruder") ? config.extruder() : 0;
|
||||
}
|
||||
|
||||
// BBS
|
||||
bool has_modifier = false;
|
||||
for (auto sel : sels) {
|
||||
if (obj_list()->GetModel()->GetVolumeType(sel) == ModelVolumeType::PARAMETER_MODIFIER) {
|
||||
has_modifier = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (/*int i = has_modifier ? 0 : 1*/int i = 0; i <= filaments_cnt; i++)
|
||||
for (size_t display_idx = 0; display_idx <= ordered_filament_ids.size(); ++display_idx)
|
||||
{
|
||||
// BBS
|
||||
//bool is_active_extruder = i == initial_extruder;
|
||||
const int actual_filament_id = display_idx == 0 ? 0 : int(ordered_filament_ids[display_idx - 1]);
|
||||
bool is_active_extruder = false;
|
||||
|
||||
wxString item_name = filament_menu_item_name(i);
|
||||
wxString item_name = filament_menu_item_name(actual_filament_id, int(display_idx));
|
||||
|
||||
if (is_active_extruder) {
|
||||
item_name << " (" + _L("current") + ")";
|
||||
}
|
||||
|
||||
append_menu_item(extruder_selection_menu, wxID_ANY, item_name, "",
|
||||
[i](wxCommandEvent&) { obj_list()->set_extruder_for_selected_items(i); }, i == 0 ? wxNullBitmap : *icons[i - 1], menu,
|
||||
[actual_filament_id](wxCommandEvent&) { obj_list()->set_extruder_for_selected_items(actual_filament_id); },
|
||||
actual_filament_id == 0 || size_t(actual_filament_id - 1) >= icons.size() ? wxNullBitmap : *icons[size_t(actual_filament_id - 1)], menu,
|
||||
[is_active_extruder]() { return !is_active_extruder; }, m_parent);
|
||||
}
|
||||
menu->Append(wxID_ANY, name, extruder_selection_menu, _L("Change Filament"));
|
||||
|
||||
@@ -89,14 +89,48 @@ static std::vector<int> get_extruder_id_for_volumes(const ModelObject &model_obj
|
||||
return extruders_idx;
|
||||
}
|
||||
|
||||
static std::vector<unsigned int> get_display_filament_ids(size_t total_filaments)
|
||||
{
|
||||
std::vector<unsigned int> ordered_filament_ids;
|
||||
if (wxGetApp().plater() != nullptr)
|
||||
ordered_filament_ids = wxGetApp().plater()->sidebar().get_ui_ordered_filament_ids();
|
||||
|
||||
std::vector<unsigned int> sanitized_filament_ids;
|
||||
sanitized_filament_ids.reserve(total_filaments);
|
||||
std::vector<bool> used_filament_ids(total_filaments + 1, false);
|
||||
for (const unsigned int filament_id : ordered_filament_ids) {
|
||||
if (filament_id == 0 || filament_id > total_filaments || used_filament_ids[filament_id])
|
||||
continue;
|
||||
used_filament_ids[filament_id] = true;
|
||||
sanitized_filament_ids.emplace_back(filament_id);
|
||||
}
|
||||
|
||||
for (unsigned int filament_id = 1; filament_id <= total_filaments; ++filament_id) {
|
||||
if (!used_filament_ids[filament_id])
|
||||
sanitized_filament_ids.emplace_back(filament_id);
|
||||
}
|
||||
|
||||
return sanitized_filament_ids;
|
||||
}
|
||||
|
||||
void GLGizmoMmuSegmentation::init_extruders_data(const std::vector<ColorRGBA> &extruder_colors)
|
||||
{
|
||||
const size_t old_selected = m_selected_extruder_idx;
|
||||
const unsigned int old_selected_filament_id =
|
||||
m_selected_extruder_idx < m_display_filament_ids.size() ? m_display_filament_ids[m_selected_extruder_idx] :
|
||||
(m_selected_extruder_idx < m_extruders_colors.size() ? unsigned(m_selected_extruder_idx + 1) : 0);
|
||||
|
||||
m_extruders_colors = extruder_colors;
|
||||
m_selected_extruder_idx = m_extruders_colors.empty() ? 0 : std::min(old_selected, m_extruders_colors.size() - 1);
|
||||
m_display_filament_ids = get_display_filament_ids(m_extruders_colors.size());
|
||||
|
||||
m_selected_extruder_idx = 0;
|
||||
if (!m_display_filament_ids.empty()) {
|
||||
auto selected_it = std::find(m_display_filament_ids.begin(), m_display_filament_ids.end(), old_selected_filament_id);
|
||||
if (selected_it != m_display_filament_ids.end())
|
||||
m_selected_extruder_idx = size_t(std::distance(m_display_filament_ids.begin(), selected_it));
|
||||
}
|
||||
|
||||
// keep remap table consistent with current extruder count
|
||||
m_extruder_remap.resize(m_extruders_colors.size());
|
||||
m_extruder_remap.resize(m_display_filament_ids.size());
|
||||
for (size_t i = 0; i < m_extruder_remap.size(); ++i)
|
||||
m_extruder_remap[i] = i;
|
||||
}
|
||||
@@ -197,6 +231,7 @@ void GLGizmoMmuSegmentation::data_changed(bool is_serializing)
|
||||
const std::vector<ColorRGBA> current_extruder_colors = get_extruders_colors();
|
||||
const int prev_extruders_count = int(m_extruders_colors.size());
|
||||
const int current_extruders_count = int(current_extruder_colors.size());
|
||||
const std::vector<unsigned int> current_display_filament_ids = get_display_filament_ids(current_extruder_colors.size());
|
||||
if (prev_extruders_count != current_extruders_count) {
|
||||
if (current_extruder_colors.size() > GLGizmoMmuSegmentation::EXTRUDERS_LIMIT)
|
||||
show_notification_extruders_limit_exceeded();
|
||||
@@ -210,6 +245,9 @@ void GLGizmoMmuSegmentation::data_changed(bool is_serializing)
|
||||
this->init_extruders_data(current_extruder_colors);
|
||||
this->update_triangle_selectors_colors();
|
||||
}
|
||||
else if (current_display_filament_ids != m_display_filament_ids) {
|
||||
this->init_extruders_data(current_extruder_colors);
|
||||
}
|
||||
else if (model_object != nullptr && get_extruder_id_for_volumes(*model_object) != m_volumes_extruder_idxs) {
|
||||
this->init_model_triangle_selectors();
|
||||
}
|
||||
@@ -219,7 +257,7 @@ void GLGizmoMmuSegmentation::data_changed(bool is_serializing)
|
||||
bool GLGizmoMmuSegmentation::on_number_key_down(int number)
|
||||
{
|
||||
int extruder_idx = number - 1;
|
||||
if (extruder_idx < m_extruders_colors.size() && extruder_idx >= 0)
|
||||
if (extruder_idx >= 0 && size_t(extruder_idx) < m_display_filament_ids.size())
|
||||
m_selected_extruder_idx = extruder_idx;
|
||||
|
||||
return true;
|
||||
@@ -421,9 +459,12 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
|
||||
m_imgui->text(m_desc.at("filaments"));
|
||||
|
||||
float start_pos_x = ImGui::GetCursorPos().x;
|
||||
size_t n_extruder_colors = std::min(GLGizmoMmuSegmentation::EXTRUDERS_LIMIT, m_extruders_colors.size());
|
||||
size_t n_extruder_colors = std::min(GLGizmoMmuSegmentation::EXTRUDERS_LIMIT, m_display_filament_ids.size());
|
||||
for (size_t extruder_idx = 0; extruder_idx < n_extruder_colors; ++extruder_idx) {
|
||||
const ColorRGBA &extruder_color = m_extruders_colors[extruder_idx];
|
||||
const unsigned int actual_filament_id = m_display_filament_ids[extruder_idx];
|
||||
if (actual_filament_id == 0 || actual_filament_id > m_extruders_colors.size())
|
||||
continue;
|
||||
const ColorRGBA &extruder_color = m_extruders_colors[actual_filament_id - 1];
|
||||
ImVec4 color_vec = ImGuiWrapper::to_ImVec4(extruder_color);
|
||||
std::string color_label = std::string("##extruder color ") + std::to_string(extruder_idx);
|
||||
std::string item_text = std::to_string(extruder_idx + 1);
|
||||
@@ -914,10 +955,12 @@ PainterGizmoType GLGizmoMmuSegmentation::get_painter_type() const
|
||||
// BBS
|
||||
ColorRGBA GLGizmoMmuSegmentation::get_cursor_hover_color() const
|
||||
{
|
||||
if (m_selected_extruder_idx < m_extruders_colors.size())
|
||||
return m_extruders_colors[m_selected_extruder_idx];
|
||||
else
|
||||
return m_extruders_colors[0];
|
||||
if (m_selected_extruder_idx < m_display_filament_ids.size()) {
|
||||
const unsigned int actual_filament_id = m_display_filament_ids[m_selected_extruder_idx];
|
||||
if (actual_filament_id >= 1 && actual_filament_id <= m_extruders_colors.size())
|
||||
return m_extruders_colors[actual_filament_id - 1];
|
||||
}
|
||||
return m_extruders_colors.empty() ? ColorRGBA() : m_extruders_colors[0];
|
||||
}
|
||||
|
||||
void GLGizmoMmuSegmentation::on_set_state()
|
||||
@@ -1021,7 +1064,7 @@ void GLMmSegmentationGizmo3DScene::finalize_triangle_indices()
|
||||
|
||||
void GLGizmoMmuSegmentation::render_filament_remap_ui(float window_width, float max_tooltip_width)
|
||||
{
|
||||
size_t n_extr = std::min((size_t)EnforcerBlockerType::ExtruderMax, m_extruders_colors.size());
|
||||
size_t n_extr = std::min((size_t)EnforcerBlockerType::ExtruderMax, m_display_filament_ids.size());
|
||||
|
||||
const std::string max_label = std::to_string(std::max<size_t>(n_extr, 1));
|
||||
const ImVec2 max_label_size = ImGui::CalcTextSize(max_label.c_str(), NULL, true);
|
||||
@@ -1031,7 +1074,10 @@ void GLGizmoMmuSegmentation::render_filament_remap_ui(float window_width, float
|
||||
const float start_pos_x = ImGui::GetCursorPosX();
|
||||
|
||||
for (int src = 0; src < (int)n_extr; ++src) {
|
||||
const ColorRGBA &dst_col = m_extruders_colors[m_extruder_remap[src]];
|
||||
const unsigned int dst_filament_id = m_extruder_remap[src] < m_display_filament_ids.size() ? m_display_filament_ids[m_extruder_remap[src]] : 0;
|
||||
if (dst_filament_id == 0 || dst_filament_id > m_extruders_colors.size())
|
||||
continue;
|
||||
const ColorRGBA &dst_col = m_extruders_colors[dst_filament_id - 1];
|
||||
ImVec4 col_vec = ImGuiWrapper::to_ImVec4(dst_col);
|
||||
|
||||
if (src % max_items_per_line != 0) {
|
||||
@@ -1100,7 +1146,10 @@ void GLGizmoMmuSegmentation::render_filament_remap_ui(float window_width, float
|
||||
const float popup_start_pos_x = ImGui::GetCursorPosX();
|
||||
|
||||
for (int dst = 0; dst < (int)n_extr; ++dst) {
|
||||
const ColorRGBA &dst_col_popup = m_extruders_colors[dst];
|
||||
const unsigned int popup_filament_id = m_display_filament_ids[dst];
|
||||
if (popup_filament_id == 0 || popup_filament_id > m_extruders_colors.size())
|
||||
continue;
|
||||
const ColorRGBA &dst_col_popup = m_extruders_colors[popup_filament_id - 1];
|
||||
ImVec4 dst_vec = ImGuiWrapper::to_ImVec4(dst_col_popup);
|
||||
if (dst % max_items_per_line != 0)
|
||||
ImGui::SameLine(popup_start_pos_x + item_width * (dst % max_items_per_line));
|
||||
@@ -1184,18 +1233,23 @@ void GLGizmoMmuSegmentation::remap_filament_assignments()
|
||||
for (size_t i = 0; i <= MAX_EBT; ++i)
|
||||
state_map[i] = static_cast<EnforcerBlockerType>(i);
|
||||
|
||||
size_t n_extr = std::min(m_extruder_remap.size(), MAX_EBT);
|
||||
const int start_extruder = (int) EnforcerBlockerType::Extruder1;
|
||||
size_t n_extr = std::min({m_extruder_remap.size(), m_display_filament_ids.size(), MAX_EBT});
|
||||
bool any_change = false;
|
||||
for (size_t src = 0; src < n_extr; ++src) {
|
||||
size_t dst = m_extruder_remap[src];
|
||||
if (dst != src) {
|
||||
state_map[src+start_extruder] = static_cast<EnforcerBlockerType>(dst+start_extruder);
|
||||
if (src == 0)
|
||||
state_map[0] = static_cast<EnforcerBlockerType>(dst + start_extruder);
|
||||
const size_t dst = m_extruder_remap[src];
|
||||
if (dst >= m_display_filament_ids.size())
|
||||
continue;
|
||||
|
||||
any_change = true;
|
||||
}
|
||||
const unsigned int src_state = m_display_filament_ids[src];
|
||||
const unsigned int dst_state = m_display_filament_ids[dst];
|
||||
if (src_state == 0 || dst_state == 0 || src_state == dst_state)
|
||||
continue;
|
||||
|
||||
state_map[src_state] = static_cast<EnforcerBlockerType>(dst_state);
|
||||
if (src_state == 1)
|
||||
state_map[0] = static_cast<EnforcerBlockerType>(dst_state);
|
||||
|
||||
any_change = true;
|
||||
}
|
||||
if (!any_change)
|
||||
return;
|
||||
|
||||
@@ -85,7 +85,12 @@ protected:
|
||||
ColorRGBA get_cursor_hover_color() const override;
|
||||
void on_set_state() override;
|
||||
|
||||
EnforcerBlockerType get_left_button_state_type() const override { return EnforcerBlockerType(m_selected_extruder_idx + 1); }
|
||||
EnforcerBlockerType get_left_button_state_type() const override
|
||||
{
|
||||
if (m_selected_extruder_idx < m_display_filament_ids.size())
|
||||
return EnforcerBlockerType(m_display_filament_ids[m_selected_extruder_idx]);
|
||||
return EnforcerBlockerType::Extruder1;
|
||||
}
|
||||
EnforcerBlockerType get_right_button_state_type() const override { return EnforcerBlockerType(-1); }
|
||||
|
||||
void on_render_input_window(float x, float y, float bottom_limit) override;
|
||||
@@ -103,6 +108,7 @@ protected:
|
||||
// BBS
|
||||
size_t m_selected_extruder_idx = 0;
|
||||
std::vector<ColorRGBA> m_extruders_colors;
|
||||
std::vector<unsigned int> m_display_filament_ids;
|
||||
std::vector<int> m_volumes_extruder_idxs;
|
||||
|
||||
// BBS
|
||||
|
||||
+259
-6
@@ -660,6 +660,14 @@ struct Sidebar::priv
|
||||
bool m_mixed_filaments_collapsed = false; // Collapse state
|
||||
bool m_skip_mixed_filament_sync_once = false; // Local edits already mutated manager in place.
|
||||
std::unordered_set<size_t> m_expanded_mixed_filament_rows; // Expanded row editors
|
||||
struct MixedFilamentRowBinding {
|
||||
size_t mixed_id = size_t(-1);
|
||||
wxWindow *row = nullptr;
|
||||
};
|
||||
std::vector<MixedFilamentRowBinding> m_mixed_filament_row_bindings;
|
||||
std::vector<uint64_t> m_mixed_filament_ui_order;
|
||||
bool m_mixed_filament_drag_active = false;
|
||||
size_t m_mixed_filament_drag_source_mixed_id = size_t(-1);
|
||||
wxStaticLine* m_staticline2;
|
||||
wxPanel* m_panel_project_title;
|
||||
ScalableButton* m_filament_icon = nullptr;
|
||||
@@ -3870,6 +3878,82 @@ void MixedFilamentConfigPanel::update_preview()
|
||||
}
|
||||
}
|
||||
|
||||
class MixedFilamentDragHandle : public wxPanel
|
||||
{
|
||||
public:
|
||||
MixedFilamentDragHandle(wxWindow *parent, const wxColour &dot_color, const wxColour &bg_color)
|
||||
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE)
|
||||
, m_dot_color(dot_color)
|
||||
{
|
||||
const wxSize handle_size = parent ? parent->FromDIP(wxSize(14, 18)) : wxSize(14, 18);
|
||||
SetMinSize(handle_size);
|
||||
SetMaxSize(handle_size);
|
||||
SetInitialSize(handle_size);
|
||||
SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
SetBackgroundColour(bg_color);
|
||||
SetCursor(wxCursor(wxCURSOR_SIZING));
|
||||
Bind(wxEVT_PAINT, &MixedFilamentDragHandle::on_paint, this);
|
||||
}
|
||||
|
||||
void set_colors(const wxColour &dot_color, const wxColour &bg_color)
|
||||
{
|
||||
m_dot_color = dot_color;
|
||||
SetBackgroundColour(bg_color);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
private:
|
||||
void on_paint(wxPaintEvent &)
|
||||
{
|
||||
wxAutoBufferedPaintDC dc(this);
|
||||
dc.SetBackground(wxBrush(GetBackgroundColour()));
|
||||
dc.Clear();
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetBrush(wxBrush(m_dot_color));
|
||||
|
||||
const wxSize size = GetClientSize();
|
||||
const int radius = std::max(1, FromDIP(1));
|
||||
const int left_x = std::max(radius, size.x / 2 - FromDIP(2));
|
||||
const int right_x = std::min(size.x - radius - 1, size.x / 2 + FromDIP(2));
|
||||
const int top_y = std::max(radius + 1, size.y / 2 - FromDIP(5));
|
||||
const int gap_y = FromDIP(4);
|
||||
|
||||
for (int row = 0; row < 3; ++row) {
|
||||
const int y = top_y + row * gap_y;
|
||||
dc.DrawCircle(wxPoint(left_x, y), radius);
|
||||
dc.DrawCircle(wxPoint(right_x, y), radius);
|
||||
}
|
||||
}
|
||||
|
||||
wxColour m_dot_color;
|
||||
};
|
||||
|
||||
static std::vector<size_t> build_mixed_filament_ui_indices(const std::vector<MixedFilament> &mixed,
|
||||
const std::vector<uint64_t> &preferred_order)
|
||||
{
|
||||
std::vector<size_t> ordered_indices;
|
||||
std::vector<bool> used(mixed.size(), false);
|
||||
|
||||
for (const uint64_t stable_id : preferred_order) {
|
||||
for (size_t idx = 0; idx < mixed.size(); ++idx) {
|
||||
const MixedFilament &entry = mixed[idx];
|
||||
if (used[idx] || entry.deleted || entry.stable_id != stable_id)
|
||||
continue;
|
||||
used[idx] = true;
|
||||
ordered_indices.emplace_back(idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t idx = 0; idx < mixed.size(); ++idx) {
|
||||
if (used[idx] || mixed[idx].deleted)
|
||||
continue;
|
||||
ordered_indices.emplace_back(idx);
|
||||
}
|
||||
|
||||
return ordered_indices;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Sidebar::update_mixed_filament_panel(bool sync_manager)
|
||||
@@ -4321,6 +4405,19 @@ void Sidebar::update_mixed_filament_panel(bool sync_manager)
|
||||
}
|
||||
|
||||
auto &mixed = mixed_mgr.mixed_filaments();
|
||||
const std::vector<size_t> ordered_mixed_indices = build_mixed_filament_ui_indices(mixed, p->m_mixed_filament_ui_order);
|
||||
std::vector<uint64_t> sanitized_mixed_ui_order_ids;
|
||||
sanitized_mixed_ui_order_ids.reserve(ordered_mixed_indices.size());
|
||||
for (const size_t mixed_id : ordered_mixed_indices) {
|
||||
if (mixed_id < mixed.size() && mixed[mixed_id].stable_id != 0)
|
||||
sanitized_mixed_ui_order_ids.emplace_back(mixed[mixed_id].stable_id);
|
||||
}
|
||||
p->m_mixed_filament_ui_order = std::move(sanitized_mixed_ui_order_ids);
|
||||
|
||||
p->m_mixed_filament_drag_active = false;
|
||||
p->m_mixed_filament_drag_source_mixed_id = size_t(-1);
|
||||
p->m_mixed_filament_row_bindings.clear();
|
||||
|
||||
const int compact_gap_x = FromDIP(6);
|
||||
const int compact_gap_y = FromDIP(4);
|
||||
const int compact_row_pad = FromDIP(6);
|
||||
@@ -4493,17 +4590,43 @@ void Sidebar::update_mixed_filament_panel(bool sync_manager)
|
||||
}
|
||||
};
|
||||
|
||||
size_t visible_mixed_idx = 0;
|
||||
for (size_t mixed_id = 0; mixed_id < mixed.size(); ++mixed_id) {
|
||||
auto current_mixed_filament_ui_order = [this, &mixed]() {
|
||||
std::vector<uint64_t> ordered_ids;
|
||||
ordered_ids.reserve(p->m_mixed_filament_row_bindings.size());
|
||||
for (const auto &binding : p->m_mixed_filament_row_bindings) {
|
||||
if (binding.mixed_id < mixed.size() && mixed[binding.mixed_id].stable_id != 0)
|
||||
ordered_ids.emplace_back(mixed[binding.mixed_id].stable_id);
|
||||
}
|
||||
return ordered_ids;
|
||||
};
|
||||
|
||||
auto drop_insert_position = [this]() {
|
||||
const wxPoint mouse_pos = wxGetMousePosition();
|
||||
size_t visible_idx = 0;
|
||||
for (const auto &binding : p->m_mixed_filament_row_bindings) {
|
||||
if (binding.row == nullptr || !binding.row->IsShown())
|
||||
continue;
|
||||
|
||||
const wxPoint top_left = binding.row->ClientToScreen(wxPoint(0, 0));
|
||||
const int row_h = std::max(binding.row->GetSize().GetHeight(), binding.row->GetBestSize().GetHeight());
|
||||
const int center_y = top_left.y + row_h / 2;
|
||||
if (mouse_pos.y < center_y)
|
||||
return visible_idx;
|
||||
|
||||
++visible_idx;
|
||||
}
|
||||
return visible_idx;
|
||||
};
|
||||
|
||||
for (size_t display_mixed_idx = 0; display_mixed_idx < ordered_mixed_indices.size(); ++display_mixed_idx) {
|
||||
const size_t mixed_id = ordered_mixed_indices[display_mixed_idx];
|
||||
MixedFilament &mf = mixed[mixed_id];
|
||||
if (mf.deleted)
|
||||
continue;
|
||||
const size_t display_mixed_idx = visible_mixed_idx++;
|
||||
const bool auto_row = !mf.custom;
|
||||
|
||||
auto *row = new wxPanel(rows_scroller, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
|
||||
row->SetBackgroundColour(mixed_row_bg);
|
||||
auto *row_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
p->m_mixed_filament_row_bindings.push_back({mixed_id, row});
|
||||
|
||||
auto *header_panel = new wxPanel(row, wxID_ANY);
|
||||
header_panel->SetBackgroundColour(mixed_row_bg);
|
||||
@@ -4512,6 +4635,10 @@ void Sidebar::update_mixed_filament_panel(bool sync_manager)
|
||||
const std::string synced_color = compute_entry_display_color(mf);
|
||||
if (mf.display_color != synced_color)
|
||||
mf.display_color = synced_color;
|
||||
auto *drag_handle = new MixedFilamentDragHandle(header_panel, mixed_summary_fg, mixed_row_bg);
|
||||
drag_handle->SetToolTip(_L("Drag to reorder mixed filaments in this panel."));
|
||||
header_sizer->Add(drag_handle, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, compact_gap_x);
|
||||
|
||||
wxColour swatch_color = parse_mixed_color(mf.display_color);
|
||||
auto *swatch = new wxPanel(header_panel, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(12), FromDIP(12)));
|
||||
swatch->SetBackgroundColour(swatch_color);
|
||||
@@ -4633,11 +4760,12 @@ void Sidebar::update_mixed_filament_panel(bool sync_manager)
|
||||
editor_host->Hide();
|
||||
row_sizer->Add(editor_host, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, compact_row_pad);
|
||||
|
||||
auto set_row_hover = [row, header_panel, editor_host, mixed_row_bg, mixed_row_hover_bg](bool hovered) {
|
||||
auto set_row_hover = [row, header_panel, editor_host, drag_handle, mixed_summary_fg, mixed_row_bg, mixed_row_hover_bg](bool hovered) {
|
||||
const wxColour bg = hovered ? mixed_row_hover_bg : mixed_row_bg;
|
||||
if (row) row->SetBackgroundColour(bg);
|
||||
if (header_panel) header_panel->SetBackgroundColour(bg);
|
||||
if (editor_host) editor_host->SetBackgroundColour(bg);
|
||||
if (drag_handle) drag_handle->set_colors(mixed_summary_fg, bg);
|
||||
if (row) row->Refresh();
|
||||
if (header_panel) header_panel->Refresh();
|
||||
if (editor_host) editor_host->Refresh();
|
||||
@@ -4730,6 +4858,93 @@ void Sidebar::update_mixed_filament_panel(bool sync_manager)
|
||||
});
|
||||
};
|
||||
|
||||
auto release_drag_capture = [this]() {
|
||||
p->m_mixed_filament_drag_active = false;
|
||||
p->m_mixed_filament_drag_source_mixed_id = size_t(-1);
|
||||
};
|
||||
|
||||
auto bind_drag_target = [this,
|
||||
mixed_id,
|
||||
&mixed,
|
||||
drop_insert_position,
|
||||
current_mixed_filament_ui_order,
|
||||
release_drag_capture](wxWindow *target) {
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
target->Bind(wxEVT_LEFT_DOWN, [this, mixed_id, target](wxMouseEvent &evt) {
|
||||
if (!target)
|
||||
return;
|
||||
p->m_mixed_filament_drag_active = true;
|
||||
p->m_mixed_filament_drag_source_mixed_id = mixed_id;
|
||||
if (!target->HasCapture())
|
||||
target->CaptureMouse();
|
||||
evt.StopPropagation();
|
||||
});
|
||||
|
||||
target->Bind(wxEVT_MOTION, [this](wxMouseEvent &evt) {
|
||||
if (p->m_mixed_filament_drag_active)
|
||||
evt.StopPropagation();
|
||||
});
|
||||
|
||||
target->Bind(wxEVT_LEFT_UP, [this, &mixed, target, drop_insert_position, current_mixed_filament_ui_order](wxMouseEvent &evt) {
|
||||
if (target && target->HasCapture())
|
||||
target->ReleaseMouse();
|
||||
|
||||
if (!p->m_mixed_filament_drag_active || p->m_mixed_filament_drag_source_mixed_id >= mixed.size()) {
|
||||
p->m_mixed_filament_drag_active = false;
|
||||
p->m_mixed_filament_drag_source_mixed_id = size_t(-1);
|
||||
evt.StopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t source_mixed_id = p->m_mixed_filament_drag_source_mixed_id;
|
||||
p->m_mixed_filament_drag_active = false;
|
||||
p->m_mixed_filament_drag_source_mixed_id = size_t(-1);
|
||||
|
||||
std::vector<size_t> current_mixed_ids;
|
||||
current_mixed_ids.reserve(p->m_mixed_filament_row_bindings.size());
|
||||
for (const auto &binding : p->m_mixed_filament_row_bindings) {
|
||||
if (binding.mixed_id < mixed.size() && !mixed[binding.mixed_id].deleted)
|
||||
current_mixed_ids.emplace_back(binding.mixed_id);
|
||||
}
|
||||
|
||||
const auto source_it = std::find(current_mixed_ids.begin(), current_mixed_ids.end(), source_mixed_id);
|
||||
if (source_it == current_mixed_ids.end()) {
|
||||
evt.StopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t source_pos = size_t(std::distance(current_mixed_ids.begin(), source_it));
|
||||
size_t insert_pos = drop_insert_position();
|
||||
insert_pos = std::min(insert_pos, current_mixed_ids.size());
|
||||
|
||||
current_mixed_ids.erase(source_it);
|
||||
if (insert_pos > source_pos)
|
||||
--insert_pos;
|
||||
insert_pos = std::min(insert_pos, current_mixed_ids.size());
|
||||
current_mixed_ids.insert(current_mixed_ids.begin() + ptrdiff_t(insert_pos), source_mixed_id);
|
||||
|
||||
std::vector<uint64_t> reordered_stable_ids;
|
||||
reordered_stable_ids.reserve(current_mixed_ids.size());
|
||||
for (const size_t row_mixed_id : current_mixed_ids) {
|
||||
if (row_mixed_id < mixed.size() && mixed[row_mixed_id].stable_id != 0)
|
||||
reordered_stable_ids.emplace_back(mixed[row_mixed_id].stable_id);
|
||||
}
|
||||
|
||||
if (reordered_stable_ids != current_mixed_filament_ui_order()) {
|
||||
p->m_mixed_filament_ui_order = std::move(reordered_stable_ids);
|
||||
update_mixed_filament_panel(false);
|
||||
}
|
||||
|
||||
evt.StopPropagation();
|
||||
});
|
||||
|
||||
target->Bind(wxEVT_MOUSE_CAPTURE_LOST, [release_drag_capture](wxMouseCaptureLostEvent &) {
|
||||
release_drag_capture();
|
||||
});
|
||||
};
|
||||
|
||||
header_panel->SetToolTip(auto_row ?
|
||||
_L("Click to edit automatic mixed filament settings (saved as custom).") :
|
||||
_L("Click to expand/retract mixed filament settings"));
|
||||
@@ -4743,6 +4958,8 @@ void Sidebar::update_mixed_filament_panel(bool sync_manager)
|
||||
bind_hover_target(name_label);
|
||||
bind_hover_target(summary_label);
|
||||
bind_hover_target(swatch);
|
||||
bind_hover_target(drag_handle);
|
||||
bind_drag_target(drag_handle);
|
||||
|
||||
del_btn->Bind(wxEVT_LEFT_UP, [](wxMouseEvent &evt) {
|
||||
evt.StopPropagation();
|
||||
@@ -4774,6 +4991,42 @@ void Sidebar::update_mixed_filament_panel(bool sync_manager)
|
||||
refresh_model_canvas_colors();
|
||||
}
|
||||
|
||||
std::vector<unsigned int> Sidebar::get_ui_ordered_filament_ids() const
|
||||
{
|
||||
const size_t num_physical = static_cast<size_t>(std::max(wxGetApp().filaments_cnt(), 0));
|
||||
std::vector<unsigned int> ordered_filament_ids;
|
||||
ordered_filament_ids.reserve(num_physical);
|
||||
for (size_t idx = 0; idx < num_physical; ++idx)
|
||||
ordered_filament_ids.emplace_back(unsigned(idx + 1));
|
||||
|
||||
if (wxGetApp().preset_bundle == nullptr)
|
||||
return ordered_filament_ids;
|
||||
|
||||
const auto &mixed = wxGetApp().preset_bundle->mixed_filaments.mixed_filaments();
|
||||
if (mixed.empty())
|
||||
return ordered_filament_ids;
|
||||
|
||||
const std::vector<size_t> ordered_mixed_indices = build_mixed_filament_ui_indices(mixed, p->m_mixed_filament_ui_order);
|
||||
std::vector<unsigned int> actual_filament_id_by_mixed_idx(mixed.size(), 0);
|
||||
unsigned int next_filament_id = unsigned(num_physical + 1);
|
||||
for (size_t mixed_idx = 0; mixed_idx < mixed.size(); ++mixed_idx) {
|
||||
if (!mixed[mixed_idx].enabled || mixed[mixed_idx].deleted)
|
||||
continue;
|
||||
actual_filament_id_by_mixed_idx[mixed_idx] = next_filament_id++;
|
||||
}
|
||||
|
||||
ordered_filament_ids.reserve(size_t(next_filament_id - 1));
|
||||
for (const size_t mixed_idx : ordered_mixed_indices) {
|
||||
if (mixed_idx >= actual_filament_id_by_mixed_idx.size())
|
||||
continue;
|
||||
const unsigned int actual_filament_id = actual_filament_id_by_mixed_idx[mixed_idx];
|
||||
if (actual_filament_id != 0)
|
||||
ordered_filament_ids.emplace_back(actual_filament_id);
|
||||
}
|
||||
|
||||
return ordered_filament_ids;
|
||||
}
|
||||
|
||||
void Sidebar::add_filament() {
|
||||
if (p->combos_filament.size() >= MAXIMUM_EXTRUDER_NUMBER) return;
|
||||
wxColour new_col = Plater::get_next_color_for_filament();
|
||||
|
||||
@@ -157,6 +157,7 @@ public:
|
||||
|
||||
void on_filaments_delete(size_t filament_id);
|
||||
void update_mixed_filament_panel(bool sync_manager = true);
|
||||
std::vector<unsigned int> get_ui_ordered_filament_ids() const;
|
||||
// BBS
|
||||
void on_bed_type_change(BedType bed_type);
|
||||
void load_ams_list(std::string const & device, MachineObject* obj);
|
||||
|
||||
Reference in New Issue
Block a user