Commit Graph

368 Commits

Author SHA1 Message Date
Rodrigo Faselli
bc4b977a81 Merge branch 'main' into feature/cache_profiles_and_optimize_loading_speed 2026-07-23 17:20:32 -03:00
SoftFever
7db0a59cc1 fix: H2C carousel - port BBS NozzleStatusRecorder for per-slot purge tracking (#14800)
## Problem

On H2C (carousel) printers, the wipe tower purge volume calculation in
`_make_wipe_tower()` tracks filament state **per-extruder** (2 slots).
Since H2C has up to 7 carousel nozzle slots on a single extruder, all
filaments sharing that extruder are collapsed into one tracking slot.
This causes:

Test:

[5cubes.3mf.zip](https://github.com/user-attachments/files/30092551/5cubes.3mf.zip)

- **Massive redundant AMS flushing** every filament change on the
carousel triggers a full purge against the "previous" filament, even
when the target nozzle slot already has the correct filament loaded
- **60.9g total weight** instead of ~17g (**3.5× material waste**)
- **3h09m print time** instead of ~1h57m (**60% longer**)

## Root Cause

The code uses `nozzle_cur_filament_ids[extruder_id]` (a 2-element array)
to track which filament was last used for each extruder. BambuStudio
uses `NozzleStatusRecorder`, which tracks per `group_id` (physical
carousel slot 0..6).

## Changes

| File | Change |
|---|---|
| `Print.cpp` | Replace `nozzle_cur_filament_ids` with
`NozzleStatusRecorder`. Use `get_nozzle_for_filament()` to resolve the
physical carousel slot per layer. Select `filament_prime_volume_nc` for
nozzle changes, `filament_prime_volume` for filament changes. |
| `PrintConfig.hpp` | Add `ConfigOptionFloats filament_prime_volume`
(per-filament EC prime volume, missing from upstream but present in BBS
and H2C profiles) |
| `PrintConfig.cpp` | Register `filament_prime_volume` with default
45mm³ (matching BBS) |
| `Preset.cpp` | Add `filament_prime_volume` to preset keys |

Also includes `tests/compare_analyzer/` - two standalone Python tools
for G-code slice comparison and temperature timeline analysis (stdlib
only, no dependencies).

## Test Results (5-color H2C Hybrid print, same 3mf project)

| Metric | Upstream (broken) | **Fixed** | BBS (reference) |
|---|---|---|---|
| **Total weight** | 60.90g | **16.20g**  | 17.47g |
| **Print time** | 3h09m | **1h57m**  | 1h51m |
| **Filament changes** | 105 | 105 | 140 |
| **Tool changes** | 35 | 35 | 35 |
| **Critical discrepancies vs BBS** | ⚠️ YES |  None | — |


## Analysis Tools (`tests/compare_analyzer/`)

Two standalone Python tools (stdlib only, no dependencies) for deep
G-code comparison:

- **`compare_slices.py`** - comprehensive .3mf slice comparison:
filament usage, nozzle mapping, tool change sequences, prime tower
analysis, temperature timeline, retract parameters, and automatic
critical discrepancy detection (weight/time anomalies)
- **`show_temp_plot.py`** - interactive HTML temperature timeline
plotter for visualising heater profiles during multi-nozzle prints
(supports single-file and side-by-side comparison)

Usage:
```bash
python3 tests/compare_analyzer/compare_slices.py file1.3mf file2.3mf --labels "Upstream" "Fixed"
python3 tests/compare_analyzer/show_temp_plot.py file1.3mf file2.3mf
```


## Screenshots

### OrcaSlicer Upstream (unfixed) - 60.90g, 3h09m
<img width="1512" height="982" alt="Screenshot 2026-07-16 at 15 22 58"
src="https://github.com/user-attachments/assets/3efb2bff-ff1e-43db-9669-feafa5921b51"
/>


### OrcaSlicer Fixed - 16.20g, 1h57m
<img width="1512" height="982" alt="Screenshot 2026-07-16 at 15 23 08"
src="https://github.com/user-attachments/assets/c1d36dc5-9b01-4691-80ef-7364540e1f4e"
/>

### BambuStudio Reference - 17.47g, 1h51m
<img width="1512" height="982" alt="Screenshot 2026-07-16 at 15 24 52"
src="https://github.com/user-attachments/assets/5c0b11e2-64f4-40e9-8c7c-3f42519786c3"
/>

### Temperature Timeline: Upstream vs Fixed
<img width="1511" height="829" alt="Screenshot 2026-07-16 at 15 23 35"
src="https://github.com/user-attachments/assets/926c2cb5-dfd4-4ce0-bb40-82e6165eb134"
/>


### Temperature Timeline: Fixed vs BBS

<img width="1512" height="825" alt="Screenshot 2026-07-16 at 15 23 51"
src="https://github.com/user-attachments/assets/85c72dda-e779-4aa6-8118-fb17e5f8482d"
/>


## Compatibility

Safe for non-carousel printers: when each extruder has a single nozzle,
`group_id == extruder_id`, so `NozzleStatusRecorder` behaves identically
to the original per-extruder tracking. The `filament_prime_volume`
default (45mm³) matches the existing global `prime_volume` default.

## Reference
BambuStudio `Print.cpp` `_make_wipe_tower()` L3341-3392 -
`NozzleStatusRecorder` pattern.
2026-07-22 12:59:17 +08:00
Ian Chua
8de1ff37bd fix: deep_diff typo 2026-07-21 14:52:02 +08:00
Ian Chua
8b93cc5df3 prune stale plugin capability overrides (#14862)
* prune stale plugin capability overrides

* fix: configure button still shows (n) modified configs after removing

* fix: add slicing_pipeline_plugin to deep_diff
2026-07-21 12:55:44 +08:00
SoftFever
65ab9b61a8 Merge branch 'main' into feature/h2c_support_clean_fixes 2026-07-20 00:02:43 +08:00
SoftFever
a152c7bcad Name the plugin capability config option consistently
The preset option was plugin_preference_overrides while the GUI field type
that renders it was GUIType::plugin_config, for one and the same thing.
Settle on "config": the store, the dialog and the Python hooks all say config
already, so renaming that way touches 4 files instead of the whole plugin
subsystem and the public plugin API.

Keep the _overrides suffix — the option is the preset's override layer over
the base PluginConfig store, a distinction EffectiveCapabilityConfig tracks.

Also wrap the printer tab's group heading in L(); it was the only one of the
three missing it, and was therefore untranslatable.
2026-07-17 18:34:15 +08:00
Ian Chua
4c60781cf4 fix: merge branch feat/plugin-feature 2026-07-17 14:02:10 +08:00
SoftFever
b663f851fe Merge branch 'main' into feat/plugin-feature 2026-07-17 11:30:34 +08:00
denis svinarchuk
407c78fb30 fix: port BBS NozzleStatusRecorder pattern for per-carousel-slot purge tracking
The upstream _make_wipe_tower() tracked purge volumes per-extruder (2 slots),
which collapsed all H2C carousel filaments into one slot and caused massive
redundant AMS flushing (~40g instead of ~0.4g).

Changes:
- Print.cpp: Replace per-extruder nozzle_cur_filament_ids with BBS
  NozzleStatusRecorder that tracks per group_id (carousel slot 0..6).
  Use get_nozzle_for_filament() to resolve physical slot per layer.
  Select filament_prime_volume_nc for nozzle changes, filament_prime_volume
  for filament changes (BBS pattern).
- PrintConfig.hpp/cpp: Register filament_prime_volume (per-filament EC prime
  volume, default 45mm³) matching BBS PrintConfig.
- Preset.cpp: Add filament_prime_volume to preset keys list.

Safe for non-carousel printers: group_id == extruder_id when each extruder
has one nozzle, so NozzleStatusRecorder behaves identically to the original
per-extruder tracking.

Reference to BBS: BambuStudio/src/libslic3r/Print.cpp _make_wipe_tower() L3341-3392
2026-07-16 14:54:46 +01:00
Mqrius
6d1974a662 Restore flow calibration special order, overridable via fill order (#14786) 2026-07-16 09:10:15 -03:00
Ian Chua
cd8c42b125 fix merge conflicts 2026-07-15 21:04:42 +08:00
SoftFever
0849c44ae0 Merge branch 'main' into dev/ams-heat 2026-07-15 19:45:27 +08:00
SoftFever
8cb0cb7693 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).
2026-07-15 17:18:46 +08:00
Mqrius
c84d5c7943 Add top/bottom surface fill order control (Outward/Inward) for Concentric, Archimedean Chords and Octagram Spiral (#14179)
Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
2026-07-14 15:34:13 -03:00
Valerii Bokhan
50768e0716 Feature: Retract amount after wipe (#11015)
Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
2026-07-14 14:42:16 -03:00
Noisyfox
246f2d32bf Merge branch 'main' into dev/ams-heat
# Conflicts:
#	src/libslic3r/Preset.cpp
#	src/libslic3r/PrintConfig.hpp
#	src/slic3r/GUI/DeviceCore/CMakeLists.txt
#	src/slic3r/GUI/DeviceCore/DevDefs.h
#	src/slic3r/GUI/DeviceCore/DevFilaSystem.cpp
#	src/slic3r/GUI/DeviceCore/DevFilaSystem.h
#	src/slic3r/GUI/DeviceCore/DevUtilBackend.cpp
#	src/slic3r/GUI/DeviceCore/DevUtilBackend.h
#	src/slic3r/GUI/DeviceManager.cpp
#	src/slic3r/GUI/DeviceManager.hpp
#	src/slic3r/GUI/SelectMachine.cpp
#	src/slic3r/GUI/SelectMachine.hpp
2026-07-14 10:10:19 +08:00
SoftFever
74813b401f Merge remote-tracking branch 'origin/main' into feature/h2c_support_clean
# Conflicts:
#	localization/i18n/fr/OrcaSlicer_fr.po
#	localization/i18n/list.txt
2026-07-14 02:54:20 +08:00
Ian Chua
5b3e1b921c feat: sidebar plugin config UI 2026-07-13 20:39:41 +08:00
Noisyfox
49282858a4 Merge branch 'main' into dev/ams-heat 2026-07-13 14:43:45 +08:00
Noisyfox
6a254c35d4 Make printer profile swithing faster (#14437)
* Fix issue that switching printer profile is slow.
`wxGetApp().get_tab(preset_type)->select_preset(preset_name);` is called twice when switching printer profiles. Only one needed.

* Avoid unnecessary type conversion & function call during printer profile switching:
- Don't call `config->opt_string("printer_model")` repeatedly
- Use ref when possible during iterating
- Avoid unnecessary `wxString` to `std::string` conversion
2026-07-13 09:52:18 +08:00
SoftFever
19352215da feat(plugin)!: merge G-code post-processing into the slicing pipeline as psGCodePostProcess
G-code post-processing is now a step of the slicing-pipeline plugin rather than a
separate capability type. One capability class can transform slices at the geometry
seams AND edit the final G-code, behind a single picker/option.

- Add SlicingPipelineStepPlugin::psGCodePostProcess (bound as
  orca.slicing.Step.psGCodePostProcess). Unlike the geometry steps it fires from the
  GUI export path in PostProcessor.cpp, not from Print::process(): ctx.print/ctx.object
  are None and the plugin edits the file at ctx.gcode_path in place. It may run more
  than once per slice (file export and/or upload) and its output is not shown in the
  preview.
- Extend SlicingPipelineContext with gcode_path/host/output_name and a C++-only
  full_config; config_value() falls back to it when there is no live Print.
- PostProcessor.cpp dispatches SlicingPipelinePluginCapability at psGCodePostProcess,
  driven by the existing slicing_pipeline_plugin option.
- The exported G-code lives outside data_dir(), so the plugin audit sandbox would
  block the write; the trampoline's audit setup grants ctx.gcode_path's folder as a
  scoped allowed root, gated on a non-empty gcode_path so the geometry-step hooks gain
  no extra filesystem access.

BREAKING CHANGE: the separate G-code post-processing capability type is removed.
- orca.gcode.GCodePluginCapabilityBase and orca.PluginType.PostProcessing are gone;
  post-processing plugins migrate to orca.slicing.SlicingPipelineCapabilityBase +
  Step.psGCodePostProcess (and gain ctx.params / ctx.config_value()).
- The post_process_plugin config option is removed; use slicing_pipeline_plugin.
  Presets carrying the old key degrade to the standard unknown-key warning.
- Manifest type = "post-processing" now maps to Unknown (advisory only; the loader
  dispatches on the C++ get_type()).

Also repairs two latent build breaks the branch carried: stale Step enum value usages
in test_slicing_pipeline_hook.cpp and a reference to the removed
ConfigOptionDef::PluginType::None in Tab::on_value_change (now is_plugin_backed()).
Adds the orca_gcode_stamp sample plugin and a psGCodePostProcess binding test.
2026-07-10 19:57:35 +08:00
SoftFever
826e36fb1e feat(printer): add cooling filter support flag and expose its toggle
cooling_filter_enabled existed as a config option but was shown nowhere,
and there was no capability flag to gate it. The cooling filter and air
filtration are alternative accessories sharing the same duct, so a
printer declares one or the other.

- new hidden printer capability flag support_cooling_filter
- "Use cooling filter" toggle in the Accessory group, shown only when
  the printer supports it; the air-filtration toggle hides in that case
  (no vendor restriction: third-party printers keep air filtration)
- explicit defaults (0) in the common machine base
- H2C declares support_cooling_filter=1 instead of support_air_filtration;
  its start-gcode already carries the cooling-filter conditional, so the
  toggle is functional. On H2C this drops the two exhaust-fan lines that
  air filtration emitted for ABS-class filaments, matching the printer's
  actual duct accessory; H2C is new on this branch so no existing user
  output changes.

Printers without the flag keep exactly the previous accessory UI and
g-code.
2026-07-10 16:38:46 +08:00
SoftFever
b12aad6a8c feat(orient): auto-orient the largest overhang toward the cooling fan
New printer option fan_direction (undefine/left/right/both, default
undefine) declares which side the auxiliary part-cooling airflow comes
from. When set and the printer has an auxiliary fan, auto-orient adds a
yaw rotation so the dominant overhang area faces the airflow, and newly
added primitive shapes are pre-oriented the same way (except the Cube,
whose axis-aligned bounding box the pressure-advance pattern calibration
depends on).

- FanDirection enum + fan_direction printer option (Accessory group,
  enabled only with auxiliary_fan)
- orient engine: weighted overhang areas per candidate, yaw-direction
  search, vertical rotation applied on top of the primary orientation;
  the cooling weights are taken from the candidate actually chosen,
  including the flat-bottom tie-break
- orient_for_cooling() for primitive placement
- set fan_direction=left on H2C/H2D/H2D Pro/X1/X1E/P1S 0.4 profiles
  (X1C/H2S/P2S/X2D/Qidi X-Max 4 already carried the key, which now
  takes effect)

With fan_direction unset or no auxiliary fan the vertical rotation stays
identity and auto-orient results are unchanged; slicing and g-code are
never affected.
2026-07-10 16:21:48 +08:00
SoftFever
00816968a2 Merge branch 'main' into feature/h2c_support_clean 2026-07-09 22:17:20 +08:00
ExPikaPaka
d102ed1df4 Merge branch 'main' into feature/cache_profiles_and_optimize_loading_speed 2026-07-09 08:39:08 +02:00
π²
bc6ffcfb31 Anisotropic surfaces + Separated Infills (remake) (#11682)
Co-authored-by: Rodrigo Faselli <162915171+RF47@users.noreply.github.com>
Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
2026-07-08 15:40:19 -03:00
Ian Bassi
20a66fa99b Top Surface Expansion (#14296)
Co-authored-by: Rodrigo Faselli <162915171+RF47@users.noreply.github.com>
2026-07-08 14:20:40 -03:00
Ian Bassi
da149ee75a Add toolchange ordering option (Standard/Cyclic). (#13582) 2026-07-08 14:18:41 -03:00
SoftFever
237ef41b06 feat(libslic3r): multi-nozzle slicing engine for H2C/A2L
Port BambuStudio's dual-nozzle slicing core: H2C-era config keys, filament-to-nozzle grouping with per-layer dynamic regrouping, filament/nozzle/hotend gcode placeholder vocabulary, multi-nozzle wipe tower pre-heat/pre-cool, the two-pass pre-cooling injector, and corexy farthest-point timelapse.
2026-07-09 01:16:25 +08:00
SoftFever
f81a24abfb feat(plugin): expose the slicing print-graph as raw orca.host classes + Twistify sample
Adds PluginHostSlicing, which registers the print-graph data model (Print,
PrintObject, Layer, LayerRegion, Surface, ExPolygon, extrusions, ...) into the
orca.host submodule in the same raw-class style as PluginHostApi's Model/Preset
graph, with shared helpers in PluginBindingUtils. SlicingPipelinePluginCapability
is trimmed to the capability surface (the standalone SlicingNumpy helper is folded
away). Adds the Twistify example plugin next to Inset and broadens the binding,
hook, and plugin-install tests.
2026-07-08 00:05:28 +08:00
Noisyfox
7f67946dbf Fix incorrect length modification when loading device-related parameters
(cherry picked from commit bambulab/BambuStudio@ebf57372da)

Co-Authored-By: weizhen.xie <weizhen.xie@bambulab.com>
2026-07-07 22:02:10 +08:00
weizhen.xie
ae5d9c26fb ENH: Add filament ams/chamber parameters
Jira: None
Change-Id: I4c0a2d5b7e1c503fc9af9eb656fc6325e99af1de
(cherry picked from commit ce88e7794cb8786fae85603617757628a963e807)
2026-07-07 21:01:42 +08:00
Noisyfox
f713c7ae49 Make sure codes uses same structure/naming/position as BambuStudio
for easier code comparasion & porting in the future
2026-07-07 17:07:40 +08:00
ExPikaPaka
34fae25ed4 2026-07-06 12:24:47 +02:00
Florian
2d4f7a7437 added option to limit polyhole edges (#12349)
Co-authored-by: Rodrigo Faselli <162915171+RF47@users.noreply.github.com>
2026-07-04 23:03:36 -03:00
ExPikaPaka
b3a0c8bd40 Preserve disabled filament overrides (nil) through cloud sync (#14550) 2026-07-04 10:42:48 +08:00
Valerii Bokhan
1882861a98 Feature: Small perimeters speed for supports (#13459) 2026-07-03 17:27:57 -03:00
Ian Bassi
a6dd002fe7 Top and Bottom layer directions (#13631)
* Top layer direction

* Bottom layer direction

* comSimple
2026-07-03 17:27:05 -03:00
Ian Chua
ecddf3d18f feat: Python Plugins 2026-07-02 17:49:36 +08:00
SoftFever
b90439adba Merge branch 'main' into feature/cache_profiles_and_optimize_loading_speed 2026-07-01 16:21:11 +08:00
Ioannis Giannakas
3c8c667dbd Add "First layer fan speed" option (per filament) (#14270)
Implement First layer fan speed
2026-06-30 10:48:58 +01:00
Rodrigo Faselli
c9afb98ca2 Merge branch 'main' into feature/cache_profiles_and_optimize_loading_speed 2026-06-28 21:27:14 -03:00
Ian Chua
a0846ec215 fix: update .info base_id if it is mismatched or empty (#14430)
* fix: update .info base_id if it is mismatched or empty

* Merge branch 'main' into fix/update-base-id-on-mismatch-or-missing

* early return
2026-06-27 23:07:44 +08:00
Ian Chua
0e8288de36 fix: old preset names should resolved renamed_from field (#14429)
* fix: old preset names should resolved renamed_from field

* chore: remove misleading comments

* Merge branch 'main' into fix/consider_renamed_from

* normalize_inherits

* improve find_preset2 performace
2026-06-27 22:15:43 +08:00
Ioannis Giannakas
0e4928f200 Introduce minimal chamber temperature field (gcode chamber_min_temperature (#14340)
Introduce minimal chamber temperature field (gcode chamber_min_temperature)
2026-06-27 13:27:01 +01:00
SoftFever
8cb2e4e01e profiles: deterministic setting_id from vendor/type/name (#14432)
* profiles: enforce globally-unique, per-vendor-namespaced setting_id

Many non-Bambu vendors copied Bambu's generic setting_ids (GFSA04 alone
appeared in 1557 files), so setting_id was not globally unique. This
namespaces every vendor's ids and reserves Bambu/OrcaFilamentLibrary space.

- Reserve "G*" (Bambu) and "O*" (OrcaFilamentLibrary) id spaces.
- Assign each other vendor a 2-char prefix (first+last letter, collision
  resolved) and renumber every instantiated preset to <PREFIX><NNNN>.
- Strip setting_id from base profiles (instantiation:false) per Bambu's
  convention; assign one to instantiated presets that lacked it.
- Remove the pre-existing misspelled "settings_id" key (91 files).
- filament_id is left untouched (it is a per-material id).
- Add one-time migration script scripts/assign_vendor_setting_ids.py with a
  persisted registry resources/profiles/vendor_prefixes.json. Re-runs freeze
  existing ids; only new vendors/profiles get new ids.
- Bump version in each changed vendor index file.
- Extend scripts/orca_extra_profile_check.py with a CI guard: global
  uniqueness, in-namespace, no base setting_id, no gaps, no settings_id typo.

7425 profile files changed across 61 vendors; 0 cross-vendor collisions;
validator clean; migration idempotent. BBL and OrcaFilamentLibrary id spaces
untouched.

* profiles: add setting_id authoring guide for new vendors / profiles

* profiles: drop in-repo README; setting_id guide now lives in the wiki

* profiles: derive setting_id deterministically from vendor/type/name

* bump profile version
2026-06-27 20:11:25 +08:00
Rodrigo Faselli
d102157138 Merge branch 'main' into feature/cache_profiles_and_optimize_loading_speed 2026-06-26 07:47:50 -03:00
ExPikaPaka
517fa29d6f Add cereal serialize() to VendorProfile, PrinterModel, Preset, and Semver 2026-06-18 08:34:27 +02:00
SoftFever
9eeb73b68b feat: Support 3MF as g-code (use_3mf option) (#14238)
* feat: add support for 3MF file format in printer configurations and export options

* fix file extension

* enable 3mf for X Max 4

* disable use_3mf for X Plus 4

* Fixed an issue where `label_object_enabled` was not properly propagated to 3mf

* enable exclude object for Max 4

* remove hardcoded use 3mf for flashforge, move them to the new printer profiles config
2026-06-17 15:39:40 +08:00
SoftFever
7a8f5a88c9 Merge branch 'main' into feature/cache_profiles_and_optimize_loading_speed 2026-06-16 16:27:46 +08:00