Transform: option to transform origins in object mode

Currently supports mesh, armature, lattice, curve & metaballs.

Access from pivot popover.
This commit is contained in:
Campbell Barton 2019-08-22 13:45:31 +10:00
parent 71c43e9225
commit acdb14d264
Notes: blender-bot 2023-02-14 01:06:38 +01:00
Referenced by issue #69003, Transform object origins (adjusting origins, not the data)
17 changed files with 613 additions and 7 deletions

View File

@ -5890,7 +5890,9 @@ class VIEW3D_PT_pivot_point(Panel):
if (obj is None) or (mode in {'OBJECT', 'POSE', 'WEIGHT_PAINT'}):
col.separator()
col.prop(tool_settings, "use_transform_pivot_point_align")
col.label(text="Affect Only")
col.prop(tool_settings, "use_transform_data_origin", text="Origins")
col.prop(tool_settings, "use_transform_pivot_point_align", text="Locations")
class VIEW3D_PT_snapping(Panel):

View File

@ -127,7 +127,14 @@ void BKE_curve_nurb_vert_active_validate(struct Curve *cu);
float (*BKE_curve_nurbs_vert_coords_alloc(struct ListBase *lb, int *r_vert_len))[3];
void BKE_curve_nurbs_vert_coords_get(struct ListBase *lb, float (*vert_coords)[3], int vert_len);
void BKE_curve_nurbs_vert_coords_apply(struct ListBase *lb, const float (*vert_coords)[3]);
void BKE_curve_nurbs_vert_coords_apply_with_mat4(struct ListBase *lb,
const float (*vert_coords)[3],
const float mat[4][4],
const bool constrain_2d);
void BKE_curve_nurbs_vert_coords_apply(struct ListBase *lb,
const float (*vert_coords)[3],
const bool constrain_2d);
float (*BKE_curve_nurbs_key_vert_coords_alloc(struct ListBase *lb,
float *key,

View File

@ -90,6 +90,9 @@ void armature_deform_verts(struct Object *armOb,
float (*BKE_lattice_vert_coords_alloc(const struct Lattice *lt, int *r_vert_len))[3];
void BKE_lattice_vert_coords_get(const struct Lattice *lt, float (*vert_coords)[3]);
void BKE_lattice_vert_coords_apply_with_mat4(struct Lattice *lt,
const float (*vert_coords)[3],
const float mat[4][4]);
void BKE_lattice_vert_coords_apply(struct Lattice *lt, const float (*vert_coords)[3]);
void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph,
struct Scene *scene,

View File

@ -269,6 +269,9 @@ void BKE_mesh_count_selected_items(const struct Mesh *mesh, int r_count[3]);
float (*BKE_mesh_vert_coords_alloc(const struct Mesh *mesh, int *r_vert_len))[3];
void BKE_mesh_vert_coords_get(const struct Mesh *mesh, float (*vert_coords)[3]);
void BKE_mesh_vert_coords_apply_with_mat4(struct Mesh *mesh,
const float (*vert_coords)[3],
const float mat[4][4]);
void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float (*vert_coords)[3]);
void BKE_mesh_vert_normals_apply(struct Mesh *mesh, const short (*vertNormals)[3]);

View File

@ -4641,7 +4641,50 @@ float (*BKE_curve_nurbs_vert_coords_alloc(ListBase *lb, int *r_vert_len))[3]
return vert_coords;
}
void BKE_curve_nurbs_vert_coords_apply(ListBase *lb, const float (*vert_coords)[3])
void BKE_curve_nurbs_vert_coords_apply_with_mat4(ListBase *lb,
const float (*vert_coords)[3],
const float mat[4][4],
const bool constrain_2d)
{
const float *co = vert_coords[0];
Nurb *nu;
int i;
for (nu = lb->first; nu; nu = nu->next) {
if (nu->type == CU_BEZIER) {
BezTriple *bezt = nu->bezt;
for (i = 0; i < nu->pntsu; i++, bezt++) {
mul_v3_m4v3(bezt->vec[0], mat, co);
co += 3;
mul_v3_m4v3(bezt->vec[1], mat, co);
co += 3;
mul_v3_m4v3(bezt->vec[2], mat, co);
co += 3;
}
}
else {
BPoint *bp = nu->bp;
for (i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) {
mul_v3_m4v3(bp->vec, mat, co);
co += 3;
}
}
if (constrain_2d) {
if (nu->flag & CU_2D) {
BKE_nurb_test_2d(nu);
}
}
calchandlesNurb_intern(nu, true);
}
}
void BKE_curve_nurbs_vert_coords_apply(ListBase *lb,
const float (*vert_coords)[3],
const bool constrain_2d)
{
const float *co = vert_coords[0];
@ -4667,6 +4710,12 @@ void BKE_curve_nurbs_vert_coords_apply(ListBase *lb, const float (*vert_coords)[
}
}
if (constrain_2d) {
if (nu->flag & CU_2D) {
BKE_nurb_test_2d(nu);
}
}
calchandlesNurb_intern(nu, true);
}
}

View File

@ -920,7 +920,7 @@ static void curve_calc_modifiers_pre(
}
if (deformedVerts) {
BKE_curve_nurbs_vert_coords_apply(nurb, deformedVerts);
BKE_curve_nurbs_vert_coords_apply(nurb, deformedVerts, false);
MEM_freeN(deformedVerts);
}
if (keyVerts) { /* these are not passed through modifier stack */

View File

@ -1073,6 +1073,16 @@ float (*BKE_lattice_vert_coords_alloc(const Lattice *lt, int *r_vert_len))[3]
return vert_coords;
}
void BKE_lattice_vert_coords_apply_with_mat4(struct Lattice *lt,
const float (*vertexCos)[3],
const float mat[4][4])
{
int i, numVerts = lt->pntsu * lt->pntsv * lt->pntsw;
for (i = 0; i < numVerts; i++) {
mul_v3_m4v3(lt->def[i].vec, mat, vertexCos[i]);
}
}
void BKE_lattice_vert_coords_apply(Lattice *lt, const float (*vert_coords)[3])
{
const int vert_len = lt->pntsu * lt->pntsv * lt->pntsw;

View File

@ -1675,6 +1675,19 @@ void BKE_mesh_vert_coords_apply(Mesh *mesh, const float (*vert_coords)[3])
mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
}
void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh,
const float (*vert_coords)[3],
const float mat[4][4])
{
/* This will just return the pointer if it wasn't a referenced layer. */
MVert *mv = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert);
mesh->mvert = mv;
for (int i = 0; i < mesh->totvert; i++, mv++) {
mul_v3_m4v3(mv->co, mat, vert_coords[i]);
}
mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
}
void BKE_mesh_vert_normals_apply(Mesh *mesh, const short (*vert_normals)[3])
{
/* This will just return the pointer if it wasn't a referenced layer. */

View File

@ -44,6 +44,7 @@ struct Scene;
struct ShaderFxData;
struct View3D;
struct ViewLayer;
struct XFormObjectData;
struct bConstraint;
struct bContext;
struct bFaceMap;
@ -403,6 +404,12 @@ bool ED_object_jump_to_bone(struct bContext *C,
void ED_object_facemap_face_add(struct Object *ob, struct bFaceMap *fmap, int facenum);
void ED_object_facemap_face_remove(struct Object *ob, struct bFaceMap *fmap, int facenum);
/* object_data_transform.c */
struct XFormObjectData *ED_object_data_xform_create(struct ID *id);
void ED_object_data_xform_destroy(struct XFormObjectData *xod);
void ED_object_data_xform_by_mat4(struct XFormObjectData *xod, const float mat[4][4]);
#ifdef __cplusplus
}
#endif

View File

@ -48,6 +48,7 @@ set(SRC
object_collection.c
object_constraint.c
object_data_transfer.c
object_data_transform.c
object_edit.c
object_facemap_ops.c
object_gpencil_modifier.c

View File

@ -0,0 +1,333 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*/
/** \file
* \ingroup edobj
*
* Use to transform object origins only.
*
* This is a small API to store & apply transformations to object data,
* where a transformation matrix can be continually applied ontop of the original values
* so we don't loose precision over time.
*/
#include <stdlib.h>
#include <string.h>
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_collection_types.h"
#include "DNA_lattice_types.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BKE_curve.h"
#include "BKE_mball.h"
#include "BKE_mesh.h"
#include "BKE_armature.h"
#include "BKE_lattice.h"
#include "DEG_depsgraph.h"
#include "WM_types.h"
#include "ED_object.h"
#include "MEM_guardedalloc.h"
/* -------------------------------------------------------------------- */
/** \name Internal Transform Get/Apply
*
* Some object data types don't have utility functions to access their transformation data.
* Define these locally.
*
* \{ */
/* Armature */
struct ElemData_Armature {
float tail[3];
float head[3];
float roll;
float arm_tail[3];
float arm_head[3];
float arm_roll;
float rad_tail;
float rad_head;
float dist;
float xwidth;
float zwidth;
};
static struct ElemData_Armature *armature_coords_and_quats_get_recurse(
const ListBase *bone_base, struct ElemData_Armature *elem_array)
{
struct ElemData_Armature *elem = elem_array;
for (const Bone *bone = bone_base->first; bone; bone = bone->next) {
#define COPY_PTR(member) memcpy(elem->member, bone->member, sizeof(bone->member))
#define COPY_VAL(member) memcpy(&elem->member, &bone->member, sizeof(bone->member))
COPY_PTR(head);
COPY_PTR(tail);
COPY_VAL(roll);
COPY_PTR(arm_head);
COPY_PTR(arm_tail);
COPY_VAL(arm_roll);
COPY_VAL(rad_tail);
COPY_VAL(rad_head);
COPY_VAL(dist);
COPY_VAL(xwidth);
COPY_VAL(zwidth);
#undef COPY_PTR
#undef COPY_VAL
elem = armature_coords_and_quats_get_recurse(&bone->childbase, elem + 1);
}
return elem;
}
static void armature_coords_and_quats_get(const bArmature *arm,
struct ElemData_Armature *elem_array)
{
armature_coords_and_quats_get_recurse(&arm->bonebase, elem_array);
}
static const struct ElemData_Armature *armature_coords_and_quats_apply_with_mat4_recurse(
ListBase *bone_base, const struct ElemData_Armature *elem_array, const float mat[4][4])
{
const struct ElemData_Armature *elem = elem_array;
for (Bone *bone = bone_base->first; bone; bone = bone->next) {
#define COPY_PTR(member) memcpy(bone->member, elem->member, sizeof(bone->member))
#define COPY_VAL(member) memcpy(&bone->member, &elem->member, sizeof(bone->member))
COPY_PTR(head);
COPY_PTR(tail);
COPY_VAL(roll);
COPY_PTR(arm_head);
COPY_PTR(arm_tail);
COPY_VAL(arm_roll);
COPY_VAL(rad_tail);
COPY_VAL(rad_head);
COPY_VAL(dist);
COPY_VAL(xwidth);
COPY_VAL(zwidth);
#undef COPY_PTR
#undef COPY_VAL
elem = armature_coords_and_quats_apply_with_mat4_recurse(&bone->childbase, elem + 1, mat);
}
return elem;
}
static void armature_coords_and_quats_apply_with_mat4(bArmature *arm,
const struct ElemData_Armature *elem_array,
const float mat[4][4])
{
armature_coords_and_quats_apply_with_mat4_recurse(&arm->bonebase, elem_array, mat);
BKE_armature_transform(arm, mat, true);
}
/* MetaBall */
struct ElemData_MetaBall {
float co[3];
float quat[4];
float exp[3];
float rad;
};
static void metaball_coords_and_quats_get(const MetaBall *mb, struct ElemData_MetaBall *elem_array)
{
struct ElemData_MetaBall *elem = elem_array;
for (const MetaElem *ml = mb->elems.first; ml; ml = ml->next, elem++) {
copy_v3_v3(elem->co, &ml->x);
copy_qt_qt(elem->quat, ml->quat);
copy_v3_v3(elem->exp, &ml->expx);
elem->rad = ml->rad;
}
}
static void metaball_coords_and_quats_apply_with_mat4(MetaBall *mb,
const struct ElemData_MetaBall *elem_array,
const float mat[4][4])
{
const struct ElemData_MetaBall *elem = elem_array;
for (MetaElem *ml = mb->elems.first; ml; ml = ml->next, elem++) {
copy_v3_v3(&ml->x, elem->co);
copy_qt_qt(ml->quat, elem->quat);
copy_v3_v3(&ml->expx, elem->exp);
ml->rad = elem->rad;
}
BKE_mball_transform(mb, mat, true);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Public Object Data Storage API
*
* Used for interactively transforming object data.
*
* Store object data transformation in an opaque struct.
* \{ */
struct XFormObjectData {
ID *id;
};
struct XFormObjectData_Mesh {
struct XFormObjectData base;
float elem_array[0][3];
};
struct XFormObjectData_Lattice {
struct XFormObjectData base;
float elem_array[0][3];
};
struct XFormObjectData_Curve {
struct XFormObjectData base;
float elem_array[0][3];
};
struct XFormObjectData_Armature {
struct XFormObjectData base;
struct ElemData_Armature elem_array[0];
};
struct XFormObjectData_MetaBall {
struct XFormObjectData base;
struct ElemData_MetaBall elem_array[0];
};
struct XFormObjectData *ED_object_data_xform_create(ID *id)
{
struct XFormObjectData *xod_base = NULL;
switch (GS(id->name)) {
case ID_ME: {
Mesh *me = (Mesh *)id;
const int elem_array_len = me->totvert;
struct XFormObjectData_Mesh *xod = MEM_mallocN(
sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__);
BKE_mesh_vert_coords_get(me, xod->elem_array);
xod_base = &xod->base;
break;
}
case ID_LT: {
Lattice *lt = (Lattice *)id;
const int elem_array_len = lt->pntsu * lt->pntsv * lt->pntsw;
struct XFormObjectData_Lattice *xod = MEM_mallocN(
sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__);
BKE_lattice_vert_coords_get(lt, xod->elem_array);
xod_base = &xod->base;
break;
}
case ID_CU: {
Curve *cu = (Curve *)id;
const short ob_type = BKE_curve_type_get(cu);
if (ob_type == OB_FONT) {
/* We could support translation. */
break;
}
const int elem_array_len = BKE_nurbList_verts_count(&cu->nurb);
struct XFormObjectData_Curve *xod = MEM_mallocN(
sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__);
BKE_curve_nurbs_vert_coords_get(&cu->nurb, xod->elem_array, elem_array_len);
xod_base = &xod->base;
break;
}
case ID_AR: {
bArmature *arm = (bArmature *)id;
const int elem_array_len = BKE_armature_bonelist_count(&arm->bonebase);
struct XFormObjectData_Armature *xod = MEM_mallocN(
sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__);
armature_coords_and_quats_get(arm, xod->elem_array);
xod_base = &xod->base;
break;
}
case ID_MB: {
MetaBall *mb = (MetaBall *)id;
const int elem_array_len = BLI_listbase_count(&mb->elems);
struct XFormObjectData_MetaBall *xod = MEM_mallocN(
sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__);
metaball_coords_and_quats_get(mb, xod->elem_array);
xod_base = &xod->base;
break;
}
default: {
break;
}
}
if (xod_base) {
xod_base->id = id;
}
return xod_base;
}
void ED_object_data_xform_destroy(struct XFormObjectData *xod)
{
MEM_freeN(xod);
}
void ED_object_data_xform_by_mat4(struct XFormObjectData *xod_base, const float mat[4][4])
{
switch (GS(xod_base->id->name)) {
case ID_ME: {
Mesh *me = (Mesh *)xod_base->id;
struct XFormObjectData_Mesh *xod = (struct XFormObjectData_Mesh *)xod_base;
BKE_mesh_vert_coords_apply_with_mat4(me, xod->elem_array, mat);
break;
}
case ID_LT: {
Lattice *lt = (Lattice *)xod_base->id;
struct XFormObjectData_Lattice *xod = (struct XFormObjectData_Lattice *)xod_base;
BKE_lattice_vert_coords_apply_with_mat4(lt, xod->elem_array, mat);
break;
}
case ID_CU: {
Curve *cu = (Curve *)xod_base->id;
struct XFormObjectData_Curve *xod = (struct XFormObjectData_Curve *)xod_base;
BKE_curve_nurbs_vert_coords_apply_with_mat4(&cu->nurb, xod->elem_array, mat, true);
break;
}
case ID_AR: {
bArmature *arm = (bArmature *)xod_base->id;
struct XFormObjectData_Armature *xod = (struct XFormObjectData_Armature *)xod_base;
armature_coords_and_quats_apply_with_mat4(arm, xod->elem_array, mat);
break;
}
case ID_MB: {
MetaBall *mb = (MetaBall *)xod_base->id;
struct XFormObjectData_MetaBall *xod = (struct XFormObjectData_MetaBall *)xod_base;
metaball_coords_and_quats_apply_with_mat4(mb, xod->elem_array, mat);
break;
}
default: {
break;
}
}
}
/** \} */

View File

@ -716,7 +716,7 @@ static int modifier_apply_obdata(
vertexCos = BKE_curve_nurbs_vert_coords_alloc(&curve_eval->nurb, &numVerts);
mti->deformVerts(md_eval, &mectx, NULL, vertexCos, numVerts);
BKE_curve_nurbs_vert_coords_apply(&curve->nurb, vertexCos);
BKE_curve_nurbs_vert_coords_apply(&curve->nurb, vertexCos, false);
MEM_freeN(vertexCos);

View File

@ -723,6 +723,16 @@ typedef struct TransInfo {
/** Typically for mode settings. */
TransCustomDataContainer custom;
/**
* 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;
} TransInfo;
/* ******************** Macros & Prototypes *********************** */
@ -794,6 +804,10 @@ enum {
T_MODAL_CURSOR_SET = 1 << 26,
T_CLNOR_REBUILD = 1 << 27,
/** When transforming object's, adjust the object data so it stays in the same place. */
T_OBJECT_DATA_IN_OBJECT_MODE = 1 << 28,
};
/** #TransInfo.modifiers */
@ -1167,4 +1181,7 @@ bool checkUseAxisMatrix(TransInfo *t);
th != tc_end; \
th++, i++)
void trans_obdata_in_obmode_free_all(struct TransInfo *t);
void trans_obdata_in_obmode_update_all(struct TransInfo *t);
#endif

View File

@ -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;

View File

@ -81,6 +81,7 @@
#include "BKE_workspace.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
#include "ED_anim_api.h"
#include "ED_armature.h"
@ -1149,6 +1150,10 @@ static void recalcData_objects(TransInfo *t)
/* Update motion paths once for all transformed objects. */
ED_objects_recalculate_paths(t->context, t->scene, true);
}
if (t->flag & T_OBJECT_DATA_IN_OBJECT_MODE) {
trans_obdata_in_obmode_update_all(t);
}
}
}
@ -1918,6 +1923,10 @@ void postTrans(bContext *C, TransInfo *t)
BLI_rng_free(t->rng);
}
if (t->flag & T_OBJECT_DATA_IN_OBJECT_MODE) {
trans_obdata_in_obmode_free_all(t);
}
freeSnapping(t);
}

View File

@ -2020,6 +2020,7 @@ extern const char *RE_engine_id_CYCLES;
/* ToolSettings.transform_flag */
enum {
SCE_XFORM_AXIS_ALIGN = (1 << 0),
SCE_XFORM_DATA_ORIGIN = (1 << 1),
};
/* ToolSettings.object_flag */

View File

@ -2935,8 +2935,12 @@ static void rna_def_tool_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_transform_pivot_point_align", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "transform_flag", SCE_XFORM_AXIS_ALIGN);
RNA_def_property_ui_text(
prop, "Only Origins", "Manipulate origins (object, pose and weight paint mode only)");
RNA_def_property_ui_icon(prop, ICON_CENTER_ONLY, 0);
prop, "Only Locations", "Manipulate origins (object, pose and weight paint mode only)");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "use_transform_data_origin", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "transform_flag", SCE_XFORM_DATA_ORIGIN);
RNA_def_property_ui_text(prop, "Data Origins", "Manipulate object data");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "use_mesh_automerge", PROP_BOOLEAN, PROP_NONE);