Blender  V2.93
view3d_snap.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  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
24 #include "MEM_guardedalloc.h"
25 
26 #include "DNA_armature_types.h"
27 #include "DNA_object_types.h"
28 
29 #include "BLI_array.h"
30 #include "BLI_math.h"
31 #include "BLI_utildefines.h"
32 
33 #include "BKE_action.h"
34 #include "BKE_armature.h"
35 #include "BKE_context.h"
36 #include "BKE_editmesh.h"
37 #include "BKE_layer.h"
38 #include "BKE_main.h"
39 #include "BKE_mball.h"
40 #include "BKE_object.h"
41 #include "BKE_report.h"
42 #include "BKE_scene.h"
43 #include "BKE_tracking.h"
44 
45 #include "DEG_depsgraph.h"
46 #include "DEG_depsgraph_query.h"
47 
48 #include "WM_api.h"
49 #include "WM_types.h"
50 
51 #include "RNA_access.h"
52 #include "RNA_define.h"
53 
54 #include "ED_keyframing.h"
55 #include "ED_object.h"
56 #include "ED_screen.h"
57 #include "ED_transverts.h"
58 
59 #include "view3d_intern.h"
60 
61 static bool snap_curs_to_sel_ex(bContext *C, float cursor[3]);
62 static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3]);
63 
64 /* -------------------------------------------------------------------- */
70 {
75  ARegion *region = CTX_wm_region(C);
76  View3D *v3d = CTX_wm_view3d(C);
77  TransVertStore tvs = {NULL};
78  TransVert *tv;
79  float gridf, imat[3][3], bmat[3][3], vec[3];
80  int a;
81 
82  gridf = ED_view3d_grid_view_scale(scene, v3d, region, NULL);
83 
84  if (OBEDIT_FROM_OBACT(obact)) {
85  ViewLayer *view_layer = CTX_data_view_layer(C);
86  uint objects_len = 0;
88  view_layer, CTX_wm_view3d(C), &objects_len);
89  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
90  Object *obedit = objects[ob_index];
91 
92  if (obedit->type == OB_MESH) {
94 
95  if (em->bm->totvertsel == 0) {
96  continue;
97  }
98  }
99 
100  if (ED_transverts_check_obedit(obedit)) {
101  ED_transverts_create_from_obedit(&tvs, obedit, 0);
102  }
103 
104  if (tvs.transverts_tot != 0) {
105  copy_m3_m4(bmat, obedit->obmat);
106  invert_m3_m3(imat, bmat);
107 
108  tv = tvs.transverts;
109  for (a = 0; a < tvs.transverts_tot; a++, tv++) {
110  copy_v3_v3(vec, tv->loc);
111  mul_m3_v3(bmat, vec);
112  add_v3_v3(vec, obedit->obmat[3]);
113  vec[0] = gridf * floorf(0.5f + vec[0] / gridf);
114  vec[1] = gridf * floorf(0.5f + vec[1] / gridf);
115  vec[2] = gridf * floorf(0.5f + vec[2] / gridf);
116  sub_v3_v3(vec, obedit->obmat[3]);
117 
118  mul_m3_v3(imat, vec);
119  copy_v3_v3(tv->loc, vec);
120  }
121  ED_transverts_update_obedit(&tvs, obedit);
122  }
123  ED_transverts_free(&tvs);
124  }
125  MEM_freeN(objects);
126  }
127  else if (OBPOSE_FROM_OBACT(obact)) {
129  uint objects_len = 0;
130  Object **objects_eval = BKE_object_pose_array_get(view_layer_eval, v3d, &objects_len);
131  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
132  Object *ob_eval = objects_eval[ob_index];
133  Object *ob = DEG_get_original_object(ob_eval);
134  bPoseChannel *pchan_eval;
135  bArmature *arm_eval = ob_eval->data;
136 
137  invert_m4_m4(ob_eval->imat, ob_eval->obmat);
138 
139  for (pchan_eval = ob_eval->pose->chanbase.first; pchan_eval; pchan_eval = pchan_eval->next) {
140  if (pchan_eval->bone->flag & BONE_SELECTED) {
141  if (pchan_eval->bone->layer & arm_eval->layer) {
142  if ((pchan_eval->bone->flag & BONE_CONNECTED) == 0) {
143  float nLoc[3];
144 
145  /* get nearest grid point to snap to */
146  copy_v3_v3(nLoc, pchan_eval->pose_mat[3]);
147  /* We must operate in world space! */
148  mul_m4_v3(ob_eval->obmat, nLoc);
149  vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf);
150  vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf);
151  vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf);
152  /* Back in object space... */
153  mul_m4_v3(ob_eval->imat, vec);
154 
155  /* Get location of grid point in pose space. */
156  BKE_armature_loc_pose_to_bone(pchan_eval, vec, vec);
157 
158  /* adjust location on the original pchan*/
159  bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, pchan_eval->name);
160  if ((pchan->protectflag & OB_LOCK_LOCX) == 0) {
161  pchan->loc[0] = vec[0];
162  }
163  if ((pchan->protectflag & OB_LOCK_LOCY) == 0) {
164  pchan->loc[1] = vec[1];
165  }
166  if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) {
167  pchan->loc[2] = vec[2];
168  }
169 
170  /* auto-keyframing */
171  ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
172  }
173  /* if the bone has a parent and is connected to the parent,
174  * don't do anything - will break chain unless we do auto-ik.
175  */
176  }
177  }
178  }
179  ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
180 
182  }
183  MEM_freeN(objects_eval);
184  }
185  else {
186  /* Object mode. */
187  Main *bmain = CTX_data_main(C);
188 
190 
191  const bool use_transform_skip_children = (scene->toolsettings->transform_flag &
193  const bool use_transform_data_origin = (scene->toolsettings->transform_flag &
195  struct XFormObjectSkipChild_Container *xcs = NULL;
196  struct XFormObjectData_Container *xds = NULL;
197 
198  /* Build object array. */
199  Object **objects_eval = NULL;
200  uint objects_eval_len;
201  {
202  BLI_array_declare(objects_eval);
203  FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN (view_layer_eval, v3d, ob_eval) {
204  BLI_array_append(objects_eval, ob_eval);
205  }
207  objects_eval_len = BLI_array_len(objects_eval);
208  }
209 
210  if (use_transform_skip_children) {
211  ViewLayer *view_layer = CTX_data_view_layer(C);
212 
213  Object **objects = MEM_malloc_arrayN(objects_eval_len, sizeof(*objects), __func__);
214 
215  for (int ob_index = 0; ob_index < objects_eval_len; ob_index++) {
216  Object *ob_eval = objects_eval[ob_index];
217  objects[ob_index] = DEG_get_original_object(ob_eval);
218  }
222  xcs, view_layer, objects, objects_eval_len);
223  MEM_freeN(objects);
224  }
225  if (use_transform_data_origin) {
228  }
229 
230  for (int ob_index = 0; ob_index < objects_eval_len; ob_index++) {
231  Object *ob_eval = objects_eval[ob_index];
232  Object *ob = DEG_get_original_object(ob_eval);
233  vec[0] = -ob_eval->obmat[3][0] + gridf * floorf(0.5f + ob_eval->obmat[3][0] / gridf);
234  vec[1] = -ob_eval->obmat[3][1] + gridf * floorf(0.5f + ob_eval->obmat[3][1] / gridf);
235  vec[2] = -ob_eval->obmat[3][2] + gridf * floorf(0.5f + ob_eval->obmat[3][2] / gridf);
236 
237  if (ob->parent) {
238  float originmat[3][3];
240 
241  invert_m3_m3(imat, originmat);
242  mul_m3_v3(imat, vec);
243  }
244  if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
245  ob->loc[0] = ob_eval->loc[0] + vec[0];
246  }
247  if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
248  ob->loc[1] = ob_eval->loc[1] + vec[1];
249  }
250  if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
251  ob->loc[2] = ob_eval->loc[2] + vec[2];
252  }
253 
254  /* auto-keyframing */
255  ED_autokeyframe_object(C, scene, ob, ks);
256 
257  if (use_transform_data_origin) {
259  }
260 
262  }
263 
264  if (objects_eval) {
265  MEM_freeN(objects_eval);
266  }
267 
268  if (use_transform_skip_children) {
271  }
272  if (use_transform_data_origin) {
275  }
276  }
277 
279 
280  return OPERATOR_FINISHED;
281 }
282 
284 {
285  /* identifiers */
286  ot->name = "Snap Selection to Grid";
287  ot->description = "Snap selected item(s) to their nearest grid division";
288  ot->idname = "VIEW3D_OT_snap_selected_to_grid";
289 
290  /* api callbacks */
293 
294  /* flags */
296 }
297 
300 /* -------------------------------------------------------------------- */
314  const float snap_target_global[3],
315  const bool use_offset)
316 {
318  Object *obedit = CTX_data_edit_object(C);
319  Object *obact = CTX_data_active_object(C);
320  View3D *v3d = CTX_wm_view3d(C);
321  TransVertStore tvs = {NULL};
322  TransVert *tv;
323  float imat[3][3], bmat[3][3];
324  float center_global[3];
325  float offset_global[3];
326  int a;
327 
328  if (use_offset) {
330  snap_calc_active_center(C, true, center_global)) {
331  /* pass */
332  }
333  else {
334  snap_curs_to_sel_ex(C, center_global);
335  }
336  sub_v3_v3v3(offset_global, snap_target_global, center_global);
337  }
338 
339  if (obedit) {
340  float snap_target_local[3];
341  ViewLayer *view_layer = CTX_data_view_layer(C);
342  uint objects_len = 0;
344  view_layer, CTX_wm_view3d(C), &objects_len);
345  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
346  obedit = objects[ob_index];
347 
348  if (obedit->type == OB_MESH) {
349  BMEditMesh *em = BKE_editmesh_from_object(obedit);
350 
351  if (em->bm->totvertsel == 0) {
352  continue;
353  }
354  }
355 
356  if (ED_transverts_check_obedit(obedit)) {
357  ED_transverts_create_from_obedit(&tvs, obedit, 0);
358  }
359 
360  if (tvs.transverts_tot != 0) {
361  copy_m3_m4(bmat, obedit->obmat);
362  invert_m3_m3(imat, bmat);
363 
364  /* get the cursor in object space */
365  sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]);
366  mul_m3_v3(imat, snap_target_local);
367 
368  if (use_offset) {
369  float offset_local[3];
370 
371  mul_v3_m3v3(offset_local, imat, offset_global);
372 
373  tv = tvs.transverts;
374  for (a = 0; a < tvs.transverts_tot; a++, tv++) {
375  add_v3_v3(tv->loc, offset_local);
376  }
377  }
378  else {
379  tv = tvs.transverts;
380  for (a = 0; a < tvs.transverts_tot; a++, tv++) {
381  copy_v3_v3(tv->loc, snap_target_local);
382  }
383  }
384  ED_transverts_update_obedit(&tvs, obedit);
385  }
386  ED_transverts_free(&tvs);
387  }
388  MEM_freeN(objects);
389  }
390  else if (OBPOSE_FROM_OBACT(obact)) {
392  ViewLayer *view_layer = CTX_data_view_layer(C);
393  uint objects_len = 0;
394  Object **objects = BKE_object_pose_array_get(view_layer, v3d, &objects_len);
395 
396  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
397  Object *ob = objects[ob_index];
398  bPoseChannel *pchan;
399  bArmature *arm = ob->data;
400  float snap_target_local[3];
401 
402  invert_m4_m4(ob->imat, ob->obmat);
403  mul_v3_m4v3(snap_target_local, ob->imat, snap_target_global);
404 
405  for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
406  if ((pchan->bone->flag & BONE_SELECTED) && (PBONE_VISIBLE(arm, pchan->bone)) &&
407  /* if the bone has a parent and is connected to the parent,
408  * don't do anything - will break chain unless we do auto-ik.
409  */
410  (pchan->bone->flag & BONE_CONNECTED) == 0) {
411  pchan->bone->flag |= BONE_TRANSFORM;
412  }
413  else {
414  pchan->bone->flag &= ~BONE_TRANSFORM;
415  }
416  }
417 
418  for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
419  if ((pchan->bone->flag & BONE_TRANSFORM) &&
420  /* check that our parents not transformed (if we have one) */
421  ((pchan->bone->parent &&
423  /* Get position in pchan (pose) space. */
424  float cursor_pose[3];
425 
426  if (use_offset) {
427  mul_v3_m4v3(cursor_pose, ob->obmat, pchan->pose_mat[3]);
428  add_v3_v3(cursor_pose, offset_global);
429 
430  mul_m4_v3(ob->imat, cursor_pose);
431  BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose);
432  }
433  else {
434  BKE_armature_loc_pose_to_bone(pchan, snap_target_local, cursor_pose);
435  }
436 
437  /* copy new position */
438  if ((pchan->protectflag & OB_LOCK_LOCX) == 0) {
439  pchan->loc[0] = cursor_pose[0];
440  }
441  if ((pchan->protectflag & OB_LOCK_LOCY) == 0) {
442  pchan->loc[1] = cursor_pose[1];
443  }
444  if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) {
445  pchan->loc[2] = cursor_pose[2];
446  }
447 
448  /* auto-keyframing */
449  ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
450  }
451  }
452 
453  for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
454  pchan->bone->flag &= ~BONE_TRANSFORM;
455  }
456 
457  ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
458 
460  }
461  MEM_freeN(objects);
462  }
463  else {
465  Main *bmain = CTX_data_main(C);
467 
468  /* Reset flags. */
469  for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
470  ob->flag &= ~OB_DONE;
471  }
472 
473  /* Build object array, tag objects we're transforming. */
474  ViewLayer *view_layer = CTX_data_view_layer(C);
475  Object **objects = NULL;
476  uint objects_len;
477  {
478  BLI_array_declare(objects);
479  FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN (view_layer, v3d, ob) {
480  BLI_array_append(objects, ob);
481  ob->flag |= OB_DONE;
482  }
484  objects_len = BLI_array_len(objects);
485  }
486 
487  const bool use_transform_skip_children = (scene->toolsettings->transform_flag &
489  const bool use_transform_data_origin = (scene->toolsettings->transform_flag &
491  struct XFormObjectSkipChild_Container *xcs = NULL;
492  struct XFormObjectData_Container *xds = NULL;
493 
494  if (use_transform_skip_children) {
498  xcs, view_layer, objects, objects_len);
499  }
500  if (use_transform_data_origin) {
503 
504  /* Initialize the transform data in a separate loop because the depsgraph
505  * may be evaluated while setting the locations. */
506  for (int ob_index = 0; ob_index < objects_len; ob_index++) {
507  Object *ob = objects[ob_index];
509  }
510  }
511 
512  for (int ob_index = 0; ob_index < objects_len; ob_index++) {
513  Object *ob = objects[ob_index];
514 
515  if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) {
516 
517  float cursor_parent[3]; /* parent-relative */
518 
519  if (use_offset) {
520  add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global);
521  }
522  else {
523  copy_v3_v3(cursor_parent, snap_target_global);
524  }
525 
526  sub_v3_v3(cursor_parent, ob->obmat[3]);
527 
528  if (ob->parent) {
529  float originmat[3][3], parentmat[4][4];
530  /* Use the evaluated object here because sometimes
531  * `ob->parent->runtime.curve_cache` is required. */
533  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
534 
535  BKE_object_get_parent_matrix(ob_eval, ob_eval->parent, parentmat);
536  mul_m3_m4m4(originmat, parentmat, ob->parentinv);
537  invert_m3_m3(imat, originmat);
538  mul_m3_v3(imat, cursor_parent);
539  }
540  if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
541  ob->loc[0] += cursor_parent[0];
542  }
543  if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
544  ob->loc[1] += cursor_parent[1];
545  }
546  if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
547  ob->loc[2] += cursor_parent[2];
548  }
549 
550  /* auto-keyframing */
551  ED_autokeyframe_object(C, scene, ob, ks);
552 
554  }
555  }
556 
557  if (objects) {
558  MEM_freeN(objects);
559  }
560 
561  if (use_transform_skip_children) {
564  }
565  if (use_transform_data_origin) {
568  }
569  }
570 
572 
573  return OPERATOR_FINISHED;
574 }
575 
578 /* -------------------------------------------------------------------- */
583 {
584  const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
585 
587 
588  const float *snap_target_global = scene->cursor.location;
589 
590  return snap_selected_to_location(C, snap_target_global, use_offset);
591 }
592 
594 {
595  /* identifiers */
596  ot->name = "Snap Selection to Cursor";
597  ot->description = "Snap selected item(s) to the 3D cursor";
598  ot->idname = "VIEW3D_OT_snap_selected_to_cursor";
599 
600  /* api callbacks */
603 
604  /* flags */
606 
607  /* rna */
609  "use_offset",
610  1,
611  "Offset",
612  "If the selection should be snapped as a whole or by each object center");
613 }
614 
617 /* -------------------------------------------------------------------- */
623 {
624  float snap_target_global[3];
625 
626  if (snap_calc_active_center(C, false, snap_target_global) == false) {
627  BKE_report(op->reports, RPT_ERROR, "No active element found!");
628  return OPERATOR_CANCELLED;
629  }
630 
631  return snap_selected_to_location(C, snap_target_global, false);
632 }
633 
635 {
636  /* identifiers */
637  ot->name = "Snap Selection to Active";
638  ot->description = "Snap selected item(s) to the active item";
639  ot->idname = "VIEW3D_OT_snap_selected_to_active";
640 
641  /* api callbacks */
644 
645  /* flags */
647 }
648 
651 /* -------------------------------------------------------------------- */
657 {
659  ARegion *region = CTX_wm_region(C);
660  View3D *v3d = CTX_wm_view3d(C);
661  float gridf, *curs;
662 
663  gridf = ED_view3d_grid_view_scale(scene, v3d, region, NULL);
664  curs = scene->cursor.location;
665 
666  curs[0] = gridf * floorf(0.5f + curs[0] / gridf);
667  curs[1] = gridf * floorf(0.5f + curs[1] / gridf);
668  curs[2] = gridf * floorf(0.5f + curs[2] / gridf);
669 
672 
673  return OPERATOR_FINISHED;
674 }
675 
677 {
678  /* identifiers */
679  ot->name = "Snap Cursor to Grid";
680  ot->description = "Snap 3D cursor to the nearest grid division";
681  ot->idname = "VIEW3D_OT_snap_cursor_to_grid";
682 
683  /* api callbacks */
686 
687  /* flags */
689 }
690 
693 /* -------------------------------------------------------------------- */
701 static void bundle_midpoint(Scene *scene, Object *ob, float r_vec[3])
702 {
703  MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
704  MovieTracking *tracking;
705  MovieTrackingObject *object;
706  bool ok = false;
707  float min[3], max[3], mat[4][4], pos[3], cammat[4][4];
708 
709  if (!clip) {
710  return;
711  }
712 
713  tracking = &clip->tracking;
714 
715  copy_m4_m4(cammat, ob->obmat);
716 
718 
719  INIT_MINMAX(min, max);
720 
721  for (object = tracking->objects.first; object; object = object->next) {
722  ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
723  MovieTrackingTrack *track = tracksbase->first;
724  float obmat[4][4];
725 
726  if (object->flag & TRACKING_OBJECT_CAMERA) {
727  copy_m4_m4(obmat, mat);
728  }
729  else {
730  float imat[4][4];
731 
733  invert_m4(imat);
734 
735  mul_m4_m4m4(obmat, cammat, imat);
736  }
737 
738  while (track) {
739  if ((track->flag & TRACK_HAS_BUNDLE) && TRACK_SELECTED(track)) {
740  ok = 1;
741  mul_v3_m4v3(pos, obmat, track->bundle_pos);
743  }
744 
745  track = track->next;
746  }
747  }
748 
749  if (ok) {
750  mid_v3_v3v3(r_vec, min, max);
751  }
752 }
753 
755 static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
756 {
759  Object *obedit = CTX_data_edit_object(C);
761  View3D *v3d = CTX_wm_view3d(C);
762  TransVertStore tvs = {NULL};
763  TransVert *tv;
764  float bmat[3][3], vec[3], min[3], max[3], centroid[3];
765  int count = 0;
766 
767  INIT_MINMAX(min, max);
768  zero_v3(centroid);
769 
770  if (obedit) {
771  ViewLayer *view_layer = CTX_data_view_layer(C);
772  uint objects_len = 0;
774  view_layer, CTX_wm_view3d(C), &objects_len);
775  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
776  obedit = objects[ob_index];
777 
778  /* We can do that quick check for meshes only... */
779  if (obedit->type == OB_MESH) {
780  BMEditMesh *em = BKE_editmesh_from_object(obedit);
781 
782  if (em->bm->totvertsel == 0) {
783  continue;
784  }
785  }
786 
787  if (ED_transverts_check_obedit(obedit)) {
789  }
790 
791  count += tvs.transverts_tot;
792  if (tvs.transverts_tot != 0) {
793  Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit);
794  copy_m3_m4(bmat, obedit_eval->obmat);
795 
796  tv = tvs.transverts;
797  for (int i = 0; i < tvs.transverts_tot; i++, tv++) {
798  copy_v3_v3(vec, tv->loc);
799  mul_m3_v3(bmat, vec);
800  add_v3_v3(vec, obedit_eval->obmat[3]);
801  add_v3_v3(centroid, vec);
802  minmax_v3v3_v3(min, max, vec);
803  }
804  }
805  ED_transverts_free(&tvs);
806  }
807  MEM_freeN(objects);
808  }
809  else {
810  Object *obact = CTX_data_active_object(C);
811 
812  if (obact && (obact->mode & OB_MODE_POSE)) {
813  Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
814  bArmature *arm = obact_eval->data;
815  bPoseChannel *pchan;
816  for (pchan = obact_eval->pose->chanbase.first; pchan; pchan = pchan->next) {
817  if (arm->layer & pchan->bone->layer) {
818  if (pchan->bone->flag & BONE_SELECTED) {
819  copy_v3_v3(vec, pchan->pose_head);
820  mul_m4_v3(obact_eval->obmat, vec);
821  add_v3_v3(centroid, vec);
822  minmax_v3v3_v3(min, max, vec);
823  count++;
824  }
825  }
826  }
827  }
828  else {
829  FOREACH_SELECTED_OBJECT_BEGIN (view_layer_eval, v3d, ob_eval) {
830  copy_v3_v3(vec, ob_eval->obmat[3]);
831 
832  /* special case for camera -- snap to bundles */
833  if (ob_eval->type == OB_CAMERA) {
834  /* snap to bundles should happen only when bundles are visible */
835  if (v3d->flag2 & V3D_SHOW_RECONSTRUCTION) {
837  }
838  }
839 
840  add_v3_v3(centroid, vec);
841  minmax_v3v3_v3(min, max, vec);
842  count++;
843  }
845  }
846  }
847 
848  if (count == 0) {
849  return false;
850  }
851 
853  mid_v3_v3v3(cursor, min, max);
854  }
855  else {
856  mul_v3_fl(centroid, 1.0f / (float)count);
857  copy_v3_v3(cursor, centroid);
858  }
859  return true;
860 }
861 
863 {
868 
869  return OPERATOR_FINISHED;
870  }
871  return OPERATOR_CANCELLED;
872 }
873 
875 {
876  /* identifiers */
877  ot->name = "Snap Cursor to Selected";
878  ot->description = "Snap 3D cursor to the middle of the selected item(s)";
879  ot->idname = "VIEW3D_OT_snap_cursor_to_selected";
880 
881  /* api callbacks */
884 
885  /* flags */
887 }
888 
891 /* -------------------------------------------------------------------- */
901 static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3])
902 {
904  if (ob == NULL) {
905  return false;
906  }
907  return ED_object_calc_active_center(ob, select_only, r_center);
908 }
909 
911 {
913 
917 
918  return OPERATOR_FINISHED;
919  }
920  return OPERATOR_CANCELLED;
921 }
922 
924 {
925  /* identifiers */
926  ot->name = "Snap Cursor to Active";
927  ot->description = "Snap 3D cursor to the active item";
928  ot->idname = "VIEW3D_OT_snap_cursor_to_active";
929 
930  /* api callbacks */
933 
934  /* flags */
936 }
937 
940 /* -------------------------------------------------------------------- */
946 {
948  float mat3[3][3];
949  unit_m3(mat3);
950 
952  BKE_scene_cursor_mat3_to_rot(&scene->cursor, mat3, false);
953 
955 
957  return OPERATOR_FINISHED;
958 }
959 
961 {
962  /* identifiers */
963  ot->name = "Snap Cursor to World Origin";
964  ot->description = "Snap 3D cursor to the world origin";
965  ot->idname = "VIEW3D_OT_snap_cursor_to_center";
966 
967  /* api callbacks */
970 
971  /* flags */
973 }
974 
977 /* -------------------------------------------------------------------- */
985 bool ED_view3d_minmax_verts(Object *obedit, float r_min[3], float r_max[3])
986 {
987  TransVertStore tvs = {NULL};
988  TransVert *tv;
989  float centroid[3], vec[3], bmat[3][3];
990 
991  /* Metaballs are an exception. */
992  if (obedit->type == OB_MBALL) {
993  float ob_min[3], ob_max[3];
994  bool changed;
995 
996  changed = BKE_mball_minmax_ex(obedit->data, ob_min, ob_max, obedit->obmat, SELECT);
997  if (changed) {
998  minmax_v3v3_v3(r_min, r_max, ob_min);
999  minmax_v3v3_v3(r_min, r_max, ob_max);
1000  }
1001  return changed;
1002  }
1003 
1004  if (ED_transverts_check_obedit(obedit)) {
1006  }
1007 
1008  if (tvs.transverts_tot == 0) {
1009  return false;
1010  }
1011 
1012  copy_m3_m4(bmat, obedit->obmat);
1013 
1014  tv = tvs.transverts;
1015  for (int a = 0; a < tvs.transverts_tot; a++, tv++) {
1016  copy_v3_v3(vec, (tv->flag & TX_VERT_USE_MAPLOC) ? tv->maploc : tv->loc);
1017  mul_m3_v3(bmat, vec);
1018  add_v3_v3(vec, obedit->obmat[3]);
1019  add_v3_v3(centroid, vec);
1020  minmax_v3v3_v3(r_min, r_max, vec);
1021  }
1022 
1023  ED_transverts_free(&tvs);
1024 
1025  return true;
1026 }
1027 
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
void BKE_armature_loc_pose_to_bone(struct bPoseChannel *pchan, const float inloc[3], float outloc[3])
Definition: armature.c:1853
bool BKE_armature_bone_flag_test_recursive(const struct Bone *bone, int flag)
#define PBONE_VISIBLE(arm, bone)
Definition: BKE_armature.h:338
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1296
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1279
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:760
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1401
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
BMEditMesh * BKE_editmesh_from_object(struct Object *ob)
Return the BMEditMesh for a given object.
Definition: editmesh.c:85
#define FOREACH_SELECTED_EDITABLE_OBJECT_END
Definition: BKE_layer.h:231
#define FOREACH_SELECTED_OBJECT_BEGIN(_view_layer, _v3d, _instance)
Definition: BKE_layer.h:200
#define BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, r_len)
Definition: BKE_layer.h:426
#define FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN(_view_layer, _v3d, _instance)
Definition: BKE_layer.h:218
#define FOREACH_SELECTED_OBJECT_END
Definition: BKE_layer.h:213
bool BKE_mball_minmax_ex(const struct MetaBall *mb, float min[3], float max[3], const float obmat[4][4], const short flag)
General operations, lookup, etc. for blender objects.
struct MovieClip * BKE_object_movieclip_get(struct Scene *scene, struct Object *ob, bool use_default)
Definition: object.c:5079
void BKE_object_get_parent_matrix(struct Object *ob, struct Object *par, float r_parentmat[4][4])
Definition: object.c:3494
struct Object ** BKE_object_pose_array_get(struct ViewLayer *view_layer, struct View3D *v3d, unsigned int *r_objects_len)
Definition: object.c:2556
void BKE_object_where_is_calc_ex(struct Depsgraph *depsgraph, struct Scene *scene, struct RigidBodyWorld *rbw, struct Object *ob, float r_originmat[3][3])
Definition: object.c:3647
bool BKE_object_flag_test_recursive(const struct Object *ob, short flag)
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
void BKE_scene_cursor_mat3_to_rot(struct View3DCursor *cursor, const float mat[3][3], bool use_compat)
Definition: scene.c:3688
void BKE_scene_graph_evaluated_ensure(struct Depsgraph *depsgraph, struct Main *bmain)
Definition: scene.c:2718
void BKE_tracking_get_camera_object_matrix(struct Object *camera_object, float mat[4][4])
Definition: tracking.c:399
void BKE_tracking_camera_get_reconstructed_interpolate(struct MovieTracking *tracking, struct MovieTrackingObject *object, float framenr, float mat[4][4])
Definition: tracking.c:2374
#define TRACK_SELECTED(track)
Definition: BKE_tracking.h:489
struct ListBase * BKE_tracking_object_get_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object)
Definition: tracking.c:2218
A (mainly) macro array library.
#define BLI_array_append(arr, item)
Definition: BLI_array.h:104
#define BLI_array_declare(arr)
Definition: BLI_array.h:62
#define BLI_array_len(arr)
Definition: BLI_array.h:74
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:930
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:262
bool invert_m4(float R[4][4])
Definition: math_matrix.c:1187
void unit_m3(float m[3][3])
Definition: math_matrix.c:58
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:105
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
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 mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:742
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:901
void mul_m3_m4m4(float R[3][3], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:525
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
Definition: math_vector.c:1020
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 add_v3_v3v3(float r[3], const float a[3], const float b[3])
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:270
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
unsigned int uint
Definition: BLI_sys_types.h:83
#define INIT_MINMAX(min, max)
#define UNUSED(x)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
void DEG_id_tag_update(struct ID *id, int flag)
struct Object * DEG_get_original_object(struct Object *object)
struct ViewLayer * DEG_get_evaluated_view_layer(const struct Depsgraph *graph)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:599
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:654
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
@ POSE_LOCKED
@ POSE_DO_UNLOCK
@ BONE_SELECTED
@ BONE_TRANSFORM
@ BONE_CONNECTED
@ OB_MODE_POSE
Object is a sort of wrapper for general info.
#define OB_DONE
@ OB_LOCK_LOCY
@ OB_LOCK_LOCZ
@ OB_LOCK_LOCX
@ OB_MBALL
@ OB_CAMERA
@ OB_MESH
#define OBPOSE_FROM_OBACT(ob)
#define OBEDIT_FROM_OBACT(ob)
@ SCE_XFORM_SKIP_CHILDREN
@ SCE_XFORM_DATA_ORIGIN
@ TRACK_HAS_BUNDLE
@ TRACKING_OBJECT_CAMERA
@ V3D_AROUND_ACTIVE
@ V3D_AROUND_CENTER_BOUNDS
#define V3D_SHOW_RECONSTRUCTION
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
#define ANIM_KS_LOCATION_ID
void ED_object_xform_skip_child_container_item_ensure_from_array(struct XFormObjectSkipChild_Container *xcs, struct ViewLayer *view_layer, struct Object **objects, uint objects_len)
Definition: object_utils.c:183
bool ED_object_calc_active_center(struct Object *ob, const bool select_only, float r_center[3])
Definition: object_utils.c:125
void ED_object_xform_skip_child_container_update_all(struct XFormObjectSkipChild_Container *xcs, struct Main *bmain, struct Depsgraph *depsgraph)
Definition: object_utils.c:270
void ED_object_xform_skip_child_container_destroy(struct XFormObjectSkipChild_Container *xcs)
Definition: object_utils.c:243
struct XFormObjectSkipChild_Container * ED_object_xform_skip_child_container_create(void)
Definition: object_utils.c:174
void ED_object_data_xform_container_destroy(struct XFormObjectData_Container *xds)
Definition: object_utils.c:426
void ED_object_data_xform_container_item_ensure(struct XFormObjectData_Container *xds, struct Object *ob)
Definition: object_utils.c:354
void ED_object_data_xform_container_update_all(struct XFormObjectData_Container *xds, struct Main *bmain, struct Depsgraph *depsgraph)
Definition: object_utils.c:375
struct XFormObjectData_Container * ED_object_data_xform_container_create(void)
Definition: object_utils.c:419
bool ED_operator_view3d_active(struct bContext *C)
Definition: screen_ops.c:230
bool ED_operator_region_view3d_active(struct bContext *C)
Definition: screen_ops.c:235
@ TX_VERT_USE_MAPLOC
Definition: ED_transverts.h:73
bool ED_transverts_check_obedit(Object *obedit)
void ED_transverts_update_obedit(TransVertStore *tvs, struct Object *obedit)
Definition: ed_transverts.c:52
void ED_transverts_free(TransVertStore *tvs)
@ TM_SKIP_HANDLES
Definition: ED_transverts.h:66
@ TM_ALL_JOINTS
Definition: ED_transverts.h:64
void ED_transverts_create_from_obedit(TransVertStore *tvs, struct Object *obedit, const int mode)
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
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:39
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_TRANSFORM
Definition: WM_types.h:357
#define ND_SPACE_VIEW3D
Definition: WM_types.h:423
#define NC_OBJECT
Definition: WM_types.h:280
#define NC_SPACE
Definition: WM_types.h:293
#define SELECT
Scene scene
const Depsgraph * depsgraph
uint pos
int count
#define floorf(x)
bool ED_autokeyframe_object(bContext *C, Scene *scene, Object *ob, KeyingSet *ks)
Definition: keyframing.c:3003
bool ED_autokeyframe_pchan(bContext *C, Scene *scene, Object *ob, bPoseChannel *pchan, KeyingSet *ks)
Definition: keyframing.c:3023
KeyingSet * ANIM_get_keyingset_for_autokeying(const Scene *scene, const char *transformKSName)
Definition: keyingsets.c:725
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
static unsigned a[3]
Definition: RandGen.cpp:92
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
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
#define min(a, b)
Definition: sort.c:51
struct BMesh * bm
Definition: BKE_editmesh.h:52
int totvertsel
Definition: bmesh_class.h:298
struct Bone * parent
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
ListBase objects
Definition: BKE_main.h:148
struct MovieTracking tracking
struct MovieTrackingObject * next
struct MovieTrackingTrack * next
struct bPose * pose
float loc[3]
float imat[4][4]
float parentinv[4][4]
float obmat[4][4]
short protectflag
struct Object * parent
void * data
struct ToolSettings * toolsettings
struct RenderData r
View3DCursor cursor
char transform_pivot_point
struct TransVert * transverts
Definition: ED_transverts.h:40
float * loc
Definition: ED_transverts.h:33
float maploc[3]
Definition: ED_transverts.h:34
unsigned int layer
struct Bone * bone
float pose_head[3]
struct bPoseChannel * next
float pose_mat[4][4]
ListBase chanbase
short flag
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
struct ReportList * reports
struct PointerRNA * ptr
float max
bool ED_view3d_minmax_verts(Object *obedit, float r_min[3], float r_max[3])
Definition: view3d_snap.c:985
static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
Definition: view3d_snap.c:69
void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
Definition: view3d_snap.c:676
static void bundle_midpoint(Scene *scene, Object *ob, float r_vec[3])
Definition: view3d_snap.c:701
static int snap_curs_to_active_exec(bContext *C, wmOperator *UNUSED(op))
Definition: view3d_snap.c:910
static int snap_curs_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
Definition: view3d_snap.c:656
void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
Definition: view3d_snap.c:283
void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
Definition: view3d_snap.c:874
static int snap_selected_to_active_exec(bContext *C, wmOperator *op)
Definition: view3d_snap.c:622
void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot)
Definition: view3d_snap.c:960
static int snap_curs_to_sel_exec(bContext *C, wmOperator *UNUSED(op))
Definition: view3d_snap.c:862
static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3])
Definition: view3d_snap.c:901
static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset)
Definition: view3d_snap.c:313
static int snap_selected_to_cursor_exec(bContext *C, wmOperator *op)
Definition: view3d_snap.c:582
void VIEW3D_OT_snap_selected_to_active(wmOperatorType *ot)
Definition: view3d_snap.c:634
static int snap_curs_to_center_exec(bContext *C, wmOperator *UNUSED(op))
Definition: view3d_snap.c:945
static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
Definition: view3d_snap.c:755
void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
Definition: view3d_snap.c:923
void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
Definition: view3d_snap.c:593
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3156