Commit Graph
32379 Commits
Author SHA1 Message Date
Clifford Garwood 061190558f Merge upstream main: surface fill order, retract-after-wipe, i18n
Resolved conflicts in PrintConfig.hpp and Preset.cpp. Both were adjacent to upstream's
removal of calib_flowrate_topinfill_special_order (superseded by the new
top/bottom_surface_fill_order options); took upstream's removal from the option class
and the print-options list while keeping our new IMEX options (imex_parallel_mode,
imex_head_filament_map) and the IMEX enums (ImexToolLayout, ImexVizTheme) alongside
upstream's new SurfaceFillOrder enum. The option remains in PrintConfig's legacy
ignore-set so old projects still load.
2026-07-15 01:45:44 -04:00
Tommaso BianchiandClaude Opus 4.8 f4160595b0 Kill the remaining Design-tab UI freezes
query_topology: indexing a body face-by-face was quadratic — face_by_index
re-walks the explorer and edge_by_index rebuilds the whole indexed map on every
single call. On a 15.7k-face / 25.6k-edge imported solid this blew past the
MCP 15 s main-thread timeout with the UI frozen throughout. GeometryEngine
gains faces_of()/edges_of(), which enumerate once in the very same order (ids
stay interchangeable with the _by_index accessors, so fillet/up_to_face targets
are unaffected). Measured on that body: 15 s timeout -> 0.46 s.

Feature ops: every commit-time m_doc.recompute() (fillet, cut, shell, boolean,
extrude, ...) now goes through recompute_guarded(), which runs the rebuild on a
worker thread. Live-preview/drag paths stay inline on purpose — yielding inside
a drag would be worse than the stall.

run_off_ui_thread(): the progress dialog is now created only after 300 ms, so a
fast op does not flash a dialog, while input stays blocked (wxWindowDisabler)
for the whole operation since the worker owns the document.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-07-15 00:13:10 +02:00
Tommaso BianchiandClaude Opus 4.8 01aa6903f0 Harden the GL canvases against dropped frames and UI-thread freezes
Viewport: GLCanvas3D::on_idle() cleared m_dirty even when
_refresh_if_shown_on_screen() rendered nothing because the canvas was not on
screen yet — a frame requested while the notebook was still showing a page got
silently swallowed and the viewport stayed blank until some later event dirtied
it again. _refresh_if_shown_on_screen() now reports whether it rendered, and
on_idle keeps the canvas dirty when it did not. Covers Design/Prepare/Preview.

Freeze: a big STEP (17.8 MB) spent ~40-50 s inside OCCT on the UI thread
(read_step_solids + recompute), so the window stopped repainting and the
compositor marked the app unresponsive. Both now run on a worker thread behind
an app-modal pulsing progress dialog: the UI keeps painting and the document
cannot be touched while the worker owns it. OCCT's Standard_Failure is not a
std::exception, so the worker catches it explicitly — an escaping exception
would terminate the process.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-07-15 00:04:25 +02:00
Tommaso BianchiandClaude Opus 4.8 6d9368276c Fix Design tab not painting on hardware GL after a page switch
request_repaint() only invalidates the canvas (Refresh()) on the hardware-GL
path and relies on a wxEVT_PAINT to follow. When the notebook re-shows the
Design page, that invalidation is issued mid-show and dropped: no paint event
arrives, the canvas never renders, and the pane stays blank until another tab
switch forces an expose. Software GL renders directly, so it never showed there.

force_repaint() defers past the show, then Refresh() + Update() for a
synchronous paint. Called from on_tab_shown().

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-07-14 23:26:58 +02:00
Ian Bassi 1889ffb22a Localization: Improve bot + Update po files (#14748) 2026-07-14 16:03:15 -03:00
MqriusandIan Bassi 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
SoftFever c3f78723fb Run slice-validation sweep on engine PRs in CI 2026-07-15 02:10:16 +08:00
SoftFever f1fd49c12f Add slice-validation sweep for shipped profiles 2026-07-15 01:49:04 +08:00
Valerii BokhanandIan Bassi 50768e0716 Feature: Retract amount after wipe (#11015)
Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
2026-07-14 14:42:16 -03:00
SoftFever 0545750c1b fix profile errors caught in new tests 2026-07-15 00:08:26 +08:00
SoftFever 591d1ac948 fix qidi profile errors 2026-07-15 00:06:54 +08:00
SoftFever 28bb05ac83 Suppress excessive warnings 2026-07-15 00:06:13 +08:00
Clifford GarwoodandClaude Opus 4.8 90e8ff7cee fix(imex): align the preview marker grid with the plate zone grid
Follow-up to the cross-gantry mirror axis change, from an adversarial review of it.

GCodeViewer builds its own copy of the zone grid to place the sequential-preview
carriage markers, and it must reproduce PartPlate::calc_imex_zones exactly or the
markers drift away from the ghosts they are meant to track. It did not, in two ways,
because sizing the grid and placing a cell answer different questions:

  - Sizing: calc_imex_zones counts every Copy/Mirror tool's OWN column, including the
    non-representatives of an aggregated (Span) gantry -- they still donate a column.
    GCodeViewer only ever saw the representative, so on an aggregated gantry it could
    count fewer columns than the plate and lay its markers out against wider strips.

  - Placement: calc_imex_zones PINS an aggregated cell to the primary's column, because
    that row-strip spans the full bed and has no column of its own. GCodeViewer used the
    representative's own column, which put the marker a strip away from the ghost
    whenever the representative was not column-paired with the primary.

Track the two sets separately: grid_tool_ids sizes the grid from own columns, eff_col_of
pins only aggregated tools when placing. Out-of-grid tool indices are deliberately left
unfiltered -- calc_imex_zones drops them while calc_imex_ghosts keeps them, so no policy
here can agree with both, and a comment says so rather than pretending otherwise.

Also:
  - The mirror-axis rule lived in three copies (two PartPlate lambdas plus an inline
    re-derivation here). Hoist it to imex_mirror_axis_for() so the ghosts and the markers
    cannot drift apart, and unit-test it, including degenerate tools_per_gantry.
  - Drop imex_head_transform's mirror_axis default. A defaulted axis silently hands a
    forgetful caller the X reflection, which is wrong for every cross-gantry tool and
    fails silently -- exactly how a stale test kept certifying the old rule.
  - Replace that stale test: it asserted a diagonal mirror "flips X only", the rule this
    work overturned, and stayed green only because of the default.
  - A secondary sharing the primary's gantry now takes the primary's Y box facing. The
    box shows the side a tool could be hit from, and two tools on one beam can only be
    hit by the same other gantry. No-op on the rear-* layouts, where the hardcoded value
    already matched; on front-* layouts it pointed the box away from the only tools that
    could reach it.
  - Correct two comments that described the aggregated X-frame substitution as a
    reflection plane. It is not one: it exists to zero gantry_offset.x, and removing it
    would push aggregated ghosts a column off their strip.

Verified: 385/385 tests; CLI slice of the IMEX regression project is byte-identical to
the previous commit's G-code apart from the timestamp, confirming this is
visualization-only and cannot affect sliced output.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 10:01:09 -04:00
Clifford GarwoodandClaude Opus 4.8 0cb1788b23 fix(tests): use ASCII hyphens in IMEX test names so Windows can run them
catch_discover_tests registers each Catch2 test with ctest by name, and ctest then
re-invokes the binary passing that name back as a -# filter. The IMEX test names
contain em dashes (U+2014). They survive discovery, but on Windows the round trip
through the console codepage mangles them, so the filter matches nothing:

    Filters: "imex_head_transform G-- copy mode is pure translation"
    No test cases matched  ->  No tests ran  ->  exit != 0  ->  ctest: Failed

All 85 IMEX tests were reported as failures on both Windows x64 and arm64 without a
single one of them ever executing. Linux and macOS are UTF-8 end to end and were
unaffected, which is why this went unnoticed since the names were introduced in
77c32a2e15.

These were the only non-ASCII test names in the whole tests/ tree. Renaming them to
plain hyphens costs nothing and keeps the suite portable.

Test names only -- no assertion, no logic, no comment is touched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 10:00:50 -04:00
Ian Chua 71d0380467 fix: preset resolution 2026-07-14 19:48:39 +08:00
Noisyfox 8fe7a33ae6 Merge branch 'main' into dev/ams-heat 2026-07-14 17:05:53 +08:00
Ian Chua 3daa4336e3 fix: resizable plugins dialog 2026-07-14 15:13:10 +08:00
Ian Chua 06cd8ad0d5 chore: UI Updates 2026-07-14 14:42:32 +08:00
Ian Chua 8cc4eaea1e update some comments 2026-07-14 13:31:28 +08:00
Ian Chua fbed6f7dc6 cleanup 2026-07-14 13:10:42 +08:00
Clifford Garwood 11b894dc85 Merge upstream main (wipe tower height initialization fix) 2026-07-14 00:57:31 -04:00
Clifford Garwood f850912123 fix(imex): mirror across the gantry-row axis on two-gantry printers
A Mirror tool reflects across the boundary it shares with the primary's zone, and
which boundary that is depends on where the tool sits:

  - Same gantry: the tools are side by side along X, so the shared boundary is
    vertical and the reflection negates X. This is what single-gantry IDEX does,
    and it was the only case the code modelled.
  - Different gantry: the zones are stacked along Y (front strip vs rear strip),
    so the shared boundary is horizontal and the reflection negates Y. The part
    that comes off gantry 1 is a Y-reflection of the tool directly behind it.

imex_head_transform() hardcoded diag(-1, 1, 1) for every mirror, as its own TODO
acknowledged. Lift the axis to a caller-supplied ImexMirrorAxis; PartPlate picks it
from the tool's gantry row. Both reflections keep det = -1, so a mirrored part stays
a true mirror image rather than a 180-degree rotation, which would print the
primary's part merely turned around.

The correct axis removes two workarounds. Both ghost paths special-cased aggregated
mirrors to "drop the X reflection, translate 1:1 and bake the flip into the mesh"
because reflecting X pushed the ghost off-bed as the primary was dragged. With a Y
reflection the X translation is already zero for aggregated tools, so that falls out
for free and the special cases are deleted.

Preview markers follow the same rule, which also fixes two placement bugs:

  - Mirrors reflected across a Copy tool's zone edge, falling back to the primary's
    column when a row had no Copy. In iq-mirror (0:P,1:C,2:M,3:M) the front row has
    no Copy, so t2 and t3 both fell back and computed the identical X — both drawn
    on top of each other in t3's zone. A mirror now reflects within its own zone.
  - The toolhead footprint box flipped to the far side of the nozzle for any mirror
    right of the primary. That only holds for an X-axis mirror, which reverses the
    carriage's orientation; a cross-gantry mirror keeps the X orientation of the
    tool behind it, so its box stays on the same side.

Tests cover the cross-gantry and diagonal cases, that the axis is caller-supplied
rather than inferred from the offset vector, and that both axes are reflections
(det = -1) rather than rotations.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 00:57:31 -04:00
Ian Chua 86a4cec753 fix: preset overrides on sidebar 2026-07-14 12:57:06 +08:00
Ian Chua 796080ff76 fix: naming 2026-07-14 11:34:06 +08:00
Kris Austin 3c0338f462 fix: wipe tower height crash triggered by H2C/A2L support (#14758)
The new "Prime-tower visits..." test from #14685 (H2C/A2L support) throws
"Coordinate outside allowed range" at random on CI, on both Windows arm64 and
Linux x86_64. It's an uninitialized read of WipeTowerData::height.

#10780 (H2D/H2S) added a second wipe tower path, generate_new(), that fills in
depth, bbx, brim_width and rib_offset but not height. The older generate() sets
height, and clear() never did, so on the generate_new path it stays garbage.

first_layer_wipe_tower_corners() passes height to get_wipe_tower_cone_base() as
R = tan(cone_angle/2) * height. The stray bytes are usually zero, so R is zero
and the slice is fine, which is why it passes most runs on every platform. When
they aren't zero the cone radius runs past ClipperLib's limit and the slice
throws. Nothing selects for it, so it just flakes around.

#14685's test is the first to exercise this path, so that's when it started
showing up.

Initializing height in clear() fixes it, same as the m_origin fix in #13712. The
BBL generate_new path has no stabilization cone, so height = 0 is right.
2026-07-14 11:22:25 +08: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
Clifford Garwood 7e272f0303 fix(print): keep derived physical_extruder_map in the original-config snapshot
Print::apply() derives physical_extruder_map from printer_extruder_id and writes
it into new_full_config, but does so after m_ori_full_print_config is snapshotted.
The selector write-back path rebuilds m_full_print_config from that snapshot, so
m_full_print_config kept the unexpanded default while every subsequent apply
re-derived the expanded map. An unchanged config therefore diffed on
physical_extruder_map on every re-apply, and since that key is not handled by
invalidate_state_by_config_options() it fell through to the catch-all and
invalidated every step — forcing a full reslice on each apply.

Mirror the derived map into the snapshot so the two stay consistent.

Caught by the upstream test 'Selector write-back expands migrating filaments and
survives re-apply', which asserts a re-applied unchanged config is not
APPLY_STATUS_INVALIDATED.
2026-07-13 16:22:28 -04:00
Clifford Garwood fdb0e20f36 Merge upstream main (Bambu H2C/A2L multi-nozzle support) into IMEX branch
Conflicts were all co-located additions rather than design collisions:
- GCode.cpp: adopt upstream's toolchange(filament_id, nozzle_id) signature and
  per-variant set_config_index() while keeping the IMEX bare-T<n> suppression;
  rebase the second-layer temperature loop's non-IMEX branch onto upstream's
  get_filament_config_index() resolution.
- Preset.cpp / PresetBundle.cpp / PrintConfig.cpp: keep both sides' option-list
  and enum-map entries.
- GLCanvas3D.cpp: upstream's printable_heights argument plus the IMEX ghost pass.
- PartPlate.cpp: keep <set> (still used).
- test_gcodewriter.cpp / test_3mf.cpp: keep both sides' test cases.
2026-07-13 16:22:22 -04:00
SoftFever 25216998b3 Add Bambu H2C and A2L machine support (#14685)
# Description

This PR adds full support for Bambu H2C and A2L printers.

All features should work, including pre-heating and cooling.

The Filament Track Switch feature has been ported but hasn't been tested
yet. Feedback is welcome.


# Screenshots/Recordings/Graphs


https://github.com/user-attachments/assets/417f0e32-1967-4536-b732-3c8dc8d4dd4a

<img width="1369" height="999" alt="image"
src="https://github.com/user-attachments/assets/3c3c12ee-69c7-44ef-90f1-badc2a7e803a"
/>

<img width="848" height="580" alt="image"
src="https://github.com/user-attachments/assets/28186a99-979d-4059-b40e-798162c30ce2"
/>

<img width="892" height="551" alt="image"
src="https://github.com/user-attachments/assets/22823921-f22d-4c4d-9b89-43070120d8a6"
/>


## Tests


- [x] Multi-color/material test printing on H2C
- [x] Test printing on A2L
- [x] Test printing on P1S
- [x] Test printing on other tool changers to confirm no regressions
~~- [ ] Optional: test with newer plugin. Note: existing v02.03.00.62
plugin works without any issues~~ Will address as separate task

[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
2026-07-14 02:55:08 +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
SoftFever df1e114b72 resolve current_filament_id/current_nozzle_id in layer_change_gcode - enhanced 2026-07-14 02:12:09 +08:00
SoftFever 56f672ecbd resolve current_filament_id/current_nozzle_id in layer_change_gcode (fixes X2D) 2026-07-14 01:26:34 +08:00
Clifford Garwood 0ba09780d1 Merge upstream main into IMEX parallel printing branch
Resolves two conflicts:
- GLCanvas3D.hpp: keep both the IMEX ghost render declarations and
  upstream's _render_wireframe_overlay().
- test_gcodewriter.cpp: both sides appended test cases to the same
  region; keep upstream's origin/machine-limit tests alongside the
  pressure-advance and temperature scenarios.
2026-07-13 13:17:45 -04:00
SoftFever 9aa90fa6a8 update BBL H2D and X2D profiles 2026-07-14 00:52:54 +08:00
foXaCe ec96ca17b8 i18n(fr): align walls with the glossary and complete the catalog (#14623) 2026-07-13 13:52:33 -03:00
Alexandre Folle de Menezes 174f043f67 Changes in pt-BR to conform to the translation Glossary (#14629) 2026-07-13 13:17:57 -03:00
Alexandre Folle de MenezesandIan Bassi 3395d87240 pt-BR translation fixes after added context (#14679)
Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
2026-07-13 13:17:15 -03:00
Felix14_v2 32216dc931 Update OrcaSlicer_ru.po (#14745) 2026-07-13 12:35:30 -03:00
SoftFever 2268544a68 fix test error on Windows ARM64 2026-07-13 23:26:16 +08:00
foXaCe c41e685a69 i18n: wrap hardcoded GUI strings (undo/redo labels, dialogs, notifications) + FR (#14729) 2026-07-13 12:19:33 -03:00
Ian Chua 5b3e1b921c feat: sidebar plugin config UI 2026-07-13 20:39:41 +08:00
Andrew 635f5a3529 Merge remote-tracking branch 'public/feat/plugin-feature' into feature/speed-dial
# Conflicts:
#	src/slic3r/GUI/PluginsDialog.cpp
2026-07-13 19:39:42 +08:00
Andrew 476fa73e43 Prevent script execution during shutdown
Skip script action calls when the application
is closing to avoid post-teardown issues.
2026-07-13 19:20:23 +08:00
Andrew c3ebf38a07 Prevent hidden action execution
Block execution of actions from an empty list
until user input specifies a selection, ensuring
actions not displayed don't trigger unexpectedly.
2026-07-13 19:20:15 +08:00
SoftFever 35ffe49b17 Fix sending print jobs to Bambu H2C printer 2026-07-13 18:13:15 +08:00
Andrew 87c9ab138c Protect action identity from mutation
Keep action identity and display metadata
constructor-set so registry keys cannot drift
from the objects they index.

Require sources to publish unique ownership while
the registry retains shared keepalive for runs.

Preserve opaque IDs and persisted state keys.
2026-07-13 17:32:34 +08:00
Andrew b4c9747f09 fix(plugins): prevent callback races
Lifecycle callbacks can be registered while
another thread dispatches them, risking races
and iterator invalidation.

Snapshot shared callback objects under a mutex,
then invoke them unlocked to preserve reentrancy
and mutable callback state.
2026-07-13 17:25:39 +08:00
Andrew 592e5f92f8 Tone down inactive favourite stars 2026-07-13 16:00:32 +08:00
Andrew 39357533b2 Harden speed dial helper inputs 2026-07-13 16:00:29 +08:00
Andrew 5a3e4abb18 Catch plugin actions loaded during startup 2026-07-13 16:00:25 +08:00