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