fix [#34802] Individual Transformation Confusing in Edit Mode

Individual transformation now works in editmode mesh faces/edge, armature bones and metaballs.
This commit is contained in:
Campbell Barton
2013-04-04 09:20:46 +00:00
parent 82636ab0fb
commit ef1af9f9c4
6 changed files with 148 additions and 110 deletions

View File

@@ -619,7 +619,7 @@ void BM_editselection_center(BMEditSelection *ese, float r_center[3])
}
else if (ese->htype == BM_FACE) {
BMFace *efa = (BMFace *)ese->ele;
BM_face_calc_center_bounds(efa, r_center);
BM_face_calc_center_mean(efa, r_center);
}
}

View File

@@ -72,7 +72,7 @@ typedef struct TransSnap {
short target;
short modePoint;
short modeSelect;
short align;
bool align;
char project;
char snap_self;
short peel;
@@ -593,7 +593,7 @@ void flushTransGraphData(TransInfo *t);
void remake_graph_transdata(TransInfo *t, struct ListBase *anim_data);
void flushTransUVs(TransInfo *t);
void flushTransParticles(TransInfo *t);
int clipUVTransform(TransInfo *t, float *vec, int resize);
bool clipUVTransform(TransInfo *t, float vec[2], const bool resize);
void clipUVData(TransInfo *t);
void flushTransNodes(TransInfo *t);
void flushTransSeq(TransInfo *t);
@@ -628,8 +628,8 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char tex
void constraintNumInput(TransInfo *t, float vec[3]);
int isLockConstraint(TransInfo *t);
int getConstraintSpaceDimension(TransInfo *t);
bool isLockConstraint(TransInfo *t);
int getConstraintSpaceDimension(TransInfo *t);
char constraintModeToChar(TransInfo *t);
void startConstraint(TransInfo *t);
@@ -652,21 +652,21 @@ typedef enum {
void snapGrid(TransInfo *t, float *val);
void snapGridAction(TransInfo *t, float *val, GearsType action);
int activeSnap(TransInfo *t);
int validSnap(TransInfo *t);
bool activeSnap(TransInfo *t);
bool validSnap(TransInfo *t);
void initSnapping(struct TransInfo *t, struct wmOperator *op);
void applyProject(TransInfo *t);
void applySnapping(TransInfo *t, float *vec);
void resetSnapping(TransInfo *t);
int handleSnapping(TransInfo *t, const struct wmEvent *event);
bool handleSnapping(TransInfo *t, const struct wmEvent *event);
void drawSnapping(const struct bContext *C, TransInfo *t);
int usingSnappingNormal(TransInfo *t);
int validSnappingNormal(TransInfo *t);
bool usingSnappingNormal(TransInfo *t);
bool validSnappingNormal(TransInfo *t);
void getSnapPoint(TransInfo *t, float vec[3]);
void addSnapPoint(TransInfo *t);
int updateSelectedSnapPoint(TransInfo *t);
bool updateSelectedSnapPoint(TransInfo *t);
void removeSnapPoint(TransInfo *t);
/********************** Mouse Input ******************************/
@@ -729,8 +729,8 @@ struct TransformOrientation *createMeshSpace(struct bContext *C, struct ReportLi
struct TransformOrientation *createBoneSpace(struct bContext *C, struct ReportList *reports, char *name, int overwrite);
/* Those two fill in mat and return non-zero on success */
int createSpaceNormal(float mat[3][3], float normal[3]);
int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]);
bool createSpaceNormal(float mat[3][3], const float normal[3]);
bool createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]);
struct TransformOrientation *addMatrixSpace(struct bContext *C, float mat[3][3], char name[], int overwrite);
void applyTransformOrientation(const struct bContext *C, float mat[3][3], char *name);

View File

@@ -557,13 +557,17 @@ void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[])
void setLocalConstraint(TransInfo *t, int mode, const char text[])
{
/* edit-mode now allows local transforms too */
#if 0
if (t->flag & T_EDIT) {
float obmat[3][3];
copy_m3_m4(obmat, t->scene->obedit->obmat);
normalize_m3(obmat);
setConstraint(t, obmat, mode, text);
}
else {
else
#endif
{
if (t->total == 1) {
setConstraint(t, t->data->axismtx, mode, text);
}
@@ -743,37 +747,42 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
static void drawObjectConstraint(TransInfo *t)
{
int i;
TransData *td = t->data;
/* Draw the first one lighter because that's the one who controls the others.
* Meaning the transformation is projected on that one and just copied on the others
* constraint space.
* In a nutshell, the object with light axis is controlled by the user and the others follow.
* Without drawing the first light, users have little clue what they are doing.
*/
if (t->con.mode & CON_AXIS0) {
drawLine(t, td->ob->obmat[3], td->axismtx[0], 'X', DRAWLIGHT);
}
if (t->con.mode & CON_AXIS1) {
drawLine(t, td->ob->obmat[3], td->axismtx[1], 'Y', DRAWLIGHT);
}
if (t->con.mode & CON_AXIS2) {
drawLine(t, td->ob->obmat[3], td->axismtx[2], 'Z', DRAWLIGHT);
}
short options = DRAWLIGHT;
TransData *td = t->data;
int i;
td++;
for (i = 0; i < t->total; i++, td++) {
float co[3];
if (t->flag & T_OBJECT) {
copy_v3_v3(co, td->ob->obmat[3]);
}
else if (t->flag & T_EDIT) {
mul_v3_m4v3(co, t->obedit->obmat, td->center);
}
else if (t->flag & T_POSE) {
mul_v3_m4v3(co, t->poseobj->obmat, td->center);
}
else {
copy_v3_v3(co, td->center);
}
for (i = 1; i < t->total; i++, td++) {
if (t->con.mode & CON_AXIS0) {
drawLine(t, td->ob->obmat[3], td->axismtx[0], 'X', 0);
drawLine(t, td->center, td->axismtx[0], 'X', options);
}
if (t->con.mode & CON_AXIS1) {
drawLine(t, td->ob->obmat[3], td->axismtx[1], 'Y', 0);
drawLine(t, td->center, td->axismtx[1], 'Y', options);
}
if (t->con.mode & CON_AXIS2) {
drawLine(t, td->ob->obmat[3], td->axismtx[2], 'Z', 0);
drawLine(t, td->center, td->axismtx[2], 'Z', options);
}
options &= ~DRAWLIGHT;
}
}
@@ -992,20 +1001,20 @@ char constraintModeToChar(TransInfo *t)
}
int isLockConstraint(TransInfo *t)
bool isLockConstraint(TransInfo *t)
{
int mode = t->con.mode;
if ((mode & (CON_AXIS0 | CON_AXIS1)) == (CON_AXIS0 | CON_AXIS1))
return 1;
return true;
if ((mode & (CON_AXIS1 | CON_AXIS2)) == (CON_AXIS1 | CON_AXIS2))
return 1;
return true;
if ((mode & (CON_AXIS0 | CON_AXIS2)) == (CON_AXIS0 | CON_AXIS2))
return 1;
return true;
return 0;
return false;
}
/*

View File

@@ -125,7 +125,7 @@
/* local function prototype - for Object/Bone Constraints */
static short constraints_list_needinv(TransInfo *t, ListBase *list);
static bool constraints_list_needinv(TransInfo *t, ListBase *list);
/* ************************** Functions *************************** */
@@ -1236,6 +1236,8 @@ static void createTransMBallVerts(TransInfo *t)
copy_v3_v3(td->iloc, td->loc);
copy_v3_v3(td->center, td->loc);
quat_to_mat3(td->axismtx, ml->quat);
if (ml->flag & SELECT) td->flag = TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
else td->flag = TD_USEQUAT;
@@ -1858,32 +1860,29 @@ static void editmesh_set_connectivity_distance(BMEditMesh *em, float mtx[3][3],
MEM_freeN(tots);
}
/* loop-in-a-loop I know, but we need it! (ton) */
static void get_face_center(float r_cent[3], BMVert *eve)
static BMElem *bm_vert_single_select_face(BMVert *eve)
{
BMFace *efa;
BMElem *ele;
BMIter iter;
BM_ITER_ELEM (efa, &iter, eve, BM_FACES_OF_VERT) {
if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_face_calc_center_mean(efa, r_cent);
break;
BM_ITER_ELEM (ele, &iter, eve, BM_FACES_OF_VERT) {
if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
return ele;
}
}
return NULL;
}
static void get_edge_center(float r_cent[3], BMVert *eve)
static BMElem *bm_vert_single_select_edge(BMVert *eve)
{
BMEdge *eed;
BMElem *ele;
BMIter iter;
BM_ITER_ELEM (eed, &iter, eve, BM_EDGES_OF_VERT) {
if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
mid_v3_v3v3(r_cent, eed->v1->co, eed->v2->co);
break;
BM_ITER_ELEM (ele, &iter, eve, BM_EDGES_OF_VERT) {
if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
return ele;
}
}
return NULL;
}
/* way to overwrite what data is edited with transform */
@@ -1895,25 +1894,51 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx
// td->loc = key->co;
//else
td->loc = eve->co;
copy_v3_v3(td->iloc, td->loc);
copy_v3_v3(td->center, td->loc);
if (t->around == V3D_LOCAL) {
if (em->selectmode & SCE_SELECT_FACE)
get_face_center(td->center, eve);
else if (em->selectmode & SCE_SELECT_EDGE)
get_edge_center(td->center, eve);
}
copy_v3_v3(td->iloc, td->loc);
BMElem *ele;
bool is_axismat_set = false;
if (em->selectmode & (SCE_SELECT_FACE | SCE_SELECT_EDGE) &&
(ele = ((em->selectmode & SCE_SELECT_FACE) ?
bm_vert_single_select_face(eve) :
bm_vert_single_select_edge(eve))))
{
float normal[3], tangent[3];
BMEditSelection ese;
ese.next = ese.prev = NULL;
ese.ele = ele;
ese.htype = ele->head.htype;
BM_editselection_center(&ese, td->center);
BM_editselection_normal(&ese, normal);
BM_editselection_plane(&ese, tangent);
if (createSpaceNormalTangent(td->axismtx, normal, tangent)) {
is_axismat_set = true;
}
}
/* for verts or fallback when createSpaceNormalTangent fails */
if (is_axismat_set == false) {
axis_dominant_v3_to_m3(td->axismtx, eve->no);
invert_m3(td->axismtx);
}
}
else {
/* Setting normals */
copy_v3_v3(td->axismtx[2], eve->no);
td->axismtx[0][0] =
td->axismtx[0][1] =
td->axismtx[0][2] =
td->axismtx[1][0] =
td->axismtx[1][1] =
td->axismtx[1][2] = 0.0f;
}
// Setting normals
copy_v3_v3(td->axismtx[2], eve->no);
td->axismtx[0][0] =
td->axismtx[0][1] =
td->axismtx[0][2] =
td->axismtx[1][0] =
td->axismtx[1][1] =
td->axismtx[1][2] = 0.0f;
td->ext = NULL;
td->val = NULL;
@@ -2503,7 +2528,7 @@ void flushTransUVs(TransInfo *t)
}
}
int clipUVTransform(TransInfo *t, float *vec, int resize)
bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
{
TransData *td;
int a, clipx = 1, clipy = 1;
@@ -2574,16 +2599,16 @@ void clipUVData(TransInfo *t)
/* ********************* ANIMATION EDITORS (GENERAL) ************************* */
/* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
static short FrameOnMouseSide(char side, float frame, float cframe)
static bool FrameOnMouseSide(char side, float frame, float cframe)
{
/* both sides, so it doesn't matter */
if (side == 'B') return 1;
if (side == 'B') return true;
/* only on the named side */
if (side == 'R')
return (frame >= cframe) ? 1 : 0;
return (frame >= cframe);
else
return (frame <= cframe) ? 1 : 0;
return (frame <= cframe);
}
/* ********************* NLA EDITOR ************************* */
@@ -4523,7 +4548,7 @@ static void createTransSeqData(bContext *C, TransInfo *t)
* These particular constraints benefit from this, but others don't, hence
* this semi-hack ;-) - Aligorith
*/
static short constraints_list_needinv(TransInfo *t, ListBase *list)
static bool constraints_list_needinv(TransInfo *t, ListBase *list)
{
bConstraint *con;
@@ -4536,26 +4561,30 @@ static short constraints_list_needinv(TransInfo *t, ListBase *list)
if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f)) {
/* (affirmative) returns for specific constraints here... */
/* constraints that require this regardless */
if (con->type == CONSTRAINT_TYPE_CHILDOF) return 1;
if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) return 1;
if (con->type == CONSTRAINT_TYPE_CLAMPTO) return 1;
if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) return 1;
if (con->type == CONSTRAINT_TYPE_FOLLOWTRACK) return 1;
if (ELEM5(con->type,
CONSTRAINT_TYPE_CHILDOF,
CONSTRAINT_TYPE_FOLLOWPATH,
CONSTRAINT_TYPE_CLAMPTO,
CONSTRAINT_TYPE_OBJECTSOLVER,
CONSTRAINT_TYPE_FOLLOWTRACK))
{
return true;
}
/* constraints that require this only under special conditions */
if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
/* CopyRot constraint only does this when rotating, and offset is on */
bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
if ((data->flag & ROTLIKE_OFFSET) && (t->mode == TFM_ROTATION))
return 1;
return true;
}
}
}
}
/* no appropriate candidates found */
return 0;
return false;
}
/* transcribe given object into TransData for Transforming */
@@ -4563,8 +4592,8 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
{
Scene *scene = t->scene;
float obmtx[3][3];
short constinv;
short skip_invert = 0;
bool constinv;
bool skip_invert = false;
if (t->mode != TFM_DUMMY && ob->rigidbody_object) {
float rot[3][3], scale[3];
@@ -4602,15 +4631,15 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
/* disable constraints inversion for dummy pass */
if (t->mode == TFM_DUMMY)
skip_invert = 1;
skip_invert = true;
if (skip_invert == 0 && constinv == 0) {
if (constinv == 0)
if (skip_invert == false && constinv == false) {
if (constinv == false)
ob->transflag |= OB_NO_CONSTRAINTS; /* BKE_object_where_is_calc_time checks this */
BKE_object_where_is_calc(t->scene, ob);
if (constinv == 0)
if (constinv == false)
ob->transflag &= ~OB_NO_CONSTRAINTS;
}
else
@@ -4762,19 +4791,19 @@ static void set_trans_object_base_flags(TransInfo *t)
}
}
static int mark_children(Object *ob)
static bool mark_children(Object *ob)
{
if (ob->flag & (SELECT | BA_TRANSFORM_CHILD))
return 1;
return true;
if (ob->parent) {
if (mark_children(ob->parent)) {
ob->flag |= BA_TRANSFORM_CHILD;
return 1;
return true;
}
}
return 0;
return false;
}
static int count_proportional_objects(TransInfo *t)

View File

@@ -213,13 +213,13 @@ TransformOrientation *createMeshSpace(bContext *C, ReportList *reports, char *na
return addMatrixSpace(C, mat, name, overwrite);
}
int createSpaceNormal(float mat[3][3], float normal[3])
bool createSpaceNormal(float mat[3][3], const float normal[3])
{
float tangent[3] = {0.0f, 0.0f, 1.0f};
copy_v3_v3(mat[2], normal);
if (normalize_v3(mat[2]) == 0.0f) {
return 0; /* error return */
return false; /* error return */
}
cross_v3_v3v3(mat[0], mat[2], tangent);
@@ -233,14 +233,14 @@ int createSpaceNormal(float mat[3][3], float normal[3])
normalize_m3(mat);
return 1;
return true;
}
int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3])
bool createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3])
{
copy_v3_v3(mat[2], normal);
if (normalize_v3(mat[2]) == 0.0f) {
return 0; /* error return */
return false; /* error return */
}
/* preempt zero length tangent from causing trouble */
@@ -250,14 +250,14 @@ int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3])
cross_v3_v3v3(mat[0], mat[2], tangent);
if (normalize_v3(mat[0]) == 0.0f) {
return 0; /* error return */
return false; /* error return */
}
cross_v3_v3v3(mat[1], mat[2], mat[0]);
normalize_m3(mat);
return 1;
return true;
}
TransformOrientation *addMatrixSpace(bContext *C, float mat[3][3], char name[], int overwrite)

View File

@@ -124,13 +124,13 @@ int BIF_snappingSupported(Object *obedit)
}
#endif
int validSnap(TransInfo *t)
bool validSnap(TransInfo *t)
{
return (t->tsnap.status & (POINT_INIT | TARGET_INIT)) == (POINT_INIT | TARGET_INIT) ||
(t->tsnap.status & (MULTI_POINTS | TARGET_INIT)) == (MULTI_POINTS | TARGET_INIT);
}
int activeSnap(TransInfo *t)
bool activeSnap(TransInfo *t)
{
return (t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP || (t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP_INVERT;
}
@@ -264,9 +264,9 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
}
}
int handleSnapping(TransInfo *t, const wmEvent *event)
bool handleSnapping(TransInfo *t, const wmEvent *event)
{
int status = 0;
bool status = false;
#if 0 // XXX need a proper selector for all snap mode
if (BIF_snappingSupported(t->obedit) && event->type == TABKEY && event->shift) {
@@ -372,7 +372,7 @@ void applySnapping(TransInfo *t, float *vec)
void resetSnapping(TransInfo *t)
{
t->tsnap.status = 0;
t->tsnap.align = 0;
t->tsnap.align = false;
t->tsnap.project = 0;
t->tsnap.mode = 0;
t->tsnap.modeSelect = 0;
@@ -387,20 +387,20 @@ void resetSnapping(TransInfo *t)
t->tsnap.snapNodeBorder = 0;
}
int usingSnappingNormal(TransInfo *t)
bool usingSnappingNormal(TransInfo *t)
{
return t->tsnap.align;
}
int validSnappingNormal(TransInfo *t)
bool validSnappingNormal(TransInfo *t)
{
if (validSnap(t)) {
if (dot_v3v3(t->tsnap.snapNormal, t->tsnap.snapNormal) > 0) {
return 1;
return true;
}
}
return 0;
return false;
}
static void initSnappingMode(TransInfo *t)
@@ -603,9 +603,9 @@ void addSnapPoint(TransInfo *t)
}
}
int updateSelectedSnapPoint(TransInfo *t)
bool updateSelectedSnapPoint(TransInfo *t)
{
int status = 0;
bool status = false;
if (t->tsnap.status & MULTI_POINTS) {
TransSnapPoint *p, *closest_p = NULL;
float closest_dist = TRANSFORM_SNAP_MAX_PX;
@@ -628,7 +628,7 @@ int updateSelectedSnapPoint(TransInfo *t)
}
if (closest_p) {
status = t->tsnap.selectedPoint == closest_p ? 0 : 1;
status = (t->tsnap.selectedPoint != closest_p);
t->tsnap.selectedPoint = closest_p;
}
}