From 8f8bfd6a28fc19626c5789ac7d8ca5e808e72d9c Mon Sep 17 00:00:00 2001 From: Downtime Date: Mon, 19 Oct 2026 19:20:51 -0500 Subject: [PATCH] fix: align custom gcode placeholder metadata (#16272) Declare the runtime placeholders that filament, layer-change, timelapse, wrapping-detection, machine-end and change-filament G-code receive, so the Edit G-code dialog can list them and a build with ORCA_CHECK_GCODE_PLACEHOLDERS no longer rejects them. Adds the missing toolchange_z definition and wraps the new labels and tooltips in L() so they get translated. --- src/libslic3r/PrintConfig.cpp | 89 ++++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 48d92da201..56c3dc5af6 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -13493,12 +13493,30 @@ static std::map s_CustomGcodeSpecificP // Machine G-code {"file_start_gcode", {}}, {"machine_start_gcode", {}}, - {"machine_end_gcode", {"layer_num", "layer_z", "max_layer_z", "filament_extruder_id"}}, + {"machine_end_gcode", {"layer_num", "layer_z", "max_layer_z", "filament_extruder_id", + "current_filament_id", "current_extruder_id", "current_nozzle_id", + "nozzle_diameter_at_nozzle_id", "nozzle_volume_types"}}, {"before_layer_change_gcode", {"layer_num", "layer_z", "max_layer_z"}}, - {"layer_change_gcode", {"layer_num", "layer_z", "max_layer_z"}}, - {"timelapse_gcode", {"layer_num", "layer_z", "max_layer_z"}}, - {"change_filament_gcode", {"layer_num", "layer_z", "max_layer_z", "next_extruder", "previous_extruder", "fan_speed", + {"layer_change_gcode", {"layer_num", "layer_z", "max_layer_z", "most_used_physical_extruder_id", + "current_filament_id", "current_nozzle_id", "curr_y_acceleration_limit", + "curr_accumulated_mass", "curr_layer_mass"}}, + {"timelapse_gcode", {"layer_num", "layer_z", "max_layer_z", "most_used_physical_extruder_id", + "curr_physical_extruder_id", "timelapse_pos_x", "timelapse_pos_y", + "has_timelapse_safe_pos", "timelapse_inline_photo", + "farthest_point_timelapse_enabled", "clear_to_x0"}}, + {"wrapping_detection_gcode", {"layer_num", "layer_z", "max_layer_z", "most_used_physical_extruder_id", + "curr_physical_extruder_id"}}, + {"change_filament_gcode", {"layer_num", "layer_z", "max_layer_z", "next_extruder", "previous_extruder", + "current_hotend", "next_hotend", "current_nozzle_id", "next_nozzle_id", + "current_filament_id", "next_filament_id", "old_extruder_variant", "new_extruder_variant", + "nozzle_diameter_at_nozzle_id", "nozzle_volume_types", "filament_retract_length_nc", + "new_extruder_retracted_length", "outer_wall_volumetric_speed", "fan_speed", "first_flush_volume", "flush_length_1", "flush_length_2", "flush_length_3", "flush_length_4", + "flush_length", "flush_volumetric_speeds", "flush_temperatures", "filament_cooling_before_tower", + "wipe_avoid_perimeter", "wipe_avoid_pos_x", "is_prime_tower_interface", + "filament_tower_interface_purge_volume", "filament_tower_interface_print_temp", + "wipe_tower_center_pos_x", "wipe_tower_center_pos_y", "wipe_tower_center_pos_valid", + "temperature", "nozzle_temperature", "first_layer_temperature", "nozzle_temperature_initial_layer", "new_filament_e_feedrate", "new_filament_temp", "new_retract_length", "new_retract_length_toolchange", "old_filament_e_feedrate", "old_filament_temp", "old_retract_length", "old_retract_length_toolchange", "relative_e_axis", "second_flush_volume", "toolchange_count", "toolchange_z", @@ -13511,8 +13529,18 @@ static std::map s_CustomGcodeSpecificP {"machine_pause_gcode", {}}, {"template_custom_gcode", {}}, // Filament G-code - {"filament_start_gcode", {"filament_extruder_id"}}, - {"filament_end_gcode", {"layer_num", "layer_z", "max_layer_z", "filament_extruder_id"}}, + {"filament_start_gcode", {"layer_num", "layer_z", "max_layer_z", "filament_extruder_id", + "current_filament_id", "current_extruder_id", "current_nozzle_id", + "nozzle_diameter_at_nozzle_id", "nozzle_volume_types", + "retraction_distance_when_cut", "long_retraction_when_cut", + "temperature", "nozzle_temperature", "first_layer_temperature", + "nozzle_temperature_initial_layer"}}, + {"filament_end_gcode", {"layer_num", "layer_z", "max_layer_z", "filament_extruder_id", + "current_filament_id", "current_extruder_id", "current_nozzle_id", + "nozzle_diameter_at_nozzle_id", "nozzle_volume_types", + "retraction_distance_when_cut", "long_retraction_when_cut", + "temperature", "nozzle_temperature", "first_layer_temperature", + "nozzle_temperature_initial_layer"}}, }; const std::map& custom_gcode_specific_placeholders() @@ -13541,11 +13569,44 @@ CustomGcodeSpecificConfigDef::CustomGcodeSpecificConfigDef() def->label = L("Filament extruder ID"); def->tooltip = L("The current extruder ID. The same as current_extruder."); + new_def("current_filament_id", coInt, L("Current filament ID"), L("Index of the currently active filament. The index is zero-based (first filament has index 0).")); + new_def("current_extruder_id", coInt, L("Current extruder ID"), L("Index of the currently active physical extruder. The index is zero-based (first extruder has index 0).")); + new_def("current_nozzle_id", coInt, L("Current nozzle ID"), L("Index of the currently active nozzle. The index is zero-based (first nozzle has index 0).")); + new_def("nozzle_diameter_at_nozzle_id", coFloats, L("Nozzle diameters"), L("Nozzle diameters indexed by nozzle ID.")); + new_def("nozzle_volume_types", coStrings, L("Nozzle volume types"), L("Nozzle volume variants indexed by nozzle ID.")); + new_def("retraction_distance_when_cut", coFloat, L("Retraction distance when cut"), L("Retraction distance used when cutting filament.")); + new_def("long_retraction_when_cut", coBool, L("Long retraction when cut"), L("Whether long retraction is used when cutting filament.")); + +// layer_change_gcode + new_def("most_used_physical_extruder_id", coInt, L("Most-used physical extruder ID"), L("Index of the physical extruder used most often on the current layer. The index is zero-based (first extruder has index 0).")); + new_def("curr_y_acceleration_limit", coFloat, L("Current Y acceleration limit"), L("Current Y-axis acceleration limit after the bed-mass adjustment.")); + new_def("curr_accumulated_mass", coFloat, L("Current accumulated mass"), L("Accumulated printed mass at the current layer.")); + new_def("curr_layer_mass", coFloat, L("Current layer mass"), L("Printed mass of the previous layer.")); + +// timelapse_gcode + new_def("curr_physical_extruder_id", coInt, L("Current physical extruder ID"), L("Index of the physical extruder active for the current layer. The index is zero-based (first extruder has index 0).")); + new_def("timelapse_pos_x", coInt, L("Timelapse position X"), L("Selected X position for timelapse capture.")); + new_def("timelapse_pos_y", coInt, L("Timelapse position Y"), L("Selected Y position for timelapse capture.")); + new_def("has_timelapse_safe_pos", coBool, L("Has timelapse safe position"), L("Whether a safe timelapse position was found.")); + new_def("timelapse_inline_photo", coBool, L("Timelapse inline photo"), L("Whether the timelapse photo is captured at the inline position.")); + new_def("farthest_point_timelapse_enabled", coBool, L("Farthest-point timelapse enabled"), L("Whether farthest-point timelapse positioning is active.")); + new_def("clear_to_x0", coBool, L("Clear to X0"), L("Whether the timelapse move is clear to X0.")); + // change_filament_gcode new_def("previous_extruder", coInt, L("Previous extruder"), L("Index of the extruder that is being unloaded. The index is zero based (first extruder has index 0).")); new_def("next_extruder", coInt, L("Next extruder"), L("Index of the extruder that is being loaded. The index is zero based (first extruder has index 0).")); + new_def("current_hotend", coInt, L("Current hotend"), L("Zero-based extruder index of the outgoing filament. On Bambu printers it is -1, or the nozzle ID when a filament moves between nozzles across layers.")); + new_def("next_hotend", coInt, L("Next hotend"), L("Zero-based extruder index of the incoming filament. On Bambu printers it is -1, or the nozzle ID when a filament moves between nozzles across layers.")); + new_def("next_nozzle_id", coInt, L("Next nozzle ID"), L("Index of the nozzle associated with the incoming filament. The index is zero-based (first nozzle has index 0).")); + new_def("next_filament_id", coInt, L("Next filament ID"), L("Index of the incoming filament. The index is zero-based (first filament has index 0).")); + new_def("old_extruder_variant", coString, L("Old extruder variant"), L("Nozzle-volume variant of the outgoing extruder.")); + new_def("new_extruder_variant", coString, L("New extruder variant"), L("Nozzle-volume variant of the incoming extruder.")); + new_def("filament_retract_length_nc", coFloat, L("Filament nozzle-change retract length"), L("Nozzle-change retraction length of the outgoing filament.")); + new_def("new_extruder_retracted_length", coFloat, L("New extruder retracted length"), L("Currently parked retraction length of the incoming extruder.")); + new_def("outer_wall_volumetric_speed", coFloat, L("Outer wall volumetric speed"), L("Volumetric speed used for the outer wall.")); new_def("relative_e_axis", coBool, L("Relative e-axis"), L("Indicates if relative positioning is being used.")); new_def("toolchange_count", coInt, L("Toolchange count"), L("The number of toolchanges throughout the print.")); + new_def("toolchange_z", coFloat, L("Toolchange Z"), L("The Z position during the toolchange.")); new_def("fan_speed", coNone, "", ""); //Option is no longer used and is zeroed by placeholder parser for compatability new_def("old_retract_length", coFloat, L("Old retract length"), L("The retraction length of the previous filament.")); new_def("new_retract_length", coFloat, L("New retract length"), L("The retraction length of the new filament.")); @@ -13570,6 +13631,22 @@ CustomGcodeSpecificConfigDef::CustomGcodeSpecificConfigDef() new_def("flush_length_2", coFloat, L("Flush Length 2"), L("The second flush length.")); new_def("flush_length_3", coFloat, L("Flush Length 3"), L("The third flush length.")); new_def("flush_length_4", coFloat, L("Flush Length 4"), L("The fourth flush length.")); + new_def("flush_length", coFloat, L("Flush length"), L("Total flush length.")); + new_def("flush_volumetric_speeds", coFloats, L("Flush volumetric speeds"), L("Flush volumetric speeds for each filament.")); + new_def("flush_temperatures", coInts, L("Flush temperatures"), L("Flush temperatures for each filament.")); + new_def("filament_cooling_before_tower", coFloats, L("Filament cooling before tower"), L("Temperature drop before entering filament tower")); + new_def("wipe_avoid_perimeter", coBool, L("Avoid wipe perimeter"), L("Whether travel should avoid the wipe perimeter.")); + new_def("wipe_avoid_pos_x", coFloat, L("Wipe avoidance X"), L("X position used to avoid the wipe area.")); + new_def("is_prime_tower_interface", coBool, L("Prime tower interface"), L("Whether the current purge is for a prime-tower interface.")); + new_def("filament_tower_interface_purge_volume", coFloat, L("Interface layer purge length"), L("Purge length for prime tower interface layer (where different materials meet).")); + new_def("filament_tower_interface_print_temp", coInt, L("Filament tower interface print temperature"), L("Print temperature used for the filament tower interface.")); + new_def("wipe_tower_center_pos_x", coFloat, L("Wipe tower center X"), L("X coordinate of the nozzle's wipe-tower wait position, 2 mm outside the tower edge.")); + new_def("wipe_tower_center_pos_y", coFloat, L("Wipe tower center Y"), L("Y coordinate of the nozzle's wipe-tower wait position.")); + new_def("wipe_tower_center_pos_valid", coBool, L("Wipe tower center position valid"), L("Whether the print has a wipe tower.")); + new_def("temperature", coInts, L("Temperature"), L("Nozzle temperatures indexed by filament.")); + new_def("nozzle_temperature", coInts, L("Nozzle temperature"), L("Nozzle temperatures indexed by filament.")); + new_def("first_layer_temperature", coInts, L("First layer temperature"), L("First-layer nozzle temperatures indexed by filament.")); + new_def("nozzle_temperature_initial_layer", coInts, L("Nozzle temperature initial layer"), L("First-layer nozzle temperatures indexed by filament.")); // change_extrusion_role_gcode // The whole tooltip is one literal so that the GUI can look it up in the catalog.