Blender  V3.3
object_utils.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <stdlib.h>
8 #include <string.h>
9 
10 #include "DNA_anim_types.h"
11 #include "DNA_armature_types.h"
12 #include "DNA_collection_types.h"
13 #include "DNA_meta_types.h"
14 #include "DNA_object_types.h"
15 #include "DNA_scene_types.h"
16 
17 #include "BLI_listbase.h"
18 #include "BLI_math.h"
19 #include "BLI_utildefines.h"
20 
21 #include "BKE_action.h"
22 #include "BKE_armature.h"
23 #include "BKE_editmesh.h"
24 #include "BKE_lattice.h"
25 #include "BKE_object.h"
26 #include "BKE_scene.h"
27 
28 #include "DEG_depsgraph_query.h"
29 
30 #include "WM_types.h"
31 
32 #include "ED_curve.h"
33 #include "ED_object.h" /* own include */
34 
35 #include "MEM_guardedalloc.h"
36 
37 /* -------------------------------------------------------------------- */
42  const bool select_only,
43  float r_center[3])
44 {
45  switch (obedit->type) {
46  case OB_MESH: {
48  BMEditSelection ese;
49 
50  if (BM_select_history_active_get(em->bm, &ese)) {
51  BM_editselection_center(&ese, r_center);
52  return true;
53  }
54  break;
55  }
56  case OB_ARMATURE: {
57  bArmature *arm = obedit->data;
58  EditBone *ebo = arm->act_edbone;
59 
60  if (ebo && (!select_only || (ebo->flag & (BONE_SELECTED | BONE_ROOTSEL)))) {
61  copy_v3_v3(r_center, ebo->head);
62  return true;
63  }
64 
65  break;
66  }
67  case OB_CURVES_LEGACY:
68  case OB_SURF: {
69  Curve *cu = obedit->data;
70 
71  if (ED_curve_active_center(cu, r_center)) {
72  return true;
73  }
74  break;
75  }
76  case OB_MBALL: {
77  MetaBall *mb = obedit->data;
78  MetaElem *ml_act = mb->lastelem;
79 
80  if (ml_act && (!select_only || (ml_act->flag & SELECT))) {
81  copy_v3_v3(r_center, &ml_act->x);
82  return true;
83  }
84  break;
85  }
86  case OB_LATTICE: {
87  BPoint *actbp = BKE_lattice_active_point_get(obedit->data);
88 
89  if (actbp) {
90  copy_v3_v3(r_center, actbp->vec);
91  return true;
92  }
93  break;
94  }
95  }
96 
97  return false;
98 }
99 
101  const bool select_only,
102  float r_center[3])
103 {
105  if (pchan && (!select_only || (pchan->bone->flag & BONE_SELECTED))) {
106  copy_v3_v3(r_center, pchan->pose_head);
107  return true;
108  }
109  return false;
110 }
111 
112 bool ED_object_calc_active_center(Object *ob, const bool select_only, float r_center[3])
113 {
114  if (ob->mode & OB_MODE_EDIT) {
115  if (ED_object_calc_active_center_for_editmode(ob, select_only, r_center)) {
116  mul_m4_v3(ob->obmat, r_center);
117  return true;
118  }
119  return false;
120  }
121  if (ob->mode & OB_MODE_POSE) {
122  if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) {
123  mul_m4_v3(ob->obmat, r_center);
124  return true;
125  }
126  return false;
127  }
128  if (!select_only || (ob->base_flag & BASE_SELECTED)) {
129  copy_v3_v3(r_center, ob->obmat[3]);
130  return true;
131  }
132  return false;
133 }
134 
137 /* -------------------------------------------------------------------- */
149 };
150 
152  float obmat_orig[4][4];
153  float parent_obmat_orig[4][4];
156  float parentinv_orig[4][4];
158  int mode;
159 };
160 
162 {
163  struct XFormObjectSkipChild_Container *xcs = MEM_callocN(sizeof(*xcs), __func__);
164  if (xcs->obchild_in_obmode_map == NULL) {
165  xcs->obchild_in_obmode_map = BLI_ghash_ptr_new(__func__);
166  }
167  return xcs;
168 }
169 
171  struct XFormObjectSkipChild_Container *xcs,
172  ViewLayer *view_layer,
173  Object **objects,
174  uint objects_len)
175 {
176  GSet *objects_in_transdata = BLI_gset_ptr_new_ex(__func__, objects_len);
177  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
178  Object *ob = objects[ob_index];
179  BLI_gset_add(objects_in_transdata, ob);
180  }
181 
182  LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
183  Object *ob = base->object;
184  if (ob->parent != NULL) {
185  if (!BLI_gset_haskey(objects_in_transdata, ob)) {
186  if (BLI_gset_haskey(objects_in_transdata, ob->parent)) {
189  }
190  }
191  else {
192  if (!BLI_gset_haskey(objects_in_transdata, ob->parent)) {
193  Object *ob_parent_recurse = ob->parent;
194  if (ob_parent_recurse != NULL) {
195  while (ob_parent_recurse != NULL) {
196  if (BLI_gset_haskey(objects_in_transdata, ob_parent_recurse)) {
197  break;
198  }
199  ob_parent_recurse = ob_parent_recurse->parent;
200  }
201 
202  if (ob_parent_recurse) {
204  xcs, ob, ob_parent_recurse, XFORM_OB_SKIP_CHILD_PARENT_APPLY);
205  }
206  }
207  }
208  }
209  }
210  }
211 
212  LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
213  Object *ob = base->object;
214 
215  if (BLI_gset_haskey(objects_in_transdata, ob)) {
216  /* pass. */
217  }
218  else if (ob->parent != NULL) {
219  if (BLI_gset_haskey(objects_in_transdata, ob->parent)) {
220  if (!BLI_gset_haskey(objects_in_transdata, ob)) {
223  }
224  }
225  }
226  }
227  BLI_gset_free(objects_in_transdata, NULL);
228 }
229 
231 {
233  MEM_freeN(xcs);
234 }
235 
237  Object *ob,
238  Object *ob_parent_recurse,
239  int mode)
240 {
241  void **xf_p;
242  if (!BLI_ghash_ensure_p(xcs->obchild_in_obmode_map, ob, &xf_p)) {
243  struct XFormObjectSkipChild *xf = MEM_mallocN(sizeof(*xf), __func__);
245  copy_m4_m4(xf->obmat_orig, ob->obmat);
248  if (ob_parent_recurse) {
250  }
251  xf->mode = mode;
253  *xf_p = xf;
254  }
255 }
256 
258  struct Main *bmain,
259  struct Depsgraph *depsgraph)
260 {
262 
263  GHashIterator gh_iter;
264  GHASH_ITER (gh_iter, xcs->obchild_in_obmode_map) {
265  Object *ob = BLI_ghashIterator_getKey(&gh_iter);
266  struct XFormObjectSkipChild *xf = BLI_ghashIterator_getValue(&gh_iter);
267 
268  /* The following blocks below assign 'dmat'. */
269  float dmat[4][4];
270 
272  /* Parent is transformed, this isn't so compensate. */
273  Object *ob_parent_eval = DEG_get_evaluated_object(depsgraph, ob->parent);
274  mul_m4_m4m4(dmat, xf->parent_obmat_inv_orig, ob_parent_eval->obmat);
275  invert_m4(dmat);
276  }
278  /* Calculate parent matrix (from the root transform). */
279  Object *ob_parent_recurse_eval = DEG_get_evaluated_object(depsgraph, xf->ob_parent_recurse);
280  float parent_recurse_obmat_inv[4][4];
281  invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->obmat);
282  mul_m4_m4m4(dmat, xf->parent_recurse_obmat_orig, parent_recurse_obmat_inv);
283  invert_m4(dmat);
284  float parent_obmat_calc[4][4];
285  mul_m4_m4m4(parent_obmat_calc, dmat, xf->parent_obmat_orig);
286 
287  /* Apply to the parent inverse matrix. */
288  mul_m4_m4m4(dmat, xf->parent_obmat_inv_orig, parent_obmat_calc);
289  invert_m4(dmat);
290  }
291  else {
293  /* Transform this - without transform data. */
294  Object *ob_parent_recurse_eval = DEG_get_evaluated_object(depsgraph, xf->ob_parent_recurse);
295  float parent_recurse_obmat_inv[4][4];
296  invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->obmat);
297  mul_m4_m4m4(dmat, xf->parent_recurse_obmat_orig, parent_recurse_obmat_inv);
298  invert_m4(dmat);
299  float obmat_calc[4][4];
300  mul_m4_m4m4(obmat_calc, dmat, xf->obmat_orig);
301  /* obmat_calc is just obmat. */
302 
303  /* Get the matrices relative to the parent. */
304  float obmat_parent_relative_orig[4][4];
305  float obmat_parent_relative_calc[4][4];
306  float obmat_parent_relative_inv_orig[4][4];
307 
308  mul_m4_m4m4(obmat_parent_relative_orig, xf->parent_obmat_inv_orig, xf->obmat_orig);
309  mul_m4_m4m4(obmat_parent_relative_calc, xf->parent_obmat_inv_orig, obmat_calc);
310  invert_m4_m4(obmat_parent_relative_inv_orig, obmat_parent_relative_orig);
311 
312  /* Apply to the parent inverse matrix. */
313  mul_m4_m4m4(dmat, obmat_parent_relative_calc, obmat_parent_relative_inv_orig);
314  }
315 
316  mul_m4_m4m4(ob->parentinv, dmat, xf->parentinv_orig);
317 
319  }
320 }
321 
324 /* -------------------------------------------------------------------- */
333 };
334 
337  float obmat_orig[4][4];
339 };
340 
342 {
343  if (xds->obdata_in_obmode_map == NULL) {
344  xds->obdata_in_obmode_map = BLI_ghash_ptr_new(__func__);
345  }
346 
347  void **xf_p;
348  if (!BLI_ghash_ensure_p(xds->obdata_in_obmode_map, ob->data, &xf_p)) {
349  struct XFormObjectData_Extra *xf = MEM_mallocN(sizeof(*xf), __func__);
350  copy_m4_m4(xf->obmat_orig, ob->obmat);
351  xf->ob = ob;
352  /* Result may be NULL, that's OK. */
354  *xf_p = xf;
355  }
356 }
357 
359  struct Main *bmain,
361 {
362  if (xds->obdata_in_obmode_map == NULL) {
363  return;
364  }
366 
367  GHashIterator gh_iter;
368  GHASH_ITER (gh_iter, xds->obdata_in_obmode_map) {
369  ID *id = BLI_ghashIterator_getKey(&gh_iter);
370  struct XFormObjectData_Extra *xf = BLI_ghashIterator_getValue(&gh_iter);
371  if (xf->xod == NULL) {
372  continue;
373  }
374 
375  Object *ob_eval = DEG_get_evaluated_object(depsgraph, xf->ob);
376  float imat[4][4], dmat[4][4];
377  invert_m4_m4(imat, xf->obmat_orig);
378  mul_m4_m4m4(dmat, imat, ob_eval->obmat);
379  invert_m4(dmat);
380 
382  if (xf->ob->type == OB_ARMATURE) {
383  /* TODO: none of the current flags properly update armatures, needs investigation. */
384  DEG_id_tag_update(id, 0);
385  }
386  else {
388  }
389  }
390 }
391 
393 static void trans_obdata_in_obmode_free_elem(void *xf_p)
394 {
395  struct XFormObjectData_Extra *xf = xf_p;
396  if (xf->xod) {
398  }
399  MEM_freeN(xf);
400 }
401 
403 {
404  struct XFormObjectData_Container *xds = MEM_callocN(sizeof(*xds), __func__);
405  xds->obdata_in_obmode_map = BLI_ghash_ptr_new(__func__);
406  return xds;
407 }
408 
410 {
412  MEM_freeN(xds);
413 }
414 
417 /* -------------------------------------------------------------------- */
424 static bool object_parent_in_set(GSet *objects_set, Object *ob)
425 {
426  for (Object *parent = ob->parent; parent; parent = parent->parent) {
427  if (BLI_gset_lookup(objects_set, parent)) {
428  return true;
429  }
430  }
431  return false;
432 }
433 
434 void ED_object_xform_array_m4(Object **objects, uint objects_len, const float matrix[4][4])
435 {
436  /* Filter out objects that have parents in `objects_set`. */
437  {
438  GSet *objects_set = BLI_gset_ptr_new_ex(__func__, objects_len);
439  for (uint i = 0; i < objects_len; i++) {
440  BLI_gset_add(objects_set, objects[i]);
441  }
442  for (uint i = 0; i < objects_len;) {
443  if (object_parent_in_set(objects_set, objects[i])) {
444  objects[i] = objects[--objects_len];
445  }
446  else {
447  i++;
448  }
449  }
450  BLI_gset_free(objects_set, NULL);
451  }
452 
453  /* Detect translation only matrix, prevent rotation/scale channels from being touched at all. */
454  bool is_translation_only;
455  {
456  float test_m4_a[4][4], test_m4_b[4][4];
457  unit_m4(test_m4_a);
458  copy_m4_m4(test_m4_b, matrix);
459  zero_v3(test_m4_b[3]);
460  is_translation_only = equals_m4m4(test_m4_a, test_m4_b);
461  }
462 
463  if (is_translation_only) {
464  for (uint i = 0; i < objects_len; i++) {
465  Object *ob = objects[i];
466  add_v3_v3(ob->loc, matrix[3]);
468  }
469  }
470  else {
471  for (uint i = 0; i < objects_len; i++) {
472  float m4[4][4];
473  Object *ob = objects[i];
474  BKE_object_to_mat4(ob, m4);
475  mul_m4_m4m4(m4, matrix, m4);
476  BKE_object_apply_mat4(ob, m4, true, true);
478  }
479  }
480 }
481 
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_active_if_layer_visible(struct Object *ob)
Definition: action.c:720
BMEditMesh * BKE_editmesh_from_object(struct Object *ob)
Return the BMEditMesh for a given object.
Definition: editmesh.c:58
struct BPoint * BKE_lattice_active_point_get(struct Lattice *lt)
Definition: lattice.c:597
General operations, lookup, etc. for blender objects.
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_scene_graph_evaluated_ensure(struct Depsgraph *depsgraph, struct Main *bmain)
Definition: scene.cc:2653
#define BLI_assert(a)
Definition: BLI_assert.h:46
struct GSet GSet
Definition: BLI_ghash.h:340
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:298
bool BLI_gset_haskey(const GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:1007
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:302
#define GHASH_ITER(gh_iter_, ghash_)
Definition: BLI_ghash.h:321
void * BLI_gset_lookup(const GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:1061
GSet * BLI_gset_ptr_new_ex(const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:863
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1037
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:755
bool BLI_gset_add(GSet *gs, void *key)
Definition: BLI_ghash.c:969
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
bool invert_m4(float R[4][4])
Definition: math_matrix.c:1206
void unit_m4(float m[4][4])
Definition: rct.c:1090
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
bool equals_m4m4(const float mat1[4][4], const float mat2[4][4])
Definition: math_matrix.c:2531
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
MINLINE void copy_v3_v3(float r[3], const float a[3])
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
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
void DEG_id_tag_update(struct ID *id, int flag)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:771
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ BONE_ROOTSEL
@ BONE_SELECTED
Object groups, one object can be in many groups at once.
@ BASE_SELECTED
@ OB_MODE_EDIT
@ OB_MODE_POSE
Object is a sort of wrapper for general info.
@ OB_LATTICE
@ OB_MBALL
@ OB_SURF
@ OB_ARMATURE
@ OB_MESH
@ OB_CURVES_LEGACY
void ED_object_data_xform_destroy(struct XFormObjectData *xod_base)
void ED_object_data_xform_by_mat4(struct XFormObjectData *xod, const float mat[4][4])
@ XFORM_OB_SKIP_CHILD_PARENT_APPLY
Definition: ED_object.h:109
@ XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM_INDIRECT
Definition: ED_object.h:102
@ XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM
Definition: ED_object.h:97
struct XFormObjectData * ED_object_data_xform_create(struct ID *id)
Read Guarded memory(de)allocation.
void BM_editselection_center(BMEditSelection *ese, float r_center[3])
bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
#define SELECT
const Depsgraph * depsgraph
bool ED_curve_active_center(Curve *cu, float center[3])
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
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_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
void ED_object_xform_array_m4(Object **objects, uint objects_len, const float matrix[4][4])
Definition: object_utils.c:434
void ED_object_data_xform_container_update_all(struct XFormObjectData_Container *xds, struct Main *bmain, Depsgraph *depsgraph)
Definition: object_utils.c:358
static void trans_obdata_in_obmode_free_elem(void *xf_p)
Definition: object_utils.c:393
bool ED_object_calc_active_center(Object *ob, const bool select_only, float r_center[3])
Definition: object_utils.c:112
void ED_object_data_xform_container_destroy(struct XFormObjectData_Container *xds)
Definition: object_utils.c:409
bool ED_object_calc_active_center_for_editmode(Object *obedit, const bool select_only, float r_center[3])
Definition: object_utils.c:41
void ED_object_xform_skip_child_container_item_ensure(struct XFormObjectSkipChild_Container *xcs, Object *ob, Object *ob_parent_recurse, int mode)
Definition: object_utils.c:236
static bool object_parent_in_set(GSet *objects_set, Object *ob)
Definition: object_utils.c:424
void ED_object_data_xform_container_item_ensure(struct XFormObjectData_Container *xds, Object *ob)
Definition: object_utils.c:341
bool ED_object_calc_active_center_for_posemode(Object *ob, const bool select_only, float r_center[3])
Definition: object_utils.c:100
void ED_object_xform_skip_child_container_item_ensure_from_array(struct XFormObjectSkipChild_Container *xcs, ViewLayer *view_layer, Object **objects, uint objects_len)
Definition: object_utils.c:170
struct XFormObjectData_Container * ED_object_data_xform_container_create(void)
Definition: object_utils.c:402
struct BMesh * bm
Definition: BKE_editmesh.h:40
float vec[4]
float head[3]
Definition: BKE_armature.h:53
Definition: DNA_ID.h:368
Definition: BKE_main.h:121
MetaElem * lastelem
short flag
short base_flag
float loc[3]
float parentinv[4][4]
float obmat[4][4]
struct Object * parent
void * data
ListBase object_bases
struct XFormObjectData * xod
Definition: object_utils.c:338
float obmat_orig[4][4]
Definition: object_utils.c:337
float obmat_orig[4][4]
Definition: object_utils.c:152
float parent_obmat_inv_orig[4][4]
Definition: object_utils.c:154
Object * ob_parent_recurse
Definition: object_utils.c:157
float parent_obmat_orig[4][4]
Definition: object_utils.c:153
float parent_recurse_obmat_orig[4][4]
Definition: object_utils.c:155
float parentinv_orig[4][4]
Definition: object_utils.c:156
struct EditBone * act_edbone
struct Bone * bone
float pose_head[3]