From a5b2600b2cc12bb3b1409df2be7036ba22459268 Mon Sep 17 00:00:00 2001 From: Clifford Garwood Date: Sat, 22 Aug 2026 00:27:57 -0400 Subject: [PATCH] fix(imex): re-register the IMEX mode icon's bed raycaster after rebuilding it SceneRaycasterItem keeps the MeshRaycaster it was registered with as a raw pointer, while PickingModel::reset() destroys it through a unique_ptr. Rebuilding an icon therefore invalidates any registration still referring to it. refresh_imex_icon(), reached only from Plater::on_config_change when is_imex or the bed shape changes, rebuilt the IMEX mode icon without touching the SceneRaycaster. The stale entry survived, and the next picking pass dereferenced freed memory inside AABBMesh::intersect_ray. Swap that one registration in place, matching how calc_vertex_for_plate_name() handles the name-edit icon. Only the mode icon is registered for picking -- the warning badge beside it is a plain GLModel -- so a single id is affected and the blanket remove/re-register reload_scene() performs is not needed here. Crashes were delayed and looked unrelated to the config change, because bed raycasters are only tested when the camera looks down (SceneRaycaster::hit). The reported dump landed on File > New Project, whose render ran a picking pass with a registration that had gone stale earlier. Co-Authored-By: Claude Opus 5 (1M context) --- src/slic3r/GUI/PartPlate.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 8dece5360b..46215b2d87 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -1025,6 +1025,8 @@ std::string PartPlate::build_imex_cache_key() const } // Reposition the IMEX mode icon without requiring a full set_shape() rebuild. +static void register_model_for_picking(GLCanvas3D &canvas, PickingModel &model, int id); + // Called when is_imex is toggled on a printer whose bed shape matches the current plate, // which would otherwise cause set_shape() to short-circuit before reaching icon calc. void PartPlate::refresh_imex_icon() @@ -1038,6 +1040,15 @@ void PartPlate::refresh_imex_icon() int imex_slot = dual_bbl ? 7 : 6; calc_vertex_for_icons(imex_slot, m_imex_mode_icon); calc_vertex_for_imex_warn_badge(imex_slot, m_imex_warn_icon); + + // calc_vertex_for_icons() destroyed the MeshRaycaster that SceneRaycaster still + // holds by raw pointer; swap the registration as calc_vertex_for_plate_name() does. + // Only the mode icon is picked -- the warn badge is a plain GLModel. + if (GLCanvas3D *canvas = m_plater->get_view3D_canvas3D()) { + canvas->remove_raycasters_for_picking(SceneRaycaster::EType::Bed, + picking_id_component(PLATE_IMEX_MODE_ID)); + register_model_for_picking(*canvas, m_imex_mode_icon, picking_id_component(PLATE_IMEX_MODE_ID)); + } } }