Blender  V3.3
wm_gizmo_map.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2014 Blender Foundation. All rights reserved. */
3 
8 #include <string.h>
9 
10 #include "BLI_buffer.h"
11 #include "BLI_ghash.h"
12 #include "BLI_listbase.h"
13 #include "BLI_math.h"
14 #include "BLI_math_bits.h"
15 #include "BLI_rect.h"
16 
17 #include "BKE_context.h"
18 #include "BKE_global.h"
19 #include "BKE_main.h"
20 
21 #include "ED_screen.h"
22 #include "ED_select_utils.h"
23 #include "ED_view3d.h"
24 
25 #include "GPU_framebuffer.h"
26 #include "GPU_matrix.h"
27 #include "GPU_platform.h"
28 #include "GPU_select.h"
29 #include "GPU_state.h"
30 #include "GPU_viewport.h"
31 
32 #include "MEM_guardedalloc.h"
33 
34 #include "WM_api.h"
35 #include "WM_types.h"
36 #include "wm_event_system.h"
37 
38 /* for tool-tips */
39 #include "UI_interface.h"
40 
41 #include "DEG_depsgraph.h"
42 
43 /* own includes */
44 #include "wm_gizmo_intern.h"
45 #include "wm_gizmo_wmapi.h"
46 
52 
56 /* so operator removal can trigger update */
62 
66 
68 
72 enum {
76 };
77 
78 /* -------------------------------------------------------------------- */
86 {
88  if (len <= msel->len_alloc) {
89  return;
90  }
91  msel->items = MEM_reallocN(msel->items, sizeof(*msel->items) * len);
92  msel->len_alloc = len;
93 }
94 
96 {
98  MEM_SAFE_FREE(msel->items);
99  msel->len = 0;
100  msel->len_alloc = 0;
101 }
102 
103 void wm_gizmomap_select_array_shrink(wmGizmoMap *gzmap, int len_subtract)
104 {
106  msel->len -= len_subtract;
107  if (msel->len <= 0) {
109  }
110  else {
111  if (msel->len < msel->len_alloc / 2) {
112  msel->items = MEM_reallocN(msel->items, sizeof(*msel->items) * msel->len);
113  msel->len_alloc = msel->len;
114  }
115  }
116 }
117 
119 {
121  BLI_assert(msel->len <= msel->len_alloc);
122  if (msel->len == msel->len_alloc) {
123  msel->len_alloc = (msel->len + 1) * 2;
124  msel->items = MEM_reallocN(msel->items, sizeof(*msel->items) * msel->len_alloc);
125  }
126  msel->items[msel->len++] = gz;
127 }
128 
130 {
132  /* remove gizmo from selected_gizmos array */
133  for (int i = 0; i < msel->len; i++) {
134  if (msel->items[i] == gz) {
135  for (int j = i; j < (msel->len - 1); j++) {
136  msel->items[j] = msel->items[j + 1];
137  }
139  break;
140  }
141  }
142 }
143 
146 /* -------------------------------------------------------------------- */
151  wmGizmoMap *gzmap)
152 {
153  gzmap->type = gzmap_type;
154  gzmap->is_init = true;
156 
157  /* create all gizmo-groups for this gizmo-map. We may create an empty one
158  * too in anticipation of gizmos from operators etc */
159  LISTBASE_FOREACH (wmGizmoGroupTypeRef *, gzgt_ref, &gzmap_type->grouptype_refs) {
160  wm_gizmogroup_new_from_type(gzmap, gzgt_ref->type);
161  }
162 
163  return gzmap;
164 }
165 
167 {
168  wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(gzmap_params);
169  wmGizmoMap *gzmap = MEM_callocN(sizeof(wmGizmoMap), "GizmoMap");
170  wm_gizmomap_new_from_type_ex(gzmap_type, gzmap);
171  return gzmap;
172 }
173 
175 {
176  /* Clear first so further calls don't waste time trying to maintain correct array state. */
178 
179  for (wmGizmoGroup *gzgroup = gzmap->groups.first, *gzgroup_next; gzgroup;
180  gzgroup = gzgroup_next) {
181  gzgroup_next = gzgroup->next;
182  BLI_assert(gzgroup->parent_gzmap == gzmap);
183  wm_gizmogroup_free(NULL, gzgroup);
184  }
186 }
187 
189 {
190  wm_gizmomap_free_data(gzmap);
191  MEM_freeN(gzmap);
192 }
193 
195 {
196  wmGizmoMapType *gzmap_type = gzmap->type;
197  wm_gizmomap_free_data(gzmap);
198  memset(gzmap, 0x0, sizeof(*gzmap));
199  wm_gizmomap_new_from_type_ex(gzmap_type, gzmap);
200 }
201 
202 wmGizmoGroup *WM_gizmomap_group_find(struct wmGizmoMap *gzmap, const char *idname)
203 {
204  wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false);
205  if (gzgt) {
206  return WM_gizmomap_group_find_ptr(gzmap, gzgt);
207  }
208  return NULL;
209 }
210 
212  const struct wmGizmoGroupType *gzgt)
213 {
214  LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
215  if (gzgroup->type == gzgt) {
216  return gzgroup;
217  }
218  }
219  return NULL;
220 }
221 
223 {
224  return &gzmap->groups;
225 }
226 
228 {
229  return gzmap->gzmap_context.select.len != 0;
230 }
231 
233 {
234  return gzmap->gzmap_context.modal;
235 }
236 
237 bool WM_gizmomap_minmax(const wmGizmoMap *gzmap,
238  bool UNUSED(use_hidden),
239  bool use_select,
240  float r_min[3],
241  float r_max[3])
242 {
243  if (use_select) {
244  int i;
245  for (i = 0; i < gzmap->gzmap_context.select.len; i++) {
246  minmax_v3v3_v3(r_min, r_max, gzmap->gzmap_context.select.items[i]->matrix_basis[3]);
247  }
248  return i != 0;
249  }
250 
251  bool ok = false;
252  BLI_assert_msg(0, "TODO");
253  return ok;
254 }
255 
266  wmGizmoMap *gzmap,
267  bool (*poll)(const wmGizmo *, void *),
268  void *data,
269  const eWM_GizmoFlag flag_exclude)
270 {
271  GHash *hash = BLI_ghash_ptr_new(__func__);
272 
273  /* collect gizmos */
274  LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
275  if (WM_gizmo_group_type_poll(C, gzgroup->type)) {
276  LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
277  if (((flag_exclude == 0) || ((gz->flag & flag_exclude) == 0)) &&
278  (!poll || poll(gz, data))) {
279  BLI_ghash_insert(hash, gz, gz);
280  }
281  }
282  }
283  }
284 
285  return hash;
286 }
287 
289 {
291  if (gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
293  }
294  else {
296  }
297  return step;
298 }
299 
301 {
303  if (gzmap) {
305  }
306 }
307 
309 {
310  if (gzmap) {
311  for (int i = 0; i < WM_GIZMOMAP_DRAWSTEP_MAX; i++) {
313  }
314  }
315 }
316 
318 {
319  LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
320  if (gzgroup->hide.delay_refresh_for_tweak) {
321  return true;
322  }
323  }
324  return false;
325 }
326 
328  wmGizmo *gz,
329  const bContext *C,
330  ListBase *draw_gizmos,
331  const eWM_GizmoFlagMapDrawStep drawstep)
332 {
333  int do_draw = wm_gizmo_is_visible(gz);
334  if (do_draw == 0) {
335  /* skip */
336  }
337  else {
338  /* Ensure we get RNA updates */
339  if (do_draw & WM_GIZMO_IS_VISIBLE_UPDATE) {
340  /* hover gizmos need updating, even if we don't draw them */
341  wm_gizmo_update(gz, C, (gzmap->update_flag[drawstep] & GIZMOMAP_IS_PREPARE_DRAW) != 0);
342  }
343  if (do_draw & WM_GIZMO_IS_VISIBLE_DRAW) {
344  BLI_addhead(draw_gizmos, BLI_genericNodeN(gz));
345  }
346  return true;
347  }
348 
349  return false;
350 }
351 
357  const bContext *C,
358  ListBase *draw_gizmos,
359  const eWM_GizmoFlagMapDrawStep drawstep)
360 {
361  if (!gzmap || BLI_listbase_is_empty(&gzmap->groups)) {
362  return;
363  }
364 
365  gzmap->is_init = false;
366 
367  wmGizmo *gz_modal = gzmap->gzmap_context.modal;
368 
369  /* Allow refresh functions to ask to be refreshed again, clear before the loop below. */
370  const bool do_refresh = gzmap->update_flag[drawstep] & GIZMOMAP_IS_REFRESH_CALLBACK;
371  gzmap->update_flag[drawstep] &= ~GIZMOMAP_IS_REFRESH_CALLBACK;
372 
373  LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
374  /* check group visibility - drawstep first to avoid unnecessary call of group poll callback */
375  if (!wm_gizmogroup_is_visible_in_drawstep(gzgroup, drawstep)) {
376  continue;
377  }
378 
379  if (gz_modal && (gzgroup == gz_modal->parent_gzgroup)) {
380  if (gzgroup->type->flag & WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE) {
381  continue;
382  }
383  }
384  else { /* Don't poll modal gizmo since some poll functions unlink. */
385  if (!WM_gizmo_group_type_poll(C, gzgroup->type)) {
386  continue;
387  }
388  /* When modal only show other gizmo groups tagged with #WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL. */
389  if (gz_modal && ((gzgroup->type->flag & WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL) == 0)) {
390  continue;
391  }
392  }
393 
394  /* Needs to be initialized on first draw. */
395  /* XXX weak: Gizmo-group may skip refreshing if it's invisible
396  * (map gets untagged nevertheless). */
397  if (do_refresh) {
398  /* force refresh again. */
399  gzgroup->init_flag &= ~WM_GIZMOGROUP_INIT_REFRESH;
400  }
401  /* Calls `setup`, `setup_keymap` and `refresh` if they're defined. */
402  WM_gizmogroup_ensure_init(C, gzgroup);
403 
404  /* Check after ensure which can run refresh and update this value. */
405  if (gzgroup->hide.any != 0) {
406  continue;
407  }
408 
409  /* prepare drawing */
410  if (gzgroup->type->draw_prepare) {
411  gzgroup->type->draw_prepare(C, gzgroup);
412  }
413 
414  LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
415  gizmo_prepare_drawing(gzmap, gz, C, draw_gizmos, drawstep);
416  }
417  }
418 
419  gzmap->update_flag[drawstep] &= ~GIZMOMAP_IS_PREPARE_DRAW;
420 }
421 
426 static void gizmos_draw_list(const wmGizmoMap *gzmap, const bContext *C, ListBase *draw_gizmos)
427 {
428  /* Can be empty if we're dynamically added and removed. */
429  if ((gzmap == NULL) || BLI_listbase_is_empty(&gzmap->groups)) {
430  return;
431  }
432 
433  /* TODO(campbell): This will need it own shader probably?
434  * Don't think it can be handled from that point though. */
435  /* const bool use_lighting = (U.gizmo_flag & V3D_GIZMO_SHADED) != 0; */
436 
437  bool is_depth_prev = false;
438 
439  /* draw_gizmos contains all visible gizmos - draw them */
440  for (LinkData *link = draw_gizmos->first, *link_next; link; link = link_next) {
441  wmGizmo *gz = link->data;
442  link_next = link->next;
443 
444  bool is_depth = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_DEPTH_3D) != 0;
445 
446  /* Weak! since we don't 100% support depth yet (select ignores depth)
447  * always show highlighted. */
448  if (is_depth && (gz->state & WM_GIZMO_STATE_HIGHLIGHT)) {
449  is_depth = false;
450  }
451 
452  if (is_depth == is_depth_prev) {
453  /* pass */
454  }
455  else {
456  if (is_depth) {
458  }
459  else {
461  }
462  is_depth_prev = is_depth;
463  }
464 
465  /* XXX force AntiAlias Gizmos. */
466  GPU_line_smooth(true);
467  GPU_polygon_smooth(true);
468 
469  gz->type->draw(C, gz);
470 
471  GPU_line_smooth(false);
472  GPU_polygon_smooth(false);
473 
474  /* free/remove gizmo link after drawing */
475  BLI_freelinkN(draw_gizmos, link);
476  }
477 
478  if (is_depth_prev) {
480  }
481 }
482 
484  const bContext *C,
485  const eWM_GizmoFlagMapDrawStep drawstep)
486 {
487  if (!WM_gizmo_context_check_drawstep(C, drawstep)) {
488  return;
489  }
490 
491  ListBase draw_gizmos = {NULL};
492 
493  gizmomap_prepare_drawing(gzmap, C, &draw_gizmos, drawstep);
494  gizmos_draw_list(gzmap, C, &draw_gizmos);
495  BLI_assert(BLI_listbase_is_empty(&draw_gizmos));
496 }
497 
499  wmGizmo **visible_gizmos,
500  const int visible_gizmos_len,
501  bool *r_use_select_bias)
502 {
503 
504  /* TODO(campbell): this depends on depth buffer being written to,
505  * currently broken for the 3D view. */
506  bool is_depth_prev = false;
507  bool is_depth_skip_prev = false;
508 
509  for (int select_id = 0; select_id < visible_gizmos_len; select_id++) {
510  wmGizmo *gz = visible_gizmos[select_id];
511  if (gz->type->draw_select == NULL) {
512  continue;
513  }
514 
515  bool is_depth = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_DEPTH_3D) != 0;
516  if (is_depth == is_depth_prev) {
517  /* pass */
518  }
519  else {
520  if (is_depth) {
522  }
523  else {
525  }
526  is_depth_prev = is_depth;
527  }
528  bool is_depth_skip = (gz->flag & WM_GIZMO_SELECT_BACKGROUND) != 0;
529  if (is_depth_skip == is_depth_skip_prev) {
530  /* pass */
531  }
532  else {
533  GPU_depth_mask(!is_depth_skip);
534  is_depth_skip_prev = is_depth_skip;
535  }
536 
537  if (gz->select_bias != 0.0) {
538  *r_use_select_bias = true;
539  }
540 
541  /* pass the selection id shifted by 8 bits. Last 8 bits are used for selected gizmo part id */
542 
543  gz->type->draw_select(C, gz, select_id << 8);
544  }
545 
546  if (is_depth_prev) {
548  }
549  if (is_depth_skip_prev) {
550  GPU_depth_mask(true);
551  }
552 }
553 
554 static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
555  const int visible_gizmos_len,
556  const bContext *C,
557  const int co[2],
558  const int hotspot)
559 {
560  const wmWindowManager *wm = CTX_wm_manager(C);
562  ARegion *region = CTX_wm_region(C);
563  View3D *v3d = area->spacedata.first;
565  rcti rect;
566  /* Almost certainly overkill, but allow for many custom gizmos. */
568  short hits;
569 
570  BLI_rcti_init_pt_radius(&rect, co, hotspot);
571 
573  wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, &rect);
574 
575  bool use_select_bias = false;
576 
577  /* TODO: waiting for the GPU in the middle of the event loop for every
578  * mouse move is bad for performance, we need to find a solution to not
579  * use the GPU or draw something once. (see T61474) */
581  /* do the drawing */
582  gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias);
583 
584  hits = GPU_select_end();
585 
586  if (hits > 0) {
588  gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias);
589  GPU_select_end();
590  }
591 
593  wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, NULL);
594 
595  if (use_select_bias && (hits > 1)) {
596  float co_direction[3];
597  float co_screen[3] = {co[0], co[1], 0.0f};
598  ED_view3d_win_to_vector(region, (float[2]){UNPACK2(co)}, co_direction);
599 
600  RegionView3D *rv3d = region->regiondata;
601  const int viewport[4] = {0, 0, region->winx, region->winy};
602  float co_3d_origin[3];
603 
604  GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d_origin);
605 
606  GPUSelectResult *buf_iter = buffer;
607  int hit_found = -1;
608  float dot_best = FLT_MAX;
609 
610  for (int i = 0; i < hits; i++, buf_iter++) {
611  BLI_assert(buf_iter->id != -1);
612  wmGizmo *gz = visible_gizmos[buf_iter->id >> 8];
613  float co_3d[3];
614  co_screen[2] = (float)((double)buf_iter->depth / (double)UINT_MAX);
615  GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d);
616  float select_bias = gz->select_bias;
617  if ((gz->flag & WM_GIZMO_DRAW_NO_SCALE) == 0) {
618  select_bias *= gz->scale_final;
619  }
620  sub_v3_v3(co_3d, co_3d_origin);
621  const float dot_test = dot_v3v3(co_3d, co_direction) - select_bias;
622  if (dot_best > dot_test) {
623  dot_best = dot_test;
624  hit_found = buf_iter->id;
625  }
626  }
627  return hit_found;
628  }
629 
630  const GPUSelectResult *hit_near = GPU_select_buffer_near(buffer, hits);
631  return hit_near ? hit_near->id : -1;
632 }
633 
638  const int co[2],
639  wmGizmo **visible_gizmos,
640  const int visible_gizmos_len,
641  int *r_part)
642 {
643  wmGizmo *result = NULL;
644  int visible_gizmos_len_trim = visible_gizmos_len;
645  int hit = -1;
646 
647  *r_part = 0;
648 
649  /* set up view matrices */
651 
652  /* Search for 3D gizmo's that use the 2D callback for checking intersections. */
653  bool has_3d = false;
654  {
655  for (int select_id = 0; select_id < visible_gizmos_len; select_id++) {
656  wmGizmo *gz = visible_gizmos[select_id];
657  /* With both defined, favor the 3D, in case the gizmo can be used in 2D or 3D views. */
658  if (gz->type->test_select && (gz->type->draw_select == NULL)) {
659  if ((*r_part = gz->type->test_select(C, gz, co)) != -1) {
660  hit = select_id;
661  result = gz;
662  /* Don't search past this when checking intersections. */
663  visible_gizmos_len_trim = select_id;
664  break;
665  }
666  }
667  else if (gz->type->draw_select != NULL) {
668  has_3d = true;
669  }
670  }
671  }
672 
673  /* Search for 3D intersections if they're before 2D that have been found (if any).
674  * This way we always use the first hit. */
675  if (has_3d) {
676 
677  /* The depth buffer is needed for for gizmos to obscure each other. */
679 
680  /* When switching between modes and the mouse pointer is over a gizmo, the highlight test is
681  * performed before the viewport is fully initialized (region->draw_buffer = NULL).
682  * When this is the case we should not use depth testing. */
683  if (viewport == NULL) {
684  return NULL;
685  }
686  GPUTexture *depth_tx = GPU_viewport_depth_texture(viewport);
687  GPUFrameBuffer *depth_read_fb = NULL;
688  GPU_framebuffer_ensure_config(&depth_read_fb,
689  {
690  GPU_ATTACHMENT_TEXTURE(depth_tx),
691  GPU_ATTACHMENT_NONE,
692  });
693  GPU_framebuffer_bind(depth_read_fb);
694 
695  const int hotspot_radii[] = {
696  3 * U.pixelsize,
697  /* This runs on mouse move, careful doing too many tests! */
698  10 * U.pixelsize,
699  };
700  for (int i = 0; i < ARRAY_SIZE(hotspot_radii); i++) {
702  visible_gizmos, visible_gizmos_len_trim, C, co, hotspot_radii[i]);
703  if (hit != -1) {
704  break;
705  }
706  }
707 
709  GPU_framebuffer_free(depth_read_fb);
710 
711  if (hit != -1) {
712  const int select_id = hit >> 8;
713  const int select_part = hit & 0xff;
714  BLI_assert(select_id < visible_gizmos_len);
715  *r_part = select_part;
716  result = visible_gizmos[select_id];
717  }
718  }
719 
720  return result;
721 }
722 
724  bContext *C,
725  const wmEvent *event,
726  int *r_part)
727 {
729  wmGizmo *gz = NULL;
730  BLI_buffer_declare_static(wmGizmo *, visible_3d_gizmos, BLI_BUFFER_NOP, 128);
731  bool do_step[WM_GIZMOMAP_DRAWSTEP_MAX];
732 
733  int mval[2];
734  if (event->val == KM_CLICK_DRAG) {
736  }
737  else {
738  copy_v2_v2_int(mval, event->mval);
739  }
740 
741  for (int i = 0; i < ARRAY_SIZE(do_step); i++) {
742  do_step[i] = WM_gizmo_context_check_drawstep(C, i);
743  }
744 
745  LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
746 
747  /* If it were important we could initialize here,
748  * but this only happens when events are handled before drawing,
749  * just skip to keep code-path for initializing gizmos simple. */
750  if ((gzgroup->hide.any != 0) || ((gzgroup->init_flag & WM_GIZMOGROUP_INIT_SETUP) == 0)) {
751  continue;
752  }
753 
754  if (WM_gizmo_group_type_poll(C, gzgroup->type)) {
756  if (do_step[step]) {
757  if (gzmap->update_flag[step] & GIZMOMAP_IS_REFRESH_CALLBACK) {
758  WM_gizmo_group_refresh(C, gzgroup);
759  /* cleared below */
760  }
761  if (step == WM_GIZMOMAP_DRAWSTEP_3D) {
763  wm, gzgroup, event->modifier, &visible_3d_gizmos);
764  }
765  else if (step == WM_GIZMOMAP_DRAWSTEP_2D) {
767  wm, gzgroup, C, event->modifier, mval, r_part))) {
768  break;
769  }
770  }
771  }
772  }
773  }
774 
775  if (visible_3d_gizmos.count) {
776  /* 2D gizmos get priority. */
777  if (gz == NULL) {
779  C, mval, visible_3d_gizmos.data, visible_3d_gizmos.count, r_part);
780  }
781  }
782  BLI_buffer_free(&visible_3d_gizmos);
783 
786 
787  return gz;
788 }
789 
791 {
792  LISTBASE_FOREACH (wmEventHandler *, handler_base, &region->handlers) {
793  if (handler_base->type == WM_HANDLER_TYPE_GIZMO) {
794  wmEventHandler_Gizmo *handler = (wmEventHandler_Gizmo *)handler_base;
795  if (handler->gizmo_map == gzmap) {
796  return;
797  }
798  }
799  }
800 
801  wmEventHandler_Gizmo *handler = MEM_callocN(sizeof(*handler), __func__);
802  handler->head.type = WM_HANDLER_TYPE_GIZMO;
803  BLI_assert(gzmap == region->gizmo_map);
804  handler->gizmo_map = gzmap;
805  BLI_addtail(&region->handlers, handler);
806 }
807 
809 {
810  const bool modal_running = (handler->op != NULL);
811 
812  /* happens on render or when joining areas */
813  if (!handler->context.region || !handler->context.region->gizmo_map) {
814  return;
815  }
816 
817  wmGizmoMap *gzmap = handler->context.region->gizmo_map;
818  wmGizmo *gz = wm_gizmomap_modal_get(gzmap);
820  ARegion *region = CTX_wm_region(C);
821 
823 
824  /* regular update for running operator */
825  if (modal_running) {
826  wmGizmoOpElem *gzop = gz ? WM_gizmo_operator_get(gz, gz->highlight_part) : NULL;
827  if (gz && gzop && (gzop->type != NULL) && (gzop->type == handler->op->type)) {
828  wmGizmoFnModal modal_fn = gz->custom_modal ? gz->custom_modal : gz->type->modal;
829  if (modal_fn != NULL) {
830  int retval = modal_fn(C, gz, event, 0);
831  /* The gizmo is tried to the operator, we can't choose when to exit. */
833  UNUSED_VARS_NDEBUG(retval);
834  }
835  }
836  }
837  /* operator not running anymore */
838  else {
839  wm_gizmomap_highlight_set(gzmap, C, NULL, 0);
840  if (gz) {
841  /* This isn't defined if it ends because of success of cancel, we may want to change. */
842  bool cancel = true;
843  if (gz->type->exit) {
844  gz->type->exit(C, gz, cancel);
845  }
846  wm_gizmomap_modal_set(gzmap, C, gz, NULL, false);
847  }
848  }
849 
850  /* restore the area */
852  CTX_wm_region_set(C, region);
853 }
854 
856 {
858 
859  if (msel->items == NULL || msel->len == 0) {
860  return false;
861  }
862 
863  for (int i = 0; i < msel->len; i++) {
864  wm_gizmo_select_set_ex(gzmap, msel->items[i], false, false, true);
865  }
866 
868 
869  /* always return true, we already checked
870  * if there's anything to deselect */
871  return true;
872 }
873 
875 {
877 }
878 
884 {
886  /* GHash is used here to avoid having to loop over all gizmos twice (once to
887  * get tot_sel for allocating, once for actually selecting). Instead we collect
888  * selectable gizmos in hash table and use this to get tot_sel and do selection */
889 
892  GHashIterator gh_iter;
893  int i;
894  bool changed = false;
895 
897 
898  GHASH_ITER_INDEX (gh_iter, hash, i) {
899  wmGizmo *gz_iter = BLI_ghashIterator_getValue(&gh_iter);
900  WM_gizmo_select_set(gzmap, gz_iter, true);
901  }
902  /* highlight first gizmo */
903  wm_gizmomap_highlight_set(gzmap, C, msel->items[0], msel->items[0]->highlight_part);
904 
905  BLI_assert(BLI_ghash_len(hash) == msel->len);
906 
908  return changed;
909 }
910 
911 bool WM_gizmomap_select_all(bContext *C, wmGizmoMap *gzmap, const int action)
912 {
913  bool changed = false;
914 
915  switch (action) {
916  case SEL_SELECT:
917  changed = wm_gizmomap_select_all_intern(C, gzmap);
918  break;
919  case SEL_DESELECT:
920  changed = wm_gizmomap_deselect_all(gzmap);
921  break;
922  default:
924  break;
925  }
926 
927  if (changed) {
929  }
930 
931  return changed;
932 }
933 
935 {
936  bScreen *screen = CTX_wm_screen(C);
937 
938  if (screen) {
939  ScrArea *area;
940 
941  for (area = screen->areabase.first; area; area = area->next) {
942  if (area == handler->context.area) {
943  break;
944  }
945  }
946  if (area == NULL) {
947  /* when changing screen layouts with running modal handlers (like render display), this
948  * is not an error to print */
949  printf("internal error: modal gizmo-map handler has invalid area\n");
950  }
951  else {
952  ARegion *region;
954  for (region = area->regionbase.first; region; region = region->next) {
955  if (region == handler->context.region) {
956  break;
957  }
958  }
959  /* XXX no warning print here, after full-area and back regions are remade */
960  if (region) {
961  CTX_wm_region_set(C, region);
962  }
963  }
964  }
965 }
966 
968 {
969  /* pass */
970 }
971 
973 {
974  wmGizmo *gz = gzmap->gzmap_context.highlight;
975  if (gz && gz->type->cursor_get) {
976  WM_cursor_set(win, gz->type->cursor_get(gz));
977  return true;
978  }
979 
980  return false;
981 }
982 
983 bool wm_gizmomap_highlight_set(wmGizmoMap *gzmap, const bContext *C, wmGizmo *gz, int part)
984 {
985  if ((gz != gzmap->gzmap_context.highlight) || (gz && part != gz->highlight_part)) {
986  const bool init_last_cursor = !(gzmap->gzmap_context.highlight &&
987  gzmap->gzmap_context.last_cursor != -1);
988  if (gzmap->gzmap_context.highlight) {
991  }
992 
993  gzmap->gzmap_context.highlight = gz;
994 
995  if (gz) {
997  gz->highlight_part = part;
998  if (init_last_cursor) {
999  gzmap->gzmap_context.last_cursor = -1;
1000  }
1001 
1002  if (C && gz->type->cursor_get) {
1003  wmWindow *win = CTX_wm_window(C);
1004  if (init_last_cursor) {
1005  gzmap->gzmap_context.last_cursor = win->cursor;
1006  }
1007  WM_cursor_set(win, gz->type->cursor_get(gz));
1008  }
1009  }
1010  else {
1011  if (C && gzmap->gzmap_context.last_cursor != -1) {
1012  wmWindow *win = CTX_wm_window(C);
1014  }
1015  gzmap->gzmap_context.last_cursor = -1;
1016  }
1017 
1018  /* tag the region for redraw */
1019  if (C) {
1020  ARegion *region = CTX_wm_region(C);
1022  }
1023 
1024  return true;
1025  }
1026 
1027  return false;
1028 }
1029 
1031 {
1032  return gzmap->gzmap_context.highlight;
1033 }
1034 
1036  wmGizmoMap *gzmap, bContext *C, wmGizmo *gz, const wmEvent *event, bool enable)
1037 {
1038  bool do_refresh = false;
1039 
1040  if (enable) {
1041  BLI_assert(gzmap->gzmap_context.modal == NULL);
1042  wmWindow *win = CTX_wm_window(C);
1043 
1044  WM_tooltip_clear(C, win);
1045 
1046  /* Use even if we don't have invoke, so we can setup data before an operator runs. */
1047  if (gz->parent_gzgroup->type->invoke_prepare) {
1048  gz->parent_gzgroup->type->invoke_prepare(C, gz->parent_gzgroup, gz, event);
1049  }
1050 
1051  if (gz->type->invoke && (gz->type->modal || gz->custom_modal)) {
1052  const int retval = gz->type->invoke(C, gz, event);
1053  if ((retval & OPERATOR_RUNNING_MODAL) == 0) {
1054  return;
1055  }
1056  }
1057 
1058  if (gzmap->gzmap_context.modal != gz) {
1059  do_refresh = true;
1060  }
1061  gz->state |= WM_GIZMO_STATE_MODAL;
1062  gzmap->gzmap_context.modal = gz;
1063 
1064  if ((gz->flag & WM_GIZMO_MOVE_CURSOR) && (event->tablet.is_motion_absolute == false)) {
1066  copy_v2_v2_int(gzmap->gzmap_context.event_xy, event->xy);
1068  }
1069  else {
1070  gzmap->gzmap_context.event_xy[0] = INT_MAX;
1071  }
1072 
1073  struct wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, gz->highlight_part);
1074  if (gzop && gzop->type) {
1075  const int retval = WM_gizmo_operator_invoke(C, gz, gzop, event);
1076  if ((retval & OPERATOR_RUNNING_MODAL) == 0) {
1077  wm_gizmomap_modal_set(gzmap, C, gz, event, false);
1078  }
1079 
1080  /* we failed to hook the gizmo to the operator handler or operator was cancelled, return */
1081  if (!gzmap->gzmap_context.modal) {
1082  gz->state &= ~WM_GIZMO_STATE_MODAL;
1084  }
1085  }
1086  }
1087  else {
1088  BLI_assert(ELEM(gzmap->gzmap_context.modal, NULL, gz));
1089 
1090  /* deactivate, gizmo but first take care of some stuff */
1091  if (gz) {
1092  gz->state &= ~WM_GIZMO_STATE_MODAL;
1094  }
1095 
1096  if (gzmap->gzmap_context.modal != NULL) {
1097  do_refresh = true;
1098  }
1099  gzmap->gzmap_context.modal = NULL;
1100 
1101  if (C) {
1102  wmWindow *win = CTX_wm_window(C);
1103  if (gzmap->gzmap_context.event_xy[0] != INT_MAX) {
1104  /* Check if some other part of Blender (typically operators)
1105  * have adjusted the grab mode since it was set.
1106  * If so: warp, so we have a predictable outcome. */
1107  if (gzmap->gzmap_context.event_grabcursor == win->grabcursor) {
1109  }
1110  else {
1112  }
1113  }
1116  }
1117 
1118  gzmap->gzmap_context.event_xy[0] = INT_MAX;
1119  }
1120 
1121  if (do_refresh) {
1123  gz->parent_gzgroup);
1124  gzmap->update_flag[step] |= GIZMOMAP_IS_REFRESH_CALLBACK;
1125  }
1126 }
1127 
1129 {
1130  return gzmap->gzmap_context.modal;
1131 }
1132 
1133 wmGizmo **wm_gizmomap_selected_get(wmGizmoMap *gzmap, int *r_selected_len)
1134 {
1135  *r_selected_len = gzmap->gzmap_context.select.len;
1136  return gzmap->gzmap_context.select.items;
1137 }
1138 
1140 {
1141  return &gzmap->groups;
1142 }
1143 
1145  wmGizmoMap *gzmap,
1146  ARegion *region,
1147  struct wmMsgBus *mbus)
1148 {
1149  LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
1150  if ((gzgroup->hide.any != 0) || (gzgroup->init_flag & WM_GIZMOGROUP_INIT_SETUP) == 0 ||
1151  !WM_gizmo_group_type_poll(C, gzgroup->type)) {
1152  continue;
1153  }
1154  LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
1155  if (gz->flag & WM_GIZMO_HIDDEN) {
1156  continue;
1157  }
1158  WM_gizmo_target_property_subscribe_all(gz, mbus, region);
1159  }
1160  if (gzgroup->type->message_subscribe != NULL) {
1161  gzgroup->type->message_subscribe(C, gzgroup, mbus);
1162  }
1163  }
1164 }
1165  /* wmGizmoMap */
1167 
1168 /* -------------------------------------------------------------------- */
1173  struct ARegion *region,
1174  int *UNUSED(r_pass),
1175  double *UNUSED(pass_delay),
1176  bool *r_exit_on_event)
1177 {
1178  wmGizmoMap *gzmap = region->gizmo_map;
1179  *r_exit_on_event = false;
1180  if (gzmap) {
1181  wmGizmo *gz = gzmap->gzmap_context.highlight;
1182  if (gz) {
1183  wmGizmoGroup *gzgroup = gz->parent_gzgroup;
1184  if ((gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) != 0) {
1185  /* On screen area of 3D gizmos may be large, exit on cursor motion. */
1186  *r_exit_on_event = true;
1187  }
1188  return UI_tooltip_create_from_gizmo(C, gz);
1189  }
1190  }
1191  return NULL;
1192 }
1193  /* wmGizmoMapType */
1195 
1196 /* -------------------------------------------------------------------- */
1201 {
1202  LISTBASE_FOREACH (wmGizmoMapType *, gzmap_type, &gizmomaptypes) {
1203  if (gzmap_type->spaceid == gzmap_params->spaceid &&
1204  gzmap_type->regionid == gzmap_params->regionid) {
1205  return gzmap_type;
1206  }
1207  }
1208 
1209  return NULL;
1210 }
1211 
1213 {
1214  wmGizmoMapType *gzmap_type = WM_gizmomaptype_find(gzmap_params);
1215 
1216  if (gzmap_type) {
1217  return gzmap_type;
1218  }
1219 
1220  gzmap_type = MEM_callocN(sizeof(wmGizmoMapType), "gizmotype list");
1221  gzmap_type->spaceid = gzmap_params->spaceid;
1222  gzmap_type->regionid = gzmap_params->regionid;
1223  BLI_addhead(&gizmomaptypes, gzmap_type);
1224 
1225  return gzmap_type;
1226 }
1227 
1229 {
1230  for (wmGizmoMapType *gzmap_type = gizmomaptypes.first, *gzmap_type_next; gzmap_type;
1231  gzmap_type = gzmap_type_next) {
1232  gzmap_type_next = gzmap_type->next;
1233  for (wmGizmoGroupTypeRef *gzgt_ref = gzmap_type->grouptype_refs.first, *gzgt_next; gzgt_ref;
1234  gzgt_ref = gzgt_next) {
1235  gzgt_next = gzgt_ref->next;
1236  WM_gizmomaptype_group_free(gzgt_ref);
1237  }
1238  MEM_freeN(gzmap_type);
1239  }
1240 }
1241 
1243 {
1244  LISTBASE_FOREACH (wmGizmoMapType *, gzmap_type, &gizmomaptypes) {
1245  LISTBASE_FOREACH (wmGizmoGroupTypeRef *, gzgt_ref, &gzmap_type->grouptype_refs) {
1246  wm_gizmogrouptype_setup_keymap(gzgt_ref->type, keyconf);
1247  }
1248  }
1249 
1251 }
1252  /* wmGizmoMapType */
1254 
1255 /* -------------------------------------------------------------------- */
1260 {
1261  /* tag for update on next use */
1264 
1266 }
1267 
1269  wmGizmoGroupType *gzgt)
1270 {
1271  /* tag for update on next use */
1274 
1276 }
1277 
1279 {
1280  gzmap->tag_remove_group = true;
1281 
1283 }
1284 
1285 void WM_gizmoconfig_update(struct Main *bmain)
1286 {
1287  if (G.background) {
1288  return;
1289  }
1290 
1291  if (wm_gzmap_type_update_flag == 0) {
1292  return;
1293  }
1294 
1296  LISTBASE_FOREACH (wmGizmoMapType *, gzmap_type, &gizmomaptypes) {
1297  if (gzmap_type->type_update_flag & WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE) {
1298  gzmap_type->type_update_flag &= ~WM_GIZMOMAPTYPE_UPDATE_REMOVE;
1299  for (wmGizmoGroupTypeRef *gzgt_ref = gzmap_type->grouptype_refs.first, *gzgt_ref_next;
1300  gzgt_ref;
1301  gzgt_ref = gzgt_ref_next) {
1302  gzgt_ref_next = gzgt_ref->next;
1303  if (gzgt_ref->type->type_update_flag & WM_GIZMOMAPTYPE_UPDATE_REMOVE) {
1304  gzgt_ref->type->type_update_flag &= ~WM_GIZMOMAPTYPE_UPDATE_REMOVE;
1305  WM_gizmomaptype_group_unlink(NULL, bmain, gzmap_type, gzgt_ref->type);
1306  }
1307  }
1308  }
1309  }
1310 
1312  }
1313 
1315  LISTBASE_FOREACH (wmGizmoMapType *, gzmap_type, &gizmomaptypes) {
1317  if (gzmap_type->type_update_flag & type_update_all) {
1318  gzmap_type->type_update_flag &= ~type_update_all;
1319  LISTBASE_FOREACH (wmGizmoGroupTypeRef *, gzgt_ref, &gzmap_type->grouptype_refs) {
1320  if (gzgt_ref->type->type_update_flag & WM_GIZMOMAPTYPE_KEYMAP_INIT) {
1321  WM_gizmomaptype_group_init_runtime_keymap(bmain, gzgt_ref->type);
1322  gzgt_ref->type->type_update_flag &= ~WM_GIZMOMAPTYPE_KEYMAP_INIT;
1323  }
1324 
1325  if (gzgt_ref->type->type_update_flag & WM_GIZMOMAPTYPE_UPDATE_INIT) {
1326  WM_gizmomaptype_group_init_runtime(bmain, gzmap_type, gzgt_ref->type);
1327  gzgt_ref->type->type_update_flag &= ~WM_GIZMOMAPTYPE_UPDATE_INIT;
1328  }
1329  }
1330  }
1331  }
1332 
1334  }
1335 
1337  for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
1338  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
1339  LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
1340  ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
1341  &sl->regionbase;
1342  LISTBASE_FOREACH (ARegion *, region, regionbase) {
1343  wmGizmoMap *gzmap = region->gizmo_map;
1344  if (gzmap != NULL && gzmap->tag_remove_group) {
1345  gzmap->tag_remove_group = false;
1346 
1347  for (wmGizmoGroup *gzgroup = gzmap->groups.first, *gzgroup_next; gzgroup;
1348  gzgroup = gzgroup_next) {
1349  gzgroup_next = gzgroup->next;
1350  if (gzgroup->tag_remove) {
1351  wm_gizmogroup_free(NULL, gzgroup);
1353  }
1354  }
1355  }
1356  }
1357  }
1358  }
1359  }
1361  }
1362 }
1363 
1366 /* -------------------------------------------------------------------- */
1374 {
1375  for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
1376  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
1377  LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
1378  ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase : &sl->regionbase;
1379  LISTBASE_FOREACH (ARegion *, region, regionbase) {
1380  wmGizmoMap *gzmap = region->gizmo_map;
1381  if ((gzmap != NULL) && (gzmap->is_init == false)) {
1382  WM_gizmomap_reinit(gzmap);
1383  }
1384  }
1385  }
1386  }
1387  }
1388 }
1389 
typedef float(TangentPoint)[2]
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
void CTX_wm_region_set(bContext *C, struct ARegion *region)
Definition: context.c:1009
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 ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1505
void CTX_wm_area_set(bContext *C, struct ScrArea *area)
Definition: context.c:997
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
@ BLI_BUFFER_NOP
Definition: BLI_buffer.h:21
#define BLI_buffer_declare_static(type_, name_, flag_, static_count_)
Definition: BLI_buffer.h:25
#define BLI_buffer_free(name_)
Definition: BLI_buffer.h:94
#define BLI_INLINE
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:302
unsigned int BLI_ghash_len(const GHash *gh) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:705
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:710
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:863
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
#define GHASH_ITER_INDEX(gh_iter_, ghash_, i_)
Definition: BLI_ghash.h:325
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
struct LinkData * BLI_genericNodeN(void *data)
Definition: listbase.c:842
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
Definition: math_vector.c:867
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void copy_v2_v2_int(int r[2], const int a[2])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void BLI_rcti_init_pt_radius(struct rcti *rect, const int xy[2], int size)
Definition: rct.c:469
unsigned char uchar
Definition: BLI_sys_types.h:70
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNPACK2(a)
#define ARRAY_SIZE(arr)
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
#define ELEM(...)
typedef double(DMatrix)[4][4]
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
@ OPERATOR_RUNNING_MODAL
void ED_region_tag_redraw_editor_overlays(struct ARegion *region)
Definition: area.c:690
@ SEL_SELECT
@ SEL_DESELECT
void ED_view3d_draw_setup_view(const struct wmWindowManager *wm, struct wmWindow *win, struct Depsgraph *depsgraph, struct Scene *scene, struct ARegion *region, struct View3D *v3d, const float viewmat[4][4], const float winmat[4][4], const struct rcti *rect)
void ED_view3d_win_to_vector(const struct ARegion *region, const float mval[2], float r_out[3])
#define MAXPICKELEMS
Definition: ED_view3d.h:894
void view3d_operator_needs_opengl(const struct bContext *C)
struct GPUFrameBuffer GPUFrameBuffer
void GPU_framebuffer_restore(void)
void GPU_framebuffer_free(GPUFrameBuffer *fb)
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
bool GPU_matrix_unproject_3fv(const float win[3], const float model_inverted[4][4], const float proj[4][4], const int view[4], float r_world[3])
Definition: gpu_matrix.cc:500
void GPU_select_begin(GPUSelectResult *buffer, unsigned int buffer_len, const struct rcti *input, eGPUSelectMode mode, int oldhits)
@ GPU_SELECT_NEAREST_SECOND_PASS
Definition: GPU_select.h:23
@ GPU_SELECT_NEAREST_FIRST_PASS
Definition: GPU_select.h:22
const GPUSelectResult * GPU_select_buffer_near(const GPUSelectResult *buffer, int hits)
Definition: gpu_select.c:206
unsigned int GPU_select_end(void)
Definition: gpu_select.c:135
void GPU_line_smooth(bool enable)
Definition: gpu_state.cc:75
void GPU_depth_mask(bool depth)
Definition: gpu_state.cc:107
@ GPU_DEPTH_LESS_EQUAL
Definition: GPU_state.h:86
@ GPU_DEPTH_NONE
Definition: GPU_state.h:83
void GPU_depth_test(eGPUDepthTest test)
Definition: gpu_state.cc:65
void GPU_polygon_smooth(bool enable)
Definition: gpu_state.cc:80
struct GPUTexture GPUTexture
Definition: GPU_texture.h:17
GPUTexture * GPU_viewport_depth_texture(GPUViewport *viewport)
Definition: gpu_viewport.c:569
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
#define C
Definition: RandGen.cpp:25
struct ARegion * UI_tooltip_create_from_gizmo(struct bContext *C, struct wmGizmo *gz)
eWM_GizmoFlagMapDrawStep
@ WM_GIZMOMAP_DRAWSTEP_3D
@ WM_GIZMOMAP_DRAWSTEP_2D
@ WM_GIZMOMAPTYPE_UPDATE_REMOVE
@ WM_GIZMOMAPTYPE_KEYMAP_INIT
@ WM_GIZMOMAPTYPE_UPDATE_INIT
@ WM_GIZMOGROUP_INIT_REFRESH
@ WM_GIZMOGROUP_INIT_SETUP
eWM_GizmoFlag
@ WM_GIZMO_DRAW_NO_SCALE
@ WM_GIZMO_HIDDEN
@ WM_GIZMO_MOVE_CURSOR
@ WM_GIZMO_SELECT_BACKGROUND
@ WM_GIZMO_HIDDEN_SELECT
@ WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE
@ WM_GIZMOGROUPTYPE_DEPTH_3D
@ WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL
@ WM_GIZMOGROUPTYPE_3D
@ WM_GIZMOGROUPTYPE_SELECT
@ WM_GIZMO_STATE_HIGHLIGHT
@ WM_GIZMO_STATE_MODAL
#define WM_GIZMOMAP_DRAWSTEP_MAX
@ KM_CLICK_DRAG
Definition: WM_types.h:275
@ WM_CURSOR_WRAP_XY
Definition: WM_types.h:192
unsigned int U
Definition: btGjkEpa3.h:78
const Depsgraph * depsgraph
int len
Definition: draw_manager.c:108
#define UINT_MAX
Definition: hash_md5.c:43
ccl_global float * buffer
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define G(x, y, z)
static void area(int d1, int d2, int e1, int e2, float weights[2])
#define hash
Definition: noise.c:153
void * regiondata
struct ARegion * next
ListBase handlers
struct wmGizmoMap * gizmo_map
unsigned int id
Definition: GPU_select.h:34
unsigned int depth
Definition: GPU_select.h:42
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase screens
Definition: BKE_main.h:183
ListBase areabase
wmEventHandler head
struct wmGizmoMap * gizmo_map
struct ScrArea * area
struct ARegion * region
struct wmEventHandler_Op::@1207 context
enum eWM_EventHandlerType type
short val
Definition: WM_types.h:680
int xy[2]
Definition: WM_types.h:682
int mval[2]
Definition: WM_types.h:684
uint8_t modifier
Definition: WM_types.h:693
wmTabletData tablet
Definition: WM_types.h:705
wmGizmoGroupFnInvokePrepare invoke_prepare
eWM_GizmoFlagGroupTypeFlag flag
eWM_GizmoFlagMapTypeUpdateFlag type_update_flag
struct wmGizmoGroupType * type
struct wmGizmo ** items
eWM_GizmoFlagMapTypeUpdateFlag type_update_flag
ListBase grouptype_refs
char update_flag[WM_GIZMOMAP_DRAWSTEP_MAX]
struct wmGizmoMapType * type
bool tag_remove_group
ListBase groups
struct wmGizmo * modal
short event_grabcursor
struct wmGizmo * highlight
struct wmGizmoMapSelectState select
struct wmGizmoMap::@1182 gzmap_context
Gizmo map runtime context.
struct wmOperatorType * type
wmGizmoFnDraw draw
wmGizmoFnModal modal
wmGizmoFnTestSelect test_select
wmGizmoFnExit exit
wmGizmoFnCursorGet cursor_get
wmGizmoFnInvoke invoke
wmGizmoFnDrawSelect draw_select
void * interaction_data
eWM_GizmoFlagState state
struct wmGizmoGroup * parent_gzgroup
int highlight_part
float matrix_basis[4][4]
float select_bias
struct wmGizmo * next
float scale_final
eWM_GizmoFlag flag
wmGizmoFnModal custom_modal
const struct wmGizmoType * type
struct wmOperatorType * type
char is_motion_absolute
Definition: WM_types.h:632
uint len_alloc
void WM_cursor_set(wmWindow *win, int curs)
Definition: wm_cursors.c:126
void WM_cursor_grab_enable(wmWindow *win, int wrap, bool hide, int bounds[4])
Definition: wm_cursors.c:226
void WM_cursor_grab_disable(wmWindow *win, const int mouse_ungrab_xy[2])
Definition: wm_cursors.c:263
GPUViewport * WM_draw_region_get_viewport(ARegion *region)
Definition: wm_draw.c:846
void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2])
void WM_event_add_mousemove(wmWindow *win)
@ WM_HANDLER_TYPE_GIZMO
bool wm_gizmo_select_set_ex(wmGizmoMap *gzmap, wmGizmo *gz, bool select, bool use_array, bool use_callback)
Definition: wm_gizmo.c:357
bool WM_gizmo_context_check_drawstep(const struct bContext *C, eWM_GizmoFlagMapDrawStep step)
Definition: wm_gizmo.c:704
int WM_gizmo_operator_invoke(bContext *C, wmGizmo *gz, wmGizmoOpElem *gzop, const wmEvent *event)
Definition: wm_gizmo.c:229
void wm_gizmo_update(wmGizmo *gz, const bContext *C, const bool refresh_map)
Definition: wm_gizmo.c:474
struct wmGizmoOpElem * WM_gizmo_operator_get(wmGizmo *gz, int part_index)
Definition: wm_gizmo.c:195
bool WM_gizmo_select_set(wmGizmoMap *gzmap, wmGizmo *gz, bool select)
Definition: wm_gizmo.c:397
int wm_gizmo_is_visible(wmGizmo *gz)
Definition: wm_gizmo.c:482
int(* wmGizmoFnModal)(struct bContext *, struct wmGizmo *, const struct wmEvent *, eWM_GizmoFlagTweak)
Definition: wm_gizmo_fn.h:42
void WM_gizmo_group_refresh(const bContext *C, wmGizmoGroup *gzgroup)
void WM_gizmomaptype_group_init_runtime_keymap(const Main *bmain, wmGizmoGroupType *gzgt)
wmGizmoGroup * wm_gizmogroup_new_from_type(wmGizmoMap *gzmap, wmGizmoGroupType *gzgt)
void WM_gizmomaptype_group_init_runtime(const Main *bmain, wmGizmoMapType *gzmap_type, wmGizmoGroupType *gzgt)
void wm_gizmogrouptype_setup_keymap(wmGizmoGroupType *gzgt, wmKeyConfig *keyconf)
void WM_gizmogroup_ensure_init(const bContext *C, wmGizmoGroup *gzgroup)
wmKeyMap * wm_gizmogroup_tweak_modal_keymap(wmKeyConfig *keyconf)
bool wm_gizmogroup_is_visible_in_drawstep(const wmGizmoGroup *gzgroup, const eWM_GizmoFlagMapDrawStep drawstep)
void WM_gizmomaptype_group_free(wmGizmoGroupTypeRef *gzgt_ref)
void wm_gizmogroup_intersectable_gizmos_to_list(wmWindowManager *wm, const wmGizmoGroup *gzgroup, const int event_modifier, BLI_Buffer *visible_gizmos)
wmGizmo * wm_gizmogroup_find_intersected_gizmo(wmWindowManager *wm, const wmGizmoGroup *gzgroup, bContext *C, const int event_modifier, const int mval[2], int *r_part)
bool WM_gizmo_group_type_poll(const bContext *C, const wmGizmoGroupType *gzgt)
void WM_gizmomaptype_group_unlink(bContext *C, Main *bmain, wmGizmoMapType *gzmap_type, const wmGizmoGroupType *gzgt)
void wm_gizmogroup_free(bContext *C, wmGizmoGroup *gzgroup)
wmGizmoGroupType * WM_gizmogrouptype_find(const char *idname, bool quiet)
@ WM_GIZMO_IS_VISIBLE_DRAW
@ WM_GIZMO_IS_VISIBLE_UPDATE
wmGizmoMapType * WM_gizmomaptype_find(const struct wmGizmoMapType_Params *gzmap_params)
static wmGizmo * gizmo_find_intersected_3d(bContext *C, const int co[2], wmGizmo **visible_gizmos, const int visible_gizmos_len, int *r_part)
Definition: wm_gizmo_map.c:637
void wm_gizmomap_modal_set(wmGizmoMap *gzmap, bContext *C, wmGizmo *gz, const wmEvent *event, bool enable)
eWM_GizmoFlagMapDrawStep WM_gizmomap_drawstep_from_gizmo_group(const wmGizmoGroup *gzgroup)
Definition: wm_gizmo_map.c:288
wmGizmoMapType * WM_gizmomaptype_ensure(const struct wmGizmoMapType_Params *gzmap_params)
static void wm_gizmomap_select_array_ensure_len_alloc(wmGizmoMap *gzmap, int len)
Definition: wm_gizmo_map.c:85
bool WM_gizmomap_is_any_selected(const wmGizmoMap *gzmap)
Definition: wm_gizmo_map.c:227
wmGizmo * wm_gizmomap_highlight_get(wmGizmoMap *gzmap)
void wm_gizmomaptypes_free(void)
wmGizmo * WM_gizmomap_get_modal(const wmGizmoMap *gzmap)
Definition: wm_gizmo_map.c:232
void wm_gizmomaps_handled_modal_update(bContext *C, wmEvent *event, wmEventHandler_Op *handler)
Definition: wm_gizmo_map.c:808
bool wm_gizmomap_highlight_set(wmGizmoMap *gzmap, const bContext *C, wmGizmo *gz, int part)
Definition: wm_gizmo_map.c:983
void WM_gizmomap_tag_refresh_drawstep(wmGizmoMap *gzmap, const eWM_GizmoFlagMapDrawStep drawstep)
Definition: wm_gizmo_map.c:300
void WM_reinit_gizmomap_all(Main *bmain)
struct ARegion * WM_gizmomap_tooltip_init(struct bContext *C, struct ARegion *region, int *UNUSED(r_pass), double *UNUSED(pass_delay), bool *r_exit_on_event)
static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos, const int visible_gizmos_len, const bContext *C, const int co[2], const int hotspot)
Definition: wm_gizmo_map.c:554
void WM_gizmoconfig_update_tag_group_type_init(wmGizmoMapType *gzmap_type, wmGizmoGroupType *gzgt)
bool WM_gizmomap_minmax(const wmGizmoMap *gzmap, bool UNUSED(use_hidden), bool use_select, float r_min[3], float r_max[3])
Definition: wm_gizmo_map.c:237
bool WM_gizmomap_tag_delay_refresh_for_tweak_check(wmGizmoMap *gzmap)
Definition: wm_gizmo_map.c:317
void wm_gizmomap_select_array_remove(wmGizmoMap *gzmap, wmGizmo *gz)
Definition: wm_gizmo_map.c:129
ListBase * wm_gizmomap_groups_get(wmGizmoMap *gzmap)
void WM_gizmomap_tag_refresh(wmGizmoMap *gzmap)
Definition: wm_gizmo_map.c:308
@ GIZMOMAP_IS_PREPARE_DRAW
Definition: wm_gizmo_map.c:74
@ GIZMOMAP_IS_REFRESH_CALLBACK
Definition: wm_gizmo_map.c:75
bool WM_gizmomap_select_all(bContext *C, wmGizmoMap *gzmap, const int action)
Definition: wm_gizmo_map.c:911
static void gizmos_draw_list(const wmGizmoMap *gzmap, const bContext *C, ListBase *draw_gizmos)
Definition: wm_gizmo_map.c:426
static ListBase gizmomaptypes
Definition: wm_gizmo_map.c:51
void WM_gizmoconfig_update_tag_group_type_remove(wmGizmoMapType *gzmap_type, wmGizmoGroupType *gzgt)
wmGizmoGroup * WM_gizmomap_group_find_ptr(struct wmGizmoMap *gzmap, const struct wmGizmoGroupType *gzgt)
Definition: wm_gizmo_map.c:211
static void wm_gizmomap_free_data(wmGizmoMap *gzmap)
Definition: wm_gizmo_map.c:174
void wm_gizmomap_remove(wmGizmoMap *gzmap)
Definition: wm_gizmo_map.c:188
void WM_gizmomap_draw(wmGizmoMap *gzmap, const bContext *C, const eWM_GizmoFlagMapDrawStep drawstep)
Definition: wm_gizmo_map.c:483
void WM_gizmomap_reinit(wmGizmoMap *gzmap)
Definition: wm_gizmo_map.c:194
static void gizmo_draw_select_3d_loop(const bContext *C, wmGizmo **visible_gizmos, const int visible_gizmos_len, bool *r_use_select_bias)
Definition: wm_gizmo_map.c:498
static bool wm_gizmomap_select_all_intern(bContext *C, wmGizmoMap *gzmap)
Definition: wm_gizmo_map.c:883
BLI_INLINE bool gizmo_selectable_poll(const wmGizmo *gz, void *UNUSED(data))
Definition: wm_gizmo_map.c:874
void wm_gizmomap_handler_context_op(bContext *C, wmEventHandler_Op *handler)
Definition: wm_gizmo_map.c:934
static eWM_GizmoFlagGroupTypeGlobalFlag wm_gzmap_type_update_flag
Definition: wm_gizmo_map.c:67
bool WM_gizmomap_cursor_set(const wmGizmoMap *gzmap, wmWindow *win)
Definition: wm_gizmo_map.c:972
static bool gizmo_prepare_drawing(wmGizmoMap *gzmap, wmGizmo *gz, const bContext *C, ListBase *draw_gizmos, const eWM_GizmoFlagMapDrawStep drawstep)
Definition: wm_gizmo_map.c:327
void wm_gizmomap_select_array_clear(wmGizmoMap *gzmap)
Definition: wm_gizmo_map.c:95
void WM_gizmomap_add_handlers(ARegion *region, wmGizmoMap *gzmap)
Definition: wm_gizmo_map.c:790
wmGizmoGroup * WM_gizmomap_group_find(struct wmGizmoMap *gzmap, const char *idname)
Definition: wm_gizmo_map.c:202
void WM_gizmoconfig_update_tag_group_remove(wmGizmoMap *gzmap)
static wmGizmoMap * wm_gizmomap_new_from_type_ex(struct wmGizmoMapType *gzmap_type, wmGizmoMap *gzmap)
Definition: wm_gizmo_map.c:150
wmGizmo * wm_gizmomap_highlight_find(wmGizmoMap *gzmap, bContext *C, const wmEvent *event, int *r_part)
Definition: wm_gizmo_map.c:723
void wm_gizmos_keymap(wmKeyConfig *keyconf)
void WM_gizmoconfig_update(struct Main *bmain)
eWM_GizmoFlagGroupTypeGlobalFlag
Definition: wm_gizmo_map.c:57
@ WM_GIZMOTYPE_GLOBAL_UPDATE_REMOVE
Definition: wm_gizmo_map.c:64
@ WM_GIZMOMAPTYPE_GLOBAL_UPDATE_INIT
Definition: wm_gizmo_map.c:59
@ WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE
Definition: wm_gizmo_map.c:61
const ListBase * WM_gizmomap_group_list(wmGizmoMap *gzmap)
Definition: wm_gizmo_map.c:222
wmGizmo * wm_gizmomap_modal_get(wmGizmoMap *gzmap)
void wm_gizmomap_select_array_push_back(wmGizmoMap *gzmap, wmGizmo *gz)
Definition: wm_gizmo_map.c:118
void wm_gizmomap_select_array_shrink(wmGizmoMap *gzmap, int len_subtract)
Definition: wm_gizmo_map.c:103
bool wm_gizmomap_deselect_all(wmGizmoMap *gzmap)
Definition: wm_gizmo_map.c:855
void WM_gizmomap_message_subscribe(const bContext *C, wmGizmoMap *gzmap, ARegion *region, struct wmMsgBus *mbus)
void wm_gizmomap_handler_context_gizmo(bContext *UNUSED(C), wmEventHandler_Gizmo *UNUSED(handler))
Definition: wm_gizmo_map.c:967
static GHash * WM_gizmomap_gizmo_hash_new(const bContext *C, wmGizmoMap *gzmap, bool(*poll)(const wmGizmo *, void *), void *data, const eWM_GizmoFlag flag_exclude)
Definition: wm_gizmo_map.c:265
static void gizmomap_prepare_drawing(wmGizmoMap *gzmap, const bContext *C, ListBase *draw_gizmos, const eWM_GizmoFlagMapDrawStep drawstep)
Definition: wm_gizmo_map.c:356
wmGizmo ** wm_gizmomap_selected_get(wmGizmoMap *gzmap, int *r_selected_len)
wmGizmoMap * WM_gizmomap_new_from_type(const struct wmGizmoMapType_Params *gzmap_params)
Definition: wm_gizmo_map.c:166
void WM_gizmo_target_property_subscribe_all(wmGizmo *gz, struct wmMsgBus *mbus, ARegion *region)
void WM_tooltip_clear(bContext *C, wmWindow *win)
Definition: wm_tooltip.c:80
void WM_cursor_warp(wmWindow *win, int x, int y)
Definition: wm_window.c:2054