From 6929d8aa5993d4a8616e52c9787f29baf1c9f955 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 21 Dec 2019 12:59:58 +1100 Subject: Object: extract data transform container into own API --- source/blender/editors/include/ED_object.h | 10 +++ .../blender/editors/object/object_data_transform.c | 99 ++++++++++++++++++++++ .../editors/transform/transform_convert_object.c | 84 +++--------------- 3 files changed, 120 insertions(+), 73 deletions(-) diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index a5f56689c95..d27eeb270ac 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -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 diff --git a/source/blender/editors/object/object_data_transform.c b/source/blender/editors/object/object_data_transform.c index 51d8fb8fd72..29b0cb88935 100644 --- a/source/blender/editors/object/object_data_transform.c +++ b/source/blender/editors/object/object_data_transform.c @@ -49,10 +49,12 @@ #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); +} + +/** \} */ diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c index 331a3eea59f..16dfdd35c32 100644 --- a/source/blender/editors/transform/transform_convert_object.c +++ b/source/blender/editors/transform/transform_convert_object.c @@ -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); } } } -- cgit v1.2.3