From ef1af9f9c41a9cb33550bcaf396023ff840a3dab Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 4 Apr 2013 09:20:46 +0000 Subject: fix [#34802] Individual Transformation Confusing in Edit Mode Individual transformation now works in editmode mesh faces/edge, armature bones and metaballs. --- source/blender/editors/transform/transform.h | 24 ++-- .../editors/transform/transform_constraints.c | 55 +++++---- .../editors/transform/transform_conversions.c | 137 +++++++++++++-------- .../editors/transform/transform_orientations.c | 14 +-- source/blender/editors/transform/transform_snap.c | 24 ++-- 5 files changed, 146 insertions(+), 108 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index a551ef5008e..1f08bfda6a6 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -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); diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index f3026205ea2..7678051fd38 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -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; } /* diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index f84c967711c..661d7055036 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -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); + 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; } - copy_v3_v3(td->iloc, td->loc); - // 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) diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 0c1f169935a..023083a98ff 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -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) diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index e04ea3f84c3..c6ab33124ef 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -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; } } -- cgit v1.2.3