# Description
Plugin discovery now distinguishes an unavailable or invalid
.install_state.json from a valid sidecar. During transient filesystem
replacement, the existing enabled state is preserved instead of being
reset, preventing plugins from unexpectedly losing their auto-load
behavior during rescans.
Thanks @WeLizard for pointing this out.
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
# Description
Fixes some bugs reported by users and the community
# Fix 1: Latest Version
If the user updates the plugin version on OrcaCloud without a changelog,
the latest version shown on OrcaSlicer won't be accurate.
## Issue
OrcaSlicer uses the changelog returned by OrcaCloud backend as the
source of truth, even though we query a latest version from the backend
as well. The changelog only consists of version entries that have
changelogs so if the latest one, e.g. 1.2.0 has no changelog, but 1.1.0
has, the latest version will be interpreted as 1.1.0.
## Fix
Don't use the changelog for version tracking, just use it for the
plugins dialog changelog tab.
# Fix 2: Host theme script / window.orca bridge leaks into cross-origin
child iframes
If a plugin's embedded app renders its own `<iframe>` (its real
catalog/dashboard UI, or a third-party auth/payment widget), that child
document also gets, uninvited: the host theme `<style>` block fighting
whatever CSS the child page already defines.
## Issue
OrcaSlicer injects host themed scripts and window.orca bridge into every
page, potentially breaking any cross origin child frames or `<iframes>`
in general.
## Fix
Only inject top level frames by checking `if (window.top !==
window.self) return;`.
# Fix 3: Transferring Slicing Pipeline Plugin config when switching
printers (#14832)
Select an entry in the Process tab's "Slicing Pipeline Plugin" picker,
switch the active printer preset, then click **Transfer** in the
"modified settings" dialog — OrcaSlicer crashes immediately and
repeatably. Changing other settings (e.g. a single scalar option) does
not reproduce it; only this picker does.
## Issue
`slicing_pipeline_plugin` is a vector option (`coStrings`) with an empty
default. `deep_diff` diffs vector options per-index, so selecting a
plugin produced a `"slicing_pipeline_plugin#0"` dirty key instead of a
plain one. Unlike genuine per-extruder options, this key wasn't caught
by the printer-switch filter that discards stale per-extruder changes,
so it got cached and replayed through `ConfigBase::apply_only`'s
`'#'`-indexed branch, which calls `ConfigOptionVector::set_at()` on the
freshly-reloaded (and still empty) destination vector. `set_at()`'s only
empty-vector guard is an `assert()`, which is compiled out of Release
builds, so it dereferences `values.front()` on an empty vector —
undefined behavior, matching the reported ACCESS_VIOLATION.
## Fix
Treat `slicing_pipeline_plugin` as a single atomic value in `deep_diff`
(`Preset.cpp`), same as `printable_area`/`thumbnails`/etc.,
since it isn't actually per-extruder data. It's now diffed and replayed
as a whole option (`ConfigOptionVector::set()`, a plain vector
assignment) instead of the index-based `set_at()` path — removing the
crash unconditionally, regardless of whether the two printers share the
same extruder configuration.
# Fix 4: Stale .whl cache
After a .whl was loaded once, if at runtime, the .whl is replaced with a
new one, the plugin system will use the stale .whl cache.
## Fix
Added an option in the context menu to Reload or Delete Cache and Reload
for locally installed plugins. The assumption here is that users
shouldn't be modify cloud plugins, and if they want to develop on a
subscribed cloud plugin, they should create a local copy of it.
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
## 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.
* Ensure spiral lift positive quadrant
* check for printable area
* clamp area
* simpler version
* Adjust printable area bounds with safety safety margin
Added safety margin to printable area bounds calculations.
* increase safety margin
* Refactor safety margin calculations in GCodeWriter
* New Logic
Co-Authored-By: Ian Bassi <12130714+ianalexis@users.noreply.github.com>
---------
Co-authored-by: Ian Bassi <12130714+ianalexis@users.noreply.github.com>
# Description
Typo introduced a regression failure. Fixes failing tests.
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
* fix: constrain PA_Line calibration bounding box to model geometry
- PA_Line bounding box now uses actual model convex hull for X constraint instead of full printable area
- Skip EXCLUDE_OBJECT_DEFINE for PA_Line mode (single object, no exclusion needed)
- Add tool config files to .gitignore
* modified: .gitignore
* fix: add gcode type annotations and fix box height in PA line calibration
- Label calibration segments with appropriate TYPE comments (Outer wall, Bottom surface, Top surface, Custom) for proper gcode processing
- Fix bounding box height calculation to account for z_offset
- Add LAYER_CHANGE and HEIGHT comments for multi-layer numbering display
* fix: lock PA_Line bounding box X to bed centre instead of model hull
* Added extra TYPE to ensure text/numbers/glyphs are labelled correctly
` gcode << ";TYPE:Outer wall\n"; `
* Remove hardcoded Perl path in OpenSSL.cmake
Remove hardcoded Perl path for Windows configuration.
* Add cross compilation support for Windows in OpenSSL.cmake
* Remove unnecessary blank line in OpenSSL.cmake
* Set perl config command back to variable
Accidentally uploaded version with hardcoded path for my local environment
* whitespace adjustment in previous
* removed personal .gitignore config
Remove specific files and directories from .gitignore.
* Fix box height parameter in DrawBoxOptArgs
Update DrawBoxOptArgs to use `m_height_layer` instead of `m_height_layer*2+z_offset`. This isn't a Z coordinate, it's a layer height
* Replace hardcoded extrusion type with call to `GCodeProcessor::reserved_tag` Etags
* Get pa_line bounding box from actual calibration variables
Updated calibration line bounding box calculation to use actual geometry for X bounds, using a fake call to generate the calibration pattern.
This will accurately get the size of the calibration pattern, massively reducing wasted time from bed mesh probing.
* Implement print_extents method in CalibPressureAdvanceLine
Add print_extents method to calculate bounding box extents based on bed dimensions.
* Declare print_extents method in CalibPressureAdvanceLine
Added print_extents method to return X-bounds of the pattern.
* Fixed whitespace issues
* Adjust print_extents to account for delta printers
Check if the printer is delta layout and adjust bed dimensions if so.
Used code from `CalibPressureAdvanceLine::generate_test`
* Added semicolons to reserved tags
Didn't realise etags wouldn't add semicolon - added these
* only include number list in bounding box if number list is used
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* avoid bounding box overflowing bed
* Tabs to spaces
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
- WipeTower: use filament_ramming_volumetric_speed(_nc) for ramming, falling back to
max_vol_speed only when nil; gate precool temps on enable_pre_heating
- ToolOrderUtils: disable the inter-layer forecast in the per-nozzle base reorder so
H2D/H2C ordering is unchanged
- PrintConfig: stop stripping filament_prime_volume in handle_legacy; document that
prime_volume drives the Type2 wipe tower and filament_prime_volume the Type1 one
- GCodeProcessor: exclude post-print end-gcode M400 dwells from the M73 estimate and
drop the dead air-filtration state
- Trim verbose BambuStudio source-location comments across the port
# Description
<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->
## Tests
<!--
> Please describe the tests that you have conducted to verify the changes made in this PR.
-->
load_local_machines_from_config() iterated a reference to the live
m_local_machines map while erase_local_machine() erased from it for
printers without access rights, invalidating the range-for iterator
(use-after-free on ++it). Iterate a copy instead, as the code did
before commit 5028a5000e.