mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-10 01:01:57 +00:00
Merge upstream/main into belt-printer
Brings belt-printer up to main4b4a261787. Resolutions: - G-code header (#15897, #15915): main moved the header, config and thumbnail block later in _do_export; write_belt_header() moves with it, still after the thumbnails and outside the BTT_TFT gate. - _extrude: first-layer acceleration keeps the per-path first-layer plane test with main's cached nozzle index (#16028); main's set_speed out-param form (#16108) everywhere else. - GCodeWriter (#16108): the arc-to-polyline fallback for machine mappings that cannot express G2/G3 now runs in the out-param extrude_arc_to_xy, which is the overload GCode calls, and appends to the caller's string. - GCodeProcessorResult: the belt fields join main's forwarding assign. - Clipper2 (#15969): belt arrange helpers take Slic3r::Point; the tree support join types lose their ClipperLib qualifier. - CLI arrange (#15837): belt printers still reserve no wipe tower. - Wipe tower options (#15841): the two new sparse-layer toggles are hidden for belt printers like the rest of the tower options. - Keyboard shortcuts (#15706): main's registry replaces the old key switch; the belt view toggle is re-registered in the next commit. - Print::process: the belt purge-plan undo runs before main's SliceStarted event. - scripts/filament_id_snapshot.json: deleted on main (a77209af8f). - Includes and appended tests: union of both sides.
This commit is contained in:
@@ -1,20 +1,45 @@
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "Geometry.hpp"
|
||||
#include "CustomGCode.hpp"
|
||||
#include "Config.hpp"
|
||||
#include "Model.hpp"
|
||||
#include "Point.hpp"
|
||||
#include "Polygon.hpp"
|
||||
#include "Print.hpp"
|
||||
#include "BeltTransform.hpp"
|
||||
#include "FilamentMixer.hpp"
|
||||
#include "Slicing.hpp"
|
||||
#include "libslic3r.h"
|
||||
#include "PrintConfig.hpp"
|
||||
#include "PrintBase.hpp"
|
||||
#include "libslic3r_version.h"
|
||||
#include "TriangleSelector.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <cassert>
|
||||
#include <cfloat>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <initializer_list>
|
||||
#include <set>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <mutex>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// Add or remove support modifier ModelVolumes from model_object_dst to match the ModelVolumes of model_object_new
|
||||
// Add or remove support and Precise Seam modifier ModelVolumes from model_object_dst to match the ModelVolumes of model_object_new
|
||||
// in the exact order and with the same IDs.
|
||||
// It is expected, that the model_object_dst already contains the non-support volumes of model_object_new in the correct order.
|
||||
// Other volume types must already match model_object_new in the correct order.
|
||||
// Friend to ModelVolume to allow copying.
|
||||
// static is not accepted by gcc if declared as a friend of ModelObject.
|
||||
/* static */ void model_volume_list_update_supports(ModelObject &model_object_dst, const ModelObject &model_object_new)
|
||||
/* static */ void model_volume_list_update_supports_and_seams(ModelObject &model_object_dst, const ModelObject &model_object_new)
|
||||
{
|
||||
typedef std::pair<const ModelVolume*, bool> ModelVolumeWithStatus;
|
||||
std::vector<ModelVolumeWithStatus> old_volumes;
|
||||
@@ -34,18 +59,22 @@ namespace Slic3r {
|
||||
assert(! it->second); // not consumed yet
|
||||
it->second = true;
|
||||
ModelVolume *model_volume_dst = const_cast<ModelVolume*>(it->first);
|
||||
// For support modifiers, the type may have been switched from blocker to enforcer and vice versa.
|
||||
assert((model_volume_dst->is_support_modifier() && model_volume_src->is_support_modifier()) || model_volume_dst->type() == model_volume_src->type());
|
||||
// Type may switch within support family, within precise_seam family, or between them.
|
||||
assert((model_volume_dst->is_support_modifier() && model_volume_src->is_support_modifier()) ||
|
||||
(model_volume_dst->is_precise_seam() && model_volume_src->is_precise_seam()) ||
|
||||
(model_volume_dst->is_support_modifier() && model_volume_src->is_precise_seam()) ||
|
||||
(model_volume_dst->is_precise_seam() && model_volume_src->is_support_modifier()) ||
|
||||
model_volume_dst->type() == model_volume_src->type());
|
||||
model_object_dst.volumes.emplace_back(model_volume_dst);
|
||||
if (model_volume_dst->is_support_modifier()) {
|
||||
// For support modifiers, the type may have been switched from blocker to enforcer and vice versa.
|
||||
if (model_volume_dst->is_support_modifier() || model_volume_dst->is_precise_seam()) {
|
||||
// Type may have been switched within or between support/precise_seam families.
|
||||
model_volume_dst->set_type(model_volume_src->type());
|
||||
model_volume_dst->set_transformation(model_volume_src->get_transformation());
|
||||
}
|
||||
assert(model_volume_dst->get_matrix().isApprox(model_volume_src->get_matrix()));
|
||||
} else {
|
||||
// The volume was not found in the old list. Create a new copy.
|
||||
assert(model_volume_src->is_support_modifier());
|
||||
assert(model_volume_src->is_support_modifier() || model_volume_src->is_precise_seam());
|
||||
model_object_dst.volumes.emplace_back(new ModelVolume(*model_volume_src));
|
||||
model_object_dst.volumes.back()->set_model_object(&model_object_dst);
|
||||
}
|
||||
@@ -56,17 +85,20 @@ namespace Slic3r {
|
||||
delete mv_with_status.first;
|
||||
}
|
||||
|
||||
static inline void model_volume_list_copy_configs(ModelObject &model_object_dst, const ModelObject &model_object_src, const ModelVolumeType type)
|
||||
// Copy configs of ModelVolumes matching type_filter predicate from src to dst.
|
||||
// Mirrors the template pattern of model_volume_list_changed() in Model.cpp.
|
||||
template<typename TypeFilterFn>
|
||||
static inline void model_volume_list_copy_configs(ModelObject &model_object_dst, const ModelObject &model_object_src, TypeFilterFn type_filter)
|
||||
{
|
||||
size_t i_src, i_dst;
|
||||
for (i_src = 0, i_dst = 0; i_src < model_object_src.volumes.size() && i_dst < model_object_dst.volumes.size();) {
|
||||
const ModelVolume &mv_src = *model_object_src.volumes[i_src];
|
||||
ModelVolume &mv_dst = *model_object_dst.volumes[i_dst];
|
||||
if (mv_src.type() != type) {
|
||||
if (! type_filter(mv_src.type())) {
|
||||
++ i_src;
|
||||
continue;
|
||||
}
|
||||
if (mv_dst.type() != type) {
|
||||
if (! type_filter(mv_dst.type())) {
|
||||
++ i_dst;
|
||||
continue;
|
||||
}
|
||||
@@ -89,6 +121,20 @@ static inline void model_volume_list_copy_configs(ModelObject &model_object_dst,
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience overload: single volume type.
|
||||
static inline void model_volume_list_copy_configs(ModelObject &model_object_dst, const ModelObject &model_object_src, const ModelVolumeType type)
|
||||
{
|
||||
model_volume_list_copy_configs(model_object_dst, model_object_src, [type](const ModelVolumeType t) { return t == type; });
|
||||
}
|
||||
|
||||
// Convenience overload: multiple volume types at once (e.g. all precise seam types).
|
||||
static inline void model_volume_list_copy_configs(ModelObject &model_object_dst, const ModelObject &model_object_src, const std::initializer_list<ModelVolumeType> &types)
|
||||
{
|
||||
model_volume_list_copy_configs(model_object_dst, model_object_src, [&types](const ModelVolumeType t) {
|
||||
return std::find(types.begin(), types.end(), t) != types.end();
|
||||
});
|
||||
}
|
||||
|
||||
static inline void layer_height_ranges_copy_configs(t_layer_config_ranges &lr_dst, const t_layer_config_ranges &lr_src)
|
||||
{
|
||||
assert(lr_dst.size() == lr_src.size());
|
||||
@@ -702,7 +748,10 @@ void print_objects_regions_invalidate_keep_some_volumes(PrintObjectRegions &prin
|
||||
for (; i_old < old_volumes.size(); ++ i_old)
|
||||
if (old_volumes[i_old]->id() >= new_volumes[i_new]->id())
|
||||
break;
|
||||
if (i_old != old_volumes.size() && old_volumes[i_old]->id() == new_volumes[i_new]->id()) {
|
||||
// IDs survive type changes: an old volume that was not a solid or modifier was never cached,
|
||||
// so treat it as new instead of looking it up.
|
||||
if (i_old != old_volumes.size() && old_volumes[i_old]->id() == new_volumes[i_new]->id() &&
|
||||
model_volume_solid_or_modifier(*old_volumes[i_old])) {
|
||||
if (old_volumes[i_old]->get_matrix().isApprox(new_volumes[i_new]->get_matrix())) {
|
||||
// Reuse the volume.
|
||||
for (; print_object_regions.cached_volume_ids[i_cached_volume] < old_volumes[i_old]->id(); ++ i_cached_volume)
|
||||
@@ -1307,7 +1356,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
// Reproduce that exact expansion here so an unchanged config diffs empty — the expanded
|
||||
// keys invalidate the wipe tower / g-code export, and the placeholder parser aliases
|
||||
// the full config — instead of trimming back to one slot per filament.
|
||||
auto group_result = std::dynamic_pointer_cast<MultiNozzleUtils::LayeredNozzleGroupResult>(this->get_nozzle_group_result());
|
||||
auto group_result = this->get_layered_nozzle_group_result();
|
||||
std::unordered_map<int, std::vector<FilamentVariantUse>> filament_variant_uses;
|
||||
if (group_result && group_result->is_support_dynamic_nozzle_map()
|
||||
&& collect_filament_variant_uses(*group_result, m_ori_full_print_config, filament_variant_uses))
|
||||
@@ -1315,7 +1364,9 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
extruder_count, extruder_volume_type_count, filament_keys,
|
||||
"filament_self_index", "filament_extruder_variant",
|
||||
&dynamic_slot_indices);
|
||||
else if ((extruder_count > 1) || different_extruder)
|
||||
// Orca: also on a printer with a single extruder variant once a filament defines several
|
||||
// (e.g. Standard and High Flow), so each filament takes its variant for that extruder.
|
||||
else if ((extruder_count > 1) || different_extruder || new_full_config.has_multi_variant_filament())
|
||||
new_full_config.update_values_to_printer_extruders_for_multiple_filaments(m_ori_full_print_config, extruder_count, extruder_volume_type_count, filament_keys,
|
||||
"filament_self_index", "filament_extruder_variant");
|
||||
}
|
||||
@@ -1637,6 +1688,11 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
|
||||
// 3) Synchronize ModelObjects & PrintObjects.
|
||||
const std::initializer_list<ModelVolumeType> solid_or_modifier_types { ModelVolumeType::MODEL_PART, ModelVolumeType::NEGATIVE_VOLUME, ModelVolumeType::PARAMETER_MODIFIER };
|
||||
const std::initializer_list<ModelVolumeType> precise_seam_types {
|
||||
ModelVolumeType::PRECISE_SEAM_CENTER, ModelVolumeType::PRECISE_SEAM_LEFT,
|
||||
ModelVolumeType::PRECISE_SEAM_RIGHT, ModelVolumeType::PRECISE_SEAM_ENFORCED,
|
||||
ModelVolumeType::PRECISE_SEAM_BLOCKED, ModelVolumeType::PRECISE_SEAM_NEUTRAL
|
||||
};
|
||||
for (size_t idx_model_object = 0; idx_model_object < model.objects.size(); ++ idx_model_object) {
|
||||
ModelObject &model_object = *m_model.objects[idx_model_object];
|
||||
ModelObjectStatus &model_object_status = const_cast<ModelObjectStatus&>(model_object_status_db.reuse(model_object));
|
||||
@@ -1654,6 +1710,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
model_fuzzy_skin_data_changed(model_object, model_object_new);
|
||||
bool supports_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_BLOCKER) ||
|
||||
model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_ENFORCER);
|
||||
bool precise_seam_differ = model_volume_list_changed(model_object, model_object_new, precise_seam_types);
|
||||
bool layer_height_ranges_differ = ! layer_height_ranges_equal(model_object.layer_config_ranges, model_object_new.layer_config_ranges, model_object_new.layer_height_profile.empty());
|
||||
bool model_origin_translation_differ = model_object.origin_translation != model_object_new.origin_translation;
|
||||
bool brim_points_differ = model_brim_points_data_changed(model_object, model_object_new);
|
||||
@@ -1696,13 +1753,20 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
// Invalidate just the supports step.
|
||||
for (const PrintObjectStatus &print_object_status : print_objects_range)
|
||||
update_apply_status(print_object_status.print_object->invalidate_step(posSupportMaterial));
|
||||
if (supports_differ) {
|
||||
// Copy just the support volumes.
|
||||
model_volume_list_update_supports(model_object, model_object_new);
|
||||
}
|
||||
}
|
||||
if (precise_seam_differ) {
|
||||
// First stop background processing before shuffling or deleting the ModelVolumes in the ModelObject's list.
|
||||
this->call_cancel_callback();
|
||||
update_apply_status(false);
|
||||
// Invalidate seam placement (affects G-code export).
|
||||
update_apply_status(this->invalidate_step(psGCodeExport));
|
||||
} else if (model_custom_seam_data_changed(model_object, model_object_new)) {
|
||||
update_apply_status(this->invalidate_step(psGCodeExport));
|
||||
}
|
||||
// Synchronize both families once, after cancellation and all affected-step invalidations.
|
||||
// This also handles type changes between supports and Precise Seam before copying configs below.
|
||||
if (supports_differ || precise_seam_differ)
|
||||
model_volume_list_update_supports_and_seams(model_object, model_object_new);
|
||||
if (brim_points_differ) {
|
||||
model_object.brim_points = model_object_new.brim_points;
|
||||
update_apply_status(this->invalidate_all_steps());
|
||||
@@ -1727,6 +1791,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
//FIXME What to do with m_material_id?
|
||||
model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, ModelVolumeType::MODEL_PART);
|
||||
model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, ModelVolumeType::PARAMETER_MODIFIER);
|
||||
// Synchronize Precise Seam modifier volumes
|
||||
model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, precise_seam_types);
|
||||
layer_height_ranges_copy_configs(model_object.layer_config_ranges /* dst */, model_object_new.layer_config_ranges /* src */);
|
||||
// Copy the ModelObject name, input_file and instances. The instances will be compared against PrintObject instances in the next step.
|
||||
model_object.name = model_object_new.name;
|
||||
|
||||
Reference in New Issue
Block a user