Blender  V3.3
view3d_placement.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
12 #include "MEM_guardedalloc.h"
13 
14 #include "BKE_context.h"
15 
16 #include "RNA_access.h"
17 #include "RNA_define.h"
18 #include "RNA_enum_types.h"
19 
20 #include "WM_api.h"
21 #include "WM_toolsystem.h"
22 
23 #include "ED_gizmo_utils.h"
24 #include "ED_screen.h"
25 #include "ED_space_api.h"
26 #include "ED_view3d.h"
27 
28 #include "UI_resources.h"
29 
30 #include "GPU_immediate.h"
31 
32 #include "view3d_intern.h"
33 
34 static const char *view3d_gzgt_placement_id = "VIEW3D_GGT_placement";
35 
41 static const float eps_view_align = 1e-2f;
42 
43 /* -------------------------------------------------------------------- */
53 };
54 
58 };
59 
63 };
64 
68 };
69 
71  /* Window manager variables (set these even when waiting for input). */
76 
79 
80  float co_src[3];
81 
83  struct {
95  float plane[4];
96  float co_dst[3];
97 
122 
127 
128  } step[2];
129 
131  float view_plane[4];
132 
133  float matrix_orient[3][3];
135 
138  float snap_co[3];
139 
141  enum {
145 
147 
149  bool use_tool;
150 
153 
156 
157  enum ePlace_SnapTo snap_to;
158 };
159 
162 /* -------------------------------------------------------------------- */
170  const float plane[4],
171  const float mval[2],
172  const float *plane_fallback,
173  float r_out[3])
174 {
175  RegionView3D *rv3d = region->regiondata;
176  bool do_clip = rv3d->is_persp;
177  if (plane_fallback != NULL) {
179  region, plane, mval, do_clip, plane_fallback, r_out);
180  }
181  return ED_view3d_win_to_3d_on_plane(region, plane, mval, do_clip, r_out);
182 }
183 
187 static int dot_v3_array_find_max_index(const float dirs[][3],
188  const int dirs_len,
189  const float dir_test[3],
190  bool is_signed)
191 {
192  int index_found = -1;
193  float dot_best = -1.0f;
194  for (int i = 0; i < dirs_len; i++) {
195  float dot_test = dot_v3v3(dirs[i], dir_test);
196  if (is_signed == false) {
197  dot_test = fabsf(dot_test);
198  }
199  if ((index_found == -1) || (dot_test > dot_best)) {
200  dot_best = dot_test;
201  index_found = i;
202  }
203  }
204  return index_found;
205 }
206 
208  idp_gizmogroup_from_region)(ARegion *region)
209 {
210  wmGizmoMap *gzmap = region->gizmo_map;
211  return gzmap ? WM_gizmomap_group_find(gzmap, view3d_gzgt_placement_id) : NULL;
212 }
213 
220  Scene *scene, View3D *v3d, ARegion *region, const float co_relative[3], float co[3])
221 {
223  return false;
224  }
225 
226  const float grid_size = ED_view3d_grid_view_scale(scene, v3d, region, NULL);
227  if (UNLIKELY(grid_size == 0.0f)) {
228  return false;
229  }
230 
232  co_relative = NULL;
233  }
234 
235  if (co_relative != NULL) {
236  sub_v3_v3(co, co_relative);
237  }
238  mul_v3_fl(co, 1.0f / grid_size);
239  co[0] = roundf(co[0]);
240  co[1] = roundf(co[1]);
241  co[2] = roundf(co[2]);
242  mul_v3_fl(co, grid_size);
243  if (co_relative != NULL) {
244  add_v3_v3(co, co_relative);
245  }
246 
247  return true;
248 }
249 
252 /* -------------------------------------------------------------------- */
256 static void draw_line_loop(const float coords[][3], int coords_len, const float color[4])
257 {
260 
262  GPU_vertbuf_data_alloc(vert, coords_len);
263 
264  for (int i = 0; i < coords_len; i++) {
265  GPU_vertbuf_attr_set(vert, pos, i, coords[i]);
266  }
267 
271 
272  GPU_batch_uniform_4fv(batch, "color", color);
273 
274  float viewport[4];
275  GPU_viewport_size_get_f(viewport);
276  GPU_batch_uniform_2fv(batch, "viewportSize", &viewport[2]);
277  GPU_batch_uniform_1f(batch, "lineWidth", U.pixelsize);
278 
280 
283 }
284 
285 static void draw_line_pairs(const float coords_a[][3],
286  float coords_b[][3],
287  int coords_len,
288  const float color[4])
289 {
292 
294  GPU_vertbuf_data_alloc(vert, coords_len * 2);
295 
296  for (int i = 0; i < coords_len; i++) {
297  GPU_vertbuf_attr_set(vert, pos, i * 2, coords_a[i]);
298  GPU_vertbuf_attr_set(vert, pos, (i * 2) + 1, coords_b[i]);
299  }
300 
304 
305  GPU_batch_uniform_4fv(batch, "color", color);
306 
307  float viewport[4];
308  GPU_viewport_size_get_f(viewport);
309  GPU_batch_uniform_2fv(batch, "viewportSize", &viewport[2]);
310  GPU_batch_uniform_1f(batch, "lineWidth", U.pixelsize);
311 
313 
316 }
317 
318 static void draw_line_bounds(const BoundBox *bounds, const float color[4])
319 {
322 
323  const int edges[12][2] = {
324  /* First side. */
325  {0, 1},
326  {1, 2},
327  {2, 3},
328  {3, 0},
329  /* Second side. */
330  {4, 5},
331  {5, 6},
332  {6, 7},
333  {7, 4},
334  /* Edges between. */
335  {0, 4},
336  {1, 5},
337  {2, 6},
338  {3, 7},
339  };
340 
342  GPU_vertbuf_data_alloc(vert, ARRAY_SIZE(edges) * 2);
343 
344  for (int i = 0, j = 0; i < ARRAY_SIZE(edges); i++) {
345  GPU_vertbuf_attr_set(vert, pos, j++, bounds->vec[edges[i][0]]);
346  GPU_vertbuf_attr_set(vert, pos, j++, bounds->vec[edges[i][1]]);
347  }
348 
352 
353  GPU_batch_uniform_4fv(batch, "color", color);
354 
355  float viewport[4];
356  GPU_viewport_size_get_f(viewport);
357  GPU_batch_uniform_2fv(batch, "viewportSize", &viewport[2]);
358  GPU_batch_uniform_1f(batch, "lineWidth", U.pixelsize);
359 
361 
364 }
365 
366 static bool calc_bbox(struct InteractivePlaceData *ipd, BoundBox *bounds)
367 {
368  memset(bounds, 0x0, sizeof(*bounds));
369 
370  if (compare_v3v3(ipd->co_src, ipd->step[0].co_dst, FLT_EPSILON)) {
371  return false;
372  }
373 
374  float matrix_orient_inv[3][3];
375  invert_m3_m3(matrix_orient_inv, ipd->matrix_orient);
376 
377  const int x_axis = (ipd->orient_axis + 1) % 3;
378  const int y_axis = (ipd->orient_axis + 2) % 3;
379 
380  float quad_base[4][3];
381  float quad_secondary[4][3];
382 
383  copy_v3_v3(quad_base[0], ipd->co_src);
384  copy_v3_v3(quad_base[2], ipd->step[0].co_dst);
385 
386  /* Only set when we have a fixed aspect. */
387  float fixed_aspect_dimension;
388 
389  /* *** Primary *** */
390 
391  {
392  float delta_local[3];
393  float delta_a[3];
394  float delta_b[3];
395 
396  sub_v3_v3v3(delta_local, ipd->step[0].co_dst, ipd->co_src);
397  mul_m3_v3(matrix_orient_inv, delta_local);
398 
399  copy_v3_v3(delta_a, delta_local);
400  copy_v3_v3(delta_b, delta_local);
401  delta_a[ipd->orient_axis] = 0.0f;
402  delta_b[ipd->orient_axis] = 0.0f;
403 
404  delta_a[x_axis] = 0.0f;
405  delta_b[y_axis] = 0.0f;
406 
407  /* Assign here in case secondary. */
408  fixed_aspect_dimension = max_ff(fabsf(delta_a[y_axis]), fabsf(delta_b[x_axis]));
409 
410  if (ipd->step[0].is_fixed_aspect) {
411  delta_a[y_axis] = copysignf(fixed_aspect_dimension, delta_a[y_axis]);
412  delta_b[x_axis] = copysignf(fixed_aspect_dimension, delta_b[x_axis]);
413  }
414 
415  mul_m3_v3(ipd->matrix_orient, delta_a);
416  mul_m3_v3(ipd->matrix_orient, delta_b);
417 
418  if (ipd->step[0].is_fixed_aspect) {
419  /* Recalculate the destination point. */
420  copy_v3_v3(quad_base[2], ipd->co_src);
421  add_v3_v3(quad_base[2], delta_a);
422  add_v3_v3(quad_base[2], delta_b);
423  }
424 
425  add_v3_v3v3(quad_base[1], ipd->co_src, delta_a);
426  add_v3_v3v3(quad_base[3], ipd->co_src, delta_b);
427  }
428 
429  if (ipd->step[0].is_centered) {
430  /* Use a copy in case aspect was applied to the quad. */
431  float base_co_dst[3];
432  copy_v3_v3(base_co_dst, quad_base[2]);
433  for (int i = 0; i < ARRAY_SIZE(quad_base); i++) {
434  sub_v3_v3(quad_base[i], base_co_dst);
435  mul_v3_fl(quad_base[i], 2.0f);
436  add_v3_v3(quad_base[i], base_co_dst);
437  }
438  fixed_aspect_dimension *= 2.0f;
439  }
440 
441  /* *** Secondary *** */
442 
443  float delta_local[3];
444  if (ipd->step_index == STEP_DEPTH) {
445  sub_v3_v3v3(delta_local, ipd->step[1].co_dst, ipd->step[0].co_dst);
446  }
447  else {
448  zero_v3(delta_local);
449  }
450 
451  if (ipd->step[1].is_fixed_aspect) {
452  if (!is_zero_v3(delta_local)) {
453  normalize_v3_length(delta_local, fixed_aspect_dimension);
454  }
455  }
456 
457  if (ipd->step[1].is_centered) {
458  float temp_delta[3];
459  if (ipd->step[1].is_fixed_aspect) {
460  mul_v3_v3fl(temp_delta, delta_local, 0.5f);
461  }
462  else {
463  copy_v3_v3(temp_delta, delta_local);
464  mul_v3_fl(delta_local, 2.0f);
465  }
466 
467  for (int i = 0; i < ARRAY_SIZE(quad_base); i++) {
468  sub_v3_v3(quad_base[i], temp_delta);
469  }
470  }
471 
472  if ((ipd->step_index == STEP_DEPTH) &&
473  (compare_v3v3(ipd->step[0].co_dst, ipd->step[1].co_dst, FLT_EPSILON) == false)) {
474 
475  for (int i = 0; i < ARRAY_SIZE(quad_base); i++) {
476  add_v3_v3v3(quad_secondary[i], quad_base[i], delta_local);
477  }
478  }
479  else {
480  copy_v3_v3(quad_secondary[0], quad_base[0]);
481  copy_v3_v3(quad_secondary[1], quad_base[1]);
482  copy_v3_v3(quad_secondary[2], quad_base[2]);
483  copy_v3_v3(quad_secondary[3], quad_base[3]);
484  }
485 
486  for (int i = 0; i < 4; i++) {
487  copy_v3_v3(bounds->vec[i], quad_base[i]);
488  copy_v3_v3(bounds->vec[i + 4], quad_secondary[i]);
489  }
490 
491  return true;
492 }
493 
494 static void draw_circle_in_quad(const float v1[3],
495  const float v2[3],
496  const float v3[3],
497  const float v4[3],
498  const int resolution,
499  const float color[4])
500 {
501  /* This isn't so efficient. */
502  const float quad[4][2] = {
503  {-1, -1},
504  {+1, -1},
505  {+1, +1},
506  {-1, +1},
507  };
508 
509  float(*coords)[3] = MEM_mallocN(sizeof(float[3]) * (resolution + 1), __func__);
510  for (int i = 0; i <= resolution; i++) {
511  float theta = ((2.0f * M_PI) * ((float)i / (float)resolution)) + 0.01f;
512  float x = cosf(theta);
513  float y = sinf(theta);
514  const float pt[2] = {x, y};
515  float w[4];
517 
518  float *co = coords[i];
519  zero_v3(co);
520  madd_v3_v3fl(co, v1, w[0]);
521  madd_v3_v3fl(co, v2, w[1]);
522  madd_v3_v3fl(co, v3, w[2]);
523  madd_v3_v3fl(co, v4, w[3]);
524  }
525  draw_line_loop(coords, resolution + 1, color);
526  MEM_freeN(coords);
527 }
528 
531 /* -------------------------------------------------------------------- */
535 static void draw_primitive_view_impl(const struct bContext *C,
536  struct InteractivePlaceData *ipd,
537  const float color[4],
538  int flatten_axis)
539 {
540  UNUSED_VARS(C);
541 
543  calc_bbox(ipd, &bounds);
544 
545  /* Use cavalier projection, since it maps the scale usefully to the cursor. */
546  if (flatten_axis == STEP_BASE) {
547  /* Calculate the plane that would be defined by the side of the cube vertices
548  * if the plane had any volume. */
549 
550  float no[3];
551 
553  no, ipd->matrix_orient[ipd->orient_axis], ipd->matrix_orient[(ipd->orient_axis + 1) % 3]);
554 
555  RegionView3D *rv3d = ipd->region->regiondata;
556  copy_v3_v3(no, rv3d->viewinv[2]);
557  normalize_v3(no);
558 
559  float base_plane[4];
560 
561  plane_from_point_normal_v3(base_plane, bounds.vec[0], no);
562 
563  /* Offset all vertices even though we only need to offset the half of them.
564  * This is harmless as `dist` will be zero for the `base_plane` aligned side of the cube. */
565  for (int i = 0; i < ARRAY_SIZE(bounds.vec); i++) {
566  const float dist = dist_signed_to_plane_v3(bounds.vec[i], base_plane);
567  madd_v3_v3fl(bounds.vec[i], base_plane, -dist);
568  madd_v3_v3fl(bounds.vec[i], ipd->step[STEP_BASE].degenerate_diagonal_display, dist);
569  }
570  }
571 
572  if (flatten_axis == STEP_DEPTH) {
573  const float *base_plane = ipd->step[0].plane;
574  for (int i = 0; i < 4; i++) {
575  const float dist = dist_signed_to_plane_v3(bounds.vec[i + 4], base_plane);
576  madd_v3_v3fl(bounds.vec[i + 4], base_plane, -dist);
577  madd_v3_v3fl(bounds.vec[i + 4], ipd->step[STEP_DEPTH].degenerate_diagonal_display, dist);
578  }
579  }
580 
582 
584  /* pass */
585  }
588  draw_circle_in_quad(UNPACK4((&bounds.vec[4])), 32, color);
589  }
590  else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CONE) {
592 
593  float center[3];
594  mid_v3_v3v3v3v3(center, UNPACK4((&bounds.vec[4])));
595 
596  float coords_a[4][3];
597  float coords_b[4][3];
598 
599  for (int i = 0; i < 4; i++) {
600  copy_v3_v3(coords_a[i], center);
601  mid_v3_v3v3(coords_b[i], bounds.vec[i], bounds.vec[(i + 1) % 4]);
602  }
603 
604  draw_line_pairs(coords_a, coords_b, 4, color);
605  }
606  else if (ELEM(ipd->primitive_type,
609  /* See bound-box diagram for reference. */
610 
611  /* Primary Side. */
612  float v01[3], v12[3], v23[3], v30[3];
613  mid_v3_v3v3(v01, bounds.vec[0], bounds.vec[1]);
614  mid_v3_v3v3(v12, bounds.vec[1], bounds.vec[2]);
615  mid_v3_v3v3(v23, bounds.vec[2], bounds.vec[3]);
616  mid_v3_v3v3(v30, bounds.vec[3], bounds.vec[0]);
617  /* Secondary Side. */
618  float v45[3], v56[3], v67[3], v74[3];
619  mid_v3_v3v3(v45, bounds.vec[4], bounds.vec[5]);
620  mid_v3_v3v3(v56, bounds.vec[5], bounds.vec[6]);
621  mid_v3_v3v3(v67, bounds.vec[6], bounds.vec[7]);
622  mid_v3_v3v3(v74, bounds.vec[7], bounds.vec[4]);
623  /* Edges between. */
624  float v04[3], v15[3], v26[3], v37[3];
625  mid_v3_v3v3(v04, bounds.vec[0], bounds.vec[4]);
626  mid_v3_v3v3(v15, bounds.vec[1], bounds.vec[5]);
627  mid_v3_v3v3(v26, bounds.vec[2], bounds.vec[6]);
628  mid_v3_v3v3(v37, bounds.vec[3], bounds.vec[7]);
629 
630  draw_circle_in_quad(v01, v45, v67, v23, 32, color);
631  draw_circle_in_quad(v30, v12, v56, v74, 32, color);
632  draw_circle_in_quad(v04, v15, v26, v37, 32, color);
633  }
634 }
635 
636 static void draw_primitive_view(const struct bContext *C, ARegion *UNUSED(region), void *arg)
637 {
638  struct InteractivePlaceData *ipd = arg;
639  float color[4];
641 
642  const bool use_depth = !XRAY_ENABLED(ipd->v3d);
643  const eGPUDepthTest depth_test_enabled = GPU_depth_test_get();
644 
645  if (use_depth) {
647  color[3] = 0.15f;
648  draw_primitive_view_impl(C, ipd, color, -1);
649  }
650 
651  /* Show a flattened projection if the current step is aligned to the view. */
652  if (ipd->step[ipd->step_index].is_degenerate_view_align) {
653  const RegionView3D *rv3d = ipd->region->regiondata;
654  if (!rv3d->is_persp) {
656  }
657  }
658 
659  if (use_depth) {
661  }
662  color[3] = 1.0f;
663  draw_primitive_view_impl(C, ipd, color, -1);
664 
665  if (use_depth) {
666  if (depth_test_enabled == false) {
668  }
669  }
670 }
671 
674 /* -------------------------------------------------------------------- */
681  const wmEvent *UNUSED(event),
682  float r_co_src[3],
683  float r_matrix_orient[3][3],
684  bool *r_is_enabled,
685  bool *r_is_snap_invert)
686 {
688  copy_v3_v3(r_co_src, snap_data->loc);
689  if (r_matrix_orient) {
690  copy_m3_m3(r_matrix_orient, snap_data->plane_omat);
691  }
692  if (r_is_enabled) {
693  *r_is_enabled = snap_data->is_enabled;
694  }
695  if (r_is_snap_invert) {
696  *r_is_snap_invert = snap_data->is_snap_invert;
697  }
698  return snap_data->snap_elem != SCE_SNAP_MODE_NONE;
699 }
700 
703 /* -------------------------------------------------------------------- */
707 static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEvent *event)
708 {
710 
711  const int plane_axis = snap_state->plane_axis;
712  const enum ePlace_SnapTo snap_to = RNA_enum_get(op->ptr, "snap_target");
713 
714  const enum ePlace_Origin plane_origin[2] = {
715  RNA_enum_get(op->ptr, "plane_origin_base"),
716  RNA_enum_get(op->ptr, "plane_origin_depth"),
717  };
718  const enum ePlace_Aspect plane_aspect[2] = {
719  RNA_enum_get(op->ptr, "plane_aspect_base"),
720  RNA_enum_get(op->ptr, "plane_aspect_depth"),
721  };
722 
723  struct InteractivePlaceData *ipd = op->customdata;
724 
726 
728  if (snap_state_new) {
729  ipd->snap_state = snap_state = snap_state_new;
730 
731  /* For drag events, update the location since it will be set from the drag-start.
732  * This is needed as cursor-drawing doesn't deal with drag events and will use
733  * the current cursor location instead of the drag-start. */
734  if (event->val == KM_CLICK_DRAG) {
735  /* Set this flag so snapping always updated. */
736  int mval[2];
737  WM_event_drag_start_mval(event, ipd->region, mval);
738  int flag_orig = snap_state_new->flag;
739  snap_state_new->flag |= V3D_SNAPCURSOR_TOGGLE_ALWAYS_TRUE;
740 
741  /* Be sure to also compute the #V3DSnapCursorData.plane_omat. */
742  snap_state->draw_plane = true;
743 
744  ED_view3d_cursor_snap_data_update(snap_state_new, C, mval[0], mval[1]);
745  snap_state_new->flag = flag_orig;
746  }
747  }
748 
749  snap_state->draw_point = true;
750  snap_state->draw_plane = true;
751  ipd->is_snap_found =
753  C, event, ipd->co_src, ipd->matrix_orient, &ipd->use_snap, &ipd->is_snap_invert) != 0;
754 
755  snap_state->draw_plane = false;
757 
758  ipd->orient_axis = plane_axis;
759  for (int i = 0; i < 2; i++) {
760  ipd->step[i].is_centered_init = (plane_origin[i] == PLACE_ORIGIN_CENTER);
761  ipd->step[i].is_centered = ipd->step[i].is_centered_init;
762 
763  ipd->step[i].is_fixed_aspect_init = (plane_aspect[i] == PLACE_ASPECT_FIXED);
764  ipd->step[i].is_fixed_aspect = ipd->step[i].is_fixed_aspect_init;
765  }
766 
767  ipd->step_index = STEP_BASE;
768  ipd->snap_to = snap_to;
769 
770  plane_from_point_normal_v3(ipd->step[0].plane, ipd->co_src, ipd->matrix_orient[plane_axis]);
771 
772  copy_v3_v3(ipd->step[0].co_dst, ipd->co_src);
773 
774  {
775  RegionView3D *rv3d = ipd->region->regiondata;
776  const float view_axis_dot = fabsf(dot_v3v3(rv3d->viewinv[2], ipd->matrix_orient[plane_axis]));
777  ipd->step[STEP_BASE].is_degenerate_view_align = view_axis_dot < eps_view_align;
778  ipd->step[STEP_DEPTH].is_degenerate_view_align = fabsf(view_axis_dot - 1.0f) < eps_view_align;
779 
780  float view_axis[3];
781  normalize_v3_v3(view_axis, rv3d->viewinv[2]);
782  plane_from_point_normal_v3(ipd->view_plane, ipd->co_src, view_axis);
783  }
784 
787  RegionView3D *rv3d = ipd->region->regiondata;
788  float axis_view[3];
789  add_v3_v3v3(axis_view, rv3d->viewinv[0], rv3d->viewinv[1]);
790  normalize_v3(axis_view);
791 
792  /* Setup fallback axes. */
793  for (int i = 0; i < 2; i++) {
794  if (ipd->step[i].is_degenerate_view_align) {
795  const int degenerate_axis =
796  (i == STEP_BASE) ?
797  /* For #STEP_BASE find the orient axis that align to the view. */
798  dot_v3_array_find_max_index(ipd->matrix_orient, 3, rv3d->viewinv[2], false) :
799  /* For #STEP_DEPTH the orient axis is always view aligned when degenerate. */
800  ipd->orient_axis;
801 
802  float axis_fallback[4][3];
803  const int x_axis = (degenerate_axis + 1) % 3;
804  const int y_axis = (degenerate_axis + 2) % 3;
805 
806  /* Assign 4x diagonal axes, find which one is closest to the viewport diagonal
807  * bottom left to top right, for a predictable direction from a user perspective. */
808  add_v3_v3v3(axis_fallback[0], ipd->matrix_orient[x_axis], ipd->matrix_orient[y_axis]);
809  sub_v3_v3v3(axis_fallback[1], ipd->matrix_orient[x_axis], ipd->matrix_orient[y_axis]);
810  negate_v3_v3(axis_fallback[2], axis_fallback[0]);
811  negate_v3_v3(axis_fallback[3], axis_fallback[1]);
812 
813  const int axis_best = dot_v3_array_find_max_index(axis_fallback, 4, axis_view, true);
814  normalize_v3_v3(ipd->step[i].degenerate_diagonal, axis_fallback[axis_best]);
816 
817  /* `degenerate_view_plane_fallback` is used to map cursor motion from a view aligned
818  * plane back onto the view aligned plane.
819  *
820  * The dot product check below ensures cursor motion
821  * isn't inverted from a user perspective. */
822  const bool degenerate_axis_is_flip = dot_v3v3(ipd->matrix_orient[degenerate_axis],
823  ((i == STEP_BASE) ?
824  ipd->step[i].degenerate_diagonal :
825  rv3d->viewinv[2])) < 0.0f;
826 
828  if (degenerate_axis_is_flip) {
830  }
831  }
832  }
833  }
834 
837 
839 
840  /* Setup the primitive type. */
841  {
842  PropertyRNA *prop = RNA_struct_find_property(op->ptr, "primitive_type");
843  if (RNA_property_is_set(op->ptr, prop)) {
844  ipd->primitive_type = RNA_property_enum_get(op->ptr, prop);
845  ipd->use_tool = false;
846  }
847  else {
848  ipd->use_tool = true;
849 
850  /* Get from the tool, a bit of a non-standard way of operating. */
851  const bToolRef *tref = ipd->area->runtime.tool;
852  if (tref && STREQ(tref->idname, "builtin.primitive_cube_add")) {
854  }
855  else if (tref && STREQ(tref->idname, "builtin.primitive_cylinder_add")) {
857  }
858  else if (tref && STREQ(tref->idname, "builtin.primitive_cone_add")) {
860  }
861  else if (tref && STREQ(tref->idname, "builtin.primitive_uv_sphere_add")) {
863  }
864  else if (tref && STREQ(tref->idname, "builtin.primitive_ico_sphere_add")) {
866  }
867  else {
868  /* If the user runs this as an operator they should set the 'primitive_type',
869  * however running from operator search will end up at this point. */
871  ipd->use_tool = false;
872  }
873  }
874  }
875 }
876 
878 {
879  const bool wait_for_input = RNA_boolean_get(op->ptr, "wait_for_input");
880 
881  struct InteractivePlaceData *ipd = MEM_callocN(sizeof(*ipd), __func__);
882  op->customdata = ipd;
883 
884  ipd->scene = CTX_data_scene(C);
885  ipd->area = CTX_wm_area(C);
886  ipd->region = CTX_wm_region(C);
887  ipd->v3d = CTX_wm_view3d(C);
888 
889  if (wait_for_input) {
890  ipd->wait_for_input = true;
891  /* TODO: support snapping when not using with tool. */
892 #if 0
894 #endif
895  }
896  else {
897  view3d_interactive_add_begin(C, op, event);
898  }
899 
901 
902  return OPERATOR_RUNNING_MODAL;
903 }
904 
906 {
907  UNUSED_VARS(C);
908 
909  struct InteractivePlaceData *ipd = op->customdata;
911 
913 
915 
916  MEM_freeN(ipd);
917 }
918 
920 {
922 }
923 
924 enum {
931 };
932 
934 {
935  static const EnumPropertyItem modal_items[] = {
936  {PLACE_MODAL_SNAP_ON, "SNAP_ON", 0, "Snap On", ""},
937  {PLACE_MODAL_SNAP_OFF, "SNAP_OFF", 0, "Snap Off", ""},
938  {PLACE_MODAL_FIXED_ASPECT_ON, "FIXED_ASPECT_ON", 0, "Fixed Aspect On", ""},
939  {PLACE_MODAL_FIXED_ASPECT_OFF, "FIXED_ASPECT_OFF", 0, "Fixed Aspect Off", ""},
940  {PLACE_MODAL_PIVOT_CENTER_ON, "PIVOT_CENTER_ON", 0, "Center Pivot On", ""},
941  {PLACE_MODAL_PIVOT_CENTER_OFF, "PIVOT_CENTER_OFF", 0, "Center Pivot Off", ""},
942  {0, NULL, 0, NULL, NULL},
943  };
944 
945  const char *keymap_name = "View3D Placement Modal";
946  wmKeyMap *keymap = WM_modalkeymap_find(keyconf, keymap_name);
947 
948  /* This function is called for each space-type, only needs to add map once. */
949  if (keymap && keymap->modal_items) {
950  return;
951  }
952 
953  keymap = WM_modalkeymap_ensure(keyconf, keymap_name, modal_items);
954 
955  WM_modalkeymap_assign(keymap, "VIEW3D_OT_interactive_add");
956 }
957 
959 {
960  UNUSED_VARS(C, op);
961 
962  struct InteractivePlaceData *ipd = op->customdata;
963 
964  ARegion *region = ipd->region;
965  bool do_redraw = false;
966  bool do_cursor_update = false;
967 
968  /* Handle modal key-map. */
969  if (event->type == EVT_MODAL_MAP) {
970  bool is_fallthrough = false;
971  switch (event->val) {
973  is_fallthrough = true;
975  }
977  ipd->step[ipd->step_index].is_fixed_aspect =
978  is_fallthrough ^ ipd->step[ipd->step_index].is_fixed_aspect_init;
979  do_redraw = true;
980  break;
981  }
983  is_fallthrough = true;
985  }
987  ipd->step[ipd->step_index].is_centered = is_fallthrough ^
988  ipd->step[ipd->step_index].is_centered_init;
989  do_redraw = true;
990  break;
991  }
992  case PLACE_MODAL_SNAP_ON: {
993  is_fallthrough = true;
995  }
996  case PLACE_MODAL_SNAP_OFF: {
997  const ToolSettings *ts = ipd->scene->toolsettings;
998  ipd->is_snap_invert = is_fallthrough;
999  ipd->use_snap = (ipd->is_snap_invert == !(ts->snap_flag & SCE_SNAP));
1000  do_cursor_update = true;
1001  break;
1002  }
1003  }
1004  }
1005  else {
1006  switch (event->type) {
1007  case EVT_ESCKEY:
1008  case RIGHTMOUSE: {
1010  return OPERATOR_CANCELLED;
1011  }
1012  case MOUSEMOVE: {
1013  do_cursor_update = true;
1014  break;
1015  }
1016  }
1017  }
1018 
1019  if (ipd->wait_for_input) {
1020  if (ELEM(event->type, LEFTMOUSE)) {
1021  if (event->val == KM_PRESS) {
1022  view3d_interactive_add_begin(C, op, event);
1023  ipd->wait_for_input = false;
1024  return OPERATOR_RUNNING_MODAL;
1025  }
1026  }
1027  return OPERATOR_RUNNING_MODAL;
1028  }
1029 
1030  if (ipd->step_index == STEP_BASE) {
1031  if (ELEM(event->type, ipd->launch_event, LEFTMOUSE)) {
1032  if (event->val == KM_RELEASE) {
1034 
1035  /* Set secondary plane. */
1036 
1037  /* Create normal. */
1038  {
1039  RegionView3D *rv3d = region->regiondata;
1040  float no[3], no_temp[3];
1041 
1043  cross_v3_v3v3(no_temp, ipd->step[0].plane, ipd->step[STEP_DEPTH].degenerate_diagonal);
1044  cross_v3_v3v3(no, no_temp, ipd->step[0].plane);
1045  }
1046  else {
1047  cross_v3_v3v3(no_temp, ipd->step[0].plane, rv3d->viewinv[2]);
1048  cross_v3_v3v3(no, no_temp, ipd->step[0].plane);
1049  }
1050  normalize_v3(no);
1051 
1052  plane_from_point_normal_v3(ipd->step[1].plane, ipd->step[0].co_dst, no);
1053  }
1054 
1055  copy_v3_v3(ipd->step[1].co_dst, ipd->step[0].co_dst);
1056  ipd->step_index = STEP_DEPTH;
1057 
1058  /* Use the toggle from the previous step. */
1059  if (ipd->step[0].is_centered != ipd->step[0].is_centered_init) {
1060  ipd->step[1].is_centered = !ipd->step[1].is_centered;
1061  }
1062  if (ipd->step[0].is_fixed_aspect != ipd->step[0].is_fixed_aspect_init) {
1063  ipd->step[1].is_fixed_aspect = !ipd->step[1].is_fixed_aspect;
1064  }
1065  }
1066  }
1067  }
1068  else if (ipd->step_index == STEP_DEPTH) {
1069  if (ELEM(event->type, ipd->launch_event, LEFTMOUSE)) {
1070  if (event->val == KM_PRESS) {
1071 
1072  BoundBox bounds;
1073  calc_bbox(ipd, &bounds);
1074 
1075  float location[3];
1076  float rotation[3];
1077  float scale[3];
1078 
1079  float matrix_orient_axis[3][3];
1080  copy_m3_m3(matrix_orient_axis, ipd->matrix_orient);
1081  if (ipd->orient_axis != 2) {
1082  swap_v3_v3(matrix_orient_axis[2], matrix_orient_axis[ipd->orient_axis]);
1083  swap_v3_v3(matrix_orient_axis[0], matrix_orient_axis[1]);
1084  }
1085  /* Needed for shapes where the sign matters (cone for eg). */
1086  {
1087  float delta[3];
1088  sub_v3_v3v3(delta, bounds.vec[0], bounds.vec[4]);
1089  if (dot_v3v3(ipd->matrix_orient[ipd->orient_axis], delta) > 0.0f) {
1090  negate_v3(matrix_orient_axis[2]);
1091 
1092  /* Only flip Y so we don't flip a single axis which causes problems. */
1093  negate_v3(matrix_orient_axis[1]);
1094  }
1095  }
1096 
1097  mat3_to_eul(rotation, matrix_orient_axis);
1098 
1099  mid_v3_v3v3(location, bounds.vec[0], bounds.vec[6]);
1100  const int cube_verts[3] = {3, 1, 4};
1101  for (int i = 0; i < 3; i++) {
1102  scale[i] = len_v3v3(bounds.vec[0], bounds.vec[cube_verts[i]]);
1103  /* Primitives have size 2 by default, compensate for this here. */
1104  scale[i] /= 2.0f;
1105  }
1106 
1107  wmOperatorType *ot = NULL;
1108  PointerRNA op_props;
1110  ot = WM_operatortype_find("MESH_OT_primitive_cube_add", false);
1111  }
1112  else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CYLINDER) {
1113  ot = WM_operatortype_find("MESH_OT_primitive_cylinder_add", false);
1114  }
1115  else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CONE) {
1116  ot = WM_operatortype_find("MESH_OT_primitive_cone_add", false);
1117  }
1119  ot = WM_operatortype_find("MESH_OT_primitive_uv_sphere_add", false);
1120  }
1122  ot = WM_operatortype_find("MESH_OT_primitive_ico_sphere_add", false);
1123  }
1124 
1125  if (ot != NULL) {
1127 
1128  if (ipd->use_tool) {
1129  bToolRef *tref = ipd->area->runtime.tool;
1130  PointerRNA temp_props;
1131  WM_toolsystem_ref_properties_init_for_keymap(tref, &temp_props, &op_props, ot);
1132  SWAP(PointerRNA, temp_props, op_props);
1133  WM_operator_properties_free(&temp_props);
1134  }
1135 
1136  RNA_float_set_array(&op_props, "rotation", rotation);
1137  RNA_float_set_array(&op_props, "location", location);
1138  RNA_float_set_array(&op_props, "scale", scale);
1139 
1140  /* Always use the defaults here since desired bounds have been set interactively, it does
1141  * not make sense to use a different values from a previous command. */
1143  RNA_float_set(&op_props, "size", 2.0f);
1144  }
1145  if (ELEM(ipd->primitive_type,
1149  RNA_float_set(&op_props, "radius", 1.0f);
1150  }
1151  if (ELEM(
1153  RNA_float_set(&op_props, "depth", 2.0f);
1154  }
1156  RNA_float_set(&op_props, "radius1", 1.0f);
1157  RNA_float_set(&op_props, "radius2", 0.0f);
1158  }
1159 
1161  WM_operator_properties_free(&op_props);
1162  }
1163  else {
1164  BLI_assert(0);
1165  }
1166 
1168  return OPERATOR_FINISHED;
1169  }
1170  }
1171  }
1172  else {
1173  BLI_assert(0);
1174  }
1175 
1176  if (do_cursor_update) {
1177  float mval_fl[2];
1178  WM_event_drag_start_mval_fl(event, region, mval_fl);
1179 
1180  /* Calculate the snap location on mouse-move or when toggling snap. */
1181  ipd->is_snap_found = false;
1182  if (ipd->use_snap) {
1184  C, event, ipd->snap_co, NULL, NULL, NULL);
1185  }
1186 
1187  if (ipd->step_index == STEP_BASE) {
1188  if (ipd->is_snap_found) {
1190  ipd->step[STEP_BASE].co_dst, ipd->step[STEP_BASE].plane, ipd->snap_co);
1191  }
1192  else {
1194  region,
1195  ipd->step[STEP_BASE].plane,
1196  mval_fl,
1198  ipd->step[STEP_BASE].co_dst)) {
1199  /* pass */
1200  }
1201 
1202  if (ipd->use_snap && (ipd->snap_to == PLACE_SNAP_TO_DEFAULT)) {
1204  ipd->scene, ipd->v3d, ipd->region, ipd->co_src, ipd->step[STEP_BASE].co_dst)) {
1205  }
1206  }
1207  }
1208  }
1209  else if (ipd->step_index == STEP_DEPTH) {
1210  if (ipd->is_snap_found) {
1212  ipd->step[STEP_DEPTH].co_dst, ipd->step[STEP_DEPTH].plane, ipd->snap_co);
1213  }
1214  else {
1216  region,
1217  ipd->step[STEP_DEPTH].plane,
1218  mval_fl,
1220  ipd->step[STEP_DEPTH].co_dst)) {
1221  /* pass */
1222  }
1223 
1224  if (ipd->use_snap && (ipd->snap_to == PLACE_SNAP_TO_DEFAULT)) {
1226  ipd->scene, ipd->v3d, ipd->region, ipd->co_src, ipd->step[STEP_DEPTH].co_dst)) {
1227  }
1228  }
1229  }
1230 
1231  /* Correct the point so it's aligned with the 'ipd->step[0].co_dst'. */
1232  float close[3], delta[3];
1234  close, ipd->step[STEP_BASE].plane, ipd->step[STEP_DEPTH].co_dst);
1235  sub_v3_v3v3(delta, close, ipd->step[STEP_BASE].co_dst);
1236  sub_v3_v3(ipd->step[STEP_DEPTH].co_dst, delta);
1237  }
1238  do_redraw = true;
1239  }
1240 
1241  if (do_redraw) {
1243  }
1244 
1245  return OPERATOR_RUNNING_MODAL;
1246 }
1247 
1249 {
1250  const enum eContextObjectMode mode = CTX_data_mode_enum(C);
1251  return ELEM(mode, CTX_MODE_OBJECT, CTX_MODE_EDIT_MESH);
1252 }
1253 
1255  struct PropertyRNA *UNUSED(prop))
1256 {
1258  return snap_state->plane_axis;
1259 }
1260 
1262  struct PropertyRNA *UNUSED(prop),
1263  int value)
1264 {
1266  snap_state->plane_axis = (short)value;
1268 }
1269 
1271  struct PropertyRNA *UNUSED(prop))
1272 {
1274  return snap_state->plane_depth;
1275 }
1276 
1278  struct PropertyRNA *UNUSED(prop),
1279  int value)
1280 {
1282  snap_state->plane_depth = value;
1284 }
1285 
1287  struct PropertyRNA *UNUSED(prop))
1288 {
1290  return snap_state->plane_orient;
1291 }
1292 
1294  struct PropertyRNA *UNUSED(prop),
1295  int value)
1296 {
1298  snap_state->plane_orient = value;
1300 }
1301 
1303  struct PropertyRNA *UNUSED(prop))
1304 {
1307  return PLACE_SNAP_TO_DEFAULT;
1308  }
1309 
1310  /* Make sure you keep a consistent #snap_mode. */
1312  return PLACE_SNAP_TO_GEOMETRY;
1313 }
1314 
1316  struct PropertyRNA *UNUSED(prop),
1317  int value)
1318 {
1319  eSnapMode snap_mode = SCE_SNAP_MODE_NONE; /* #toolsettings->snap_mode. */
1320  const enum ePlace_SnapTo snap_to = value;
1322  snap_mode = SCE_SNAP_MODE_GEOM;
1323  }
1324 
1326  snap_state->snap_elem_force = snap_mode;
1328 }
1329 
1331  struct PropertyRNA *UNUSED(prop))
1332 {
1335 }
1336 
1338  struct PropertyRNA *UNUSED(prop),
1339  bool value)
1340 {
1344 }
1345 
1347 {
1348  /* identifiers */
1349  ot->name = "Add Primitive Object";
1350  ot->description = "Interactively add an object";
1351  ot->idname = "VIEW3D_OT_interactive_add";
1352 
1353  /* api callbacks */
1358 
1359  /* NOTE: let the operator we call handle undo and registering itself. */
1360  /* flags */
1361  ot->flag = 0;
1362 
1363  /* properties */
1364  PropertyRNA *prop;
1365 
1366  /* WORKAROUND: properties with `_funcs_runtime` should not be saved in keymaps.
1367  * So reassign the #PROP_IDPROPERTY flag to trick the property as not being set.
1368  * (See #RNA_property_is_set). */
1371 
1372  /* Normally not accessed directly, leave unset and check the active tool. */
1373  static const EnumPropertyItem primitive_type[] = {
1374  {PLACE_PRIMITIVE_TYPE_CUBE, "CUBE", 0, "Cube", ""},
1375  {PLACE_PRIMITIVE_TYPE_CYLINDER, "CYLINDER", 0, "Cylinder", ""},
1376  {PLACE_PRIMITIVE_TYPE_CONE, "CONE", 0, "Cone", ""},
1377  {PLACE_PRIMITIVE_TYPE_SPHERE_UV, "SPHERE_UV", 0, "UV Sphere", ""},
1378  {PLACE_PRIMITIVE_TYPE_SPHERE_ICO, "SPHERE_ICO", 0, "ICO Sphere", ""},
1379  {0, NULL, 0, NULL, NULL},
1380  };
1381 
1382  prop = RNA_def_property(ot->srna, "primitive_type", PROP_ENUM, PROP_NONE);
1383  RNA_def_property_ui_text(prop, "Primitive", "");
1386 
1387  prop = RNA_def_property(ot->srna, "plane_axis", PROP_ENUM, PROP_NONE);
1388  RNA_def_property_ui_text(prop, "Plane Axis", "The axis used for placing the base region");
1393  RNA_def_property_flag(prop, unsalvageable);
1394 
1395  prop = RNA_def_boolean(ot->srna,
1396  "plane_axis_auto",
1397  false,
1398  "Auto Axis",
1399  "Select the closest axis when placing objects "
1400  "(surface overrides)");
1403  RNA_def_property_flag(prop, unsalvageable);
1404 
1405  static const EnumPropertyItem plane_depth_items[] = {
1407  "SURFACE",
1408  0,
1409  "Surface",
1410  "Start placing on the surface, using the 3D cursor position as a fallback"},
1412  "CURSOR_PLANE",
1413  0,
1414  "Cursor Plane",
1415  "Start placement using a point projected onto the orientation axis "
1416  "at the 3D cursor position"},
1418  "CURSOR_VIEW",
1419  0,
1420  "Cursor View",
1421  "Start placement using a point projected onto the view plane at the 3D cursor position"},
1422  {0, NULL, 0, NULL, NULL},
1423  };
1424  prop = RNA_def_property(ot->srna, "plane_depth", PROP_ENUM, PROP_NONE);
1425  RNA_def_property_ui_text(prop, "Position", "The initial depth used when placing the cursor");
1427  RNA_def_property_enum_items(prop, plane_depth_items);
1430  RNA_def_property_flag(prop, unsalvageable);
1431 
1432  static const EnumPropertyItem plane_orientation_items[] = {
1434  "SURFACE",
1435  ICON_SNAP_NORMAL,
1436  "Surface",
1437  "Use the surface normal (using the transform orientation as a fallback)"},
1439  "DEFAULT",
1440  ICON_ORIENTATION_GLOBAL,
1441  "Default",
1442  "Use the current transform orientation"},
1443  {0, NULL, 0, NULL, NULL},
1444  };
1445  prop = RNA_def_property(ot->srna, "plane_orientation", PROP_ENUM, PROP_NONE);
1446  RNA_def_property_ui_text(prop, "Orientation", "The initial depth used when placing the cursor");
1448  RNA_def_property_enum_items(prop, plane_orientation_items);
1451  RNA_def_property_flag(prop, unsalvageable);
1452 
1453  static const EnumPropertyItem snap_to_items[] = {
1454  {PLACE_SNAP_TO_GEOMETRY, "GEOMETRY", 0, "Geometry", "Snap to all geometry"},
1455  {PLACE_SNAP_TO_DEFAULT, "DEFAULT", 0, "Default", "Use the current snap settings"},
1456  {0, NULL, 0, NULL, NULL},
1457  };
1458  prop = RNA_def_property(ot->srna, "snap_target", PROP_ENUM, PROP_NONE);
1459  RNA_def_property_ui_text(prop, "Snap to", "The target to use while snapping");
1461  RNA_def_property_enum_items(prop, snap_to_items);
1464  RNA_def_property_flag(prop, unsalvageable);
1465 
1466  { /* Plane Origin. */
1467  static const EnumPropertyItem items[] = {
1468  {PLACE_ORIGIN_BASE, "EDGE", 0, "Edge", "Start placing the edge position"},
1469  {PLACE_ORIGIN_CENTER, "CENTER", 0, "Center", "Start placing the center position"},
1470  {0, NULL, 0, NULL, NULL},
1471  };
1472  const char *identifiers[2] = {"plane_origin_base", "plane_origin_depth"};
1473  for (int i = 0; i < 2; i++) {
1474  prop = RNA_def_property(ot->srna, identifiers[i], PROP_ENUM, PROP_NONE);
1475  RNA_def_property_ui_text(prop, "Origin", "The initial position for placement");
1477  RNA_def_property_enum_items(prop, items);
1479  }
1480  }
1481 
1482  { /* Plane Aspect. */
1483  static const EnumPropertyItem items[] = {
1484  {PLACE_ASPECT_FREE, "FREE", 0, "Free", "Use an unconstrained aspect"},
1485  {PLACE_ASPECT_FIXED, "FIXED", 0, "Fixed", "Use a fixed 1:1 aspect"},
1486  {0, NULL, 0, NULL, NULL},
1487  };
1488  const char *identifiers[2] = {"plane_aspect_base", "plane_aspect_depth"};
1489  for (int i = 0; i < 2; i++) {
1490  prop = RNA_def_property(ot->srna, identifiers[i], PROP_ENUM, PROP_NONE);
1491  RNA_def_property_ui_text(prop, "Aspect", "The initial aspect setting");
1493  RNA_def_property_enum_items(prop, items);
1495  }
1496  }
1497 
1498  /* When not accessed via a tool. */
1499  prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
1501 }
1502 
1505 /* -------------------------------------------------------------------- */
1512 static void preview_plane_free_fn(void *customdata)
1513 {
1514  V3DSnapCursorState *snap_state = customdata;
1516 }
1517 
1519 {
1521  if (snap_state) {
1522  snap_state->gzgrp_type = gzgroup->type;
1523  snap_state->draw_plane = true;
1524 
1525  gzgroup->customdata = snap_state;
1527  }
1528 }
1529 
1531 {
1532  gzgt->name = "Placement Widget";
1534 
1536 
1539 
1542 }
1543 
typedef float(TangentPoint)[2]
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
eContextObjectMode
Definition: BKE_context.h:103
@ CTX_MODE_OBJECT
Definition: BKE_context.h:118
@ CTX_MODE_EDIT_MESH
Definition: BKE_context.h:104
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
enum eContextObjectMode CTX_data_mode_enum(const bContext *C)
Definition: context.c:1228
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define ATTR_FALLTHROUGH
MINLINE float max_ff(float a, float b)
#define M_PI
Definition: BLI_math_base.h:20
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition: math_geom.c:209
void closest_to_plane_normalized_v3(float r_close[3], const float plane[4], const float pt[3])
Definition: math_geom.c:408
float dist_signed_to_plane_v3(const float p[3], const float plane[4])
Definition: math_geom.c:461
void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const float v3[2], const float v4[2], const float co[2], float w[4])
Definition: math_geom.c:3769
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:926
void copy_m3_m3(float m1[3][3], const float m2[3][3])
Definition: math_matrix.c:71
bool invert_m3_m3(float R[3][3], const float A[3][3])
Definition: math_matrix.c:1180
void mat3_to_eul(float eul[3], const float mat[3][3])
void mid_v3_v3v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_vector.c:263
MINLINE bool compare_v3v3(const float a[3], const float b[3], float limit) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
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 bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3_length(float r[3], float unit_scale)
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:237
MINLINE void swap_v3_v3(float a[3], float b[3])
MINLINE void zero_v3(float r[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNPACK4(a)
#define ARRAY_SIZE(arr)
#define UNUSED_VARS(...)
#define SWAP(type, a, b)
#define UNUSED(x)
#define UNLIKELY(x)
#define ELEM(...)
#define STREQ(a, b)
@ SCE_SNAP
@ SCE_SNAP_ABS_GRID
eSnapMode
@ SCE_SNAP_MODE_INCREMENT
@ SCE_SNAP_MODE_NONE
@ SCE_SNAP_MODE_GEOM
@ RGN_TYPE_WINDOW
@ SPACE_VIEW3D
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
bool ED_gizmo_poll_or_unlink_delayed_from_tool(const struct bContext *C, struct wmGizmoGroupType *gzgt)
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:655
#define REGION_DRAW_POST_VIEW
Definition: ED_space_api.h:62
void * ED_region_draw_cb_activate(struct ARegionType *art, void(*draw)(const struct bContext *, struct ARegion *, void *), void *customdata, int type)
Definition: spacetypes.c:226
bool ED_region_draw_cb_exit(struct ARegionType *art, void *handle)
Definition: spacetypes.c:241
@ V3D_PLACE_ORIENT_DEFAULT
Definition: ED_view3d.h:299
@ V3D_PLACE_ORIENT_SURFACE
Definition: ED_view3d.h:298
bool ED_view3d_win_to_3d_on_plane(const struct ARegion *region, const float plane[4], const float mval[2], bool do_clip, float r_out[3])
#define XRAY_ENABLED(v3d)
Definition: ED_view3d.h:1299
void ED_view3d_cursor_snap_state_default_set(V3DSnapCursorState *state)
void ED_view3d_cursor_snap_prevpoint_set(V3DSnapCursorState *state, const float prev_point[3])
V3DSnapCursorData * ED_view3d_cursor_snap_data_get(void)
@ V3D_SNAPCURSOR_TOGGLE_ALWAYS_TRUE
Definition: ED_view3d.h:284
void ED_view3d_cursor_snap_data_update(V3DSnapCursorState *state, const struct bContext *C, int x, int y)
bool ED_view3d_win_to_3d_on_plane_with_fallback(const struct ARegion *region, const float plane[4], const float mval[2], bool do_clip, const float plane_fallback[4], float r_out[3])
float ED_view3d_grid_view_scale(struct Scene *scene, struct View3D *v3d, struct ARegion *region, const char **r_grid_unit)
Definition: view3d_draw.c:901
void ED_view3d_cursor_snap_deactive(V3DSnapCursorState *state)
V3DSnapCursorState * ED_view3d_cursor_snap_active(void)
V3DSnapCursorState * ED_view3d_cursor_snap_state_get(void)
@ V3D_PLACE_DEPTH_CURSOR_VIEW
Definition: ED_view3d.h:294
@ V3D_PLACE_DEPTH_CURSOR_PLANE
Definition: ED_view3d.h:293
@ V3D_PLACE_DEPTH_SURFACE
Definition: ED_view3d.h:292
NSNotificationCenter * center
GPUBatch
Definition: GPU_batch.h:78
#define GPU_batch_uniform_1f(batch, name, x)
Definition: GPU_batch.h:144
void GPU_batch_discard(GPUBatch *)
Definition: gpu_batch.cc:109
void GPU_batch_program_set_builtin(GPUBatch *batch, eGPUBuiltinShader shader_id)
Definition: gpu_batch.cc:287
#define GPU_batch_uniform_2fv(batch, name, val)
Definition: GPU_batch.h:150
GPUBatch * GPU_batch_create_ex(GPUPrimType prim, GPUVertBuf *vert, GPUIndexBuf *elem, eGPUBatchFlag owns_flag)
Definition: gpu_batch.cc:43
void GPU_batch_draw(GPUBatch *batch)
Definition: gpu_batch.cc:223
#define GPU_batch_uniform_4fv(batch, name, val)
Definition: GPU_batch.h:152
@ GPU_BATCH_OWNS_VBO
Definition: GPU_batch.h:30
GPUVertFormat * immVertexFormat(void)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
@ GPU_PRIM_LINE_LOOP
Definition: GPU_primitive.h:23
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:20
@ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR
Definition: GPU_shader.h:253
@ GPU_BLEND_NONE
Definition: GPU_state.h:60
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:62
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:39
eGPUDepthTest
Definition: GPU_state.h:82
@ GPU_DEPTH_LESS_EQUAL
Definition: GPU_state.h:86
@ GPU_DEPTH_NONE
Definition: GPU_state.h:83
eGPUDepthTest GPU_depth_test_get(void)
Definition: gpu_state.cc:236
void GPU_depth_test(eGPUDepthTest test)
Definition: gpu_state.cc:65
void GPU_viewport_size_get_f(float coords[4])
Definition: gpu_state.cc:259
#define GPU_vertbuf_create_with_format(format)
struct GPUVertBuf GPUVertBuf
void GPU_vertbuf_data_alloc(GPUVertBuf *, uint v_len)
void GPU_vertbuf_attr_set(GPUVertBuf *, uint a_idx, uint v_idx, const void *data)
@ 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 Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
@ PROP_ENUM
Definition: RNA_types.h:63
PropertyFlag
Definition: RNA_types.h:183
@ PROP_PTR_NO_OWNERSHIP
Definition: RNA_types.h:257
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
@ PROP_HIDDEN
Definition: RNA_types.h:216
@ PROP_IDPROPERTY
Definition: RNA_types.h:288
@ PROP_NONE
Definition: RNA_types.h:126
#define C
Definition: RandGen.cpp:25
void UI_GetThemeColor3fv(int colorid, float col[3])
Definition: resources.c:1165
@ TH_GIZMO_PRIMARY
Definition: UI_resources.h:305
@ WM_GIZMOGROUPTYPE_SCALE
@ WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL
@ WM_GIZMOGROUPTYPE_3D
@ KM_PRESS
Definition: WM_types.h:267
@ KM_CLICK_DRAG
Definition: WM_types.h:275
@ KM_RELEASE
Definition: WM_types.h:268
@ WM_OP_EXEC_DEFAULT
Definition: WM_types.h:208
ATTR_WARN_UNUSED_RESULT const BMVert * v2
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition: btDbvt.cpp:299
unsigned int U
Definition: btGjkEpa3.h:78
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
#define sinf(x)
Definition: cuda/compat.h:102
#define cosf(x)
Definition: cuda/compat.h:101
Scene scene
uint pos
GPUBatch * quad
struct @653::@655 batch
format
Definition: logImageCore.h:38
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
#define copysignf(x, y)
Definition: metal/compat.h:220
#define fabsf(x)
Definition: metal/compat.h:219
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:5271
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
Definition: rna_access.c:4968
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3402
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
Definition: rna_access.c:4992
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
void RNA_def_property_enum_default(PropertyRNA *prop, int value)
Definition: rna_define.c:2106
void RNA_def_property_ui_text(PropertyRNA *prop, const char *name, const char *description)
Definition: rna_define.c:1645
void RNA_def_property_enum_funcs_runtime(PropertyRNA *prop, EnumPropertyGetFunc getfunc, EnumPropertySetFunc setfunc, EnumPropertyItemFunc itemfunc)
Definition: rna_define.c:3258
void RNA_def_property_enum_items(PropertyRNA *prop, const EnumPropertyItem *item)
Definition: rna_define.c:1872
PropertyRNA * RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier, int type, int subtype)
Definition: rna_define.c:1257
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
void RNA_def_property_boolean_funcs_runtime(PropertyRNA *prop, BooleanPropertyGetFunc getfunc, BooleanPropertySetFunc setfunc)
Definition: rna_define.c:2982
const EnumPropertyItem rna_enum_axis_xyz_items[]
Definition: rna_modifier.c:615
void * regiondata
struct ARegionType * type
struct InteractivePlaceData::@586 step[2]
enum ePlace_PrimType primitive_type
float degenerate_diagonal_display[3]
enum InteractivePlaceData::@587 step_index
enum ePlace_SnapTo snap_to
V3DSnapCursorState * snap_state
float viewinv[4][4]
struct ToolSettings * toolsettings
struct bToolRef * tool
ScrArea_Runtime runtime
eSnapMode snap_elem
Definition: ED_view3d.h:303
float plane_omat[3][3]
Definition: ED_view3d.h:308
eV3DSnapCursor flag
Definition: ED_view3d.h:317
eV3DPlaceOrient plane_orient
Definition: ED_view3d.h:319
struct wmGizmoGroupType * gzgrp_type
Definition: ED_view3d.h:323
eV3DPlaceDepth plane_depth
Definition: ED_view3d.h:318
eSnapMode snap_elem_force
Definition: ED_view3d.h:326
bool use_plane_axis_auto
Definition: ED_view3d.h:328
char idname[64]
short val
Definition: WM_types.h:680
short type
Definition: WM_types.h:678
wmGizmoGroupFnInit setup
const char * idname
eWM_GizmoFlagGroupTypeFlag flag
wmGizmoGroupFnPoll poll
struct wmGizmoMapType_Params gzmap_params
const char * name
struct wmGizmoGroupType * type
void(* customdata_free)(void *)
const void * modal_items
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
struct PointerRNA * ptr
static int idp_rna_plane_depth_get_fn(struct PointerRNA *UNUSED(ptr), struct PropertyRNA *UNUSED(prop))
static int dot_v3_array_find_max_index(const float dirs[][3], const int dirs_len, const float dir_test[3], bool is_signed)
ePlace_SnapTo
@ PLACE_SNAP_TO_DEFAULT
@ PLACE_SNAP_TO_GEOMETRY
static void draw_line_pairs(const float coords_a[][3], float coords_b[][3], int coords_len, const float color[4])
ePlace_PrimType
@ PLACE_PRIMITIVE_TYPE_SPHERE_ICO
@ PLACE_PRIMITIVE_TYPE_CONE
@ PLACE_PRIMITIVE_TYPE_CUBE
@ PLACE_PRIMITIVE_TYPE_SPHERE_UV
@ PLACE_PRIMITIVE_TYPE_CYLINDER
static void draw_primitive_view(const struct bContext *C, ARegion *UNUSED(region), void *arg)
static const char * view3d_gzgt_placement_id
static bool view3d_win_to_3d_on_plane_maybe_fallback(const ARegion *region, const float plane[4], const float mval[2], const float *plane_fallback, float r_out[3])
static void draw_line_loop(const float coords[][3], int coords_len, const float color[4])
static void idp_rna_snap_target_set_fn(struct PointerRNA *UNUSED(ptr), struct PropertyRNA *UNUSED(prop), int value)
static void idp_rna_plane_axis_set_fn(struct PointerRNA *UNUSED(ptr), struct PropertyRNA *UNUSED(prop), int value)
static void draw_line_bounds(const BoundBox *bounds, const float color[4])
static int idp_rna_snap_target_get_fn(struct PointerRNA *UNUSED(ptr), struct PropertyRNA *UNUSED(prop))
static const float eps_view_align
static void view3d_interactive_add_cancel(bContext *C, wmOperator *op)
@ PLACE_MODAL_FIXED_ASPECT_OFF
@ PLACE_MODAL_FIXED_ASPECT_ON
@ PLACE_MODAL_SNAP_OFF
@ PLACE_MODAL_SNAP_ON
@ PLACE_MODAL_PIVOT_CENTER_OFF
@ PLACE_MODAL_PIVOT_CENTER_ON
static void WIDGETGROUP_placement_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
static void idp_rna_use_plane_axis_auto_set_fn(struct PointerRNA *UNUSED(ptr), struct PropertyRNA *UNUSED(prop), bool value)
static void idp_rna_plane_depth_set_fn(struct PointerRNA *UNUSED(ptr), struct PropertyRNA *UNUSED(prop), int value)
static bool idp_snap_calc_incremental(Scene *scene, View3D *v3d, ARegion *region, const float co_relative[3], float co[3])
static bool calc_bbox(struct InteractivePlaceData *ipd, BoundBox *bounds)
static void draw_circle_in_quad(const float v1[3], const float v2[3], const float v3[3], const float v4[3], const int resolution, const float color[4])
static bool view3d_interactive_add_poll(bContext *C)
static UNUSED_FUNCTION_WITH_RETURN_TYPE(wmGizmoGroup *, idp_gizmogroup_from_region)
static void preview_plane_free_fn(void *customdata)
static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEvent *event)
void VIEW3D_GGT_placement(wmGizmoGroupType *gzgt)
static bool view3d_interactive_add_calc_snap(bContext *UNUSED(C), const wmEvent *UNUSED(event), float r_co_src[3], float r_matrix_orient[3][3], bool *r_is_enabled, bool *r_is_snap_invert)
ePlace_Origin
@ PLACE_ORIGIN_BASE
@ PLACE_ORIGIN_CENTER
static int view3d_interactive_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void view3d_interactive_add_exit(bContext *C, wmOperator *op)
static int idp_rna_plane_axis_get_fn(struct PointerRNA *UNUSED(ptr), struct PropertyRNA *UNUSED(prop))
static int idp_rna_plane_orient_get_fn(struct PointerRNA *UNUSED(ptr), struct PropertyRNA *UNUSED(prop))
static void draw_primitive_view_impl(const struct bContext *C, struct InteractivePlaceData *ipd, const float color[4], int flatten_axis)
void VIEW3D_OT_interactive_add(struct wmOperatorType *ot)
static void idp_rna_plane_orient_set_fn(struct PointerRNA *UNUSED(ptr), struct PropertyRNA *UNUSED(prop), int value)
static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEvent *event)
static bool idp_rna_use_plane_axis_auto_get_fn(struct PointerRNA *UNUSED(ptr), struct PropertyRNA *UNUSED(prop))
void viewplace_modal_keymap(wmKeyConfig *keyconf)
ePlace_Aspect
@ PLACE_ASPECT_FIXED
@ PLACE_ASPECT_FREE
void WM_event_drag_start_mval_fl(const wmEvent *event, const ARegion *region, float r_mval[2])
void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2])
int WM_userdef_event_type_from_keymap_type(int kmitype)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
int WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
@ RIGHTMOUSE
@ EVT_MODAL_MAP
@ MOUSEMOVE
@ LEFTMOUSE
@ EVT_ESCKEY
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479
bool WM_gizmo_group_type_ensure(const char *idname)
wmGizmoGroup * WM_gizmomap_group_find(struct wmGizmoMap *gzmap, const char *idname)
Definition: wm_gizmo_map.c:202
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition: wm_keymap.c:914
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
Definition: wm_keymap.c:985
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition: wm_keymap.c:888
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
Definition: wm_operators.c:661
void WM_operator_properties_free(PointerRNA *ptr)
Definition: wm_operators.c:783
void WM_toolsystem_ref_properties_init_for_keymap(bToolRef *tref, PointerRNA *dst_ptr, PointerRNA *src_ptr, wmOperatorType *ot)