From b1d4d75aab81eecf409956f15bf9c795715dfe86 Mon Sep 17 00:00:00 2001 From: Joseph Eagar Date: Tue, 22 Sep 2009 08:41:03 +0000 Subject: brought back edge slide. --- source/blender/editors/include/ED_mesh.h | 8 + source/blender/editors/include/ED_transform.h | 3 +- source/blender/editors/mesh/editmesh_tools.c | 6 +- source/blender/editors/mesh/mesh_intern.h | 6 - source/blender/editors/mesh/mesh_ops.c | 1 + source/blender/editors/transform/transform.c | 669 +++++++++++++++++++++ source/blender/editors/transform/transform.h | 32 + .../blender/editors/transform/transform_generics.c | 4 + source/blender/editors/transform/transform_ops.c | 1 + 9 files changed, 721 insertions(+), 9 deletions(-) (limited to 'source') diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index a2dba89ec20..a871ab555a5 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -175,5 +175,13 @@ float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int ver struct MDeformWeight *ED_vgroup_weight_verify(struct MDeformVert *dv, int defgroup); struct MDeformWeight *ED_vgroup_weight_get(struct MDeformVert *dv, int defgroup); +/*needed by edge slide*/ +struct EditVert *editedge_getOtherVert(struct EditEdge *eed, struct EditVert *eve); +struct EditVert *editedge_getSharedVert(struct EditEdge *eed, struct EditEdge *eed2); +int editedge_containsVert(struct EditEdge *eed, struct EditVert *eve); +int editface_containsVert(struct EditFace *efa, struct EditVert *eve); +int editface_containsEdge(struct EditFace *efa, struct EditEdge *eed); +short sharesFace(struct EditMesh *em, struct EditEdge *e1, struct EditEdge *e2); + #endif /* ED_MESH_H */ diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 96425f725e9..bf3111de5dc 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -75,7 +75,8 @@ enum { TFM_BAKE_TIME, TFM_BEVEL, TFM_BWEIGHT, - TFM_ALIGN + TFM_ALIGN, + TFM_EDGE_SLIDE } TfmMode; /* TRANSFORM CONTEXTS */ diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 46b941f70df..2c20e4a147c 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -3868,11 +3868,11 @@ typedef struct SlideVert { EditVert origvert; } SlideVert; +#if 0 int EdgeSlide(EditMesh *em, wmOperator *op, short immediate, float imperc) { return 0; /* XXX REFACTOR - #if 0'd for now, otherwise can't make 64bit windows builds on 64bit machine */ -#if 0 useless: goto useless // because it doesn't do anything right now @@ -4654,11 +4654,12 @@ useless: } return 1; -#endif // END OF XXX } +#endif // END OF XXX int EdgeLoopDelete(EditMesh *em, wmOperator *op) { +#if 0 //XXX won't work with new edgeslide /* temporal flag setting so we keep UVs when deleting edge loops, * this is a bit of a hack but it works how you would want in almost all cases */ @@ -4677,6 +4678,7 @@ int EdgeLoopDelete(EditMesh *em, wmOperator *op) EM_select_flush(em); // DAG_id_flush_update(obedit->data, OB_RECALC_DATA); return 1; +#endif } diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 11a974f2c49..37a6d0f384f 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -61,12 +61,6 @@ extern struct EditEdge *addedgelist(EditMesh *em, struct EditVert *v1, struct Ed extern struct EditFace *addfacelist(EditMesh *em, struct EditVert *v1, struct EditVert *v2, struct EditVert *v3, struct EditVert *v4, struct EditFace *example, struct EditFace *exampleEdges); extern struct EditEdge *findedgelist(EditMesh *em, struct EditVert *v1, struct EditVert *v2); -EditVert *editedge_getOtherVert(EditEdge *eed, EditVert *eve); -EditVert *editedge_getSharedVert(EditEdge *eed, EditEdge *eed2); -int editedge_containsVert(struct EditEdge *eed, struct EditVert *eve); -int editface_containsVert(struct EditFace *efa, struct EditVert *eve); -int editface_containsEdge(struct EditFace *efa, struct EditEdge *eed); - void em_setup_viewcontext(struct bContext *C, ViewContext *vc); void MESH_OT_separate(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index f22adc597c7..3f1bbbb9097 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -113,6 +113,7 @@ static int edge_specials_invoke(bContext *C, wmOperator *op, wmEvent *event) uiItemEnumO(layout, "Rotate Edge CCW", 0, "MESH_OT_edge_rotate", "direction", 2); //uiItemO(layout, "Loopcut", 0, "MESH_OT_loop_cut"); // CutEdgeloop(em, 1); //uiItemO(layout, "Edge Slide", 0, "MESH_OT_edge_slide"); // EdgeSlide(em, 0,0.0); + uiItemEnumO(layout, "Edge Slide", 0, "TFM_OT_transform", "mode", TFM_EDGE_SLIDE); uiItemO(layout, "Edge Loop", 0, "MESH_OT_loop_multi_select"); uiItemBooleanO(layout, "Edge Ring", 0, "MESH_OT_loop_multi_select", "ring", 1); uiItemO(layout, NULL, 0, "MESH_OT_loop_to_region"); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index e877f1fecae..8f3fcfedd18 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -100,6 +100,7 @@ #include "ED_markers.h" #include "ED_util.h" #include "ED_view3d.h" +#include "ED_mesh.h" #include "UI_view2d.h" #include "WM_types.h" @@ -108,6 +109,8 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_editVert.h" +#include "BLI_ghash.h" +#include "BLI_linklist.h" #include "PIL_time.h" /* sleep */ @@ -1428,6 +1431,9 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int case TFM_BONE_ENVELOPE: initBoneEnvelope(t); break; + case TFM_EDGE_SLIDE: + initEdgeSlide(t); + break; case TFM_BONE_ROLL: initBoneRoll(t); break; @@ -4029,6 +4035,669 @@ int BoneEnvelope(TransInfo *t, short mval[2]) return 1; } +/* ******************** Edge Slide *************** */ + +static int createSlideVerts(TransInfo *t) +{ + Mesh *me = t->obedit->data; + EditMesh *em = me->edit_mesh; + EditFace *efa; + EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL; + EditVert *ev, *nearest = NULL; + LinkNode *edgelist = NULL, *vertlist=NULL, *look; + GHash *vertgh; + TransDataSlideVert *tempsv; + float perc = 0, percp = 0,vertdist; // XXX, projectMat[4][4]; + float shiftlabda= 0.0f,len = 0.0f; + int i, j, numsel, numadded=0, timesthrough = 0, vertsel=0, prop=1, cancel = 0,flip=0; + int wasshift = 0; + /* UV correction vars */ + GHash **uvarray= NULL; + SlideData *sld = MEM_callocN(sizeof(*sld), "sld"); + int uvlay_tot= CustomData_number_of_layers(&em->fdata, CD_MTFACE); + int uvlay_idx; + TransDataSlideUv *slideuvs=NULL, *suv=NULL, *suv_last=NULL; + RegionView3D *v3d = t->ar->regiondata; + float projectMat[4][4]; + float start[3] = {0.0f, 0.0f, 0.0f}, end[3] = {0.0f, 0.0f, 0.0f}; + float vec[3]; + //short mval[2], mvalo[2]; + float labda = 0.0f, totvec=0.0; + + view3d_get_object_project_mat(v3d, t->obedit, projectMat); + + //mvalo[0] = -1; mvalo[1] = -1; + numsel =0; + + // Get number of selected edges and clear some flags + for(eed=em->edges.first;eed;eed=eed->next) { + eed->f1 = 0; + eed->f2 = 0; + if(eed->f & SELECT) numsel++; + } + + for(ev=em->verts.first;ev;ev=ev->next) { + ev->f1 = 0; + } + + //Make sure each edge only has 2 faces + // make sure loop doesn't cross face + for(efa=em->faces.first;efa;efa=efa->next) { + int ct = 0; + if(efa->e1->f & SELECT) { + ct++; + efa->e1->f1++; + if(efa->e1->f1 > 2) { + //BKE_report(op->reports, RPT_ERROR, "3+ face edge"); + return 0; + } + } + if(efa->e2->f & SELECT) { + ct++; + efa->e2->f1++; + if(efa->e2->f1 > 2) { + //BKE_report(op->reports, RPT_ERROR, "3+ face edge"); + return 0; + } + } + if(efa->e3->f & SELECT) { + ct++; + efa->e3->f1++; + if(efa->e3->f1 > 2) { + //BKE_report(op->reports, RPT_ERROR, "3+ face edge"); + return 0; + } + } + if(efa->e4 && efa->e4->f & SELECT) { + ct++; + efa->e4->f1++; + if(efa->e4->f1 > 2) { + //BKE_report(op->reports, RPT_ERROR, "3+ face edge"); + return 0; + } + } + // Make sure loop is not 2 edges of same face + if(ct > 1) { + //BKE_report(op->reports, RPT_ERROR, "Loop crosses itself"); + return 0; + } + } + + // Get # of selected verts + for(ev=em->verts.first;ev;ev=ev->next) { + if(ev->f & SELECT) vertsel++; + } + + // Test for multiple segments + if(vertsel > numsel+1) { + //BKE_report(op->reports, RPT_ERROR, "Please choose a single edge loop"); + return 0; + } + + // Get the edgeloop in order - mark f1 with SELECT once added + for(eed=em->edges.first;eed;eed=eed->next) { + if((eed->f & SELECT) && !(eed->f1 & SELECT)) { + // If this is the first edge added, just put it in + if(!edgelist) { + BLI_linklist_prepend(&edgelist,eed); + numadded++; + first = eed; + last = eed; + eed->f1 = SELECT; + } else { + if(editedge_getSharedVert(eed, last)) { + BLI_linklist_append(&edgelist,eed); + eed->f1 = SELECT; + numadded++; + last = eed; + } else if(editedge_getSharedVert(eed, first)) { + BLI_linklist_prepend(&edgelist,eed); + eed->f1 = SELECT; + numadded++; + first = eed; + } + } + } + if(eed->next == NULL && numadded != numsel) { + eed=em->edges.first; + timesthrough++; + } + + // It looks like there was an unexpected case - Hopefully should not happen + if(timesthrough >= numsel*2) { + BLI_linklist_free(edgelist,NULL); + //BKE_report(op->reports, RPT_ERROR, "Could not order loop"); + return 0; + } + } + + // Put the verts in order in a linklist + look = edgelist; + while(look) { + eed = look->link; + if(!vertlist) { + if(look->next) { + temp = look->next->link; + + //This is the first entry takes care of extra vert + if(eed->v1 != temp->v1 && eed->v1 != temp->v2) { + BLI_linklist_append(&vertlist,eed->v1); + eed->v1->f1 = 1; + } else { + BLI_linklist_append(&vertlist,eed->v2); + eed->v2->f1 = 1; + } + } else { + //This is the case that we only have 1 edge + BLI_linklist_append(&vertlist,eed->v1); + eed->v1->f1 = 1; + } + } + // for all the entries + if(eed->v1->f1 != 1) { + BLI_linklist_append(&vertlist,eed->v1); + eed->v1->f1 = 1; + } else if(eed->v2->f1 != 1) { + BLI_linklist_append(&vertlist,eed->v2); + eed->v2->f1 = 1; + } + look = look->next; + } + + // populate the SlideVerts + + vertgh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + look = vertlist; + while(look) { + i=0; + j=0; + ev = look->link; + tempsv = (struct TransDataSlideVert*)MEM_mallocN(sizeof(struct TransDataSlideVert),"SlideVert"); + tempsv->up = NULL; + tempsv->down = NULL; + tempsv->origvert.co[0] = ev->co[0]; + tempsv->origvert.co[1] = ev->co[1]; + tempsv->origvert.co[2] = ev->co[2]; + tempsv->origvert.no[0] = ev->no[0]; + tempsv->origvert.no[1] = ev->no[1]; + tempsv->origvert.no[2] = ev->no[2]; + // i is total edges that vert is on + // j is total selected edges that vert is on + + for(eed=em->edges.first;eed;eed=eed->next) { + if(eed->v1 == ev || eed->v2 == ev) { + i++; + if(eed->f & SELECT) { + j++; + } + } + } + // If the vert is in the middle of an edge loop, it touches 2 selected edges and 2 unselected edges + if(i == 4 && j == 2) { + for(eed=em->edges.first;eed;eed=eed->next) { + if(editedge_containsVert(eed, ev)) { + if(!(eed->f & SELECT)) { + if(!tempsv->up) { + tempsv->up = eed; + } else if (!(tempsv->down)) { + tempsv->down = eed; + } + } + } + } + } + // If it is on the end of the loop, it touches 1 selected and as least 2 more unselected + if(i >= 3 && j == 1) { + for(eed=em->edges.first;eed;eed=eed->next) { + if(editedge_containsVert(eed, ev) && eed->f & SELECT) { + for(efa = em->faces.first;efa;efa=efa->next) { + if(editface_containsEdge(efa, eed)) { + if(editedge_containsVert(efa->e1, ev) && efa->e1 != eed) { + if(!tempsv->up) { + tempsv->up = efa->e1; + } else if (!(tempsv->down)) { + tempsv->down = efa->e1; + } + } + if(editedge_containsVert(efa->e2, ev) && efa->e2 != eed) { + if(!tempsv->up) { + tempsv->up = efa->e2; + } else if (!(tempsv->down)) { + tempsv->down = efa->e2; + } + } + if(editedge_containsVert(efa->e3, ev) && efa->e3 != eed) { + if(!tempsv->up) { + tempsv->up = efa->e3; + } else if (!(tempsv->down)) { + tempsv->down = efa->e3; + } + } + if(efa->e4) { + if(editedge_containsVert(efa->e4, ev) && efa->e4 != eed) { + if(!tempsv->up) { + tempsv->up = efa->e4; + } else if (!(tempsv->down)) { + tempsv->down = efa->e4; + } + } + } + + } + } + } + } + } + if(i > 4 && j == 2) { + BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN); + BLI_linklist_free(vertlist,NULL); + BLI_linklist_free(edgelist,NULL); + return 0; + } + BLI_ghash_insert(vertgh,ev,tempsv); + + look = look->next; + } + + // make sure the UPs nad DOWNs are 'faceloops' + // Also find the nearest slidevert to the cursor + + look = vertlist; + nearest = NULL; + vertdist = -1; + while(look) { + tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link); + + if(!tempsv->up || !tempsv->down) { + //BKE_report(op->reports, RPT_ERROR, "Missing rails"); + BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN); + BLI_linklist_free(vertlist,NULL); + BLI_linklist_free(edgelist,NULL); + return 0; + } + + if(me->drawflag & ME_DRAW_EDGELEN) { + if(!(tempsv->up->f & SELECT)) { + tempsv->up->f |= SELECT; + tempsv->up->f2 |= 16; + } else { + tempsv->up->f2 |= ~16; + } + if(!(tempsv->down->f & SELECT)) { + tempsv->down->f |= SELECT; + tempsv->down->f2 |= 16; + } else { + tempsv->down->f2 |= ~16; + } + } + + if(look->next != NULL) { + TransDataSlideVert *sv; + + ev = (EditVert*)look->next->link; + sv = BLI_ghash_lookup(vertgh, ev); + + if(sv) { + float co[3], co2[3], vec[3]; + + if(!sharesFace(em, tempsv->up,sv->up)) { + EditEdge *swap; + swap = sv->up; + sv->up = sv->down; + sv->down = swap; + } + + view3d_project_float(t->ar, tempsv->up->v1->co, co, projectMat); + view3d_project_float(t->ar, tempsv->up->v2->co, co2, projectMat); + + if (ev == sv->up->v1) { + VecSubf(vec, co, co2); + } else { + VecSubf(vec, co2, co); + } + + VecAddf(start, start, vec); + + view3d_project_float(t->ar, tempsv->down->v1->co, co, projectMat); + view3d_project_float(t->ar, tempsv->down->v2->co, co2, projectMat); + + if (ev == sv->down->v1) { + VecSubf(vec, co2, co); + } else { + VecSubf(vec, co, co2); + } + + VecAddf(end, end, vec); + + totvec += 1.0f; + nearest = (EditVert*)look->link; + } + } + + + + look = look->next; + } + + VecAddf(start, start, end); + VecMulf(start, 0.5*(1.0/totvec)); + VECCOPY(vec, start); + start[0] = t->mval[0]; + start[1] = t->mval[1]; + VecAddf(end, start, vec); + + sld->start[0] = (short) start[0]; + sld->start[1] = (short) start[1]; + sld->end[0] = (short) end[0]; + sld->end[1] = (short) end[1]; + + if (uvlay_tot) { // XXX && (scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) { + int maxnum = 0; + + uvarray = MEM_callocN( uvlay_tot * sizeof(GHash *), "SlideUVs Array"); + sld->totuv = uvlay_tot; + suv_last = slideuvs = MEM_callocN( uvlay_tot * (numadded+1) * sizeof(TransDataSlideUv), "SlideUVs"); /* uvLayers * verts */ + suv = NULL; + + for (uvlay_idx=0; uvlay_idxverts.first;ev;ev=ev->next) { + ev->tmp.l = 0; + } + look = vertlist; + while(look) { + float *uv_new; + tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link); + + ev = look->link; + suv = NULL; + for(efa = em->faces.first;efa;efa=efa->next) { + if (ev->tmp.l != -1) { /* test for self, in this case its invalid */ + int k=-1; /* face corner */ + + /* Is this vert in the faces corner? */ + if (efa->v1==ev) k=0; + else if (efa->v2==ev) k=1; + else if (efa->v3==ev) k=2; + else if (efa->v4 && efa->v4==ev) k=3; + + if (k != -1) { + MTFace *tf = CustomData_em_get_n(&em->fdata, efa->data, CD_MTFACE, uvlay_idx); + EditVert *ev_up, *ev_down; + + uv_new = tf->uv[k]; + + if (ev->tmp.l) { + if (fabs(suv->origuv[0]-uv_new[0]) > 0.0001 || fabs(suv->origuv[1]-uv_new[1])) { + ev->tmp.l = -1; /* Tag as invalid */ + BLI_linklist_free(suv->fuv_list,NULL); + suv->fuv_list = NULL; + BLI_ghash_remove(uvarray[uvlay_idx],ev, NULL, NULL); + suv = NULL; + break; + } + } else { + ev->tmp.l = 1; + suv = suv_last; + + suv->fuv_list = NULL; + suv->uv_up = suv->uv_down = NULL; + suv->origuv[0] = uv_new[0]; + suv->origuv[1] = uv_new[1]; + + BLI_linklist_prepend(&suv->fuv_list, uv_new); + BLI_ghash_insert(uvarray[uvlay_idx],ev,suv); + + suv_last++; /* advance to next slide UV */ + maxnum++; + } + + /* Now get the uvs along the up or down edge if we can */ + if (suv) { + if (!suv->uv_up) { + ev_up = editedge_getOtherVert(tempsv->up,ev); + if (efa->v1==ev_up) suv->uv_up = tf->uv[0]; + else if (efa->v2==ev_up) suv->uv_up = tf->uv[1]; + else if (efa->v3==ev_up) suv->uv_up = tf->uv[2]; + else if (efa->v4 && efa->v4==ev_up) suv->uv_up = tf->uv[3]; + } + if (!suv->uv_down) { /* if the first face was apart of the up edge, it cant be apart of the down edge */ + ev_down = editedge_getOtherVert(tempsv->down,ev); + if (efa->v1==ev_down) suv->uv_down = tf->uv[0]; + else if (efa->v2==ev_down) suv->uv_down = tf->uv[1]; + else if (efa->v3==ev_down) suv->uv_down = tf->uv[2]; + else if (efa->v4 && efa->v4==ev_down) suv->uv_down = tf->uv[3]; + } + + /* Copy the pointers to the face UV's */ + BLI_linklist_prepend(&suv->fuv_list, uv_new); + } + } + } + } + look = look->next; + } + } /* end uv layer loop */ + } /* end uvlay_tot */ + + sld->uvhash = uvarray; + sld->slideuv = slideuvs; + sld->vhash = vertgh; + sld->nearest = nearest; + sld->vertlist = vertlist; + sld->edgelist = edgelist; + sld->suv_last = suv_last; + sld->uvlay_tot = uvlay_tot; + + // we should have enough info now to slide + + t->customData = sld; + + return 1; +} + +void initEdgeSlide(TransInfo *t) +{ + SlideData *sld; + + t->mode = TFM_EDGE_SLIDE; + t->transform = EdgeSlide; + + createSlideVerts(t); + sld = t->customData; + + initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO); + setCustomPoints(t, &t->mouse, sld->end, sld->start); + + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = (float)((5.0/180)*M_PI); + t->snap[2] = t->snap[1] * 0.2f; + + t->flag |= T_NO_CONSTRAINT; +} + +int doEdgeSlide(TransInfo *t, float perc) +{ + Mesh *me= t->obedit->data; + EditMesh *em = me->edit_mesh; + SlideData *sld = t->customData; + EditEdge *first=NULL,*last=NULL, *temp = NULL; + EditVert *ev, *nearest = sld->nearest; + EditVert *centerVert, *upVert, *downVert; + LinkNode *edgelist = sld->edgelist, *vertlist=sld->vertlist, *look; + GHash *vertgh = sld->vhash; + TransDataSlideVert *tempsv; + float shiftlabda= 0.0f,len = 0.0f; + int i = 0, numadded=0, timesthrough = 0, vertsel=0, prop=1, cancel = 0,flip=0; + int wasshift = 0; + /* UV correction vars */ + GHash **uvarray= sld->uvhash; + int uvlay_tot= CustomData_number_of_layers(&em->fdata, CD_MTFACE); + int uvlay_idx; + TransDataSlideUv *slideuvs=sld->slideuv, *suv=sld->slideuv, *suv_last=NULL; + float uv_tmp[2]; + LinkNode *fuv_link; + float labda = 0.0f; + + len = 0.0f; + + tempsv = BLI_ghash_lookup(vertgh,nearest); + + centerVert = editedge_getSharedVert(tempsv->up, tempsv->down); + upVert = editedge_getOtherVert(tempsv->up, centerVert); + downVert = editedge_getOtherVert(tempsv->down, centerVert); + + len = MIN2(perc, VecLenf(upVert->co,downVert->co)); + len = MAX2(len, 0); + + //Adjust Edgeloop + if(prop) { + look = vertlist; + while(look) { + EditVert *tempev; + ev = look->link; + tempsv = BLI_ghash_lookup(vertgh,ev); + + tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev); + VecLerpf(ev->co, tempsv->origvert.co, tempev->co, fabs(perc)); + + if (uvlay_tot) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { + for (uvlay_idx=0; uvlay_idxfuv_list && suv->uv_up && suv->uv_down) { + Vec2Lerpf(uv_tmp, suv->origuv, (perc>=0)?suv->uv_up:suv->uv_down, fabs(perc)); + fuv_link = suv->fuv_list; + while (fuv_link) { + VECCOPY2D(((float *)fuv_link->link), uv_tmp); + fuv_link = fuv_link->next; + } + } + } + } + + look = look->next; + } + } + else { + //Non prop code + look = vertlist; + while(look) { + float newlen; + ev = look->link; + tempsv = BLI_ghash_lookup(vertgh,ev); + newlen = (len / VecLenf(editedge_getOtherVert(tempsv->up,ev)->co,editedge_getOtherVert(tempsv->down,ev)->co)); + if(newlen > 1.0) {newlen = 1.0;} + if(newlen < 0.0) {newlen = 0.0;} + if(flip == 0) { + VecLerpf(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen)); + if (uvlay_tot) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { + /* dont do anything if no UVs */ + for (uvlay_idx=0; uvlay_idxfuv_list && suv->uv_up && suv->uv_down) { + Vec2Lerpf(uv_tmp, suv->uv_down, suv->uv_up, fabs(newlen)); + fuv_link = suv->fuv_list; + while (fuv_link) { + VECCOPY2D(((float *)fuv_link->link), uv_tmp); + fuv_link = fuv_link->next; + } + } + } + } + } else{ + VecLerpf(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen)); + + if (uvlay_tot) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { + /* dont do anything if no UVs */ + for (uvlay_idx=0; uvlay_idxfuv_list && suv->uv_up && suv->uv_down) { + Vec2Lerpf(uv_tmp, suv->uv_up, suv->uv_down, fabs(newlen)); + fuv_link = suv->fuv_list; + while (fuv_link) { + VECCOPY2D(((float *)fuv_link->link), uv_tmp); + fuv_link = fuv_link->next; + } + } + } + } + } + look = look->next; + } + + } + + return 1; +} + +void freeSlideVerts(TransInfo *t) +{ + TransDataSlideUv *suv; + SlideData *sld = t->customData; + int uvlay_idx; + + //BLI_ghash_free(edgesgh, freeGHash, NULL); + BLI_ghash_free(sld->vhash, NULL, (GHashValFreeFP)MEM_freeN); + BLI_linklist_free(sld->vertlist, NULL); + BLI_linklist_free(sld->edgelist, NULL); + + if (sld->uvlay_tot) { + for (uvlay_idx=0; uvlay_idxuvlay_tot; uvlay_idx++) { + BLI_ghash_free(sld->uvhash[uvlay_idx], NULL, NULL); + } + MEM_freeN(sld->slideuv); + MEM_freeN(sld->uvhash); + + suv = sld->suv_last-1; + while (suv >= sld->slideuv) { + if (suv->fuv_list) { + BLI_linklist_free(suv->fuv_list,NULL); + } + suv--; + } + } + + MEM_freeN(sld); +} + +int EdgeSlide(TransInfo *t, short mval[2]) +{ + TransData *td = t->data; + char str[50]; + float final; + + final = t->values[0]; + + snapGrid(t, &final); + + if (hasNumInput(&t->num)) { + char c[20]; + + applyNumInput(&t->num, &final); + + outputNumInput(&(t->num), c); + + sprintf(str, "Edge Slide Percent: %s", &c[0]); + } + else { + sprintf(str, "Edge Slide Percent: %.2f", final); + } + + CLAMP(final, -1.0f, 1.0f); + + /*do stuff here*/ + doEdgeSlide(t, final); + + recalcData(t); + + ED_area_headerprint(t->sa, str); + + return 1; +} /* ******************** EditBone roll *************** */ diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 2ff6d6d3dce..404257a55ff 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -32,6 +32,8 @@ #include "ED_transform.h" +#include "BLI_editVert.h" + /* ************************** Types ***************************** */ struct TransInfo; @@ -179,6 +181,31 @@ typedef struct TransDataNla { int handle; /* handle-index: 0 for dummy entry, -1 for start, 1 for end, 2 for both ends */ } TransDataNla; +struct LinkNode; +struct EditEdge; +struct EditVert; +struct GHash; +typedef struct TransDataSlideUv { + float origuv[2]; + float *uv_up, *uv_down; + //float *fuv[4]; + struct LinkNode *fuv_list; +} TransDataSlideUv; + +typedef struct TransDataSlideVert { + struct EditEdge *up, *down; + struct EditVert origvert; +} TransDataSlideVert; + +typedef struct SlideData { + TransDataSlideUv *slideuv, *suv_last; + int totuv, uvlay_tot; + struct GHash *vhash, **uvhash; + struct EditVert *nearest; + struct LinkNode *edgelist, *vertlist; + short start[2], end[2]; +} SlideData; + typedef struct TransData { float dist; /* Distance needed to affect element (for Proportionnal Editing) */ float rdist; /* Distance to the nearest element (for Proportionnal Editing) */ @@ -467,6 +494,9 @@ int BoneEnvelope(TransInfo *t, short mval[2]); void initBoneRoll(TransInfo *t); int BoneRoll(TransInfo *t, short mval[2]); +void initEdgeSlide(TransInfo *t); +int EdgeSlide(TransInfo *t, short mval[2]); + void initTimeTranslate(TransInfo *t); int TimeTranslate(TransInfo *t, short mval[2]); @@ -667,6 +697,8 @@ int getTransformOrientation(const struct bContext *C, float normal[3], float pla int createSpaceNormal(float mat[3][3], float normal[3]); int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]); +void freeSlideVerts(TransInfo *t); + #endif diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index d93e92616e1..59429d65e7b 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1073,6 +1073,10 @@ void postTrans (TransInfo *t) { MEM_freeN(t->mouse.data); } + + if (t->mode == TFM_EDGE_SLIDE) { + freeSlideVerts(t); + } } void applyTransObjects(TransInfo *t) diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 4bf0e44de7f..69819da8cc2 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -578,6 +578,7 @@ void TFM_OT_transform(struct wmOperatorType *ot) {TFM_BEVEL, "BEVEL", 0, "Bevel", ""}, {TFM_BWEIGHT, "BWEIGHT", 0, "Bweight", ""}, {TFM_ALIGN, "ALIGN", 0, "Align", ""}, + {TFM_EDGE_SLIDE, "EDGESLIDE", 0, "Edge Slide", ""}, {0, NULL, 0, NULL, NULL} }; -- cgit v1.2.3