mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-06 09:37:55 +00:00
Merge branch 'main' into feat/plugin-feature
Resolve five conflicts, all of which needed both sides rather than a pick: - BackgroundSlicingProcess: ours was a pure tabs->spaces reformat of base, so keep main's per-filament volume/nozzle map read-back (its only change here). - GUI_App: main's #12506 else-if attached to an `if` this branch deleted; re-expressed onto the same-agent early-return path (the agent factory caches per id, so pointer equality is the same predicate). - MainFrame: both sides relocated Sync Presets independently; keep main's push_notification plus the branch's Plugins menu items. - Tab: the "TODO: Orca: Support hybrid" blocks were unchanged base, not a branch decision; take main's enabled Hybrid to match the already auto-merged siblings. - test_config: union of both sides' cases (6 plugin + 9 multi-nozzle).
This commit is contained in:
@@ -1316,9 +1316,23 @@ int CLI::run(int argc, char **argv)
|
||||
return CLI_INVALID_PARAMS;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << "finished setup params, argc="<< argc << std::endl;
|
||||
std::string temp_path = wxFileName::GetTempDir().utf8_str().data();
|
||||
std::string temp_path = per_user_temp_dir(wxFileName::GetTempDir().utf8_str().data(), per_user_temp_id());
|
||||
// Some consumers write into the temp root directly, so create it up front.
|
||||
try {
|
||||
boost::filesystem::create_directories(temp_path);
|
||||
} catch (const std::exception &ex) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "failed to create per-user temp dir " << temp_path << ": " << ex.what();
|
||||
}
|
||||
set_temporary_dir(temp_path);
|
||||
|
||||
// The Filament Track Switch flags are live-device state with no meaning in headless slicing;
|
||||
// default both off unless explicitly provided on the command line, so an old 3MF that had
|
||||
// them enabled still slices without the switch behavior.
|
||||
if (!m_extra_config.has("has_filament_switcher"))
|
||||
m_extra_config.set_key_value("has_filament_switcher", new ConfigOptionBool(false));
|
||||
if (!m_extra_config.has("enable_filament_dynamic_map"))
|
||||
m_extra_config.set_key_value("enable_filament_dynamic_map", new ConfigOptionBool(false));
|
||||
|
||||
m_extra_config.apply(m_config, true);
|
||||
m_extra_config.normalize_fdm();
|
||||
|
||||
@@ -1696,11 +1710,13 @@ int CLI::run(int argc, char **argv)
|
||||
const Vec3d &instance_offset = model_instance->get_offset();
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("instance %1% transform {%2%,%3%,%4%} at %5%:%6%")% model_object->name % instance_offset.x() % instance_offset.y() %instance_offset.z() % __FUNCTION__ % __LINE__<< std::endl;
|
||||
}*/
|
||||
current_printer_name = config.option<ConfigOptionString>("printer_settings_id")->value;
|
||||
current_process_name = config.option<ConfigOptionString>("print_settings_id")->value;
|
||||
// Read defensively — a 3mf missing preset ids (e.g. one produced
|
||||
// by a non-GUI writer) would otherwise crash here on the deref.
|
||||
if (const auto *o = config.option<ConfigOptionString>("printer_settings_id")) current_printer_name = o->value;
|
||||
if (const auto *o = config.option<ConfigOptionString>("print_settings_id")) current_process_name = o->value;
|
||||
current_printer_model = config.option<ConfigOptionString>("printer_model", true)->value;
|
||||
current_filaments_name = config.option<ConfigOptionStrings>("filament_settings_id")->values;
|
||||
current_extruder_count = config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
|
||||
if (const auto *o = config.option<ConfigOptionStrings>("filament_settings_id")) current_filaments_name = o->values;
|
||||
if (const auto *o = config.option<ConfigOptionFloats>("nozzle_diameter")) current_extruder_count = o->values.size();
|
||||
current_printer_variant_count = config.option<ConfigOptionStrings>("printer_extruder_variant", true)->values.size();
|
||||
current_print_variant_count = config.option<ConfigOptionStrings>("print_extruder_variant", true)->values.size();
|
||||
current_is_multi_extruder = current_extruder_count > 1;
|
||||
@@ -5930,6 +5946,72 @@ int CLI::run(int argc, char **argv)
|
||||
else
|
||||
filament_maps = part_plate->get_real_filament_maps(m_print_config);
|
||||
|
||||
// Multi-nozzle printers need the per-filament volume assignment as a grouping
|
||||
// input in the manual modes: synthesize it from the per-extruder flow types when
|
||||
// the caller did not provide one (an extruder whose nozzle stats span several
|
||||
// volume types keeps the per-filament choice), and require explicit maps in
|
||||
// nozzle-manual mode.
|
||||
auto max_nozzle_counts_opt = m_print_config.option<ConfigOptionIntsNullable>("extruder_max_nozzle_count");
|
||||
// Skip nil entries: a nullable-int nil is INT_MAX (> 1) and would otherwise falsely pass the gate.
|
||||
bool support_multi_nozzle =
|
||||
max_nozzle_counts_opt &&
|
||||
std::any_of(max_nozzle_counts_opt->values.begin(), max_nozzle_counts_opt->values.end(),
|
||||
[](int v) { return v > 1 && v != ConfigOptionIntsNullable::nil_value(); });
|
||||
if (support_multi_nozzle && (mode == fmmManual || mode == fmmNozzleManual) && (plate_to_slice != 0)) {
|
||||
// Orca: the grouping result is reconstructed purely from the passed maps in
|
||||
// nozzle-manual mode, so all of them must be present (there are no separate
|
||||
// per-nozzle CLI parameters to rebuild them from).
|
||||
if (mode == FilamentMapMode::fmmNozzleManual &&
|
||||
(!m_extra_config.has("filament_volume_map") || !m_extra_config.has("filament_nozzle_map") ||
|
||||
!m_extra_config.has("filament_map"))) {
|
||||
BOOST_LOG_TRIVIAL(error)
|
||||
<< boost::format("%1%, can not find filament_volume_map/filament_nozzle_map/filament_map under Nozzle Manual mode") % __LINE__;
|
||||
record_exit_reson(outfile_dir, CLI_INVALID_PARAMS, index + 1, cli_errors[CLI_INVALID_PARAMS], sliced_info);
|
||||
flush_and_exit(CLI_INVALID_PARAMS);
|
||||
}
|
||||
|
||||
if (mode == fmmManual) {
|
||||
// Build the volume map when absent: filaments on a single-volume extruder
|
||||
// print with that extruder's volume; a mixed-volume extruder keeps the
|
||||
// per-filament choice (default Standard).
|
||||
std::vector<NozzleVolumeType> using_nozzle_volume_type = new_nozzle_volume_type;
|
||||
using_nozzle_volume_type.resize(new_extruder_count, nvtStandard);
|
||||
if (auto extruder_nozzle_stats_opt = m_print_config.option<ConfigOptionStrings>("extruder_nozzle_stats")) {
|
||||
auto nozzle_stats = get_extruder_nozzle_stats(extruder_nozzle_stats_opt->values);
|
||||
for (int e_index = 0; e_index < new_extruder_count && e_index < (int) nozzle_stats.size(); e_index++) {
|
||||
if (nozzle_stats[e_index].size() > 1) {
|
||||
using_nozzle_volume_type[e_index] = nvtHybrid;
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1% : extruder %2%, set nozzle_volume_type to hybrid ") % __LINE__ % (e_index + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::vector<int> &manual_volume_maps = m_extra_config.option<ConfigOptionInts>("filament_volume_map", true)->values;
|
||||
// default to standard flow
|
||||
manual_volume_maps.resize(filament_count, (int) (nvtStandard));
|
||||
for (int f_index = 0; f_index < filament_count && f_index < (int) filament_maps.size(); f_index++) {
|
||||
int f_extruder_index = filament_maps[f_index] - 1;
|
||||
if (f_extruder_index >= 0 && f_extruder_index < new_extruder_count &&
|
||||
using_nozzle_volume_type[f_extruder_index] != nvtHybrid) {
|
||||
manual_volume_maps[f_index] = int(using_nozzle_volume_type[f_extruder_index]);
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1% : filament %2% extruder %3%, set filament_volume_map to %4% ") % __LINE__ % (f_index + 1) % (f_extruder_index + 1) % manual_volume_maps[f_index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_extra_config.has("filament_volume_map")) {
|
||||
part_plate->set_filament_volume_maps(m_extra_config.option<ConfigOptionInts>("filament_volume_map")->values);
|
||||
}
|
||||
if (m_extra_config.has("filament_nozzle_map")) {
|
||||
part_plate->set_filament_nozzle_maps(m_extra_config.option<ConfigOptionInts>("filament_nozzle_map")->values);
|
||||
}
|
||||
}
|
||||
else if (!support_multi_nozzle && (mode == fmmNozzleManual)) {
|
||||
BOOST_LOG_TRIVIAL(error)
|
||||
<< boost::format("%1%, Nozzle Manual mode not supported for %2%") % __LINE__ % new_printer_name;
|
||||
record_exit_reson(outfile_dir, CLI_INVALID_PARAMS, index + 1, cli_errors[CLI_INVALID_PARAMS], sliced_info);
|
||||
flush_and_exit(CLI_INVALID_PARAMS);
|
||||
}
|
||||
|
||||
for (int index = 0; index < filament_maps.size(); index++)
|
||||
{
|
||||
int filament_extruder = filament_maps[index];
|
||||
@@ -6168,6 +6250,22 @@ int CLI::run(int argc, char **argv)
|
||||
BOOST_LOG_TRIVIAL(info) << "print::process: first time_using_cache is " << time_using_cache << " secs.";
|
||||
}
|
||||
if (printer_technology == ptFFF) {
|
||||
// Read the engine's final grouping back onto the plate so an exported
|
||||
// project (--export-3mf / gcode.3mf) carries the concrete maps in its
|
||||
// plate settings, matching what a GUI slice persists.
|
||||
// Orca: deliberately gated to multi-extruder printers so single-extruder
|
||||
// exports keep their plate settings unchanged.
|
||||
if (new_extruder_count > 1) {
|
||||
FilamentMapMode current_map_mode = print_fff->config().filament_map_mode.value;
|
||||
if (is_auto_filament_map_mode(current_map_mode)) {
|
||||
part_plate->set_filament_maps(print_fff->get_filament_maps());
|
||||
part_plate->set_filament_volume_maps(print_fff->get_filament_volume_maps());
|
||||
}
|
||||
if (current_map_mode != FilamentMapMode::fmmNozzleManual) {
|
||||
part_plate->set_filament_nozzle_maps(print_fff->get_filament_nozzle_maps());
|
||||
}
|
||||
}
|
||||
|
||||
std::string conflict_result = print_fff->get_conflict_string();
|
||||
if (!conflict_result.empty()) {
|
||||
BOOST_LOG_TRIVIAL(error) << "plate "<< index+1<< ": found slicing result conflict!"<< std::endl;
|
||||
@@ -7352,7 +7450,7 @@ bool CLI::export_project(Model *model, std::string& path, PlateDataPtrs &partpla
|
||||
bool success = false;
|
||||
|
||||
StoreParams store_params;
|
||||
store_params.path = path.c_str();
|
||||
store_params.path = path;
|
||||
store_params.model = model;
|
||||
store_params.plate_data_list = partplate_data;
|
||||
store_params.project_presets = project_presets;
|
||||
|
||||
Reference in New Issue
Block a user