Blender V5.0
interface_query.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "BLI_listbase.h"
12#include "BLI_math_rotation.h"
13#include "BLI_math_vector.h"
14#include "BLI_rect.h"
15#include "BLI_string.h"
16#include "BLI_utildefines.h"
17
18#include "DNA_screen_types.h"
19
20#include "BKE_screen.hh"
21
22#include "UI_view2d.hh"
23
24#include "RNA_access.hh"
25
26#include "interface_intern.hh"
27
28#include "UI_abstract_view.hh"
29
30#include "WM_api.hh"
31#include "WM_types.hh"
32
34
35/* -------------------------------------------------------------------- */
38
49
54
67
68bool ui_but_is_interactive_ex(const uiBut *but, const bool labeledit, const bool for_tooltip)
69{
70 /* NOTE: #ButType::Label is included for highlights, this allows drags. */
72 if (for_tooltip) {
73 /* It's important labels are considered interactive for the purpose of showing tooltip. */
74 if (!ui_but_drag_is_draggable(but) && but->tip_func == nullptr &&
75 but->tip_custom_func == nullptr && but->tip_quick_func == nullptr &&
76 (but->tip == nullptr || but->tip[0] == '\0'))
77 {
78 return false;
79 }
80 }
81 else {
82 if (!ui_but_drag_is_draggable(but)) {
83 return false;
84 }
85 }
86 }
87
89 return false;
90 }
91 if (but->flag & UI_HIDDEN) {
92 return false;
93 }
94 if (but->flag & UI_SCROLLED) {
95 return false;
96 }
97 if ((but->type == ButType::Text) &&
99 !labeledit)
100 {
101 return false;
102 }
103 if ((but->type == ButType::ListRow) && labeledit) {
104 return false;
105 }
106 if (but->type == ButType::ViewItem) {
107 const uiButViewItem *but_item = static_cast<const uiButViewItem *>(but);
108 return but_item->view_item->is_interactive();
109 }
110
111 return true;
112}
113
114bool ui_but_is_interactive(const uiBut *but, const bool labeledit)
115{
116 return ui_but_is_interactive_ex(but, labeledit, false);
117}
118
119bool UI_but_is_utf8(const uiBut *but)
120{
121 if (but->rnaprop) {
122 const int subtype = RNA_property_subtype(but->rnaprop);
124 }
125 return !(but->flag & UI_BUT_NO_UTF8);
126}
127
128#ifdef USE_UI_POPOVER_ONCE
130{
132}
133#endif
134
136{
137 return (but->rnapoin.data && but->rnaprop && RNA_property_array_check(but->rnaprop));
138}
139
141bool UI_but_is_tool(const uiBut *but)
142{
143 /* very evil! */
144 if (but->optype != nullptr) {
145 if (g_ot_tool_set_by_id == nullptr) {
146 g_ot_tool_set_by_id = WM_operatortype_find("WM_OT_tool_set_by_id", false);
147 }
148 if (but->optype == g_ot_tool_set_by_id) {
149 return true;
150 }
151 }
152 return false;
153}
154
156{
157 return (but->drawflag & UI_BUT_HAS_QUICK_TOOLTIP) != 0;
158}
159
160int ui_but_icon(const uiBut *but)
161{
162 if (!(but->flag & UI_HAS_ICON)) {
163 return ICON_NONE;
164 }
165
166 const bool is_preview = (but->flag & UI_BUT_ICON_PREVIEW) != 0;
167
168 /* While icon is loading, show loading icon at the normal icon size. */
169 if (ui_icon_is_preview_deferred_loading(but->icon, is_preview)) {
170 return ICON_PREVIEW_LOADING;
171 }
172
173 /* Consecutive icons can be toggle between. */
174 if (but->drawflag & UI_BUT_ICON_REVERSE) {
175 return but->icon - but->iconadd;
176 }
177 return but->icon + but->iconadd;
178}
179
181
182/* -------------------------------------------------------------------- */
185
186void ui_but_pie_dir(RadialDirection dir, float vec[2])
187{
188 float angle;
189
191
193 vec[0] = cosf(angle);
194 vec[1] = sinf(angle);
195}
196
197static bool ui_but_isect_pie_seg(const uiBlock *block, const uiBut *but)
198{
199 if (block->pie_data.flags & UI_PIE_INVALID_DIR) {
200 return false;
201 }
202
203 /* Plus/minus 45 degrees: `cosf(DEG2RADF(45)) == M_SQRT1_2`. */
204 const float angle_4th_cos = M_SQRT1_2;
205 /* Plus/minus 22.5 degrees: `cosf(DEG2RADF(22.5))`. */
206 const float angle_8th_cos = 0.9238795f;
207
208 /* Use a large bias so edge-cases fall back to comparing with the adjacent direction. */
209 const float eps_bias = 1e-4;
210
211 float but_dir[2];
212 ui_but_pie_dir(but->pie_dir, but_dir);
213
214 const float angle_but_cos = dot_v2v2(but_dir, block->pie_data.pie_dir);
215 /* Outside range (with bias). */
216 if (angle_but_cos < angle_4th_cos - eps_bias) {
217 return false;
218 }
219 /* Inside range (with bias). */
220 if (angle_but_cos > angle_8th_cos + eps_bias) {
221 return true;
222 }
223
224 /* Check if adjacent direction is closer (with tie breaker). */
225 RadialDirection dir_adjacent_8th, dir_adjacent_4th;
226 if (angle_signed_v2v2(but_dir, block->pie_data.pie_dir) < 0.0f) {
227 dir_adjacent_8th = UI_RADIAL_DIRECTION_PREV(but->pie_dir);
228 dir_adjacent_4th = UI_RADIAL_DIRECTION_PREV(dir_adjacent_8th);
229 }
230 else {
231 dir_adjacent_8th = UI_RADIAL_DIRECTION_NEXT(but->pie_dir);
232 dir_adjacent_4th = UI_RADIAL_DIRECTION_NEXT(dir_adjacent_8th);
233 }
234
235 const bool has_8th_adjacent = block->pie_data.pie_dir_mask & (1 << int(dir_adjacent_8th));
236
237 /* Compare with the adjacent direction (even if there is no button). */
238 const RadialDirection dir_adjacent = has_8th_adjacent ? dir_adjacent_8th : dir_adjacent_4th;
239 float but_dir_adjacent[2];
240 ui_but_pie_dir(dir_adjacent, but_dir_adjacent);
241
242 const float angle_adjacent_cos = dot_v2v2(but_dir_adjacent, block->pie_data.pie_dir);
243
244 /* Tie breaker, so one of the buttons is always selected. */
245 if (UNLIKELY(angle_but_cos == angle_adjacent_cos)) {
246 return but->pie_dir > dir_adjacent;
247 }
248 return angle_but_cos > angle_adjacent_cos;
249}
250
251bool ui_but_contains_pt(const uiBut *but, float mx, float my)
252{
253 return BLI_rctf_isect_pt(&but->rect, mx, my);
254}
255
256bool ui_but_contains_rect(const uiBut *but, const rctf *rect)
257{
258 return BLI_rctf_isect(&but->rect, rect, nullptr);
259}
260
261bool ui_but_contains_point_px(const uiBut *but, const ARegion *region, const int xy[2])
262{
263 uiBlock *block = but->block;
264 if (!ui_region_contains_point_px(region, xy)) {
265 return false;
266 }
267
268 float mx = xy[0], my = xy[1];
269 ui_window_to_block_fl(region, block, &mx, &my);
270
271 if (but->pie_dir != UI_RADIAL_NONE) {
272 if (!ui_but_isect_pie_seg(block, but)) {
273 return false;
274 }
275 }
276 else if (!ui_but_contains_pt(but, mx, my)) {
277 return false;
278 }
279
280 return true;
281}
282
283bool ui_but_contains_point_px_icon(const uiBut *but, ARegion *region, const wmEvent *event)
284{
285 rcti rect;
286 int x = event->xy[0], y = event->xy[1];
287
288 ui_window_to_block(region, but->block, &x, &y);
289
290 BLI_rcti_rctf_copy(&rect, &but->rect);
291
292 if (but->dragflag & UI_BUT_DRAG_FULL_BUT) {
293 /* use button size itself */
294 }
295 else if (but->drawflag & UI_BUT_ICON_LEFT) {
296 rect.xmax = rect.xmin + BLI_rcti_size_y(&rect);
297 }
298 else {
299 const int delta = BLI_rcti_size_x(&rect) - BLI_rcti_size_y(&rect);
300 rect.xmin += delta / 2;
301 rect.xmax -= delta / 2;
302 }
303
304 return BLI_rcti_isect_pt(&rect, x, y);
305}
306
307static uiBut *ui_but_find(const ARegion *region,
308 const uiButFindPollFn find_poll,
309 const void *find_custom_data)
310{
311 LISTBASE_FOREACH (uiBlock *, block, &region->runtime->uiblocks) {
312 for (int i = block->buttons.size() - 1; i >= 0; i--) {
313 uiBut *but = block->buttons[i].get();
314 if (find_poll && find_poll(but, find_custom_data) == false) {
315 continue;
316 }
317 return but;
318 }
319 }
320
321 return nullptr;
322}
323
325 const int xy[2],
326 const bool labeledit,
327 const bool for_tooltip,
328 const uiButFindPollFn find_poll,
329 const void *find_custom_data)
330{
331 uiBut *butover = nullptr;
332
333 if (!ui_region_contains_point_px(region, xy)) {
334 return nullptr;
335 }
336 LISTBASE_FOREACH (uiBlock *, block, &region->runtime->uiblocks) {
337 float mx = xy[0], my = xy[1];
338 ui_window_to_block_fl(region, block, &mx, &my);
339
340 for (int i = block->buttons.size() - 1; i >= 0; i--) {
341 uiBut *but = block->buttons[i].get();
342 if (find_poll && find_poll(but, find_custom_data) == false) {
343 continue;
344 }
345 if (ui_but_is_interactive_ex(but, labeledit, for_tooltip)) {
346 if (but->pie_dir != UI_RADIAL_NONE) {
347 if (ui_but_isect_pie_seg(block, but)) {
348 butover = but;
349 break;
350 }
351 }
352 else if (ui_but_contains_pt(but, mx, my)) {
353 butover = but;
354 break;
355 }
356 }
357 }
358
359 /* CLIP_EVENTS prevents the event from reaching other blocks */
360 if (block->flag & UI_BLOCK_CLIP_EVENTS) {
361 /* check if mouse is inside block */
362 if (BLI_rctf_isect_pt(&block->rect, mx, my)) {
363 break;
364 }
365 }
366 }
367
368 return butover;
369}
370
371uiBut *UI_but_find_mouse_over(const ARegion *region, const wmEvent *event)
372{
374 region, event->xy, event->modifier & KM_CTRL, false, nullptr, nullptr);
375}
376
377uiBut *ui_but_find_rect_over(const ARegion *region, const rcti *rect_px)
378{
379 if (!ui_region_contains_rect_px(region, rect_px)) {
380 return nullptr;
381 }
382
383 /* Currently no need to expose this at the moment. */
384 const bool labeledit = true;
385 rctf rect_px_fl;
386 BLI_rctf_rcti_copy(&rect_px_fl, rect_px);
387 uiBut *butover = nullptr;
388
389 LISTBASE_FOREACH (uiBlock *, block, &region->runtime->uiblocks) {
390 rctf rect_block;
391 ui_window_to_block_rctf(region, block, &rect_block, &rect_px_fl);
392
393 for (int i = block->buttons.size() - 1; i >= 0; i--) {
394 uiBut *but = block->buttons[i].get();
395 if (ui_but_is_interactive(but, labeledit)) {
396 /* No pie menu support. */
398 if (ui_but_contains_rect(but, &rect_block)) {
399 butover = but;
400 break;
401 }
402 }
403 }
404
405 /* CLIP_EVENTS prevents the event from reaching other blocks */
406 if (block->flag & UI_BLOCK_CLIP_EVENTS) {
407 /* check if mouse is inside block */
408 if (BLI_rctf_isect(&block->rect, &rect_block, nullptr)) {
409 break;
410 }
411 }
412 }
413 return butover;
414}
415
416uiBut *ui_list_find_mouse_over_ex(const ARegion *region, const int xy[2])
417{
418 if (!ui_region_contains_point_px(region, xy)) {
419 return nullptr;
420 }
421 LISTBASE_FOREACH (uiBlock *, block, &region->runtime->uiblocks) {
422 float mx = xy[0], my = xy[1];
423 ui_window_to_block_fl(region, block, &mx, &my);
424 for (int i = block->buttons.size() - 1; i >= 0; i--) {
425 uiBut *but = block->buttons[i].get();
426 if (but->type == ButType::ListBox && ui_but_contains_pt(but, mx, my)) {
427 return but;
428 }
429 }
430 }
431
432 return nullptr;
433}
434
435uiBut *ui_list_find_mouse_over(const ARegion *region, const wmEvent *event)
436{
437 if (event == nullptr) {
438 /* If there is no info about the mouse, just act as if there is nothing underneath it. */
439 return nullptr;
440 }
441 return ui_list_find_mouse_over_ex(region, event->xy);
442}
443
444uiList *UI_list_find_mouse_over(const ARegion *region, const wmEvent *event)
445{
446 uiBut *list_but = ui_list_find_mouse_over(region, event);
447 if (!list_but) {
448 return nullptr;
449 }
450
451 return static_cast<uiList *>(list_but->custom_data);
452}
453
454static bool ui_list_contains_row(const uiBut *listbox_but, const uiBut *listrow_but)
455{
456 BLI_assert(listbox_but->type == ButType::ListBox);
457 BLI_assert(listrow_but->type == ButType::ListRow);
458 /* The list box and its rows have the same RNA data (active data pointer/prop). */
459 return ui_but_rna_equals(listbox_but, listrow_but);
460}
461
462static bool ui_but_is_listrow(const uiBut *but, const void * /*customdata*/)
463{
464 return but->type == ButType::ListRow;
465}
466
467uiBut *ui_list_row_find_mouse_over(const ARegion *region, const int xy[2])
468{
469 return ui_but_find_mouse_over_ex(region, xy, false, false, ui_but_is_listrow, nullptr);
470}
471
476
477static bool ui_but_is_listrow_at_index(const uiBut *but, const void *customdata)
478{
479 const ListRowFindIndexData *find_data = static_cast<const ListRowFindIndexData *>(customdata);
480
481 return ui_but_is_listrow(but, nullptr) && ui_list_contains_row(find_data->listbox, but) &&
482 (but->hardmax == find_data->index);
483}
484
485uiBut *ui_list_row_find_index(const ARegion *region, const int index, uiBut *listbox)
486{
487 BLI_assert(listbox->type == ButType::ListBox);
489 data.index = index;
490 data.listbox = listbox;
492}
493
494static bool ui_but_is_view_item_fn(const uiBut *but, const void * /*customdata*/)
495{
496 return but->type == ButType::ViewItem;
497}
498
499uiBut *ui_view_item_find_mouse_over(const ARegion *region, const int xy[2])
500{
501 return ui_but_find_mouse_over_ex(region, xy, false, false, ui_but_is_view_item_fn, nullptr);
502}
503
504static bool ui_but_is_active_view_item(const uiBut *but, const void * /*customdata*/)
505{
506 if (but->type != ButType::ViewItem) {
507 return false;
508 }
509
510 const uiButViewItem *view_item_but = (const uiButViewItem *)but;
511 return view_item_but->view_item->is_active();
512}
513
515{
516 return ui_but_find(region, ui_but_is_active_view_item, nullptr);
517}
518
520{
521 return ui_but_find(
522 region,
523 [](const uiBut *but, const void * /*find_custom_data*/) {
524 if (but->type != ButType::ViewItem) {
525 return false;
526 }
527
528 const uiButViewItem *view_item_but = static_cast<const uiButViewItem *>(but);
529 return view_item_but->view_item->is_search_highlight();
530 },
531 nullptr);
532}
533
535
536/* -------------------------------------------------------------------- */
539
541{
542 for (int idx = but->block->but_index(but) - 1; idx >= 0; idx--) {
543 but = but->block->buttons[idx].get();
544 if (ui_but_is_editable(but)) {
545 return but;
546 }
547 }
548 return nullptr;
549}
550
552{
553 for (int i = but->block->but_index(but) + 1; i < but->block->buttons.size(); i++) {
554 but = but->block->buttons[i].get();
555 if (ui_but_is_editable(but)) {
556 return but;
557 }
558 }
559 return nullptr;
560}
561
563{
564 for (const std::unique_ptr<uiBut> &but : block->buttons) {
565 if (ui_but_is_editable(but.get())) {
566 return but.get();
567 }
568 }
569 return nullptr;
570}
571
573{
574 for (int i = block->buttons.size() - 1; i >= 0; i--) {
575 uiBut *but = block->buttons[i].get();
576 if (ui_but_is_editable(but)) {
577 return but;
578 }
579 }
580 return nullptr;
581}
582
584{
585 if (U.uiflag & USER_CONTINUOUS_MOUSE) {
586 if (ELEM(but->type,
594 {
595 return true;
596 }
597 }
598
599 return false;
600}
601
603{
604 return but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD);
605}
606
608
609/* -------------------------------------------------------------------- */
612
614{
615 if (but->flag & UI_BUT_HAS_SEP_CHAR) {
616 const size_t sep_index = but->drawstr.find(UI_SEP_CHAR);
617 if (sep_index != std::string::npos) {
618 return sep_index;
619 }
620 }
621 return but->drawstr.size();
622}
623
625{
626 size_t str_len_clip = ui_but_drawstr_len_without_sep_char(but);
627 return blender::StringRef(but->drawstr).substr(0, str_len_clip);
628}
629
631{
632 if (but->tip == nullptr) {
633 return 0;
634 }
635 const int64_t str_step = but->tip.find('\n');
636 if (str_step == StringRef::not_found) {
637 return but->tip.size();
638 }
639 return str_step;
640}
641
643
644/* -------------------------------------------------------------------- */
647
649{
650 for (const std::unique_ptr<uiBut> &but : block->buttons) {
651 if (but->active) {
652 return but.get();
653 }
654 }
655
656 return nullptr;
657}
658
659bool ui_block_is_menu(const uiBlock *block)
660{
661 return (((block->flag & UI_BLOCK_LOOP) != 0) &&
662 /* non-menu popups use keep-open, so check this is off */
663 ((block->flag & UI_BLOCK_KEEP_OPEN) == 0));
664}
665
666bool ui_block_is_popover(const uiBlock *block)
667{
668 return (block->flag & UI_BLOCK_POPOVER) != 0;
669}
670
672{
673 return ((block->flag & UI_BLOCK_PIE_MENU) != 0);
674}
675
677{
678 return (ui_block_is_menu(block) || ui_block_is_popover(block) || ui_block_is_pie_menu(block));
679}
680
681static const uiBut *ui_but_next_non_separator(const uiBut *but)
682{
683 if (!but) {
684 return nullptr;
685 }
686 for (int i = but->block->but_index(but); i < but->block->buttons.size(); i++) {
687 but = but->block->buttons[i].get();
689 return but;
690 }
691 }
692 return nullptr;
693}
694
695bool UI_block_is_empty_ex(const uiBlock *block, const bool skip_title)
696{
697 const uiBut *but = block->first_but();
698 if (skip_title) {
699 /* Skip the first label, since popups often have a title,
700 * we may want to consider the block empty in this case. */
701 but = ui_but_next_non_separator(but);
702 if (but && but->type == ButType::Label) {
703 but = block->next_but(but);
704 }
705 }
706 return (ui_but_next_non_separator(but) == nullptr);
707}
708
709bool UI_block_is_empty(const uiBlock *block)
710{
711 return UI_block_is_empty_ex(block, false);
712}
713
715{
716 if (ui_block_is_menu(block) && !ui_block_is_pie_menu(block)) {
717 const uiBut *but = block->last_but();
718 return (but && !ELEM(but->type, ButType::SeprLine, ButType::Sepr));
719 }
720 return true;
721}
722
724{
725 for (const std::unique_ptr<uiBut> &but : block->buttons) {
726 if ((but->flag & UI_BUT_ACTIVE_DEFAULT) && ((but->flag & UI_HIDDEN) == 0)) {
727 return true;
728 }
729 }
730 return false;
731}
732
734
735/* -------------------------------------------------------------------- */
738
739uiBlock *ui_block_find_mouse_over_ex(const ARegion *region, const int xy[2], bool only_clip)
740{
741 if (!ui_region_contains_point_px(region, xy)) {
742 return nullptr;
743 }
744 LISTBASE_FOREACH (uiBlock *, block, &region->runtime->uiblocks) {
745 if (only_clip) {
746 if ((block->flag & UI_BLOCK_CLIP_EVENTS) == 0) {
747 continue;
748 }
749 }
750 float mx = xy[0], my = xy[1];
751 ui_window_to_block_fl(region, block, &mx, &my);
752 if (BLI_rctf_isect_pt(&block->rect, mx, my)) {
753 return block;
754 }
755 }
756 return nullptr;
757}
758
759uiBlock *ui_block_find_mouse_over(const ARegion *region, const wmEvent *event, bool only_clip)
760{
761 return ui_block_find_mouse_over_ex(region, event->xy, only_clip);
762}
763
765
766/* -------------------------------------------------------------------- */
769
771{
772 LISTBASE_FOREACH (uiBlock *, block, &region->runtime->uiblocks) {
773 uiBut *but = ui_block_active_but_get(block);
774 if (but) {
775 return but;
776 }
777 }
778
779 return nullptr;
780}
781
782uiBut *ui_region_find_first_but_test_flag(ARegion *region, int flag_include, int flag_exclude)
783{
784 LISTBASE_FOREACH (uiBlock *, block, &region->runtime->uiblocks) {
785 for (const std::unique_ptr<uiBut> &but : block->buttons) {
786 if (((but->flag & flag_include) == flag_include) && ((but->flag & flag_exclude) == 0)) {
787 return but.get();
788 }
789 }
790 }
791
792 return nullptr;
793}
794
796
797/* -------------------------------------------------------------------- */
800
801bool ui_region_contains_point_px(const ARegion *region, const int xy[2])
802{
803 rcti winrct;
804 ui_region_winrct_get_no_margin(region, &winrct);
805 if (!BLI_rcti_isect_pt_v(&winrct, xy)) {
806 return false;
807 }
808
809 /* also, check that with view2d, that the mouse is not over the scroll-bars
810 * NOTE: care is needed here, since the mask rect may include the scroll-bars
811 * even when they are not visible, so we need to make a copy of the mask to
812 * use to check
813 */
814 if (region->v2d.mask.xmin != region->v2d.mask.xmax) {
815 const View2D *v2d = &region->v2d;
816 int mx = xy[0], my = xy[1];
817
818 ui_window_to_region(region, &mx, &my);
819 if (!BLI_rcti_isect_pt(&v2d->mask, mx, my) ||
820 UI_view2d_mouse_in_scrollers(region, &region->v2d, xy))
821 {
822 return false;
823 }
824 }
825
826 return true;
827}
828
829bool ui_region_contains_rect_px(const ARegion *region, const rcti *rect_px)
830{
831 rcti winrct;
832 ui_region_winrct_get_no_margin(region, &winrct);
833 if (!BLI_rcti_isect(&winrct, rect_px, nullptr)) {
834 return false;
835 }
836
837 /* See comment in 'ui_region_contains_point_px' */
838 if (region->v2d.mask.xmin != region->v2d.mask.xmax) {
839 const View2D *v2d = &region->v2d;
840 rcti rect_region;
841 ui_window_to_region_rcti(region, &rect_region, rect_px);
842 if (!BLI_rcti_isect(&v2d->mask, &rect_region, nullptr) ||
843 UI_view2d_rect_in_scrollers(region, &region->v2d, rect_px))
844 {
845 return false;
846 }
847 }
848
849 return true;
850}
851
853
854/* -------------------------------------------------------------------- */
857
859{
860 LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
861 rcti winrct;
862
863 ui_region_winrct_get_no_margin(region, &winrct);
864
865 if (BLI_rcti_isect_pt_v(&winrct, xy)) {
866 return region;
867 }
868 }
869 return nullptr;
870}
871
873{
874 return ui_screen_region_find_mouse_over_ex(screen, event->xy);
875}
876
878
879/* -------------------------------------------------------------------- */
882
887
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
#define DEG2RADF(_deg)
#define M_SQRT1_2
float angle_signed_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
bool BLI_rcti_isect_pt_v(const struct rcti *rect, const int xy[2])
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:198
bool BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest)
bool BLI_rcti_isect_pt(const struct rcti *rect, int x, int y)
bool BLI_rcti_isect(const struct rcti *src1, const struct rcti *src2, struct rcti *dest)
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:194
bool BLI_rctf_isect_pt(const struct rctf *rect, float x, float y)
void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src)
void BLI_rcti_rctf_copy(struct rcti *dst, const struct rctf *src)
#define UNLIKELY(x)
#define ELEM(...)
@ USER_CONTINUOUS_MOUSE
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
@ PROP_BYTESTRING
Definition RNA_types.hh:240
@ PROP_FILENAME
Definition RNA_types.hh:238
@ PROP_PASSWORD
Definition RNA_types.hh:243
@ PROP_DIRPATH
Definition RNA_types.hh:237
@ PROP_FILEPATH
Definition RNA_types.hh:236
@ UI_BLOCK_CLIP_EVENTS
@ UI_BLOCK_LOOP
@ UI_BLOCK_PIE_MENU
@ UI_BLOCK_KEEP_OPEN
@ UI_BLOCK_POPOVER
#define UI_SEP_CHAR
@ UI_BUT_ACTIVE_DEFAULT
@ UI_BUT_NO_UTF8
@ UI_BUT_HAS_SEP_CHAR
@ UI_BUT_ICON_PREVIEW
@ UI_BUT_DRAG_FULL_BUT
@ UI_BUT_ICON_LEFT
@ UI_BUT_HAS_QUICK_TOOLTIP
@ UI_BUT_ICON_REVERSE
char char UI_view2d_mouse_in_scrollers(const ARegion *region, const View2D *v2d, const int xy[2]) ATTR_NONNULL(1
char char char char UI_view2d_rect_in_scrollers(const ARegion *region, const View2D *v2d, const rcti *rect) ATTR_NONNULL(1
@ KM_CTRL
Definition WM_types.hh:279
#define U
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
long long int int64_t
int64_t size() const
static constexpr int64_t not_found
constexpr int64_t find(char c, int64_t pos=0) const
constexpr StringRef substr(int64_t start, int64_t size) const
constexpr int64_t size() const
void ui_window_to_block(const ARegion *region, const uiBlock *block, int *x, int *y)
Definition interface.cc:228
const short ui_radial_dir_to_angle[8]
void ui_window_to_region_rcti(const ARegion *region, rcti *rect_dst, const rcti *rct_src)
Definition interface.cc:245
void ui_window_to_region(const ARegion *region, int *x, int *y)
Definition interface.cc:239
void ui_window_to_block_fl(const ARegion *region, const uiBlock *block, float *x, float *y)
Definition interface.cc:191
bool ui_but_rna_equals(const uiBut *a, const uiBut *b)
Definition interface.cc:766
void ui_window_to_block_rctf(const ARegion *region, const uiBlock *block, rctf *rct_dst, const rctf *rct_src)
Definition interface.cc:218
void ui_region_winrct_get_no_margin(const ARegion *region, rcti *r_rect)
Definition interface.cc:388
bool ui_but_drag_is_draggable(const uiBut *but)
bool ui_icon_is_preview_deferred_loading(const int icon_id, const bool big)
@ UI_PIE_INVALID_DIR
#define UI_RADIAL_DIRECTION_NEXT(dir)
bool ui_but_is_toggle(const uiBut *but) ATTR_WARN_UNUSED_RESULT
bool(*)(const uiBut *but, const void *customdata) uiButFindPollFn
RadialDirection
@ UI_RADIAL_NONE
#define UI_RADIAL_DIRECTION_PREV(dir)
bool ui_but_contains_pt(const uiBut *but, float mx, float my) ATTR_WARN_UNUSED_RESULT
@ UI_HIDDEN
@ UI_SCROLLED
@ UI_HAS_ICON
uiBut * ui_list_find_mouse_over(const ARegion *region, const wmEvent *event)
size_t ui_but_drawstr_len_without_sep_char(const uiBut *but)
uiList * UI_list_find_mouse_over(const ARegion *region, const wmEvent *event)
static bool ui_but_is_listrow_at_index(const uiBut *but, const void *customdata)
uiBut * ui_block_active_but_get(const uiBlock *block)
bool UI_block_is_empty_ex(const uiBlock *block, const bool skip_title)
blender::StringRef ui_but_drawstr_without_sep_char(const uiBut *but)
bool UI_block_can_add_separator(const uiBlock *block)
bool ui_but_contains_point_px(const uiBut *but, const ARegion *region, const int xy[2])
bool UI_but_has_quick_tooltip(const uiBut *but)
bool ui_block_is_popup_any(const uiBlock *block)
static uiBut * ui_but_find(const ARegion *region, const uiButFindPollFn find_poll, const void *find_custom_data)
bool ui_but_is_toggle(const uiBut *but)
bool ui_but_contains_pt(const uiBut *but, float mx, float my)
uiBut * ui_but_find_mouse_over_ex(const ARegion *region, const int xy[2], const bool labeledit, const bool for_tooltip, const uiButFindPollFn find_poll, const void *find_custom_data)
uiBut * ui_but_next(uiBut *but)
bool ui_but_contains_rect(const uiBut *but, const rctf *rect)
bool ui_but_contains_password(const uiBut *but)
ARegion * ui_screen_region_find_mouse_over(bScreen *screen, const wmEvent *event)
bool UI_but_is_utf8(const uiBut *but)
size_t ui_but_tip_len_only_first_line(const uiBut *but)
bool UI_block_is_empty(const uiBlock *block)
uiBut * ui_view_item_find_active(const ARegion *region)
static const uiBut * ui_but_next_non_separator(const uiBut *but)
static wmOperatorType * g_ot_tool_set_by_id
static bool ui_list_contains_row(const uiBut *listbox_but, const uiBut *listrow_but)
void ui_interface_tag_script_reload_queries()
uiBut * ui_list_row_find_mouse_over(const ARegion *region, const int xy[2])
static bool ui_but_is_active_view_item(const uiBut *but, const void *)
static bool ui_but_isect_pie_seg(const uiBlock *block, const uiBut *but)
bool ui_but_contains_point_px_icon(const uiBut *but, ARegion *region, const wmEvent *event)
bool ui_block_is_popover(const uiBlock *block)
uiBlock * ui_block_find_mouse_over_ex(const ARegion *region, const int xy[2], bool only_clip)
bool ui_but_is_editable(const uiBut *but)
ARegion * ui_screen_region_find_mouse_over_ex(bScreen *screen, const int xy[2])
bool ui_block_is_pie_menu(const uiBlock *block)
bool ui_but_is_cursor_warp(const uiBut *but)
bool UI_block_has_active_default_button(const uiBlock *block)
uiBut * ui_view_item_find_mouse_over(const ARegion *region, const int xy[2])
bool ui_region_contains_point_px(const ARegion *region, const int xy[2])
uiBut * ui_view_item_find_search_highlight(const ARegion *region)
uiBlock * ui_block_find_mouse_over(const ARegion *region, const wmEvent *event, bool only_clip)
uiBut * ui_region_find_first_but_test_flag(ARegion *region, int flag_include, int flag_exclude)
bool ui_but_is_interactive_ex(const uiBut *but, const bool labeledit, const bool for_tooltip)
uiBut * ui_but_prev(uiBut *but)
static bool ui_but_is_view_item_fn(const uiBut *but, const void *)
uiBut * UI_but_find_mouse_over(const ARegion *region, const wmEvent *event)
uiBut * ui_list_find_mouse_over_ex(const ARegion *region, const int xy[2])
bool ui_block_is_menu(const uiBlock *block)
bool ui_region_contains_rect_px(const ARegion *region, const rcti *rect_px)
bool ui_but_is_popover_once_compat(const uiBut *but)
bool ui_but_is_interactive(const uiBut *but, const bool labeledit)
void ui_but_pie_dir(RadialDirection dir, float vec[2])
uiBut * ui_region_find_active_but(ARegion *region)
int ui_but_icon(const uiBut *but)
uiBut * ui_but_last(uiBlock *block)
bool ui_but_is_editable_as_text(const uiBut *but)
bool UI_but_is_tool(const uiBut *but)
uiBut * ui_but_first(uiBlock *block)
uiBut * ui_but_find_rect_over(const ARegion *region, const rcti *rect_px)
static bool ui_but_is_listrow(const uiBut *but, const void *)
uiBut * ui_list_row_find_index(const ARegion *region, const int index, uiBut *listbox)
bool ui_but_has_array_value(const uiBut *but)
#define sinf
#define cosf
bool RNA_property_array_check(PropertyRNA *prop)
PropertySubType RNA_property_subtype(PropertyRNA *prop)
ARegionRuntimeHandle * runtime
void * data
Definition RNA_types.hh:53
ListBase regionbase
int xmin
int xmax
blender::Vector< std::unique_ptr< uiBut > > buttons
PieMenuData pie_data
uiBut * first_but() const
Definition interface.cc:304
int but_index(const uiBut *but) const
Definition interface.cc:274
uiBut * next_but(const uiBut *but) const
Definition interface.cc:286
uiBut * last_but() const
Definition interface.cc:309
blender::ui::AbstractViewItem * view_item
int8_t dragflag
void * custom_data
RadialDirection pie_dir
blender::ui::EmbossType emboss
PropertyRNA * rnaprop
wmOperatorType * optype
std::function< std::string(const uiBut *)> tip_quick_func
ButType type
uiBlock * block
uiButToolTipFunc tip_func
std::string drawstr
BIFIconID icon
PointerRNA rnapoin
blender::StringRef tip
uiButToolTipCustomFunc tip_custom_func
wmEventModifierFlag modifier
Definition WM_types.hh:774
int xy[2]
Definition WM_types.hh:761
i
Definition text_draw.cc:230
int xy[2]
Definition wm_draw.cc:178
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)