Blender V5.0
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
8
9#include <cstring>
10
11#include "BLI_ghash.h"
12#include "BLI_listbase.h"
13#include "BLI_math_vector.h"
15#include "BLI_rect.h"
16#include "BLI_vector.hh"
17
18#include "BKE_context.hh"
19#include "BKE_global.hh"
20#include "BKE_main.hh"
21#include "BKE_screen.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_select.hh"
30#include "GPU_state.hh"
31#include "GPU_viewport.hh"
32
33#include "MEM_guardedalloc.h"
34
35#include "WM_api.hh"
36#include "WM_types.hh"
37#include "wm_event_system.hh"
38
39/* For tool-tips. */
40#include "UI_interface.hh"
41
42#include "DEG_depsgraph.hh"
43
44/* Own includes. */
45#include "wm_gizmo_intern.hh"
46#include "wm_gizmo_wmapi.hh"
47
52static ListBase gizmomaptypes = {nullptr, nullptr};
53
57/* So operator removal can trigger update. */
78
81
85enum {
89};
90
91/* -------------------------------------------------------------------- */
97
99{
102 return;
103 }
104 msel->items = static_cast<wmGizmo **>(MEM_reallocN(msel->items, sizeof(*msel->items) * len));
105 msel->len_alloc = len;
106}
107
109{
111 MEM_SAFE_FREE(msel->items);
112 msel->len = 0;
113 msel->len_alloc = 0;
114}
115
116void wm_gizmomap_select_array_shrink(wmGizmoMap *gzmap, int len_subtract)
117{
119 msel->len -= len_subtract;
120 if (msel->len <= 0) {
122 }
123 else {
124 if (msel->len < msel->len_alloc / 2) {
125 msel->items = static_cast<wmGizmo **>(
126 MEM_reallocN(msel->items, sizeof(*msel->items) * msel->len));
127 msel->len_alloc = msel->len;
128 }
129 }
130}
131
133{
135 BLI_assert(msel->len <= msel->len_alloc);
136 if (msel->len == msel->len_alloc) {
137 msel->len_alloc = (msel->len + 1) * 2;
138 msel->items = static_cast<wmGizmo **>(
139 MEM_reallocN(msel->items, sizeof(*msel->items) * msel->len_alloc));
140 }
141 msel->items[msel->len++] = gz;
142}
143
145{
147 /* Remove gizmo from selected_gizmos array. */
148 for (int i = 0; i < msel->len; i++) {
149 if (msel->items[i] == gz) {
150 for (int j = i; j < (msel->len - 1); j++) {
151 msel->items[j] = msel->items[j + 1];
152 }
154 break;
155 }
156 }
157}
158
160
161/* -------------------------------------------------------------------- */
164
166{
167 gzmap->type = gzmap_type;
168 gzmap->is_init = true;
170
171 /* Create all gizmo-groups for this gizmo-map. We may create an empty one
172 * too in anticipation of gizmos from operators etc. */
173 LISTBASE_FOREACH (wmGizmoGroupTypeRef *, gzgt_ref, &gzmap_type->grouptype_refs) {
174 wm_gizmogroup_new_from_type(gzmap, gzgt_ref->type);
175 }
176
177 return gzmap;
178}
179
181{
182 wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(gzmap_params);
183 wmGizmoMap *gzmap = MEM_callocN<wmGizmoMap>("GizmoMap");
184 wm_gizmomap_new_from_type_ex(gzmap_type, gzmap);
185 return gzmap;
186}
187
189{
190 /* Clear first so further calls don't waste time trying to maintain correct array state. */
192
193 for (wmGizmoGroup *gzgroup = static_cast<wmGizmoGroup *>(gzmap->groups.first), *gzgroup_next;
194 gzgroup;
195 gzgroup = gzgroup_next)
196 {
197 gzgroup_next = gzgroup->next;
198 BLI_assert(gzgroup->parent_gzmap == gzmap);
199 wm_gizmogroup_free(nullptr, gzgroup);
200 }
202}
203
205{
207 MEM_freeN(gzmap);
208}
209
211{
212 wmGizmoMapType *gzmap_type = gzmap->type;
214 memset(gzmap, 0x0, sizeof(*gzmap));
215 wm_gizmomap_new_from_type_ex(gzmap_type, gzmap);
216}
217
219{
220 wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false);
221 if (gzgt) {
222 return WM_gizmomap_group_find_ptr(gzmap, gzgt);
223 }
224 return nullptr;
225}
226
228{
229 LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
230 if (gzgroup->type == gzgt) {
231 return gzgroup;
232 }
233 }
234 return nullptr;
235}
236
238{
239 return &gzmap->groups;
240}
241
243{
244 return gzmap->gzmap_context.select.len != 0;
245}
246
248{
249 return gzmap->gzmap_context.modal;
250}
251
253 const wmGizmoMap *gzmap, bool /*use_hidden*/, bool use_select, float r_min[3], float r_max[3])
254{
255 if (use_select) {
256 int i;
257 for (i = 0; i < gzmap->gzmap_context.select.len; i++) {
258 minmax_v3v3_v3(r_min, r_max, gzmap->gzmap_context.select.items[i]->matrix_basis[3]);
259 }
260 return i != 0;
261 }
262
263 bool ok = false;
264 BLI_assert_msg(0, "TODO");
265 return ok;
266}
267
278 wmGizmoMap *gzmap,
279 bool (*poll)(const wmGizmo *, void *),
280 void *data,
281 const eWM_GizmoFlag flag_exclude)
282{
283 GHash *hash = BLI_ghash_ptr_new(__func__);
284
285 /* Collect gizmos. */
286 LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
287 if (WM_gizmo_group_type_poll(C, gzgroup->type)) {
288 LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
289 if (((flag_exclude == 0) || ((gz->flag & flag_exclude) == 0)) && (!poll || poll(gz, data)))
290 {
291 BLI_ghash_insert(hash, gz, gz);
292 }
293 }
294 }
295 }
296
297 return hash;
298}
299
311
313{
315 if (gzmap) {
317 /* This could be split out into a separate tagging function,
318 * in practice both when refreshing the highlight should also be updated. */
319 gzmap->tag_highlight_pending = true;
320 }
321}
322
324{
325 if (gzmap) {
326 for (int i = 0; i < WM_GIZMOMAP_DRAWSTEP_MAX; i++) {
328 }
329 /* See code-comment for #WM_gizmomap_tag_refresh_drawstep. */
330 gzmap->tag_highlight_pending = true;
331 }
332}
333
335{
336 LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
337 if (gzgroup->hide.delay_refresh_for_tweak) {
338 return true;
339 }
340 }
341 return false;
342}
343
345 wmGizmo *gz,
346 const bContext *C,
347 ListBase *draw_gizmos,
348 const eWM_GizmoFlagMapDrawStep drawstep)
349{
350 int do_draw = wm_gizmo_is_visible(gz);
351 if (do_draw == 0) {
352 /* Skip. */
353 }
354 else {
355 /* Ensure we get RNA updates. */
356 if (do_draw & WM_GIZMO_IS_VISIBLE_UPDATE) {
357 /* Hover gizmos need updating, even if we don't draw them. */
358 wm_gizmo_update(gz, C, (gzmap->update_flag[drawstep] & GIZMOMAP_IS_PREPARE_DRAW) != 0);
359 }
360 if (do_draw & WM_GIZMO_IS_VISIBLE_DRAW) {
361 BLI_addhead(draw_gizmos, BLI_genericNodeN(gz));
362 }
363 return true;
364 }
365
366 return false;
367}
368
374 const bContext *C,
375 ListBase *draw_gizmos,
376 const eWM_GizmoFlagMapDrawStep drawstep)
377{
378 if (!gzmap || BLI_listbase_is_empty(&gzmap->groups)) {
379 return;
380 }
381
382 gzmap->is_init = false;
383
384 wmGizmo *gz_modal = gzmap->gzmap_context.modal;
385
386 /* Allow refresh functions to ask to be refreshed again, clear before the loop below. */
387 const bool do_refresh = gzmap->update_flag[drawstep] & GIZMOMAP_IS_REFRESH_CALLBACK;
388 gzmap->update_flag[drawstep] &= ~GIZMOMAP_IS_REFRESH_CALLBACK;
389
390 LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
391 /* Check group visibility - drawstep first to avoid unnecessary call of group poll callback. */
392 if (!wm_gizmogroup_is_visible_in_drawstep(gzgroup, drawstep)) {
393 continue;
394 }
395
396 if (gz_modal && (gzgroup == gz_modal->parent_gzgroup)) {
397 if (gzgroup->type->flag & WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE) {
398 continue;
399 }
400 }
401 else { /* Don't poll modal gizmo since some poll functions unlink. */
402 if (!WM_gizmo_group_type_poll(C, gzgroup->type)) {
403 continue;
404 }
405 /* When modal only show other gizmo groups tagged with #WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL. */
406 if (gz_modal && ((gzgroup->type->flag & WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL) == 0)) {
407 continue;
408 }
409 }
410
411 /* Needs to be initialized on first draw. */
412 /* XXX weak: Gizmo-group may skip refreshing if it's invisible
413 * (map gets untagged nevertheless). */
414 if (do_refresh) {
415 /* Force refresh again. */
416 gzgroup->init_flag &= ~WM_GIZMOGROUP_INIT_REFRESH;
417 }
418 /* Calls `setup`, `setup_keymap` and `refresh` if they're defined. */
420
421 /* Check after ensure which can run refresh and update this value. */
422 if (gzgroup->hide.any != 0) {
423 continue;
424 }
425
426 /* Prepare drawing. */
427 if (gzgroup->type->draw_prepare) {
428 gzgroup->type->draw_prepare(C, gzgroup);
429 }
430
431 LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
432 gizmo_prepare_drawing(gzmap, gz, C, draw_gizmos, drawstep);
433 }
434 }
435
436 gzmap->update_flag[drawstep] &= ~GIZMOMAP_IS_PREPARE_DRAW;
437}
438
443static void gizmos_draw_list(const wmGizmoMap *gzmap, const bContext *C, ListBase *draw_gizmos)
444{
445 /* Can be empty if we're dynamically added and removed. */
446 if ((gzmap == nullptr) || BLI_listbase_is_empty(&gzmap->groups)) {
447 return;
448 }
449
450 /* TODO(@ideasman42): This will need its own shader probably?
451 * Don't think it can be handled from that point though. */
452 // const bool use_lighting = (U.gizmo_flag & V3D_GIZMO_SHADED) != 0;
453
454 bool is_depth_prev = false;
455
456 /* `draw_gizmos` contains all visible gizmos - draw them. */
457 for (LinkData *link = static_cast<LinkData *>(draw_gizmos->first), *link_next; link;
458 link = link_next)
459 {
460 wmGizmo *gz = static_cast<wmGizmo *>(link->data);
461 link_next = link->next;
462
463 bool is_depth = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_DEPTH_3D) != 0;
464
465 /* Weak! since we don't 100% support depth yet (select ignores depth)
466 * always show highlighted. */
467 if (is_depth && (gz->state & WM_GIZMO_STATE_HIGHLIGHT)) {
468 is_depth = false;
469 }
470
471 if (is_depth == is_depth_prev) {
472 /* Pass. */
473 }
474 else {
475 if (is_depth) {
477 }
478 else {
480 }
481 is_depth_prev = is_depth;
482 }
483
484 /* XXX force AntiAlias Gizmos. */
485 GPU_line_smooth(true);
486 GPU_polygon_smooth(true);
487
488 gz->type->draw(C, gz);
489
490 GPU_line_smooth(false);
491 GPU_polygon_smooth(false);
492
493 /* Free/remove gizmo link after drawing. */
494 BLI_freelinkN(draw_gizmos, link);
495 }
496
497 if (is_depth_prev) {
499 }
500}
501
503 const bContext *C,
504 const eWM_GizmoFlagMapDrawStep drawstep)
505{
506 if (!WM_gizmo_context_check_drawstep(C, drawstep)) {
507 return;
508 }
509
510 ListBase draw_gizmos = {nullptr};
511
512 gizmomap_prepare_drawing(gzmap, C, &draw_gizmos, drawstep);
513 gizmos_draw_list(gzmap, C, &draw_gizmos);
514 BLI_assert(BLI_listbase_is_empty(&draw_gizmos));
515}
516
518 wmGizmo **visible_gizmos,
519 const int visible_gizmos_len,
520 bool *r_use_select_bias)
521{
522 /* WORKAROUND(#132196): `GPU_DEPTH_NONE` leads to issues with Intel GPU drivers on Windows
523 * where camera gizmos cannot be shifted. `glGetQueryObjectuiv` for `GL_SAMPLES_PASSED`
524 * seems to return zero in all cases. This might be due to undefined behavior of OpenGL
525 * when the depth test is disabled and rendering to a depth render target-only framebuffer.
526 * Using `GPU_DEPTH_ALWAYS` fixes the issue. */
527 const bool use_intel_gpu_workaround = true;
528
529 /* Set default depth state. */
530 GPU_depth_test(use_intel_gpu_workaround ? GPU_DEPTH_ALWAYS : GPU_DEPTH_NONE);
531 GPU_depth_mask(true);
532 bool is_depth_prev = false;
533 bool is_depth_skip_prev = false;
534
535 for (int select_id = 0; select_id < visible_gizmos_len; select_id++) {
536 wmGizmo *gz = visible_gizmos[select_id];
537 if (gz->type->draw_select == nullptr) {
538 continue;
539 }
540
541 bool is_depth = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_DEPTH_3D) != 0;
542 if (is_depth == is_depth_prev) {
543 /* Pass. */
544 }
545 else {
546 if (is_depth) {
548 }
549 else {
550 GPU_depth_test(use_intel_gpu_workaround ? GPU_DEPTH_ALWAYS : GPU_DEPTH_NONE);
551 }
552 is_depth_prev = is_depth;
553 }
554 bool is_depth_skip = (gz->flag & WM_GIZMO_SELECT_BACKGROUND) != 0;
555 if (is_depth_skip == is_depth_skip_prev) {
556 /* Pass. */
557 }
558 else {
559 GPU_depth_mask(!is_depth_skip);
560 is_depth_skip_prev = is_depth_skip;
561 }
562
563 if (gz->select_bias != 0.0) {
564 *r_use_select_bias = true;
565 }
566
567 /* Pass the selection id shifted by 8 bits. Last 8 bits are used for selected gizmo part id. */
568
569 gz->type->draw_select(C, gz, select_id << 8);
570 }
571
572 /* Reset depth state. */
573
574 if (is_depth_prev || use_intel_gpu_workaround) {
576 }
577 if (is_depth_skip_prev) {
578 GPU_depth_mask(true);
579 }
580}
581
582static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
583 const int visible_gizmos_len,
584 const bContext *C,
585 const int co[2],
586 const int hotspot)
587{
588 const wmWindowManager *wm = CTX_wm_manager(C);
589 ScrArea *area = CTX_wm_area(C);
590 ARegion *region = CTX_wm_region(C);
591 View3D *v3d = static_cast<View3D *>(area->spacedata.first);
593 rcti rect;
594 /* Almost certainly overkill, but allow for many custom gizmos. */
595 GPUSelectBuffer buffer;
596 short hits;
597
598 BLI_rcti_init_pt_radius(&rect, co, hotspot);
599
601 wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, nullptr, nullptr, &rect);
602
603 bool use_select_bias = false;
604
605 /* TODO: waiting for the GPU in the middle of the event loop for every
606 * mouse move is bad for performance, we need to find a solution to not
607 * use the GPU or draw something once, see #61474. */
609 /* Do the drawing. */
610 gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias);
611
612 hits = GPU_select_end();
613
614 if (hits > 0) {
616 gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias);
618 }
619
621 wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, nullptr, nullptr, nullptr);
622
623 const blender::Span<GPUSelectResult> hit_results = buffer.storage.as_span().take_front(hits);
624 if (use_select_bias && (hits > 1)) {
625 float co_direction[3];
626 float co_screen[3] = {float(co[0]), float(co[1]), 0.0f};
627 ED_view3d_win_to_vector(region, blender::float2{float(co[0]), float(co[1])}, co_direction);
628
629 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
630 const int viewport[4] = {0, 0, region->winx, region->winy};
631 float co_3d_origin[3];
632
633 GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d_origin);
634
635 int hit_found = -1;
636 float dot_best = FLT_MAX;
637
638 for (const GPUSelectResult &hit_result : hit_results) {
639 BLI_assert(hit_result.id != -1);
640 wmGizmo *gz = visible_gizmos[hit_result.id >> 8];
641 float co_3d[3];
642 co_screen[2] = float(double(hit_result.depth) / double(UINT_MAX));
643 GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d);
644 float select_bias = gz->select_bias;
645 if ((gz->flag & WM_GIZMO_DRAW_NO_SCALE) == 0) {
646 select_bias *= gz->scale_final;
647 }
648 sub_v3_v3(co_3d, co_3d_origin);
649 const float dot_test = dot_v3v3(co_3d, co_direction) - select_bias;
650 if (dot_best > dot_test) {
651 dot_best = dot_test;
652 hit_found = hit_result.id;
653 }
654 }
655 return hit_found;
656 }
657
658 const GPUSelectResult *hit_near = GPU_select_buffer_near(hit_results);
659 return hit_near ? hit_near->id : -1;
660}
661
666 const int co[2],
667 wmGizmo **visible_gizmos,
668 const int visible_gizmos_len,
669 int *r_part)
670{
671 wmGizmo *result = nullptr;
672 int visible_gizmos_len_trim = visible_gizmos_len;
673 int hit = -1;
674
675 *r_part = 0;
676
677 /* Set up view matrices. */
679
680 /* Search for 3D gizmo's that use the 2D callback for checking intersections. */
681 bool has_3d = false;
682 {
683 for (int select_id = 0; select_id < visible_gizmos_len; select_id++) {
684 wmGizmo *gz = visible_gizmos[select_id];
685 /* With both defined, favor the 3D, in case the gizmo can be used in 2D or 3D views. */
686 if (gz->type->test_select && (gz->type->draw_select == nullptr)) {
687 if ((*r_part = gz->type->test_select(C, gz, co)) != -1) {
688 hit = select_id;
689 result = gz;
690 /* Don't search past this when checking intersections. */
691 visible_gizmos_len_trim = select_id;
692 break;
693 }
694 }
695 else if (gz->type->draw_select != nullptr) {
696 has_3d = true;
697 }
698 }
699 }
700
701 /* Search for 3D intersections if they're before 2D that have been found (if any).
702 * This way we always use the first hit. */
703 if (has_3d) {
704
705 /* The depth buffer is needed for gizmos to obscure each other. */
707
708 /* When switching between modes and the mouse pointer is over a gizmo, the highlight test is
709 * performed before the viewport is fully initialized (region->runtime->draw_buffer = nullptr).
710 * When this is the case we should not use depth testing. */
711 if (viewport == nullptr) {
712 return nullptr;
713 }
715 blender::gpu::FrameBuffer *depth_read_fb = nullptr;
716 GPU_framebuffer_ensure_config(&depth_read_fb,
717 {
718 GPU_ATTACHMENT_TEXTURE(depth_tx),
720 });
721 GPU_framebuffer_bind(depth_read_fb);
722
723 /* NOTE(@ideasman42): Regarding the hit-radius:
724 *
725 * - These must remain constant for all event types
726 * since changing the radius per event types means non-motion events
727 * can cause the gizmo not to be highlighted.
728 * - A single large radius would result in gizmos that are further away from the cursor
729 * with a nearer Z-depth being highlighted.
730 * So only use the larger radius when the first (smaller) pass has no hits.
731 * - As this runs on cursor-motion, avoid doing too many tests (currently 2x).
732 */
733 const int hotspot_radii[] = {
734 /* Use a small value so it's possible to accurately pick a gizmo
735 * when multiple are overlapping. */
736 int(3.0f * UI_SCALE_FAC),
737 /* Use a larger value as a fallback so wire gizmos aren't difficult to click on. */
738 int(10.0f * UI_SCALE_FAC),
739 };
740 for (int i = 0; i < ARRAY_SIZE(hotspot_radii); i++) {
742 visible_gizmos, visible_gizmos_len_trim, C, co, hotspot_radii[i]);
743 if (hit != -1) {
744 break;
745 }
746 }
747
749 GPU_framebuffer_free(depth_read_fb);
750
751 if (hit != -1) {
752 const int select_id = hit >> 8;
753 const int select_part = hit & 0xff;
754 BLI_assert(select_id < visible_gizmos_len);
755 *r_part = select_part;
756 result = visible_gizmos[select_id];
757 }
758 }
759
760 return result;
761}
762
764{
765 return gzmap->tag_highlight_pending;
766}
768{
769 return gzmap->tag_highlight_pending = false;
770}
771
773 bContext *C,
774 const wmEvent *event,
775 int *r_part)
776{
778 wmGizmo *gz = nullptr;
779 blender::Vector<wmGizmo *, 128> visible_3d_gizmos;
780 bool do_step[WM_GIZMOMAP_DRAWSTEP_MAX];
781
782 int mval[2];
783 if (event->val == KM_PRESS_DRAG) {
785 }
786 else {
787 copy_v2_v2_int(mval, event->mval);
788 }
789
790 for (int i = 0; i < ARRAY_SIZE(do_step); i++) {
792 }
793
794 LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
795
796 /* If it were important we could initialize here,
797 * but this only happens when events are handled before drawing,
798 * just skip to keep code-path for initializing gizmos simple. */
799 if ((gzgroup->hide.any != 0) || ((gzgroup->init_flag & WM_GIZMOGROUP_INIT_SETUP) == 0)) {
800 continue;
801 }
802
803 if (WM_gizmo_group_type_poll(C, gzgroup->type)) {
805 if (do_step[step]) {
807 WM_gizmo_group_refresh(C, gzgroup);
808 /* Cleared below. */
809 }
812 wm, gzgroup, event->modifier, &visible_3d_gizmos);
813 }
814 else if (step == WM_GIZMOMAP_DRAWSTEP_2D) {
816 wm, gzgroup, C, event->modifier, mval, r_part)))
817 {
818 break;
819 }
820 }
821 }
822 }
823 }
824
825 if (!visible_3d_gizmos.is_empty()) {
826 /* 2D gizmos get priority. */
827 if (gz == nullptr) {
829 C, mval, visible_3d_gizmos.data(), visible_3d_gizmos.size(), r_part);
830 }
831 }
832
835
836 return gz;
837}
838
840{
841 LISTBASE_FOREACH (wmEventHandler *, handler_base, &region->runtime->handlers) {
842 if (handler_base->type == WM_HANDLER_TYPE_GIZMO) {
843 wmEventHandler_Gizmo *handler = (wmEventHandler_Gizmo *)handler_base;
844 if (handler->gizmo_map == gzmap) {
845 return;
846 }
847 }
848 }
849
852 BLI_assert(gzmap == region->runtime->gizmo_map);
853 handler->gizmo_map = gzmap;
854 BLI_addtail(&region->runtime->handlers, handler);
855}
856
858{
859 const bool modal_running = (handler->op != nullptr);
860
861 /* Happens on render or when joining areas. */
862 if (!handler->context.region || !handler->context.region->runtime->gizmo_map) {
863 return;
864 }
865
866 wmGizmoMap *gzmap = handler->context.region->runtime->gizmo_map;
867 wmGizmo *gz = wm_gizmomap_modal_get(gzmap);
868 ScrArea *area = CTX_wm_area(C);
869 ARegion *region = CTX_wm_region(C);
870
872
873 /* Regular update for running operator. */
874 if (modal_running) {
875 wmGizmoOpElem *gzop = gz ? WM_gizmo_operator_get(gz, gz->highlight_part) : nullptr;
876 if (gz && gzop && (gzop->type != nullptr) && (gzop->type == handler->op->type)) {
877 wmGizmoFnModal modal_fn = gz->custom_modal ? gz->custom_modal : gz->type->modal;
878 if (modal_fn != nullptr) {
879 const wmOperatorStatus retval = modal_fn(C, gz, event, eWM_GizmoFlagTweak(0));
880 OPERATOR_RETVAL_CHECK(retval);
881 /* The gizmo is tried to the operator, we can't choose when to exit. */
883 UNUSED_VARS_NDEBUG(retval);
884 }
885 }
886 }
887 /* Operator not running anymore. */
888 else {
889 wm_gizmomap_highlight_set(gzmap, C, nullptr, 0);
890 if (gz) {
891 /* This isn't defined if it ends because of success of cancel, we may want to change. */
892 bool cancel = true;
893 if (gz->type->exit) {
894 gz->type->exit(C, gz, cancel);
895 }
896 wm_gizmomap_modal_set(gzmap, C, gz, nullptr, false);
897 }
898 }
899
900 /* Restore the area. */
901 CTX_wm_area_set(C, area);
902 CTX_wm_region_set(C, region);
903}
904
906{
908
909 if (msel->items == nullptr || msel->len == 0) {
910 return false;
911 }
912
913 for (int i = 0; i < msel->len; i++) {
914 wm_gizmo_select_set_ex(gzmap, msel->items[i], false, false, true);
915 }
916
918
919 /* Always return true, we already checked
920 * if there's anything to deselect. */
921 return true;
922}
923
924static bool gizmo_selectable_poll(const wmGizmo *gz, void * /*data*/)
925{
927}
928
934{
936 /* GHash is used here to avoid having to loop over all gizmos twice (once to
937 * get tot_sel for allocating, once for actually selecting). Instead we collect
938 * selectable gizmos in hash table and use this to get tot_sel and do selection. */
939
942 GHashIterator gh_iter;
943 int i;
944 bool changed = false;
945
947
948 GHASH_ITER_INDEX (gh_iter, hash, i) {
949 wmGizmo *gz_iter = static_cast<wmGizmo *>(BLI_ghashIterator_getValue(&gh_iter));
950 WM_gizmo_select_set(gzmap, gz_iter, true);
951 }
952 /* Highlight first gizmo. */
953 wm_gizmomap_highlight_set(gzmap, C, msel->items[0], msel->items[0]->highlight_part);
954
955 BLI_assert(BLI_ghash_len(hash) == msel->len);
956
957 BLI_ghash_free(hash, nullptr, nullptr);
958 return changed;
959}
960
961bool WM_gizmomap_select_all(bContext *C, wmGizmoMap *gzmap, const int action)
962{
963 bool changed = false;
964
965 switch (action) {
966 case SEL_SELECT:
967 changed = wm_gizmomap_select_all_intern(C, gzmap);
968 break;
969 case SEL_DESELECT:
970 changed = wm_gizmomap_deselect_all(gzmap);
971 break;
972 default:
974 break;
975 }
976
977 if (changed) {
979 }
980
981 return changed;
982}
983
985{
986 bScreen *screen = CTX_wm_screen(C);
987
988 if (screen) {
989 ScrArea *area;
990
991 for (area = static_cast<ScrArea *>(screen->areabase.first); area; area = area->next) {
992 if (area == handler->context.area) {
993 break;
994 }
995 }
996 if (area == nullptr) {
997 /* When changing screen layouts with running modal handlers (like render display),
998 * this is not an error to print. */
999 }
1000 else {
1001 ARegion *region;
1002 CTX_wm_area_set(C, area);
1003 for (region = static_cast<ARegion *>(area->regionbase.first); region; region = region->next)
1004 {
1005 if (region == handler->context.region) {
1006 break;
1007 }
1008 }
1009 /* XXX no warning print here, after full-area and back regions are remade. */
1010 if (region) {
1011 CTX_wm_region_set(C, region);
1012 }
1013 }
1014 }
1015}
1016
1018{
1019 /* Pass. */
1020}
1021
1023{
1024 wmGizmo *gz = gzmap->gzmap_context.highlight;
1025 if (gz && gz->type->cursor_get) {
1026 WM_cursor_set(win, gz->type->cursor_get(gz));
1027 return true;
1028 }
1029
1030 return false;
1031}
1032
1033bool wm_gizmomap_highlight_set(wmGizmoMap *gzmap, const bContext *C, wmGizmo *gz, int part)
1034{
1035 if ((gz != gzmap->gzmap_context.highlight) || (gz && part != gz->highlight_part)) {
1036 const bool init_last_cursor = !(gzmap->gzmap_context.highlight &&
1037 gzmap->gzmap_context.last_cursor != -1);
1038 if (gzmap->gzmap_context.highlight) {
1041 }
1042
1043 gzmap->gzmap_context.highlight = gz;
1044
1045 if (gz) {
1047 gz->highlight_part = part;
1048 if (init_last_cursor) {
1049 gzmap->gzmap_context.last_cursor = -1;
1050 }
1051
1052 if (C && gz->type->cursor_get) {
1053 wmWindow *win = CTX_wm_window(C);
1054 if (init_last_cursor) {
1055 gzmap->gzmap_context.last_cursor = win->cursor;
1056 }
1057 WM_cursor_set(win, gz->type->cursor_get(gz));
1058 }
1059 }
1060 else {
1061 if (C && gzmap->gzmap_context.last_cursor != -1) {
1062 wmWindow *win = CTX_wm_window(C);
1064 }
1065 gzmap->gzmap_context.last_cursor = -1;
1066 }
1067
1068 /* Tag the region for redraw. */
1069 if (C) {
1070 ARegion *region = CTX_wm_region(C);
1072 }
1073
1074 return true;
1075 }
1076
1077 return false;
1078}
1079
1081{
1082 return gzmap->gzmap_context.highlight;
1083}
1084
1086 wmGizmoMap *gzmap, bContext *C, wmGizmo *gz, const wmEvent *event, bool enable)
1087{
1088 bool do_refresh = false;
1089
1090 if (enable) {
1091 BLI_assert(gzmap->gzmap_context.modal == nullptr);
1092 wmWindow *win = CTX_wm_window(C);
1093
1094 WM_tooltip_clear(C, win);
1095
1096 /* Use even if we don't have invoke, so we can setup data before an operator runs. */
1098 gz->parent_gzgroup->type->invoke_prepare(C, gz->parent_gzgroup, gz, event);
1099 }
1100
1101 if (gz->type->invoke && (gz->type->modal || gz->custom_modal)) {
1102 const wmOperatorStatus retval = gz->type->invoke(C, gz, event);
1103 OPERATOR_RETVAL_CHECK(retval);
1104
1105 if ((retval & OPERATOR_RUNNING_MODAL) == 0) {
1106 return;
1107 }
1108 }
1109
1110 if (gzmap->gzmap_context.modal != gz) {
1111 do_refresh = true;
1112 }
1114 gzmap->gzmap_context.modal = gz;
1115
1116 if ((gz->flag & WM_GIZMO_MOVE_CURSOR) && (event->tablet.is_motion_absolute == false)) {
1117 WM_cursor_grab_enable(win, WM_CURSOR_WRAP_XY, nullptr, true);
1118 copy_v2_v2_int(gzmap->gzmap_context.event_xy, event->xy);
1120 }
1121 else {
1122 gzmap->gzmap_context.event_xy[0] = INT_MAX;
1123 }
1124
1126 if (gzop && gzop->type) {
1127 const wmOperatorStatus retval = WM_gizmo_operator_invoke(C, gz, gzop, event);
1128 OPERATOR_RETVAL_CHECK(retval);
1129
1130 if ((retval & OPERATOR_RUNNING_MODAL) == 0) {
1131 wm_gizmomap_modal_set(gzmap, C, gz, event, false);
1132 }
1133
1134 /* We failed to hook the gizmo to the operator handler or operator was canceled, return. */
1135 if (!gzmap->gzmap_context.modal) {
1138 }
1139 }
1140 }
1141 else {
1142 BLI_assert(ELEM(gzmap->gzmap_context.modal, nullptr, gz));
1143
1144 /* Deactivate, gizmo but first take care of some stuff. */
1145 if (gz) {
1148 }
1149
1150 if (gzmap->gzmap_context.modal != nullptr) {
1151 do_refresh = true;
1152 }
1153 gzmap->gzmap_context.modal = nullptr;
1154
1155 if (C) {
1156 wmWindow *win = CTX_wm_window(C);
1157 if (gzmap->gzmap_context.event_xy[0] != INT_MAX) {
1158 /* Check if some other part of Blender (typically operators)
1159 * have adjusted the grab mode since it was set.
1160 * If so: warp, so we have a predictable outcome. */
1161 if (gzmap->gzmap_context.event_grabcursor == win->grabcursor) {
1163 }
1164 else {
1166 }
1167 }
1170 }
1171
1172 gzmap->gzmap_context.event_xy[0] = INT_MAX;
1173 }
1174
1175 if (do_refresh) {
1176 const int update_flag = GIZMOMAP_IS_REFRESH_CALLBACK;
1178 gz->parent_gzgroup);
1179 gzmap->update_flag[step] |= update_flag;
1180
1181 /* Ensure the update flag is set for gizmos that were hidden while modal, see #104817. */
1182 for (int i = 0; i < WM_GIZMOMAP_DRAWSTEP_MAX; i++) {
1184 if (step_iter == step) {
1185 continue;
1186 }
1187 if ((gzmap->update_flag[i] & update_flag) == update_flag) {
1188 continue;
1189 }
1190 LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
1191 if (((gzgroup->type->flag & WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL) == 0) &&
1192 wm_gizmogroup_is_visible_in_drawstep(gzgroup, step_iter))
1193 {
1194 gzmap->update_flag[i] |= update_flag;
1195 break;
1196 }
1197 }
1198 }
1199 }
1200}
1201
1203{
1204 return gzmap->gzmap_context.modal;
1205}
1206
1207wmGizmo **wm_gizmomap_selected_get(wmGizmoMap *gzmap, int *r_selected_len)
1208{
1209 *r_selected_len = gzmap->gzmap_context.select.len;
1210 return gzmap->gzmap_context.select.items;
1211}
1212
1214{
1215 return &gzmap->groups;
1216}
1217
1219 wmGizmoMap *gzmap,
1220 ARegion *region,
1221 wmMsgBus *mbus)
1222{
1223 LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) {
1224 if ((gzgroup->hide.any != 0) || (gzgroup->init_flag & WM_GIZMOGROUP_INIT_SETUP) == 0 ||
1225 !WM_gizmo_group_type_poll(C, gzgroup->type))
1226 {
1227 continue;
1228 }
1229 LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
1230 if (gz->flag & WM_GIZMO_HIDDEN) {
1231 continue;
1232 }
1234 }
1235 if (gzgroup->type->message_subscribe != nullptr) {
1236 gzgroup->type->message_subscribe(C, gzgroup, mbus);
1237 }
1238 }
1239}
1240 /* #wmGizmoMap. */
1242
1243/* -------------------------------------------------------------------- */
1246
1248 bContext *C, ARegion *region, int * /*r_pass*/, double * /*pass_delay*/, bool *r_exit_on_event)
1249{
1250 wmGizmoMap *gzmap = region->runtime->gizmo_map;
1251 *r_exit_on_event = false;
1252 if (gzmap) {
1253 wmGizmo *gz = gzmap->gzmap_context.highlight;
1254 if (gz) {
1255 wmGizmoGroup *gzgroup = gz->parent_gzgroup;
1256 if ((gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) != 0) {
1257 /* On screen area of 3D gizmos may be large, exit on cursor motion. */
1258 *r_exit_on_event = true;
1259 }
1260 return UI_tooltip_create_from_gizmo(C, gz);
1261 }
1262 }
1263 return nullptr;
1264}
1265 /* #wmGizmoMapType. */
1267
1268/* -------------------------------------------------------------------- */
1271
1273{
1275 if (gzmap_type->spaceid == gzmap_params->spaceid &&
1276 gzmap_type->regionid == gzmap_params->regionid)
1277 {
1278 return gzmap_type;
1279 }
1280 }
1281
1282 return nullptr;
1283}
1284
1286{
1287 wmGizmoMapType *gzmap_type = WM_gizmomaptype_find(gzmap_params);
1288
1289 if (gzmap_type) {
1290 return gzmap_type;
1291 }
1292
1293 gzmap_type = MEM_callocN<wmGizmoMapType>("gizmotype list");
1294 gzmap_type->spaceid = gzmap_params->spaceid;
1295 gzmap_type->regionid = gzmap_params->regionid;
1296 BLI_addhead(&gizmomaptypes, gzmap_type);
1297
1298 return gzmap_type;
1299}
1300
1302{
1303 for (wmGizmoMapType *gzmap_type = static_cast<wmGizmoMapType *>(gizmomaptypes.first),
1304 *gzmap_type_next;
1305 gzmap_type;
1306 gzmap_type = gzmap_type_next)
1307 {
1308 gzmap_type_next = gzmap_type->next;
1309 for (wmGizmoGroupTypeRef *
1310 gzgt_ref = static_cast<wmGizmoGroupTypeRef *>(gzmap_type->grouptype_refs.first),
1311 *gzgt_next;
1312 gzgt_ref;
1313 gzgt_ref = gzgt_next)
1314 {
1315 gzgt_next = gzgt_ref->next;
1317 }
1318 MEM_freeN(gzmap_type);
1319 }
1320}
1321
1323{
1325 LISTBASE_FOREACH (wmGizmoGroupTypeRef *, gzgt_ref, &gzmap_type->grouptype_refs) {
1326 wm_gizmogrouptype_setup_keymap(gzgt_ref->type, keyconf);
1327 }
1328 }
1329
1331}
1332 /* #wmGizmoMapType. */
1334
1335/* -------------------------------------------------------------------- */
1338
1347
1357
1364
1369
1371{
1372 if (G.background) {
1373 return;
1374 }
1375
1376 if (wm_gzmap_type_update_flag == 0) {
1377 return;
1378 }
1379
1382 if (gzmap_type->type_update_flag & WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE) {
1383 gzmap_type->type_update_flag &= ~WM_GIZMOMAPTYPE_UPDATE_REMOVE;
1384 for (wmGizmoGroupTypeRef *
1385 gzgt_ref = static_cast<wmGizmoGroupTypeRef *>(gzmap_type->grouptype_refs.first),
1386 *gzgt_ref_next;
1387 gzgt_ref;
1388 gzgt_ref = gzgt_ref_next)
1389 {
1390 gzgt_ref_next = gzgt_ref->next;
1391 if (gzgt_ref->type->type_update_flag & WM_GIZMOMAPTYPE_UPDATE_REMOVE) {
1392 gzgt_ref->type->type_update_flag &= ~WM_GIZMOMAPTYPE_UPDATE_REMOVE;
1393 WM_gizmomaptype_group_unlink(nullptr, bmain, gzmap_type, gzgt_ref->type);
1394 }
1395 }
1396 }
1397 }
1398
1400 }
1401
1405 if (gzmap_type->type_update_flag & type_update_all) {
1406 gzmap_type->type_update_flag &= ~eWM_GizmoFlagMapTypeUpdateFlag(type_update_all);
1407 LISTBASE_FOREACH (wmGizmoGroupTypeRef *, gzgt_ref, &gzmap_type->grouptype_refs) {
1408 if (gzgt_ref->type->type_update_flag & WM_GIZMOMAPTYPE_KEYMAP_INIT) {
1409 WM_gizmomaptype_group_init_runtime_keymap(bmain, gzgt_ref->type);
1410 gzgt_ref->type->type_update_flag &= ~WM_GIZMOMAPTYPE_KEYMAP_INIT;
1411 }
1412
1413 if (gzgt_ref->type->type_update_flag & WM_GIZMOMAPTYPE_UPDATE_INIT) {
1414 WM_gizmomaptype_group_init_runtime(bmain, gzmap_type, gzgt_ref->type);
1415 gzgt_ref->type->type_update_flag &= ~WM_GIZMOMAPTYPE_UPDATE_INIT;
1416 }
1417 }
1418 }
1419 }
1420
1422 }
1423
1425 for (bScreen *screen = static_cast<bScreen *>(bmain->screens.first); screen;
1426 screen = static_cast<bScreen *>(screen->id.next))
1427 {
1428 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
1429 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
1430 ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
1431 &sl->regionbase;
1432 LISTBASE_FOREACH (ARegion *, region, regionbase) {
1433 wmGizmoMap *gzmap = region->runtime->gizmo_map;
1434 if (gzmap != nullptr && gzmap->tag_remove_group) {
1435 gzmap->tag_remove_group = false;
1436
1437 for (wmGizmoGroup *gzgroup = static_cast<wmGizmoGroup *>(gzmap->groups.first),
1438 *gzgroup_next;
1439 gzgroup;
1440 gzgroup = gzgroup_next)
1441 {
1442 gzgroup_next = gzgroup->next;
1443 if (gzgroup->tag_remove) {
1444 wm_gizmogroup_free(nullptr, gzgroup);
1446 }
1447 }
1448 }
1449 }
1450 }
1451 }
1452 }
1454 }
1455
1459 }
1460}
1461
1463
1464/* -------------------------------------------------------------------- */
1470
1472{
1473 for (bScreen *screen = static_cast<bScreen *>(bmain->screens.first); screen;
1474 screen = static_cast<bScreen *>(screen->id.next))
1475 {
1476 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
1477 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
1478 ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase : &sl->regionbase;
1479 LISTBASE_FOREACH (ARegion *, region, regionbase) {
1480 wmGizmoMap *gzmap = region->runtime->gizmo_map;
1481 if ((gzmap != nullptr) && (gzmap->is_init == false)) {
1482 WM_gizmomap_reinit(gzmap);
1483
1484 /* Without a redraw elements can fail to activate
1485 * (such as the 2D viewport buttons). */
1486 ED_region_tag_redraw(region);
1487 }
1488 }
1489 }
1490 }
1491 }
1492}
1493
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:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:299
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.cc:702
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.cc:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:860
#define GHASH_ITER_INDEX(gh_iter_, ghash_, i_)
Definition BLI_ghash.h:322
LinkData * BLI_genericNodeN(void *data)
Definition listbase.cc:922
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_freelinkN(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:270
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_addhead(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:91
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.cc:466
unsigned char uchar
unsigned int uint
#define UNPACK2(a)
#define ARRAY_SIZE(arr)
#define ENUM_OPERATORS(_type, _max)
#define UNUSED_VARS_NDEBUG(...)
#define ELEM(...)
#define UI_SCALE_FAC
@ OPERATOR_RUNNING_MODAL
#define OPERATOR_RETVAL_CHECK(ret)
void ED_region_tag_redraw_editor_overlays(ARegion *region)
Definition area.cc:654
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:618
@ SEL_SELECT
@ SEL_DESELECT
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 view3d_operator_needs_gpu(const bContext *C)
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_free(blender::gpu::FrameBuffer *fb)
#define GPU_framebuffer_ensure_config(_fb,...)
void GPU_framebuffer_bind(blender::gpu::FrameBuffer *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])
const GPUSelectResult * GPU_select_buffer_near(const blender::Span< GPUSelectResult > hit_results)
void GPU_select_begin(GPUSelectBuffer *buffer, const rcti *input, GPUSelectMode mode, int oldhits)
unsigned int GPU_select_end()
@ GPU_SELECT_NEAREST_SECOND_PASS
Definition GPU_select.hh:23
@ GPU_SELECT_NEAREST_FIRST_PASS
Definition GPU_select.hh:22
@ GPU_DEPTH_ALWAYS
Definition GPU_state.hh:112
@ GPU_DEPTH_LESS_EQUAL
Definition GPU_state.hh:114
@ GPU_DEPTH_NONE
Definition GPU_state.hh:111
void GPU_line_smooth(bool enable)
Definition gpu_state.cc:78
void GPU_depth_mask(bool depth)
Definition gpu_state.cc:110
void GPU_depth_test(GPUDepthTest test)
Definition gpu_state.cc:68
void GPU_polygon_smooth(bool enable)
Definition gpu_state.cc:83
blender::gpu::Texture * GPU_viewport_depth_texture(GPUViewport *viewport)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
#define C
Definition RandGen.cpp:29
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_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_PRESS_DRAG
Definition WM_types.hh:319
@ WM_CURSOR_WRAP_XY
Definition WM_types.hh:229
BMesh const char void * data
BPy_StructRNA * depsgraph
int64_t size() const
bool is_empty() const
Span< T > as_span() const
nullptr float
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
#define UINT_MAX
Definition hash_md5.cc:44
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
VecBase< float, 2 > float2
#define hash
Definition noise_c.cc:154
#define FLT_MAX
Definition stdcycles.h:14
void * regiondata
ARegionRuntimeHandle * runtime
struct ARegion * next
GPUSelectStorage storage
Definition GPU_select.hh:47
unsigned int id
Definition GPU_select.hh:34
void * first
ListBase screens
Definition BKE_main.hh:292
ListBase spacedata
struct ScrArea * next
ListBase regionbase
ListBase areabase
struct wmGizmoMap * gizmo_map
struct wmEventHandler_Op::@143214277125013224360266000304213254210030120033 context
eWM_EventHandlerType type
wmEventModifierFlag modifier
Definition WM_types.hh:774
short val
Definition WM_types.hh:759
int xy[2]
Definition WM_types.hh:761
int mval[2]
Definition WM_types.hh:763
wmTabletData tablet
Definition WM_types.hh:786
wmGizmoGroupFnInvokePrepare invoke_prepare
eWM_GizmoFlagGroupTypeFlag flag
eWM_GizmoFlagMapTypeUpdateFlag type_update_flag
wmGizmoGroupType * type
struct wmGizmo ** items
eWM_GizmoFlagMapTypeUpdateFlag type_update_flag
wmGizmoMapSelectState select
char update_flag[WM_GIZMOMAP_DRAWSTEP_MAX]
wmGizmo * modal
bool tag_highlight_pending
wmGizmoMapType * type
struct wmGizmoMap::@114263143030171315362141314326010164050332242157 gzmap_context
Gizmo map runtime context.
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:712
i
Definition text_draw.cc:230
uint len_alloc
uint len
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:940
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:360
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:728
wmOperatorStatus 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:493
bool WM_gizmo_select_set(wmGizmoMap *gzmap, wmGizmo *gz, bool select)
Definition wm_gizmo.cc:400
int wm_gizmo_is_visible(wmGizmo *gz)
Definition wm_gizmo.cc:501
wmOperatorStatus(*)(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_intersectable_gizmos_to_list(wmWindowManager *wm, const wmGizmoGroup *gzgroup, const int event_modifier, blender::Vector< wmGizmo *, 128 > *r_visible_gizmos)
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)
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 StringRef 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)
bool wm_gizmomap_highlight_handled(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)
wmGizmoGroup * WM_gizmomap_group_find(wmGizmoMap *gzmap, const char *idname)
void wm_gizmomaptypes_free()
@ GIZMOMAP_IS_PREPARE_DRAW
@ GIZMOMAP_IS_REFRESH_CALLBACK
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_highlight_pending(const wmGizmoMap *gzmap)
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:82
void WM_cursor_warp(wmWindow *win, int x, int y)