Blender  V2.93
area.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 <stdio.h>
25 #include <string.h>
26 
27 #include "MEM_guardedalloc.h"
28 
29 #include "DNA_userdef_types.h"
30 
31 #include "BLI_blenlib.h"
32 #include "BLI_linklist_stack.h"
33 #include "BLI_math.h"
34 #include "BLI_rand.h"
35 #include "BLI_utildefines.h"
36 
37 #include "BKE_context.h"
38 #include "BKE_global.h"
39 #include "BKE_image.h"
40 #include "BKE_screen.h"
41 #include "BKE_workspace.h"
42 
43 #include "RNA_access.h"
44 #include "RNA_types.h"
45 
46 #include "WM_api.h"
47 #include "WM_message.h"
48 #include "WM_toolsystem.h"
49 #include "WM_types.h"
50 
51 #include "ED_buttons.h"
52 #include "ED_screen.h"
53 #include "ED_screen_types.h"
54 #include "ED_space_api.h"
55 #include "ED_time_scrub_ui.h"
56 
57 #include "GPU_framebuffer.h"
58 #include "GPU_immediate.h"
59 #include "GPU_immediate_util.h"
60 #include "GPU_matrix.h"
61 #include "GPU_state.h"
62 
63 #include "BLF_api.h"
64 
65 #include "IMB_imbuf_types.h"
66 #include "IMB_metadata.h"
67 
68 #include "UI_interface.h"
69 #include "UI_interface_icons.h"
70 #include "UI_resources.h"
71 #include "UI_view2d.h"
72 
73 #include "screen_intern.h"
74 
76  REGION_EMBOSS_LEFT = (1 << 0),
77  REGION_EMBOSS_TOP = (1 << 1),
79  REGION_EMBOSS_RIGHT = (1 << 3),
82 };
83 
84 /* general area and region code */
85 
86 static void region_draw_emboss(const ARegion *region, const rcti *scirct, int sides)
87 {
88  /* translate scissor rect to region space */
89  const rcti rect = {.xmin = scirct->xmin - region->winrct.xmin,
90  .xmax = scirct->xmax - region->winrct.xmin,
91  .ymin = scirct->ymin - region->winrct.ymin,
92  .ymax = scirct->ymax - region->winrct.ymin};
93 
94  /* set transp line */
96 
97  float color[4] = {0.0f, 0.0f, 0.0f, 0.25f};
99 
103  immUniformColor4fv(color);
104 
106 
107  /* right */
108  if (sides & REGION_EMBOSS_RIGHT) {
109  immVertex2f(pos, rect.xmax, rect.ymax);
110  immVertex2f(pos, rect.xmax, rect.ymin);
111  }
112 
113  /* bottom */
114  if (sides & REGION_EMBOSS_BOTTOM) {
115  immVertex2f(pos, rect.xmax, rect.ymin);
116  immVertex2f(pos, rect.xmin, rect.ymin);
117  }
118 
119  /* left */
120  if (sides & REGION_EMBOSS_LEFT) {
121  immVertex2f(pos, rect.xmin, rect.ymin);
122  immVertex2f(pos, rect.xmin, rect.ymax);
123  }
124 
125  /* top */
126  if (sides & REGION_EMBOSS_TOP) {
127  immVertex2f(pos, rect.xmin, rect.ymax);
128  immVertex2f(pos, rect.xmax, rect.ymax);
129  }
130 
131  immEnd();
133 
135 }
136 
138 {
141 }
142 
143 /* only exported for WM */
145 {
146  ARegion *region = params->region;
147  wmNotifier *notifier = params->notifier;
148 
149  /* generic notes first */
150  switch (notifier->category) {
151  case NC_WM:
152  if (notifier->data == ND_FILEREAD) {
153  ED_region_tag_redraw(region);
154  }
155  break;
156  case NC_WINDOW:
157  ED_region_tag_redraw(region);
158  break;
159  }
160 
161  if (region->type && region->type->listener) {
162  region->type->listener(params);
163  }
164 }
165 
166 /* only exported for WM */
168 {
169  /* no generic notes? */
170  if (params->area->type && params->area->type->listener) {
171  params->area->type->listener(params);
172  }
173 }
174 
175 /* only exported for WM */
177 {
178  /* no generic notes? */
179  if (area->type && area->type->refresh) {
180  area->type->refresh(C, area);
181  }
182  area->do_refresh = false;
183 }
184 
189  short UNUSED(x1), short UNUSED(y1), short x2, short y2, float alpha)
190 {
191  UI_icon_draw_ex(x2 - U.widget_unit,
192  y2 - U.widget_unit,
193  ICON_FULLSCREEN_EXIT,
194  U.inv_dpi_fac,
195  min_ff(alpha, 0.75f),
196  0.0f,
197  NULL,
198  false);
199 }
200 
204 static void area_draw_azone(short UNUSED(x1), short UNUSED(y1), short UNUSED(x2), short UNUSED(y2))
205 {
206  /* No drawing needed since all corners are action zone, and visually distinguishable. */
207 }
208 
212 static void draw_azone_arrow(float x1, float y1, float x2, float y2, AZEdge edge)
213 {
214  const float size = 0.2f * U.widget_unit;
215  const float l = 1.0f; /* arrow length */
216  const float s = 0.25f; /* arrow thickness */
217  const float hl = l / 2.0f;
218  const float points[6][2] = {
219  {0, -hl}, {l, hl}, {l - s, hl + s}, {0, s + s - hl}, {s - l, hl + s}, {-l, hl}};
220  const float center[2] = {(x1 + x2) / 2, (y1 + y2) / 2};
221 
222  int axis;
223  int sign;
224  switch (edge) {
226  axis = 0;
227  sign = 1;
228  break;
230  axis = 0;
231  sign = -1;
232  break;
233  case AE_LEFT_TO_TOPRIGHT:
234  axis = 1;
235  sign = 1;
236  break;
237  case AE_RIGHT_TO_TOPLEFT:
238  axis = 1;
239  sign = -1;
240  break;
241  default:
242  BLI_assert(0);
243  return;
244  }
245 
248 
250  /* NOTE(fclem): There is something strange going on with Mesa and GPU_SHADER_2D_UNIFORM_COLOR
251  * that causes a crash on some GPUs (see T76113). Using 3D variant avoid the issue. */
253  immUniformColor4f(0.8f, 0.8f, 0.8f, 0.4f);
254 
256  for (int i = 0; i < 6; i++) {
257  if (axis == 0) {
258  immVertex2f(pos, center[0] + points[i][0] * size, center[1] + points[i][1] * sign * size);
259  }
260  else {
261  immVertex2f(pos, center[0] + points[i][1] * sign * size, center[1] + points[i][0] * size);
262  }
263  }
264  immEnd();
265 
268 }
269 
271 {
273 
274  /* add code to draw region hidden as 'too small' */
275  switch (az->edge) {
278  break;
281  break;
282  case AE_LEFT_TO_TOPRIGHT:
284  break;
285  case AE_RIGHT_TO_TOPLEFT:
287  break;
288  }
289 
290  /* Workaround for different color spaces between normal areas and the ones using GPUViewports. */
291  float alpha = WM_region_use_viewport(area, region) ? 0.6f : 0.4f;
292  const float color[4] = {0.05f, 0.05f, 0.05f, alpha};
294  &(const rctf){
295  .xmin = (float)az->x1,
296  .xmax = (float)az->x2,
297  .ymin = (float)az->y1,
298  .ymax = (float)az->y2,
299  },
300  true,
301  4.0f,
302  color);
303 
304  draw_azone_arrow((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, az->edge);
305 }
306 
308 {
310 }
311 
312 static void region_draw_azones(ScrArea *area, ARegion *region)
313 {
314  if (!area) {
315  return;
316  }
317 
318  GPU_line_width(1.0f);
320 
321  GPU_matrix_push();
322  GPU_matrix_translate_2f(-region->winrct.xmin, -region->winrct.ymin);
323 
324  LISTBASE_FOREACH (AZone *, az, &area->actionzones) {
325  /* test if action zone is over this region */
326  rcti azrct;
327  BLI_rcti_init(&azrct, az->x1, az->x2, az->y1, az->y2);
328 
329  if (BLI_rcti_isect(&region->drawrct, &azrct, NULL)) {
330  if (az->type == AZONE_AREA) {
331  area_draw_azone(az->x1, az->y1, az->x2, az->y2);
332  }
333  else if (az->type == AZONE_REGION) {
334  if (az->region) {
335  /* only display tab or icons when the region is hidden */
336  if (az->region->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
337  region_draw_azone_tab_arrow(area, region, az);
338  }
339  }
340  }
341  else if (az->type == AZONE_FULLSCREEN) {
342  if (az->alpha > 0.0f) {
343  area_draw_azone_fullscreen(az->x1, az->y1, az->x2, az->y2, az->alpha);
344  }
345  }
346  }
347  if (!IS_EQF(az->alpha, 0.0f) && ELEM(az->type, AZONE_FULLSCREEN, AZONE_REGION_SCROLL)) {
349  }
350  }
351 
352  GPU_matrix_pop();
353 
355 }
356 
358 {
359  bool overlap = ED_region_is_overlap(area->spacetype, region->regiontype);
360 
361  if (overlap) {
362  GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f);
363  }
364  else {
366  }
367 
368  int fontid = BLF_set_default();
369 
370  const float width = BLF_width(fontid, region->headerstr, BLF_DRAW_STR_DUMMY_MAX);
371  const float x = UI_UNIT_X;
372  const float y = 0.4f * UI_UNIT_Y;
373 
374  if (overlap) {
375  const float pad = 2.0f * UI_DPI_FAC;
376  const float x1 = x - (UI_UNIT_X - pad);
377  const float x2 = x + width + (UI_UNIT_X - pad);
378  const float y1 = pad;
379  const float y2 = region->winy - pad;
380 
382 
383  float color[4] = {0.0f, 0.0f, 0.0f, 0.5f};
387  &(const rctf){
388  .xmin = x1,
389  .xmax = x2,
390  .ymin = y1,
391  .ymax = y2,
392  },
393  true,
394  4.0f,
395  color);
396 
397  UI_FontThemeColor(fontid, TH_TEXT);
398  }
399  else {
400  UI_FontThemeColor(fontid, TH_TEXT);
401  }
402 
403  BLF_position(fontid, x, y, 0.0f);
404  BLF_draw(fontid, region->headerstr, BLF_DRAW_STR_DUMMY_MAX);
405 }
406 
408  /* Follow wmMsgNotifyFn spec */
409  bContext *UNUSED(C),
410  wmMsgSubscribeKey *UNUSED(msg_key),
411  wmMsgSubscribeValue *msg_val)
412 {
413  ARegion *region = msg_val->owner;
414  ED_region_tag_redraw(region);
415 
416  /* This avoids _many_ situations where header/properties control display settings.
417  * the common case is space properties in the header */
419  while (region && region->prev) {
420  region = region->prev;
421  }
422  for (; region; region = region->next) {
424  ED_region_tag_redraw(region);
425  }
426  }
427  }
428 }
429 
431  /* Follow wmMsgNotifyFn spec */
432  bContext *UNUSED(C),
433  wmMsgSubscribeKey *UNUSED(msg_key),
434  wmMsgSubscribeValue *msg_val)
435 {
436  ScrArea *area = msg_val->user_data;
438 }
439 
440 /* Follow ARegionType.message_subscribe */
442 {
443  struct wmMsgBus *mbus = params->message_bus;
444  WorkSpace *workspace = params->workspace;
445  ARegion *region = params->region;
446 
448  wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
449  .owner = region,
450  .user_data = region,
452  };
454  mbus, &workspace->id, workspace, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
455 }
456 
458 {
459  struct wmMsgBus *mbus = params->message_bus;
460  WorkSpace *workspace = params->workspace;
461  ARegion *region = params->region;
462 
463  BLI_assert(region->regiontype == RGN_TYPE_UI);
464  const char *panel_category_tool = "Tool";
465  const char *category = UI_panel_category_active_get(region, false);
466 
467  bool update_region = false;
468  if (category && STREQ(category, panel_category_tool)) {
469  update_region = true;
470  }
471  else {
472  /* Check if a tool category panel is pinned and visible in another category. */
473  LISTBASE_FOREACH (Panel *, panel, &region->panels) {
474  if (UI_panel_is_active(panel) && panel->flag & PNL_PIN &&
475  STREQ(panel->type->category, panel_category_tool)) {
476  update_region = true;
477  break;
478  }
479  }
480  }
481 
482  if (update_region) {
483  wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
484  .owner = region,
485  .user_data = region,
487  };
489  mbus, &workspace->id, workspace, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
490  }
491 }
492 
500 {
501  return (area->winx < 3) || (area->winy < 3);
502 }
503 
504 /* only exported for WM */
506 {
507  /* This is optional, only needed for dynamically sized regions. */
509  ARegionType *at = region->type;
510 
511  if (!at->layout) {
512  return;
513  }
514 
515  if (at->do_lock || (area && area_is_pseudo_minimized(area))) {
516  return;
517  }
518 
519  region->do_draw |= RGN_DRAWING;
520 
521  UI_SetTheme(area ? area->spacetype : 0, at->regionid);
522  at->layout(C, region);
523 
524  /* Clear temporary update flag. */
526 }
527 
528 /* only exported for WM */
530 {
531  wmWindow *win = CTX_wm_window(C);
533  ARegionType *at = region->type;
534 
535  /* see BKE_spacedata_draw_locks() */
536  if (at->do_lock) {
537  return;
538  }
539 
540  region->do_draw |= RGN_DRAWING;
541 
542  /* Set viewport, scissor, ortho and region->drawrct. */
543  wmPartialViewport(&region->drawrct, &region->winrct, &region->drawrct);
544 
546 
547  UI_SetTheme(area ? area->spacetype : 0, at->regionid);
548 
551  return;
552  }
553  /* optional header info instead? */
554  if (region->headerstr) {
555  region_draw_status_text(area, region);
556  }
557  else if (at->draw) {
558  at->draw(C, region);
559  }
560 
561  /* XXX test: add convention to end regions always in pixel space,
562  * for drawing of borders/gestures etc */
563  ED_region_pixelspace(region);
564 
565  /* Remove sRGB override by rebinding the framebuffer. */
568 
570 
571  region_draw_azones(area, region);
572 
573  /* for debugging unneeded area redraws and partial redraw */
574  if (G.debug_value == 888) {
580  immRectf(pos,
581  region->drawrct.xmin - region->winrct.xmin,
582  region->drawrct.ymin - region->winrct.ymin,
583  region->drawrct.xmax - region->winrct.xmin,
584  region->drawrct.ymax - region->winrct.ymin);
587  }
588 
589  memset(&region->drawrct, 0, sizeof(region->drawrct));
590 
592 
593  if (area) {
594  const bScreen *screen = WM_window_get_active_screen(win);
595 
596  /* Only region emboss for top-bar */
597  if ((screen->state != SCREENFULL) && ED_area_is_global(area)) {
599  }
600  else if ((region->regiontype == RGN_TYPE_WINDOW) && (region->alignment == RGN_ALIGN_QSPLIT)) {
601 
602  /* draw separating lines between the quad views */
603 
604  float color[4] = {0.0f, 0.0f, 0.0f, 0.8f};
609  immUniformColor4fv(color);
610  GPU_line_width(1.0f);
612  0,
613  0,
614  region->winrct.xmax - region->winrct.xmin + 1,
615  region->winrct.ymax - region->winrct.ymin + 1);
617  }
618  }
619 
620  /* We may want to detach message-subscriptions from drawing. */
621  {
622  WorkSpace *workspace = CTX_wm_workspace(C);
624  bScreen *screen = WM_window_get_active_screen(win);
626  struct wmMsgBus *mbus = wm->message_bus;
627  WM_msgbus_clear_by_owner(mbus, region);
628 
629  /* Cheat, always subscribe to this space type properties.
630  *
631  * This covers most cases and avoids copy-paste similar code for each space type.
632  */
633  if (ELEM(
635  SpaceLink *sl = area->spacedata.first;
636 
637  PointerRNA ptr;
638  RNA_pointer_create(&screen->id, &RNA_Space, sl, &ptr);
639 
640  wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
641  .owner = region,
642  .user_data = region,
644  };
645  /* All properties for this space type. */
646  WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_region_tag_redraw, __func__);
647  }
648 
649  wmRegionMessageSubscribeParams message_subscribe_params = {
650  .context = C,
651  .message_bus = mbus,
652  .workspace = workspace,
653  .scene = scene,
654  .screen = screen,
655  .area = area,
656  .region = region,
657  };
658  ED_region_message_subscribe(&message_subscribe_params);
659  }
660 }
661 
662 /* **********************************
663  * maybe silly, but let's try for now
664  * to keep these tags protected
665  * ********************************** */
666 
668 {
669  /* don't tag redraw while drawing, it shouldn't happen normally
670  * but python scripts can cause this to happen indirectly */
671  if (region && !(region->do_draw & RGN_DRAWING)) {
672  /* zero region means full region redraw */
674  region->do_draw |= RGN_DRAW;
675  memset(&region->drawrct, 0, sizeof(region->drawrct));
676  }
677 }
678 
680 {
681  if (region) {
682  region->do_draw_paintcursor = RGN_DRAW;
683  }
684 }
685 
687 {
688  if (region && !(region->do_draw & (RGN_DRAWING | RGN_DRAW))) {
690  region->do_draw |= RGN_DRAW_NO_REBUILD;
691  memset(&region->drawrct, 0, sizeof(region->drawrct));
692  }
693 }
694 
696 {
697  if (region) {
698  region->do_draw |= RGN_REFRESH_UI;
699  }
700 }
701 
707 {
708  if (region && !(region->do_draw & (RGN_DRAWING | RGN_DRAW))) {
709  if (region->do_draw & RGN_DRAW_PARTIAL) {
710  ED_region_tag_redraw(region);
711  }
712  else {
714  }
715  }
716 }
717 
718 void ED_region_tag_redraw_partial(ARegion *region, const rcti *rct, bool rebuild)
719 {
720  if (region && !(region->do_draw & RGN_DRAWING)) {
721  if (region->do_draw & RGN_DRAW_PARTIAL) {
722  /* Partial redraw already set, expand region. */
723  BLI_rcti_union(&region->drawrct, rct);
724  if (rebuild) {
725  region->do_draw &= ~RGN_DRAW_NO_REBUILD;
726  }
727  }
728  else if (region->do_draw & (RGN_DRAW | RGN_DRAW_NO_REBUILD)) {
729  /* Full redraw already requested. */
730  if (rebuild) {
731  region->do_draw &= ~RGN_DRAW_NO_REBUILD;
732  }
733  }
734  else {
735  /* No redraw set yet, set partial region. */
736  region->drawrct = *rct;
737  region->do_draw |= RGN_DRAW_PARTIAL;
738  if (!rebuild) {
739  region->do_draw |= RGN_DRAW_NO_REBUILD;
740  }
741  }
742  }
743 }
744 
746 {
747  if (area) {
748  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
749  ED_region_tag_redraw(region);
750  }
751  }
752 }
753 
755 {
756  if (area) {
757  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
759  }
760  }
761 }
762 
764 {
765  if (area) {
766  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
767  if (region->regiontype == regiontype) {
768  ED_region_tag_redraw(region);
769  }
770  }
771  }
772 }
773 
775 {
776  if (area) {
777  area->do_refresh = true;
778  }
779 }
780 
781 /* *************************************************************** */
782 
786 const char *ED_area_region_search_filter_get(const ScrArea *area, const ARegion *region)
787 {
788  /* Only the properties editor has a search string for now. */
789  if (area->spacetype == SPACE_PROPERTIES) {
790  SpaceProperties *sbuts = area->spacedata.first;
791  if (region->regiontype == RGN_TYPE_WINDOW) {
792  return ED_buttons_search_string_get(sbuts);
793  }
794  }
795 
796  return NULL;
797 }
798 
803 {
805 
806  const char *search_filter = ED_area_region_search_filter_get(area, region);
807  SET_FLAG_FROM_TEST(region->flag,
808  region->regiontype == RGN_TYPE_WINDOW && search_filter[0] != '\0',
810 }
811 
812 /* *************************************************************** */
813 
814 /* use NULL to disable it */
815 void ED_area_status_text(ScrArea *area, const char *str)
816 {
817  /* happens when running transform operators in background mode */
818  if (area == NULL) {
819  return;
820  }
821 
822  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
823  if (region->regiontype == RGN_TYPE_HEADER) {
824  if (str) {
825  if (region->headerstr == NULL) {
826  region->headerstr = MEM_mallocN(UI_MAX_DRAW_STR, "headerprint");
827  }
828  BLI_strncpy(region->headerstr, str, UI_MAX_DRAW_STR);
829  BLI_str_rstrip(region->headerstr);
830  }
831  else if (region->headerstr) {
832  MEM_freeN(region->headerstr);
833  region->headerstr = NULL;
834  }
835  ED_region_tag_redraw(region);
836  }
837  }
838 }
839 
841 {
842  wmWindow *win = CTX_wm_window(C);
843  WorkSpace *workspace = CTX_wm_workspace(C);
844 
845  /* Can be NULL when running operators in background mode. */
846  if (workspace == NULL) {
847  return;
848  }
849 
850  if (str) {
851  if (workspace->status_text == NULL) {
852  workspace->status_text = MEM_mallocN(UI_MAX_DRAW_STR, "headerprint");
853  }
855  }
856  else if (workspace->status_text) {
857  MEM_freeN(workspace->status_text);
858  workspace->status_text = NULL;
859  }
860 
861  /* Redraw status bar. */
863  if (area->spacetype == SPACE_STATUSBAR) {
865  break;
866  }
867  }
868 }
869 
870 /* ************************************************************ */
871 
872 static void area_azone_init(wmWindow *win, const bScreen *screen, ScrArea *area)
873 {
874  /* reinitialize entirely, regions and fullscreen add azones too */
875  BLI_freelistN(&area->actionzones);
876 
877  if (screen->state != SCREENNORMAL) {
878  return;
879  }
880 
881  if (U.app_flag & USER_APP_LOCK_UI_LAYOUT) {
882  return;
883  }
884 
885  if (ED_area_is_global(area)) {
886  return;
887  }
888 
889  if (screen->temp) {
890  return;
891  }
892 
893  const float coords[4][4] = {
894  /* Bottom-left. */
895  {area->totrct.xmin - U.pixelsize,
896  area->totrct.ymin - U.pixelsize,
897  area->totrct.xmin + AZONESPOTW,
898  area->totrct.ymin + AZONESPOTH},
899  /* Bottom-right. */
900  {area->totrct.xmax - AZONESPOTW,
901  area->totrct.ymin - U.pixelsize,
902  area->totrct.xmax + U.pixelsize,
903  area->totrct.ymin + AZONESPOTH},
904  /* Top-left. */
905  {area->totrct.xmin - U.pixelsize,
906  area->totrct.ymax - AZONESPOTH,
907  area->totrct.xmin + AZONESPOTW,
908  area->totrct.ymax + U.pixelsize},
909  /* Top-right. */
910  {area->totrct.xmax - AZONESPOTW,
911  area->totrct.ymax - AZONESPOTH,
912  area->totrct.xmax + U.pixelsize,
913  area->totrct.ymax + U.pixelsize},
914  };
915 
916  for (int i = 0; i < 4; i++) {
917  /* can't click on bottom corners on OS X, already used for resizing */
918 #ifdef __APPLE__
919  if (!WM_window_is_fullscreen(win) &&
920  ((coords[i][0] == 0 && coords[i][1] == 0) ||
921  (coords[i][0] == WM_window_pixels_x(win) && coords[i][1] == 0))) {
922  continue;
923  }
924 #else
925  (void)win;
926 #endif
927 
928  /* set area action zones */
929  AZone *az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
930  BLI_addtail(&(area->actionzones), az);
931  az->type = AZONE_AREA;
932  az->x1 = coords[i][0];
933  az->y1 = coords[i][1];
934  az->x2 = coords[i][2];
935  az->y2 = coords[i][3];
936  BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
937  }
938 }
939 
941 {
942  if (ED_area_is_global(area) || (region->regiontype != RGN_TYPE_WINDOW)) {
943  return;
944  }
945 
946  AZone *az = (AZone *)MEM_callocN(sizeof(AZone), "fullscreen action zone");
947  BLI_addtail(&(area->actionzones), az);
948  az->type = AZONE_FULLSCREEN;
949  az->region = region;
950  az->alpha = 0.0f;
951 
952  if (U.uiflag2 & USER_REGION_OVERLAP) {
953  const rcti *rect_visible = ED_region_visible_rect(region);
954  az->x2 = region->winrct.xmin + rect_visible->xmax;
955  az->y2 = region->winrct.ymin + rect_visible->ymax;
956  }
957  else {
958  az->x2 = region->winrct.xmax;
959  az->y2 = region->winrct.ymax;
960  }
961  az->x1 = az->x2 - AZONEFADEOUT;
962  az->y1 = az->y2 - AZONEFADEOUT;
963 
964  BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
965 }
966 
967 #define AZONEPAD_EDGE (0.1f * U.widget_unit)
968 #define AZONEPAD_ICON (0.45f * U.widget_unit)
969 static void region_azone_edge(AZone *az, ARegion *region)
970 {
971  switch (az->edge) {
973  az->x1 = region->winrct.xmin;
974  az->y1 = region->winrct.ymax - AZONEPAD_EDGE;
975  az->x2 = region->winrct.xmax;
976  az->y2 = region->winrct.ymax + AZONEPAD_EDGE;
977  break;
979  az->x1 = region->winrct.xmin;
980  az->y1 = region->winrct.ymin + AZONEPAD_EDGE;
981  az->x2 = region->winrct.xmax;
982  az->y2 = region->winrct.ymin - AZONEPAD_EDGE;
983  break;
984  case AE_LEFT_TO_TOPRIGHT:
985  az->x1 = region->winrct.xmin - AZONEPAD_EDGE;
986  az->y1 = region->winrct.ymin;
987  az->x2 = region->winrct.xmin + AZONEPAD_EDGE;
988  az->y2 = region->winrct.ymax;
989  break;
990  case AE_RIGHT_TO_TOPLEFT:
991  az->x1 = region->winrct.xmax + AZONEPAD_EDGE;
992  az->y1 = region->winrct.ymin;
993  az->x2 = region->winrct.xmax - AZONEPAD_EDGE;
994  az->y2 = region->winrct.ymax;
995  break;
996  }
997  BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
998 }
999 
1000 /* region already made zero sized, in shape of edge */
1001 static void region_azone_tab_plus(ScrArea *area, AZone *az, ARegion *region)
1002 {
1003  float edge_offset = 1.0f;
1004  const float tab_size_x = 0.7f * U.widget_unit;
1005  const float tab_size_y = 0.4f * U.widget_unit;
1006 
1007  int tot = 0;
1008  LISTBASE_FOREACH (AZone *, azt, &area->actionzones) {
1009  if (azt->edge == az->edge) {
1010  tot++;
1011  }
1012  }
1013 
1014  switch (az->edge) {
1015  case AE_TOP_TO_BOTTOMRIGHT: {
1016  int add = (region->winrct.ymax == area->totrct.ymin) ? 1 : 0;
1017  az->x1 = region->winrct.xmax - ((edge_offset + 1.0f) * tab_size_x);
1018  az->y1 = region->winrct.ymax - add;
1019  az->x2 = region->winrct.xmax - (edge_offset * tab_size_x);
1020  az->y2 = region->winrct.ymax - add + tab_size_y;
1021  break;
1022  }
1023  case AE_BOTTOM_TO_TOPLEFT:
1024  az->x1 = region->winrct.xmax - ((edge_offset + 1.0f) * tab_size_x);
1025  az->y1 = region->winrct.ymin - tab_size_y;
1026  az->x2 = region->winrct.xmax - (edge_offset * tab_size_x);
1027  az->y2 = region->winrct.ymin;
1028  break;
1029  case AE_LEFT_TO_TOPRIGHT:
1030  az->x1 = region->winrct.xmin - tab_size_y;
1031  az->y1 = region->winrct.ymax - ((edge_offset + 1.0f) * tab_size_x);
1032  az->x2 = region->winrct.xmin;
1033  az->y2 = region->winrct.ymax - (edge_offset * tab_size_x);
1034  break;
1035  case AE_RIGHT_TO_TOPLEFT:
1036  az->x1 = region->winrct.xmax;
1037  az->y1 = region->winrct.ymax - ((edge_offset + 1.0f) * tab_size_x);
1038  az->x2 = region->winrct.xmax + tab_size_y;
1039  az->y2 = region->winrct.ymax - (edge_offset * tab_size_x);
1040  break;
1041  }
1042  /* rect needed for mouse pointer test */
1043  BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
1044 }
1045 
1046 static bool region_azone_edge_poll(const ARegion *region, const bool is_fullscreen)
1047 {
1048  const bool is_hidden = (region->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL));
1049 
1050  if (is_hidden && is_fullscreen) {
1051  return false;
1052  }
1053  if (!is_hidden && ELEM(region->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
1054  return false;
1055  }
1056 
1057  return true;
1058 }
1059 
1061  ARegion *region,
1062  AZEdge edge,
1063  const bool is_fullscreen)
1064 {
1065  const bool is_hidden = (region->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL));
1066 
1067  if (!region_azone_edge_poll(region, is_fullscreen)) {
1068  return;
1069  }
1070 
1071  AZone *az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
1072  BLI_addtail(&(area->actionzones), az);
1073  az->type = AZONE_REGION;
1074  az->region = region;
1075  az->edge = edge;
1076 
1077  if (is_hidden) {
1078  region_azone_tab_plus(area, az, region);
1079  }
1080  else {
1081  region_azone_edge(az, region);
1082  }
1083 }
1084 
1086  ARegion *region,
1087  AZScrollDirection direction)
1088 {
1089  rcti scroller_vert = (direction == AZ_SCROLL_VERT) ? region->v2d.vert : region->v2d.hor;
1090  AZone *az = MEM_callocN(sizeof(*az), __func__);
1091 
1092  BLI_addtail(&area->actionzones, az);
1093  az->type = AZONE_REGION_SCROLL;
1094  az->region = region;
1095  az->direction = direction;
1096 
1097  if (direction == AZ_SCROLL_VERT) {
1098  az->region->v2d.alpha_vert = 0;
1099  }
1100  else if (direction == AZ_SCROLL_HOR) {
1101  az->region->v2d.alpha_hor = 0;
1102  }
1103 
1104  BLI_rcti_translate(&scroller_vert, region->winrct.xmin, region->winrct.ymin);
1105  az->x1 = scroller_vert.xmin - AZONEFADEIN;
1106  az->y1 = scroller_vert.ymin - AZONEFADEIN;
1107  az->x2 = scroller_vert.xmax + AZONEFADEIN;
1108  az->y2 = scroller_vert.ymax + AZONEFADEIN;
1109 
1110  BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
1111 }
1112 
1114 {
1115  const View2D *v2d = &region->v2d;
1116 
1117  if ((v2d->scroll & V2D_SCROLL_VERTICAL) && ((v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) == 0)) {
1119  }
1120  if ((v2d->scroll & V2D_SCROLL_HORIZONTAL) &&
1121  ((v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) == 0)) {
1123  }
1124 }
1125 
1126 /* *************************************************************** */
1128  ARegion *region,
1129  const int alignment,
1130  const bool is_fullscreen)
1131 {
1132 
1133  /* edge code (t b l r) is along which area edge azone will be drawn */
1134  if (alignment == RGN_ALIGN_TOP) {
1135  region_azone_edge_init(area, region, AE_BOTTOM_TO_TOPLEFT, is_fullscreen);
1136  }
1137  else if (alignment == RGN_ALIGN_BOTTOM) {
1138  region_azone_edge_init(area, region, AE_TOP_TO_BOTTOMRIGHT, is_fullscreen);
1139  }
1140  else if (alignment == RGN_ALIGN_RIGHT) {
1141  region_azone_edge_init(area, region, AE_LEFT_TO_TOPRIGHT, is_fullscreen);
1142  }
1143  else if (alignment == RGN_ALIGN_LEFT) {
1144  region_azone_edge_init(area, region, AE_RIGHT_TO_TOPLEFT, is_fullscreen);
1145  }
1146 }
1147 
1148 static void region_azones_add(const bScreen *screen, ScrArea *area, ARegion *region)
1149 {
1150  const bool is_fullscreen = screen->state == SCREENFULL;
1151 
1152  /* Only display tab or icons when the header region is hidden
1153  * (not the tool header - they overlap). */
1154  if (region->regiontype == RGN_TYPE_TOOL_HEADER) {
1155  return;
1156  }
1157 
1158  region_azones_add_edge(area, region, RGN_ALIGN_ENUM_FROM_MASK(region->alignment), is_fullscreen);
1159 
1160  /* For a split region also continue the azone edge from the next region if this region is aligned
1161  * with the next */
1162  if ((region->alignment & RGN_SPLIT_PREV) && region->prev) {
1164  area, region, RGN_ALIGN_ENUM_FROM_MASK(region->prev->alignment), is_fullscreen);
1165  }
1166 
1167  if (is_fullscreen) {
1168  fullscreen_azone_init(area, region);
1169  }
1170 
1172 }
1173 
1174 /* dir is direction to check, not the splitting edge direction! */
1175 static int rct_fits(const rcti *rect, char dir, int size)
1176 {
1177  if (dir == 'h') {
1178  return BLI_rcti_size_x(rect) + 1 - size;
1179  }
1180  /* 'v' */
1181  return BLI_rcti_size_y(rect) + 1 - size;
1182 }
1183 
1184 /* *************************************************************** */
1185 
1186 /* region should be overlapping */
1187 /* function checks if some overlapping region was defined before - on same place */
1188 static void region_overlap_fix(ScrArea *area, ARegion *region)
1189 {
1190  /* find overlapping previous region on same place */
1191  ARegion *region_iter;
1192  int align1 = 0;
1193  const int align = RGN_ALIGN_ENUM_FROM_MASK(region->alignment);
1194  for (region_iter = region->prev; region_iter; region_iter = region_iter->prev) {
1195  if (region_iter->flag & RGN_FLAG_HIDDEN) {
1196  continue;
1197  }
1198 
1199  if (region_iter->overlap && ((region_iter->alignment & RGN_SPLIT_PREV) == 0)) {
1200  if (ELEM(region_iter->alignment, RGN_ALIGN_FLOAT)) {
1201  continue;
1202  }
1203  align1 = region_iter->alignment;
1204  if (BLI_rcti_isect(&region_iter->winrct, &region->winrct, NULL)) {
1205  if (align1 != align) {
1206  /* Left overlapping right or vice-versa, forbid this! */
1207  region->flag |= RGN_FLAG_TOO_SMALL;
1208  return;
1209  }
1210  /* Else, we have our previous region on same side. */
1211  break;
1212  }
1213  }
1214  }
1215 
1216  /* Guard against flags slipping through that would have to be masked out in usages below. */
1217  BLI_assert(align1 == RGN_ALIGN_ENUM_FROM_MASK(align1));
1218 
1219  /* translate or close */
1220  if (region_iter) {
1221  if (align1 == RGN_ALIGN_LEFT) {
1222  if (region->winrct.xmax + region_iter->winx > area->winx - U.widget_unit) {
1223  region->flag |= RGN_FLAG_TOO_SMALL;
1224  return;
1225  }
1226  BLI_rcti_translate(&region->winrct, region_iter->winx, 0);
1227  }
1228  else if (align1 == RGN_ALIGN_RIGHT) {
1229  if (region->winrct.xmin - region_iter->winx < U.widget_unit) {
1230  region->flag |= RGN_FLAG_TOO_SMALL;
1231  return;
1232  }
1233  BLI_rcti_translate(&region->winrct, -region_iter->winx, 0);
1234  }
1235  }
1236 
1237  /* At this point, 'region' is in its final position and still open.
1238  * Make a final check it does not overlap any previous 'other side' region. */
1239  for (region_iter = region->prev; region_iter; region_iter = region_iter->prev) {
1240  if (region_iter->flag & RGN_FLAG_HIDDEN) {
1241  continue;
1242  }
1243  if (ELEM(region_iter->alignment, RGN_ALIGN_FLOAT)) {
1244  continue;
1245  }
1246 
1247  if (region_iter->overlap && (region_iter->alignment & RGN_SPLIT_PREV) == 0) {
1248  if ((region_iter->alignment != align) &&
1249  BLI_rcti_isect(&region_iter->winrct, &region->winrct, NULL)) {
1250  /* Left overlapping right or vice-versa, forbid this! */
1251  region->flag |= RGN_FLAG_TOO_SMALL;
1252  return;
1253  }
1254  }
1255  }
1256 }
1257 
1258 /* overlapping regions only in the following restricted cases */
1259 bool ED_region_is_overlap(int spacetype, int regiontype)
1260 {
1261  if (regiontype == RGN_TYPE_HUD) {
1262  return true;
1263  }
1264  if (U.uiflag2 & USER_REGION_OVERLAP) {
1265  if (spacetype == SPACE_NODE) {
1266  if (regiontype == RGN_TYPE_TOOLS) {
1267  return true;
1268  }
1269  }
1270  else if (ELEM(spacetype, SPACE_VIEW3D, SPACE_IMAGE)) {
1271  if (ELEM(regiontype,
1273  RGN_TYPE_UI,
1276  RGN_TYPE_FOOTER)) {
1277  return true;
1278  }
1279  }
1280  }
1281 
1282  return false;
1283 }
1284 
1286  ScrArea *area, ARegion *region, rcti *remainder, rcti *overlap_remainder, int quad)
1287 {
1288  rcti *remainder_prev = remainder;
1289 
1290  if (region == NULL) {
1291  return;
1292  }
1293 
1294  int prev_winx = region->winx;
1295  int prev_winy = region->winy;
1296 
1297  /* no returns in function, winrct gets set in the end again */
1298  BLI_rcti_init(&region->winrct, 0, 0, 0, 0);
1299 
1300  /* for test; allow split of previously defined region */
1301  if (region->alignment & RGN_SPLIT_PREV) {
1302  if (region->prev) {
1303  remainder = &region->prev->winrct;
1304  }
1305  }
1306 
1307  int alignment = RGN_ALIGN_ENUM_FROM_MASK(region->alignment);
1308 
1309  /* set here, assuming userpref switching forces to call this again */
1310  region->overlap = ED_region_is_overlap(area->spacetype, region->regiontype);
1311 
1312  /* clear state flags first */
1314  /* user errors */
1315  if ((region->next == NULL) && !ELEM(alignment, RGN_ALIGN_QSPLIT, RGN_ALIGN_FLOAT)) {
1316  alignment = RGN_ALIGN_NONE;
1317  }
1318 
1319  /* If both the ARegion.sizex/y and the prefsize are 0, the region is tagged as too small, even
1320  * before the layout for dynamic regions is created. #wm_draw_window_offscreen() allows the
1321  * layout to be created despite the RGN_FLAG_TOO_SMALL flag being set. But there may still be
1322  * regions that don't have a separate ARegionType.layout callback. For those, set a default
1323  * prefsize so they can become visible. */
1324  if ((region->flag & RGN_FLAG_DYNAMIC_SIZE) && !(region->type->layout)) {
1325  if ((region->sizex == 0) && (region->type->prefsizex == 0)) {
1326  region->type->prefsizex = AREAMINX;
1327  }
1328  if ((region->sizey == 0) && (region->type->prefsizey == 0)) {
1329  region->type->prefsizey = HEADERY;
1330  }
1331  }
1332 
1333  /* prefsize, taking into account DPI */
1334  int prefsizex = UI_DPI_FAC *
1335  ((region->sizex > 1) ? region->sizex + 0.5f : region->type->prefsizex);
1336  int prefsizey;
1337 
1338  if (region->flag & RGN_FLAG_PREFSIZE_OR_HIDDEN) {
1339  prefsizex = UI_DPI_FAC * region->type->prefsizex;
1340  prefsizey = UI_DPI_FAC * region->type->prefsizey;
1341  }
1342  else if (region->regiontype == RGN_TYPE_HEADER) {
1343  prefsizey = ED_area_headersize();
1344  }
1345  else if (region->regiontype == RGN_TYPE_TOOL_HEADER) {
1346  prefsizey = ED_area_headersize();
1347  }
1348  else if (region->regiontype == RGN_TYPE_FOOTER) {
1349  prefsizey = ED_area_footersize();
1350  }
1351  else if (ED_area_is_global(area)) {
1352  prefsizey = ED_region_global_size_y();
1353  }
1354  else {
1355  prefsizey = UI_DPI_FAC * (region->sizey > 1 ? region->sizey + 0.5f : region->type->prefsizey);
1356  }
1357 
1358  if (region->flag & RGN_FLAG_HIDDEN) {
1359  /* hidden is user flag */
1360  }
1361  else if (alignment == RGN_ALIGN_FLOAT) {
1368  const int size_min[2] = {UI_UNIT_X, UI_UNIT_Y};
1369  rcti overlap_remainder_margin = *overlap_remainder;
1370 
1371  BLI_rcti_resize(&overlap_remainder_margin,
1372  max_ii(0, BLI_rcti_size_x(overlap_remainder) - UI_UNIT_X / 2),
1373  max_ii(0, BLI_rcti_size_y(overlap_remainder) - UI_UNIT_Y / 2));
1374  region->winrct.xmin = overlap_remainder_margin.xmin + region->runtime.offset_x;
1375  region->winrct.ymin = overlap_remainder_margin.ymin + region->runtime.offset_y;
1376  region->winrct.xmax = region->winrct.xmin + prefsizex - 1;
1377  region->winrct.ymax = region->winrct.ymin + prefsizey - 1;
1378 
1379  BLI_rcti_isect(&region->winrct, &overlap_remainder_margin, &region->winrct);
1380 
1381  if (BLI_rcti_size_x(&region->winrct) != prefsizex - 1) {
1382  region->flag |= RGN_FLAG_SIZE_CLAMP_X;
1383  }
1384  if (BLI_rcti_size_y(&region->winrct) != prefsizey - 1) {
1385  region->flag |= RGN_FLAG_SIZE_CLAMP_Y;
1386  }
1387 
1388  /* We need to use a test that wont have been previously clamped. */
1389  rcti winrct_test = {
1390  .xmin = region->winrct.xmin,
1391  .ymin = region->winrct.ymin,
1392  .xmax = region->winrct.xmin + size_min[0],
1393  .ymax = region->winrct.ymin + size_min[1],
1394  };
1395  BLI_rcti_isect(&winrct_test, &overlap_remainder_margin, &winrct_test);
1396  if (BLI_rcti_size_x(&winrct_test) < size_min[0] ||
1397  BLI_rcti_size_y(&winrct_test) < size_min[1]) {
1398  region->flag |= RGN_FLAG_TOO_SMALL;
1399  }
1400  }
1401  else if (rct_fits(remainder, 'v', 1) < 0 || rct_fits(remainder, 'h', 1) < 0) {
1402  /* remainder is too small for any usage */
1403  region->flag |= RGN_FLAG_TOO_SMALL;
1404  }
1405  else if (alignment == RGN_ALIGN_NONE) {
1406  /* typically last region */
1407  region->winrct = *remainder;
1408  BLI_rcti_init(remainder, 0, 0, 0, 0);
1409  }
1410  else if (ELEM(alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
1411  rcti *winrct = (region->overlap) ? overlap_remainder : remainder;
1412 
1413  if ((prefsizey == 0) || (rct_fits(winrct, 'v', prefsizey) < 0)) {
1414  region->flag |= RGN_FLAG_TOO_SMALL;
1415  }
1416  else {
1417  int fac = rct_fits(winrct, 'v', prefsizey);
1418 
1419  if (fac < 0) {
1420  prefsizey += fac;
1421  }
1422 
1423  region->winrct = *winrct;
1424 
1425  if (alignment == RGN_ALIGN_TOP) {
1426  region->winrct.ymin = region->winrct.ymax - prefsizey + 1;
1427  winrct->ymax = region->winrct.ymin - 1;
1428  }
1429  else {
1430  region->winrct.ymax = region->winrct.ymin + prefsizey - 1;
1431  winrct->ymin = region->winrct.ymax + 1;
1432  }
1433  BLI_rcti_sanitize(winrct);
1434  }
1435  }
1436  else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
1437  rcti *winrct = (region->overlap) ? overlap_remainder : remainder;
1438 
1439  if ((prefsizex == 0) || (rct_fits(winrct, 'h', prefsizex) < 0)) {
1440  region->flag |= RGN_FLAG_TOO_SMALL;
1441  }
1442  else {
1443  int fac = rct_fits(winrct, 'h', prefsizex);
1444 
1445  if (fac < 0) {
1446  prefsizex += fac;
1447  }
1448 
1449  region->winrct = *winrct;
1450 
1451  if (alignment == RGN_ALIGN_RIGHT) {
1452  region->winrct.xmin = region->winrct.xmax - prefsizex + 1;
1453  winrct->xmax = region->winrct.xmin - 1;
1454  }
1455  else {
1456  region->winrct.xmax = region->winrct.xmin + prefsizex - 1;
1457  winrct->xmin = region->winrct.xmax + 1;
1458  }
1459  BLI_rcti_sanitize(winrct);
1460  }
1461  }
1462  else if (ELEM(alignment, RGN_ALIGN_VSPLIT, RGN_ALIGN_HSPLIT)) {
1463  /* percentage subdiv*/
1464  region->winrct = *remainder;
1465 
1466  if (alignment == RGN_ALIGN_HSPLIT) {
1467  if (rct_fits(remainder, 'h', prefsizex) > 4) {
1468  region->winrct.xmax = BLI_rcti_cent_x(remainder);
1469  remainder->xmin = region->winrct.xmax + 1;
1470  }
1471  else {
1472  BLI_rcti_init(remainder, 0, 0, 0, 0);
1473  }
1474  }
1475  else {
1476  if (rct_fits(remainder, 'v', prefsizey) > 4) {
1477  region->winrct.ymax = BLI_rcti_cent_y(remainder);
1478  remainder->ymin = region->winrct.ymax + 1;
1479  }
1480  else {
1481  BLI_rcti_init(remainder, 0, 0, 0, 0);
1482  }
1483  }
1484  }
1485  else if (alignment == RGN_ALIGN_QSPLIT) {
1486  region->winrct = *remainder;
1487 
1488  /* test if there's still 4 regions left */
1489  if (quad == 0) {
1490  ARegion *region_test = region->next;
1491  int count = 1;
1492 
1493  while (region_test) {
1494  region_test->alignment = RGN_ALIGN_QSPLIT;
1495  region_test = region_test->next;
1496  count++;
1497  }
1498 
1499  if (count != 4) {
1500  /* let's stop adding regions */
1501  BLI_rcti_init(remainder, 0, 0, 0, 0);
1502  if (G.debug & G_DEBUG) {
1503  printf("region quadsplit failed\n");
1504  }
1505  }
1506  else {
1507  quad = 1;
1508  }
1509  }
1510  if (quad) {
1511  if (quad == 1) { /* left bottom */
1512  region->winrct.xmax = BLI_rcti_cent_x(remainder);
1513  region->winrct.ymax = BLI_rcti_cent_y(remainder);
1514  }
1515  else if (quad == 2) { /* left top */
1516  region->winrct.xmax = BLI_rcti_cent_x(remainder);
1517  region->winrct.ymin = BLI_rcti_cent_y(remainder) + 1;
1518  }
1519  else if (quad == 3) { /* right bottom */
1520  region->winrct.xmin = BLI_rcti_cent_x(remainder) + 1;
1521  region->winrct.ymax = BLI_rcti_cent_y(remainder);
1522  }
1523  else { /* right top */
1524  region->winrct.xmin = BLI_rcti_cent_x(remainder) + 1;
1525  region->winrct.ymin = BLI_rcti_cent_y(remainder) + 1;
1526  BLI_rcti_init(remainder, 0, 0, 0, 0);
1527  }
1528 
1529  /* Fix any negative dimensions. This can happen when a quad split 3d view gets to small. (see
1530  * T72200). */
1531  BLI_rcti_sanitize(&region->winrct);
1532 
1533  quad++;
1534  }
1535  }
1536 
1537  /* for speedup */
1538  region->winx = BLI_rcti_size_x(&region->winrct) + 1;
1539  region->winy = BLI_rcti_size_y(&region->winrct) + 1;
1540 
1541  /* if region opened normally, we store this for hide/reveal usage */
1542  /* prevent rounding errors for UI_DPI_FAC mult and divide */
1543  if (region->winx > 1) {
1544  region->sizex = (region->winx + 0.5f) / UI_DPI_FAC;
1545  }
1546  if (region->winy > 1) {
1547  region->sizey = (region->winy + 0.5f) / UI_DPI_FAC;
1548  }
1549 
1550  /* exception for multiple overlapping regions on same spot */
1551  if (region->overlap && (alignment != RGN_ALIGN_FLOAT)) {
1552  region_overlap_fix(area, region);
1553  }
1554 
1555  /* set winrect for azones */
1556  if (region->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
1557  region->winrct = (region->overlap) ? *overlap_remainder : *remainder;
1558 
1559  switch (alignment) {
1560  case RGN_ALIGN_TOP:
1561  region->winrct.ymin = region->winrct.ymax;
1562  break;
1563  case RGN_ALIGN_BOTTOM:
1564  region->winrct.ymax = region->winrct.ymin;
1565  break;
1566  case RGN_ALIGN_RIGHT:
1567  region->winrct.xmin = region->winrct.xmax;
1568  break;
1569  case RGN_ALIGN_LEFT:
1570  region->winrct.xmax = region->winrct.xmin;
1571  break;
1572  default:
1573  /* prevent winrct to be valid */
1574  region->winrct.xmax = region->winrct.xmin;
1575  break;
1576  }
1577 
1578  /* Size on one axis is now 0, the other axis may still be invalid (negative) though. */
1579  BLI_rcti_sanitize(&region->winrct);
1580  }
1581 
1582  /* restore prev-split exception */
1583  if (region->alignment & RGN_SPLIT_PREV) {
1584  if (region->prev) {
1585  remainder = remainder_prev;
1586  region->prev->winx = BLI_rcti_size_x(&region->prev->winrct) + 1;
1587  region->prev->winy = BLI_rcti_size_y(&region->prev->winrct) + 1;
1588  }
1589  }
1590 
1591  /* After non-overlapping region, all following overlapping regions
1592  * fit within the remaining space again. */
1593  if (!region->overlap) {
1594  *overlap_remainder = *remainder;
1595  }
1596 
1597  BLI_assert(BLI_rcti_is_valid(&region->winrct));
1598 
1599  region_rect_recursive(area, region->next, remainder, overlap_remainder, quad);
1600 
1601  /* Tag for redraw if size changes. */
1602  if (region->winx != prev_winx || region->winy != prev_winy) {
1603  /* 3D View needs a full rebuild in case a progressive render runs. Rest can live with
1604  * no-rebuild (e.g. Outliner) */
1605  if (area->spacetype == SPACE_VIEW3D) {
1606  ED_region_tag_redraw(region);
1607  }
1608  else {
1610  }
1611  }
1612 
1613  /* Clear, initialize on demand. */
1614  memset(&region->runtime.visible_rect, 0, sizeof(region->runtime.visible_rect));
1615 }
1616 
1617 static void area_calc_totrct(ScrArea *area, const rcti *window_rect)
1618 {
1619  short px = (short)U.pixelsize;
1620 
1621  area->totrct.xmin = area->v1->vec.x;
1622  area->totrct.xmax = area->v4->vec.x;
1623  area->totrct.ymin = area->v1->vec.y;
1624  area->totrct.ymax = area->v2->vec.y;
1625 
1626  /* scale down totrct by 1 pixel on all sides not matching window borders */
1627  if (area->totrct.xmin > window_rect->xmin) {
1628  area->totrct.xmin += px;
1629  }
1630  if (area->totrct.xmax < (window_rect->xmax - 1)) {
1631  area->totrct.xmax -= px;
1632  }
1633  if (area->totrct.ymin > window_rect->ymin) {
1634  area->totrct.ymin += px;
1635  }
1636  if (area->totrct.ymax < (window_rect->ymax - 1)) {
1637  area->totrct.ymax -= px;
1638  }
1639  /* Although the following asserts are correct they lead to a very unstable Blender.
1640  * And the asserts would fail even in 2.7x
1641  * (they were added in 2.8x as part of the top-bar commit).
1642  * For more details see T54864. */
1643 #if 0
1644  BLI_assert(area->totrct.xmin >= 0);
1645  BLI_assert(area->totrct.xmax >= 0);
1646  BLI_assert(area->totrct.ymin >= 0);
1647  BLI_assert(area->totrct.ymax >= 0);
1648 #endif
1649 
1650  /* for speedup */
1651  area->winx = BLI_rcti_size_x(&area->totrct) + 1;
1652  area->winy = BLI_rcti_size_y(&area->totrct) + 1;
1653 }
1654 
1655 /* used for area initialize below */
1656 static void region_subwindow(ARegion *region)
1657 {
1658  bool hidden = (region->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) != 0;
1659 
1660  if ((region->alignment & RGN_SPLIT_PREV) && region->prev) {
1661  hidden = hidden || (region->prev->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL));
1662  }
1663 
1664  region->visible = !hidden;
1665 }
1666 
1667 static bool event_in_markers_region(const ARegion *region, const wmEvent *event)
1668 {
1669  rcti rect = region->winrct;
1670  rect.ymax = rect.ymin + UI_MARKER_MARGIN_Y;
1671  return BLI_rcti_isect_pt(&rect, event->x, event->y);
1672 }
1673 
1678  wmWindowManager *wm, ScrArea *area, ARegion *region, ListBase *handlers, int flag)
1679 {
1680  BLI_assert(region ? (&region->handlers == handlers) : (&area->handlers == handlers));
1681 
1682  /* note, add-handler checks if it already exists */
1683 
1684  /* XXX it would be good to have boundbox checks for some of these... */
1685  if (flag & ED_KEYMAP_UI) {
1686  wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "User Interface", 0, 0);
1687  WM_event_add_keymap_handler(handlers, keymap);
1688 
1689  /* user interface widgets */
1690  UI_region_handlers_add(handlers);
1691  }
1692  if (flag & ED_KEYMAP_GIZMO) {
1694  if (region) {
1695  /* Anything else is confusing, only allow this. */
1696  BLI_assert(&region->handlers == handlers);
1697  if (region->gizmo_map == NULL) {
1699  &(const struct wmGizmoMapType_Params){area->spacetype, region->type->regionid});
1700  }
1701  WM_gizmomap_add_handlers(region, region->gizmo_map);
1702  }
1703  }
1704  if (flag & ED_KEYMAP_VIEW2D) {
1705  /* 2d-viewport handling+manipulation */
1706  wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D", 0, 0);
1707  WM_event_add_keymap_handler(handlers, keymap);
1708  }
1709  if (flag & ED_KEYMAP_ANIMATION) {
1710  wmKeyMap *keymap;
1711 
1712  /* time-markers */
1713  keymap = WM_keymap_ensure(wm->defaultconf, "Markers", 0, 0);
1715 
1716  /* time-scrub */
1717  keymap = WM_keymap_ensure(wm->defaultconf, "Time Scrub", 0, 0);
1719 
1720  /* frame changing and timeline operators (for time spaces) */
1721  keymap = WM_keymap_ensure(wm->defaultconf, "Animation", 0, 0);
1722  WM_event_add_keymap_handler(handlers, keymap);
1723  }
1724  if (flag & ED_KEYMAP_TOOL) {
1729  }
1730  if (flag & ED_KEYMAP_FRAMES) {
1731  /* frame changing/jumping (for all spaces) */
1732  wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Frames", 0, 0);
1733  WM_event_add_keymap_handler(handlers, keymap);
1734  }
1735  if (flag & ED_KEYMAP_HEADER) {
1736  /* standard keymap for headers regions */
1737  wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Region Context Menu", 0, 0);
1738  WM_event_add_keymap_handler(handlers, keymap);
1739  }
1740  if (flag & ED_KEYMAP_FOOTER) {
1741  /* standard keymap for footer regions */
1742  wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Region Context Menu", 0, 0);
1743  WM_event_add_keymap_handler(handlers, keymap);
1744  }
1745  if (flag & ED_KEYMAP_NAVBAR) {
1746  /* standard keymap for Navigation bar regions */
1747  wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Region Context Menu", 0, 0);
1748  WM_event_add_keymap_handler(&region->handlers, keymap);
1749  }
1750 
1751  /* Keep last because of LMB/RMB handling, see: T57527. */
1752  if (flag & ED_KEYMAP_GPENCIL) {
1753  /* grease pencil */
1754  /* NOTE: This is now 4 keymaps - One for basic functionality,
1755  * and others for special stroke modes (edit, paint and sculpt).
1756  *
1757  * For now, it's easier to just include all,
1758  * since you hardly want one without the others.
1759  */
1760  wmKeyMap *keymap_general = WM_keymap_ensure(wm->defaultconf, "Grease Pencil", 0, 0);
1761  WM_event_add_keymap_handler(handlers, keymap_general);
1762 
1763  wmKeyMap *keymap_curve_edit = WM_keymap_ensure(
1764  wm->defaultconf, "Grease Pencil Stroke Curve Edit Mode", 0, 0);
1765  WM_event_add_keymap_handler(handlers, keymap_curve_edit);
1766 
1767  wmKeyMap *keymap_edit = WM_keymap_ensure(
1768  wm->defaultconf, "Grease Pencil Stroke Edit Mode", 0, 0);
1769  WM_event_add_keymap_handler(handlers, keymap_edit);
1770 
1771  wmKeyMap *keymap_paint = WM_keymap_ensure(
1772  wm->defaultconf, "Grease Pencil Stroke Paint Mode", 0, 0);
1773  WM_event_add_keymap_handler(handlers, keymap_paint);
1774 
1775  wmKeyMap *keymap_paint_draw = WM_keymap_ensure(
1776  wm->defaultconf, "Grease Pencil Stroke Paint (Draw brush)", 0, 0);
1777  WM_event_add_keymap_handler(handlers, keymap_paint_draw);
1778 
1779  wmKeyMap *keymap_paint_erase = WM_keymap_ensure(
1780  wm->defaultconf, "Grease Pencil Stroke Paint (Erase)", 0, 0);
1781  WM_event_add_keymap_handler(handlers, keymap_paint_erase);
1782 
1783  wmKeyMap *keymap_paint_fill = WM_keymap_ensure(
1784  wm->defaultconf, "Grease Pencil Stroke Paint (Fill)", 0, 0);
1785  WM_event_add_keymap_handler(handlers, keymap_paint_fill);
1786 
1787  wmKeyMap *keymap_paint_tint = WM_keymap_ensure(
1788  wm->defaultconf, "Grease Pencil Stroke Paint (Tint)", 0, 0);
1789  WM_event_add_keymap_handler(handlers, keymap_paint_tint);
1790 
1791  wmKeyMap *keymap_sculpt = WM_keymap_ensure(
1792  wm->defaultconf, "Grease Pencil Stroke Sculpt Mode", 0, 0);
1793  WM_event_add_keymap_handler(handlers, keymap_sculpt);
1794 
1795  wmKeyMap *keymap_vertex = WM_keymap_ensure(
1796  wm->defaultconf, "Grease Pencil Stroke Vertex Mode", 0, 0);
1797  WM_event_add_keymap_handler(handlers, keymap_vertex);
1798 
1799  wmKeyMap *keymap_vertex_draw = WM_keymap_ensure(
1800  wm->defaultconf, "Grease Pencil Stroke Vertex (Draw)", 0, 0);
1801  WM_event_add_keymap_handler(handlers, keymap_vertex_draw);
1802 
1803  wmKeyMap *keymap_vertex_blur = WM_keymap_ensure(
1804  wm->defaultconf, "Grease Pencil Stroke Vertex (Blur)", 0, 0);
1805  WM_event_add_keymap_handler(handlers, keymap_vertex_blur);
1806 
1807  wmKeyMap *keymap_vertex_average = WM_keymap_ensure(
1808  wm->defaultconf, "Grease Pencil Stroke Vertex (Average)", 0, 0);
1809  WM_event_add_keymap_handler(handlers, keymap_vertex_average);
1810 
1811  wmKeyMap *keymap_vertex_smear = WM_keymap_ensure(
1812  wm->defaultconf, "Grease Pencil Stroke Vertex (Smear)", 0, 0);
1813  WM_event_add_keymap_handler(handlers, keymap_vertex_smear);
1814 
1815  wmKeyMap *keymap_vertex_replace = WM_keymap_ensure(
1816  wm->defaultconf, "Grease Pencil Stroke Vertex (Replace)", 0, 0);
1817  WM_event_add_keymap_handler(handlers, keymap_vertex_replace);
1818 
1819  wmKeyMap *keymap_sculpt_smooth = WM_keymap_ensure(
1820  wm->defaultconf, "Grease Pencil Stroke Sculpt (Smooth)", 0, 0);
1821  WM_event_add_keymap_handler(handlers, keymap_sculpt_smooth);
1822 
1823  wmKeyMap *keymap_sculpt_thickness = WM_keymap_ensure(
1824  wm->defaultconf, "Grease Pencil Stroke Sculpt (Thickness)", 0, 0);
1825  WM_event_add_keymap_handler(handlers, keymap_sculpt_thickness);
1826 
1827  wmKeyMap *keymap_sculpt_strength = WM_keymap_ensure(
1828  wm->defaultconf, "Grease Pencil Stroke Sculpt (Strength)", 0, 0);
1829  WM_event_add_keymap_handler(handlers, keymap_sculpt_strength);
1830 
1831  wmKeyMap *keymap_sculpt_grab = WM_keymap_ensure(
1832  wm->defaultconf, "Grease Pencil Stroke Sculpt (Grab)", 0, 0);
1833  WM_event_add_keymap_handler(handlers, keymap_sculpt_grab);
1834 
1835  wmKeyMap *keymap_sculpt_push = WM_keymap_ensure(
1836  wm->defaultconf, "Grease Pencil Stroke Sculpt (Push)", 0, 0);
1837  WM_event_add_keymap_handler(handlers, keymap_sculpt_push);
1838 
1839  wmKeyMap *keymap_sculpt_twist = WM_keymap_ensure(
1840  wm->defaultconf, "Grease Pencil Stroke Sculpt (Twist)", 0, 0);
1841  WM_event_add_keymap_handler(handlers, keymap_sculpt_twist);
1842 
1843  wmKeyMap *keymap_sculpt_pinch = WM_keymap_ensure(
1844  wm->defaultconf, "Grease Pencil Stroke Sculpt (Pinch)", 0, 0);
1845  WM_event_add_keymap_handler(handlers, keymap_sculpt_pinch);
1846 
1847  wmKeyMap *keymap_sculpt_randomize = WM_keymap_ensure(
1848  wm->defaultconf, "Grease Pencil Stroke Sculpt (Randomize)", 0, 0);
1849  WM_event_add_keymap_handler(handlers, keymap_sculpt_randomize);
1850 
1851  wmKeyMap *keymap_sculpt_clone = WM_keymap_ensure(
1852  wm->defaultconf, "Grease Pencil Stroke Sculpt (Clone)", 0, 0);
1853  WM_event_add_keymap_handler(handlers, keymap_sculpt_clone);
1854 
1855  wmKeyMap *keymap_weight = WM_keymap_ensure(
1856  wm->defaultconf, "Grease Pencil Stroke Weight Mode", 0, 0);
1857  WM_event_add_keymap_handler(handlers, keymap_weight);
1858 
1859  wmKeyMap *keymap_weight_draw = WM_keymap_ensure(
1860  wm->defaultconf, "Grease Pencil Stroke Weight (Draw)", 0, 0);
1861  WM_event_add_keymap_handler(handlers, keymap_weight_draw);
1862  }
1863 }
1864 
1866 {
1867  if (!(area->flag & AREA_FLAG_REGION_SIZE_UPDATE)) {
1868  return;
1869  }
1870  const bScreen *screen = WM_window_get_active_screen(win);
1871 
1872  rcti window_rect;
1873  WM_window_rect_calc(win, &window_rect);
1874  area_calc_totrct(area, &window_rect);
1875 
1876  /* region rect sizes */
1877  rcti rect = area->totrct;
1878  rcti overlap_rect = rect;
1879  region_rect_recursive(area, area->regionbase.first, &rect, &overlap_rect, 0);
1880 
1881  /* Dynamically sized regions may have changed region sizes, so we have to force azone update. */
1882  area_azone_init(win, screen, area);
1883 
1884  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
1885  region_subwindow(region);
1886 
1887  /* region size may have changed, init does necessary adjustments */
1888  if (region->type->init) {
1889  region->type->init(wm, region);
1890  }
1891 
1892  /* Some AZones use View2D data which is only updated in region init, so call that first! */
1893  region_azones_add(screen, area, region);
1894  }
1896 
1898 }
1899 
1900 bool ED_area_has_shared_border(struct ScrArea *a, struct ScrArea *b)
1901 {
1902  return area_getorientation(a, b) != -1;
1903 }
1904 
1905 /* called in screen_refresh, or screens_init, also area size changes */
1907 {
1908  WorkSpace *workspace = WM_window_get_active_workspace(win);
1910  ViewLayer *view_layer = WM_window_get_active_view_layer(win);
1911 
1912  if (ED_area_is_global(area) && (area->global->flag & GLOBAL_AREA_IS_HIDDEN)) {
1913  return;
1914  }
1915 
1916  rcti window_rect;
1917  WM_window_rect_calc(win, &window_rect);
1918 
1919  /* set typedefinitions */
1920  area->type = BKE_spacetype_from_id(area->spacetype);
1921 
1922  if (area->type == NULL) {
1923  area->spacetype = SPACE_VIEW3D;
1924  area->type = BKE_spacetype_from_id(area->spacetype);
1925  }
1926 
1927  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
1928  region->type = BKE_regiontype_from_id_or_first(area->type, region->regiontype);
1929  }
1930 
1931  /* area sizes */
1932  area_calc_totrct(area, &window_rect);
1933 
1934  /* region rect sizes */
1935  rcti rect = area->totrct;
1936  rcti overlap_rect = rect;
1937  region_rect_recursive(area, area->regionbase.first, &rect, &overlap_rect, 0);
1939 
1940  /* default area handlers */
1941  ed_default_handlers(wm, area, NULL, &area->handlers, area->type->keymapflag);
1942  /* checks spacedata, adds own handlers */
1943  if (area->type->init) {
1944  area->type->init(wm, area);
1945  }
1946 
1947  /* clear all azones, add the area triangle widgets */
1948  area_azone_init(win, screen, area);
1949 
1950  /* region windows, default and own handlers */
1951  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
1952  region_subwindow(region);
1953 
1954  if (region->visible) {
1955  /* default region handlers */
1956  ed_default_handlers(wm, area, region, &region->handlers, region->type->keymapflag);
1957  /* own handlers */
1958  if (region->type->init) {
1959  region->type->init(wm, region);
1960  }
1961  }
1962  else {
1963  /* prevent uiblocks to run */
1964  UI_blocklist_free(NULL, &region->uiblocks);
1965  }
1966 
1967  /* Some AZones use View2D data which is only updated in region init, so call that first! */
1968  region_azones_add(screen, area, region);
1969  }
1970 
1971  /* Avoid re-initializing tools while resizing the window. */
1972  if ((G.moving & G_TRANSFORM_WM) == 0) {
1973  if ((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) {
1974  WM_toolsystem_refresh_screen_area(workspace, view_layer, area);
1976  }
1977  else {
1978  area->runtime.tool = NULL;
1979  area->runtime.is_tool_set = true;
1980  }
1981  }
1982 }
1983 
1984 static void region_update_rect(ARegion *region)
1985 {
1986  region->winx = BLI_rcti_size_x(&region->winrct) + 1;
1987  region->winy = BLI_rcti_size_y(&region->winrct) + 1;
1988 
1989  /* v2d mask is used to subtract scrollbars from a 2d view. Needs initialize here. */
1990  BLI_rcti_init(&region->v2d.mask, 0, region->winx - 1, 0, region->winy - 1);
1991 }
1992 
1997 {
1998  region_update_rect(region);
1999 }
2000 
2001 /* externally called for floating regions like menus */
2003 {
2004  BLI_assert(region->alignment == RGN_ALIGN_FLOAT);
2005 
2006  /* refresh can be called before window opened */
2007  region_subwindow(region);
2008 
2009  region_update_rect(region);
2010 }
2011 
2013 {
2014  if (region != NULL) {
2015  if ((region->gizmo_map != NULL) && WM_gizmomap_cursor_set(region->gizmo_map, win)) {
2016  return;
2017  }
2018  if (area && region->type && region->type->cursor) {
2019  region->type->cursor(win, area, region);
2020  return;
2021  }
2022  }
2023 
2024  if (WM_cursor_set_from_tool(win, area, region)) {
2025  return;
2026  }
2027 
2029 }
2030 
2031 /* for use after changing visibility of regions */
2033 {
2034  if (region->flag & RGN_FLAG_HIDDEN) {
2035  WM_event_remove_handlers(C, &region->handlers);
2036  }
2037 
2040 }
2041 
2042 /* for quick toggle, can skip fades */
2043 void region_toggle_hidden(bContext *C, ARegion *region, const bool do_fade)
2044 {
2045  ScrArea *area = CTX_wm_area(C);
2046 
2047  region->flag ^= RGN_FLAG_HIDDEN;
2048 
2049  if (do_fade && region->overlap) {
2050  /* starts a timer, and in end calls the stuff below itself (region_sblend_invoke()) */
2052  }
2053  else {
2055  }
2056 }
2057 
2058 /* exported to all editors, uses fading default */
2060 {
2061  region_toggle_hidden(C, region, true);
2062 }
2063 
2067 void ED_area_data_copy(ScrArea *area_dst, ScrArea *area_src, const bool do_free)
2068 {
2069  const char spacetype = area_dst->spacetype;
2070  const short flag_copy = HEADER_NO_PULLDOWN;
2071 
2072  area_dst->spacetype = area_src->spacetype;
2073  area_dst->type = area_src->type;
2074 
2075  area_dst->flag = (area_dst->flag & ~flag_copy) | (area_src->flag & flag_copy);
2076 
2077  /* area */
2078  if (do_free) {
2079  BKE_spacedata_freelist(&area_dst->spacedata);
2080  }
2081  BKE_spacedata_copylist(&area_dst->spacedata, &area_src->spacedata);
2082 
2083  /* Note; SPACE_EMPTY is possible on new screens */
2084 
2085  /* regions */
2086  if (do_free) {
2087  SpaceType *st = BKE_spacetype_from_id(spacetype);
2088  LISTBASE_FOREACH (ARegion *, region, &area_dst->regionbase) {
2089  BKE_area_region_free(st, region);
2090  }
2091  BLI_freelistN(&area_dst->regionbase);
2092  }
2093  SpaceType *st = BKE_spacetype_from_id(area_src->spacetype);
2094  LISTBASE_FOREACH (ARegion *, region, &area_src->regionbase) {
2095  ARegion *newar = BKE_area_region_copy(st, region);
2096  BLI_addtail(&area_dst->regionbase, newar);
2097  }
2098 }
2099 
2100 void ED_area_data_swap(ScrArea *area_dst, ScrArea *area_src)
2101 {
2102  SWAP(char, area_dst->spacetype, area_src->spacetype);
2103  SWAP(SpaceType *, area_dst->type, area_src->type);
2104 
2105  SWAP(ListBase, area_dst->spacedata, area_src->spacedata);
2106  SWAP(ListBase, area_dst->regionbase, area_src->regionbase);
2107 }
2108 
2109 /* -------------------------------------------------------------------- */
2121  struct {
2126  short alignment;
2130  bool hidden;
2132 };
2133 
2135 {
2136  for (int index = 0; index < RGN_TYPE_LEN; index++) {
2137  r_align_info->by_type[index].alignment = -1;
2138  /* Default to true, when it doesn't exist - it's effectively hidden. */
2139  r_align_info->by_type[index].hidden = true;
2140  }
2141 
2142  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
2143  const int index = region->regiontype;
2144  if ((uint)index < RGN_TYPE_LEN) {
2145  r_align_info->by_type[index].alignment = RGN_ALIGN_ENUM_FROM_MASK(region->alignment);
2146  r_align_info->by_type[index].hidden = (region->flag & RGN_FLAG_HIDDEN) != 0;
2147  }
2148  }
2149 }
2150 
2159  const struct RegionTypeAlignInfo *region_align_info, const short fallback)
2160 {
2161  const short header_alignment = region_align_info->by_type[RGN_TYPE_HEADER].alignment;
2162  const short tool_header_alignment = region_align_info->by_type[RGN_TYPE_TOOL_HEADER].alignment;
2163 
2164  const bool header_hidden = region_align_info->by_type[RGN_TYPE_HEADER].hidden;
2165  const bool tool_header_hidden = region_align_info->by_type[RGN_TYPE_TOOL_HEADER].hidden;
2166 
2167  if ((tool_header_alignment != -1) &&
2168  /* If tool-header is hidden, use header alignment. */
2169  ((tool_header_hidden == false) ||
2170  /* Don't prioritize the tool-header if both are hidden (behave as if both are visible).
2171  * Without this, switching to a space with headers hidden will flip the alignment
2172  * upon switching to a space with visible headers. */
2173  (header_hidden && tool_header_hidden))) {
2174  return tool_header_alignment;
2175  }
2176  if (header_alignment != -1) {
2177  return header_alignment;
2178  }
2179  return fallback;
2180 }
2181 
2205  const struct RegionTypeAlignInfo *region_align_info_src,
2206  const struct RegionTypeAlignInfo *region_align_info_dst,
2207  ARegion *region_by_type[RGN_TYPE_LEN])
2208 {
2209  /* Abbreviate access. */
2210  const short header_alignment_src = region_align_info_src->by_type[RGN_TYPE_HEADER].alignment;
2211  const short tool_header_alignment_src =
2212  region_align_info_src->by_type[RGN_TYPE_TOOL_HEADER].alignment;
2213 
2214  const bool tool_header_hidden_src = region_align_info_src->by_type[RGN_TYPE_TOOL_HEADER].hidden;
2215 
2216  const short primary_header_alignment_src = region_alignment_from_header_and_tool_header_state(
2217  region_align_info_src, -1);
2218 
2219  /* Neither alignments are usable, don't sync. */
2220  if (primary_header_alignment_src == -1) {
2221  return;
2222  }
2223 
2224  const short header_alignment_dst = region_align_info_dst->by_type[RGN_TYPE_HEADER].alignment;
2225  const short tool_header_alignment_dst =
2226  region_align_info_dst->by_type[RGN_TYPE_TOOL_HEADER].alignment;
2227  const short footer_alignment_dst = region_align_info_dst->by_type[RGN_TYPE_FOOTER].alignment;
2228 
2229  const bool tool_header_hidden_dst = region_align_info_dst->by_type[RGN_TYPE_TOOL_HEADER].hidden;
2230 
2231  /* New synchronized alignments to set (or ignore when left as -1). */
2232  short header_alignment_sync = -1;
2233  short tool_header_alignment_sync = -1;
2234  short footer_alignment_sync = -1;
2235 
2236  /* Both source/destination areas have same region configurations regarding headers.
2237  * Simply copy the values. */
2238  if (((header_alignment_src != -1) == (header_alignment_dst != -1)) &&
2239  ((tool_header_alignment_src != -1) == (tool_header_alignment_dst != -1)) &&
2240  (tool_header_hidden_src == tool_header_hidden_dst)) {
2241  if (header_alignment_dst != -1) {
2242  header_alignment_sync = header_alignment_src;
2243  }
2244  if (tool_header_alignment_dst != -1) {
2245  tool_header_alignment_sync = tool_header_alignment_src;
2246  }
2247  }
2248  else {
2249  /* Not an exact match, check the space selector isn't moving. */
2250  const short primary_header_alignment_dst = region_alignment_from_header_and_tool_header_state(
2251  region_align_info_dst, -1);
2252 
2253  if (primary_header_alignment_src != primary_header_alignment_dst) {
2254  if ((header_alignment_dst != -1) && (tool_header_alignment_dst != -1)) {
2255  if (header_alignment_dst == tool_header_alignment_dst) {
2256  /* Apply to both. */
2257  tool_header_alignment_sync = primary_header_alignment_src;
2258  header_alignment_sync = primary_header_alignment_src;
2259  }
2260  else {
2261  /* Keep on opposite sides. */
2262  tool_header_alignment_sync = primary_header_alignment_src;
2263  header_alignment_sync = (tool_header_alignment_sync == RGN_ALIGN_BOTTOM) ?
2264  RGN_ALIGN_TOP :
2266  }
2267  }
2268  else {
2269  /* Apply what we can to regions that exist. */
2270  if (header_alignment_dst != -1) {
2271  header_alignment_sync = primary_header_alignment_src;
2272  }
2273  if (tool_header_alignment_dst != -1) {
2274  tool_header_alignment_sync = primary_header_alignment_src;
2275  }
2276  }
2277  }
2278  }
2279 
2280  if (footer_alignment_dst != -1) {
2281  if ((header_alignment_dst != -1) && (header_alignment_dst == footer_alignment_dst)) {
2282  /* Apply to both. */
2283  footer_alignment_sync = primary_header_alignment_src;
2284  }
2285  else {
2286  /* Keep on opposite sides. */
2287  footer_alignment_sync = (primary_header_alignment_src == RGN_ALIGN_BOTTOM) ?
2288  RGN_ALIGN_TOP :
2290  }
2291  }
2292 
2293  /* Finally apply synchronized flags. */
2294  if (header_alignment_sync != -1) {
2295  ARegion *region = region_by_type[RGN_TYPE_HEADER];
2296  if (region != NULL) {
2297  region->alignment = RGN_ALIGN_ENUM_FROM_MASK(header_alignment_sync) |
2299  }
2300  }
2301 
2302  if (tool_header_alignment_sync != -1) {
2303  ARegion *region = region_by_type[RGN_TYPE_TOOL_HEADER];
2304  if (region != NULL) {
2305  region->alignment = RGN_ALIGN_ENUM_FROM_MASK(tool_header_alignment_sync) |
2307  }
2308  }
2309 
2310  if (footer_alignment_sync != -1) {
2311  ARegion *region = region_by_type[RGN_TYPE_FOOTER];
2312  if (region != NULL) {
2313  region->alignment = RGN_ALIGN_ENUM_FROM_MASK(footer_alignment_sync) |
2315  }
2316  }
2317 }
2318 
2320  ScrArea *area, const struct RegionTypeAlignInfo region_align_info_src[RGN_TYPE_LEN])
2321 {
2322  ARegion *region_by_type[RGN_TYPE_LEN] = {NULL};
2323  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
2324  const int index = region->regiontype;
2325  if ((uint)index < RGN_TYPE_LEN) {
2326  region_by_type[index] = region;
2327  }
2328  }
2329 
2330  struct RegionTypeAlignInfo region_align_info_dst;
2331  region_align_info_from_area(area, &region_align_info_dst);
2332 
2333  if ((region_by_type[RGN_TYPE_HEADER] != NULL) ||
2334  (region_by_type[RGN_TYPE_TOOL_HEADER] != NULL)) {
2336  region_align_info_src, &region_align_info_dst, region_by_type);
2337  }
2338 
2339  /* Note that we could support other region types. */
2340 }
2341 
2344 /* *********** Space switching code *********** */
2345 
2347 {
2348  ScrArea *tmp = MEM_callocN(sizeof(ScrArea), "addscrarea");
2349  wmWindow *win = CTX_wm_window(C);
2350 
2351  ED_area_exit(C, sa1);
2352  ED_area_exit(C, sa2);
2353 
2354  ED_area_data_copy(tmp, sa1, false);
2355  ED_area_data_copy(sa1, sa2, true);
2356  ED_area_data_copy(sa2, tmp, true);
2357  ED_area_init(CTX_wm_manager(C), win, sa1);
2358  ED_area_init(CTX_wm_manager(C), win, sa2);
2359 
2360  BKE_screen_area_free(tmp);
2361  MEM_freeN(tmp);
2362 
2363  /* tell WM to refresh, cursor types etc */
2365 
2366  ED_area_tag_redraw(sa1);
2367  ED_area_tag_refresh(sa1);
2368  ED_area_tag_redraw(sa2);
2369  ED_area_tag_refresh(sa2);
2370 }
2371 
2375 void ED_area_newspace(bContext *C, ScrArea *area, int type, const bool skip_region_exit)
2376 {
2377  wmWindow *win = CTX_wm_window(C);
2378 
2379  if (area->spacetype != type) {
2380  SpaceLink *slold = area->spacedata.first;
2381  /* store area->type->exit callback */
2382  void *area_exit = area->type ? area->type->exit : NULL;
2383  /* When the user switches between space-types from the type-selector,
2384  * changing the header-type is jarring (especially when using Ctrl-MouseWheel).
2385  *
2386  * However, add-on install for example, forces the header to the top which shouldn't
2387  * be applied back to the previous space type when closing - see: T57724
2388  *
2389  * Newly created windows wont have any space data, use the alignment
2390  * the space type defaults to in this case instead
2391  * (needed for preferences to have space-type on bottom).
2392  */
2393 
2394  bool sync_header_alignment = false;
2395  struct RegionTypeAlignInfo region_align_info[RGN_TYPE_LEN];
2396  if ((slold != NULL) && (slold->link_flag & SPACE_FLAG_TYPE_TEMPORARY) == 0) {
2397  region_align_info_from_area(area, region_align_info);
2398  sync_header_alignment = true;
2399  }
2400 
2401  /* in some cases (opening temp space) we don't want to
2402  * call area exit callback, so we temporarily unset it */
2403  if (skip_region_exit && area->type) {
2404  area->type->exit = NULL;
2405  }
2406 
2407  ED_area_exit(C, area);
2408 
2409  /* restore old area exit callback */
2410  if (skip_region_exit && area->type) {
2411  area->type->exit = area_exit;
2412  }
2413 
2415 
2416  area->spacetype = type;
2417  area->type = st;
2418 
2419  /* If st->create may be called, don't use context until then. The
2420  * area->type->context() callback has changed but data may be invalid
2421  * (e.g. with properties editor) until space-data is properly created */
2422 
2423  /* check previously stored space */
2424  SpaceLink *sl = NULL;
2425  LISTBASE_FOREACH (SpaceLink *, sl_iter, &area->spacedata) {
2426  if (sl_iter->spacetype == type) {
2427  sl = sl_iter;
2428  break;
2429  }
2430  }
2431 
2432  /* old spacedata... happened during work on 2.50, remove */
2433  if (sl && BLI_listbase_is_empty(&sl->regionbase)) {
2434  st->free(sl);
2435  BLI_freelinkN(&area->spacedata, sl);
2436  if (slold == sl) {
2437  slold = NULL;
2438  }
2439  sl = NULL;
2440  }
2441 
2442  if (sl) {
2443  /* swap regions */
2444  slold->regionbase = area->regionbase;
2445  area->regionbase = sl->regionbase;
2447  /* SPACE_FLAG_TYPE_WAS_ACTIVE is only used to go back to a previously active space that is
2448  * overlapped by temporary ones. It's now properly activated, so the flag should be cleared
2449  * at this point. */
2451 
2452  /* put in front of list */
2453  BLI_remlink(&area->spacedata, sl);
2454  BLI_addhead(&area->spacedata, sl);
2455  }
2456  else {
2457  /* new space */
2458  if (st) {
2459  /* Don't get scene from context here which may depend on space-data. */
2461  sl = st->create(area, scene);
2462  BLI_addhead(&area->spacedata, sl);
2463 
2464  /* swap regions */
2465  if (slold) {
2466  slold->regionbase = area->regionbase;
2467  }
2468  area->regionbase = sl->regionbase;
2470  }
2471  }
2472 
2473  /* Sync header alignment. */
2474  if (sync_header_alignment) {
2475  region_align_info_to_area(area, region_align_info);
2476  }
2477 
2479 
2480  /* tell WM to refresh, cursor types etc */
2482 
2483  /* send space change notifier */
2485 
2487  }
2488 
2489  /* also redraw when re-used */
2491 }
2492 
2494 {
2495  SpaceLink *sl = area->spacedata.first;
2496 
2497  /* First toggle to the next temporary space in the list. */
2498  for (SpaceLink *sl_iter = sl->next; sl_iter; sl_iter = sl_iter->next) {
2499  if (sl_iter->link_flag & SPACE_FLAG_TYPE_TEMPORARY) {
2500  return sl_iter;
2501  }
2502  }
2503 
2504  /* No temporary space, find the item marked as last active. */
2505  for (SpaceLink *sl_iter = sl->next; sl_iter; sl_iter = sl_iter->next) {
2506  if (sl_iter->link_flag & SPACE_FLAG_TYPE_WAS_ACTIVE) {
2507  return sl_iter;
2508  }
2509  }
2510 
2511  /* If neither is found, we can just return to the regular previous one. */
2512  return sl->next;
2513 }
2514 
2516 {
2517  SpaceLink *sl = area->spacedata.first;
2518  SpaceLink *prevspace = sl ? area_get_prevspace(area) : NULL;
2519 
2520  if (prevspace) {
2521  ED_area_newspace(C, area, prevspace->spacetype, false);
2522  /* We've exited the space, so it can't be considered temporary anymore. */
2524  }
2525  else {
2526  /* no change */
2527  return;
2528  }
2529  /* If this is a stacked fullscreen, changing to previous area exits it (meaning we're still in a
2530  * fullscreen, but not in a stacked one). */
2532 
2534 
2535  /* send space change notifier */
2537 }
2538 
2539 /* returns offset for next button in header */
2540 int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco)
2541 {
2542  ScrArea *area = CTX_wm_area(C);
2543  bScreen *screen = CTX_wm_screen(C);
2544  PointerRNA areaptr;
2545  int xco = 0.4 * U.widget_unit;
2546 
2547  RNA_pointer_create(&(screen->id), &RNA_Area, area, &areaptr);
2548 
2549  uiDefButR(block,
2550  UI_BTYPE_MENU,
2551  0,
2552  "",
2553  xco,
2554  yco,
2555  1.6 * U.widget_unit,
2556  U.widget_unit,
2557  &areaptr,
2558  "ui_type",
2559  0,
2560  0.0f,
2561  0.0f,
2562  0.0f,
2563  0.0f,
2564  "");
2565 
2566  return xco + 1.7 * U.widget_unit;
2567 }
2568 
2569 /************************ standard UI regions ************************/
2570 
2572 {
2573  ScrArea *area = CTX_wm_area(C);
2574 
2575  switch (region->regiontype) {
2576  case RGN_TYPE_HEADER:
2577  case RGN_TYPE_TOOL_HEADER:
2579  return TH_HEADER;
2580  }
2581  else {
2582  return TH_HEADERDESEL;
2583  }
2584  case RGN_TYPE_PREVIEW:
2585  return TH_PREVIEW_BACK;
2586  default:
2587  return TH_BACK;
2588  }
2589 }
2590 
2591 static void region_clear_color(const bContext *C, const ARegion *region, ThemeColorID colorid)
2592 {
2593  if (region->alignment == RGN_ALIGN_FLOAT) {
2594  /* handle our own drawing. */
2595  }
2596  else if (region->overlap) {
2597  /* view should be in pixelspace */
2599 
2600  float back[4];
2601  UI_GetThemeColor4fv(colorid, back);
2602  GPU_clear_color(back[3] * back[0], back[3] * back[1], back[3] * back[2], back[3]);
2603  }
2604  else {
2605  UI_ThemeClearColor(colorid);
2606  }
2607 }
2608 
2609 BLI_INLINE bool streq_array_any(const char *s, const char *arr[])
2610 {
2611  for (uint i = 0; arr[i]; i++) {
2612  if (STREQ(arr[i], s)) {
2613  return true;
2614  }
2615  }
2616  return false;
2617 }
2618 
2628 static void ed_panel_draw(const bContext *C,
2629  ARegion *region,
2630  ListBase *lb,
2631  PanelType *pt,
2632  Panel *panel,
2633  int w,
2634  int em,
2635  char *unique_panel_str,
2636  const char *search_filter)
2637 {
2638  const uiStyle *style = UI_style_get_dpi();
2639 
2640  /* Draw panel. */
2641 
2643  strncpy(block_name, pt->idname, BKE_ST_MAXNAME);
2644  if (unique_panel_str != NULL) {
2645  /* Instanced panels should have already been added at this point. */
2646  strncat(block_name, unique_panel_str, INSTANCED_PANEL_UNIQUE_STR_LEN);
2647  }
2648  uiBlock *block = UI_block_begin(C, region, block_name, UI_EMBOSS);
2649 
2650  bool open;
2651  panel = UI_panel_begin(region, lb, block, pt, panel, &open);
2652 
2653  const bool search_filter_active = search_filter != NULL && search_filter[0] != '\0';
2654 
2655  /* bad fixed values */
2656  int xco, yco, h = 0;
2657  int headerend = w - UI_UNIT_X;
2658 
2660  if (pt->draw_header_preset && !(pt->flag & PANEL_TYPE_NO_HEADER)) {
2661  /* for preset menu */
2662  panel->layout = UI_block_layout(block,
2665  0,
2666  (UI_UNIT_Y * 1.1f) + style->panelspace,
2667  UI_UNIT_Y,
2668  1,
2669  0,
2670  style);
2671 
2672  pt->draw_header_preset(C, panel);
2673 
2674  UI_block_apply_search_filter(block, search_filter);
2675  UI_block_layout_resolve(block, &xco, &yco);
2676  UI_block_translate(block, headerend - xco, 0);
2677  panel->layout = NULL;
2678  }
2679 
2680  if (pt->draw_header && !(pt->flag & PANEL_TYPE_NO_HEADER)) {
2681  int labelx, labely;
2682  UI_panel_label_offset(block, &labelx, &labely);
2683 
2684  /* Unusual case: Use expanding layout (buttons stretch to available width). */
2685  if (pt->flag & PANEL_TYPE_HEADER_EXPAND) {
2686  uiLayout *layout = UI_block_layout(block,
2689  labelx,
2690  labely,
2691  headerend - 2 * style->panelspace,
2692  1,
2693  0,
2694  style);
2695  panel->layout = uiLayoutRow(layout, false);
2696  }
2697  /* Regular case: Normal panel with fixed size buttons. */
2698  else {
2699  panel->layout = UI_block_layout(
2700  block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, labelx, labely, UI_UNIT_Y, 1, 0, style);
2701  }
2702 
2703  pt->draw_header(C, panel);
2704 
2705  UI_block_apply_search_filter(block, search_filter);
2706  UI_block_layout_resolve(block, &xco, &yco);
2707  panel->labelofs = xco - labelx;
2708  panel->layout = NULL;
2709  }
2710  else {
2711  panel->labelofs = 0;
2712  }
2714 
2715  if (open || search_filter_active) {
2716  short panelContext;
2717 
2718  /* panel context can either be toolbar region or normal panels region */
2719  if (pt->flag & PANEL_TYPE_LAYOUT_VERT_BAR) {
2720  panelContext = UI_LAYOUT_VERT_BAR;
2721  }
2722  else if (region->regiontype == RGN_TYPE_TOOLS) {
2723  panelContext = UI_LAYOUT_TOOLBAR;
2724  }
2725  else {
2726  panelContext = UI_LAYOUT_PANEL;
2727  }
2728 
2729  panel->layout = UI_block_layout(
2730  block,
2732  panelContext,
2733  (pt->flag & PANEL_TYPE_LAYOUT_VERT_BAR) ? 0 : style->panelspace,
2734  0,
2735  (pt->flag & PANEL_TYPE_LAYOUT_VERT_BAR) ? 0 : w - 2 * style->panelspace,
2736  em,
2737  0,
2738  style);
2739 
2740  pt->draw(C, panel);
2741 
2742  UI_block_apply_search_filter(block, search_filter);
2743  UI_block_layout_resolve(block, &xco, &yco);
2744  panel->layout = NULL;
2745 
2746  if (yco != 0) {
2747  h = -yco + 2 * style->panelspace;
2748  }
2749  }
2750 
2751  UI_block_end(C, block);
2752 
2753  /* Draw child panels. */
2754  if (open || search_filter_active) {
2755  LISTBASE_FOREACH (LinkData *, link, &pt->children) {
2756  PanelType *child_pt = link->data;
2757  Panel *child_panel = UI_panel_find_by_type(&panel->children, child_pt);
2758 
2759  if (child_pt->draw && (!child_pt->poll || child_pt->poll(C, child_pt))) {
2760  ed_panel_draw(C,
2761  region,
2762  &panel->children,
2763  child_pt,
2764  child_panel,
2765  w,
2766  em,
2767  unique_panel_str,
2768  search_filter);
2769  }
2770  }
2771  }
2772 
2773  UI_panel_end(panel, w, h);
2774 }
2775 
2779 static bool panel_add_check(const bContext *C,
2780  const WorkSpace *workspace,
2781  const char *contexts[],
2782  const char *category_override,
2783  PanelType *panel_type)
2784 {
2785  /* Only add top level panels. */
2786  if (panel_type->parent) {
2787  return false;
2788  }
2789  /* Check the category override first. */
2790  if (category_override) {
2791  if (!STREQ(panel_type->category, category_override)) {
2792  return false;
2793  }
2794  }
2795 
2796  /* Verify context. */
2797  if (contexts != NULL && panel_type->context[0]) {
2798  if (!streq_array_any(panel_type->context, contexts)) {
2799  return false;
2800  }
2801  }
2802 
2803  /* If we're tagged, only use compatible. */
2804  if (panel_type->owner_id[0]) {
2805  if (!BKE_workspace_owner_id_check(workspace, panel_type->owner_id)) {
2806  return false;
2807  }
2808  }
2809 
2810  if (LIKELY(panel_type->draw)) {
2811  if (panel_type->poll && !panel_type->poll(C, panel_type)) {
2812  return false;
2813  }
2814  }
2815 
2816  return true;
2817 }
2818 
2819 static bool region_uses_category_tabs(const ScrArea *area, const ARegion *region)
2820 {
2821  /* XXX, should use some better check? */
2822  /* For now also has hardcoded check for clip editor until it supports actual toolbar. */
2823  return ((1 << region->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) ||
2824  (region->regiontype == RGN_TYPE_TOOLS && area->spacetype == SPACE_CLIP);
2825 }
2826 
2827 static const char *region_panels_collect_categories(ARegion *region,
2828  LinkNode *panel_types_stack,
2829  bool *use_category_tabs)
2830 {
2832 
2833  /* gather unique categories */
2834  for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) {
2835  PanelType *pt = pt_link->link;
2836  if (pt->category[0]) {
2837  if (!UI_panel_category_find(region, pt->category)) {
2838  UI_panel_category_add(region, pt->category);
2839  }
2840  }
2841  }
2842 
2843  if (UI_panel_category_is_visible(region)) {
2844  return UI_panel_category_active_get(region, true);
2845  }
2846 
2847  *use_category_tabs = false;
2848  return NULL;
2849 }
2850 
2857  ARegion *region,
2858  ListBase *paneltypes,
2859  const char *contexts[],
2860  const char *category_override)
2861 {
2862  /* collect panels to draw */
2863  WorkSpace *workspace = CTX_wm_workspace(C);
2864  LinkNode *panel_types_stack = NULL;
2865  LISTBASE_FOREACH_BACKWARD (PanelType *, pt, paneltypes) {
2866  if (panel_add_check(C, workspace, contexts, category_override, pt)) {
2867  BLI_linklist_prepend_alloca(&panel_types_stack, pt);
2868  }
2869  }
2870 
2871  region->runtime.category = NULL;
2872 
2873  ScrArea *area = CTX_wm_area(C);
2874  View2D *v2d = &region->v2d;
2875 
2876  bool use_category_tabs = (category_override == NULL) && region_uses_category_tabs(area, region);
2877  /* offset panels for small vertical tab area */
2878  const char *category = NULL;
2879  const int category_tabs_width = UI_PANEL_CATEGORY_MARGIN_WIDTH;
2880  int margin_x = 0;
2881  const bool region_layout_based = region->flag & RGN_FLAG_DYNAMIC_SIZE;
2882  bool update_tot_size = true;
2883 
2884  /* only allow scrolling in vertical direction */
2886  v2d->keepofs &= ~(V2D_LOCKOFS_Y | V2D_KEEPOFS_X);
2887  v2d->scroll &= ~V2D_SCROLL_BOTTOM;
2888  v2d->scroll |= V2D_SCROLL_RIGHT;
2889 
2890  /* collect categories */
2891  if (use_category_tabs) {
2892  category = region_panels_collect_categories(region, panel_types_stack, &use_category_tabs);
2893  }
2894  if (use_category_tabs) {
2895  margin_x = category_tabs_width;
2896  }
2897 
2898  const int w = BLI_rctf_size_x(&v2d->cur) - margin_x;
2899  /* Works out to 10 * UI_UNIT_X or 20 * UI_UNIT_X. */
2900  const int em = (region->type->prefsizex) ? 10 : 20;
2901 
2902  const int w_box_panel = w - UI_PANEL_BOX_STYLE_MARGIN * 2.0f;
2903 
2904  /* create panels */
2905  UI_panels_begin(C, region);
2906 
2907  /* Get search string for property search. */
2908  const char *search_filter = ED_area_region_search_filter_get(area, region);
2909 
2910  /* set view2d view matrix - UI_block_begin() stores it */
2911  UI_view2d_view_ortho(v2d);
2912 
2913  bool has_instanced_panel = false;
2914  for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) {
2915  PanelType *pt = pt_link->link;
2916 
2917  if (pt->flag & PANEL_TYPE_INSTANCED) {
2918  has_instanced_panel = true;
2919  continue;
2920  }
2921  Panel *panel = UI_panel_find_by_type(&region->panels, pt);
2922 
2923  if (use_category_tabs && pt->category[0] && !STREQ(category, pt->category)) {
2924  if ((panel == NULL) || ((panel->flag & PNL_PIN) == 0)) {
2925  continue;
2926  }
2927  }
2928 
2929  if (panel && UI_panel_is_dragging(panel)) {
2930  /* Prevent View2d.tot rectangle size changes while dragging panels. */
2931  update_tot_size = false;
2932  }
2933 
2934  ed_panel_draw(C,
2935  region,
2936  &region->panels,
2937  pt,
2938  panel,
2939  (pt->flag & PANEL_TYPE_DRAW_BOX) ? w_box_panel : w,
2940  em,
2941  NULL,
2942  search_filter);
2943  }
2944 
2945  /* Draw "polyinstantaited" panels that don't have a 1 to 1 correspondence with their types. */
2946  if (has_instanced_panel) {
2947  LISTBASE_FOREACH (Panel *, panel, &region->panels) {
2948  if (panel->type == NULL) {
2949  continue; /* Some panels don't have a type. */
2950  }
2951  if (!(panel->type->flag & PANEL_TYPE_INSTANCED)) {
2952  continue;
2953  }
2954  if (use_category_tabs && panel->type->category[0] &&
2955  !STREQ(category, panel->type->category)) {
2956  continue;
2957  }
2958 
2959  if (panel && UI_panel_is_dragging(panel)) {
2960  /* Prevent View2d.tot rectangle size changes while dragging panels. */
2961  update_tot_size = false;
2962  }
2963 
2964  /* Use a unique identifier for instanced panels, otherwise an old block for a different
2965  * panel of the same type might be found. */
2966  char unique_panel_str[INSTANCED_PANEL_UNIQUE_STR_LEN];
2967  UI_list_panel_unique_str(panel, unique_panel_str);
2968  ed_panel_draw(C,
2969  region,
2970  &region->panels,
2971  panel->type,
2972  panel,
2973  (panel->type->flag & PANEL_TYPE_DRAW_BOX) ? w_box_panel : w,
2974  em,
2975  unique_panel_str,
2976  search_filter);
2977  }
2978  }
2979 
2980  /* align panels and return size */
2981  int x, y;
2982  UI_panels_end(C, region, &x, &y);
2983 
2984  /* before setting the view */
2985  if (region_layout_based) {
2986  /* XXX, only single panel support atm.
2987  * Can't use x/y values calculated above because they're not using the real height of panels,
2988  * instead they calculate offsets for the next panel to start drawing. */
2989  Panel *panel = region->panels.last;
2990  if (panel != NULL) {
2991  const int size_dyn[2] = {
2992  UI_UNIT_X * (UI_panel_is_closed(panel) ? 8 : 14) / UI_DPI_FAC,
2993  UI_panel_size_y(panel) / UI_DPI_FAC,
2994  };
2995  /* region size is layout based and needs to be updated */
2996  if ((region->sizex != size_dyn[0]) || (region->sizey != size_dyn[1])) {
2997  region->sizex = size_dyn[0];
2998  region->sizey = size_dyn[1];
3000  }
3001  y = fabsf(region->sizey * UI_DPI_FAC - 1);
3002  }
3003  }
3004  else {
3005  /* We always keep the scroll offset -
3006  * so the total view gets increased with the scrolled away part. */
3007  if (v2d->cur.ymax < -FLT_EPSILON) {
3008  /* Clamp to lower view boundary */
3009  if (v2d->tot.ymin < -v2d->winy) {
3010  y = min_ii(y, 0);
3011  }
3012  else {
3013  y = min_ii(y, v2d->cur.ymin);
3014  }
3015  }
3016 
3017  y = -y;
3018  }
3019 
3020  if (update_tot_size) {
3021  /* this also changes the 'cur' */
3022  UI_view2d_totRect_set(v2d, x, y);
3023  }
3024 
3025  if (use_category_tabs) {
3026  region->runtime.category = category;
3027  }
3028 }
3029 
3031 {
3032  ED_region_panels_layout_ex(C, region, &region->type->paneltypes, NULL, NULL);
3033 }
3034 
3036 {
3037  View2D *v2d = &region->v2d;
3038 
3039  if (region->alignment != RGN_ALIGN_FLOAT) {
3041  C, region, (region->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
3042  }
3043 
3044  /* reset line width for drawing tabs */
3045  GPU_line_width(1.0f);
3046 
3047  /* set the view */
3048  UI_view2d_view_ortho(v2d);
3049 
3050  /* View2D matrix might have changed due to dynamic sized regions. */
3052 
3053  /* draw panels */
3054  UI_panels_draw(C, region);
3055 
3056  /* restore view matrix */
3058 
3059  /* Set in layout. */
3060  if (region->runtime.category) {
3061  UI_panel_category_draw_all(region, region->runtime.category);
3062  }
3063 
3064  /* scrollers */
3065  bool use_mask = false;
3066  rcti mask;
3067  if (region->runtime.category &&
3069  use_mask = true;
3072  }
3073  UI_view2d_scrollers_draw(v2d, use_mask ? &mask : NULL);
3074 }
3075 
3076 void ED_region_panels_ex(const bContext *C, ARegion *region, const char *contexts[])
3077 {
3078  /* TODO: remove? */
3079  ED_region_panels_layout_ex(C, region, &region->type->paneltypes, contexts, NULL);
3080  ED_region_panels_draw(C, region);
3081 }
3082 
3083 void ED_region_panels(const bContext *C, ARegion *region)
3084 {
3085  /* TODO: remove? */
3086  ED_region_panels_layout(C, region);
3087  ED_region_panels_draw(C, region);
3088 }
3089 
3091 {
3092  UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_PANELS_UI, region->winx, region->winy);
3093 
3094  wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D Buttons List", 0, 0);
3095  WM_event_add_keymap_handler(&region->handlers, keymap);
3096 }
3097 
3104 static bool panel_property_search(const bContext *C,
3105  ARegion *region,
3106  const uiStyle *style,
3107  Panel *panel,
3108  PanelType *panel_type,
3109  const char *search_filter)
3110 {
3111  uiBlock *block = UI_block_begin(C, region, panel_type->idname, UI_EMBOSS);
3112  UI_block_set_search_only(block, true);
3113 
3114  /* Skip panels that give meaningless search results. */
3115  if (panel_type->flag & PANEL_TYPE_NO_SEARCH) {
3116  return false;
3117  }
3118 
3119  if (panel == NULL) {
3120  bool open; /* Dummy variable. */
3121  panel = UI_panel_begin(region, &region->panels, block, panel_type, panel, &open);
3122  }
3123 
3124  /* Build the layouts. Because they are only used for search,
3125  * they don't need any of the proper style or layout information. */
3126  if (panel->type->draw_header_preset != NULL) {
3127  panel->layout = UI_block_layout(
3128  block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, 0, 0, 0, 0, 0, style);
3129  panel_type->draw_header_preset(C, panel);
3130  }
3131  if (panel->type->draw_header != NULL) {
3132  panel->layout = UI_block_layout(
3133  block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, 0, 0, 0, 0, 0, style);
3134  panel_type->draw_header(C, panel);
3135  }
3136  if (LIKELY(panel->type->draw != NULL)) {
3137  panel->layout = UI_block_layout(
3138  block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 0, 0, 0, style);
3139  panel_type->draw(C, panel);
3140  }
3141 
3142  UI_block_layout_free(block);
3143 
3144  /* We could check after each layout to increase the likelihood of returning early,
3145  * but that probably wouldn't make much of a difference anyway. */
3146  if (UI_block_apply_search_filter(block, search_filter)) {
3147  return true;
3148  }
3149 
3150  LISTBASE_FOREACH (LinkData *, link, &panel_type->children) {
3151  PanelType *panel_type_child = link->data;
3152  if (!panel_type_child->poll || panel_type_child->poll(C, panel_type_child)) {
3153  /* Search for the existing child panel here because it might be an instanced
3154  * child panel with a custom data field that will be needed to build the layout. */
3155  Panel *child_panel = UI_panel_find_by_type(&panel->children, panel_type_child);
3156  if (panel_property_search(C, region, style, child_panel, panel_type_child, search_filter)) {
3157  return true;
3158  }
3159  }
3160  }
3161 
3162  return false;
3163 }
3164 
3170  ARegion *region,
3171  ListBase *paneltypes,
3172  const char *contexts[],
3173  const char *category_override)
3174 {
3175  ScrArea *area = CTX_wm_area(C);
3176  WorkSpace *workspace = CTX_wm_workspace(C);
3177  const uiStyle *style = UI_style_get_dpi();
3178  const char *search_filter = ED_area_region_search_filter_get(area, region);
3179 
3180  LinkNode *panel_types_stack = NULL;
3181  LISTBASE_FOREACH_BACKWARD (PanelType *, pt, paneltypes) {
3182  if (panel_add_check(C, workspace, contexts, category_override, pt)) {
3183  BLI_linklist_prepend_alloca(&panel_types_stack, pt);
3184  }
3185  }
3186 
3187  const char *category = NULL;
3188  bool use_category_tabs = (category_override == NULL) && region_uses_category_tabs(area, region);
3189  if (use_category_tabs) {
3190  category = region_panels_collect_categories(region, panel_types_stack, &use_category_tabs);
3191  }
3192 
3193  /* Run property search for each panel, stopping if a result is found. */
3194  bool has_result = true;
3195  bool has_instanced_panel = false;
3196  for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) {
3197  PanelType *panel_type = pt_link->link;
3198  /* Note that these checks are duplicated from #ED_region_panels_layout_ex. */
3199  if (panel_type->flag & PANEL_TYPE_INSTANCED) {
3200  has_instanced_panel = true;
3201  continue;
3202  }
3203 
3204  if (use_category_tabs) {
3205  if (panel_type->category[0] && !STREQ(category, panel_type->category)) {
3206  continue;
3207  }
3208  }
3209 
3210  /* We start property search with an empty panel list, so there's
3211  * no point in trying to find an existing panel with this type. */
3212  has_result = panel_property_search(C, region, style, NULL, panel_type, search_filter);
3213  if (has_result) {
3214  break;
3215  }
3216  }
3217 
3218  /* Run property search for instanced panels (created in the layout calls of previous panels). */
3219  if (!has_result && has_instanced_panel) {
3220  LISTBASE_FOREACH (Panel *, panel, &region->panels) {
3221  /* Note that these checks are duplicated from #ED_region_panels_layout_ex. */
3222  if (panel->type == NULL || !(panel->type->flag & PANEL_TYPE_INSTANCED)) {
3223  continue;
3224  }
3225  if (use_category_tabs) {
3226  if (panel->type->category[0] && !STREQ(category, panel->type->category)) {
3227  continue;
3228  }
3229  }
3230 
3231  has_result = panel_property_search(C, region, style, panel, panel->type, search_filter);
3232  if (has_result) {
3233  break;
3234  }
3235  }
3236  }
3237 
3238  /* Free the panels and blocks, as they are only used for search. */
3239  UI_blocklist_free(C, &region->uiblocks);
3240  UI_panels_free_instanced(C, region);
3242 
3243  return has_result;
3244 }
3245 
3247 {
3248  const uiStyle *style = UI_style_get_dpi();
3249  bool region_layout_based = region->flag & RGN_FLAG_DYNAMIC_SIZE;
3250 
3251  /* Height of buttons and scaling needed to achieve it. */
3252  const int buttony = min_ii(UI_UNIT_Y, region->winy - 2 * UI_DPI_FAC);
3253  const float buttony_scale = buttony / (float)UI_UNIT_Y;
3254 
3255  /* Vertically center buttons. */
3256  int xco = UI_HEADER_OFFSET;
3257  int yco = buttony + (region->winy - buttony) / 2;
3258  int maxco = xco;
3259 
3260  /* XXX workaround for 1 px alignment issue. Not sure what causes it...
3261  * Would prefer a proper fix - Julian */
3263  yco -= 1;
3264  }
3265 
3266  /* set view2d view matrix for scrolling (without scrollers) */
3267  UI_view2d_view_ortho(&region->v2d);
3268 
3269  /* draw all headers types */
3270  LISTBASE_FOREACH (HeaderType *, ht, &region->type->headertypes) {
3271  if (ht->poll && !ht->poll(C, ht)) {
3272  continue;
3273  }
3274 
3275  uiBlock *block = UI_block_begin(C, region, ht->idname, UI_EMBOSS);
3276  uiLayout *layout = UI_block_layout(
3277  block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, yco, buttony, 1, 0, style);
3278 
3279  if (buttony_scale != 1.0f) {
3280  uiLayoutSetScaleY(layout, buttony_scale);
3281  }
3282 
3283  Header header = {NULL};
3284  if (ht->draw) {
3285  header.type = ht;
3286  header.layout = layout;
3287  ht->draw(C, &header);
3288  if (ht->next) {
3289  uiItemS(layout);
3290  }
3291 
3292  /* for view2d */
3293  xco = uiLayoutGetWidth(layout);
3294  if (xco > maxco) {
3295  maxco = xco;
3296  }
3297  }
3298 
3299  UI_block_layout_resolve(block, &xco, &yco);
3300 
3301  /* for view2d */
3302  if (xco > maxco) {
3303  maxco = xco;
3304  }
3305 
3306  int new_sizex = (maxco + UI_HEADER_OFFSET) / UI_DPI_FAC;
3307 
3308  if (region_layout_based && (region->sizex != new_sizex)) {
3309  /* region size is layout based and needs to be updated */
3310  ScrArea *area = CTX_wm_area(C);
3311 
3312  region->sizex = new_sizex;
3314  }
3315 
3316  UI_block_end(C, block);
3317 
3318  /* In most cases there is only ever one header, it never makes sense to draw more than one
3319  * header in the same region, this results in overlapping buttons, see: T60195. */
3320  break;
3321  }
3322 
3323  if (!region_layout_based) {
3324  maxco += UI_HEADER_OFFSET;
3325  }
3326 
3327  /* always as last */
3328  UI_view2d_totRect_set(&region->v2d, maxco, region->winy);
3329 
3330  /* restore view matrix */
3332 }
3333 
3335 {
3336  /* clear */
3337  region_clear_color(C, region, region_background_color_id(C, region));
3338 
3339  UI_view2d_view_ortho(&region->v2d);
3340 
3341  /* View2D matrix might have changed due to dynamic sized regions. */
3343 
3344  /* draw blocks */
3345  UI_blocklist_draw(C, &region->uiblocks);
3346 
3347  /* restore view matrix */
3349 }
3350 
3351 void ED_region_header(const bContext *C, ARegion *region)
3352 {
3353  /* TODO: remove? */
3354  ED_region_header_layout(C, region);
3355  ED_region_header_draw(C, region);
3356 }
3357 
3359 {
3360  UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_HEADER, region->winx, region->winy);
3361 }
3362 
3364 {
3365  /* Accommodate widget and padding. */
3366  return U.widget_unit + (int)(UI_DPI_FAC * HEADER_PADDING_Y);
3367 }
3368 
3370 {
3371  return ED_area_headersize();
3372 }
3373 
3378 {
3380  return round_fl_to_int(area->global->cur_fixed_height * UI_DPI_FAC);
3381 }
3383 {
3385  return round_fl_to_int(area->global->size_min * UI_DPI_FAC);
3386 }
3388 {
3390  return round_fl_to_int(area->global->size_max * UI_DPI_FAC);
3391 }
3392 
3394 {
3395  return area->global != NULL;
3396 }
3397 
3399 {
3400  ScrArea *global_area = win->global_areas.areabase.first;
3401 
3402  if (!global_area) {
3403  return screen->areabase.first;
3404  }
3405  if ((global_area->global->flag & GLOBAL_AREA_IS_HIDDEN) == 0) {
3406  return global_area;
3407  }
3408  /* Find next visible area. */
3409  return ED_screen_areas_iter_next(screen, global_area);
3410 }
3412 {
3413  if (area->global == NULL) {
3414  return area->next;
3415  }
3416 
3417  for (ScrArea *area_iter = area->next; area_iter; area_iter = area_iter->next) {
3418  if ((area_iter->global->flag & GLOBAL_AREA_IS_HIDDEN) == 0) {
3419  return area_iter;
3420  }
3421  }
3422  /* No visible next global area found, start iterating over layout areas. */
3423  return screen->areabase.first;
3424 }
3425 
3433 {
3434  return ED_area_headersize(); /* same size as header */
3435 }
3436 
3438  const char *text_array[],
3439  float fill_color[4],
3440  const bool full_redraw)
3441 {
3442  const int header_height = UI_UNIT_Y;
3443  const uiStyle *style = UI_style_get_dpi();
3444  int fontid = style->widget.uifont_id;
3445  int scissor[4];
3446  int num_lines = 0;
3447 
3448  /* background box */
3449  rcti rect = *ED_region_visible_rect(region);
3450 
3451  /* Box fill entire width or just around text. */
3452  if (!full_redraw) {
3453  const char **text = &text_array[0];
3454  while (*text) {
3455  rect.xmax = min_ii(rect.xmax,
3456  rect.xmin + BLF_width(fontid, *text, BLF_DRAW_STR_DUMMY_MAX) +
3457  1.2f * U.widget_unit);
3458  text++;
3459  num_lines++;
3460  }
3461  }
3462  /* Just count the line number. */
3463  else {
3464  const char **text = &text_array[0];
3465  while (*text) {
3466  text++;
3467  num_lines++;
3468  }
3469  }
3470 
3471  rect.ymin = rect.ymax - header_height * num_lines;
3472 
3473  /* setup scissor */
3474  GPU_scissor_get(scissor);
3475  GPU_scissor(rect.xmin, rect.ymin, BLI_rcti_size_x(&rect) + 1, BLI_rcti_size_y(&rect) + 1);
3476 
3481  immUniformColor4fv(fill_color);
3482  immRecti(pos, rect.xmin, rect.ymin, rect.xmax + 1, rect.ymax + 1);
3483  immUnbindProgram();
3485 
3486  /* text */
3487  UI_FontThemeColor(fontid, TH_TEXT_HI);
3488  BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
3489  BLF_enable(fontid, BLF_CLIPPING);
3490  int offset = num_lines - 1;
3491  {
3492  const char **text = &text_array[0];
3493  while (*text) {
3494  BLF_position(fontid,
3495  rect.xmin + 0.6f * U.widget_unit,
3496  rect.ymin + 0.3f * U.widget_unit + offset * header_height,
3497  0.0f);
3498  BLF_draw(fontid, *text, BLF_DRAW_STR_DUMMY_MAX);
3499  text++;
3500  offset--;
3501  }
3502  }
3503 
3504  BLF_disable(fontid, BLF_CLIPPING);
3505 
3506  /* restore scissor as it was before */
3507  GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
3508 }
3509 
3511  const char *text,
3512  float fill_color[4],
3513  const bool full_redraw)
3514 {
3515  const char *text_array[2] = {text, NULL};
3516  ED_region_info_draw_multiline(region, text_array, fill_color, full_redraw);
3517 }
3518 
3522 
3523 static void metadata_panel_draw_field(const char *field, const char *value, void *ctx_v)
3524 {
3526  uiLayout *row = uiLayoutRow(ctx->layout, false);
3527  uiItemL(row, field, ICON_NONE);
3528  uiItemL(row, value, ICON_NONE);
3529 }
3530 
3532 {
3534  ctx.layout = layout;
3536 }
3537 
3538 void ED_region_grid_draw(ARegion *region, float zoomx, float zoomy, float x0, float y0)
3539 {
3540  /* the image is located inside (x0, y0), (x0+1, y0+1) as set by view2d */
3541  int x1, y1, x2, y2;
3542  UI_view2d_view_to_region(&region->v2d, x0, y0, &x1, &y1);
3543  UI_view2d_view_to_region(&region->v2d, x0 + 1.0f, y0 + 1.0f, &x2, &y2);
3544 
3547 
3548  float gridcolor[4];
3549  UI_GetThemeColor4fv(TH_GRID, gridcolor);
3550 
3552  /* To fake alpha-blending, color shading is reduced when alpha is nearing 0. */
3553  immUniformThemeColorBlendShade(TH_BACK, TH_GRID, gridcolor[3], 20 * gridcolor[3]);
3554  immRectf(pos, x1, y1, x2, y2);
3555  immUnbindProgram();
3556 
3557  /* gridsize adapted to zoom level */
3558  float gridsize = 0.5f * (zoomx + zoomy);
3559  float gridstep = 1.0f / 32.0f;
3560  if (gridsize <= 0.0f) {
3561  return;
3562  }
3563 
3564  if (gridsize < 1.0f) {
3565  while (gridsize < 1.0f) {
3566  gridsize *= 4.0f;
3567  gridstep *= 4.0f;
3568  }
3569  }
3570  else {
3571  while (gridsize >= 4.0f) {
3572  gridsize /= 4.0f;
3573  gridstep /= 4.0f;
3574  }
3575  }
3576 
3577  float blendfac = 0.25f * gridsize - floorf(0.25f * gridsize);
3578  CLAMP(blendfac, 0.0f, 1.0f);
3579 
3580  int count_fine = 1.0f / gridstep;
3581  int count_large = 1.0f / (4.0f * gridstep);
3582 
3583  if (count_fine > 0) {
3587 
3589  immBegin(GPU_PRIM_LINES, 4 * count_fine + 4 * count_large);
3590 
3591  float theme_color[3];
3592  UI_GetThemeColorShade3fv(TH_GRID, (int)(20.0f * (1.0f - blendfac)), theme_color);
3593  float fac = 0.0f;
3594 
3595  /* the fine resolution level */
3596  for (int i = 0; i < count_fine; i++) {
3597  immAttr3fv(color, theme_color);
3598  immVertex2f(pos, x1, y1 * (1.0f - fac) + y2 * fac);
3599  immAttr3fv(color, theme_color);
3600  immVertex2f(pos, x2, y1 * (1.0f - fac) + y2 * fac);
3601  immAttr3fv(color, theme_color);
3602  immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y1);
3603  immAttr3fv(color, theme_color);
3604  immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y2);
3605  fac += gridstep;
3606  }
3607 
3608  if (count_large > 0) {
3609  UI_GetThemeColor3fv(TH_GRID, theme_color);
3610  fac = 0.0f;
3611 
3612  /* the large resolution level */
3613  for (int i = 0; i < count_large; i++) {
3614  immAttr3fv(color, theme_color);
3615  immVertex2f(pos, x1, y1 * (1.0f - fac) + y2 * fac);
3616  immAttr3fv(color, theme_color);
3617  immVertex2f(pos, x2, y1 * (1.0f - fac) + y2 * fac);
3618  immAttr3fv(color, theme_color);
3619  immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y1);
3620  immAttr3fv(color, theme_color);
3621  immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y2);
3622  fac += 4.0f * gridstep;
3623  }
3624  }
3625 
3626  immEnd();
3627  immUnbindProgram();
3628  }
3629 }
3630 
3631 /* If the area has overlapping regions, it returns visible rect for Region *region */
3632 /* rect gets returned in local region coordinates */
3633 static void region_visible_rect_calc(ARegion *region, rcti *rect)
3634 {
3635  ARegion *region_iter = region;
3636 
3637  /* allow function to be called without area */
3638  while (region_iter->prev) {
3639  region_iter = region_iter->prev;
3640  }
3641 
3642  *rect = region->winrct;
3643 
3644  /* check if a region overlaps with the current one */
3645  for (; region_iter; region_iter = region_iter->next) {
3646  if (region != region_iter && region_iter->overlap) {
3647  if (BLI_rcti_isect(rect, &region_iter->winrct, NULL)) {
3648  int alignment = RGN_ALIGN_ENUM_FROM_MASK(region_iter->alignment);
3649 
3650  if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
3651  /* Overlap left, also check 1 pixel offset (2 regions on one side). */
3652  if (abs(rect->xmin - region_iter->winrct.xmin) < 2) {
3653  rect->xmin = region_iter->winrct.xmax;
3654  }
3655 
3656  /* Overlap right. */
3657  if (abs(rect->xmax - region_iter->winrct.xmax) < 2) {
3658  rect->xmax = region_iter->winrct.xmin;
3659  }
3660  }
3661  else if (ELEM(alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
3662  /* Same logic as above for vertical regions. */
3663  if (abs(rect->ymin - region_iter->winrct.ymin) < 2) {
3664  rect->ymin = region_iter->winrct.ymax;
3665  }
3666  if (abs(rect->ymax - region_iter->winrct.ymax) < 2) {
3667  rect->ymax = region_iter->winrct.ymin;
3668  }
3669  }
3670  else if (alignment == RGN_ALIGN_FLOAT) {
3671  /* Skip floating. */
3672  }
3673  else {
3674  BLI_assert(!"Region overlap with unknown alignment");
3675  }
3676  }
3677  }
3678  }
3679  BLI_rcti_translate(rect, -region->winrct.xmin, -region->winrct.ymin);
3680 }
3681 
3683 {
3684  rcti *rect = &region->runtime.visible_rect;
3685  if (rect->xmin == 0 && rect->ymin == 0 && rect->xmax == 0 && rect->ymax == 0) {
3686  region_visible_rect_calc(region, rect);
3687  }
3688  return rect;
3689 }
3690 
3691 /* Cache display helpers */
3692 
3694 {
3695  /* Local coordinate visible rect inside region, to accommodate overlapping ui. */
3696  const rcti *rect_visible = ED_region_visible_rect(region);
3697  const int region_bottom = rect_visible->ymin;
3698 
3702  immUniformColor4ub(128, 128, 255, 64);
3703  immRecti(pos, 0, region_bottom, region->winx, region_bottom + 8 * UI_DPI_FAC);
3704  immUnbindProgram();
3705 }
3706 
3707 void ED_region_cache_draw_curfra_label(const int framenr, const float x, const float y)
3708 {
3709  const uiStyle *style = UI_style_get();
3710  int fontid = style->widget.uifont_id;
3711  char numstr[32];
3712  float font_dims[2] = {0.0f, 0.0f};
3713 
3714  /* frame number */
3715  BLF_size(fontid, 11.0f * U.pixelsize, U.dpi);
3716  BLI_snprintf(numstr, sizeof(numstr), "%d", framenr);
3717 
3718  BLF_width_and_height(fontid, numstr, sizeof(numstr), &font_dims[0], &font_dims[1]);
3719 
3724  immRecti(pos, x, y, x + font_dims[0] + 6.0f, y + font_dims[1] + 4.0f);
3725  immUnbindProgram();
3726 
3727  UI_FontThemeColor(fontid, TH_TEXT);
3728  BLF_position(fontid, x + 2.0f, y + 2.0f, 0.0f);
3729  BLF_draw(fontid, numstr, sizeof(numstr));
3730 }
3731 
3733  ARegion *region, const int num_segments, const int *points, const int sfra, const int efra)
3734 {
3735  if (num_segments) {
3736  /* Local coordinate visible rect inside region, to accommodate overlapping ui. */
3737  const rcti *rect_visible = ED_region_visible_rect(region);
3738  const int region_bottom = rect_visible->ymin;
3739 
3743  immUniformColor4ub(128, 128, 255, 128);
3744 
3745  for (int a = 0; a < num_segments; a++) {
3746  float x1 = (float)(points[a * 2] - sfra) / (efra - sfra + 1) * region->winx;
3747  float x2 = (float)(points[a * 2 + 1] - sfra + 1) / (efra - sfra + 1) * region->winx;
3748 
3749  immRecti(pos, x1, region_bottom, x2, region_bottom + 8 * UI_DPI_FAC);
3750  /* TODO(merwin): use primitive restart to draw multiple rects more efficiently */
3751  }
3752 
3753  immUnbindProgram();
3754  }
3755 }
3756 
3761 {
3762  ARegion *region = params->region;
3763  const bContext *C = params->context;
3764  struct wmMsgBus *mbus = params->message_bus;
3765 
3766  if (region->gizmo_map != NULL) {
3767  WM_gizmomap_message_subscribe(C, region->gizmo_map, region, mbus);
3768  }
3769 
3770  if (!BLI_listbase_is_empty(&region->uiblocks)) {
3771  UI_region_message_subscribe(region, mbus);
3772  }
3773 
3774  if (region->type->message_subscribe != NULL) {
3775  region->type->message_subscribe(params);
3776  }
3777 }
3778 
3780 {
3781  /* Use a larger value because toggling scrollbars can jump in size. */
3782  const int snap_match_threshold = 16;
3783  if (region->type->snap_size != NULL) {
3784  return ((((region->sizex - region->type->snap_size(region, region->sizex, 0)) <=
3785  snap_match_threshold)
3786  << 0) |
3787  (((region->sizey - region->type->snap_size(region, region->sizey, 1)) <=
3788  snap_match_threshold)
3789  << 1));
3790  }
3791  return 0;
3792 }
3793 
3794 bool ED_region_snap_size_apply(ARegion *region, int snap_flag)
3795 {
3796  bool changed = false;
3797  if (region->type->snap_size != NULL) {
3798  if (snap_flag & (1 << 0)) {
3799  short snap_size = region->type->snap_size(region, region->sizex, 0);
3800  if (snap_size != region->sizex) {
3801  region->sizex = snap_size;
3802  changed = true;
3803  }
3804  }
3805  if (snap_flag & (1 << 1)) {
3806  short snap_size = region->type->snap_size(region, region->sizey, 1);
3807  if (snap_size != region->sizey) {
3808  region->sizey = snap_size;
3809  changed = true;
3810  }
3811  }
3812  }
3813  return changed;
3814 }
typedef float(TangentPoint)[2]
struct WorkSpace * CTX_wm_workspace(const bContext *C)
Definition: context.c:704
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:714
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:689
struct bScreen * CTX_wm_screen(const bContext *C)
Definition: context.c:709
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
@ G_DEBUG
Definition: BKE_global.h:133
@ G_TRANSFORM_WM
Definition: BKE_global.h:222
void BKE_screen_area_free(struct ScrArea *area)
Definition: screen.c:709
void BKE_area_region_panels_free(struct ListBase *panels)
Definition: screen.c:652
struct ARegionType * BKE_regiontype_from_id_or_first(const struct SpaceType *st, int regionid)
#define BKE_ST_MAXNAME
Definition: BKE_screen.h:68
void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2)
Definition: screen.c:527
void BKE_spacedata_freelist(ListBase *lb)
Definition: screen.c:440
void BKE_area_region_free(struct SpaceType *st, struct ARegion *region)
Definition: screen.c:663
struct ARegion * BKE_area_region_copy(const struct SpaceType *st, const struct ARegion *region)
struct SpaceType * BKE_spacetype_from_id(int spaceid)
Definition: screen.c:382
@ PANEL_TYPE_DRAW_BOX
Definition: BKE_screen.h:305
@ PANEL_TYPE_NO_HEADER
Definition: BKE_screen.h:298
@ PANEL_TYPE_INSTANCED
Definition: BKE_screen.h:303
@ PANEL_TYPE_LAYOUT_VERT_BAR
Definition: BKE_screen.h:301
@ PANEL_TYPE_NO_SEARCH
Definition: BKE_screen.h:307
@ PANEL_TYPE_HEADER_EXPAND
Definition: BKE_screen.h:300
bool BKE_workspace_owner_id_check(const struct WorkSpace *workspace, const char *owner_id) ATTR_NONNULL()
struct bScreen * BKE_workspace_active_screen_get(const struct WorkSpaceInstanceHook *hook) GETTER_ATTRS
#define BLF_CLIPPING
Definition: BLF_api.h:270
float BLF_width(int fontid, const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: blf.c:723
void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height) ATTR_NONNULL()
Definition: blf.c:698
void BLF_draw(int fontid, const char *str, size_t len) ATTR_NONNULL(2)
Definition: blf.c:542
#define BLF_DRAW_STR_DUMMY_MAX
Definition: BLF_api.h:283
void BLF_disable(int fontid, int option)
Definition: blf.c:283
void BLF_size(int fontid, int size, int dpi)
Definition: blf.c:367
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
void BLF_position(int fontid, float x, float y, float z)
Definition: blf.c:312
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_INLINE
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:87
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:281
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
Definition: BLI_listbase.h:184
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:128
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
MINLINE int round_fl_to_int(float a)
MINLINE int min_ii(int a, int b)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
Random number functions.
float BLI_thread_frand(int thread) ATTR_WARN_UNUSED_RESULT
Definition: rand.cc:241
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:157
bool BLI_rcti_is_valid(const struct rcti *rect)
void BLI_rcti_translate(struct rcti *rect, int x, int y)
Definition: rct.c:597
void BLI_rcti_union(struct rcti *rct1, const struct rcti *rct2)
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
Definition: rct.c:446
bool BLI_rcti_isect_pt(const struct rcti *rect, const int x, const int y)
void BLI_rcti_resize(struct rcti *rect, int x, int y)
Definition: rct.c:638
void BLI_rcti_sanitize(struct rcti *rect)
Definition: rct.c:488
bool BLI_rcti_isect(const struct rcti *src1, const struct rcti *src2, struct rcti *dest)
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:153
BLI_INLINE int BLI_rcti_cent_y(const struct rcti *rct)
Definition: BLI_rect.h:140
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition: BLI_rect.h:161
BLI_INLINE int BLI_rcti_cent_x(const struct rcti *rct)
Definition: BLI_rect.h:136
void BLI_str_rstrip(char *str) ATTR_NONNULL()
Definition: string.c:915
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
unsigned int uint
Definition: BLI_sys_types.h:83
#define SWAP(type, a, b)
#define UNUSED(x)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define IS_EQF(a, b)
#define STREQ(a, b)
#define LIKELY(x)
#define HEADERY
@ PNL_PIN
#define RGN_ALIGN_ENUM_FROM_MASK(align)
@ RGN_ALIGN_BOTTOM
@ RGN_ALIGN_LEFT
@ RGN_ALIGN_TOP
@ RGN_ALIGN_RIGHT
@ RGN_SPLIT_PREV
@ RGN_ALIGN_HSPLIT
@ RGN_ALIGN_VSPLIT
@ RGN_ALIGN_NONE
@ RGN_ALIGN_FLOAT
@ RGN_ALIGN_QSPLIT
#define RGN_TYPE_LEN
#define AREAMINX
@ GLOBAL_AREA_IS_HIDDEN
@ SCREENFULL
@ SCREENNORMAL
@ AREA_FLAG_ACTIVE_TOOL_UPDATE
@ AREA_FLAG_REGION_SIZE_UPDATE
@ AREA_FLAG_STACKED_FULLSCREEN
@ AREA_FLAG_ACTIONZONES_UPDATE
@ HEADER_NO_PULLDOWN
@ RGN_DRAW_NO_REBUILD
@ RGN_DRAW_PARTIAL
@ RGN_DRAWING
@ RGN_DRAW
@ RGN_REFRESH_UI
@ RGN_DRAW_EDITOR_OVERLAYS
#define RGN_TYPE_HAS_CATEGORY_MASK
#define HEADER_PADDING_Y
@ RGN_FLAG_SEARCH_FILTER_UPDATE
@ RGN_FLAG_DYNAMIC_SIZE
@ RGN_FLAG_SIZE_CLAMP_X
@ RGN_FLAG_HIDDEN
@ RGN_FLAG_SIZE_CLAMP_Y
@ RGN_FLAG_PREFSIZE_OR_HIDDEN
@ RGN_FLAG_TOO_SMALL
@ RGN_FLAG_SEARCH_FILTER_ACTIVE
@ RGN_TYPE_CHANNELS
@ RGN_TYPE_TOOL_HEADER
@ RGN_TYPE_UI
@ RGN_TYPE_WINDOW
@ RGN_TYPE_HUD
@ RGN_TYPE_PREVIEW
@ RGN_TYPE_FOOTER
@ RGN_TYPE_HEADER
@ RGN_TYPE_TOOLS
@ RGN_TYPE_TOOL_PROPS
#define RGN_ALIGN_FLAG_FROM_MASK(align)
@ SPACE_CLIP
@ SPACE_STATUSBAR
@ SPACE_TOPBAR
@ SPACE_NODE
@ SPACE_PROPERTIES
@ SPACE_IMAGE
@ SPACE_VIEW3D
@ SPACE_FLAG_TYPE_WAS_ACTIVE
@ SPACE_FLAG_TYPE_TEMPORARY
@ USER_REGION_OVERLAP
@ USER_APP_LOCK_UI_LAYOUT
@ V2D_SCROLL_HORIZONTAL
@ V2D_SCROLL_VERTICAL_HANDLES
@ V2D_SCROLL_RIGHT
@ V2D_SCROLL_BOTTOM
@ V2D_SCROLL_HORIZONTAL_HANDLES
@ V2D_SCROLL_VERTICAL
@ V2D_LOCKOFS_X
@ V2D_LOCKOFS_Y
@ V2D_KEEPOFS_Y
@ V2D_KEEPOFS_X
const char * ED_buttons_search_string_get(struct SpaceProperties *sbuts)
void ED_region_visibility_change_update_animated(struct bContext *C, struct ScrArea *area, struct ARegion *region)
Definition: screen_ops.c:5170
void ED_area_exit(struct bContext *C, struct ScrArea *area)
Definition: screen_edit.c:603
@ ED_KEYMAP_NAVBAR
Definition: ED_screen.h:449
@ ED_KEYMAP_UI
Definition: ED_screen.h:440
@ ED_KEYMAP_ANIMATION
Definition: ED_screen.h:444
@ ED_KEYMAP_HEADER
Definition: ED_screen.h:446
@ ED_KEYMAP_TOOL
Definition: ED_screen.h:442
@ ED_KEYMAP_GPENCIL
Definition: ED_screen.h:448
@ ED_KEYMAP_GIZMO
Definition: ED_screen.h:441
@ ED_KEYMAP_VIEW2D
Definition: ED_screen.h:443
@ ED_KEYMAP_FRAMES
Definition: ED_screen.h:445
@ ED_KEYMAP_FOOTER
Definition: ED_screen.h:447
struct AZone * ED_area_azones_update(ScrArea *area, const int mouse_xy[])
int ED_screen_area_active(const struct bContext *C)
@ AZONE_REGION
@ AZONE_FULLSCREEN
@ AZONE_REGION_SCROLL
@ AZONE_AREA
AZScrollDirection
@ AZ_SCROLL_HOR
@ AZ_SCROLL_VERT
AZEdge
@ AE_LEFT_TO_TOPRIGHT
@ AE_RIGHT_TO_TOPLEFT
@ AE_BOTTOM_TO_TOPLEFT
@ AE_TOP_TO_BOTTOMRIGHT
void ED_region_draw_cb_draw(const struct bContext *, struct ARegion *, int)
#define REGION_DRAW_POST_PIXEL
Definition: ED_space_api.h:67
NSNotificationCenter * center
struct GPUFrameBuffer GPUFrameBuffer
GPUFrameBuffer * GPU_framebuffer_active_get(void)
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
void immUniformColor4f(float r, float g, float b, float a)
void immUnbindProgram(void)
void immVertex2f(uint attr_id, float x, float y)
void immUniformThemeColor(int color_id)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immBeginAtMost(GPUPrimType, uint max_vertex_len)
void immUniformColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
void immUniformColor4fv(const float rgba[4])
GPUVertFormat * immVertexFormat(void)
void immUniformThemeColorBlendShade(int color_id1, int color_id2, float fac, int offset)
void immAttr3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void immEnd(void)
void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2)
void immRecti(uint pos, int x1, int y1, int x2, int y2)
void immRectf(uint pos, float x1, float y1, float x2, float y2)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble y1
_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 const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble x2
_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 y
void GPU_matrix_pop(void)
Definition: gpu_matrix.cc:142
void GPU_matrix_push(void)
Definition: gpu_matrix.cc:135
void GPU_matrix_identity_set(void)
Definition: gpu_matrix.cc:184
void GPU_matrix_translate_2f(float x, float y)
Definition: gpu_matrix.cc:190
@ GPU_PRIM_TRI_FAN
Definition: GPU_primitive.h:41
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:36
@ GPU_SHADER_2D_UNIFORM_COLOR
Definition: GPU_shader.h:171
@ GPU_SHADER_3D_UNIFORM_COLOR
Definition: GPU_shader.h:200
@ GPU_SHADER_2D_FLAT_COLOR
Definition: GPU_shader.h:178
@ GPU_BLEND_NONE
Definition: GPU_state.h:55
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:57
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:55
void GPU_line_width(float width)
Definition: gpu_state.cc:173
void GPU_scissor(int x, int y, int width, int height)
Definition: gpu_state.cc:204
void GPU_scissor_get(int coords[4])
Definition: gpu_state.cc:274
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT_TO_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
void GPU_vertformat_clear(GPUVertFormat *)
@ GPU_COMP_F32
@ GPU_COMP_I32
Contains defines and structs used throughout the imbuf module.
void IMB_metadata_foreach(struct ImBuf *ibuf, IMBMetadataForeachCb callback, void *userdata)
Definition: metadata.c:107
Read Guarded memory(de)allocation.
Group RGB to Bright Vector Camera CLAMP
StructRNA RNA_Space
StructRNA RNA_Area
#define C
Definition: RandGen.cpp:39
#define UI_UNIT_Y
void UI_panel_category_clear_all(struct ARegion *region)
void UI_blocklist_free(const struct bContext *C, struct ListBase *lb)
void UI_panel_category_draw_all(struct ARegion *region, const char *category_id_active)
@ UI_EMBOSS
Definition: UI_interface.h:107
void UI_panels_begin(const struct bContext *C, struct ARegion *region)
const struct uiStyle * UI_style_get_dpi(void)
void UI_panel_header_buttons_begin(struct Panel *panel)
bool UI_block_apply_search_filter(uiBlock *block, const char *search_filter)
@ UI_CNR_BOTTOM_LEFT
@ UI_CNR_BOTTOM_RIGHT
@ UI_CNR_ALL
@ UI_CNR_TOP_LEFT
@ UI_CNR_TOP_RIGHT
@ UI_LAYOUT_PANEL
@ UI_LAYOUT_VERT_BAR
@ UI_LAYOUT_TOOLBAR
@ UI_LAYOUT_HEADER
void UI_panel_label_offset(const struct uiBlock *block, int *r_x, int *r_y)
void uiLayoutSetScaleY(uiLayout *layout, float scale)
void UI_blocklist_update_window_matrix(const struct bContext *C, const struct ListBase *lb)
const char * UI_panel_category_active_get(struct ARegion *region, bool set_fallback)
int UI_panel_size_y(const struct Panel *panel)
void uiItemL(uiLayout *layout, const char *name, int icon)
const struct uiStyle * UI_style_get(void)
void UI_blocklist_free_inactive(const struct bContext *C, struct ListBase *lb)
struct Panel * UI_panel_find_by_type(struct ListBase *lb, const struct PanelType *pt)
void UI_draw_roundbox_corner_set(int type)
void uiItemS(uiLayout *layout)
void UI_region_message_subscribe(struct ARegion *region, struct wmMsgBus *mbus)
Definition: interface.c:2092
struct PanelCategoryDyn * UI_panel_category_find(const struct ARegion *region, const char *idname)
bool UI_panel_is_active(const struct Panel *panel)
void UI_panel_end(struct Panel *panel, int width, int height)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void UI_list_panel_unique_str(struct Panel *panel, char *r_name)
void UI_panels_free_instanced(const struct bContext *C, struct ARegion *region)
#define UI_HEADER_OFFSET
void UI_panel_category_add(struct ARegion *region, const char *name)
void UI_block_end(const struct bContext *C, uiBlock *block)
uiBut * uiDefButR(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, struct PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip)
Definition: interface.c:5144
#define UI_PANEL_BOX_STYLE_MARGIN
Definition: UI_interface.h:251
#define UI_MAX_DRAW_STR
Definition: UI_interface.h:90
#define UI_DPI_FAC
Definition: UI_interface.h:309
uiLayout * UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, const struct uiStyle *style)
void UI_panel_header_buttons_end(struct Panel *panel)
void UI_panels_end(const struct bContext *C, struct ARegion *region, int *r_x, int *r_y)
#define UI_PANEL_CATEGORY_MARGIN_WIDTH
Definition: UI_interface.h:249
bool UI_panel_category_is_visible(const struct ARegion *region)
int uiLayoutGetWidth(uiLayout *layout)
void UI_draw_roundbox_aa(const struct rctf *rect, bool filled, float rad, const float color[4])
uiBlock * UI_block_begin(const struct bContext *C, struct ARegion *region, const char *name, eUIEmbossType emboss)
void UI_block_layout_free(uiBlock *block)
void UI_blocklist_draw(const struct bContext *C, const struct ListBase *lb)
void UI_panels_draw(const struct bContext *C, struct ARegion *region)
void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y)
void UI_region_handlers_add(struct ListBase *handlers)
struct Panel * UI_panel_begin(struct ARegion *region, struct ListBase *lb, uiBlock *block, struct PanelType *pt, struct Panel *panel, bool *r_open)
#define UI_UNIT_X
@ UI_LAYOUT_VERTICAL
@ UI_LAYOUT_HORIZONTAL
@ UI_BTYPE_MENU
Definition: UI_interface.h:338
void UI_block_translate(uiBlock *block, int x, int y)
Definition: interface.c:353
#define INSTANCED_PANEL_UNIQUE_STR_LEN
bool UI_panel_is_closed(const struct Panel *panel)
void UI_block_set_search_only(uiBlock *block, bool search_only)
Definition: interface.c:3561
bool UI_panel_is_dragging(const struct Panel *panel)
void UI_icon_draw_ex(float x, float y, int icon_id, float aspect, float alpha, float desaturate, const uchar mono_color[4], const bool mono_border)
void UI_GetThemeColor3fv(int colorid, float col[3])
Definition: resources.c:1191
ThemeColorID
Definition: UI_resources.h:49
@ TH_HEADER
Definition: UI_resources.h:66
@ TH_GRID
Definition: UI_resources.h:84
@ TH_BACK
Definition: UI_resources.h:55
@ TH_PREVIEW_BACK
Definition: UI_resources.h:232
@ TH_CFRAME
Definition: UI_resources.h:113
@ TH_HEADERDESEL
Definition: UI_resources.h:67
@ TH_EDITOR_OUTLINE
Definition: UI_resources.h:310
@ TH_TEXT
Definition: UI_resources.h:58
@ TH_TEXT_HI
Definition: UI_resources.h:59
void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3])
Definition: resources.c:1218
void UI_ThemeClearColor(int colorid)
Definition: resources.c:1478
void UI_GetThemeColor4fv(int colorid, float col[4])
Definition: resources.c:1199
void UI_FontThemeColor(int fontid, int colorid)
Definition: resources.c:1156
void UI_SetTheme(int spacetype, int regionid)
Definition: resources.c:1064
#define UI_MARKER_MARGIN_Y
Definition: UI_view2d.h:282
void UI_view2d_region_reinit(struct View2D *v2d, short type, int winx, int winy)
Definition: view2d.c:240
void UI_view2d_totRect_set(struct View2D *v2d, int width, int height)
Definition: view2d.c:1052
void UI_view2d_view_restore(const struct bContext *C)
void UI_view2d_view_ortho(const struct View2D *v2d)
void UI_view2d_view_to_region(const struct View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) ATTR_NONNULL()
void UI_view2d_mask_from_win(const struct View2D *v2d, struct rcti *r_mask)
void UI_view2d_scrollers_draw(struct View2D *v2d, const struct rcti *mask_custom)
@ V2D_COMMONVIEW_HEADER
Definition: UI_view2d.h:57
@ V2D_COMMONVIEW_PANELS_UI
Definition: UI_view2d.h:59
#define WM_TOOLSYSTEM_SPACE_MASK
Definition: WM_toolsystem.h:43
#define NC_WINDOW
Definition: WM_types.h:277
#define ND_FILEREAD
Definition: WM_types.h:311
#define ND_SPACE_CHANGED
Definition: WM_types.h:432
#define NC_WM
Definition: WM_types.h:276
#define NC_SPACE
Definition: WM_types.h:293
void ED_area_do_mgs_subscribe_for_tool_header(const wmRegionMessageSubscribeParams *params)
Definition: area.c:441
void ED_area_tag_redraw(ScrArea *area)
Definition: area.c:745
const char * ED_area_region_search_filter_get(const ScrArea *area, const ARegion *region)
Definition: area.c:786
static void region_align_info_from_area(ScrArea *area, struct RegionTypeAlignInfo *r_align_info)
Definition: area.c:2134
int ED_region_snap_size_test(const ARegion *region)
Definition: area.c:3779
ScrArea * ED_screen_areas_iter_first(const wmWindow *win, const bScreen *screen)
Definition: area.c:3398
bool ED_area_has_shared_border(struct ScrArea *a, struct ScrArea *b)
Definition: area.c:1900
bool ED_region_property_search(const bContext *C, ARegion *region, ListBase *paneltypes, const char *contexts[], const char *category_override)
Definition: area.c:3169
void ED_region_tag_refresh_ui(ARegion *region)
Definition: area.c:695
void ED_area_do_mgs_subscribe_for_tool_ui(const wmRegionMessageSubscribeParams *params)
Definition: area.c:457
void ED_region_update_rect(ARegion *region)
Definition: area.c:1996
BLI_INLINE bool streq_array_any(const char *s, const char *arr[])
Definition: area.c:2609
static bool panel_add_check(const bContext *C, const WorkSpace *workspace, const char *contexts[], const char *category_override, PanelType *panel_type)
Definition: area.c:2779
void ED_region_cursor_set(wmWindow *win, ScrArea *area, ARegion *region)
Definition: area.c:2012
void ED_region_do_listen(wmRegionListenerParams *params)
Definition: area.c:144
int ED_area_global_size_y(const ScrArea *area)
Definition: area.c:3377
void ED_region_search_filter_update(const ScrArea *area, ARegion *region)
Definition: area.c:802
void ED_region_toggle_hidden(bContext *C, ARegion *region)
Definition: area.c:2059
static bool region_uses_category_tabs(const ScrArea *area, const ARegion *region)
Definition: area.c:2819
struct MetadataPanelDrawContext MetadataPanelDrawContext
static void area_azone_tag_update(ScrArea *area)
Definition: area.c:307
int ED_area_global_min_size_y(const ScrArea *area)
Definition: area.c:3382
RegionEmbossSide
Definition: area.c:75
@ REGION_EMBOSS_BOTTOM
Definition: area.c:78
@ REGION_EMBOSS_ALL
Definition: area.c:80
@ REGION_EMBOSS_TOP
Definition: area.c:77
@ REGION_EMBOSS_LEFT
Definition: area.c:76
@ REGION_EMBOSS_RIGHT
Definition: area.c:79
static int rct_fits(const rcti *rect, char dir, int size)
Definition: area.c:1175
void ED_region_tag_redraw_editor_overlays(struct ARegion *region)
Definition: area.c:706
void ED_region_floating_init(ARegion *region)
Definition: area.c:2002
ScrArea * ED_screen_areas_iter_next(const bScreen *screen, const ScrArea *area)
Definition: area.c:3411
static short region_alignment_from_header_and_tool_header_state(const struct RegionTypeAlignInfo *region_align_info, const short fallback)
Definition: area.c:2158
void ED_area_status_text(ScrArea *area, const char *str)
Definition: area.c:815
static void region_draw_azones(ScrArea *area, ARegion *region)
Definition: area.c:312
void ED_area_tag_redraw_no_rebuild(ScrArea *area)
Definition: area.c:754
int ED_area_global_max_size_y(const ScrArea *area)
Definition: area.c:3387
void ED_region_panels(const bContext *C, ARegion *region)
Definition: area.c:3083
void ED_region_info_draw(ARegion *region, const char *text, float fill_color[4], const bool full_redraw)
Definition: area.c:3510
void region_toggle_hidden(bContext *C, ARegion *region, const bool do_fade)
Definition: area.c:2043
void ED_region_header(const bContext *C, ARegion *region)
Definition: area.c:3351
static void region_overlap_fix(ScrArea *area, ARegion *region)
Definition: area.c:1188
void ED_area_do_listen(wmSpaceTypeListenerParams *params)
Definition: area.c:167
static bool panel_property_search(const bContext *C, ARegion *region, const uiStyle *style, Panel *panel, PanelType *panel_type, const char *search_filter)
Definition: area.c:3104
void ED_region_do_msg_notify_tag_redraw(bContext *UNUSED(C), wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
Definition: area.c:407
int ED_area_headersize(void)
Definition: area.c:3363
void ED_region_cache_draw_cached_segments(ARegion *region, const int num_segments, const int *points, const int sfra, const int efra)
Definition: area.c:3732
void ED_region_header_init(ARegion *region)
Definition: area.c:3358
bool ED_area_is_global(const ScrArea *area)
Definition: area.c:3393
void ED_region_cache_draw_background(ARegion *region)
Definition: area.c:3693
void ED_area_swapspace(bContext *C, ScrArea *sa1, ScrArea *sa2)
Definition: area.c:2346
static void region_draw_emboss(const ARegion *region, const rcti *scirct, int sides)
Definition: area.c:86
static void area_calc_totrct(ScrArea *area, const rcti *window_rect)
Definition: area.c:1617
void ED_area_data_copy(ScrArea *area_dst, ScrArea *area_src, const bool do_free)
Definition: area.c:2067
static void region_align_info_to_area(ScrArea *area, const struct RegionTypeAlignInfo region_align_info_src[RGN_TYPE_LEN])
Definition: area.c:2319
void ED_region_header_draw(const bContext *C, ARegion *region)
Definition: area.c:3334
static void region_azone_edge_init(ScrArea *area, ARegion *region, AZEdge edge, const bool is_fullscreen)
Definition: area.c:1060
void ED_region_tag_redraw_no_rebuild(ARegion *region)
Definition: area.c:686
void ED_area_tag_redraw_regiontype(ScrArea *area, int regiontype)
Definition: area.c:763
bool ED_region_snap_size_apply(ARegion *region, int snap_flag)
Definition: area.c:3794
bool ED_region_is_overlap(int spacetype, int regiontype)
Definition: area.c:1259
static void metadata_panel_draw_field(const char *field, const char *value, void *ctx_v)
Definition: area.c:3523
void ED_region_tag_redraw_partial(ARegion *region, const rcti *rct, bool rebuild)
Definition: area.c:718
static const char * region_panels_collect_categories(ARegion *region, LinkNode *panel_types_stack, bool *use_category_tabs)
Definition: area.c:2827
static void region_azone_scrollbar_init(ScrArea *area, ARegion *region, AZScrollDirection direction)
Definition: area.c:1085
static void region_visible_rect_calc(ARegion *region, rcti *rect)
Definition: area.c:3633
void ED_area_do_msg_notify_tag_refresh(bContext *UNUSED(C), wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
Definition: area.c:430
static void region_azones_add(const bScreen *screen, ScrArea *area, ARegion *region)
Definition: area.c:1148
void ED_region_visibility_change_update(bContext *C, ScrArea *area, ARegion *region)
Definition: area.c:2032
static void area_azone_init(wmWindow *win, const bScreen *screen, ScrArea *area)
Definition: area.c:872
void ED_region_do_layout(bContext *C, ARegion *region)
Definition: area.c:505
void ED_region_tag_redraw_cursor(ARegion *region)
Definition: area.c:679
void ED_area_newspace(bContext *C, ScrArea *area, int type, const bool skip_region_exit)
Definition: area.c:2375
static void area_draw_azone_fullscreen(short UNUSED(x1), short UNUSED(y1), short x2, short y2, float alpha)
Corner widget use for quitting fullscreen.
Definition: area.c:188
void ED_region_pixelspace(ARegion *region)
Definition: area.c:137
void ED_region_cache_draw_curfra_label(const int framenr, const float x, const float y)
Definition: area.c:3707
void ED_area_data_swap(ScrArea *area_dst, ScrArea *area_src)
Definition: area.c:2100
void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *area)
Definition: area.c:1865
void ED_area_tag_refresh(ScrArea *area)
Definition: area.c:774
static void region_azone_tab_plus(ScrArea *area, AZone *az, ARegion *region)
Definition: area.c:1001
static void ed_default_handlers(wmWindowManager *wm, ScrArea *area, ARegion *region, ListBase *handlers, int flag)
Definition: area.c:1677
static bool region_azone_edge_poll(const ARegion *region, const bool is_fullscreen)
Definition: area.c:1046
#define AZONEPAD_EDGE
Definition: area.c:967
int ED_area_footersize(void)
Definition: area.c:3369
void ED_area_do_refresh(bContext *C, ScrArea *area)
Definition: area.c:176
static void region_azone_edge(AZone *az, ARegion *region)
Definition: area.c:969
static void region_clear_color(const bContext *C, const ARegion *region, ThemeColorID colorid)
Definition: area.c:2591
void ED_region_panels_layout(const bContext *C, ARegion *region)
Definition: area.c:3030
void ED_region_panels_init(wmWindowManager *wm, ARegion *region)
Definition: area.c:3090
void ED_workspace_status_text(bContext *C, const char *str)
Definition: area.c:840
void ED_region_image_metadata_panel_draw(ImBuf *ibuf, uiLayout *layout)
Definition: area.c:3531
static bool event_in_markers_region(const ARegion *region, const wmEvent *event)
Definition: area.c:1667
static void region_draw_azone_tab_arrow(ScrArea *area, ARegion *region, AZone *az)
Definition: area.c:270
static void region_update_rect(ARegion *region)
Definition: area.c:1984
int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco)
Definition: area.c:2540
static void ed_panel_draw(const bContext *C, ARegion *region, ListBase *lb, PanelType *pt, Panel *panel, int w, int em, char *unique_panel_str, const char *search_filter)
Definition: area.c:2628
static void region_subwindow(ARegion *region)
Definition: area.c:1656
static ThemeColorID region_background_color_id(const bContext *C, const ARegion *region)
Definition: area.c:2571
void ED_region_do_draw(bContext *C, ARegion *region)
Definition: area.c:529
void ED_region_tag_redraw(ARegion *region)
Definition: area.c:667
void ED_region_panels_layout_ex(const bContext *C, ARegion *region, ListBase *paneltypes, const char *contexts[], const char *category_override)
Definition: area.c:2856
void ED_region_message_subscribe(wmRegionMessageSubscribeParams *params)
Definition: area.c:3760
static void region_align_info_to_area_for_headers(const struct RegionTypeAlignInfo *region_align_info_src, const struct RegionTypeAlignInfo *region_align_info_dst, ARegion *region_by_type[RGN_TYPE_LEN])
Definition: area.c:2204
void ED_region_grid_draw(ARegion *region, float zoomx, float zoomy, float x0, float y0)
Definition: area.c:3538
static void region_draw_status_text(ScrArea *area, ARegion *region)
Definition: area.c:357
static SpaceLink * area_get_prevspace(ScrArea *area)
Definition: area.c:2493
static void fullscreen_azone_init(ScrArea *area, ARegion *region)
Definition: area.c:940
void ED_area_prevspace(bContext *C, ScrArea *area)
Definition: area.c:2515
static bool area_is_pseudo_minimized(const ScrArea *area)
Definition: area.c:499
static void area_draw_azone(short UNUSED(x1), short UNUSED(y1), short UNUSED(x2), short UNUSED(y2))
Corner widgets use for dragging and splitting the view.
Definition: area.c:204
static void region_rect_recursive(ScrArea *area, ARegion *region, rcti *remainder, rcti *overlap_remainder, int quad)
Definition: area.c:1285
void ED_area_init(wmWindowManager *wm, wmWindow *win, ScrArea *area)
Definition: area.c:1906
int ED_region_global_size_y(void)
Definition: area.c:3432
static void draw_azone_arrow(float x1, float y1, float x2, float y2, AZEdge edge)
Edge widgets to show hidden panels such as the toolbar and headers.
Definition: area.c:212
static void region_azones_scrollbars_init(ScrArea *area, ARegion *region)
Definition: area.c:1113
void ED_region_panels_ex(const bContext *C, ARegion *region, const char *contexts[])
Definition: area.c:3076
static void region_azones_add_edge(ScrArea *area, ARegion *region, const int alignment, const bool is_fullscreen)
Definition: area.c:1127
void ED_region_panels_draw(const bContext *C, ARegion *region)
Definition: area.c:3035
void ED_region_header_layout(const bContext *C, ARegion *region)
Definition: area.c:3246
void ED_region_info_draw_multiline(ARegion *region, const char *text_array[], float fill_color[4], const bool full_redraw)
Definition: area.c:3437
const rcti * ED_region_visible_rect(ARegion *region)
Definition: area.c:3682
ATTR_WARN_UNUSED_RESULT const BMLoop * l
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
unsigned int U
Definition: btGjkEpa3.h:78
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
Scene scene
static CCL_NAMESPACE_BEGIN const double alpha
#define str(s)
uint pos
GPUBatch * quad
void GPU_clear_color(float red, float green, float blue, float alpha)
BLI_INLINE float fb(float length, float L)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
int count
#define floorf(x)
#define fabsf(x)
format
Definition: logImageCore.h:47
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static void add(GHash *messages, MemArena *memarena, const Message *msg)
Definition: msgfmt.c:268
static unsigned a[3]
Definition: RandGen.cpp:92
double sign(double arg)
Definition: utility.h:250
static void area(int d1, int d2, int e1, int e2, float weights[2])
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:146
int area_getorientation(ScrArea *area, ScrArea *sb)
Definition: screen_edit.c:285
#define AZONESPOTW
Definition: screen_intern.h:32
#define AZONESPOTH
Definition: screen_intern.h:33
#define AZONEFADEIN
Definition: screen_intern.h:34
#define AZONEFADEOUT
Definition: screen_intern.h:35
void(* draw)(const struct bContext *C, struct ARegion *region)
Definition: BKE_screen.h:169
void(* message_subscribe)(const wmRegionMessageSubscribeParams *params)
Definition: BKE_screen.h:185
void(* cursor)(struct wmWindow *win, struct ScrArea *area, struct ARegion *region)
Definition: BKE_screen.h:197
int(* snap_size)(const struct ARegion *region, int size, int axis)
Definition: BKE_screen.h:181
void(* listener)(const wmRegionListenerParams *params)
Definition: BKE_screen.h:183
ListBase headertypes
Definition: BKE_screen.h:219
void(* layout)(const struct bContext *C, struct ARegion *region)
Definition: BKE_screen.h:179
ListBase paneltypes
Definition: BKE_screen.h:216
short do_lock
Definition: BKE_screen.h:229
const char * category
short do_draw_paintcursor
ARegion_Runtime runtime
struct ARegion * prev
char * headerstr
struct ARegion * next
ListBase panels
ListBase handlers
short alignment
short regiontype
struct wmGizmoMap * gizmo_map
struct ARegionType * type
ListBase uiblocks
short y2
float alpha
AZEdge edge
ARegion * region
short x1
short x2
short y1
struct HeaderType * type
Definition: BKE_screen.h:366
struct uiLayout * layout
Definition: BKE_screen.h:367
struct LinkNode * next
Definition: BLI_linklist.h:39
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
uiLayout * layout
Definition: area.c:3520
char owner_id[BKE_ST_MAXNAME]
Definition: BKE_screen.h:247
void(* draw)(const struct bContext *C, struct Panel *panel)
Definition: BKE_screen.h:266
void(* draw_header_preset)(const struct bContext *C, struct Panel *panel)
Definition: BKE_screen.h:264
bool(* poll)(const struct bContext *C, struct PanelType *pt)
Definition: BKE_screen.h:260
void(* draw_header)(const struct bContext *C, struct Panel *panel)
Definition: BKE_screen.h:262
char idname[BKE_ST_MAXNAME]
Definition: BKE_screen.h:241
char context[BKE_ST_MAXNAME]
Definition: BKE_screen.h:245
ListBase children
Definition: BKE_screen.h:289
char category[BKE_ST_MAXNAME]
Definition: BKE_screen.h:246
struct PanelType * parent
Definition: BKE_screen.h:288
struct PanelType * type
short labelofs
struct uiLayout * layout
short flag
ListBase children
struct RegionTypeAlignInfo::@482 by_type[RGN_TYPE_LEN]
ListBase areabase
ListBase spacedata
struct SpaceType * type
ListBase regionbase
ScrGlobalAreaData * global
void(* free)(struct SpaceLink *sl)
Definition: BKE_screen.h:88
struct SpaceLink *(* create)(const struct ScrArea *area, const struct Scene *scene)
Definition: BKE_screen.h:86
char alpha_vert
short keepofs
short winy
short scroll
ListBase areabase
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
short panelspace
uiFontStyle widget
int y
Definition: WM_types.h:581
int x
Definition: WM_types.h:581
unsigned int data
Definition: WM_types.h:260
unsigned int category
Definition: WM_types.h:260
const struct bContext * context
Definition: BKE_screen.h:150
struct wmMsgBus * message_bus
struct wmKeyConfig * defaultconf
struct wmEvent * eventstate
ScrAreaMap global_areas
struct WorkSpaceInstanceHook * workspace_hook
bool ED_time_scrub_event_in_region(const ARegion *region, const wmEvent *event)
__forceinline const avxi abs(const avxi &a)
Definition: util_avxi.h:186
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
#define G(x, y, z)
void WM_cursor_set(wmWindow *win, int curs)
Definition: wm_cursors.c:142
bool WM_cursor_set_from_tool(struct wmWindow *win, const ScrArea *area, const ARegion *region)
Definition: wm_cursors.c:190
@ WM_CURSOR_DEFAULT
Definition: wm_cursors.h:34
bool WM_region_use_viewport(ScrArea *area, ARegion *region)
Definition: wm_draw.c:310
struct wmEventHandler_Keymap * WM_event_add_keymap_handler_dynamic(ListBase *handlers, wmEventHandler_KeymapDynamicFn *keymap_fn, void *user_data)
wmKeyMap * WM_event_get_keymap_from_toolsystem_fallback(wmWindowManager *wm, wmEventHandler_Keymap *handler)
wmEventHandler_Keymap * WM_event_add_keymap_handler_poll(ListBase *handlers, wmKeyMap *keymap, EventHandlerPoll poll)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmKeyMap * WM_event_get_keymap_from_toolsystem(wmWindowManager *wm, wmEventHandler_Keymap *handler)
wmEventHandler_Keymap * WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
void WM_event_remove_handlers(bContext *C, ListBase *handlers)
void WM_event_add_mousemove(wmWindow *win)
PointerRNA * ptr
Definition: wm_files.c:3157
bool WM_gizmomap_cursor_set(const wmGizmoMap *gzmap, wmWindow *win)
Definition: wm_gizmo_map.c:988
void WM_gizmomap_add_handlers(ARegion *region, wmGizmoMap *gzmap)
Definition: wm_gizmo_map.c:792
void WM_gizmomap_message_subscribe(const bContext *C, wmGizmoMap *gzmap, ARegion *region, struct wmMsgBus *mbus)
wmGizmoMap * WM_gizmomap_new_from_type(const struct wmGizmoMapType_Params *gzmap_params)
Definition: wm_gizmo_map.c:182
wmKeyMap * WM_keymap_ensure(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
Definition: wm_keymap.c:852
void WM_msgbus_clear_by_owner(struct wmMsgBus *mbus, void *owner)
#define WM_msg_subscribe_rna_prop(mbus, id_, data_, type_, prop_, value)
void WM_msg_subscribe_rna(struct wmMsgBus *mbus, PointerRNA *ptr, const PropertyRNA *prop, const wmMsgSubscribeValue *msg_val_params, const char *id_repr)
void wmPartialViewport(rcti *drawrct, const rcti *winrct, const rcti *partialrct)
Definition: wm_subwindow.c:49
void wmOrtho2_region_pixelspace(const ARegion *region)
Definition: wm_subwindow.c:120
void WM_toolsystem_refresh_screen_area(WorkSpace *workspace, ViewLayer *view_layer, ScrArea *area)
bool WM_window_is_fullscreen(const wmWindow *win)
Definition: wm_window.c:2187
bScreen * WM_window_get_active_screen(const wmWindow *win)
Definition: wm_window.c:2372
ViewLayer * WM_window_get_active_view_layer(const wmWindow *win)
Definition: wm_window.c:2286
WorkSpace * WM_window_get_active_workspace(const wmWindow *win)
Definition: wm_window.c:2335
void WM_window_rect_calc(const wmWindow *win, rcti *r_rect)
Definition: wm_window.c:2146
int WM_window_pixels_x(const wmWindow *win)
Definition: wm_window.c:2130
Scene * WM_window_get_active_scene(const wmWindow *win)
Definition: wm_window.c:2249