Blender  V2.93
view2d.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  * The Original Code is Copyright (C) 2008 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include <float.h>
25 #include <limits.h>
26 #include <math.h>
27 #include <string.h>
28 
29 #include "MEM_guardedalloc.h"
30 
31 #include "DNA_scene_types.h"
32 #include "DNA_userdef_types.h"
33 
34 #include "BLI_array.h"
35 #include "BLI_link_utils.h"
36 #include "BLI_listbase.h"
37 #include "BLI_math.h"
38 #include "BLI_memarena.h"
39 #include "BLI_rect.h"
40 #include "BLI_string.h"
41 #include "BLI_timecode.h"
42 #include "BLI_utildefines.h"
43 
44 #include "BKE_context.h"
45 #include "BKE_global.h"
46 #include "BKE_screen.h"
47 
48 #include "GPU_immediate.h"
49 #include "GPU_matrix.h"
50 #include "GPU_state.h"
51 
52 #include "WM_api.h"
53 
54 #include "BLF_api.h"
55 
56 #include "ED_screen.h"
57 
58 #include "UI_interface.h"
59 #include "UI_view2d.h"
60 
61 #include "interface_intern.h"
62 
63 static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize);
64 
65 /* -------------------------------------------------------------------- */
69 BLI_INLINE int clamp_float_to_int(const float f)
70 {
71  const float min = (float)INT_MIN;
72  const float max = (float)INT_MAX;
73 
74  if (UNLIKELY(f < min)) {
75  return min;
76  }
77  if (UNLIKELY(f > max)) {
78  return (int)max;
79  }
80  return (int)f;
81 }
82 
87 BLI_INLINE void clamp_rctf_to_rcti(rcti *dst, const rctf *src)
88 {
89  dst->xmin = clamp_float_to_int(src->xmin);
90  dst->xmax = clamp_float_to_int(src->xmax);
91  dst->ymin = clamp_float_to_int(src->ymin);
92  dst->ymax = clamp_float_to_int(src->ymax);
93 }
94 
95 /* XXX still unresolved: scrolls hide/unhide vs region mask handling */
96 /* XXX there's V2D_SCROLL_HORIZONTAL_HIDE and V2D_SCROLL_HORIZONTAL_FULLR ... */
97 
100 /* -------------------------------------------------------------------- */
111 static int view2d_scroll_mapped(int scroll)
112 {
113  if (scroll & V2D_SCROLL_HORIZONTAL_FULLR) {
114  scroll &= ~V2D_SCROLL_HORIZONTAL;
115  }
116  if (scroll & V2D_SCROLL_VERTICAL_FULLR) {
117  scroll &= ~V2D_SCROLL_VERTICAL;
118  }
119  return scroll;
120 }
121 
122 void UI_view2d_mask_from_win(const View2D *v2d, rcti *r_mask)
123 {
124  r_mask->xmin = 0;
125  r_mask->ymin = 0;
126  r_mask->xmax = v2d->winx - 1; /* -1 yes! masks are pixels */
127  r_mask->ymax = v2d->winy - 1;
128 }
129 
135 static void view2d_masks(View2D *v2d, const rcti *mask_scroll)
136 {
137  int scroll;
138 
139  /* mask - view frame */
140  UI_view2d_mask_from_win(v2d, &v2d->mask);
141  if (mask_scroll == NULL) {
142  mask_scroll = &v2d->mask;
143  }
144 
145  /* check size if hiding flag is set: */
146  if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) {
147  if (!(v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES)) {
148  if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur)) {
150  }
151  else {
153  }
154  }
155  }
156  if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) {
157  if (!(v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES)) {
158  if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur)) {
160  }
161  else {
163  }
164  }
165  }
166 
167  scroll = view2d_scroll_mapped(v2d->scroll);
168 
169  /* scrollers are based off regionsize
170  * - they can only be on one to two edges of the region they define
171  * - if they overlap, they must not occupy the corners (which are reserved for other widgets)
172  */
173  if (scroll) {
174  float scroll_width, scroll_height;
175 
176  UI_view2d_scroller_size_get(v2d, &scroll_width, &scroll_height);
177 
178  /* vertical scroller */
179  if (scroll & V2D_SCROLL_LEFT) {
180  /* on left-hand edge of region */
181  v2d->vert = *mask_scroll;
182  v2d->vert.xmax = scroll_width;
183  }
184  else if (scroll & V2D_SCROLL_RIGHT) {
185  /* on right-hand edge of region */
186  v2d->vert = *mask_scroll;
187  v2d->vert.xmax++; /* one pixel extra... was leaving a minor gap... */
188  v2d->vert.xmin = v2d->vert.xmax - scroll_width;
189  }
190 
191  /* Currently, all regions that have vertical scale handles,
192  * also have the scrubbing area at the top.
193  * So the scrollbar has to move down a bit. */
194  if (scroll & V2D_SCROLL_VERTICAL_HANDLES) {
196  }
197 
198  /* horizontal scroller */
199  if (scroll & V2D_SCROLL_BOTTOM) {
200  /* on bottom edge of region */
201  v2d->hor = *mask_scroll;
202  v2d->hor.ymax = scroll_height;
203  }
204  else if (scroll & V2D_SCROLL_TOP) {
205  /* on upper edge of region */
206  v2d->hor = *mask_scroll;
207  v2d->hor.ymin = v2d->hor.ymax - scroll_height;
208  }
209 
210  /* adjust vertical scroller if there's a horizontal scroller, to leave corner free */
211  if (scroll & V2D_SCROLL_VERTICAL) {
212  if (scroll & V2D_SCROLL_BOTTOM) {
213  /* on bottom edge of region */
214  v2d->vert.ymin = v2d->hor.ymax;
215  }
216  else if (scroll & V2D_SCROLL_TOP) {
217  /* on upper edge of region */
218  v2d->vert.ymax = v2d->hor.ymin;
219  }
220  }
221  }
222 }
223 
226 /* -------------------------------------------------------------------- */
240 void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
241 {
242  bool tot_changed = false, do_init;
243  const uiStyle *style = UI_style_get();
244 
245  do_init = (v2d->flag & V2D_IS_INIT) == 0;
246 
247  /* see eView2D_CommonViewTypes in UI_view2d.h for available view presets */
248  switch (type) {
249  /* 'standard view' - optimum setup for 'standard' view behavior,
250  * that should be used new views as basis for their
251  * own unique View2D settings, which should be used instead of this in most cases...
252  */
254  /* for now, aspect ratio should be maintained,
255  * and zoom is clamped within sane default limits */
257  v2d->minzoom = 0.01f;
258  v2d->maxzoom = 1000.0f;
259 
260  /* View2D tot rect and cur should be same size,
261  * and aligned using 'standard' OpenGL coordinates for now:
262  * - region can resize 'tot' later to fit other data
263  * - keeptot is only within bounds, as strict locking is not that critical
264  * - view is aligned for (0,0) -> (winx-1, winy-1) setup
265  */
268  if (do_init) {
269  v2d->tot.xmin = v2d->tot.ymin = 0.0f;
270  v2d->tot.xmax = (float)(winx - 1);
271  v2d->tot.ymax = (float)(winy - 1);
272 
273  v2d->cur = v2d->tot;
274  }
275  /* scrollers - should we have these by default? */
276  /* XXX for now, we don't override this, or set it either! */
277  break;
278  }
279  /* 'list/channel view' - zoom, aspect ratio, and alignment restrictions are set here */
280  case V2D_COMMONVIEW_LIST: {
281  /* zoom + aspect ratio are locked */
283  v2d->minzoom = v2d->maxzoom = 1.0f;
284 
285  /* tot rect has strictly regulated placement, and must only occur in +/- quadrant */
288  tot_changed = do_init;
289 
290  /* scroller settings are currently not set here... that is left for regions... */
291  break;
292  }
293  /* 'stack view' - practically the same as list/channel view,
294  * except is located in the pos y half instead.
295  * Zoom, aspect ratio, and alignment restrictions are set here. */
296  case V2D_COMMONVIEW_STACK: {
297  /* zoom + aspect ratio are locked */
299  v2d->minzoom = v2d->maxzoom = 1.0f;
300 
301  /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
304  tot_changed = do_init;
305 
306  /* scroller settings are currently not set here... that is left for regions... */
307  break;
308  }
309  /* 'header' regions - zoom, aspect ratio,
310  * alignment, and panning restrictions are set here */
311  case V2D_COMMONVIEW_HEADER: {
312  /* zoom + aspect ratio are locked */
314  v2d->minzoom = v2d->maxzoom = 1.0f;
315 
316  if (do_init) {
317  v2d->tot.xmin = 0.0f;
318  v2d->tot.xmax = winx;
319  v2d->tot.ymin = 0.0f;
320  v2d->tot.ymax = winy;
321  v2d->cur = v2d->tot;
322 
323  v2d->min[0] = v2d->max[0] = (float)(winx - 1);
324  v2d->min[1] = v2d->max[1] = (float)(winy - 1);
325  }
326  /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
329  tot_changed = do_init;
330 
331  /* panning in y-axis is prohibited */
332  v2d->keepofs = V2D_LOCKOFS_Y;
333 
334  /* absolutely no scrollers allowed */
335  v2d->scroll = 0;
336  break;
337  }
338  /* panels view, with horizontal/vertical align */
340 
341  /* for now, aspect ratio should be maintained,
342  * and zoom is clamped within sane default limits */
344  v2d->minzoom = 0.5f;
345  v2d->maxzoom = 2.0f;
346 
349 
350  /* note, scroll is being flipped in ED_region_panels() drawing */
352 
353  if (do_init) {
354  const float panelzoom = (style) ? style->panelzoom : 1.0f;
355 
356  v2d->tot.xmin = 0.0f;
357  v2d->tot.xmax = winx;
358 
359  v2d->tot.ymax = 0.0f;
360  v2d->tot.ymin = -winy;
361 
362  v2d->cur.xmin = 0.0f;
363  v2d->cur.xmax = (winx)*panelzoom;
364 
365  v2d->cur.ymax = 0.0f;
366  v2d->cur.ymin = (-winy) * panelzoom;
367  }
368  break;
369  }
370  /* other view types are completely defined using their own settings already */
371  default:
372  /* we don't do anything here,
373  * as settings should be fine, but just make sure that rect */
374  break;
375  }
376 
377  /* set initialized flag so that View2D doesn't get reinitialized next time again */
378  v2d->flag |= V2D_IS_INIT;
379 
380  /* store view size */
381  v2d->winx = winx;
382  v2d->winy = winy;
383 
384  view2d_masks(v2d, NULL);
385 
386  if (do_init) {
387  /* Visible by default. */
388  v2d->alpha_hor = v2d->alpha_vert = 255;
389  }
390 
391  /* set 'tot' rect before setting cur? */
392  /* XXX confusing stuff here still */
393  if (tot_changed) {
394  UI_view2d_totRect_set_resize(v2d, winx, winy, !do_init);
395  }
396  else {
397  ui_view2d_curRect_validate_resize(v2d, !do_init);
398  }
399 }
400 
405 /* XXX pre2.5 -> this used to be called test_view2d() */
406 static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize)
407 {
408  float totwidth, totheight, curwidth, curheight, width, height;
409  float winx, winy;
410  rctf *cur, *tot;
411 
412  /* use mask as size of region that View2D resides in, as it takes into account
413  * scrollbars already - keep in sync with zoomx/zoomy in view_zoomstep_apply_ex! */
414  winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
415  winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
416 
417  /* get pointers to rcts for less typing */
418  cur = &v2d->cur;
419  tot = &v2d->tot;
420 
421  /* we must satisfy the following constraints (in decreasing order of importance):
422  * - alignment restrictions are respected
423  * - cur must not fall outside of tot
424  * - axis locks (zoom and offset) must be maintained
425  * - zoom must not be excessive (check either sizes or zoom values)
426  * - aspect ratio should be respected (NOTE: this is quite closely related to zoom too)
427  */
428 
429  /* Step 1: if keepzoom, adjust the sizes of the rects only
430  * - firstly, we calculate the sizes of the rects
431  * - curwidth and curheight are saved as reference... modify width and height values here
432  */
433  totwidth = BLI_rctf_size_x(tot);
434  totheight = BLI_rctf_size_y(tot);
435  /* keep in sync with zoomx/zoomy in view_zoomstep_apply_ex! */
436  curwidth = width = BLI_rctf_size_x(cur);
437  curheight = height = BLI_rctf_size_y(cur);
438 
439  /* if zoom is locked, size on the appropriate axis is reset to mask size */
440  if (v2d->keepzoom & V2D_LOCKZOOM_X) {
441  width = winx;
442  }
443  if (v2d->keepzoom & V2D_LOCKZOOM_Y) {
444  height = winy;
445  }
446 
447  /* values used to divide, so make it safe
448  * NOTE: width and height must use FLT_MIN instead of 1, otherwise it is impossible to
449  * get enough resolution in Graph Editor for editing some curves
450  */
451  if (width < FLT_MIN) {
452  width = 1;
453  }
454  if (height < FLT_MIN) {
455  height = 1;
456  }
457  if (winx < 1) {
458  winx = 1;
459  }
460  if (winy < 1) {
461  winy = 1;
462  }
463 
464  /* V2D_LIMITZOOM indicates that zoom level should be preserved when the window size changes */
465  if (resize && (v2d->keepzoom & V2D_KEEPZOOM)) {
466  float zoom, oldzoom;
467 
468  if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
469  zoom = winx / width;
470  oldzoom = v2d->oldwinx / curwidth;
471 
472  if (oldzoom != zoom) {
473  width *= zoom / oldzoom;
474  }
475  }
476 
477  if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
478  zoom = winy / height;
479  oldzoom = v2d->oldwiny / curheight;
480 
481  if (oldzoom != zoom) {
482  height *= zoom / oldzoom;
483  }
484  }
485  }
486  /* keepzoom (V2D_LIMITZOOM set), indicates that zoom level on each axis must not exceed limits
487  * NOTE: in general, it is not expected that the lock-zoom will be used in conjunction with this
488  */
489  else if (v2d->keepzoom & V2D_LIMITZOOM) {
490 
491  /* check if excessive zoom on x-axis */
492  if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
493  const float zoom = winx / width;
494  if (zoom < v2d->minzoom) {
495  width = winx / v2d->minzoom;
496  }
497  else if (zoom > v2d->maxzoom) {
498  width = winx / v2d->maxzoom;
499  }
500  }
501 
502  /* check if excessive zoom on y-axis */
503  if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
504  const float zoom = winy / height;
505  if (zoom < v2d->minzoom) {
506  height = winy / v2d->minzoom;
507  }
508  else if (zoom > v2d->maxzoom) {
509  height = winy / v2d->maxzoom;
510  }
511  }
512  }
513  else {
514  /* make sure sizes don't exceed that of the min/max sizes
515  * (even though we're not doing zoom clamping) */
516  CLAMP(width, v2d->min[0], v2d->max[0]);
517  CLAMP(height, v2d->min[1], v2d->max[1]);
518  }
519 
520  /* check if we should restore aspect ratio (if view size changed) */
521  if (v2d->keepzoom & V2D_KEEPASPECT) {
522  bool do_x = false, do_y = false, do_cur /* , do_win */ /* UNUSED */;
523  float curRatio, winRatio;
524 
525  /* when a window edge changes, the aspect ratio can't be used to
526  * find which is the best new 'cur' rect. that's why it stores 'old'
527  */
528  if (winx != v2d->oldwinx) {
529  do_x = true;
530  }
531  if (winy != v2d->oldwiny) {
532  do_y = true;
533  }
534 
535  curRatio = height / width;
536  winRatio = winy / winx;
537 
538  /* both sizes change (area/region maximized) */
539  if (do_x == do_y) {
540  if (do_x && do_y) {
541  /* here is 1,1 case, so all others must be 0,0 */
542  if (fabsf(winx - v2d->oldwinx) > fabsf(winy - v2d->oldwiny)) {
543  do_y = false;
544  }
545  else {
546  do_x = false;
547  }
548  }
549  else if (winRatio > curRatio) {
550  do_x = false;
551  }
552  else {
553  do_x = true;
554  }
555  }
556  do_cur = do_x;
557  /* do_win = do_y; */ /* UNUSED */
558 
559  if (do_cur) {
560  if ((v2d->keeptot == V2D_KEEPTOT_STRICT) && (winx != v2d->oldwinx)) {
561  /* Special exception for Outliner (and later channel-lists):
562  * - The view may be moved left to avoid contents
563  * being pushed out of view when view shrinks.
564  * - The keeptot code will make sure cur->xmin will not be less than tot->xmin
565  * (which cannot be allowed).
566  * - width is not adjusted for changed ratios here.
567  */
568  if (winx < v2d->oldwinx) {
569  const float temp = v2d->oldwinx - winx;
570 
571  cur->xmin -= temp;
572  cur->xmax -= temp;
573 
574  /* width does not get modified, as keepaspect here is just set to make
575  * sure visible area adjusts to changing view shape!
576  */
577  }
578  }
579  else {
580  /* portrait window: correct for x */
581  width = height / winRatio;
582  }
583  }
584  else {
585  if ((v2d->keeptot == V2D_KEEPTOT_STRICT) && (winy != v2d->oldwiny)) {
586  /* special exception for Outliner (and later channel-lists):
587  * - Currently, no actions need to be taken here...
588  */
589 
590  if (winy < v2d->oldwiny) {
591  const float temp = v2d->oldwiny - winy;
592 
593  if (v2d->align & V2D_ALIGN_NO_NEG_Y) {
594  cur->ymin -= temp;
595  cur->ymax -= temp;
596  }
597  else { /* Assume V2D_ALIGN_NO_POS_Y or combination */
598  cur->ymin += temp;
599  cur->ymax += temp;
600  }
601  }
602  }
603  else {
604  /* landscape window: correct for y */
605  height = width * winRatio;
606  }
607  }
608 
609  /* store region size for next time */
610  v2d->oldwinx = (short)winx;
611  v2d->oldwiny = (short)winy;
612  }
613 
614  /* Step 2: apply new sizes to cur rect,
615  * but need to take into account alignment settings here... */
616  if ((width != curwidth) || (height != curheight)) {
617  float temp, dh;
618 
619  /* Resize from center-point, unless otherwise specified. */
620  if (width != curwidth) {
621  if (v2d->keepofs & V2D_LOCKOFS_X) {
622  cur->xmax += width - BLI_rctf_size_x(cur);
623  }
624  else if (v2d->keepofs & V2D_KEEPOFS_X) {
625  if (v2d->align & V2D_ALIGN_NO_POS_X) {
626  cur->xmin -= width - BLI_rctf_size_x(cur);
627  }
628  else {
629  cur->xmax += width - BLI_rctf_size_x(cur);
630  }
631  }
632  else {
633  temp = BLI_rctf_cent_x(cur);
634  dh = width * 0.5f;
635 
636  cur->xmin = temp - dh;
637  cur->xmax = temp + dh;
638  }
639  }
640  if (height != curheight) {
641  if (v2d->keepofs & V2D_LOCKOFS_Y) {
642  cur->ymax += height - BLI_rctf_size_y(cur);
643  }
644  else if (v2d->keepofs & V2D_KEEPOFS_Y) {
645  if (v2d->align & V2D_ALIGN_NO_POS_Y) {
646  cur->ymin -= height - BLI_rctf_size_y(cur);
647  }
648  else {
649  cur->ymax += height - BLI_rctf_size_y(cur);
650  }
651  }
652  else {
653  temp = BLI_rctf_cent_y(cur);
654  dh = height * 0.5f;
655 
656  cur->ymin = temp - dh;
657  cur->ymax = temp + dh;
658  }
659  }
660  }
661 
662  /* Step 3: adjust so that it doesn't fall outside of bounds of 'tot' */
663  if (v2d->keeptot) {
664  float temp, diff;
665 
666  /* recalculate extents of cur */
667  curwidth = BLI_rctf_size_x(cur);
668  curheight = BLI_rctf_size_y(cur);
669 
670  /* width */
671  if ((curwidth > totwidth) &&
673  /* if zoom doesn't have to be maintained, just clamp edges */
674  if (cur->xmin < tot->xmin) {
675  cur->xmin = tot->xmin;
676  }
677  if (cur->xmax > tot->xmax) {
678  cur->xmax = tot->xmax;
679  }
680  }
681  else if (v2d->keeptot == V2D_KEEPTOT_STRICT) {
682  /* This is an exception for the outliner (and later channel-lists, headers)
683  * - must clamp within tot rect (absolutely no excuses)
684  * --> therefore, cur->xmin must not be less than tot->xmin
685  */
686  if (cur->xmin < tot->xmin) {
687  /* move cur across so that it sits at minimum of tot */
688  temp = tot->xmin - cur->xmin;
689 
690  cur->xmin += temp;
691  cur->xmax += temp;
692  }
693  else if (cur->xmax > tot->xmax) {
694  /* - only offset by difference of cur-xmax and tot-xmax if that would not move
695  * cur-xmin to lie past tot-xmin
696  * - otherwise, simply shift to tot-xmin???
697  */
698  temp = cur->xmax - tot->xmax;
699 
700  if ((cur->xmin - temp) < tot->xmin) {
701  /* only offset by difference from cur-min and tot-min */
702  temp = cur->xmin - tot->xmin;
703 
704  cur->xmin -= temp;
705  cur->xmax -= temp;
706  }
707  else {
708  cur->xmin -= temp;
709  cur->xmax -= temp;
710  }
711  }
712  }
713  else {
714  /* This here occurs when:
715  * - width too big, but maintaining zoom (i.e. widths cannot be changed)
716  * - width is OK, but need to check if outside of boundaries
717  *
718  * So, resolution is to just shift view by the gap between the extremities.
719  * We favor moving the 'minimum' across, as that's origin for most things.
720  * (XXX - in the past, max was favored... if there are bugs, swap!)
721  */
722  if ((cur->xmin < tot->xmin) && (cur->xmax > tot->xmax)) {
723  /* outside boundaries on both sides,
724  * so take middle-point of tot, and place in balanced way */
725  temp = BLI_rctf_cent_x(tot);
726  diff = curwidth * 0.5f;
727 
728  cur->xmin = temp - diff;
729  cur->xmax = temp + diff;
730  }
731  else if (cur->xmin < tot->xmin) {
732  /* move cur across so that it sits at minimum of tot */
733  temp = tot->xmin - cur->xmin;
734 
735  cur->xmin += temp;
736  cur->xmax += temp;
737  }
738  else if (cur->xmax > tot->xmax) {
739  /* - only offset by difference of cur-xmax and tot-xmax if that would not move
740  * cur-xmin to lie past tot-xmin
741  * - otherwise, simply shift to tot-xmin???
742  */
743  temp = cur->xmax - tot->xmax;
744 
745  if ((cur->xmin - temp) < tot->xmin) {
746  /* only offset by difference from cur-min and tot-min */
747  temp = cur->xmin - tot->xmin;
748 
749  cur->xmin -= temp;
750  cur->xmax -= temp;
751  }
752  else {
753  cur->xmin -= temp;
754  cur->xmax -= temp;
755  }
756  }
757  }
758 
759  /* height */
760  if ((curheight > totheight) &&
762  /* if zoom doesn't have to be maintained, just clamp edges */
763  if (cur->ymin < tot->ymin) {
764  cur->ymin = tot->ymin;
765  }
766  if (cur->ymax > tot->ymax) {
767  cur->ymax = tot->ymax;
768  }
769  }
770  else {
771  /* This here occurs when:
772  * - height too big, but maintaining zoom (i.e. heights cannot be changed)
773  * - height is OK, but need to check if outside of boundaries
774  *
775  * So, resolution is to just shift view by the gap between the extremities.
776  * We favor moving the 'minimum' across, as that's origin for most things.
777  */
778  if ((cur->ymin < tot->ymin) && (cur->ymax > tot->ymax)) {
779  /* outside boundaries on both sides,
780  * so take middle-point of tot, and place in balanced way */
781  temp = BLI_rctf_cent_y(tot);
782  diff = curheight * 0.5f;
783 
784  cur->ymin = temp - diff;
785  cur->ymax = temp + diff;
786  }
787  else if (cur->ymin < tot->ymin) {
788  /* there's still space remaining, so shift up */
789  temp = tot->ymin - cur->ymin;
790 
791  cur->ymin += temp;
792  cur->ymax += temp;
793  }
794  else if (cur->ymax > tot->ymax) {
795  /* there's still space remaining, so shift down */
796  temp = cur->ymax - tot->ymax;
797 
798  cur->ymin -= temp;
799  cur->ymax -= temp;
800  }
801  }
802  }
803 
804  /* Step 4: Make sure alignment restrictions are respected */
805  if (v2d->align) {
806  /* If alignment flags are set (but keeptot is not), they must still be respected, as although
807  * they don't specify any particular bounds to stay within, they do define ranges which are
808  * invalid.
809  *
810  * Here, we only check to make sure that on each axis, the 'cur' rect doesn't stray into these
811  * invalid zones, otherwise we offset.
812  */
813 
814  /* handle width - posx and negx flags are mutually exclusive, so watch out */
815  if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
816  /* width is in negative-x half */
817  if (v2d->cur.xmax > 0) {
818  v2d->cur.xmin -= v2d->cur.xmax;
819  v2d->cur.xmax = 0.0f;
820  }
821  }
822  else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
823  /* width is in positive-x half */
824  if (v2d->cur.xmin < 0) {
825  v2d->cur.xmax -= v2d->cur.xmin;
826  v2d->cur.xmin = 0.0f;
827  }
828  }
829 
830  /* handle height - posx and negx flags are mutually exclusive, so watch out */
831  if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
832  /* height is in negative-y half */
833  if (v2d->cur.ymax > 0) {
834  v2d->cur.ymin -= v2d->cur.ymax;
835  v2d->cur.ymax = 0.0f;
836  }
837  }
838  else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
839  /* height is in positive-y half */
840  if (v2d->cur.ymin < 0) {
841  v2d->cur.ymax -= v2d->cur.ymin;
842  v2d->cur.ymin = 0.0f;
843  }
844  }
845  }
846 
847  /* set masks */
848  view2d_masks(v2d, NULL);
849 }
850 
852 {
854 }
855 
857 {
859 
860  ARegion *region = CTX_wm_region(C);
861 
862  if (region->type->on_view2d_changed != NULL) {
863  region->type->on_view2d_changed(C, region);
864  }
865 }
866 
867 /* ------------------ */
868 
870 {
872 }
873 
874 /* Called by menus to activate it, or by view2d operators
875  * to make sure 'related' views stay in synchrony */
876 void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
877 {
878  /* don't continue if no view syncing to be done */
879  if ((v2dcur->flag & (V2D_VIEWSYNC_SCREEN_TIME | V2D_VIEWSYNC_AREA_VERTICAL)) == 0) {
880  return;
881  }
882 
883  /* check if doing within area syncing (i.e. channels/vertical) */
884  if ((v2dcur->flag & V2D_VIEWSYNC_AREA_VERTICAL) && (area)) {
885  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
886  /* don't operate on self */
887  if (v2dcur != &region->v2d) {
888  /* only if view has vertical locks enabled */
889  if (region->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL) {
890  if (flag == V2D_LOCK_COPY) {
891  /* other views with locks on must copy active */
892  region->v2d.cur.ymin = v2dcur->cur.ymin;
893  region->v2d.cur.ymax = v2dcur->cur.ymax;
894  }
895  else { /* V2D_LOCK_SET */
896  /* active must copy others */
897  v2dcur->cur.ymin = region->v2d.cur.ymin;
898  v2dcur->cur.ymax = region->v2d.cur.ymax;
899  }
900 
901  /* region possibly changed, so refresh */
903  }
904  }
905  }
906  }
907 
908  /* check if doing whole screen syncing (i.e. time/horizontal) */
909  if ((v2dcur->flag & V2D_VIEWSYNC_SCREEN_TIME) && (screen)) {
910  LISTBASE_FOREACH (ScrArea *, area_iter, &screen->areabase) {
911  if (!UI_view2d_area_supports_sync(area_iter)) {
912  continue;
913  }
914  LISTBASE_FOREACH (ARegion *, region, &area_iter->regionbase) {
915  /* don't operate on self */
916  if (v2dcur != &region->v2d) {
917  /* only if view has horizontal locks enabled */
918  if (region->v2d.flag & V2D_VIEWSYNC_SCREEN_TIME) {
919  if (flag == V2D_LOCK_COPY) {
920  /* other views with locks on must copy active */
921  region->v2d.cur.xmin = v2dcur->cur.xmin;
922  region->v2d.cur.xmax = v2dcur->cur.xmax;
923  }
924  else { /* V2D_LOCK_SET */
925  /* active must copy others */
926  v2dcur->cur.xmin = region->v2d.cur.xmin;
927  v2dcur->cur.xmax = region->v2d.cur.xmax;
928  }
929 
930  /* region possibly changed, so refresh */
932  }
933  }
934  }
935  }
936  }
937 }
938 
945 {
946  float width, height;
947 
948  /* assume width and height of 'cur' rect by default, should be same size as mask */
949  width = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
950  height = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
951 
952  /* handle width - posx and negx flags are mutually exclusive, so watch out */
953  if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
954  /* width is in negative-x half */
955  v2d->cur.xmin = -width;
956  v2d->cur.xmax = 0.0f;
957  }
958  else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
959  /* width is in positive-x half */
960  v2d->cur.xmin = 0.0f;
961  v2d->cur.xmax = width;
962  }
963  else {
964  /* width is centered around (x == 0) */
965  const float dx = width / 2.0f;
966 
967  v2d->cur.xmin = -dx;
968  v2d->cur.xmax = dx;
969  }
970 
971  /* handle height - posx and negx flags are mutually exclusive, so watch out */
972  if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
973  /* height is in negative-y half */
974  v2d->cur.ymin = -height;
975  v2d->cur.ymax = 0.0f;
976  }
977  else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
978  /* height is in positive-y half */
979  v2d->cur.ymin = 0.0f;
980  v2d->cur.ymax = height;
981  }
982  else {
983  /* height is centered around (y == 0) */
984  const float dy = height / 2.0f;
985 
986  v2d->cur.ymin = -dy;
987  v2d->cur.ymax = dy;
988  }
989 }
990 
991 /* ------------------ */
992 
993 /* Change the size of the maximum viewable area (i.e. 'tot' rect) */
994 void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resize)
995 {
996  /* don't do anything if either value is 0 */
997  width = abs(width);
998  height = abs(height);
999 
1000  if (ELEM(0, width, height)) {
1001  if (G.debug & G_DEBUG) {
1002  printf("Error: View2D totRect set exiting: v2d=%p width=%d height=%d\n",
1003  (void *)v2d,
1004  width,
1005  height); /* XXX temp debug info */
1006  }
1007  return;
1008  }
1009 
1010  /* handle width - posx and negx flags are mutually exclusive, so watch out */
1011  if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
1012  /* width is in negative-x half */
1013  v2d->tot.xmin = (float)-width;
1014  v2d->tot.xmax = 0.0f;
1015  }
1016  else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
1017  /* width is in positive-x half */
1018  v2d->tot.xmin = 0.0f;
1019  v2d->tot.xmax = (float)width;
1020  }
1021  else {
1022  /* width is centered around (x == 0) */
1023  const float dx = (float)width / 2.0f;
1024 
1025  v2d->tot.xmin = -dx;
1026  v2d->tot.xmax = dx;
1027  }
1028 
1029  /* handle height - posx and negx flags are mutually exclusive, so watch out */
1030  if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
1031  /* height is in negative-y half */
1032  v2d->tot.ymin = (float)-height;
1033  v2d->tot.ymax = 0.0f;
1034  }
1035  else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
1036  /* height is in positive-y half */
1037  v2d->tot.ymin = 0.0f;
1038  v2d->tot.ymax = (float)height;
1039  }
1040  else {
1041  /* height is centered around (y == 0) */
1042  const float dy = (float)height / 2.0f;
1043 
1044  v2d->tot.ymin = -dy;
1045  v2d->tot.ymax = dy;
1046  }
1047 
1048  /* make sure that 'cur' rect is in a valid state as a result of these changes */
1049  ui_view2d_curRect_validate_resize(v2d, resize);
1050 }
1051 
1053 {
1055 }
1056 
1058 {
1059  /* TODO(sergey): This way we avoid threading conflict with sequencer rendering
1060  * text strip. But ideally we want to make glyph cache to be fully safe
1061  * for threading.
1062  */
1063  if (G.is_rendering) {
1064  return;
1065  }
1066  /* While scaling we can accumulate fonts at many sizes (~20 or so).
1067  * Not an issue with embedded font, but can use over 500Mb with i18n ones! See T38244. */
1068 
1069  /* Note: only some views draw text, we could check for this case to avoid cleaning cache. */
1070  BLF_cache_clear();
1071 }
1072 
1075 /* -------------------------------------------------------------------- */
1079 /* mapping function to ensure 'cur' draws extended over the area where sliders are */
1080 static void view2d_map_cur_using_mask(const View2D *v2d, rctf *r_curmasked)
1081 {
1082  *r_curmasked = v2d->cur;
1083 
1084  if (view2d_scroll_mapped(v2d->scroll)) {
1085  const float sizex = BLI_rcti_size_x(&v2d->mask);
1086  const float sizey = BLI_rcti_size_y(&v2d->mask);
1087 
1088  /* prevent tiny or narrow regions to get
1089  * invalid coordinates - mask can get negative even... */
1090  if (sizex > 0.0f && sizey > 0.0f) {
1091  const float dx = BLI_rctf_size_x(&v2d->cur) / (sizex + 1);
1092  const float dy = BLI_rctf_size_y(&v2d->cur) / (sizey + 1);
1093 
1094  if (v2d->mask.xmin != 0) {
1095  r_curmasked->xmin -= dx * (float)v2d->mask.xmin;
1096  }
1097  if (v2d->mask.xmax + 1 != v2d->winx) {
1098  r_curmasked->xmax += dx * (float)(v2d->winx - v2d->mask.xmax - 1);
1099  }
1100 
1101  if (v2d->mask.ymin != 0) {
1102  r_curmasked->ymin -= dy * (float)v2d->mask.ymin;
1103  }
1104  if (v2d->mask.ymax + 1 != v2d->winy) {
1105  r_curmasked->ymax += dy * (float)(v2d->winy - v2d->mask.ymax - 1);
1106  }
1107  }
1108  }
1109 }
1110 
1111 /* Set view matrices to use 'cur' rect as viewing frame for View2D drawing */
1113 {
1114  rctf curmasked;
1115  const int sizex = BLI_rcti_size_x(&v2d->mask);
1116  const int sizey = BLI_rcti_size_y(&v2d->mask);
1117  const float eps = 0.001f;
1118  float xofs = 0.0f, yofs = 0.0f;
1119 
1120  /* Pixel offsets (-GLA_PIXEL_OFS) are needed to get 1:1
1121  * correspondence with pixels for smooth UI drawing,
1122  * but only applied where requested.
1123  */
1124  /* XXX brecht: instead of zero at least use a tiny offset, otherwise
1125  * pixel rounding is effectively random due to float inaccuracy */
1126  if (sizex > 0) {
1127  xofs = eps * BLI_rctf_size_x(&v2d->cur) / sizex;
1128  }
1129  if (sizey > 0) {
1130  yofs = eps * BLI_rctf_size_y(&v2d->cur) / sizey;
1131  }
1132 
1133  /* apply mask-based adjustments to cur rect (due to scrollers),
1134  * to eliminate scaling artifacts */
1135  view2d_map_cur_using_mask(v2d, &curmasked);
1136 
1137  BLI_rctf_translate(&curmasked, -xofs, -yofs);
1138 
1139  /* XXX ton: this flag set by outliner, for icons */
1140  if (v2d->flag & V2D_PIXELOFS_X) {
1141  curmasked.xmin = floorf(curmasked.xmin) - (eps + xofs);
1142  curmasked.xmax = floorf(curmasked.xmax) - (eps + xofs);
1143  }
1144  if (v2d->flag & V2D_PIXELOFS_Y) {
1145  curmasked.ymin = floorf(curmasked.ymin) - (eps + yofs);
1146  curmasked.ymax = floorf(curmasked.ymax) - (eps + yofs);
1147  }
1148 
1149  /* set matrix on all appropriate axes */
1150  wmOrtho2(curmasked.xmin, curmasked.xmax, curmasked.ymin, curmasked.ymax);
1151 }
1152 
1159 void UI_view2d_view_orthoSpecial(ARegion *region, View2D *v2d, const bool xaxis)
1160 {
1161  rctf curmasked;
1162  float xofs, yofs;
1163 
1164  /* Pixel offsets (-GLA_PIXEL_OFS) are needed to get 1:1
1165  * correspondence with pixels for smooth UI drawing,
1166  * but only applied where requested.
1167  */
1168  /* XXX temp (ton) */
1169  xofs = 0.0f; // (v2d->flag & V2D_PIXELOFS_X) ? GLA_PIXEL_OFS : 0.0f;
1170  yofs = 0.0f; // (v2d->flag & V2D_PIXELOFS_Y) ? GLA_PIXEL_OFS : 0.0f;
1171 
1172  /* apply mask-based adjustments to cur rect (due to scrollers),
1173  * to eliminate scaling artifacts */
1174  view2d_map_cur_using_mask(v2d, &curmasked);
1175 
1176  /* only set matrix with 'cur' coordinates on relevant axes */
1177  if (xaxis) {
1178  wmOrtho2(curmasked.xmin - xofs, curmasked.xmax - xofs, -yofs, region->winy - yofs);
1179  }
1180  else {
1181  wmOrtho2(-xofs, region->winx - xofs, curmasked.ymin - yofs, curmasked.ymax - yofs);
1182  }
1183 }
1184 
1185 /* Restore view matrices after drawing */
1187 {
1188  ARegion *region = CTX_wm_region(C);
1189  const int width = BLI_rcti_size_x(&region->winrct) + 1;
1190  const int height = BLI_rcti_size_y(&region->winrct) + 1;
1191 
1192  wmOrtho2(0.0f, (float)width, 0.0f, (float)height);
1194 
1195  // ED_region_pixelspace(CTX_wm_region(C));
1196 }
1197 
1200 /* -------------------------------------------------------------------- */
1204 /* Draw a constant grid in given 2d-region */
1205 void UI_view2d_constant_grid_draw(const View2D *v2d, float step)
1206 {
1207  float start_x, start_y;
1208  int count_x, count_y;
1209 
1210  start_x = v2d->cur.xmin;
1211  if (start_x < 0.0) {
1212  start_x += -(float)fmod(v2d->cur.xmin, step);
1213  }
1214  else {
1215  start_x += (step - (float)fmod(v2d->cur.xmin, step));
1216  }
1217 
1218  if (start_x > v2d->cur.xmax) {
1219  count_x = 0;
1220  }
1221  else {
1222  count_x = (v2d->cur.xmax - start_x) / step + 1;
1223  }
1224 
1225  start_y = v2d->cur.ymin;
1226  if (start_y < 0.0) {
1227  start_y += -(float)fmod(v2d->cur.ymin, step);
1228  }
1229  else {
1230  start_y += (step - (float)fabs(fmod(v2d->cur.ymin, step)));
1231  }
1232 
1233  if (start_y > v2d->cur.ymax) {
1234  count_y = 0;
1235  }
1236  else {
1237  count_y = (v2d->cur.ymax - start_y) / step + 1;
1238  }
1239 
1240  if (count_x > 0 || count_y > 0) {
1243  const uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1244  float theme_color[3];
1245 
1246  UI_GetThemeColorShade3fv(TH_BACK, -10, theme_color);
1247 
1249  immBegin(GPU_PRIM_LINES, count_x * 2 + count_y * 2 + 4);
1250 
1251  immAttr3fv(color, theme_color);
1252  for (int i = 0; i < count_x; start_x += step, i++) {
1253  immVertex2f(pos, start_x, v2d->cur.ymin);
1254  immVertex2f(pos, start_x, v2d->cur.ymax);
1255  }
1256 
1257  for (int i = 0; i < count_y; start_y += step, i++) {
1258  immVertex2f(pos, v2d->cur.xmin, start_y);
1259  immVertex2f(pos, v2d->cur.xmax, start_y);
1260  }
1261 
1262  /* X and Y axis */
1263  UI_GetThemeColorShade3fv(TH_BACK, -18, theme_color);
1264 
1265  immAttr3fv(color, theme_color);
1266  immVertex2f(pos, 0.0f, v2d->cur.ymin);
1267  immVertex2f(pos, 0.0f, v2d->cur.ymax);
1268  immVertex2f(pos, v2d->cur.xmin, 0.0f);
1269  immVertex2f(pos, v2d->cur.xmax, 0.0f);
1270 
1271  immEnd();
1272  immUnbindProgram();
1273  }
1274 }
1275 
1276 /* Draw a multi-level grid in given 2d-region */
1278  const View2D *v2d, int colorid, float step, int level_size, int totlevels)
1279 {
1280  /* Exit if there is nothing to draw */
1281  if (totlevels == 0) {
1282  return;
1283  }
1284 
1285  int offset = -10;
1286  float lstep = step;
1287  uchar grid_line_color[3];
1288 
1289  /* Make an estimate of at least how many vertices will be needed */
1290  uint vertex_count = 4;
1291  vertex_count += 2 * ((int)((v2d->cur.xmax - v2d->cur.xmin) / lstep) + 1);
1292  vertex_count += 2 * ((int)((v2d->cur.ymax - v2d->cur.ymin) / lstep) + 1);
1293 
1296  uint color = GPU_vertformat_attr_add(
1298 
1299  GPU_line_width(1.0f);
1300 
1302  immBeginAtMost(GPU_PRIM_LINES, vertex_count);
1303 
1304  for (int level = 0; level < totlevels; level++) {
1305  /* Blend the background color (colorid) with the grid color, to avoid either too low contrast
1306  * or high contrast grid lines. This only has an effect if colorid != TH_GRID. */
1307  UI_GetThemeColorBlendShade3ubv(colorid, TH_GRID, 0.25f, offset, grid_line_color);
1308 
1309  int i = (int)(v2d->cur.xmin / lstep);
1310  if (v2d->cur.xmin > 0.0f) {
1311  i++;
1312  }
1313  float start = i * lstep;
1314 
1315  for (; start < v2d->cur.xmax; start += lstep, i++) {
1316  if (i == 0 || (level < totlevels - 1 && i % level_size == 0)) {
1317  continue;
1318  }
1319 
1320  immAttrSkip(color);
1321  immVertex2f(pos, start, v2d->cur.ymin);
1322  immAttr3ubv(color, grid_line_color);
1323  immVertex2f(pos, start, v2d->cur.ymax);
1324  }
1325 
1326  i = (int)(v2d->cur.ymin / lstep);
1327  if (v2d->cur.ymin > 0.0f) {
1328  i++;
1329  }
1330  start = i * lstep;
1331 
1332  for (; start < v2d->cur.ymax; start += lstep, i++) {
1333  if (i == 0 || (level < totlevels - 1 && i % level_size == 0)) {
1334  continue;
1335  }
1336 
1337  immAttrSkip(color);
1338  immVertex2f(pos, v2d->cur.xmin, start);
1339  immAttr3ubv(color, grid_line_color);
1340  immVertex2f(pos, v2d->cur.xmax, start);
1341  }
1342 
1343  lstep *= level_size;
1344  offset -= 6;
1345  }
1346 
1347  /* X and Y axis */
1349  colorid, TH_GRID, 0.5f, -18 + ((totlevels - 1) * -6), grid_line_color);
1350 
1351  immAttrSkip(color);
1352  immVertex2f(pos, 0.0f, v2d->cur.ymin);
1353  immAttr3ubv(color, grid_line_color);
1354  immVertex2f(pos, 0.0f, v2d->cur.ymax);
1355 
1356  immAttrSkip(color);
1357  immVertex2f(pos, v2d->cur.xmin, 0.0f);
1358  immAttr3ubv(color, grid_line_color);
1359  immVertex2f(pos, v2d->cur.xmax, 0.0f);
1360 
1361  immEnd();
1362  immUnbindProgram();
1363 }
1364 
1367 /* -------------------------------------------------------------------- */
1378  /* focus bubbles */
1379  int vert_min, vert_max; /* vertical scrollbar */
1380  int hor_min, hor_max; /* horizontal scrollbar */
1381 
1384  /* set if sliders are full, we don't draw them */
1385  /* int horfull, vertfull; */ /* UNUSED */
1386 };
1387 
1388 /* Calculate relevant scroller properties */
1390  const rcti *mask_custom,
1391  struct View2DScrollers *r_scrollers)
1392 {
1393  rcti vert, hor;
1394  float fac1, fac2, totsize, scrollsize;
1395  const int scroll = view2d_scroll_mapped(v2d->scroll);
1396  int smaller;
1397 
1398  /* Always update before drawing (for dynamically sized scrollers). */
1399  view2d_masks(v2d, mask_custom);
1400 
1401  vert = v2d->vert;
1402  hor = v2d->hor;
1403 
1404  /* slider rects need to be smaller than region and not interfere with splitter areas */
1405  hor.xmin += UI_HEADER_OFFSET;
1406  hor.xmax -= UI_HEADER_OFFSET;
1407  vert.ymin += UI_HEADER_OFFSET;
1408  vert.ymax -= UI_HEADER_OFFSET;
1409 
1410  /* width of sliders */
1411  smaller = (int)(0.1f * U.widget_unit);
1412  if (scroll & V2D_SCROLL_BOTTOM) {
1413  hor.ymin += smaller;
1414  }
1415  else {
1416  hor.ymax -= smaller;
1417  }
1418 
1419  if (scroll & V2D_SCROLL_LEFT) {
1420  vert.xmin += smaller;
1421  }
1422  else {
1423  vert.xmax -= smaller;
1424  }
1425 
1428 
1429  /* store in scrollers, used for drawing */
1430  r_scrollers->vert = vert;
1431  r_scrollers->hor = hor;
1432 
1433  /* scroller 'buttons':
1434  * - These should always remain within the visible region of the scrollbar
1435  * - They represent the region of 'tot' that is visible in 'cur'
1436  */
1437 
1438  /* horizontal scrollers */
1439  if (scroll & V2D_SCROLL_HORIZONTAL) {
1440  /* scroller 'button' extents */
1441  totsize = BLI_rctf_size_x(&v2d->tot);
1442  scrollsize = (float)BLI_rcti_size_x(&hor);
1443  if (totsize == 0.0f) {
1444  totsize = 1.0f; /* avoid divide by zero */
1445  }
1446 
1447  fac1 = (v2d->cur.xmin - v2d->tot.xmin) / totsize;
1448  if (fac1 <= 0.0f) {
1449  r_scrollers->hor_min = hor.xmin;
1450  }
1451  else {
1452  r_scrollers->hor_min = (int)(hor.xmin + (fac1 * scrollsize));
1453  }
1454 
1455  fac2 = (v2d->cur.xmax - v2d->tot.xmin) / totsize;
1456  if (fac2 >= 1.0f) {
1457  r_scrollers->hor_max = hor.xmax;
1458  }
1459  else {
1460  r_scrollers->hor_max = (int)(hor.xmin + (fac2 * scrollsize));
1461  }
1462 
1463  /* prevent inverted sliders */
1464  if (r_scrollers->hor_min > r_scrollers->hor_max) {
1465  r_scrollers->hor_min = r_scrollers->hor_max;
1466  }
1467  /* prevent sliders from being too small to grab */
1468  if ((r_scrollers->hor_max - r_scrollers->hor_min) < V2D_SCROLL_THUMB_SIZE_MIN) {
1469  r_scrollers->hor_max = r_scrollers->hor_min + V2D_SCROLL_THUMB_SIZE_MIN;
1470 
1471  CLAMP(r_scrollers->hor_max, hor.xmin + V2D_SCROLL_THUMB_SIZE_MIN, hor.xmax);
1472  CLAMP(r_scrollers->hor_min, hor.xmin, hor.xmax - V2D_SCROLL_THUMB_SIZE_MIN);
1473  }
1474  }
1475 
1476  /* vertical scrollers */
1477  if (scroll & V2D_SCROLL_VERTICAL) {
1478  /* scroller 'button' extents */
1479  totsize = BLI_rctf_size_y(&v2d->tot);
1480  scrollsize = (float)BLI_rcti_size_y(&vert);
1481  if (totsize == 0.0f) {
1482  totsize = 1.0f; /* avoid divide by zero */
1483  }
1484 
1485  fac1 = (v2d->cur.ymin - v2d->tot.ymin) / totsize;
1486  if (fac1 <= 0.0f) {
1487  r_scrollers->vert_min = vert.ymin;
1488  }
1489  else {
1490  r_scrollers->vert_min = (int)(vert.ymin + (fac1 * scrollsize));
1491  }
1492 
1493  fac2 = (v2d->cur.ymax - v2d->tot.ymin) / totsize;
1494  if (fac2 >= 1.0f) {
1495  r_scrollers->vert_max = vert.ymax;
1496  }
1497  else {
1498  r_scrollers->vert_max = (int)(vert.ymin + (fac2 * scrollsize));
1499  }
1500 
1501  /* prevent inverted sliders */
1502  if (r_scrollers->vert_min > r_scrollers->vert_max) {
1503  r_scrollers->vert_min = r_scrollers->vert_max;
1504  }
1505  /* prevent sliders from being too small to grab */
1506  if ((r_scrollers->vert_max - r_scrollers->vert_min) < V2D_SCROLL_THUMB_SIZE_MIN) {
1507  r_scrollers->vert_max = r_scrollers->vert_min + V2D_SCROLL_THUMB_SIZE_MIN;
1508 
1509  CLAMP(r_scrollers->vert_max, vert.ymin + V2D_SCROLL_THUMB_SIZE_MIN, vert.ymax);
1510  CLAMP(r_scrollers->vert_min, vert.ymin, vert.ymax - V2D_SCROLL_THUMB_SIZE_MIN);
1511  }
1512  }
1513 }
1514 
1515 /* Draw scrollbars in the given 2d-region */
1516 void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
1517 {
1518  View2DScrollers scrollers;
1519  UI_view2d_scrollers_calc(v2d, mask_custom, &scrollers);
1520  bTheme *btheme = UI_GetTheme();
1521  rcti vert, hor;
1522  const int scroll = view2d_scroll_mapped(v2d->scroll);
1523  const char emboss_alpha = btheme->tui.widget_emboss[3];
1524  uchar scrollers_back_color[4];
1525 
1526  /* Color for scrollbar backs */
1527  UI_GetThemeColor4ubv(TH_BACK, scrollers_back_color);
1528 
1529  /* make copies of rects for less typing */
1530  vert = scrollers.vert;
1531  hor = scrollers.hor;
1532 
1533  /* horizontal scrollbar */
1534  if (scroll & V2D_SCROLL_HORIZONTAL) {
1535  uiWidgetColors wcol = btheme->tui.wcol_scroll;
1536  const float alpha_fac = v2d->alpha_hor / 255.0f;
1537  rcti slider;
1538  int state;
1539 
1540  slider.xmin = scrollers.hor_min;
1541  slider.xmax = scrollers.hor_max;
1542  slider.ymin = hor.ymin;
1543  slider.ymax = hor.ymax;
1544 
1546 
1547  wcol.inner[3] *= alpha_fac;
1548  wcol.item[3] *= alpha_fac;
1549  wcol.outline[3] *= alpha_fac;
1550  btheme->tui.widget_emboss[3] *= alpha_fac; /* will be reset later */
1551 
1552  /* show zoom handles if:
1553  * - zooming on x-axis is allowed (no scroll otherwise)
1554  * - slider bubble is large enough (no overdraw confusion)
1555  * - scale is shown on the scroller
1556  * (workaround to make sure that button windows don't show these,
1557  * and only the time-grids with their zoom-ability can do so).
1558  */
1559  if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 && (v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) &&
1562  }
1563 
1564  UI_draw_widget_scroll(&wcol, &hor, &slider, state);
1565  }
1566 
1567  /* vertical scrollbar */
1568  if (scroll & V2D_SCROLL_VERTICAL) {
1569  uiWidgetColors wcol = btheme->tui.wcol_scroll;
1570  rcti slider;
1571  const float alpha_fac = v2d->alpha_vert / 255.0f;
1572  int state;
1573 
1574  slider.xmin = vert.xmin;
1575  slider.xmax = vert.xmax;
1576  slider.ymin = scrollers.vert_min;
1577  slider.ymax = scrollers.vert_max;
1578 
1580 
1581  wcol.inner[3] *= alpha_fac;
1582  wcol.item[3] *= alpha_fac;
1583  wcol.outline[3] *= alpha_fac;
1584  btheme->tui.widget_emboss[3] *= alpha_fac; /* will be reset later */
1585 
1586  /* show zoom handles if:
1587  * - zooming on y-axis is allowed (no scroll otherwise)
1588  * - slider bubble is large enough (no overdraw confusion)
1589  * - scale is shown on the scroller
1590  * (workaround to make sure that button windows don't show these,
1591  * and only the time-grids with their zoomability can do so)
1592  */
1593  if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 && (v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) &&
1596  }
1597 
1598  UI_draw_widget_scroll(&wcol, &vert, &slider, state);
1599  }
1600 
1601  /* Was changed above, so reset. */
1602  btheme->tui.widget_emboss[3] = emboss_alpha;
1603 }
1604 
1607 /* -------------------------------------------------------------------- */
1623 void UI_view2d_listview_view_to_cell(float columnwidth,
1624  float rowheight,
1625  float startx,
1626  float starty,
1627  float viewx,
1628  float viewy,
1629  int *r_column,
1630  int *r_row)
1631 {
1632  if (r_column) {
1633  if (columnwidth > 0) {
1634  /* Columns go from left to right (x increases). */
1635  *r_column = floorf((viewx - startx) / columnwidth);
1636  }
1637  else {
1638  *r_column = 0;
1639  }
1640  }
1641 
1642  if (r_row) {
1643  if (rowheight > 0) {
1644  /* Rows got from top to bottom (y decreases). */
1645  *r_row = floorf((starty - viewy) / rowheight);
1646  }
1647  else {
1648  *r_row = 0;
1649  }
1650  }
1651 }
1652 
1655 /* -------------------------------------------------------------------- */
1659 float UI_view2d_region_to_view_x(const struct View2D *v2d, float x)
1660 {
1661  return (v2d->cur.xmin +
1662  (BLI_rctf_size_x(&v2d->cur) * (x - v2d->mask.xmin) / BLI_rcti_size_x(&v2d->mask)));
1663 }
1664 float UI_view2d_region_to_view_y(const struct View2D *v2d, float y)
1665 {
1666  return (v2d->cur.ymin +
1667  (BLI_rctf_size_y(&v2d->cur) * (y - v2d->mask.ymin) / BLI_rcti_size_y(&v2d->mask)));
1668 }
1669 
1677  const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y)
1678 {
1679  *r_view_x = UI_view2d_region_to_view_x(v2d, x);
1680  *r_view_y = UI_view2d_region_to_view_y(v2d, y);
1681 }
1682 
1683 void UI_view2d_region_to_view_rctf(const View2D *v2d, const rctf *rect_src, rctf *rect_dst)
1684 {
1685  const float cur_size[2] = {BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur)};
1686  const float mask_size[2] = {BLI_rcti_size_x(&v2d->mask), BLI_rcti_size_y(&v2d->mask)};
1687 
1688  rect_dst->xmin = (v2d->cur.xmin +
1689  (cur_size[0] * (rect_src->xmin - v2d->mask.xmin) / mask_size[0]));
1690  rect_dst->xmax = (v2d->cur.xmin +
1691  (cur_size[0] * (rect_src->xmax - v2d->mask.xmin) / mask_size[0]));
1692  rect_dst->ymin = (v2d->cur.ymin +
1693  (cur_size[1] * (rect_src->ymin - v2d->mask.ymin) / mask_size[1]));
1694  rect_dst->ymax = (v2d->cur.ymin +
1695  (cur_size[1] * (rect_src->ymax - v2d->mask.ymin) / mask_size[1]));
1696 }
1697 
1698 float UI_view2d_view_to_region_x(const View2D *v2d, float x)
1699 {
1700  return (v2d->mask.xmin +
1701  (((x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur)) * BLI_rcti_size_x(&v2d->mask)));
1702 }
1703 float UI_view2d_view_to_region_y(const View2D *v2d, float y)
1704 {
1705  return (v2d->mask.ymin +
1706  (((y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur)) * BLI_rcti_size_y(&v2d->mask)));
1707 }
1708 
1717  const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
1718 {
1719  /* express given coordinates as proportional values */
1720  x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
1721  y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
1722 
1723  /* check if values are within bounds */
1724  if ((x >= 0.0f) && (x <= 1.0f) && (y >= 0.0f) && (y <= 1.0f)) {
1725  *r_region_x = (int)(v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask)));
1726  *r_region_y = (int)(v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask)));
1727 
1728  return true;
1729  }
1730 
1731  /* set initial value in case coordinate lies outside of bounds */
1732  *r_region_x = *r_region_y = V2D_IS_CLIPPED;
1733 
1734  return false;
1735 }
1736 
1746  const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
1747 {
1748  /* step 1: express given coordinates as proportional values */
1749  x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
1750  y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
1751 
1752  /* step 2: convert proportional distances to screen coordinates */
1753  x = v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask));
1754  y = v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask));
1755 
1756  /* although we don't clamp to lie within region bounds, we must avoid exceeding size of ints */
1757  *r_region_x = clamp_float_to_int(x);
1758  *r_region_y = clamp_float_to_int(y);
1759 }
1760 
1762  const View2D *v2d, float x, float y, float *r_region_x, float *r_region_y)
1763 {
1764  /* express given coordinates as proportional values */
1765  x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
1766  y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
1767 
1768  /* convert proportional distances to screen coordinates */
1769  *r_region_x = v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask));
1770  *r_region_y = v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask));
1771 }
1772 
1773 void UI_view2d_view_to_region_rcti(const View2D *v2d, const rctf *rect_src, rcti *rect_dst)
1774 {
1775  const float cur_size[2] = {BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur)};
1776  const float mask_size[2] = {BLI_rcti_size_x(&v2d->mask), BLI_rcti_size_y(&v2d->mask)};
1777  rctf rect_tmp;
1778 
1779  /* step 1: express given coordinates as proportional values */
1780  rect_tmp.xmin = (rect_src->xmin - v2d->cur.xmin) / cur_size[0];
1781  rect_tmp.xmax = (rect_src->xmax - v2d->cur.xmin) / cur_size[0];
1782  rect_tmp.ymin = (rect_src->ymin - v2d->cur.ymin) / cur_size[1];
1783  rect_tmp.ymax = (rect_src->ymax - v2d->cur.ymin) / cur_size[1];
1784 
1785  /* step 2: convert proportional distances to screen coordinates */
1786  rect_tmp.xmin = v2d->mask.xmin + (rect_tmp.xmin * mask_size[0]);
1787  rect_tmp.xmax = v2d->mask.xmin + (rect_tmp.xmax * mask_size[0]);
1788  rect_tmp.ymin = v2d->mask.ymin + (rect_tmp.ymin * mask_size[1]);
1789  rect_tmp.ymax = v2d->mask.ymin + (rect_tmp.ymax * mask_size[1]);
1790 
1791  clamp_rctf_to_rcti(rect_dst, &rect_tmp);
1792 }
1793 
1794 void UI_view2d_view_to_region_m4(const View2D *v2d, float matrix[4][4])
1795 {
1796  rctf mask;
1797  unit_m4(matrix);
1798  BLI_rctf_rcti_copy(&mask, &v2d->mask);
1800 }
1801 
1802 bool UI_view2d_view_to_region_rcti_clip(const View2D *v2d, const rctf *rect_src, rcti *rect_dst)
1803 {
1804  const float cur_size[2] = {BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur)};
1805  const float mask_size[2] = {BLI_rcti_size_x(&v2d->mask), BLI_rcti_size_y(&v2d->mask)};
1806  rctf rect_tmp;
1807 
1808  BLI_assert(rect_src->xmin <= rect_src->xmax && rect_src->ymin <= rect_src->ymax);
1809 
1810  /* step 1: express given coordinates as proportional values */
1811  rect_tmp.xmin = (rect_src->xmin - v2d->cur.xmin) / cur_size[0];
1812  rect_tmp.xmax = (rect_src->xmax - v2d->cur.xmin) / cur_size[0];
1813  rect_tmp.ymin = (rect_src->ymin - v2d->cur.ymin) / cur_size[1];
1814  rect_tmp.ymax = (rect_src->ymax - v2d->cur.ymin) / cur_size[1];
1815 
1816  if (((rect_tmp.xmax < 0.0f) || (rect_tmp.xmin > 1.0f) || (rect_tmp.ymax < 0.0f) ||
1817  (rect_tmp.ymin > 1.0f)) == 0) {
1818  /* step 2: convert proportional distances to screen coordinates */
1819  rect_tmp.xmin = v2d->mask.xmin + (rect_tmp.xmin * mask_size[0]);
1820  rect_tmp.xmax = v2d->mask.ymin + (rect_tmp.xmax * mask_size[0]);
1821  rect_tmp.ymin = v2d->mask.ymin + (rect_tmp.ymin * mask_size[1]);
1822  rect_tmp.ymax = v2d->mask.ymin + (rect_tmp.ymax * mask_size[1]);
1823 
1824  clamp_rctf_to_rcti(rect_dst, &rect_tmp);
1825 
1826  return true;
1827  }
1828 
1829  rect_dst->xmin = rect_dst->xmax = rect_dst->ymin = rect_dst->ymax = V2D_IS_CLIPPED;
1830  return false;
1831 }
1832 
1835 /* -------------------------------------------------------------------- */
1839 /* View2D data by default resides in region, so get from region stored in context */
1841 {
1842  ScrArea *area = CTX_wm_area(C);
1843  ARegion *region = CTX_wm_region(C);
1844 
1845  if (area == NULL) {
1846  return NULL;
1847  }
1848  if (region == NULL) {
1849  return NULL;
1850  }
1851  return &(region->v2d);
1852 }
1853 
1854 /* same as above, but it returns regionwindow. Utility for pulldowns or buttons */
1856 {
1857  ScrArea *area = CTX_wm_area(C);
1858  ARegion *region = CTX_wm_region(C);
1859 
1860  if (area == NULL) {
1861  return NULL;
1862  }
1863  if (region == NULL) {
1864  return NULL;
1865  }
1866  if (region->regiontype != RGN_TYPE_WINDOW) {
1868  return region_win ? &(region_win->v2d) : NULL;
1869  }
1870  return &(region->v2d);
1871 }
1872 
1873 /* Get scrollbar sizes of the current 2D view. The size will be zero if the view has its scrollbars
1874  * disabled. */
1875 void UI_view2d_scroller_size_get(const View2D *v2d, float *r_x, float *r_y)
1876 {
1877  const int scroll = view2d_scroll_mapped(v2d->scroll);
1878 
1879  if (r_x) {
1880  if (scroll & V2D_SCROLL_VERTICAL) {
1882  }
1883  else {
1884  *r_x = 0;
1885  }
1886  }
1887  if (r_y) {
1888  if (scroll & V2D_SCROLL_HORIZONTAL) {
1891  }
1892  else {
1893  *r_y = 0;
1894  }
1895  }
1896 }
1897 
1906 void UI_view2d_scale_get(const View2D *v2d, float *r_x, float *r_y)
1907 {
1908  if (r_x) {
1909  *r_x = UI_view2d_scale_get_x(v2d);
1910  }
1911  if (r_y) {
1912  *r_y = UI_view2d_scale_get_y(v2d);
1913  }
1914 }
1916 {
1917  return BLI_rcti_size_x(&v2d->mask) / BLI_rctf_size_x(&v2d->cur);
1918 }
1920 {
1921  return BLI_rcti_size_y(&v2d->mask) / BLI_rctf_size_y(&v2d->cur);
1922 }
1926 void UI_view2d_scale_get_inverse(const View2D *v2d, float *r_x, float *r_y)
1927 {
1928  if (r_x) {
1929  *r_x = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
1930  }
1931  if (r_y) {
1932  *r_y = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
1933  }
1934 }
1935 
1940 void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y)
1941 {
1942  /* get center */
1943  if (r_x) {
1944  *r_x = BLI_rctf_cent_x(&v2d->cur);
1945  }
1946  if (r_y) {
1947  *r_y = BLI_rctf_cent_y(&v2d->cur);
1948  }
1949 }
1950 void UI_view2d_center_set(struct View2D *v2d, float x, float y)
1951 {
1952  BLI_rctf_recenter(&v2d->cur, x, y);
1953 
1954  /* make sure that 'cur' rect is in a valid state as a result of these changes */
1956 }
1957 
1964 void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac)
1965 {
1966  if (xfac != -1.0f) {
1967  const float xsize = BLI_rctf_size_x(&v2d->cur);
1968  const float xmin = v2d->tot.xmin;
1969  const float xmax = v2d->tot.xmax - xsize;
1970 
1971  v2d->cur.xmin = (xmin * (1.0f - xfac)) + (xmax * xfac);
1972  v2d->cur.xmax = v2d->cur.xmin + xsize;
1973  }
1974 
1975  if (yfac != -1.0f) {
1976  const float ysize = BLI_rctf_size_y(&v2d->cur);
1977  const float ymin = v2d->tot.ymin;
1978  const float ymax = v2d->tot.ymax - ysize;
1979 
1980  v2d->cur.ymin = (ymin * (1.0f - yfac)) + (ymax * yfac);
1981  v2d->cur.ymax = v2d->cur.ymin + ysize;
1982  }
1983 
1985 }
1986 
1999  const ARegion *region, const View2D *v2d, int x, int y, int *r_scroll)
2000 {
2001  const int scroll = view2d_scroll_mapped(v2d->scroll);
2002  *r_scroll = scroll;
2003 
2004  if (scroll) {
2005  /* Move to region-coordinates. */
2006  const int co[2] = {
2007  x - region->winrct.xmin,
2008  y - region->winrct.ymin,
2009  };
2010  if (scroll & V2D_SCROLL_HORIZONTAL) {
2011  if (IN_2D_HORIZ_SCROLL(v2d, co)) {
2012  return 'h';
2013  }
2014  }
2015  if (scroll & V2D_SCROLL_VERTICAL) {
2016  if (IN_2D_VERT_SCROLL(v2d, co)) {
2017  return 'v';
2018  }
2019  }
2020  }
2021 
2022  return 0;
2023 }
2024 
2026  const View2D *v2d,
2027  const rcti *rect,
2028  int *r_scroll)
2029 {
2030  const int scroll = view2d_scroll_mapped(v2d->scroll);
2031  *r_scroll = scroll;
2032 
2033  if (scroll) {
2034  /* Move to region-coordinates. */
2035  rcti rect_region = *rect;
2036  BLI_rcti_translate(&rect_region, -region->winrct.xmin, region->winrct.ymin);
2037  if (scroll & V2D_SCROLL_HORIZONTAL) {
2038  if (IN_2D_HORIZ_SCROLL_RECT(v2d, &rect_region)) {
2039  return 'h';
2040  }
2041  }
2042  if (scroll & V2D_SCROLL_VERTICAL) {
2043  if (IN_2D_VERT_SCROLL_RECT(v2d, &rect_region)) {
2044  return 'v';
2045  }
2046  }
2047  }
2048 
2049  return 0;
2050 }
2051 
2052 char UI_view2d_mouse_in_scrollers(const ARegion *region, const View2D *v2d, int x, int y)
2053 {
2054  int scroll_dummy = 0;
2055  return UI_view2d_mouse_in_scrollers_ex(region, v2d, x, y, &scroll_dummy);
2056 }
2057 
2058 char UI_view2d_rect_in_scrollers(const ARegion *region, const View2D *v2d, const rcti *rect)
2059 {
2060  int scroll_dummy = 0;
2061  return UI_view2d_rect_in_scrollers_ex(region, v2d, rect, &scroll_dummy);
2062 }
2063 
2066 /* -------------------------------------------------------------------- */
2070 typedef struct View2DString {
2072  union {
2073  uchar ub[4];
2074  int pack;
2075  } col;
2077  int mval[2];
2078 
2079  /* str is allocated past the end */
2080  char str[0];
2082 
2083 /* assumes caches are used correctly, so for time being no local storage in v2d */
2086 
2088  View2D *v2d, float x, float y, const char *str, size_t str_len, const uchar col[4])
2089 {
2090  int mval[2];
2091 
2092  BLI_assert(str_len == strlen(str));
2093 
2094  if (UI_view2d_view_to_region_clip(v2d, x, y, &mval[0], &mval[1])) {
2095  const int alloc_len = str_len + 1;
2096  View2DString *v2s;
2097 
2098  if (g_v2d_strings_arena == NULL) {
2100  }
2101 
2102  v2s = BLI_memarena_alloc(g_v2d_strings_arena, sizeof(View2DString) + alloc_len);
2103 
2105 
2106  v2s->col.pack = *((const int *)col);
2107 
2108  memset(&v2s->rect, 0, sizeof(v2s->rect));
2109 
2110  v2s->mval[0] = mval[0];
2111  v2s->mval[1] = mval[1];
2112 
2113  memcpy(v2s->str, str, alloc_len);
2114  }
2115 }
2116 
2117 /* no clip (yet) */
2119  View2D *v2d, const rctf *rect_view, const char *str, size_t str_len, const uchar col[4])
2120 {
2121  rcti rect;
2122 
2123  BLI_assert(str_len == strlen(str));
2124 
2125  if (UI_view2d_view_to_region_rcti_clip(v2d, rect_view, &rect)) {
2126  const int alloc_len = str_len + 1;
2127  View2DString *v2s;
2128 
2129  if (g_v2d_strings_arena == NULL) {
2131  }
2132 
2133  v2s = BLI_memarena_alloc(g_v2d_strings_arena, sizeof(View2DString) + alloc_len);
2134 
2136 
2137  v2s->col.pack = *((const int *)col);
2138 
2139  v2s->rect = rect;
2140 
2141  v2s->mval[0] = v2s->rect.xmin;
2142  v2s->mval[1] = v2s->rect.ymin;
2143 
2144  memcpy(v2s->str, str, alloc_len);
2145  }
2146 }
2147 
2149 {
2150  View2DString *v2s;
2151  int col_pack_prev = 0;
2152 
2153  /* investigate using BLF_ascender() */
2154  const int font_id = BLF_default();
2155 
2156  BLF_set_default();
2157  const float default_height = g_v2d_strings ? BLF_height(font_id, "28", 3) : 0.0f;
2158 
2160 
2161  for (v2s = g_v2d_strings; v2s; v2s = v2s->next) {
2162  int xofs = 0, yofs;
2163 
2164  yofs = ceil(0.5f * (BLI_rcti_size_y(&v2s->rect) - default_height));
2165  if (yofs < 1) {
2166  yofs = 1;
2167  }
2168 
2169  if (col_pack_prev != v2s->col.pack) {
2170  BLF_color3ubv(font_id, v2s->col.ub);
2171  col_pack_prev = v2s->col.pack;
2172  }
2173 
2174  if (v2s->rect.xmin >= v2s->rect.xmax) {
2175  BLF_draw_default((float)(v2s->mval[0] + xofs),
2176  (float)(v2s->mval[1] + yofs),
2177  0.0,
2178  v2s->str,
2180  }
2181  else {
2182  BLF_enable(font_id, BLF_CLIPPING);
2183  BLF_clipping(
2184  font_id, v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4);
2186  v2s->rect.xmin + xofs, v2s->rect.ymin + yofs, 0.0f, v2s->str, BLF_DRAW_STR_DUMMY_MAX);
2187  BLF_disable(font_id, BLF_CLIPPING);
2188  }
2189  }
2190  g_v2d_strings = NULL;
2191 
2192  if (g_v2d_strings_arena) {
2195  }
2196 }
2197 
typedef float(TangentPoint)[2]
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:714
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
@ G_DEBUG
Definition: BKE_global.h:133
struct ARegion * BKE_area_find_region_type(const struct ScrArea *area, int type)
void BLF_draw_default(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL()
Definition: blf_default.c:71
#define BLF_CLIPPING
Definition: BLF_api.h:270
void BLF_color3ubv(int fontid, const unsigned char rgb[3])
Definition: blf.c:411
void BLF_cache_clear(void)
Definition: blf.c:105
int BLF_default(void)
Definition: blf_default.c:55
#define BLF_DRAW_STR_DUMMY_MAX
Definition: BLF_api.h:283
void BLF_disable(int fontid, int option)
Definition: blf.c:283
float BLF_height(int fontid, const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: blf.c:752
void BLF_enable(int fontid, int option)
Definition: blf.c:274
void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax)
Definition: blf.c:810
int BLF_set_default(void)
Definition: blf_default.c:61
A (mainly) macro array library.
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_INLINE
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void unit_m4(float m[4][4])
Definition: rct.c:1140
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:109
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:131
struct MemArena * BLI_memarena_new(const size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2) ATTR_MALLOC
Definition: BLI_memarena.c:79
void BLI_rctf_translate(struct rctf *rect, float x, float y)
Definition: rct.c:604
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:157
BLI_INLINE float BLI_rctf_cent_y(const struct rctf *rct)
Definition: BLI_rect.h:148
BLI_INLINE float BLI_rctf_cent_x(const struct rctf *rct)
Definition: BLI_rect.h:144
void BLI_rcti_translate(struct rcti *rect, int x, int y)
Definition: rct.c:597
void BLI_rctf_transform_calc_m4_pivot_min(const rctf *dst, const rctf *src, float matrix[4][4])
Definition: rct.c:592
void BLI_rctf_recenter(struct rctf *rect, float x, float y)
Definition: rct.c:618
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:153
void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src)
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition: BLI_rect.h:161
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition: BLI_rect.h:165
unsigned char uchar
Definition: BLI_sys_types.h:86
unsigned int uint
Definition: BLI_sys_types.h:83
#define CLAMP_MAX(a, c)
#define UNLIKELY(x)
#define ELEM(...)
@ RGN_TYPE_WINDOW
@ SPACE_CLIP
@ SPACE_ACTION
@ SPACE_NLA
@ SPACE_SEQ
@ SPACE_GRAPH
@ V2D_VIEWSYNC_SCREEN_TIME
@ V2D_PIXELOFS_X
@ V2D_IS_INIT
@ V2D_PIXELOFS_Y
@ V2D_VIEWSYNC_AREA_VERTICAL
@ V2D_SCROLL_V_ACTIVE
@ V2D_SCROLL_H_ACTIVE
@ V2D_KEEPTOT_BOUNDS
@ V2D_KEEPTOT_STRICT
@ V2D_SCROLL_LEFT
@ V2D_SCROLL_HORIZONTAL_FULLR
@ V2D_SCROLL_HORIZONTAL_HIDE
@ V2D_SCROLL_VERTICAL_FULLR
@ V2D_SCROLL_VERTICAL_HIDE
@ V2D_SCROLL_HORIZONTAL
@ V2D_SCROLL_TOP
@ V2D_SCROLL_VERTICAL_HANDLES
@ V2D_SCROLL_RIGHT
@ V2D_SCROLL_BOTTOM
@ V2D_SCROLL_HORIZONTAL_HANDLES
@ V2D_SCROLL_VERTICAL
@ V2D_ALIGN_NO_NEG_X
@ V2D_ALIGN_NO_NEG_Y
@ V2D_ALIGN_NO_POS_Y
@ V2D_ALIGN_NO_POS_X
@ V2D_LIMITZOOM
@ V2D_LOCKZOOM_X
@ V2D_KEEPZOOM
@ V2D_KEEPASPECT
@ V2D_LOCKZOOM_Y
@ V2D_LOCKOFS_X
@ V2D_LOCKOFS_Y
@ V2D_KEEPOFS_Y
@ V2D_KEEPOFS_X
void ED_region_tag_redraw_no_rebuild(struct ARegion *region)
Definition: area.c:686
void immAttr3ubv(uint attr_id, const unsigned char data[3])
void immAttrSkip(uint attr_id)
void immUnbindProgram(void)
void immVertex2f(uint attr_id, float x, float y)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immBeginAtMost(GPUPrimType, uint max_vertex_len)
GPUVertFormat * immVertexFormat(void)
void immAttr3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void immEnd(void)
_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 width
_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 type
_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
void GPU_matrix_identity_set(void)
Definition: gpu_matrix.cc:184
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:36
@ GPU_SHADER_2D_FLAT_COLOR
Definition: GPU_shader.h:178
void GPU_line_width(float width)
Definition: gpu_state.cc:173
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT_TO_FLOAT_UNIT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
@ GPU_COMP_U8
Read Guarded memory(de)allocation.
#define MEM_SIZE_OPTIMAL(size)
Group RGB to Bright Vector Camera CLAMP
#define C
Definition: RandGen.cpp:39
const struct uiStyle * UI_style_get(void)
#define UI_HEADER_OFFSET
@ UI_SCROLL_PRESSED
Definition: UI_interface.h:457
@ UI_SCROLL_ARROWS
Definition: UI_interface.h:458
void UI_draw_widget_scroll(struct uiWidgetColors *wcol, const struct rcti *rect, const struct rcti *slider, int state)
@ TH_GRID
Definition: UI_resources.h:84
@ TH_BACK
Definition: UI_resources.h:55
void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3])
Definition: resources.c:1218
struct bTheme * UI_GetTheme(void)
Definition: resources.c:1086
void UI_GetThemeColorBlendShade3ubv(int colorid1, int colorid2, float fac, int offset, unsigned char col[3])
Definition: resources.c:1252
void UI_GetThemeColor4ubv(int colorid, unsigned char col[4])
Definition: resources.c:1381
#define V2D_SCROLL_HEIGHT
Definition: UI_view2d.h:67
#define V2D_LOCK_COPY
Definition: UI_view2d.h:84
#define V2D_SCROLL_HANDLE_HEIGHT
Definition: UI_view2d.h:70
#define V2D_SCROLL_THUMB_SIZE_MIN
Definition: UI_view2d.h:77
#define IN_2D_HORIZ_SCROLL(v2d, co)
Definition: UI_view2d.h:91
#define V2D_SCROLL_WIDTH
Definition: UI_view2d.h:68
#define V2D_SCROLL_HANDLE_WIDTH
Definition: UI_view2d.h:71
#define IN_2D_VERT_SCROLL(v2d, co)
Definition: UI_view2d.h:90
#define UI_TIME_SCRUB_MARGIN_Y
Definition: UI_view2d.h:283
#define IN_2D_VERT_SCROLL_RECT(v2d, rct)
Definition: UI_view2d.h:93
#define V2D_SCROLL_HANDLE_SIZE_HOTSPOT
Definition: UI_view2d.h:74
@ V2D_COMMONVIEW_LIST
Definition: UI_view2d.h:53
@ V2D_COMMONVIEW_STACK
Definition: UI_view2d.h:55
@ V2D_COMMONVIEW_HEADER
Definition: UI_view2d.h:57
@ V2D_COMMONVIEW_STANDARD
Definition: UI_view2d.h:51
@ V2D_COMMONVIEW_PANELS_UI
Definition: UI_view2d.h:59
#define V2D_IS_CLIPPED
Definition: UI_view2d.h:40
#define IN_2D_HORIZ_SCROLL_RECT(v2d, rct)
Definition: UI_view2d.h:94
unsigned int U
Definition: btGjkEpa3.h:78
#define str(s)
uint pos
uint col
#define floorf(x)
#define fabsf(x)
format
Definition: logImageCore.h:47
static ulong state[N]
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt=1)
static void area(int d1, int d2, int e1, int e2, float weights[2])
const btScalar eps
Definition: poly34.cpp:11
#define min(a, b)
Definition: sort.c:51
void(* on_view2d_changed)(const struct bContext *C, struct ARegion *region)
Definition: BKE_screen.h:210
short regiontype
struct ARegionType * type
uiWidgetColors wcol_scroll
unsigned char widget_emboss[4]
union View2DString::@423 col
char str[0]
Definition: view2d.c:2080
struct View2DString * next
Definition: view2d.c:2071
int mval[2]
Definition: view2d.c:2077
rcti rect
Definition: view2d.c:2076
uchar ub[4]
Definition: view2d.c:2073
short flag
char alpha_vert
short winx
float minzoom
short align
short keeptot
short scroll_ui
short oldwiny
float max[2]
short keepzoom
short keepofs
short winy
char alpha_hor
float min[2]
short oldwinx
short scroll
float maxzoom
ListBase areabase
ThemeUI tui
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
unsigned char inner[4]
unsigned char outline[4]
unsigned char item[4]
float max
__forceinline const avxi abs(const avxi &a)
Definition: util_avxi.h:186
ccl_device_inline float2 fabs(const float2 &a)
ccl_device_inline float3 ceil(const float3 &a)
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
#define G(x, y, z)
char UI_view2d_rect_in_scrollers(const ARegion *region, const View2D *v2d, const rcti *rect)
Definition: view2d.c:2058
struct View2DString View2DString
void UI_view2d_curRect_validate(View2D *v2d)
Definition: view2d.c:851
void UI_view2d_center_set(struct View2D *v2d, float x, float y)
Definition: view2d.c:1950
void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
Definition: view2d.c:876
void UI_view2d_scale_get_inverse(const View2D *v2d, float *r_x, float *r_y)
Definition: view2d.c:1926
void UI_view2d_curRect_reset(View2D *v2d)
Definition: view2d.c:944
static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize)
Definition: view2d.c:406
void UI_view2d_scroller_size_get(const View2D *v2d, float *r_x, float *r_y)
Definition: view2d.c:1875
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y)
Definition: view2d.c:1676
void UI_view2d_view_orthoSpecial(ARegion *region, View2D *v2d, const bool xaxis)
Definition: view2d.c:1159
void UI_view2d_multi_grid_draw(const View2D *v2d, int colorid, float step, int level_size, int totlevels)
Definition: view2d.c:1277
static View2DString * g_v2d_strings
Definition: view2d.c:2085
void UI_view2d_view_to_region_rcti(const View2D *v2d, const rctf *rect_src, rcti *rect_dst)
Definition: view2d.c:1773
bool UI_view2d_view_to_region_clip(const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
Definition: view2d.c:1716
bool UI_view2d_view_to_region_rcti_clip(const View2D *v2d, const rctf *rect_src, rcti *rect_dst)
Definition: view2d.c:1802
void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
Definition: view2d.c:1516
BLI_INLINE void clamp_rctf_to_rcti(rcti *dst, const rctf *src)
Definition: view2d.c:87
View2D * UI_view2d_fromcontext(const bContext *C)
Definition: view2d.c:1840
void UI_view2d_view_restore(const bContext *C)
Definition: view2d.c:1186
void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
Definition: view2d.c:240
void UI_view2d_curRect_changed(const bContext *C, View2D *v2d)
Definition: view2d.c:856
void UI_view2d_text_cache_draw(ARegion *region)
Definition: view2d.c:2148
void UI_view2d_totRect_set(View2D *v2d, int width, int height)
Definition: view2d.c:1052
void UI_view2d_region_to_view_rctf(const View2D *v2d, const rctf *rect_src, rctf *rect_dst)
Definition: view2d.c:1683
static int view2d_scroll_mapped(int scroll)
Definition: view2d.c:111
float UI_view2d_view_to_region_y(const View2D *v2d, float y)
Definition: view2d.c:1703
char UI_view2d_mouse_in_scrollers(const ARegion *region, const View2D *v2d, int x, int y)
Definition: view2d.c:2052
void UI_view2d_listview_view_to_cell(float columnwidth, float rowheight, float startx, float starty, float viewx, float viewy, int *r_column, int *r_row)
Definition: view2d.c:1623
void UI_view2d_view_ortho(const View2D *v2d)
Definition: view2d.c:1112
static MemArena * g_v2d_strings_arena
Definition: view2d.c:2084
void UI_view2d_view_to_region(const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
Definition: view2d.c:1745
void UI_view2d_zoom_cache_reset(void)
Definition: view2d.c:1057
View2D * UI_view2d_fromcontext_rwin(const bContext *C)
Definition: view2d.c:1855
float UI_view2d_scale_get_y(const View2D *v2d)
Definition: view2d.c:1919
void UI_view2d_scale_get(const View2D *v2d, float *r_x, float *r_y)
Definition: view2d.c:1906
bool UI_view2d_area_supports_sync(ScrArea *area)
Definition: view2d.c:869
void UI_view2d_mask_from_win(const View2D *v2d, rcti *r_mask)
Definition: view2d.c:122
char UI_view2d_rect_in_scrollers_ex(const ARegion *region, const View2D *v2d, const rcti *rect, int *r_scroll)
Definition: view2d.c:2025
void UI_view2d_view_to_region_m4(const View2D *v2d, float matrix[4][4])
Definition: view2d.c:1794
void UI_view2d_view_to_region_fl(const View2D *v2d, float x, float y, float *r_region_x, float *r_region_y)
Definition: view2d.c:1761
float UI_view2d_region_to_view_x(const struct View2D *v2d, float x)
Definition: view2d.c:1659
void UI_view2d_text_cache_add(View2D *v2d, float x, float y, const char *str, size_t str_len, const uchar col[4])
Definition: view2d.c:2087
float UI_view2d_view_to_region_x(const View2D *v2d, float x)
Definition: view2d.c:1698
void UI_view2d_scrollers_calc(View2D *v2d, const rcti *mask_custom, struct View2DScrollers *r_scrollers)
Definition: view2d.c:1389
void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y)
Definition: view2d.c:1940
char UI_view2d_mouse_in_scrollers_ex(const ARegion *region, const View2D *v2d, int x, int y, int *r_scroll)
Definition: view2d.c:1998
void UI_view2d_constant_grid_draw(const View2D *v2d, float step)
Definition: view2d.c:1205
float UI_view2d_region_to_view_y(const struct View2D *v2d, float y)
Definition: view2d.c:1664
static void view2d_map_cur_using_mask(const View2D *v2d, rctf *r_curmasked)
Definition: view2d.c:1080
void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resize)
Definition: view2d.c:994
BLI_INLINE int clamp_float_to_int(const float f)
Definition: view2d.c:69
static void view2d_masks(View2D *v2d, const rcti *mask_scroll)
Definition: view2d.c:135
void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac)
Definition: view2d.c:1964
void UI_view2d_text_cache_add_rectf(View2D *v2d, const rctf *rect_view, const char *str, size_t str_len, const uchar col[4])
Definition: view2d.c:2118
float UI_view2d_scale_get_x(const View2D *v2d)
Definition: view2d.c:1915
void wmOrtho2(float x1, float x2, float y1, float y2)
Definition: wm_subwindow.c:100
void wmOrtho2_region_pixelspace(const ARegion *region)
Definition: wm_subwindow.c:120