diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-03-22 10:51:04 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-03-22 15:38:24 +0300 |
commit | 2d606187461dd087a8aa6a55ac92b24383ab269a (patch) | |
tree | 5ca2635905c493bb3805c9194b053bf5d292be90 | |
parent | c2584c1fad5140ea7507171f470d345a18ed49d5 (diff) |
UI: refactor queries into interface_query.c
interface_handlers.c is quite large (over 10k lines),
move general button utility functions into a separate file.
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 331 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_intern.h | 57 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_query.c | 358 |
3 files changed, 401 insertions, 345 deletions
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index ed0a9192c8f..a8e4d1737c3 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -391,12 +391,6 @@ typedef struct uiAfterFunc { } uiAfterFunc; -static bool ui_but_is_interactive(const uiBut *but, const bool labeledit); -static bool ui_but_contains_pt(const uiBut *but, float mx, float my); -static bool ui_but_contains_point_px(ARegion *ar, const uiBut *but, int x, int y); -static bool ui_but_contains_point_px_icon(const uiBut *but, ARegion *ar, const wmEvent *event); -static bool ui_region_contains_point_px(const ARegion *ar, int x, int y); -static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, const bool labeledit); static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type); static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state); static void button_activate_exit( @@ -422,200 +416,10 @@ static bool but_copypaste_curve_alive = false; /** \name UI Queries * \{ */ -void ui_but_pie_dir(RadialDirection dir, float vec[2]) +bool ui_but_is_editing(const uiBut *but) { - float angle; - - BLI_assert(dir != UI_RADIAL_NONE); - - angle = DEG2RADF((float)ui_radial_dir_to_angle[dir]); - vec[0] = cosf(angle); - vec[1] = sinf(angle); -} - -static bool ui_but_isect_pie_seg(const uiBlock *block, const uiBut *but) -{ - const float angle_range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_4 : M_PI_4 / 2.0; - float vec[2]; - - if (block->pie_data.flags & UI_PIE_INVALID_DIR) - return false; - - ui_but_pie_dir(but->pie_dir, vec); - - if (saacos(dot_v2v2(vec, block->pie_data.pie_dir)) < angle_range) - return true; - - return false; -} - -static bool ui_but_contains_pt(const uiBut *but, float mx, float my) -{ - return BLI_rctf_isect_pt(&but->rect, mx, my); -} - -static bool ui_but_contains_point_px(ARegion *ar, const uiBut *but, int x, int y) -{ - uiBlock *block = but->block; - float mx, my; - if (!ui_region_contains_point_px(ar, x, y)) - return false; - - mx = x; - my = y; - - ui_window_to_block_fl(ar, block, &mx, &my); - - if (but->pie_dir != UI_RADIAL_NONE) { - if (!ui_but_isect_pie_seg(block, but)) { - return false; - } - } - else if (!ui_but_contains_pt(but, mx, my)) { - return false; - } - - return true; -} - -static bool ui_but_contains_point_px_icon(const uiBut *but, ARegion *ar, const wmEvent *event) -{ - rcti rect; - int x = event->x, y = event->y; - - ui_window_to_block(ar, but->block, &x, &y); - - BLI_rcti_rctf_copy(&rect, &but->rect); - - if (but->imb || but->type == UI_BTYPE_COLOR) { - /* use button size itself */ - } - else if (but->drawflag & UI_BUT_ICON_LEFT) { - rect.xmax = rect.xmin + (BLI_rcti_size_y(&rect)); - } - else { - int delta = BLI_rcti_size_x(&rect) - BLI_rcti_size_y(&rect); - rect.xmin += delta / 2; - rect.xmax -= delta / 2; - } - - return BLI_rcti_isect_pt(&rect, x, y); -} - -static bool ui_region_contains_point_px(const ARegion *ar, int x, int y) -{ - rcti winrct; - - /* scale down area rect to exclude shadow */ - ui_region_winrct_get_no_margin(ar, &winrct); - - /* check if the mouse is in the region */ - if (!BLI_rcti_isect_pt(&winrct, x, y)) { - for (uiBlock *block = ar->uiblocks.first; block; block = block->next) - block->auto_open = false; - - return false; - } - - /* also, check that with view2d, that the mouse is not over the scrollbars - * NOTE: care is needed here, since the mask rect may include the scrollbars - * even when they are not visible, so we need to make a copy of the mask to - * use to check - */ - if (ar->v2d.mask.xmin != ar->v2d.mask.xmax) { - const View2D *v2d = &ar->v2d; - int mx, my; - - /* convert window coordinates to region coordinates */ - mx = x; - my = y; - ui_window_to_region(ar, &mx, &my); - - /* check if in the rect */ - if (!BLI_rcti_isect_pt(&v2d->mask, mx, my) || UI_view2d_mouse_in_scrollers(ar, &ar->v2d, x, y)) { - return false; - } - } - - return true; -} - -/* x and y are only used in case event is NULL... */ -static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, const bool labeledit) -{ - uiBlock *block; - uiBut *but, *butover = NULL; - float mx, my; - -// if (!win->active) -// return NULL; - if (!ui_region_contains_point_px(ar, x, y)) - return NULL; - - for (block = ar->uiblocks.first; block; block = block->next) { - mx = x; - my = y; - ui_window_to_block_fl(ar, block, &mx, &my); - - for (but = block->buttons.last; but; but = but->prev) { - if (ui_but_is_interactive(but, labeledit)) { - if (but->pie_dir != UI_RADIAL_NONE) { - if (ui_but_isect_pie_seg(block, but)) { - butover = but; - break; - } - } - else if (ui_but_contains_pt(but, mx, my)) { - butover = but; - break; - } - } - } - - /* CLIP_EVENTS prevents the event from reaching other blocks */ - if (block->flag & UI_BLOCK_CLIP_EVENTS) { - /* check if mouse is inside block */ - if (BLI_rctf_isect_pt(&block->rect, mx, my)) { - break; - } - } - } - - return butover; -} - -uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event) -{ - return ui_but_find_mouse_over_ex(ar, event->x, event->y, event->ctrl != 0); -} - -static uiBut *ui_list_find_mouse_over_ex(ARegion *ar, int x, int y) -{ - uiBlock *block; - uiBut *but; - float mx, my; - - if (!ui_region_contains_point_px(ar, x, y)) - return NULL; - - for (block = ar->uiblocks.first; block; block = block->next) { - mx = x; - my = y; - ui_window_to_block_fl(ar, block, &mx, &my); - - for (but = block->buttons.last; but; but = but->prev) { - if (but->type == UI_BTYPE_LISTBOX && ui_but_contains_pt(but, mx, my)) { - return but; - } - } - } - - return NULL; -} - -static uiBut *ui_list_find_mouse_over(ARegion *ar, const wmEvent *event) -{ - return ui_list_find_mouse_over_ex(ar, event->x, event->y); + uiHandleButtonData *data = but->active; + return (data && ELEM(data->state, BUTTON_STATE_TEXT_EDITING, BUTTON_STATE_NUM_EDITING)); } /* assumes event type is MOUSEPAN */ @@ -651,91 +455,6 @@ void ui_pan_to_scroll(const wmEvent *event, int *type, int *val) } } -static uiBut *ui_but_prev(uiBut *but) -{ - while (but->prev) { - but = but->prev; - if (ui_but_is_editable(but)) return but; - } - return NULL; -} - -static uiBut *ui_but_next(uiBut *but) -{ - while (but->next) { - but = but->next; - if (ui_but_is_editable(but)) return but; - } - return NULL; -} - -static uiBut *ui_but_first(uiBlock *block) -{ - uiBut *but; - - but = block->buttons.first; - while (but) { - if (ui_but_is_editable(but)) return but; - but = but->next; - } - return NULL; -} - -static uiBut *ui_but_last(uiBlock *block) -{ - uiBut *but; - - but = block->buttons.last; - while (but) { - if (ui_but_is_editable(but)) return but; - but = but->prev; - } - return NULL; -} - -static bool ui_but_is_cursor_warp(const uiBut *but) -{ - if (U.uiflag & USER_CONTINUOUS_MOUSE) { - if (ELEM(but->type, - UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_HSVCIRCLE, - UI_BTYPE_TRACK_PREVIEW, UI_BTYPE_HSVCUBE, UI_BTYPE_CURVE)) - { - return true; - } - } - - return false; -} - -static bool ui_but_contains_password(const uiBut *but) -{ - return but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD); -} - -/** - * Can we mouse over the button or is it hidden/disabled/layout. - * \note ctrl is kind of a hack currently, - * so that non-embossed UI_BTYPE_TEXT button behaves as a label when ctrl is not pressed. - */ -static bool ui_but_is_interactive(const uiBut *but, const bool labeledit) -{ - /* note, UI_BTYPE_LABEL is included for highlights, this allows drags */ - if ((but->type == UI_BTYPE_LABEL) && but->dragpoin == NULL) - return false; - if (ELEM(but->type, UI_BTYPE_ROUNDBOX, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_LISTBOX)) - return false; - if (but->flag & UI_HIDDEN) - return false; - if (but->flag & UI_SCROLLED) - return false; - if ((but->type == UI_BTYPE_TEXT) && (but->dt == UI_EMBOSS_NONE) && !labeledit) - return false; - if ((but->type == UI_BTYPE_LISTROW) && labeledit) - return false; - - return true; -} - static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but_b) { return ((but_a->type == but_b->type) && @@ -775,30 +494,6 @@ uiBut *ui_but_find_select_in_enum(uiBut *but, int direction) return but_found; } -uiBut *ui_but_find_active_in_region(ARegion *ar) -{ - uiBlock *block; - uiBut *but; - - for (block = ar->uiblocks.first; block; block = block->next) - for (but = block->buttons.first; but; but = but->next) - if (but->active) - return but; - - return NULL; -} - -bool ui_but_is_active(ARegion *ar) -{ - return (ui_but_find_active_in_region(ar) != NULL); -} - -bool ui_but_is_editing(uiBut *but) -{ - uiHandleButtonData *data = but->active; - return (data && ELEM(data->state, BUTTON_STATE_TEXT_EDITING, BUTTON_STATE_NUM_EDITING)); -} - static float ui_mouse_scale_warp_factor(const bool shift) { return shift ? 0.05f : 1.0f; @@ -815,18 +510,6 @@ static void ui_mouse_scale_warp( *r_my = (data->dragstarty * (1.0f - fac) + my * fac); } -/* file selectors are exempt from utf-8 checks */ -bool ui_but_is_utf8(const uiBut *but) -{ - if (but->rnaprop) { - const int subtype = RNA_property_subtype(but->rnaprop); - return !(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME, PROP_BYTESTRING)); - } - else { - return !(but->flag & UI_BUT_NO_UTF8); - } -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -2521,14 +2204,6 @@ static void ui_but_paste_numeric_value(bContext *C, uiBut *but, uiHandleButtonDa } } -static bool ui_but_has_array_value(uiBut *but) -{ - return (but->rnapoin.data && but->rnaprop && - ELEM(RNA_property_subtype(but->rnaprop), PROP_COLOR, PROP_TRANSLATION, PROP_DIRECTION, - PROP_VELOCITY, PROP_ACCELERATION, PROP_MATRIX, PROP_EULER, PROP_QUATERNION, PROP_AXISANGLE, - PROP_XYZ, PROP_XYZ_LENGTH, PROP_COLOR_GAMMA, PROP_COORDS)); -} - static void ui_but_paste_normalized_vector(bContext *C, uiBut *but, char *buf_paste) { float xyz[3]; diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 84608e89348..fbfb37b9902 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -490,7 +490,6 @@ extern bool ui_but_is_bool(const uiBut *but) ATTR_WARN_UNUSED_RESULT; extern bool ui_but_is_unit(const uiBut *but) ATTR_WARN_UNUSED_RESULT; extern bool ui_but_is_compatible(const uiBut *but_a, const uiBut *but_b) ATTR_WARN_UNUSED_RESULT; extern bool ui_but_is_rna_valid(uiBut *but) ATTR_WARN_UNUSED_RESULT; -extern bool ui_but_is_utf8(const uiBut *but) ATTR_WARN_UNUSED_RESULT; extern bool ui_but_supports_cycling(const uiBut *but) ATTR_WARN_UNUSED_RESULT; extern int ui_but_is_pushed_ex(uiBut *but, double *value) ATTR_WARN_UNUSED_RESULT; @@ -686,14 +685,10 @@ extern void ui_but_activate_over(struct bContext *C, struct ARegion *ar, uiBut * extern void ui_but_execute_begin(struct bContext *C, struct ARegion *ar, uiBut *but, void **active_back); extern void ui_but_execute_end(struct bContext *C, struct ARegion *ar, uiBut *but, void *active_back); extern void ui_but_active_free(const struct bContext *C, uiBut *but); -extern bool ui_but_is_active(struct ARegion *ar) ATTR_WARN_UNUSED_RESULT; -extern bool ui_but_is_editing(uiBut *but); extern int ui_but_menu_direction(uiBut *but); extern void ui_but_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, const bool restore); extern uiBut *ui_but_find_select_in_enum(uiBut *but, int direction); -extern uiBut *ui_but_find_active_in_region(struct ARegion *ar); -extern uiBut *ui_but_find_mouse_over(struct ARegion *ar, const struct wmEvent *event); -void ui_but_pie_dir(RadialDirection dir, float vec[2]); +bool ui_but_is_editing(const uiBut *but); float ui_block_calc_pie_segment(struct uiBlock *block, const float event_xy[2]); void ui_but_add_shortcut(uiBut *but, const char *key_str, const bool do_strip); @@ -807,15 +802,47 @@ void ui_but_anim_decorate_cb(struct bContext *C, void *arg_but, void *arg_dummy) void ui_but_anim_decorate_update_from_flag(uiBut *but); /* interface_query.c */ -bool ui_but_is_editable(const uiBut *but); -bool ui_but_is_editable_as_text(const uiBut *but); -bool ui_but_is_toggle(const uiBut *but); -bool ui_but_is_popover_once_compat(const uiBut *but); - -extern bool ui_block_is_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT; -extern bool ui_block_is_popover(const uiBlock *block) ATTR_WARN_UNUSED_RESULT; -extern bool ui_block_is_pie_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT; -extern bool ui_block_is_popup_any(const uiBlock *block) ATTR_WARN_UNUSED_RESULT; +bool ui_but_is_editable(const uiBut *but) ATTR_WARN_UNUSED_RESULT; +bool ui_but_is_editable_as_text(const uiBut *but) ATTR_WARN_UNUSED_RESULT; +bool ui_but_is_toggle(const uiBut *but) ATTR_WARN_UNUSED_RESULT; +bool ui_but_is_interactive(const uiBut *but, const bool labeledit) ATTR_WARN_UNUSED_RESULT; +bool ui_but_is_utf8(const uiBut *but) ATTR_WARN_UNUSED_RESULT; +bool ui_but_is_popover_once_compat(const uiBut *but) ATTR_WARN_UNUSED_RESULT; +bool ui_but_has_array_value(const uiBut *but) ATTR_WARN_UNUSED_RESULT; +void ui_but_pie_dir(RadialDirection dir, float vec[2]); + +bool ui_but_is_cursor_warp(const uiBut *but) ATTR_WARN_UNUSED_RESULT; + +bool ui_but_contains_pt( + const uiBut *but, float mx, float my) ATTR_WARN_UNUSED_RESULT; +bool ui_but_contains_point_px_icon( + const uiBut *but, struct ARegion *ar, const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT; +bool ui_but_contains_point_px( + const struct ARegion *ar, const uiBut *but, int x, int y) ATTR_WARN_UNUSED_RESULT; +bool ui_region_contains_point_px( + const struct ARegion *ar, int x, int y) ATTR_WARN_UNUSED_RESULT; + +uiBut *ui_list_find_mouse_over(ARegion *ar, const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT; + +uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, const bool labeledit) ATTR_WARN_UNUSED_RESULT; +uiBut *ui_but_find_mouse_over(struct ARegion *ar, const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT; + +uiBut *ui_list_find_mouse_over_ex(struct ARegion *ar, int x, int y) ATTR_WARN_UNUSED_RESULT; + +bool ui_but_is_active(struct ARegion *ar) ATTR_WARN_UNUSED_RESULT; +bool ui_but_contains_password(const uiBut *but) ATTR_WARN_UNUSED_RESULT; + +uiBut *ui_but_prev(uiBut *but) ATTR_WARN_UNUSED_RESULT; +uiBut *ui_but_next(uiBut *but) ATTR_WARN_UNUSED_RESULT; +uiBut *ui_but_first(uiBlock *block) ATTR_WARN_UNUSED_RESULT; +uiBut *ui_but_last(uiBlock *block) ATTR_WARN_UNUSED_RESULT; + +bool ui_block_is_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT; +bool ui_block_is_popover(const uiBlock *block) ATTR_WARN_UNUSED_RESULT; +bool ui_block_is_pie_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT; +bool ui_block_is_popup_any(const uiBlock *block) ATTR_WARN_UNUSED_RESULT; + +uiBut *ui_but_find_active_in_region(struct ARegion *ar) ATTR_WARN_UNUSED_RESULT; /* interface_context_menu.c */ bool ui_popup_context_menu_for_button(struct bContext *C, uiBut *but); diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.c index ad83bce97a6..d123ac7278a 100644 --- a/source/blender/editors/interface/interface_query.c +++ b/source/blender/editors/interface/interface_query.c @@ -21,10 +21,15 @@ */ #include "BLI_utildefines.h" +#include "BLI_math.h" +#include "BLI_rect.h" #include "DNA_screen_types.h" #include "UI_interface.h" +#include "UI_view2d.h" + +#include "RNA_access.h" #include "interface_intern.h" @@ -32,9 +37,10 @@ #include "WM_types.h" /* -------------------------------------------------------------------- */ -/** \name Button (uiBut) +/** \name Button (#uiBut) State * \{ */ + bool ui_but_is_editable(const uiBut *but) { return !ELEM( @@ -67,6 +73,43 @@ bool ui_but_is_toggle(const uiBut *but) ); } +/** + * Can we mouse over the button or is it hidden/disabled/layout. + * \note ctrl is kind of a hack currently, + * so that non-embossed UI_BTYPE_TEXT button behaves as a label when ctrl is not pressed. + */ +bool ui_but_is_interactive(const uiBut *but, const bool labeledit) +{ + /* note, UI_BTYPE_LABEL is included for highlights, this allows drags */ + if ((but->type == UI_BTYPE_LABEL) && but->dragpoin == NULL) + return false; + if (ELEM(but->type, UI_BTYPE_ROUNDBOX, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_LISTBOX)) + return false; + if (but->flag & UI_HIDDEN) + return false; + if (but->flag & UI_SCROLLED) + return false; + if ((but->type == UI_BTYPE_TEXT) && (but->dt == UI_EMBOSS_NONE) && !labeledit) + return false; + if ((but->type == UI_BTYPE_LISTROW) && labeledit) + return false; + + return true; +} + +/* file selectors are exempt from utf-8 checks */ +bool ui_but_is_utf8(const uiBut *but) +{ + if (but->rnaprop) { + const int subtype = RNA_property_subtype(but->rnaprop); + return !(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME, PROP_BYTESTRING)); + } + else { + return !(but->flag & UI_BUT_NO_UTF8); + } +} + + #ifdef USE_UI_POPOVER_ONCE bool ui_but_is_popover_once_compat(const uiBut *but) { @@ -77,6 +120,16 @@ bool ui_but_is_popover_once_compat(const uiBut *but) } #endif +bool ui_but_has_array_value(const uiBut *but) +{ + return (but->rnapoin.data && but->rnaprop && + ELEM(RNA_property_subtype(but->rnaprop), PROP_COLOR, PROP_TRANSLATION, PROP_DIRECTION, + PROP_VELOCITY, PROP_ACCELERATION, PROP_MATRIX, PROP_EULER, PROP_QUATERNION, PROP_AXISANGLE, + PROP_XYZ, PROP_XYZ_LENGTH, PROP_COLOR_GAMMA, PROP_COORDS)); +} + + + bool UI_but_is_tool(const uiBut *but) { /* very evil! */ @@ -103,7 +156,239 @@ bool UI_but_has_tooltip_label(const uiBut *but) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Block (uiBlock) +/** \name Button (#uiBut) Spatial + * \{ */ + +void ui_but_pie_dir(RadialDirection dir, float vec[2]) +{ + float angle; + + BLI_assert(dir != UI_RADIAL_NONE); + + angle = DEG2RADF((float)ui_radial_dir_to_angle[dir]); + vec[0] = cosf(angle); + vec[1] = sinf(angle); +} + +static bool ui_but_isect_pie_seg(const uiBlock *block, const uiBut *but) +{ + const float angle_range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_4 : M_PI_4 / 2.0; + float vec[2]; + + if (block->pie_data.flags & UI_PIE_INVALID_DIR) + return false; + + ui_but_pie_dir(but->pie_dir, vec); + + if (saacos(dot_v2v2(vec, block->pie_data.pie_dir)) < angle_range) + return true; + + return false; +} + +bool ui_but_contains_pt(const uiBut *but, float mx, float my) +{ + return BLI_rctf_isect_pt(&but->rect, mx, my); +} + +bool ui_but_contains_point_px(const ARegion *ar, const uiBut *but, int x, int y) +{ + uiBlock *block = but->block; + float mx, my; + if (!ui_region_contains_point_px(ar, x, y)) + return false; + + mx = x; + my = y; + + ui_window_to_block_fl(ar, block, &mx, &my); + + if (but->pie_dir != UI_RADIAL_NONE) { + if (!ui_but_isect_pie_seg(block, but)) { + return false; + } + } + else if (!ui_but_contains_pt(but, mx, my)) { + return false; + } + + return true; +} + +bool ui_but_contains_point_px_icon(const uiBut *but, ARegion *ar, const wmEvent *event) +{ + rcti rect; + int x = event->x, y = event->y; + + ui_window_to_block(ar, but->block, &x, &y); + + BLI_rcti_rctf_copy(&rect, &but->rect); + + if (but->imb || but->type == UI_BTYPE_COLOR) { + /* use button size itself */ + } + else if (but->drawflag & UI_BUT_ICON_LEFT) { + rect.xmax = rect.xmin + (BLI_rcti_size_y(&rect)); + } + else { + int delta = BLI_rcti_size_x(&rect) - BLI_rcti_size_y(&rect); + rect.xmin += delta / 2; + rect.xmax -= delta / 2; + } + + return BLI_rcti_isect_pt(&rect, x, y); +} + +/* x and y are only used in case event is NULL... */ +uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, const bool labeledit) +{ + uiBlock *block; + uiBut *but, *butover = NULL; + float mx, my; + +// if (!win->active) +// return NULL; + if (!ui_region_contains_point_px(ar, x, y)) + return NULL; + + for (block = ar->uiblocks.first; block; block = block->next) { + mx = x; + my = y; + ui_window_to_block_fl(ar, block, &mx, &my); + + for (but = block->buttons.last; but; but = but->prev) { + if (ui_but_is_interactive(but, labeledit)) { + if (but->pie_dir != UI_RADIAL_NONE) { + if (ui_but_isect_pie_seg(block, but)) { + butover = but; + break; + } + } + else if (ui_but_contains_pt(but, mx, my)) { + butover = but; + break; + } + } + } + + /* CLIP_EVENTS prevents the event from reaching other blocks */ + if (block->flag & UI_BLOCK_CLIP_EVENTS) { + /* check if mouse is inside block */ + if (BLI_rctf_isect_pt(&block->rect, mx, my)) { + break; + } + } + } + + return butover; +} + +uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event) +{ + return ui_but_find_mouse_over_ex(ar, event->x, event->y, event->ctrl != 0); +} + +uiBut *ui_list_find_mouse_over_ex(ARegion *ar, int x, int y) +{ + uiBlock *block; + uiBut *but; + float mx, my; + + if (!ui_region_contains_point_px(ar, x, y)) + return NULL; + + for (block = ar->uiblocks.first; block; block = block->next) { + mx = x; + my = y; + ui_window_to_block_fl(ar, block, &mx, &my); + + for (but = block->buttons.last; but; but = but->prev) { + if (but->type == UI_BTYPE_LISTBOX && ui_but_contains_pt(but, mx, my)) { + return but; + } + } + } + + return NULL; +} + +uiBut *ui_list_find_mouse_over(ARegion *ar, const wmEvent *event) +{ + return ui_list_find_mouse_over_ex(ar, event->x, event->y); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ +/** \name Button (#uiBut) Relations + * \{ */ + +uiBut *ui_but_prev(uiBut *but) +{ + while (but->prev) { + but = but->prev; + if (ui_but_is_editable(but)) return but; + } + return NULL; +} + +uiBut *ui_but_next(uiBut *but) +{ + while (but->next) { + but = but->next; + if (ui_but_is_editable(but)) return but; + } + return NULL; +} + +uiBut *ui_but_first(uiBlock *block) +{ + uiBut *but; + + but = block->buttons.first; + while (but) { + if (ui_but_is_editable(but)) return but; + but = but->next; + } + return NULL; +} + +uiBut *ui_but_last(uiBlock *block) +{ + uiBut *but; + + but = block->buttons.last; + while (but) { + if (ui_but_is_editable(but)) return but; + but = but->prev; + } + return NULL; +} + +bool ui_but_is_cursor_warp(const uiBut *but) +{ + if (U.uiflag & USER_CONTINUOUS_MOUSE) { + if (ELEM(but->type, + UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_HSVCIRCLE, + UI_BTYPE_TRACK_PREVIEW, UI_BTYPE_HSVCUBE, UI_BTYPE_CURVE)) + { + return true; + } + } + + return false; +} + +bool ui_but_contains_password(const uiBut *but) +{ + return but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Block (#uiBlock) State * \{ */ bool ui_block_is_menu(const uiBlock *block) @@ -143,3 +428,72 @@ bool UI_block_is_empty(const uiBlock *block) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Region (#ARegion) State + * \{ */ + +bool ui_but_is_active(ARegion *ar) +{ + return (ui_but_find_active_in_region(ar) != NULL); +} + + +uiBut *ui_but_find_active_in_region(ARegion *ar) +{ + uiBlock *block; + uiBut *but; + + for (block = ar->uiblocks.first; block; block = block->next) + for (but = block->buttons.first; but; but = but->next) + if (but->active) + return but; + + return NULL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Region (#ARegion) State + * \{ */ + +bool ui_region_contains_point_px(const ARegion *ar, int x, int y) +{ + rcti winrct; + + /* scale down area rect to exclude shadow */ + ui_region_winrct_get_no_margin(ar, &winrct); + + /* check if the mouse is in the region */ + if (!BLI_rcti_isect_pt(&winrct, x, y)) { + for (uiBlock *block = ar->uiblocks.first; block; block = block->next) + block->auto_open = false; + + return false; + } + + /* also, check that with view2d, that the mouse is not over the scrollbars + * NOTE: care is needed here, since the mask rect may include the scrollbars + * even when they are not visible, so we need to make a copy of the mask to + * use to check + */ + if (ar->v2d.mask.xmin != ar->v2d.mask.xmax) { + const View2D *v2d = &ar->v2d; + int mx, my; + + /* convert window coordinates to region coordinates */ + mx = x; + my = y; + ui_window_to_region(ar, &mx, &my); + + /* check if in the rect */ + if (!BLI_rcti_isect_pt(&v2d->mask, mx, my) || UI_view2d_mouse_in_scrollers(ar, &ar->v2d, x, y)) { + return false; + } + } + + return true; +} + +/** \} */ |