Blender  V2.93
object_transform.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 <stdlib.h>
25 #include <string.h>
26 
27 #include "DNA_anim_types.h"
28 #include "DNA_armature_types.h"
29 #include "DNA_collection_types.h"
30 #include "DNA_gpencil_types.h"
31 #include "DNA_lattice_types.h"
32 #include "DNA_light_types.h"
33 #include "DNA_mesh_types.h"
34 #include "DNA_meta_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_scene_types.h"
37 
38 #include "BLI_array.h"
39 #include "BLI_listbase.h"
40 #include "BLI_math.h"
41 #include "BLI_utildefines.h"
42 
43 #include "BKE_armature.h"
44 #include "BKE_context.h"
45 #include "BKE_curve.h"
46 #include "BKE_editmesh.h"
47 #include "BKE_gpencil.h"
48 #include "BKE_gpencil_geom.h"
49 #include "BKE_idtype.h"
50 #include "BKE_lattice.h"
51 #include "BKE_layer.h"
52 #include "BKE_lib_id.h"
53 #include "BKE_main.h"
54 #include "BKE_mball.h"
55 #include "BKE_mesh.h"
56 #include "BKE_multires.h"
57 #include "BKE_object.h"
58 #include "BKE_report.h"
59 #include "BKE_scene.h"
60 #include "BKE_tracking.h"
61 
62 #include "DEG_depsgraph.h"
63 #include "DEG_depsgraph_query.h"
64 
65 #include "RNA_access.h"
66 #include "RNA_define.h"
67 
68 #include "WM_api.h"
69 #include "WM_types.h"
70 
71 #include "ED_armature.h"
72 #include "ED_gpencil.h"
73 #include "ED_keyframing.h"
74 #include "ED_mesh.h"
75 #include "ED_object.h"
76 #include "ED_screen.h"
77 #include "ED_view3d.h"
78 
79 #include "MEM_guardedalloc.h"
80 
81 #include "object_intern.h"
82 
83 /* -------------------------------------------------------------------- */
87 /* clear location of object */
88 static void object_clear_loc(Object *ob, const bool clear_delta)
89 {
90  /* clear location if not locked */
91  if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
92  ob->loc[0] = 0.0f;
93  if (clear_delta) {
94  ob->dloc[0] = 0.0f;
95  }
96  }
97  if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
98  ob->loc[1] = 0.0f;
99  if (clear_delta) {
100  ob->dloc[1] = 0.0f;
101  }
102  }
103  if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
104  ob->loc[2] = 0.0f;
105  if (clear_delta) {
106  ob->dloc[2] = 0.0f;
107  }
108  }
109 }
110 
111 /* clear rotation of object */
112 static void object_clear_rot(Object *ob, const bool clear_delta)
113 {
114  /* clear rotations that aren't locked */
116  if (ob->protectflag & OB_LOCK_ROT4D) {
117  /* perform clamping on a component by component basis */
118  if (ob->rotmode == ROT_MODE_AXISANGLE) {
119  if ((ob->protectflag & OB_LOCK_ROTW) == 0) {
120  ob->rotAngle = 0.0f;
121  if (clear_delta) {
122  ob->drotAngle = 0.0f;
123  }
124  }
125  if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
126  ob->rotAxis[0] = 0.0f;
127  if (clear_delta) {
128  ob->drotAxis[0] = 0.0f;
129  }
130  }
131  if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
132  ob->rotAxis[1] = 0.0f;
133  if (clear_delta) {
134  ob->drotAxis[1] = 0.0f;
135  }
136  }
137  if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
138  ob->rotAxis[2] = 0.0f;
139  if (clear_delta) {
140  ob->drotAxis[2] = 0.0f;
141  }
142  }
143 
144  /* Check validity of axis - axis should never be 0,0,0
145  * (if so, then we make it rotate about y). */
146  if (IS_EQF(ob->rotAxis[0], ob->rotAxis[1]) && IS_EQF(ob->rotAxis[1], ob->rotAxis[2])) {
147  ob->rotAxis[1] = 1.0f;
148  }
149  if (IS_EQF(ob->drotAxis[0], ob->drotAxis[1]) && IS_EQF(ob->drotAxis[1], ob->drotAxis[2]) &&
150  clear_delta) {
151  ob->drotAxis[1] = 1.0f;
152  }
153  }
154  else if (ob->rotmode == ROT_MODE_QUAT) {
155  if ((ob->protectflag & OB_LOCK_ROTW) == 0) {
156  ob->quat[0] = 1.0f;
157  if (clear_delta) {
158  ob->dquat[0] = 1.0f;
159  }
160  }
161  if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
162  ob->quat[1] = 0.0f;
163  if (clear_delta) {
164  ob->dquat[1] = 0.0f;
165  }
166  }
167  if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
168  ob->quat[2] = 0.0f;
169  if (clear_delta) {
170  ob->dquat[2] = 0.0f;
171  }
172  }
173  if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
174  ob->quat[3] = 0.0f;
175  if (clear_delta) {
176  ob->dquat[3] = 0.0f;
177  }
178  }
179  /* TODO: does this quat need normalizing now? */
180  }
181  else {
182  /* the flag may have been set for the other modes, so just ignore the extra flag... */
183  if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
184  ob->rot[0] = 0.0f;
185  if (clear_delta) {
186  ob->drot[0] = 0.0f;
187  }
188  }
189  if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
190  ob->rot[1] = 0.0f;
191  if (clear_delta) {
192  ob->drot[1] = 0.0f;
193  }
194  }
195  if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
196  ob->rot[2] = 0.0f;
197  if (clear_delta) {
198  ob->drot[2] = 0.0f;
199  }
200  }
201  }
202  }
203  else {
204  /* perform clamping using euler form (3-components) */
205  /* FIXME: deltas are not handled for these cases yet... */
206  float eul[3], oldeul[3], quat1[4] = {0};
207 
208  if (ob->rotmode == ROT_MODE_QUAT) {
209  copy_qt_qt(quat1, ob->quat);
210  quat_to_eul(oldeul, ob->quat);
211  }
212  else if (ob->rotmode == ROT_MODE_AXISANGLE) {
214  }
215  else {
216  copy_v3_v3(oldeul, ob->rot);
217  }
218 
219  eul[0] = eul[1] = eul[2] = 0.0f;
220 
221  if (ob->protectflag & OB_LOCK_ROTX) {
222  eul[0] = oldeul[0];
223  }
224  if (ob->protectflag & OB_LOCK_ROTY) {
225  eul[1] = oldeul[1];
226  }
227  if (ob->protectflag & OB_LOCK_ROTZ) {
228  eul[2] = oldeul[2];
229  }
230 
231  if (ob->rotmode == ROT_MODE_QUAT) {
232  eul_to_quat(ob->quat, eul);
233  /* quaternions flip w sign to accumulate rotations correctly */
234  if ((quat1[0] < 0.0f && ob->quat[0] > 0.0f) || (quat1[0] > 0.0f && ob->quat[0] < 0.0f)) {
235  mul_qt_fl(ob->quat, -1.0f);
236  }
237  }
238  else if (ob->rotmode == ROT_MODE_AXISANGLE) {
240  }
241  else {
242  copy_v3_v3(ob->rot, eul);
243  }
244  }
245  } /* Duplicated in source/blender/editors/armature/editarmature.c */
246  else {
247  if (ob->rotmode == ROT_MODE_QUAT) {
248  unit_qt(ob->quat);
249  if (clear_delta) {
250  unit_qt(ob->dquat);
251  }
252  }
253  else if (ob->rotmode == ROT_MODE_AXISANGLE) {
254  unit_axis_angle(ob->rotAxis, &ob->rotAngle);
255  if (clear_delta) {
257  }
258  }
259  else {
260  zero_v3(ob->rot);
261  if (clear_delta) {
262  zero_v3(ob->drot);
263  }
264  }
265  }
266 }
267 
268 /* clear scale of object */
269 static void object_clear_scale(Object *ob, const bool clear_delta)
270 {
271  /* clear scale factors which are not locked */
272  if ((ob->protectflag & OB_LOCK_SCALEX) == 0) {
273  ob->scale[0] = 1.0f;
274  if (clear_delta) {
275  ob->dscale[0] = 1.0f;
276  }
277  }
278  if ((ob->protectflag & OB_LOCK_SCALEY) == 0) {
279  ob->scale[1] = 1.0f;
280  if (clear_delta) {
281  ob->dscale[1] = 1.0f;
282  }
283  }
284  if ((ob->protectflag & OB_LOCK_SCALEZ) == 0) {
285  ob->scale[2] = 1.0f;
286  if (clear_delta) {
287  ob->dscale[2] = 1.0f;
288  }
289  }
290 }
291 
292 /* generic exec for clear-transform operators */
294  wmOperator *op,
295  void (*clear_func)(Object *, const bool),
296  const char default_ksName[])
297 {
299  Main *bmain = CTX_data_main(C);
301  ViewLayer *view_layer = CTX_data_view_layer(C);
302  /* May be NULL. */
303  View3D *v3d = CTX_wm_view3d(C);
304  KeyingSet *ks;
305  const bool clear_delta = RNA_boolean_get(op->ptr, "clear_delta");
306 
307  BLI_assert(!ELEM(NULL, clear_func, default_ksName));
308 
309  Object **objects = NULL;
310  uint objects_len = 0;
311  {
312  BLI_array_declare(objects);
313  FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN (view_layer, v3d, ob) {
314  BLI_array_append(objects, ob);
315  }
317  objects_len = BLI_array_len(objects);
318  }
319 
320  if (objects == NULL) {
321  return OPERATOR_CANCELLED;
322  }
323 
324  /* Support transforming the object data. */
325  const bool use_transform_skip_children = (scene->toolsettings->transform_flag &
327  const bool use_transform_data_origin = (scene->toolsettings->transform_flag &
329  struct XFormObjectSkipChild_Container *xcs = NULL;
330  struct XFormObjectData_Container *xds = NULL;
331 
332  if (use_transform_skip_children) {
336  xcs, view_layer, objects, objects_len);
337  }
338  if (use_transform_data_origin) {
341  }
342 
343  /* get KeyingSet to use */
344  ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
345 
346  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
347  Object *ob = objects[ob_index];
348 
349  if (use_transform_data_origin) {
351  }
352 
353  /* run provided clearing function */
354  clear_func(ob, clear_delta);
355 
356  ED_autokeyframe_object(C, scene, ob, ks);
357 
358  /* tag for updates */
360  }
361  MEM_freeN(objects);
362 
363  if (use_transform_skip_children) {
366  }
367 
368  if (use_transform_data_origin) {
371  }
372 
373  /* this is needed so children are also updated */
375 
376  return OPERATOR_FINISHED;
377 }
378 
381 /* -------------------------------------------------------------------- */
386 {
388 }
389 
391 {
392  /* identifiers */
393  ot->name = "Clear Location";
394  ot->description = "Clear the object's location";
395  ot->idname = "OBJECT_OT_location_clear";
396 
397  /* api callbacks */
400 
401  /* flags */
403 
404  /* properties */
406  ot->srna,
407  "clear_delta",
408  false,
409  "Clear Delta",
410  "Clear delta location in addition to clearing the normal location transform");
411 }
412 
415 /* -------------------------------------------------------------------- */
420 {
422 }
423 
425 {
426  /* identifiers */
427  ot->name = "Clear Rotation";
428  ot->description = "Clear the object's rotation";
429  ot->idname = "OBJECT_OT_rotation_clear";
430 
431  /* api callbacks */
434 
435  /* flags */
437 
438  /* properties */
440  ot->srna,
441  "clear_delta",
442  false,
443  "Clear Delta",
444  "Clear delta rotation in addition to clearing the normal rotation transform");
445 }
446 
449 /* -------------------------------------------------------------------- */
454 {
456 }
457 
459 {
460  /* identifiers */
461  ot->name = "Clear Scale";
462  ot->description = "Clear the object's scale";
463  ot->idname = "OBJECT_OT_scale_clear";
464 
465  /* api callbacks */
468 
469  /* flags */
471 
472  /* properties */
474  ot->srna,
475  "clear_delta",
476  false,
477  "Clear Delta",
478  "Clear delta scale in addition to clearing the normal scale transform");
479 }
480 
483 /* -------------------------------------------------------------------- */
488 {
489  float *v1, *v3;
490  float mat[3][3];
491 
492  CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
493  if (ob->parent) {
494  /* vectors pointed to by v1 and v3 will get modified */
495  v1 = ob->loc;
496  v3 = ob->parentinv[3];
497 
498  copy_m3_m4(mat, ob->parentinv);
499  negate_v3_v3(v3, v1);
500  mul_m3_v3(mat, v3);
501  }
502 
504  }
505  CTX_DATA_END;
506 
508 
509  return OPERATOR_FINISHED;
510 }
511 
513 {
514  /* identifiers */
515  ot->name = "Clear Origin";
516  ot->description = "Clear the object's origin";
517  ot->idname = "OBJECT_OT_origin_clear";
518 
519  /* api callbacks */
522 
523  /* flags */
525 }
526 
529 /* -------------------------------------------------------------------- */
533 /* use this when the loc/size/rot of the parent has changed but the children
534  * should stay in the same place, e.g. for apply-size-rot or object center */
536 {
537  Object workob;
538  Object *ob_child;
539 
540  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
541 
542  /* a change was made, adjust the children to compensate */
543  for (ob_child = bmain->objects.first; ob_child; ob_child = ob_child->id.next) {
544  if (ob_child->parent == ob) {
545  Object *ob_child_eval = DEG_get_evaluated_object(depsgraph, ob_child);
546  BKE_object_apply_mat4(ob_child_eval, ob_child_eval->obmat, true, false);
547  BKE_object_workob_calc_parent(depsgraph, scene, ob_child_eval, &workob);
548  invert_m4_m4(ob_child->parentinv, workob.obmat);
549  /* Copy result of BKE_object_apply_mat4(). */
550  BKE_object_transform_copy(ob_child, ob_child_eval);
551  /* Make sure evaluated object is in a consistent state with the original one.
552  * It might be needed for applying transform on its children. */
553  copy_m4_m4(ob_child_eval->parentinv, ob_child->parentinv);
554  BKE_object_eval_transform_all(depsgraph, scene_eval, ob_child_eval);
555  /* Tag for update.
556  * This is because parent matrix did change, so in theory the child object might now be
557  * evaluated to a different location in another editing context. */
559  }
560  }
561 }
562 
564  Object *object,
565  Object **sorted_objects,
566  int *object_index)
567 {
568  if (!ELEM(object->parent, NULL, root_object)) {
570  root_object, object->parent, sorted_objects, object_index);
571  }
572  if (object->id.tag & LIB_TAG_DOIT) {
573  sorted_objects[*object_index] = object;
574  (*object_index)++;
575  object->id.tag &= ~LIB_TAG_DOIT;
576  }
577 }
578 
579 static Object **sorted_selected_editable_objects(bContext *C, int *r_num_objects)
580 {
581  Main *bmain = CTX_data_main(C);
582 
583  /* Count all objects, but also tag all the selected ones. */
584  BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
585  int num_objects = 0;
586  CTX_DATA_BEGIN (C, Object *, object, selected_editable_objects) {
587  object->id.tag |= LIB_TAG_DOIT;
588  num_objects++;
589  }
590  CTX_DATA_END;
591  if (num_objects == 0) {
592  *r_num_objects = 0;
593  return NULL;
594  }
595 
596  /* Append all the objects. */
597  Object **sorted_objects = MEM_malloc_arrayN(num_objects, sizeof(Object *), "sorted objects");
598  int object_index = 0;
599  CTX_DATA_BEGIN (C, Object *, object, selected_editable_objects) {
600  if ((object->id.tag & LIB_TAG_DOIT) == 0) {
601  continue;
602  }
603  append_sorted_object_parent_hierarchy(object, object, sorted_objects, &object_index);
604  }
605  CTX_DATA_END;
606 
607  *r_num_objects = num_objects;
608 
609  return sorted_objects;
610 }
611 
613  ReportList *reports,
614  bool apply_loc,
615  bool apply_rot,
616  bool apply_scale,
617  bool do_props)
618 {
619  Main *bmain = CTX_data_main(C);
622  float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
623  bool changed = true;
624 
625  /* first check if we can execute */
626  CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
627  if (ELEM(ob->type,
628  OB_MESH,
629  OB_ARMATURE,
630  OB_LATTICE,
631  OB_MBALL,
632  OB_CURVE,
633  OB_SURF,
634  OB_FONT,
635  OB_GPENCIL)) {
636  ID *obdata = ob->data;
637  if (ID_REAL_USERS(obdata) > 1) {
638  BKE_reportf(reports,
639  RPT_ERROR,
640  "Cannot apply to a multi user: Object \"%s\", %s \"%s\", aborting",
641  ob->id.name + 2,
643  obdata->name + 2);
644  changed = false;
645  }
646 
647  if (ID_IS_LINKED(obdata)) {
648  BKE_reportf(reports,
649  RPT_ERROR,
650  "Cannot apply to library data: Object \"%s\", %s \"%s\", aborting",
651  ob->id.name + 2,
653  obdata->name + 2);
654  changed = false;
655  }
656  }
657 
658  if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
659  ID *obdata = ob->data;
660  Curve *cu;
661 
662  cu = ob->data;
663 
664  if (((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) && (apply_rot || apply_loc)) {
665  BKE_reportf(
666  reports,
667  RPT_ERROR,
668  "Rotation/Location can't apply to a 2D curve: Object \"%s\", %s \"%s\", aborting",
669  ob->id.name + 2,
671  obdata->name + 2);
672  changed = false;
673  }
674  if (cu->key) {
675  BKE_reportf(reports,
676  RPT_ERROR,
677  "Can't apply to a curve with shape-keys: Object \"%s\", %s \"%s\", aborting",
678  ob->id.name + 2,
680  obdata->name + 2);
681  changed = false;
682  }
683  }
684 
685  if (ob->type == OB_FONT) {
686  if (apply_rot || apply_loc) {
687  BKE_reportf(
688  reports, RPT_ERROR, "Font's can only have scale applied: \"%s\"", ob->id.name + 2);
689  changed = false;
690  }
691  }
692 
693  if (ob->type == OB_GPENCIL) {
694  bGPdata *gpd = ob->data;
695  if (gpd) {
696  if (gpd->layers.first) {
697  /* Unsupported configuration */
698  bool has_unparented_layers = false;
699 
700  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
701  /* Parented layers aren't supported as we can't easily re-evaluate
702  * the scene to sample parent movement */
703  if (gpl->parent == NULL) {
704  has_unparented_layers = true;
705  break;
706  }
707  }
708 
709  if (has_unparented_layers == false) {
710  BKE_reportf(reports,
711  RPT_ERROR,
712  "Can't apply to a GP datablock where all layers are parented: Object "
713  "\"%s\", %s \"%s\", aborting",
714  ob->id.name + 2,
716  gpd->id.name + 2);
717  changed = false;
718  }
719  }
720  else {
721  /* No layers/data */
722  BKE_reportf(
723  reports,
724  RPT_ERROR,
725  "Can't apply to GP datablock with no layers: Object \"%s\", %s \"%s\", aborting",
726  ob->id.name + 2,
728  gpd->id.name + 2);
729  }
730  }
731  }
732 
733  if (ob->type == OB_LAMP) {
734  Light *la = ob->data;
735  if (la->type == LA_AREA) {
736  if (apply_rot || apply_loc) {
737  BKE_reportf(reports,
738  RPT_ERROR,
739  "Area Lights can only have scale applied: \"%s\"",
740  ob->id.name + 2);
741  changed = false;
742  }
743  }
744  }
745  }
746  CTX_DATA_END;
747 
748  if (!changed) {
749  return OPERATOR_CANCELLED;
750  }
751 
752  changed = false;
753 
754  /* now execute */
755  int num_objects;
756  Object **objects = sorted_selected_editable_objects(C, &num_objects);
757  if (objects == NULL) {
758  return OPERATOR_CANCELLED;
759  }
760 
761  for (int object_index = 0; object_index < num_objects; object_index++) {
762  Object *ob = objects[object_index];
763 
764  /* calculate rotation/scale matrix */
765  if (apply_scale && apply_rot) {
766  BKE_object_to_mat3(ob, rsmat);
767  }
768  else if (apply_scale) {
769  BKE_object_scale_to_mat3(ob, rsmat);
770  }
771  else if (apply_rot) {
772  float tmat[3][3], timat[3][3];
773 
774  /* simple rotation matrix */
775  BKE_object_rot_to_mat3(ob, rsmat, true);
776 
777  /* correct for scale, note mul_m3_m3m3 has swapped args! */
778  BKE_object_scale_to_mat3(ob, tmat);
779  invert_m3_m3(timat, tmat);
780  mul_m3_m3m3(rsmat, timat, rsmat);
781  mul_m3_m3m3(rsmat, rsmat, tmat);
782  }
783  else {
784  unit_m3(rsmat);
785  }
786 
787  copy_m4_m3(mat, rsmat);
788 
789  /* calculate translation */
790  if (apply_loc) {
791  add_v3_v3v3(mat[3], ob->loc, ob->dloc);
792 
793  if (!(apply_scale && apply_rot)) {
794  float tmat[3][3];
795  /* correct for scale and rotation that is still applied */
796  BKE_object_to_mat3(ob, obmat);
797  invert_m3_m3(iobmat, obmat);
798  mul_m3_m3m3(tmat, rsmat, iobmat);
799  mul_m3_v3(tmat, mat[3]);
800  }
801  }
802 
803  /* apply to object data */
804  if (ob->type == OB_MESH) {
805  Mesh *me = ob->data;
806 
807  if (apply_scale) {
809  }
810 
811  /* adjust data */
812  BKE_mesh_transform(me, mat, true);
813 
814  /* update normals */
816  }
817  else if (ob->type == OB_ARMATURE) {
818  bArmature *arm = ob->data;
819  BKE_armature_transform(arm, mat, do_props);
820  }
821  else if (ob->type == OB_LATTICE) {
822  Lattice *lt = ob->data;
823 
824  BKE_lattice_transform(lt, mat, true);
825  }
826  else if (ob->type == OB_MBALL) {
827  MetaBall *mb = ob->data;
828  BKE_mball_transform(mb, mat, do_props);
829  }
830  else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
831  Curve *cu = ob->data;
832  scale = mat3_to_scale(rsmat);
833  BKE_curve_transform_ex(cu, mat, true, do_props, scale);
834  }
835  else if (ob->type == OB_FONT) {
836  Curve *cu = ob->data;
837 
838  scale = mat3_to_scale(rsmat);
839 
840  for (int i = 0; i < cu->totbox; i++) {
841  TextBox *tb = &cu->tb[i];
842  tb->x *= scale;
843  tb->y *= scale;
844  tb->w *= scale;
845  tb->h *= scale;
846  }
847 
848  if (do_props) {
849  cu->fsize *= scale;
850  }
851  }
852  else if (ob->type == OB_GPENCIL) {
853  bGPdata *gpd = ob->data;
854  BKE_gpencil_transform(gpd, mat);
855  }
856  else if (ob->type == OB_CAMERA) {
857  MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
858 
859  /* applying scale on camera actually scales clip's reconstruction.
860  * of there's clip assigned to camera nothing to do actually.
861  */
862  if (!clip) {
863  continue;
864  }
865 
866  if (apply_scale) {
868  }
869  }
870  else if (ob->type == OB_EMPTY) {
871  /* It's possible for empties too, even though they don't
872  * really have obdata, since we can simply apply the maximum
873  * scaling to the empty's drawsize.
874  *
875  * Core Assumptions:
876  * 1) Most scaled empties have uniform scaling
877  * (i.e. for visibility reasons), AND/OR
878  * 2) Preserving non-uniform scaling is not that important,
879  * and is something that many users would be willing to
880  * sacrifice for having an easy way to do this.
881  */
882 
883  if ((apply_loc == false) && (apply_rot == false) && (apply_scale == true)) {
884  float max_scale = max_fff(fabsf(ob->scale[0]), fabsf(ob->scale[1]), fabsf(ob->scale[2]));
885  ob->empty_drawsize *= max_scale;
886  }
887  }
888  else if (ob->type == OB_LAMP) {
889  Light *la = ob->data;
890  if (la->type != LA_AREA) {
891  continue;
892  }
893 
894  bool keeps_aspect_ratio = compare_ff_relative(rsmat[0][0], rsmat[1][1], FLT_EPSILON, 64);
895  if ((la->area_shape == LA_AREA_SQUARE) && !keeps_aspect_ratio) {
896  la->area_shape = LA_AREA_RECT;
897  la->area_sizey = la->area_size;
898  }
899  else if ((la->area_shape == LA_AREA_DISK) && !keeps_aspect_ratio) {
901  la->area_sizey = la->area_size;
902  }
903 
904  la->area_size *= rsmat[0][0];
905  la->area_sizey *= rsmat[1][1];
906  la->area_sizez *= rsmat[2][2];
907  }
908  else {
909  continue;
910  }
911 
912  if (apply_loc) {
913  zero_v3(ob->loc);
914  zero_v3(ob->dloc);
915  }
916  if (apply_scale) {
917  copy_v3_fl(ob->scale, 1.0f);
918  copy_v3_fl(ob->dscale, 1.0f);
919  }
920  if (apply_rot) {
921  zero_v3(ob->rot);
922  zero_v3(ob->drot);
923  unit_qt(ob->quat);
924  unit_qt(ob->dquat);
925  unit_axis_angle(ob->rotAxis, &ob->rotAngle);
927  }
928 
929  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
930  BKE_object_transform_copy(ob_eval, ob);
931 
933  if (ob->type == OB_ARMATURE) {
934  /* needed for bone parents */
936  BKE_pose_where_is(depsgraph, scene, ob_eval);
937  }
938 
939  ignore_parent_tx(bmain, depsgraph, scene, ob);
940 
942 
943  changed = true;
944  }
945 
946  MEM_freeN(objects);
947 
948  if (!changed) {
949  BKE_report(reports, RPT_WARNING, "Objects have no data to transform");
950  return OPERATOR_CANCELLED;
951  }
952 
954  return OPERATOR_FINISHED;
955 }
956 
958 {
961  bool changed = false;
962 
963  CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
964  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
966  BKE_object_apply_mat4(ob_eval, ob_eval->obmat, true, true);
967  BKE_object_transform_copy(ob, ob_eval);
968 
969  /* update for any children that may get moved */
971 
972  changed = true;
973  }
974  CTX_DATA_END;
975 
976  if (!changed) {
977  return OPERATOR_CANCELLED;
978  }
979 
981  return OPERATOR_FINISHED;
982 }
983 
985 {
986  /* identifiers */
987  ot->name = "Apply Visual Transform";
988  ot->description = "Apply the object's visual transformation to its data";
989  ot->idname = "OBJECT_OT_visual_transform_apply";
990 
991  /* api callbacks */
994 
995  /* flags */
997 }
998 
1000 {
1001  const bool loc = RNA_boolean_get(op->ptr, "location");
1002  const bool rot = RNA_boolean_get(op->ptr, "rotation");
1003  const bool sca = RNA_boolean_get(op->ptr, "scale");
1004  const bool do_props = RNA_boolean_get(op->ptr, "properties");
1005 
1006  if (loc || rot || sca) {
1007  return apply_objects_internal(C, op->reports, loc, rot, sca, do_props);
1008  }
1009  /* allow for redo */
1010  return OPERATOR_FINISHED;
1011 }
1012 
1014 {
1015  /* identifiers */
1016  ot->name = "Apply Object Transform";
1017  ot->description = "Apply the object's transformation to its data";
1018  ot->idname = "OBJECT_OT_transform_apply";
1019 
1020  /* api callbacks */
1023 
1024  /* flags */
1026 
1027  RNA_def_boolean(ot->srna, "location", true, "Location", "");
1028  RNA_def_boolean(ot->srna, "rotation", true, "Rotation", "");
1029  RNA_def_boolean(ot->srna, "scale", true, "Scale", "");
1031  "properties",
1032  true,
1033  "Apply Properties",
1034  "Modify properties such as curve vertex radius, font size and bone envelope");
1035 }
1036 
1039 /* -------------------------------------------------------------------- */
1043 enum {
1049 };
1050 
1052 {
1053  Main *bmain = CTX_data_main(C);
1055  Object *obact = CTX_data_active_object(C);
1056  Object *obedit = CTX_data_edit_object(C);
1058  Object *tob;
1059  float cent[3], cent_neg[3], centn[3];
1060  const float *cursor = scene->cursor.location;
1061  int centermode = RNA_enum_get(op->ptr, "type");
1062 
1063  /* keep track of what is changed */
1064  int tot_change = 0, tot_lib_error = 0, tot_multiuser_arm_error = 0;
1065 
1066  if (obedit && centermode != GEOMETRY_TO_ORIGIN) {
1067  BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode");
1068  return OPERATOR_CANCELLED;
1069  }
1070 
1071  int around;
1072  {
1073  PropertyRNA *prop_center = RNA_struct_find_property(op->ptr, "center");
1074  if (RNA_property_is_set(op->ptr, prop_center)) {
1075  around = RNA_property_enum_get(op->ptr, prop_center);
1076  }
1077  else {
1079  around = V3D_AROUND_CENTER_BOUNDS;
1080  }
1081  else {
1082  around = V3D_AROUND_CENTER_MEDIAN;
1083  }
1084  RNA_property_enum_set(op->ptr, prop_center, around);
1085  }
1086  }
1087 
1088  zero_v3(cent);
1089 
1090  if (obedit) {
1091  if (obedit->type == OB_MESH) {
1092  Mesh *me = obedit->data;
1093  BMEditMesh *em = me->edit_mesh;
1094  BMVert *eve;
1095  BMIter iter;
1096 
1097  if (centermode == ORIGIN_TO_CURSOR) {
1098  copy_v3_v3(cent, cursor);
1099  invert_m4_m4(obedit->imat, obedit->obmat);
1100  mul_m4_v3(obedit->imat, cent);
1101  }
1102  else {
1103  if (around == V3D_AROUND_CENTER_BOUNDS) {
1104  float min[3], max[3];
1105  INIT_MINMAX(min, max);
1106  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
1107  minmax_v3v3_v3(min, max, eve->co);
1108  }
1109  mid_v3_v3v3(cent, min, max);
1110  }
1111  else { /* #V3D_AROUND_CENTER_MEDIAN. */
1112  if (em->bm->totvert) {
1113  const float total_div = 1.0f / (float)em->bm->totvert;
1114  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
1115  madd_v3_v3fl(cent, eve->co, total_div);
1116  }
1117  }
1118  }
1119  }
1120 
1121  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
1122  sub_v3_v3(eve->co, cent);
1123  }
1124 
1126  tot_change++;
1128  }
1129  }
1130 
1131  int num_objects;
1132  Object **objects = sorted_selected_editable_objects(C, &num_objects);
1133  if (objects == NULL) {
1134  return OPERATOR_CANCELLED;
1135  }
1136 
1137  /* reset flags */
1138  for (int object_index = 0; object_index < num_objects; object_index++) {
1139  Object *ob = objects[object_index];
1140  ob->flag &= ~OB_DONE;
1141 
1142  /* move active first */
1143  if (ob == obact) {
1144  memmove(&objects[1], objects, object_index * sizeof(Object *));
1145  objects[0] = ob;
1146  }
1147  }
1148 
1149  for (tob = bmain->objects.first; tob; tob = tob->id.next) {
1150  if (tob->data) {
1151  ((ID *)tob->data)->tag &= ~LIB_TAG_DOIT;
1152  }
1153  if (tob->instance_collection) {
1154  ((ID *)tob->instance_collection)->tag &= ~LIB_TAG_DOIT;
1155  }
1156  }
1157 
1158  for (int object_index = 0; object_index < num_objects; object_index++) {
1159  Object *ob = objects[object_index];
1160 
1161  if ((ob->flag & OB_DONE) == 0) {
1162  bool do_inverse_offset = false;
1163  ob->flag |= OB_DONE;
1164 
1165  if (centermode == ORIGIN_TO_CURSOR) {
1166  copy_v3_v3(cent, cursor);
1167  invert_m4_m4(ob->imat, ob->obmat);
1168  mul_m4_v3(ob->imat, cent);
1169  }
1170 
1171  if (ob->data == NULL) {
1172  /* special support for dupligroups */
1173  if ((ob->transflag & OB_DUPLICOLLECTION) && ob->instance_collection &&
1174  (ob->instance_collection->id.tag & LIB_TAG_DOIT) == 0) {
1175  if (ID_IS_LINKED(ob->instance_collection)) {
1176  tot_lib_error++;
1177  }
1178  else {
1179  if (centermode == ORIGIN_TO_CURSOR) {
1180  /* done */
1181  }
1182  else {
1183  float min[3], max[3];
1184  /* only bounds support */
1185  INIT_MINMAX(min, max);
1187  mid_v3_v3v3(cent, min, max);
1188  invert_m4_m4(ob->imat, ob->obmat);
1189  mul_m4_v3(ob->imat, cent);
1190  }
1191 
1193 
1194  tot_change++;
1196  do_inverse_offset = true;
1197  }
1198  }
1199  }
1200  else if (ID_IS_LINKED(ob->data)) {
1201  tot_lib_error++;
1202  }
1203  else if (ob->type == OB_MESH) {
1204  if (obedit == NULL) {
1205  Mesh *me = ob->data;
1206 
1207  if (centermode == ORIGIN_TO_CURSOR) {
1208  /* done */
1209  }
1210  else if (centermode == ORIGIN_TO_CENTER_OF_MASS_SURFACE) {
1211  BKE_mesh_center_of_surface(me, cent);
1212  }
1213  else if (centermode == ORIGIN_TO_CENTER_OF_MASS_VOLUME) {
1214  BKE_mesh_center_of_volume(me, cent);
1215  }
1216  else if (around == V3D_AROUND_CENTER_BOUNDS) {
1217  BKE_mesh_center_bounds(me, cent);
1218  }
1219  else { /* #V3D_AROUND_CENTER_MEDIAN. */
1220  BKE_mesh_center_median(me, cent);
1221  }
1222 
1223  negate_v3_v3(cent_neg, cent);
1224  BKE_mesh_translate(me, cent_neg, 1);
1225 
1226  tot_change++;
1227  me->id.tag |= LIB_TAG_DOIT;
1228  do_inverse_offset = true;
1229  }
1230  }
1231  else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
1232  Curve *cu = ob->data;
1233 
1234  if (centermode == ORIGIN_TO_CURSOR) {
1235  /* done */
1236  }
1237  else if (around == V3D_AROUND_CENTER_BOUNDS) {
1238  BKE_curve_center_bounds(cu, cent);
1239  }
1240  else { /* #V3D_AROUND_CENTER_MEDIAN. */
1241  BKE_curve_center_median(cu, cent);
1242  }
1243 
1244  /* don't allow Z change if curve is 2D */
1245  if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) {
1246  cent[2] = 0.0;
1247  }
1248 
1249  negate_v3_v3(cent_neg, cent);
1250  BKE_curve_translate(cu, cent_neg, 1);
1251 
1252  tot_change++;
1253  cu->id.tag |= LIB_TAG_DOIT;
1254  do_inverse_offset = true;
1255 
1256  if (obedit) {
1257  if (centermode == GEOMETRY_TO_ORIGIN) {
1259  }
1260  break;
1261  }
1262  }
1263  else if (ob->type == OB_FONT) {
1264  /* get from bb */
1265 
1266  Curve *cu = ob->data;
1267 
1268  if (ob->runtime.bb == NULL && (centermode != ORIGIN_TO_CURSOR)) {
1269  /* do nothing*/
1270  }
1271  else {
1272  if (centermode == ORIGIN_TO_CURSOR) {
1273  /* done */
1274  }
1275  else {
1276  /* extra 0.5 is the height o above line */
1277  cent[0] = 0.5f * (ob->runtime.bb->vec[4][0] + ob->runtime.bb->vec[0][0]);
1278  cent[1] = 0.5f * (ob->runtime.bb->vec[0][1] + ob->runtime.bb->vec[2][1]);
1279  }
1280 
1281  cent[2] = 0.0f;
1282 
1283  cu->xof = cu->xof - cent[0];
1284  cu->yof = cu->yof - cent[1];
1285 
1286  tot_change++;
1287  cu->id.tag |= LIB_TAG_DOIT;
1288  do_inverse_offset = true;
1289  }
1290  }
1291  else if (ob->type == OB_ARMATURE) {
1292  bArmature *arm = ob->data;
1293 
1294  if (ID_REAL_USERS(arm) > 1) {
1295 #if 0
1296  BKE_report(op->reports, RPT_ERROR, "Cannot apply to a multi user armature");
1297  return;
1298 #endif
1299  tot_multiuser_arm_error++;
1300  }
1301  else {
1302  /* Function to recenter armatures in editarmature.c
1303  * Bone + object locations are handled there.
1304  */
1305  ED_armature_origin_set(bmain, ob, cursor, centermode, around);
1306 
1307  tot_change++;
1308  arm->id.tag |= LIB_TAG_DOIT;
1309  /* do_inverse_offset = true; */ /* docenter_armature() handles this */
1310 
1311  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
1312  BKE_object_transform_copy(ob_eval, ob);
1315  BKE_pose_where_is(depsgraph, scene, ob_eval); /* needed for bone parents */
1316 
1317  ignore_parent_tx(bmain, depsgraph, scene, ob);
1318 
1319  if (obedit) {
1320  break;
1321  }
1322  }
1323  }
1324  else if (ob->type == OB_MBALL) {
1325  MetaBall *mb = ob->data;
1326 
1327  if (centermode == ORIGIN_TO_CURSOR) {
1328  /* done */
1329  }
1330  else if (around == V3D_AROUND_CENTER_BOUNDS) {
1331  BKE_mball_center_bounds(mb, cent);
1332  }
1333  else { /* #V3D_AROUND_CENTER_MEDIAN. */
1334  BKE_mball_center_median(mb, cent);
1335  }
1336 
1337  negate_v3_v3(cent_neg, cent);
1338  BKE_mball_translate(mb, cent_neg);
1339 
1340  tot_change++;
1341  mb->id.tag |= LIB_TAG_DOIT;
1342  do_inverse_offset = true;
1343 
1344  if (obedit) {
1345  if (centermode == GEOMETRY_TO_ORIGIN) {
1347  }
1348  break;
1349  }
1350  }
1351  else if (ob->type == OB_LATTICE) {
1352  Lattice *lt = ob->data;
1353 
1354  if (centermode == ORIGIN_TO_CURSOR) {
1355  /* done */
1356  }
1357  else if (around == V3D_AROUND_CENTER_BOUNDS) {
1358  BKE_lattice_center_bounds(lt, cent);
1359  }
1360  else { /* #V3D_AROUND_CENTER_MEDIAN. */
1361  BKE_lattice_center_median(lt, cent);
1362  }
1363 
1364  negate_v3_v3(cent_neg, cent);
1365  BKE_lattice_translate(lt, cent_neg, 1);
1366 
1367  tot_change++;
1368  lt->id.tag |= LIB_TAG_DOIT;
1369  do_inverse_offset = true;
1370  }
1371  else if (ob->type == OB_GPENCIL) {
1372  bGPdata *gpd = ob->data;
1373  float gpcenter[3];
1374  if (gpd) {
1375  if (centermode == ORIGIN_TO_GEOMETRY) {
1376  zero_v3(gpcenter);
1377  BKE_gpencil_centroid_3d(gpd, gpcenter);
1378  add_v3_v3(gpcenter, ob->obmat[3]);
1379  }
1380  if (centermode == ORIGIN_TO_CURSOR) {
1381  copy_v3_v3(gpcenter, cursor);
1382  }
1383  if (ELEM(centermode, ORIGIN_TO_GEOMETRY, ORIGIN_TO_CURSOR)) {
1384  bGPDspoint *pt;
1385  float imat[3][3], bmat[3][3];
1386  float offset_global[3];
1387  float offset_local[3];
1388  int i;
1389 
1390  sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]);
1391  copy_m3_m4(bmat, obact->obmat);
1392  invert_m3_m3(imat, bmat);
1393  mul_m3_v3(imat, offset_global);
1394  mul_v3_m3v3(offset_local, imat, offset_global);
1395 
1396  float diff_mat[4][4];
1397  float inverse_diff_mat[4][4];
1398 
1399  /* recalculate all strokes
1400  * (all layers are considered without evaluating lock attributes) */
1401  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1402  /* calculate difference matrix */
1403  BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat);
1404  /* undo matrix */
1405  invert_m4_m4(inverse_diff_mat, diff_mat);
1406  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
1407  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
1408  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1409  float mpt[3];
1410  mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
1411  sub_v3_v3(mpt, offset_local);
1412  mul_v3_m4v3(&pt->x, diff_mat, mpt);
1413  }
1415  }
1416  }
1417  }
1418  tot_change++;
1419  if (centermode == ORIGIN_TO_GEOMETRY) {
1420  copy_v3_v3(ob->loc, gpcenter);
1421  }
1424 
1425  ob->id.tag |= LIB_TAG_DOIT;
1426  do_inverse_offset = true;
1427  }
1428  else {
1429  BKE_report(op->reports,
1430  RPT_WARNING,
1431  "Grease Pencil Object does not support this set origin option");
1432  }
1433  }
1434  }
1435 
1436  /* offset other selected objects */
1437  if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) {
1438  float obmat[4][4];
1439 
1440  /* was the object data modified
1441  * note: the functions above must set 'cent' */
1442 
1443  /* convert the offset to parent space */
1444  BKE_object_to_mat4(ob, obmat);
1445  mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */
1446 
1447  add_v3_v3(ob->loc, centn);
1448 
1449  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
1450  BKE_object_transform_copy(ob_eval, ob);
1452  if (ob->type == OB_ARMATURE) {
1453  /* needed for bone parents */
1455  BKE_pose_where_is(depsgraph, scene, ob_eval);
1456  }
1457 
1458  ignore_parent_tx(bmain, depsgraph, scene, ob);
1459 
1460  /* other users? */
1461  // CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects)
1462  //{
1463 
1464  /* use existing context looper */
1465  for (int other_object_index = 0; other_object_index < num_objects; other_object_index++) {
1466  Object *ob_other = objects[other_object_index];
1467 
1468  if ((ob_other->flag & OB_DONE) == 0 &&
1469  ((ob->data && (ob->data == ob_other->data)) ||
1470  (ob->instance_collection == ob_other->instance_collection &&
1471  (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION))) {
1472  ob_other->flag |= OB_DONE;
1474 
1475  mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */
1476  add_v3_v3(ob_other->loc, centn);
1477 
1478  Object *ob_other_eval = DEG_get_evaluated_object(depsgraph, ob_other);
1479  BKE_object_transform_copy(ob_other_eval, ob_other);
1480  BKE_object_where_is_calc(depsgraph, scene, ob_other_eval);
1481  if (ob_other->type == OB_ARMATURE) {
1482  /* needed for bone parents */
1484  BKE_pose_where_is(depsgraph, scene, ob_other_eval);
1485  }
1486  ignore_parent_tx(bmain, depsgraph, scene, ob_other);
1487  }
1488  }
1489  // CTX_DATA_END;
1490  }
1491  }
1492  }
1493  MEM_freeN(objects);
1494 
1495  for (tob = bmain->objects.first; tob; tob = tob->id.next) {
1496  if (tob->data && (((ID *)tob->data)->tag & LIB_TAG_DOIT)) {
1499  }
1500  /* special support for dupligroups */
1501  else if (tob->instance_collection && tob->instance_collection->id.tag & LIB_TAG_DOIT) {
1504  }
1505  }
1506 
1507  if (tot_change) {
1509  }
1510 
1511  /* Warn if any errors occurred */
1512  if (tot_lib_error + tot_multiuser_arm_error) {
1513  BKE_reportf(op->reports,
1514  RPT_WARNING,
1515  "%i object(s) not centered, %i changed:",
1516  tot_lib_error + tot_multiuser_arm_error,
1517  tot_change);
1518  if (tot_lib_error) {
1519  BKE_reportf(op->reports, RPT_WARNING, "|%i linked library object(s)", tot_lib_error);
1520  }
1521  if (tot_multiuser_arm_error) {
1522  BKE_reportf(
1523  op->reports, RPT_WARNING, "|%i multiuser armature object(s)", tot_multiuser_arm_error);
1524  }
1525  }
1526 
1527  return OPERATOR_FINISHED;
1528 }
1529 
1531 {
1532  static const EnumPropertyItem prop_set_center_types[] = {
1534  "GEOMETRY_ORIGIN",
1535  0,
1536  "Geometry to Origin",
1537  "Move object geometry to object origin"},
1539  "ORIGIN_GEOMETRY",
1540  0,
1541  "Origin to Geometry",
1542  "Calculate the center of geometry based on the current pivot point (median, otherwise "
1543  "bounding box)"},
1545  "ORIGIN_CURSOR",
1546  0,
1547  "Origin to 3D Cursor",
1548  "Move object origin to position of the 3D cursor"},
1549  /* Intentional naming mismatch since some scripts refer to this. */
1551  "ORIGIN_CENTER_OF_MASS",
1552  0,
1553  "Origin to Center of Mass (Surface)",
1554  "Calculate the center of mass from the surface area"},
1556  "ORIGIN_CENTER_OF_VOLUME",
1557  0,
1558  "Origin to Center of Mass (Volume)",
1559  "Calculate the center of mass from the volume (must be manifold geometry with consistent "
1560  "normals)"},
1561  {0, NULL, 0, NULL, NULL},
1562  };
1563 
1564  static const EnumPropertyItem prop_set_bounds_types[] = {
1565  {V3D_AROUND_CENTER_MEDIAN, "MEDIAN", 0, "Median Center", ""},
1566  {V3D_AROUND_CENTER_BOUNDS, "BOUNDS", 0, "Bounds Center", ""},
1567  {0, NULL, 0, NULL, NULL},
1568  };
1569 
1570  /* identifiers */
1571  ot->name = "Set Origin";
1572  ot->description =
1573  "Set the object's origin, by either moving the data, or set to center of data, or use 3D "
1574  "cursor";
1575  ot->idname = "OBJECT_OT_origin_set";
1576 
1577  /* api callbacks */
1580 
1582 
1583  /* flags */
1585 
1586  ot->prop = RNA_def_enum(ot->srna, "type", prop_set_center_types, 0, "Type", "");
1587  RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_AROUND_CENTER_MEDIAN, "Center", "");
1588 }
1589 
1592 /* -------------------------------------------------------------------- */
1601 #define USE_RELATIVE_ROTATION
1603 #define USE_RENDER_OVERRIDE
1608 #define USE_FAKE_DEPTH_INIT
1609 
1612  float rot_mat[3][3];
1613  void *obtfm;
1614  float xform_dist;
1616 
1617 #ifdef USE_RELATIVE_ROTATION
1618  /* use when translating multiple */
1619  float xform_rot_offset[3][3];
1620 #endif
1621 };
1622 
1625  struct {
1626  float depth;
1627  float normal[3];
1630  } prev;
1631 
1635 
1637 };
1638 
1639 #ifdef USE_FAKE_DEPTH_INIT
1641  const int mval[2])
1642 {
1643  struct XFormAxisItem *item = xfd->object_data;
1644  float view_co_a[3], view_co_b[3];
1645  const float mval_fl[2] = {UNPACK2(mval)};
1646  ED_view3d_win_to_ray(xfd->vc.region, mval_fl, view_co_a, view_co_b);
1647  add_v3_v3(view_co_b, view_co_a);
1648  float center[3] = {0.0f};
1649  int center_tot = 0;
1650  for (int i = 0; i < xfd->object_data_len; i++, item++) {
1651  const Object *ob = item->ob;
1652  const float *ob_co_a = ob->obmat[3];
1653  float ob_co_b[3];
1654  add_v3_v3v3(ob_co_b, ob->obmat[3], ob->obmat[2]);
1655  float view_isect[3], ob_isect[3];
1656  if (isect_line_line_v3(view_co_a, view_co_b, ob_co_a, ob_co_b, view_isect, ob_isect)) {
1657  add_v3_v3(center, view_isect);
1658  center_tot += 1;
1659  }
1660  }
1661  if (center_tot) {
1662  mul_v3_fl(center, 1.0f / center_tot);
1663  float center_proj[3];
1664  ED_view3d_project(xfd->vc.region, center, center_proj);
1665  xfd->prev.depth = center_proj[2];
1666  xfd->prev.is_depth_valid = true;
1667  }
1668 }
1669 #endif /* USE_FAKE_DEPTH_INIT */
1670 
1671 static bool object_is_target_compat(const Object *ob)
1672 {
1673  if (ob->type == OB_LAMP) {
1674  const Light *la = ob->data;
1675  if (ELEM(la->type, LA_SUN, LA_SPOT, LA_AREA)) {
1676  return true;
1677  }
1678  }
1679  /* We might want to enable this later, for now just lights. */
1680 #if 0
1681  else if (ob->type == OB_CAMERA) {
1682  return true;
1683  }
1684 #endif
1685  return false;
1686 }
1687 
1689 {
1690  struct XFormAxisData *xfd = op->customdata;
1691  struct XFormAxisItem *item = xfd->object_data;
1692 
1693 #ifdef USE_RENDER_OVERRIDE
1694  if (xfd->vc.rv3d->depths) {
1695  xfd->vc.rv3d->depths->damaged = true;
1696  }
1697 #endif
1698 
1699  for (int i = 0; i < xfd->object_data_len; i++, item++) {
1700  MEM_freeN(item->obtfm);
1701  }
1702  MEM_freeN(xfd->object_data);
1703  MEM_freeN(xfd);
1704  op->customdata = NULL;
1705 }
1706 
1707 /* We may want to expose as alternative to: BKE_object_apply_rotation */
1708 static void object_apply_rotation(Object *ob, const float rmat[3][3])
1709 {
1710  float size[3];
1711  float loc[3];
1712  float rmat4[4][4];
1713  copy_m4_m3(rmat4, rmat);
1714 
1715  copy_v3_v3(size, ob->scale);
1716  copy_v3_v3(loc, ob->loc);
1717  BKE_object_apply_mat4(ob, rmat4, true, true);
1718  copy_v3_v3(ob->scale, size);
1719  copy_v3_v3(ob->loc, loc);
1720 }
1721 /* We may want to extract this to: BKE_object_apply_location */
1722 static void object_apply_location(Object *ob, const float loc[3])
1723 {
1724  /* quick but weak */
1725  Object ob_prev = *ob;
1726  float mat[4][4];
1727  copy_m4_m4(mat, ob->obmat);
1728  copy_v3_v3(mat[3], loc);
1729  BKE_object_apply_mat4(ob, mat, true, true);
1730  copy_v3_v3(mat[3], ob->loc);
1731  *ob = ob_prev;
1732  copy_v3_v3(ob->loc, mat[3]);
1733 }
1734 
1736  const float rot_orig[3][3],
1737  const float axis[3],
1738  const float location[3],
1739  const bool z_flip)
1740 {
1741  float delta[3];
1742  sub_v3_v3v3(delta, ob->obmat[3], location);
1743  if (normalize_v3(delta) != 0.0f) {
1744  if (z_flip) {
1745  negate_v3(delta);
1746  }
1747 
1748  if (len_squared_v3v3(delta, axis) > FLT_EPSILON) {
1749  float delta_rot[3][3];
1750  float final_rot[3][3];
1751  rotation_between_vecs_to_mat3(delta_rot, axis, delta);
1752 
1753  mul_m3_m3m3(final_rot, delta_rot, rot_orig);
1754 
1755  object_apply_rotation(ob, final_rot);
1756 
1757  return true;
1758  }
1759  }
1760  return false;
1761 }
1762 
1764 {
1765  struct XFormAxisData *xfd = op->customdata;
1766  struct XFormAxisItem *item = xfd->object_data;
1767  for (int i = 0; i < xfd->object_data_len; i++, item++) {
1768  BKE_object_tfm_restore(item->ob, item->obtfm);
1771  }
1772 
1774 }
1775 
1777 {
1779  ViewContext vc;
1781 
1782  if (vc.obact == NULL || !object_is_target_compat(vc.obact)) {
1783  /* Falls back to texture space transform. */
1784  return OPERATOR_PASS_THROUGH;
1785  }
1786 
1787 #ifdef USE_RENDER_OVERRIDE
1788  int flag2_prev = vc.v3d->flag2;
1789  vc.v3d->flag2 |= V3D_HIDE_OVERLAYS;
1790 #endif
1791 
1793 
1794 #ifdef USE_RENDER_OVERRIDE
1795  vc.v3d->flag2 = flag2_prev;
1796 #endif
1797 
1798  if (vc.rv3d->depths == NULL) {
1799  BKE_report(op->reports, RPT_WARNING, "Unable to access depth buffer, using view plane");
1800  return OPERATOR_CANCELLED;
1801  }
1802 
1804 
1805  struct XFormAxisData *xfd;
1806  xfd = op->customdata = MEM_callocN(sizeof(struct XFormAxisData), __func__);
1807 
1808  /* Don't change this at runtime. */
1809  xfd->vc = vc;
1810  xfd->vc.mval[0] = event->mval[0];
1811  xfd->vc.mval[1] = event->mval[1];
1812 
1813  xfd->prev.depth = 1.0f;
1814  xfd->prev.is_depth_valid = false;
1815  xfd->prev.is_normal_valid = false;
1816  xfd->is_translate = false;
1817 
1819 
1820  {
1821  struct XFormAxisItem *object_data = NULL;
1822  BLI_array_declare(object_data);
1823 
1824  struct XFormAxisItem *item = BLI_array_append_ret(object_data);
1825  item->ob = xfd->vc.obact;
1826 
1827  CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1828  if ((ob != xfd->vc.obact) && object_is_target_compat(ob)) {
1829  item = BLI_array_append_ret(object_data);
1830  item->ob = ob;
1831  }
1832  }
1833  CTX_DATA_END;
1834 
1835  xfd->object_data = object_data;
1836  xfd->object_data_len = BLI_array_len(object_data);
1837 
1838  if (xfd->object_data_len != BLI_array_len(object_data)) {
1839  xfd->object_data = MEM_reallocN(xfd->object_data,
1840  xfd->object_data_len * sizeof(*xfd->object_data));
1841  }
1842  }
1843 
1844  {
1845  struct XFormAxisItem *item = xfd->object_data;
1846  for (int i = 0; i < xfd->object_data_len; i++, item++) {
1847  item->obtfm = BKE_object_tfm_backup(item->ob);
1848  BKE_object_rot_to_mat3(item->ob, item->rot_mat, true);
1849 
1850  /* Detect negative scale matrix. */
1851  float full_mat3[3][3];
1852  BKE_object_to_mat3(item->ob, full_mat3);
1853  item->is_z_flip = dot_v3v3(item->rot_mat[2], full_mat3[2]) < 0.0f;
1854  }
1855  }
1856 
1858 
1859  return OPERATOR_RUNNING_MODAL;
1860 }
1861 
1863 {
1864  struct XFormAxisData *xfd = op->customdata;
1865  ARegion *region = xfd->vc.region;
1866 
1868 
1869  const bool is_translate = (event->ctrl != 0);
1870  const bool is_translate_init = is_translate && (xfd->is_translate != is_translate);
1871 
1872  if (event->type == MOUSEMOVE || is_translate_init) {
1873  const ViewDepths *depths = xfd->vc.rv3d->depths;
1874  if (depths && ((uint)event->mval[0] < depths->w) && ((uint)event->mval[1] < depths->h)) {
1875  float depth_fl = 1.0f;
1876  ED_view3d_depth_read_cached(depths, event->mval, 0, &depth_fl);
1877  float location_world[3];
1878  if (depth_fl == 1.0f) {
1879  if (xfd->prev.is_depth_valid) {
1880  depth_fl = xfd->prev.depth;
1881  }
1882  }
1883 
1884 #ifdef USE_FAKE_DEPTH_INIT
1885  /* First time only. */
1886  if (depth_fl == 1.0f) {
1887  if (xfd->prev.is_depth_valid == false) {
1889  if (xfd->prev.is_depth_valid) {
1890  depth_fl = xfd->prev.depth;
1891  }
1892  }
1893  }
1894 #endif
1895 
1896  double depth = (double)depth_fl;
1897  if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
1898  xfd->prev.depth = depth_fl;
1899  xfd->prev.is_depth_valid = true;
1900  if (ED_view3d_depth_unproject(region, event->mval, depth, location_world)) {
1901  if (is_translate) {
1902 
1903  float normal[3];
1904  bool normal_found = false;
1905  if (ED_view3d_depth_read_cached_normal(&xfd->vc, event->mval, normal)) {
1906  normal_found = true;
1907 
1908  /* cheap attempt to smooth normals out a bit! */
1909  const int ofs = 2;
1910  for (int x = -ofs; x <= ofs; x += ofs / 2) {
1911  for (int y = -ofs; y <= ofs; y += ofs / 2) {
1912  if (x != 0 && y != 0) {
1913  const int mval_ofs[2] = {event->mval[0] + x, event->mval[1] + y};
1914  float n[3];
1915  if (ED_view3d_depth_read_cached_normal(&xfd->vc, mval_ofs, n)) {
1916  add_v3_v3(normal, n);
1917  }
1918  }
1919  }
1920  }
1922  }
1923  else if (xfd->prev.is_normal_valid) {
1924  copy_v3_v3(normal, xfd->prev.normal);
1925  normal_found = true;
1926  }
1927 
1928  {
1929 #ifdef USE_RELATIVE_ROTATION
1930  if (is_translate_init && xfd->object_data_len > 1) {
1931  float xform_rot_offset_inv_first[3][3];
1932  struct XFormAxisItem *item = xfd->object_data;
1933  for (int i = 0; i < xfd->object_data_len; i++, item++) {
1934  copy_m3_m4(item->xform_rot_offset, item->ob->obmat);
1936 
1937  if (i == 0) {
1938  invert_m3_m3(xform_rot_offset_inv_first, xfd->object_data[0].xform_rot_offset);
1939  }
1940  else {
1942  item->xform_rot_offset,
1943  xform_rot_offset_inv_first);
1944  }
1945  }
1946  }
1947 
1948 #endif
1949 
1950  struct XFormAxisItem *item = xfd->object_data;
1951  for (int i = 0; i < xfd->object_data_len; i++, item++) {
1952  if (is_translate_init) {
1953  float ob_axis[3];
1954  item->xform_dist = len_v3v3(item->ob->obmat[3], location_world);
1955  normalize_v3_v3(ob_axis, item->ob->obmat[2]);
1956  /* Scale to avoid adding distance when moving between surfaces. */
1957  if (normal_found) {
1958  float scale = fabsf(dot_v3v3(ob_axis, normal));
1959  item->xform_dist *= scale;
1960  }
1961  }
1962 
1963  float target_normal[3];
1964 
1965  if (normal_found) {
1966  copy_v3_v3(target_normal, normal);
1967  }
1968  else {
1969  normalize_v3_v3(target_normal, item->ob->obmat[2]);
1970  }
1971 
1972 #ifdef USE_RELATIVE_ROTATION
1973  if (normal_found) {
1974  if (i != 0) {
1975  mul_m3_v3(item->xform_rot_offset, target_normal);
1976  }
1977  }
1978 #endif
1979  {
1980  float loc[3];
1981 
1982  copy_v3_v3(loc, location_world);
1983  madd_v3_v3fl(loc, target_normal, item->xform_dist);
1984  object_apply_location(item->ob, loc);
1985  /* so orient behaves as expected */
1986  copy_v3_v3(item->ob->obmat[3], loc);
1987  }
1988 
1990  item->ob, item->rot_mat, item->rot_mat[2], location_world, item->is_z_flip);
1991 
1994  }
1995  if (normal_found) {
1996  copy_v3_v3(xfd->prev.normal, normal);
1997  xfd->prev.is_normal_valid = true;
1998  }
1999  }
2000  }
2001  else {
2002  struct XFormAxisItem *item = xfd->object_data;
2003  for (int i = 0; i < xfd->object_data_len; i++, item++) {
2004  if (object_orient_to_location(item->ob,
2005  item->rot_mat,
2006  item->rot_mat[2],
2007  location_world,
2008  item->is_z_flip)) {
2011  }
2012  }
2013  xfd->prev.is_normal_valid = false;
2014  }
2015  }
2016  }
2017  }
2018  xfd->is_translate = is_translate;
2019 
2021  }
2022 
2023  bool is_finished = false;
2024 
2025  if (ISMOUSE(xfd->init_event)) {
2026  if ((event->type == xfd->init_event) && (event->val == KM_RELEASE)) {
2027  is_finished = true;
2028  }
2029  }
2030  else {
2031  if (ELEM(event->type, LEFTMOUSE, EVT_RETKEY, EVT_PADENTER)) {
2032  is_finished = true;
2033  }
2034  }
2035 
2036  if (is_finished) {
2038  return OPERATOR_FINISHED;
2039  }
2040  if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
2042  return OPERATOR_CANCELLED;
2043  }
2044 
2045  return OPERATOR_RUNNING_MODAL;
2046 }
2047 
2049 {
2050  /* identifiers */
2051  ot->name = "Interactive Light Track to Cursor";
2052  ot->description = "Interactively point cameras and lights to a location (Ctrl translates)";
2053  ot->idname = "OBJECT_OT_transform_axis_target";
2054 
2055  /* api callbacks */
2060 
2061  /* flags */
2063 }
2064 
2065 #undef USE_RELATIVE_ROTATION
2066 
typedef float(TangentPoint)[2]
void BKE_armature_transform(struct bArmature *arm, const float mat[4][4], const bool do_props)
Definition: armature.c:567
void BKE_pose_where_is(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
Definition: armature.c:2739
void BKE_armature_copy_bone_transforms(struct bArmature *armature_dst, const struct bArmature *armature_src)
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
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:252
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 Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1401
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
#define CTX_DATA_END
Definition: BKE_context.h:260
bool BKE_curve_center_median(struct Curve *cu, float cent[3])
Definition: curve.c:5224
void BKE_curve_transform_ex(struct Curve *cu, const float mat[4][4], const bool do_keys, const bool do_props, const float unit_scale)
Definition: curve.c:5273
bool BKE_curve_center_bounds(struct Curve *cu, float cent[3])
Definition: curve.c:5261
void BKE_curve_translate(struct Curve *cu, const float offset[3], const bool do_keys)
Definition: curve.c:5344
void BKE_gpencil_layer_transform_matrix_get(const struct Depsgraph *depsgraph, struct Object *obact, struct bGPDlayer *gpl, float diff_mat[4][4])
void BKE_gpencil_centroid_3d(struct bGPdata *gpd, float r_centroid[3])
Definition: gpencil_geom.c:130
void BKE_gpencil_stroke_geometry_update(struct bGPdata *gpd, struct bGPDstroke *gps)
void BKE_gpencil_transform(struct bGPdata *gpd, const float mat[4][4])
const char * BKE_idtype_idcode_to_name(const short idcode)
Definition: idtype.c:168
void BKE_lattice_translate(struct Lattice *lt, const float offset[3], bool do_keys)
Definition: lattice.c:737
void BKE_lattice_center_bounds(struct Lattice *lt, float cent[3])
Definition: lattice.c:705
void BKE_lattice_center_median(struct Lattice *lt, float cent[3])
Definition: lattice.c:623
void BKE_lattice_transform(struct Lattice *lt, const float mat[4][4], bool do_keys)
Definition: lattice.c:715
#define FOREACH_SELECTED_EDITABLE_OBJECT_END
Definition: BKE_layer.h:231
#define FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN(_view_layer, _v3d, _instance)
Definition: BKE_layer.h:218
void BKE_main_id_tag_all(struct Main *mainvar, const int tag, const bool value)
Definition: lib_id.c:923
bool BKE_mball_center_median(const struct MetaBall *mb, float r_cent[3])
void BKE_mball_translate(struct MetaBall *mb, const float offset[3])
Definition: mball.c:643
bool BKE_mball_center_bounds(const struct MetaBall *mb, float r_cent[3])
void BKE_mball_transform(struct MetaBall *mb, const float mat[4][4], const bool do_props)
Definition: mball.c:617
bool BKE_mesh_center_of_volume(const struct Mesh *me, float r_cent[3])
bool BKE_mesh_center_median(const struct Mesh *me, float r_cent[3])
void BKE_mesh_calc_normals(struct Mesh *me)
bool BKE_mesh_center_of_surface(const struct Mesh *me, float r_cent[3])
bool BKE_mesh_center_bounds(const struct Mesh *me, float r_cent[3])
void BKE_mesh_transform(struct Mesh *me, const float mat[4][4], bool do_keys)
Definition: mesh.c:1485
void BKE_mesh_translate(struct Mesh *me, const float offset[3], const bool do_keys)
Definition: mesh.c:1522
void multiresModifier_scale_disp(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
Definition: multires.c:1451
General operations, lookup, etc. for blender objects.
void BKE_object_batch_cache_dirty_tag(struct Object *ob)
struct MovieClip * BKE_object_movieclip_get(struct Scene *scene, struct Object *ob, bool use_default)
Definition: object.c:5079
void BKE_object_tfm_restore(struct Object *ob, void *obtfm_pt)
Definition: object.c:4273
bool BKE_object_minmax_dupli(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden)
Definition: object.c:4138
void * BKE_object_tfm_backup(struct Object *ob)
Definition: object.c:4250
void BKE_object_where_is_calc(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
Definition: object.c:3653
void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src)
void BKE_object_rot_to_mat3(const struct Object *ob, float r_mat[3][3], bool use_drot)
void BKE_object_to_mat3(struct Object *ob, float r_mat[3][3])
Definition: object.c:3220
void BKE_object_to_mat4(struct Object *ob, float r_mat[4][4])
Definition: object.c:3234
void BKE_object_workob_calc_parent(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct Object *workob)
Definition: object.c:3667
void BKE_object_scale_to_mat3(struct Object *ob, float r_mat[3][3])
Definition: object.c:3038
void BKE_object_eval_transform_all(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *object)
void BKE_object_apply_mat4(struct Object *ob, const float mat[4][4], const bool use_compat, const bool use_parent)
Definition: object.c:3754
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
void BKE_reportf(ReportList *reports, ReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_scene_graph_evaluated_ensure(struct Depsgraph *depsgraph, struct Main *bmain)
Definition: scene.c:2718
void BKE_tracking_reconstruction_scale(struct MovieTracking *tracking, float scale[3])
A (mainly) macro array library.
#define BLI_array_append(arr, item)
Definition: BLI_array.h:104
#define BLI_array_append_ret(arr)
Definition: BLI_array.h:114
#define BLI_array_declare(arr)
Definition: BLI_array.h:62
#define BLI_array_len(arr)
Definition: BLI_array.h:74
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
MINLINE float max_fff(float a, float b, float c)
MINLINE int compare_ff_relative(float a, float b, const float max_diff, const int max_ulps)
int isect_line_line_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float r_i1[3], float r_i2[3])
Definition: math_geom.c:3103
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:930
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
void copy_m4_m3(float m1[4][4], const float m2[3][3])
Definition: math_matrix.c:120
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
void normalize_m3(float R[3][3]) ATTR_NONNULL()
Definition: math_matrix.c:1919
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
float mat3_to_scale(const float M[3][3])
Definition: math_matrix.c:2187
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_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:391
void mul_v3_mat3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:804
void eulO_to_axis_angle(float axis[3], float *angle, const float eul[3], const short order)
void mul_qt_fl(float q[4], const float f)
@ EULER_ORDER_DEFAULT
void unit_qt(float q[4])
Definition: math_rotation.c:46
void eul_to_quat(float quat[4], const float eul[3])
void quat_to_eul(float eul[3], const float quat[4])
void axis_angle_to_eulO(float eul[3], const short order, const float axis[3], const float angle)
void rotation_between_vecs_to_mat3(float m[3][3], const float v1[3], const float v2[3])
void unit_axis_angle(float axis[3], float *angle)
Definition: math_rotation.c:38
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:52
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
Definition: math_vector.c:1020
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:270
MINLINE void copy_v3_fl(float r[3], float f)
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 UNPACK2(a)
#define INIT_MINMAX(min, max)
#define UNUSED(x)
#define ELEM(...)
#define IS_EQF(a, b)
typedef double(DMatrix)[4][4]
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
void DEG_id_tag_update(struct ID *id, int flag)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
@ 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
@ LIB_TAG_DOIT
Definition: DNA_ID.h:554
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:426
#define ID_REAL_USERS(id)
Definition: DNA_ID.h:413
@ ID_GD
Definition: DNA_ID_enums.h:83
@ ROT_MODE_QUAT
@ ROT_MODE_AXISANGLE
Object groups, one object can be in many groups at once.
@ CU_3D
#define LA_AREA
#define LA_SPOT
#define LA_AREA_SQUARE
#define LA_AREA_ELLIPSE
#define LA_SUN
#define LA_AREA_DISK
#define LA_AREA_RECT
Object is a sort of wrapper for general info.
#define OB_DONE
@ OB_LOCK_ROTZ
@ OB_LOCK_ROT4D
@ OB_LOCK_SCALEZ
@ OB_LOCK_ROTX
@ OB_LOCK_SCALEX
@ OB_LOCK_ROTW
@ OB_LOCK_LOCY
@ OB_LOCK_LOCZ
@ OB_LOCK_ROTY
@ OB_LOCK_SCALEY
@ OB_LOCK_LOCX
@ OB_DUPLICOLLECTION
@ OB_LATTICE
@ OB_MBALL
@ OB_EMPTY
@ OB_SURF
@ OB_CAMERA
@ OB_FONT
@ OB_ARMATURE
@ OB_LAMP
@ OB_MESH
@ OB_CURVE
@ OB_GPENCIL
@ SCE_XFORM_SKIP_CHILDREN
@ SCE_XFORM_DATA_ORIGIN
@ V3D_AROUND_CENTER_BOUNDS
@ V3D_AROUND_CENTER_MEDIAN
#define V3D_HIDE_OVERLAYS
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
#define ANIM_KS_LOCATION_ID
#define ANIM_KS_SCALING_ID
#define ANIM_KS_ROTATION_ID
void EDBM_mesh_normals_update(struct BMEditMesh *em)
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
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
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:667
bool ED_operator_objectmode(struct bContext *C)
Definition: screen_ops.c:201
bool ED_operator_scene_editable(struct bContext *C)
Definition: screen_ops.c:192
bool ED_operator_region_view3d_active(struct bContext *C)
Definition: screen_ops.c:235
bool ED_view3d_depth_read_cached(const ViewDepths *vd, const int mval[2], int margin, float *r_depth)
void ED_view3d_viewcontext_init(struct bContext *C, struct ViewContext *vc, struct Depsgraph *depsgraph)
void ED_view3d_win_to_ray(const struct ARegion *region, const float mval[2], float r_ray_start[3], float r_ray_normal[3])
bool ED_view3d_depth_read_cached_normal(const ViewContext *vc, const int mval[2], float r_normal[3])
bool ED_view3d_depth_unproject(const struct ARegion *region, const int mval[2], const double depth, float r_location_world[3])
void ED_view3d_project(const struct ARegion *region, const float world[3], float r_region_co[3])
@ V3D_DEPTH_NO_GPENCIL
Definition: ED_view3d.h:148
void ED_view3d_depth_override(struct Depsgraph *depsgraph, struct ARegion *region, struct View3D *v3d, struct Object *obact, eV3DDepthOverrideMode mode, bool update_cache)
Definition: view3d_draw.c:2331
void view3d_operator_needs_opengl(const struct bContext *C)
NSNotificationCenter * center
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
#define C
Definition: RandGen.cpp:39
@ OPTYPE_BLOCKING
Definition: WM_types.h:157
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_TRANSFORM
Definition: WM_types.h:357
#define NC_OBJECT
Definition: WM_types.h:280
#define KM_RELEASE
Definition: WM_types.h:243
void ED_armature_origin_set(Main *bmain, Object *ob, const float cursor[3], int centermode, int around)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_VERTS_OF_MESH
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
Scene scene
const Depsgraph * depsgraph
#define rot(x, k)
IconTextureDrawCall normal
#define GS(x)
Definition: iris.c:241
#define fabsf(x)
bool ED_autokeyframe_object(bContext *C, Scene *scene, Object *ob, KeyingSet *ks)
Definition: keyframing.c:3003
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
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
static void object_apply_rotation(Object *ob, const float rmat[3][3])
void OBJECT_OT_location_clear(wmOperatorType *ot)
static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op))
static bool object_is_target_compat(const Object *ob)
static int visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
void OBJECT_OT_transform_axis_target(wmOperatorType *ot)
void OBJECT_OT_rotation_clear(wmOperatorType *ot)
static bool object_orient_to_location(Object *ob, const float rot_orig[3][3], const float axis[3], const float location[3], const bool z_flip)
static Object ** sorted_selected_editable_objects(bContext *C, int *r_num_objects)
static void object_clear_scale(Object *ob, const bool clear_delta)
static void ignore_parent_tx(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
static void object_transform_axis_target_free_data(wmOperator *op)
static void object_apply_location(Object *ob, const float loc[3])
static void append_sorted_object_parent_hierarchy(Object *root_object, Object *object, Object **sorted_objects, int *object_index)
static int object_scale_clear_exec(bContext *C, wmOperator *op)
static int object_rotation_clear_exec(bContext *C, wmOperator *op)
@ ORIGIN_TO_GEOMETRY
@ GEOMETRY_TO_ORIGIN
@ ORIGIN_TO_CURSOR
@ ORIGIN_TO_CENTER_OF_MASS_VOLUME
@ ORIGIN_TO_CENTER_OF_MASS_SURFACE
static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int object_origin_set_exec(bContext *C, wmOperator *op)
static void object_clear_loc(Object *ob, const bool clear_delta)
static int object_location_clear_exec(bContext *C, wmOperator *op)
void OBJECT_OT_visual_transform_apply(wmOperatorType *ot)
static void object_transform_axis_target_calc_depth_init(struct XFormAxisData *xfd, const int mval[2])
static void object_clear_rot(Object *ob, const bool clear_delta)
void OBJECT_OT_origin_clear(wmOperatorType *ot)
void OBJECT_OT_origin_set(wmOperatorType *ot)
static int object_clear_transform_generic_exec(bContext *C, wmOperator *op, void(*clear_func)(Object *, const bool), const char default_ksName[])
void OBJECT_OT_transform_apply(wmOperatorType *ot)
static int object_transform_apply_exec(bContext *C, wmOperator *op)
static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_loc, bool apply_rot, bool apply_scale, bool do_props)
void OBJECT_OT_scale_clear(wmOperatorType *ot)
static void object_transform_axis_target_cancel(bContext *C, wmOperator *op)
static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, const wmEvent *event)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:6655
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
Definition: rna_access.c:3562
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:866
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3543
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
#define min(a, b)
Definition: sort.c:51
struct BMesh * bm
Definition: BKE_editmesh.h:52
float co[3]
Definition: bmesh_class.h:99
int totvert
Definition: bmesh_class.h:297
float vec[8][3]
float instance_offset[3]
float xof
struct TextBox * tb
struct Key * key
float fsize
float yof
Definition: DNA_ID.h:273
int tag
Definition: DNA_ID.h:292
void * next
Definition: DNA_ID.h:274
char name[66]
Definition: DNA_ID.h:283
float area_sizez
float area_sizey
short area_shape
float area_size
short type
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
ListBase objects
Definition: BKE_main.h:148
struct BMEditMesh * edit_mesh
struct MovieTracking tracking
struct BoundBox * bb
short transflag
struct Collection * instance_collection
float drot[3]
float dquat[4]
float loc[3]
float dloc[3]
float scale[3]
float imat[4][4]
float rot[3]
float parentinv[4][4]
Object_Runtime runtime
float drotAxis[3]
float empty_drawsize
float obmat[4][4]
float quat[4]
short rotmode
float rotAngle
float rotAxis[3]
float drotAngle
float dscale[3]
short protectflag
struct Object * parent
void * data
struct ViewDepths * depths
struct ToolSettings * toolsettings
View3DCursor cursor
char transform_pivot_point
struct Depsgraph * depsgraph
Definition: ED_view3d.h:75
int mval[2]
Definition: ED_view3d.h:85
struct ARegion * region
Definition: ED_view3d.h:80
struct Object * obact
Definition: ED_view3d.h:78
struct View3D * v3d
Definition: ED_view3d.h:81
struct RegionView3D * rv3d
Definition: ED_view3d.h:83
bool damaged
Definition: ED_view3d.h:94
unsigned short w
Definition: ED_view3d.h:89
double depth_range[2]
Definition: ED_view3d.h:92
unsigned short h
Definition: ED_view3d.h:89
struct XFormAxisItem * object_data
struct XFormAxisData::@474 prev
float xform_rot_offset[3][3]
float rot_mat[3][3]
ListBase layers
short val
Definition: WM_types.h:579
int mval[2]
Definition: WM_types.h:583
short type
Definition: WM_types.h:577
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
struct ReportList * reports
struct PointerRNA * ptr
float max
int WM_userdef_event_type_from_keymap_type(int kmitype)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ RIGHTMOUSE
@ EVT_PADENTER
@ MOUSEMOVE
@ LEFTMOUSE
@ EVT_ESCKEY
@ EVT_RETKEY
#define ISMOUSE(event_type)
wmOperatorType * ot
Definition: wm_files.c:3156
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: wm_operators.c:982