UI: avoid subtracting shadow from winrct
For popup interactions we need to know if events are in the region or not, however subtracting the shadow isn't so reliable, since its not always added to all sides of a popup. Instead, get the winrct value from a popup using the block rect, otherwise the winrct as-is.
This commit is contained in:
@@ -92,6 +92,7 @@ void BLI_rcti_union(struct rcti *rcti1, const struct rcti *rcti2);
|
||||
void BLI_rctf_union(struct rctf *rctf1, const struct rctf *rctf2);
|
||||
void BLI_rcti_rctf_copy(struct rcti *dst, const struct rctf *src);
|
||||
void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src);
|
||||
void BLI_rcti_rctf_copy_floor(struct rcti *dst, const struct rctf *src);
|
||||
|
||||
void BLI_rctf_rotate_expand(rctf *dst, const rctf *src, const float angle);
|
||||
|
||||
|
@@ -584,6 +584,14 @@ void BLI_rcti_rctf_copy(rcti *dst, const rctf *src)
|
||||
dst->ymax = dst->ymin + floorf(BLI_rctf_size_y(src) + 0.5f);
|
||||
}
|
||||
|
||||
void BLI_rcti_rctf_copy_floor(rcti *dst, const rctf *src)
|
||||
{
|
||||
dst->xmin = floorf(src->xmin);
|
||||
dst->xmax = floorf(src->xmax);
|
||||
dst->ymin = floorf(src->ymin);
|
||||
dst->ymax = floorf(src->ymax);
|
||||
}
|
||||
|
||||
void BLI_rctf_rcti_copy(rctf *dst, const rcti *src)
|
||||
{
|
||||
dst->xmin = src->xmin;
|
||||
|
@@ -215,6 +215,23 @@ void ui_region_to_window(const ARegion *ar, int *x, int *y)
|
||||
*x += ar->winrct.xmin;
|
||||
*y += ar->winrct.ymin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Popups will add a margin to #ARegion.winrct for shadow,
|
||||
* for interactivity (point-inside tests for eg), we want the winrct without the margin added.
|
||||
*/
|
||||
void ui_region_winrct_get_no_margin(const struct ARegion *ar, struct rcti *r_rect)
|
||||
{
|
||||
uiBlock *block = ar->uiblocks.first;
|
||||
if (block && block->flag & UI_BLOCK_LOOP) {
|
||||
BLI_rcti_rctf_copy_floor(r_rect, &block->rect);
|
||||
BLI_rcti_translate(r_rect, ar->winrct.xmin, ar->winrct.ymin);
|
||||
}
|
||||
else {
|
||||
*r_rect = ar->winrct;
|
||||
}
|
||||
}
|
||||
|
||||
/* ******************* block calc ************************* */
|
||||
|
||||
void ui_block_translate(uiBlock *block, int x, int y)
|
||||
@@ -1313,16 +1330,8 @@ static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, u
|
||||
rctf rectf;
|
||||
|
||||
ui_block_to_window_rctf(ar, block, &rectf, (but) ? &but->rect : &block->rect);
|
||||
|
||||
rectf.xmin -= ar->winrct.xmin;
|
||||
rectf.ymin -= ar->winrct.ymin;
|
||||
rectf.xmax -= ar->winrct.xmin;
|
||||
rectf.ymax -= ar->winrct.ymin;
|
||||
|
||||
rect->xmin = floorf(rectf.xmin);
|
||||
rect->ymin = floorf(rectf.ymin);
|
||||
rect->xmax = floorf(rectf.xmax);
|
||||
rect->ymax = floorf(rectf.ymax);
|
||||
BLI_rcti_rctf_copy_floor(rect, &rectf);
|
||||
BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin);
|
||||
}
|
||||
|
||||
/* uses local copy of style, to scale things down, and allow widgets to change stuff */
|
||||
|
@@ -7226,18 +7226,13 @@ static void ui_blocks_set_tooltips(ARegion *ar, const bool enable)
|
||||
static bool ui_region_contains_point_px(ARegion *ar, int x, int y)
|
||||
{
|
||||
uiBlock *block = ar->uiblocks.first;
|
||||
rcti rect = ar->winrct;
|
||||
const bool is_block_loop = block->flag & UI_BLOCK_LOOP;
|
||||
rcti winrct;
|
||||
|
||||
/* scale down area rect to exclude shadow */
|
||||
if (is_block_loop) {
|
||||
const int shadow_xy = UI_ThemeMenuShadowWidth();
|
||||
BLI_rcti_resize(&rect, BLI_rcti_size_x(&ar->winrct) - shadow_xy * 2,
|
||||
BLI_rcti_size_y(&ar->winrct) - shadow_xy * 2);
|
||||
}
|
||||
ui_region_winrct_get_no_margin(ar, &winrct);
|
||||
|
||||
/* check if the mouse is in the region */
|
||||
if (!BLI_rcti_isect_pt(&rect, x, y)) {
|
||||
if (!BLI_rcti_isect_pt(&winrct, x, y)) {
|
||||
for (block = ar->uiblocks.first; block; block = block->next)
|
||||
block->auto_open = false;
|
||||
|
||||
@@ -9703,16 +9698,14 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE
|
||||
uiBut *but_other;
|
||||
uiHandleButtonData *data;
|
||||
bool is_inside_menu = false;
|
||||
const int shadow_xy = UI_ThemeMenuShadowWidth();
|
||||
|
||||
/* look for a popup menu containing the mouse */
|
||||
for (ar_temp = screen->regionbase.first; ar_temp; ar_temp = ar_temp->next) {
|
||||
rcti rect = ar_temp->winrct;
|
||||
rcti winrct;
|
||||
|
||||
/* resize region rect to ignore shadow */
|
||||
BLI_rcti_resize(&rect, BLI_rcti_size_x(&ar_temp->winrct) - shadow_xy * 2,
|
||||
BLI_rcti_size_y(&ar_temp->winrct) - shadow_xy * 2);
|
||||
if (BLI_rcti_isect_pt_v(&rect, &event->x)) {
|
||||
ui_region_winrct_get_no_margin(ar_temp, &winrct);
|
||||
|
||||
if (BLI_rcti_isect_pt_v(&winrct, &event->x)) {
|
||||
BLI_assert(ar_temp->type->regionid == RGN_TYPE_TEMPORARY);
|
||||
|
||||
is_inside_menu = true;
|
||||
|
@@ -450,6 +450,7 @@ extern void ui_window_to_block_fl(const struct ARegion *ar, uiBlock *block, floa
|
||||
extern void ui_window_to_block(const struct ARegion *ar, uiBlock *block, int *x, int *y);
|
||||
extern void ui_window_to_region(const ARegion *ar, int *x, int *y);
|
||||
extern void ui_region_to_window(const struct ARegion *ar, int *x, int *y);
|
||||
extern void ui_region_winrct_get_no_margin(const struct ARegion *ar, struct rcti *r_rect);
|
||||
|
||||
extern double ui_but_value_get(uiBut *but);
|
||||
extern void ui_but_value_set(uiBut *but, double value);
|
||||
|
Reference in New Issue
Block a user