Fix #136563: Crash clicking on a light after it has been deleted

Failure to refresh the highlighted gizmo meant that clicking
on a highlighted gizmo would attempt to activate it even though
it's poll function failed - which crashed in this case.

Resolve the common-case by ensuring a call to refresh the gizmo-map
causes the event system to re-evaluate the highlighted gizmo,
even if the cursor doesn't move.

Since it's still possible the call to "refresh" the gizmo is missed,
gizmo_tweak_invoke now checks the gizmo-groups poll succeeds with an
assert and early return if it doesn't. This would have prevented the
crash although the highlighted-gizmo still won't be reset - causing
the cursor to display as if it's over a gizmo until it's moved.
This commit is contained in:
Campbell Barton
2025-04-09 11:21:55 +00:00
parent ff85c97278
commit 82a37e143f
5 changed files with 37 additions and 2 deletions

View File

@@ -572,8 +572,16 @@ static wmOperatorStatus gizmo_tweak_invoke(bContext *C, wmOperator *op, const wm
if (!gz) {
/* #wm_handlers_do_intern shouldn't let this happen. */
BLI_assert_unreachable();
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
BLI_assert_msg(false, "the gizmo should never be null, this is a bug!");
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
}
if (!WM_gizmo_group_type_poll(C, gz->parent_gzgroup->type)) {
/* The event-system should prevent this from happening, see: #137146.
* May be caused by the context changing without tagging #wmGizmoMap::tag_highlight_pending,
* typically via #WM_gizmomap_tag_refresh. */
BLI_assert_msg(false, "the gizmo-group's poll should always succeed, this is a bug!");
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
}
const int highlight_part_init = gz->highlight_part;

View File

@@ -107,6 +107,9 @@ struct wmGizmoMap {
/** When set, one of the items in 'groups' has #wmGizmoGroup.tag_remove set. */
bool tag_remove_group;
/** When set, the event system re-calculates highlight even without cursor motion. */
bool tag_highlight_pending;
/**
* \brief Gizmo map runtime context
*

View File

@@ -314,6 +314,9 @@ void WM_gizmomap_tag_refresh_drawstep(wmGizmoMap *gzmap, const eWM_GizmoFlagMapD
BLI_assert(uint(drawstep) < WM_GIZMOMAP_DRAWSTEP_MAX);
if (gzmap) {
gzmap->update_flag[drawstep] |= (GIZMOMAP_IS_PREPARE_DRAW | GIZMOMAP_IS_REFRESH_CALLBACK);
/* This could be split out into a separate tagging function,
* in practice both when refreshing the highlight should also be updated. */
gzmap->tag_highlight_pending = true;
}
}
@@ -323,6 +326,8 @@ void WM_gizmomap_tag_refresh(wmGizmoMap *gzmap)
for (int i = 0; i < WM_GIZMOMAP_DRAWSTEP_MAX; i++) {
gzmap->update_flag[i] |= (GIZMOMAP_IS_PREPARE_DRAW | GIZMOMAP_IS_REFRESH_CALLBACK);
}
/* See code-comment for #WM_gizmomap_tag_refresh_drawstep. */
gzmap->tag_highlight_pending = true;
}
}
@@ -739,6 +744,15 @@ static wmGizmo *gizmo_find_intersected_3d(bContext *C,
return result;
}
bool wm_gizmomap_highlight_pending(const wmGizmoMap *gzmap)
{
return gzmap->tag_highlight_pending;
}
bool wm_gizmomap_highlight_handled(wmGizmoMap *gzmap)
{
return gzmap->tag_highlight_pending = false;
}
wmGizmo *wm_gizmomap_highlight_find(wmGizmoMap *gzmap,
bContext *C,
const wmEvent *event,

View File

@@ -78,6 +78,8 @@ void wm_gizmomaps_handled_modal_update(bContext *C, wmEvent *event, wmEventHandl
void wm_gizmomap_handler_context_op(bContext *C, wmEventHandler_Op *handler);
void wm_gizmomap_handler_context_gizmo(bContext *C, wmEventHandler_Gizmo *handler);
bool wm_gizmomap_highlight_pending(const wmGizmoMap *gzmap);
bool wm_gizmomap_highlight_handled(wmGizmoMap *gzmap);
/**
* Try to find a gizmo under the mouse position. 2D intersections have priority over
* 3D ones (could check for smallest screen-space distance but not needed right now).

View File

@@ -3270,6 +3270,12 @@ static eHandlerActionFlag wm_handlers_do_gizmo_handler(bContext *C,
}
}
if (prev.gz_modal == nullptr) {
if (handle_highlight == false && wm_gizmomap_highlight_pending(gzmap)) {
handle_highlight = true;
}
}
if (handle_highlight) {
int part = -1;
gz = wm_gizmomap_highlight_find(gzmap, C, event, &part);
@@ -3288,6 +3294,8 @@ static eHandlerActionFlag wm_handlers_do_gizmo_handler(bContext *C,
}
}
}
wm_gizmomap_highlight_handled(gzmap);
}
/* Don't use from now on. */