feat: Add File header G-code option and print_time_sec/filament_length_m placeholders (#12186)

## Problem

Some Creality printers (e.g. Ender-3 V3 SE) rely on metadata comments in the first lines of G-code files to display print info on the screen (estimated time, filament usage, layer height). This follows a format originally used by Cura/Creality Print:
```
;FLAVOR:Marlin
;TIME:3708.97
;Filament used:6.21m
;Layer height:0.2
```

OrcaSlicer currently has no way to write content before the `HEADER_BLOCK` in the G-code output, and does not expose `print_time_sec` or `filament_length_m` as usable placeholders. As a result, these printers show zeroed-out print info on screen.

## Changes

### 1. New placeholders (post-processing)
Added two new G-code placeholders resolved during post-processing:
- `{print_time_sec}` — total estimated print time in seconds (double)
- `{filament_length_m}` — total filament length in meters (double)

These values are only available after G-code generation, so they use inline marker replacement (`@PRINT_TIME_SEC@`, `@FILAMENT_LENGTH_M@`) that `GCodeProcessor::run_post_process()` substitutes with actual computed values — the same pattern used by existing M73 and layer count placeholders.

### 2. New "File header G-code" option (`machine_top_gcode`)
Added a new G-code field in **Printer Settings > Machine G-code** that writes content at the very top of the output file, before `HEADER_BLOCK_START`. This allows users to add firmware-specific metadata that must appear in the first lines.

### 3. Creality Ender-3 V3 SE profile update
Pre-configured the Ender-3 V3 SE profiles (all 4 nozzle variants) with a default `machine_top_gcode` value matching the Cura-compatible header format, so print info displays correctly out of the box.

# Screenshots

| Before (current OrcaSlicer) | After (this PR) |
|---|---|
| ![IMG_5285](https://github.com/user-attachments/assets/fdd2cc96-6593-4108-83f4-e272d5547467) | ![IMG_5286](https://github.com/user-attachments/assets/6cb4091a-4560-4596-93d9-49f2ff8f0a2b) |

## Tests

- Sliced test model with Ender-3 V3 SE profile
- Verified G-code output contains correct values in first lines:
  - `;TIME:` with actual print time in seconds
  - `;Filament used:` with filament length in meters
  - `;Layer height:` with correct layer height
- Verified `{print_time_sec}` and `{filament_length_m}` work in both Machine Start G-code and File header G-code fields
- Verified empty `machine_top_gcode` produces no extra output
- Built and tested on macOS (arm64)
This commit is contained in:
davyd
2026-02-08 12:56:28 -03:00
committed by GitHub
parent 1663dab6ff
commit 2f2f0df6af
11 changed files with 99 additions and 3 deletions

View File

@@ -5398,6 +5398,18 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionInt(1));
def = this->add("file_start_gcode", coString);
def->label = L("File header G-code");
def->tooltip = L("G-code written at the very top of the output file, before any other content. "
"Useful for adding metadata that printer firmware reads from the first lines of the file "
"(e.g. estimated print time, filament usage). "
"Supports placeholders like {print_time_sec} and {used_filament_length}.");
def->multiline = true;
def->full_width = true;
def->height = 8;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionString(""));
def = this->add("machine_start_gcode", coString);
def->label = L("Start G-code");
def->tooltip = L("Start G-code when starting the entire print.");
@@ -10299,6 +10311,14 @@ PrintStatisticsConfigDef::PrintStatisticsConfigDef()
def = this->add("used_filament", coFloat);
def->label = L("Used filament");
def->tooltip = L("Total length of filament used in the print.");
def = this->add("print_time_sec", coString);
def->label = L("Print time (seconds)");
def->tooltip = L("Total estimated print time in seconds. Replaced with actual value during post-processing.");
def = this->add("used_filament_length", coString);
def->label = L("Filament length (meters)");
def->tooltip = L("Total filament length used in meters. Replaced with actual value during post-processing.");
}
ObjectsInfoConfigDef::ObjectsInfoConfigDef()
@@ -10433,6 +10453,7 @@ OtherPresetsConfigDef::OtherPresetsConfigDef()
static std::map<t_custom_gcode_key, t_config_option_keys> s_CustomGcodeSpecificPlaceholders{
// Machine G-code
{"file_start_gcode", {}},
{"machine_start_gcode", {}},
{"machine_end_gcode", {"layer_num", "layer_z", "max_layer_z", "filament_extruder_id"}},
{"before_layer_change_gcode", {"layer_num", "layer_z", "max_layer_z"}},