Blender  V3.3
view2d.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2008 Blender Foundation. All rights reserved. */
3 
8 #include <cfloat>
9 #include <climits>
10 #include <cmath>
11 #include <cstring>
12 
13 #include "MEM_guardedalloc.h"
14 
15 #include "DNA_scene_types.h"
16 #include "DNA_userdef_types.h"
17 
18 #include "BLI_array.h"
19 #include "BLI_easing.h"
20 #include "BLI_link_utils.h"
21 #include "BLI_listbase.h"
22 #include "BLI_math.h"
23 #include "BLI_memarena.h"
24 #include "BLI_rect.h"
25 #include "BLI_string.h"
26 #include "BLI_timecode.h"
27 #include "BLI_utildefines.h"
28 
29 #include "BKE_context.h"
30 #include "BKE_global.h"
31 #include "BKE_screen.h"
32 
33 #include "GPU_immediate.h"
34 #include "GPU_matrix.h"
35 #include "GPU_state.h"
36 
37 #include "WM_api.h"
38 
39 #include "BLF_api.h"
40 
41 #include "ED_screen.h"
42 
43 #include "UI_interface.h"
44 #include "UI_view2d.h"
45 
46 #include "interface_intern.h"
47 
48 static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize);
49 
50 /* -------------------------------------------------------------------- */
54 BLI_INLINE int clamp_float_to_int(const float f)
55 {
56  const float min = (float)INT_MIN;
57  const float max = (float)INT_MAX;
58 
59  if (UNLIKELY(f < min)) {
60  return min;
61  }
62  if (UNLIKELY(f > max)) {
63  return (int)max;
64  }
65  return (int)f;
66 }
67 
73 {
74  dst->xmin = clamp_float_to_int(src->xmin);
75  dst->xmax = clamp_float_to_int(src->xmax);
76  dst->ymin = clamp_float_to_int(src->ymin);
77  dst->ymax = clamp_float_to_int(src->ymax);
78 }
79 
80 /* XXX still unresolved: scrolls hide/unhide vs region mask handling */
81 /* XXX there's V2D_SCROLL_HORIZONTAL_HIDE and V2D_SCROLL_HORIZONTAL_FULLR ... */
82 
85 /* -------------------------------------------------------------------- */
96 static int view2d_scroll_mapped(int scroll)
97 {
98  if (scroll & V2D_SCROLL_HORIZONTAL_FULLR) {
99  scroll &= ~V2D_SCROLL_HORIZONTAL;
100  }
101  if (scroll & V2D_SCROLL_VERTICAL_FULLR) {
102  scroll &= ~V2D_SCROLL_VERTICAL;
103  }
104  return scroll;
105 }
106 
107 void UI_view2d_mask_from_win(const View2D *v2d, rcti *r_mask)
108 {
109  r_mask->xmin = 0;
110  r_mask->ymin = 0;
111  r_mask->xmax = v2d->winx - 1; /* -1 yes! masks are pixels */
112  r_mask->ymax = v2d->winy - 1;
113 }
114 
120 static void view2d_masks(View2D *v2d, const rcti *mask_scroll)
121 {
122  int scroll;
123 
124  /* mask - view frame */
125  UI_view2d_mask_from_win(v2d, &v2d->mask);
126  if (mask_scroll == nullptr) {
127  mask_scroll = &v2d->mask;
128  }
129 
130  /* check size if hiding flag is set: */
131  if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) {
132  if (!(v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES)) {
133  if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur)) {
135  }
136  else {
138  }
139  }
140  }
141  if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) {
142  if (!(v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES)) {
143  if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur)) {
145  }
146  else {
148  }
149  }
150  }
151 
152  /* Do not use mapped scroll here because we want to update scroller rects
153  * even if they are not displayed. For init purposes. See T75003.*/
154  scroll = v2d->scroll;
155 
156  /* Scrollers are based off region-size:
157  * - they can only be on one to two edges of the region they define
158  * - if they overlap, they must not occupy the corners (which are reserved for other widgets)
159  */
160  if (scroll) {
161  float scroll_width, scroll_height;
162 
163  UI_view2d_scroller_size_get(v2d, false, &scroll_width, &scroll_height);
164 
165  /* vertical scroller */
166  if (scroll & V2D_SCROLL_LEFT) {
167  /* on left-hand edge of region */
168  v2d->vert = *mask_scroll;
169  v2d->vert.xmax = scroll_width;
170  }
171  else if (scroll & V2D_SCROLL_RIGHT) {
172  /* on right-hand edge of region */
173  v2d->vert = *mask_scroll;
174  v2d->vert.xmax++; /* one pixel extra... was leaving a minor gap... */
175  v2d->vert.xmin = v2d->vert.xmax - scroll_width;
176  }
177 
178  /* Currently, all regions that have vertical scale handles,
179  * also have the scrubbing area at the top.
180  * So the scrollbar has to move down a bit. */
181  if (scroll & V2D_SCROLL_VERTICAL_HANDLES) {
183  }
184 
185  /* horizontal scroller */
186  if (scroll & V2D_SCROLL_BOTTOM) {
187  /* on bottom edge of region */
188  v2d->hor = *mask_scroll;
189  v2d->hor.ymax = scroll_height;
190  }
191  else if (scroll & V2D_SCROLL_TOP) {
192  /* on upper edge of region */
193  v2d->hor = *mask_scroll;
194  v2d->hor.ymin = v2d->hor.ymax - scroll_height;
195  }
196 
197  /* adjust vertical scroller if there's a horizontal scroller, to leave corner free */
198  if (scroll & V2D_SCROLL_VERTICAL) {
199  if (scroll & V2D_SCROLL_BOTTOM) {
200  /* on bottom edge of region */
201  v2d->vert.ymin = v2d->hor.ymax;
202  }
203  else if (scroll & V2D_SCROLL_TOP) {
204  /* on upper edge of region */
205  v2d->vert.ymax = v2d->hor.ymin;
206  }
207  }
208  }
209 }
210 
213 /* -------------------------------------------------------------------- */
217 void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
218 {
219  bool tot_changed = false, do_init;
220  const uiStyle *style = UI_style_get();
221 
222  do_init = (v2d->flag & V2D_IS_INIT) == 0;
223 
224  /* see eView2D_CommonViewTypes in UI_view2d.h for available view presets */
225  switch (type) {
226  /* 'standard view' - optimum setup for 'standard' view behavior,
227  * that should be used new views as basis for their
228  * own unique View2D settings, which should be used instead of this in most cases...
229  */
231  /* for now, aspect ratio should be maintained,
232  * and zoom is clamped within sane default limits */
234  v2d->minzoom = 0.01f;
235  v2d->maxzoom = 1000.0f;
236 
237  /* View2D tot rect and cur should be same size,
238  * and aligned using 'standard' OpenGL coordinates for now:
239  * - region can resize 'tot' later to fit other data
240  * - keeptot is only within bounds, as strict locking is not that critical
241  * - view is aligned for (0,0) -> (winx-1, winy-1) setup
242  */
245  if (do_init) {
246  v2d->tot.xmin = v2d->tot.ymin = 0.0f;
247  v2d->tot.xmax = (float)(winx - 1);
248  v2d->tot.ymax = (float)(winy - 1);
249 
250  v2d->cur = v2d->tot;
251  }
252  /* scrollers - should we have these by default? */
253  /* XXX for now, we don't override this, or set it either! */
254  break;
255  }
256  /* 'list/channel view' - zoom, aspect ratio, and alignment restrictions are set here */
257  case V2D_COMMONVIEW_LIST: {
258  /* zoom + aspect ratio are locked */
260  v2d->minzoom = v2d->maxzoom = 1.0f;
261 
262  /* tot rect has strictly regulated placement, and must only occur in +/- quadrant */
265  tot_changed = do_init;
266 
267  /* scroller settings are currently not set here... that is left for regions... */
268  break;
269  }
270  /* 'stack view' - practically the same as list/channel view,
271  * except is located in the pos y half instead.
272  * Zoom, aspect ratio, and alignment restrictions are set here. */
273  case V2D_COMMONVIEW_STACK: {
274  /* zoom + aspect ratio are locked */
276  v2d->minzoom = v2d->maxzoom = 1.0f;
277 
278  /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
281  tot_changed = do_init;
282 
283  /* scroller settings are currently not set here... that is left for regions... */
284  break;
285  }
286  /* 'header' regions - zoom, aspect ratio,
287  * alignment, and panning restrictions are set here */
288  case V2D_COMMONVIEW_HEADER: {
289  /* zoom + aspect ratio are locked */
291  v2d->minzoom = v2d->maxzoom = 1.0f;
292 
293  if (do_init) {
294  v2d->tot.xmin = 0.0f;
295  v2d->tot.xmax = winx;
296  v2d->tot.ymin = 0.0f;
297  v2d->tot.ymax = winy;
298  v2d->cur = v2d->tot;
299 
300  v2d->min[0] = v2d->max[0] = (float)(winx - 1);
301  v2d->min[1] = v2d->max[1] = (float)(winy - 1);
302  }
303  /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
306  tot_changed = do_init;
307 
308  /* panning in y-axis is prohibited */
309  v2d->keepofs = V2D_LOCKOFS_Y;
310 
311  /* absolutely no scrollers allowed */
312  v2d->scroll = 0;
313  break;
314  }
315  /* panels view, with horizontal/vertical align */
317 
318  /* for now, aspect ratio should be maintained,
319  * and zoom is clamped within sane default limits */
321  v2d->minzoom = 0.5f;
322  v2d->maxzoom = 2.0f;
323 
326 
327  /* NOTE: scroll is being flipped in #ED_region_panels() drawing. */
329 
330  if (do_init) {
331  const float panelzoom = (style) ? style->panelzoom : 1.0f;
332 
333  v2d->tot.xmin = 0.0f;
334  v2d->tot.xmax = winx;
335 
336  v2d->tot.ymax = 0.0f;
337  v2d->tot.ymin = -winy;
338 
339  v2d->cur.xmin = 0.0f;
340  v2d->cur.xmax = (winx)*panelzoom;
341 
342  v2d->cur.ymax = 0.0f;
343  v2d->cur.ymin = (-winy) * panelzoom;
344  }
345  break;
346  }
347  /* other view types are completely defined using their own settings already */
348  default:
349  /* we don't do anything here,
350  * as settings should be fine, but just make sure that rect */
351  break;
352  }
353 
354  /* set initialized flag so that View2D doesn't get reinitialized next time again */
355  v2d->flag |= V2D_IS_INIT;
356 
357  /* store view size */
358  v2d->winx = winx;
359  v2d->winy = winy;
360 
361  view2d_masks(v2d, nullptr);
362 
363  if (do_init) {
364  /* Visible by default. */
365  v2d->alpha_hor = v2d->alpha_vert = 255;
366  }
367 
368  /* set 'tot' rect before setting cur? */
369  /* XXX confusing stuff here still */
370  if (tot_changed) {
371  UI_view2d_totRect_set_resize(v2d, winx, winy, !do_init);
372  }
373  else {
374  ui_view2d_curRect_validate_resize(v2d, !do_init);
375  }
376 }
377 
382 /* XXX pre2.5 -> this used to be called test_view2d() */
383 static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize)
384 {
385  float totwidth, totheight, curwidth, curheight, width, height;
386  float winx, winy;
387  rctf *cur, *tot;
388 
389  /* use mask as size of region that View2D resides in, as it takes into account
390  * scrollbars already - keep in sync with zoomx/zoomy in view_zoomstep_apply_ex! */
391  winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
392  winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
393 
394  /* get pointers to rcts for less typing */
395  cur = &v2d->cur;
396  tot = &v2d->tot;
397 
398  /* we must satisfy the following constraints (in decreasing order of importance):
399  * - alignment restrictions are respected
400  * - cur must not fall outside of tot
401  * - axis locks (zoom and offset) must be maintained
402  * - zoom must not be excessive (check either sizes or zoom values)
403  * - aspect ratio should be respected (NOTE: this is quite closely related to zoom too)
404  */
405 
406  /* Step 1: if keepzoom, adjust the sizes of the rects only
407  * - firstly, we calculate the sizes of the rects
408  * - curwidth and curheight are saved as reference... modify width and height values here
409  */
410  totwidth = BLI_rctf_size_x(tot);
411  totheight = BLI_rctf_size_y(tot);
412  /* keep in sync with zoomx/zoomy in view_zoomstep_apply_ex! */
413  curwidth = width = BLI_rctf_size_x(cur);
414  curheight = height = BLI_rctf_size_y(cur);
415 
416  /* if zoom is locked, size on the appropriate axis is reset to mask size */
417  if (v2d->keepzoom & V2D_LOCKZOOM_X) {
418  width = winx;
419  }
420  if (v2d->keepzoom & V2D_LOCKZOOM_Y) {
421  height = winy;
422  }
423 
424  /* values used to divide, so make it safe
425  * NOTE: width and height must use FLT_MIN instead of 1, otherwise it is impossible to
426  * get enough resolution in Graph Editor for editing some curves
427  */
428  if (width < FLT_MIN) {
429  width = 1;
430  }
431  if (height < FLT_MIN) {
432  height = 1;
433  }
434  if (winx < 1) {
435  winx = 1;
436  }
437  if (winy < 1) {
438  winy = 1;
439  }
440 
441  /* V2D_LIMITZOOM indicates that zoom level should be preserved when the window size changes */
442  if (resize && (v2d->keepzoom & V2D_KEEPZOOM)) {
443  float zoom, oldzoom;
444 
445  if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
446  zoom = winx / width;
447  oldzoom = v2d->oldwinx / curwidth;
448 
449  if (oldzoom != zoom) {
450  width *= zoom / oldzoom;
451  }
452  }
453 
454  if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
455  zoom = winy / height;
456  oldzoom = v2d->oldwiny / curheight;
457 
458  if (oldzoom != zoom) {
459  height *= zoom / oldzoom;
460  }
461  }
462  }
463  /* keepzoom (V2D_LIMITZOOM set), indicates that zoom level on each axis must not exceed limits
464  * NOTE: in general, it is not expected that the lock-zoom will be used in conjunction with this
465  */
466  else if (v2d->keepzoom & V2D_LIMITZOOM) {
467 
468  /* check if excessive zoom on x-axis */
469  if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
470  const float zoom = winx / width;
471  if (zoom < v2d->minzoom) {
472  width = winx / v2d->minzoom;
473  }
474  else if (zoom > v2d->maxzoom) {
475  width = winx / v2d->maxzoom;
476  }
477  }
478 
479  /* check if excessive zoom on y-axis */
480  if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
481  const float zoom = winy / height;
482  if (zoom < v2d->minzoom) {
483  height = winy / v2d->minzoom;
484  }
485  else if (zoom > v2d->maxzoom) {
486  height = winy / v2d->maxzoom;
487  }
488  }
489  }
490  else {
491  /* make sure sizes don't exceed that of the min/max sizes
492  * (even though we're not doing zoom clamping) */
493  CLAMP(width, v2d->min[0], v2d->max[0]);
494  CLAMP(height, v2d->min[1], v2d->max[1]);
495  }
496 
497  /* check if we should restore aspect ratio (if view size changed) */
498  if (v2d->keepzoom & V2D_KEEPASPECT) {
499  bool do_x = false, do_y = false, do_cur;
500  float curRatio, winRatio;
501 
502  /* when a window edge changes, the aspect ratio can't be used to
503  * find which is the best new 'cur' rect. that's why it stores 'old'
504  */
505  if (winx != v2d->oldwinx) {
506  do_x = true;
507  }
508  if (winy != v2d->oldwiny) {
509  do_y = true;
510  }
511 
512  curRatio = height / width;
513  winRatio = winy / winx;
514 
515  /* Both sizes change (area/region maximized). */
516  if (do_x == do_y) {
517  if (do_x && do_y) {
518  /* here is 1,1 case, so all others must be 0,0 */
519  if (fabsf(winx - v2d->oldwinx) > fabsf(winy - v2d->oldwiny)) {
520  do_y = false;
521  }
522  else {
523  do_x = false;
524  }
525  }
526  else if (winRatio > curRatio) {
527  do_x = false;
528  }
529  else {
530  do_x = true;
531  }
532  }
533  do_cur = do_x;
534  /* do_win = do_y; */ /* UNUSED */
535 
536  if (do_cur) {
537  if ((v2d->keeptot == V2D_KEEPTOT_STRICT) && (winx != v2d->oldwinx)) {
538  /* Special exception for Outliner (and later channel-lists):
539  * - The view may be moved left to avoid contents
540  * being pushed out of view when view shrinks.
541  * - The keeptot code will make sure cur->xmin will not be less than tot->xmin
542  * (which cannot be allowed).
543  * - width is not adjusted for changed ratios here.
544  */
545  if (winx < v2d->oldwinx) {
546  const float temp = v2d->oldwinx - winx;
547 
548  cur->xmin -= temp;
549  cur->xmax -= temp;
550 
551  /* width does not get modified, as keepaspect here is just set to make
552  * sure visible area adjusts to changing view shape!
553  */
554  }
555  }
556  else {
557  /* portrait window: correct for x */
558  width = height / winRatio;
559  }
560  }
561  else {
562  if ((v2d->keeptot == V2D_KEEPTOT_STRICT) && (winy != v2d->oldwiny)) {
563  /* special exception for Outliner (and later channel-lists):
564  * - Currently, no actions need to be taken here...
565  */
566 
567  if (winy < v2d->oldwiny) {
568  const float temp = v2d->oldwiny - winy;
569 
570  if (v2d->align & V2D_ALIGN_NO_NEG_Y) {
571  cur->ymin -= temp;
572  cur->ymax -= temp;
573  }
574  else { /* Assume V2D_ALIGN_NO_POS_Y or combination */
575  cur->ymin += temp;
576  cur->ymax += temp;
577  }
578  }
579  }
580  else {
581  /* landscape window: correct for y */
582  height = width * winRatio;
583  }
584  }
585 
586  /* store region size for next time */
587  v2d->oldwinx = (short)winx;
588  v2d->oldwiny = (short)winy;
589  }
590 
591  /* Step 2: apply new sizes to cur rect,
592  * but need to take into account alignment settings here... */
593  if ((width != curwidth) || (height != curheight)) {
594  float temp, dh;
595 
596  /* Resize from center-point, unless otherwise specified. */
597  if (width != curwidth) {
598  if (v2d->keepofs & V2D_LOCKOFS_X) {
599  cur->xmax += width - BLI_rctf_size_x(cur);
600  }
601  else if (v2d->keepofs & V2D_KEEPOFS_X) {
602  if (v2d->align & V2D_ALIGN_NO_POS_X) {
603  cur->xmin -= width - BLI_rctf_size_x(cur);
604  }
605  else {
606  cur->xmax += width - BLI_rctf_size_x(cur);
607  }
608  }
609  else {
610  temp = BLI_rctf_cent_x(cur);
611  dh = width * 0.5f;
612 
613  cur->xmin = temp - dh;
614  cur->xmax = temp + dh;
615  }
616  }
617  if (height != curheight) {
618  if (v2d->keepofs & V2D_LOCKOFS_Y) {
619  cur->ymax += height - BLI_rctf_size_y(cur);
620  }
621  else if (v2d->keepofs & V2D_KEEPOFS_Y) {
622  if (v2d->align & V2D_ALIGN_NO_POS_Y) {
623  cur->ymin -= height - BLI_rctf_size_y(cur);
624  }
625  else {
626  cur->ymax += height - BLI_rctf_size_y(cur);
627  }
628  }
629  else {
630  temp = BLI_rctf_cent_y(cur);
631  dh = height * 0.5f;
632 
633  cur->ymin = temp - dh;
634  cur->ymax = temp + dh;
635  }
636  }
637  }
638 
639  /* Step 3: adjust so that it doesn't fall outside of bounds of 'tot' */
640  if (v2d->keeptot) {
641  float temp, diff;
642 
643  /* recalculate extents of cur */
644  curwidth = BLI_rctf_size_x(cur);
645  curheight = BLI_rctf_size_y(cur);
646 
647  /* width */
648  if ((curwidth > totwidth) &&
650  /* if zoom doesn't have to be maintained, just clamp edges */
651  if (cur->xmin < tot->xmin) {
652  cur->xmin = tot->xmin;
653  }
654  if (cur->xmax > tot->xmax) {
655  cur->xmax = tot->xmax;
656  }
657  }
658  else if (v2d->keeptot == V2D_KEEPTOT_STRICT) {
659  /* This is an exception for the outliner (and later channel-lists, headers)
660  * - must clamp within tot rect (absolutely no excuses)
661  * --> therefore, cur->xmin must not be less than tot->xmin
662  */
663  if (cur->xmin < tot->xmin) {
664  /* move cur across so that it sits at minimum of tot */
665  temp = tot->xmin - cur->xmin;
666 
667  cur->xmin += temp;
668  cur->xmax += temp;
669  }
670  else if (cur->xmax > tot->xmax) {
671  /* - only offset by difference of cur-xmax and tot-xmax if that would not move
672  * cur-xmin to lie past tot-xmin
673  * - otherwise, simply shift to tot-xmin???
674  */
675  temp = cur->xmax - tot->xmax;
676 
677  if ((cur->xmin - temp) < tot->xmin) {
678  /* only offset by difference from cur-min and tot-min */
679  temp = cur->xmin - tot->xmin;
680 
681  cur->xmin -= temp;
682  cur->xmax -= temp;
683  }
684  else {
685  cur->xmin -= temp;
686  cur->xmax -= temp;
687  }
688  }
689  }
690  else {
691  /* This here occurs when:
692  * - width too big, but maintaining zoom (i.e. widths cannot be changed)
693  * - width is OK, but need to check if outside of boundaries
694  *
695  * So, resolution is to just shift view by the gap between the extremities.
696  * We favor moving the 'minimum' across, as that's origin for most things.
697  * (XXX: in the past, max was favored... if there are bugs, swap!)
698  */
699  if ((cur->xmin < tot->xmin) && (cur->xmax > tot->xmax)) {
700  /* outside boundaries on both sides,
701  * so take middle-point of tot, and place in balanced way */
702  temp = BLI_rctf_cent_x(tot);
703  diff = curwidth * 0.5f;
704 
705  cur->xmin = temp - diff;
706  cur->xmax = temp + diff;
707  }
708  else if (cur->xmin < tot->xmin) {
709  /* move cur across so that it sits at minimum of tot */
710  temp = tot->xmin - cur->xmin;
711 
712  cur->xmin += temp;
713  cur->xmax += temp;
714  }
715  else if (cur->xmax > tot->xmax) {
716  /* - only offset by difference of cur-xmax and tot-xmax if that would not move
717  * cur-xmin to lie past tot-xmin
718  * - otherwise, simply shift to tot-xmin???
719  */
720  temp = cur->xmax - tot->xmax;
721 
722  if ((cur->xmin - temp) < tot->xmin) {
723  /* only offset by difference from cur-min and tot-min */
724  temp = cur->xmin - tot->xmin;
725 
726  cur->xmin -= temp;
727  cur->xmax -= temp;
728  }
729  else {
730  cur->xmin -= temp;
731  cur->xmax -= temp;
732  }
733  }
734  }
735 
736  /* height */
737  if ((curheight > totheight) &&
739  /* if zoom doesn't have to be maintained, just clamp edges */
740  if (cur->ymin < tot->ymin) {
741  cur->ymin = tot->ymin;
742  }
743  if (cur->ymax > tot->ymax) {
744  cur->ymax = tot->ymax;
745  }
746  }
747  else {
748  /* This here occurs when:
749  * - height too big, but maintaining zoom (i.e. heights cannot be changed)
750  * - height is OK, but need to check if outside of boundaries
751  *
752  * So, resolution is to just shift view by the gap between the extremities.
753  * We favor moving the 'minimum' across, as that's origin for most things.
754  */
755  if ((cur->ymin < tot->ymin) && (cur->ymax > tot->ymax)) {
756  /* outside boundaries on both sides,
757  * so take middle-point of tot, and place in balanced way */
758  temp = BLI_rctf_cent_y(tot);
759  diff = curheight * 0.5f;
760 
761  cur->ymin = temp - diff;
762  cur->ymax = temp + diff;
763  }
764  else if (cur->ymin < tot->ymin) {
765  /* there's still space remaining, so shift up */
766  temp = tot->ymin - cur->ymin;
767 
768  cur->ymin += temp;
769  cur->ymax += temp;
770  }
771  else if (cur->ymax > tot->ymax) {
772  /* there's still space remaining, so shift down */
773  temp = cur->ymax - tot->ymax;
774 
775  cur->ymin -= temp;
776  cur->ymax -= temp;
777  }
778  }
779  }
780 
781  /* Step 4: Make sure alignment restrictions are respected */
782  if (v2d->align) {
783  /* If alignment flags are set (but keeptot is not), they must still be respected, as although
784  * they don't specify any particular bounds to stay within, they do define ranges which are
785  * invalid.
786  *
787  * Here, we only check to make sure that on each axis, the 'cur' rect doesn't stray into these
788  * invalid zones, otherwise we offset.
789  */
790 
791  /* handle width - posx and negx flags are mutually exclusive, so watch out */
792  if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
793  /* width is in negative-x half */
794  if (v2d->cur.xmax > 0) {
795  v2d->cur.xmin -= v2d->cur.xmax;
796  v2d->cur.xmax = 0.0f;
797  }
798  }
799  else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
800  /* width is in positive-x half */
801  if (v2d->cur.xmin < 0) {
802  v2d->cur.xmax -= v2d->cur.xmin;
803  v2d->cur.xmin = 0.0f;
804  }
805  }
806 
807  /* handle height - posx and negx flags are mutually exclusive, so watch out */
808  if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
809  /* height is in negative-y half */
810  if (v2d->cur.ymax > 0) {
811  v2d->cur.ymin -= v2d->cur.ymax;
812  v2d->cur.ymax = 0.0f;
813  }
814  }
815  else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
816  /* height is in positive-y half */
817  if (v2d->cur.ymin < 0) {
818  v2d->cur.ymax -= v2d->cur.ymin;
819  v2d->cur.ymin = 0.0f;
820  }
821  }
822  }
823 
824  /* set masks */
825  view2d_masks(v2d, nullptr);
826 }
827 
829 {
831 }
832 
834 {
836 
837  ARegion *region = CTX_wm_region(C);
838 
839  if (region->type->on_view2d_changed != nullptr) {
840  region->type->on_view2d_changed(C, region);
841  }
842 }
843 
844 /* ------------------ */
845 
847 {
849 }
850 
851 void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
852 {
853  /* don't continue if no view syncing to be done */
854  if ((v2dcur->flag & (V2D_VIEWSYNC_SCREEN_TIME | V2D_VIEWSYNC_AREA_VERTICAL)) == 0) {
855  return;
856  }
857 
858  /* check if doing within area syncing (i.e. channels/vertical) */
859  if ((v2dcur->flag & V2D_VIEWSYNC_AREA_VERTICAL) && (area)) {
860  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
861  /* don't operate on self */
862  if (v2dcur != &region->v2d) {
863  /* only if view has vertical locks enabled */
864  if (region->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL) {
865  if (flag == V2D_LOCK_COPY) {
866  /* other views with locks on must copy active */
867  region->v2d.cur.ymin = v2dcur->cur.ymin;
868  region->v2d.cur.ymax = v2dcur->cur.ymax;
869  }
870  else { /* V2D_LOCK_SET */
871  /* active must copy others */
872  v2dcur->cur.ymin = region->v2d.cur.ymin;
873  v2dcur->cur.ymax = region->v2d.cur.ymax;
874  }
875 
876  /* region possibly changed, so refresh */
878  }
879  }
880  }
881  }
882 
883  /* check if doing whole screen syncing (i.e. time/horizontal) */
884  if ((v2dcur->flag & V2D_VIEWSYNC_SCREEN_TIME) && (screen)) {
885  LISTBASE_FOREACH (ScrArea *, area_iter, &screen->areabase) {
886  if (!UI_view2d_area_supports_sync(area_iter)) {
887  continue;
888  }
889  LISTBASE_FOREACH (ARegion *, region, &area_iter->regionbase) {
890  /* don't operate on self */
891  if (v2dcur != &region->v2d) {
892  /* only if view has horizontal locks enabled */
893  if (region->v2d.flag & V2D_VIEWSYNC_SCREEN_TIME) {
894  if (flag == V2D_LOCK_COPY) {
895  /* other views with locks on must copy active */
896  region->v2d.cur.xmin = v2dcur->cur.xmin;
897  region->v2d.cur.xmax = v2dcur->cur.xmax;
898  }
899  else { /* V2D_LOCK_SET */
900  /* active must copy others */
901  v2dcur->cur.xmin = region->v2d.cur.xmin;
902  v2dcur->cur.xmax = region->v2d.cur.xmax;
903  }
904 
905  /* region possibly changed, so refresh */
907  }
908  }
909  }
910  }
911  }
912 }
913 
915 {
916  float width, height;
917 
918  /* assume width and height of 'cur' rect by default, should be same size as mask */
919  width = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
920  height = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
921 
922  /* handle width - posx and negx flags are mutually exclusive, so watch out */
923  if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
924  /* width is in negative-x half */
925  v2d->cur.xmin = -width;
926  v2d->cur.xmax = 0.0f;
927  }
928  else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
929  /* width is in positive-x half */
930  v2d->cur.xmin = 0.0f;
931  v2d->cur.xmax = width;
932  }
933  else {
934  /* width is centered around (x == 0) */
935  const float dx = width / 2.0f;
936 
937  v2d->cur.xmin = -dx;
938  v2d->cur.xmax = dx;
939  }
940 
941  /* handle height - posx and negx flags are mutually exclusive, so watch out */
942  if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
943  /* height is in negative-y half */
944  v2d->cur.ymin = -height;
945  v2d->cur.ymax = 0.0f;
946  }
947  else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
948  /* height is in positive-y half */
949  v2d->cur.ymin = 0.0f;
950  v2d->cur.ymax = height;
951  }
952  else {
953  /* height is centered around (y == 0) */
954  const float dy = height / 2.0f;
955 
956  v2d->cur.ymin = -dy;
957  v2d->cur.ymax = dy;
958  }
959 }
960 
961 /* ------------------ */
962 
963 void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resize)
964 {
965  /* don't do anything if either value is 0 */
966  width = abs(width);
967  height = abs(height);
968 
969  if (ELEM(0, width, height)) {
970  if (G.debug & G_DEBUG) {
971  /* XXX: temp debug info. */
972  printf("Error: View2D totRect set exiting: v2d=%p width=%d height=%d\n",
973  (void *)v2d,
974  width,
975  height);
976  }
977  return;
978  }
979 
980  /* handle width - posx and negx flags are mutually exclusive, so watch out */
981  if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
982  /* width is in negative-x half */
983  v2d->tot.xmin = (float)-width;
984  v2d->tot.xmax = 0.0f;
985  }
986  else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
987  /* width is in positive-x half */
988  v2d->tot.xmin = 0.0f;
989  v2d->tot.xmax = (float)width;
990  }
991  else {
992  /* width is centered around (x == 0) */
993  const float dx = (float)width / 2.0f;
994 
995  v2d->tot.xmin = -dx;
996  v2d->tot.xmax = dx;
997  }
998 
999  /* handle height - posx and negx flags are mutually exclusive, so watch out */
1000  if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
1001  /* height is in negative-y half */
1002  v2d->tot.ymin = (float)-height;
1003  v2d->tot.ymax = 0.0f;
1004  }
1005  else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
1006  /* height is in positive-y half */
1007  v2d->tot.ymin = 0.0f;
1008  v2d->tot.ymax = (float)height;
1009  }
1010  else {
1011  /* height is centered around (y == 0) */
1012  const float dy = (float)height / 2.0f;
1013 
1014  v2d->tot.ymin = -dy;
1015  v2d->tot.ymax = dy;
1016  }
1017 
1018  /* make sure that 'cur' rect is in a valid state as a result of these changes */
1019  ui_view2d_curRect_validate_resize(v2d, resize);
1020 }
1021 
1023 {
1025 }
1026 
1028 {
1029  /* TODO(sergey): This way we avoid threading conflict with sequencer rendering
1030  * text strip. But ideally we want to make glyph cache to be fully safe
1031  * for threading.
1032  */
1033  if (G.is_rendering) {
1034  return;
1035  }
1036  /* While scaling we can accumulate fonts at many sizes (~20 or so).
1037  * Not an issue with embedded font, but can use over 500Mb with i18n ones! See T38244. */
1038 
1039  /* NOTE: only some views draw text, we could check for this case to avoid cleaning cache. */
1040  BLF_cache_clear();
1041 }
1042 
1045 /* -------------------------------------------------------------------- */
1049 /* mapping function to ensure 'cur' draws extended over the area where sliders are */
1050 static void view2d_map_cur_using_mask(const View2D *v2d, rctf *r_curmasked)
1051 {
1052  *r_curmasked = v2d->cur;
1053 
1054  if (view2d_scroll_mapped(v2d->scroll)) {
1055  const float sizex = BLI_rcti_size_x(&v2d->mask);
1056  const float sizey = BLI_rcti_size_y(&v2d->mask);
1057 
1058  /* prevent tiny or narrow regions to get
1059  * invalid coordinates - mask can get negative even... */
1060  if (sizex > 0.0f && sizey > 0.0f) {
1061  const float dx = BLI_rctf_size_x(&v2d->cur) / (sizex + 1);
1062  const float dy = BLI_rctf_size_y(&v2d->cur) / (sizey + 1);
1063 
1064  if (v2d->mask.xmin != 0) {
1065  r_curmasked->xmin -= dx * (float)v2d->mask.xmin;
1066  }
1067  if (v2d->mask.xmax + 1 != v2d->winx) {
1068  r_curmasked->xmax += dx * (float)(v2d->winx - v2d->mask.xmax - 1);
1069  }
1070 
1071  if (v2d->mask.ymin != 0) {
1072  r_curmasked->ymin -= dy * (float)v2d->mask.ymin;
1073  }
1074  if (v2d->mask.ymax + 1 != v2d->winy) {
1075  r_curmasked->ymax += dy * (float)(v2d->winy - v2d->mask.ymax - 1);
1076  }
1077  }
1078  }
1079 }
1080 
1082 {
1083  rctf curmasked;
1084  const int sizex = BLI_rcti_size_x(&v2d->mask);
1085  const int sizey = BLI_rcti_size_y(&v2d->mask);
1086  const float eps = 0.001f;
1087  float xofs = 0.0f, yofs = 0.0f;
1088 
1089  /* Pixel offsets (-GLA_PIXEL_OFS) are needed to get 1:1
1090  * correspondence with pixels for smooth UI drawing,
1091  * but only applied where requested.
1092  */
1093  /* XXX brecht: instead of zero at least use a tiny offset, otherwise
1094  * pixel rounding is effectively random due to float inaccuracy */
1095  if (sizex > 0) {
1096  xofs = eps * BLI_rctf_size_x(&v2d->cur) / sizex;
1097  }
1098  if (sizey > 0) {
1099  yofs = eps * BLI_rctf_size_y(&v2d->cur) / sizey;
1100  }
1101 
1102  /* apply mask-based adjustments to cur rect (due to scrollers),
1103  * to eliminate scaling artifacts */
1104  view2d_map_cur_using_mask(v2d, &curmasked);
1105 
1106  BLI_rctf_translate(&curmasked, -xofs, -yofs);
1107 
1108  /* XXX ton: this flag set by outliner, for icons */
1109  if (v2d->flag & V2D_PIXELOFS_X) {
1110  curmasked.xmin = floorf(curmasked.xmin) - (eps + xofs);
1111  curmasked.xmax = floorf(curmasked.xmax) - (eps + xofs);
1112  }
1113  if (v2d->flag & V2D_PIXELOFS_Y) {
1114  curmasked.ymin = floorf(curmasked.ymin) - (eps + yofs);
1115  curmasked.ymax = floorf(curmasked.ymax) - (eps + yofs);
1116  }
1117 
1118  /* set matrix on all appropriate axes */
1119  wmOrtho2(curmasked.xmin, curmasked.xmax, curmasked.ymin, curmasked.ymax);
1120 }
1121 
1122 void UI_view2d_view_orthoSpecial(ARegion *region, View2D *v2d, const bool xaxis)
1123 {
1124  rctf curmasked;
1125  float xofs, yofs;
1126 
1127  /* Pixel offsets (-GLA_PIXEL_OFS) are needed to get 1:1
1128  * correspondence with pixels for smooth UI drawing,
1129  * but only applied where requested.
1130  */
1131  /* XXX(ton): temp. */
1132  xofs = 0.0f; // (v2d->flag & V2D_PIXELOFS_X) ? GLA_PIXEL_OFS : 0.0f;
1133  yofs = 0.0f; // (v2d->flag & V2D_PIXELOFS_Y) ? GLA_PIXEL_OFS : 0.0f;
1134 
1135  /* apply mask-based adjustments to cur rect (due to scrollers),
1136  * to eliminate scaling artifacts */
1137  view2d_map_cur_using_mask(v2d, &curmasked);
1138 
1139  /* only set matrix with 'cur' coordinates on relevant axes */
1140  if (xaxis) {
1141  wmOrtho2(curmasked.xmin - xofs, curmasked.xmax - xofs, -yofs, region->winy - yofs);
1142  }
1143  else {
1144  wmOrtho2(-xofs, region->winx - xofs, curmasked.ymin - yofs, curmasked.ymax - yofs);
1145  }
1146 }
1147 
1149 {
1150  ARegion *region = CTX_wm_region(C);
1151  const int width = BLI_rcti_size_x(&region->winrct) + 1;
1152  const int height = BLI_rcti_size_y(&region->winrct) + 1;
1153 
1154  wmOrtho2(0.0f, (float)width, 0.0f, (float)height);
1156 
1157  // ED_region_pixelspace(CTX_wm_region(C));
1158 }
1159 
1162 /* -------------------------------------------------------------------- */
1167  const View2D *v2d, int colorid, float step, int level_size, int totlevels)
1168 {
1169  /* Exit if there is nothing to draw */
1170  if (totlevels == 0) {
1171  return;
1172  }
1173 
1174  int offset = -10;
1175  float lstep = step;
1176  uchar grid_line_color[3];
1177 
1178  /* Make an estimate of at least how many vertices will be needed */
1179  uint vertex_count = 4;
1180  vertex_count += 2 * ((int)((v2d->cur.xmax - v2d->cur.xmin) / lstep) + 1);
1181  vertex_count += 2 * ((int)((v2d->cur.ymax - v2d->cur.ymin) / lstep) + 1);
1182 
1187 
1188  GPU_line_width(1.0f);
1189 
1191  immBeginAtMost(GPU_PRIM_LINES, vertex_count);
1192 
1193  for (int level = 0; level < totlevels; level++) {
1194  /* Blend the background color (colorid) with the grid color, to avoid either too low contrast
1195  * or high contrast grid lines. This only has an effect if colorid != TH_GRID. */
1196  UI_GetThemeColorBlendShade3ubv(colorid, TH_GRID, 0.25f, offset, grid_line_color);
1197 
1198  int i = (int)(v2d->cur.xmin / lstep);
1199  if (v2d->cur.xmin > 0.0f) {
1200  i++;
1201  }
1202  float start = i * lstep;
1203 
1204  for (; start < v2d->cur.xmax; start += lstep, i++) {
1205  if (i == 0 || (level < totlevels - 1 && i % level_size == 0)) {
1206  continue;
1207  }
1208 
1209  immAttrSkip(color);
1210  immVertex2f(pos, start, v2d->cur.ymin);
1211  immAttr3ubv(color, grid_line_color);
1212  immVertex2f(pos, start, v2d->cur.ymax);
1213  }
1214 
1215  i = (int)(v2d->cur.ymin / lstep);
1216  if (v2d->cur.ymin > 0.0f) {
1217  i++;
1218  }
1219  start = i * lstep;
1220 
1221  for (; start < v2d->cur.ymax; start += lstep, i++) {
1222  if (i == 0 || (level < totlevels - 1 && i % level_size == 0)) {
1223  continue;
1224  }
1225 
1226  immAttrSkip(color);
1227  immVertex2f(pos, v2d->cur.xmin, start);
1228  immAttr3ubv(color, grid_line_color);
1229  immVertex2f(pos, v2d->cur.xmax, start);
1230  }
1231 
1232  lstep *= level_size;
1233  offset -= 6;
1234  }
1235 
1236  /* X and Y axis */
1238  colorid, TH_GRID, 0.5f, -18 + ((totlevels - 1) * -6), grid_line_color);
1239 
1240  immAttrSkip(color);
1241  immVertex2f(pos, 0.0f, v2d->cur.ymin);
1242  immAttr3ubv(color, grid_line_color);
1243  immVertex2f(pos, 0.0f, v2d->cur.ymax);
1244 
1245  immAttrSkip(color);
1246  immVertex2f(pos, v2d->cur.xmin, 0.0f);
1247  immAttr3ubv(color, grid_line_color);
1248  immVertex2f(pos, v2d->cur.xmax, 0.0f);
1249 
1250  immEnd();
1251  immUnbindProgram();
1252 }
1253 
1255  const float step, const float min, const float max, float *r_start, int *r_count)
1256 {
1257  *r_start = min;
1258  if (*r_start < 0.0f) {
1259  *r_start += -(float)fmod(min, step);
1260  }
1261  else {
1262  *r_start += step - (float)fabs(fmod(min, step));
1263  }
1264 
1265  if (*r_start > max) {
1266  *r_count = 0;
1267  }
1268  else {
1269  *r_count = (max - *r_start) / step + 1;
1270  }
1271 }
1272 
1274  const int grid_color_id,
1275  const float min_step,
1276  const int grid_subdivisions)
1277 {
1278  BLI_assert(grid_subdivisions >= 0 && grid_subdivisions < 4);
1279  if (grid_subdivisions == 0) {
1280  return;
1281  }
1282 
1283  const float zoom_x = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur);
1284 
1287  const uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
1289 
1290  /* Scaling the dots fully with the zoom looks too busy, but a bit of size variation is nice. */
1291  const float min_point_size = 2.0f * UI_DPI_FAC;
1292  const float point_size_factor = 1.5f;
1293  const float max_point_size = point_size_factor * min_point_size;
1294 
1295  /* Each consecutive grid level is five times larger than the previous. */
1296  const int subdivision_scale = 5;
1297 
1298  const float view_level = logf(min_step / zoom_x) / logf(subdivision_scale);
1299  const int largest_visible_level = (int)view_level;
1300 
1301  for (int level_offset = 0; level_offset <= grid_subdivisions; level_offset++) {
1302  const int level = largest_visible_level - level_offset;
1303 
1304  if (level < 0) {
1305  break;
1306  }
1307 
1308  const float level_scale = powf(subdivision_scale, level);
1309  const float point_size_precise = min_point_size * level_scale * zoom_x;
1310  const float point_size_draw = ceilf(
1311  clamp_f(point_size_precise, min_point_size, max_point_size));
1312 
1313  /* To compensate the for the clamped point_size we adjust the alpha to make the overall
1314  * brightness of the grid background more consistent. */
1315  const float alpha = pow2f(point_size_precise / point_size_draw);
1316 
1317  /* Make sure we don't draw points once the alpha gets too low. */
1318  const float alpha_cutoff = 0.01f;
1319  if (alpha < alpha_cutoff) {
1320  break;
1321  }
1322  const float alpha_clamped = clamp_f((1.0f + alpha_cutoff) * alpha - alpha_cutoff, 0.0f, 1.0f);
1323 
1324  /* If we have don't draw enough subdivision levels so they fade out naturally, we apply an
1325  * additional fade to the last level to avoid pop in. */
1326  const bool last_level = level_offset == grid_subdivisions;
1327  const float subdivision_fade = last_level ? (1.0f - fractf(view_level)) : 1.0f;
1328 
1329  float color[4];
1330  UI_GetThemeColor3fv(grid_color_id, color);
1331  color[3] = alpha_clamped * subdivision_fade;
1332 
1333  const float step = min_step * level_scale;
1334  int count_x;
1335  float start_x;
1336  grid_axis_start_and_count(step, v2d->cur.xmin, v2d->cur.xmax, &start_x, &count_x);
1337  int count_y;
1338  float start_y;
1339  grid_axis_start_and_count(step, v2d->cur.ymin, v2d->cur.ymax, &start_y, &count_y);
1340  if (count_x == 0 || count_y == 0) {
1341  continue;
1342  }
1343 
1344  GPU_point_size(point_size_draw);
1345  immBegin(GPU_PRIM_POINTS, count_x * count_y);
1346 
1347  /* Theoretically drawing on top of lower grid levels could be avoided, but it would also
1348  * increase the complexity of this loop, which isn't worth the time at the moment. */
1349  for (int i_y = 0; i_y < count_y; i_y++) {
1350  const float y = start_y + step * i_y;
1351  for (int i_x = 0; i_x < count_x; i_x++) {
1352  const float x = start_x + step * i_x;
1353  immAttr4fv(color_id, color);
1354  immVertex2f(pos, x, y);
1355  }
1356  }
1357 
1358  immEnd();
1359  }
1360 
1361  immUnbindProgram();
1362 }
1363 
1366 /* -------------------------------------------------------------------- */
1377  /* focus bubbles */
1378  /* focus bubbles */
1379  /* focus bubbles */
1380  int vert_min, vert_max; /* vertical scrollbar */
1381  int hor_min, hor_max; /* horizontal scrollbar */
1382 
1385  /* set if sliders are full, we don't draw them */
1386  /* int horfull, vertfull; */ /* UNUSED */
1387 };
1388 
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 void UI_view2d_scrollers_draw_ex(View2D *v2d, const rcti *mask_custom, bool use_full_hide)
1516 {
1517  View2DScrollers scrollers;
1518  UI_view2d_scrollers_calc(v2d, mask_custom, &scrollers);
1519  bTheme *btheme = UI_GetTheme();
1520  rcti vert, hor;
1521  const int scroll = view2d_scroll_mapped(v2d->scroll);
1522  const char emboss_alpha = btheme->tui.widget_emboss[3];
1523  const float alpha_min = use_full_hide ? 0.0f : V2D_SCROLL_MIN_ALPHA;
1524 
1525  uchar scrollers_back_color[4];
1526 
1527  /* Color for scrollbar backs */
1528  UI_GetThemeColor4ubv(TH_BACK, scrollers_back_color);
1529 
1530  /* make copies of rects for less typing */
1531  vert = scrollers.vert;
1532  hor = scrollers.hor;
1533 
1534  /* horizontal scrollbar */
1535  if (scroll & V2D_SCROLL_HORIZONTAL) {
1536  uiWidgetColors wcol = btheme->tui.wcol_scroll;
1537  /* 0..255 -> min...1 */
1538  const float alpha_fac = ((v2d->alpha_hor / 255.0f) * (1.0f - alpha_min)) + alpha_min;
1539  rcti slider;
1540  int state;
1541 
1542  slider.xmin = scrollers.hor_min;
1543  slider.xmax = scrollers.hor_max;
1544  slider.ymin = hor.ymin;
1545  slider.ymax = hor.ymax;
1546 
1548 
1549  wcol.inner[3] *= alpha_fac;
1550  wcol.item[3] *= alpha_fac;
1551  wcol.outline[3] = 0;
1552  btheme->tui.widget_emboss[3] = 0; /* will be reset later */
1553 
1554  /* show zoom handles if:
1555  * - zooming on x-axis is allowed (no scroll otherwise)
1556  * - slider bubble is large enough (no overdraw confusion)
1557  * - scale is shown on the scroller
1558  * (workaround to make sure that button windows don't show these,
1559  * and only the time-grids with their zoom-ability can do so).
1560  */
1561  if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 && (v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) &&
1564  }
1565 
1566  UI_draw_widget_scroll(&wcol, &hor, &slider, state);
1567  }
1568 
1569  /* vertical scrollbar */
1570  if (scroll & V2D_SCROLL_VERTICAL) {
1571  uiWidgetColors wcol = btheme->tui.wcol_scroll;
1572  rcti slider;
1573  /* 0..255 -> min...1 */
1574  const float alpha_fac = ((v2d->alpha_vert / 255.0f) * (1.0f - alpha_min)) + alpha_min;
1575  int state;
1576 
1577  slider.xmin = vert.xmin;
1578  slider.xmax = vert.xmax;
1579  slider.ymin = scrollers.vert_min;
1580  slider.ymax = scrollers.vert_max;
1581 
1583 
1584  wcol.inner[3] *= alpha_fac;
1585  wcol.item[3] *= alpha_fac;
1586  wcol.outline[3] = 0;
1587  btheme->tui.widget_emboss[3] = 0; /* will be reset later */
1588 
1589  /* show zoom handles if:
1590  * - zooming on y-axis is allowed (no scroll otherwise)
1591  * - slider bubble is large enough (no overdraw confusion)
1592  * - scale is shown on the scroller
1593  * (workaround to make sure that button windows don't show these,
1594  * and only the time-grids with their zoomability can do so)
1595  */
1596  if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 && (v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) &&
1599  }
1600 
1601  UI_draw_widget_scroll(&wcol, &vert, &slider, state);
1602  }
1603 
1604  /* Was changed above, so reset. */
1605  btheme->tui.widget_emboss[3] = emboss_alpha;
1606 }
1607 
1608 void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
1609 {
1610  UI_view2d_scrollers_draw_ex(v2d, mask_custom, false);
1611 }
1612 
1615 /* -------------------------------------------------------------------- */
1619 void UI_view2d_listview_view_to_cell(float columnwidth,
1620  float rowheight,
1621  float startx,
1622  float starty,
1623  float viewx,
1624  float viewy,
1625  int *r_column,
1626  int *r_row)
1627 {
1628  if (r_column) {
1629  if (columnwidth > 0) {
1630  /* Columns go from left to right (x increases). */
1631  *r_column = floorf((viewx - startx) / columnwidth);
1632  }
1633  else {
1634  *r_column = 0;
1635  }
1636  }
1637 
1638  if (r_row) {
1639  if (rowheight > 0) {
1640  /* Rows got from top to bottom (y decreases). */
1641  *r_row = floorf((starty - viewy) / rowheight);
1642  }
1643  else {
1644  *r_row = 0;
1645  }
1646  }
1647 }
1648 
1651 /* -------------------------------------------------------------------- */
1655 float UI_view2d_region_to_view_x(const struct View2D *v2d, float x)
1656 {
1657  return (v2d->cur.xmin +
1658  (BLI_rctf_size_x(&v2d->cur) * (x - v2d->mask.xmin) / BLI_rcti_size_x(&v2d->mask)));
1659 }
1660 float UI_view2d_region_to_view_y(const struct View2D *v2d, float y)
1661 {
1662  return (v2d->cur.ymin +
1663  (BLI_rctf_size_y(&v2d->cur) * (y - v2d->mask.ymin) / BLI_rcti_size_y(&v2d->mask)));
1664 }
1665 
1667  const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y)
1668 {
1669  *r_view_x = UI_view2d_region_to_view_x(v2d, x);
1670  *r_view_y = UI_view2d_region_to_view_y(v2d, y);
1671 }
1672 
1673 void UI_view2d_region_to_view_rctf(const View2D *v2d, const rctf *rect_src, rctf *rect_dst)
1674 {
1675  const float cur_size[2] = {BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur)};
1676  const float mask_size[2] = {(float)BLI_rcti_size_x(&v2d->mask),
1677  (float)BLI_rcti_size_y(&v2d->mask)};
1678 
1679  rect_dst->xmin = (v2d->cur.xmin +
1680  (cur_size[0] * (rect_src->xmin - v2d->mask.xmin) / mask_size[0]));
1681  rect_dst->xmax = (v2d->cur.xmin +
1682  (cur_size[0] * (rect_src->xmax - v2d->mask.xmin) / mask_size[0]));
1683  rect_dst->ymin = (v2d->cur.ymin +
1684  (cur_size[1] * (rect_src->ymin - v2d->mask.ymin) / mask_size[1]));
1685  rect_dst->ymax = (v2d->cur.ymin +
1686  (cur_size[1] * (rect_src->ymax - v2d->mask.ymin) / mask_size[1]));
1687 }
1688 
1689 float UI_view2d_view_to_region_x(const View2D *v2d, float x)
1690 {
1691  return (v2d->mask.xmin +
1692  (((x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur)) * BLI_rcti_size_x(&v2d->mask)));
1693 }
1694 float UI_view2d_view_to_region_y(const View2D *v2d, float y)
1695 {
1696  return (v2d->mask.ymin +
1697  (((y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur)) * BLI_rcti_size_y(&v2d->mask)));
1698 }
1699 
1701  const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
1702 {
1703  /* express given coordinates as proportional values */
1704  x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
1705  y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
1706 
1707  /* check if values are within bounds */
1708  if ((x >= 0.0f) && (x <= 1.0f) && (y >= 0.0f) && (y <= 1.0f)) {
1709  *r_region_x = (int)(v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask)));
1710  *r_region_y = (int)(v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask)));
1711 
1712  return true;
1713  }
1714 
1715  /* set initial value in case coordinate lies outside of bounds */
1716  *r_region_x = *r_region_y = V2D_IS_CLIPPED;
1717 
1718  return false;
1719 }
1720 
1722  const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
1723 {
1724  /* Step 1: express given coordinates as proportional values. */
1725  x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
1726  y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
1727 
1728  /* Step 2: convert proportional distances to screen coordinates. */
1729  x = v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask));
1730  y = v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask));
1731 
1732  /* Although we don't clamp to lie within region bounds, we must avoid exceeding size of ints. */
1733  *r_region_x = clamp_float_to_int(x);
1734  *r_region_y = clamp_float_to_int(y);
1735 }
1736 
1738  const View2D *v2d, float x, float y, float *r_region_x, float *r_region_y)
1739 {
1740  /* express given coordinates as proportional values */
1741  x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
1742  y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
1743 
1744  /* convert proportional distances to screen coordinates */
1745  *r_region_x = v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask));
1746  *r_region_y = v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask));
1747 }
1748 
1750  const float xy_a[2],
1751  const float xy_b[2],
1752  int r_region_a[2],
1753  int r_region_b[2])
1754 {
1755  rctf rect_unit;
1756  rect_unit.xmin = rect_unit.ymin = 0.0f;
1757  rect_unit.xmax = rect_unit.ymax = 1.0f;
1758 
1759  /* Express given coordinates as proportional values. */
1760  const float s_a[2] = {
1761  (xy_a[0] - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur),
1762  (xy_a[1] - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur),
1763  };
1764  const float s_b[2] = {
1765  (xy_b[0] - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur),
1766  (xy_b[1] - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur),
1767  };
1768 
1769  /* Set initial value in case coordinates lie outside bounds. */
1770  r_region_a[0] = r_region_b[0] = r_region_a[1] = r_region_b[1] = V2D_IS_CLIPPED;
1771 
1772  if (BLI_rctf_isect_segment(&rect_unit, s_a, s_b)) {
1773  r_region_a[0] = (int)(v2d->mask.xmin + (s_a[0] * BLI_rcti_size_x(&v2d->mask)));
1774  r_region_a[1] = (int)(v2d->mask.ymin + (s_a[1] * BLI_rcti_size_y(&v2d->mask)));
1775  r_region_b[0] = (int)(v2d->mask.xmin + (s_b[0] * BLI_rcti_size_x(&v2d->mask)));
1776  r_region_b[1] = (int)(v2d->mask.ymin + (s_b[1] * BLI_rcti_size_y(&v2d->mask)));
1777 
1778  return true;
1779  }
1780 
1781  return false;
1782 }
1783 
1784 void UI_view2d_view_to_region_rcti(const View2D *v2d, const rctf *rect_src, rcti *rect_dst)
1785 {
1786  const float cur_size[2] = {BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur)};
1787  const float mask_size[2] = {(float)BLI_rcti_size_x(&v2d->mask),
1788  (float)BLI_rcti_size_y(&v2d->mask)};
1789  rctf rect_tmp;
1790 
1791  /* Step 1: express given coordinates as proportional values. */
1792  rect_tmp.xmin = (rect_src->xmin - v2d->cur.xmin) / cur_size[0];
1793  rect_tmp.xmax = (rect_src->xmax - v2d->cur.xmin) / cur_size[0];
1794  rect_tmp.ymin = (rect_src->ymin - v2d->cur.ymin) / cur_size[1];
1795  rect_tmp.ymax = (rect_src->ymax - v2d->cur.ymin) / cur_size[1];
1796 
1797  /* Step 2: convert proportional distances to screen coordinates. */
1798  rect_tmp.xmin = v2d->mask.xmin + (rect_tmp.xmin * mask_size[0]);
1799  rect_tmp.xmax = v2d->mask.xmin + (rect_tmp.xmax * mask_size[0]);
1800  rect_tmp.ymin = v2d->mask.ymin + (rect_tmp.ymin * mask_size[1]);
1801  rect_tmp.ymax = v2d->mask.ymin + (rect_tmp.ymax * mask_size[1]);
1802 
1803  clamp_rctf_to_rcti(rect_dst, &rect_tmp);
1804 }
1805 
1806 void UI_view2d_view_to_region_m4(const View2D *v2d, float matrix[4][4])
1807 {
1808  rctf mask;
1809  unit_m4(matrix);
1810  BLI_rctf_rcti_copy(&mask, &v2d->mask);
1812 }
1813 
1814 bool UI_view2d_view_to_region_rcti_clip(const View2D *v2d, const rctf *rect_src, rcti *rect_dst)
1815 {
1816  const float cur_size[2] = {BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur)};
1817  const float mask_size[2] = {(float)BLI_rcti_size_x(&v2d->mask),
1818  (float)BLI_rcti_size_y(&v2d->mask)};
1819  rctf rect_tmp;
1820 
1821  BLI_assert(rect_src->xmin <= rect_src->xmax && rect_src->ymin <= rect_src->ymax);
1822 
1823  /* Step 1: express given coordinates as proportional values. */
1824  rect_tmp.xmin = (rect_src->xmin - v2d->cur.xmin) / cur_size[0];
1825  rect_tmp.xmax = (rect_src->xmax - v2d->cur.xmin) / cur_size[0];
1826  rect_tmp.ymin = (rect_src->ymin - v2d->cur.ymin) / cur_size[1];
1827  rect_tmp.ymax = (rect_src->ymax - v2d->cur.ymin) / cur_size[1];
1828 
1829  if (((rect_tmp.xmax < 0.0f) || (rect_tmp.xmin > 1.0f) || (rect_tmp.ymax < 0.0f) ||
1830  (rect_tmp.ymin > 1.0f)) == 0) {
1831  /* Step 2: convert proportional distances to screen coordinates. */
1832  rect_tmp.xmin = v2d->mask.xmin + (rect_tmp.xmin * mask_size[0]);
1833  rect_tmp.xmax = v2d->mask.ymin + (rect_tmp.xmax * mask_size[0]);
1834  rect_tmp.ymin = v2d->mask.ymin + (rect_tmp.ymin * mask_size[1]);
1835  rect_tmp.ymax = v2d->mask.ymin + (rect_tmp.ymax * mask_size[1]);
1836 
1837  clamp_rctf_to_rcti(rect_dst, &rect_tmp);
1838 
1839  return true;
1840  }
1841 
1842  rect_dst->xmin = rect_dst->xmax = rect_dst->ymin = rect_dst->ymax = V2D_IS_CLIPPED;
1843  return false;
1844 }
1845 
1848 /* -------------------------------------------------------------------- */
1853 {
1854  ScrArea *area = CTX_wm_area(C);
1855  ARegion *region = CTX_wm_region(C);
1856 
1857  if (area == nullptr) {
1858  return nullptr;
1859  }
1860  if (region == nullptr) {
1861  return nullptr;
1862  }
1863  return &(region->v2d);
1864 }
1865 
1867 {
1868  ScrArea *area = CTX_wm_area(C);
1869  ARegion *region = CTX_wm_region(C);
1870 
1871  if (area == nullptr) {
1872  return nullptr;
1873  }
1874  if (region == nullptr) {
1875  return nullptr;
1876  }
1877  if (region->regiontype != RGN_TYPE_WINDOW) {
1879  return region_win ? &(region_win->v2d) : nullptr;
1880  }
1881  return &(region->v2d);
1882 }
1883 
1884 void UI_view2d_scroller_size_get(const View2D *v2d, bool mapped, float *r_x, float *r_y)
1885 {
1886  const int scroll = (mapped) ? view2d_scroll_mapped(v2d->scroll) : v2d->scroll;
1887 
1888  if (r_x) {
1889  if (scroll & V2D_SCROLL_VERTICAL) {
1891  *r_x = ((*r_x - V2D_SCROLL_MIN_WIDTH) * (v2d->alpha_vert / 255.0f)) + V2D_SCROLL_MIN_WIDTH;
1892  }
1893  else {
1894  *r_x = 0;
1895  }
1896  }
1897  if (r_y) {
1898  if (scroll & V2D_SCROLL_HORIZONTAL) {
1901  *r_y = ((*r_y - V2D_SCROLL_MIN_WIDTH) * (v2d->alpha_hor / 255.0f)) + V2D_SCROLL_MIN_WIDTH;
1902  }
1903  else {
1904  *r_y = 0;
1905  }
1906  }
1907 }
1908 
1909 void UI_view2d_scale_get(const View2D *v2d, float *r_x, float *r_y)
1910 {
1911  if (r_x) {
1912  *r_x = UI_view2d_scale_get_x(v2d);
1913  }
1914  if (r_y) {
1915  *r_y = UI_view2d_scale_get_y(v2d);
1916  }
1917 }
1919 {
1920  return BLI_rcti_size_x(&v2d->mask) / BLI_rctf_size_x(&v2d->cur);
1921 }
1923 {
1924  return BLI_rcti_size_y(&v2d->mask) / BLI_rctf_size_y(&v2d->cur);
1925 }
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 
1936 void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y)
1937 {
1938  /* get center */
1939  if (r_x) {
1940  *r_x = BLI_rctf_cent_x(&v2d->cur);
1941  }
1942  if (r_y) {
1943  *r_y = BLI_rctf_cent_y(&v2d->cur);
1944  }
1945 }
1946 void UI_view2d_center_set(struct View2D *v2d, float x, float y)
1947 {
1948  BLI_rctf_recenter(&v2d->cur, x, y);
1949 
1950  /* make sure that 'cur' rect is in a valid state as a result of these changes */
1952 }
1953 
1954 void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac)
1955 {
1956  if (xfac != -1.0f) {
1957  const float xsize = BLI_rctf_size_x(&v2d->cur);
1958  const float xmin = v2d->tot.xmin;
1959  const float xmax = v2d->tot.xmax - xsize;
1960 
1961  v2d->cur.xmin = (xmin * (1.0f - xfac)) + (xmax * xfac);
1962  v2d->cur.xmax = v2d->cur.xmin + xsize;
1963  }
1964 
1965  if (yfac != -1.0f) {
1966  const float ysize = BLI_rctf_size_y(&v2d->cur);
1967  const float ymin = v2d->tot.ymin;
1968  const float ymax = v2d->tot.ymax - ysize;
1969 
1970  v2d->cur.ymin = (ymin * (1.0f - yfac)) + (ymax * yfac);
1971  v2d->cur.ymax = v2d->cur.ymin + ysize;
1972  }
1973 
1975 }
1976 
1978  const View2D *v2d,
1979  const int xy[2],
1980  int *r_scroll)
1981 {
1982  const int scroll = view2d_scroll_mapped(v2d->scroll);
1983  *r_scroll = scroll;
1984 
1985  if (scroll) {
1986  /* Move to region-coordinates. */
1987  const int co[2] = {
1988  xy[0] - region->winrct.xmin,
1989  xy[1] - region->winrct.ymin,
1990  };
1991  if (scroll & V2D_SCROLL_HORIZONTAL) {
1992  if (IN_2D_HORIZ_SCROLL(v2d, co)) {
1993  return 'h';
1994  }
1995  }
1996  if (scroll & V2D_SCROLL_VERTICAL) {
1997  if (IN_2D_VERT_SCROLL(v2d, co)) {
1998  return 'v';
1999  }
2000  }
2001  }
2002 
2003  return 0;
2004 }
2005 
2007  const View2D *v2d,
2008  const rcti *rect,
2009  int *r_scroll)
2010 {
2011  const int scroll = view2d_scroll_mapped(v2d->scroll);
2012  *r_scroll = scroll;
2013 
2014  if (scroll) {
2015  /* Move to region-coordinates. */
2016  rcti rect_region = *rect;
2017  BLI_rcti_translate(&rect_region, -region->winrct.xmin, region->winrct.ymin);
2018  if (scroll & V2D_SCROLL_HORIZONTAL) {
2019  if (IN_2D_HORIZ_SCROLL_RECT(v2d, &rect_region)) {
2020  return 'h';
2021  }
2022  }
2023  if (scroll & V2D_SCROLL_VERTICAL) {
2024  if (IN_2D_VERT_SCROLL_RECT(v2d, &rect_region)) {
2025  return 'v';
2026  }
2027  }
2028  }
2029 
2030  return 0;
2031 }
2032 
2033 char UI_view2d_mouse_in_scrollers(const ARegion *region, const View2D *v2d, const int xy[2])
2034 {
2035  int scroll_dummy = 0;
2036  return UI_view2d_mouse_in_scrollers_ex(region, v2d, xy, &scroll_dummy);
2037 }
2038 
2039 char UI_view2d_rect_in_scrollers(const ARegion *region, const View2D *v2d, const rcti *rect)
2040 {
2041  int scroll_dummy = 0;
2042  return UI_view2d_rect_in_scrollers_ex(region, v2d, rect, &scroll_dummy);
2043 }
2044 
2047 /* -------------------------------------------------------------------- */
2053  union {
2054  uchar ub[4];
2055  int pack;
2056  } col;
2058  int mval[2];
2059 
2060  /* str is allocated past the end */
2061  char str[0];
2062 };
2063 
2064 /* assumes caches are used correctly, so for time being no local storage in v2d */
2065 static MemArena *g_v2d_strings_arena = nullptr;
2066 static View2DString *g_v2d_strings = nullptr;
2067 
2069  View2D *v2d, float x, float y, const char *str, size_t str_len, const uchar col[4])
2070 {
2071  int mval[2];
2072 
2073  BLI_assert(str_len == strlen(str));
2074 
2075  if (UI_view2d_view_to_region_clip(v2d, x, y, &mval[0], &mval[1])) {
2076  const int alloc_len = str_len + 1;
2077 
2078  if (g_v2d_strings_arena == nullptr) {
2080  }
2081 
2082  View2DString *v2s = static_cast<View2DString *>(
2083  BLI_memarena_alloc(g_v2d_strings_arena, sizeof(View2DString) + alloc_len));
2084 
2086 
2087  v2s->col.pack = *((const int *)col);
2088 
2089  memset(&v2s->rect, 0, sizeof(v2s->rect));
2090 
2091  v2s->mval[0] = mval[0];
2092  v2s->mval[1] = mval[1];
2093 
2094  memcpy(v2s->str, str, alloc_len);
2095  }
2096 }
2097 
2099  View2D *v2d, const rctf *rect_view, const char *str, size_t str_len, const uchar col[4])
2100 {
2101  rcti rect;
2102 
2103  BLI_assert(str_len == strlen(str));
2104 
2105  if (UI_view2d_view_to_region_rcti_clip(v2d, rect_view, &rect)) {
2106  const int alloc_len = str_len + 1;
2107 
2108  if (g_v2d_strings_arena == nullptr) {
2110  }
2111 
2112  View2DString *v2s = static_cast<View2DString *>(
2113  BLI_memarena_alloc(g_v2d_strings_arena, sizeof(View2DString) + alloc_len));
2114 
2116 
2117  v2s->col.pack = *((const int *)col);
2118 
2119  v2s->rect = rect;
2120 
2121  v2s->mval[0] = v2s->rect.xmin;
2122  v2s->mval[1] = v2s->rect.ymin;
2123 
2124  memcpy(v2s->str, str, alloc_len);
2125  }
2126 }
2127 
2129 {
2130  View2DString *v2s;
2131  int col_pack_prev = 0;
2132 
2133  /* investigate using BLF_ascender() */
2134  const int font_id = BLF_default();
2135 
2136  BLF_set_default();
2137  const float default_height = g_v2d_strings ? BLF_height(font_id, "28", 3) : 0.0f;
2138 
2140 
2141  for (v2s = g_v2d_strings; v2s; v2s = v2s->next) {
2142  int xofs = 0, yofs;
2143 
2144  yofs = ceil(0.5f * (BLI_rcti_size_y(&v2s->rect) - default_height));
2145  if (yofs < 1) {
2146  yofs = 1;
2147  }
2148 
2149  if (col_pack_prev != v2s->col.pack) {
2150  BLF_color3ubv(font_id, v2s->col.ub);
2151  col_pack_prev = v2s->col.pack;
2152  }
2153 
2154  BLF_enable(font_id, BLF_CLIPPING);
2155  BLF_clipping(
2156  font_id, v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4);
2158  v2s->rect.xmin + xofs, v2s->rect.ymin + yofs, 0.0f, v2s->str, BLF_DRAW_STR_DUMMY_MAX);
2159  BLF_disable(font_id, BLF_CLIPPING);
2160  }
2161  g_v2d_strings = nullptr;
2162 
2163  if (g_v2d_strings_arena) {
2165  g_v2d_strings_arena = nullptr;
2166  }
2167 }
2168 
typedef float(TangentPoint)[2]
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
@ G_DEBUG
Definition: BKE_global.h:174
struct ARegion * BKE_area_find_region_type(const struct ScrArea *area, int type)
@ BLF_CLIPPING
Definition: BLF_api.h:335
void BLF_color3ubv(int fontid, const unsigned char rgb[3])
Definition: blf.c:407
void BLF_clipping(int fontid, int xmin, int ymin, int xmax, int ymax)
Definition: blf.c:775
void BLF_cache_clear(void)
Definition: blf.c:83
float BLF_height(int fontid, const char *str, size_t str_len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: blf.c:717
int BLF_default(void)
Definition: blf_default.c:44
#define BLF_DRAW_STR_DUMMY_MAX
Definition: BLF_api.h:356
void BLF_disable(int fontid, int option)
Definition: blf.c:279
void BLF_enable(int fontid, int option)
Definition: blf.c:270
void BLF_draw_default(float x, float y, float z, const char *str, size_t str_len) ATTR_NONNULL()
Definition: blf_default.c:59
int BLF_set_default(void)
Definition: blf_default.c:50
A (mainly) macro array library.
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_INLINE
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
MINLINE float pow2f(float x)
MINLINE float clamp_f(float value, float min, float max)
void unit_m4(float m[4][4])
Definition: rct.c:1090
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:94
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
Definition: BLI_memarena.c:64
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:116
void BLI_rctf_translate(struct rctf *rect, float x, float y)
Definition: rct.c:566
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:190
BLI_INLINE float BLI_rctf_cent_y(const struct rctf *rct)
Definition: BLI_rect.h:181
BLI_INLINE float BLI_rctf_cent_x(const struct rctf *rct)
Definition: BLI_rect.h:177
void BLI_rcti_translate(struct rcti *rect, int x, int y)
Definition: rct.c:559
void BLI_rctf_transform_calc_m4_pivot_min(const rctf *dst, const rctf *src, float matrix[4][4])
Definition: rct.c:554
bool BLI_rctf_isect_segment(const struct rctf *rect, const float s1[2], const float s2[2])
void BLI_rctf_recenter(struct rctf *rect, float x, float y)
Definition: rct.c:580
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
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:194
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition: BLI_rect.h:198
unsigned char uchar
Definition: BLI_sys_types.h:70
unsigned int uint
Definition: BLI_sys_types.h:67
#define CLAMP_MAX(a, c)
#define UNLIKELY(x)
#define ELEM(...)
@ RGN_TYPE_WINDOW
@ SPACE_CLIP
@ SPACE_ACTION
@ SPACE_NLA
@ SPACE_SEQ
@ SPACE_GRAPH
@ V2D_KEEPTOT_BOUNDS
@ V2D_KEEPTOT_STRICT
@ V2D_LOCKOFS_X
@ V2D_LOCKOFS_Y
@ V2D_KEEPOFS_Y
@ V2D_KEEPOFS_X
@ V2D_SCROLL_V_ACTIVE
@ V2D_SCROLL_H_ACTIVE
@ V2D_LIMITZOOM
@ V2D_LOCKZOOM_X
@ V2D_KEEPZOOM
@ V2D_KEEPASPECT
@ V2D_LOCKZOOM_Y
@ V2D_VIEWSYNC_SCREEN_TIME
@ V2D_PIXELOFS_X
@ V2D_IS_INIT
@ V2D_PIXELOFS_Y
@ V2D_VIEWSYNC_AREA_VERTICAL
@ 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
void ED_region_tag_redraw_no_rebuild(struct ARegion *region)
Definition: area.c:674
void immAttr3ubv(uint attr_id, const unsigned char data[3])
void immAttr4fv(uint attr_id, const float data[4])
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 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 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 type
_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
void GPU_matrix_identity_set(void)
Definition: gpu_matrix.cc:168
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:20
@ GPU_PRIM_POINTS
Definition: GPU_primitive.h:19
@ GPU_SHADER_2D_FLAT_COLOR
Definition: GPU_shader.h:208
void GPU_line_width(float width)
Definition: gpu_state.cc:158
void GPU_point_size(float size)
Definition: gpu_state.cc:164
@ 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 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
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 a value between a minimum and a maximum Vector Perform vector math operation Invert a color
#define C
Definition: RandGen.cpp:25
@ UI_SCROLL_PRESSED
Definition: UI_interface.h:456
@ UI_SCROLL_ARROWS
Definition: UI_interface.h:457
const struct uiStyle * UI_style_get(void)
#define UI_HEADER_OFFSET
#define UI_DPI_FAC
Definition: UI_interface.h:305
void UI_draw_widget_scroll(struct uiWidgetColors *wcol, const struct rcti *rect, const struct rcti *slider, int state)
void UI_GetThemeColor3fv(int colorid, float col[3])
Definition: resources.c:1165
@ TH_GRID
Definition: UI_resources.h:68
@ TH_BACK
Definition: UI_resources.h:39
struct bTheme * UI_GetTheme(void)
Definition: resources.c:1067
void UI_GetThemeColorBlendShade3ubv(int colorid1, int colorid2, float fac, int offset, unsigned char col[3])
Definition: resources.c:1225
void UI_GetThemeColor4ubv(int colorid, unsigned char col[4])
Definition: resources.c:1352
#define V2D_SCROLL_HEIGHT
Definition: UI_view2d.h:54
#define V2D_LOCK_COPY
Definition: UI_view2d.h:82
#define V2D_SCROLL_MIN_ALPHA
Definition: UI_view2d.h:58
#define V2D_SCROLL_HANDLE_HEIGHT
Definition: UI_view2d.h:68
#define V2D_SCROLL_THUMB_SIZE_MIN
Definition: UI_view2d.h:75
#define IN_2D_HORIZ_SCROLL(v2d, co)
Definition: UI_view2d.h:89
#define V2D_SCROLL_WIDTH
Definition: UI_view2d.h:55
#define V2D_SCROLL_HANDLE_WIDTH
Definition: UI_view2d.h:69
#define IN_2D_VERT_SCROLL(v2d, co)
Definition: UI_view2d.h:88
#define UI_TIME_SCRUB_MARGIN_Y
Definition: UI_view2d.h:450
#define IN_2D_VERT_SCROLL_RECT(v2d, rct)
Definition: UI_view2d.h:91
#define V2D_SCROLL_HANDLE_SIZE_HOTSPOT
Definition: UI_view2d.h:72
#define V2D_SCROLL_MIN_WIDTH
Definition: UI_view2d.h:61
@ V2D_COMMONVIEW_LIST
Definition: UI_view2d.h:38
@ V2D_COMMONVIEW_STACK
Definition: UI_view2d.h:40
@ V2D_COMMONVIEW_HEADER
Definition: UI_view2d.h:42
@ V2D_COMMONVIEW_STANDARD
Definition: UI_view2d.h:36
@ V2D_COMMONVIEW_PANELS_UI
Definition: UI_view2d.h:44
#define V2D_IS_CLIPPED
Definition: UI_view2d.h:25
#define IN_2D_HORIZ_SCROLL_RECT(v2d, rct)
Definition: UI_view2d.h:92
unsigned int U
Definition: btGjkEpa3.h:78
#define logf(x)
Definition: cuda/compat.h:105
#define powf(x, y)
Definition: cuda/compat.h:103
SyclQueue void void * src
#define str(s)
uint pos
uint col
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
const int state
format
Definition: logImageCore.h:38
MINLINE float fractf(float a)
ccl_device_inline float2 fabs(const float2 &a)
Definition: math_float2.h:222
ccl_device_inline float3 ceil(const float3 &a)
Definition: math_float3.h:363
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
#define G(x, y, z)
#define ceilf(x)
Definition: metal/compat.h:225
#define floorf(x)
Definition: metal/compat.h:224
#define fabsf(x)
Definition: metal/compat.h:219
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])
T abs(const T &a)
const btScalar eps
Definition: poly34.cpp:11
#define min(a, b)
Definition: sort.c:35
void(* on_view2d_changed)(const struct bContext *C, struct ARegion *region)
Definition: BKE_screen.h:192
short regiontype
struct ARegionType * type
uiWidgetColors wcol_scroll
unsigned char widget_emboss[4]
char str[0]
Definition: view2d.cc:2061
struct View2DString * next
Definition: view2d.cc:2052
union View2DString::@443 col
int mval[2]
Definition: view2d.cc:2058
uchar ub[4]
Definition: view2d.cc:2054
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:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63
float panelzoom
unsigned char inner[4]
unsigned char outline[4]
unsigned char item[4]
float max
char UI_view2d_rect_in_scrollers(const ARegion *region, const View2D *v2d, const rcti *rect)
Definition: view2d.cc:2039
void UI_view2d_curRect_validate(View2D *v2d)
Definition: view2d.cc:828
void UI_view2d_center_set(struct View2D *v2d, float x, float y)
Definition: view2d.cc:1946
void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
Definition: view2d.cc:851
static void grid_axis_start_and_count(const float step, const float min, const float max, float *r_start, int *r_count)
Definition: view2d.cc:1254
void UI_view2d_scale_get_inverse(const View2D *v2d, float *r_x, float *r_y)
Definition: view2d.cc:1926
void UI_view2d_curRect_reset(View2D *v2d)
Definition: view2d.cc:914
static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize)
Definition: view2d.cc:383
bool UI_view2d_view_to_region_segment_clip(const View2D *v2d, const float xy_a[2], const float xy_b[2], int r_region_a[2], int r_region_b[2])
Definition: view2d.cc:1749
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y)
Definition: view2d.cc:1666
void UI_view2d_view_orthoSpecial(ARegion *region, View2D *v2d, const bool xaxis)
Definition: view2d.cc:1122
char UI_view2d_mouse_in_scrollers(const ARegion *region, const View2D *v2d, const int xy[2])
Definition: view2d.cc:2033
void UI_view2d_multi_grid_draw(const View2D *v2d, int colorid, float step, int level_size, int totlevels)
Definition: view2d.cc:1166
static View2DString * g_v2d_strings
Definition: view2d.cc:2066
void UI_view2d_view_to_region_rcti(const View2D *v2d, const rctf *rect_src, rcti *rect_dst)
Definition: view2d.cc:1784
bool UI_view2d_view_to_region_clip(const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
Definition: view2d.cc:1700
bool UI_view2d_view_to_region_rcti_clip(const View2D *v2d, const rctf *rect_src, rcti *rect_dst)
Definition: view2d.cc:1814
char UI_view2d_mouse_in_scrollers_ex(const ARegion *region, const View2D *v2d, const int xy[2], int *r_scroll)
Definition: view2d.cc:1977
void UI_view2d_dot_grid_draw(const View2D *v2d, const int grid_color_id, const float min_step, const int grid_subdivisions)
Definition: view2d.cc:1273
void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
Definition: view2d.cc:1608
BLI_INLINE void clamp_rctf_to_rcti(rcti *dst, const rctf *src)
Definition: view2d.cc:72
View2D * UI_view2d_fromcontext(const bContext *C)
Definition: view2d.cc:1852
void UI_view2d_view_restore(const bContext *C)
Definition: view2d.cc:1148
void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
Definition: view2d.cc:217
void UI_view2d_curRect_changed(const bContext *C, View2D *v2d)
Definition: view2d.cc:833
void UI_view2d_text_cache_draw(ARegion *region)
Definition: view2d.cc:2128
void UI_view2d_totRect_set(View2D *v2d, int width, int height)
Definition: view2d.cc:1022
void UI_view2d_region_to_view_rctf(const View2D *v2d, const rctf *rect_src, rctf *rect_dst)
Definition: view2d.cc:1673
static int view2d_scroll_mapped(int scroll)
Definition: view2d.cc:96
float UI_view2d_view_to_region_y(const View2D *v2d, float y)
Definition: view2d.cc:1694
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.cc:1619
void UI_view2d_view_ortho(const View2D *v2d)
Definition: view2d.cc:1081
static MemArena * g_v2d_strings_arena
Definition: view2d.cc:2065
void UI_view2d_view_to_region(const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
Definition: view2d.cc:1721
void UI_view2d_zoom_cache_reset(void)
Definition: view2d.cc:1027
View2D * UI_view2d_fromcontext_rwin(const bContext *C)
Definition: view2d.cc:1866
float UI_view2d_scale_get_y(const View2D *v2d)
Definition: view2d.cc:1922
void UI_view2d_scroller_size_get(const View2D *v2d, bool mapped, float *r_x, float *r_y)
Definition: view2d.cc:1884
void UI_view2d_scale_get(const View2D *v2d, float *r_x, float *r_y)
Definition: view2d.cc:1909
bool UI_view2d_area_supports_sync(ScrArea *area)
Definition: view2d.cc:846
void UI_view2d_mask_from_win(const View2D *v2d, rcti *r_mask)
Definition: view2d.cc:107
char UI_view2d_rect_in_scrollers_ex(const ARegion *region, const View2D *v2d, const rcti *rect, int *r_scroll)
Definition: view2d.cc:2006
void UI_view2d_view_to_region_m4(const View2D *v2d, float matrix[4][4])
Definition: view2d.cc:1806
void UI_view2d_view_to_region_fl(const View2D *v2d, float x, float y, float *r_region_x, float *r_region_y)
Definition: view2d.cc:1737
float UI_view2d_region_to_view_x(const struct View2D *v2d, float x)
Definition: view2d.cc:1655
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.cc:2068
float UI_view2d_view_to_region_x(const View2D *v2d, float x)
Definition: view2d.cc:1689
void UI_view2d_scrollers_calc(View2D *v2d, const rcti *mask_custom, struct View2DScrollers *r_scrollers)
Definition: view2d.cc:1389
void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y)
Definition: view2d.cc:1936
float UI_view2d_region_to_view_y(const struct View2D *v2d, float y)
Definition: view2d.cc:1660
static void view2d_map_cur_using_mask(const View2D *v2d, rctf *r_curmasked)
Definition: view2d.cc:1050
void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resize)
Definition: view2d.cc:963
BLI_INLINE int clamp_float_to_int(const float f)
Definition: view2d.cc:54
void UI_view2d_scrollers_draw_ex(View2D *v2d, const rcti *mask_custom, bool use_full_hide)
Definition: view2d.cc:1515
static void view2d_masks(View2D *v2d, const rcti *mask_scroll)
Definition: view2d.cc:120
void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac)
Definition: view2d.cc:1954
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.cc:2098
float UI_view2d_scale_get_x(const View2D *v2d)
Definition: view2d.cc:1918
int xy[2]
Definition: wm_draw.c:135
void wmOrtho2(float x1, float x2, float y1, float y2)
Definition: wm_subwindow.c:84
void wmOrtho2_region_pixelspace(const ARegion *region)
Definition: wm_subwindow.c:103