Blender V4.5
view3d_snap.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
10#include "DNA_object_types.h"
12
13#include "BLI_bounds.hh"
14#include "BLI_listbase.h"
15#include "BLI_math_matrix.h"
16#include "BLI_math_matrix.hh"
17#include "BLI_math_rotation.h"
18#include "BLI_math_vector.h"
19#include "BLI_math_vector.hh"
20#include "BLI_utildefines.h"
21#include "BLI_vector.hh"
22
23#include "BKE_action.hh"
24#include "BKE_armature.hh"
25#include "BKE_context.hh"
26#include "BKE_crazyspace.hh"
27#include "BKE_editmesh.hh"
28#include "BKE_layer.hh"
29#include "BKE_main.hh"
30#include "BKE_mball.hh"
31#include "BKE_object.hh"
32#include "BKE_report.hh"
33#include "BKE_scene.hh"
34#include "BKE_tracking.h"
35
36#include "DEG_depsgraph.hh"
38
39#include "WM_api.hh"
40#include "WM_types.hh"
41
42#include "RNA_access.hh"
43#include "RNA_define.hh"
44
45#include "ED_anim_api.hh"
46#include "ED_curves.hh"
47#include "ED_grease_pencil.hh"
48#include "ED_keyframing.hh"
49#include "ED_object.hh"
50#include "ED_pointcloud.hh"
51#include "ED_screen.hh"
52#include "ED_transverts.hh"
53
54#include "ANIM_action.hh"
55#include "ANIM_armature.hh"
57#include "ANIM_keyframing.hh"
58#include "ANIM_keyingsets.hh"
59
60#include "view3d_intern.hh"
61
62using blender::Vector;
63
64static bool snap_curs_to_sel_ex(bContext *C, const int pivot_point, float r_cursor[3]);
65static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3]);
66
67/* -------------------------------------------------------------------- */
70
73{
74 using namespace blender::ed;
78 Scene *scene = CTX_data_scene(C);
79 ARegion *region = CTX_wm_region(C);
80 View3D *v3d = CTX_wm_view3d(C);
81 TransVertStore tvs = {nullptr};
82 TransVert *tv;
83 float gridf, imat[3][3], bmat[3][3], vec[3];
84 int a;
85
86 gridf = ED_view3d_grid_view_scale(scene, v3d, region, nullptr);
87
88 if (OBEDIT_FROM_OBACT(obact)) {
89 ViewLayer *view_layer = CTX_data_view_layer(C);
91 scene, view_layer, CTX_wm_view3d(C));
92 for (Object *obedit : objects) {
93 if (obedit->type == OB_MESH) {
95
96 if (em->bm->totvertsel == 0) {
97 continue;
98 }
99 }
100
102 continue;
103 }
104
105 if (ED_transverts_check_obedit(obedit)) {
106 ED_transverts_create_from_obedit(&tvs, obedit, 0);
107 }
108
109 if (tvs.transverts_tot != 0) {
110 copy_m3_m4(bmat, obedit->object_to_world().ptr());
111 invert_m3_m3(imat, bmat);
112
113 tv = tvs.transverts;
114 for (a = 0; a < tvs.transverts_tot; a++, tv++) {
115 copy_v3_v3(vec, tv->loc);
116 mul_m3_v3(bmat, vec);
117 add_v3_v3(vec, obedit->object_to_world().location());
118 vec[0] = gridf * floorf(0.5f + vec[0] / gridf);
119 vec[1] = gridf * floorf(0.5f + vec[1] / gridf);
120 vec[2] = gridf * floorf(0.5f + vec[2] / gridf);
121 sub_v3_v3(vec, obedit->object_to_world().location());
122
123 mul_m3_v3(imat, vec);
124 copy_v3_v3(tv->loc, vec);
125 }
126 ED_transverts_update_obedit(&tvs, obedit);
127 }
128 ED_transverts_free(&tvs);
129 }
130 }
131 else if (OBPOSE_FROM_OBACT(obact)) {
133 Vector<Object *> objects_eval = BKE_object_pose_array_get(scene, view_layer_eval, v3d);
134 for (Object *ob_eval : objects_eval) {
135 Object *ob = DEG_get_original(ob_eval);
136 bArmature *arm_eval = static_cast<bArmature *>(ob_eval->data);
137
138 invert_m4_m4(ob_eval->runtime->world_to_object.ptr(), ob_eval->object_to_world().ptr());
139
140 LISTBASE_FOREACH (bPoseChannel *, pchan_eval, &ob_eval->pose->chanbase) {
141 if (pchan_eval->bone->flag & BONE_SELECTED) {
142 if (ANIM_bonecoll_is_visible_pchan(arm_eval, pchan_eval)) {
143 if ((pchan_eval->bone->flag & BONE_CONNECTED) == 0) {
144 float nLoc[3];
145
146 /* get nearest grid point to snap to */
147 copy_v3_v3(nLoc, pchan_eval->pose_mat[3]);
148 /* We must operate in world space! */
149 mul_m4_v3(ob_eval->object_to_world().ptr(), nLoc);
150 vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf);
151 vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf);
152 vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf);
153 /* Back in object space... */
154 mul_m4_v3(ob_eval->world_to_object().ptr(), vec);
155
156 /* Get location of grid point in pose space. */
157 BKE_armature_loc_pose_to_bone(pchan_eval, vec, vec);
158
159 /* Adjust location on the original pchan. */
160 bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, pchan_eval->name);
162
163 /* auto-keyframing */
164 blender::animrig::autokeyframe_pchan(C, scene, ob, pchan, ks);
165 }
166 /* if the bone has a parent and is connected to the parent,
167 * don't do anything - will break chain unless we do auto-ik.
168 */
169 }
170 }
171 }
173
175 }
176 }
177 else {
178 /* Object mode. */
179 Main *bmain = CTX_data_main(C);
180
182
183 const bool use_transform_skip_children = (scene->toolsettings->transform_flag &
185 const bool use_transform_data_origin = (scene->toolsettings->transform_flag &
189
190 /* Build object array. */
191 Vector<Object *> objects_eval;
192 Vector<Object *> objects_orig;
193 {
194 FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN (view_layer_eval, v3d, ob_eval) {
195 objects_eval.append(ob_eval);
196 objects_orig.append(DEG_get_original(ob_eval));
197 }
199 }
200
201 if (use_transform_skip_children) {
202 ViewLayer *view_layer = CTX_data_view_layer(C);
203
204 Vector<Object *> objects(objects_eval.size());
205 for (Object *ob_eval : objects_eval) {
206 objects.append_unchecked(DEG_get_original(ob_eval));
207 }
211 xcs, scene, view_layer, objects.data(), objects.size());
212 }
213 if (use_transform_data_origin) {
216 }
217
220 }
221
222 for (Object *ob_eval : objects_eval) {
223 Object *ob = DEG_get_original(ob_eval);
224 vec[0] = -ob_eval->object_to_world().location()[0] +
225 gridf * floorf(0.5f + ob_eval->object_to_world().location()[0] / gridf);
226 vec[1] = -ob_eval->object_to_world().location()[1] +
227 gridf * floorf(0.5f + ob_eval->object_to_world().location()[1] / gridf);
228 vec[2] = -ob_eval->object_to_world().location()[2] +
229 gridf * floorf(0.5f + ob_eval->object_to_world().location()[2] / gridf);
230
231 if (ob->parent) {
232 float originmat[3][3];
233 BKE_object_where_is_calc_ex(depsgraph, scene, nullptr, ob, originmat);
234
235 invert_m3_m3(imat, originmat);
236 mul_m3_v3(imat, vec);
237 }
238
239 const blender::float3 loc_final = blender::float3(ob_eval->loc) + blender::float3(vec);
241
242 /* auto-keyframing */
244
245 if (use_transform_data_origin) {
247 }
248
250 }
251
252 if (use_transform_skip_children) {
255 }
256 if (use_transform_data_origin) {
259 }
260 }
261
263
264 return OPERATOR_FINISHED;
265}
266
268{
269 /* identifiers */
270 ot->name = "Snap Selection to Grid";
271 ot->description = "Snap selected item(s) to their nearest grid division";
272 ot->idname = "VIEW3D_OT_snap_selected_to_grid";
273
274 /* API callbacks. */
277
278 /* flags */
280}
281
283
284/* -------------------------------------------------------------------- */
287
303 wmOperator *op,
304 const blender::float3 &target_loc_global,
305 const View3DCursor *target_orientation_global,
306 const bool use_offset,
307 const int pivot_point,
308 const bool use_toolsettings)
309{
310 using namespace blender::ed;
311 Scene *scene = CTX_data_scene(C);
312 Object *obedit = CTX_data_edit_object(C);
314 View3D *v3d = CTX_wm_view3d(C);
315 TransVertStore tvs = {nullptr};
316 TransVert *tv;
317 float imat[3][3], bmat[3][3];
318 float center_global[3];
319 float offset_global[3];
320 int a;
321
322 /* Some use of this needs to transform into local-space. */
323 const bool use_rotation = target_orientation_global != nullptr;
324 const blender::float3x3 target_rot_global =
325 target_orientation_global ? target_orientation_global->matrix<blender::float3x3>() :
327
328 if (use_offset) {
329 if ((pivot_point == V3D_AROUND_ACTIVE) && snap_calc_active_center(C, true, center_global)) {
330 /* pass */
331 }
332 else {
333 snap_curs_to_sel_ex(C, pivot_point, center_global);
334 }
335 sub_v3_v3v3(offset_global, target_loc_global, center_global);
336 }
337
338 if (obedit) {
339 blender::float3 target_loc_local;
340 ViewLayer *view_layer = CTX_data_view_layer(C);
342 scene, view_layer, v3d);
343 for (const int ob_index : objects.index_range()) {
344 obedit = objects[ob_index];
345
346 if (obedit->type == OB_MESH) {
348
349 if (em->bm->totvertsel == 0) {
350 continue;
351 }
352 }
353
355 continue;
356 }
357
358 if (ED_transverts_check_obedit(obedit)) {
359 ED_transverts_create_from_obedit(&tvs, obedit, 0);
360 }
361
362 if (tvs.transverts_tot != 0) {
363 copy_m3_m4(bmat, obedit->object_to_world().ptr());
364 invert_m3_m3(imat, bmat);
365
366 /* Get the `target_loc_global` in object space. */
367 sub_v3_v3v3(target_loc_local, target_loc_global, obedit->object_to_world().location());
368 mul_m3_v3(imat, target_loc_local);
369
370 if (use_offset) {
371 blender::float3 offset_local;
372
373 mul_v3_m3v3(offset_local, imat, offset_global);
374
375 tv = tvs.transverts;
376 for (a = 0; a < tvs.transverts_tot; a++, tv++) {
377 add_v3_v3(tv->loc, offset_local);
378 }
379 }
380 else {
381 tv = tvs.transverts;
382 for (a = 0; a < tvs.transverts_tot; a++, tv++) {
383 copy_v3_v3(tv->loc, target_loc_local);
384 }
385 }
386 ED_transverts_update_obedit(&tvs, obedit);
387 }
388 ED_transverts_free(&tvs);
389 }
390 }
391 else if (OBPOSE_FROM_OBACT(obact)) {
393 ViewLayer *view_layer = CTX_data_view_layer(C);
394 Vector<Object *> objects = BKE_object_pose_array_get(scene, view_layer, v3d);
395 Main *bmain = CTX_data_main(C);
398
399 for (Object *ob : objects) {
400 bArmature *arm = static_cast<bArmature *>(ob->data);
401 blender::float3 target_loc_local;
402
403 invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
404 mul_v3_m4v3(target_loc_local, ob->world_to_object().ptr(), target_loc_global);
405
406 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
407 if ((pchan->bone->flag & BONE_SELECTED) &&
409 /* if the bone has a parent and is connected to the parent,
410 * don't do anything - will break chain unless we do auto-ik.
411 */
412 (pchan->bone->flag & BONE_CONNECTED) == 0)
413 {
414 pchan->bone->flag |= BONE_TRANSFORM;
415 }
416 else {
417 pchan->bone->flag &= ~BONE_TRANSFORM;
418 }
419 }
420
421 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
422 if ((pchan->bone->flag & BONE_TRANSFORM) &&
423 /* check that our parents not transformed (if we have one) */
424 ((pchan->bone->parent &&
425 BKE_armature_bone_flag_test_recursive(pchan->bone->parent, BONE_TRANSFORM)) == 0))
426 {
427 /* Get position in pchan (pose) space. */
428 blender::float3 target_loc_pose;
429
430 if (use_offset) {
431 mul_v3_m4v3(target_loc_pose, ob->object_to_world().ptr(), pchan->pose_mat[3]);
432 add_v3_v3(target_loc_pose, offset_global);
433
434 if (use_rotation) {
435 sub_v3_v3(target_loc_pose, target_loc_global);
436 mul_m3_v3(target_rot_global.ptr(), target_loc_pose);
437 add_v3_v3(target_loc_pose, target_loc_global);
438 }
439
440 mul_m4_v3(ob->world_to_object().ptr(), target_loc_pose);
441 BKE_armature_loc_pose_to_bone(pchan, target_loc_pose, target_loc_pose);
442 }
443 else {
444 BKE_armature_loc_pose_to_bone(pchan, target_loc_local, target_loc_pose);
445 }
446
447 if (use_rotation) {
448 BKE_pchan_mat3_to_rot(pchan, target_rot_global.ptr(), false);
449
450 if (pchan->rotmode == ROT_MODE_QUAT) {
451 float quat[4];
452 mat3_normalized_to_quat(quat, target_rot_global.ptr());
453
454 if (use_toolsettings) {
456 }
457 else {
458 copy_v4_v4(pchan->quat, quat);
459 }
460 }
461 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
462 float rot_axis[3];
463 float rot_angle;
464 mat3_to_axis_angle(rot_axis, &rot_angle, target_rot_global.ptr());
465
466 if (use_toolsettings) {
467 BKE_pchan_protected_rotation_axisangle_set(pchan, rot_axis, rot_angle);
468 }
469 else {
470 copy_v3_v3(pchan->rotAxis, rot_axis);
471 pchan->rotAngle = rot_angle;
472 }
473 }
474 else {
475 float rot_euler[3];
476 mat3_to_eulO(rot_euler, pchan->rotmode, target_rot_global.ptr());
477
478 if (use_toolsettings) {
480 }
481 else {
482 copy_v3_v3(pchan->eul, rot_euler);
483 }
484 }
485 }
486
487 /* copy new position */
488 if (use_toolsettings) {
489 BKE_pchan_protected_location_set(pchan, target_loc_pose);
490
491 /* auto-keyframing */
492 blender::animrig::autokeyframe_pchan(C, scene, ob, pchan, ks);
493 }
494 else {
495 copy_v3_v3(pchan->loc, target_loc_pose);
496 }
497 }
498 }
499
500 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
501 pchan->bone->flag &= ~BONE_TRANSFORM;
502 }
503
504 ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
505
507 }
508 }
509 else {
511 Main *bmain = CTX_data_main(C);
514
515 /* Reset flags. */
516 for (Object *ob = static_cast<Object *>(bmain->objects.first); ob;
517 ob = static_cast<Object *>(ob->id.next))
518 {
519 ob->flag &= ~OB_DONE;
520 }
521
522 /* Build object array, tag objects we're transforming. */
523 ViewLayer *view_layer = CTX_data_view_layer(C);
524 Vector<Object *> objects;
525 {
526 FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN (view_layer, v3d, ob) {
527 objects.append(ob);
528 ob->flag |= OB_DONE;
529 }
531 }
532
533 const bool use_transform_skip_children = use_toolsettings &&
536 const bool use_transform_data_origin = use_toolsettings &&
541
542 if (use_transform_skip_children) {
545 xcs, scene, view_layer, objects.data(), objects.size());
546 }
547 if (use_transform_data_origin) {
549
550 /* Initialize the transform data in a separate loop because the depsgraph
551 * may be evaluated while setting the locations. */
552 for (Object *ob : objects) {
554 }
555 }
556
559 }
560
561 for (Object *ob : objects) {
562 if (ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) {
563 continue;
564 }
565
566 blender::float3 target_loc_local; /* parent-relative */
567
568 if (use_offset) {
569 add_v3_v3v3(target_loc_local, ob->object_to_world().location(), offset_global);
570
571 if (use_rotation) {
572 sub_v3_v3(target_loc_local, target_loc_global);
573 mul_m3_v3(target_rot_global.ptr(), target_loc_local);
574 add_v3_v3(target_loc_local, target_loc_global);
575 }
576 }
577 else {
578 copy_v3_v3(target_loc_local, target_loc_global);
579 }
580 sub_v3_v3(target_loc_local, ob->object_to_world().location());
581
582 /* Calculate a parent relative copy. */
583 blender::float3x3 target_rot = target_rot_global;
584 if (ob->parent) {
585 float originmat[3][3], parentmat[4][4];
586 /* Use the evaluated object here because sometimes
587 * `ob->parent->runtime->curve_cache` is required. */
589 Object *ob_eval = DEG_get_evaluated(depsgraph, ob);
590
591 BKE_object_get_parent_matrix(ob_eval, ob_eval->parent, parentmat);
592 mul_m3_m4m4(originmat, parentmat, ob->parentinv);
593 invert_m3_m3(imat, originmat);
594 mul_m3_v3(imat, target_loc_local);
595 mul_m3_m3m3(target_rot.ptr(), imat, target_rot.ptr());
596 }
597 if (use_toolsettings) {
598 const blender::float3 loc_final = blender::float3(ob->loc) + target_loc_local;
600
601 /* auto-keyframing */
603 }
604 else {
605 add_v3_v3(ob->loc, target_loc_local);
606 }
607
608 if (use_rotation) {
609 const bool assign_rotation_directly = (ob->rotmode ==
610 target_orientation_global->rotation_mode &&
611 ob->parent == nullptr);
612
613 if (ob->rotmode == ROT_MODE_QUAT) {
614 float quat[4];
615 if (assign_rotation_directly) {
616 copy_v4_v4(quat, target_orientation_global->rotation_quaternion);
617 }
618 else {
619 mat3_normalized_to_quat(quat, target_rot.ptr());
620 }
621 if (use_toolsettings) {
623 }
624 else {
625 copy_v4_v4(ob->quat, quat);
626 }
627 }
628 else if (ob->rotmode == ROT_MODE_AXISANGLE) {
629 float rot_axis[3];
630 float rot_angle;
631 if (assign_rotation_directly) {
632 copy_v3_v3(rot_axis, target_orientation_global->rotation_axis);
633 rot_angle = target_orientation_global->rotation_angle;
634 }
635 else {
636 mat3_to_axis_angle(rot_axis, &rot_angle, target_rot.ptr());
637 }
638 if (use_toolsettings) {
639 BKE_object_protected_rotation_axisangle_set(ob, rot_axis, rot_angle);
640 }
641 else {
642 copy_v3_v3(ob->rotAxis, rot_axis);
643 ob->rotAngle = rot_angle;
644 }
645 }
646 else {
647 float rot_euler[3];
648 if (assign_rotation_directly) {
649 copy_v3_v3(rot_euler, target_orientation_global->rotation_euler);
650 }
651 else {
652 mat3_to_eulO(rot_euler, ob->rotmode, target_rot.ptr());
653 }
654 if (use_toolsettings) {
656 }
657 else {
658 copy_v3_v3(ob->rot, rot_euler);
659 }
660 }
661
662 /* auto-keyframing */
664 }
665
667 }
668
669 if (use_transform_skip_children) {
672 }
673 if (use_transform_data_origin) {
676 }
677 }
678
680
681 return true;
682}
683
685 wmOperator *op,
686 const float target_loc_global[3],
687 const int pivot_point)
688{
689 /* These could be passed as arguments if needed. */
690 /* Always use pivot point. */
691 const bool use_offset = true;
692 /* Disable object protected flags & auto-keyframing,
693 * so this can be used as a low level function. */
694 const bool use_toolsettings = false;
696 C, op, target_loc_global, nullptr, use_offset, pivot_point, use_toolsettings);
697}
698
700
701/* -------------------------------------------------------------------- */
704
706{
707 const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
708 const bool use_rotation = RNA_boolean_get(op->ptr, "use_rotation");
709
710 Scene *scene = CTX_data_scene(C);
711
712 const float *target_loc_global = scene->cursor.location;
713 const View3DCursor *snap_orientation = use_rotation ? &scene->cursor : nullptr;
714 const int pivot_point = scene->toolsettings->transform_pivot_point;
715
717 C, op, target_loc_global, snap_orientation, use_offset, pivot_point, true))
718 {
719 return OPERATOR_FINISHED;
720 }
721 return OPERATOR_CANCELLED;
722}
723
725{
726 /* identifiers */
727 ot->name = "Snap Selection to Cursor";
728 ot->description = "Snap selected item(s) to the 3D cursor";
729 ot->idname = "VIEW3D_OT_snap_selected_to_cursor";
730
731 /* API callbacks. */
734
735 /* flags */
737
738 /* rna */
739 RNA_def_boolean(ot->srna,
740 "use_offset",
741 true,
742 "Offset",
743 "If the selection should be snapped as a whole or by each object center");
744 RNA_def_boolean(ot->srna,
745 "use_rotation",
746 false,
747 "Rotation",
748 "If the selection should be rotated to match the cursor");
749}
750
752
753/* -------------------------------------------------------------------- */
756
759{
760 float target_loc_global[3];
761
762 if (snap_calc_active_center(C, false, target_loc_global) == false) {
763 BKE_report(op->reports, RPT_ERROR, "No active element found!");
764 return OPERATOR_CANCELLED;
765 }
766
767 if (!snap_selected_to_location_rotation(C, op, target_loc_global, nullptr, false, -1, true)) {
768 return OPERATOR_CANCELLED;
769 }
770 return OPERATOR_FINISHED;
771}
772
774{
775 /* identifiers */
776 ot->name = "Snap Selection to Active";
777 ot->description = "Snap selected item(s) to the active item";
778 ot->idname = "VIEW3D_OT_snap_selected_to_active";
779
780 /* API callbacks. */
783
784 /* flags */
786}
787
789
790/* -------------------------------------------------------------------- */
793
796{
797 Scene *scene = CTX_data_scene(C);
798 ARegion *region = CTX_wm_region(C);
799 View3D *v3d = CTX_wm_view3d(C);
800 float gridf, *curs;
801
802 gridf = ED_view3d_grid_view_scale(scene, v3d, region, nullptr);
803 curs = scene->cursor.location;
804
805 curs[0] = gridf * floorf(0.5f + curs[0] / gridf);
806 curs[1] = gridf * floorf(0.5f + curs[1] / gridf);
807 curs[2] = gridf * floorf(0.5f + curs[2] / gridf);
808
809 WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, nullptr); /* hrm */
811
812 return OPERATOR_FINISHED;
813}
814
816{
817 /* identifiers */
818 ot->name = "Snap Cursor to Grid";
819 ot->description = "Snap 3D cursor to the nearest grid division";
820 ot->idname = "VIEW3D_OT_snap_cursor_to_grid";
821
822 /* API callbacks. */
825
826 /* flags */
827 ot->flag = OPTYPE_REGISTER;
828}
829
831
832/* -------------------------------------------------------------------- */
835
840static void bundle_midpoint(Scene *scene, Object *ob, float r_vec[3])
841{
842 MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
843 bool ok = false;
844 float min[3], max[3], mat[4][4], pos[3], cammat[4][4];
845
846 if (!clip) {
847 return;
848 }
849
850 MovieTracking *tracking = &clip->tracking;
851
852 copy_m4_m4(cammat, ob->object_to_world().ptr());
853
855
857
858 LISTBASE_FOREACH (MovieTrackingObject *, tracking_object, &tracking->objects) {
859 float obmat[4][4];
860
861 if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
862 copy_m4_m4(obmat, mat);
863 }
864 else {
865 float imat[4][4];
866
868 tracking, tracking_object, scene->r.cfra, imat);
869 invert_m4(imat);
870
871 mul_m4_m4m4(obmat, cammat, imat);
872 }
873
874 LISTBASE_FOREACH (const MovieTrackingTrack *, track, &tracking_object->tracks) {
875 if ((track->flag & TRACK_HAS_BUNDLE) && TRACK_SELECTED(track)) {
876 ok = true;
877 mul_v3_m4v3(pos, obmat, track->bundle_pos);
879 }
880 }
881 }
882
883 if (ok) {
884 mid_v3_v3v3(r_vec, min, max);
885 }
886}
887
889static bool snap_curs_to_sel_ex(bContext *C, const int pivot_point, float r_cursor[3])
890{
893 Object *obedit = CTX_data_edit_object(C);
894 Scene *scene = CTX_data_scene(C);
895 View3D *v3d = CTX_wm_view3d(C);
896 TransVertStore tvs = {nullptr};
897 TransVert *tv;
898 float bmat[3][3], vec[3], min[3], max[3], centroid[3];
899 int count = 0;
900
902 zero_v3(centroid);
903
904 if (obedit) {
905 ViewLayer *view_layer = CTX_data_view_layer(C);
907 scene, view_layer, CTX_wm_view3d(C));
908 for (const int ob_index : objects.index_range()) {
909 obedit = objects[ob_index];
910
911 /* We can do that quick check for meshes only... */
912 if (obedit->type == OB_MESH) {
914
915 if (em->bm->totvertsel == 0) {
916 continue;
917 }
918 }
919
920 if (ED_transverts_check_obedit(obedit)) {
922 }
923
924 count += tvs.transverts_tot;
925 if (tvs.transverts_tot != 0) {
926 Object *obedit_eval = DEG_get_evaluated(depsgraph, obedit);
927 copy_m3_m4(bmat, obedit_eval->object_to_world().ptr());
928
929 tv = tvs.transverts;
930 for (int i = 0; i < tvs.transverts_tot; i++, tv++) {
931 copy_v3_v3(vec, tv->loc);
932 mul_m3_v3(bmat, vec);
933 add_v3_v3(vec, obedit_eval->object_to_world().location());
934 add_v3_v3(centroid, vec);
935 minmax_v3v3_v3(min, max, vec);
936 }
937 }
938 ED_transverts_free(&tvs);
939 }
940 }
941 else {
943
944 if (obact && (obact->mode & OB_MODE_POSE)) {
945 Object *obact_eval = DEG_get_evaluated(depsgraph, obact);
946 bArmature *arm = static_cast<bArmature *>(obact_eval->data);
947 LISTBASE_FOREACH (bPoseChannel *, pchan, &obact_eval->pose->chanbase) {
948 if (ANIM_bonecoll_is_visible_pchan(arm, pchan)) {
949 if (pchan->bone->flag & BONE_SELECTED) {
950 copy_v3_v3(vec, pchan->pose_head);
951 mul_m4_v3(obact_eval->object_to_world().ptr(), vec);
952 add_v3_v3(centroid, vec);
953 minmax_v3v3_v3(min, max, vec);
954 count++;
955 }
956 }
957 }
958 }
959 else {
960 FOREACH_SELECTED_OBJECT_BEGIN (view_layer_eval, v3d, ob_eval) {
961 copy_v3_v3(vec, ob_eval->object_to_world().location());
962
963 /* special case for camera -- snap to bundles */
964 if (ob_eval->type == OB_CAMERA) {
965 /* snap to bundles should happen only when bundles are visible */
966 if (v3d->flag2 & V3D_SHOW_RECONSTRUCTION) {
967 bundle_midpoint(scene, DEG_get_original(ob_eval), vec);
968 }
969 }
970
971 add_v3_v3(centroid, vec);
972 minmax_v3v3_v3(min, max, vec);
973 count++;
974 }
976 }
977 }
978
979 if (count == 0) {
980 return false;
981 }
982
983 if (pivot_point == V3D_AROUND_CENTER_BOUNDS) {
984 mid_v3_v3v3(r_cursor, min, max);
985 }
986 else {
987 mul_v3_fl(centroid, 1.0f / float(count));
988 copy_v3_v3(r_cursor, centroid);
989 }
990 return true;
991}
992
994{
995 Scene *scene = CTX_data_scene(C);
996 const int pivot_point = scene->toolsettings->transform_pivot_point;
997 if (snap_curs_to_sel_ex(C, pivot_point, scene->cursor.location)) {
1000
1001 return OPERATOR_FINISHED;
1002 }
1003 return OPERATOR_CANCELLED;
1004}
1005
1007{
1008 /* identifiers */
1009 ot->name = "Snap Cursor to Selected";
1010 ot->description = "Snap 3D cursor to the middle of the selected item(s)";
1011 ot->idname = "VIEW3D_OT_snap_cursor_to_selected";
1012
1013 /* API callbacks. */
1014 ot->exec = snap_curs_to_sel_exec;
1016
1017 /* flags */
1018 ot->flag = OPTYPE_REGISTER;
1019}
1020
1022
1023/* -------------------------------------------------------------------- */
1026
1033static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3])
1034{
1036 if (ob == nullptr) {
1037 return false;
1038 }
1039 return blender::ed::object::calc_active_center(ob, select_only, r_center);
1040}
1041
1043{
1044 Scene *scene = CTX_data_scene(C);
1045
1046 if (snap_calc_active_center(C, false, scene->cursor.location)) {
1049
1050 return OPERATOR_FINISHED;
1051 }
1052 return OPERATOR_CANCELLED;
1053}
1054
1056{
1057 /* identifiers */
1058 ot->name = "Snap Cursor to Active";
1059 ot->description = "Snap 3D cursor to the active item";
1060 ot->idname = "VIEW3D_OT_snap_cursor_to_active";
1061
1062 /* API callbacks. */
1065
1066 /* flags */
1067 ot->flag = OPTYPE_REGISTER;
1068}
1069
1071
1072/* -------------------------------------------------------------------- */
1075
1078{
1079 Scene *scene = CTX_data_scene(C);
1080
1081 scene->cursor.set_matrix(blender::float4x4::identity(), false);
1082
1084
1086 return OPERATOR_FINISHED;
1087}
1088
1090{
1091 /* identifiers */
1092 ot->name = "Snap Cursor to World Origin";
1093 ot->description = "Snap 3D cursor to the world origin";
1094 ot->idname = "VIEW3D_OT_snap_cursor_to_center";
1095
1096 /* API callbacks. */
1099
1100 /* flags */
1101 ot->flag = OPTYPE_REGISTER;
1102}
1103
1105
1106/* -------------------------------------------------------------------- */
1109
1110static std::optional<blender::Bounds<blender::float3>> bounds_min_max_with_transform(
1112 const blender::Span<blender::float3> positions,
1113 const blender::IndexMask &mask)
1114{
1115 using namespace blender;
1116 if (mask.is_empty()) {
1117 return std::nullopt;
1118 }
1120 mask.index_range(),
1121 1024,
1122 Bounds<float3>(math::transform_point(transform, positions[mask.first()])),
1123 [&](const IndexRange range, Bounds<float3> init) {
1124 mask.slice(range).foreach_index([&](const int i) {
1125 math::min_max(math::transform_point(transform, positions[i]), init.min, init.max);
1126 });
1127 return init;
1128 },
1129 [](const Bounds<float3> &a, const Bounds<float3> &b) { return bounds::merge(a, b); });
1130}
1131
1132bool ED_view3d_minmax_verts(const Scene *scene, Object *obedit, float r_min[3], float r_max[3])
1133{
1134 using namespace blender;
1135 using namespace blender::ed;
1136 TransVertStore tvs = {nullptr};
1137 TransVert *tv;
1138 float centroid[3], vec[3], bmat[3][3];
1139
1140 /* Meta-balls are an exception. */
1141 if (obedit->type == OB_MBALL) {
1142 float ob_min[3], ob_max[3];
1143 bool changed;
1144
1145 changed = BKE_mball_minmax_ex(static_cast<const MetaBall *>(obedit->data),
1146 ob_min,
1147 ob_max,
1148 obedit->object_to_world().ptr(),
1149 SELECT);
1150 if (changed) {
1151 minmax_v3v3_v3(r_min, r_max, ob_min);
1152 minmax_v3v3_v3(r_min, r_max, ob_max);
1153 }
1154 return changed;
1155 }
1156 if (obedit->type == OB_POINTCLOUD) {
1157 const Object &ob_orig = *DEG_get_original(obedit);
1158 const PointCloud &pointcloud = *static_cast<const PointCloud *>(ob_orig.data);
1159
1160 IndexMaskMemory memory;
1162
1163 const std::optional<Bounds<float3>> bounds = bounds_min_max_with_transform(
1164 obedit->object_to_world(), pointcloud.positions(), mask);
1165
1166 if (bounds) {
1167 minmax_v3v3_v3(r_min, r_max, bounds->min);
1168 minmax_v3v3_v3(r_min, r_max, bounds->max);
1169 return true;
1170 }
1171 return false;
1172 }
1173 if (obedit->type == OB_CURVES) {
1174 const Object &ob_orig = *DEG_get_original(obedit);
1175 const Curves &curves_id = *static_cast<const Curves *>(ob_orig.data);
1176 const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
1177
1178 IndexMaskMemory memory;
1180
1181 const bke::crazyspace::GeometryDeformation deformation =
1183
1184 const std::optional<Bounds<float3>> bounds = bounds_min_max_with_transform(
1185 obedit->object_to_world(), deformation.positions, mask);
1186
1187 if (bounds) {
1188 minmax_v3v3_v3(r_min, r_max, bounds->min);
1189 minmax_v3v3_v3(r_min, r_max, bounds->max);
1190 return true;
1191 }
1192 return false;
1193 }
1194 if (obedit->type == OB_GREASE_PENCIL) {
1195 Object &ob_orig = *DEG_get_original(obedit);
1196 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob_orig.data);
1197
1198 std::optional<Bounds<float3>> bounds = std::nullopt;
1199
1201 greasepencil::retrieve_editable_drawings(*scene, grease_pencil);
1202 for (const greasepencil::MutableDrawingInfo info : drawings) {
1203 const bke::CurvesGeometry &curves = info.drawing.strokes();
1204 if (curves.is_empty()) {
1205 continue;
1206 }
1207
1208 IndexMaskMemory memory;
1210 ob_orig, info.drawing, info.layer_index, memory);
1211 if (points.is_empty()) {
1212 continue;
1213 }
1214
1215 const bke::crazyspace::GeometryDeformation deformation =
1217 obedit, ob_orig, info.drawing);
1218
1219 const bke::greasepencil::Layer &layer = grease_pencil.layer(info.layer_index);
1220 const float4x4 layer_to_world = layer.to_world_space(*obedit);
1221
1223 bounds, bounds_min_max_with_transform(layer_to_world, deformation.positions, points));
1224 }
1225
1226 if (bounds) {
1227 minmax_v3v3_v3(r_min, r_max, bounds->min);
1228 minmax_v3v3_v3(r_min, r_max, bounds->max);
1229 return true;
1230 }
1231 return false;
1232 }
1233
1234 if (ED_transverts_check_obedit(obedit)) {
1236 }
1237
1238 if (tvs.transverts_tot == 0) {
1239 return false;
1240 }
1241
1242 copy_m3_m4(bmat, obedit->object_to_world().ptr());
1243
1244 tv = tvs.transverts;
1245 for (int a = 0; a < tvs.transverts_tot; a++, tv++) {
1246 copy_v3_v3(vec, (tv->flag & TX_VERT_USE_MAPLOC) ? tv->maploc : tv->loc);
1247 mul_m3_v3(bmat, vec);
1248 add_v3_v3(vec, obedit->object_to_world().location());
1249 add_v3_v3(centroid, vec);
1250 minmax_v3v3_v3(r_min, r_max, vec);
1251 }
1252
1253 ED_transverts_free(&tvs);
1254
1255 return true;
1256}
1257
Functions and classes to work with Actions.
Functions to deal with Armatures.
C++ functions to deal with Armature collections (i.e. the successor of bone layers).
bool ANIM_bonecoll_is_visible_pchan(const bArmature *armature, const bPoseChannel *pchan)
Functions to insert, delete or modify keyframes.
Functionality to interact with keying sets.
static constexpr const char * ANIM_KS_LOCATION_ID
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
void BKE_pchan_protected_rotation_axisangle_set(bPoseChannel *pchan, const float axis[3], float angle)
Definition armature.cc:2522
void BKE_pchan_protected_location_set(bPoseChannel *pchan, const float location[3])
Definition armature.cc:2467
void BKE_armature_loc_pose_to_bone(const bPoseChannel *pchan, const float inloc[3], float outloc[3])
Definition armature.cc:2299
bool BKE_armature_bone_flag_test_recursive(const Bone *bone, int flag)
Definition armature.cc:868
void BKE_pchan_mat3_to_rot(bPoseChannel *pchan, const float mat[3][3], bool use_compat)
Definition armature.cc:2343
void BKE_pchan_protected_rotation_euler_set(bPoseChannel *pchan, const float rotation_euler[3])
Definition armature.cc:2509
void BKE_pchan_protected_rotation_quaternion_set(bPoseChannel *pchan, const float quat[4])
Definition armature.cc:2493
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
Main * CTX_data_main(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition editmesh.cc:61
#define FOREACH_SELECTED_EDITABLE_OBJECT_END
Definition BKE_layer.hh:327
#define FOREACH_SELECTED_OBJECT_BEGIN(_view_layer, _v3d, _instance)
Definition BKE_layer.hh:298
#define FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN(_view_layer, _v3d, _instance)
Definition BKE_layer.hh:315
#define FOREACH_SELECTED_OBJECT_END
Definition BKE_layer.hh:310
blender::Vector< Object * > BKE_view_layer_array_from_objects_in_edit_mode_unique_data(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
bool BKE_mball_minmax_ex(const MetaBall *mb, float min[3], float max[3], const float obmat[4][4], short flag)
Definition mball.cc:456
General operations, lookup, etc. for blender objects.
void BKE_object_protected_location_set(Object *ob, const float location[3])
bool BKE_object_flag_test_recursive(const Object *ob, short flag)
MovieClip * BKE_object_movieclip_get(Scene *scene, const Object *ob, bool use_default)
void BKE_object_get_parent_matrix(const Object *ob, Object *par, float r_parentmat[4][4])
void BKE_object_where_is_calc_ex(Depsgraph *depsgraph, Scene *scene, RigidBodyWorld *rbw, Object *ob, float r_originmat[3][3])
void BKE_object_protected_rotation_quaternion_set(Object *ob, const float quat[4])
void BKE_object_protected_rotation_euler_set(Object *ob, const float euler[3])
blender::Vector< Object * > BKE_object_pose_array_get(const Scene *scene, ViewLayer *view_layer, View3D *v3d)
void BKE_object_protected_rotation_axisangle_set(Object *ob, const float axis[3], float angle)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
void BKE_scene_graph_evaluated_ensure(Depsgraph *depsgraph, Main *bmain)
Definition scene.cc:2623
void BKE_tracking_get_camera_object_matrix(const struct Object *camera_object, float mat[4][4])
#define TRACK_SELECTED(track)
void BKE_tracking_camera_get_reconstructed_interpolate(struct MovieTracking *tracking, struct MovieTrackingObject *tracking_object, float framenr, float mat[4][4])
Definition tracking.cc:2145
#define LISTBASE_FOREACH(type, var, list)
void mul_m3_v3(const float M[3][3], float r[3])
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
void mul_m4_v3(const float M[4][4], float r[3])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
bool invert_m4(float mat[4][4])
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
void mul_m3_m4m4(float R[3][3], const float A[4][4], const float B[4][4])
void mat3_to_axis_angle(float axis[3], float *angle, const float mat[3][3])
void mat3_to_eulO(float eul[3], short order, const float m[3][3])
void mat3_normalized_to_quat(float q[4], const float mat[3][3])
MINLINE void copy_v4_v4(float r[4], const float a[4])
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void 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])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
#define INIT_MINMAX(min, max)
void DEG_id_tag_update(ID *id, unsigned int flags)
ViewLayer * DEG_get_evaluated_view_layer(const Depsgraph *graph)
T * DEG_get_original(T *id)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:962
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1026
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:982
@ ROT_MODE_QUAT
@ ROT_MODE_AXISANGLE
@ POSE_LOCKED
@ POSE_DO_UNLOCK
@ BONE_SELECTED
@ BONE_TRANSFORM
@ BONE_CONNECTED
@ OB_MODE_POSE
Object is a sort of wrapper for general info.
@ OB_DONE
@ OB_MBALL
@ OB_CAMERA
@ OB_GREASE_PENCIL
@ OB_MESH
@ OB_POINTCLOUD
@ OB_CURVES
#define OBPOSE_FROM_OBACT(ob)
#define OBEDIT_FROM_OBACT(ob)
@ SCE_XFORM_SKIP_CHILDREN
@ SCE_XFORM_DATA_ORIGIN
@ TRACKING_OBJECT_CAMERA
@ TRACK_HAS_BUNDLE
@ V3D_SHOW_RECONSTRUCTION
@ V3D_AROUND_ACTIVE
@ V3D_AROUND_CENTER_BOUNDS
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
bool ED_operator_view3d_active(bContext *C)
bool ED_operator_region_view3d_active(bContext *C)
bool ED_transverts_check_obedit(const Object *obedit)
void ED_transverts_create_from_obedit(TransVertStore *tvs, const Object *obedit, int mode)
void ED_transverts_free(TransVertStore *tvs)
void ED_transverts_update_obedit(TransVertStore *tvs, Object *obedit)
@ TX_VERT_USE_MAPLOC
@ TM_SKIP_HANDLES
@ TM_CALC_MAPLOC
@ TM_ALL_JOINTS
float ED_view3d_grid_view_scale(const Scene *scene, const View3D *v3d, const ARegion *region, const char **r_grid_unit)
#define C
Definition RandGen.cpp:29
#define ND_TRANSFORM
Definition WM_types.hh:453
#define ND_SPACE_VIEW3D
Definition WM_types.hh:525
#define NC_OBJECT
Definition WM_types.hh:376
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define NC_SPACE
Definition WM_types.hh:389
void ANIM_deselect_keys_in_animation_editors(bContext *C)
Definition anim_deps.cc:478
BPy_StructRNA * depsgraph
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
bool is_empty() const
int64_t size() const
void append(const T &value)
IndexRange index_range() const
void append_unchecked(const T &value)
float4x4 to_world_space(const Object &object) const
#define SELECT
#define floorf(x)
uint pos
MatBase< 4, 4 > float4x4
int count
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
bool is_autokey_on(const Scene *scene)
KeyingSet * get_keyingset_for_autokeying(const Scene *scene, const char *transformKSName)
bool bone_is_visible_pchan(const bArmature *armature, const bPoseChannel *pchan)
bool autokeyframe_pchan(bContext *C, Scene *scene, Object *ob, bPoseChannel *pchan, KeyingSet *ks)
void autokeyframe_object(bContext *C, const Scene *scene, Object *ob, Span< RNAPath > rna_paths)
GeometryDeformation get_evaluated_grease_pencil_drawing_deformation(const Object *ob_eval, const Object &ob_orig, const bke::greasepencil::Drawing &drawing_orig)
GeometryDeformation get_evaluated_curves_deformation(const Object *ob_eval, const Object &ob_orig)
Bounds< T > merge(const Bounds< T > &a, const Bounds< T > &b)
Definition BLI_bounds.hh:26
IndexMask retrieve_selected_points(const bke::CurvesGeometry &curves, IndexMaskMemory &memory)
IndexMask retrieve_editable_and_selected_points(Object &object, const bke::greasepencil::Drawing &drawing, int layer_index, IndexMaskMemory &memory)
Vector< MutableDrawingInfo > retrieve_editable_drawings(const Scene &scene, GreasePencil &grease_pencil)
bool calc_active_center(Object *ob, bool select_only, float r_center[3])
void xform_skip_child_container_item_ensure_from_array(XFormObjectSkipChild_Container *xcs, const Scene *scene, ViewLayer *view_layer, Object **objects, uint objects_len)
void data_xform_container_destroy(XFormObjectData_Container *xds)
bool shape_key_report_if_locked(const Object *obedit, ReportList *reports)
XFormObjectSkipChild_Container * xform_skip_child_container_create()
void data_xform_container_update_all(XFormObjectData_Container *xds, Main *bmain, Depsgraph *depsgraph)
void object_xform_skip_child_container_destroy(XFormObjectSkipChild_Container *xcs)
void data_xform_container_item_ensure(XFormObjectData_Container *xds, Object *ob)
void object_xform_skip_child_container_update_all(XFormObjectSkipChild_Container *xcs, Main *bmain, Depsgraph *depsgraph)
XFormObjectData_Container * data_xform_container_create()
IndexMask retrieve_selected_points(const PointCloud &pointcloud, IndexMaskMemory &memory)
Definition selection.cc:342
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
Definition BLI_task.hh:151
MatBase< float, 4, 4 > float4x4
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
static void init(bNodeTree *, bNode *node)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
#define min(a, b)
Definition sort.cc:36
int totvertsel
CurvesGeometry geometry
void * first
ListBase objects
Definition BKE_main.hh:247
struct MovieTracking tracking
struct bPose * pose
struct Object * parent
struct ToolSettings * toolsettings
struct RenderData r
View3DCursor cursor
TransVert * transverts
float * loc
float maploc[3]
float rotation_axis[3]
float rotation_quaternion[4]
float rotation_euler[3]
ListBase chanbase
const c_style_mat & ptr() const
struct ReportList * reports
struct PointerRNA * ptr
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
static wmOperatorStatus snap_curs_to_grid_exec(bContext *C, wmOperator *)
static wmOperatorStatus snap_curs_to_active_exec(bContext *C, wmOperator *)
static void bundle_midpoint(Scene *scene, Object *ob, float r_vec[3])
static wmOperatorStatus snap_selected_to_active_exec(bContext *C, wmOperator *op)
bool ED_view3d_snap_selected_to_location(bContext *C, wmOperator *op, const float target_loc_global[3], const int pivot_point)
static wmOperatorStatus snap_selected_to_cursor_exec(bContext *C, wmOperator *op)
static bool snap_curs_to_sel_ex(bContext *C, const int pivot_point, float r_cursor[3])
static wmOperatorStatus snap_sel_to_grid_exec(bContext *C, wmOperator *op)
static bool snap_selected_to_location_rotation(bContext *C, wmOperator *op, const blender::float3 &target_loc_global, const View3DCursor *target_orientation_global, const bool use_offset, const int pivot_point, const bool use_toolsettings)
void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
static wmOperatorStatus snap_curs_to_sel_exec(bContext *C, wmOperator *)
static wmOperatorStatus snap_curs_to_center_exec(bContext *C, wmOperator *)
void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot)
bool ED_view3d_minmax_verts(const Scene *scene, Object *obedit, float r_min[3], float r_max[3])
static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3])
static std::optional< blender::Bounds< blender::float3 > > bounds_min_max_with_transform(const blender::float4x4 &transform, const blender::Span< blender::float3 > positions, const blender::IndexMask &mask)
void VIEW3D_OT_snap_selected_to_active(wmOperatorType *ot)
void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4226