Blender V5.0
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->flag & POSE_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
288/* Return true if the bone or any of its parents has the given runtime flag set. */
290{
291 if (pose_bone->runtime.flag & flag) {
292 return true;
293 }
294 if (pose_bone->parent) {
296 }
297 return false;
298}
299
315 wmOperator *op,
316 const blender::float3 &target_loc_global,
317 const View3DCursor *target_orientation_global,
318 const bool use_offset,
319 const int pivot_point,
320 const bool use_toolsettings)
321{
322 using namespace blender::ed;
323 Scene *scene = CTX_data_scene(C);
324 Object *obedit = CTX_data_edit_object(C);
326 View3D *v3d = CTX_wm_view3d(C);
327 TransVertStore tvs = {nullptr};
328 TransVert *tv;
329 float imat[3][3], bmat[3][3];
330 float center_global[3];
331 float offset_global[3];
332 int a;
333
334 /* Some use of this needs to transform into local-space. */
335 const bool use_rotation = target_orientation_global != nullptr;
336 const blender::float3x3 target_rot_global =
337 target_orientation_global ? target_orientation_global->matrix<blender::float3x3>() :
339
340 if (use_offset) {
341 if ((pivot_point == V3D_AROUND_ACTIVE) && snap_calc_active_center(C, true, center_global)) {
342 /* pass */
343 }
344 else {
345 snap_curs_to_sel_ex(C, pivot_point, center_global);
346 }
347 sub_v3_v3v3(offset_global, target_loc_global, center_global);
348 }
349
350 if (obedit) {
351 blender::float3 target_loc_local;
352 ViewLayer *view_layer = CTX_data_view_layer(C);
354 scene, view_layer, v3d);
355 for (const int ob_index : objects.index_range()) {
356 obedit = objects[ob_index];
357
358 if (obedit->type == OB_MESH) {
360
361 if (em->bm->totvertsel == 0) {
362 continue;
363 }
364 }
365
367 continue;
368 }
369
370 if (ED_transverts_check_obedit(obedit)) {
371 ED_transverts_create_from_obedit(&tvs, obedit, 0);
372 }
373
374 if (tvs.transverts_tot != 0) {
375 copy_m3_m4(bmat, obedit->object_to_world().ptr());
376 invert_m3_m3(imat, bmat);
377
378 /* Get the `target_loc_global` in object space. */
379 sub_v3_v3v3(target_loc_local, target_loc_global, obedit->object_to_world().location());
380 mul_m3_v3(imat, target_loc_local);
381
382 if (use_offset) {
383 blender::float3 offset_local;
384
385 mul_v3_m3v3(offset_local, imat, offset_global);
386
387 tv = tvs.transverts;
388 for (a = 0; a < tvs.transverts_tot; a++, tv++) {
389 add_v3_v3(tv->loc, offset_local);
390 }
391 }
392 else {
393 tv = tvs.transverts;
394 for (a = 0; a < tvs.transverts_tot; a++, tv++) {
395 copy_v3_v3(tv->loc, target_loc_local);
396 }
397 }
398 ED_transverts_update_obedit(&tvs, obedit);
399 }
400 ED_transverts_free(&tvs);
401 }
402 }
403 else if (OBPOSE_FROM_OBACT(obact)) {
405 ViewLayer *view_layer = CTX_data_view_layer(C);
406 Vector<Object *> objects = BKE_object_pose_array_get(scene, view_layer, v3d);
407 Main *bmain = CTX_data_main(C);
410
411 for (Object *ob : objects) {
412 bArmature *arm = static_cast<bArmature *>(ob->data);
413 blender::float3 target_loc_local;
414
415 invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
416 mul_v3_m4v3(target_loc_local, ob->world_to_object().ptr(), target_loc_global);
417
418 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
419 if ((pchan->flag & POSE_SELECTED) && blender::animrig::bone_is_visible(arm, pchan) &&
420 /* if the bone has a parent and is connected to the parent,
421 * don't do anything - will break chain unless we do auto-ik.
422 */
423 (pchan->bone->flag & BONE_CONNECTED) == 0)
424 {
425 pchan->runtime.flag |= POSE_RUNTIME_TRANSFORM;
426 }
427 else {
428 pchan->runtime.flag &= ~POSE_RUNTIME_TRANSFORM;
429 }
430 }
431
432 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
433 if ((pchan->runtime.flag & POSE_RUNTIME_TRANSFORM) &&
434 /* check that our parents not transformed (if we have one) */
435 ((pchan->bone->parent &&
437 {
438 /* Get position in pchan (pose) space. */
439 blender::float3 target_loc_pose;
440
441 if (use_offset) {
442 mul_v3_m4v3(target_loc_pose, ob->object_to_world().ptr(), pchan->pose_mat[3]);
443 add_v3_v3(target_loc_pose, offset_global);
444
445 if (use_rotation) {
446 sub_v3_v3(target_loc_pose, target_loc_global);
447 mul_m3_v3(target_rot_global.ptr(), target_loc_pose);
448 add_v3_v3(target_loc_pose, target_loc_global);
449 }
450
451 mul_m4_v3(ob->world_to_object().ptr(), target_loc_pose);
452 BKE_armature_loc_pose_to_bone(pchan, target_loc_pose, target_loc_pose);
453 }
454 else {
455 BKE_armature_loc_pose_to_bone(pchan, target_loc_local, target_loc_pose);
456 }
457
458 if (use_rotation) {
459 BKE_pchan_mat3_to_rot(pchan, target_rot_global.ptr(), false);
460
461 if (pchan->rotmode == ROT_MODE_QUAT) {
462 float quat[4];
463 mat3_normalized_to_quat(quat, target_rot_global.ptr());
464
465 if (use_toolsettings) {
467 }
468 else {
469 copy_v4_v4(pchan->quat, quat);
470 }
471 }
472 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
473 float rot_axis[3];
474 float rot_angle;
475 mat3_to_axis_angle(rot_axis, &rot_angle, target_rot_global.ptr());
476
477 if (use_toolsettings) {
478 BKE_pchan_protected_rotation_axisangle_set(pchan, rot_axis, rot_angle);
479 }
480 else {
481 copy_v3_v3(pchan->rotAxis, rot_axis);
482 pchan->rotAngle = rot_angle;
483 }
484 }
485 else {
486 float rot_euler[3];
487 mat3_to_eulO(rot_euler, pchan->rotmode, target_rot_global.ptr());
488
489 if (use_toolsettings) {
491 }
492 else {
493 copy_v3_v3(pchan->eul, rot_euler);
494 }
495 }
496 }
497
498 /* copy new position */
499 if (use_toolsettings) {
500 BKE_pchan_protected_location_set(pchan, target_loc_pose);
501
502 /* auto-keyframing */
503 blender::animrig::autokeyframe_pchan(C, scene, ob, pchan, ks);
504 }
505 else {
506 copy_v3_v3(pchan->loc, target_loc_pose);
507 }
508 }
509 }
510
511 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
512 pchan->runtime.flag &= ~POSE_RUNTIME_TRANSFORM;
513 }
514
515 ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
516
518 }
519 }
520 else {
522 Main *bmain = CTX_data_main(C);
525
526 /* Reset flags. */
527 for (Object *ob = static_cast<Object *>(bmain->objects.first); ob;
528 ob = static_cast<Object *>(ob->id.next))
529 {
530 ob->flag &= ~OB_DONE;
531 }
532
533 /* Build object array, tag objects we're transforming. */
534 ViewLayer *view_layer = CTX_data_view_layer(C);
535 Vector<Object *> objects;
536 {
537 FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN (view_layer, v3d, ob) {
538 objects.append(ob);
539 ob->flag |= OB_DONE;
540 }
542 }
543
544 const bool use_transform_skip_children = use_toolsettings &&
547 const bool use_transform_data_origin = use_toolsettings &&
552
553 if (use_transform_skip_children) {
556 xcs, scene, view_layer, objects.data(), objects.size());
557 }
558 if (use_transform_data_origin) {
560
561 /* Initialize the transform data in a separate loop because the depsgraph
562 * may be evaluated while setting the locations. */
563 for (Object *ob : objects) {
565 }
566 }
567
570 }
571
572 for (Object *ob : objects) {
573 /* With offset enabled, skip child objects whose parents are also transformed
574 * to avoid double transform. */
575 if (use_offset) {
576 if (ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) {
577 continue;
578 }
579 }
580
581 blender::float3 target_loc_local; /* parent-relative */
582
583 if (use_offset) {
584 add_v3_v3v3(target_loc_local, ob->object_to_world().location(), offset_global);
585
586 if (use_rotation) {
587 sub_v3_v3(target_loc_local, target_loc_global);
588 mul_m3_v3(target_rot_global.ptr(), target_loc_local);
589 add_v3_v3(target_loc_local, target_loc_global);
590 }
591 }
592 else {
593 copy_v3_v3(target_loc_local, target_loc_global);
594 }
595 sub_v3_v3(target_loc_local, ob->object_to_world().location());
596
597 /* Calculate a parent relative copy. */
598 blender::float3x3 target_rot = target_rot_global;
599 if (ob->parent) {
600 float originmat[3][3], parentmat[4][4];
601 /* Use the evaluated object here because sometimes
602 * `ob->parent->runtime->curve_cache` is required. */
604 Object *ob_eval = DEG_get_evaluated(depsgraph, ob);
605
606 BKE_object_get_parent_matrix(ob_eval, ob_eval->parent, parentmat);
607 mul_m3_m4m4(originmat, parentmat, ob->parentinv);
608 invert_m3_m3(imat, originmat);
609 mul_m3_v3(imat, target_loc_local);
610 mul_m3_m3m3(target_rot.ptr(), imat, target_rot.ptr());
611 }
612 if (use_toolsettings) {
613 const blender::float3 loc_final = blender::float3(ob->loc) + target_loc_local;
615
616 /* auto-keyframing */
618 }
619 else {
620 add_v3_v3(ob->loc, target_loc_local);
621 }
622
623 if (use_rotation) {
624 const bool assign_rotation_directly = (ob->rotmode ==
625 target_orientation_global->rotation_mode &&
626 ob->parent == nullptr);
627
628 if (ob->rotmode == ROT_MODE_QUAT) {
629 float quat[4];
630 if (assign_rotation_directly) {
631 copy_v4_v4(quat, target_orientation_global->rotation_quaternion);
632 }
633 else {
634 mat3_normalized_to_quat(quat, target_rot.ptr());
635 }
636 if (use_toolsettings) {
638 }
639 else {
640 copy_v4_v4(ob->quat, quat);
641 }
642 }
643 else if (ob->rotmode == ROT_MODE_AXISANGLE) {
644 float rot_axis[3];
645 float rot_angle;
646 if (assign_rotation_directly) {
647 copy_v3_v3(rot_axis, target_orientation_global->rotation_axis);
648 rot_angle = target_orientation_global->rotation_angle;
649 }
650 else {
651 mat3_to_axis_angle(rot_axis, &rot_angle, target_rot.ptr());
652 }
653 if (use_toolsettings) {
654 BKE_object_protected_rotation_axisangle_set(ob, rot_axis, rot_angle);
655 }
656 else {
657 copy_v3_v3(ob->rotAxis, rot_axis);
658 ob->rotAngle = rot_angle;
659 }
660 }
661 else {
662 float rot_euler[3];
663 if (assign_rotation_directly) {
664 copy_v3_v3(rot_euler, target_orientation_global->rotation_euler);
665 }
666 else {
667 mat3_to_eulO(rot_euler, ob->rotmode, target_rot.ptr());
668 }
669 if (use_toolsettings) {
671 }
672 else {
673 copy_v3_v3(ob->rot, rot_euler);
674 }
675 }
676
677 /* auto-keyframing */
679 }
680
682 }
683
684 if (use_transform_skip_children) {
687 }
688 if (use_transform_data_origin) {
691 }
692 }
693
695
696 return true;
697}
698
700 wmOperator *op,
701 const float target_loc_global[3],
702 const int pivot_point)
703{
704 /* These could be passed as arguments if needed. */
705 /* Always use pivot point. */
706 const bool use_offset = true;
707 /* Disable object protected flags & auto-keyframing,
708 * so this can be used as a low level function. */
709 const bool use_toolsettings = false;
711 C, op, target_loc_global, nullptr, use_offset, pivot_point, use_toolsettings);
712}
713
715
716/* -------------------------------------------------------------------- */
719
721{
722 const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
723 const bool use_rotation = RNA_boolean_get(op->ptr, "use_rotation");
724
725 Scene *scene = CTX_data_scene(C);
726
727 const float *target_loc_global = scene->cursor.location;
728 const View3DCursor *snap_orientation = use_rotation ? &scene->cursor : nullptr;
729 const int pivot_point = scene->toolsettings->transform_pivot_point;
730
732 C, op, target_loc_global, snap_orientation, use_offset, pivot_point, true))
733 {
734 return OPERATOR_FINISHED;
735 }
736 return OPERATOR_CANCELLED;
737}
738
740{
741 /* identifiers */
742 ot->name = "Snap Selection to Cursor";
743 ot->description = "Snap selected item(s) to the 3D cursor";
744 ot->idname = "VIEW3D_OT_snap_selected_to_cursor";
745
746 /* API callbacks. */
749
750 /* flags */
752
753 /* rna */
754 RNA_def_boolean(ot->srna,
755 "use_offset",
756 true,
757 "Offset",
758 "If the selection should be snapped as a whole or by each object center");
759 RNA_def_boolean(ot->srna,
760 "use_rotation",
761 false,
762 "Rotation",
763 "If the selection should be rotated to match the cursor");
764}
765
767
768/* -------------------------------------------------------------------- */
771
774{
775 float target_loc_global[3];
776
777 if (snap_calc_active_center(C, false, target_loc_global) == false) {
778 BKE_report(op->reports, RPT_ERROR, "No active element found!");
779 return OPERATOR_CANCELLED;
780 }
781
782 if (!snap_selected_to_location_rotation(C, op, target_loc_global, nullptr, false, -1, true)) {
783 return OPERATOR_CANCELLED;
784 }
785 return OPERATOR_FINISHED;
786}
787
789{
790 /* identifiers */
791 ot->name = "Snap Selection to Active";
792 ot->description = "Snap selected item(s) to the active item";
793 ot->idname = "VIEW3D_OT_snap_selected_to_active";
794
795 /* API callbacks. */
798
799 /* flags */
801}
802
804
805/* -------------------------------------------------------------------- */
808
811{
812 Scene *scene = CTX_data_scene(C);
813 ARegion *region = CTX_wm_region(C);
814 View3D *v3d = CTX_wm_view3d(C);
815 float gridf, *curs;
816
817 gridf = ED_view3d_grid_view_scale(scene, v3d, region, nullptr);
818 curs = scene->cursor.location;
819
820 curs[0] = gridf * floorf(0.5f + curs[0] / gridf);
821 curs[1] = gridf * floorf(0.5f + curs[1] / gridf);
822 curs[2] = gridf * floorf(0.5f + curs[2] / gridf);
823
824 WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, nullptr); /* hrm */
826
827 return OPERATOR_FINISHED;
828}
829
831{
832 /* identifiers */
833 ot->name = "Snap Cursor to Grid";
834 ot->description = "Snap 3D cursor to the nearest grid division";
835 ot->idname = "VIEW3D_OT_snap_cursor_to_grid";
836
837 /* API callbacks. */
840
841 /* flags */
842 ot->flag = OPTYPE_REGISTER;
843}
844
846
847/* -------------------------------------------------------------------- */
850
855static void bundle_midpoint(Scene *scene, Object *ob, float r_vec[3])
856{
857 MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
858 bool ok = false;
859 float min[3], max[3], mat[4][4], pos[3], cammat[4][4];
860
861 if (!clip) {
862 return;
863 }
864
865 MovieTracking *tracking = &clip->tracking;
866
867 copy_m4_m4(cammat, ob->object_to_world().ptr());
868
870
872
873 LISTBASE_FOREACH (MovieTrackingObject *, tracking_object, &tracking->objects) {
874 float obmat[4][4];
875
876 if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
877 copy_m4_m4(obmat, mat);
878 }
879 else {
880 float imat[4][4];
881
883 tracking, tracking_object, scene->r.cfra, imat);
884 invert_m4(imat);
885
886 mul_m4_m4m4(obmat, cammat, imat);
887 }
888
889 LISTBASE_FOREACH (const MovieTrackingTrack *, track, &tracking_object->tracks) {
890 if ((track->flag & TRACK_HAS_BUNDLE) && TRACK_SELECTED(track)) {
891 ok = true;
892 mul_v3_m4v3(pos, obmat, track->bundle_pos);
894 }
895 }
896 }
897
898 if (ok) {
899 mid_v3_v3v3(r_vec, min, max);
900 }
901}
902
904static bool snap_curs_to_sel_ex(bContext *C, const int pivot_point, float r_cursor[3])
905{
908 Object *obedit = CTX_data_edit_object(C);
909 Scene *scene = CTX_data_scene(C);
910 View3D *v3d = CTX_wm_view3d(C);
911 TransVertStore tvs = {nullptr};
912 TransVert *tv;
913 float bmat[3][3], vec[3], min[3], max[3], centroid[3];
914 int count = 0;
915
917 zero_v3(centroid);
918
919 if (obedit) {
920 ViewLayer *view_layer = CTX_data_view_layer(C);
922 scene, view_layer, CTX_wm_view3d(C));
923 for (const int ob_index : objects.index_range()) {
924 obedit = objects[ob_index];
925
926 /* We can do that quick check for meshes only... */
927 if (obedit->type == OB_MESH) {
929
930 if (em->bm->totvertsel == 0) {
931 continue;
932 }
933 }
934
935 if (ED_transverts_check_obedit(obedit)) {
936 const Object *obedit_eval = DEG_get_evaluated(depsgraph, obedit);
938 }
939
940 count += tvs.transverts_tot;
941 if (tvs.transverts_tot != 0) {
942 Object *obedit_eval = DEG_get_evaluated(depsgraph, obedit);
943 copy_m3_m4(bmat, obedit_eval->object_to_world().ptr());
944
945 tv = tvs.transverts;
946 for (int i = 0; i < tvs.transverts_tot; i++, tv++) {
947 copy_v3_v3(vec, tv->loc);
948 mul_m3_v3(bmat, vec);
949 add_v3_v3(vec, obedit_eval->object_to_world().location());
950 add_v3_v3(centroid, vec);
951 minmax_v3v3_v3(min, max, vec);
952 }
953 }
954 ED_transverts_free(&tvs);
955 }
956 }
957 else {
959
960 if (obact && (obact->mode & OB_MODE_POSE)) {
961 Object *obact_eval = DEG_get_evaluated(depsgraph, obact);
962 bArmature *arm = static_cast<bArmature *>(obact_eval->data);
963 LISTBASE_FOREACH (bPoseChannel *, pchan, &obact_eval->pose->chanbase) {
964 if (ANIM_bonecoll_is_visible_pchan(arm, pchan)) {
965 if (pchan->flag & POSE_SELECTED) {
966 copy_v3_v3(vec, pchan->pose_head);
967 mul_m4_v3(obact_eval->object_to_world().ptr(), vec);
968 add_v3_v3(centroid, vec);
969 minmax_v3v3_v3(min, max, vec);
970 count++;
971 }
972 }
973 }
974 }
975 else {
976 FOREACH_SELECTED_OBJECT_BEGIN (view_layer_eval, v3d, ob_eval) {
977 copy_v3_v3(vec, ob_eval->object_to_world().location());
978
979 /* special case for camera -- snap to bundles */
980 if (ob_eval->type == OB_CAMERA) {
981 /* snap to bundles should happen only when bundles are visible */
982 if (v3d->flag2 & V3D_SHOW_RECONSTRUCTION) {
983 bundle_midpoint(scene, DEG_get_original(ob_eval), vec);
984 }
985 }
986
987 add_v3_v3(centroid, vec);
988 minmax_v3v3_v3(min, max, vec);
989 count++;
990 }
992 }
993 }
994
995 if (count == 0) {
996 return false;
997 }
998
999 if (pivot_point == V3D_AROUND_CENTER_BOUNDS) {
1000 mid_v3_v3v3(r_cursor, min, max);
1001 }
1002 else {
1003 mul_v3_fl(centroid, 1.0f / float(count));
1004 copy_v3_v3(r_cursor, centroid);
1005 }
1006 return true;
1007}
1008
1010{
1011 Scene *scene = CTX_data_scene(C);
1012 const int pivot_point = scene->toolsettings->transform_pivot_point;
1013 if (snap_curs_to_sel_ex(C, pivot_point, scene->cursor.location)) {
1016
1017 return OPERATOR_FINISHED;
1018 }
1019 return OPERATOR_CANCELLED;
1020}
1021
1023{
1024 /* identifiers */
1025 ot->name = "Snap Cursor to Selected";
1026 ot->description = "Snap 3D cursor to the middle of the selected item(s)";
1027 ot->idname = "VIEW3D_OT_snap_cursor_to_selected";
1028
1029 /* API callbacks. */
1030 ot->exec = snap_curs_to_sel_exec;
1032
1033 /* flags */
1034 ot->flag = OPTYPE_REGISTER;
1035}
1036
1038
1039/* -------------------------------------------------------------------- */
1042
1049static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3])
1050{
1052 if (ob == nullptr) {
1053 return false;
1054 }
1055 return blender::ed::object::calc_active_center(ob, select_only, r_center);
1056}
1057
1059{
1060 Scene *scene = CTX_data_scene(C);
1061
1062 if (snap_calc_active_center(C, false, scene->cursor.location)) {
1065
1066 return OPERATOR_FINISHED;
1067 }
1068 return OPERATOR_CANCELLED;
1069}
1070
1072{
1073 /* identifiers */
1074 ot->name = "Snap Cursor to Active";
1075 ot->description = "Snap 3D cursor to the active item";
1076 ot->idname = "VIEW3D_OT_snap_cursor_to_active";
1077
1078 /* API callbacks. */
1081
1082 /* flags */
1083 ot->flag = OPTYPE_REGISTER;
1084}
1085
1087
1088/* -------------------------------------------------------------------- */
1091
1094{
1095 Scene *scene = CTX_data_scene(C);
1096
1097 scene->cursor.set_matrix(blender::float4x4::identity(), false);
1098
1100
1102 return OPERATOR_FINISHED;
1103}
1104
1106{
1107 /* identifiers */
1108 ot->name = "Snap Cursor to World Origin";
1109 ot->description = "Snap 3D cursor to the world origin";
1110 ot->idname = "VIEW3D_OT_snap_cursor_to_center";
1111
1112 /* API callbacks. */
1115
1116 /* flags */
1117 ot->flag = OPTYPE_REGISTER;
1118}
1119
1121
1122/* -------------------------------------------------------------------- */
1125
1126static std::optional<blender::Bounds<blender::float3>> bounds_min_max_with_transform(
1128 const blender::Span<blender::float3> positions,
1129 const blender::IndexMask &mask)
1130{
1131 using namespace blender;
1132 if (mask.is_empty()) {
1133 return std::nullopt;
1134 }
1136 mask.index_range(),
1137 1024,
1138 Bounds<float3>(math::transform_point(transform, positions[mask.first()])),
1139 [&](const IndexRange range, Bounds<float3> init) {
1140 mask.slice(range).foreach_index([&](const int i) {
1141 math::min_max(math::transform_point(transform, positions[i]), init.min, init.max);
1142 });
1143 return init;
1144 },
1145 [](const Bounds<float3> &a, const Bounds<float3> &b) { return bounds::merge(a, b); });
1146}
1147
1148bool ED_view3d_minmax_verts(const Scene *scene, Object *obedit, float r_min[3], float r_max[3])
1149{
1150 using namespace blender;
1151 using namespace blender::ed;
1152 TransVertStore tvs = {nullptr};
1153 TransVert *tv;
1154 float centroid[3], vec[3], bmat[3][3];
1155
1156 /* Meta-balls are an exception. */
1157 if (obedit->type == OB_MBALL) {
1158 float ob_min[3], ob_max[3];
1159 bool changed;
1160
1161 changed = BKE_mball_minmax_ex(static_cast<const MetaBall *>(obedit->data),
1162 ob_min,
1163 ob_max,
1164 obedit->object_to_world().ptr(),
1165 SELECT);
1166 if (changed) {
1167 minmax_v3v3_v3(r_min, r_max, ob_min);
1168 minmax_v3v3_v3(r_min, r_max, ob_max);
1169 }
1170 return changed;
1171 }
1172 if (obedit->type == OB_POINTCLOUD) {
1173 const Object &ob_orig = *DEG_get_original(obedit);
1174 const PointCloud &pointcloud = *static_cast<const PointCloud *>(ob_orig.data);
1175
1176 IndexMaskMemory memory;
1178
1179 const std::optional<Bounds<float3>> bounds = bounds_min_max_with_transform(
1180 obedit->object_to_world(), pointcloud.positions(), mask);
1181
1182 if (bounds) {
1183 minmax_v3v3_v3(r_min, r_max, bounds->min);
1184 minmax_v3v3_v3(r_min, r_max, bounds->max);
1185 return true;
1186 }
1187 return false;
1188 }
1189 if (obedit->type == OB_CURVES) {
1190 const Object &ob_orig = *DEG_get_original(obedit);
1191 const Curves &curves_id = *static_cast<const Curves *>(ob_orig.data);
1192 const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
1193
1194 IndexMaskMemory memory;
1196
1197 const bke::crazyspace::GeometryDeformation deformation =
1199
1200 const std::optional<Bounds<float3>> bounds = bounds_min_max_with_transform(
1201 obedit->object_to_world(), deformation.positions, mask);
1202
1203 if (bounds) {
1204 minmax_v3v3_v3(r_min, r_max, bounds->min);
1205 minmax_v3v3_v3(r_min, r_max, bounds->max);
1206 return true;
1207 }
1208 return false;
1209 }
1210 if (obedit->type == OB_GREASE_PENCIL) {
1211 Object &ob_orig = *DEG_get_original(obedit);
1212 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob_orig.data);
1213
1214 std::optional<Bounds<float3>> bounds = std::nullopt;
1215
1217 greasepencil::retrieve_editable_drawings(*scene, grease_pencil);
1218 for (const greasepencil::MutableDrawingInfo info : drawings) {
1219 const bke::CurvesGeometry &curves = info.drawing.strokes();
1220 if (curves.is_empty()) {
1221 continue;
1222 }
1223
1224 IndexMaskMemory memory;
1226 ob_orig, info.drawing, info.layer_index, memory);
1227 if (points.is_empty()) {
1228 continue;
1229 }
1230
1231 const bke::crazyspace::GeometryDeformation deformation =
1233 obedit, ob_orig, info.drawing);
1234
1235 const bke::greasepencil::Layer &layer = grease_pencil.layer(info.layer_index);
1236 const float4x4 layer_to_world = layer.to_world_space(*obedit);
1237
1239 bounds, bounds_min_max_with_transform(layer_to_world, deformation.positions, points));
1240 }
1241
1242 if (bounds) {
1243 minmax_v3v3_v3(r_min, r_max, bounds->min);
1244 minmax_v3v3_v3(r_min, r_max, bounds->max);
1245 return true;
1246 }
1247 return false;
1248 }
1249
1250 if (ED_transverts_check_obedit(obedit)) {
1252 }
1253
1254 if (tvs.transverts_tot == 0) {
1255 return false;
1256 }
1257
1258 copy_m3_m4(bmat, obedit->object_to_world().ptr());
1259
1260 tv = tvs.transverts;
1261 for (int a = 0; a < tvs.transverts_tot; a++, tv++) {
1262 copy_v3_v3(vec, (tv->flag & TX_VERT_USE_MAPLOC) ? tv->maploc : tv->loc);
1263 mul_m3_v3(bmat, vec);
1264 add_v3_v3(vec, obedit->object_to_world().location());
1265 add_v3_v3(centroid, vec);
1266 minmax_v3v3_v3(r_min, r_max, vec);
1267 }
1268
1269 ED_transverts_free(&tvs);
1270
1271 return true;
1272}
1273
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)
void BKE_pchan_protected_location_set(bPoseChannel *pchan, const float location[3])
void BKE_armature_loc_pose_to_bone(const bPoseChannel *pchan, const float inloc[3], float outloc[3])
void BKE_pchan_mat3_to_rot(bPoseChannel *pchan, const float mat[3][3], bool use_compat)
void BKE_pchan_protected_rotation_euler_set(bPoseChannel *pchan, const float rotation_euler[3])
void BKE_pchan_protected_rotation_quaternion_set(bPoseChannel *pchan, const float quat[4])
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:451
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)
@ RPT_ERROR
Definition BKE_report.hh:39
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
void BKE_scene_graph_evaluated_ensure(Depsgraph *depsgraph, Main *bmain)
Definition scene.cc:2626
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:2146
#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:1054
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1118
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ POSE_RUNTIME_TRANSFORM
@ ROT_MODE_QUAT
@ ROT_MODE_AXISANGLE
@ POSE_SELECTED
@ POSE_LOCKED
@ POSE_DO_UNLOCK
@ BONE_CONNECTED
@ OB_MODE_POSE
Object is a sort of wrapper for general info.
@ OB_MBALL
@ OB_CAMERA
@ OB_GREASE_PENCIL
@ OB_MESH
@ OB_POINTCLOUD
@ OB_CURVES
@ OB_DONE
#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_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)
@ TX_VERT_USE_MAPLOC
void ED_transverts_update_obedit(TransVertStore *tvs, Object *obedit)
@ 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
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define ND_TRANSFORM
Definition WM_types.hh:456
#define ND_SPACE_VIEW3D
Definition WM_types.hh:528
#define NC_OBJECT
Definition WM_types.hh:379
#define NC_SPACE
Definition WM_types.hh:392
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
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)
bool bone_is_visible(const bArmature *armature, const Bone *bone)
KeyingSet * get_keyingset_for_autokeying(const Scene *scene, const char *transformKSName)
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:279
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)
#define floorf
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:280
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]
struct bPoseChannel * parent
struct bPoseChannel_Runtime runtime
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)
static bool pose_bone_runtime_flag_test_recursive(const bPoseChannel *pose_bone, int flag)
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:4237
uint8_t flag
Definition wm_window.cc:145