Every preview frame redrew the whole scene, whether the camera had moved or a
tooltip had faded. A cursor drifting over the canvas, a hovered legend row, a
notification or the frame rate overlay each cost a full draw of every toolpath,
so a large print stayed slow with nothing happening.
Behind a preference, the window's colour and depth are now copied into a
framebuffer of the same size, sample count and depth format right after the
scene pass, and while nothing that pass draws has changed they are copied
back instead of redrawn; only the panels, the marker and the overlays are
drawn on top. What counts as a change is the camera's matrices, the canvas
size, the hovered and current plate, the world axes, a colour mode change,
and two counters from the viewer: one that libvgcode bumps whenever it
applies an update or binds another set, one the G-code viewer bumps on load,
reset, shell changes and its own toggles. A pending viewer update also forces
a redraw. A driver that refuses the blit disables the cache for the session
and the preview falls back to drawing every frame.
The frames that follow a change cost what they did before; what changes is
that a frame with no change costs a blit. On the tall fixture under llvmpipe,
cursor motion over the canvas produced a frame every 600 ms and now every
110 ms, limited by the input rate. At rest, after a slider click and after a
wheel burst the preview is pixel identical with the preference on and off,
and with it off the preview is pixel identical to before.
On a dome or a cone the shell showed holes: dashes of inner wall and overhang
wall through gaps, and darkness behind them. Each layer's ring on a slope is
inset from the one below by less than a grid cell, so the height map cannot see
the step, and the interior of the lower layer that fills it, its first inner
wall above all, had been left out. Inner wall segments whose midpoint lies
within a line and a half of an outer wall segment of the same layer now stay on
the shell, found by exact distance against the outer walls bucketed by cell,
and a segment counts as visible from above or below when any of its cells is
the topmost or bottommost occupant, since the exposed band is narrower than the
chords that cross it. Interior roles that are visible that way stay too.
The layer stride at rest was sized from the camera's zoom value and tilt, which
does not describe a perspective view: zoomed in on the test project it reached
64, so each kept ring stood 6 mm tall while the surface curved away under it.
One layer's height is now projected through the camera's own matrices, at the
centre of the toolpaths and at the camera target, and the stride follows that.
On the test project the shell at rest gains 43 k segments for the first inner
walls, 171 k to 214 k, and the dome and cone draw closed. The nine-cube plate
draws 96 k at the default view and 12 k from above.
With the shell at rest and layers merged, the skipped layers kept every segment
exposed to the layer next to it. On the tall fixture that was 25000 wipe tower
segments over its whole height: wherever the tower's footprint edge lands one
grid cell differently from one layer to the next, the cell reads as uncovered,
though hundreds of layers sit on top. The same test also kept whatever lies
under an overhang.
The classification now records the highest and lowest layer occupying each
cell over the whole print, in the pass that already rasterizes the layers, and
a segment is visible from above when its layer is the topmost occupant of at
least half its cells, and from below likewise with the bottommost. A skipped
layer at rest keeps only the segments visible from the side the camera is on,
which the viewer is told along with the stride. The exposed bit stays for the
dragging set, which is not rebuilt with the camera.
On the tall fixture with the shell at rest, against 334 ms at full detail:
default view 17679 segments 18 ms (was 37585 / 85 ms)
from above 7935 segments 7 ms (was 28682 / 58 ms)
The two-cube fixture still keeps every facing wall, and the classification
stays at 90 ms for 636 layers with the maps merged over each worker's touched
rectangle only.
Two cubes standing a few millimetres apart lost the walls that face each
other: the gap-closing that makes sparse infill read as solid bridged the gap
as well, so the footprint became one block and those walls were no longer on
its boundary. The closing now dilates each connected component on its own and
leaves a cell two components both reach empty, so no gap between objects is
ever bridged, and the raw cells are put back after the erosion, which would
otherwise eat into a wall that faces such a gap. On a two-cube fixture with a
2 mm gap every facing wall segment is kept where none was before.
Looking from above, every layer's walls project onto the same outline, yet
each cost a segment. With the shell drawn at rest the walls of one layer in N
are now drawn, N layers tall through a shader uniform so the wall stays solid,
while the exposed top and bottom surfaces of every layer stay so that no step
disappears. N follows the view: how many layers fit in two pixels at the
current zoom and tilt, from 1 side-on and close up to 64 straight down, and it
is left alone while the user is dragging since a change rebuilds the sets. The
same taller drawing applies to the dragging set, which stops it looking
striped, and in shell mode the dragging set keeps the exposed surfaces of the
layers it skips too. The first layer's grown boxes are clamped at the bed.
On the tall fixture with the shell at rest, against 334 ms at full detail:
default view 37585 segments 85 ms (was 215797 / 181 ms)
from above 28682 segments 58 ms
The classification now records which shell segments are exposed from above or
below, in a second bit set alongside the first.
A plate of large objects can be slow to draw even when nothing is moving, and
the reductions built for dragging cannot help there because they skip layers.
So a second choice, applied at all times, leaves out the internal infill roles
or everything but the shell while drawing every layer. It is a third index
buffer filled by the same walk as the other two and bound whenever the dragging
set is not; the options need no counterpart since every layer is drawn. The
shell classification is shared, computed once when either choice asks for it.
On the 636-layer three-filament fixture at rest, against 448467 segments in
334 ms at full detail:
internal infill left out 347208 segments 272 ms
everything but the shell 215797 segments 181 ms
With the shell at rest and the shell at one layer in four while dragging, the
drag frame is 62 ms. At rest with the choice set to nothing, the preview is
pixel identical to before.
The reduced toolpath set was only ever bound during a camera drag. The slider
check read is_dirty(), which the slider raises inside its own render and
_render_gcode() consumes at the end of the same frame, so it was never true at
the start of the next one; the only time it was true was the frame after a
keyboard or wheel step, which then drew one coarse frame followed by one full
frame. The navigator cube and the mouse wheel never engaged it at all, and the
extra frame requested on every level change was a full-detail frame drawn for
nothing, since the level is chosen before the draw. The reduced buffers were
also built and uploaded on every slider tick with the preference off.
Dragging is now read from ImGui's active id for the sliders and from the
navigator's own flag, a wheel step holds the reduced set for a 150 ms settle
time with the restoring frame scheduled for when it runs out, and nothing is
built while the preference is off.
What the reduced set leaves out is now a choice: skip layers only, skip the
internal infill roles, or keep the shell only. The shell is found geometrically
at load, once per print: every layer is rasterized into a half-millimetre
occupancy grid and closed so that sparse infill reads as solid, a cell is on the
shell when any of its six neighbours is empty, and a segment is kept when at
least half of its cells are. Being geometric it works for the wipe tower, whose
every segment shares one role and which is the bulk of a tall print, where
dropping roles could not. The layer stride is a preference too, one layer in
every N with both ends of the visible range always whole.
On the 636-layer three-filament fixture, frames during a drag against 448467
segments drawn in 334 ms at full detail:
skip layers only, 1 in 4 110691 segments 83 ms
skip internal infill, 1 in 4 85661 segments 68 ms
shell only, 1 in 4 54382 segments 52 ms
skip internal infill, every layer 347208 segments 255 ms
shell only, every layer 215797 segments 170 ms
The shell classification takes 63 ms once per load, split across threads. At
rest the preview is pixel identical to before in every configuration, and the
frame after a release or a settled wheel burst is the full one.
The preview's frame cost is linear in the number of visible segments and nothing
else: at 46 % of the layers the frame is 45 % of the time. A tall wipe tower puts
enough segments on screen that dragging the camera or a slider cannot keep up, and
no amount of shaving per-segment work fixes that - only drawing fewer segments does.
Everything cheaper was measured first and ruled out. Of the remaining frame, 31 % is
vertex shading and 69 % is triangle setup, so both halves scale with segment count.
Screen-space decimation is useless here: the median extrusion segment is 2.5 mm and
only 0.4 % are sub-pixel at full-plate zoom, so a threshold small enough to be
invisible removes nothing. Merging collinear runs is no better - 2.6 % of this
print's moves are collinear with the one before.
So the reduction has to be one the user can see, which means it only happens while
they are dragging, and only if they ask for it. update_enabled_entities() already
walks every vertex to decide what is visible; it now fills a second pair of index
buffers in the same walk, dropping the interior infill roles and keeping one layer
in four. Because both sets are built together, switching between them is a buffer
binding - no rebuild, no per-frame CPU work, which is what made occlusion culling
unattractive. GLCanvas3D flips the flag while the mouse is down on the canvas or
either slider is live, and asks for one more frame when the level changes so the
full-detail frame lands on release. The top of the visible layer range is always
kept whole: it is the surface being looked at, and the only layer drawn at full
colour in top-layer-only mode.
On the 636-layer, 351k-vertex three-filament fixture the set drops from 448467
segments to 85661 (19 %), and a frame during a drag goes from 298 ms to 52 ms.
Off by default, behind Preferences > Graphics > G-code Preview. With it off the
preview is pixel identical to before, and with it on the preview at rest is pixel
identical to the preview with it off - the reduced set is only ever bound mid-drag.
Verified both, plus that releasing the mouse restores full detail at an unchanged
camera. The OpenGL ES path keeps a single set of entities and is untouched.
The G-code preview's cost is linear in the number of toolpath vertices, and on a
tall multi-filament print the wipe tower dominates that count: it emits a roughly
constant 160-180 moves on every layer whatever the object is, measured at 57-61%
of all moves on a three-filament print.
Four places scanned or allocated across the whole vertex array. None of them
needed to.
get_estimated_time_at re-accumulated the estimated time from vertex 0 on every
call, and its caller is the tool marker tooltip, which ImGui re-renders every
frame while the properties panel is unfolded. It now reads a running sum built
during load from the total the load loop was already keeping, so the value is
the same addition in the same order and the float result is unchanged. At the
351k vertices of a 636-layer test print this drops the call from 238us to
0.006us.
update_view_full_range walked from vertex 0 to find where the layer range starts,
on every slider tick. It now starts at the first vertex of that layer. The index
is derived from the vertices rather than from Layers::Item::range, because
Layers::update folds a vertex whose layer_id arrives out of order into whichever
bucket is open, which makes that range the wrong answer in general; the index
costs four bytes per layer, not per vertex.
update_colors_texture allocated one float per vertex of the whole print on every
slider tick. It now reuses a buffer.
render_legend fetched the layer Zs and the per-layer times from inside loops over
the custom G-code items, and built whole vectors only to test them for emptiness.
The times are hoisted, the Zs are built lazily so a print with no colour change
does not pay for them at all, and the emptiness tests use the existing counters.
No rendering behaviour changes. Verified by loading the same project in this
build and a build of the parent commit under Xvfb and comparing frames across
five interaction states, including the unfolded tooltip whose Time row is the
output of the function that changed: pixel identical.
* build: enable /Zc:lambda for MSVC
MSVC keeps its legacy lambda processor under /std:c++17, which rejects
reading a constexpr constant inside a lambda that does not capture it
(C3493). No other compiler requires that capture, and clang reports it as
an unused one, so the two cannot both be satisfied without the flag.
/Zc:lambda selects the conforming lambda parser that clang and GCC
already use. It is implied by /std:c++20 and /permissive-, so it is only
needed while we are on C++17. clang-cl is conforming already and does not
take the flag.
It requires VS2019 16.8, so build_release_vs.bat now says 16.8+.
* build: clear 237 unused lambda capture warnings
236 captures across 81 files, 142 of them `this`. Removing an unused
capture changes no behavior; clang does not report a capture whose type
has a non-trivial destructor, so nothing held only to extend an object's
lifetime is in this set.
Nine of them are the second half of the warning, "is not required to be
captured for this use", where the capture is a const or constexpr value
the body does read. Those depend on the /Zc:lambda change in the previous
commit. One of them, in FillRectilinear.cpp, had been worked around with
an #ifndef __APPLE__ guard around the capture list, which is now gone.
GUI_ObjectTableSettings.cpp captured its reset button only to read it
inside #ifdef __WXOSX_MAC__. That branch now takes the button from the
event it is already handling.
* build: fail configure on MSVC older than 19.28 instead of dropping /Zc:lambda
cl.exe answers an unrecognized /Zc: sub-option with warning D9002 and keeps
going, so on VS2019 before 16.8 the flag is silently ignored and the build
instead dies with C3493 in FillRectilinear.cpp, nowhere near the cause.
* fix: delete three locals that are now unused
Their only remaining use was the lambda capture this branch removed. The
Clang builds set -Wno-unused-variable, so the build never flagged them.
---------
Co-authored-by: Rodrigo Faselli <162915171+RF47@users.noreply.github.com>
Adds a new "Length" row to the sequential marker position popup in GCodeViewer and updates row capacity accordingly.
For arc commands (G2/G3) that are split into multiple vertices, it now sums segment distances across vertices with the same gcode_id so the displayed value reflects the full move length instead of a single chord.
Multi-nozzle sync widget, AMS rack-nozzle mapping popup, calibration rework, send-dialog nozzle mapping and extruder-count UI. Includes the fix to persist the AMS sync badge on filament cards (H2C/A2L and direct-sync printers).
fix: apply smart preview defaults per extruder count session
- Track last extruder count (1=single, 2+=multi) instead of boolean flag
- Apply appropriate default (ColorPrint/FeatureType) when count changes
- User selections persist within same extruder count
- Symmetric behavior: both single and multi actively apply defaults
- Delete duplicate dead code block (uncommented TODO scaffolding)
Behavior:
- First slice (any type) → appropriate default
- User changes view → persists on re-slice
- Switch single→single or multi→multi → persists
- Switch single↔multi → appropriate default applies
Switching to a printer with fewer filaments (e.g. H2D -> X2D) threw
std::out_of_range in check_filament_printable. Clear stale per-volume
extruder config on count shrink and bound-check filament indices at the
read sites.
* feat(viewer): Display travel distance and move count in G-code summary
This commit introduces a new feature that enhances the G-code viewer by displaying the total travel distance and the total number of travel moves in the 'Line Type' summary.
This provides users with more detailed statistics about their prints, helping them to better understand the printer's behavior and identify opportunities to optimize travel moves for faster print times.
This commit also fixes a critical bug in the G-code processor where the travel distance was being calculated incorrectly. The distance variable was not being updated for non-extruding travel moves, leading to inaccurate statistics. The calculation has been corrected to ensure it is performed for all relevant move types, resulting in accurate travel distance reporting.
* Subfix segments
kilo mega giga tera peta exa
* Add missing values
* Grams to Kilos and tons
* add distance
* Fix tool view
* Record and display seam distances
Track seam-related distances in print statistics and show them in the GCode viewer. Added total_seam_gap_distance and total_seam_scarf_distance to PrintEstimatedStatistics (with initialization). In GCode::extrude_loop the code now computes seam gap and scarf distances and accumulates them for external perimeters. GCodeViewer uses the summed seam distance when the Seams option is selected in the legend.
* Fix travel / wipe distances
* Update GCode.cpp
* Filament changes estimated time
---------
Co-authored-by: Steve Scargall <37674041+sscargal@users.noreply.github.com>
* Fix speed popup refresh and sizing in Preview
Fix two UX issues in the Preview actual speed profile popup.
Keyboard-driven horizontal slider changes could leave the popup visually stale
until a later input event, which made keyboard navigation feel delayed.
Also, the speed-profile popup could briefly render at an incorrect height
before resizing on the next frame.
This change makes keyboard slider updates explicitly request a follow-up frame,
so refresh no longer depends on incidental mouse activity.
It also removes auto-resize from ToolPositionTableWnd and sizes the popup
before begin() each frame. The popup height is computed from plot height,
table rows, and window paddings, then clamped to at least the height of the
adjacent ToolPosition window.
The popup width is now computed from translated header text and padding terms,
with a 16:9-derived minimum for a more stable appearance. The width is cached
for the session and recalculated when UI scale changes.
Result:
- keyboard navigation updates reliably
- popup no longer shows the transient wrong-height first draw
- sizing is more stable across scale and localization
* Fix ToolPosition window also + other fixes
* Fix compile error when ENABLE_ACTUAL_SPEED_DEBUG disabled
IMGUI_DEFINE_MATH_OPERATORS is needed even if ENABLE_ACTUAL_SPEED_DEBUG is not enabled
* Guard seam fallback vertex index in GCodeViewer
* 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
- Wrap GetToolTipCtrl() call in GUI_App.cpp with #if wxVERSION_NUMBER < 3300
guard, as this API may not be accessible in wxWidgets 3.3. The dark tooltip
theming is cosmetic and non-critical.
- Add explicit #include <wx/utils.h> to 7 source files that use functions from
that header (wxGetMousePosition, wxLaunchDefaultBrowser, wxGetDisplaySize,
wxBell) but relied on transitive includes. This preempts breakage from
wxWidgets 3.3 reducing transitive includes.
Files with wx/utils.h added: BBLTopbar.cpp, CreatePresetsDialog.cpp,
CameraPopup.cpp, GLCanvas3D.cpp, GCodeViewer.cpp, GUI_ObjectList.cpp,
FilamentMapPanel.cpp.
Skipped BindDialog.cpp and FilamentPickerDialog.cpp as they already include
wx/wx.h which provides wx/utils.h transitively.
Part of wxWidgets 3.1.5 -> 3.3.2 upgrade.
* Add Pressure Advance visualization support
Signed-off-by: minicx <minicx@disroot.org>
* Port Pressure Advance visualization to libvgcode architecture
Adapt PA visualization (originally in commit e3a77259) to work with
the new libvgcode library introduced by upstream PR #10735.
Changes across the libvgcode stack:
- PathVertex: add pressure_advance field
- Types.hpp: add PressureAdvance to EViewType enum
- ViewerImpl: add ColorRange, color mapping, range updates for PA
- LibVGCodeWrapper: pass pressure_advance from MoveVertex to PathVertex
GCodeViewer UI integration:
- Add "Pressure Advance" to view type dropdown
- Add PA color range in legend (3 decimal places)
- Add PA value display in sequential view marker tooltip
- Add PA row in position properties table
The GCodeProcessor PA parsing (M900, M572, SET_PRESSURE_ADVANCE)
is preserved from the original implementation.
* Tag Pressure Advance visualization changes with ORCA comments
Signed-off-by: minicx <minicx@disroot.org>
---------
Signed-off-by: minicx <minicx@disroot.org>
Co-authored-by: Ioannis Giannakas <59056762+igiannakas@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
* Fix: GCodeViewer displaying inconsistent data in title and body
* Fix: remove actual flow info from GCodeViewer title
* Refactor: reduce repetition of N/A and headers
Fix layer/time display in Preview legend for pause/custom G-code
The Preview legend showed incorrect layer numbers and elapsed time for pause/custom G-code entries. The issue was caused by:
• get_layer_id_at() performing a strict upper_bound search on float Z values, while custom G-code stores Z positions as doubles. Minor precision differences often pushed the lookup to return layer 0 or the last layer.
• The legend displayed the raw zero-based layer index.
Fixes included:
• Fetch layer Z values as doubles and use an epsilon-based closest-layer search.
• Display layers as 1-based values for user-facing UI.
• Accumulate time up to the beginning of the identified layer.
This aligns the legend with the vertical slider marker and provides consistent pause/custom G-code reporting.
* line type by default single extruder
* Defautl to color print if use multicolor
* Update condition for setting view type in GCodeViewer
* Refine default view type selection in GCodeViewer
Improves logic for selecting the default view type based on nozzle and filament preset counts. Now selects 'Summary' for multiple nozzles, 'ColorPrint' for single nozzle with multiple filaments, and 'FeatureType' otherwise.
* Refactor multimaterial detection in GCodeViewer
Introduced a 'multimaterial' boolean to clarify logic for detecting multiple filament presets. This improves readability and maintains consistent behavior when setting the view type based on extruder and filament count.
* Bugfixes
* Reduce size of diff
to avoid merge conflicts when we cherry-pick from upstream :)
* remove extraneous space
---------
Co-authored-by: Andrew Sun <as-com@users.noreply.github.com>