Blender  V3.3
screen_geometry.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
11 #include "BLI_listbase.h"
12 #include "BLI_math.h"
13 #include "BLI_rect.h"
14 
15 #include "BKE_screen.h"
16 
17 #include "DNA_screen_types.h"
19 
20 #include "ED_screen.h"
21 
22 #include "MEM_guardedalloc.h"
23 
24 #include "WM_api.h"
25 
26 #include "screen_intern.h"
27 
29 {
30  return area->v2->vec.y - area->v1->vec.y + 1;
31 }
33 {
34  return area->v4->vec.x - area->v1->vec.x + 1;
35 }
36 
37 ScrVert *screen_geom_vertex_add_ex(ScrAreaMap *area_map, short x, short y)
38 {
39  ScrVert *sv = MEM_callocN(sizeof(ScrVert), "addscrvert");
40  sv->vec.x = x;
41  sv->vec.y = y;
42 
43  BLI_addtail(&area_map->vertbase, sv);
44  return sv;
45 }
46 ScrVert *screen_geom_vertex_add(bScreen *screen, short x, short y)
47 {
49 }
50 
52 {
53  ScrEdge *se = MEM_callocN(sizeof(ScrEdge), "addscredge");
54 
56  se->v1 = v1;
57  se->v2 = v2;
58 
59  BLI_addtail(&area_map->edgebase, se);
60  return se;
61 }
63 {
65 }
66 
68 {
69  return (se->v1->vec.y == se->v2->vec.y);
70 }
71 
73  const rcti *bounds_rect,
74  const int mx,
75  const int my)
76 {
77  int safety = BORDERPADDING;
78 
79  CLAMP_MIN(safety, 2);
80 
81  LISTBASE_FOREACH (ScrEdge *, se, &area_map->edgebase) {
83  if ((se->v1->vec.y > bounds_rect->ymin) && (se->v1->vec.y < (bounds_rect->ymax - 1))) {
84  short min, max;
85  min = MIN2(se->v1->vec.x, se->v2->vec.x);
86  max = MAX2(se->v1->vec.x, se->v2->vec.x);
87 
88  if (abs(my - se->v1->vec.y) <= safety && mx >= min && mx <= max) {
89  return se;
90  }
91  }
92  }
93  else {
94  if ((se->v1->vec.x > bounds_rect->xmin) && (se->v1->vec.x < (bounds_rect->xmax - 1))) {
95  short min, max;
96  min = MIN2(se->v1->vec.y, se->v2->vec.y);
97  max = MAX2(se->v1->vec.y, se->v2->vec.y);
98 
99  if (abs(mx - se->v1->vec.x) <= safety && my >= min && my <= max) {
100  return se;
101  }
102  }
103  }
104  }
105 
106  return NULL;
107 }
108 
110  const bScreen *screen,
111  const int mx,
112  const int my)
113 {
114  if (U.app_flag & USER_APP_LOCK_EDGE_RESIZE) {
115  return NULL;
116  }
117 
118  /* Use layout size (screen excluding global areas) for screen-layout area edges */
119  rcti screen_rect;
120  WM_window_screen_rect_calc(win, &screen_rect);
122  AREAMAP_FROM_SCREEN(screen), &screen_rect, mx, my);
123 
124  if (!se) {
125  /* Use entire window size (screen including global areas) for global area edges */
126  rcti win_rect;
127  WM_window_rect_calc(win, &win_rect);
128  se = screen_geom_area_map_find_active_scredge(&win->global_areas, &win_rect, mx, my);
129  }
130  return se;
131 }
132 
138  const bScreen *screen,
139  const rcti *screen_rect)
140 {
141 
142  const int screen_size_x = BLI_rcti_size_x(screen_rect);
143  const int screen_size_y = BLI_rcti_size_y(screen_rect);
144  bool needs_another_pass = false;
145 
146  /* calculate size */
147  float min[2] = {20000.0f, 20000.0f};
148  float max[2] = {0.0f, 0.0f};
149 
150  LISTBASE_FOREACH (ScrVert *, sv, &screen->vertbase) {
151  const float fv[2] = {(float)sv->vec.x, (float)sv->vec.y};
152  minmax_v2v2_v2(min, max, fv);
153  }
154 
155  int screen_size_x_prev = (max[0] - min[0]) + 1;
156  int screen_size_y_prev = (max[1] - min[1]) + 1;
157 
158  if (screen_size_x_prev != screen_size_x || screen_size_y_prev != screen_size_y) {
159  const float facx = ((float)screen_size_x - 1) / ((float)screen_size_x_prev - 1);
160  const float facy = ((float)screen_size_y - 1) / ((float)screen_size_y_prev - 1);
161 
162  /* make sure it fits! */
163  LISTBASE_FOREACH (ScrVert *, sv, &screen->vertbase) {
164  sv->vec.x = screen_rect->xmin + round_fl_to_short((sv->vec.x - min[0]) * facx);
165  CLAMP(sv->vec.x, screen_rect->xmin, screen_rect->xmax - 1);
166 
167  sv->vec.y = screen_rect->ymin + round_fl_to_short((sv->vec.y - min[1]) * facy);
168  CLAMP(sv->vec.y, screen_rect->ymin, screen_rect->ymax - 1);
169  }
170 
171  /* test for collapsed areas. This could happen in some blender version... */
172  /* ton: removed option now, it needs Context... */
173 
174  int headery = ED_area_headersize() + (U.pixelsize * 2);
175 
176  if (facy > 1) {
177  /* Keep timeline small in video edit workspace. */
178  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
179  if (area->spacetype == SPACE_ACTION && area->v1->vec.y == screen_rect->ymin &&
180  screen_geom_area_height(area) <= headery * facy + 1) {
181  ScrEdge *se = BKE_screen_find_edge(screen, area->v2, area->v3);
182  if (se) {
183  const int yval = area->v1->vec.y + headery - 1;
184 
186 
187  /* all selected vertices get the right offset */
188  LISTBASE_FOREACH (ScrVert *, sv, &screen->vertbase) {
189  /* if is a collapsed area */
190  if (!ELEM(sv, area->v1, area->v4)) {
191  if (sv->flag) {
192  sv->vec.y = yval;
193  /* Changed size of a area. Run another pass to ensure everything still fits. */
194  needs_another_pass = true;
195  }
196  }
197  }
198  }
199  }
200  }
201  }
202  if (facy < 1) {
203  /* make each window at least ED_area_headersize() high */
204  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
205  if (screen_geom_area_height(area) < headery) {
206  /* lower edge */
207  ScrEdge *se = BKE_screen_find_edge(screen, area->v4, area->v1);
208  if (se && area->v1 != area->v2) {
209  const int yval = area->v2->vec.y - headery + 1;
210 
212 
213  /* all selected vertices get the right offset */
214  LISTBASE_FOREACH (ScrVert *, sv, &screen->vertbase) {
215  /* if is not a collapsed area */
216  if (!ELEM(sv, area->v2, area->v3)) {
217  if (sv->flag) {
218  sv->vec.y = yval;
219  /* Changed size of a area. Run another pass to ensure everything still fits. */
220  needs_another_pass = true;
221  }
222  }
223  }
224  }
225  }
226  }
227  }
228  }
229 
230  return needs_another_pass;
231 }
232 
233 void screen_geom_vertices_scale(const wmWindow *win, bScreen *screen)
234 {
235  rcti window_rect, screen_rect;
236  WM_window_rect_calc(win, &window_rect);
237  WM_window_screen_rect_calc(win, &screen_rect);
238 
239  bool needs_another_pass;
240  int max_passes_left = 10; /* Avoids endless loop. Number is rather arbitrary. */
241  do {
242  needs_another_pass = screen_geom_vertices_scale_pass(win, screen, &screen_rect);
243  max_passes_left--;
244  } while (needs_another_pass && (max_passes_left > 0));
245 
246  /* Global areas have a fixed size that only changes with the DPI.
247  * Here we ensure that exactly this size is set. */
249  if (area->global->flag & GLOBAL_AREA_IS_HIDDEN) {
250  continue;
251  }
252 
253  int height = ED_area_global_size_y(area) - 1;
254 
255  if (area->v1->vec.y > window_rect.ymin) {
256  height += U.pixelsize;
257  }
258  if (area->v2->vec.y < (window_rect.ymax - 1)) {
259  height += U.pixelsize;
260  }
261 
262  /* width */
263  area->v1->vec.x = area->v2->vec.x = window_rect.xmin;
264  area->v3->vec.x = area->v4->vec.x = window_rect.xmax - 1;
265  /* height */
266  area->v1->vec.y = area->v4->vec.y = window_rect.ymin;
267  area->v2->vec.y = area->v3->vec.y = window_rect.ymax - 1;
268 
269  switch (area->global->align) {
271  area->v1->vec.y = area->v4->vec.y = area->v2->vec.y - height;
272  break;
274  area->v2->vec.y = area->v3->vec.y = area->v1->vec.y + height;
275  break;
276  }
277  }
278 }
279 
281  const rcti *window_rect,
282  const eScreenAxis dir_axis,
283  float fac)
284 {
285  const int cur_area_width = screen_geom_area_width(area);
286  const int cur_area_height = screen_geom_area_height(area);
287  const short area_min_x = AREAMINX;
288  const short area_min_y = ED_area_headersize();
289 
290  /* area big enough? */
291  if (dir_axis == SCREEN_AXIS_V) {
292  if (cur_area_width <= 2 * area_min_x) {
293  return 0;
294  }
295  }
296  else if (dir_axis == SCREEN_AXIS_H) {
297  if (cur_area_height <= 2 * area_min_y) {
298  return 0;
299  }
300  }
301 
302  /* to be sure */
303  CLAMP(fac, 0.0f, 1.0f);
304 
305  if (dir_axis == SCREEN_AXIS_H) {
306  short y = area->v1->vec.y + round_fl_to_short(fac * cur_area_height);
307 
308  int area_min = area_min_y;
309 
310  if (area->v1->vec.y > window_rect->ymin) {
311  area_min += U.pixelsize;
312  }
313  if (area->v2->vec.y < (window_rect->ymax - 1)) {
314  area_min += U.pixelsize;
315  }
316 
317  if (y - area->v1->vec.y < area_min) {
318  y = area->v1->vec.y + area_min;
319  }
320  else if (area->v2->vec.y - y < area_min) {
321  y = area->v2->vec.y - area_min;
322  }
323 
324  return y;
325  }
326 
327  short x = area->v1->vec.x + round_fl_to_short(fac * cur_area_width);
328 
329  int area_min = area_min_x;
330 
331  if (area->v1->vec.x > window_rect->xmin) {
332  area_min += U.pixelsize;
333  }
334  if (area->v4->vec.x < (window_rect->xmax - 1)) {
335  area_min += U.pixelsize;
336  }
337 
338  if (x - area->v1->vec.x < area_min) {
339  x = area->v1->vec.x + area_min;
340  }
341  else if (area->v4->vec.x - x < area_min) {
342  x = area->v4->vec.x - area_min;
343  }
344 
345  return x;
346 }
347 
349 {
350  bScreen *screen = WM_window_get_active_screen(win);
351 
352  /* 'dir_axis' is the direction of EDGE */
353  eScreenAxis dir_axis;
354  if (edge->v1->vec.x == edge->v2->vec.x) {
355  dir_axis = SCREEN_AXIS_V;
356  }
357  else {
358  dir_axis = SCREEN_AXIS_H;
359  }
360 
361  ED_screen_verts_iter(win, screen, sv)
362  {
363  sv->flag = 0;
364  }
365 
366  edge->v1->flag = 1;
367  edge->v2->flag = 1;
368 
369  /* select connected, only in the right direction */
370  bool oneselected = true;
371  while (oneselected) {
372  oneselected = false;
373  LISTBASE_FOREACH (ScrEdge *, se, &screen->edgebase) {
374  if (se->v1->flag + se->v2->flag == 1) {
375  if (dir_axis == SCREEN_AXIS_H) {
376  if (se->v1->vec.y == se->v2->vec.y) {
377  se->v1->flag = se->v2->flag = 1;
378  oneselected = true;
379  }
380  }
381  else if (dir_axis == SCREEN_AXIS_V) {
382  if (se->v1->vec.x == se->v2->vec.x) {
383  se->v1->flag = se->v2->flag = 1;
384  oneselected = true;
385  }
386  }
387  }
388  }
389  }
390 }
typedef float(TangentPoint)[2]
struct ScrEdge * BKE_screen_find_edge(const struct bScreen *screen, struct ScrVert *v1, struct ScrVert *v2)
void BKE_screen_sort_scrvert(struct ScrVert **v1, struct ScrVert **v2)
Definition: screen.c:716
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
MINLINE short round_fl_to_short(float a)
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
Definition: math_vector.c:890
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:190
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
#define MAX2(a, b)
#define ELEM(...)
#define MIN2(a, b)
#define CLAMP_MIN(a, b)
#define AREAMAP_FROM_SCREEN(screen)
#define AREAMINX
@ GLOBAL_AREA_IS_HIDDEN
@ GLOBAL_AREA_ALIGN_BOTTOM
@ GLOBAL_AREA_ALIGN_TOP
@ SPACE_ACTION
@ USER_APP_LOCK_EDGE_RESIZE
int ED_area_global_size_y(const ScrArea *area)
Definition: area.c:3433
#define ED_screen_verts_iter(win, screen, vert_name)
Definition: ED_screen.h:270
int ED_area_headersize(void)
Definition: area.c:3422
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
ATTR_WARN_UNUSED_RESULT const BMVert * v2
unsigned int U
Definition: btGjkEpa3.h:78
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static void area(int d1, int d2, int e1, int e2, float weights[2])
T abs(const T &a)
ScrEdge * screen_geom_area_map_find_active_scredge(const ScrAreaMap *area_map, const rcti *bounds_rect, const int mx, const int my)
void screen_geom_select_connected_edge(const wmWindow *win, ScrEdge *edge)
bool screen_geom_edge_is_horizontal(ScrEdge *se)
ScrEdge * screen_geom_find_active_scredge(const wmWindow *win, const bScreen *screen, const int mx, const int my)
static bool screen_geom_vertices_scale_pass(const wmWindow *win, const bScreen *screen, const rcti *screen_rect)
ScrEdge * screen_geom_edge_add(bScreen *screen, ScrVert *v1, ScrVert *v2)
ScrVert * screen_geom_vertex_add(bScreen *screen, short x, short y)
int screen_geom_area_width(const ScrArea *area)
ScrEdge * screen_geom_edge_add_ex(ScrAreaMap *area_map, ScrVert *v1, ScrVert *v2)
int screen_geom_area_height(const ScrArea *area)
ScrVert * screen_geom_vertex_add_ex(ScrAreaMap *area_map, short x, short y)
void screen_geom_vertices_scale(const wmWindow *win, bScreen *screen)
Main screen-layout calculation function.
short screen_geom_find_area_split_point(const ScrArea *area, const rcti *window_rect, const eScreenAxis dir_axis, float fac)
#define BORDERPADDING
Definition: screen_intern.h:51
eScreenAxis
Definition: screen_intern.h:32
@ SCREEN_AXIS_V
Definition: screen_intern.h:36
@ SCREEN_AXIS_H
Definition: screen_intern.h:34
#define min(a, b)
Definition: sort.c:35
ListBase vertbase
ListBase edgebase
ListBase areabase
ScrVert * v1
ScrVert * v2
ListBase edgebase
ListBase vertbase
ListBase areabase
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
short y
Definition: DNA_vec_types.h:18
short x
Definition: DNA_vec_types.h:18
ScrAreaMap global_areas
float max
bScreen * WM_window_get_active_screen(const wmWindow *win)
Definition: wm_window.c:2300
void WM_window_rect_calc(const wmWindow *win, rcti *r_rect)
Definition: wm_window.c:2089
void WM_window_screen_rect_calc(const wmWindow *win, rcti *r_rect)
Definition: wm_window.c:2093