Blender  V3.3
object_transform.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include <cstdlib>
9 #include <cstring>
10 #include <numeric>
11 
12 #include "DNA_anim_types.h"
13 #include "DNA_armature_types.h"
14 #include "DNA_collection_types.h"
15 #include "DNA_gpencil_types.h"
16 #include "DNA_lattice_types.h"
17 #include "DNA_light_types.h"
18 #include "DNA_mesh_types.h"
19 #include "DNA_meta_types.h"
20 #include "DNA_object_types.h"
21 #include "DNA_scene_types.h"
22 
23 #include "BLI_array.hh"
24 #include "BLI_listbase.h"
25 #include "BLI_math.h"
26 #include "BLI_math_vector.hh"
27 #include "BLI_utildefines.h"
28 #include "BLI_vector.hh"
29 
30 #include "BKE_armature.h"
31 #include "BKE_context.h"
32 #include "BKE_curve.h"
33 #include "BKE_curves.hh"
34 #include "BKE_editmesh.h"
35 #include "BKE_gpencil.h"
36 #include "BKE_gpencil_geom.h"
37 #include "BKE_idtype.h"
38 #include "BKE_lattice.h"
39 #include "BKE_layer.h"
40 #include "BKE_lib_id.h"
41 #include "BKE_main.h"
42 #include "BKE_mball.h"
43 #include "BKE_mesh.h"
44 #include "BKE_multires.h"
45 #include "BKE_object.h"
46 #include "BKE_report.h"
47 #include "BKE_scene.h"
48 #include "BKE_tracking.h"
49 
50 #include "DEG_depsgraph.h"
51 #include "DEG_depsgraph_query.h"
52 
53 #include "RNA_access.h"
54 #include "RNA_define.h"
55 
56 #include "WM_api.h"
57 #include "WM_types.h"
58 
59 #include "ED_armature.h"
60 #include "ED_gpencil.h"
61 #include "ED_keyframing.h"
62 #include "ED_mesh.h"
63 #include "ED_object.h"
64 #include "ED_screen.h"
65 #include "ED_view3d.h"
66 
67 #include "MEM_guardedalloc.h"
68 
69 #include "object_intern.h"
70 
71 using blender::Array;
72 using blender::float2;
73 using blender::float3;
74 using blender::Vector;
75 
76 /* -------------------------------------------------------------------- */
80 /* clear location of object */
81 static void object_clear_loc(Object *ob, const bool clear_delta)
82 {
83  /* clear location if not locked */
84  if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
85  ob->loc[0] = 0.0f;
86  if (clear_delta) {
87  ob->dloc[0] = 0.0f;
88  }
89  }
90  if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
91  ob->loc[1] = 0.0f;
92  if (clear_delta) {
93  ob->dloc[1] = 0.0f;
94  }
95  }
96  if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
97  ob->loc[2] = 0.0f;
98  if (clear_delta) {
99  ob->dloc[2] = 0.0f;
100  }
101  }
102 }
103 
104 /* clear rotation of object */
105 static void object_clear_rot(Object *ob, const bool clear_delta)
106 {
107  /* clear rotations that aren't locked */
109  if (ob->protectflag & OB_LOCK_ROT4D) {
110  /* perform clamping on a component by component basis */
111  if (ob->rotmode == ROT_MODE_AXISANGLE) {
112  if ((ob->protectflag & OB_LOCK_ROTW) == 0) {
113  ob->rotAngle = 0.0f;
114  if (clear_delta) {
115  ob->drotAngle = 0.0f;
116  }
117  }
118  if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
119  ob->rotAxis[0] = 0.0f;
120  if (clear_delta) {
121  ob->drotAxis[0] = 0.0f;
122  }
123  }
124  if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
125  ob->rotAxis[1] = 0.0f;
126  if (clear_delta) {
127  ob->drotAxis[1] = 0.0f;
128  }
129  }
130  if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
131  ob->rotAxis[2] = 0.0f;
132  if (clear_delta) {
133  ob->drotAxis[2] = 0.0f;
134  }
135  }
136 
137  /* Check validity of axis - axis should never be 0,0,0
138  * (if so, then we make it rotate about y). */
139  if (IS_EQF(ob->rotAxis[0], ob->rotAxis[1]) && IS_EQF(ob->rotAxis[1], ob->rotAxis[2])) {
140  ob->rotAxis[1] = 1.0f;
141  }
142  if (IS_EQF(ob->drotAxis[0], ob->drotAxis[1]) && IS_EQF(ob->drotAxis[1], ob->drotAxis[2]) &&
143  clear_delta) {
144  ob->drotAxis[1] = 1.0f;
145  }
146  }
147  else if (ob->rotmode == ROT_MODE_QUAT) {
148  if ((ob->protectflag & OB_LOCK_ROTW) == 0) {
149  ob->quat[0] = 1.0f;
150  if (clear_delta) {
151  ob->dquat[0] = 1.0f;
152  }
153  }
154  if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
155  ob->quat[1] = 0.0f;
156  if (clear_delta) {
157  ob->dquat[1] = 0.0f;
158  }
159  }
160  if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
161  ob->quat[2] = 0.0f;
162  if (clear_delta) {
163  ob->dquat[2] = 0.0f;
164  }
165  }
166  if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
167  ob->quat[3] = 0.0f;
168  if (clear_delta) {
169  ob->dquat[3] = 0.0f;
170  }
171  }
172  /* TODO: does this quat need normalizing now? */
173  }
174  else {
175  /* the flag may have been set for the other modes, so just ignore the extra flag... */
176  if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
177  ob->rot[0] = 0.0f;
178  if (clear_delta) {
179  ob->drot[0] = 0.0f;
180  }
181  }
182  if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
183  ob->rot[1] = 0.0f;
184  if (clear_delta) {
185  ob->drot[1] = 0.0f;
186  }
187  }
188  if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
189  ob->rot[2] = 0.0f;
190  if (clear_delta) {
191  ob->drot[2] = 0.0f;
192  }
193  }
194  }
195  }
196  else {
197  /* perform clamping using euler form (3-components) */
198  /* FIXME: deltas are not handled for these cases yet... */
199  float eul[3], oldeul[3], quat1[4] = {0};
200 
201  if (ob->rotmode == ROT_MODE_QUAT) {
202  copy_qt_qt(quat1, ob->quat);
203  quat_to_eul(oldeul, ob->quat);
204  }
205  else if (ob->rotmode == ROT_MODE_AXISANGLE) {
207  }
208  else {
209  copy_v3_v3(oldeul, ob->rot);
210  }
211 
212  eul[0] = eul[1] = eul[2] = 0.0f;
213 
214  if (ob->protectflag & OB_LOCK_ROTX) {
215  eul[0] = oldeul[0];
216  }
217  if (ob->protectflag & OB_LOCK_ROTY) {
218  eul[1] = oldeul[1];
219  }
220  if (ob->protectflag & OB_LOCK_ROTZ) {
221  eul[2] = oldeul[2];
222  }
223 
224  if (ob->rotmode == ROT_MODE_QUAT) {
225  eul_to_quat(ob->quat, eul);
226  /* quaternions flip w sign to accumulate rotations correctly */
227  if ((quat1[0] < 0.0f && ob->quat[0] > 0.0f) || (quat1[0] > 0.0f && ob->quat[0] < 0.0f)) {
228  mul_qt_fl(ob->quat, -1.0f);
229  }
230  }
231  else if (ob->rotmode == ROT_MODE_AXISANGLE) {
233  }
234  else {
235  copy_v3_v3(ob->rot, eul);
236  }
237  }
238  } /* Duplicated in source/blender/editors/armature/editarmature.c */
239  else {
240  if (ob->rotmode == ROT_MODE_QUAT) {
241  unit_qt(ob->quat);
242  if (clear_delta) {
243  unit_qt(ob->dquat);
244  }
245  }
246  else if (ob->rotmode == ROT_MODE_AXISANGLE) {
247  unit_axis_angle(ob->rotAxis, &ob->rotAngle);
248  if (clear_delta) {
250  }
251  }
252  else {
253  zero_v3(ob->rot);
254  if (clear_delta) {
255  zero_v3(ob->drot);
256  }
257  }
258  }
259 }
260 
261 /* clear scale of object */
262 static void object_clear_scale(Object *ob, const bool clear_delta)
263 {
264  /* clear scale factors which are not locked */
265  if ((ob->protectflag & OB_LOCK_SCALEX) == 0) {
266  ob->scale[0] = 1.0f;
267  if (clear_delta) {
268  ob->dscale[0] = 1.0f;
269  }
270  }
271  if ((ob->protectflag & OB_LOCK_SCALEY) == 0) {
272  ob->scale[1] = 1.0f;
273  if (clear_delta) {
274  ob->dscale[1] = 1.0f;
275  }
276  }
277  if ((ob->protectflag & OB_LOCK_SCALEZ) == 0) {
278  ob->scale[2] = 1.0f;
279  if (clear_delta) {
280  ob->dscale[2] = 1.0f;
281  }
282  }
283 }
284 
285 /* generic exec for clear-transform operators */
287  wmOperator *op,
288  void (*clear_func)(Object *, const bool),
289  const char default_ksName[])
290 {
292  Main *bmain = CTX_data_main(C);
294  ViewLayer *view_layer = CTX_data_view_layer(C);
295  /* May be null. */
296  View3D *v3d = CTX_wm_view3d(C);
297  KeyingSet *ks;
298  const bool clear_delta = RNA_boolean_get(op->ptr, "clear_delta");
299 
300  BLI_assert(!ELEM(nullptr, clear_func, default_ksName));
301 
302  Vector<Object *> objects;
303  FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN (view_layer, v3d, ob) {
304  objects.append(ob);
305  }
307 
308  if (objects.is_empty()) {
309  return OPERATOR_CANCELLED;
310  }
311 
312  /* Support transforming the object data. */
313  const bool use_transform_skip_children = (scene->toolsettings->transform_flag &
315  const bool use_transform_data_origin = (scene->toolsettings->transform_flag &
317  struct XFormObjectSkipChild_Container *xcs = nullptr;
318  struct XFormObjectData_Container *xds = nullptr;
319 
320  if (use_transform_skip_children) {
324  xcs, view_layer, objects.data(), objects.size());
325  }
326  if (use_transform_data_origin) {
329  }
330 
331  /* get KeyingSet to use */
332  ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
333 
334  for (Object *ob : objects) {
335  if (use_transform_data_origin) {
337  }
338 
339  /* run provided clearing function */
340  clear_func(ob, clear_delta);
341 
342  ED_autokeyframe_object(C, scene, ob, ks);
343 
344  /* tag for updates */
346  }
347 
348  if (use_transform_skip_children) {
351  }
352 
353  if (use_transform_data_origin) {
356  }
357 
358  /* this is needed so children are also updated */
360 
361  return OPERATOR_FINISHED;
362 }
363 
366 /* -------------------------------------------------------------------- */
371 {
373 }
374 
376 {
377  /* identifiers */
378  ot->name = "Clear Location";
379  ot->description = "Clear the object's location";
380  ot->idname = "OBJECT_OT_location_clear";
381 
382  /* api callbacks */
385 
386  /* flags */
388 
389  /* properties */
391  ot->srna,
392  "clear_delta",
393  false,
394  "Clear Delta",
395  "Clear delta location in addition to clearing the normal location transform");
396 }
397 
400 /* -------------------------------------------------------------------- */
405 {
407 }
408 
410 {
411  /* identifiers */
412  ot->name = "Clear Rotation";
413  ot->description = "Clear the object's rotation";
414  ot->idname = "OBJECT_OT_rotation_clear";
415 
416  /* api callbacks */
419 
420  /* flags */
422 
423  /* properties */
425  ot->srna,
426  "clear_delta",
427  false,
428  "Clear Delta",
429  "Clear delta rotation in addition to clearing the normal rotation transform");
430 }
431 
434 /* -------------------------------------------------------------------- */
439 {
441 }
442 
444 {
445  /* identifiers */
446  ot->name = "Clear Scale";
447  ot->description = "Clear the object's scale";
448  ot->idname = "OBJECT_OT_scale_clear";
449 
450  /* api callbacks */
453 
454  /* flags */
456 
457  /* properties */
459  ot->srna,
460  "clear_delta",
461  false,
462  "Clear Delta",
463  "Clear delta scale in addition to clearing the normal scale transform");
464 }
465 
468 /* -------------------------------------------------------------------- */
473 {
474  float *v1, *v3;
475  float mat[3][3];
476 
477  CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
478  if (ob->parent) {
479  /* vectors pointed to by v1 and v3 will get modified */
480  v1 = ob->loc;
481  v3 = ob->parentinv[3];
482 
483  copy_m3_m4(mat, ob->parentinv);
484  negate_v3_v3(v3, v1);
485  mul_m3_v3(mat, v3);
486  }
487 
489  }
490  CTX_DATA_END;
491 
493 
494  return OPERATOR_FINISHED;
495 }
496 
498 {
499  /* identifiers */
500  ot->name = "Clear Origin";
501  ot->description = "Clear the object's origin";
502  ot->idname = "OBJECT_OT_origin_clear";
503 
504  /* api callbacks */
507 
508  /* flags */
510 }
511 
514 /* -------------------------------------------------------------------- */
518 /* use this when the loc/size/rot of the parent has changed but the children
519  * should stay in the same place, e.g. for apply-size-rot or object center */
521 {
522  Object workob;
523 
524  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
525 
526  /* a change was made, adjust the children to compensate */
527  LISTBASE_FOREACH (Object *, ob_child, &bmain->objects) {
528  if (ob_child->parent == ob) {
529  Object *ob_child_eval = DEG_get_evaluated_object(depsgraph, ob_child);
530  BKE_object_apply_mat4(ob_child_eval, ob_child_eval->obmat, true, false);
531  BKE_object_workob_calc_parent(depsgraph, scene, ob_child_eval, &workob);
532  invert_m4_m4(ob_child->parentinv, workob.obmat);
533  /* Copy result of BKE_object_apply_mat4(). */
534  BKE_object_transform_copy(ob_child, ob_child_eval);
535  /* Make sure evaluated object is in a consistent state with the original one.
536  * It might be needed for applying transform on its children. */
537  copy_m4_m4(ob_child_eval->parentinv, ob_child->parentinv);
538  BKE_object_eval_transform_all(depsgraph, scene_eval, ob_child_eval);
539  /* Tag for update.
540  * This is because parent matrix did change, so in theory the child object might now be
541  * evaluated to a different location in another editing context. */
542  DEG_id_tag_update(&ob_child->id, ID_RECALC_TRANSFORM);
543  }
544  }
545 }
546 
548  Object *object,
549  Object **sorted_objects,
550  int *object_index)
551 {
552  if (!ELEM(object->parent, nullptr, root_object)) {
554  root_object, object->parent, sorted_objects, object_index);
555  }
556  if (object->id.tag & LIB_TAG_DOIT) {
557  sorted_objects[*object_index] = object;
558  (*object_index)++;
559  object->id.tag &= ~LIB_TAG_DOIT;
560  }
561 }
562 
564 {
565  Main *bmain = CTX_data_main(C);
566 
567  /* Count all objects, but also tag all the selected ones. */
568  BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
569  int num_objects = 0;
570  CTX_DATA_BEGIN (C, Object *, object, selected_editable_objects) {
571  object->id.tag |= LIB_TAG_DOIT;
572  num_objects++;
573  }
574  CTX_DATA_END;
575  if (num_objects == 0) {
576  return {};
577  }
578 
579  /* Append all the objects. */
580  Array<Object *> sorted_objects(num_objects);
581  int object_index = 0;
582  CTX_DATA_BEGIN (C, Object *, object, selected_editable_objects) {
583  if ((object->id.tag & LIB_TAG_DOIT) == 0) {
584  continue;
585  }
586  append_sorted_object_parent_hierarchy(object, object, sorted_objects.data(), &object_index);
587  }
588  CTX_DATA_END;
589 
590  return sorted_objects;
591 }
592 
597 {
598  Object *obact = CTX_data_active_object(C);
599 
600  if (ELEM(nullptr, obact, obact->data)) {
601  return false;
602  }
603 
604  if (ID_REAL_USERS(obact->data) == 1) {
605  return false;
606  }
607 
608  bool all_objects_same_data = true;
609  bool obact_selected = false;
610 
611  CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
612  if (ob->data != obact->data) {
613  all_objects_same_data = false;
614  break;
615  }
616 
617  if (ob == obact) {
618  obact_selected = true;
619  }
620  }
621  CTX_DATA_END;
622 
623  return all_objects_same_data && obact_selected;
624 }
625 
632 {
635 
636  /* Counting the number of objects is valid since it's known the
637  * selection is only made up of users of the active objects data. */
638  return (ID_REAL_USERS(ob->data) > CTX_DATA_COUNT(C, selected_editable_objects));
639 }
640 
642  ReportList *reports,
643  bool apply_loc,
644  bool apply_rot,
645  bool apply_scale,
646  bool do_props,
647  bool do_single_user)
648 {
649  Main *bmain = CTX_data_main(C);
652  float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
653  bool changed = true;
654  bool const do_multi_user = apply_objects_internal_can_multiuser(C);
655  float obact_invmat[4][4], obact_parent[4][4], obact_parentinv[4][4];
656 
657  /* Only used when do_multi_user is set. */
658  Object *obact = nullptr;
659  bool make_single_user = false;
660 
661  if (do_multi_user) {
662  obact = CTX_data_active_object(C);
663  invert_m4_m4(obact_invmat, obact->obmat);
664 
665  Object workob;
667  copy_m4_m4(obact_parent, workob.obmat);
668  copy_m4_m4(obact_parentinv, obact->parentinv);
669 
671  if (do_single_user) {
672  make_single_user = true;
673  }
674  else {
675  ID *obact_data = static_cast<ID *>(obact->data);
676  BKE_reportf(reports,
677  RPT_ERROR,
678  R"(Cannot apply to a multi user: Object "%s", %s "%s", aborting)",
679  obact->id.name + 2,
680  BKE_idtype_idcode_to_name(GS(obact_data->name)),
681  obact_data->name + 2);
682  return OPERATOR_CANCELLED;
683  }
684  }
685  }
686 
687  /* first check if we can execute */
688  CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
689  if (ELEM(ob->type,
690  OB_MESH,
691  OB_ARMATURE,
692  OB_LATTICE,
693  OB_MBALL,
695  OB_SURF,
696  OB_FONT,
697  OB_GPENCIL,
698  OB_CURVES)) {
699  ID *obdata = static_cast<ID *>(ob->data);
700  if (!do_multi_user && ID_REAL_USERS(obdata) > 1) {
701  BKE_reportf(reports,
702  RPT_ERROR,
703  R"(Cannot apply to a multi user: Object "%s", %s "%s", aborting)",
704  ob->id.name + 2,
706  obdata->name + 2);
707  changed = false;
708  }
709 
710  if (ID_IS_LINKED(obdata) || ID_IS_OVERRIDE_LIBRARY(obdata)) {
711  BKE_reportf(reports,
712  RPT_ERROR,
713  R"(Cannot apply to library or override data: Object "%s", %s "%s", aborting)",
714  ob->id.name + 2,
716  obdata->name + 2);
717  changed = false;
718  }
719  }
720 
721  if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
722  ID *obdata = static_cast<ID *>(ob->data);
723  Curve *cu = static_cast<Curve *>(ob->data);
724 
725  if (((ob->type == OB_CURVES_LEGACY) && !(cu->flag & CU_3D)) && (apply_rot || apply_loc)) {
726  BKE_reportf(
727  reports,
728  RPT_ERROR,
729  R"(Rotation/Location can't apply to a 2D curve: Object "%s", %s "%s", aborting)",
730  ob->id.name + 2,
732  obdata->name + 2);
733  changed = false;
734  }
735  if (cu->key) {
736  BKE_reportf(reports,
737  RPT_ERROR,
738  R"(Can't apply to a curve with shape-keys: Object "%s", %s "%s", aborting)",
739  ob->id.name + 2,
741  obdata->name + 2);
742  changed = false;
743  }
744  }
745 
746  if (ob->type == OB_FONT) {
747  if (apply_rot || apply_loc) {
748  BKE_reportf(
749  reports, RPT_ERROR, "Font's can only have scale applied: \"%s\"", ob->id.name + 2);
750  changed = false;
751  }
752  }
753 
754  if (ob->type == OB_GPENCIL) {
755  bGPdata *gpd = static_cast<bGPdata *>(ob->data);
756  if (gpd) {
757  if (gpd->layers.first) {
758  /* Unsupported configuration */
759  bool has_unparented_layers = false;
760 
761  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
762  /* Parented layers aren't supported as we can't easily re-evaluate
763  * the scene to sample parent movement */
764  if (gpl->parent == nullptr) {
765  has_unparented_layers = true;
766  break;
767  }
768  }
769 
770  if (has_unparented_layers == false) {
771  BKE_reportf(reports,
772  RPT_ERROR,
773  "Can't apply to a GP data-block where all layers are parented: Object "
774  "\"%s\", %s \"%s\", aborting",
775  ob->id.name + 2,
777  gpd->id.name + 2);
778  changed = false;
779  }
780  }
781  else {
782  /* No layers/data */
783  BKE_reportf(
784  reports,
785  RPT_ERROR,
786  R"(Can't apply to GP data-block with no layers: Object "%s", %s "%s", aborting)",
787  ob->id.name + 2,
789  gpd->id.name + 2);
790  }
791  }
792  }
793 
794  if (ob->type == OB_LAMP) {
795  Light *la = static_cast<Light *>(ob->data);
796  if (la->type == LA_AREA) {
797  if (apply_rot || apply_loc) {
798  BKE_reportf(reports,
799  RPT_ERROR,
800  "Area Lights can only have scale applied: \"%s\"",
801  ob->id.name + 2);
802  changed = false;
803  }
804  }
805  }
806  }
807  CTX_DATA_END;
808 
809  if (!changed) {
810  return OPERATOR_CANCELLED;
811  }
812 
813  changed = false;
814 
815  /* now execute */
816 
817  if (make_single_user) {
818  /* Make single user. */
819  ED_object_single_obdata_user(bmain, scene, obact);
821  WM_event_add_notifier(C, NC_WINDOW, nullptr);
823  }
824 
826  if (objects.is_empty()) {
827  return OPERATOR_CANCELLED;
828  }
829 
830  for (Object *ob : objects) {
831  /* calculate rotation/scale matrix */
832  if (apply_scale && apply_rot) {
833  BKE_object_to_mat3(ob, rsmat);
834  }
835  else if (apply_scale) {
836  BKE_object_scale_to_mat3(ob, rsmat);
837  }
838  else if (apply_rot) {
839  float tmat[3][3], timat[3][3];
840 
841  /* simple rotation matrix */
842  BKE_object_rot_to_mat3(ob, rsmat, true);
843 
844  /* correct for scale, note mul_m3_m3m3 has swapped args! */
845  BKE_object_scale_to_mat3(ob, tmat);
846  invert_m3_m3(timat, tmat);
847  mul_m3_m3m3(rsmat, timat, rsmat);
848  mul_m3_m3m3(rsmat, rsmat, tmat);
849  }
850  else {
851  unit_m3(rsmat);
852  }
853 
854  copy_m4_m3(mat, rsmat);
855 
856  /* calculate translation */
857  if (apply_loc) {
858  add_v3_v3v3(mat[3], ob->loc, ob->dloc);
859 
860  if (!(apply_scale && apply_rot)) {
861  float tmat[3][3];
862  /* correct for scale and rotation that is still applied */
863  BKE_object_to_mat3(ob, obmat);
864  invert_m3_m3(iobmat, obmat);
865  mul_m3_m3m3(tmat, rsmat, iobmat);
866  mul_m3_v3(tmat, mat[3]);
867  }
868  }
869 
870  /* apply to object data */
871  if (do_multi_user && ob != obact) {
872  /* Don't apply, just set the new object data, the correct
873  * transformations will happen later. */
874  id_us_min((ID *)ob->data);
875  ob->data = obact->data;
876  id_us_plus((ID *)ob->data);
877  }
878  else if (ob->type == OB_MESH) {
879  Mesh *me = static_cast<Mesh *>(ob->data);
880 
881  if (apply_scale) {
883  }
884 
885  /* adjust data */
886  BKE_mesh_transform(me, mat, true);
887  }
888  else if (ob->type == OB_ARMATURE) {
889  bArmature *arm = static_cast<bArmature *>(ob->data);
890  BKE_armature_transform(arm, mat, do_props);
891  }
892  else if (ob->type == OB_LATTICE) {
893  Lattice *lt = static_cast<Lattice *>(ob->data);
894 
895  BKE_lattice_transform(lt, mat, true);
896  }
897  else if (ob->type == OB_MBALL) {
898  MetaBall *mb = static_cast<MetaBall *>(ob->data);
899  BKE_mball_transform(mb, mat, do_props);
900  }
901  else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
902  Curve *cu = static_cast<Curve *>(ob->data);
903  scale = mat3_to_scale(rsmat);
904  BKE_curve_transform_ex(cu, mat, true, do_props, scale);
905  }
906  else if (ob->type == OB_FONT) {
907  Curve *cu = static_cast<Curve *>(ob->data);
908 
909  scale = mat3_to_scale(rsmat);
910 
911  for (int i = 0; i < cu->totbox; i++) {
912  TextBox *tb = &cu->tb[i];
913  tb->x *= scale;
914  tb->y *= scale;
915  tb->w *= scale;
916  tb->h *= scale;
917  }
918 
919  if (do_props) {
920  cu->fsize *= scale;
921  }
922  }
923  else if (ob->type == OB_GPENCIL) {
924  bGPdata *gpd = static_cast<bGPdata *>(ob->data);
925  BKE_gpencil_transform(gpd, mat);
926  }
927  else if (ob->type == OB_CURVES) {
928  Curves &curves = *static_cast<Curves *>(ob->data);
931  }
932  else if (ob->type == OB_CAMERA) {
933  MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
934 
935  /* applying scale on camera actually scales clip's reconstruction.
936  * of there's clip assigned to camera nothing to do actually.
937  */
938  if (!clip) {
939  continue;
940  }
941 
942  if (apply_scale) {
943  BKE_tracking_reconstruction_scale(&clip->tracking, ob->scale);
944  }
945  }
946  else if (ob->type == OB_EMPTY) {
947  /* It's possible for empties too, even though they don't
948  * really have obdata, since we can simply apply the maximum
949  * scaling to the empty's drawsize.
950  *
951  * Core Assumptions:
952  * 1) Most scaled empties have uniform scaling
953  * (i.e. for visibility reasons), AND/OR
954  * 2) Preserving non-uniform scaling is not that important,
955  * and is something that many users would be willing to
956  * sacrifice for having an easy way to do this.
957  */
958 
959  if ((apply_loc == false) && (apply_rot == false) && (apply_scale == true)) {
960  float max_scale = max_fff(fabsf(ob->scale[0]), fabsf(ob->scale[1]), fabsf(ob->scale[2]));
961  ob->empty_drawsize *= max_scale;
962  }
963  }
964  else if (ob->type == OB_LAMP) {
965  Light *la = static_cast<Light *>(ob->data);
966  if (la->type != LA_AREA) {
967  continue;
968  }
969 
970  bool keeps_aspect_ratio = compare_ff_relative(rsmat[0][0], rsmat[1][1], FLT_EPSILON, 64);
971  if ((la->area_shape == LA_AREA_SQUARE) && !keeps_aspect_ratio) {
972  la->area_shape = LA_AREA_RECT;
973  la->area_sizey = la->area_size;
974  }
975  else if ((la->area_shape == LA_AREA_DISK) && !keeps_aspect_ratio) {
977  la->area_sizey = la->area_size;
978  }
979 
980  la->area_size *= rsmat[0][0];
981  la->area_sizey *= rsmat[1][1];
982  la->area_sizez *= rsmat[2][2];
983  }
984  else {
985  continue;
986  }
987 
988  if (do_multi_user && ob != obact) {
989  float _obmat[4][4], _iobmat[4][4];
990  float _mat[4][4];
991 
992  copy_m4_m4(_obmat, ob->obmat);
993  invert_m4_m4(_iobmat, _obmat);
994 
995  copy_m4_m4(_mat, _obmat);
996  mul_m4_m4_post(_mat, obact_invmat);
997  mul_m4_m4_post(_mat, obact_parent);
998  mul_m4_m4_post(_mat, obact_parentinv);
999 
1000  if (apply_loc && apply_scale && apply_rot) {
1001  BKE_object_apply_mat4(ob, _mat, false, true);
1002  }
1003  else {
1004  Object ob_temp = blender::dna::shallow_copy(*ob);
1005  BKE_object_apply_mat4(&ob_temp, _mat, false, true);
1006 
1007  if (apply_loc) {
1008  copy_v3_v3(ob->loc, ob_temp.loc);
1009  }
1010 
1011  if (apply_scale) {
1012  copy_v3_v3(ob->scale, ob_temp.scale);
1013  }
1014 
1015  if (apply_rot) {
1016  copy_v4_v4(ob->quat, ob_temp.quat);
1017  copy_v3_v3(ob->rot, ob_temp.rot);
1018  copy_v3_v3(ob->rotAxis, ob_temp.rotAxis);
1019  ob->rotAngle = ob_temp.rotAngle;
1020  }
1021  }
1022  }
1023  else {
1024  if (apply_loc) {
1025  zero_v3(ob->loc);
1026  zero_v3(ob->dloc);
1027  }
1028  if (apply_scale) {
1029  copy_v3_fl(ob->scale, 1.0f);
1030  copy_v3_fl(ob->dscale, 1.0f);
1031  }
1032  if (apply_rot) {
1033  zero_v3(ob->rot);
1034  zero_v3(ob->drot);
1035  unit_qt(ob->quat);
1036  unit_qt(ob->dquat);
1037  unit_axis_angle(ob->rotAxis, &ob->rotAngle);
1038  unit_axis_angle(ob->drotAxis, &ob->drotAngle);
1039  }
1040  }
1041 
1042  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
1043  BKE_object_transform_copy(ob_eval, ob);
1044 
1046  if (ob->type == OB_ARMATURE) {
1047  /* needed for bone parents */
1048  BKE_armature_copy_bone_transforms(static_cast<bArmature *>(ob_eval->data),
1049  static_cast<bArmature *>(ob->data));
1050  BKE_pose_where_is(depsgraph, scene, ob_eval);
1051  }
1052 
1053  ignore_parent_tx(bmain, depsgraph, scene, ob);
1054 
1056 
1057  changed = true;
1058  }
1059 
1060  if (!changed) {
1061  BKE_report(reports, RPT_WARNING, "Objects have no data to transform");
1062  return OPERATOR_CANCELLED;
1063  }
1064 
1066  return OPERATOR_FINISHED;
1067 }
1068 
1070 {
1073  bool changed = false;
1074 
1075  CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1076  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
1078  BKE_object_apply_mat4(ob_eval, ob_eval->obmat, true, true);
1079  BKE_object_transform_copy(ob, ob_eval);
1080 
1081  /* update for any children that may get moved */
1083 
1084  changed = true;
1085  }
1086  CTX_DATA_END;
1087 
1088  if (!changed) {
1089  return OPERATOR_CANCELLED;
1090  }
1091 
1093  return OPERATOR_FINISHED;
1094 }
1095 
1097 {
1098  /* identifiers */
1099  ot->name = "Apply Visual Transform";
1100  ot->description = "Apply the object's visual transformation to its data";
1101  ot->idname = "OBJECT_OT_visual_transform_apply";
1102 
1103  /* api callbacks */
1106 
1107  /* flags */
1109 }
1110 
1112 {
1113  const bool loc = RNA_boolean_get(op->ptr, "location");
1114  const bool rot = RNA_boolean_get(op->ptr, "rotation");
1115  const bool sca = RNA_boolean_get(op->ptr, "scale");
1116  const bool do_props = RNA_boolean_get(op->ptr, "properties");
1117  const bool do_single_user = RNA_boolean_get(op->ptr, "isolate_users");
1118 
1119  if (loc || rot || sca) {
1120  return apply_objects_internal(C, op->reports, loc, rot, sca, do_props, do_single_user);
1121  }
1122  /* allow for redo */
1123  return OPERATOR_FINISHED;
1124 }
1125 
1127 {
1129 
1130  bool can_handle_multiuser = apply_objects_internal_can_multiuser(C);
1131  bool need_single_user = can_handle_multiuser && apply_objects_internal_need_single_user(C);
1132 
1133  if ((ob != nullptr) && (ob->data != nullptr) && need_single_user) {
1134  PropertyRNA *prop = RNA_struct_find_property(op->ptr, "isolate_users");
1135  if (!RNA_property_is_set(op->ptr, prop)) {
1136  RNA_property_boolean_set(op->ptr, prop, true);
1137  }
1138  if (RNA_property_boolean_get(op->ptr, prop)) {
1140  C, op, "Create new object-data users and apply transformation");
1141  }
1142  }
1143  return object_transform_apply_exec(C, op);
1144 }
1145 
1147 {
1148  /* identifiers */
1149  ot->name = "Apply Object Transform";
1150  ot->description = "Apply the object's transformation to its data";
1151  ot->idname = "OBJECT_OT_transform_apply";
1152 
1153  /* api callbacks */
1157 
1158  /* flags */
1160 
1161  RNA_def_boolean(ot->srna, "location", true, "Location", "");
1162  RNA_def_boolean(ot->srna, "rotation", true, "Rotation", "");
1163  RNA_def_boolean(ot->srna, "scale", true, "Scale", "");
1165  "properties",
1166  true,
1167  "Apply Properties",
1168  "Modify properties such as curve vertex radius, font size and bone envelope");
1170  "isolate_users",
1171  false,
1172  "Isolate Multi User Data",
1173  "Create new object-data users if needed");
1176 }
1177 
1180 /* -------------------------------------------------------------------- */
1185 {
1186  CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1187  if (ob->parent == nullptr) {
1188  continue;
1189  }
1190 
1193  }
1194  CTX_DATA_END;
1195 
1197 
1198  return OPERATOR_FINISHED;
1199 }
1200 
1202 {
1203  /* identifiers */
1204  ot->name = "Apply Parent Inverse";
1205  ot->description = "Apply the object's parent inverse to its data";
1206  ot->idname = "OBJECT_OT_parent_inverse_apply";
1207 
1208  /* api callbacks */
1211 
1212  /* flags */
1214 }
1215 
1218 /* -------------------------------------------------------------------- */
1222 enum {
1228 };
1229 
1231 {
1232  Main *bmain = CTX_data_main(C);
1234  Object *obact = CTX_data_active_object(C);
1235  Object *obedit = CTX_data_edit_object(C);
1237  float3 cent, cent_neg, centn;
1238  const float *cursor = scene->cursor.location;
1239  int centermode = RNA_enum_get(op->ptr, "type");
1240 
1241  /* keep track of what is changed */
1242  int tot_change = 0, tot_lib_error = 0, tot_multiuser_arm_error = 0;
1243 
1244  if (obedit && centermode != GEOMETRY_TO_ORIGIN) {
1245  BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode");
1246  return OPERATOR_CANCELLED;
1247  }
1248 
1249  int around;
1250  {
1251  PropertyRNA *prop_center = RNA_struct_find_property(op->ptr, "center");
1252  if (RNA_property_is_set(op->ptr, prop_center)) {
1253  around = RNA_property_enum_get(op->ptr, prop_center);
1254  }
1255  else {
1257  around = V3D_AROUND_CENTER_BOUNDS;
1258  }
1259  else {
1260  around = V3D_AROUND_CENTER_MEDIAN;
1261  }
1262  RNA_property_enum_set(op->ptr, prop_center, around);
1263  }
1264  }
1265 
1266  zero_v3(cent);
1267 
1268  if (obedit) {
1269  if (obedit->type == OB_MESH) {
1270  Mesh *me = static_cast<Mesh *>(obedit->data);
1271  BMEditMesh *em = me->edit_mesh;
1272  BMVert *eve;
1273  BMIter iter;
1274 
1275  if (centermode == ORIGIN_TO_CURSOR) {
1276  copy_v3_v3(cent, cursor);
1277  invert_m4_m4(obedit->imat, obedit->obmat);
1278  mul_m4_v3(obedit->imat, cent);
1279  }
1280  else {
1281  if (around == V3D_AROUND_CENTER_BOUNDS) {
1282  float min[3], max[3];
1283  INIT_MINMAX(min, max);
1284  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
1285  minmax_v3v3_v3(min, max, eve->co);
1286  }
1287  mid_v3_v3v3(cent, min, max);
1288  }
1289  else { /* #V3D_AROUND_CENTER_MEDIAN. */
1290  if (em->bm->totvert) {
1291  const float total_div = 1.0f / (float)em->bm->totvert;
1292  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
1293  madd_v3_v3fl(cent, eve->co, total_div);
1294  }
1295  }
1296  }
1297  }
1298 
1299  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
1300  sub_v3_v3(eve->co, cent);
1301  }
1302 
1304  tot_change++;
1306  }
1307  }
1308 
1310  if (objects.is_empty()) {
1311  return OPERATOR_CANCELLED;
1312  }
1313 
1314  /* reset flags */
1315  for (const int object_index : objects.index_range()) {
1316  Object *ob = objects[object_index];
1317  ob->flag &= ~OB_DONE;
1318 
1319  /* move active first */
1320  if (ob == obact && objects.size() > 1) {
1321  memmove(&objects[1], objects.data(), object_index * sizeof(Object *));
1322  objects[0] = ob;
1323  }
1324  }
1325 
1326  LISTBASE_FOREACH (Object *, tob, &bmain->objects) {
1327  if (tob->data) {
1328  ((ID *)tob->data)->tag &= ~LIB_TAG_DOIT;
1329  }
1330  if (tob->instance_collection) {
1331  ((ID *)tob->instance_collection)->tag &= ~LIB_TAG_DOIT;
1332  }
1333  }
1334 
1335  for (Object *ob : objects) {
1336  if (ob->flag & OB_DONE) {
1337  continue;
1338  }
1339 
1340  bool do_inverse_offset = false;
1341  ob->flag |= OB_DONE;
1342 
1343  if (centermode == ORIGIN_TO_CURSOR) {
1344  copy_v3_v3(cent, cursor);
1345  invert_m4_m4(ob->imat, ob->obmat);
1346  mul_m4_v3(ob->imat, cent);
1347  }
1348 
1349  if (ob->data == nullptr) {
1350  /* Special support for instanced collections. */
1351  if ((ob->transflag & OB_DUPLICOLLECTION) && ob->instance_collection &&
1352  (ob->instance_collection->id.tag & LIB_TAG_DOIT) == 0) {
1353  if (!BKE_id_is_editable(bmain, &ob->instance_collection->id)) {
1354  tot_lib_error++;
1355  }
1356  else {
1357  if (centermode == ORIGIN_TO_CURSOR) {
1358  /* done */
1359  }
1360  else {
1361  float min[3], max[3];
1362  /* only bounds support */
1363  INIT_MINMAX(min, max);
1365  mid_v3_v3v3(cent, min, max);
1366  invert_m4_m4(ob->imat, ob->obmat);
1367  mul_m4_v3(ob->imat, cent);
1368  }
1369 
1370  add_v3_v3(ob->instance_collection->instance_offset, cent);
1371 
1372  tot_change++;
1373  ob->instance_collection->id.tag |= LIB_TAG_DOIT;
1374  do_inverse_offset = true;
1375  }
1376  }
1377  }
1378  else if (ID_IS_LINKED(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob->data)) {
1379  tot_lib_error++;
1380  }
1381  else if (ob->type == OB_MESH) {
1382  if (obedit == nullptr) {
1383  Mesh *me = static_cast<Mesh *>(ob->data);
1384 
1385  if (centermode == ORIGIN_TO_CURSOR) {
1386  /* done */
1387  }
1388  else if (centermode == ORIGIN_TO_CENTER_OF_MASS_SURFACE) {
1389  BKE_mesh_center_of_surface(me, cent);
1390  }
1391  else if (centermode == ORIGIN_TO_CENTER_OF_MASS_VOLUME) {
1392  BKE_mesh_center_of_volume(me, cent);
1393  }
1394  else if (around == V3D_AROUND_CENTER_BOUNDS) {
1395  BKE_mesh_center_bounds(me, cent);
1396  }
1397  else { /* #V3D_AROUND_CENTER_MEDIAN. */
1398  BKE_mesh_center_median(me, cent);
1399  }
1400 
1401  negate_v3_v3(cent_neg, cent);
1402  BKE_mesh_translate(me, cent_neg, true);
1403 
1404  tot_change++;
1405  me->id.tag |= LIB_TAG_DOIT;
1406  do_inverse_offset = true;
1407  }
1408  }
1409  else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
1410  Curve *cu = static_cast<Curve *>(ob->data);
1411 
1412  if (centermode == ORIGIN_TO_CURSOR) {
1413  /* done */
1414  }
1415  else if (around == V3D_AROUND_CENTER_BOUNDS) {
1416  BKE_curve_center_bounds(cu, cent);
1417  }
1418  else { /* #V3D_AROUND_CENTER_MEDIAN. */
1419  BKE_curve_center_median(cu, cent);
1420  }
1421 
1422  /* don't allow Z change if curve is 2D */
1423  if ((ob->type == OB_CURVES_LEGACY) && !(cu->flag & CU_3D)) {
1424  cent[2] = 0.0;
1425  }
1426 
1427  negate_v3_v3(cent_neg, cent);
1428  BKE_curve_translate(cu, cent_neg, true);
1429 
1430  tot_change++;
1431  cu->id.tag |= LIB_TAG_DOIT;
1432  do_inverse_offset = true;
1433 
1434  if (obedit) {
1435  if (centermode == GEOMETRY_TO_ORIGIN) {
1437  }
1438  break;
1439  }
1440  }
1441  else if (ob->type == OB_FONT) {
1442  /* Get from bounding-box. */
1443 
1444  Curve *cu = static_cast<Curve *>(ob->data);
1445 
1446  if (ob->runtime.bb == nullptr && (centermode != ORIGIN_TO_CURSOR)) {
1447  /* Do nothing. */
1448  }
1449  else {
1450  if (centermode == ORIGIN_TO_CURSOR) {
1451  /* Done. */
1452  }
1453  else {
1454  /* extra 0.5 is the height o above line */
1455  cent[0] = 0.5f * (ob->runtime.bb->vec[4][0] + ob->runtime.bb->vec[0][0]);
1456  cent[1] = 0.5f * (ob->runtime.bb->vec[0][1] + ob->runtime.bb->vec[2][1]);
1457  }
1458 
1459  cent[2] = 0.0f;
1460 
1461  cu->xof = cu->xof - cent[0];
1462  cu->yof = cu->yof - cent[1];
1463 
1464  tot_change++;
1465  cu->id.tag |= LIB_TAG_DOIT;
1466  do_inverse_offset = true;
1467  }
1468  }
1469  else if (ob->type == OB_ARMATURE) {
1470  bArmature *arm = static_cast<bArmature *>(ob->data);
1471 
1472  if (ID_REAL_USERS(arm) > 1) {
1473 #if 0
1474  BKE_report(op->reports, RPT_ERROR, "Cannot apply to a multi user armature");
1475  return;
1476 #endif
1477  tot_multiuser_arm_error++;
1478  }
1479  else {
1480  /* Function to recenter armatures in editarmature.c
1481  * Bone + object locations are handled there.
1482  */
1483  ED_armature_origin_set(bmain, ob, cursor, centermode, around);
1484 
1485  tot_change++;
1486  arm->id.tag |= LIB_TAG_DOIT;
1487  /* do_inverse_offset = true; */ /* docenter_armature() handles this */
1488 
1489  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
1490  BKE_object_transform_copy(ob_eval, ob);
1491  BKE_armature_copy_bone_transforms(static_cast<bArmature *>(ob_eval->data),
1492  static_cast<bArmature *>(ob->data));
1494  BKE_pose_where_is(depsgraph, scene, ob_eval); /* needed for bone parents */
1495 
1496  ignore_parent_tx(bmain, depsgraph, scene, ob);
1497 
1498  if (obedit) {
1499  break;
1500  }
1501  }
1502  }
1503  else if (ob->type == OB_MBALL) {
1504  MetaBall *mb = static_cast<MetaBall *>(ob->data);
1505 
1506  if (centermode == ORIGIN_TO_CURSOR) {
1507  /* done */
1508  }
1509  else if (around == V3D_AROUND_CENTER_BOUNDS) {
1510  BKE_mball_center_bounds(mb, cent);
1511  }
1512  else { /* #V3D_AROUND_CENTER_MEDIAN. */
1513  BKE_mball_center_median(mb, cent);
1514  }
1515 
1516  negate_v3_v3(cent_neg, cent);
1517  BKE_mball_translate(mb, cent_neg);
1518 
1519  tot_change++;
1520  mb->id.tag |= LIB_TAG_DOIT;
1521  do_inverse_offset = true;
1522 
1523  if (obedit) {
1524  if (centermode == GEOMETRY_TO_ORIGIN) {
1526  }
1527  break;
1528  }
1529  }
1530  else if (ob->type == OB_LATTICE) {
1531  Lattice *lt = static_cast<Lattice *>(ob->data);
1532 
1533  if (centermode == ORIGIN_TO_CURSOR) {
1534  /* done */
1535  }
1536  else if (around == V3D_AROUND_CENTER_BOUNDS) {
1537  BKE_lattice_center_bounds(lt, cent);
1538  }
1539  else { /* #V3D_AROUND_CENTER_MEDIAN. */
1540  BKE_lattice_center_median(lt, cent);
1541  }
1542 
1543  negate_v3_v3(cent_neg, cent);
1544  BKE_lattice_translate(lt, cent_neg, true);
1545 
1546  tot_change++;
1547  lt->id.tag |= LIB_TAG_DOIT;
1548  do_inverse_offset = true;
1549  }
1550  else if (ob->type == OB_GPENCIL) {
1551  bGPdata *gpd = static_cast<bGPdata *>(ob->data);
1552  float gpcenter[3];
1553  if (gpd) {
1554  if (centermode == ORIGIN_TO_GEOMETRY) {
1555  zero_v3(gpcenter);
1556  BKE_gpencil_centroid_3d(gpd, gpcenter);
1557  add_v3_v3(gpcenter, ob->obmat[3]);
1558  }
1559  if (centermode == ORIGIN_TO_CURSOR) {
1560  copy_v3_v3(gpcenter, cursor);
1561  }
1562  if (ELEM(centermode, ORIGIN_TO_GEOMETRY, ORIGIN_TO_CURSOR)) {
1563  bGPDspoint *pt;
1564  float imat[3][3], bmat[3][3];
1565  float offset_global[3];
1566  float offset_local[3];
1567  int i;
1568 
1569  sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]);
1570  copy_m3_m4(bmat, obact->obmat);
1571  invert_m3_m3(imat, bmat);
1572  mul_m3_v3(imat, offset_global);
1573  mul_v3_m3v3(offset_local, imat, offset_global);
1574 
1575  float diff_mat[4][4];
1576  float inverse_diff_mat[4][4];
1577 
1578  /* recalculate all strokes
1579  * (all layers are considered without evaluating lock attributes) */
1580  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1581  /* calculate difference matrix */
1582  BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat);
1583  /* undo matrix */
1584  invert_m4_m4(inverse_diff_mat, diff_mat);
1585  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
1586  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
1587  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1588  float mpt[3];
1589  mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
1590  sub_v3_v3(mpt, offset_local);
1591  mul_v3_m4v3(&pt->x, diff_mat, mpt);
1592  }
1593 
1594  /* Apply transform to edit-curve. */
1595  if (gps->editcurve != nullptr) {
1596  for (i = 0; i < gps->editcurve->tot_curve_points; i++) {
1597  BezTriple *bezt = &gps->editcurve->curve_points[i].bezt;
1598  for (int j = 0; j < 3; j++) {
1599  float mpt[3];
1600  mul_v3_m4v3(mpt, inverse_diff_mat, bezt->vec[j]);
1601  sub_v3_v3(mpt, offset_local);
1602  mul_v3_m4v3(bezt->vec[j], diff_mat, mpt);
1603  }
1604  }
1605  }
1607  }
1608  }
1609  }
1610  tot_change++;
1611  if (centermode == ORIGIN_TO_GEOMETRY) {
1612  copy_v3_v3(ob->loc, gpcenter);
1613  }
1616 
1617  ob->id.tag |= LIB_TAG_DOIT;
1618  do_inverse_offset = true;
1619  }
1620  else {
1621  BKE_report(op->reports,
1622  RPT_WARNING,
1623  "Grease Pencil Object does not support this set origin option");
1624  }
1625  }
1626  }
1627  else if (ob->type == OB_CURVES) {
1628  using namespace blender;
1629  Curves &curves_id = *static_cast<Curves *>(ob->data);
1633  BKE_report(
1634  op->reports, RPT_WARNING, "Curves Object does not support this set origin operation");
1635  continue;
1636  }
1637 
1638  if (curves.points_num() == 0) {
1639  continue;
1640  }
1641 
1642  if (centermode == ORIGIN_TO_CURSOR) {
1643  /* done */
1644  }
1645  else if (around == V3D_AROUND_CENTER_BOUNDS) {
1646  float3 min;
1647  float3 max;
1648  if (curves.bounds_min_max(min, max)) {
1649  cent = math::midpoint(min, max);
1650  }
1651  }
1652  else if (around == V3D_AROUND_CENTER_MEDIAN) {
1653  Span<float3> positions = curves.positions();
1654  cent = std::accumulate(positions.begin(), positions.end(), float3(0)) /
1655  curves.points_num();
1656  }
1657 
1658  tot_change++;
1659  curves.translate(-cent);
1660  curves_id.id.tag |= LIB_TAG_DOIT;
1661  do_inverse_offset = true;
1662  }
1663 
1664  /* offset other selected objects */
1665  if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) {
1666  float obmat[4][4];
1667 
1668  /* was the object data modified
1669  * NOTE: the functions above must set 'cent'. */
1670 
1671  /* convert the offset to parent space */
1672  BKE_object_to_mat4(ob, obmat);
1673  mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */
1674 
1675  add_v3_v3(ob->loc, centn);
1676 
1677  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
1678  BKE_object_transform_copy(ob_eval, ob);
1680  if (ob->type == OB_ARMATURE) {
1681  /* needed for bone parents */
1682  BKE_armature_copy_bone_transforms(static_cast<bArmature *>(ob_eval->data),
1683  static_cast<bArmature *>(ob->data));
1684  BKE_pose_where_is(depsgraph, scene, ob_eval);
1685  }
1686 
1687  ignore_parent_tx(bmain, depsgraph, scene, ob);
1688 
1689  /* other users? */
1690  // CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects)
1691  //{
1692 
1693  /* use existing context looper */
1694  for (Object *ob_other : objects) {
1695  if ((ob_other->flag & OB_DONE) == 0 &&
1696  ((ob->data && (ob->data == ob_other->data)) ||
1697  (ob->instance_collection == ob_other->instance_collection &&
1698  (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION))) {
1699  ob_other->flag |= OB_DONE;
1701 
1702  mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */
1703  add_v3_v3(ob_other->loc, centn);
1704 
1705  Object *ob_other_eval = DEG_get_evaluated_object(depsgraph, ob_other);
1706  BKE_object_transform_copy(ob_other_eval, ob_other);
1707  BKE_object_where_is_calc(depsgraph, scene, ob_other_eval);
1708  if (ob_other->type == OB_ARMATURE) {
1709  /* needed for bone parents */
1710  BKE_armature_copy_bone_transforms(static_cast<bArmature *>(ob_eval->data),
1711  static_cast<bArmature *>(ob->data));
1712  BKE_pose_where_is(depsgraph, scene, ob_other_eval);
1713  }
1714  ignore_parent_tx(bmain, depsgraph, scene, ob_other);
1715  }
1716  }
1717  // CTX_DATA_END;
1718  }
1719  }
1720 
1721  LISTBASE_FOREACH (Object *, tob, &bmain->objects) {
1722  if (tob->data && (((ID *)tob->data)->tag & LIB_TAG_DOIT)) {
1725  }
1726  /* Special support for dupli-groups. */
1727  else if (tob->instance_collection && tob->instance_collection->id.tag & LIB_TAG_DOIT) {
1729  DEG_id_tag_update(&tob->instance_collection->id, ID_RECALC_COPY_ON_WRITE);
1730  }
1731  }
1732 
1733  if (tot_change) {
1735  }
1736 
1737  /* Warn if any errors occurred */
1738  if (tot_lib_error + tot_multiuser_arm_error) {
1739  BKE_reportf(op->reports,
1740  RPT_WARNING,
1741  "%i object(s) not centered, %i changed:",
1742  tot_lib_error + tot_multiuser_arm_error,
1743  tot_change);
1744  if (tot_lib_error) {
1745  BKE_reportf(op->reports, RPT_WARNING, "|%i linked library object(s)", tot_lib_error);
1746  }
1747  if (tot_multiuser_arm_error) {
1748  BKE_reportf(
1749  op->reports, RPT_WARNING, "|%i multiuser armature object(s)", tot_multiuser_arm_error);
1750  }
1751  }
1752 
1753  return OPERATOR_FINISHED;
1754 }
1755 
1757 {
1758  static const EnumPropertyItem prop_set_center_types[] = {
1760  "GEOMETRY_ORIGIN",
1761  0,
1762  "Geometry to Origin",
1763  "Move object geometry to object origin"},
1765  "ORIGIN_GEOMETRY",
1766  0,
1767  "Origin to Geometry",
1768  "Calculate the center of geometry based on the current pivot point (median, otherwise "
1769  "bounding box)"},
1771  "ORIGIN_CURSOR",
1772  0,
1773  "Origin to 3D Cursor",
1774  "Move object origin to position of the 3D cursor"},
1775  /* Intentional naming mismatch since some scripts refer to this. */
1777  "ORIGIN_CENTER_OF_MASS",
1778  0,
1779  "Origin to Center of Mass (Surface)",
1780  "Calculate the center of mass from the surface area"},
1782  "ORIGIN_CENTER_OF_VOLUME",
1783  0,
1784  "Origin to Center of Mass (Volume)",
1785  "Calculate the center of mass from the volume (must be manifold geometry with consistent "
1786  "normals)"},
1787  {0, nullptr, 0, nullptr, nullptr},
1788  };
1789 
1790  static const EnumPropertyItem prop_set_bounds_types[] = {
1791  {V3D_AROUND_CENTER_MEDIAN, "MEDIAN", 0, "Median Center", ""},
1792  {V3D_AROUND_CENTER_BOUNDS, "BOUNDS", 0, "Bounds Center", ""},
1793  {0, nullptr, 0, nullptr, nullptr},
1794  };
1795 
1796  /* identifiers */
1797  ot->name = "Set Origin";
1798  ot->description =
1799  "Set the object's origin, by either moving the data, or set to center of data, or use 3D "
1800  "cursor";
1801  ot->idname = "OBJECT_OT_origin_set";
1802 
1803  /* api callbacks */
1806 
1808 
1809  /* flags */
1811 
1812  ot->prop = RNA_def_enum(ot->srna, "type", prop_set_center_types, 0, "Type", "");
1813  RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_AROUND_CENTER_MEDIAN, "Center", "");
1814 }
1815 
1818 /* -------------------------------------------------------------------- */
1827 #define USE_RELATIVE_ROTATION
1829 #define USE_RENDER_OVERRIDE
1834 #define USE_FAKE_DEPTH_INIT
1835 
1838  float rot_mat[3][3];
1839  void *obtfm;
1840  float xform_dist;
1842 
1843 #ifdef USE_RELATIVE_ROTATION
1844  /* use when translating multiple */
1845  float xform_rot_offset[3][3];
1846 #endif
1847 };
1848 
1852  struct {
1853  float depth;
1854  float normal[3];
1857  } prev;
1858 
1861 
1863 };
1864 
1865 #ifdef USE_FAKE_DEPTH_INIT
1867 {
1868  float view_co_a[3], view_co_b[3];
1869  const float2 mval_fl = {static_cast<float>(mval[0]), static_cast<float>(mval[1])};
1870  ED_view3d_win_to_ray(xfd->vc.region, mval_fl, view_co_a, view_co_b);
1871  add_v3_v3(view_co_b, view_co_a);
1872  float center[3] = {0.0f};
1873  int center_tot = 0;
1874  for (XFormAxisItem &item : xfd->object_data) {
1875  const Object *ob = item.ob;
1876  const float *ob_co_a = ob->obmat[3];
1877  float ob_co_b[3];
1878  add_v3_v3v3(ob_co_b, ob->obmat[3], ob->obmat[2]);
1879  float view_isect[3], ob_isect[3];
1880  if (isect_line_line_v3(view_co_a, view_co_b, ob_co_a, ob_co_b, view_isect, ob_isect)) {
1881  add_v3_v3(center, view_isect);
1882  center_tot += 1;
1883  }
1884  }
1885  if (center_tot) {
1886  mul_v3_fl(center, 1.0f / center_tot);
1887  float center_proj[3];
1888  ED_view3d_project_v3(xfd->vc.region, center, center_proj);
1889  xfd->prev.depth = center_proj[2];
1890  xfd->prev.is_depth_valid = true;
1891  }
1892 }
1893 #endif /* USE_FAKE_DEPTH_INIT */
1894 
1895 static bool object_is_target_compat(const Object *ob)
1896 {
1897  if (ob->type == OB_LAMP) {
1898  const Light *la = static_cast<Light *>(ob->data);
1899  if (ELEM(la->type, LA_SUN, LA_SPOT, LA_AREA)) {
1900  return true;
1901  }
1902  }
1903  /* We might want to enable this later, for now just lights. */
1904 #if 0
1905  else if (ob->type == OB_CAMERA) {
1906  return true;
1907  }
1908 #endif
1909  return false;
1910 }
1911 
1913 {
1914  XFormAxisData *xfd = static_cast<XFormAxisData *>(op->customdata);
1915 
1916 #ifdef USE_RENDER_OVERRIDE
1917  if (xfd->depths) {
1919  }
1920 #endif
1921 
1922  for (XFormAxisItem &item : xfd->object_data) {
1923  MEM_freeN(item.obtfm);
1924  }
1925  MEM_delete(xfd);
1926  op->customdata = nullptr;
1927 }
1928 
1929 /* We may want to expose as alternative to: BKE_object_apply_rotation */
1930 static void object_apply_rotation(Object *ob, const float rmat[3][3])
1931 {
1932  float size[3];
1933  float loc[3];
1934  float rmat4[4][4];
1935  copy_m4_m3(rmat4, rmat);
1936 
1937  copy_v3_v3(size, ob->scale);
1938  copy_v3_v3(loc, ob->loc);
1939  BKE_object_apply_mat4(ob, rmat4, true, true);
1940  copy_v3_v3(ob->scale, size);
1941  copy_v3_v3(ob->loc, loc);
1942 }
1943 /* We may want to extract this to: BKE_object_apply_location */
1944 static void object_apply_location(Object *ob, const float loc[3])
1945 {
1946  /* quick but weak */
1947  Object ob_prev = blender::dna::shallow_copy(*ob);
1948  float mat[4][4];
1949  copy_m4_m4(mat, ob->obmat);
1950  copy_v3_v3(mat[3], loc);
1951  BKE_object_apply_mat4(ob, mat, true, true);
1952  copy_v3_v3(mat[3], ob->loc);
1953  *ob = blender::dna::shallow_copy(ob_prev);
1954  copy_v3_v3(ob->loc, mat[3]);
1955 }
1956 
1958  const float rot_orig[3][3],
1959  const float axis[3],
1960  const float location[3],
1961  const bool z_flip)
1962 {
1963  float delta[3];
1964  sub_v3_v3v3(delta, ob->obmat[3], location);
1965  if (normalize_v3(delta) != 0.0f) {
1966  if (z_flip) {
1967  negate_v3(delta);
1968  }
1969 
1970  if (len_squared_v3v3(delta, axis) > FLT_EPSILON) {
1971  float delta_rot[3][3];
1972  float final_rot[3][3];
1973  rotation_between_vecs_to_mat3(delta_rot, axis, delta);
1974 
1975  mul_m3_m3m3(final_rot, delta_rot, rot_orig);
1976 
1977  object_apply_rotation(ob, final_rot);
1978 
1979  return true;
1980  }
1981  }
1982  return false;
1983 }
1984 
1986 {
1987  XFormAxisData *xfd = static_cast<XFormAxisData *>(op->customdata);
1988  for (XFormAxisItem &item : xfd->object_data) {
1989  BKE_object_tfm_restore(item.ob, item.obtfm);
1992  }
1993 
1995 }
1996 
1998 {
2000  ViewContext vc;
2002 
2003  if (vc.obact == nullptr || !object_is_target_compat(vc.obact)) {
2004  /* Falls back to texture space transform. */
2005  return OPERATOR_PASS_THROUGH;
2006  }
2007 
2008 #ifdef USE_RENDER_OVERRIDE
2009  int flag2_prev = vc.v3d->flag2;
2010  vc.v3d->flag2 |= V3D_HIDE_OVERLAYS;
2011 #endif
2012 
2013  ViewDepths *depths = nullptr;
2015  vc.depsgraph, vc.region, vc.v3d, nullptr, V3D_DEPTH_NO_GPENCIL, &depths);
2016 
2017 #ifdef USE_RENDER_OVERRIDE
2018  vc.v3d->flag2 = flag2_prev;
2019 #endif
2020 
2021  if (depths == nullptr) {
2022  BKE_report(op->reports, RPT_WARNING, "Unable to access depth buffer, using view plane");
2023  return OPERATOR_CANCELLED;
2024  }
2025 
2027 
2028  XFormAxisData *xfd = MEM_new<XFormAxisData>(__func__);
2029  op->customdata = xfd;
2030 
2031  /* Don't change this at runtime. */
2032  xfd->vc = vc;
2033  xfd->depths = depths;
2034  xfd->vc.mval[0] = event->mval[0];
2035  xfd->vc.mval[1] = event->mval[1];
2036 
2037  xfd->prev.depth = 1.0f;
2038  xfd->prev.is_depth_valid = false;
2039  xfd->prev.is_normal_valid = false;
2040  xfd->is_translate = false;
2041 
2043 
2044  xfd->object_data.append({});
2045  xfd->object_data.last().ob = xfd->vc.obact;
2046 
2047  CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
2048  if ((ob != xfd->vc.obact) && object_is_target_compat(ob)) {
2049  xfd->object_data.append({});
2050  xfd->object_data.last().ob = ob;
2051  }
2052  }
2053  CTX_DATA_END;
2054 
2055  for (XFormAxisItem &item : xfd->object_data) {
2056  item.obtfm = BKE_object_tfm_backup(item.ob);
2057  BKE_object_rot_to_mat3(item.ob, item.rot_mat, true);
2058 
2059  /* Detect negative scale matrix. */
2060  float full_mat3[3][3];
2061  BKE_object_to_mat3(item.ob, full_mat3);
2062  item.is_z_flip = dot_v3v3(item.rot_mat[2], full_mat3[2]) < 0.0f;
2063  }
2064 
2066 
2067  return OPERATOR_RUNNING_MODAL;
2068 }
2069 
2071 {
2072  XFormAxisData *xfd = static_cast<XFormAxisData *>(op->customdata);
2073  ARegion *region = xfd->vc.region;
2074 
2076 
2077  const bool is_translate = event->modifier & KM_CTRL;
2078  const bool is_translate_init = is_translate && (xfd->is_translate != is_translate);
2079 
2080  if (event->type == MOUSEMOVE || is_translate_init) {
2081  const ViewDepths *depths = xfd->depths;
2082  if (depths && ((uint)event->mval[0] < depths->w) && ((uint)event->mval[1] < depths->h)) {
2083  float depth_fl = 1.0f;
2084  ED_view3d_depth_read_cached(depths, event->mval, 0, &depth_fl);
2085  float location_world[3];
2086  if (depth_fl == 1.0f) {
2087  if (xfd->prev.is_depth_valid) {
2088  depth_fl = xfd->prev.depth;
2089  }
2090  }
2091 
2092 #ifdef USE_FAKE_DEPTH_INIT
2093  /* First time only. */
2094  if (depth_fl == 1.0f) {
2095  if (xfd->prev.is_depth_valid == false) {
2097  if (xfd->prev.is_depth_valid) {
2098  depth_fl = xfd->prev.depth;
2099  }
2100  }
2101  }
2102 #endif
2103 
2104  double depth = (double)depth_fl;
2105  if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
2106  xfd->prev.depth = depth_fl;
2107  xfd->prev.is_depth_valid = true;
2108  if (ED_view3d_depth_unproject_v3(region, event->mval, depth, location_world)) {
2109  if (is_translate) {
2110 
2111  float normal[3];
2112  bool normal_found = false;
2113  if (ED_view3d_depth_read_cached_normal(region, depths, event->mval, normal)) {
2114  normal_found = true;
2115 
2116  /* cheap attempt to smooth normals out a bit! */
2117  const int ofs = 2;
2118  for (int x = -ofs; x <= ofs; x += ofs / 2) {
2119  for (int y = -ofs; y <= ofs; y += ofs / 2) {
2120  if (x != 0 && y != 0) {
2121  const int mval_ofs[2] = {event->mval[0] + x, event->mval[1] + y};
2122  float n[3];
2123  if (ED_view3d_depth_read_cached_normal(region, depths, mval_ofs, n)) {
2124  add_v3_v3(normal, n);
2125  }
2126  }
2127  }
2128  }
2130  }
2131  else if (xfd->prev.is_normal_valid) {
2132  copy_v3_v3(normal, xfd->prev.normal);
2133  normal_found = true;
2134  }
2135 
2136  {
2137 #ifdef USE_RELATIVE_ROTATION
2138  if (is_translate_init && xfd->object_data.size() > 1) {
2139  float xform_rot_offset_inv_first[3][3];
2140  for (const int i : xfd->object_data.index_range()) {
2141  XFormAxisItem &item = xfd->object_data[i];
2142  copy_m3_m4(item.xform_rot_offset, item.ob->obmat);
2144 
2145  if (i == 0) {
2146  invert_m3_m3(xform_rot_offset_inv_first, xfd->object_data[0].xform_rot_offset);
2147  }
2148  else {
2149  mul_m3_m3m3(
2150  item.xform_rot_offset, item.xform_rot_offset, xform_rot_offset_inv_first);
2151  }
2152  }
2153  }
2154 
2155 #endif
2156 
2157  for (const int i : xfd->object_data.index_range()) {
2158  XFormAxisItem &item = xfd->object_data[i];
2159  if (is_translate_init) {
2160  float ob_axis[3];
2161  item.xform_dist = len_v3v3(item.ob->obmat[3], location_world);
2162  normalize_v3_v3(ob_axis, item.ob->obmat[2]);
2163  /* Scale to avoid adding distance when moving between surfaces. */
2164  if (normal_found) {
2165  float scale = fabsf(dot_v3v3(ob_axis, normal));
2166  item.xform_dist *= scale;
2167  }
2168  }
2169 
2170  float target_normal[3];
2171 
2172  if (normal_found) {
2173  copy_v3_v3(target_normal, normal);
2174  }
2175  else {
2176  normalize_v3_v3(target_normal, item.ob->obmat[2]);
2177  }
2178 
2179 #ifdef USE_RELATIVE_ROTATION
2180  if (normal_found) {
2181  if (i != 0) {
2182  mul_m3_v3(item.xform_rot_offset, target_normal);
2183  }
2184  }
2185 #endif
2186  {
2187  float loc[3];
2188 
2189  copy_v3_v3(loc, location_world);
2190  madd_v3_v3fl(loc, target_normal, item.xform_dist);
2191  object_apply_location(item.ob, loc);
2192  /* so orient behaves as expected */
2193  copy_v3_v3(item.ob->obmat[3], loc);
2194  }
2195 
2197  item.ob, item.rot_mat, item.rot_mat[2], location_world, item.is_z_flip);
2198 
2201  }
2202  if (normal_found) {
2203  copy_v3_v3(xfd->prev.normal, normal);
2204  xfd->prev.is_normal_valid = true;
2205  }
2206  }
2207  }
2208  else {
2209  for (XFormAxisItem &item : xfd->object_data) {
2211  item.ob, item.rot_mat, item.rot_mat[2], location_world, item.is_z_flip)) {
2214  }
2215  }
2216  xfd->prev.is_normal_valid = false;
2217  }
2218  }
2219  }
2220  }
2221  xfd->is_translate = is_translate;
2222 
2224  }
2225 
2226  bool is_finished = false;
2227 
2228  if (ISMOUSE_BUTTON(xfd->init_event)) {
2229  if ((event->type == xfd->init_event) && (event->val == KM_RELEASE)) {
2230  is_finished = true;
2231  }
2232  }
2233  else {
2234  if (ELEM(event->type, LEFTMOUSE, EVT_RETKEY, EVT_PADENTER)) {
2235  is_finished = true;
2236  }
2237  }
2238 
2239  if (is_finished) {
2241  return OPERATOR_FINISHED;
2242  }
2243  if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
2245  return OPERATOR_CANCELLED;
2246  }
2247 
2248  return OPERATOR_RUNNING_MODAL;
2249 }
2250 
2252 {
2253  /* identifiers */
2254  ot->name = "Interactive Light Track to Cursor";
2255  ot->description = "Interactively point cameras and lights to a location (Ctrl translates)";
2256  ot->idname = "OBJECT_OT_transform_axis_target";
2257 
2258  /* api callbacks */
2263 
2264  /* flags */
2266 }
2267 
2268 #undef USE_RELATIVE_ROTATION
2269 
typedef float(TangentPoint)[2]
void BKE_armature_transform(struct bArmature *arm, const float mat[4][4], bool do_props)
Definition: armature.c:556
void BKE_pose_where_is(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
Definition: armature.c:2538
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:1090
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1370
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:269
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
#define CTX_DATA_COUNT(C, member)
Definition: BKE_context.h:290
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1505
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
#define CTX_DATA_END
Definition: BKE_context.h:278
bool BKE_curve_center_median(struct Curve *cu, float cent[3])
Definition: curve.cc:5126
void BKE_curve_translate(struct Curve *cu, const float offset[3], bool do_keys)
Definition: curve.cc:5253
void BKE_curve_transform_ex(struct Curve *cu, const float mat[4][4], bool do_keys, bool do_props, float unit_scale)
Definition: curve.cc:5175
bool BKE_curve_center_bounds(struct Curve *cu, float cent[3])
Definition: curve.cc:5163
Low-level operations for curves.
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])
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(short idcode)
Definition: idtype.c:142
void BKE_lattice_translate(struct Lattice *lt, const float offset[3], bool do_keys)
Definition: lattice.c:728
void BKE_lattice_center_bounds(struct Lattice *lt, float cent[3])
Definition: lattice.c:696
void BKE_lattice_center_median(struct Lattice *lt, float cent[3])
Definition: lattice.c:614
void BKE_lattice_transform(struct Lattice *lt, const float mat[4][4], bool do_keys)
Definition: lattice.c:706
#define FOREACH_SELECTED_EDITABLE_OBJECT_END
Definition: BKE_layer.h:332
#define FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN(_view_layer, _v3d, _instance)
Definition: BKE_layer.h:320
void BKE_main_id_newptr_and_tag_clear(struct Main *bmain)
Definition: lib_id.c:1465
void BKE_main_id_tag_all(struct Main *mainvar, int tag, bool value)
Definition: lib_id.c:930
bool BKE_id_is_editable(const struct Main *bmain, const struct ID *id)
void id_us_min(struct ID *id)
Definition: lib_id.c:313
void id_us_plus(struct ID *id)
Definition: lib_id.c:305
bool BKE_mball_center_median(const struct MetaBall *mb, float r_cent[3])
void BKE_mball_transform(struct MetaBall *mb, const float mat[4][4], bool do_props)
Definition: mball.c:613
void BKE_mball_translate(struct MetaBall *mb, const float offset[3])
Definition: mball.c:639
bool BKE_mball_center_bounds(const struct MetaBall *mb, float r_cent[3])
void BKE_mesh_translate(struct Mesh *me, const float offset[3], bool do_keys)
Definition: mesh.cc:1632
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])
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.cc:1594
void multiresModifier_scale_disp(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
Definition: multires.c:1421
General operations, lookup, etc. for blender objects.
void BKE_object_batch_cache_dirty_tag(struct Object *ob)
bool BKE_object_minmax_dupli(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, float r_min[3], float r_max[3], bool use_hidden)
Definition: object.cc:4075
struct MovieClip * BKE_object_movieclip_get(struct Scene *scene, struct Object *ob, bool use_default)
Definition: object.cc:5042
void BKE_object_tfm_restore(struct Object *ob, void *obtfm_pt)
Definition: object.cc:4242
void * BKE_object_tfm_backup(struct Object *ob)
Definition: object.cc:4219
void BKE_object_where_is_calc(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
Definition: object.cc:3495
void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src)
void BKE_object_apply_parent_inverse(struct Object *ob)
Definition: object.cc:3583
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.cc:3069
void BKE_object_to_mat4(struct Object *ob, float r_mat[4][4])
Definition: object.cc:3082
void BKE_object_apply_mat4(struct Object *ob, const float mat[4][4], bool use_compat, bool use_parent)
Definition: object.cc:3575
void BKE_object_workob_calc_parent(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct Object *workob)
Definition: object.cc:3501
void BKE_object_scale_to_mat3(struct Object *ob, float r_mat[3][3])
Definition: object.cc:2887
void BKE_object_eval_transform_all(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *object)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
void BKE_scene_graph_evaluated_ensure(struct Depsgraph *depsgraph, struct Main *bmain)
Definition: scene.cc:2653
void BKE_tracking_reconstruction_scale(struct MovieTracking *tracking, float scale[3])
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
MINLINE float max_fff(float a, float b, float c)
MINLINE int compare_ff_relative(float a, float b, float max_diff, 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:2935
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:926
void unit_m3(float m[3][3])
Definition: math_matrix.c:40
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
void copy_m4_m3(float m1[4][4], const float m2[3][3])
Definition: math_matrix.c:102
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void normalize_m3(float R[3][3]) ATTR_NONNULL()
Definition: math_matrix.c:1912
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
float mat3_to_scale(const float M[3][3])
Definition: math_matrix.c:2176
bool invert_m3_m3(float R[3][3], const float A[3][3])
Definition: math_matrix.c:1180
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:897
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:388
void mul_m4_m4_post(float R[4][4], const float B[4][4])
Definition: math_matrix.c:380
void mul_v3_mat3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:800
@ EULER_ORDER_DEFAULT
void eulO_to_axis_angle(float axis[3], float *angle, const float eul[3], short order)
void mul_qt_fl(float q[4], float f)
void unit_qt(float q[4])
Definition: math_rotation.c:27
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], short order, const float axis[3], 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:19
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:33
MINLINE void copy_v4_v4(float r[4], const float a[4])
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:867
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:237
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:67
#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:35
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
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:771
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:834
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
@ LIB_TAG_DOIT
Definition: DNA_ID.h:707
#define ID_REAL_USERS(id)
Definition: DNA_ID.h:553
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:588
@ ID_GD
Definition: DNA_ID_enums.h:71
@ 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_LATTICE
@ OB_MBALL
@ OB_EMPTY
@ OB_SURF
@ OB_CAMERA
@ OB_FONT
@ OB_ARMATURE
@ OB_LAMP
@ OB_MESH
@ OB_CURVES_LEGACY
@ OB_CURVES
@ OB_GPENCIL
@ 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
@ 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:170
void ED_object_xform_skip_child_container_update_all(struct XFormObjectSkipChild_Container *xcs, struct Main *bmain, struct Depsgraph *depsgraph)
Definition: object_utils.c:257
void ED_object_single_obdata_user(struct Main *bmain, struct Scene *scene, struct Object *ob)
void ED_object_xform_skip_child_container_destroy(struct XFormObjectSkipChild_Container *xcs)
Definition: object_utils.c:230
struct XFormObjectSkipChild_Container * ED_object_xform_skip_child_container_create(void)
Definition: object_utils.c:161
struct Object * ED_object_active_context(const struct bContext *C)
void ED_object_data_xform_container_destroy(struct XFormObjectData_Container *xds)
Definition: object_utils.c:409
void ED_object_data_xform_container_item_ensure(struct XFormObjectData_Container *xds, struct Object *ob)
Definition: object_utils.c:341
void ED_object_data_xform_container_update_all(struct XFormObjectData_Container *xds, struct Main *bmain, struct Depsgraph *depsgraph)
Definition: object_utils.c:358
struct XFormObjectData_Container * ED_object_data_xform_container_create(void)
Definition: object_utils.c:402
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:655
bool ED_operator_objectmode(struct bContext *C)
Definition: screen_ops.c:186
bool ED_operator_scene_editable(struct bContext *C)
Definition: screen_ops.c:177
bool ED_operator_region_view3d_active(struct bContext *C)
Definition: screen_ops.c:230
bool ED_view3d_depth_read_cached(const ViewDepths *vd, const int mval[2], int margin, float *r_depth)
void ED_view3d_project_v3(const struct ARegion *region, const float world[3], float r_region_co[3])
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 struct ARegion *region, const ViewDepths *depths, const int mval[2], float r_normal[3])
void ED_view3d_depths_free(ViewDepths *depths)
Definition: view3d_draw.c:2366
@ V3D_DEPTH_NO_GPENCIL
Definition: ED_view3d.h:182
bool ED_view3d_depth_unproject_v3(const struct ARegion *region, const int mval[2], double depth, float r_location_world[3])
void view3d_operator_needs_opengl(const struct bContext *C)
void ED_view3d_depth_override(struct Depsgraph *depsgraph, struct ARegion *region, struct View3D *v3d, struct Object *obact, eV3DDepthOverrideMode mode, struct ViewDepths **r_depths)
Definition: view3d_draw.c:2294
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.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
@ PROP_HIDDEN
Definition: RNA_types.h:216
#define C
Definition: RandGen.cpp:25
@ KM_RELEASE
Definition: WM_types.h:268
@ OPTYPE_BLOCKING
Definition: WM_types.h:150
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_WINDOW
Definition: WM_types.h:325
#define ND_TRANSFORM
Definition: WM_types.h:405
@ KM_CTRL
Definition: WM_types.h:239
#define NC_OBJECT
Definition: WM_types.h:329
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
int64_t size() const
Definition: BLI_array.hh:244
const T * data() const
Definition: BLI_array.hh:300
IndexRange index_range() const
Definition: BLI_array.hh:348
bool is_empty() const
Definition: BLI_array.hh:252
int64_t size() const
Definition: BLI_vector.hh:694
void append(const T &value)
Definition: BLI_vector.hh:433
const T & last(const int64_t n=0) const
Definition: BLI_vector.hh:663
bool is_empty() const
Definition: BLI_vector.hh:706
IndexRange index_range() const
Definition: BLI_vector.hh:920
static CurvesGeometry & wrap(::CurvesGeometry &dna_struct)
Definition: BKE_curves.hh:138
void transform(const float4x4 &matrix)
Scene scene
const Depsgraph * depsgraph
#define rot(x, k)
IconTextureDrawCall normal
#define GS(x)
Definition: iris.c:225
bool ED_autokeyframe_object(bContext *C, Scene *scene, Object *ob, KeyingSet *ks)
Definition: keyframing.c:3070
KeyingSet * ANIM_get_keyingset_for_autokeying(const Scene *scene, const char *transformKSName)
Definition: keyingsets.c:696
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
#define fabsf(x)
Definition: metal/compat.h:219
T midpoint(const T &a, const T &b)
vec_base< float, 3 > float3
vec_base< float, 2 > float2
MutableSpan< float3 > positions
static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_loc, bool apply_rot, bool apply_scale, bool do_props, bool do_single_user)
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 void object_clear_scale(Object *ob, const bool clear_delta)
static void ignore_parent_tx(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
void OBJECT_OT_parent_inverse_apply(wmOperatorType *ot)
static void object_transform_axis_target_calc_depth_init(XFormAxisData *xfd, const int mval[2])
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)
static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const wmEvent *event)
static Array< Object * > sorted_selected_editable_objects(bContext *C)
static bool apply_objects_internal_can_multiuser(bContext *C)
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)
static bool apply_objects_internal_need_single_user(bContext *C)
void OBJECT_OT_visual_transform_apply(wmOperatorType *ot)
@ ORIGIN_TO_GEOMETRY
@ GEOMETRY_TO_ORIGIN
@ ORIGIN_TO_CURSOR
@ ORIGIN_TO_CENTER_OF_MASS_VOLUME
@ ORIGIN_TO_CENTER_OF_MASS_SURFACE
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 object_parent_inverse_apply_exec(bContext *C, wmOperator *UNUSED(op))
static int object_transform_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
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:5271
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
Definition: rna_access.c:3421
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2153
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
Definition: rna_access.c:2180
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3402
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
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:3783
#define min(a, b)
Definition: sort.c:35
struct BMesh * bm
Definition: BKE_editmesh.h:40
float co[3]
Definition: bmesh_class.h:87
int totvert
Definition: bmesh_class.h:297
float vec[3][3]
float xof
struct TextBox * tb
struct Key * key
float fsize
float yof
CurvesGeometry geometry
Definition: DNA_ID.h:368
int tag
Definition: DNA_ID.h:387
char name[66]
Definition: DNA_ID.h:378
float area_sizez
float area_sizey
short area_shape
float area_size
short type
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase objects
Definition: BKE_main.h:170
struct BMEditMesh * edit_mesh
struct MovieTracking tracking
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]
float drotAxis[3]
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 ToolSettings * toolsettings
View3DCursor cursor
char transform_pivot_point
struct Depsgraph * depsgraph
Definition: ED_view3d.h:64
int mval[2]
Definition: ED_view3d.h:74
struct ARegion * region
Definition: ED_view3d.h:69
struct Object * obact
Definition: ED_view3d.h:67
struct View3D * v3d
Definition: ED_view3d.h:70
unsigned short w
Definition: ED_view3d.h:78
double depth_range[2]
Definition: ED_view3d.h:81
unsigned short h
Definition: ED_view3d.h:78
struct XFormAxisData::@499 prev
ViewDepths * depths
Vector< XFormAxisItem > object_data
float xform_rot_offset[3][3]
float rot_mat[3][3]
ListBase layers
short val
Definition: WM_types.h:680
int mval[2]
Definition: WM_types.h:684
short type
Definition: WM_types.h:678
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
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)
#define ISMOUSE_BUTTON(event_type)
@ RIGHTMOUSE
@ EVT_PADENTER
@ MOUSEMOVE
@ LEFTMOUSE
@ EVT_ESCKEY
@ EVT_RETKEY
wmOperatorType * ot
Definition: wm_files.c:3479
int WM_operator_confirm_message(bContext *C, wmOperator *op, const char *message)
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))