Allow specifying print order within each layer (#3685)

* Allow reordering objects regardless of print seq

* Add option to control the layer print order

* Sort object by their order in object list instead of id

* Show print order when print order is the same as the object list

* Ensure the print order when print order is same as object list

* Update option name

---------

Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
Noisyfox 2024-01-21 20:11:09 +08:00 committed by GitHub
parent e92be73894
commit 26505e23ee
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 54 additions and 28 deletions

View file

@ -1834,6 +1834,15 @@ static inline std::vector<const PrintInstance*> sort_object_instances_by_max_z(c
//BBS: add sort logic for seq-print //BBS: add sort logic for seq-print
std::vector<const PrintInstance*> sort_object_instances_by_model_order(const Print& print, bool init_order) std::vector<const PrintInstance*> sort_object_instances_by_model_order(const Print& print, bool init_order)
{ {
auto find_object_index = [](const Model& model, const ModelObject* obj) {
for (int index = 0; index < model.objects.size(); index++)
{
if (model.objects[index] == obj)
return index;
}
return -1;
};
// Build up map from ModelInstance* to PrintInstance* // Build up map from ModelInstance* to PrintInstance*
std::vector<std::pair<const ModelInstance*, const PrintInstance*>> model_instance_to_print_instance; std::vector<std::pair<const ModelInstance*, const PrintInstance*>> model_instance_to_print_instance;
model_instance_to_print_instance.reserve(print.num_object_instances()); model_instance_to_print_instance.reserve(print.num_object_instances());
@ -1841,10 +1850,16 @@ std::vector<const PrintInstance*> sort_object_instances_by_model_order(const Pri
for (const PrintInstance &print_instance : print_object->instances()) for (const PrintInstance &print_instance : print_object->instances())
{ {
if (init_order) if (init_order)
const_cast<ModelInstance*>(print_instance.model_instance)->arrange_order = print_instance.model_instance->id().id; const_cast<ModelInstance*>(print_instance.model_instance)->arrange_order = find_object_index(print.model(), print_object->model_object());
model_instance_to_print_instance.emplace_back(print_instance.model_instance, &print_instance); model_instance_to_print_instance.emplace_back(print_instance.model_instance, &print_instance);
} }
std::sort(model_instance_to_print_instance.begin(), model_instance_to_print_instance.end(), [](auto &l, auto &r) { return l.first->arrange_order < r.first->arrange_order; }); std::sort(model_instance_to_print_instance.begin(), model_instance_to_print_instance.end(), [](auto &l, auto &r) { return l.first->arrange_order < r.first->arrange_order; });
if (init_order) {
// Re-assign the arrange_order so each instance has a unique order number
for (int k = 0; k < model_instance_to_print_instance.size(); k++) {
const_cast<ModelInstance*>(model_instance_to_print_instance[k].first)->arrange_order = k + 1;
}
}
std::vector<const PrintInstance*> instances; std::vector<const PrintInstance*> instances;
instances.reserve(model_instance_to_print_instance.size()); instances.reserve(model_instance_to_print_instance.size());
@ -2203,8 +2218,11 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
// In non-sequential print, the printing extruders may have been modified by the extruder switches stored in Model::custom_gcode_per_print_z. // In non-sequential print, the printing extruders may have been modified by the extruder switches stored in Model::custom_gcode_per_print_z.
// Therefore initialize the printing extruders from there. // Therefore initialize the printing extruders from there.
this->set_extruders(tool_ordering.all_extruders()); this->set_extruders(tool_ordering.all_extruders());
// Order object instances using a nearest neighbor search. print_object_instances_ordering =
print_object_instances_ordering = chain_print_object_instances(print); // By default, order object instances using a nearest neighbor search.
print.config().print_order == PrintOrder::Default ? chain_print_object_instances(print)
// Otherwise same order as the object list
: sort_object_instances_by_model_order(print);
} }
if (initial_extruder_id == (unsigned int)-1) { if (initial_extruder_id == (unsigned int)-1) {
// Nothing to print! // Nothing to print!
@ -3972,7 +3990,7 @@ LayerResult GCode::process_layer(
std::vector<InstanceToPrint> instances_to_print; std::vector<InstanceToPrint> instances_to_print;
bool has_prime_tower = print.config().enable_prime_tower bool has_prime_tower = print.config().enable_prime_tower
&& print.extruders().size() > 1 && print.extruders().size() > 1
&& (print.config().print_sequence == PrintSequence::ByLayer && ((print.config().print_sequence == PrintSequence::ByLayer && print.config().print_order == PrintOrder::Default)
|| (print.config().print_sequence == PrintSequence::ByObject && print.objects().size() == 1)); || (print.config().print_sequence == PrintSequence::ByObject && print.objects().size() == 1));
if (has_prime_tower) { if (has_prime_tower) {
int plate_idx = print.get_plate_index(); int plate_idx = print.get_plate_index();

View file

@ -786,7 +786,7 @@ static std::vector<std::string> s_Preset_print_options {
"independent_support_layer_height", "independent_support_layer_height",
"support_angle", "support_interface_top_layers", "support_interface_bottom_layers", "support_angle", "support_interface_top_layers", "support_interface_bottom_layers",
"support_interface_pattern", "support_interface_spacing", "support_interface_loop_pattern", "support_interface_pattern", "support_interface_spacing", "support_interface_loop_pattern",
"support_top_z_distance", "support_on_build_plate_only","support_critical_regions_only", "bridge_no_support", "thick_bridges", "thick_internal_bridges","dont_filter_internal_bridges", "max_bridge_length", "print_sequence", "support_remove_small_overhang", "support_top_z_distance", "support_on_build_plate_only","support_critical_regions_only", "bridge_no_support", "thick_bridges", "thick_internal_bridges","dont_filter_internal_bridges", "max_bridge_length", "print_sequence", "print_order", "support_remove_small_overhang",
"filename_format", "wall_filament", "support_bottom_z_distance", "filename_format", "wall_filament", "support_bottom_z_distance",
"sparse_infill_filament", "solid_infill_filament", "support_filament", "support_interface_filament","support_interface_not_for_body", "sparse_infill_filament", "solid_infill_filament", "support_filament", "support_interface_filament","support_interface_not_for_body",
"ooze_prevention", "standby_temperature_delta", "interface_shells", "line_width", "initial_layer_line_width", "ooze_prevention", "standby_temperature_delta", "interface_shells", "line_width", "initial_layer_line_width",

View file

@ -314,6 +314,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
//|| opt_key == "resolution" //|| opt_key == "resolution"
//BBS: when enable arc fitting, we must re-generate perimeter //BBS: when enable arc fitting, we must re-generate perimeter
|| opt_key == "enable_arc_fitting" || opt_key == "enable_arc_fitting"
|| opt_key == "print_order"
|| opt_key == "wall_sequence") { || opt_key == "wall_sequence") {
osteps.emplace_back(posPerimeters); osteps.emplace_back(posPerimeters);
osteps.emplace_back(posEstimateCurledExtrusions); osteps.emplace_back(posEstimateCurledExtrusions);

View file

@ -195,6 +195,12 @@ static t_config_enum_values s_keys_map_PrintSequence {
}; };
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrintSequence) CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrintSequence)
static t_config_enum_values s_keys_map_PrintOrder{
{ "default", int(PrintOrder::Default) },
{ "as_obj_list", int(PrintOrder::AsObjectList)},
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrintOrder)
static t_config_enum_values s_keys_map_SlicingMode { static t_config_enum_values s_keys_map_SlicingMode {
{ "regular", int(SlicingMode::Regular) }, { "regular", int(SlicingMode::Regular) },
{ "even_odd", int(SlicingMode::EvenOdd) }, { "even_odd", int(SlicingMode::EvenOdd) },
@ -1171,6 +1177,17 @@ void PrintConfigDef::init_fff_params()
def->mode = comSimple; def->mode = comSimple;
def->set_default_value(new ConfigOptionEnum<PrintSequence>(PrintSequence::ByLayer)); def->set_default_value(new ConfigOptionEnum<PrintSequence>(PrintSequence::ByLayer));
def = this->add("print_order", coEnum);
def->label = L("Layer order");
def->tooltip = L("Print order within a single layer");
def->enum_keys_map = &ConfigOptionEnum<PrintOrder>::get_enum_values();
def->enum_values.push_back("default");
def->enum_values.push_back("as_obj_list");
def->enum_labels.push_back(L("Default"));
def->enum_labels.push_back(L("As object list"));
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<PrintOrder>(PrintOrder::Default));
def = this->add("slow_down_for_layer_cooling", coBools); def = this->add("slow_down_for_layer_cooling", coBools);
def->label = L("Slow printing down for better layer cooling"); def->label = L("Slow printing down for better layer cooling");
def->tooltip = L("Enable this option to slow printing speed down to make the final layer time not shorter than " def->tooltip = L("Enable this option to slow printing speed down to make the final layer time not shorter than "

View file

@ -106,6 +106,13 @@ enum class PrintSequence {
Count, Count,
}; };
enum class PrintOrder
{
Default,
AsObjectList,
Count,
};
enum class SlicingMode enum class SlicingMode
{ {
// Regular, applying ClipperLib::pftNonZero rule when creating ExPolygons. // Regular, applying ClipperLib::pftNonZero rule when creating ExPolygons.
@ -1101,6 +1108,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionInts, overhang_fan_speed)) ((ConfigOptionInts, overhang_fan_speed))
((ConfigOptionEnumsGeneric, overhang_fan_threshold)) ((ConfigOptionEnumsGeneric, overhang_fan_threshold))
((ConfigOptionEnum<PrintSequence>,print_sequence)) ((ConfigOptionEnum<PrintSequence>,print_sequence))
((ConfigOptionEnum<PrintOrder>, print_order))
((ConfigOptionInts, first_layer_print_sequence)) ((ConfigOptionInts, first_layer_print_sequence))
((ConfigOptionBools, slow_down_for_layer_cooling)) ((ConfigOptionBools, slow_down_for_layer_cooling))
((ConfigOptionInts, close_fan_the_first_x_layers)) ((ConfigOptionInts, close_fan_the_first_x_layers))

View file

@ -661,9 +661,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
for (auto el : { "ironing_pattern", "ironing_flow", "ironing_spacing", "ironing_speed", "ironing_angle" }) for (auto el : { "ironing_pattern", "ironing_flow", "ironing_spacing", "ironing_speed", "ironing_angle" })
toggle_line(el, has_ironing); toggle_line(el, has_ironing);
// bool have_sequential_printing = (config->opt_enum<PrintSequence>("print_sequence") == PrintSequence::ByObject); bool have_sequential_printing = (config->opt_enum<PrintSequence>("print_sequence") == PrintSequence::ByObject);
// for (auto el : { "extruder_clearance_radius", "extruder_clearance_height_to_rod", "extruder_clearance_height_to_lid" }) // for (auto el : { "extruder_clearance_radius", "extruder_clearance_height_to_rod", "extruder_clearance_height_to_lid" })
// toggle_field(el, have_sequential_printing); // toggle_field(el, have_sequential_printing);
toggle_field("print_order", !have_sequential_printing);
bool have_ooze_prevention = config->opt_bool("ooze_prevention"); bool have_ooze_prevention = config->opt_bool("ooze_prevention");
toggle_field("standby_temperature_delta", have_ooze_prevention); toggle_field("standby_temperature_delta", have_ooze_prevention);

View file

@ -7304,10 +7304,10 @@ void GLCanvas3D::_render_overlays()
auto curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate(); auto curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
auto curr_print_seq = curr_plate->get_real_print_seq(); auto curr_print_seq = curr_plate->get_real_print_seq();
bool sequential_print = (curr_print_seq == PrintSequence::ByObject); const Print* print = fff_print();
bool sequential_print = (curr_print_seq == PrintSequence::ByObject) || print->config().print_order == PrintOrder::AsObjectList;
std::vector<const ModelInstance*> sorted_instances; std::vector<const ModelInstance*> sorted_instances;
if (sequential_print) { if (sequential_print) {
const Print* print = fff_print();
if (print) { if (print) {
for (const PrintObject *print_object : print->objects()) for (const PrintObject *print_object : print->objects())
{ {

View file

@ -1545,26 +1545,6 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
} }
if (type & itObject) { if (type & itObject) {
int curr_obj_id = m_objects_model->GetIdByItem(event.GetItem());
PartPlateList& partplate_list = wxGetApp().plater()->get_partplate_list();
int from_plate = partplate_list.find_instance(curr_obj_id, 0);
if (from_plate == -1) {
event.Veto();
return;
}
auto curr_plate_seq = partplate_list.get_plate(from_plate)->get_print_seq();
if (curr_plate_seq == PrintSequence::ByDefault) {
auto curr_preset_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
if (curr_preset_config.has("print_sequence"))
curr_plate_seq = curr_preset_config.option<ConfigOptionEnum<PrintSequence>>("print_sequence")->value;
}
if (curr_plate_seq != PrintSequence::ByObject) {
//drag forbidden under bylayer mode
event.Veto();
return;
}
m_dragged_data.init(m_objects_model->GetIdByItem(item), type); m_dragged_data.init(m_objects_model->GetIdByItem(item), type);
} }
else if (type & itVolume){ else if (type & itVolume){

View file

@ -2188,6 +2188,7 @@ void TabPrint::build()
optgroup = page->new_optgroup(L("Special mode"), L"param_special"); optgroup = page->new_optgroup(L("Special mode"), L"param_special");
optgroup->append_single_option_line("slicing_mode"); optgroup->append_single_option_line("slicing_mode");
optgroup->append_single_option_line("print_sequence", "sequent-print"); optgroup->append_single_option_line("print_sequence", "sequent-print");
optgroup->append_single_option_line("print_order");
optgroup->append_single_option_line("spiral_mode", "spiral-vase"); optgroup->append_single_option_line("spiral_mode", "spiral-vase");
optgroup->append_single_option_line("spiral_mode_smooth", "spiral-vase#smooth"); optgroup->append_single_option_line("spiral_mode_smooth", "spiral-vase#smooth");
optgroup->append_single_option_line("spiral_mode_max_xy_smoothing", "spiral-vase#max-xy-smoothing"); optgroup->append_single_option_line("spiral_mode_max_xy_smoothing", "spiral-vase#max-xy-smoothing");