Merge upstream/main into belt-printer

Brings belt-printer up to main 4b4a261787. 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:
harrierpigeon
2026-10-04 19:20:33 -05:00
11471 changed files with 2992690 additions and 2720441 deletions
+72 -50
View File
@@ -1,6 +1,11 @@
#ifndef slic3r_GCodeProcessor_hpp_
#define slic3r_GCodeProcessor_hpp_
#include "libslic3r/CommonDefs.hpp"
#include "libslic3r/libslic3r.h"
#include "libslic3r/Polygon.hpp"
#include "libslic3r/Config.hpp"
#include "libslic3r/ArcFitter.hpp"
#include "libslic3r/GCodeReader.hpp"
#include "libslic3r/Point.hpp"
#include "libslic3r/ExtrusionEntity.hpp"
@@ -9,8 +14,17 @@
#include "libslic3r/MultiNozzleUtils.hpp"
#include "libslic3r/GCode/MachineFrameTransform.hpp"
#include <cstddef>
#include <cassert>
#include <cstdint>
#include <array>
#include <unordered_map>
#include <utility>
#include <map>
#include <memory>
#include <functional>
#include <cstdlib>
#include <set>
#include <vector>
#include <mutex>
#include <string>
@@ -340,60 +354,63 @@ class Print;
//BBS: add mutex for protection of gcode result
mutable std::mutex result_mutex;
GCodeProcessorResult& operator=(const GCodeProcessorResult &other)
GCodeProcessorResult& operator=(const GCodeProcessorResult &other) { assign(other); return *this; }
// Declared because the user-declared copy assignment suppresses the implicit move.
GCodeProcessorResult& operator=(GCodeProcessorResult &&other) { assign(std::move(other)); return *this; }
// Add a new member here, or neither assignment transfers it.
template<class Other> void assign(Other &&other)
{
filename = other.filename;
id = other.id;
moves = other.moves;
lines_ends = other.lines_ends;
printable_area = other.printable_area;
bed_exclude_area = other.bed_exclude_area;
wrapping_exclude_area = other.wrapping_exclude_area;
toolpath_outside = other.toolpath_outside;
label_object_enabled = other.label_object_enabled;
long_retraction_when_cut = other.long_retraction_when_cut;
timelapse_warning_code = other.timelapse_warning_code;
printable_height = other.printable_height;
settings_ids = other.settings_ids;
filaments_count = other.filaments_count;
extruder_colors = other.extruder_colors;
filament_diameters = other.filament_diameters;
filament_densities = other.filament_densities;
filament_costs = other.filament_costs;
print_statistics = other.print_statistics;
custom_gcode_per_print_z = other.custom_gcode_per_print_z;
spiral_vase_mode = other.spiral_vase_mode;
warnings = other.warnings;
bed_type = other.bed_type;
gcode_check_result = other.gcode_check_result;
limit_filament_maps = other.limit_filament_maps;
filament_printable_reuslt = other.filament_printable_reuslt;
filename = std::forward<Other>(other).filename;
id = std::forward<Other>(other).id;
moves = std::forward<Other>(other).moves;
lines_ends = std::forward<Other>(other).lines_ends;
printable_area = std::forward<Other>(other).printable_area;
bed_exclude_area = std::forward<Other>(other).bed_exclude_area;
wrapping_exclude_area = std::forward<Other>(other).wrapping_exclude_area;
toolpath_outside = std::forward<Other>(other).toolpath_outside;
label_object_enabled = std::forward<Other>(other).label_object_enabled;
long_retraction_when_cut = std::forward<Other>(other).long_retraction_when_cut;
timelapse_warning_code = std::forward<Other>(other).timelapse_warning_code;
printable_height = std::forward<Other>(other).printable_height;
settings_ids = std::forward<Other>(other).settings_ids;
filaments_count = std::forward<Other>(other).filaments_count;
extruder_colors = std::forward<Other>(other).extruder_colors;
filament_diameters = std::forward<Other>(other).filament_diameters;
filament_densities = std::forward<Other>(other).filament_densities;
filament_costs = std::forward<Other>(other).filament_costs;
print_statistics = std::forward<Other>(other).print_statistics;
custom_gcode_per_print_z = std::forward<Other>(other).custom_gcode_per_print_z;
spiral_vase_mode = std::forward<Other>(other).spiral_vase_mode;
warnings = std::forward<Other>(other).warnings;
bed_type = std::forward<Other>(other).bed_type;
gcode_check_result = std::forward<Other>(other).gcode_check_result;
limit_filament_maps = std::forward<Other>(other).limit_filament_maps;
filament_printable_reuslt = std::forward<Other>(other).filament_printable_reuslt;
// Orca: copy the shared grouping result so a copied result keeps it (shared_ptr =>
// memory-safe), rather than leaving a stale pointer on the target. No g-code effect either way.
nozzle_group_result = other.nozzle_group_result;
nozzle_group_result = std::forward<Other>(other).nozzle_group_result;
// Keep the per-extruder hotend types on a copied result (injector input).
extruder_types = other.extruder_types;
printer_extruder_variant = other.printer_extruder_variant;
printer_extruder_id = other.printer_extruder_id;
layer_filaments = other.layer_filaments;
filament_change_sequence = other.filament_change_sequence;
used_mixed_filaments = other.used_mixed_filaments;
nozzle_change_sequence = other.nozzle_change_sequence;
optimal_assignment = other.optimal_assignment;
filament_change_count_map = other.filament_change_count_map;
extruder_types = std::forward<Other>(other).extruder_types;
printer_extruder_variant = std::forward<Other>(other).printer_extruder_variant;
printer_extruder_id = std::forward<Other>(other).printer_extruder_id;
layer_filaments = std::forward<Other>(other).layer_filaments;
filament_change_sequence = std::forward<Other>(other).filament_change_sequence;
used_mixed_filaments = std::forward<Other>(other).used_mixed_filaments;
nozzle_change_sequence = std::forward<Other>(other).nozzle_change_sequence;
optimal_assignment = std::forward<Other>(other).optimal_assignment;
filament_change_count_map = std::forward<Other>(other).filament_change_count_map;
// Keep the SKIPPABLE per-type time on a copied result.
skippable_part_time = other.skippable_part_time;
initial_layer_time = other.initial_layer_time;
belt_tilt_angle = other.belt_tilt_angle;
belt_z_origin = other.belt_z_origin;
machine_frame_transform_active = other.machine_frame_transform_active;
preslice_remap_x = other.preslice_remap_x;
preslice_remap_y = other.preslice_remap_y;
preslice_remap_z = other.preslice_remap_z;
skippable_part_time = std::forward<Other>(other).skippable_part_time;
initial_layer_time = std::forward<Other>(other).initial_layer_time;
belt_tilt_angle = std::forward<Other>(other).belt_tilt_angle;
belt_z_origin = std::forward<Other>(other).belt_z_origin;
machine_frame_transform_active = std::forward<Other>(other).machine_frame_transform_active;
preslice_remap_x = std::forward<Other>(other).preslice_remap_x;
preslice_remap_y = std::forward<Other>(other).preslice_remap_y;
preslice_remap_z = std::forward<Other>(other).preslice_remap_z;
#if ENABLE_GCODE_VIEWER_STATISTICS
time = other.time;
time = std::forward<Other>(other).time;
#endif
return *this;
}
void lock() const { result_mutex.lock(); }
void unlock() const { result_mutex.unlock(); }
@@ -535,6 +552,10 @@ class Print;
Wipe_Tower_Start,
Wipe_Tower_End,
PA_Change,
Print_Time_Total_Sec_Placeholder,
Print_Time_Day_Placeholder,
Print_Time_Hour_Placeholder,
Print_Time_Minute_Placeholder,
Print_Time_Sec_Placeholder,
Used_Filament_Length_Placeholder,
};
@@ -544,7 +565,7 @@ class Print;
static bool contains_reserved_tag(const std::string& gcode, std::string& found_tag);
// checks the given gcode for reserved tags and returns true when finding any
// (the first max_count found tags are returned into found_tag)
static bool contains_reserved_tags(const std::string& gcode, unsigned int max_count, std::vector<std::string>& found_tag);
static bool contains_reserved_tags(const std::string& gcode, unsigned int max_count, std::vector<std::string>& found_tag, bool is_bbl_printer);
static int get_gcode_last_filament(const std::string &gcode_str);
static bool get_last_z_from_gcode(const std::string& gcode_str, double& z);
@@ -1229,6 +1250,9 @@ class Print;
EProducer m_producer;
TimeProcessor m_time_processor;
// calculate_time()'s map from each block's move id to its index after the actual speed moves are inserted,
// a member to reuse its capacity.
std::vector<std::pair<unsigned int, unsigned int>> m_actual_speed_id_map;
UsedFilaments m_used_filaments;
Print* m_print{ nullptr };
@@ -1574,5 +1598,3 @@ class Print;
} /* namespace Slic3r */
#endif /* slic3r_GCodeProcessor_hpp_ */