Repository navigation
Conversation
The GL-free half of the Showcase tab (design: tests/design_showcase_tab.md, owner-approved D1-D17 with the D12 branding watermark): - libslic3r/Showcase/ShowcaseScene: per-plate scenes (background, floor, world-fixed light, camera and saved views, export settings, watermark), the three S1 presets, scenes.json with unknown-key preservation and a read-only path for newer schemas, content-hashed images, the export plan (SSAA/MSAA, 8192 cap, 1 GB budget, SSAO radius scale), the safe frame, the watermark layout and the CPU image helpers. - Model::showcase, a plain value member (no object id, not in undo/redo). - 3MF: Metadata/showcase/scenes.json and Metadata/showcase/<sha256>.png|jpg in project saves and backups; left out of Export Bambu 3MF and of sliced-plate files. A damaged file opens the project without scenes. - RealisticRenderSettings: the realistic-view switches as one value, read from the app config exactly as GLCanvas3D did. - tests/libslic3r/test_showcase_scene.cpp. Deft
GLCanvas3D's realistic-view checks (_is_realistic_view_enabled, shadows, SSAO, Phong) now read RealisticRenderSettings: the preferences, exactly as before, unless a caller hands the canvas its own copy. That is what lets the Showcase canvas render with its own switches without touching the user's viewport preferences (design R2). The struct also carries what only Showcase changes, each defaulting to today's behaviour: a world-fixed key light (shadow map and phong's key light), the shadow intensity (0.35), the shadow map size (2048), the shadow fit box, plate-shadow on/off, and the SSAO radius scale and alpha handling (new optional uniforms in the 140 phong.fs / ssao.fs whose GLSL defaults reproduce the old output). Prepare and Preview are unchanged. Deft
Design D1 / risk R1. The tab positions now come from MainTabs.hpp (no wx, unit tested): Showcase is 3, Device and every tab after it moved up by one. The audit of every TabPosition use found nothing that compares or stores tab numbers; what needed changing: - MainFrame::update_layout inserts the plater a third time, as Showcase (new tab_showcase_active.svg in the tab icon style), and the layout reset removes every plater page. - The Device page is inserted at device_page_position(): tpMonitor once the plater pages are in, right after Home before that. - The page-changed handler posts EVT_GLVIEWTOOLBAR_SHOWCASE for the new tab, and Preview is re-selected from Showcase as from Prepare. - select_tab(m_plater) does not leave Showcase for Prepare (as for Preview). - Ctrl+1..4 on a settings field still open Home, Prepare, Preview and Device (they used raw indices, so Ctrl+4 would have opened Showcase). - sw_SwitchTab knows "Showcase". - tests/slic3rutils/main_tabs_tests.cpp. Deft
The Showcase tab (design tests/design_showcase_tab.md, phase S1): - ShowcaseView: the plater's third page, a GLCanvas3D of its own (CanvasShowcase, hosted like AssembleView) and a side panel: plate, look preset, hide plate / prime tower, background (solid, vertical or radial gradient, image fill/fit/tile, transparent), floor (shadow only, solid, grid), world-fixed key light (direction, height, shadows, darkness, ambient occlusion), camera (projection, frame model, saved views), export (size presets or custom up to 8192, Draft/High/Best, PNG/JPEG, copy to clipboard) and the D12 watermark (logo and/or text, position, size, opacity, margin, font, colour, reusable presets in <data dir>/showcase/watermarks.json; off by default). - ShowcaseRenderer (a friend of GLCanvas3D): one drawing function for the live view and the export - backdrop, the plate or a faded floor disc, the shadow map with the scene's world-fixed light (D14), the plate's objects through phong, SSAO. The export renders the live safe frame into an off-screen framebuffer with supersampling and MSAA, a 1 GB budget and logged fallbacks, resolves before SSAO (radius scaled to the export) and reads back; transparent exports keep their alpha. - Two optional core-profile shaders (showcase_background, showcase_floor); without them the tab draws the plain gradient and no floor. - GLCanvas3D: the Showcase canvas renders through the renderer, takes only camera keys, and leaves the warnings to Prepare's canvas. - Plater: the view in the panel list, camera hand-over on enter/leave (the editing camera and the perspective preference come back as they were), the sidebar hidden in Showcase, scenes cleared on a new project, copied on open and shifted when a plate is deleted. Prepare and Preview are unchanged: every new branch is keyed on the Showcase canvas or panel. Deft
D3: the assets of the Showcase lighting and floors, all CC0 1.0, with their sources, licence and processing in a README next to them (2.6 MB in all): - resources/textures/showcase/environments: six Poly Haven HDRIs (studio, workshop, dark studio, outdoor, overcast, sunset), each baked into a 768x248 RGBM atlas - a cube map with five GGX-prefiltered roughness levels - and nine SH coefficients for the diffuse light in environments.json. Pre-filtered offline, so the app needs no HDR decoder, compute shader or runtime prefilter (GL 3.2 / Mac 4.1 core). - resources/textures/showcase/floors: six ambientCG colour maps (oak, walnut, concrete, marble, linen, slate), 1024 px tileable JPEGs with their real-world tile size and a roughness in floors.json. - scripts/showcase/bake_showcase_assets.py: the bake (no downloads; the source URLs are listed in it), with --verify and --preview. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GyZMaDcPGxnKdWv5zzccoC Deft
The GL-free half of Showcase phase S2 (design tests/design_showcase_tab.md): - ShowcaseMaterial: the filament finish inferred from the preset name and filament_type (D4, whole words, no new profile key), the per-finish material parameters, colour temperature, and the layer-line maths (layer tables from generate_object_layers, the uniform shortcut, the fade below ~1.5 px a layer that the shader mirrors). - ShowcaseScene: schema 2. Key brightness and colour, fill and rim around the world-fixed key (D14), the lights panel's setups, the bundled environment with brightness/rotation, exposure, shadow softness; backdrop blur and an Environment backdrop; photo and picture floors, glossy reflection, contact shadow; per-filament finish overrides and layer lines; WebP; "use as project cover" (D10, off by default). Presets Desk wood and Outdoor join S1's three. Schema 1 files read with the new defaults; an S1 build opens schema 2 read-only. - ShowcaseAssets: the bundled environment and floor manifests, the environment atlas layout, RGBM and SH helpers. - ShowcaseWebP: a lossless WebP (VP8L) encoder, as the deps have no libwebp; checked bit-exact against libwebp's decoder. - tests: test_showcase_materials.cpp and S2 3MF round trips. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GyZMaDcPGxnKdWv5zzccoC Deft
…loors The Showcase renderer for phase S2. Every path is the Showcase canvas' own; phong, ssao and GLCanvas3D are unchanged, so Prepare and Preview draw exactly as before. - showcase_material (optional, 140 core): GGX + Lambert in linear light per filament finish (anisotropic silk, clear coat, tinted metal, fibre speckle, translucency sorted per volume, D15), key/fill/rim fixed in the world with the key's shadow map, image-based light from a bundled pre-filtered cube map (SH diffuse, split-sum specular, no LUT, no compute), procedural layer lines at the object's real layer heights that fade out under ~1.5 px a layer, PBR Neutral tone map. Without the shader the objects go through phong as in S1. - Each painted colour of an MMU volume renders with its filament's finish. - Floor: photo textures and user pictures tiled in mm, a planar mirror pass (half size, mipmapped by roughness) and a contact shadow from a blurred top-down footprint (showcase_contact + showcase_blur, optional) that a shadow catcher keeps as alpha in transparent exports. - Backdrop: the environment through the camera, and image blur. - ShowcaseTextures: manifests, atlas and picture uploads, the project's filament slots. Samplers each on their own unit (macOS). - Export-size buffers are freed after each export. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GyZMaDcPGxnKdWv5zzccoC Deft
ShowcaseView for phase S2: - Lighting: setup (three-point arrangements), key brightness and colour, fill and rim, shadow softness, environment with brightness and rotation, exposure. - Materials: layer lines (Off / Subtle / Real / Exaggerated) and one row per filament - swatch, preset, "Auto: <inferred finish>" or an override, rebuilt when the filaments change. - Floor: Photo (bundled textures) and My picture, tile size, reflection, contact shadow. Background: Environment, blur. - Export: WebP (lossless) and "Use as project cover" (D10, opt-in): the export, centre-cropped to 240 px, becomes the auxiliary thumbnail_3mf.png the project saves as its cover. - The layer lines are worked out again on entering the tab and on reload. - New strings use _L(); ShowcaseTextures.cpp is in the gettext list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GyZMaDcPGxnKdWv5zzccoC Deft
When the Showcase view first drew, macOS printed once: "unit 1
GLD_TEXTURE_INDEX_CUBE_MAP is unloadable and bound to sampler type
(Float) - using zero texture". showcase_background and
showcase_material both declare samplerCube env_map, parked on unit 6
by GLShadersManager, but the renderer binds the environment cube there
only when one is in use: background mode 5, or a scene with an
environment for the materials. Every other draw (a colour, gradient,
picture or transparent backdrop, the "None" environment, or before an
environment loads) ran with texture 0 on that unit's cube target, an
incomplete texture. Nothing looked wrong because those paths never
take the branch that samples env_map, and the driver logs it once.
("Unit 1" is the driver's own index of env_map among each program's
samplers, not GL unit 1.) The cube upload itself is complete: every
level up to GL_TEXTURE_MAX_LEVEL is uploaded at the right size.
The 1x1 fallback textures that start_using() binds on parked units
covered 2D and 3D only. Map the cube sampler types to
GL_TEXTURE_CUBE_MAP and add a 1x1 opaque black fallback cube (black
decodes to no light, i.e. "no environment"), so env_map always has a
complete texture. The GL debug texture check now understands cube maps
too, so a regression shows in the log with the shader and sampler
name. The Showcase shaders exist only in the 140 set, so there is no
110 variant to change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deft
On macOS the Showcase options ran past the right edge of the side
panel, so the ends of sliders, choices and button rows were cut off
and could not be used, and the panel could not be made wider. The
panel was created as a wxScrolledWindow of wxSize(32 * em, -1) with
vertical scrolling only. That explicit width became the panel's
minimum size, which overrides its best size in the view's sizer, so
the panel stayed at exactly 32 em whatever its rows needed, and with
no horizontal scrolling anything wider was simply clipped. 32 em was
tuned on Windows; with the macOS system font and its wider native
controls (a 150 pt default slider, roomier pop-up buttons and push
buttons) the Light rows ("Environment brightness" plus a slider), the
Materials rows (a 14 em name plus the finish choice) and the camera
button row need more than that, and on a Mac with legacy scroll bars
the vertical bar takes another 15 pt out of it. Longer translations
hit the same wall on every platform.
Now fit_side_width() measures the panel's rows (the sizer's minimum
plus the vertical scroll bar) and makes the panel at least that wide,
at least the 32 em default, and at least what the user dragged it to,
leaving the canvas 24 em. It runs on construction, on every resize of
the view, after the materials rows are rebuilt, after the controls are
synced and after an export's status line changes. A sash on the
panel's left edge (the Plater sidebar's sash colours, a resize cursor)
widens it; double-clicking it fits the panel to its contents again.
The dragged width is kept in the app config in tenths of an em, so it
carries over between 100%, 150% and Retina displays. Where the window
is too narrow for both, the panel now scrolls sideways instead of
clipping. The lists of user-chosen names (plates, saved views,
watermark presets) and the watermark font button get a set 12 em
width, so a long name is cut short rather than widening the panel;
they still grow with it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deft
The core-profile GL test now checks the cube map fallback texture with the 2D and 3D ones, and that showcase_background and showcase_material see complete textures on every sampler, env_map's cube included, when nothing is bound on unit 6: the state that made macOS log "unit 1 GLD_TEXTURE_INDEX_CUBE_MAP is unloadable" on the first Showcase draw. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Deft
Showcase S2 (Mac): options panel fits its controls and can be widened; fallback cube map for env_map
A QIDI X-Max 4 / X-Plus 4 / Q2 with a QIDI Box ignored the sliced material: an ASA plate printed from the PLA left loaded by the last job, while bed, chamber and nozzle temperatures followed the ASA profile. The Box firmware feeds T<n> from the slot named by the saved variable value_t<n>. Nothing in the G-code sets it; QIDIStudio sends SAVE_VARIABLE enable_box / value_t<n> commands before every start (SelectMachine.cpp), and QIDI's own Moonraker does the same for cloud prints. EdgeSlicer sent nothing, so the printer reused stale slots. - PrintHostDeviceStatus: the Moonraker probe now also asks for multi_color_controller and reads the Box slots (type, colour, loaded) the way QIDIStudio's QDSDevice::updateBoxDataByJson does. - Send dialog: auto-match prefers a slot holding the plate filament's own material over a closer colour; for a QIDI Box it never falls back to colour alone. A note explains what "As sliced" means for the Box. - Upload queue: for a QIDI Box print, sends the mapping as SAVE_VARIABLE lines via /printer/gcode/script before the upload, and stops the send if the printer refuses it rather than print the wrong material. - Tests for the Box parsing and the generated script. Deft
Review fixes for the QIDI Box slot mapping: - The material-first auto-match applies to a QIDI Box only. Every other host that reports slots (U1, Elegoo CANVAS) keeps the nearest-colour rule exactly, colourless slots skipped. The rule moves into PrintHostDevices::auto_match_slot so the tests reach it. - Before the Box mapping goes out, the queue reads print_stats; a printer that is printing or paused (or does not say) gets nothing and the send stops with a clear error. The send dialog greys out "Upload and Print" for a busy QIDI Box printer. - value_t<n> is quoted exactly as QIDIStudio quotes it: VALUE="'slotN'". - The script target keeps a bracketed IPv6 address whole. - PrintHost.cpp is listed for gettext. - Tests: the nearest-colour rule for other hosts, the QIDI material rule, the busy states, the print_stats reply, the quoting, and a U1 is never a QIDI Box. Deft
…, polar cooler)
QIDI firmware keeps the last value it was given for each of these, and
QIDIStudio sends every one of them before a LAN start (SelectMachine.cpp).
EdgeSlicer sent none, so a print inherited the previous print's settings.
- Probe: a printer whose Moonraker answers multi_color_controller (Box or
not) is QIDI firmware; an `output_pin polar_cooler` object means it has
the polar cooler.
- Send dialog: for those printers, a "Print options" group:
* Use QIDI Box (only with a Box; on by default; off greys out the slot
table and sends enable_box=0 with no mapping)
* Auto bed leveling: G31 (probe a fresh mesh) / G32 (saved mesh)
* Timelapse: Moonraker's /machine/timelapse/settings?enabled=
* Polar cooler (only when present): SAVE_VARIABLE enable_polar_cooler
Leveling, timelapse and polar cooler are remembered between sends.
- Queue: the G-code options and Box mapping go out as one script before
the upload (a refusal stops the send, as before); the timelapse goes to
Moonraker separately and a refusal there only logs.
- PrintHostJob::qidi_box becomes qidi_start_script + qidi_timelapse.
- Tests for the detection and the generated script.
Deft
Review fixes for the QIDI print options: - Auto bed leveling starts off and remembers the person's choice. - G31/G32 is its own script call after the Box call. A refusal is logged and the print goes ahead; it never blocks the Box mapping or the print. The Box call keeps enable_box, the slot mapping and the polar cooler. - "Use QIDI Box" starts on only when the printer says a Box slot is loaded (PrintHostDevices::qidi_option_defaults). - The busy-printer guard covers every QIDI call (Box, leveling, timelapse), and "Upload and Print" is greyed out for any QIDI printer that is printing or paused. - The timelapse URL comes from PrinterStorage::base_url_of, so https and IPv6 addresses work. - The stray rebuild_qidi_options / update_mapping_enabled declarations on FlashforgePrintHostSendDialog are gone. - Tests: the split scripts, the option defaults (leveling off, Box only with a loaded slot, remembered choices), and a U1 or stock Klipper is never QIDI. Deft
Conflicts: the mapping auto-match takes the Elegoo dialog's preselect_slot first, then PrintHostDevices::auto_match_slot (QIDI material rules gated on qidi_box). Slot keeps one name field for both a QIDI Box slot and a CANVAS tray; label() reads CANVAS trays first. Status keeps canvas and qidi_box; the dialog keeps both sets of declarations. Deft
Brings in main through #610's merge. Conflicts: the dialog keeps the Elegoo preselect_slot / mapping_warning / update_mapping_note / mapping_choice_positions / plate_filament / m_mapping_note beside the QIDI rebuild_qidi_options / update_mapping_enabled / m_qidi_* members; Status keeps canvas beside qidi_box, qidi and qidi_polar_cooler. Deft
PrintHostDeviceStatus probes crealityprint hosts over the port-9999 boxsInfo WebSocket and fills the existing mapping table. The send dialog gains Use CFS and Calibrate before printing; start_print sends colorMatch then multiColorPrint when CFS is on. Auto-match prefers material, then CFS over the external spool. Co-authored-by: aceRage <aceRage@users.noreply.github.com>
…fs-send-d523 Carry the deadline-bound Creality WebSocket helper and preset model fallback into the CFS send path. start_print and query_boxes_info now use CrealityWsClient instead of synchronous Beast calls. Co-authored-by: aceRage <aceRage@users.noreply.github.com>
The send dialog probes on a worker and posts the result; Creality uses a
1 s deadline so a silent printer returns quickly. colorMatch ids now come
from the G-code filament index (T{idx/4+1}{A+idx%4}) with the mapped
box/slot as the destination. Auto-match stays Creality-only; other hosts
keep redmean. Hostile JSON range-checks doubles, caps at 1 MB, accepts
#RRGGBBAA, and skips colour-only picks that conflict on material.
Co-authored-by: aceRage <aceRage@users.noreply.github.com>
…fs-send-d523 # Conflicts: # tests/slic3rutils/printhost_devices_tests.cpp Co-authored-by: aceRage <aceRage@users.noreply.github.com>
… one socket Upload/Print stay off during "Checking printer..." so an early press cannot send an empty mapping (F16). The probe thread is joinable and the alive token is checked under a lock before CallAfter (F17). colorMatch retries and multiColorPrint share one WebSocket; a failed match is an error and does not send multiColorPrint (F19). Co-authored-by: aceRage <aceRage@users.noreply.github.com>
…fs-send-d523 Co-authored-by: aceRage <aceRage@users.noreply.github.com>
Match upstream Orca / Creality Print: write both commands, do not wait for a colorMatch reply (a timed read would cancel the stream). Write failure is still an error. Also disable the Elegoo Upload button while the probe is pending, drop the token lock before apply_device_status, and show a busy cursor around probe joins. Co-authored-by: aceRage <aceRage@users.noreply.github.com>
This was referenced Oct 19, 2026
#614 checked wxTheApp for null, but the theme and dark-mode tests install a plain wxApp; wxGetApp() then static_casts it to GUI_App and reads app_config from garbage. slic3rutils_tests still segfaulted in the GL thumbnail section whenever those tests ran first (they do on the Showcase branch). Deft
QIDI send: offer QIDIStudio's print options (Box, leveling, timelapse, polar cooler)
GLModel: read smooth normals only through a real GUI_App
Showcase S2: lighting, materials, layer lines
Release 2.4.6.2: version bump and notes
Elegoo CC upload now uses MaterialItem colour cards and a MappingItem slot popup instead of a text combo, while the start-print slot_map is unchanged. Other hosts keep the existing rows; Bambu and Snapmaker are not switched over. Co-authored-by: aceRage <aceRage@users.noreply.github.com>
Call the panel's DPI/theme handlers from the send dialog, use dark-mode colours only on the new badge and panel paths, add the panel to gettext, label Elegoo warnings with the same 1A-1D tiles, shrink the badge so long types still fit, number unit-less slots 1..N, and keep read-only auto-match visual while encoding an empty mapping. Co-authored-by: aceRage <aceRage@users.noreply.github.com>
update_mapping_note combines mapping_warning() and third_party_mismatch_warning(). Read-only mismatch compares T-number identity, not the visual auto-match. The nozzle badge pill follows Body_10 extent so labels like 10 fit. Co-authored-by: aceRage <aceRage@users.noreply.github.com>
…ity-cfs-send-d523 Adopt the shared Bambu-style filament map panel for CFS printers via use_third_party_map_panel(). Slots fill unit/tray as 1A-1D with colour and type; colorMatch reads mapping_choice_positions() and stays byte-identical to the old wxChoice loop. Conflicts in PrintHostDialogs and PrintHostDeviceStatus were resolved by keeping both Creality CFS and QIDI Box hooks. Co-authored-by: aceRage <aceRage@users.noreply.github.com>
cursor Bot
pushed a commit
that referenced
this pull request
Oct 19, 2026
…-sync-d523 Carry the shared Bambu-style filament map panel (#625 via #616) up the Creality stack. CFS sync has no send-dialog mapping of its own. Conflicts in printhost_devices_tests.cpp kept both the CFS sync preset-match cases and the color_match_from_positions identity test. Co-authored-by: aceRage <aceRage@users.noreply.github.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Depends on #625 (merge #625 first).
#625 adoption: CFS printers opt in with
use_third_party_map_panel(). Slots fillunit/trayas 1A–1D with the slot's colour and type (and the filament nozzle badge).colorMatchis built frommapping_choice_positions(), byte-identical to the oldwxChoiceloop.AddGrowableColis on the inner combo grid only. No CFSmapping_warning()override; F14 dropped the has_rows gate, and the empty base return is correct.Phase 2 of the Creality send-gap stack (research C3+C4, plus X3). This is the #610/#611 analogue for Creality: a CFS probe feeds EdgeSlicer’s existing send-dialog mapping table (no second dialog), and the start path sends
colorMatchthenmultiColorPrintwhen CFS is used.Stacked on Phase 1 (
cursor/creality-k1-k2-root-d523). Merge Phase 1 first; GitHub will then retarget this PR tomain.Does not affect Snapmaker printers. Needs a Creality K1/K2 hardware smoke (with and without CFS) before merge. Not a U1 check.
Review 1/3 (B1, B2, F3–F10)
CrealityWsClientgives the extra call a ~1 s hard deadline.colorMatchid isT{idx/4+1}{'A'+idx%4}from the G-code filament index. Destination box/slot are the mapped target fields.json_intrange-checks doubles before the int cast;parse_cfs_responserejects bodies over 1 MB.opGcodeFile+enableSelfTest.auto_match_slotis Creality/CFS only. Other hosts keep redmean.#RRGGBBAA(and 8 hex digits) strip alpha to#RRGGBB.probe()is aligned with the worker + post-back path.Re-review 1/3 (F16–F19; B3 via #618)
alive/genchecked under a mutex;CallAfterbails ifwxTheAppis gone.extendedInfo()and the B2 test both callcolor_match_value().colorMatchandmultiColorPrintshare one WebSocket.Re-review 2/3 (B4, F21–F23; B5 via #618)
CrealityPrint.cpp~414–434) and Creality Print. On the one shared socket: writecolorMatch, then writemultiColorPrint, fire-and-forget. Do not wait for acolorMatchreply. A timed read would cancel the Beast stream (B3); that would block the start or close the socket, so there is no inter-write read. The 5× retry loop is gone. A write failure is still an error.build_device_ui()and creates Upload later; it now appliesm_probe_pending/set_send_enabled(false)after that button exists (same as the base dialog).wxBusyCursoraround probejoin()in the destructor and before starting a new probe.CallAfterchecks the token under the lock, releases it, then walks windows and callsapply_device_status().Upstream sources
CrealityPrint::query_boxes_info,CrealityPrintAgent::parse_cfs_response,CrealityPrintHostSendDialog(colorMatch_n,enableSelfTest), TEXT WebSocket + heartbeat acks.sendToPrinterPage/deviceMgrJS: CFS on →colorMatchthenmultiColorPrint {gcode, enableSelfTest}; CFS off →opGcodeFile+enableSelfTest. Auto-match order: CFS type+colour > CFS type > ext type+colour > ext type.What was adapted
CrealityPrintHostSendDialog. Probe lives inPrintHostDeviceStatus. Slots fill the existing table.Use CFSandCalibrate before printingsit onPrintHostSendDialog. Both are remembered underrecent.extendedInfo()on the base dialog returnsuseCFS,enableSelfTest,colorMatch_nfor Creality hosts.printer_agentis still inert (X1).Expected conflicts
rebuild_mapping_rowsauto-match,PrintHostDeviceStatus.hppSlot/Status,printhost_devices_tests.cpp.PrintHostDialogs.hpp/.cpp(options panel,extendedInfo, destructor / probe token).can_probe(),probe(), tests. Merge by keeping bothif (host_type == …)arms.extendedInfooverride is unchanged.Untested
ThirdPartyFilamentMap.cppcompiled.Tests
Catch2 v2 in
printhost_devices_tests.cpp: sampleboxsInfo, variants, hostile JSON, auto-match,#RRGGBBAA, command shapes,color_match_value()(F18),color_match_from_positionsbyte-identical to the old wxChoice loop, 1A–1D unit/tray plus colour/type.Smoke checklist (Creality hardware)
opGcodeFile+/usr/data).colorMatchthenmultiColorPrinton one socket, no wait for a colorMatch ack. Use CFS off →opGcodeFile.opGcodeFile+enableSelfTest(F4).colorMatchmatches the previous combo choices.