Blender  V2.93
area_query.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
23 #include "DNA_userdef_types.h"
24 
25 #include "BLI_blenlib.h"
26 #include "BLI_math_base.h"
27 #include "BLI_utildefines.h"
28 
29 #include "RNA_types.h"
30 
31 #include "ED_screen.h"
32 
33 #include "UI_interface.h"
34 #include "UI_view2d.h"
35 
36 bool ED_region_overlap_isect_x(const ARegion *region, const int event_x)
37 {
38  BLI_assert(region->overlap);
39  /* No contents, skip it. */
40  if (region->v2d.mask.xmin == region->v2d.mask.xmax) {
41  return false;
42  }
43  return BLI_rctf_isect_x(&region->v2d.tot,
44  UI_view2d_region_to_view_x(&region->v2d, event_x - region->winrct.xmin));
45 }
46 
47 bool ED_region_overlap_isect_y(const ARegion *region, const int event_y)
48 {
49  BLI_assert(region->overlap);
50  /* No contents, skip it. */
51  if (region->v2d.mask.ymin == region->v2d.mask.ymax) {
52  return false;
53  }
54  return BLI_rctf_isect_y(&region->v2d.tot,
55  UI_view2d_region_to_view_y(&region->v2d, event_y - region->winrct.ymin));
56 }
57 
58 bool ED_region_overlap_isect_xy(const ARegion *region, const int event_xy[2])
59 {
60  return (ED_region_overlap_isect_x(region, event_xy[0]) &&
61  ED_region_overlap_isect_y(region, event_xy[1]));
62 }
63 
64 bool ED_region_overlap_isect_any_xy(const ScrArea *area, const int event_xy[2])
65 {
66  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
67  if (ED_region_is_overlap(area->spacetype, region->regiontype)) {
68  if (ED_region_overlap_isect_xy(region, event_xy)) {
69  return true;
70  }
71  }
72  }
73  return false;
74 }
75 
76 bool ED_region_panel_category_gutter_calc_rect(const ARegion *region, rcti *r_region_gutter)
77 {
78  *r_region_gutter = region->winrct;
79  if (UI_panel_category_is_visible(region)) {
80  const int category_tabs_width = round_fl_to_int(UI_view2d_scale_get_x(&region->v2d) *
82  const int alignment = RGN_ALIGN_ENUM_FROM_MASK(region->alignment);
83 
84  if (alignment == RGN_ALIGN_LEFT) {
85  r_region_gutter->xmax = r_region_gutter->xmin + category_tabs_width;
86  }
87  else if (alignment == RGN_ALIGN_RIGHT) {
88  r_region_gutter->xmin = r_region_gutter->xmax - category_tabs_width;
89  }
90  else {
91  BLI_assert(!"Unsupported alignment");
92  }
93  return true;
94  }
95  return false;
96 }
97 
98 bool ED_region_panel_category_gutter_isect_xy(const ARegion *region, const int event_xy[2])
99 {
100  rcti region_gutter;
101  if (ED_region_panel_category_gutter_calc_rect(region, &region_gutter)) {
102  return BLI_rcti_isect_pt_v(&region_gutter, event_xy);
103  }
104  return false;
105 }
106 
108  const int event_x,
109  const int margin)
110 {
111  BLI_assert(region->overlap);
112  /* No contents, skip it. */
113  if (region->v2d.mask.xmin == region->v2d.mask.xmax) {
114  return false;
115  }
116  int region_x = event_x - region->winrct.xmin;
117  return ((region->v2d.tot.xmin <= UI_view2d_region_to_view_x(&region->v2d, region_x + margin)) &&
118  (region->v2d.tot.xmax >= UI_view2d_region_to_view_x(&region->v2d, region_x - margin)));
119 }
120 
122  const int event_y,
123  const int margin)
124 {
125  BLI_assert(region->overlap);
126  /* No contents, skip it. */
127  if (region->v2d.mask.ymin == region->v2d.mask.ymax) {
128  return false;
129  }
130  int region_y = event_y - region->winrct.ymin;
131  return ((region->v2d.tot.ymin <= UI_view2d_region_to_view_y(&region->v2d, region_y + margin)) &&
132  (region->v2d.tot.ymax >= UI_view2d_region_to_view_y(&region->v2d, region_y - margin)));
133 }
134 
136  const int event_xy[2],
137  const int margin)
138 {
139  return (ED_region_overlap_isect_x_with_margin(region, event_xy[0], margin) &&
140  ED_region_overlap_isect_y_with_margin(region, event_xy[1], margin));
141 }
142 
143 bool ED_region_contains_xy(const ARegion *region, const int event_xy[2])
144 {
145  /* Only use the margin when inside the region. */
146  if (BLI_rcti_isect_pt_v(&region->winrct, event_xy)) {
147  if (region->overlap) {
148  const int overlap_margin = UI_REGION_OVERLAP_MARGIN;
149  /* Note the View2D.tot isn't reliable for headers with spacers otherwise
150  * we'd check #ED_region_overlap_isect_xy_with_margin for both bases. */
151  if (region->v2d.keeptot == V2D_KEEPTOT_STRICT) {
152  /* Header. */
153  rcti rect;
154  BLI_rcti_init_pt_radius(&rect, event_xy, overlap_margin);
155  if (UI_region_but_find_rect_over(region, &rect) == NULL) {
156  return false;
157  }
158  }
159  else {
160  /* Side-bar & any other kind of overlapping region. */
161 
162  const int alignment = RGN_ALIGN_ENUM_FROM_MASK(region->alignment);
163 
164  /* Check alignment to avoid region tabs being clipped out
165  * by only clipping a single axis for aligned regions. */
166  if (ELEM(alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
167  if (!ED_region_overlap_isect_x_with_margin(region, event_xy[0], overlap_margin)) {
168  return false;
169  }
170  }
171  else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
172  if (ED_region_panel_category_gutter_isect_xy(region, event_xy)) {
173  /* pass */
174  }
175  else if (!ED_region_overlap_isect_y_with_margin(region, event_xy[1], overlap_margin)) {
176  return false;
177  }
178  }
179  else {
180  /* No panel categories for horizontal regions currently. */
181  if (!ED_region_overlap_isect_xy_with_margin(region, event_xy, overlap_margin)) {
182  return false;
183  }
184  }
185  }
186  }
187  return true;
188  }
189  return false;
190 }
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
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, const float x)
Definition: rct.c:114
bool BLI_rctf_isect_y(const rctf *rect, const float y)
Definition: rct.c:125
void BLI_rcti_init_pt_radius(struct rcti *rect, const int xy[2], int size)
Definition: rct.c:508
#define ELEM(...)
#define RGN_ALIGN_ENUM_FROM_MASK(align)
@ RGN_ALIGN_BOTTOM
@ RGN_ALIGN_LEFT
@ RGN_ALIGN_TOP
@ RGN_ALIGN_RIGHT
@ V2D_KEEPTOT_STRICT
bool ED_region_is_overlap(int spacetype, int regiontype)
Definition: area.c:1259
#define UI_REGION_OVERLAP_MARGIN
Definition: UI_interface.h:100
#define UI_PANEL_CATEGORY_MARGIN_WIDTH
Definition: UI_interface.h:249
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.c:1659
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.c:1664
bool ED_region_panel_category_gutter_isect_xy(const ARegion *region, const int event_xy[2])
Definition: area_query.c:98
bool ED_region_overlap_isect_any_xy(const ScrArea *area, const int event_xy[2])
Definition: area_query.c:64
bool ED_region_contains_xy(const ARegion *region, const int event_xy[2])
Definition: area_query.c:143
bool ED_region_overlap_isect_x_with_margin(const ARegion *region, const int event_x, const int margin)
Definition: area_query.c:107
bool ED_region_overlap_isect_y(const ARegion *region, const int event_y)
Definition: area_query.c:47
bool ED_region_overlap_isect_xy(const ARegion *region, const int event_xy[2])
Definition: area_query.c:58
bool ED_region_panel_category_gutter_calc_rect(const ARegion *region, rcti *r_region_gutter)
Definition: area_query.c:76
bool ED_region_overlap_isect_x(const ARegion *region, const int event_x)
Definition: area_query.c:36
bool ED_region_overlap_isect_y_with_margin(const ARegion *region, const int event_y, const int margin)
Definition: area_query.c:121
bool ED_region_overlap_isect_xy_with_margin(const ARegion *region, const int event_xy[2], const int margin)
Definition: area_query.c:135
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:85
float xmin
Definition: DNA_vec_types.h:85
float ymax
Definition: DNA_vec_types.h:86
float ymin
Definition: DNA_vec_types.h:86
int ymin
Definition: DNA_vec_types.h:80
int ymax
Definition: DNA_vec_types.h:80
int xmin
Definition: DNA_vec_types.h:79
int xmax
Definition: DNA_vec_types.h:79