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) <noreply@anthropic.com>
This commit is contained in:
Clifford Garwood
2026-08-22 12:37:28 -04:00
co-authored by Claude Opus 5
parent ef8d80980d
commit a5b2600b2c
+11
View File
@@ -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));
}
}
}