Blender  V3.3
area_query.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include "DNA_userdef_types.h"
10 
11 #include "BLI_blenlib.h"
12 #include "BLI_math_base.h"
13 #include "BLI_utildefines.h"
14 
15 #include "RNA_types.h"
16 
17 #include "ED_screen.h"
18 
19 #include "UI_interface.h"
20 #include "UI_view2d.h"
21 
22 bool ED_region_overlap_isect_x(const ARegion *region, const int event_x)
23 {
24  BLI_assert(region->overlap);
25  /* No contents, skip it. */
26  if (region->v2d.mask.xmin == region->v2d.mask.xmax) {
27  return false;
28  }
29  return BLI_rctf_isect_x(&region->v2d.tot,
30  UI_view2d_region_to_view_x(&region->v2d, event_x - region->winrct.xmin));
31 }
32 
33 bool ED_region_overlap_isect_y(const ARegion *region, const int event_y)
34 {
35  BLI_assert(region->overlap);
36  /* No contents, skip it. */
37  if (region->v2d.mask.ymin == region->v2d.mask.ymax) {
38  return false;
39  }
40  return BLI_rctf_isect_y(&region->v2d.tot,
41  UI_view2d_region_to_view_y(&region->v2d, event_y - region->winrct.ymin));
42 }
43 
44 bool ED_region_overlap_isect_xy(const ARegion *region, const int event_xy[2])
45 {
46  return (ED_region_overlap_isect_x(region, event_xy[0]) &&
47  ED_region_overlap_isect_y(region, event_xy[1]));
48 }
49 
50 bool ED_region_overlap_isect_any_xy(const ScrArea *area, const int event_xy[2])
51 {
52  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
53  if (ED_region_is_overlap(area->spacetype, region->regiontype)) {
54  if (ED_region_overlap_isect_xy(region, event_xy)) {
55  return true;
56  }
57  }
58  }
59  return false;
60 }
61 
62 bool ED_region_panel_category_gutter_calc_rect(const ARegion *region, rcti *r_region_gutter)
63 {
64  *r_region_gutter = region->winrct;
65  if (UI_panel_category_is_visible(region)) {
66  const int category_tabs_width = round_fl_to_int(UI_view2d_scale_get_x(&region->v2d) *
68  const int alignment = RGN_ALIGN_ENUM_FROM_MASK(region->alignment);
69 
70  if (alignment == RGN_ALIGN_LEFT) {
71  r_region_gutter->xmax = r_region_gutter->xmin + category_tabs_width;
72  }
73  else if (alignment == RGN_ALIGN_RIGHT) {
74  r_region_gutter->xmin = r_region_gutter->xmax - category_tabs_width;
75  }
76  else {
77  BLI_assert_msg(0, "Unsupported alignment");
78  }
79  return true;
80  }
81  return false;
82 }
83 
84 bool ED_region_panel_category_gutter_isect_xy(const ARegion *region, const int event_xy[2])
85 {
86  rcti region_gutter;
87  if (ED_region_panel_category_gutter_calc_rect(region, &region_gutter)) {
88  return BLI_rcti_isect_pt_v(&region_gutter, event_xy);
89  }
90  return false;
91 }
92 
94  const int event_x,
95  const int margin)
96 {
97  BLI_assert(region->overlap);
98  /* No contents, skip it. */
99  if (region->v2d.mask.xmin == region->v2d.mask.xmax) {
100  return false;
101  }
102  int region_x = event_x - region->winrct.xmin;
103  return ((region->v2d.tot.xmin <= UI_view2d_region_to_view_x(&region->v2d, region_x + margin)) &&
104  (region->v2d.tot.xmax >= UI_view2d_region_to_view_x(&region->v2d, region_x - margin)));
105 }
106 
108  const int event_y,
109  const int margin)
110 {
111  BLI_assert(region->overlap);
112  /* No contents, skip it. */
113  if (region->v2d.mask.ymin == region->v2d.mask.ymax) {
114  return false;
115  }
116  int region_y = event_y - region->winrct.ymin;
117  return ((region->v2d.tot.ymin <= UI_view2d_region_to_view_y(&region->v2d, region_y + margin)) &&
118  (region->v2d.tot.ymax >= UI_view2d_region_to_view_y(&region->v2d, region_y - margin)));
119 }
120 
122  const int event_xy[2],
123  const int margin)
124 {
125  return (ED_region_overlap_isect_x_with_margin(region, event_xy[0], margin) &&
126  ED_region_overlap_isect_y_with_margin(region, event_xy[1], margin));
127 }
128 
129 bool ED_region_contains_xy(const ARegion *region, const int event_xy[2])
130 {
131  /* Only use the margin when inside the region. */
132  if (BLI_rcti_isect_pt_v(&region->winrct, event_xy)) {
133  if (region->overlap) {
134  const int overlap_margin = UI_REGION_OVERLAP_MARGIN;
135  /* Note the View2D.tot isn't reliable for headers with spacers otherwise
136  * we'd check #ED_region_overlap_isect_xy_with_margin for both bases. */
137  if (region->v2d.keeptot == V2D_KEEPTOT_STRICT) {
138  /* Header. */
139  rcti rect;
140  BLI_rcti_init_pt_radius(&rect, event_xy, overlap_margin);
141  if (UI_region_but_find_rect_over(region, &rect) == NULL) {
142  return false;
143  }
144  }
145  else {
146  /* Side-bar & any other kind of overlapping region. */
147 
148  const int alignment = RGN_ALIGN_ENUM_FROM_MASK(region->alignment);
149 
150  /* Check alignment to avoid region tabs being clipped out
151  * by only clipping a single axis for aligned regions. */
152  if (ELEM(alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
153  if (!ED_region_overlap_isect_x_with_margin(region, event_xy[0], overlap_margin)) {
154  return false;
155  }
156  }
157  else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
158  if (ED_region_panel_category_gutter_isect_xy(region, event_xy)) {
159  /* pass */
160  }
161  else if (!ED_region_overlap_isect_y_with_margin(region, event_xy[1], overlap_margin)) {
162  return false;
163  }
164  }
165  else {
166  /* No panel categories for horizontal regions currently. */
167  if (!ED_region_overlap_isect_xy_with_margin(region, event_xy, overlap_margin)) {
168  return false;
169  }
170  }
171  }
172  }
173  return true;
174  }
175  return false;
176 }
177 
179  const int regiontype,
180  const int event_xy[2])
181 {
182  if (!area) {
183  return NULL;
184  }
185 
186  /* Check overlapped regions first. */
187  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
188  if (!region->overlap) {
189  continue;
190  }
191  if (ELEM(regiontype, RGN_TYPE_ANY, region->regiontype)) {
192  if (ED_region_contains_xy(region, event_xy)) {
193  return region;
194  }
195  }
196  }
197  /* Now non-overlapping ones. */
198  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
199  if (region->overlap) {
200  continue;
201  }
202  if (ELEM(regiontype, RGN_TYPE_ANY, region->regiontype)) {
203  if (ED_region_contains_xy(region, event_xy)) {
204  return region;
205  }
206  }
207  }
208 
209  return NULL;
210 }
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
MINLINE int round_fl_to_int(float a)
bool BLI_rcti_isect_pt_v(const struct rcti *rect, const int xy[2])
bool BLI_rctf_isect_x(const rctf *rect, float x)
Definition: rct.c:92
void BLI_rcti_init_pt_radius(struct rcti *rect, const int xy[2], int size)
Definition: rct.c:469
bool BLI_rctf_isect_y(const rctf *rect, float y)
Definition: rct.c:103
#define ELEM(...)
#define RGN_ALIGN_ENUM_FROM_MASK(align)
@ RGN_ALIGN_BOTTOM
@ RGN_ALIGN_LEFT
@ RGN_ALIGN_TOP
@ RGN_ALIGN_RIGHT
#define RGN_TYPE_ANY
@ V2D_KEEPTOT_STRICT
bool ED_region_is_overlap(int spacetype, int regiontype)
Definition: area.c:1248
#define UI_REGION_OVERLAP_MARGIN
Definition: UI_interface.h:101
#define UI_PANEL_CATEGORY_MARGIN_WIDTH
Definition: UI_interface.h:246
bool UI_panel_category_is_visible(const struct ARegion *region)
uiBut * UI_region_but_find_rect_over(const struct ARegion *region, const struct rcti *rect_px)
float UI_view2d_region_to_view_x(const struct View2D *v2d, float x)
Definition: view2d.cc:1655
float UI_view2d_scale_get_x(const struct View2D *v2d)
float UI_view2d_region_to_view_y(const struct View2D *v2d, float y)
Definition: view2d.cc:1660
bool ED_region_panel_category_gutter_isect_xy(const ARegion *region, const int event_xy[2])
Definition: area_query.c:84
bool ED_region_overlap_isect_any_xy(const ScrArea *area, const int event_xy[2])
Definition: area_query.c:50
ARegion * ED_area_find_region_xy_visual(const ScrArea *area, const int regiontype, const int event_xy[2])
Definition: area_query.c:178
bool ED_region_contains_xy(const ARegion *region, const int event_xy[2])
Definition: area_query.c:129
bool ED_region_overlap_isect_x_with_margin(const ARegion *region, const int event_x, const int margin)
Definition: area_query.c:93
bool ED_region_overlap_isect_y(const ARegion *region, const int event_y)
Definition: area_query.c:33
bool ED_region_overlap_isect_xy(const ARegion *region, const int event_xy[2])
Definition: area_query.c:44
bool ED_region_panel_category_gutter_calc_rect(const ARegion *region, rcti *r_region_gutter)
Definition: area_query.c:62
bool ED_region_overlap_isect_x(const ARegion *region, const int event_x)
Definition: area_query.c:22
bool ED_region_overlap_isect_y_with_margin(const ARegion *region, const int event_y, const int margin)
Definition: area_query.c:107
bool ED_region_overlap_isect_xy_with_margin(const ARegion *region, const int event_xy[2], const int margin)
Definition: area_query.c:121
static void area(int d1, int d2, int e1, int e2, float weights[2])
short alignment
short keeptot
float xmax
Definition: DNA_vec_types.h:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63