This commit is contained in:
Jonas Bouchard 2026-01-18 13:17:09 +01:00 committed by GitHub
commit 31ff3cbdc6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 192 additions and 65 deletions

View file

@ -1014,7 +1014,7 @@ static std::vector<std::string> s_Preset_printer_options {
"nozzle_height", "master_extruder_id",
"default_print_profile", "inherits",
"silent_mode",
"scan_first_layer", "enable_power_loss_recovery", "wrapping_detection_layers", "wrapping_exclude_area", "machine_load_filament_time", "machine_unload_filament_time", "machine_tool_change_time", "time_cost", "machine_pause_gcode", "template_custom_gcode",
"scan_first_layer", "enable_power_loss_recovery", "wrapping_detection_layers", "wrapping_exclude_area", "machine_load_filament_time", "machine_unload_filament_time", "machine_tool_change_time", "zero_based_filament_indexing", "time_cost", "machine_pause_gcode", "template_custom_gcode",
"nozzle_type", "nozzle_hrc","auxiliary_fan", "nozzle_volume","upward_compatible_machine", "z_hop_types", "travel_slope", "retract_lift_enforce","support_chamber_temp_control","support_air_filtration","printer_structure",
"best_object_pos", "head_wrap_detect_zone",
"host_type", "print_host", "printhost_apikey", "bbl_use_printhost",

View file

@ -4447,6 +4447,12 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(-2.));
def = this->add("zero_based_filament_indexing", coBool);
def->label = L("0-based filament indexing");
def->tooltip = L("When enabled, 0-based filament indexing is used in OrcaSlicer's interface (0..N-1 instead of 1..N).");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("start_end_points", coPoints);
def->label = L("Start end points");
def->tooltip = L("The start and end points which is from cutter area to garbage can.");

View file

@ -1385,6 +1385,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, purge_in_prime_tower))
((ConfigOptionBool, enable_filament_ramming))
((ConfigOptionBool, support_multi_bed_types))
((ConfigOptionBool, zero_based_filament_indexing))
// Small Area Infill Flow Compensation
((ConfigOptionStrings, small_area_infill_flow_compensation_model))

View file

@ -345,11 +345,11 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode
break;
}
case libvgcode::EViewType::Tool: {
sprintf(buf, "%s %s%d", buf, _u8L("Tool: ").c_str(), vertex.extruder_id + 1);
sprintf(buf, "%s %s%d", buf, _u8L("Tool: ").c_str(), filament_index_from_zero_based(static_cast<int>(vertex.extruder_id)));
break;
}
case libvgcode::EViewType::ColorPrint: {
sprintf(buf, "%s %s%d", buf, _u8L("Color: ").c_str(), vertex.color_id + 1);
sprintf(buf, "%s %s%d", buf, _u8L("Color: ").c_str(), filament_index_from_zero_based(static_cast<int>(vertex.color_id)));
break;
}
case libvgcode::EViewType::ActualVolumetricFlowRate: {
@ -2480,7 +2480,7 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
for (auto it = model_volume_of_extruders_all_plates.begin(); it != model_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<std::pair<std::string, float>> columns_offsets;
columns_offsets.push_back({ std::to_string(it->first + 1), offsets[_u8L("Filament")]});
columns_offsets.push_back({ std::to_string(filament_index_from_zero_based(static_cast<int>(it->first))), offsets[_u8L("Filament")]});
char buf[64];
double unit_conver = imperial_units ? GizmoObjectManipulation::oz_to_g : 1.0;
@ -3562,7 +3562,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
const std::vector<uint8_t>& used_extruders_ids = m_viewer.get_used_extruders_ids();
for (uint8_t extruder_id : used_extruders_ids) {
::sprintf(buf, imperial_units ? "%.2f in %.2f g" : "%.2f m %.2f g", model_used_filaments_m[i], model_used_filaments_g[i]);
append_item(EItemType::Rect, libvgcode::convert(m_viewer.get_tool_colors()[extruder_id]), { { _u8L("Extruder") + " " + std::to_string(extruder_id + 1), offsets[0]}, {buf, offsets[1]} });
append_item(EItemType::Rect, libvgcode::convert(m_viewer.get_tool_colors()[extruder_id]), { { _u8L("Extruder") + " " + std::to_string(filament_index_from_zero_based(extruder_id)), offsets[0]}, {buf, offsets[1]} });
// append_item(EItemType::Rect, libvgcode::convert(m_viewer.get_tool_colors()[extruder_id]), _u8L("Extruder") + " " + std::to_string(extruder_id + 1),
// true, "", 0.0f, 0.0f, offsets, used_filaments_m[extruder_id], used_filaments_g[extruder_id]);
i++;
@ -3614,7 +3614,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
for (auto extruder_idx : used_extruders_ids) {
if (i < model_used_filaments_m.size() && i < model_used_filaments_g.size()) {
std::vector<std::pair<std::string, float>> columns_offsets;
columns_offsets.push_back({ std::to_string(extruder_idx + 1), color_print_offsets[_u8L("Filament")]});
columns_offsets.push_back({ std::to_string(filament_index_from_zero_based(extruder_idx)), color_print_offsets[_u8L("Filament")]});
char buf[64];
float column_sum_m = 0.0f;
@ -3990,7 +3990,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
ret = std::max(ret, ImGui::CalcTextSize((_u8L("Print settings") + std::string(":")).c_str()).x);
if (!m_settings_ids.filament.empty()) {
for (unsigned char i : m_viewer.get_used_extruders_ids()) {
ret = std::max(ret, ImGui::CalcTextSize((_u8L("Filament") + " " + std::to_string(i + 1) + ":").c_str()).x);
ret = std::max(ret, ImGui::CalcTextSize((_u8L("Filament") + " " + std::to_string(filament_index_from_zero_based(static_cast<int>(i))) + ":").c_str()).x);
}
}
if (ret > 0.0f)
@ -4017,7 +4017,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
for (unsigned char i : m_viewer.get_used_extruders_ids()) {
if (i < static_cast<unsigned char>(m_settings_ids.filament.size()) && !m_settings_ids.filament[i].empty()) {
std::string txt = _u8L("Filament");
txt += (m_viewer.get_used_extruders_count() == 1) ? ":" : " " + std::to_string(i + 1);
txt += (m_viewer.get_used_extruders_count() == 1) ? ":" : " " + std::to_string(filament_index_from_zero_based(static_cast<int>(i)));
imgui.text(txt);
ImGui::SameLine(offset);
imgui.text(m_settings_ids.filament[i]);

View file

@ -9492,14 +9492,14 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
if (error_iter != m_gcode_viewer.m_gcode_check_result.print_area_error_infos.begin()) {
text += "\n";
}
int extruder_id = error_iter->first + 1; // change extruder id to 1 based
int extruder_index = error_iter->first;
std::string filaments;
std::vector<int> slice_error_object_idxs;
for (size_t i = 0; i < error_iter->second.size(); ++i) {
if (i > 0) {
filaments += ", ";
}
int filament_id = error_iter->second[i].first + 1; // change filament id to 1 based
int filament_id = filament_index_from_zero_based(error_iter->second[i].first);
int object_label_id = error_iter->second[i].second;
filaments += std::to_string(filament_id);
@ -9522,7 +9522,7 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
}
}
}
std::string extruder_name = extruder_name_list[extruder_id-1];
std::string extruder_name = extruder_name_list[extruder_index];
if (error_iter->second.size() == 1) {
text += (boost::format(_u8L("Filament %s is placed in the %s, but the generated G-code path exceeds the printable range of the %s.")) %filaments %extruder_name %extruder_name).str();
}
@ -9538,11 +9538,12 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
if (error_iter != m_gcode_viewer.m_gcode_check_result.print_height_error_infos.begin()) {
text += "\n";
}
int extruder_id = error_iter->first + 1; // change extruder id to 1 based
int extruder_index = error_iter->first;
int extruder_id = filament_index_from_zero_based(extruder_index);
std::set<int> filament_ids;
std::vector<int> slice_error_object_idxs;
for (size_t i = 0; i < error_iter->second.size(); ++i) {
int filament_id = error_iter->second[i].first + 1; // change filament id to 1 based
int filament_id = filament_index_from_zero_based(error_iter->second[i].first);
int object_label_id = error_iter->second[i].second;
filament_ids.insert(filament_id);
for (int object_idx = 0; object_idx < (int) m_model->objects.size(); ++object_idx) {
@ -9575,7 +9576,7 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
}
}
}
std::string extruder_name = extruder_name_list[extruder_id-1];
std::string extruder_name = extruder_name_list[extruder_index];
if (error_iter->second.size() == 1) {
text += (boost::format(_u8L("Filament %s is placed in the %s, but the generated G-code path exceeds the printable height of the %s.")) % filaments % extruder_name % extruder_name).str();
} else {
@ -9601,10 +9602,10 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
break;
case EWarning::FilamentUnPrintableOnFirstLayer: {
std::string warning;
const std::vector<int> &conflict_filament = m_gcode_viewer.filament_printable_reuslt.conflict_filament;
std::vector<int> &conflict_filament = m_gcode_viewer.filament_printable_reuslt.conflict_filament;
auto iter = conflict_filament.begin();
for (int filament : conflict_filament) {
warning += std::to_string(filament + 1);
warning += std::to_string(filament_index_from_zero_based(filament));
warning += " ";
}
text = (boost::format(_u8L("filaments %s cannot be printed directly on the surface of this plate.")) % warning).str();

View file

@ -102,6 +102,27 @@ const std::string& shortkey_alt_prefix()
return str;
}
bool zero_based_filament_indexing()
{
const auto* preset_bundle = wxGetApp().preset_bundle;
if (!preset_bundle)
return false;
const auto& config = preset_bundle->printers.get_edited_preset().config;
const auto* opt = config.option<ConfigOptionBool>("zero_based_filament_indexing");
return opt != nullptr && opt->value;
}
int filament_index_from_zero_based(int index)
{
return index + (zero_based_filament_indexing() ? 0 : 1);
}
int filament_index_from_one_based(int index)
{
return zero_based_filament_indexing() ? index - 1 : index;
}
// opt_index = 0, by the reason of zero-index in ConfigOptionVector by default (in case only one element)
void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index /*= 0*/)
{

View file

@ -32,6 +32,10 @@ void break_to_debugger();
extern const std::string& shortkey_ctrl_prefix();
extern const std::string& shortkey_alt_prefix();
bool zero_based_filament_indexing();
int filament_index_from_zero_based(int index);
int filament_index_from_one_based(int index);
extern AppConfig* get_app_config();
extern void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_language_change);

View file

@ -923,9 +923,10 @@ void MenuFactory::append_menu_item_change_extruder(wxMenu* menu)
wxString item_name = _L("Default");
if (i > 0) {
const int display_index = filament_index_from_one_based(i);
auto preset = wxGetApp().preset_bundle->filaments.find_preset(wxGetApp().preset_bundle->filament_presets[i - 1]);
if (preset == nullptr) {
item_name = wxString::Format(_L("Filament %d"), i);
item_name = wxString::Format(_L("Filament %d"), display_index);
} else {
item_name = from_u8(preset->label(false));
}
@ -1526,8 +1527,9 @@ void MenuFactory::create_filament_action_menu(bool init, int active_filament_men
if (i == active_filament_menu_id)
continue;
const int display_index = filament_index_from_zero_based(i);
auto preset = wxGetApp().preset_bundle->filaments.find_preset(wxGetApp().preset_bundle->filament_presets[i]);
wxString item_name = preset ? from_u8(preset->label(false)) : wxString::Format(_L("Filament %d"), i + 1);
wxString item_name = preset ? wxString::Format("%d: %s", display_index, from_u8(preset->label(false))) : wxString::Format(_L("Filament %d"), display_index);
append_menu_item(sub_menu, wxID_ANY, item_name, "",
[i](wxCommandEvent&) { plater()->sidebar().change_filament(-2, i); }, *icons[i], menu,
@ -2083,9 +2085,10 @@ void MenuFactory::append_menu_item_change_filament(wxMenu* menu)
wxString item_name = _L("Default");
if (i > 0) {
const int display_index = filament_index_from_one_based(i);
auto preset = wxGetApp().preset_bundle->filaments.find_preset(wxGetApp().preset_bundle->filament_presets[i - 1]);
if (preset == nullptr) {
item_name = wxString::Format(_L("Filament %d"), i);
item_name = wxString::Format(_L("Filament %d"), display_index);
} else {
item_name = from_u8(preset->label(false));
}

View file

@ -77,6 +77,14 @@ static int filaments_count()
return wxGetApp().filaments_cnt();
}
static wxString format_filament_index_for_display(int extruder_id)
{
if (extruder_id <= 0)
return wxString::Format("%d", extruder_id);
return wxString::Format("%d", extruder_id);
}
static void take_snapshot(const std::string& snapshot_name)
{
Plater* plater = wxGetApp().plater();
@ -688,11 +696,11 @@ void ObjectList::update_filament_values_for_items(const size_t filaments_count)
auto object = (*m_objects)[i];
wxString extruder;
if (!object->config.has("extruder") || size_t(object->config.extruder()) > filaments_count) {
extruder = "1";
extruder = format_filament_index_for_display(1);
object->config.set_key_value("extruder", new ConfigOptionInt(1));
}
else {
extruder = wxString::Format("%d", object->config.extruder());
extruder = format_filament_index_for_display(object->config.extruder());
}
m_objects_model->SetExtruder(extruder, item);
@ -707,10 +715,10 @@ void ObjectList::update_filament_values_for_items(const size_t filaments_count)
if (!item) continue;
if (!object->volumes[id]->config.has("extruder") ||
size_t(object->volumes[id]->config.extruder()) > filaments_count) {
extruder = wxString::Format("%d", object->config.extruder());
extruder = format_filament_index_for_display(object->config.extruder());
}
else {
extruder = wxString::Format("%d", object->volumes[id]->config.extruder());
extruder = format_filament_index_for_display(object->volumes[id]->config.extruder());
}
m_objects_model->SetExtruder(extruder, item);
@ -737,15 +745,15 @@ void ObjectList::update_filament_values_for_items_when_delete_filament(const siz
auto object = (*m_objects)[i];
wxString extruder;
if (!object->config.has("extruder")) {
extruder = std::to_string(1);
extruder = format_filament_index_for_display(1);
object->config.set_key_value("extruder", new ConfigOptionInt(1));
}
else if (size_t(object->config.extruder()) == filament_id + 1) {
extruder = std::to_string(replace_filament_id);
extruder = format_filament_index_for_display(replace_filament_id);
object->config.set_key_value("extruder", new ConfigOptionInt(replace_filament_id));
} else {
int new_extruder = object->config.extruder() > filament_id ? object->config.extruder() - 1 : object->config.extruder();
extruder = wxString::Format("%d", new_extruder);
extruder = format_filament_index_for_display(new_extruder);
object->config.set_key_value("extruder", new ConfigOptionInt(new_extruder));
}
m_objects_model->SetExtruder(extruder, item);
@ -787,7 +795,7 @@ void ObjectList::update_filament_values_for_items_when_delete_filament(const siz
object->volumes[id]->config.set_key_value("extruder", new ConfigOptionInt(replace_filament_id));
} else {
int new_extruder = object->volumes[id]->config.extruder() > filament_id ? object->volumes[id]->config.extruder() - 1 : object->volumes[id]->config.extruder();
extruder = wxString::Format("%d", new_extruder);
extruder = format_filament_index_for_display(new_extruder);
object->volumes[id]->config.set_key_value("extruder", new ConfigOptionInt(new_extruder));
}
@ -815,12 +823,12 @@ void ObjectList::update_filament_values_for_items_when_delete_filament(const siz
auto& layer_range_item = *(l_iter);
if (layer_range_item.second.has("extruder") && layer_range_item.second.option("extruder")->getInt() == filament_id + 1) {
int new_extruder = replace_id == -1 ? 0 : (replace_id + 1);
extruder = wxString::Format("%d", new_extruder);
extruder = format_filament_index_for_display(new_extruder);
layer_range_item.second.set("extruder", new_extruder);
} else {
int layer_filament_id = layer_range_item.second.option("extruder")->getInt();
int new_extruder = layer_filament_id > filament_id ? layer_filament_id - 1 : layer_filament_id;
extruder = wxString::Format("%d", new_extruder);
extruder = format_filament_index_for_display(new_extruder);
layer_range_item.second.set("extruder", new_extruder);
}
m_objects_model->SetExtruder(extruder, layer_item);
@ -1608,7 +1616,7 @@ void ObjectList::extruder_editing()
pos.x = GetColumn(colName)->GetWidth() + GetColumn(colPrint)->GetWidth() + GetColumn(colHeight)->GetWidth() + 5;
pos.y -= GetTextExtent("m").y;
apply_extruder_selector(&m_extruder_editor, this, "1", pos, size);
apply_extruder_selector(&m_extruder_editor, this, format_filament_index_for_display(1).ToStdString(), pos, size);
m_extruder_editor->SetSelection(m_objects_model->GetExtruderNumber(item));
m_extruder_editor->Show();
@ -2772,7 +2780,7 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con
int extruder_id = last_volume->config.opt_int("extruder");
object->config.set("extruder", extruder_id);
}
wxString extruder = object->config.has("extruder") ? wxString::Format("%d", object->config.extruder()) : _devL("1");
wxString extruder = object->config.has("extruder") ? format_filament_index_for_display(object->config.extruder()) : format_filament_index_for_display(1);
m_objects_model->SetExtruder(extruder, obj_item);
}
// add settings to the object, if it has them
@ -4168,7 +4176,7 @@ void ObjectList::delete_from_model_and_list(const std::vector<ItemForDelete>& it
if (obj->volumes.size() == 1) {
wxDataViewItem parent = m_objects_model->GetItemById(item->obj_idx);
if (obj->config.has("extruder")) {
const wxString extruder = wxString::Format("%d", obj->config.extruder());
const wxString extruder = format_filament_index_for_display(obj->config.extruder());
m_objects_model->SetExtruder(extruder, parent);
}
// If last volume item with warning was deleted, unmark object item
@ -6184,7 +6192,7 @@ void ObjectList::set_extruder_for_selected_items(const int extruder)
}
}
const wxString extruder_str = wxString::Format("%d", new_extruder);
const wxString extruder_str = format_filament_index_for_display(new_extruder);
m_objects_model->SetExtruder(extruder_str, item);
}

View file

@ -2846,7 +2846,8 @@ int ObjectTablePanel::init_filaments_and_colors()
}
//parse the filaments
m_filaments_name[i] = wxString(std::to_string(i+1) + ": " + filament_presets[i]);
const int display_index = filament_index_from_zero_based(static_cast<int>(i));
m_filaments_name[i] = wxString(std::to_string(display_index) + ": " + filament_presets[i]);
i++;
}

View file

@ -192,7 +192,7 @@ void GLGizmoMmuSegmentation::data_changed(bool is_serializing)
// BBS
bool GLGizmoMmuSegmentation::on_number_key_down(int number)
{
int extruder_idx = number - 1;
int extruder_idx = zero_based_filament_indexing() ? number : number - 1;
if (extruder_idx < m_extruders_colors.size() && extruder_idx >= 0)
m_selected_extruder_idx = extruder_idx;
@ -403,7 +403,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
const ColorRGBA &extruder_color = m_extruders_colors[extruder_idx];
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);
std::string item_text = std::to_string(filament_index_from_zero_based(extruder_idx));
const ImVec2 label_size = ImGui::CalcTextSize(item_text.c_str(), NULL, true);
const ImVec2 button_size(max_label_size.x + m_imgui->scaled(0.5f),0.f);
@ -435,7 +435,8 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
color_button_high = ImGui::GetCursorPos().y - color_button - 2.0;
if (color_picked) { m_selected_extruder_idx = extruder_idx; }
if (extruder_idx < 16 && ImGui::IsItemHovered()) m_imgui->tooltip(_L("Shortcut Key ") + std::to_string(extruder_idx + 1), max_tooltip_width);
if (extruder_idx < 16 && ImGui::IsItemHovered())
m_imgui->tooltip(_L("Shortcut Key ") + std::to_string(filament_index_from_zero_based(extruder_idx)), max_tooltip_width);
// draw filament id
float gray = 0.299 * extruder_color.r() + 0.587 * extruder_color.g() + 0.114 * extruder_color.b();
@ -873,7 +874,7 @@ wxString GLGizmoMmuSegmentation::handle_snapshot_action_name(bool shift_down, GL
if (shift_down)
action_name = _L("Remove painted color");
else {
action_name = GUI::format(_L("Painted using: Filament %1%"), m_selected_extruder_idx);
action_name = GUI::format(_L("Painted using: Filament %1%"), filament_index_from_zero_based(m_selected_extruder_idx));
}
return action_name;
}
@ -1047,7 +1048,7 @@ void GLGizmoMmuSegmentation::render_filament_remap_ui(float window_width, float
#endif
// overlay destination number with proper contrast calculation
std::string dst_txt = std::to_string(m_extruder_remap[src] + 1);
std::string dst_txt = std::to_string(filament_index_from_zero_based(static_cast<int>(m_extruder_remap[src])));
float gray = 0.299f * dst_col.r() + 0.587f * dst_col.g() + 0.114f * dst_col.b();
ImVec2 txt_sz = ImGui::CalcTextSize(dst_txt.c_str());
ImVec2 pos = ImGui::GetItemRectMin();

View file

@ -3274,7 +3274,7 @@ std::tuple<ImVec2, bool> ImGuiWrapper::calculate_filament_group_text_size(const
void ImGuiWrapper::filament_group(const std::string& filament_type, const char* hex_color, unsigned char filament_id, float align_width)
{
//ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
std::string id = std::to_string(static_cast<unsigned int> (filament_id + 1));
std::string id = std::to_string(filament_index_from_zero_based(static_cast<int>(filament_id)));
ImDrawList* draw_list = ImGui::GetWindowDrawList();
static ImTextureID transparent;
ImVec2 text_size = ImGui::CalcTextSize(filament_type.c_str());

View file

@ -409,7 +409,8 @@ ObjColorPanel::~ObjColorPanel() {
void ObjColorPanel::msw_rescale()
{
for (unsigned int i = 0; i < m_extruder_icon_list.size(); ++i) {
auto bitmap = *get_extruder_color_icon(m_colours[i].GetAsString(wxC2S_HTML_SYNTAX).ToStdString(), std::to_string(i + 1), FromDIP(16), FromDIP(16));
const int display_index = filament_index_from_zero_based(static_cast<int>(i));
auto bitmap = *get_extruder_color_icon(m_colours[i].GetAsString(wxC2S_HTML_SYNTAX).ToStdString(), std::to_string(display_index), FromDIP(16), FromDIP(16));
m_extruder_icon_list[i]->SetBitmap(bitmap);
}
/* for (unsigned int i = 0; i < m_color_cluster_icon_list.size(); ++i) {
@ -530,7 +531,8 @@ wxBoxSizer *ObjColorPanel::create_extruder_icon_and_rgba_sizer(wxWindow *parent,
{
auto icon_sizer = new wxBoxSizer(wxHORIZONTAL);
wxButton *icon = new wxButton(parent, wxID_ANY, {}, wxDefaultPosition, ICON_SIZE, wxBORDER_NONE | wxBU_AUTODRAW);
icon->SetBitmap(*get_extruder_color_icon(color.GetAsString(wxC2S_HTML_SYNTAX).ToStdString(), std::to_string(id + 1), FromDIP(16), FromDIP(16)));
const int display_index = filament_index_from_zero_based(id);
icon->SetBitmap(*get_extruder_color_icon(color.GetAsString(wxC2S_HTML_SYNTAX).ToStdString(), std::to_string(display_index), FromDIP(16), FromDIP(16)));
icon->SetCanFocus(false);
m_extruder_icon_list.emplace_back(icon);
icon_sizer->Add(icon, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 0); // wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM

View file

@ -44,6 +44,14 @@ static constexpr char WarningIcon[] = "obj_warning";
static constexpr char WarningManifoldIcon[] = "obj_warning";
static constexpr char LockIcon[] = "cut_";
static wxString format_filament_index_for_display(int extruder_id)
{
if (extruder_id <= 0)
return wxString::Format("%d", extruder_id);
return wxString::Format("%d", extruder_id);
}
ObjectDataViewModelNode::ObjectDataViewModelNode(PartPlate* part_plate, wxString name) :
m_parent(nullptr),
m_name(name),
@ -611,7 +619,7 @@ wxDataViewItem ObjectDataViewModel::AddObject(ModelObject *model_object, std::st
// create object node
//const wxString extruder_str = extruder == 0 ? _(L("default")) : wxString::Format("%d", extruder);
const wxString extruder_str = wxString::Format("%d", extruder);
const wxString extruder_str = format_filament_index_for_display(extruder);
auto obj_node = new ObjectDataViewModelNode(name, extruder_str, plate_idx, model_object);
// Add warning icon if detected auto-repaire
UpdateBitmapForNode(obj_node, warning_bitmap, has_lock);
@ -678,7 +686,7 @@ wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent
extruder_str = root->m_extruder;
}
else {
extruder_str = wxString::Format("%d", extruder);
extruder_str = format_filament_index_for_display(extruder);
}
const auto node = new ObjectDataViewModelNode(root, name, volume_type, is_text_volume, is_svg_volume, extruder_str, root->m_volumes_cnt);
@ -905,7 +913,7 @@ wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_
if (!parent_node) return wxDataViewItem(0);
// BBS
wxString extruder_str = extruder == 0 ? _(L("default")) : wxString::Format("%d", extruder);
wxString extruder_str = extruder == 0 ? _(L("default")) : format_filament_index_for_display(extruder);
// get LayerRoot node
ObjectDataViewModelNode *layer_root_node;
@ -1748,7 +1756,13 @@ int ObjectDataViewModel::GetExtruderNumber(const wxDataViewItem& item) const
if (!node) // happens if item.IsOk()==false
return 0;
return atoi(node->m_extruder.c_str());
const std::string extruder = node->m_extruder.ToStdString();
char* end = nullptr;
const long value = std::strtol(extruder.c_str(), &end, 10);
if (end == extruder.c_str() || *end != '\0')
return 0;
return static_cast<int>(value);
}
wxString ObjectDataViewModel::GetColumnType(unsigned int col) const

View file

@ -834,7 +834,7 @@ struct DynamicFilamentList1Based : DynamicFilamentList
wxString get_value(int index) override
{
wxString str;
str << index+1;
str << filament_index_from_zero_based(index);
return str;
}
int index_of(wxString value) override
@ -842,8 +842,9 @@ struct DynamicFilamentList1Based : DynamicFilamentList
long n = 0;
if(!value.ToLong(&n))
return -1;
--n;
return (n >= 0 && n <= items.size()) ? int(n) : -1;
if (!zero_based_filament_indexing())
--n;
return (n >= 0 && n < static_cast<long>(items.size())) ? int(n) : -1;
}
void update(bool force = false)
{
@ -2277,7 +2278,7 @@ void Sidebar::init_filament_combo(PlaterPresetComboBox **combo, const int filame
if ((filament_idx % 2) == 0) // Dont add right column item. this one create equal spacing on left, right & middle
combo_and_btn_sizer->AddSpacer(FromDIP((filament_idx % 2) == 0 ? 12 : 3)); // Content Margin
(*combo)->clr_picker->SetLabel(wxString::Format("%d", filament_idx + 1));
(*combo)->clr_picker->SetLabel(wxString::Format("%d", filament_index_from_zero_based(filament_idx)));
combo_and_btn_sizer->Add((*combo)->clr_picker, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(SidebarProps::ElementSpacing()) - FromDIP(2)); // ElementSpacing - 2 (from combo box))
combo_and_btn_sizer->Add(*combo, 1, wxALL | wxEXPAND, FromDIP(2))->SetMinSize({-1, FromDIP(30)});

View file

@ -338,7 +338,7 @@ static Option create_option(const std::string &opt_key, const wxString &label, P
wxString category = gc.category;
if (type == Preset::TYPE_PRINTER && category.Contains("Extruder ")) {
std::string opt_idx = opt_key.substr(opt_key.find("#") + 1);
category = wxString::Format("%s %d", "Extruder", atoi(opt_idx.c_str()) + 1);
category = wxString::Format("%s %d", "Extruder", GUI::filament_index_from_zero_based(std::atoi(opt_idx.c_str())));
}
return Option{boost::nowide::widen(get_key(opt_key, type)),

View file

@ -1537,6 +1537,17 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
wxGetApp().get_tab(Preset::TYPE_PRINT)->update();
}
if (opt_key == "zero_based_filament_indexing") {
wxGetApp().sidebar().update_dynamic_filament_list();
wxGetApp().sidebar().update_all_preset_comboboxes();
wxGetApp().obj_list()->update_objects_list_filament_column(wxGetApp().filaments_cnt());
wxGetApp().plater()->update();
if (m_type == Preset::TYPE_PRINTER) {
if (auto* printer_tab = dynamic_cast<TabPrinter*>(this))
printer_tab->refresh_extruder_page_titles(boost::any_cast<bool>(value));
}
}
if(opt_key == "purge_in_prime_tower")
wxGetApp().get_tab(Preset::TYPE_PRINT)->update();
@ -4916,12 +4927,13 @@ if (is_marlin_flavor)
optgroup->append_single_option_line("machine_load_filament_time", "printer_multimaterial_advanced#filament-load-time");
optgroup->append_single_option_line("machine_unload_filament_time", "printer_multimaterial_advanced#filament-unload-time");
optgroup->append_single_option_line("machine_tool_change_time", "printer_multimaterial_advanced#tool-change-time");
optgroup->append_single_option_line("zero_based_filament_indexing", "printer_multimaterial_advanced#zero-based-filament-indexing");
m_pages.insert(m_pages.end() - n_after_single_extruder_MM, page);
}
// Orca: build missed extruder pages
for (auto extruder_idx = m_extruders_count_old; extruder_idx < m_extruders_count; ++extruder_idx) {
const wxString& page_name = (m_extruders_count > 1) ? wxString::Format("Extruder %d", int(extruder_idx + 1)) : wxString::Format("Extruder");
const wxString& page_name = (m_extruders_count > 1) ? wxString::Format("Extruder %d", filament_index_from_zero_based(static_cast<int>(extruder_idx))) : wxString::Format("Extruder");
//# build page
//const wxString& page_name = wxString::Format("Extruder %d", int(extruder_idx + 1));
@ -5044,15 +5056,15 @@ if (is_marlin_flavor)
}
// BBS. No extra extruder page for single physical extruder machine
// # remove extra pages
auto &first_extruder_title = const_cast<wxString &>(m_pages[n_before_extruders]->title());
if (m_extruders_count < m_extruders_count_old) {
m_pages.erase( m_pages.begin() + n_before_extruders + m_extruders_count,
m_pages.begin() + n_before_extruders + m_extruders_count_old);
if (m_extruders_count == 1)
first_extruder_title = wxString::Format("Extruder");
} else if (m_extruders_count_old == 1) {
first_extruder_title = wxString::Format("Extruder %d", 1);
m_pages.erase(m_pages.begin() + n_before_extruders + m_extruders_count,
m_pages.begin() + n_before_extruders + m_extruders_count_old);
}
for (size_t extruder_idx = 0; extruder_idx < m_extruders_count; ++extruder_idx) {
wxString page_title = (m_extruders_count > 1) ? wxString::Format("Extruder %d", filament_index_from_zero_based(static_cast<int>(extruder_idx))) : wxString("Extruder");
m_pages[n_before_extruders + extruder_idx]->set_title(page_title);
}
const wxString& first_extruder_title = m_pages[n_before_extruders]->title();
auto & searcher = wxGetApp().sidebar().get_searcher();
for (auto &group : m_pages[n_before_extruders]->m_optgroups) {
group->set_config_category_and_type(first_extruder_title, m_type);
@ -5076,6 +5088,43 @@ if (is_marlin_flavor)
apply_searcher();
}
void TabPrinter::refresh_extruder_page_titles(bool start_at_zero)
{
if (m_pages.empty() || m_extruders_count == 0)
return;
size_t first_extruder_page = m_pages.size();
for (size_t i = 0; i < m_pages.size(); ++i) {
const wxString& title = m_pages[i]->title();
if (title == "Extruder" || title.StartsWith("Extruder ")) {
first_extruder_page = i;
break;
}
}
if (first_extruder_page >= m_pages.size())
return;
for (size_t extruder_idx = 0; extruder_idx < m_extruders_count; ++extruder_idx) {
const size_t page_index = first_extruder_page + extruder_idx;
if (page_index >= m_pages.size())
break;
wxString page_title = (m_extruders_count > 1) ? wxString::Format("Extruder %d", static_cast<int>(extruder_idx) + (start_at_zero ? 0 : 1)) : wxString("Extruder");
m_pages[page_index]->set_title(page_title);
}
const wxString& first_extruder_title = m_pages[first_extruder_page]->title();
auto& searcher = wxGetApp().sidebar().get_searcher();
for (auto& group : m_pages[first_extruder_page]->m_optgroups) {
group->set_config_category_and_type(first_extruder_title, m_type);
for (auto& opt : group->opt_map())
searcher.add_key(opt.first + "#0", m_type, group->title, first_extruder_title);
}
rebuild_page_tree();
apply_searcher();
}
// this gets executed after preset is loaded and before GUI fields are updated
void TabPrinter::on_preset_loaded()
{
@ -7075,6 +7124,16 @@ void Page::reload_config()
group->reload_config();
}
void Page::set_title(const wxString& title)
{
if (m_title == title)
return;
m_title = title;
if (m_page_title)
m_page_title->SetLabel(_(m_title));
}
void Page::update_visibility(ConfigOptionMode mode, bool update_contolls_visibility)
{
bool ret_val = false;

View file

@ -86,6 +86,7 @@ public:
wxBoxSizer* vsizer() const { return m_vsizer; }
wxWindow* parent() const { return m_parent; }
const wxString& title() const { return m_title; }
void set_title(const wxString& title);
size_t iconID() const { return m_iconID; }
void set_config(DynamicPrintConfig* config_in) { m_config = config_in; }
void reload_config();
@ -640,6 +641,7 @@ public:
bool supports_printer_technology(const PrinterTechnology /* tech */) const override { return true; }
void set_extruder_volume_type(int extruder_id, NozzleVolumeType type);
void refresh_extruder_page_titles(bool start_at_zero);
wxSizer* create_bed_shape_widget(wxWindow* parent);
void cache_extruder_cnt(const DynamicPrintConfig* config = nullptr);

View file

@ -548,13 +548,15 @@ std::vector<wxBitmap*> get_extruder_color_icons(bool thin_icon/* = false*/)
int index = 0;
for (const auto &colors : readable_color_info) {
auto label = std::to_string(++index);
bool is_gradient = ctype[index-1] == "0";
const int display_index = Slic3r::GUI::filament_index_from_zero_based(index);
auto label = std::to_string(display_index);
bool is_gradient = ctype[index] == "0";
if (colors.size() == 1) {
bmps.push_back(get_extruder_color_icon(colors[0], label, icon_width, icon_height));
} else {
bmps.push_back(get_extruder_color_icon(colors, is_gradient, label, icon_width, icon_height));
}
++index;
}
} else {
std::vector<std::string> colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
@ -565,8 +567,10 @@ std::vector<wxBitmap*> get_extruder_color_icons(bool thin_icon/* = false*/)
const int icon_height = lround(2 * em);
int index = 0;
for (const auto &color : colors) {
auto label = std::to_string(++index);
const int display_index = Slic3r::GUI::filament_index_from_zero_based(index);
auto label = std::to_string(display_index);
bmps.push_back(get_extruder_color_icon(color, label, icon_width, icon_height));
++index;
}
}
return bmps;
@ -790,9 +794,8 @@ void apply_extruder_selector(Slic3r::GUI::BitmapComboBox** ctrl,
++i;
}
(*ctrl)->Append(use_full_item_name
? Slic3r::GUI::from_u8((boost::format("%1% %2%") % str % i).str())
: wxString::Format("%d", i), *bmp);
const int display_index = Slic3r::GUI::filament_index_from_one_based(i);
(*ctrl)->Append(use_full_item_name ? Slic3r::GUI::from_u8((boost::format("%1% %2%") % str % display_index).str()) : wxString::Format("%d", display_index), *bmp);
++i;
}
(*ctrl)->SetSelection(0);