Object: extract data transform container into own API
authorCampbell Barton <ideasman42@gmail.com>
Sat, 21 Dec 2019 01:59:58 +0000 (12:59 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 22 Dec 2019 12:34:42 +0000 (23:34 +1100)
source/blender/editors/include/ED_object.h
source/blender/editors/object/object_data_transform.c
source/blender/editors/transform/transform_convert_object.c

index a5f56689c95757cb326dacf5d5c063430f546873..d27eeb270acad803937a0dfde379bc83d515f02d 100644 (file)
@@ -421,6 +421,16 @@ void ED_object_data_xform_by_mat4(struct XFormObjectData *xod, const float mat[4
 void ED_object_data_xform_restore(struct XFormObjectData *xod);
 void ED_object_data_xform_tag_update(struct XFormObjectData *xod);
 
+/* Container helper API. */
+struct XFormObjectData_Container;
+struct XFormObjectData_Container *ED_object_data_xform_container_create(void);
+void ED_object_data_xform_container_destroy(struct XFormObjectData_Container *xds);
+void ED_object_data_xform_container_update_all(struct XFormObjectData_Container *xds,
+                                               struct Main *bmain,
+                                               struct Depsgraph *depsgraph);
+void ED_object_data_xform_container_item_ensure(struct XFormObjectData_Container *xds,
+                                                struct Object *ob);
+
 #ifdef __cplusplus
 }
 #endif
index 51d8fb8fd725b2d57a41e416506a5d2cef5156c0..29b0cb889354d4f3401abc0b404cc293c6b20050 100644 (file)
 #include "BKE_mesh.h"
 #include "BKE_armature.h"
 #include "BKE_lattice.h"
+#include "BKE_scene.h"
 
 #include "bmesh.h"
 
 #include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
 
 #include "WM_types.h"
 
@@ -575,3 +577,100 @@ void ED_object_data_xform_tag_update(struct XFormObjectData *xod_base)
 }
 
 /** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Data Transform Container
+ *
+ * Use to implement 'Affect Only Origins' feature.
+ *
+ * \{ */
+
+struct XFormObjectData_Container {
+  GHash *obdata_in_obmode_map;
+};
+
+struct XFormObjectData_Extra {
+  Object *ob;
+  float obmat_orig[4][4];
+  struct XFormObjectData *xod;
+};
+
+void ED_object_data_xform_container_item_ensure(struct XFormObjectData_Container *xds, Object *ob)
+{
+  if (xds->obdata_in_obmode_map == NULL) {
+    xds->obdata_in_obmode_map = BLI_ghash_ptr_new(__func__);
+  }
+
+  void **xf_p;
+  if (!BLI_ghash_ensure_p(xds->obdata_in_obmode_map, ob->data, &xf_p)) {
+    struct XFormObjectData_Extra *xf = MEM_mallocN(sizeof(*xf), __func__);
+    copy_m4_m4(xf->obmat_orig, ob->obmat);
+    xf->ob = ob;
+    /* Result may be NULL, that's OK. */
+    xf->xod = ED_object_data_xform_create(ob->data);
+    *xf_p = xf;
+  }
+}
+
+/**
+ * This may be called multiple times with the same data.
+ * Each time, the original transformations are re-applied, instead of accumulating the changes.
+ */
+void ED_object_data_xform_container_update_all(struct XFormObjectData_Container *xds,
+                                               struct Main *bmain,
+                                               Depsgraph *depsgraph)
+{
+  if (xds->obdata_in_obmode_map == NULL) {
+    return;
+  }
+  BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
+
+  GHashIterator gh_iter;
+  GHASH_ITER (gh_iter, xds->obdata_in_obmode_map) {
+    ID *id = BLI_ghashIterator_getKey(&gh_iter);
+    struct XFormObjectData_Extra *xf = BLI_ghashIterator_getValue(&gh_iter);
+    if (xf->xod == NULL) {
+      continue;
+    }
+
+    Object *ob_eval = DEG_get_evaluated_object(depsgraph, xf->ob);
+    float imat[4][4], dmat[4][4];
+    invert_m4_m4(imat, xf->obmat_orig);
+    mul_m4_m4m4(dmat, imat, ob_eval->obmat);
+    invert_m4(dmat);
+
+    ED_object_data_xform_by_mat4(xf->xod, dmat);
+    if (xf->ob->type == OB_ARMATURE) {
+      /* TODO: none of the current flags properly update armatures, needs investigation. */
+      DEG_id_tag_update(id, 0);
+    }
+    else {
+      DEG_id_tag_update(id, ID_RECALC_GEOMETRY);
+    }
+  }
+}
+
+/** Callback for #GHash free. */
+static void trans_obdata_in_obmode_free_elem(void *xf_p)
+{
+  struct XFormObjectData_Extra *xf = xf_p;
+  if (xf->xod) {
+    ED_object_data_xform_destroy(xf->xod);
+  }
+  MEM_freeN(xf);
+}
+
+struct XFormObjectData_Container *ED_object_data_xform_container_create(void)
+{
+  struct XFormObjectData_Container *xds = MEM_callocN(sizeof(*xds), __func__);
+  xds->obdata_in_obmode_map = BLI_ghash_ptr_new(__func__);
+  return xds;
+}
+
+void ED_object_data_xform_container_destroy(struct XFormObjectData_Container *xds)
+{
+  BLI_ghash_free(xds->obdata_in_obmode_map, NULL, trans_obdata_in_obmode_free_elem);
+  MEM_freeN(xds);
+}
+
+/** \} */
index 331a3eea59f2a337c48c3beac37da82ac67019dc..16dfdd35c322fde4bafa5ba3cfca2de5c6fcffa9 100644 (file)
@@ -55,10 +55,8 @@ typedef struct TransDataObject {
    * Object to object data transform table.
    * Don't add these to transform data because we may want to include child objects
    * which aren't being transformed.
-   * - The key is object data #ID.
-   * - The value is #XFormObjectData_Extra.
    */
-  struct GHash *obdata_in_obmode_map;
+  struct XFormObjectData_Container *xds;
 
   /**
    * Transform
@@ -69,7 +67,6 @@ typedef struct TransDataObject {
 
 } TransDataObject;
 
-static void trans_obdata_in_obmode_free_all(TransDataObject *tdo);
 static void trans_obchild_in_obmode_free_all(TransDataObject *tdo);
 
 static void freeTransObjectCustomData(TransInfo *t,
@@ -80,7 +77,7 @@ static void freeTransObjectCustomData(TransInfo *t,
   custom_data->data = NULL;
 
   if (t->options & CTX_OBMODE_XFORM_OBDATA) {
-    trans_obdata_in_obmode_free_all(tdo);
+    ED_object_data_xform_container_destroy(tdo->xds);
   }
 
   if (t->options & CTX_OBMODE_XFORM_SKIP_CHILDREN) {
@@ -98,81 +95,18 @@ static void freeTransObjectCustomData(TransInfo *t,
  * We need this to be detached from transform data because,
  * unlike transforming regular objects, we need to transform the children.
  *
+ * Nearly all of the logic here is in the 'ED_object_data_xform_container_*' API.
  * \{ */
 
-struct XFormObjectData_Extra {
-  Object *ob;
-  float obmat_orig[4][4];
-  struct XFormObjectData *xod;
-};
-
-static void trans_obdata_in_obmode_ensure_object(TransDataObject *tdo, Object *ob)
-{
-  if (tdo->obdata_in_obmode_map == NULL) {
-    tdo->obdata_in_obmode_map = BLI_ghash_ptr_new(__func__);
-  }
-
-  void **xf_p;
-  if (!BLI_ghash_ensure_p(tdo->obdata_in_obmode_map, ob->data, &xf_p)) {
-    struct XFormObjectData_Extra *xf = MEM_mallocN(sizeof(*xf), __func__);
-    copy_m4_m4(xf->obmat_orig, ob->obmat);
-    xf->ob = ob;
-    /* Result may be NULL, that's OK. */
-    xf->xod = ED_object_data_xform_create(ob->data);
-    *xf_p = xf;
-  }
-}
-
 void trans_obdata_in_obmode_update_all(TransInfo *t)
 {
   TransDataObject *tdo = t->custom.type.data;
-  if (tdo->obdata_in_obmode_map == NULL) {
+  if (tdo->xds == NULL) {
     return;
   }
 
   struct Main *bmain = CTX_data_main(t->context);
-  BKE_scene_graph_evaluated_ensure(t->depsgraph, bmain);
-
-  GHashIterator gh_iter;
-  GHASH_ITER (gh_iter, tdo->obdata_in_obmode_map) {
-    ID *id = BLI_ghashIterator_getKey(&gh_iter);
-    struct XFormObjectData_Extra *xf = BLI_ghashIterator_getValue(&gh_iter);
-    if (xf->xod == NULL) {
-      continue;
-    }
-
-    Object *ob_eval = DEG_get_evaluated_object(t->depsgraph, xf->ob);
-    float imat[4][4], dmat[4][4];
-    invert_m4_m4(imat, xf->obmat_orig);
-    mul_m4_m4m4(dmat, imat, ob_eval->obmat);
-    invert_m4(dmat);
-
-    ED_object_data_xform_by_mat4(xf->xod, dmat);
-    if (xf->ob->type == OB_ARMATURE) {
-      /* TODO: none of the current flags properly update armatures, needs investigation. */
-      DEG_id_tag_update(id, 0);
-    }
-    else {
-      DEG_id_tag_update(id, ID_RECALC_GEOMETRY);
-    }
-  }
-}
-
-/** Callback for #GHash free. */
-static void trans_obdata_in_obmode_free_elem(void *xf_p)
-{
-  struct XFormObjectData_Extra *xf = xf_p;
-  if (xf->xod) {
-    ED_object_data_xform_destroy(xf->xod);
-  }
-  MEM_freeN(xf);
-}
-
-static void trans_obdata_in_obmode_free_all(TransDataObject *tdo)
-{
-  if (tdo->obdata_in_obmode_map != NULL) {
-    BLI_ghash_free(tdo->obdata_in_obmode_map, NULL, trans_obdata_in_obmode_free_elem);
-  }
+  ED_object_data_xform_container_update_all(tdo->xds, bmain, t->depsgraph);
 }
 
 /** \} */
@@ -697,6 +631,10 @@ void createTransObject(bContext *C, TransInfo *t)
   t->custom.type.data = tdo;
   t->custom.type.free_cb = freeTransObjectCustomData;
 
+  if (t->options & CTX_OBMODE_XFORM_OBDATA) {
+    tdo->xds = ED_object_data_xform_container_create();
+  }
+
   CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
     Object *ob = base->object;
 
@@ -729,7 +667,7 @@ void createTransObject(bContext *C, TransInfo *t)
 
     if (t->options & CTX_OBMODE_XFORM_OBDATA) {
       if ((td->flag & TD_SKIP) == 0) {
-        trans_obdata_in_obmode_ensure_object(tdo, ob);
+        ED_object_data_xform_container_item_ensure(tdo->xds, ob);
       }
     }
 
@@ -797,7 +735,7 @@ void createTransObject(bContext *C, TransInfo *t)
               ob_parent = ob_parent->parent;
             }
             if (parent_in_transdata) {
-              trans_obdata_in_obmode_ensure_object(tdo, ob);
+              ED_object_data_xform_container_item_ensure(tdo->xds, ob);
             }
           }
         }