The physical_extruder_map translation used by IMEX per-tool PA emission was
inlined identically at two sites in GCode.cpp (tool-change and second-layer
transition). Extract to IMEXHelpers so the routing rule ("parallel mode AND
populated pem → physical index, else -1") is testable in isolation and the
call sites read as intent rather than re-deriving the conditional.
Production change is behavior-preserving:
- Same predicate (`!mode.empty() && mode != "primary"`)
- Same empty-pem short-circuit returning -1
- Same get_at() dispatch on hit
- Both call sites replaced with a single call
Four unit tests in [IMEX] cover the routing matrix:
- non-IMEX ("") and primary mode short-circuit
- parallel mode + empty pem short-circuits (defense-in-depth; get_at would
throw on empty values otherwise)
- identity pem (non-MMU IDEX) routes filament to itself
- MMU collapse routes multiple logical slots to one physical (7-slot profile
with 4-lane MMU on physical 0 and direct drives on 1/2/3)
All IMEX + Variant regression suites pass post-refactor (133 assertions / 48
cases under libslic3r, 25 assertions / 6 cases under fff_print [PressureAdvance]).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Validates that imex_parallel_mode and imex_head_filament_map survive a
full store_bbs_3mf → load_bbs_3mf cycle — the same silent-state-loss bug
class that produced the variant-vector truncation regression, applied to
IMEX plate state which rides the same XML metadata path.
- Positive round-trip: a plate with copy_mode + a non-trivial head
filament map ("1:2,2:3") is saved and reloaded; both options land on
the destination plate's config with the exact values preserved.
- Guard scope: a plate with mode="primary" and empty head-filament-map
does NOT emit metadata (per the serializer's short-circuit), and the
reload leaves both options absent from the destination config. If the
serializer ever regressed to writing primary-mode plates, the load
path would surface phantom "primary" strings on plates that shipped
clean — this catches that.
Both scenarios call set_temporary_dir to point the BBS exporter's backup
scaffolding at a writable per-process temp directory (by default it
resolves under root at runtime, which fails for non-root test
processes).
All 27 assertions in 2 test cases pass under [3mf][IMEX].
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Exercises the IMEX per-tool PA emission surface added in af59501f4a
("feat: firmware-agnostic per-tool PA emission for IMEX parallel modes").
Six scenarios cover the full routing matrix:
- Negative PA returns empty across all flavors (early-exit guard).
- Klipper: bare vs EXTRUDER=extruder vs EXTRUDER=extruderN. Asserts the
tool=0 case emits the unsuffixed extruder name (first Klipper extruder
is named "extruder", not "extruder0") — a subtle edge case easy to
regress.
- RRF: bare vs D0 vs DN. The D0 case matters: passing tool=0 explicitly
must emit `D0`, not the current-tool fallback.
- Marlin 2.x: bare vs T0 vs TN.
- Marlin Legacy: tool index is silently dropped — verifies the fallback
branch can't accidentally start emitting T qualifiers on firmware that
doesn't support them.
- BBL: flag wins over firmware flavor (Marlin 2 flavor + BBL flag emits
the BBL-specific `M900 K... L1000 M10`) and BBL never emits a per-tool
qualifier regardless of the tool argument.
All 25 assertions across 6 cases pass under [PressureAdvance].
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds three scenarios alongside the existing child>parent stride=1 regression
test for update_non_diff_values_to_base_config:
- stride=2 child>parent: machine_max_acceleration_x (size 4 vs 2) — confirms
the truncation guard fires for the (normal,silent)-pair stride=2 path, not
just stride=1. Catches a regression class the existing test would miss
because stride=2 routes through normalize_stride2_floats and a different
set_with_restore call site.
- equal-size (2=2): exercises the path the guard does NOT short-circuit;
asserts child per-extruder values survive set_with_restore's nil-restore
merge. Catches any future change that breaks the equal-size merge — the
fix's `cur > target ? skip` predicate could regress to `cur >= target` and
silently override child values otherwise.
- non-variant scalar: layer_height in `keys` and `different_keys` but absent
from printer_options_with_variant_1/_2. Hits the is_scalar() / "nothing to
do" branch and must remain untouched. Scopes the guard's blast radius.
All four scenarios in the [Variant] tag pass: 15 assertions, 4 test cases.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds a Catch2 scenario that builds a 2-extruder child DynamicPrintConfig
inheriting from a 1-extruder parent, calls update_non_diff_values_to_base_config
through the real printer_options_with_variant_1 / _2 key sets, and asserts
that printer_extruder_id, printer_extruder_variant, and retraction_length
retain their full size after the merge. Covers three distinct
set_with_restore<T> instantiations (Ints, Strings, Floats) and verifies
both size preservation and per-extruder value preservation.
Verified load-bearing: with the guard in update_non_diff_values_to_base_config
temporarily removed, the test fails with "1 == 2" on pe_id.values.size() and
retraction_length.values.size(); with the guard restored, all six assertions
pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
update_non_diff_values_to_base_config sizes variant_index to the parent's
(inherits-target's) extruder count, and set_with_restore then replaces
the child's vector with a parent-sized one. When the child preset has
more extruders than the parent (e.g. an IDEX preset inheriting from a
single-nozzle base), every key in printer_options_with_variant_1 is
truncated to the parent's size on project reload, destroying per-extruder
data.
Observable symptoms: objects render with the wrong color (often black)
after reopening the project, and the printer preset shows a permanent
dirty-asterisk that no save/reload cycle can clear.
The child's saved value is authoritative for its own extruder count, so
skip the parent-shaped merge for the variant-keyed branch when cur >
target. Confirmed by loading a 2-extruder IDEX preset inheriting from a
single-nozzle base: all 24 variant-keyed options previously truncated
from child_size=2 -> 1 are now preserved at size 2.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
_picking_pass_imex_ghosts is what resets m_hover_ghost_head, but _picking_pass
early-returns (mouse drag, mouse off-canvas, gizmo drag) skip that reset. If
the user switches from an IMEX printer to a non-IMEX one during such a window
the plate clears its ghost volumes while the stale head index survives,
producing an orphan tooltip anchored to nothing.
Validate the hover state against live ghost volumes before rendering the
tooltip and self-heal the indices when they no longer point at anything.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace imex_head_transform's fifth argument (Vec3d primary_origin) with a
Vec2d primary_zone_center and rewrite the Mirror branch as a true reflection
about the plane x = primary_zone_center.x + gantry_offset.x/2. Previous math
flipped about the primary's current origin, which:
* let the ghost drift out of the target zone as the primary moved, and
* made mirrored drag motion track 1:1 with the primary instead of reflecting.
The new transform places the ghost at the mirrored position within the target
zone (matching where the mirror tool actually prints) and reflects drag so
primary +X → ghost -X while Y tracks 1:1 — i.e. the ghost stays a true
mirror while the user drags. Off-row Mirror targets (e.g. T3 on a 2x2) still
reflect across the same X-plane as on-row peers.
PartPlate::calc_imex_ghosts and update_imex_ghost_transforms now feed primary_off
(the primary head's zone center) instead of an instance-space Vec3d.
Mirror tests rewritten against the new geometric contract: ghost origin at the
reflected position, primary drag deltas reflected across the zone-boundary plane.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Centralize the project→printer→printer_extruder_id fallback for the physical
extruder map. PrintApply, PartPlate (ghost color + cache key), Plater (tooltip
+ click gate) all previously open-coded the three-step lookup, and each handled
the "pem unset, derive from pei" case slightly differently — an IDEX printer
without an explicit pem could paint an UNPRINTABLE_COLOR ghost even though the
slicer would have derived a valid mapping.
- IMEXHelpers: add effective_physical_extruder_map(explicit_pem, pei) and a
PresetBundle overload that wraps the project→printer precedence.
- PrintApply: use the helper in place of the inline pei→pem normalization.
- PartPlate / Plater: call the PresetBundle overload at every ghost-color,
ghost-cache-key, tooltip, and click-gate site.
- Plater::format_imex_ghost_tooltip: when no filament resolves to a head,
surface an actionable message directing the user to extend the extruder
count in the Machine tab, instead of the generic "(no filament routed)".
- IMEXFilamentPickerPopover: hold m_pem by value so callers can pass a
stack-local derived pem without lifetime worries.
- Tests: 5 new cases covering explicit-wins, default-pem fallback, null
inputs, and the IDEX ghost-color regression that motivated this.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
PartPlate::calc_imex_zones, GCodeViewer::render, and Plater::collect_imex_warnings
each hand-rolled their own "phys:P/C/M" tokenizer with subtly different error
handling. Replace the three inline loops with parse_imex_active_tools +
imex_primary_tool_for_mode so the Primary/Copy/Mirror classification agrees
across zones, the G-code viewer legend, and slice warnings.
No behavior change: the shared helpers preserve the 1=Primary / 2=Copy /
3=Mirror encoding already consumed downstream and continue to accept the
legacy bare-index form as Primary.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replaces the plater-icon popover with colored transparent ghost copies
of primary-head instances on the plate, one per secondary active head
under its Copy/Mirror role transform. Left-click on a ghost opens a
compact filament picker popover for the ghost's head (MMU lane override).
Ghosts track the primary through drag/rotate/scale/mirror and invalidate
on mode or pem changes.
Key pieces:
IMEXHelpers -- imex_head_transform (Primary/Copy/Mirror), shared role
parser, per-head filament resolution with X-axis Mirror anchor.
PartPlate -- ghost state, volume rebuild on mode/map/object mutation,
primary_origin plumbed for Mirror reflection across the primary-row
gantry plane.
GLCanvas3D -- ghost rendering with per-head filament color and
translucent blending; picking routed via volume composite id.
Plater -- ghost click + tooltip; plater icon left-click always cycles.
IMEXFilamentPickerPopover -- BitmapComboBox row for one secondary head,
writes imex_head_filament_map on selection.
bbs_3mf -- round-trip the per-plate imex_head_filament_map option.
PrintConfig -- add imex_head_filament_map as a plate option.
MMU/AFC routing for parallel modes relies on the printer profile's
physical_extruder_map (see prior commit for authoring format). Primary-
row heads and their per-plate filament overrides are resolved through
that map, so PA and temperature emission address the correct physical
extruder when multiple logical slots share one carriage.
Tests: IMEXHelpers coverage for Primary/Copy/Mirror transforms
including a 2x2 off-row regression guard for the X-axis reflection fix.
Auto-populate physical_extruder_map (0-indexed) from printer_extruder_id
(1-indexed) in Print::apply(). The guard only runs when the map is still
at default size (<= 1 element), so printer profiles that set it explicitly
are untouched.
All IMEX parallel-mode PA and temperature emission now routes tool slot
indices through physical_extruder_map before constructing firmware
extruder qualifiers (EXTRUDER=, M104 T, M572 D). This ensures AFC/MMU
setups where multiple slots share one physical extruder get the correct
qualifier -- e.g. T6 on physical extruder 3 emits EXTRUDER=extruder3
instead of EXTRUDER=extruder6.
Profile authoring for MMU/AFC printers:
Add physical_extruder_map to the printer profile JSON as a 0-indexed
string array, one entry per logical filament slot, whose value is the
physical extruder carrying that slot. The array size must be > 1 for
the explicit map to override the auto-derive. Example for a 7-slot
printer with a 4-lane MMU on extruder 0 and three independent direct
drives on extruders 1/2/3:
"physical_extruder_map": ["0","0","0","0","1","2","3"]
Non-MMU printers need no action -- printer_extruder_id already encodes
the 1:1 mapping and the auto-derive handles it.
Deeper integration (zone validation, collision detection, filament
assignment grouping, Moonraker agent auto-population) is deferred.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* deps: Use CMAKE_BUILD_PARALLEL_LEVEL for dependency builds.
If set when initial CMake is run, don't hard-code the number of CPUs for all the
recursive child builds.
* build_linux: Pass -j1 for dependency build.
This is recommended by the comment at the top of deps/CMakeLists.txt, and makes
sense as the recursive build steps will pick up
CMAKE_BUILD_PARALLEL_LEVEL (otherwise the number of parallel jobs is squared).
# Description
- Changing the filament name from Z-Bolt PLA (ABS, ABS HT, PETG, PA) to Generic PLA @Z-Bolt (etc);
- Increased size of g-code thumbnails for S800 Dual and S1000/S1000 Dual;
- The profile structure has been optimized to reduce the variety of profiles for each printer model;
- Extruder temperatures for all filaments have been increased for hardened steel nozzles;
- New process profiles have been added for the 0.6mm nozzle (0.16mm High Quality and 0.20mm High Quality);
- Disabling multicolor printing for single-head printers;
- The "_BEFORE_LAYER_CHANGE" and "_AFTER_LAYER_CHANGE" macros have been added to printer profiles.
<!--
> Please provide a summary of the changes made in this PR. Include details such as:
> * What issue does this PR address or fix?
> * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be considered?
-->
# Screenshots/Recordings/Graphs
<img width="762" height="257" alt="изображение" src="https://github.com/user-attachments/assets/b5c2ef09-343f-47e8-adb5-fcf682866882" />
<img width="731" height="361" alt="изображение" src="https://github.com/user-attachments/assets/b3259fed-7698-4ab2-89d7-b6b00d974b02" />
<img width="736" height="889" alt="изображение" src="https://github.com/user-attachments/assets/be79822a-da82-4715-a5c0-c393f0cb98b7" />
<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->
## Tests
OrcaSlicer_profile_validator.py
<img width="1053" height="84" alt="изображение" src="https://github.com/user-attachments/assets/a3427a51-e77f-40f3-a7b4-efbd62992290" />
check_profiles.yml
<img width="2203" height="681" alt="изображение" src="https://github.com/user-attachments/assets/994d0423-660a-4e0e-be4f-4b1c72b653f3" />
orca_extra_profile_check.py
<img width="1024" height="142" alt="изображение" src="https://github.com/user-attachments/assets/ddd8e3bf-b845-48fc-b736-ca80c138ce64" />
<!--
> Please describe the tests that you have conducted to verify the changes made in this PR.
-->
Fix segfault in CLI mode when extruder/filament options absent
When slicing via CLI (--slice) with a BBL printer profile such as the
P1S, update_values_to_printer_extruders and
update_values_to_printer_extruders_for_multiple_filaments dereference
option pointers without checking for nullptr first, causing a SIGSEGV.
Root cause: printer profiles that have different_extruder=true (e.g.
P1S variants) trigger these code paths even in single-extruder CLI
invocations where filament_map, extruder_type, and nozzle_volume_type
options may not be present in the resolved config.
Fix: add null guards before dereferencing option<> / dynamic_cast<>
results, consistent with the pattern used in PR #12719. Log a warning
and return early rather than crashing.
Fixes CLI --slice segfault (exit 139) with P1S profiles.
Related: #12426, #12719
The "Pre-slice warnings" line in the IDEX/IQEX Configuration section
was a widget-only line (no options) with full_width left at the default
of 0. activate_line() only skips the option_set.front() call when
full_width=1; without it, the code falls through to:
bool is_legend_line = option_set.front().opt.gui_type == ...
Calling front() on an empty std::vector is undefined behavior. On
Windows/MSVC release builds this dereferences a null pointer and reads
at offset 0x30 (where ConfigOptionDef::gui_type lands), producing an
ACCESS_VIOLATION at 0x30. On Linux/GCC the same UB happens to be
harmless, so the crash is Windows-only and cannot be reproduced on
Linux.
Fix: set line.full_width = 1, matching the pattern used by the "Modes"
(IMEXModesCtrl) line. This takes the early-return widget path in both
append_line and activate_line, bypassing option_set.front() entirely.
Reported by tester: crash on clicking Multimaterial tab with any
printer (K3D VOSTOK confirmed), build af59501f.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
# Description
<!--
> Please provide a summary of the changes made in this PR. Include details such as:
> * What issue does this PR address or fix?
> * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be considered?
-->
# Screenshots/Recordings/Graphs
<!--
> 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.
-->
Reduce the size of current and new JSONs by standardising them with 1 tab indentation instead of 4 spaces.
This effectively reduces the size by almost 20 MB.
| Current | New |
|---|---|
| 85.2 Mib | 67 Mib |
Used [JQ](https://jqlang.org/) `--tab` to automatically format every current JSON.
> [!NOTE]
> Some profiles had the arrays on the same line, but those created by Orca were in the standard format (each object below the previous one). In some cases, this increases the number of tabs due to the new lines, but the increase is negligible, and this way both the base profiles and those created by Orca maintain the same style.
* identified code for snapping to buidlplate
* rename internal name to ensure_on_bed to be consistent, saves option in 2mf, finish Move UI, use in both ensure_on_bed() functions
* makes auto_drop a per-object setting, removes global setting
* remove adUndef, add auto_drop to constructor/serialize
* fixes drop() button
* add "auto_drop" checkmark to "load as single object" dialog,
nothing changes if auto_drop == yes || "load as single object",
if auto_drop == false and "load as single object" == false the objects now retain their relative position to each other
* retains auto_drop (and printable) state when assembling or splitting objects,
adds ObjectList::printable_state_changed() overload to be able to only provide ModelObject* vector
* adds dialog when splitting to ask if auto_drop should be disabled,
only shows when auto_drop enabled and atleast one volume floating
* adds arrow indicator on bounding box if auto_drop == false
* removes unneeded code, keeps "auto_drop" naming consistent
* makes for loop simpler in set_printable, set_auto_drop and get_auto_drop,
makes get_auto_drop const,
fixes wording in Snapshot text
---------
Co-authored-by: Hanno Witzleb <hannowitzleb@gmail.com>
Co-authored-by: SoftFever <softfeverever@gmail.com>
Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
Extends set_pressure_advance() with an optional tool index (default -1,
preserving existing behavior for all non-IMEX call sites). Per-firmware:
- Klipper: EXTRUDER=extruder[N] when tool >= 0, bare command otherwise
- RRF: M572 D<N> when tool >= 0, bare M572 otherwise (no D0 fallback)
- Marlin 2: M900 K<X> T<N> when tool >= 0, bare M900 otherwise
- Marlin Legacy / fallback: M900 K<X> always
Adds m_imex_parallel_mode to GCode, set once per export from the active
plate mode. PA and layer-transition temperature tool-qualification are
gated on this being a non-primary parallel mode — primary mode prints
use regular tool-change PA exactly like any non-IMEX printer. Secondary
active tools in parallel modes receive explicit per-tool PA at print
start since they never go through a tool-change sequence.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces MessageDialog with RichMessageDialog to show a suppress
checkbox on both slice-plate and slice-all warning paths. Persists
the choice to app_config as imex_pre_slice_warnings=false. Adds a
re-enable toggle in Printer Settings → Multimaterial → IDEX/IQEX
Configuration so the warnings can be restored if suppressed accidentally.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
update_visibility() and render() both called front() on an empty vector
when a CtrlLine had no options (pure widget lines). Added an early-return
path in update_visibility() and a null-guard in render().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Temperature emission (GCode.cpp, PrintConfig.cpp, ConfigManipulation.cpp):
- Set temperatures for all active tools in layer_change_gcode for iMEX
parallel modes (primary + secondary carriages)
- Fix filament temperature commands so Layer 1 temperatures only emit on
the first layer; subsequent layers use normal layer-change temperatures
- Remove stray temperature commands that fired outside the intended context
- Consolidate iMEX temperature handling into the second-layer transition;
clean up emission logic and naming throughout
Pre-slice warning dialogs (PartPlate.cpp/hpp, Plater.cpp):
- Collect per-plate IMEX warnings before slicing: multi-material conflict,
bed temperature mismatch between carriages (>5 °C delta), and filament
type incompatibility
- Show a dismissible Yes/No dialog from both "Slice Plate" and "Slice All"
actions; No returns to 3D view, Yes proceeds to slice
- Refresh plate thumbnails after the panel switch so previously-generated
thumbnails are not left black
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add runtime display backend detection for Wayland support
Add LinuxDisplayBackend utility to detect X11 vs Wayland at runtime
using GDK_IS_X11_DISPLAY / GDK_IS_WAYLAND_DISPLAY macros. This is
the foundation for removing the forced GDK_BACKEND=x11 and enabling
native Wayland support.
- New files: LinuxDisplayBackend.hpp/.cpp with get_linux_display_backend(),
is_running_on_wayland(), and is_running_on_x11()
- Propagate wxHAVE_GDK_X11 / wxHAVE_GDK_WAYLAND from FindGTK3.cmake
as compile definitions to libslic3r_gui
- No-op on non-Linux platforms (returns Unknown / false)
* Fix Phase 1 code quality: pragma once, source ordering, static cache
* Make X11 initialization conditional for Wayland support
Remove the unconditional GDK_BACKEND=x11 force that blocked native
Wayland. Replace with conditional logic:
- EGL safety fallback: re-force X11 only when wxUSE_GLCANVAS_EGL is
off and WAYLAND_DISPLAY is set, with a warning log
- XInitThreads() only called when DISPLAY is set (X11 in use)
- __GLX_VENDOR_LIBRARY_NAME only set when DISPLAY is present (GLX-specific)
- WEBKIT_DISABLE_COMPOSITING_MODE only set under XWayland (both
DISPLAY and WAYLAND_DISPLAY present)
- Guard X11/Xlib.h include with __has_include for robustness
- Restore display validation to accept either DISPLAY or WAYLAND_DISPLAY
This is Phase 2 of the Wayland support plan.
* Fix Phase 2: safer EGL macro check, add clarifying comments
* Add GLAD2 library and replace GLEW linkage in build system
Set up GLAD2 as a static library to replace GLEW for OpenGL loading.
GLAD2 supports both GLX and EGL, which is required for Wayland support.
- Create src/glad/ with pre-generated GLAD2 sources (GL 4.6 compat)
- Add src/glad/CMakeLists.txt building glad as a static library
- Wire glad into src/CMakeLists.txt before libvgcode
- Modify libvgcode to use shared glad for GL path (keeps local copy
only for GLES2/Emscripten) to avoid duplicate symbol conflicts
- Replace GLEW::GLEW with glad in libslic3r_gui link libraries
Note: GLEW is kept in deps for OpenCSG. Code migration from GL/glew.h
to glad/gl.h headers will follow in Phase 3B+3C.
* Fix Phase 3A+3D: libvgcode GLAD include, dead files, dlopen dep, OpenGL link var
* Migrate from GLEW to GLAD: replace headers and API calls across codebase
Replace all #include <GL/glew.h> with <glad/gl.h> across 49 source files.
Migrate GLEW API calls to GLAD equivalents:
- glewInit/glewExperimental -> gladLoaderLoadGL()
- GLEW_EXT_* / GLEW_ARB_* extension checks -> GLAD_GL_EXT_* / GLAD_GL_ARB_*
- Remove GLEW-specific EGL/GLX mismatch #error guards (not needed with GLAD)
- Replace unavailable EXT symbols with core GL equivalents in
GLCanvas3D.cpp (GL_MAX_SAMPLES, glRenderbufferStorageMultisample,
glBlitFramebuffer, GL_READ/DRAW_FRAMEBUFFER)
- Update log messages from glewInit to gladLoadGL
* Fix Phase 3B+3C: remove GLEW find, clean EXT symbols, update attribution
- Remove find_package(GLEW) block from root CMakeLists.txt since GLEW
is no longer linked by any main application code
- Remove "glew" from SLIC3R_STATIC option description
- Replace all remaining EXT framebuffer symbols with core equivalents
in render_thumbnail_framebuffer_ext and _rectangular_selection_picking_pass
- Update AboutDialog credits from GLEW to GLAD
* Enable EGL in wxWidgets and add runtime GLX/EGL selection for Wayland
- Set wxUSE_GLCANVAS_EGL=ON in wxWidgets build and Flatpak manifest
- Add PreferGLX() call on X11 sessions for driver compatibility
- Remove Phase 2 safety fallback (EGL is now always compiled in)
- Guard SwapBuffers against hidden canvases to prevent Wayland stalls
* Fix Phase 4: move PreferGLX to app startup, fix FPS counter guard
Move wxGLCanvas::PreferGLX() from OpenGLManager::create_wxglcanvas()
(static initializer) to GUI_App::on_init_inner() before any wxGLCanvas
is constructed. This prevents a race where SkipPartCanvas could trigger
wxGLBackend::Init() before the GLX preference is set. The new location
also adds explicit is_running_on_wayland() detection with a warning for
unknown backends.
Move increment_fps_counter() inside the IsShownOnScreen() guard so FPS
is only counted when a frame is actually swapped.
* Update GLFW from 3.3.7 to 3.4 for runtime Wayland/X11 backend selection
Replace the compile-time GLFW_USE_WAYLAND flag (which locked to a single
backend) with GLFW 3.4's GLFW_BUILD_WAYLAND + GLFW_BUILD_X11 flags that
build both backends and auto-select at runtime based on the available
display server. This enables the CLI thumbnail renderer to work on both
Wayland and X11 sessions without separate builds.
* wayland: Fix UI call sites that rely on global screen coordinates
On Wayland, wxGetMousePosition() returns (0,0) and SetPosition() is a
no-op for top-level windows. Fix the highest-impact call sites:
- GLCanvas3D: Use cached m_mouse.position from event handlers instead
of wxGetMousePosition() + ScreenToClient() in get_local_mouse_position()
- Plater: Use event-relative coords via ClientToScreen(e.GetPosition())
instead of wxGetMousePosition() in 3 leave-window handlers
- BBLTopbar: Use event.GetPosition() and FindToolByPosition() directly
in mouse handlers instead of wxGetMousePosition()/FindToolByCurrentPosition()
- Search: Use focus-based dismiss logic on Wayland instead of
wxGetMousePosition()-based rect checks in SearchDialog and
SearchObjectDialog
- GUI_App: Skip SetPosition() in window_pos_restore() on Wayland where
it is a no-op; still restore size and maximize state
- Button: Position tooltip relative to button widget via ClientToScreen
instead of wxGetMousePosition()
* Fix SearchDialog Wayland dismiss: guard against search_line focus
* flatpak: Add Wayland socket permission for native Wayland support
* spec
* Fix crash on Wayland when wxWidgets lacks EGL support
Restore the safety fallback that forces GDK_BACKEND=x11 when wxWidgets
was not built with wxUSE_GLCANVAS_EGL=ON. Without this, the GLX backend
tries to access a non-existent X11 display on native Wayland, crashing
in wxGLCanvas::IsDisplaySupported() with SIGSEGV at offset 0xe4.
Also add a defense-in-depth guard in detect_multisample() that skips
the IsDisplaySupported call entirely on Wayland without EGL.
Root cause: deps/wxWidgets must be rebuilt after enabling EGL. The
compile-time check in OrcaSlicer.cpp detects the mismatch and falls
back safely.
* Fix EGL detection: use wxHAS_EGL instead of wxUSE_GLCANVAS_EGL
wxUSE_GLCANVAS_EGL is a CMake build option, NOT a C++ preprocessor
macro. The actual macro defined in wxWidgets setup.h is wxHAS_EGL.
All compile-time EGL checks were using the wrong macro, causing
the safety fallback to always trigger even with a properly built
EGL-enabled wxWidgets.
* Fix GL function pointers invalidated on Wayland/EGL
gladLoaderLoadGL() dlopen's libGL.so.1 to resolve GL function pointers
via dlsym, then immediately dlclose's the handle. On X11/GLX this is
fine because the GLX context keeps libGL.so mapped. On Wayland/EGL,
nothing else holds libGL.so open, so dlclose unmaps it and all function
pointers become dangling — causing SIGSEGV on the first GL call.
Fix: on Wayland, use gladLoadGL(eglGetProcAddress) which resolves
function pointers through the EGL loader without opening/closing
libGL.so.
* fix crash on start and various rendering issues
* fix crash on close
* small refactor
* move GPU selection to desktop file
* clean up a bit
* clean up more
* fix appimage error
- add a new mode to build in docker
- Improve AppImage
1. fix libbz2 soname differeence issue on appimage
2. Downgrade to 22.04 for better compatibility
3. improve appimage overall
In iMEX (IDEX/IQEX) parallel printing modes (copy/mirror), only the
primary extruder generates toolpaths. The firmware duplicates the
primary's movements for secondary carriages, so they don't appear in
tool_ordering.all_extruders().
This caused is_extruder_used[N] to return false for secondary tools
even though they're physically active and moving.
The fix adds logic to parse the active mode's tool assignments from
imex_mode_active_tools config and marks all assigned tools as used.
Changes:
- Added null checks and bounds validation for config options
- Skip empty tool strings to avoid unnecessary parsing
- Reordered bounds checks for defensive programming
- Added clarifying comments for exception handling
This ensures is_extruder_used[N] is true for all tools in a parallel
mode, allowing printer profiles to correctly enable heaters and
emit cleanup G-code for all active carriages.
Fixes: is_extruder_used[1] returns false in copy/mirror modes (#13086)
Related: Comment [28]/[30], Comment [18] (is_extruder_used in G-code header)
Bump GitHub Actions action versions
Update workflow action versions: upgrade geekyeggo/delete-artifact from v5 to v6 and microsoft/setup-msbuild from v2 to v3 across .github/workflows/build_all.yml, build_deps.yml, and build_orca.yml. This brings workflows to newer action releases for compatibility and fixes.