* Keep User Filament Presets on Printers Their Parent Listed in 2.4.2
User presets store only their diff, so they inherit the parent's
compatible_printers. Profile changes since 2.4.2 renamed and narrowed many
system filament presets, so user presets made against them disappear from
printers they were made for and the saved selection silently falls back to
another filament at startup.
orca_profile_tool.py legacy-compat writes, per current system filament
preset, the printers it covered in an older release and no longer lists,
kept only where a preset with the same filament_id still covers the printer
and they share an extruder variant. The loader gives these printers to user
presets that inherit their parent's list, without writing any file; saving
a preset detached, cloned or with its own list drops them.
* Ask Before Migrating User Filament Presets to Their Legacy Printers
Instead of giving user presets their parent's 2.4.2 printers in memory,
detect the user presets that inherit their parent's compatible_printers
and are missing printers from the legacy map, and offer to migrate them
at startup or from Help > Migrate Filament Presets.
Migrating first backs up the user folder to
filament_preset_migration_<datetime>_backup.zip in the configuration
folder, and migrates nothing if that fails. It then writes the printers
into each preset's compatible_printers, patching only that key so the
preset keeps the parent name it was saved with and older releases can
still resolve it. Cloud-synced presets are marked for upload.
No asks again at the next launch; "Don't remind me again" stops the
startup prompt.
* Key the legacy filament preset map by the parent's 2.4.2 name
* Check the legacy filament preset map in CI
* Limit the 2.4.2 filament preset migration to presets that need it
Only presets that still name their parent as 2.4.2 did and have no printer
list of their own are offered, and a preset changed after it was found is
left alone. The startup prompt appears once, after upgrading from 2.4.2 or
earlier, as a standard dialog that keeps "Don't remind me again"; Help >
Migrate Filament Presets is unchanged. Migrating no longer overwrites an
unsaved printer-list edit or marks the project modified.
* Ask on Every Start and Take the User Presets Lock Once When Migrating Filament Presets
The startup prompt no longer depends on the version the previous run
recorded: whoever still has user filament presets that lost printers is
asked, including users already on a 2.5.0 nightly or alpha. Answering No
asks again at the next start; "Don't remind me again" stops it.
Migration takes the user presets lock once, around the backup and every
file write, instead of once per preset. A lock another instance holds is
reported once ("another OrcaSlicer instance is saving presets") with
nothing written, rather than as one failed preset after another once the
lock's cool-down kicks in. Detection records each preset's file and the
list it will get, so the writes need no collection lock while the user
presets lock is held, the order InstanceLock requires; the loaded presets
are updated afterwards.
* Run the Legacy Compatible Printers Map Check in check_profile.sh and .ps1
CI's "Check profiles" job checks resources/info/legacy_compatible_printers.json
against the v2.4.2 profiles, and its failure message points at these scripts
as the local reproduction, so they run the same check: legacy_compat, right
after profile_tool. The v2.4.2 tree comes from git archive of the tag, is
cached in the work dir like the other downloads, re-extracted with --refresh,
and fetched from upstream first when the checkout lacks the tag.
* Back Up Before the User Presets Lock and Merge Migrated Printers Into the Live List
The lock guard is meant for a few file operations, and zipping a large user
folder is not one, so the backup is taken before it and the guard covers the
writes only; each write re-reads its file, so a save that slipped in before
is still respected.
The in-memory update adds the lost printers to the list the preset holds at
that moment rather than replacing it with the one found at detection, and
leaves a pending cloud sync state alone: a download waiting to be saved kept
its newer list and its "save" flag, which "update" would have cancelled.
The lock message no longer blames another instance alone, since the lock is
also refused for a while after a miss and when the lock file cannot be
opened.
---------
Co-authored-by: SoftFever <softfeverever@gmail.com>
* Add orca-translations Claude skill and PO tool
Add a .claude skill that guides translation passes over the localization/i18n gettext catalogs. It covers the workflow: run gettext, settle new glossary terms, translate in batches, verify, and report.
Includes translation-rules.md, which condenses the placeholder, line-break and glossary rules plus the guidance on review notes.
Also adds scripts/po_tool.py (standard library only). It lists pending entries with glossary hints, validates and applies translations, adding '# AI Translated' and '# Needs human review' comments, and rewrites only the entries it changes. It can also check catalogs, look up existing translations, suggest glossary candidates and update the wiki glossary TSV.
* Let po_tool apply translations by entry id
pending now gives each entry a short id, so a translation file can name
entries by id instead of repeating the English msgid. apply accepts either.
A "review": "" item clears an earlier review note when overwriting an
entry, and check gives each msgfmt run its own temporary output file so
parallel checks do not collide.
* Fill all empty translations
Regenerate the template with run_gettext --full and translate every empty
entry in the 22 catalogs (7,089 entries) with the orca-translations skill,
following the localization glossary, including the new belt printer,
IDEX/IQEX and plugin terms. Every new entry is marked "# AI Translated";
122 also carry "# Needs human review" with what to check.
* Show entry ids in po_tool lookup and search translations
lookup now prints each entry's id, so an entry found there can be
rewritten with apply --overwrite without repeating the English, and
--msgstr searches the translations instead of the msgids, which finds
every entry that still uses a term being changed.
SKILL.md describes how to change an established term: check the
catalog's usage first, update the glossary cell, then rewrite only the
entries where the term has that meaning.
* Fix mistranslated terms and align catalogs with the glossary
Correct labels that the glossary had copied, and the entries that used
them:
- ca: Raft was rendered as the Brim term; it is now "Rai". Exhaust fan,
Monotonic line, Unretract, Slice, Lateral Honeycomb and PA Tower
labels fixed.
- cs: Lightning infill is "Blesk", not "Osvětlení" (illumination).
- sv: Retraction is "Retraktion", not "Reduktion"; Unretract,
Lagerhöjd, Delkylningsfläkt, Utsugsfläkt, Aligned Rectilinear and the
Preset label fixed.
- de: Brim is "Rand" and Skirt is "Umrandung", as most entries already
had them.
- lt: brim entries used the Skirt word "apvadas"; they now use "kraštas".
- es: Sparse infill is "relleno de baja densidad", the catalog majority.
- eu: nozzle wipe is "garbiketa", not purge.
- th: the project plate is "เพลต", distinct from the bed.
- uk: Quarter Cubic, Latin "PA" in PA Tower, and Belt purge tower.
- pl: Cross Hatch, Tri-hexagon, Volumetric speed and Raft labels.
- zh_TW: Brim stays "Brim", as the existing labels have it.
- tr: "Prime Tower" read "Prime Minister Tower".
- ko: the plugin "Capabilities" label read "performance".
- Build Volume labels fixed in tr, de, cs and eu.
All 242 rewritten entries are marked "# AI Translated".
* Make more UI text translatable and fix pluralization and context
Audit the sources for text that translators could not translate
correctly and fix it.
Mark text that reached users in English only: IDEX/IQEX role names,
plugin permission prompts and errors, 3MF/preset loading errors, G-code
placeholder parser errors, calibration and device messages, notification
texts, file dialog filters, and the config validation messages.
Replace sentences built from translated fragments, such as the prime
tower warnings, "left"/"right" nozzle names, and "Filament " + number,
with single msgids that have placeholders, so translators can reorder
and inflect them.
Use plural forms for texts with a count ("%1% mixed filaments",
"%d objects", "%1% triangles") instead of "(s)" and mismatched verbs.
Fix the swapped singular/plural pair in "The following presets inherit
this preset".
Add translation contexts where one English word has several meanings
(Subscribed/Local, Standard, Pause, View, Step, Model, Camera, Flow,
Filter, Others, Prepare, the Design tools). Show "Size" instead of
"Build Volume" in the Cut tool, which displays the object size.
Fix code that compared translated text with English (the Edit G-code
dialog group, the plugin registration failure check), and add the
bundled web pages' missing string-table entries. Use the single
character for degrees Celsius, say "G-code", and describe the head
filament map without internal jargon.
Install the libslic3r translate callback before the presets load, so
their load errors are translated, and list the 28 source files that had
marked strings but were never extracted into localization/i18n/list.txt.
* Suggest earlier translations and list fuzzy entries in po_tool pending
pending now attaches the closest earlier translation of a similar
English text (from obsolete or translated entries), so a reworded or
split string keeps its wording, and it lists fuzzy entries by default,
since users never see them. A fuzzy entry also carries its stale
translation as previous_translation.
* Fix wording of the non-boolean operands error
The logical operation error said "operators" where it means the
operands the operation was applied to.
* Translate the newly translatable strings in all languages
Regenerate the template after the translatability changes and fill every
new or changed entry in the 22 catalogs (about 12,800 entries): the
strings that became translatable, the plural forms, the entries split by
context, and the previously fuzzy singular entries that became plurals.
Every new entry is marked "# AI Translated", and about 360 also carry a
"# Needs human review" note saying what to check. Terms follow the
localization glossary. Earlier translations of reworded strings were
reused where the meaning was unchanged. Existing entries were not
changed, and obsolete entries are kept.
* Document the source translatability audit in the orca-translations skill
Add a reference describing how strings reach translators, what to look
for (untranslated text, spliced sentences, missing plurals, ambiguous
words), what not to translate, where a context cannot be carried, and
what to do after the edits, plus a scanner that lists untranslated
user-facing string literals.
* Document how to write translatable strings in AGENTS.md
Tell developers to keep each message complete in one msgid: use
placeholders instead of concatenating translated fragments, plural forms
for counts, and contexts for ambiguous words, and to list new source
files in localization/i18n/list.txt. Add a matching code review item.
* Translate the strings added since the rebase
Regenerate the template against the current main and translate the 26
new entries per language: the Fix Model commands and messages, and the
texture displacement image adjustment panel. Each new entry is marked
"# AI Translated"; existing entries are unchanged.
* tidy
#16284 closed the Slice-plate hover popup only when the Slice button opened
the filament grouping dialog. The dialog also opens from the plate's filament
grouping icon, the preview legend, slicing notification links and the send
dialog, and a popup still shown on those paths keeps the mouse capture on
macOS and starves the modal dialog of clicks. Dismiss it in
FilamentMapDialog::ShowModal() instead, so every path is covered.
The popup could also stay up on its own on macOS: an enter event stopped its
close timer, and when the timer fired with the cursor inside it returned
without re-arming, so without a later leave event the popup never closed. On
macOS the timer now keeps running while the popup is shown and closes it once
the cursor is outside. The popup also stops and frees its timer when destroyed.
The Slice-plate hover popup (FilamentGroupPopup, a wxPopupTransientWindow)
takes the mouse capture while it is shown, and on macOS its OnIdle handler
reacquires that capture whenever the cursor sits outside the popup. If the
popup is still shown when the modal filament grouping dialog opens, wx routes
every dialog mouse event to the now-hidden popup, because WX_filterSendEvent
short-circuits to the capture window while GetCapture() is non-null. The
dialog's filament blocks never receive a mouse-down, so they can't be dragged
and the whole app looks frozen even though its modal loop is healthy and the
keyboard still works.
Dismiss the popup synchronously before the dialog opens: Dismiss() hides it
and releases the capture, and hiding it stops OnIdle from reacquiring. This is
a no-op where the popup is never shown (Linux, where the hover popup is
disabled, and any non-dual-nozzle printer).
46 files include the same header twice at file scope, outside any #if,
66 times in all:
Model.cpp included Model.hpp twice, Utils.hpp <algorithm> and
<string_view> twice, seven GUI headers <wx/dataview.h> and
<wx/artprov.h> twice. The second include of each is removed.
GCodeSender.cpp and GCodeSender.hpp have been commented out of
libslic3r/CMakeLists.txt since 2022 and their only two includes are
commented out as well. Both files go, with the commented lines, and
the CMake entry for SLA/SupportTreeIGL.cpp, a file that no longer
exists.
* Stop Leaking json Through Headers and Drop Includes Kept Only for the Name
AppConfig.hpp, DeviceManager.hpp and UserManager.hpp carried a global
"using namespace nlohmann;", json_diff.hpp a global "using json =
nlohmann::json;" and PrinterFileSystem.h a global "using nlohmann::json;".
Every file that included one of them, directly or not, could write a
bare json, and 63 did without declaring it.
The last two also made the include checker treat json_diff.hpp and
PrinterFileSystem.h as the headers that provide json, so they were
included from files that use nothing else from them: 57 of the 59
includers of json_diff.hpp never name json_diff.
The five statements are removed. Headers that use the type now spell
nlohmann::json, source files declare their own "using json =
nlohmann::json;", and the includes that only supplied the name are
dropped or replaced by <nlohmann/json.hpp>.
Eight files reached json_diff.hpp only through an include that is now
gone and with it lost that header's "using namespace std;". The std
names they used unqualified are qualified.
* Declare json in OrcaSlicer.cpp on Every Platform
OrcaSlicer.cpp had its "using namespace nlohmann;" and the json include
inside the Linux-only include block, so on Windows and macOS it took
json from AppConfig.hpp's global directive, which is gone. The include
and a "using json = nlohmann::json;" now sit outside the block.
* Remove Unused Project Includes and Forward-Declare Where a Type Is Only Referenced
Generated with include-what-you-use and applied conservatively. Only OrcaSlicer's own headers, the ones under src/ and tests/, are removed or forward-declared; standard-library and third-party includes are left alone. An include is removed only when both the Release and the Debug configuration leave it unused, never from inside a conditional block, and never from a file with platform-specific blocks, which only gain includes. Files whose only use of a header sits behind a feature or debug macro (libvgcode's OpenGL ES and marker code, the ARACHNE/TESTS_EXPORT_SVGS debug output) keep their includes.
clonable_ptr.hpp gains #pragma once; it had no include guard and was only safe while Config.hpp was its sole includer.
* Remove Unused Project Includes From Files With Platform-Specific Code
A Linux include-what-you-use run cannot see the code inside _WIN32, __APPLE__ or __linux__ blocks, so its verdict is only taken where nothing the removed header declares, directly or through what it includes, is named inside those blocks. Removals also have to hold in both the Release and Debug configuration and never touch a line inside a conditional block.
* Restore the libslic3r Precompiled Header and Direct Includes Lost in the Platform Pass
The platform-file pass treated pchheader.hpp as an ordinary header and
emptied it, and left GUI_Preview.hpp and 14 other files relying on
headers they no longer reached directly.
* Restore MainFrame.hpp in ParamsDialog.cpp for the Windows-Only Reparent Call
* Include Headers That Files Reached Through Ones the Cleanup Removed
* Drop Includes Duplicated by the Cleanup or by Main's Own Additions
* Leave PreciseSeam.cpp as Main Has It After the Precise Seam Rework
The sidebar can move to either side, float, be resized, and collapse with
the canvas button or Shift+Tab. Its layout is remembered separately from
Prepare's, starts where Prepare's sidebar is, and View > Reset Window
Layout resets both tabs.
Three commits: G-code export caches its filament config slot and repeated
option lookups, per-plate bed type overrides follow the printer's multi-bed
support, and the gizmo checkboxes and texture displacement panel get styling
and refresh fixes. No conflicts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Five commits: a section view for the 3D canvas, a faster G-code preview, user
preset values kept on extruder variants they don't list, debug build CMake
fixes, and a 30 minute timeout on macOS notarization.
Two conflicts, both in GLCanvas3D. The header's were neighboring
declarations, kept from both sides. In the transparent pass, the section view
removed the assemble view's painter block that followed our ghost render;
the ghost render stays where it was, at the end of that pass.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Seven commits: painted multi-material segmentation made deterministic, missing
includes added across src/slic3r/GUI, U1 high-flow nozzle variants, Windows
ARM64 build and HTTPS fixes, and a rule added to the wxWidgets agent skill.
Three conflicts, all include lists: upstream's include pass and ours each added
to the same lists in GCodeViewer.hpp, PartPlate.hpp and PartPlate.cpp. Resolved
as the union of both. Three includes both sides had added at different places,
which git kept twice, are kept once: Color.hpp and <set> in PartPlate.cpp,
<sstream> in Plater.cpp.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Add Missing Includes Across src/slic3r/GUI
Every GUI source and header now directly includes the headers declaring what it uses, rather than relying on the precompiled header or transitive includes. Generated with clang-tidy misc-include-cleaner, plus one hand edit making CalibrationPanel.hpp self-contained.
* Drop the OS-Specific Includes Added Outside Their Platform Guards
GLib, GTK, D-Bus and POSIX headers are only used inside platform #if blocks, which already include them. Added unconditionally at the top of the file they broke the Windows build.
* Add the clang-tidy Configuration That Generated These Includes
Only misc-include-cleaner's missing-include check, with the headers it must never suggest: per-platform, internal and OS-specific ones that would break other platforms or are not meant to be included directly.
* Match Windows Paths in the clang-tidy Ignore List
Header paths use backslashes on Windows, so every / in a pattern is now [/\\]. The Windows SDK headers are ignored alongside the other OS-specific ones, and the list is one pattern per line. Suggested by @raistlin7447 from a Windows clang-cl run.
Felix14-v2's review of OrcaSlicer#16019 found the tab behaving as a world of its own.
- Icons: the design_* glyphs were drawn in a fixed light grey, made for the dark ribbon, and the
toolbar re-tinted some of them by rebuilding the bitmap from a wxImage, which drops the HiDPI
scale factor Orca sets on Windows: at 150 % the icons came out half again too large for buttons
that were sized in raw pixels, overlapping and clipped. The glyphs now use Orca's sidebar icon
grey (#949494), which the icon cache maps per theme, nothing is re-tinted, toolbar glyphs drawn
for Prepare's light toolbar use their "_dark" twin, and every size is in DIP.
- Theme: the chrome colours were read once, at construction, and nothing in the tab answered a
theme switch, so switching left light surfaces and unreadable text in a dark tab and the other
way round. The colours are now {light, dark} token pairs; MainFrame::on_sys_color_changed
reaches DesignPanel::on_sys_color_changed, which moves every token colour onto the other
theme's, runs the app's dark pass and re-rasterises the icons. Card borders are StateColors,
resolved at paint time.
- Scale: MainFrame::on_dpi_changed reaches DesignPanel::msw_rescale, which re-rasterises every
icon (buttons, flyout rows, card headers, the tree's image list, now sized from its bitmaps)
and re-measures the Orca widgets.
- Mouse: the canvas no longer forces middle-drag to orbit and right-drag to pan; it reads the
drag actions in Preferences > Control like Prepare. Left-drag is shared with picking, so the
whole-body rubber band takes Shift+left-drag while left-drag is given to the camera.
- FPS counter: ImGui's display size is shared and only refreshed when a canvas sees its own
size change; the Design canvas now re-announces its size when the tab is entered (and the
editor canvas when it is left), as Plater does between Prepare and Preview.
- Viewport text: the status line and the tool readout were top-level popups over GL. A popup
does not follow its frame, so the empty-canvas hint floated over other applications, and the
readout was never taken down with the tab. Both are drawn by the canvas in the tool's ImGui
pass now, with the theme's overlay style.
- Dialogs: messages use MessageDialog/RichMessageDialog; Add/Edit Variable is one Orca dialog
with Name and Expression fields instead of two native text prompts; the Text dialog uses
TextInput, ComboBox and CheckBox (its height is a TextInput: SpinInput is integer-only), and
enumerates the installed fonts once per session. The ribbon's Confirm/Cancel, the reference
pick buttons and the expression buttons are Orca Buttons; the variable actions are icon
buttons like the other cards'.
- Undo: the tab's own Undo/Redo buttons are gone. The top bar's Undo/Redo drive the Design
history while the tab is shown, greyed to what an undo would do, as Ctrl+Z and Edit already
did.
- The first build of the tab logs how long each phase took ("Design tab build: ..."): it is
under a second here but was reported at about fifteen on Windows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QK4VgguuCAk2hZLWgcjJb9
Eleven commits, including a typed-config G-code export speedup, a printer agent
refactor that generalizes the infrastructure beyond Bambu, gyroid optimization,
and three CLI crash fixes.
One conflict, in PrintConfig.cpp. Upstream introduced a new_def macro and began
migrating the placeholder table onto it, adding curr_bed_type that way in the
same block where this branch had added imex_mode, imex_mode_index and
imex_mode_gcode in the older def = this->add(...) form. Both sides are kept and
ours are converted to the macro, which expands to the same three statements and
wraps label and tooltip in L() exactly as before, so nothing changes about what
is registered or what is translatable.
Note for anyone building this branch: the agent refactor adds a dependency,
LibDataChannel, so the deps tree needs dep_DataChannel built before the app will
configure. A distribution package of the same name will be found first if one is
installed, and the resulting error names a missing RelWithDebInfo location
rather than the wrong package, so point LibDataChannel_DIR at the dependency
prefix if that happens.
Verified: 789 targets build clean under -Werror, and the Release suite passes
1665 of 1665, up from 1630 before the merge -- the 35 new cases arrived with it
and all pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
main moved the CAD docs into docs/HLSD/design-tab.md and the offer
generator and atlas into scripts/CAD/ (#15803).
- The four docs this branch had edited are deleted as on main. What the
branch changes about the design goes into the HLSD doc: the right-click
is judged by drift over the whole press, with no time budget; a Text
feature stores its outlines as well as its string, font and height; a
new section on how the Design canvas renders bodies (studio lighting
through the shared phong shader, B-rep edge ribbons).
- gen_offer_table.py keeps both main's atlas validation and this
branch's L() markers on user-facing strings.
- The Text verb's hint is now changed in scripts/CAD/tool_atlas.json as
well, so `gen_offer_table.py --check` passes.
- DesignPanel.cpp keeps the DesignTextDialog include and main's new
path in the offer comment.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QK4VgguuCAk2hZLWgcjJb9
* Add developer flag for printer agents
* Parse user print info on the UI thread to prevent heap corruption (#119)
get_user_print_info()'s HTTP fetch can run on a worker thread (e.g. BindJob),
but parse_user_print_info() mutates userMachineList (insert/erase/delete
MachineObject). on_machine_alive (SSDP) mutates the same maps on the UI thread
without locking, so parsing off-thread races the map and frees MachineObjects
out from under it -> heap corruption.
Keep all device-list mutation on the UI thread: parse inline when already on
the main thread, otherwise marshal via CallAfter so it stays serialized with
on_machine_alive.
* Prevent loss of user access code on LAN reselect
Keep user access code intact to maintain access rights even if
device slot is unpopulated, ensuring continuous connection
and status message reception.
* Harden send flow and separate upload failure recovery (#111)
* fix(send): harden FT send path + IP pre-flight UX
* Remove early returns
* Working Moonraker and Qidi printer agent transport (#104)
Folds the Qidi AMS box-mapping print
overrides (apply_box_mapping +
start_* wrappers) that the transport
fix builds on.
* Add support for runtime error status in plugins
Distinguish a loaded plugin whose
capability errored (RuntimeError,
warn-styled, stays checked) from a
load-time Error. Status now derives
via resolve_plugin_status(); enum
ordinal keeps dialog sort priority.
Unloading clears stale errors.
* Resolve duplicate agent ID conflicts
Reject a printer-agent capability
whose agent ID is already owned by
another capability or built-in:
flag the plugin error, disable the
capability, and warn the user
instead of silently ignoring it.
* fix: checkbox should depend on plugin is_loaded status
* Replace fake-enum printer agent dropdown (#121)
A dedicated PrinterAgentChoice field
reads rows straight from the live
agent registry and stores the agent
id string, replacing the fake-coEnum
index mapping. The field moves to
TabPrinter and registers with the
searcher so UnsavedChanges renders
it; the PhysicalPrinterDialog copy
and its update hook are removed
(#125). switch_printer_agent now
resolves ids via
resolve_printer_agent_id.
* Reset device selection on agent swap or unload (#124)
set_live_printer_agent centralizes
the swap: deselect the machine,
clear stale sidebar state and the
previous agent's Other Devices, then
install the new agent (or null when
its provider vanished). Plugin
load/unload callbacks refresh the
dropdown and re-run agent selection.
load_last_machine no longer falls
back to the first available machine.
* Gate agent mode behind use_printer_agents toggle
Replace per-printer auto-activation
(is_current_printer_agent_plugin)
with a global experimental AppConfig
toggle, default off: legacy
print-host behavior is unchanged
until the user opts in. The toggle
drives device-tab routing, print
button defaults, connect-button
visibility and sidebar layout, and
dedups machine-select dialog opens.
* Track BBLPrinterAgentPlugin.py
* Add printer-agent and plugin status tests
Ports the agent lifecycle, duplicate
agent-id, built-in-id clash and
status-resolution tests. The loader
runs on a detached worker thread, so
the lifecycle tests live in their own
executable. Tests install the
production unload-side registry
wiring themselves (no GUI in the
test binary) and register agents
manually so concurrent loads stay
deterministic.
* fix: pin HTTP to prevent connection refusal
Set `use_ssl` to false to ensure Moonraker
connectivity, as the service uses HTTP rather
than HTTPS, preventing connection issues. Initialize
device info early for reliable name resolution.
* Bring Moonraker device panel to feature parity
The monitor panel showed wrong or missing
data for Moonraker printers, and its
controls did nothing.
Push payload now carries layer number and
total layers. Remaining time replaces the
wrong total_duration - print_duration
formula. The chamber light toggle maps to
Klipper SET_PIN / SET_LED, and pause,
resume and stop post to
/printer/print/{action}. Task thumbnails
resolve via /server/files/thumbnails onto
a new MachineObject thumbnail url.
Filament sync switches to pull mode so the
agent is queried on demand.
Not compiled or run.
* Stop blocking print on unreported nozzle data
* fix: make Klipper macro lamp control reliable
* Surface Moonraker webcams and gate unrunnable controls
* Keep Bambu AMS dialect out of the agent waist
M620 is Bambu firmware dialect, not a
neutral command. Composing it in
MachineObject let non-Bambu agents
(Moonraker/Klipper) forward it and
report success on firmware that
cannot run it.
Agents now own the dialect: the
default refusal on IPrinterAgent
returns not-supported so the UI
can say so; BBLPrinterAgent keeps
the byte-identical composition.
* Fix multi-color filament logic
Reuse color decoding across functions to improve
code readability and maintain consistency in
multi-color filament handling.
* Move Moonraker commands off the UI thread
Pause/resume/stop, g-code sends, temps, and
light ran synchronous HTTP on the UI thread,
freezing the app up to 10s per click on slow
or unreachable printers.
Run them on a single agent-owned FIFO worker
so g-code ordering is preserved, while command
translation stays synchronous so unsupported-
command dialogs still work.
Add a pending-disabled state to the pause,
resume, and abort buttons for Moonraker-family
printers: the icon only flips once the
WebSocket reports the real state, which also
rules out double-click races.
* Show Snapmaker U1 camera in Device tab
The U1 exposes no /server/webcams/list entry;
its camera only captures after an explicit
camera.start_monitor RPC, which the Moonraker
websocket executes unauthenticated but only
answers over MQTT - so the call is fire and
forget.
Start the camera when the camera view is
shown and renew every 300 s: the printer
retires the capture task at ~362 s and
stop_monitor is accepted but ineffective,
so teardown is simply to stop renewing.
Frames land in monitor.jpg as still JPEGs
(~2 fps at interval 0), so the webview loads
a local HTML wrapper that repolls with a
cache buster.
* fix: start stream when camera URL changes
* fix: stop Qidi slot parse throwing on null
* Keep printer-agent progress in sync
Keep the shared task progress aligned with agent
reports that lack Bambu cloud task identity.
Release the lazily allocated task during reset to
avoid leaks when machine objects reconnect.
* docs: document the printer-agent subsystem
* fix: merge access codes into one
* Reconcile implementation split with PR tip
* feat: abstract remaining gcode commands in devicemanager
* refactor: abstract bambu specific protocol to printer agent
* refactor: push bbl workflows to bbl printer agent
* remove unused
* fix: default impl
* fix callback error
* fix: remove redundant cache
* specify api for getting file transfer url
* revert file transfer abstraction
* fix: ams filament mapping workflow
* feat: update qidi to use subscription based filament sync mode
* fix: resolve stubgen byte header conflict
* fix: ams sync info and periodic ams sync via subscription workflow
* fix: skip filament sync dialog if filamentSyncMode is none
* feat: parse nozzle information for qidi and moonraker printer agents
* fix: extend access code requirements t 0, 8 or more characters.
* remove irrelevant docs
* fix: remove heavy includes from IPrinterAgent
* fix: defer filesystem and camera abstractions
* fix: remote do_fetch_filament_info from tests
* cleanup moonraker and snapmaker printer agents
* fix: access codes regression
* fix: tests
* fix: printer agent switching on preset change
* fix: remove unused variable
* fix: snapmaker U1 SelectMachineDialog blocking print
* fix: merge artifact
* fix: clear up some unrelated changes
* feat: connect to cloud printer and monitor
* feat: connect to cloud printer and monitor
* feat: generic camera stream support for http snapshot and rtsp
* fix: build & access code UI
* feat: generic camera stream support for http snapshot and rtsp
* fix: build & access code UI
* feat: connect to cloud printer and monitor
* feat: connect to cloud printer and monitor
* fix: build errors
* feat: camera via webrtc
* fix: build
* fix: cmake
* feat: remove frame assembler and change config to set protocol
* fix: orcaprinteragent refactor
* fix: LAN paths and camera stream
* feat: use ffmpeg to render http camera stream
* fix: make model_id/dev_type optional instead of blocking
* fix: connect via ip dialog
* feat: LAN impl for Orca Printer Agent
* fix: model_id resolution method for non bambu printers
* fix: ffmpeg http camera stream jittering due to incomplete frames
* fix: revert sdcard check
* feat: check printer storage status before sending
* fix: moonraker printer agent hang on printer power cut
* fix: shim layer for any compatibiliity changes
* fix: cloud printers were using the wrong MQTT endpoint
* feat: cloud download via HTTP
* temp: doc for intended change
* fix: warnings
* fix: warnings
* fix: camera auto-play on startup
* fix: split infra from impl
* fix: uninitialized ams state blocking print
* Fixes nullptr deref
* Log first before std::move
* fix: printer agent virutal optional functions
* fix: parameterize orcaslicer_copy_test_dlls() for printer_agent_plugin_tests
* Revert "fix: parameterize orcaslicer_copy_test_dlls() for printer_agent_plugin_tests"
This reverts commit 2f566e3779.
* Guard libdatachannel. Remove unused code
* fix: unit tests & unused variables
* fix(ci): deps build order for datachannel
* Resolve printer agent first before getting cloud printer agent
* fix(ci): set depends openssl
* fix: re-include apply header guarded by ifdef __APPLE__
* fix(ci): add libdatachannel to flatpak manifest
* fix: add internal_developer_mode chekc back to MediaPlayCtrl::load()
* fix: invoke js clearInterval on WebMediaController::stop
* fix: change rtc log level
* fix: inject provider, agent id and generation to get_user_print_info to ensure correct metadata
* fix: revert moonraker specific behavior
* fix: remove stale comment
* fix: use ORCA_CLOUD_PROVIDER instead of hardcoded string
* fix: remove hardcoded ICE servers
* feat: enable https camera stream mode
* fix: move non-mandatory printer agent function stubs to IPrinterAgent
* fix: dedupe compatible printer type check
* fix: stop the correct media controller
* fix: scope get_my_machine_list to printers listed under the current printer agent
* fix: move printer agent plugin tests into test_plugin_lifecycle.cpp
* fix: always build bundled DataChannel dep
* fix: disable unused DataChannel media support
* revert: filament sync work
* fix: wrap command_* with small wrapper
* fix: regression bug, connecting to bambu needs bblp username
* fix: default impl for vendor agnostic gcode commansd
* refactor: media controller playback routing and ownership
* fix: bump libdatachannel ver & update flatpak to use tar instead
* fix: stop flatpak DataChannel build from re-cloning over the sandboxed network
* fix: update windows ffmpeg prebuild
* fix: update printer agent plugin API
* fix: shift camera signaling channel to network agent
* fix: follow external-packages for flatpak libdatachannel deps & add flatpak path to use source_dir
* feat: add printer-agent.md doc to HLSD
* fix: guard DeviceManager command dispatch when no printer agent is bound
* fix: port BBL implementations from #15711
* refactor: connect_printer api and dialog
* fix(tests): make omitted printer agent operations answer like a missing agent
* fix: preserve printer agent defaults in PrinterAgentPluginCapabilityTrampoline
* test: cover printer agent default command dispatch
* fix: validate windows FFmpeg avformat library
* feat: extend optional printer model warnings to calibration & ams workflows
* fix: handle malformed printer progress values safely
* fix: clear webview document on stop
* chore: reduce diagnostic logging level to trace
* refactor: centralize printer compatibility checks
* tests: add device manager integration coverage
* tests: cover WebMediaController lifecycle with wxWebView stub
* fix: make integration tests headless
* refactor: collapse command_ams_refresh_rfid and command_ams_refresh_rfid2
* refactor: make printer connection SSL agent-specific
* fix: persist input printer host and port
* fix: use correct device id for Moonraker connections
* fix: make moonraker gcode commands asynchronous
* fix: preserve moonraker device names
* fix: add include for non BBL_RELEASE_TO_PUBLIC path in BBLPrinterAgent
---------
Co-authored-by: Andrew <159703254+andrewsoonqn@users.noreply.github.com>
Co-authored-by: SoftFever <softfeverever@gmail.com>
Co-authored-by: Lam Wei Lun <weilun.lam@gmail.com>
Keyboard and mouse
- Esc drops what is pending (picks, a dimension's first point, an edit-op or transform) and
never applies it; Enter applies a ready edit-op/transform, ends a polyline/spline chain,
ends an armed tool, and confirms a feature card exactly when its ✓ is enabled.
- Right-click only abandons the gesture in progress; with nothing pending it opens the offer
in every tool (Trim, edit-ops, transforms, Dimension, Constrain, TransformArt, move gizmo).
Clicking empty space no longer commits. The offer needs no timing, only a still press.
- Delete removes only an explicit selection. Undo/redo inside a sketch go through the same
route as the buttons (whole shapes, with redo); Edit > Undo follows the shown tab.
- The canvas no longer handles Delete/Esc/Ctrl+Z itself (Backspace in a value field deleted
the geometry it measured); F is in the panel's key map.
- Value fields: a refused value keeps the field open with the reason; click outside and Tab
commit; an untouched field commits the exact value; any decimal separator is accepted;
lengths are always mm; validation is the same for every editor.
- Snapping: the marker shows only where the click will actually snap; pick tolerances are
one set of pixel budgets (Constrain picks within reach; no mm floor on labels).
Messages and consistency
- set_status(kind, text) gives every status line its own colour and glyph; kernel errors are
translated into sentences and formatted, not concatenated; sketch refusals go to the status
line instead of the per-frame HUD that erased them.
- Hints describe the gestures that now work; Dimension shows its second step; Constrain uses
the sketch palette (red means conflict only); the straight slot's value is its width.
- Hole/Thread/Project keep the user's pick or refuse up front; circular pattern opens with its
own preview; thread fields use the nominal diameter and the ISO internal depth.
Integration
- MCP loads the project's recipe before touching the document, refuses to mutate it while the
tab is busy, never runs a request that already timed out, only replaces a socket at its
path, caps line length and removes the socket at exit; not started in the G-code viewer.
- Hiding a feature keeps later body references on their bodies; a design keeps its modeling
origin across printer changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QK4VgguuCAk2hZLWgcjJb9
Upstream moved pressure advance onto the extruder variant: enable_pressure_advance,
pressure_advance and the four adaptive keys joined filament_options_with_variant,
the repeated inline blocks in set_extruder() became a helper, and the lookups
moved from the filament id to get_filament_config_index().
All three conflicts were the same collision, because this branch had modified two
of those same inline blocks to pass a tool qualifier so each carriage is addressed
explicitly in parallel modes. Taking either side whole would have lost something:
upstream's drops the qualifier and leaves parallel carriages with no pressure
advance, ours drops the per-variant indexing and reads the wrong column on a
multi-variant printer. The helper now takes an optional tool, defaulting to -1,
which omits the qualifier. imex_pem_tool_for() already returns -1 off IMEX and in
primary mode, so non-IMEX output is unchanged, and the three call sites that never
passed a tool keep upstream's behavior exactly.
The third conflict was two test cases appended at the same place. Both are kept.
Separately, one defect that merged cleanly and so was not flagged: the loop that
emits pressure advance for secondary carriages at the start of a print still
bounded and indexed those vectors with a raw filament id. They are variant
expanded now, so their length is columns rather than filament slots -- the value
read was the wrong column, and the bound no longer sat in slot space, letting an
out-of-slot filament through. It now bounds on filament_diameter and translates
with get_filament_config_index(), which is what the sibling second-layer
temperature loop already does.
Verified: both changed translation units compile clean under -Werror. The merge
was resolved independently twice and the two resolutions agree on every line of
code. Not yet run: the Release test suite and a parallel-mode slice sweep.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The two conflicts are both places where upstream landed on top of IDEX/IQEX
code. In GCode.cpp the relocated file header block meets the IMEX placeholder
block, and the placeholders are set first: file_start_gcode is processed through
the placeholder parser now, which throws on a name it does not know, so a script
naming {imex_mode} would abort the export if the header ran first. In
test_multifilament.cpp both sides appended a case at the end of the file.
orca.host.ui.create_dock_panel(html, title, width, height, on_message,
on_close, dock) hosts plugin HTML in a pane of the Plater's dock manager,
next to the sidebar, and returns a UiDockPanel handle
(post/show/hide/close/is_open). The arguments follow create_window(). The
panel uses the window.orca bridge of plugin windows, restores its position
and size from the saved window layout, hides with the Plater off the Prepare
and Preview tabs when floating, and is closed with its plugin; plugin panes
are removed in MainFrame::shutdown().
The web view hosting moves out of PluginPage into a shared WebPanel base:
bootstrap page and swap to the plugin HTML, theme, element-default and
bridge scripts, window.orca message parsing, delivery to the page, and live
re-theming, also re-applied on every load after the swap. Pages tabs and
docked panels both derive from it. Pages tabs now re-theme in place on a
theme change instead of being reloaded, and a window.orca call a host does
not support is logged.
What the hosts share no longer lives in one of them: the bootstrap page, the
base URL and the plugin-window bridge move to Widgets/WebHosting, used by
WebDialog and WebPanel alike. The Plater restores plugin panes with a new
saved-layout parser, GUI/AuiPaneLayout, kept in its own small header so
slic3rutils can test it without pulling in the Plater.
The web hosting classes carry no plugin name, so other hosts can reuse them:
PluginWebDialog becomes WebDialog (its bootstrap page moves to
resources/web/dialog/WebDialog), and destroy_for_plugin(),
load_plugin_content() and plugin_defaults_user_script() become
destroy_silently(), load_page_html() and element_defaults_user_script().
Includes a sample plugin (sandboxes/orca_dock_panel_plugin_any.py) and
binding and layout-helper tests in slic3rutils.
* build: clear 2 warnings - cast the NSTextField the class check already proved
mainframe_text_field is NSTextField* and was assigned a bare NSView*, which
Clang reports as -Wincompatible-pointer-types. Both assignments sit inside
if ([viewObject class] == [NSTextField self]), so the runtime type is already
guaranteed, and the line above the second one casts the same variable the same
way to call setTextColor. macOS only, since nothing else compiles this file.
* build: clear 6 warning categories from the clang-cl inventory
-Wmissing-braces (9). Aggregates whose first member is itself an aggregate.
GUID's fourth member is BYTE[8], so the trailing eight bytes take their own
braces. The others were reaching for zero-initialization with {0} and say {}
now. bbs_3mf's backup Task ends in an anonymous union, which needs braces of
its own; those braces initialize the union's first member rather than the one
named at the call site, so the RemoveBackup site says so in a comment.
-Wmacro-redefined (11). SendMultiMachinePage.hpp defines five names that
Preferences.hpp, PresetBundleDialog.hpp, ExportPresetBundleDialog.hpp and
TroubleshootDialog.hpp also define with different values, so the value in
force depended on include order. All nine of this file's DESIGN_ macros take
the SEND_ prefix it already uses for its own macros, values unchanged, so a
DESIGN_ name added elsewhere later cannot collide with it again. They read as
one page-local palette, a 900 to 400 gray ramp plus sizes, so the four with
no current readers stay: dropping them would leave gaps in a named scale. test_marchingsquares.cpp defines NOMINMAX,
which libslic3r already passes as a PUBLIC compile definition, so it takes
the #ifndef guard the other suites use.
-Wbraced-scalar-init (3). Two PushStyleVar calls resolve to the float
overload, so the braces were initializing a scalar. ConfigOptionFloatsNullable
already takes an initializer_list, so the inner braces did the same thing.
-Wmicrosoft-goto (2). Both gotos in copy_file_gui jump forward over the
initialization of size, dwRead and dwWrite, which only MSVC accepts. Those
declarations move up to join the others at the top of the function.
-Wunused-private-field (3). Every use of ColourPicker's m_clrData and
m_picker_widget is behind !defined(__linux__), so on Linux they are written
and never read; the members now carry the same guard. ParamsPanel's
m_size_move is read nowhere. Tab has its own, which is the one Tab.cpp uses.
-Wnonportable-include-path (2). BaseException.h asked for "stackwalker.h"
and the file on disk is StackWalker.h.