Blender V4.3
view3d_cursor_snap.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2020 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "DNA_object_types.h"
12
13#include "BLI_listbase.h"
14#include "BLI_math_matrix.h"
16#include "BLI_rect.h"
17
18#include "MEM_guardedalloc.h"
19
20#include "BKE_context.hh"
21#include "BKE_global.hh"
22#include "BKE_layer.hh"
23#include "BKE_main.hh"
24#include "BKE_object.hh"
25#include "BKE_scene.hh"
26#include "BKE_screen.hh"
27
28#include "GPU_immediate.hh"
29#include "GPU_matrix.hh"
30
31#include "ED_screen.hh"
32#include "ED_transform.hh"
34#include "ED_view3d.hh"
35
36#include "UI_resources.hh"
37
38#include "RNA_access.hh"
39
41
42#include "WM_api.hh"
43
44#define STATE_INTERN_GET(state) \
45\
46 (SnapStateIntern *)((char *)state - offsetof(SnapStateIntern, snap_state))
47
52
57
59 const Scene *scene;
61
63
64 /* Copy of the parameters of the last event state in order to detect updates. */
65 struct {
66 int x;
67 int y;
70
71#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
74#endif
75
77
79};
80
83 data.state_default.flag = V3D_SNAPCURSOR_SNAP_EDIT_GEOM_FINAL;
84 copy_v4_v4_uchar(data.state_default.target_color, blender::uchar4{255, 255, 255, 255});
85 copy_v4_v4_uchar(data.state_default.source_color, blender::uchar4{255, 255, 255, 128});
86 copy_v4_v4_uchar(data.state_default.color_box, blender::uchar4{255, 255, 255, 128});
87 copy_v3_fl(data.state_default.box_dimensions, 1.0f);
88 data.state_default.draw_point = true;
89 return data;
90}();
91
96static const float eps_view_align = 1e-2f;
97
101static void v3d_cursor_poject_surface_normal(const float normal[3],
102 const float obmat[4][4],
103 float r_mat[3][3])
104{
105 float mat[3][3];
106 copy_m3_m4(mat, obmat);
107 normalize_m3(mat);
108
109 float dot_best = fabsf(dot_v3v3(mat[0], normal));
110 int i_best = 0;
111 for (int i = 1; i < 3; i++) {
112 float dot_test = fabsf(dot_v3v3(mat[i], normal));
113 if (dot_test > dot_best) {
114 i_best = i;
115 dot_best = dot_test;
116 }
117 }
118 if (dot_v3v3(mat[i_best], normal) < 0.0f) {
119 negate_v3(mat[(i_best + 1) % 3]);
120 negate_v3(mat[(i_best + 2) % 3]);
121 }
122 copy_v3_v3(mat[i_best], normal);
123 orthogonalize_m3(mat, i_best);
124 normalize_m3(mat);
125
126 copy_v3_v3(r_mat[0], mat[(i_best + 1) % 3]);
127 copy_v3_v3(r_mat[1], mat[(i_best + 2) % 3]);
128 copy_v3_v3(r_mat[2], mat[i_best]);
129}
130
134static bool mat3_align_axis_to_v3(float mat[3][3], const int axis_align, const float v[3])
135{
136 float dot_best = -1.0f;
137 int axis_found = axis_align;
138 for (int i = 0; i < 3; i++) {
139 const float dot_test = fabsf(dot_v3v3(mat[i], v));
140 if (dot_test > dot_best) {
141 dot_best = dot_test;
142 axis_found = i;
143 }
144 }
145
146 if (axis_align != axis_found) {
147 float tmat[3][3];
148 copy_m3_m3(tmat, mat);
149 const int offset = mod_i(axis_found - axis_align, 3);
150 for (int i = 0; i < 3; i++) {
151 copy_v3_v3(mat[i], tmat[(i + offset) % 3]);
152 }
153 return true;
154 }
155 return false;
156}
157
158/* -------------------------------------------------------------------- */
161
162static void v3d_cursor_plane_draw_grid(const int resolution,
163 const float scale,
164 const float scale_fade,
165 const float matrix[4][4],
166 const int plane_axis,
167 const float color[4])
168{
169 BLI_assert(scale_fade <= scale);
170 const int resolution_min = resolution - 1;
171 float color_fade[4] = {UNPACK4(color)};
172 const float *center = matrix[3];
173
175 GPU_line_smooth(true);
176 GPU_line_width(1.0f);
177
180 const uint col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
181
183
184 const size_t coords_len = resolution * resolution;
185 float(*coords)[3] = static_cast<float(*)[3]>(
186 MEM_mallocN(sizeof(*coords) * coords_len, __func__));
187
188 const int axis_x = (plane_axis + 0) % 3;
189 const int axis_y = (plane_axis + 1) % 3;
190 const int axis_z = (plane_axis + 2) % 3;
191
192 int i;
193 const float resolution_div = float(1.0f) / float(resolution);
194 i = 0;
195 for (int x = 0; x < resolution; x++) {
196 const float x_fl = (x * resolution_div) - 0.5f;
197 for (int y = 0; y < resolution; y++) {
198 const float y_fl = (y * resolution_div) - 0.5f;
199 coords[i][axis_x] = 0.0f;
200 coords[i][axis_y] = x_fl * scale;
201 coords[i][axis_z] = y_fl * scale;
202 mul_m4_v3(matrix, coords[i]);
203 i += 1;
204 }
205 }
206 BLI_assert(i == int(coords_len));
207 immBeginAtMost(GPU_PRIM_LINES, coords_len * 4);
208 i = 0;
209 for (int x = 0; x < resolution_min; x++) {
210 for (int y = 0; y < resolution_min; y++) {
211
212/* Add #resolution_div to ensure we fade-out entirely. */
213#define FADE(v) \
214\
215 max_ff(0.0f, (1.0f - square_f(((len_v3v3(v, center) / scale_fade) + resolution_div) * 2.0f)))
216
217 const float *v0 = coords[(resolution * x) + y];
218 const float *v1 = coords[(resolution * (x + 1)) + y];
219 const float *v2 = coords[(resolution * x) + (y + 1)];
220
221 const float f0 = FADE(v0);
222 const float f1 = FADE(v1);
223 const float f2 = FADE(v2);
224
225 if (f0 > 0.0f || f1 > 0.0f) {
226 color_fade[3] = color[3] * f0;
227 immAttr4fv(col_id, color_fade);
228 immVertex3fv(pos_id, v0);
229 color_fade[3] = color[3] * f1;
230 immAttr4fv(col_id, color_fade);
231 immVertex3fv(pos_id, v1);
232 }
233 if (f0 > 0.0f || f2 > 0.0f) {
234 color_fade[3] = color[3] * f0;
235 immAttr4fv(col_id, color_fade);
236 immVertex3fv(pos_id, v0);
237
238 color_fade[3] = color[3] * f2;
239 immAttr4fv(col_id, color_fade);
240 immVertex3fv(pos_id, v2);
241 }
242
243#undef FADE
244
245 i++;
246 }
247 }
248
249 MEM_freeN(coords);
250
251 immEnd();
252
254
255 GPU_line_smooth(false);
257}
258
259static void v3d_cursor_plane_draw(const RegionView3D *rv3d,
260 const int plane_axis,
261 const float matrix[4][4])
262{
263 /* Draw */
264 float pixel_size;
265
266 if (rv3d->is_persp) {
267 float center[3];
268 negate_v3_v3(center, rv3d->ofs);
269 pixel_size = ED_view3d_pixel_size(rv3d, center);
270 }
271 else {
272 pixel_size = ED_view3d_pixel_size(rv3d, matrix[3]);
273 }
274
275 if (pixel_size > FLT_EPSILON) {
276
277 /* Arbitrary, 1.0 is a little too strong though. */
278 float color_alpha = 0.75f;
279 if (rv3d->is_persp) {
280 /* Scale down the alpha when this is drawn very small,
281 * since the add shader causes the small size to show too dense & bright. */
282 const float relative_pixel_scale = pixel_size / ED_view3d_pixel_size(rv3d, matrix[3]);
283 if (relative_pixel_scale < 1.0f) {
284 color_alpha *= max_ff(square_f(relative_pixel_scale), 0.3f);
285 }
286 }
287
288 {
289 /* Extra adjustment when it's near view-aligned as it seems overly bright. */
290 float view_vector[3];
291 ED_view3d_global_to_vector(rv3d, matrix[3], view_vector);
292 float view_dot = fabsf(dot_v3v3(matrix[plane_axis], view_vector));
293 color_alpha *= max_ff(0.3f, 1.0f - square_f(square_f(1.0f - view_dot)));
294 }
295
296 const float scale_mod = U.gizmo_size * 2 * UI_SCALE_FAC / U.pixelsize;
297
298 float final_scale = (scale_mod * pixel_size);
299
300 const int lines_subdiv = 10;
301 int lines = lines_subdiv;
302
303 float final_scale_fade = final_scale;
304 final_scale = ceil_power_of_10(final_scale);
305
306 float fac = final_scale_fade / final_scale;
307
308 float color[4] = {1, 1, 1, color_alpha};
309 color[3] *= square_f(1.0f - fac);
310 if (color[3] > 0.0f) {
312 lines * lines_subdiv, final_scale, final_scale_fade, matrix, plane_axis, color);
313 }
314
315 color[3] = color_alpha;
316 /* When the grid is large, we only need the 2x lines in the middle. */
317 if (fac < 0.2f) {
318 lines = 1;
319 final_scale = final_scale_fade;
320 }
321 v3d_cursor_plane_draw_grid(lines, final_scale, final_scale_fade, matrix, plane_axis, color);
322 }
323}
324
325static void cursor_box_draw(const float dimensions[3], uchar color[4])
326{
329
331 GPU_line_smooth(true);
332 GPU_line_width(1.0f);
333
336 imm_draw_cube_corners_3d(pos_id, blender::float3{0.0f, 0.0f, dimensions[2]}, dimensions, 0.15f);
338
339 GPU_line_smooth(false);
341}
342
344 uint attr_pos, const float loc[3], const float size, eSnapMode snap_type, const uchar color[4])
345{
346 if (snap_type == SCE_SNAP_TO_GRID) {
347 /* No drawing. */
348 return;
349 }
350
352
354
355 float model_view_new[4][4];
356 GPU_matrix_model_view_get(model_view_new);
357 translate_m4(model_view_new, UNPACK3(loc));
358 copy_v3_fl3(model_view_new[0], size, 0.0f, 0.0f);
359 copy_v3_fl3(model_view_new[1], 0.0f, size, 0.0f);
360 copy_v3_fl3(model_view_new[2], 0.0f, 0.0f, size);
361 GPU_matrix_set(model_view_new);
362
363 float size_b = 1.0f;
364 switch (snap_type) {
366 imm_draw_circle_wire_3d(attr_pos, 0.0f, 0.0f, 1.0f, 24);
367
369 immVertex3f(attr_pos, -size_b, -size_b, 0.0f);
370 immVertex3f(attr_pos, +size_b, +size_b, 0.0f);
371 immVertex3f(attr_pos, -size_b, +size_b, 0.0f);
372 immVertex3f(attr_pos, +size_b, -size_b, 0.0f);
373 immEnd();
374 break;
377 immVertex3f(attr_pos, -size_b, -size_b, 0.0f);
378 immVertex3f(attr_pos, -size_b, +size_b, 0.0f);
379 immVertex3f(attr_pos, +size_b, +size_b, 0.0f);
380 immVertex3f(attr_pos, +size_b, -size_b, 0.0f);
381 immEnd();
382 break;
385 immVertex3f(attr_pos, -size_b, -size_b, 0.0f);
386 immVertex3f(attr_pos, 0.0f, 0.866f * size_b, 0.0f);
387 immVertex3f(attr_pos, +size_b, -size_b, 0.0f);
388 immEnd();
389 break;
392 immVertex3f(attr_pos, -size_b, +size_b, 0.0f);
393 immVertex3f(attr_pos, -size_b, -size_b, 0.0f);
394 immVertex3f(attr_pos, +size_b, -size_b, 0.0f);
395 immEnd();
396
398 immVertex3f(attr_pos, -size_b, 0.0f, 0.0f);
399 immVertex3f(attr_pos, 0.0f, 0.0f, 0.0f);
400 immVertex3f(attr_pos, 0.0f, -size_b, 0.0f);
401 immEnd();
402 break;
403 case SCE_SNAP_TO_EDGE:
405 immVertex3f(attr_pos, -size_b, -size_b, 0.0f);
406 immVertex3f(attr_pos, +size_b, +size_b, 0.0f);
407 immVertex3f(attr_pos, -size_b, +size_b, 0.0f);
408 immVertex3f(attr_pos, +size_b, -size_b, 0.0f);
409 immEnd();
410 break;
411 case SCE_SNAP_TO_FACE:
412 default:
413 imm_draw_circle_wire_3d(attr_pos, 0.0f, 0.0f, 1.0f, 24);
414 break;
415 }
416
418}
419
421 const float source_loc[3],
422 const float target_loc[3],
423 const eSnapMode source_type,
424 const eSnapMode target_type,
425 const uchar source_color[4],
426 const uchar target_color[4])
427{
428 if (!source_loc && !target_loc) {
429 return;
430 }
431
432 /* The size of the symbol is larger than the vertex size.
433 * This prevents overlaps. */
434 float radius = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
436
438 GPU_line_smooth(true);
439 GPU_line_width(1.5f);
441
442 if (target_loc) {
444 target_loc,
445 radius * ED_view3d_pixel_size(rv3d, target_loc),
446 target_type,
447 target_color);
448 }
449
450 if (source_loc) {
452 source_loc,
453 radius * ED_view3d_pixel_size(rv3d, source_loc),
454 source_type,
455 source_color);
456
457 if (target_loc && (target_type & SCE_SNAP_TO_EDGE_PERPENDICULAR)) {
458 /* Dashed line. */
460
462 float viewport_size[4];
463 GPU_viewport_size_get_f(viewport_size);
464 immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
465 immUniform1f("dash_width", 6.0f * U.pixelsize);
466 immUniform1f("udash_factor", 1.0f / 4.0f);
467 immUniformColor4ubv(source_color);
468
470 immVertex3fv(pos, source_loc);
471 immVertex3fv(pos, target_loc);
472 immEnd();
473 }
474 }
475
476 GPU_line_smooth(false);
479}
480
482
483/* -------------------------------------------------------------------- */
486
487/* Checks if the current event is different from the one captured in the last update. */
490 const int x,
491 const int y,
492 uint8_t event_modifier)
493{
494 if ((x != data_intern->last_eventstate.x) || (y != data_intern->last_eventstate.y)) {
495 return true;
496 }
497
498#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
499 if (!(state && (state->flag & V3D_SNAPCURSOR_TOGGLE_ALWAYS_TRUE))) {
500 if (event_modifier != data_intern->last_eventstate.modifier) {
501 return true;
502 }
503 }
504#endif
505
506 return false;
507}
508
509/* Copies the current eventstate. */
511 const int x,
512 const int y)
513{
514 cursor_snap->last_eventstate.x = x;
515 cursor_snap->last_eventstate.y = y;
516}
517
518#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
520 uint8_t event_modifier)
521{
522 data_intern->last_eventstate.modifier = event_modifier;
523}
524
525static bool v3d_cursor_is_snap_invert(SnapCursorDataIntern *data_intern, uint8_t event_modifier)
526{
527 if (event_modifier == data_intern->last_eventstate.modifier) {
528 /* Nothing has changed. */
529 return data_intern->snap_data.is_snap_invert;
530 }
531
532 /* Save new eventstate. */
533 data_intern->last_eventstate.modifier = event_modifier;
534
535 const int snap_on = data_intern->snap_on;
536
537 const wmWindowManager *wm = static_cast<wmWindowManager *>(G.main->wm.first);
538 wmKeyMap *keymap = WM_keymap_active(wm, data_intern->keymap);
539 LISTBASE_FOREACH (const wmKeyMapItem *, kmi, &keymap->items) {
540 if (kmi->flag & KMI_INACTIVE) {
541 continue;
542 }
543
544 if (kmi->propvalue == snap_on) {
545 if ((ELEM(kmi->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY) && (event_modifier & KM_CTRL)) ||
546 (ELEM(kmi->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY) && (event_modifier & KM_SHIFT)) ||
547 (ELEM(kmi->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY) && (event_modifier & KM_ALT)) ||
548 ((kmi->type == EVT_OSKEY) && (event_modifier & KM_OSKEY)))
549 {
550 return true;
551 }
552 }
553 }
554 return false;
555}
556#endif
557
559
560/* -------------------------------------------------------------------- */
563
565{
566 if (tool_settings->snap_mode_tools == SCE_SNAP_TO_NONE) {
567 /* Use the snap modes defined in the scene instead. */
568 eSnapMode snap_mode = eSnapMode(tool_settings->snap_mode);
569 if ((snap_mode & SCE_SNAP_TO_INCREMENT) && (tool_settings->snap_flag & SCE_SNAP_ABS_GRID)) {
570 /* Convert snap to increment to snap to grid. */
571 snap_mode |= SCE_SNAP_TO_GRID;
572 }
573 return snap_mode;
574 }
575 return eSnapMode(tool_settings->snap_mode_tools);
576}
577
579{
580 SnapCursorDataIntern *data_intern = &g_data_intern;
581 if (data_intern->snap_context_v3d && (data_intern->scene != scene)) {
583 data_intern->snap_context_v3d = nullptr;
584 }
585 if (data_intern->snap_context_v3d == nullptr) {
587 data_intern->scene = scene;
588 }
589}
590
592{
593 /* If any of the states require the plane, calculate the `plane_omat`. */
595 if (state->snap_state.draw_plane || state->snap_state.draw_box) {
596 return true;
597 }
598 }
599 return false;
600}
601
603 const bContext *C,
604 Depsgraph *depsgraph,
605 Scene *scene,
606 const ARegion *region,
607 View3D *v3d,
608 int x,
609 int y,
610 uint8_t event_modifier)
611{
612 SnapCursorDataIntern *data_intern = &g_data_intern;
613 V3DSnapCursorData *snap_data = &data_intern->snap_data;
614 ToolSettings *tool_settings = scene->toolsettings;
615
616 eSnapMode snap_elements = v3d_cursor_snap_elements(tool_settings);
617 const bool calc_plane_omat = v3d_cursor_snap_calc_plane();
618
619 snap_data->is_enabled = true;
621#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
622 snap_data->is_snap_invert = v3d_cursor_is_snap_invert(data_intern, event_modifier);
623#endif
624
625 if (snap_data->is_snap_invert != ((tool_settings->snap_flag & SCE_SNAP) == 0)) {
626 snap_data->is_enabled = false;
627 if (!calc_plane_omat) {
628 snap_data->type_target = SCE_SNAP_TO_NONE;
629 return;
630 }
631 snap_elements = SCE_SNAP_TO_NONE;
632 }
633 }
634
635 const bool use_surface_nor = tool_settings->plane_orient == V3D_PLACE_ORIENT_SURFACE;
636 const bool use_surface_co = snap_data->is_enabled ||
637 tool_settings->plane_depth == V3D_PLACE_DEPTH_SURFACE;
638
639 float co[3], no[3], face_nor[3], obmat[4][4], omat[3][3];
640 eSnapMode snap_elem = SCE_SNAP_TO_NONE;
641 int snap_elem_index[3] = {-1, -1, -1};
642 int index = -1;
643
644 const float mval_fl[2] = {float(x), float(y)};
645 zero_v3(no);
646 zero_v3(face_nor);
647 unit_m3(omat);
648
649 if (use_surface_nor || use_surface_co) {
651
652 data_intern->snap_elem_hidden = SCE_SNAP_TO_NONE;
653 if (calc_plane_omat && !(snap_elements & SCE_SNAP_TO_FACE)) {
654 data_intern->snap_elem_hidden = SCE_SNAP_TO_FACE;
655 snap_elements |= SCE_SNAP_TO_FACE;
656 }
657
658 if (snap_elements & (SCE_SNAP_TO_GEOM | SCE_SNAP_TO_GRID)) {
659 float prev_co[3] = {0.0f};
660 if (state->prevpoint) {
661 copy_v3_v3(prev_co, state->prevpoint);
662 }
663 else {
664 snap_elements &= ~SCE_SNAP_TO_EDGE_PERPENDICULAR;
665 }
666
667 eSnapEditType edit_mode_type = (state->flag & V3D_SNAPCURSOR_SNAP_EDIT_GEOM_FINAL) ?
672
673 float dist_px = 12.0f * U.pixelsize;
674
676 params.snap_target_select = SCE_SNAP_TARGET_ALL;
677 params.edit_mode_type = edit_mode_type;
678 params.occlusion_test = (state->flag & V3D_SNAPCURSOR_OCCLUSION_ALWAYS_TRUE) ?
682 depsgraph,
683 region,
684 v3d,
685 snap_elements,
686 &params,
687 nullptr,
688 mval_fl,
689 prev_co,
690 &dist_px,
691 co,
692 no,
693 &index,
694 nullptr,
695 obmat,
696 face_nor);
697 if ((snap_elem & data_intern->snap_elem_hidden) && (snap_elements & SCE_SNAP_TO_GRID)) {
698 BLI_assert(snap_elem != SCE_SNAP_TO_GRID);
699 params.occlusion_test = SNAP_OCCLUSION_NEVER;
701 depsgraph,
702 region,
703 v3d,
705 &params,
706 co,
707 mval_fl,
708 prev_co,
709 &dist_px,
710 co,
711 no);
712 }
713 }
714 }
715#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
716 else {
717 v3d_cursor_eventstate_save_modifier(data_intern, event_modifier);
718 }
719#endif
720
721 if (calc_plane_omat) {
722 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
723 bool orient_surface = use_surface_nor && (snap_elem != SCE_SNAP_TO_NONE);
724 if (orient_surface) {
725 copy_m3_m4(omat, obmat);
726 }
727 else {
728 ViewLayer *view_layer = CTX_data_view_layer(C);
731 const int orient_index = BKE_scene_orientation_get_index(scene, SCE_ORIENT_DEFAULT);
732 const int pivot_point = scene->toolsettings->transform_pivot_point;
734 scene, view_layer, v3d, rv3d, ob, nullptr, orient_index, pivot_point, omat);
735
736 if (tool_settings->use_plane_axis_auto) {
737 mat3_align_axis_to_v3(omat, tool_settings->plane_axis, rv3d->viewinv[2]);
738 }
739 }
740
741 /* Non-orthogonal matrices cause the preview and final result not to match.
742 *
743 * While making orthogonal doesn't always work well (especially with gimbal orientation for
744 * e.g.) it's a corner case, without better alternatives as objects don't support shear. */
745 orthogonalize_m3(omat, tool_settings->plane_axis);
746
747 if (orient_surface) {
748 if (!is_zero_v3(face_nor)) {
749 /* Negate the face normal according to the view. */
750 float ray_dir[3];
751 if (rv3d->is_persp) {
752 BLI_assert_msg(snap_elem != SCE_SNAP_TO_NONE,
753 "Use of variable `co` without it being computed");
754
755 sub_v3_v3v3(ray_dir, co, rv3d->viewinv[3]); /* No need to normalize. */
756 }
757 else {
758 negate_v3_v3(ray_dir, rv3d->viewinv[2]);
759 }
760
761 if (dot_v3v3(ray_dir, face_nor) >= 0.0f) {
762 negate_v3(face_nor);
763 }
764 }
765 else if (!is_zero_v3(no)) {
766 copy_v3_v3(face_nor, no);
767 }
768 else {
769 face_nor[tool_settings->plane_axis] = 1.0f;
770 }
771 v3d_cursor_poject_surface_normal(face_nor, obmat, omat);
772 }
773 }
774
775 if (!use_surface_co) {
776 snap_elem = SCE_SNAP_TO_NONE;
777 }
778
779 float *co_depth = (snap_elem != SCE_SNAP_TO_NONE) ? co : scene->cursor.location;
780 snap_elem &= ~data_intern->snap_elem_hidden;
781 if (snap_elem == SCE_SNAP_TO_NONE) {
782 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
783 const float *plane_normal = omat[tool_settings->plane_axis];
784 bool do_plane_isect = (tool_settings->plane_depth != V3D_PLACE_DEPTH_CURSOR_VIEW) &&
785 (rv3d->is_persp ||
786 (fabsf(dot_v3v3(plane_normal, rv3d->viewinv[2])) > eps_view_align));
787
788 if (do_plane_isect) {
789 float plane[4];
790 plane_from_point_normal_v3(plane, co_depth, plane_normal);
791 do_plane_isect = ED_view3d_win_to_3d_on_plane(region, plane, mval_fl, rv3d->is_persp, co);
792 }
793
794 if (!do_plane_isect) {
795 ED_view3d_win_to_3d(v3d, region, co_depth, mval_fl, co);
796 }
797 }
798 else if (snap_elem & SCE_SNAP_TO_VERTEX) {
799 snap_elem_index[0] = index;
800 }
801 else if (snap_elem &
803 {
804 snap_elem_index[1] = index;
805 }
806 else if (snap_elem == SCE_SNAP_TO_FACE) {
807 snap_elem_index[2] = index;
808 }
809
810 snap_data->type_target = snap_elem;
811 copy_v3_v3(snap_data->loc, co);
812 copy_v3_v3(snap_data->nor, no);
813 copy_m4_m4(snap_data->obmat, obmat);
814 copy_v3_v3_int(snap_data->elem_index, snap_elem_index);
815
816 copy_m3_m3(snap_data->plane_omat, omat);
817
818 v3d_cursor_eventstate_save_xy(data_intern, x, y);
819}
820
822
823/* -------------------------------------------------------------------- */
826
828{
829 if (G.moving) {
830 return false;
831 }
832
833 ScrArea *area = CTX_wm_area(C);
834 if (area->spacetype != SPACE_VIEW3D) {
835 return false;
836 }
837
838 ARegion *region = CTX_wm_region(C);
839 if (region->regiontype != RGN_TYPE_WINDOW) {
840 if (!region->overlap) {
841 return false;
842 }
843 /* Sometimes the cursor may be on an invisible part of an overlapping region. */
844 wmWindow *win = CTX_wm_window(C);
845 const wmEvent *event = win->eventstate;
846 if (ED_region_overlap_isect_xy(region, event->xy)) {
847 return false;
848 }
849 /* Find the visible region under the cursor.
850 * TODO(Germano): Shouldn't this be the region in context? */
852 }
853
854 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
855 if (rv3d->rflag & RV3D_NAVIGATING) {
856 /* Don't draw the cursor while navigating. It can be distracting. */
857 return false;
858 };
859
860 /* Call this callback last and don't reuse the `state` as the caller can free the cursor. */
862 if (state->poll && !state->poll(region, state->poll_data)) {
863 return false;
864 }
865
866 return true;
867}
868
869static void v3d_cursor_snap_draw_fn(bContext *C, int x, int y, void * /*customdata*/)
870{
871 using namespace blender;
872 ScrArea *area = CTX_wm_area(C);
874 int2 xy(x, y);
875 if (region->alignment == RGN_ALIGN_QSPLIT) {
876 /* Quad-View. */
878 if (region == nullptr) {
879 return;
880 }
881 }
882
883 xy[0] -= region->winrct.xmin;
884 xy[1] -= region->winrct.ymin;
885
886 SnapCursorDataIntern *data_intern = &g_data_intern;
888 V3DSnapCursorData *snap_data = &data_intern->snap_data;
891
892 const wmWindow *win = CTX_wm_window(C);
893 const wmEvent *event = win->eventstate;
894 if (event && v3d_cursor_eventstate_has_changed(data_intern, state, UNPACK2(xy), event->modifier))
895 {
896 View3D *v3d = CTX_wm_view3d(C);
897 v3d_cursor_snap_update(state, C, depsgraph, scene, region, v3d, UNPACK2(xy), event->modifier);
898 }
899
900 const bool draw_plane = state->draw_plane || state->draw_box;
901 if (snap_data->type_target == SCE_SNAP_TO_NONE && !draw_plane) {
902 return;
903 }
904
905 /* Setup viewport & matrix. */
906 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
907 wmViewport(&region->winrct);
909 GPU_matrix_set(rv3d->viewmat);
910
911 float matrix[4][4];
912 if (draw_plane) {
913 copy_m4_m3(matrix, snap_data->plane_omat);
914 copy_v3_v3(matrix[3], snap_data->loc);
915
916 v3d_cursor_plane_draw(rv3d, scene->toolsettings->plane_axis, matrix);
917 }
918
919 if (snap_data->type_target != SCE_SNAP_TO_NONE && (state->draw_point || state->draw_box)) {
920 const float *source_loc = (snap_data->type_target & SCE_SNAP_TO_EDGE_PERPENDICULAR) ?
921 state->prevpoint :
922 nullptr;
923
925 source_loc,
926 snap_data->loc,
927 snap_data->type_source,
928 snap_data->type_target,
929 state->source_color,
930 state->target_color);
931 }
932
933 if (state->draw_box) {
934 GPU_matrix_mul(matrix);
935 cursor_box_draw(state->box_dimensions, state->color_box);
936 }
937
938 /* Restore matrix. */
939 wmWindowViewport(win);
940}
941
943
945{
946 SnapCursorDataIntern *data_intern = &g_data_intern;
947 if (BLI_listbase_is_empty(&data_intern->state_intern)) {
948 return &g_data_intern.state_default;
949 }
950 return &((SnapStateIntern *)data_intern->state_intern.last)->snap_state;
951}
952
954{
955 if (state == &g_data_intern.state_default) {
957 return;
958 }
959
960 SnapStateIntern *state_intern = STATE_INTERN_GET(state);
961 if (state_intern == (SnapStateIntern *)g_data_intern.state_intern.last) {
962 return;
963 }
964
965 if (!BLI_remlink_safe(&g_data_intern.state_intern, state_intern)) {
967 return;
968 }
969
970 BLI_addtail(&g_data_intern.state_intern, state_intern);
971}
972
974{
975 SnapCursorDataIntern *data_intern = &g_data_intern;
976
977 if (!data_intern->handle) {
978 if (!data_intern->is_initiated) {
979 /* Only initiate intern data once.
980 * TODO: ED_view3d_cursor_snap_init */
981
982#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
983 wmKeyConfig *keyconf = ((wmWindowManager *)G.main->wm.first)->defaultconf;
984
985 data_intern->keymap = WM_modalkeymap_find(keyconf, "Generic Gizmo Tweak Modal Map");
987 static_cast<const EnumPropertyItem *>(data_intern->keymap->modal_items),
988 "SNAP_ON",
989 &data_intern->snap_on);
990#endif
991 data_intern->is_initiated = true;
992 }
993
996 data_intern->handle = pc;
997 }
998}
999
1001{
1002 SnapCursorDataIntern *data_intern = &g_data_intern;
1003 if (data_intern->handle) {
1004 if (G_MAIN->wm.first) {
1005 WM_paint_cursor_end(data_intern->handle);
1006 }
1007 data_intern->handle = nullptr;
1008 }
1009 if (data_intern->snap_context_v3d) {
1011 data_intern->snap_context_v3d = nullptr;
1012 }
1013}
1014
1016{
1017 g_data_intern.state_default = *state;
1018
1019 /* These values are temporarily set by the tool.
1020 * They are not convenient as default values.
1021 * So reset to null. */
1022 g_data_intern.state_default.prevpoint = nullptr;
1023 g_data_intern.state_default.draw_plane = false;
1024 g_data_intern.state_default.draw_box = false;
1025 g_data_intern.state_default.poll = nullptr;
1026 g_data_intern.state_default.poll_data = nullptr;
1027}
1028
1030{
1031 SnapCursorDataIntern *data_intern = &g_data_intern;
1032 if (!data_intern->handle) {
1034 }
1035
1036 SnapStateIntern *state_intern = static_cast<SnapStateIntern *>(
1037 MEM_mallocN(sizeof(*state_intern), __func__));
1038 state_intern->snap_state = g_data_intern.state_default;
1039 BLI_addtail(&g_data_intern.state_intern, state_intern);
1040
1041 return (V3DSnapCursorState *)&state_intern->snap_state;
1042}
1043
1045{
1046 SnapCursorDataIntern *data_intern = &g_data_intern;
1047 if (BLI_listbase_is_empty(&data_intern->state_intern)) {
1048 return;
1049 }
1050
1051 SnapStateIntern *state_intern = STATE_INTERN_GET(state);
1052 BLI_remlink(&data_intern->state_intern, state_intern);
1053 MEM_freeN(state_intern);
1054 if (BLI_listbase_is_empty(&data_intern->state_intern)) {
1056 }
1057}
1058
1060 const float prev_point[3])
1061{
1062 SnapCursorDataIntern *data_intern = &g_data_intern;
1063 if (!state) {
1065 }
1066 if (prev_point) {
1067 copy_v3_v3(data_intern->prevpoint_stack, prev_point);
1068 state->prevpoint = data_intern->prevpoint_stack;
1069 }
1070 else {
1071 state->prevpoint = nullptr;
1072 }
1073}
1074
1076 V3DSnapCursorState *state, const bContext *C, const ARegion *region, const int x, const int y)
1077{
1078 SnapCursorDataIntern *data_intern = &g_data_intern;
1079 const wmEvent *event = CTX_wm_window(C)->eventstate;
1080 if (event && v3d_cursor_eventstate_has_changed(data_intern, state, x, y, event->modifier)) {
1083 View3D *v3d = CTX_wm_view3d(C);
1084
1085 if (!state) {
1087 }
1088 v3d_cursor_snap_update(state, C, depsgraph, scene, region, v3d, x, y, event->modifier);
1089 }
1090}
1091
1093{
1094 SnapCursorDataIntern *data_intern = &g_data_intern;
1095 return &data_intern->snap_data;
1096}
1097
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
#define G_MAIN
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
General operations, lookup, etc. for blender objects.
int BKE_scene_orientation_get_index(Scene *scene, int slot_index)
Definition scene.cc:2386
ARegion * BKE_area_find_region_xy(const ScrArea *area, int regiontype, const int xy[2]) ATTR_NONNULL(3)
Definition screen.cc:844
ARegion * BKE_area_find_region_type(const ScrArea *area, int region_type)
Definition screen.cc:815
#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_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
bool BLI_remlink_safe(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:153
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
MINLINE float max_ff(float a, float b)
MINLINE int mod_i(int i, int n)
MINLINE float square_f(float a)
float ceil_power_of_10(float f)
Definition math_base.c:74
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition math_geom.cc:215
void copy_m3_m3(float m1[3][3], const float m2[3][3])
void unit_m3(float m[3][3])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
void orthogonalize_m3(float R[3][3], int axis)
void copy_m4_m3(float m1[4][4], const float m2[3][3])
void translate_m4(float mat[4][4], float Tx, float Ty, float Tz)
void normalize_m3(float R[3][3]) ATTR_NONNULL()
void mul_m4_v3(const float M[4][4], float r[3])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v4_v4_uchar(unsigned char r[4], const unsigned char a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_v3_int(int r[3], const int a[3])
MINLINE void copy_v3_fl3(float v[3], float x, float y, float z)
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void negate_v3(float r[3])
MINLINE bool is_zero_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void zero_v3(float r[3])
unsigned char uchar
unsigned int uint
#define UNPACK2(a)
#define UNPACK4(a)
#define UNPACK3(a)
#define ELEM(...)
Scene * DEG_get_input_scene(const Depsgraph *graph)
Object is a sort of wrapper for general info.
#define SCE_SNAP_TO_GEOM
@ SCE_ORIENT_DEFAULT
#define SCE_SNAP_TO_VERTEX
@ SCE_SNAP
@ SCE_SNAP_ABS_GRID
@ SCE_SNAP_TARGET_ALL
@ SCE_SNAP_TO_EDGE
@ SCE_SNAP_TO_FACE
@ SCE_SNAP_TO_EDGE_ENDPOINT
@ SCE_SNAP_TO_INCREMENT
@ SCE_SNAP_TO_GRID
@ SCE_SNAP_TO_EDGE_MIDPOINT
@ SCE_SNAP_TO_EDGE_PERPENDICULAR
@ SCE_SNAP_TO_POINT
@ SCE_SNAP_TO_NONE
@ RGN_ALIGN_QSPLIT
@ RGN_TYPE_WINDOW
@ SPACE_VIEW3D
#define UI_SCALE_FAC
@ V3D_PLACE_ORIENT_SURFACE
@ RV3D_NAVIGATING
@ V3D_PLACE_DEPTH_CURSOR_VIEW
@ V3D_PLACE_DEPTH_SURFACE
bool ED_region_overlap_isect_xy(const ARegion *region, const int event_xy[2])
Definition area_query.cc:43
short ED_transform_calc_orientation_from_type_ex(const Scene *scene, ViewLayer *view_layer, const View3D *v3d, const RegionView3D *rv3d, Object *ob, Object *obedit, short orientation_index, int pivot_point, float r_mat[3][3])
eSnapMode ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const eSnapMode snap_to, const SnapObjectParams *params, const float init_co[3], const float mval[2], const float prev_co[3], float *dist_px, float r_loc[3], float r_no[3], int *r_index, const Object **r_ob, float r_obmat[4][4], float r_face_nor[3])
SnapObjectContext * ED_transform_snap_object_context_create(Scene *scene, int flag)
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
eSnapMode ED_transform_snap_object_project_view3d(SnapObjectContext *sctx, Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const eSnapMode snap_to, const SnapObjectParams *params, const float init_co[3], const float mval[2], const float prev_co[3], float *dist_px, float r_loc[3], float r_no[3])
void ED_view3d_global_to_vector(const RegionView3D *rv3d, const float coord[3], float r_out[3])
void ED_view3d_win_to_3d(const View3D *v3d, const ARegion *region, const float depth_pt[3], const float mval[2], float r_out[3])
float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
@ V3D_SNAPCURSOR_SNAP_EDIT_GEOM_FINAL
Definition ED_view3d.hh:329
@ V3D_SNAPCURSOR_TOGGLE_ALWAYS_TRUE
Definition ED_view3d.hh:326
@ V3D_SNAPCURSOR_OCCLUSION_ALWAYS_TRUE
Definition ED_view3d.hh:327
@ V3D_SNAPCURSOR_SNAP_EDIT_GEOM_CAGE
Definition ED_view3d.hh:330
bool ED_view3d_win_to_3d_on_plane(const ARegion *region, const float plane[4], const float mval[2], bool do_clip, float r_out[3])
void immUniformColor4ubv(const unsigned char rgba[4])
void immEnd()
void immUnbindProgram()
void immAttr4fv(uint attr_id, const float data[4])
void immUniform2f(const char *name, float x, float y)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immVertex3f(uint attr_id, float x, float y, float z)
void immBeginAtMost(GPUPrimType, uint max_vertex_len)
void immUniform1f(const char *name, float x)
GPUVertFormat * immVertexFormat()
void immVertex3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void imm_draw_circle_wire_3d(uint pos, float x, float y, float radius, int nsegments)
void imm_draw_cube_corners_3d(uint pos, const float center[3], const float aspect[3], float factor)
#define GPU_matrix_model_view_get(x)
#define GPU_matrix_set(x)
void GPU_matrix_push()
#define GPU_matrix_mul(x)
#define GPU_matrix_projection_set(x)
void GPU_matrix_pop()
@ GPU_PRIM_LINE_LOOP
@ GPU_PRIM_LINES
@ GPU_PRIM_LINE_STRIP
@ GPU_SHADER_3D_SMOOTH_COLOR
@ GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
@ GPU_BLEND_ADDITIVE
Definition GPU_state.hh:89
void GPU_blend(eGPUBlend blend)
Definition gpu_state.cc:42
void GPU_line_width(float width)
Definition gpu_state.cc:161
void GPU_line_smooth(bool enable)
Definition gpu_state.cc:78
void GPU_viewport_size_get_f(float coords[4])
Definition gpu_state.cc:262
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a color
#define C
Definition RandGen.cpp:29
@ TH_VERTEX_SIZE
float UI_GetThemeValuef(int colorid)
@ KM_CTRL
Definition WM_types.hh:256
@ KM_ALT
Definition WM_types.hh:257
@ KM_OSKEY
Definition WM_types.hh:259
@ KM_SHIFT
Definition WM_types.hh:255
#define U
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
#define fabsf(x)
draw_view in_light_buf[] float
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
format
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
static ulong state[N]
#define G(x, y, z)
blender::VecBase< uint8_t, 4 > uchar4
VecBase< float, 3 > float3
static CursorSnapshot cursor_snap
bool RNA_enum_value_from_id(const EnumPropertyItem *item, const char *identifier, int *r_value)
unsigned char uint8_t
Definition stdint.h:78
void * regiondata
void * last
float viewmat[4][4]
float viewinv[4][4]
float winmat[4][4]
struct ToolSettings * toolsettings
View3DCursor cursor
V3DSnapCursorState state_default
SnapObjectContext * snap_context_v3d
struct SnapCursorDataIntern::@104312227314070056337326077032342361162111126016 last_eventstate
V3DSnapCursorData snap_data
SnapStateIntern * next
SnapStateIntern * prev
V3DSnapCursorState snap_state
eSnapMode type_target
Definition ED_view3d.hh:336
eSnapMode type_source
Definition ED_view3d.hh:335
float plane_omat[3][3]
Definition ED_view3d.hh:341
float obmat[4][4]
Definition ED_view3d.hh:339
int ymin
int xmin
const void * modal_items
struct wmEvent * eventstate
V3DSnapCursorState * ED_view3d_cursor_snap_state_create()
static void v3d_cursor_eventstate_save_xy(SnapCursorDataIntern *cursor_snap, const int x, const int y)
void ED_view3d_cursor_snap_state_default_set(V3DSnapCursorState *state)
#define FADE(v)
static void cursor_point_draw(uint attr_pos, const float loc[3], const float size, eSnapMode snap_type, const uchar color[4])
static const float eps_view_align
V3DSnapCursorState * ED_view3d_cursor_snap_state_active_get()
static void cursor_box_draw(const float dimensions[3], uchar color[4])
void ED_view3d_cursor_snap_state_prevpoint_set(V3DSnapCursorState *state, const float prev_point[3])
static void v3d_cursor_poject_surface_normal(const float normal[3], const float obmat[4][4], float r_mat[3][3])
#define STATE_INTERN_GET(state)
static void v3d_cursor_snap_update(V3DSnapCursorState *state, const bContext *C, Depsgraph *depsgraph, Scene *scene, const ARegion *region, View3D *v3d, int x, int y, uint8_t event_modifier)
static void v3d_cursor_plane_draw(const RegionView3D *rv3d, const int plane_axis, const float matrix[4][4])
static void v3d_cursor_snap_activate()
static eSnapMode v3d_cursor_snap_elements(ToolSettings *tool_settings)
static bool v3d_cursor_eventstate_has_changed(SnapCursorDataIntern *data_intern, V3DSnapCursorState *state, const int x, const int y, uint8_t event_modifier)
static SnapCursorDataIntern g_data_intern
static bool mat3_align_axis_to_v3(float mat[3][3], const int axis_align, const float v[3])
static bool v3d_cursor_snap_calc_plane()
static bool v3d_cursor_snap_poll_fn(bContext *C)
static void v3d_cursor_snap_context_ensure(Scene *scene)
void ED_view3d_cursor_snap_state_free(V3DSnapCursorState *state)
static void v3d_cursor_eventstate_save_modifier(SnapCursorDataIntern *data_intern, uint8_t event_modifier)
static void v3d_cursor_snap_free()
void ED_view3d_cursor_snap_state_active_set(V3DSnapCursorState *state)
SnapObjectContext * ED_view3d_cursor_snap_context_ensure(Scene *scene)
void ED_view3d_cursor_snap_data_update(V3DSnapCursorState *state, const bContext *C, const ARegion *region, const int x, const int y)
static void v3d_cursor_snap_draw_fn(bContext *C, int x, int y, void *)
void ED_view3d_cursor_snap_draw_util(RegionView3D *rv3d, const float source_loc[3], const float target_loc[3], const eSnapMode source_type, const eSnapMode target_type, const uchar source_color[4], const uchar target_color[4])
static void v3d_cursor_plane_draw_grid(const int resolution, const float scale, const float scale_fade, const float matrix[4][4], const int plane_axis, const float color[4])
static bool v3d_cursor_is_snap_invert(SnapCursorDataIntern *data_intern, uint8_t event_modifier)
V3DSnapCursorData * ED_view3d_cursor_snap_data_get()
int xy[2]
Definition wm_draw.cc:170
@ EVT_RIGHTCTRLKEY
@ EVT_OSKEY
@ EVT_LEFTCTRLKEY
@ EVT_RIGHTALTKEY
@ EVT_LEFTALTKEY
@ EVT_RIGHTSHIFTKEY
@ EVT_LEFTSHIFTKEY
wmKeyMap * WM_keymap_active(const wmWindowManager *wm, wmKeyMap *keymap)
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition wm_keymap.cc:960
bool WM_paint_cursor_end(wmPaintCursor *handle)
wmPaintCursor * WM_paint_cursor_activate(short space_type, short region_type, bool(*poll)(bContext *C), wmPaintCursorDraw draw, void *customdata)
void wmViewport(const rcti *winrct)
void wmWindowViewport(const wmWindow *win)