Fix T44011: Ruler/Knife/Loop-cut fail in quad-view
This is a kind of sloppy-focus, resolving long standing bug with loop-cut/knife/ruler /w quad-view. Where activating a tool would lock onto one of quad-views, especially problematic when activating from the toolbar or menus.
This commit is contained in:
parent
5df939fd15
commit
3f80accfb3
Notes:
blender-bot
2023-10-12 12:49:04 +02:00
Referenced by issue #44582, Using Ruler on Recent builds cause crash Referenced by issue #44011, Ruler/Protractor not working in Quad view
|
@ -280,6 +280,7 @@ void BKE_screen_area_free(struct ScrArea *sa);
|
|||
|
||||
struct ARegion *BKE_area_find_region_type(struct ScrArea *sa, int type);
|
||||
struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa);
|
||||
struct ARegion *BKE_area_find_region_xy(struct ScrArea *sa, const int regiontype, int x, int y);
|
||||
struct ScrArea *BKE_screen_find_area_from_space(struct bScreen *sc, struct SpaceLink *sl) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
|
||||
struct ScrArea *BKE_screen_find_big_area(struct bScreen *sc, const int spacetype, const short min);
|
||||
struct ScrArea *BKE_screen_find_area_xy(struct bScreen *sc, const int spacetype, int x, int y);
|
||||
|
|
|
@ -405,6 +405,23 @@ ARegion *BKE_area_find_region_active_win(ScrArea *sa)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ARegion *BKE_area_find_region_xy(ScrArea *sa, const int regiontype, int x, int y)
|
||||
{
|
||||
ARegion *ar_found = NULL;
|
||||
if (sa) {
|
||||
ARegion *ar;
|
||||
for (ar = sa->regionbase.first; ar; ar = ar->next) {
|
||||
if ((regiontype == RGN_TYPE_ANY) || (ar->regiontype == regiontype)) {
|
||||
if (BLI_rcti_isect_pt(&ar->winrct, x, y)) {
|
||||
ar_found = ar;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ar_found;
|
||||
}
|
||||
|
||||
/**
|
||||
* \note, ideally we can get the area from the context,
|
||||
* there are a few places however where this isn't practical.
|
||||
|
|
|
@ -3051,6 +3051,8 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
|
||||
knifetool_init(C, kcd, only_select, cut_through, true);
|
||||
|
||||
op->flag |= OP_IS_MODAL_CURSOR_REGION;
|
||||
|
||||
/* add a modal handler for this operator - handles loop selection */
|
||||
WM_cursor_modal_set(CTX_wm_window(C), BC_KNIFECURSOR);
|
||||
WM_event_add_modal_handler(C, op);
|
||||
|
@ -3143,6 +3145,9 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
em_setup_viewcontext(C, &kcd->vc);
|
||||
kcd->ar = kcd->vc.ar;
|
||||
|
||||
view3d_operator_needs_opengl(C);
|
||||
ED_view3d_init_mats_rv3d(obedit, kcd->vc.rv3d); /* needed to initialize clipping */
|
||||
|
||||
|
@ -3302,6 +3307,13 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
if (kcd->mode == MODE_DRAGGING) {
|
||||
op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
|
||||
}
|
||||
else {
|
||||
op->flag |= OP_IS_MODAL_CURSOR_REGION;
|
||||
}
|
||||
|
||||
if (do_refresh) {
|
||||
/* we don't really need to update mval,
|
||||
* but this happens to be the best way to refresh at the moment */
|
||||
|
|
|
@ -553,6 +553,7 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
|
||||
/* add a modal handler for this operator - handles loop selection */
|
||||
if (is_interactive) {
|
||||
op->flag |= OP_IS_MODAL_CURSOR_REGION;
|
||||
WM_event_add_modal_handler(C, op);
|
||||
}
|
||||
|
||||
|
@ -639,6 +640,9 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
bool show_cuts = false;
|
||||
const bool has_numinput = hasNumInput(&lcd->num);
|
||||
|
||||
em_setup_viewcontext(C, &lcd->vc);
|
||||
lcd->ar = lcd->vc.ar;
|
||||
|
||||
view3d_operator_needs_opengl(C);
|
||||
|
||||
/* using the keyboard to input the number of cuts */
|
||||
|
|
|
@ -187,6 +187,7 @@ typedef struct RulerInfo {
|
|||
|
||||
/* wm state */
|
||||
wmWindow *win;
|
||||
ScrArea *sa;
|
||||
ARegion *ar;
|
||||
void *draw_handle_pixel;
|
||||
} RulerInfo;
|
||||
|
@ -435,7 +436,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
|
|||
UnitSettings *unit = &scene->unit;
|
||||
RulerItem *ruler_item;
|
||||
RulerInfo *ruler_info = arg;
|
||||
RegionView3D *rv3d = ruler_info->ar->regiondata;
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
// ARegion *ar = ruler_info->ar;
|
||||
const float cap_size = 4.0f;
|
||||
const float bg_margin = 4.0f * U.pixelsize;
|
||||
|
@ -798,12 +799,14 @@ static int view3d_ruler_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
|
|||
op->customdata = ruler_info;
|
||||
|
||||
ruler_info->win = win;
|
||||
ruler_info->ar = ar;
|
||||
ruler_info->sa = sa;
|
||||
ruler_info->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ruler_info_draw_pixel,
|
||||
ruler_info, REGION_DRAW_POST_PIXEL);
|
||||
|
||||
view3d_ruler_header_update(sa);
|
||||
|
||||
op->flag |= OP_IS_MODAL_CURSOR_REGION;
|
||||
|
||||
WM_cursor_modal_set(win, BC_CROSSCURSOR);
|
||||
WM_event_add_modal_handler(C, op);
|
||||
|
||||
|
@ -829,11 +832,13 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
RegionView3D *rv3d = ar->regiondata;
|
||||
|
||||
/* its possible to change spaces while running the operator [#34894] */
|
||||
if (UNLIKELY(ar != CTX_wm_region(C))) {
|
||||
if (UNLIKELY(sa != ruler_info->sa)) {
|
||||
exit_code = OPERATOR_FINISHED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ruler_info->ar = ar;
|
||||
|
||||
switch (event->type) {
|
||||
case LEFTMOUSE:
|
||||
if (event->val == KM_RELEASE) {
|
||||
|
@ -1019,6 +1024,13 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
|
||||
}
|
||||
|
||||
if (ruler_info->state == RULER_STATE_DRAG) {
|
||||
op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
|
||||
}
|
||||
else {
|
||||
op->flag |= OP_IS_MODAL_CURSOR_REGION;
|
||||
}
|
||||
|
||||
if (do_draw) {
|
||||
view3d_ruler_header_update(sa);
|
||||
|
||||
|
|
|
@ -374,6 +374,8 @@ enum {
|
|||
RGN_TYPE_TOOL_PROPS = 6,
|
||||
RGN_TYPE_PREVIEW = 7
|
||||
};
|
||||
/* use for function args */
|
||||
#define RGN_TYPE_ANY -1
|
||||
|
||||
/* region alignment */
|
||||
#define RGN_ALIGN_NONE 0
|
||||
|
|
|
@ -390,10 +390,16 @@ enum {
|
|||
|
||||
/* wmOperator flag */
|
||||
enum {
|
||||
OP_IS_MODAL_GRAB_CURSOR = (1 << 0),
|
||||
/* low level flag so exec() operators can tell if they were invoked, use with care.
|
||||
* typically this shouldn't make any difference, but it rare cases its needed (see smooth-view) */
|
||||
OP_IS_INVOKE = (1 << 1),
|
||||
OP_IS_INVOKE = (1 << 0),
|
||||
|
||||
/* When the cursor is grabbed */
|
||||
OP_IS_MODAL_GRAB_CURSOR = (1 << 1),
|
||||
|
||||
/* allow modal operators to have the region under the cursor for their context
|
||||
* (the regiontype is maintained to prevent errors) */
|
||||
OP_IS_MODAL_CURSOR_REGION = (1 << 2),
|
||||
};
|
||||
|
||||
#endif /* __DNA_WINDOWMANAGER_TYPES_H__ */
|
||||
|
|
|
@ -1416,6 +1416,10 @@ static void rna_def_operator_options_runtime(BlenderRNA *brna)
|
|||
RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_INVOKE);
|
||||
RNA_def_property_ui_text(prop, "Invoke", "True when invoked (even if only the execute callbacks available)");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
prop = RNA_def_property(srna, "use_cursor_region", PROP_BOOLEAN, PROP_BOOLEAN);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_MODAL_CURSOR_REGION);
|
||||
RNA_def_property_ui_text(prop, "Focus Region", "Enable to use the region under the cursor for modal execution");
|
||||
}
|
||||
|
||||
static void rna_def_operator(BlenderRNA *brna)
|
||||
|
|
|
@ -1337,7 +1337,7 @@ void wm_event_free_handler(wmEventHandler *handler)
|
|||
}
|
||||
|
||||
/* only set context when area/region is part of screen */
|
||||
static void wm_handler_op_context(bContext *C, wmEventHandler *handler)
|
||||
static void wm_handler_op_context(bContext *C, wmEventHandler *handler, const wmEvent *event)
|
||||
{
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
|
||||
|
@ -1358,10 +1358,27 @@ static void wm_handler_op_context(bContext *C, wmEventHandler *handler)
|
|||
}
|
||||
else {
|
||||
ARegion *ar;
|
||||
wmOperator *op = handler->op ? (handler->op->opm ? handler->op->opm : handler->op) : NULL;
|
||||
CTX_wm_area_set(C, sa);
|
||||
for (ar = sa->regionbase.first; ar; ar = ar->next)
|
||||
if (ar == handler->op_region)
|
||||
break;
|
||||
|
||||
if (op && (op->flag & OP_IS_MODAL_CURSOR_REGION)) {
|
||||
ar = BKE_area_find_region_xy(sa, handler->op_region_type, event->x, event->y);
|
||||
if (ar) {
|
||||
handler->op_region = ar;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ar = NULL;
|
||||
}
|
||||
|
||||
if (ar == NULL) {
|
||||
for (ar = sa->regionbase.first; ar; ar = ar->next) {
|
||||
if (ar == handler->op_region) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX no warning print here, after full-area and back regions are remade */
|
||||
if (ar)
|
||||
CTX_wm_region_set(C, ar);
|
||||
|
@ -1379,11 +1396,12 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
|
|||
/* C is zero on freeing database, modal handlers then already were freed */
|
||||
while ((handler = BLI_pophead(handlers))) {
|
||||
if (handler->op) {
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
if (handler->op->type->cancel) {
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
|
||||
wm_handler_op_context(C, handler);
|
||||
wm_handler_op_context(C, handler, win->eventstate);
|
||||
|
||||
if (handler->op->type->flag & OPTYPE_UNDO)
|
||||
wm->op_undo_depth++;
|
||||
|
@ -1397,7 +1415,7 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
|
|||
CTX_wm_region_set(C, region);
|
||||
}
|
||||
|
||||
WM_cursor_grab_disable(CTX_wm_window(C), NULL);
|
||||
WM_cursor_grab_disable(win, NULL);
|
||||
WM_operator_free(handler->op);
|
||||
}
|
||||
else if (handler->ui_remove) {
|
||||
|
@ -1569,7 +1587,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
|
|||
ARegion *region = CTX_wm_region(C);
|
||||
bool dbl_click_disabled = false;
|
||||
|
||||
wm_handler_op_context(C, handler);
|
||||
wm_handler_op_context(C, handler, event);
|
||||
wm_region_mouse_co(C, event);
|
||||
wm_event_modalkeymap(C, op, event, &dbl_click_disabled);
|
||||
|
||||
|
@ -1717,7 +1735,7 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand
|
|||
ED_screen_full_prevspace(C, CTX_wm_area(C));
|
||||
}
|
||||
|
||||
wm_handler_op_context(C, handler);
|
||||
wm_handler_op_context(C, handler, CTX_wm_window(C)->eventstate);
|
||||
|
||||
/* needed for UI_popup_menu_reports */
|
||||
|
||||
|
@ -2534,6 +2552,7 @@ wmEventHandler *WM_event_add_modal_handler(bContext *C, wmOperator *op)
|
|||
|
||||
handler->op_area = CTX_wm_area(C); /* means frozen screen context for modal handlers! */
|
||||
handler->op_region = CTX_wm_region(C);
|
||||
handler->op_region_type = handler->op_region ? handler->op_region->regiontype : -1;
|
||||
|
||||
BLI_addhead(&win->modalhandlers, handler);
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ typedef struct wmEventHandler {
|
|||
wmOperator *op; /* for derived/modal handlers */
|
||||
struct ScrArea *op_area; /* for derived/modal handlers */
|
||||
struct ARegion *op_region; /* for derived/modal handlers */
|
||||
short op_region_type; /* for derived/modal handlers */
|
||||
|
||||
/* ui handler */
|
||||
wmUIHandlerFunc ui_handle; /* callback receiving events */
|
||||
|
|
Loading…
Reference in New Issue