Blender  V2.93
view3d_placement.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
26 #include "MEM_guardedalloc.h"
27 
28 #include "DNA_collection_types.h"
29 #include "DNA_object_types.h"
30 #include "DNA_scene_types.h"
31 #include "DNA_vfont_types.h"
32 
33 #include "BLI_math.h"
34 #include "BLI_utildefines.h"
35 
36 #include "BKE_context.h"
37 #include "BKE_global.h"
38 #include "BKE_main.h"
39 
40 #include "RNA_access.h"
41 #include "RNA_define.h"
42 #include "RNA_enum_types.h"
43 
44 #include "WM_api.h"
45 #include "WM_toolsystem.h"
46 #include "WM_types.h"
47 
48 #include "ED_gizmo_library.h"
49 #include "ED_gizmo_utils.h"
50 #include "ED_screen.h"
51 #include "ED_space_api.h"
52 #include "ED_transform.h"
54 #include "ED_view3d.h"
55 
56 #include "UI_resources.h"
57 
58 #include "GPU_batch.h"
59 #include "GPU_immediate.h"
60 #include "GPU_matrix.h"
61 #include "GPU_state.h"
62 
63 #include "view3d_intern.h"
64 
65 static const char *view3d_gzgt_placement_id = "VIEW3D_GGT_placement";
66 
67 static void preview_plane_cursor_setup(wmGizmoGroup *gzgroup);
68 static void preview_plane_cursor_visible_set(wmGizmoGroup *gzgroup, bool do_draw);
69 
75 static const float eps_view_align = 1e-2f;
76 
77 /* -------------------------------------------------------------------- */
87 };
88 
92 };
93 
97 };
98 
103 };
104 
108 };
109 
113 };
114 
116  /* Window manager variables (set these even when waiting for input). */
121 
124 
125  float co_src[3];
126 
128  struct {
140  float plane[4];
141  float co_dst[3];
142 
167 
172 
173  } step[2];
174 
176  float view_plane[4];
177 
178  float matrix_orient[3][3];
180 
182  float snap_co[3];
183 
185  enum {
189 
191 
193  bool use_tool;
194 
197 
200 
203 
204  enum ePlace_SnapTo snap_to;
205 };
206 
209 /* -------------------------------------------------------------------- */
217  const float plane[4],
218  const float mval[2],
219  const float *plane_fallback,
220  float r_out[3])
221 {
222  RegionView3D *rv3d = region->regiondata;
223  bool do_clip = rv3d->is_persp;
224  if (plane_fallback != NULL) {
226  region, plane, mval, do_clip, plane_fallback, r_out);
227  }
228  return ED_view3d_win_to_3d_on_plane(region, plane, mval, do_clip, r_out);
229 }
230 
234 static int dot_v3_array_find_max_index(const float dirs[][3],
235  const int dirs_len,
236  const float dir_test[3],
237  bool is_signed)
238 {
239  int index_found = -1;
240  float dot_best = -1.0f;
241  for (int i = 0; i < dirs_len; i++) {
242  float dot_test = dot_v3v3(dirs[i], dir_test);
243  if (is_signed == false) {
244  dot_test = fabsf(dot_test);
245  }
246  if ((index_found == -1) || (dot_test > dot_best)) {
247  dot_best = dot_test;
248  index_found = i;
249  }
250  }
251  return index_found;
252 }
253 
257 static bool mat3_align_axis_to_v3(float mat[3][3], const int axis_align, const float v[3])
258 {
259  float dot_best = -1.0f;
260  int axis_found = axis_align;
261  for (int i = 0; i < 3; i++) {
262  const float dot_test = fabsf(dot_v3v3(mat[i], v));
263  if (dot_test > dot_best) {
264  dot_best = dot_test;
265  axis_found = i;
266  }
267  }
268 
269  if (axis_align != axis_found) {
270  float tmat[3][3];
271  copy_m3_m3(tmat, mat);
272  const int offset = mod_i(axis_found - axis_align, 3);
273  for (int i = 0; i < 3; i++) {
274  copy_v3_v3(mat[i], tmat[(i + offset) % 3]);
275  }
276  return true;
277  }
278  return false;
279 }
280 
281 /* On-screen snap distance. */
282 #define MVAL_MAX_PX_DIST 12.0f
283 
284 static bool idp_snap_point_from_gizmo_ex(wmGizmo *gz, const char *prop_id, float r_location[3])
285 {
286  if (gz->state & WM_GIZMO_STATE_HIGHLIGHT) {
287  PropertyRNA *prop_location = RNA_struct_find_property(gz->ptr, prop_id);
288  RNA_property_float_get_array(gz->ptr, prop_location, r_location);
289  return true;
290  }
291  return false;
292 }
293 
294 static bool idp_snap_point_from_gizmo(wmGizmo *gz, float r_location[3])
295 {
296  return idp_snap_point_from_gizmo_ex(gz, "location", r_location);
297 }
298 
299 static bool idp_snap_normal_from_gizmo(wmGizmo *gz, float r_normal[3])
300 {
301  return idp_snap_point_from_gizmo_ex(gz, "normal", r_normal);
302 }
303 
308  struct Depsgraph *depsgraph,
309  const float mval_fl[2],
310  const float mat_fallback[3][3],
311  const float normal_fallback[3],
312  float r_mat[3][3])
313 {
314  bool success = false;
315  float normal[3] = {0.0f};
316  float co_dummy[3];
317  /* We could use the index to get the orientation from the face. */
318  Object *ob_snap;
319  float obmat[4][4];
320 
322  depsgraph,
324  &(const struct SnapObjectParams){
325  .snap_select = SNAP_ALL,
326  .use_object_edit_cage = true,
327  },
328  mval_fl,
329  NULL,
330  NULL,
331  co_dummy,
332  normal,
333  NULL,
334  &ob_snap,
335  obmat)) {
336  /* pass */
337  }
338  else if (normal_fallback != NULL) {
339  copy_m4_m3(obmat, mat_fallback);
340  copy_v3_v3(normal, normal_fallback);
341  }
342 
343  if (!is_zero_v3(normal)) {
344  float mat[3][3];
345  copy_m3_m4(mat, obmat);
346  normalize_m3(mat);
347 
348  float dot_best = fabsf(dot_v3v3(mat[0], normal));
349  int i_best = 0;
350  for (int i = 1; i < 3; i++) {
351  float dot_test = fabsf(dot_v3v3(mat[i], normal));
352  if (dot_test > dot_best) {
353  i_best = i;
354  dot_best = dot_test;
355  }
356  }
357  if (dot_v3v3(mat[i_best], normal) < 0.0f) {
358  negate_v3(mat[(i_best + 1) % 3]);
359  negate_v3(mat[(i_best + 2) % 3]);
360  }
361  copy_v3_v3(mat[i_best], normal);
362  orthogonalize_m3(mat, i_best);
363  normalize_m3(mat);
364 
365  copy_v3_v3(r_mat[0], mat[(i_best + 1) % 3]);
366  copy_v3_v3(r_mat[1], mat[(i_best + 2) % 3]);
367  copy_v3_v3(r_mat[2], mat[i_best]);
368  success = true;
369  }
370 
371  return success;
372 }
373 
375 {
376  wmGizmoMap *gzmap = region->gizmo_map;
377  return gzmap ? WM_gizmomap_group_find(gzmap, view3d_gzgt_placement_id) : NULL;
378 }
379 
386  Scene *scene, View3D *v3d, ARegion *region, const float co_relative[3], float co[3])
387 {
389  return false;
390  }
391 
392  const float grid_size = ED_view3d_grid_view_scale(scene, v3d, region, NULL);
393  if (UNLIKELY(grid_size == 0.0f)) {
394  return false;
395  }
396 
398  co_relative = NULL;
399  }
400 
401  if (co_relative != NULL) {
402  sub_v3_v3(co, co_relative);
403  }
404  mul_v3_fl(co, 1.0f / grid_size);
405  co[0] = roundf(co[0]);
406  co[1] = roundf(co[1]);
407  co[2] = roundf(co[2]);
408  mul_v3_fl(co, grid_size);
409  if (co_relative != NULL) {
410  add_v3_v3(co, co_relative);
411  }
412 
413  return true;
414 }
415 
417  enum ePlace_SnapTo snap_to,
418  wmGizmo *gizmo)
419 {
420  const int snap_mode =
421  (snap_to == PLACE_SNAP_TO_GEOMETRY) ?
423  /* SCE_SNAP_MODE_VOLUME | SCE_SNAP_MODE_GRID | SCE_SNAP_MODE_INCREMENT | */
426 
427  RNA_enum_set(gizmo->ptr, "snap_elements_force", snap_mode);
428 }
429 
432 /* -------------------------------------------------------------------- */
436 static void draw_line_loop(const float coords[][3], int coords_len, const float color[4])
437 {
440 
442  GPU_vertbuf_data_alloc(vert, coords_len);
443 
444  for (int i = 0; i < coords_len; i++) {
445  GPU_vertbuf_attr_set(vert, pos, i, coords[i]);
446  }
447 
451 
452  GPU_batch_uniform_4fv(batch, "color", color);
453 
454  float viewport[4];
455  GPU_viewport_size_get_f(viewport);
456  GPU_batch_uniform_2fv(batch, "viewportSize", &viewport[2]);
457  GPU_batch_uniform_1f(batch, "lineWidth", U.pixelsize);
458 
460 
463 }
464 
465 static void draw_line_pairs(const float coords_a[][3],
466  float coords_b[][3],
467  int coords_len,
468  const float color[4])
469 {
472 
474  GPU_vertbuf_data_alloc(vert, coords_len * 2);
475 
476  for (int i = 0; i < coords_len; i++) {
477  GPU_vertbuf_attr_set(vert, pos, i * 2, coords_a[i]);
478  GPU_vertbuf_attr_set(vert, pos, (i * 2) + 1, coords_b[i]);
479  }
480 
484 
485  GPU_batch_uniform_4fv(batch, "color", color);
486 
487  float viewport[4];
488  GPU_viewport_size_get_f(viewport);
489  GPU_batch_uniform_2fv(batch, "viewportSize", &viewport[2]);
490  GPU_batch_uniform_1f(batch, "lineWidth", U.pixelsize);
491 
493 
496 }
497 
498 static void draw_line_bounds(const BoundBox *bounds, const float color[4])
499 {
502 
503  const int edges[12][2] = {
504  /* First side. */
505  {0, 1},
506  {1, 2},
507  {2, 3},
508  {3, 0},
509  /* Second side. */
510  {4, 5},
511  {5, 6},
512  {6, 7},
513  {7, 4},
514  /* Edges between. */
515  {0, 4},
516  {1, 5},
517  {2, 6},
518  {3, 7},
519  };
520 
522  GPU_vertbuf_data_alloc(vert, ARRAY_SIZE(edges) * 2);
523 
524  for (int i = 0, j = 0; i < ARRAY_SIZE(edges); i++) {
525  GPU_vertbuf_attr_set(vert, pos, j++, bounds->vec[edges[i][0]]);
526  GPU_vertbuf_attr_set(vert, pos, j++, bounds->vec[edges[i][1]]);
527  }
528 
532 
533  GPU_batch_uniform_4fv(batch, "color", color);
534 
535  float viewport[4];
536  GPU_viewport_size_get_f(viewport);
537  GPU_batch_uniform_2fv(batch, "viewportSize", &viewport[2]);
538  GPU_batch_uniform_1f(batch, "lineWidth", U.pixelsize);
539 
541 
544 }
545 
546 static bool calc_bbox(struct InteractivePlaceData *ipd, BoundBox *bounds)
547 {
548  memset(bounds, 0x0, sizeof(*bounds));
549 
550  if (compare_v3v3(ipd->co_src, ipd->step[0].co_dst, FLT_EPSILON)) {
551  return false;
552  }
553 
554  float matrix_orient_inv[3][3];
555  invert_m3_m3(matrix_orient_inv, ipd->matrix_orient);
556 
557  const int x_axis = (ipd->orient_axis + 1) % 3;
558  const int y_axis = (ipd->orient_axis + 2) % 3;
559 
560  float quad_base[4][3];
561  float quad_secondary[4][3];
562 
563  copy_v3_v3(quad_base[0], ipd->co_src);
564  copy_v3_v3(quad_base[2], ipd->step[0].co_dst);
565 
566  /* Only set when we have a fixed aspect. */
567  float fixed_aspect_dimension;
568 
569  /* *** Primary *** */
570 
571  {
572  float delta_local[3];
573  float delta_a[3];
574  float delta_b[3];
575 
576  sub_v3_v3v3(delta_local, ipd->step[0].co_dst, ipd->co_src);
577  mul_m3_v3(matrix_orient_inv, delta_local);
578 
579  copy_v3_v3(delta_a, delta_local);
580  copy_v3_v3(delta_b, delta_local);
581  delta_a[ipd->orient_axis] = 0.0f;
582  delta_b[ipd->orient_axis] = 0.0f;
583 
584  delta_a[x_axis] = 0.0f;
585  delta_b[y_axis] = 0.0f;
586 
587  /* Assign here in case secondary */
588  fixed_aspect_dimension = max_ff(fabsf(delta_a[y_axis]), fabsf(delta_b[x_axis]));
589 
590  if (ipd->step[0].is_fixed_aspect) {
591  delta_a[y_axis] = copysignf(fixed_aspect_dimension, delta_a[y_axis]);
592  delta_b[x_axis] = copysignf(fixed_aspect_dimension, delta_b[x_axis]);
593  }
594 
595  mul_m3_v3(ipd->matrix_orient, delta_a);
596  mul_m3_v3(ipd->matrix_orient, delta_b);
597 
598  if (ipd->step[0].is_fixed_aspect) {
599  /* Recalculate the destination point. */
600  copy_v3_v3(quad_base[2], ipd->co_src);
601  add_v3_v3(quad_base[2], delta_a);
602  add_v3_v3(quad_base[2], delta_b);
603  }
604 
605  add_v3_v3v3(quad_base[1], ipd->co_src, delta_a);
606  add_v3_v3v3(quad_base[3], ipd->co_src, delta_b);
607  }
608 
609  if (ipd->step[0].is_centered) {
610  /* Use a copy in case aspect was applied to the quad. */
611  float base_co_dst[3];
612  copy_v3_v3(base_co_dst, quad_base[2]);
613  for (int i = 0; i < ARRAY_SIZE(quad_base); i++) {
614  sub_v3_v3(quad_base[i], base_co_dst);
615  mul_v3_fl(quad_base[i], 2.0f);
616  add_v3_v3(quad_base[i], base_co_dst);
617  }
618  fixed_aspect_dimension *= 2.0f;
619  }
620 
621  /* *** Secondary *** */
622 
623  float delta_local[3];
624  if (ipd->step_index == STEP_DEPTH) {
625  sub_v3_v3v3(delta_local, ipd->step[1].co_dst, ipd->step[0].co_dst);
626  }
627  else {
628  zero_v3(delta_local);
629  }
630 
631  if (ipd->step[1].is_fixed_aspect) {
632  if (!is_zero_v3(delta_local)) {
633  normalize_v3_length(delta_local, fixed_aspect_dimension);
634  }
635  }
636 
637  if (ipd->step[1].is_centered) {
638  float temp_delta[3];
639  if (ipd->step[1].is_fixed_aspect) {
640  mul_v3_v3fl(temp_delta, delta_local, 0.5f);
641  }
642  else {
643  copy_v3_v3(temp_delta, delta_local);
644  mul_v3_fl(delta_local, 2.0f);
645  }
646 
647  for (int i = 0; i < ARRAY_SIZE(quad_base); i++) {
648  sub_v3_v3(quad_base[i], temp_delta);
649  }
650  }
651 
652  if ((ipd->step_index == STEP_DEPTH) &&
653  (compare_v3v3(ipd->step[0].co_dst, ipd->step[1].co_dst, FLT_EPSILON) == false)) {
654 
655  for (int i = 0; i < ARRAY_SIZE(quad_base); i++) {
656  add_v3_v3v3(quad_secondary[i], quad_base[i], delta_local);
657  }
658  }
659  else {
660  copy_v3_v3(quad_secondary[0], quad_base[0]);
661  copy_v3_v3(quad_secondary[1], quad_base[1]);
662  copy_v3_v3(quad_secondary[2], quad_base[2]);
663  copy_v3_v3(quad_secondary[3], quad_base[3]);
664  }
665 
666  for (int i = 0; i < 4; i++) {
667  copy_v3_v3(bounds->vec[i], quad_base[i]);
668  copy_v3_v3(bounds->vec[i + 4], quad_secondary[i]);
669  }
670 
671  return true;
672 }
673 
674 static void draw_circle_in_quad(const float v1[3],
675  const float v2[3],
676  const float v3[3],
677  const float v4[3],
678  const int resolution,
679  const float color[4])
680 {
681  /* This isn't so efficient. */
682  const float quad[4][2] = {
683  {-1, -1},
684  {+1, -1},
685  {+1, +1},
686  {-1, +1},
687  };
688 
689  float(*coords)[3] = MEM_mallocN(sizeof(float[3]) * (resolution + 1), __func__);
690  for (int i = 0; i <= resolution; i++) {
691  float theta = ((2.0f * M_PI) * ((float)i / (float)resolution)) + 0.01f;
692  float x = cosf(theta);
693  float y = sinf(theta);
694  const float pt[2] = {x, y};
695  float w[4];
697 
698  float *co = coords[i];
699  zero_v3(co);
700  madd_v3_v3fl(co, v1, w[0]);
701  madd_v3_v3fl(co, v2, w[1]);
702  madd_v3_v3fl(co, v3, w[2]);
703  madd_v3_v3fl(co, v4, w[3]);
704  }
705  draw_line_loop(coords, resolution + 1, color);
706  MEM_freeN(coords);
707 }
708 
711 /* -------------------------------------------------------------------- */
715 static void draw_primitive_view_impl(const struct bContext *C,
716  struct InteractivePlaceData *ipd,
717  const float color[4],
718  int flatten_axis)
719 {
720  UNUSED_VARS(C);
721 
723  calc_bbox(ipd, &bounds);
724 
725  /* Use cavalier projection, since it maps the scale usefully to the cursor. */
726  if (flatten_axis == STEP_BASE) {
727  /* Calculate the plane that would be defined by the side of the cube vertices
728  * if the plane had any volume. */
729 
730  float no[3];
731 
733  no, ipd->matrix_orient[ipd->orient_axis], ipd->matrix_orient[(ipd->orient_axis + 1) % 3]);
734 
735  RegionView3D *rv3d = ipd->region->regiondata;
736  copy_v3_v3(no, rv3d->viewinv[2]);
737  normalize_v3(no);
738 
739  float base_plane[4];
740 
741  plane_from_point_normal_v3(base_plane, bounds.vec[0], no);
742 
743  /* Offset all vertices even though we only need to offset the half of them.
744  * This is harmless as `dist` will be zero for the `base_plane` aligned side of the cube. */
745  for (int i = 0; i < ARRAY_SIZE(bounds.vec); i++) {
746  const float dist = dist_signed_to_plane_v3(bounds.vec[i], base_plane);
747  madd_v3_v3fl(bounds.vec[i], base_plane, -dist);
748  madd_v3_v3fl(bounds.vec[i], ipd->step[STEP_BASE].degenerate_diagonal_display, dist);
749  }
750  }
751 
752  if (flatten_axis == STEP_DEPTH) {
753  const float *base_plane = ipd->step[0].plane;
754  for (int i = 0; i < 4; i++) {
755  const float dist = dist_signed_to_plane_v3(bounds.vec[i + 4], base_plane);
756  madd_v3_v3fl(bounds.vec[i + 4], base_plane, -dist);
757  madd_v3_v3fl(bounds.vec[i + 4], ipd->step[STEP_DEPTH].degenerate_diagonal_display, dist);
758  }
759  }
760 
761  draw_line_bounds(&bounds, color);
762 
764  /* pass */
765  }
767  draw_circle_in_quad(UNPACK4(bounds.vec), 32, color);
768  draw_circle_in_quad(UNPACK4((&bounds.vec[4])), 32, color);
769  }
770  else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CONE) {
771  draw_circle_in_quad(UNPACK4(bounds.vec), 32, color);
772 
773  float center[3];
774  mid_v3_v3v3v3v3(center, UNPACK4((&bounds.vec[4])));
775 
776  float coords_a[4][3];
777  float coords_b[4][3];
778 
779  for (int i = 0; i < 4; i++) {
780  copy_v3_v3(coords_a[i], center);
781  mid_v3_v3v3(coords_b[i], bounds.vec[i], bounds.vec[(i + 1) % 4]);
782  }
783 
784  draw_line_pairs(coords_a, coords_b, 4, color);
785  }
786  else if (ELEM(ipd->primitive_type,
789  /* See bound-box diagram for reference. */
790 
791  /* Primary Side. */
792  float v01[3], v12[3], v23[3], v30[3];
793  mid_v3_v3v3(v01, bounds.vec[0], bounds.vec[1]);
794  mid_v3_v3v3(v12, bounds.vec[1], bounds.vec[2]);
795  mid_v3_v3v3(v23, bounds.vec[2], bounds.vec[3]);
796  mid_v3_v3v3(v30, bounds.vec[3], bounds.vec[0]);
797  /* Secondary Side. */
798  float v45[3], v56[3], v67[3], v74[3];
799  mid_v3_v3v3(v45, bounds.vec[4], bounds.vec[5]);
800  mid_v3_v3v3(v56, bounds.vec[5], bounds.vec[6]);
801  mid_v3_v3v3(v67, bounds.vec[6], bounds.vec[7]);
802  mid_v3_v3v3(v74, bounds.vec[7], bounds.vec[4]);
803  /* Edges between. */
804  float v04[3], v15[3], v26[3], v37[3];
805  mid_v3_v3v3(v04, bounds.vec[0], bounds.vec[4]);
806  mid_v3_v3v3(v15, bounds.vec[1], bounds.vec[5]);
807  mid_v3_v3v3(v26, bounds.vec[2], bounds.vec[6]);
808  mid_v3_v3v3(v37, bounds.vec[3], bounds.vec[7]);
809 
810  draw_circle_in_quad(v01, v45, v67, v23, 32, color);
811  draw_circle_in_quad(v30, v12, v56, v74, 32, color);
812  draw_circle_in_quad(v04, v15, v26, v37, 32, color);
813  }
814 }
815 
816 static void draw_primitive_view(const struct bContext *C, ARegion *UNUSED(region), void *arg)
817 {
818  struct InteractivePlaceData *ipd = arg;
819  float color[4];
821 
822  const bool use_depth = !XRAY_ENABLED(ipd->v3d);
823  const eGPUDepthTest depth_test_enabled = GPU_depth_test_get();
824 
825  if (use_depth) {
827  color[3] = 0.15f;
828  draw_primitive_view_impl(C, ipd, color, -1);
829  }
830 
831  /* Show a flattened projection if the current step is aligned to the view. */
832  if (ipd->step[ipd->step_index].is_degenerate_view_align) {
833  const RegionView3D *rv3d = ipd->region->regiondata;
834  if (!rv3d->is_persp) {
835  draw_primitive_view_impl(C, ipd, color, ipd->step_index);
836  }
837  }
838 
839  if (use_depth) {
841  }
842  color[3] = 1.0f;
843  draw_primitive_view_impl(C, ipd, color, -1);
844 
845  if (use_depth) {
846  if (depth_test_enabled == false) {
848  }
849  }
850 }
851 
854 /* -------------------------------------------------------------------- */
861  Scene *scene,
862  View3D *v3d,
863  ARegion *region,
864  const float mval_fl[2],
866  const enum ePlace_SnapTo snap_to,
867  const enum ePlace_Depth plane_depth,
868  const enum ePlace_Orient plane_orient,
869  const int plane_axis,
870  const bool plane_axis_auto,
871  float r_co_src[3],
872  float r_matrix_orient[3][3])
873 {
874  const RegionView3D *rv3d = region->regiondata;
875  ED_transform_calc_orientation_from_type(C, r_matrix_orient);
876 
877  /* Non-orthogonal matrices cause the preview and final result not to match.
878  *
879  * While making orthogonal doesn't always work well (especially with gimbal orientation for e.g.)
880  * it's a corner case, without better alternatives as objects don't support shear. */
881  orthogonalize_m3(r_matrix_orient, plane_axis);
882 
883  SnapObjectContext *snap_context = NULL;
884  bool snap_context_free = false;
885 
886  /* Set the orientation. */
887  if ((plane_orient == PLACE_ORIENT_SURFACE) || (plane_depth == PLACE_DEPTH_SURFACE)) {
888  snap_context = (snap_gizmo ?
890  NULL);
891  if (snap_context == NULL) {
893  snap_context_free = true;
894  }
895  }
896 
897  if (plane_orient == PLACE_ORIENT_SURFACE) {
898  bool found_surface_or_normal = false;
899  float matrix_orient_surface[3][3];
900 
901  /* Use the snap normal as a fallback in case the cursor isn't over a surface
902  * but snapping is enabled. */
903  float normal_fallback[3];
904  bool use_normal_fallback = snap_gizmo ?
905  idp_snap_normal_from_gizmo(snap_gizmo, normal_fallback) :
906  false;
907 
908  if ((snap_context != NULL) &&
909  idp_poject_surface_normal(snap_context,
911  mval_fl,
912  use_normal_fallback ? r_matrix_orient : NULL,
913  use_normal_fallback ? normal_fallback : NULL,
914  matrix_orient_surface)) {
915  copy_m3_m3(r_matrix_orient, matrix_orient_surface);
916  found_surface_or_normal = true;
917  }
918 
919  if (!found_surface_or_normal && plane_axis_auto) {
920  /* Drawing into empty space, draw onto the plane most aligned to the view direction. */
921  mat3_align_axis_to_v3(r_matrix_orient, plane_axis, rv3d->viewinv[2]);
922  }
923  }
924 
925  const bool is_snap_found = snap_gizmo ? idp_snap_point_from_gizmo(snap_gizmo, r_co_src) : false;
926 
927  if (is_snap_found) {
928  /* pass */
929  }
930  else {
931  bool use_depth_fallback = true;
932  if (plane_depth == PLACE_DEPTH_CURSOR_VIEW) {
933  /* View plane. */
934  ED_view3d_win_to_3d(v3d, region, scene->cursor.location, mval_fl, r_co_src);
935  use_depth_fallback = false;
936  }
937  else if (plane_depth == PLACE_DEPTH_SURFACE) {
938  if ((snap_context != NULL) &&
942  &(const struct SnapObjectParams){
943  .snap_select = SNAP_ALL,
944  .use_object_edit_cage = true,
945  },
946  mval_fl,
947  NULL,
948  NULL,
949  r_co_src,
950  NULL)) {
951  use_depth_fallback = false;
952  }
953  }
954 
955  /* Use as fallback to surface. */
956  if (use_depth_fallback || (plane_depth == PLACE_DEPTH_CURSOR_PLANE)) {
957  /* Cursor plane. */
958  float plane[4];
959  const float *plane_normal = r_matrix_orient[plane_axis];
960 
961  const float view_axis_dot = fabsf(dot_v3v3(rv3d->viewinv[2], r_matrix_orient[plane_axis]));
962  if (view_axis_dot < eps_view_align) {
963  /* In this case, just project onto the view plane as it's important the location
964  * is _always_ under the mouse cursor, even if it turns out that wont lie on
965  * the original 'plane' that's been calculated for us. */
966  plane_normal = rv3d->viewinv[2];
967  }
968 
970 
971  if (view3d_win_to_3d_on_plane_maybe_fallback(region, plane, mval_fl, NULL, r_co_src)) {
972  use_depth_fallback = false;
973  }
974 
975  /* Even if the calculation works, it's possible the point found is behind the view,
976  * or very far away (past the far clipping).
977  * In either case creating objects wont be useful. */
978  if (rv3d->is_persp) {
979  float dir[3];
980  sub_v3_v3v3(dir, rv3d->viewinv[3], r_co_src);
981  const float dot = dot_v3v3(dir, rv3d->viewinv[2]);
982  if (dot < v3d->clip_start || dot > v3d->clip_end) {
983  use_depth_fallback = true;
984  }
985  }
986  }
987 
988  if (use_depth_fallback) {
989  float co_depth[3];
990  /* Fallback to view center. */
991  negate_v3_v3(co_depth, rv3d->ofs);
992  ED_view3d_win_to_3d(v3d, region, co_depth, mval_fl, r_co_src);
993  }
994  }
995 
999  }
1000  }
1001 
1002  if (snap_context_free) {
1004  }
1005 }
1006 
1009 /* -------------------------------------------------------------------- */
1014 {
1015 
1016  const int plane_axis = RNA_enum_get(op->ptr, "plane_axis");
1017  const bool plane_axis_auto = RNA_boolean_get(op->ptr, "plane_axis_auto");
1018  const enum ePlace_SnapTo snap_to = RNA_enum_get(op->ptr, "snap_target");
1019  const enum ePlace_Depth plane_depth = RNA_enum_get(op->ptr, "plane_depth");
1020  const enum ePlace_Origin plane_origin[2] = {
1021  RNA_enum_get(op->ptr, "plane_origin_base"),
1022  RNA_enum_get(op->ptr, "plane_origin_depth"),
1023  };
1024  const enum ePlace_Aspect plane_aspect[2] = {
1025  RNA_enum_get(op->ptr, "plane_aspect_base"),
1026  RNA_enum_get(op->ptr, "plane_aspect_depth"),
1027  };
1028  const enum ePlace_Orient plane_orient = RNA_enum_get(op->ptr, "plane_orientation");
1029 
1030  const float mval_fl[2] = {UNPACK2(event->mval)};
1031 
1032  struct InteractivePlaceData *ipd = op->customdata;
1033 
1034  /* Assign snap gizmo which is may be used as part of the tool. */
1035  {
1037  if (gzgroup != NULL) {
1038  if (gzgroup->gizmos.first) {
1039  ipd->snap_gizmo = gzgroup->gizmos.first;
1040  }
1041 
1042  /* Can be NULL when gizmos are disabled. */
1043  if (gzgroup->customdata != NULL) {
1044  preview_plane_cursor_visible_set(gzgroup, false);
1045  }
1046  }
1047  }
1048 
1049  /* For tweak events the snap target may have changed since dragging,
1050  * update the snap target at the cursor location where tweak began.
1051  *
1052  * NOTE: we could investigating solving this in a more generic way,
1053  * so each operator doesn't have to account for it. */
1054  if (ISTWEAK(event->type)) {
1055  if (ipd->snap_gizmo != NULL) {
1058  ipd->region,
1059  ipd->v3d,
1060  G_MAIN->wm.first,
1061  mval_fl);
1062  }
1063  }
1064 
1066 
1068  ipd->scene,
1069  ipd->v3d,
1070  ipd->region,
1071  mval_fl,
1072  ipd->snap_gizmo,
1073  snap_to,
1074  plane_depth,
1075  plane_orient,
1076  plane_axis,
1077  plane_axis_auto,
1078  ipd->co_src,
1079  ipd->matrix_orient);
1080 
1081  ipd->orient_axis = plane_axis;
1082  for (int i = 0; i < 2; i++) {
1083  ipd->step[i].is_centered_init = (plane_origin[i] == PLACE_ORIGIN_CENTER);
1084  ipd->step[i].is_centered = ipd->step[i].is_centered_init;
1085 
1086  ipd->step[i].is_fixed_aspect_init = (plane_aspect[i] == PLACE_ASPECT_FIXED);
1087  ipd->step[i].is_fixed_aspect = ipd->step[i].is_fixed_aspect_init;
1088  }
1089 
1090  ipd->step_index = STEP_BASE;
1091  ipd->snap_to = snap_to;
1092 
1093  plane_from_point_normal_v3(ipd->step[0].plane, ipd->co_src, ipd->matrix_orient[plane_axis]);
1094 
1095  copy_v3_v3(ipd->step[0].co_dst, ipd->co_src);
1096 
1097  {
1098  RegionView3D *rv3d = ipd->region->regiondata;
1099  const float view_axis_dot = fabsf(dot_v3v3(rv3d->viewinv[2], ipd->matrix_orient[plane_axis]));
1100  ipd->step[STEP_BASE].is_degenerate_view_align = view_axis_dot < eps_view_align;
1101  ipd->step[STEP_DEPTH].is_degenerate_view_align = fabsf(view_axis_dot - 1.0f) < eps_view_align;
1102 
1103  float view_axis[3];
1104  normalize_v3_v3(view_axis, rv3d->viewinv[2]);
1105  plane_from_point_normal_v3(ipd->view_plane, ipd->co_src, view_axis);
1106  }
1107 
1110  RegionView3D *rv3d = ipd->region->regiondata;
1111  float axis_view[3];
1112  add_v3_v3v3(axis_view, rv3d->viewinv[0], rv3d->viewinv[1]);
1113  normalize_v3(axis_view);
1114 
1115  /* Setup fallback axes. */
1116  for (int i = 0; i < 2; i++) {
1117  if (ipd->step[i].is_degenerate_view_align) {
1118  const int degenerate_axis =
1119  (i == STEP_BASE) ?
1120  /* For #STEP_BASE find the orient axis that align to the view. */
1121  dot_v3_array_find_max_index(ipd->matrix_orient, 3, rv3d->viewinv[2], false) :
1122  /* For #STEP_DEPTH the orient axis is always view aligned when degenerate. */
1123  ipd->orient_axis;
1124 
1125  float axis_fallback[4][3];
1126  const int x_axis = (degenerate_axis + 1) % 3;
1127  const int y_axis = (degenerate_axis + 2) % 3;
1128 
1129  /* Assign 4x diagonal axes, find which one is closest to the viewport diagonal
1130  * bottom left to top right, for a predictable direction from a user perspective. */
1131  add_v3_v3v3(axis_fallback[0], ipd->matrix_orient[x_axis], ipd->matrix_orient[y_axis]);
1132  sub_v3_v3v3(axis_fallback[1], ipd->matrix_orient[x_axis], ipd->matrix_orient[y_axis]);
1133  negate_v3_v3(axis_fallback[2], axis_fallback[0]);
1134  negate_v3_v3(axis_fallback[3], axis_fallback[1]);
1135 
1136  const int axis_best = dot_v3_array_find_max_index(axis_fallback, 4, axis_view, true);
1137  normalize_v3_v3(ipd->step[i].degenerate_diagonal, axis_fallback[axis_best]);
1139 
1140  /* `degenerate_view_plane_fallback` is used to map cursor motion from a view aligned
1141  * plane back onto the view aligned plane.
1142  *
1143  * The dot product check below ensures cursor motion
1144  * isn't inverted from a user perspective. */
1145  const bool degenerate_axis_is_flip = dot_v3v3(ipd->matrix_orient[degenerate_axis],
1146  ((i == STEP_BASE) ?
1147  ipd->step[i].degenerate_diagonal :
1148  rv3d->viewinv[2])) < 0.0f;
1149 
1151  if (degenerate_axis_is_flip) {
1153  }
1154  }
1155  }
1156  }
1157 
1159  false;
1160  {
1161  const ToolSettings *ts = ipd->scene->toolsettings;
1162  ipd->use_snap = (ipd->is_snap_invert == !(ts->snap_flag & SCE_SNAP));
1163  }
1164 
1167 
1169 
1170  /* Setup the primitive type. */
1171  {
1172  PropertyRNA *prop = RNA_struct_find_property(op->ptr, "primitive_type");
1173  if (RNA_property_is_set(op->ptr, prop)) {
1174  ipd->primitive_type = RNA_property_enum_get(op->ptr, prop);
1175  ipd->use_tool = false;
1176  }
1177  else {
1178  ipd->use_tool = true;
1179 
1180  /* Get from the tool, a bit of a non-standard way of operating. */
1181  const bToolRef *tref = ipd->area->runtime.tool;
1182  if (tref && STREQ(tref->idname, "builtin.primitive_cube_add")) {
1184  }
1185  else if (tref && STREQ(tref->idname, "builtin.primitive_cylinder_add")) {
1187  }
1188  else if (tref && STREQ(tref->idname, "builtin.primitive_cone_add")) {
1190  }
1191  else if (tref && STREQ(tref->idname, "builtin.primitive_uv_sphere_add")) {
1193  }
1194  else if (tref && STREQ(tref->idname, "builtin.primitive_ico_sphere_add")) {
1196  }
1197  else {
1198  /* If the user runs this as an operator they should set the 'primitive_type',
1199  * however running from operator search will end up at this point. */
1201  ipd->use_tool = false;
1202  }
1203  }
1204  }
1205 }
1206 
1208 {
1209  const bool wait_for_input = RNA_boolean_get(op->ptr, "wait_for_input");
1210 
1211  struct InteractivePlaceData *ipd = MEM_callocN(sizeof(*ipd), __func__);
1212  op->customdata = ipd;
1213 
1214  ipd->scene = CTX_data_scene(C);
1215  ipd->area = CTX_wm_area(C);
1216  ipd->region = CTX_wm_region(C);
1217  ipd->v3d = CTX_wm_view3d(C);
1218 
1219  if (wait_for_input) {
1220  ipd->wait_for_input = true;
1221  /* TODO: support snapping when not using with tool. */
1222 #if 0
1224 #endif
1225  }
1226  else {
1227  view3d_interactive_add_begin(C, op, event);
1228  }
1229 
1231 
1232  return OPERATOR_RUNNING_MODAL;
1233 }
1234 
1236 {
1237  UNUSED_VARS(C);
1238 
1239  struct InteractivePlaceData *ipd = op->customdata;
1240 
1242 
1244 
1245  {
1247  if (gzgroup != NULL) {
1248  if (gzgroup->customdata != NULL) {
1249  preview_plane_cursor_visible_set(gzgroup, true);
1250  }
1251  }
1252  }
1253 
1254  MEM_freeN(ipd);
1255 }
1256 
1258 {
1260 }
1261 
1262 enum {
1269 };
1270 
1272 {
1273  static const EnumPropertyItem modal_items[] = {
1274  {PLACE_MODAL_SNAP_ON, "SNAP_ON", 0, "Snap On", ""},
1275  {PLACE_MODAL_SNAP_OFF, "SNAP_OFF", 0, "Snap Off", ""},
1276  {PLACE_MODAL_FIXED_ASPECT_ON, "FIXED_ASPECT_ON", 0, "Fixed Aspect On", ""},
1277  {PLACE_MODAL_FIXED_ASPECT_OFF, "FIXED_ASPECT_OFF", 0, "Fixed Aspect Off", ""},
1278  {PLACE_MODAL_PIVOT_CENTER_ON, "PIVOT_CENTER_ON", 0, "Center Pivot On", ""},
1279  {PLACE_MODAL_PIVOT_CENTER_OFF, "PIVOT_CENTER_OFF", 0, "Center Pivot Off", ""},
1280  {0, NULL, 0, NULL, NULL},
1281  };
1282 
1283  const char *keymap_name = "View3D Placement Modal";
1284  wmKeyMap *keymap = WM_modalkeymap_find(keyconf, keymap_name);
1285 
1286  /* This function is called for each space-type, only needs to add map once. */
1287  if (keymap && keymap->modal_items) {
1288  return;
1289  }
1290 
1291  keymap = WM_modalkeymap_ensure(keyconf, keymap_name, modal_items);
1292 
1293  WM_modalkeymap_assign(keymap, "VIEW3D_OT_interactive_add");
1294 }
1295 
1297 {
1298  UNUSED_VARS(C, op);
1299 
1300  struct InteractivePlaceData *ipd = op->customdata;
1301 
1302  ARegion *region = ipd->region;
1303  bool do_redraw = false;
1304  bool do_cursor_update = false;
1305 
1306  /* Handle modal key-map. */
1307  if (event->type == EVT_MODAL_MAP) {
1308  bool is_fallthrough = false;
1309  switch (event->val) {
1311  is_fallthrough = true;
1313  }
1315  ipd->step[ipd->step_index].is_fixed_aspect =
1316  is_fallthrough ^ ipd->step[ipd->step_index].is_fixed_aspect_init;
1317  do_redraw = true;
1318  break;
1319  }
1321  is_fallthrough = true;
1323  }
1325  ipd->step[ipd->step_index].is_centered = is_fallthrough ^
1326  ipd->step[ipd->step_index].is_centered_init;
1327  do_redraw = true;
1328  break;
1329  }
1330  case PLACE_MODAL_SNAP_ON: {
1331  is_fallthrough = true;
1333  }
1334  case PLACE_MODAL_SNAP_OFF: {
1335  const ToolSettings *ts = ipd->scene->toolsettings;
1336  ipd->is_snap_invert = is_fallthrough;
1337  ipd->use_snap = (ipd->is_snap_invert == !(ts->snap_flag & SCE_SNAP));
1338  do_cursor_update = true;
1339  break;
1340  }
1341  }
1342  }
1343  else {
1344  switch (event->type) {
1345  case EVT_ESCKEY:
1346  case RIGHTMOUSE: {
1348  return OPERATOR_CANCELLED;
1349  }
1350  case MOUSEMOVE: {
1351  do_cursor_update = true;
1352  break;
1353  }
1354  }
1355  }
1356 
1357  if (ipd->wait_for_input) {
1358  if (ELEM(event->type, LEFTMOUSE)) {
1359  if (event->val == KM_PRESS) {
1360  view3d_interactive_add_begin(C, op, event);
1361  ipd->wait_for_input = false;
1362  return OPERATOR_RUNNING_MODAL;
1363  }
1364  }
1365  return OPERATOR_RUNNING_MODAL;
1366  }
1367 
1368  if (ipd->step_index == STEP_BASE) {
1369  if (ELEM(event->type, ipd->launch_event, LEFTMOUSE)) {
1370  if (event->val == KM_RELEASE) {
1371  /* Set secondary plane. */
1372 
1373  /* Create normal. */
1374  {
1375  RegionView3D *rv3d = region->regiondata;
1376  float no[3], no_temp[3];
1377 
1379  cross_v3_v3v3(no_temp, ipd->step[0].plane, ipd->step[STEP_DEPTH].degenerate_diagonal);
1380  cross_v3_v3v3(no, no_temp, ipd->step[0].plane);
1381  }
1382  else {
1383  cross_v3_v3v3(no_temp, ipd->step[0].plane, rv3d->viewinv[2]);
1384  cross_v3_v3v3(no, no_temp, ipd->step[0].plane);
1385  }
1386  normalize_v3(no);
1387 
1388  plane_from_point_normal_v3(ipd->step[1].plane, ipd->step[0].co_dst, no);
1389  }
1390 
1391  copy_v3_v3(ipd->step[1].co_dst, ipd->step[0].co_dst);
1392  ipd->step_index = STEP_DEPTH;
1393 
1394  /* Use the toggle from the previous step. */
1395  if (ipd->step[0].is_centered != ipd->step[0].is_centered_init) {
1396  ipd->step[1].is_centered = !ipd->step[1].is_centered;
1397  }
1398  if (ipd->step[0].is_fixed_aspect != ipd->step[0].is_fixed_aspect_init) {
1399  ipd->step[1].is_fixed_aspect = !ipd->step[1].is_fixed_aspect;
1400  }
1401  }
1402  }
1403  }
1404  else if (ipd->step_index == STEP_DEPTH) {
1405  if (ELEM(event->type, ipd->launch_event, LEFTMOUSE)) {
1406  if (event->val == KM_PRESS) {
1407 
1408  BoundBox bounds;
1409  calc_bbox(ipd, &bounds);
1410 
1411  float location[3];
1412  float rotation[3];
1413  float scale[3];
1414 
1415  float matrix_orient_axis[3][3];
1416  copy_m3_m3(matrix_orient_axis, ipd->matrix_orient);
1417  if (ipd->orient_axis != 2) {
1418  swap_v3_v3(matrix_orient_axis[2], matrix_orient_axis[ipd->orient_axis]);
1419  swap_v3_v3(matrix_orient_axis[0], matrix_orient_axis[1]);
1420  }
1421  /* Needed for shapes where the sign matters (cone for eg). */
1422  {
1423  float delta[3];
1424  sub_v3_v3v3(delta, bounds.vec[0], bounds.vec[4]);
1425  if (dot_v3v3(ipd->matrix_orient[ipd->orient_axis], delta) > 0.0f) {
1426  negate_v3(matrix_orient_axis[2]);
1427 
1428  /* Only flip Y so we don't flip a single axis which causes problems. */
1429  negate_v3(matrix_orient_axis[1]);
1430  }
1431  }
1432 
1433  mat3_to_eul(rotation, matrix_orient_axis);
1434 
1435  mid_v3_v3v3(location, bounds.vec[0], bounds.vec[6]);
1436  const int cube_verts[3] = {3, 1, 4};
1437  for (int i = 0; i < 3; i++) {
1438  scale[i] = len_v3v3(bounds.vec[0], bounds.vec[cube_verts[i]]);
1439  /* Primitives have size 2 by default, compensate for this here. */
1440  scale[i] /= 2.0f;
1441  }
1442 
1443  wmOperatorType *ot = NULL;
1444  PointerRNA op_props;
1446  ot = WM_operatortype_find("MESH_OT_primitive_cube_add", false);
1447  }
1448  else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CYLINDER) {
1449  ot = WM_operatortype_find("MESH_OT_primitive_cylinder_add", false);
1450  }
1451  else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CONE) {
1452  ot = WM_operatortype_find("MESH_OT_primitive_cone_add", false);
1453  }
1455  ot = WM_operatortype_find("MESH_OT_primitive_uv_sphere_add", false);
1456  }
1458  ot = WM_operatortype_find("MESH_OT_primitive_ico_sphere_add", false);
1459  }
1460 
1461  if (ot != NULL) {
1463 
1464  if (ipd->use_tool) {
1465  bToolRef *tref = ipd->area->runtime.tool;
1466  PointerRNA temp_props;
1467  WM_toolsystem_ref_properties_init_for_keymap(tref, &temp_props, &op_props, ot);
1468  SWAP(PointerRNA, temp_props, op_props);
1469  WM_operator_properties_free(&temp_props);
1470  }
1471 
1472  RNA_float_set_array(&op_props, "rotation", rotation);
1473  RNA_float_set_array(&op_props, "location", location);
1474  RNA_float_set_array(&op_props, "scale", scale);
1475 
1476  /* Always use the defaults here since desired bounds have been set interactively, it does
1477  * not make sense to use a different values from a previous command. */
1479  RNA_float_set(&op_props, "size", 2.0f);
1480  }
1481  if (ELEM(ipd->primitive_type,
1485  RNA_float_set(&op_props, "radius", 1.0f);
1486  }
1487  if (ELEM(
1489  RNA_float_set(&op_props, "depth", 2.0f);
1490  }
1492  RNA_float_set(&op_props, "radius1", 1.0f);
1493  RNA_float_set(&op_props, "radius2", 0.0f);
1494  }
1495 
1497  WM_operator_properties_free(&op_props);
1498  }
1499  else {
1500  BLI_assert(0);
1501  }
1502 
1504  return OPERATOR_FINISHED;
1505  }
1506  }
1507  }
1508  else {
1509  BLI_assert(0);
1510  }
1511 
1512  if (do_cursor_update) {
1513  const float mval_fl[2] = {UNPACK2(event->mval)};
1514 
1515  /* Calculate the snap location on mouse-move or when toggling snap. */
1516  ipd->is_snap_found = false;
1517  if (ipd->use_snap) {
1518  if (ipd->snap_gizmo != NULL) {
1522  ipd->region,
1523  ipd->v3d,
1524  G_MAIN->wm.first,
1525  mval_fl)) {
1527  ipd->is_snap_found = true;
1528  }
1530  }
1531  }
1532 
1533  if (ipd->step_index == STEP_BASE) {
1534  if (ipd->is_snap_found) {
1536  ipd->step[STEP_BASE].co_dst, ipd->step[STEP_BASE].plane, ipd->snap_co);
1537  }
1538  else {
1540  region,
1541  ipd->step[STEP_BASE].plane,
1542  mval_fl,
1544  ipd->step[STEP_BASE].co_dst)) {
1545  /* pass */
1546  }
1547 
1548  if (ipd->use_snap && (ipd->snap_to == PLACE_SNAP_TO_DEFAULT)) {
1550  ipd->scene, ipd->v3d, ipd->region, ipd->co_src, ipd->step[STEP_BASE].co_dst)) {
1551  }
1552  }
1553  }
1554  }
1555  else if (ipd->step_index == STEP_DEPTH) {
1556  if (ipd->is_snap_found) {
1558  ipd->step[STEP_DEPTH].co_dst, ipd->step[STEP_DEPTH].plane, ipd->snap_co);
1559  }
1560  else {
1562  region,
1563  ipd->step[STEP_DEPTH].plane,
1564  mval_fl,
1566  ipd->step[STEP_DEPTH].co_dst)) {
1567  /* pass */
1568  }
1569 
1570  if (ipd->use_snap && (ipd->snap_to == PLACE_SNAP_TO_DEFAULT)) {
1572  ipd->scene, ipd->v3d, ipd->region, ipd->co_src, ipd->step[STEP_DEPTH].co_dst)) {
1573  }
1574  }
1575  }
1576 
1577  /* Correct the point so it's aligned with the 'ipd->step[0].co_dst'. */
1578  float close[3], delta[3];
1580  close, ipd->step[STEP_BASE].plane, ipd->step[STEP_DEPTH].co_dst);
1581  sub_v3_v3v3(delta, close, ipd->step[STEP_BASE].co_dst);
1582  sub_v3_v3(ipd->step[STEP_DEPTH].co_dst, delta);
1583  }
1584  do_redraw = true;
1585  }
1586 
1587  if (do_redraw) {
1589  }
1590 
1591  return OPERATOR_RUNNING_MODAL;
1592 }
1593 
1595 {
1596  const enum eContextObjectMode mode = CTX_data_mode_enum(C);
1597  return ELEM(mode, CTX_MODE_OBJECT, CTX_MODE_EDIT_MESH);
1598 }
1599 
1601 {
1602  /* identifiers */
1603  ot->name = "Add Primitive Object";
1604  ot->description = "Interactively add an object";
1605  ot->idname = "VIEW3D_OT_interactive_add";
1606 
1607  /* api callbacks */
1612 
1613  /* Note, let the operator we call handle undo and registering itself. */
1614  /* flags */
1615  ot->flag = 0;
1616 
1617  /* properties */
1618  PropertyRNA *prop;
1619 
1620  /* Normally not accessed directly, leave unset and check the active tool. */
1621  static const EnumPropertyItem primitive_type[] = {
1622  {PLACE_PRIMITIVE_TYPE_CUBE, "CUBE", 0, "Cube", ""},
1623  {PLACE_PRIMITIVE_TYPE_CYLINDER, "CYLINDER", 0, "Cylinder", ""},
1624  {PLACE_PRIMITIVE_TYPE_CONE, "CONE", 0, "Cone", ""},
1625  {PLACE_PRIMITIVE_TYPE_SPHERE_UV, "SPHERE_UV", 0, "UV Sphere", ""},
1626  {PLACE_PRIMITIVE_TYPE_SPHERE_ICO, "SPHERE_ICO", 0, "ICO Sphere", ""},
1627  {0, NULL, 0, NULL, NULL},
1628  };
1629  prop = RNA_def_property(ot->srna, "primitive_type", PROP_ENUM, PROP_NONE);
1630  RNA_def_property_ui_text(prop, "Primitive", "");
1633 
1634  prop = RNA_def_property(ot->srna, "plane_axis", PROP_ENUM, PROP_NONE);
1635  RNA_def_property_ui_text(prop, "Plane Axis", "The axis used for placing the base region");
1639 
1640  prop = RNA_def_boolean(ot->srna,
1641  "plane_axis_auto",
1642  false,
1643  "Auto Axis",
1644  "Select the closest axis when placing objects "
1645  "(surface overrides)");
1647 
1648  static const EnumPropertyItem plane_depth_items[] = {
1650  "SURFACE",
1651  0,
1652  "Surface",
1653  "Start placing on the surface, using the 3D cursor position as a fallback"},
1655  "CURSOR_PLANE",
1656  0,
1657  "Cursor Plane",
1658  "Start placement using a point projected onto the orientation axis "
1659  "at the 3D cursor position"},
1661  "CURSOR_VIEW",
1662  0,
1663  "Cursor View",
1664  "Start placement using a point projected onto the view plane at the 3D cursor position"},
1665  {0, NULL, 0, NULL, NULL},
1666  };
1667  prop = RNA_def_property(ot->srna, "plane_depth", PROP_ENUM, PROP_NONE);
1668  RNA_def_property_ui_text(prop, "Position", "The initial depth used when placing the cursor");
1670  RNA_def_property_enum_items(prop, plane_depth_items);
1672 
1673  static const EnumPropertyItem plane_orientation_items[] = {
1675  "SURFACE",
1676  ICON_SNAP_NORMAL,
1677  "Surface",
1678  "Use the surface normal (using the transform orientation as a fallback)"},
1680  "DEFAULT",
1681  ICON_ORIENTATION_GLOBAL,
1682  "Default",
1683  "Use the current transform orientation"},
1684  {0, NULL, 0, NULL, NULL},
1685  };
1686  prop = RNA_def_property(ot->srna, "plane_orientation", PROP_ENUM, PROP_NONE);
1687  RNA_def_property_ui_text(prop, "Orientation", "The initial depth used when placing the cursor");
1689  RNA_def_property_enum_items(prop, plane_orientation_items);
1691 
1692  static const EnumPropertyItem snap_to_items[] = {
1693  {PLACE_SNAP_TO_GEOMETRY, "GEOMETRY", 0, "Geometry", "Snap to all geometry"},
1694  {PLACE_SNAP_TO_DEFAULT, "DEFAULT", 0, "Default", "Use the current snap settings"},
1695  {0, NULL, 0, NULL, NULL},
1696  };
1697  prop = RNA_def_property(ot->srna, "snap_target", PROP_ENUM, PROP_NONE);
1698  RNA_def_property_ui_text(prop, "Snap to", "The target to use while snapping");
1700  RNA_def_property_enum_items(prop, snap_to_items);
1702 
1703  { /* Plane Origin. */
1704  static const EnumPropertyItem items[] = {
1705  {PLACE_ORIGIN_BASE, "EDGE", 0, "Edge", "Start placing the edge position"},
1706  {PLACE_ORIGIN_CENTER, "CENTER", 0, "Center", "Start placing the center position"},
1707  {0, NULL, 0, NULL, NULL},
1708  };
1709  const char *identifiers[2] = {"plane_origin_base", "plane_origin_depth"};
1710  for (int i = 0; i < 2; i++) {
1711  prop = RNA_def_property(ot->srna, identifiers[i], PROP_ENUM, PROP_NONE);
1712  RNA_def_property_ui_text(prop, "Origin", "The initial position for placement");
1714  RNA_def_property_enum_items(prop, items);
1716  }
1717  }
1718 
1719  { /* Plane Aspect. */
1720  static const EnumPropertyItem items[] = {
1721  {PLACE_ASPECT_FREE, "FREE", 0, "Free", "Use an unconstrained aspect"},
1722  {PLACE_ASPECT_FIXED, "FIXED", 0, "Fixed", "Use a fixed 1:1 aspect"},
1723  {0, NULL, 0, NULL, NULL},
1724  };
1725  const char *identifiers[2] = {"plane_aspect_base", "plane_aspect_depth"};
1726  for (int i = 0; i < 2; i++) {
1727  prop = RNA_def_property(ot->srna, identifiers[i], PROP_ENUM, PROP_NONE);
1728  RNA_def_property_ui_text(prop, "Aspect", "The initial aspect setting");
1730  RNA_def_property_enum_items(prop, items);
1732  }
1733  }
1734 
1735  /* When not accessed via a tool. */
1736  prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
1738 }
1739 
1742 /* -------------------------------------------------------------------- */
1750 {
1751  wmGizmo *gizmo;
1752 
1753  {
1754  /* The gizmo snap has to be the first gizmo. */
1755  const wmGizmoType *gzt_snap;
1756  gzt_snap = WM_gizmotype_find("GIZMO_GT_snap_3d", true);
1757  gizmo = WM_gizmo_new_ptr(gzt_snap, gzgroup, NULL);
1758 
1759  WM_gizmo_set_color(gizmo, (float[4]){1.0f, 1.0f, 1.0f, 1.0f});
1760 
1761  /* Don't handle any events, this is for display only. */
1762  gizmo->flag |= WM_GIZMO_HIDDEN_KEYMAP;
1763  }
1764 
1765  /* Sets the gizmos custom-data which has it's own free callback. */
1766  preview_plane_cursor_setup(gzgroup);
1767 }
1768 
1770 {
1771  gzgt->name = "Placement Widget";
1773 
1775 
1778 
1781 }
1782 
1785 /* -------------------------------------------------------------------- */
1795  ARegion *region,
1796  const int mval[2],
1797  float r_co[3],
1798  float r_matrix_orient[3][3],
1799  int *r_plane_axis)
1800 {
1801  wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_interactive_add", true);
1802  BLI_assert(ot != NULL);
1803  PointerRNA ptr;
1804 
1805  ScrArea *area = CTX_wm_area(C);
1807  bToolRef *tref = area->runtime.tool;
1809 
1810  const enum ePlace_SnapTo snap_to = RNA_enum_get(&ptr, "snap_target");
1811  const int plane_axis = RNA_enum_get(&ptr, "plane_axis");
1812  const bool plane_axis_auto = RNA_boolean_get(&ptr, "plane_axis_auto");
1813  const enum ePlace_Depth plane_depth = RNA_enum_get(&ptr, "plane_depth");
1814  const enum ePlace_Orient plane_orient = RNA_enum_get(&ptr, "plane_orientation");
1815 
1816  const float mval_fl[2] = {UNPACK2(mval)};
1817 
1819  View3D *v3d = CTX_wm_view3d(C);
1820 
1821  /* Assign snap gizmo which is may be used as part of the tool. */
1822  wmGizmo *snap_gizmo = NULL;
1823  {
1825  if ((gzgroup != NULL) && gzgroup->gizmos.first) {
1826  snap_gizmo = gzgroup->gizmos.first;
1827  }
1828  }
1829 
1830  /* This ensures the snap gizmo has settings from this tool.
1831  * This function call could be moved a more appropriate place,
1832  * responding to the setting being changed for example,
1833  * however setting the value isn't expensive, so do it here. */
1835 
1837  scene,
1838  v3d,
1839  region,
1840  mval_fl,
1841  snap_gizmo,
1842  snap_to,
1843  plane_depth,
1844  plane_orient,
1845  plane_axis,
1846  plane_axis_auto,
1847  r_co,
1848  r_matrix_orient);
1849  *r_plane_axis = plane_axis;
1850 }
1851 
1852 static void gizmo_plane_draw_grid(const int resolution,
1853  const float scale,
1854  const float scale_fade,
1855  const float matrix[4][4],
1856  const int plane_axis,
1857  const float color[4])
1858 {
1859  BLI_assert(scale_fade <= scale);
1860  const int resolution_min = resolution - 1;
1861  float color_fade[4] = {UNPACK4(color)};
1862  const float *center = matrix[3];
1863 
1865  GPU_line_smooth(true);
1866  GPU_line_width(1.0f);
1867 
1869  const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1870  const uint col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
1871 
1873 
1874  const size_t coords_len = resolution * resolution;
1875  float(*coords)[3] = MEM_mallocN(sizeof(*coords) * coords_len, __func__);
1876 
1877  const int axis_x = (plane_axis + 0) % 3;
1878  const int axis_y = (plane_axis + 1) % 3;
1879  const int axis_z = (plane_axis + 2) % 3;
1880 
1881  int i;
1882  const float resolution_div = (float)1.0f / (float)resolution;
1883  i = 0;
1884  for (int x = 0; x < resolution; x++) {
1885  const float x_fl = (x * resolution_div) - 0.5f;
1886  for (int y = 0; y < resolution; y++) {
1887  const float y_fl = (y * resolution_div) - 0.5f;
1888  coords[i][axis_x] = 0.0f;
1889  coords[i][axis_y] = x_fl * scale;
1890  coords[i][axis_z] = y_fl * scale;
1891  mul_m4_v3(matrix, coords[i]);
1892  i += 1;
1893  }
1894  }
1895  BLI_assert(i == coords_len);
1896  immBeginAtMost(GPU_PRIM_LINES, coords_len * 4);
1897  i = 0;
1898  for (int x = 0; x < resolution_min; x++) {
1899  for (int y = 0; y < resolution_min; y++) {
1900 
1901  /* Add #resolution_div to ensure we fade-out entirely. */
1902 #define FADE(v) \
1903  max_ff(0.0f, (1.0f - square_f(((len_v3v3(v, center) / scale_fade) + resolution_div) * 2.0f)))
1904 
1905  const float *v0 = coords[(resolution * x) + y];
1906  const float *v1 = coords[(resolution * (x + 1)) + y];
1907  const float *v2 = coords[(resolution * x) + (y + 1)];
1908 
1909  const float f0 = FADE(v0);
1910  const float f1 = FADE(v1);
1911  const float f2 = FADE(v2);
1912 
1913  if (f0 > 0.0f || f1 > 0.0f) {
1914  color_fade[3] = color[3] * f0;
1915  immAttr4fv(col_id, color_fade);
1916  immVertex3fv(pos_id, v0);
1917  color_fade[3] = color[3] * f1;
1918  immAttr4fv(col_id, color_fade);
1919  immVertex3fv(pos_id, v1);
1920  }
1921  if (f0 > 0.0f || f2 > 0.0f) {
1922  color_fade[3] = color[3] * f0;
1923  immAttr4fv(col_id, color_fade);
1924  immVertex3fv(pos_id, v0);
1925 
1926  color_fade[3] = color[3] * f2;
1927  immAttr4fv(col_id, color_fade);
1928  immVertex3fv(pos_id, v2);
1929  }
1930 
1931 #undef FADE
1932 
1933  i++;
1934  }
1935  }
1936 
1937  MEM_freeN(coords);
1938 
1939  immEnd();
1940 
1941  immUnbindProgram();
1942 
1943  GPU_line_smooth(false);
1945 }
1946 
1947 /* -------------------------------------------------------------------- */
1957 
1963  bool do_draw;
1964 
1966 
1968  float matrix[4][4];
1969 
1970  /* Check if we need to re-calculate the plane matrix. */
1971  int mval_prev[2];
1972  float persmat_prev[4][4];
1973 };
1974 
1975 static void cursor_plane_draw(bContext *C, int x, int y, void *customdata)
1976 {
1977  struct PlacementCursor *plc = (struct PlacementCursor *)customdata;
1978  ARegion *region = CTX_wm_region(C);
1979  const RegionView3D *rv3d = region->regiondata;
1980 
1981  /* Early exit.
1982  * Note that we can't do most of these checks in the poll function (besides global checks)
1983  * so test them here instead.
1984  *
1985  * This cursor is only active while the gizmo is being used
1986  * so it's not so important to have a poll function. */
1987  if (plc->do_draw == false) {
1988  return;
1989  }
1990  if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) {
1991  return;
1992  }
1993  if (rv3d->rflag & RV3D_NAVIGATING) {
1994  return;
1995  }
1996 
1997  /* Check this gizmo group is in the region. */
1998  {
1999  wmGizmoMap *gzmap = region->gizmo_map;
2000  wmGizmoGroup *gzgroup_test = WM_gizmomap_group_find_ptr(gzmap, plc->gzgroup->type);
2001  if (gzgroup_test != plc->gzgroup) {
2002  /* Wrong viewport. */
2003  return;
2004  }
2005  }
2006 
2007  const int mval[2] = {x - region->winrct.xmin, y - region->winrct.ymin};
2008 
2009  /* Update matrix? */
2010  if ((plc->mval_prev[0] != mval[0]) || (plc->mval_prev[1] != mval[1]) ||
2011  !equals_m4m4(plc->persmat_prev, rv3d->persmat)) {
2012  plc->mval_prev[0] = mval[0];
2013  plc->mval_prev[1] = mval[1];
2014 
2015  float orient_matrix[3][3];
2016  float co[3];
2017  gizmo_plane_update_cursor(C, region, mval, co, orient_matrix, &plc->plane_axis);
2018  copy_m4_m3(plc->matrix, orient_matrix);
2019  copy_v3_v3(plc->matrix[3], co);
2020 
2021  copy_m4_m4(plc->persmat_prev, rv3d->persmat);
2022  }
2023 
2024  /* Draw */
2025  float pixel_size;
2026 
2027  if (rv3d->is_persp) {
2028  float center[3];
2029  negate_v3_v3(center, rv3d->ofs);
2030  pixel_size = ED_view3d_pixel_size(rv3d, center);
2031  }
2032  else {
2033  pixel_size = ED_view3d_pixel_size(rv3d, plc->matrix[3]);
2034  }
2035 
2036  if (pixel_size > FLT_EPSILON) {
2037 
2038  /* Arbitrary, 1.0 is a little too strong though. */
2039  float color_alpha = 0.75f;
2040  if (rv3d->is_persp) {
2041  /* Scale down the alpha when this is drawn very small,
2042  * since the add shader causes the small size to show too dense & bright. */
2043  const float relative_pixel_scale = pixel_size / ED_view3d_pixel_size(rv3d, plc->matrix[3]);
2044  if (relative_pixel_scale < 1.0f) {
2045  color_alpha *= max_ff(square_f(relative_pixel_scale), 0.3f);
2046  }
2047  }
2048 
2049  {
2050  /* Extra adjustment when it's near view-aligned as it seems overly bright. */
2051  float view_vector[3];
2052  ED_view3d_global_to_vector(rv3d, plc->matrix[3], view_vector);
2053  float view_dot = fabsf(dot_v3v3(plc->matrix[plc->plane_axis], view_vector));
2054  color_alpha *= max_ff(0.3f, 1.0f - square_f(square_f(1.0f - view_dot)));
2055  }
2056 
2057  /* Setup viewport & matrix. */
2058  wmViewport(&region->winrct);
2060  GPU_matrix_push();
2062  GPU_matrix_set(rv3d->viewmat);
2063 
2064  const float scale_mod = U.gizmo_size * 2 * U.dpi_fac;
2065 
2066  float final_scale = (scale_mod * pixel_size);
2067 
2068  const int lines_subdiv = 10;
2069  int lines = lines_subdiv;
2070 
2071  float final_scale_fade = final_scale;
2072  final_scale = ceil_power_of_10(final_scale);
2073 
2074  float fac = final_scale_fade / final_scale;
2075 
2076  float color[4] = {1, 1, 1, color_alpha};
2077  color[3] *= square_f(1.0f - fac);
2078  if (color[3] > 0.0f) {
2079  gizmo_plane_draw_grid(lines * lines_subdiv,
2080  final_scale,
2081  final_scale_fade,
2082  plc->matrix,
2083  plc->plane_axis,
2084  color);
2085  }
2086 
2087  color[3] = color_alpha;
2088  /* When the grid is large, we only need the 2x lines in the middle. */
2089  if (fac < 0.2f) {
2090  lines = 1;
2091  final_scale = final_scale_fade;
2092  }
2094  lines, final_scale, final_scale_fade, plc->matrix, plc->plane_axis, color);
2095 
2096  /* Restore matrix. */
2097  GPU_matrix_pop();
2099  }
2100 }
2101 
2102 static void preview_plane_cursor_free(void *customdata)
2103 {
2104  struct PlacementCursor *plc = customdata;
2105 
2106  /* The window manager is freed first on exit. */
2107  wmWindowManager *wm = G_MAIN->wm.first;
2108  if (UNLIKELY(wm != NULL)) {
2110  }
2111  MEM_freeN(plc);
2112 }
2113 
2115 {
2117  struct PlacementCursor *plc = MEM_callocN(sizeof(*plc), __func__);
2118  plc->gzgroup = gzgroup;
2121  gzgroup->customdata = plc;
2123 
2125 }
2126 
2128 {
2129  struct PlacementCursor *plc = gzgroup->customdata;
2130  plc->do_draw = do_draw;
2131 }
2132 
typedef float(TangentPoint)[2]
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:714
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
eContextObjectMode
Definition: BKE_context.h:114
@ CTX_MODE_OBJECT
Definition: BKE_context.h:128
@ CTX_MODE_EDIT_MESH
Definition: BKE_context.h:115
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:760
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
enum eContextObjectMode CTX_data_mode_enum(const bContext *C)
Definition: context.c:1174
#define G_MAIN
Definition: BKE_global.h:232
@ G_TRANSFORM_OBJ
Definition: BKE_global.h:218
@ G_TRANSFORM_EDIT
Definition: BKE_global.h:219
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define ATTR_FALLTHROUGH
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:109
#define M_PI
Definition: BLI_math_base.h:38
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition: math_geom.c:243
void closest_to_plane_normalized_v3(float r_close[3], const float plane[4], const float pt[3])
Definition: math_geom.c:412
float dist_signed_to_plane_v3(const float p[3], const float plane[4])
Definition: math_geom.c:468
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:4026
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:930
void copy_m3_m3(float m1[3][3], const float m2[3][3])
Definition: math_matrix.c:89
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:105
void orthogonalize_m3(float R[3][3], int axis)
Definition: math_matrix.c:1425
void copy_m4_m3(float m1[4][4], const float m2[3][3])
Definition: math_matrix.c:120
void normalize_m3(float R[3][3]) ATTR_NONNULL()
Definition: math_matrix.c:1919
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
bool equals_m4m4(const float mat1[4][4], const float mat2[4][4])
Definition: math_matrix.c:2612
bool invert_m3_m3(float R[3][3], const float A[3][3])
Definition: math_matrix.c:1161
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:95
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:296
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 bool compare_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT
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])
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:270
MINLINE void swap_v3_v3(float a[3], float b[3])
MINLINE float normalize_v3_length(float r[3], const float unit_scale)
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:83
#define UNPACK2(a)
#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)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
Object groups, one object can be in many groups at once.
Object is a sort of wrapper for general info.
#define SCE_SNAP
#define SCE_SNAP_MODE_FACE
#define SCE_SNAP_ABS_GRID
#define SCE_SNAP_MODE_EDGE_PERPENDICULAR
#define SCE_SNAP_MODE_EDGE_MIDPOINT
#define SCE_SNAP_MODE_VERTEX
#define SCE_SNAP_MODE_EDGE
#define SCE_SNAP_MODE_INCREMENT
@ RGN_TYPE_WINDOW
@ SPACE_VIEW3D
#define RV3D_NAVIGATING
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ ED_SNAPGIZMO_TOGGLE_ALWAYS_TRUE
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:667
#define REGION_DRAW_POST_VIEW
Definition: ED_space_api.h:66
void * ED_region_draw_cb_activate(struct ARegionType *art, void(*draw)(const struct bContext *, struct ARegion *, void *), void *customdata, int type)
Definition: spacetypes.c:238
void ED_region_draw_cb_exit(struct ARegionType *, void *)
Definition: spacetypes.c:253
void ED_transform_calc_orientation_from_type(const struct bContext *C, float r_mat[3][3])
SnapObjectContext * ED_transform_snap_object_context_create_view3d(struct Scene *scene, int flag, const struct ARegion *region, const struct View3D *v3d)
short ED_transform_snap_object_project_view3d_ex(struct SnapObjectContext *sctx, struct Depsgraph *depsgraph, const unsigned short snap_to, const struct SnapObjectParams *params, const float mval[2], const float prev_co[3], float *dist_px, float r_loc[3], float r_no[3], int *r_index, struct Object **r_ob, float r_obmat[4][4])
bool ED_transform_snap_object_project_view3d(struct SnapObjectContext *sctx, struct Depsgraph *depsgraph, const unsigned short snap_to, const struct SnapObjectParams *params, const float mval[2], const float prev_co[3], float *dist_px, float r_loc[3], float r_no[3])
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
bool ED_view3d_win_to_3d_on_plane(const struct ARegion *region, const float plane[4], const float mval[2], const bool do_clip, float r_out[3])
#define XRAY_ENABLED(v3d)
Definition: ED_view3d.h:710
float ED_view3d_pixel_size(const struct RegionView3D *rv3d, const float co[3])
bool ED_view3d_win_to_3d_on_plane_with_fallback(const struct ARegion *region, const float plane[4], const float mval[2], const bool do_clip, const float plane_fallback[4], float r_out[3])
void ED_view3d_global_to_vector(const struct RegionView3D *rv3d, const float coord[3], float vec[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:917
void ED_view3d_win_to_3d(const struct View3D *v3d, const struct ARegion *region, const float depth_pt[3], const float mval[2], float r_out[3])
NSNotificationCenter * center
GPUBatch
Definition: GPU_batch.h:93
#define GPU_batch_uniform_1f(batch, name, x)
Definition: GPU_batch.h:134
void GPU_batch_discard(GPUBatch *)
Definition: gpu_batch.cc:127
void GPU_batch_program_set_builtin(GPUBatch *batch, eGPUBuiltinShader shader_id)
Definition: gpu_batch.cc:299
#define GPU_batch_uniform_2fv(batch, name, val)
Definition: GPU_batch.h:140
GPUBatch * GPU_batch_create_ex(GPUPrimType prim, GPUVertBuf *vert, GPUIndexBuf *elem, eGPUBatchFlag owns_flag)
Definition: gpu_batch.cc:60
void GPU_batch_draw(GPUBatch *batch)
Definition: gpu_batch.cc:234
#define GPU_batch_uniform_4fv(batch, name, val)
Definition: GPU_batch.h:142
@ GPU_BATCH_OWNS_VBO
Definition: GPU_batch.h:45
void immAttr4fv(uint attr_id, const float data[4])
void immUnbindProgram(void)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immBeginAtMost(GPUPrimType, uint max_vertex_len)
GPUVertFormat * immVertexFormat(void)
void immVertex3fv(uint attr_id, const float data[3])
void immEnd(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
void GPU_matrix_pop(void)
Definition: gpu_matrix.cc:142
void GPU_matrix_pop_projection(void)
Definition: gpu_matrix.cc:156
#define GPU_matrix_set(x)
Definition: GPU_matrix.h:224
void GPU_matrix_push(void)
Definition: gpu_matrix.cc:135
#define GPU_matrix_projection_set(x)
Definition: GPU_matrix.h:225
void GPU_matrix_push_projection(void)
Definition: gpu_matrix.cc:149
@ GPU_PRIM_LINE_LOOP
Definition: GPU_primitive.h:39
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:36
@ GPU_SHADER_3D_SMOOTH_COLOR
Definition: GPU_shader.h:215
@ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR
Definition: GPU_shader.h:223
@ GPU_BLEND_NONE
Definition: GPU_state.h:55
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:57
@ GPU_BLEND_ADDITIVE
Definition: GPU_state.h:59
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:55
void GPU_line_width(float width)
Definition: gpu_state.cc:173
void GPU_line_smooth(bool enable)
Definition: gpu_state.cc:85
eGPUDepthTest
Definition: GPU_state.h:77
@ GPU_DEPTH_LESS_EQUAL
Definition: GPU_state.h:81
@ GPU_DEPTH_NONE
Definition: GPU_state.h:78
eGPUDepthTest GPU_depth_test_get(void)
Definition: gpu_state.cc:255
void GPU_depth_test(eGPUDepthTest test)
Definition: gpu_state.cc:75
void GPU_viewport_size_get_f(float coords[4])
Definition: gpu_state.cc:279
#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.
@ PROP_ENUM
Definition: RNA_types.h:77
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
@ PROP_HIDDEN
Definition: RNA_types.h:202
@ PROP_NONE
Definition: RNA_types.h:113
#define C
Definition: RandGen.cpp:39
void UI_GetThemeColor3fv(int colorid, float col[3])
Definition: resources.c:1191
@ TH_GIZMO_PRIMARY
Definition: UI_resources.h:321
@ WM_GIZMO_HIDDEN_KEYMAP
@ WM_GIZMOGROUPTYPE_SCALE
@ WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL
@ WM_GIZMOGROUPTYPE_3D
@ WM_GIZMO_STATE_HIGHLIGHT
#define WM_toolsystem_ref_properties_ensure_from_operator(tref, ot, r_ptr)
@ WM_OP_EXEC_DEFAULT
Definition: WM_types.h:204
#define KM_PRESS
Definition: WM_types.h:242
#define KM_RELEASE
Definition: WM_types.h:243
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
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
Scene scene
const Depsgraph * depsgraph
GPUBatch * batch
Definition: drawnode.c:3779
uint pos
GPUBatch * quad
IconTextureDrawCall normal
#define sinf(x)
#define cosf(x)
#define copysignf(x, y)
#define fabsf(x)
format
Definition: logImageCore.h:47
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static void area(int d1, int d2, int e1, int e2, float weights[2])
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
Definition: rna_access.c:3033
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:6655
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:866
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
Definition: rna_access.c:6366
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3543
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6413
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
Definition: rna_access.c:6390
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
void RNA_def_property_enum_default(PropertyRNA *prop, int value)
Definition: rna_define.c:2127
void RNA_def_property_ui_text(PropertyRNA *prop, const char *name, const char *description)
Definition: rna_define.c:1676
void RNA_def_property_enum_items(PropertyRNA *prop, const EnumPropertyItem *item)
Definition: rna_define.c:1892
PropertyRNA * RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier, int type, int subtype)
Definition: rna_define.c:1279
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
const EnumPropertyItem rna_enum_axis_xyz_items[]
Definition: rna_modifier.c:584
short ED_gizmotypes_snap_3d_update(wmGizmo *gz, struct Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const wmWindowManager *wm, const float mval_fl[2])
Definition: snap3d_gizmo.c:318
bool ED_gizmotypes_snap_3d_invert_snap_get(struct wmGizmo *gz)
Definition: snap3d_gizmo.c:302
void ED_gizmotypes_snap_3d_data_get(wmGizmo *gz, float r_loc[3], float r_nor[3], int r_elem_index[3], int *r_snap_elem)
Definition: snap3d_gizmo.c:412
void ED_gizmotypes_snap_3d_flag_clear(struct wmGizmo *gz, eSnapGizmo flag)
Definition: snap3d_gizmo.c:290
bool ED_gizmotypes_snap_3d_is_enabled(wmGizmo *gz)
Definition: snap3d_gizmo.c:312
SnapObjectContext * ED_gizmotypes_snap_3d_context_ensure(Scene *scene, const ARegion *region, const View3D *v3d, wmGizmo *gz)
Definition: snap3d_gizmo.c:271
void ED_gizmotypes_snap_3d_flag_set(struct wmGizmo *gz, eSnapGizmo flag)
Definition: snap3d_gizmo.c:284
void * regiondata
struct wmGizmoMap * gizmo_map
struct ARegionType * type
enum ePlace_PrimType primitive_type
float degenerate_diagonal_display[3]
enum ePlace_SnapTo snap_to
struct InteractivePlaceData::@557 step[2]
enum InteractivePlaceData::@558 step_index
void * first
Definition: DNA_listBase.h:47
float persmat_prev[4][4]
wmGizmoGroup * gzgroup
float persmat[4][4]
float viewmat[4][4]
float viewinv[4][4]
float winmat[4][4]
struct ToolSettings * toolsettings
View3DCursor cursor
struct bToolRef * tool
ScrArea_Runtime runtime
float clip_end
char idname[64]
int ymin
Definition: DNA_vec_types.h:80
int xmin
Definition: DNA_vec_types.h:79
short val
Definition: WM_types.h:579
int mval[2]
Definition: WM_types.h:583
short type
Definition: WM_types.h:577
wmGizmoGroupFnInit setup
const char * idname
eWM_GizmoFlagGroupTypeFlag flag
wmGizmoGroupFnPoll poll
struct wmGizmoMapType_Params gzmap_params
const char * name
ListBase gizmos
struct wmGizmoGroupType * type
void(* customdata_free)(void *)
eWM_GizmoFlagState state
struct PointerRNA * ptr
eWM_GizmoFlag flag
const void * modal_items
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
struct PointerRNA * ptr
#define G(x, y, z)
static int dot_v3_array_find_max_index(const float dirs[][3], const int dirs_len, const float dir_test[3], bool is_signed)
static bool idp_snap_point_from_gizmo(wmGizmo *gz, float r_location[3])
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
ePlace_Orient
@ PLACE_ORIENT_SURFACE
@ PLACE_ORIENT_DEFAULT
static wmGizmoGroup * idp_gizmogroup_from_region(ARegion *region)
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 cursor_plane_draw(bContext *C, int x, int y, void *customdata)
static void draw_line_bounds(const BoundBox *bounds, const float color[4])
static bool idp_poject_surface_normal(SnapObjectContext *snap_context, struct Depsgraph *depsgraph, const float mval_fl[2], const float mat_fallback[3][3], const float normal_fallback[3], float r_mat[3][3])
#define FADE(v)
static const float eps_view_align
static void view3d_interactive_add_cancel(bContext *C, wmOperator *op)
static void gizmo_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 void WIDGETGROUP_placement_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
static void preview_plane_cursor_setup(wmGizmoGroup *gzgroup)
static bool idp_snap_point_from_gizmo_ex(wmGizmo *gz, const char *prop_id, float r_location[3])
static void preview_plane_cursor_free(void *customdata)
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 int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEvent *event)
void VIEW3D_GGT_placement(wmGizmoGroupType *gzgt)
ePlace_Origin
@ PLACE_ORIGIN_BASE
@ PLACE_ORIGIN_CENTER
ePlace_Depth
@ PLACE_DEPTH_SURFACE
@ PLACE_DEPTH_CURSOR_PLANE
@ PLACE_DEPTH_CURSOR_VIEW
static bool mat3_align_axis_to_v3(float mat[3][3], const int axis_align, const float v[3])
static int view3d_interactive_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void view3d_interactive_add_exit(bContext *C, wmOperator *op)
static bool idp_snap_normal_from_gizmo(wmGizmo *gz, float r_normal[3])
static void preview_plane_cursor_visible_set(wmGizmoGroup *gzgroup, bool do_draw)
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_snap_gizmo_update_snap_elements(Scene *scene, enum ePlace_SnapTo snap_to, wmGizmo *gizmo)
static void gizmo_plane_update_cursor(const bContext *C, ARegion *region, const int mval[2], float r_co[3], float r_matrix_orient[3][3], int *r_plane_axis)
static void view3d_interactive_add_calc_plane(bContext *C, Scene *scene, View3D *v3d, ARegion *region, const float mval_fl[2], wmGizmo *snap_gizmo, const enum ePlace_SnapTo snap_to, const enum ePlace_Depth plane_depth, const enum ePlace_Orient plane_orient, const int plane_axis, const bool plane_axis_auto, float r_co_src[3], float r_matrix_orient[3][3])
static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEvent *event)
void viewplace_modal_keymap(wmKeyConfig *keyconf)
@ 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
ePlace_Aspect
@ PLACE_ASPECT_FIXED
@ PLACE_ASPECT_FREE
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, short context, PointerRNA *properties)
#define ISTWEAK(event_type)
@ RIGHTMOUSE
@ EVT_MODAL_MAP
@ MOUSEMOVE
@ LEFTMOUSE
@ EVT_ESCKEY
PointerRNA * ptr
Definition: wm_files.c:3157
wmOperatorType * ot
Definition: wm_files.c:3156
wmGizmo * WM_gizmo_new_ptr(const wmGizmoType *gzt, wmGizmoGroup *gzgroup, PointerRNA *properties)
Definition: wm_gizmo.c:96
void WM_gizmo_set_color(wmGizmo *gz, const float color[4])
Definition: wm_gizmo.c:363
bool WM_gizmo_group_type_ensure(const char *idname)
wmGizmoGroup * WM_gizmomap_group_find_ptr(struct wmGizmoMap *gzmap, const struct wmGizmoGroupType *gzgt)
Definition: wm_gizmo_map.c:228
wmGizmoGroup * WM_gizmomap_group_find(struct wmGizmoMap *gzmap, const char *idname)
Definition: wm_gizmo_map.c:219
const wmGizmoType * WM_gizmotype_find(const char *idname, bool quiet)
Definition: wm_gizmo_type.c:58
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)
bool WM_paint_cursor_end(wmPaintCursor *handle)
void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
Definition: wm_operators.c:584
wmPaintCursor * WM_paint_cursor_activate(short space_type, short region_type, bool(*poll)(bContext *C), wmPaintCursorDraw draw, void *customdata)
void WM_operator_properties_free(PointerRNA *ptr)
Definition: wm_operators.c:711
void wmViewport(const rcti *winrct)
Definition: wm_subwindow.c:37
void WM_toolsystem_ref_properties_init_for_keymap(bToolRef *tref, PointerRNA *dst_ptr, PointerRNA *src_ptr, wmOperatorType *ot)