Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2019-08-22 06:45:31 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-08-24 00:34:43 +0300
commitacdb14d264c8b4eced645673f8ae8af1a96b1a90 (patch)
tree0be0b3490fe79105892e309be48f608e6ed19fc5 /source/blender/editors/transform/transform_conversions.c
parent71c43e92257c671065125330f93ed4d03b2b8250 (diff)
Transform: option to transform origins in object mode
Currently supports mesh, armature, lattice, curve & metaballs. Access from pivot popover.
Diffstat (limited to 'source/blender/editors/transform/transform_conversions.c')
-rw-r--r--source/blender/editors/transform/transform_conversions.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 2684b6e279d..4fe79dc3202 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -7678,6 +7678,90 @@ int special_transform_moving(TransInfo *t)
return 0;
}
+/* -------------------------------------------------------------------- */
+/** \name Object Data in Object Mode
+ *
+ * Use to implement 'Affect Only Origins' feature.
+ * We need this to be detached from transform data because,
+ * unlike transforming regular objects, we need to transform the children.
+ *
+ * \{ */
+
+struct XFormObjectData_Extra {
+ Object *ob;
+ float obmat_orig[4][4];
+ bool ob_dtx_axis_orig;
+ struct XFormObjectData *xod;
+};
+
+static void trans_obdata_in_obmode_ensure_object(TransInfo *t, Object *ob)
+{
+ if (t->obdata_in_obmode_map == NULL) {
+ t->obdata_in_obmode_map = BLI_ghash_ptr_new(__func__);
+ }
+
+ void **xf_p;
+ if (!BLI_ghash_ensure_p(t->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);
+ if (xf->xod) {
+ xf->ob_dtx_axis_orig = ob->dtx & OB_AXIS;
+ ob->dtx |= OB_AXIS;
+ }
+ *xf_p = xf;
+ }
+}
+
+void trans_obdata_in_obmode_update_all(TransInfo *t)
+{
+ struct Main *bmain = CTX_data_main(t->context);
+ BKE_scene_graph_evaluated_ensure(t->depsgraph, bmain);
+
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, t->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);
+ DEG_id_tag_update(id, 0);
+ }
+}
+
+/** Callback for #GHash free. */
+static void trans_obdata_in_obmode_free_elem(void *xf_p)
+{
+ struct XFormObjectData_Extra *xf = xf_p;
+ if (xf->xod) {
+ if (!xf->ob_dtx_axis_orig) {
+ xf->ob->dtx &= ~OB_AXIS;
+ DEG_id_tag_update(&xf->ob->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ ED_object_data_xform_destroy(xf->xod);
+ }
+ MEM_freeN(xf);
+}
+
+void trans_obdata_in_obmode_free_all(TransInfo *t)
+{
+ if (t->obdata_in_obmode_map != NULL) {
+ BLI_ghash_free(t->obdata_in_obmode_map, NULL, trans_obdata_in_obmode_free_elem);
+ }
+}
+
+/** \} */
+
static void createTransObject(bContext *C, TransInfo *t)
{
TransData *td = NULL;
@@ -7722,6 +7806,24 @@ static void createTransObject(bContext *C, TransInfo *t)
td->flag |= TD_SKIP;
}
+ if (t->flag & T_OBJECT_DATA_IN_OBJECT_MODE) {
+ ID *id = ob->data;
+ if (!id || id->lib) {
+ td->flag |= TD_SKIP;
+ }
+ else if (BKE_object_is_in_editmode(ob)) {
+ /* The object could have edit-mode data from another view-layer,
+ * it's such a corner-case it can be skipped for now - Campbell. */
+ td->flag |= TD_SKIP;
+ }
+ }
+
+ if (t->flag & T_OBJECT_DATA_IN_OBJECT_MODE) {
+ if ((td->flag & TD_SKIP) == 0) {
+ trans_obdata_in_obmode_ensure_object(t, ob);
+ }
+ }
+
ObjectToTransData(t, td, ob);
td->val = NULL;
td++;
@@ -7753,6 +7855,47 @@ static void createTransObject(bContext *C, TransInfo *t)
}
}
}
+
+ if (t->flag & T_OBJECT_DATA_IN_OBJECT_MODE) {
+ GSet *objects_in_transdata = BLI_gset_ptr_new_ex(__func__, tc->data_len);
+ td = tc->data;
+ for (int i = 0; i < tc->data_len; i++, td++) {
+ if ((td->flag & TD_SKIP) == 0) {
+ BLI_gset_add(objects_in_transdata, td->ob);
+ }
+ }
+
+ ViewLayer *view_layer = t->view_layer;
+ View3D *v3d = t->view;
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+
+ /* if base is not selected, not a parent of selection
+ * or not a child of selection and it is editable and selectable */
+ if ((base->flag & BASE_SELECTED) == 0 && BASE_EDITABLE(v3d, base) &&
+ BASE_SELECTABLE(v3d, base)) {
+
+ Object *ob_parent = ob->parent;
+ if (ob_parent != NULL) {
+ if (!BLI_gset_haskey(objects_in_transdata, ob)) {
+ bool parent_in_transdata = false;
+ while (ob_parent != NULL) {
+ if (BLI_gset_haskey(objects_in_transdata, ob_parent)) {
+ parent_in_transdata = true;
+ break;
+ }
+ ob_parent = ob_parent->parent;
+ }
+ if (parent_in_transdata) {
+ trans_obdata_in_obmode_ensure_object(t, ob);
+ }
+ }
+ }
+ }
+ }
+ BLI_gset_free(objects_in_transdata, NULL);
+ }
}
/* transcribe given node into TransData2D for Transforming */
@@ -9739,6 +9882,10 @@ void createTransData(bContext *C, TransInfo *t)
/* Needed for correct Object.obmat after duplication, see: T62135. */
BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context));
+ if ((scene->toolsettings->transform_flag & SCE_XFORM_DATA_ORIGIN) != 0) {
+ t->flag |= T_OBJECT_DATA_IN_OBJECT_MODE;
+ }
+
createTransObject(C, t);
countAndCleanTransDataContainer(t);
t->flag |= T_OBJECT;