Blender V4.3
wm_gizmo_map.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2014 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cstring>
10
11#include "BLI_buffer.h"
12#include "BLI_ghash.h"
13#include "BLI_listbase.h"
14#include "BLI_math_bits.h"
15#include "BLI_math_vector.h"
17#include "BLI_rect.h"
18
19#include "BKE_context.hh"
20#include "BKE_global.hh"
21#include "BKE_main.hh"
22
23#include "ED_screen.hh"
24#include "ED_select_utils.hh"
25#include "ED_view3d.hh"
26
27#include "GPU_framebuffer.hh"
28#include "GPU_matrix.hh"
29#include "GPU_platform.hh"
30#include "GPU_select.hh"
31#include "GPU_state.hh"
32#include "GPU_viewport.hh"
33
34#include "MEM_guardedalloc.h"
35
36#include "WM_api.hh"
37#include "WM_types.hh"
38#include "wm_event_system.hh"
39
40/* For tool-tips. */
41#include "UI_interface.hh"
42
43#include "DEG_depsgraph.hh"
44
45/* Own includes. */
46#include "wm_gizmo_intern.hh"
47#include "wm_gizmo_wmapi.hh"
48
53static ListBase gizmomaptypes = {nullptr, nullptr};
54
58/* So operator removal can trigger update. */
79
82
86enum {
90};
91
92/* -------------------------------------------------------------------- */
100{
103 return;
104 }
105 msel->items = static_cast<wmGizmo **>(MEM_reallocN(msel->items, sizeof(*msel->items) * len));
106 msel->len_alloc = len;
107}
108
110{
112 MEM_SAFE_FREE(msel->items);
113 msel->len = 0;
114 msel->len_alloc = 0;
115}
116
117void wm_gizmomap_select_array_shrink(wmGizmoMap *gzmap, int len_subtract)
118{
120 msel->len -= len_subtract;
121 if (msel->len <= 0) {
123 }
124 else {
125 if (msel->len < msel->len_alloc / 2) {
126 msel->items = static_cast<wmGizmo **>(
127 MEM_reallocN(msel->items, sizeof(*msel->items) * msel->len));
128 msel->len_alloc = msel->len;
129 }
130 }
131}
132
134{
136 BLI_assert(msel->len <= msel->len_alloc);
137 if (msel->len == msel->len_alloc) {
138 msel->len_alloc = (msel->len + 1) * 2;
139 msel->items = static_cast<wmGizmo **>(
140 MEM_reallocN(msel->items, sizeof(*msel->items) * msel->len_alloc));
141 }
142 msel->items[msel->len++] = gz;
143}
144
146{
148 /* Remove gizmo from selected_gizmos array. */
149 for (int i = 0; i < msel->len; i++) {
150 if (msel->items[i] == gz) {
151 for (int j = i; j < (msel->len - 1); j++) {
152 msel->items[j] = msel->items[j + 1];
153 }
155 break;
156 }
157 }
158}
159
162/* -------------------------------------------------------------------- */
167{
168 gzmap->type = gzmap_type;
169 gzmap->is_init = true;
171
172 /* Create all gizmo-groups for this gizmo-map. We may create an empty one
173 * too in anticipation of gizmos from operators etc. */
174 LISTBASE_FOREACH (wmGizmoGroupTypeRef *, gzgt_ref, &gzmap_type->grouptype_refs) {
175 wm_gizmogroup_new_from_type(gzmap, gzgt_ref->type);
176 }
177
178 return gzmap;
179}
180
182{
183 wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(gzmap_params);
184 wmGizmoMap *gzmap = static_cast<wmGizmoMap *>(MEM_callocN(sizeof(wmGizmoMap), "GizmoMap"));
185 wm_gizmomap_new_from_type_ex(gzmap_type, gzmap);
186 return gzmap;
187}
188
190{
191 /* Clear first so further calls don't waste time trying to maintain correct array state. */
193
194 for (wmGizmoGroup *gzgroup = static_cast<wmGizmoGroup *>(gzmap->groups.first), *gzgroup_next;
195 gzgroup;
196 gzgroup = gzgroup_next)
197 {
198 gzgroup_next = gzgroup->next;
199 BLI_assert(gzgroup->parent_gzmap == gzmap);
200 wm_gizmogroup_free(nullptr, gzgroup);
201 }
203}
204
206{
208 MEM_freeN(gzmap);
209}
210
212{
213 wmGizmoMapType *gzmap_type = gzmap->type;
215 memset(gzmap, 0x0, sizeof(*gzmap));
216 wm_gizmomap_new_from_type_ex(gzmap_type, gzmap);
217}
218
220{
221 wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false);
222 if (gzgt) {
223 return WM_gizmomap_group_find_ptr(gzmap, gzgt);
224 }
225 return nullptr;
226}
227
229{
230 LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
231 if (gzgroup->type == gzgt) {
232 return gzgroup;
233 }
234 }
235 return nullptr;
236}
237
239{
240 return &gzmap->groups;
241}
242
244{
245 return gzmap->gzmap_context.select.len != 0;
246}
247
249{
250 return gzmap->gzmap_context.modal;
251}
252
254 const wmGizmoMap *gzmap, bool /*use_hidden*/, bool use_select, float r_min[3], float r_max[3])
255{
256 if (use_select) {
257 int i;
258 for (i = 0; i < gzmap->gzmap_context.select.len; i++) {
259 minmax_v3v3_v3(r_min, r_max, gzmap->gzmap_context.select.items[i]->matrix_basis[3]);
260 }
261 return i != 0;
262 }
263
264 bool ok = false;
265 BLI_assert_msg(0, "TODO");
266 return ok;
267}
268
279 wmGizmoMap *gzmap,
280 bool (*poll)(const wmGizmo *, void *),
281 void *data,
282 const eWM_GizmoFlag flag_exclude)
283{
284 GHash *hash = BLI_ghash_ptr_new(__func__);
285
286 /* Collect gizmos. */
287 LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
288 if (WM_gizmo_group_type_poll(C, gzgroup->type)) {
289 LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
290 if (((flag_exclude == 0) || ((gz->flag & flag_exclude) == 0)) && (!poll || poll(gz, data)))
291 {
292 BLI_ghash_insert(hash, gz, gz);
293 }
294 }
295 }
296 }
297
298 return hash;
299}
300
302{
304 if (gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
306 }
307 else {
309 }
310 return step;
311}
312
314{
316 if (gzmap) {
318 }
319}
320
322{
323 if (gzmap) {
324 for (int i = 0; i < WM_GIZMOMAP_DRAWSTEP_MAX; i++) {
326 }
327 }
328}
329
331{
332 LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
333 if (gzgroup->hide.delay_refresh_for_tweak) {
334 return true;
335 }
336 }
337 return false;
338}
339
341 wmGizmo *gz,
342 const bContext *C,
343 ListBase *draw_gizmos,
344 const eWM_GizmoFlagMapDrawStep drawstep)
345{
346 int do_draw = wm_gizmo_is_visible(gz);
347 if (do_draw == 0) {
348 /* Skip. */
349 }
350 else {
351 /* Ensure we get RNA updates. */
352 if (do_draw & WM_GIZMO_IS_VISIBLE_UPDATE) {
353 /* Hover gizmos need updating, even if we don't draw them. */
354 wm_gizmo_update(gz, C, (gzmap->update_flag[drawstep] & GIZMOMAP_IS_PREPARE_DRAW) != 0);
355 }
356 if (do_draw & WM_GIZMO_IS_VISIBLE_DRAW) {
357 BLI_addhead(draw_gizmos, BLI_genericNodeN(gz));
358 }
359 return true;
360 }
361
362 return false;
363}
364
370 const bContext *C,
371 ListBase *draw_gizmos,
372 const eWM_GizmoFlagMapDrawStep drawstep)
373{
374 if (!gzmap || BLI_listbase_is_empty(&gzmap->groups)) {
375 return;
376 }
377
378 gzmap->is_init = false;
379
380 wmGizmo *gz_modal = gzmap->gzmap_context.modal;
381
382 /* Allow refresh functions to ask to be refreshed again, clear before the loop below. */
383 const bool do_refresh = gzmap->update_flag[drawstep] & GIZMOMAP_IS_REFRESH_CALLBACK;
384 gzmap->update_flag[drawstep] &= ~GIZMOMAP_IS_REFRESH_CALLBACK;
385
386 LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
387 /* Check group visibility - drawstep first to avoid unnecessary call of group poll callback. */
388 if (!wm_gizmogroup_is_visible_in_drawstep(gzgroup, drawstep)) {
389 continue;
390 }
391
392 if (gz_modal && (gzgroup == gz_modal->parent_gzgroup)) {
393 if (gzgroup->type->flag & WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE) {
394 continue;
395 }
396 }
397 else { /* Don't poll modal gizmo since some poll functions unlink. */
398 if (!WM_gizmo_group_type_poll(C, gzgroup->type)) {
399 continue;
400 }
401 /* When modal only show other gizmo groups tagged with #WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL. */
402 if (gz_modal && ((gzgroup->type->flag & WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL) == 0)) {
403 continue;
404 }
405 }
406
407 /* Needs to be initialized on first draw. */
408 /* XXX weak: Gizmo-group may skip refreshing if it's invisible
409 * (map gets untagged nevertheless). */
410 if (do_refresh) {
411 /* Force refresh again. */
412 gzgroup->init_flag &= ~WM_GIZMOGROUP_INIT_REFRESH;
413 }
414 /* Calls `setup`, `setup_keymap` and `refresh` if they're defined. */
415 WM_gizmogroup_ensure_init(C, gzgroup);
416
417 /* Check after ensure which can run refresh and update this value. */
418 if (gzgroup->hide.any != 0) {
419 continue;
420 }
421
422 /* Prepare drawing. */
423 if (gzgroup->type->draw_prepare) {
424 gzgroup->type->draw_prepare(C, gzgroup);
425 }
426
427 LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
428 gizmo_prepare_drawing(gzmap, gz, C, draw_gizmos, drawstep);
429 }
430 }
431
432 gzmap->update_flag[drawstep] &= ~GIZMOMAP_IS_PREPARE_DRAW;
433}
434
439static void gizmos_draw_list(const wmGizmoMap *gzmap, const bContext *C, ListBase *draw_gizmos)
440{
441 /* Can be empty if we're dynamically added and removed. */
442 if ((gzmap == nullptr) || BLI_listbase_is_empty(&gzmap->groups)) {
443 return;
444 }
445
446 /* TODO(@ideasman42): This will need its own shader probably?
447 * Don't think it can be handled from that point though. */
448 // const bool use_lighting = (U.gizmo_flag & V3D_GIZMO_SHADED) != 0;
449
450 bool is_depth_prev = false;
451
452 /* `draw_gizmos` contains all visible gizmos - draw them. */
453 for (LinkData *link = static_cast<LinkData *>(draw_gizmos->first), *link_next; link;
454 link = link_next)
455 {
456 wmGizmo *gz = static_cast<wmGizmo *>(link->data);
457 link_next = link->next;
458
459 bool is_depth = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_DEPTH_3D) != 0;
460
461 /* Weak! since we don't 100% support depth yet (select ignores depth)
462 * always show highlighted. */
463 if (is_depth && (gz->state & WM_GIZMO_STATE_HIGHLIGHT)) {
464 is_depth = false;
465 }
466
467 if (is_depth == is_depth_prev) {
468 /* Pass. */
469 }
470 else {
471 if (is_depth) {
473 }
474 else {
476 }
477 is_depth_prev = is_depth;
478 }
479
480 /* XXX force AntiAlias Gizmos. */
481 GPU_line_smooth(true);
482 GPU_polygon_smooth(true);
483
484 gz->type->draw(C, gz);
485
486 GPU_line_smooth(false);
487 GPU_polygon_smooth(false);
488
489 /* Free/remove gizmo link after drawing. */
490 BLI_freelinkN(draw_gizmos, link);
491 }
492
493 if (is_depth_prev) {
495 }
496}
497
499 const bContext *C,
500 const eWM_GizmoFlagMapDrawStep drawstep)
501{
502 if (!WM_gizmo_context_check_drawstep(C, drawstep)) {
503 return;
504 }
505
506 ListBase draw_gizmos = {nullptr};
507
508 gizmomap_prepare_drawing(gzmap, C, &draw_gizmos, drawstep);
509 gizmos_draw_list(gzmap, C, &draw_gizmos);
510 BLI_assert(BLI_listbase_is_empty(&draw_gizmos));
511}
512
514 wmGizmo **visible_gizmos,
515 const int visible_gizmos_len,
516 bool *r_use_select_bias)
517{
518
519 /* TODO(@ideasman42): this depends on depth buffer being written to,
520 * currently broken for the 3D view. */
521 bool is_depth_prev = false;
522 bool is_depth_skip_prev = false;
523
524 for (int select_id = 0; select_id < visible_gizmos_len; select_id++) {
525 wmGizmo *gz = visible_gizmos[select_id];
526 if (gz->type->draw_select == nullptr) {
527 continue;
528 }
529
530 bool is_depth = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_DEPTH_3D) != 0;
531 if (is_depth == is_depth_prev) {
532 /* Pass. */
533 }
534 else {
535 if (is_depth) {
537 }
538 else {
540 }
541 is_depth_prev = is_depth;
542 }
543 bool is_depth_skip = (gz->flag & WM_GIZMO_SELECT_BACKGROUND) != 0;
544 if (is_depth_skip == is_depth_skip_prev) {
545 /* Pass. */
546 }
547 else {
548 GPU_depth_mask(!is_depth_skip);
549 is_depth_skip_prev = is_depth_skip;
550 }
551
552 if (gz->select_bias != 0.0) {
553 *r_use_select_bias = true;
554 }
555
556 /* Pass the selection id shifted by 8 bits. Last 8 bits are used for selected gizmo part id. */
557
558 gz->type->draw_select(C, gz, select_id << 8);
559 }
560
561 if (is_depth_prev) {
563 }
564 if (is_depth_skip_prev) {
565 GPU_depth_mask(true);
566 }
567}
568
569static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
570 const int visible_gizmos_len,
571 const bContext *C,
572 const int co[2],
573 const int hotspot)
574{
575 const wmWindowManager *wm = CTX_wm_manager(C);
576 ScrArea *area = CTX_wm_area(C);
577 ARegion *region = CTX_wm_region(C);
578 View3D *v3d = static_cast<View3D *>(area->spacedata.first);
580 rcti rect;
581 /* Almost certainly overkill, but allow for many custom gizmos. */
582 GPUSelectBuffer buffer;
583 short hits;
584
585 BLI_rcti_init_pt_radius(&rect, co, hotspot);
586
588 wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, nullptr, nullptr, &rect);
589
590 bool use_select_bias = false;
591
592 /* TODO: waiting for the GPU in the middle of the event loop for every
593 * mouse move is bad for performance, we need to find a solution to not
594 * use the GPU or draw something once, see #61474. */
596 /* Do the drawing. */
597 gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias);
598
599 hits = GPU_select_end();
600
601 if (hits > 0) {
603 gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias);
605 }
606
608 wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, nullptr, nullptr, nullptr);
609
610 const blender::Span<GPUSelectResult> hit_results = buffer.storage.as_span().take_front(hits);
611 if (use_select_bias && (hits > 1)) {
612 float co_direction[3];
613 float co_screen[3] = {float(co[0]), float(co[1]), 0.0f};
614 ED_view3d_win_to_vector(region, blender::float2{float(co[0]), float(co[1])}, co_direction);
615
616 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
617 const int viewport[4] = {0, 0, region->winx, region->winy};
618 float co_3d_origin[3];
619
620 GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d_origin);
621
622 int hit_found = -1;
623 float dot_best = FLT_MAX;
624
625 for (const GPUSelectResult &hit_result : hit_results) {
626 BLI_assert(hit_result.id != -1);
627 wmGizmo *gz = visible_gizmos[hit_result.id >> 8];
628 float co_3d[3];
629 co_screen[2] = float(double(hit_result.depth) / double(UINT_MAX));
630 GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d);
631 float select_bias = gz->select_bias;
632 if ((gz->flag & WM_GIZMO_DRAW_NO_SCALE) == 0) {
633 select_bias *= gz->scale_final;
634 }
635 sub_v3_v3(co_3d, co_3d_origin);
636 const float dot_test = dot_v3v3(co_3d, co_direction) - select_bias;
637 if (dot_best > dot_test) {
638 dot_best = dot_test;
639 hit_found = hit_result.id;
640 }
641 }
642 return hit_found;
643 }
644
645 const GPUSelectResult *hit_near = GPU_select_buffer_near(hit_results);
646 return hit_near ? hit_near->id : -1;
647}
648
653 const int co[2],
654 wmGizmo **visible_gizmos,
655 const int visible_gizmos_len,
656 int *r_part)
657{
658 wmGizmo *result = nullptr;
659 int visible_gizmos_len_trim = visible_gizmos_len;
660 int hit = -1;
661
662 *r_part = 0;
663
664 /* Set up view matrices. */
666
667 /* Search for 3D gizmo's that use the 2D callback for checking intersections. */
668 bool has_3d = false;
669 {
670 for (int select_id = 0; select_id < visible_gizmos_len; select_id++) {
671 wmGizmo *gz = visible_gizmos[select_id];
672 /* With both defined, favor the 3D, in case the gizmo can be used in 2D or 3D views. */
673 if (gz->type->test_select && (gz->type->draw_select == nullptr)) {
674 if ((*r_part = gz->type->test_select(C, gz, co)) != -1) {
675 hit = select_id;
676 result = gz;
677 /* Don't search past this when checking intersections. */
678 visible_gizmos_len_trim = select_id;
679 break;
680 }
681 }
682 else if (gz->type->draw_select != nullptr) {
683 has_3d = true;
684 }
685 }
686 }
687
688 /* Search for 3D intersections if they're before 2D that have been found (if any).
689 * This way we always use the first hit. */
690 if (has_3d) {
691
692 /* The depth buffer is needed for gizmos to obscure each other. */
694
695 /* When switching between modes and the mouse pointer is over a gizmo, the highlight test is
696 * performed before the viewport is fully initialized (region->draw_buffer = nullptr).
697 * When this is the case we should not use depth testing. */
698 if (viewport == nullptr) {
699 return nullptr;
700 }
701 GPUTexture *depth_tx = GPU_viewport_depth_texture(viewport);
702 GPUFrameBuffer *depth_read_fb = nullptr;
703 GPU_framebuffer_ensure_config(&depth_read_fb,
704 {
705 GPU_ATTACHMENT_TEXTURE(depth_tx),
707 });
708 GPU_framebuffer_bind(depth_read_fb);
709
710 const int hotspot_radii[] = {
711 int(3 * U.pixelsize),
712 /* This runs on mouse move, careful doing too many tests! */
713 int(10 * U.pixelsize),
714 };
715 for (int i = 0; i < ARRAY_SIZE(hotspot_radii); i++) {
717 visible_gizmos, visible_gizmos_len_trim, C, co, hotspot_radii[i]);
718 if (hit != -1) {
719 break;
720 }
721 }
722
724 GPU_framebuffer_free(depth_read_fb);
725
726 if (hit != -1) {
727 const int select_id = hit >> 8;
728 const int select_part = hit & 0xff;
729 BLI_assert(select_id < visible_gizmos_len);
730 *r_part = select_part;
731 result = visible_gizmos[select_id];
732 }
733 }
734
735 return result;
736}
737
739 bContext *C,
740 const wmEvent *event,
741 int *r_part)
742{
744 wmGizmo *gz = nullptr;
745 BLI_buffer_declare_static(wmGizmo *, visible_3d_gizmos, BLI_BUFFER_NOP, 128);
746 bool do_step[WM_GIZMOMAP_DRAWSTEP_MAX];
747
748 int mval[2];
749 if (event->val == KM_CLICK_DRAG) {
751 }
752 else {
753 copy_v2_v2_int(mval, event->mval);
754 }
755
756 for (int i = 0; i < ARRAY_SIZE(do_step); i++) {
758 }
759
760 LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
761
762 /* If it were important we could initialize here,
763 * but this only happens when events are handled before drawing,
764 * just skip to keep code-path for initializing gizmos simple. */
765 if ((gzgroup->hide.any != 0) || ((gzgroup->init_flag & WM_GIZMOGROUP_INIT_SETUP) == 0)) {
766 continue;
767 }
768
769 if (WM_gizmo_group_type_poll(C, gzgroup->type)) {
771 if (do_step[step]) {
772 if (gzmap->update_flag[step] & GIZMOMAP_IS_REFRESH_CALLBACK) {
773 WM_gizmo_group_refresh(C, gzgroup);
774 /* Cleared below. */
775 }
776 if (step == WM_GIZMOMAP_DRAWSTEP_3D) {
778 wm, gzgroup, event->modifier, &visible_3d_gizmos);
779 }
780 else if (step == WM_GIZMOMAP_DRAWSTEP_2D) {
782 wm, gzgroup, C, event->modifier, mval, r_part)))
783 {
784 break;
785 }
786 }
787 }
788 }
789 }
790
791 if (visible_3d_gizmos.count) {
792 /* 2D gizmos get priority. */
793 if (gz == nullptr) {
795 mval,
796 static_cast<wmGizmo **>(visible_3d_gizmos.data),
797 visible_3d_gizmos.count,
798 r_part);
799 }
800 }
801 BLI_buffer_free(&visible_3d_gizmos);
802
803 gzmap->update_flag[WM_GIZMOMAP_DRAWSTEP_3D] &= ~GIZMOMAP_IS_REFRESH_CALLBACK;
804 gzmap->update_flag[WM_GIZMOMAP_DRAWSTEP_2D] &= ~GIZMOMAP_IS_REFRESH_CALLBACK;
805
806 return gz;
807}
808
810{
811 LISTBASE_FOREACH (wmEventHandler *, handler_base, &region->handlers) {
812 if (handler_base->type == WM_HANDLER_TYPE_GIZMO) {
813 wmEventHandler_Gizmo *handler = (wmEventHandler_Gizmo *)handler_base;
814 if (handler->gizmo_map == gzmap) {
815 return;
816 }
817 }
818 }
819
820 wmEventHandler_Gizmo *handler = static_cast<wmEventHandler_Gizmo *>(
821 MEM_callocN(sizeof(*handler), __func__));
823 BLI_assert(gzmap == region->gizmo_map);
824 handler->gizmo_map = gzmap;
825 BLI_addtail(&region->handlers, handler);
826}
827
829{
830 const bool modal_running = (handler->op != nullptr);
831
832 /* Happens on render or when joining areas. */
833 if (!handler->context.region || !handler->context.region->gizmo_map) {
834 return;
835 }
836
837 wmGizmoMap *gzmap = handler->context.region->gizmo_map;
838 wmGizmo *gz = wm_gizmomap_modal_get(gzmap);
839 ScrArea *area = CTX_wm_area(C);
840 ARegion *region = CTX_wm_region(C);
841
843
844 /* Regular update for running operator. */
845 if (modal_running) {
846 wmGizmoOpElem *gzop = gz ? WM_gizmo_operator_get(gz, gz->highlight_part) : nullptr;
847 if (gz && gzop && (gzop->type != nullptr) && (gzop->type == handler->op->type)) {
848 wmGizmoFnModal modal_fn = gz->custom_modal ? gz->custom_modal : gz->type->modal;
849 if (modal_fn != nullptr) {
850 int retval = modal_fn(C, gz, event, eWM_GizmoFlagTweak(0));
851 /* The gizmo is tried to the operator, we can't choose when to exit. */
853 UNUSED_VARS_NDEBUG(retval);
854 }
855 }
856 }
857 /* Operator not running anymore. */
858 else {
859 wm_gizmomap_highlight_set(gzmap, C, nullptr, 0);
860 if (gz) {
861 /* This isn't defined if it ends because of success of cancel, we may want to change. */
862 bool cancel = true;
863 if (gz->type->exit) {
864 gz->type->exit(C, gz, cancel);
865 }
866 wm_gizmomap_modal_set(gzmap, C, gz, nullptr, false);
867 }
868 }
869
870 /* Restore the area. */
871 CTX_wm_area_set(C, area);
872 CTX_wm_region_set(C, region);
873}
874
876{
878
879 if (msel->items == nullptr || msel->len == 0) {
880 return false;
881 }
882
883 for (int i = 0; i < msel->len; i++) {
884 wm_gizmo_select_set_ex(gzmap, msel->items[i], false, false, true);
885 }
886
888
889 /* Always return true, we already checked
890 * if there's anything to deselect. */
891 return true;
892}
893
894static bool gizmo_selectable_poll(const wmGizmo *gz, void * /*data*/)
895{
897}
898
904{
906 /* GHash is used here to avoid having to loop over all gizmos twice (once to
907 * get tot_sel for allocating, once for actually selecting). Instead we collect
908 * selectable gizmos in hash table and use this to get tot_sel and do selection. */
909
912 GHashIterator gh_iter;
913 int i;
914 bool changed = false;
915
917
918 GHASH_ITER_INDEX (gh_iter, hash, i) {
919 wmGizmo *gz_iter = static_cast<wmGizmo *>(BLI_ghashIterator_getValue(&gh_iter));
920 WM_gizmo_select_set(gzmap, gz_iter, true);
921 }
922 /* Highlight first gizmo. */
923 wm_gizmomap_highlight_set(gzmap, C, msel->items[0], msel->items[0]->highlight_part);
924
925 BLI_assert(BLI_ghash_len(hash) == msel->len);
926
927 BLI_ghash_free(hash, nullptr, nullptr);
928 return changed;
929}
930
931bool WM_gizmomap_select_all(bContext *C, wmGizmoMap *gzmap, const int action)
932{
933 bool changed = false;
934
935 switch (action) {
936 case SEL_SELECT:
937 changed = wm_gizmomap_select_all_intern(C, gzmap);
938 break;
939 case SEL_DESELECT:
940 changed = wm_gizmomap_deselect_all(gzmap);
941 break;
942 default:
944 break;
945 }
946
947 if (changed) {
949 }
950
951 return changed;
952}
953
955{
956 bScreen *screen = CTX_wm_screen(C);
957
958 if (screen) {
959 ScrArea *area;
960
961 for (area = static_cast<ScrArea *>(screen->areabase.first); area; area = area->next) {
962 if (area == handler->context.area) {
963 break;
964 }
965 }
966 if (area == nullptr) {
967 /* When changing screen layouts with running modal handlers (like render display),
968 * this is not an error to print. */
969 printf("internal error: modal gizmo-map handler has invalid area\n");
970 }
971 else {
972 ARegion *region;
973 CTX_wm_area_set(C, area);
974 for (region = static_cast<ARegion *>(area->regionbase.first); region; region = region->next)
975 {
976 if (region == handler->context.region) {
977 break;
978 }
979 }
980 /* XXX no warning print here, after full-area and back regions are remade. */
981 if (region) {
982 CTX_wm_region_set(C, region);
983 }
984 }
985 }
986}
987
989{
990 /* Pass. */
991}
992
994{
995 wmGizmo *gz = gzmap->gzmap_context.highlight;
996 if (gz && gz->type->cursor_get) {
997 WM_cursor_set(win, gz->type->cursor_get(gz));
998 return true;
999 }
1000
1001 return false;
1002}
1003
1004bool wm_gizmomap_highlight_set(wmGizmoMap *gzmap, const bContext *C, wmGizmo *gz, int part)
1005{
1006 if ((gz != gzmap->gzmap_context.highlight) || (gz && part != gz->highlight_part)) {
1007 const bool init_last_cursor = !(gzmap->gzmap_context.highlight &&
1008 gzmap->gzmap_context.last_cursor != -1);
1009 if (gzmap->gzmap_context.highlight) {
1010 gzmap->gzmap_context.highlight->state &= ~WM_GIZMO_STATE_HIGHLIGHT;
1012 }
1013
1014 gzmap->gzmap_context.highlight = gz;
1015
1016 if (gz) {
1018 gz->highlight_part = part;
1019 if (init_last_cursor) {
1020 gzmap->gzmap_context.last_cursor = -1;
1021 }
1022
1023 if (C && gz->type->cursor_get) {
1024 wmWindow *win = CTX_wm_window(C);
1025 if (init_last_cursor) {
1026 gzmap->gzmap_context.last_cursor = win->cursor;
1027 }
1028 WM_cursor_set(win, gz->type->cursor_get(gz));
1029 }
1030 }
1031 else {
1032 if (C && gzmap->gzmap_context.last_cursor != -1) {
1033 wmWindow *win = CTX_wm_window(C);
1035 }
1036 gzmap->gzmap_context.last_cursor = -1;
1037 }
1038
1039 /* Tag the region for redraw. */
1040 if (C) {
1041 ARegion *region = CTX_wm_region(C);
1043 }
1044
1045 return true;
1046 }
1047
1048 return false;
1049}
1050
1052{
1053 return gzmap->gzmap_context.highlight;
1054}
1055
1057 wmGizmoMap *gzmap, bContext *C, wmGizmo *gz, const wmEvent *event, bool enable)
1058{
1059 bool do_refresh = false;
1060
1061 if (enable) {
1062 BLI_assert(gzmap->gzmap_context.modal == nullptr);
1063 wmWindow *win = CTX_wm_window(C);
1064
1065 WM_tooltip_clear(C, win);
1066
1067 /* Use even if we don't have invoke, so we can setup data before an operator runs. */
1069 gz->parent_gzgroup->type->invoke_prepare(C, gz->parent_gzgroup, gz, event);
1070 }
1071
1072 if (gz->type->invoke && (gz->type->modal || gz->custom_modal)) {
1073 const int retval = gz->type->invoke(C, gz, event);
1074 if ((retval & OPERATOR_RUNNING_MODAL) == 0) {
1075 return;
1076 }
1077 }
1078
1079 if (gzmap->gzmap_context.modal != gz) {
1080 do_refresh = true;
1081 }
1083 gzmap->gzmap_context.modal = gz;
1084
1085 if ((gz->flag & WM_GIZMO_MOVE_CURSOR) && (event->tablet.is_motion_absolute == false)) {
1086 WM_cursor_grab_enable(win, WM_CURSOR_WRAP_XY, nullptr, true);
1087 copy_v2_v2_int(gzmap->gzmap_context.event_xy, event->xy);
1089 }
1090 else {
1091 gzmap->gzmap_context.event_xy[0] = INT_MAX;
1092 }
1093
1095 if (gzop && gzop->type) {
1096 const int retval = WM_gizmo_operator_invoke(C, gz, gzop, event);
1097 if ((retval & OPERATOR_RUNNING_MODAL) == 0) {
1098 wm_gizmomap_modal_set(gzmap, C, gz, event, false);
1099 }
1100
1101 /* We failed to hook the gizmo to the operator handler or operator was canceled, return. */
1102 if (!gzmap->gzmap_context.modal) {
1103 gz->state &= ~WM_GIZMO_STATE_MODAL;
1105 }
1106 }
1107 }
1108 else {
1109 BLI_assert(ELEM(gzmap->gzmap_context.modal, nullptr, gz));
1110
1111 /* Deactivate, gizmo but first take care of some stuff. */
1112 if (gz) {
1113 gz->state &= ~WM_GIZMO_STATE_MODAL;
1115 }
1116
1117 if (gzmap->gzmap_context.modal != nullptr) {
1118 do_refresh = true;
1119 }
1120 gzmap->gzmap_context.modal = nullptr;
1121
1122 if (C) {
1123 wmWindow *win = CTX_wm_window(C);
1124 if (gzmap->gzmap_context.event_xy[0] != INT_MAX) {
1125 /* Check if some other part of Blender (typically operators)
1126 * have adjusted the grab mode since it was set.
1127 * If so: warp, so we have a predictable outcome. */
1128 if (gzmap->gzmap_context.event_grabcursor == win->grabcursor) {
1130 }
1131 else {
1133 }
1134 }
1137 }
1138
1139 gzmap->gzmap_context.event_xy[0] = INT_MAX;
1140 }
1141
1142 if (do_refresh) {
1143 const int update_flag = GIZMOMAP_IS_REFRESH_CALLBACK;
1145 gz->parent_gzgroup);
1146 gzmap->update_flag[step] |= update_flag;
1147
1148 /* Ensure the update flag is set for gizmos that were hidden while modal, see #104817. */
1149 for (int i = 0; i < WM_GIZMOMAP_DRAWSTEP_MAX; i++) {
1151 if (step_iter == step) {
1152 continue;
1153 }
1154 if ((gzmap->update_flag[i] & update_flag) == update_flag) {
1155 continue;
1156 }
1157 LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
1158 if (((gzgroup->type->flag & WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL) == 0) &&
1159 wm_gizmogroup_is_visible_in_drawstep(gzgroup, step_iter))
1160 {
1161 gzmap->update_flag[i] |= update_flag;
1162 break;
1163 }
1164 }
1165 }
1166 }
1167}
1168
1170{
1171 return gzmap->gzmap_context.modal;
1172}
1173
1174wmGizmo **wm_gizmomap_selected_get(wmGizmoMap *gzmap, int *r_selected_len)
1175{
1176 *r_selected_len = gzmap->gzmap_context.select.len;
1177 return gzmap->gzmap_context.select.items;
1178}
1179
1181{
1182 return &gzmap->groups;
1183}
1184
1186 wmGizmoMap *gzmap,
1187 ARegion *region,
1188 wmMsgBus *mbus)
1189{
1190 LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
1191 if ((gzgroup->hide.any != 0) || (gzgroup->init_flag & WM_GIZMOGROUP_INIT_SETUP) == 0 ||
1192 !WM_gizmo_group_type_poll(C, gzgroup->type))
1193 {
1194 continue;
1195 }
1196 LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
1197 if (gz->flag & WM_GIZMO_HIDDEN) {
1198 continue;
1199 }
1201 }
1202 if (gzgroup->type->message_subscribe != nullptr) {
1203 gzgroup->type->message_subscribe(C, gzgroup, mbus);
1204 }
1205 }
1206}
1207
1208 /* #wmGizmoMap. */
1209
1210/* -------------------------------------------------------------------- */
1215 bContext *C, ARegion *region, int * /*r_pass*/, double * /*pass_delay*/, bool *r_exit_on_event)
1216{
1217 wmGizmoMap *gzmap = region->gizmo_map;
1218 *r_exit_on_event = false;
1219 if (gzmap) {
1220 wmGizmo *gz = gzmap->gzmap_context.highlight;
1221 if (gz) {
1222 wmGizmoGroup *gzgroup = gz->parent_gzgroup;
1223 if ((gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) != 0) {
1224 /* On screen area of 3D gizmos may be large, exit on cursor motion. */
1225 *r_exit_on_event = true;
1226 }
1227 return UI_tooltip_create_from_gizmo(C, gz);
1228 }
1229 }
1230 return nullptr;
1231}
1232
1233 /* #wmGizmoMapType. */
1234
1235/* -------------------------------------------------------------------- */
1240{
1242 if (gzmap_type->spaceid == gzmap_params->spaceid &&
1243 gzmap_type->regionid == gzmap_params->regionid)
1244 {
1245 return gzmap_type;
1246 }
1247 }
1248
1249 return nullptr;
1250}
1251
1253{
1254 wmGizmoMapType *gzmap_type = WM_gizmomaptype_find(gzmap_params);
1255
1256 if (gzmap_type) {
1257 return gzmap_type;
1258 }
1259
1260 gzmap_type = static_cast<wmGizmoMapType *>(
1261 MEM_callocN(sizeof(wmGizmoMapType), "gizmotype list"));
1262 gzmap_type->spaceid = gzmap_params->spaceid;
1263 gzmap_type->regionid = gzmap_params->regionid;
1264 BLI_addhead(&gizmomaptypes, gzmap_type);
1265
1266 return gzmap_type;
1267}
1268
1270{
1271 for (wmGizmoMapType *gzmap_type = static_cast<wmGizmoMapType *>(gizmomaptypes.first),
1272 *gzmap_type_next;
1273 gzmap_type;
1274 gzmap_type = gzmap_type_next)
1275 {
1276 gzmap_type_next = gzmap_type->next;
1277 for (wmGizmoGroupTypeRef *
1278 gzgt_ref = static_cast<wmGizmoGroupTypeRef *>(gzmap_type->grouptype_refs.first),
1279 *gzgt_next;
1280 gzgt_ref;
1281 gzgt_ref = gzgt_next)
1282 {
1283 gzgt_next = gzgt_ref->next;
1285 }
1286 MEM_freeN(gzmap_type);
1287 }
1288}
1289
1291{
1293 LISTBASE_FOREACH (wmGizmoGroupTypeRef *, gzgt_ref, &gzmap_type->grouptype_refs) {
1294 wm_gizmogrouptype_setup_keymap(gzgt_ref->type, keyconf);
1295 }
1296 }
1297
1299}
1300
1301 /* #wmGizmoMapType. */
1302
1303/* -------------------------------------------------------------------- */
1315
1325
1332
1337
1339{
1340 if (G.background) {
1341 return;
1342 }
1343
1344 if (wm_gzmap_type_update_flag == 0) {
1345 return;
1346 }
1347
1350 if (gzmap_type->type_update_flag & WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE) {
1351 gzmap_type->type_update_flag &= ~WM_GIZMOMAPTYPE_UPDATE_REMOVE;
1352 for (wmGizmoGroupTypeRef *
1353 gzgt_ref = static_cast<wmGizmoGroupTypeRef *>(gzmap_type->grouptype_refs.first),
1354 *gzgt_ref_next;
1355 gzgt_ref;
1356 gzgt_ref = gzgt_ref_next)
1357 {
1358 gzgt_ref_next = gzgt_ref->next;
1359 if (gzgt_ref->type->type_update_flag & WM_GIZMOMAPTYPE_UPDATE_REMOVE) {
1360 gzgt_ref->type->type_update_flag &= ~WM_GIZMOMAPTYPE_UPDATE_REMOVE;
1361 WM_gizmomaptype_group_unlink(nullptr, bmain, gzmap_type, gzgt_ref->type);
1362 }
1363 }
1364 }
1365 }
1366
1367 wm_gzmap_type_update_flag &= ~WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE;
1368 }
1369
1373 if (gzmap_type->type_update_flag & type_update_all) {
1374 gzmap_type->type_update_flag &= ~eWM_GizmoFlagMapTypeUpdateFlag(type_update_all);
1375 LISTBASE_FOREACH (wmGizmoGroupTypeRef *, gzgt_ref, &gzmap_type->grouptype_refs) {
1376 if (gzgt_ref->type->type_update_flag & WM_GIZMOMAPTYPE_KEYMAP_INIT) {
1377 WM_gizmomaptype_group_init_runtime_keymap(bmain, gzgt_ref->type);
1378 gzgt_ref->type->type_update_flag &= ~WM_GIZMOMAPTYPE_KEYMAP_INIT;
1379 }
1380
1381 if (gzgt_ref->type->type_update_flag & WM_GIZMOMAPTYPE_UPDATE_INIT) {
1382 WM_gizmomaptype_group_init_runtime(bmain, gzmap_type, gzgt_ref->type);
1383 gzgt_ref->type->type_update_flag &= ~WM_GIZMOMAPTYPE_UPDATE_INIT;
1384 }
1385 }
1386 }
1387 }
1388
1389 wm_gzmap_type_update_flag &= ~WM_GIZMOMAPTYPE_GLOBAL_UPDATE_INIT;
1390 }
1391
1393 for (bScreen *screen = static_cast<bScreen *>(bmain->screens.first); screen;
1394 screen = static_cast<bScreen *>(screen->id.next))
1395 {
1396 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
1397 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
1398 ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
1399 &sl->regionbase;
1400 LISTBASE_FOREACH (ARegion *, region, regionbase) {
1401 wmGizmoMap *gzmap = region->gizmo_map;
1402 if (gzmap != nullptr && gzmap->tag_remove_group) {
1403 gzmap->tag_remove_group = false;
1404
1405 for (wmGizmoGroup *gzgroup = static_cast<wmGizmoGroup *>(gzmap->groups.first),
1406 *gzgroup_next;
1407 gzgroup;
1408 gzgroup = gzgroup_next)
1409 {
1410 gzgroup_next = gzgroup->next;
1411 if (gzgroup->tag_remove) {
1412 wm_gizmogroup_free(nullptr, gzgroup);
1414 }
1415 }
1416 }
1417 }
1418 }
1419 }
1420 }
1421 wm_gzmap_type_update_flag &= ~WM_GIZMOTYPE_GLOBAL_UPDATE_REMOVE;
1422 }
1423
1426 wm_gzmap_type_update_flag &= ~WM_GIZMOTYPE_GLOBAL_REINIT_ALL;
1427 }
1428}
1429
1432/* -------------------------------------------------------------------- */
1440{
1441 for (bScreen *screen = static_cast<bScreen *>(bmain->screens.first); screen;
1442 screen = static_cast<bScreen *>(screen->id.next))
1443 {
1444 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
1445 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
1446 ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase : &sl->regionbase;
1447 LISTBASE_FOREACH (ARegion *, region, regionbase) {
1448 wmGizmoMap *gzmap = region->gizmo_map;
1449 if ((gzmap != nullptr) && (gzmap->is_init == false)) {
1450 WM_gizmomap_reinit(gzmap);
1451
1452 /* Without a redraw elements can fail to activate
1453 * (such as the 2D viewport buttons). */
1454 ED_region_tag_redraw(region);
1455 }
1456 }
1457 }
1458 }
1459 }
1460}
1461
bScreen * CTX_wm_screen(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
void CTX_wm_area_set(bContext *C, ScrArea *area)
void CTX_wm_region_set(bContext *C, ARegion *region)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
@ BLI_BUFFER_NOP
Definition BLI_buffer.h:23
#define BLI_buffer_declare_static(type_, name_, flag_, static_count_)
Definition BLI_buffer.h:27
#define BLI_buffer_free(name_)
Definition BLI_buffer.h:96
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:303
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
unsigned int BLI_ghash_len(const GHash *gh) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:702
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.c:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.c:860
#define GHASH_ITER_INDEX(gh_iter_, ghash_, i_)
Definition BLI_ghash.h:326
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:90
#define LISTBASE_FOREACH(type, var, list)
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:269
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
struct LinkData * BLI_genericNodeN(void *data)
Definition listbase.cc:909
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
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:470
unsigned char uchar
unsigned int uint
#define UNPACK2(a)
#define ARRAY_SIZE(arr)
#define ENUM_OPERATORS(_type, _max)
#define UNUSED_VARS_NDEBUG(...)
#define ELEM(...)
@ OPERATOR_RUNNING_MODAL
void ED_region_tag_redraw_editor_overlays(ARegion *region)
Definition area.cc:669
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:634
@ SEL_SELECT
@ SEL_DESELECT
void view3d_operator_needs_opengl(const bContext *C)
void ED_view3d_draw_setup_view(const wmWindowManager *wm, wmWindow *win, Depsgraph *depsgraph, Scene *scene, ARegion *region, View3D *v3d, const float viewmat[4][4], const float winmat[4][4], const rcti *rect)
void ED_view3d_win_to_vector(const ARegion *region, const float mval[2], float r_out[3])
#define GPU_ATTACHMENT_TEXTURE(_texture)
void GPU_framebuffer_restore()
#define GPU_ATTACHMENT_NONE
void GPU_framebuffer_bind(GPUFrameBuffer *framebuffer)
#define GPU_framebuffer_ensure_config(_fb,...)
void GPU_framebuffer_free(GPUFrameBuffer *framebuffer)
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])
const GPUSelectResult * GPU_select_buffer_near(const blender::Span< GPUSelectResult > hit_results)
@ GPU_SELECT_NEAREST_SECOND_PASS
Definition GPU_select.hh:22
@ GPU_SELECT_NEAREST_FIRST_PASS
Definition GPU_select.hh:21
unsigned int GPU_select_end()
void GPU_select_begin(GPUSelectBuffer *buffer, const rcti *input, eGPUSelectMode mode, int oldhits)
void GPU_line_smooth(bool enable)
Definition gpu_state.cc:78
void GPU_depth_mask(bool depth)
Definition gpu_state.cc:110
@ GPU_DEPTH_LESS_EQUAL
Definition GPU_state.hh:111
@ GPU_DEPTH_NONE
Definition GPU_state.hh:108
void GPU_depth_test(eGPUDepthTest test)
Definition gpu_state.cc:68
void GPU_polygon_smooth(bool enable)
Definition gpu_state.cc:83
GPUTexture * GPU_viewport_depth_texture(GPUViewport *viewport)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
ARegion * UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *gz)
eWM_GizmoFlagMapDrawStep
@ WM_GIZMOMAP_DRAWSTEP_3D
@ WM_GIZMOMAP_DRAWSTEP_2D
eWM_GizmoFlagTweak
Gizmo tweak flag. Bit-flag passed to gizmo while tweaking.
eWM_GizmoFlagMapTypeUpdateFlag
@ WM_GIZMOMAPTYPE_UPDATE_REMOVE
@ WM_GIZMOMAPTYPE_KEYMAP_INIT
@ WM_GIZMOMAPTYPE_UPDATE_INIT
@ 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.hh:292
@ WM_CURSOR_WRAP_XY
Definition WM_types.hh:209
unsigned int U
Definition btGjkEpa3.h:78
Span< T > as_span() const
#define printf
const Depsgraph * depsgraph
int len
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define UINT_MAX
Definition hash_md5.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
#define G(x, y, z)
#define hash
Definition noise.c:154
#define FLT_MAX
Definition stdcycles.h:14
struct wmGizmoMap * gizmo_map
GPUSelectStorage storage
Definition GPU_select.hh:46
unsigned int id
Definition GPU_select.hh:33
void * first
ListBase screens
Definition BKE_main.hh:225
struct wmGizmoMap * gizmo_map
struct wmEventHandler_Op::@1394 context
eWM_EventHandlerType type
short val
Definition WM_types.hh:724
int xy[2]
Definition WM_types.hh:726
int mval[2]
Definition WM_types.hh:728
uint8_t modifier
Definition WM_types.hh:739
wmTabletData tablet
Definition WM_types.hh:751
wmGizmoGroupFnInvokePrepare invoke_prepare
eWM_GizmoFlagGroupTypeFlag flag
eWM_GizmoFlagMapTypeUpdateFlag type_update_flag
wmGizmoGroupType * type
struct wmGizmo ** items
eWM_GizmoFlagMapTypeUpdateFlag type_update_flag
wmGizmoMapType * next
wmGizmoMapSelectState select
struct wmGizmoMap::@1370 gzmap_context
Gizmo map runtime context.
char update_flag[WM_GIZMOMAP_DRAWSTEP_MAX]
wmGizmo * modal
ListBase groups
wmGizmoMapType * type
wmGizmo * highlight
wmOperatorType * type
wmGizmoFnDraw draw
wmGizmoFnModal modal
wmGizmoFnTestSelect test_select
wmGizmoFnExit exit
wmGizmoFnCursorGet cursor_get
wmGizmoFnInvoke invoke
wmGizmoFnDrawSelect draw_select
wmGizmoGroup * parent_gzgroup
const wmGizmoType * type
void * interaction_data
eWM_GizmoFlagState state
float matrix_basis[4][4]
float select_bias
float scale_final
wmGizmo * next
eWM_GizmoFlag flag
wmGizmoFnModal custom_modal
struct wmOperatorType * type
char is_motion_absolute
Definition WM_types.hh:677
uint len_alloc
void WM_cursor_set(wmWindow *win, int curs)
void WM_cursor_grab_enable(wmWindow *win, const eWM_CursorWrapAxis wrap, const rcti *wrap_region, const bool hide)
void WM_cursor_grab_disable(wmWindow *win, const int mouse_ungrab_xy[2])
GPUViewport * WM_draw_region_get_viewport(ARegion *region)
Definition wm_draw.cc:905
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.cc:356
wmGizmoOpElem * WM_gizmo_operator_get(wmGizmo *gz, int part_index)
Definition wm_gizmo.cc:195
bool WM_gizmo_context_check_drawstep(const bContext *C, eWM_GizmoFlagMapDrawStep step)
Definition wm_gizmo.cc:716
int WM_gizmo_operator_invoke(bContext *C, wmGizmo *gz, wmGizmoOpElem *gzop, const wmEvent *event)
Definition wm_gizmo.cc:227
void wm_gizmo_update(wmGizmo *gz, const bContext *C, const bool refresh_map)
Definition wm_gizmo.cc:490
bool WM_gizmo_select_set(wmGizmoMap *gzmap, wmGizmo *gz, bool select)
Definition wm_gizmo.cc:396
int wm_gizmo_is_visible(wmGizmo *gz)
Definition wm_gizmo.cc:498
int(*)(bContext *, wmGizmo *, const wmEvent *, eWM_GizmoFlagTweak) wmGizmoFnModal
void WM_gizmo_group_refresh(const bContext *C, wmGizmoGroup *gzgroup)
void WM_gizmomaptype_group_init_runtime_keymap(const Main *bmain, 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)
wmKeyMap * wm_gizmogroup_tweak_modal_keymap(wmKeyConfig *keyconf)
void WM_gizmogroup_ensure_init(const bContext *C, wmGizmoGroup *gzgroup)
wmGizmoGroup * wm_gizmogroup_new_from_type(wmGizmoMap *gzmap, wmGizmoGroupType *gzgt)
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)
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)
wmGizmo * wm_gizmogroup_find_intersected_gizmo(wmWindowManager *wm, const wmGizmoGroup *gzgroup, bContext *C, const int event_modifier, const int mval[2], int *r_part)
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
const ListBase * WM_gizmomap_group_list(wmGizmoMap *gzmap)
ListBase * wm_gizmomap_groups_get(wmGizmoMap *gzmap)
static GHash * WM_gizmomap_gizmo_hash_new(const bContext *C, wmGizmoMap *gzmap, bool(*poll)(const wmGizmo *, void *), void *data, const eWM_GizmoFlag flag_exclude)
void wm_gizmomap_modal_set(wmGizmoMap *gzmap, bContext *C, wmGizmo *gz, const wmEvent *event, bool enable)
wmGizmoGroup * WM_gizmomap_group_find_ptr(wmGizmoMap *gzmap, const wmGizmoGroupType *gzgt)
eWM_GizmoFlagMapDrawStep WM_gizmomap_drawstep_from_gizmo_group(const wmGizmoGroup *gzgroup)
static void wm_gizmomap_select_array_ensure_len_alloc(wmGizmoMap *gzmap, int len)
bool WM_gizmomap_is_any_selected(const wmGizmoMap *gzmap)
void wm_gizmomaps_handled_modal_update(bContext *C, wmEvent *event, wmEventHandler_Op *handler)
bool wm_gizmomap_highlight_set(wmGizmoMap *gzmap, const bContext *C, wmGizmo *gz, int part)
void WM_gizmomap_tag_refresh_drawstep(wmGizmoMap *gzmap, const eWM_GizmoFlagMapDrawStep drawstep)
@ GIZMOMAP_IS_PREPARE_DRAW
@ GIZMOMAP_IS_REFRESH_CALLBACK
wmGizmoGroup * WM_gizmomap_group_find(wmGizmoMap *gzmap, const char *idname)
void wm_gizmomaptypes_free()
void WM_reinit_gizmomap_all(Main *bmain)
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)
void WM_gizmoconfig_update_tag_group_type_init(wmGizmoMapType *gzmap_type, wmGizmoGroupType *gzgt)
bool WM_gizmomap_tag_delay_refresh_for_tweak_check(wmGizmoMap *gzmap)
wmGizmo * wm_gizmomap_highlight_find(wmGizmoMap *gzmap, bContext *C, const wmEvent *event, int *r_part)
void wm_gizmomap_select_array_remove(wmGizmoMap *gzmap, wmGizmo *gz)
void WM_gizmomap_tag_refresh(wmGizmoMap *gzmap)
wmGizmo * wm_gizmomap_highlight_get(wmGizmoMap *gzmap)
bool WM_gizmomap_select_all(bContext *C, wmGizmoMap *gzmap, const int action)
wmGizmo * WM_gizmomap_get_modal(const wmGizmoMap *gzmap)
static void gizmos_draw_list(const wmGizmoMap *gzmap, const bContext *C, ListBase *draw_gizmos)
static ListBase gizmomaptypes
void WM_gizmoconfig_update(Main *bmain)
void WM_gizmoconfig_update_tag_group_type_remove(wmGizmoMapType *gzmap_type, wmGizmoGroupType *gzgt)
ARegion * WM_gizmomap_tooltip_init(bContext *C, ARegion *region, int *, double *, bool *r_exit_on_event)
static void wm_gizmomap_free_data(wmGizmoMap *gzmap)
void wm_gizmomap_remove(wmGizmoMap *gzmap)
void WM_gizmomap_draw(wmGizmoMap *gzmap, const bContext *C, const eWM_GizmoFlagMapDrawStep drawstep)
void WM_gizmoconfig_update_tag_reinit_all()
void WM_gizmomap_reinit(wmGizmoMap *gzmap)
static void gizmo_draw_select_3d_loop(const bContext *C, wmGizmo **visible_gizmos, const int visible_gizmos_len, bool *r_use_select_bias)
static bool wm_gizmomap_select_all_intern(bContext *C, wmGizmoMap *gzmap)
wmGizmoMapType * WM_gizmomaptype_find(const wmGizmoMapType_Params *gzmap_params)
void wm_gizmomap_handler_context_op(bContext *C, wmEventHandler_Op *handler)
static eWM_GizmoFlagGroupTypeGlobalFlag wm_gzmap_type_update_flag
bool WM_gizmomap_cursor_set(const wmGizmoMap *gzmap, wmWindow *win)
static bool gizmo_prepare_drawing(wmGizmoMap *gzmap, wmGizmo *gz, const bContext *C, ListBase *draw_gizmos, const eWM_GizmoFlagMapDrawStep drawstep)
void wm_gizmomap_select_array_clear(wmGizmoMap *gzmap)
void WM_gizmomap_add_handlers(ARegion *region, wmGizmoMap *gzmap)
static wmGizmoMap * wm_gizmomap_new_from_type_ex(wmGizmoMapType *gzmap_type, wmGizmoMap *gzmap)
void WM_gizmoconfig_update_tag_group_remove(wmGizmoMap *gzmap)
void wm_gizmos_keymap(wmKeyConfig *keyconf)
wmGizmo ** wm_gizmomap_selected_get(wmGizmoMap *gzmap, int *r_selected_len)
eWM_GizmoFlagGroupTypeGlobalFlag
@ WM_GIZMOTYPE_GLOBAL_UPDATE_REMOVE
@ WM_GIZMOMAPTYPE_GLOBAL_UPDATE_INIT
@ WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE
@ WM_GIZMOTYPE_GLOBAL_REINIT_ALL
static wmGizmo * gizmo_find_intersected_3d(bContext *C, const int co[2], wmGizmo **visible_gizmos, const int visible_gizmos_len, int *r_part)
bool WM_gizmomap_minmax(const wmGizmoMap *gzmap, bool, bool use_select, float r_min[3], float r_max[3])
void wm_gizmomap_select_array_push_back(wmGizmoMap *gzmap, wmGizmo *gz)
static bool gizmo_selectable_poll(const wmGizmo *gz, void *)
void wm_gizmomap_select_array_shrink(wmGizmoMap *gzmap, int len_subtract)
bool wm_gizmomap_deselect_all(wmGizmoMap *gzmap)
wmGizmoMapType * WM_gizmomaptype_ensure(const wmGizmoMapType_Params *gzmap_params)
void wm_gizmomap_handler_context_gizmo(bContext *, wmEventHandler_Gizmo *)
void WM_gizmomap_message_subscribe(const bContext *C, wmGizmoMap *gzmap, ARegion *region, wmMsgBus *mbus)
static void gizmomap_prepare_drawing(wmGizmoMap *gzmap, const bContext *C, ListBase *draw_gizmos, const eWM_GizmoFlagMapDrawStep drawstep)
wmGizmoMap * WM_gizmomap_new_from_type(const wmGizmoMapType_Params *gzmap_params)
wmGizmo * wm_gizmomap_modal_get(wmGizmoMap *gzmap)
void WM_gizmo_target_property_subscribe_all(wmGizmo *gz, wmMsgBus *mbus, ARegion *region)
void WM_tooltip_clear(bContext *C, wmWindow *win)
Definition wm_tooltip.cc:81
void WM_cursor_warp(wmWindow *win, int x, int y)