/* turns Mesh into editmesh */ void make_editMesh(Scene *scene, Object *ob) { Mesh *me= ob->data; MFace *mface; MVert *mvert; MSelect *mselect; KeyBlock *actkey; EditMesh *em; EditVert *eve, **evlist, *eve1, *eve2, *eve3, *eve4; EditFace *efa, *efa_last_sel= NULL; EditEdge *eed; EditSelection *ese; float *co, (*keyco)[3]= NULL; int tot, a, eekadoodle= 0; const short is_paint_face_sel= paint_facesel_test(ob); const short is_paint_vert_sel= is_paint_face_sel ? FALSE : paint_vertsel_test(ob); if(me->edit_mesh==NULL) me->edit_mesh= MEM_callocN(sizeof(EditMesh), "editmesh"); else /* because of reload */ free_editMesh(me->edit_mesh); em= me->edit_mesh; em->selectmode= scene->toolsettings->selectmode; // warning needs to be synced em->act_face = NULL; em->totvert= tot= me->totvert; em->totedge= me->totedge; em->totface= me->totface; if(tot==0) { return; } if(ob->actcol > 0) em->mat_nr= ob->actcol-1; /* initialize fastmalloc for editmesh */ init_editmesh_fastmalloc(em, me->totvert, me->totedge, me->totface); actkey = ob_get_keyblock(ob); if(actkey) { /* undo-ing in past for previous editmode sessions gives corrupt 'keyindex' values */ undo_editmode_clear(); keyco= actkey->data; em->shapenr= ob->shapenr; } /* make editverts */ CustomData_copy(&me->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0); mvert= me->mvert; evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist"); for(a=0; a<tot; a++, mvert++) { co= mvert->co; /* edit the shape key coordinate if available */ if(keyco && a < actkey->totelem) co= keyco[a]; eve= addvertlist(em, co, NULL); evlist[a]= eve; /* face select sets selection in next loop */ if(!is_paint_face_sel) eve->f |= (mvert->flag & SELECT); if (mvert->flag & ME_HIDE) eve->h= 1; normal_short_to_float_v3(eve->no, mvert->no); eve->bweight= ((float)mvert->bweight)/255.0f; /* lets overwrite the keyindex of the editvert * with the order it used to be in before * editmode */ eve->keyindex = a; CustomData_to_em_block(&me->vdata, &em->vdata, a, &eve->data); } if(actkey && actkey->totelem!=me->totvert); else { MEdge *medge= me->medge; CustomData_copy(&me->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0); /* make edges */ for(a=0; a<me->totedge; a++, medge++) { eed= addedgelist(em, evlist[medge->v1], evlist[medge->v2], NULL); /* eed can be zero when v1 and v2 are identical, dxf import does this... */ if(eed) { int is_sel; if (is_paint_vert_sel) { /* when from vertex select, flush flags to edges, * allow selection, code below handles editmode selection conversion */ is_sel= (eed->v1->f & SELECT) && (eed->v2->f & SELECT); } else { is_sel= (medge->flag & SELECT); } eed->crease= ((float)medge->crease)/255.0f; eed->bweight= ((float)medge->bweight)/255.0f; if(medge->flag & ME_SEAM) eed->seam= 1; if(medge->flag & ME_SHARP) eed->sharp = 1; if(medge->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines! if(medge->flag & ME_HIDE) eed->h |= 1; if(is_sel) eed->f |= SELECT; if(em->selectmode==SCE_SELECT_EDGE) EM_select_edge(eed, eed->f & SELECT); // force edge selection to vertices, seems to be needed ... CustomData_to_em_block(&me->edata,&em->edata, a, &eed->data); } } CustomData_copy(&me->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0); /* make faces */ mface= me->mface; for(a=0; a<me->totface; a++, mface++) { eve1= evlist[mface->v1]; eve2= evlist[mface->v2]; if(!mface->v3) eekadoodle= 1; eve3= evlist[mface->v3]; if(mface->v4) eve4= evlist[mface->v4]; else eve4= NULL; efa= addfacelist(em, eve1, eve2, eve3, eve4, NULL, NULL); if(efa) { CustomData_to_em_block(&me->fdata, &em->fdata, a, &efa->data); efa->mat_nr= mface->mat_nr; efa->flag= mface->flag & ~ME_HIDE; /* select and hide face flag */ if(mface->flag & ME_HIDE) { efa->h= 1; } else { int is_sel; if (!is_paint_vert_sel) { is_sel= (mface->flag & ME_FACE_SEL); } else { /* when from vertex select, flush flags to edges, * allow selection, code below handles editmode selection conversion */ is_sel= ( (efa->v1->f & SELECT) && (efa->v2->f & SELECT) && (efa->v3->f & SELECT) && (efa->v4 == NULL || efa->v4->f & SELECT) ); } if (a==me->act_face) { EM_set_actFace(em, efa); } /* dont allow hidden and selected */ if(is_sel) { efa->f |= SELECT; if(is_paint_face_sel) { EM_select_face(efa, 1); /* flush down */ } efa_last_sel= efa; } } } } } if(EM_get_actFace(em, 0)==NULL && efa_last_sel) { EM_set_actFace(em, efa_last_sel); } if(eekadoodle) error("This Mesh has old style edgecodes, please put it in the bugtracker!"); MEM_freeN(evlist); end_editmesh_fastmalloc(); // resets global function pointers if(me->mselect){ //restore editselections EM_init_index_arrays(em, 1,1,1); mselect = me->mselect; for(a=0; a<me->totselect; a++, mselect++){ /*check if recorded selection is still valid, if so copy into editmesh*/ if ( (mselect->type == EDITVERT && me->mvert[mselect->index].flag & SELECT) || (mselect->type == EDITEDGE && me->medge[mselect->index].flag & SELECT) || (mselect->type == EDITFACE && me->mface[mselect->index].flag & ME_FACE_SEL) ) { ese = MEM_callocN(sizeof(EditSelection), "Edit Selection"); ese->type = mselect->type; if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(mselect->index); else if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(mselect->index); else if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(mselect->index); BLI_addtail(&(em->selected),ese); } } EM_free_index_arrays(); } /* this creates coherent selections. also needed for older files */ EM_selectmode_set(em); /* paranoia check to enforce hide rules */ EM_hide_reset(em); /* sets helper flags which arent saved */ EM_fgon_flags(em); if (EM_get_actFace(em, 0)==NULL) { EM_set_actFace(em, em->faces.first ); /* will use the first face, this is so we alwats have an active face */ } }
static int navmesh_face_copy_exec(bContext *C, wmOperator *op) { Object *obedit= CTX_data_edit_object(C); EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); /* do work here */ EditFace *efa_act= EM_get_actFace(em, 0); if(efa_act) { if(CustomData_has_layer(&em->fdata, CD_RECAST)) { EditFace *efa; int targetPolyIdx= *(int*)CustomData_em_get(&em->fdata, efa_act->data, CD_RECAST); targetPolyIdx= targetPolyIdx>=0? targetPolyIdx : -targetPolyIdx; if(targetPolyIdx > 0) { /* set target poly idx to other selected faces */ for (efa= (EditFace *)em->faces.first; efa; efa= efa->next) { if((efa->f & SELECT) && efa != efa_act) { int* recastDataBlock= (int*)CustomData_em_get(&em->fdata, efa->data, CD_RECAST); *recastDataBlock= targetPolyIdx; } } } else { BKE_report(op->reports, RPT_ERROR, "Active face has no index set"); } } } DAG_id_tag_update((ID*)obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); BKE_mesh_end_editmesh((Mesh*)obedit->data, em); return OPERATOR_FINISHED; }
/* makes Mesh out of editmesh */ void load_editMesh(Scene *scene, Object *obedit) { Mesh *me= obedit->data; MVert *mvert, *oldverts; MEdge *medge; MFace *mface; MSelect *mselect; EditMesh *em= me->edit_mesh; EditVert *eve; EditFace *efa, *efa_act; EditEdge *eed; EditSelection *ese; float *fp, *newkey, *oldkey; int i, a, ototvert; /* this one also tests of edges are not in faces: */ /* eed->f2==0: not in face, f2==1: draw it */ /* eed->f1 : flag for dynaface (cylindertest, old engine) */ /* eve->f1 : flag for dynaface (sphere test, old engine) */ /* eve->f2 : being used in vertexnormals */ edge_drawflags(me, em); EM_stats_update(em); /* new Vertex block */ if(em->totvert==0) mvert= NULL; else mvert= MEM_callocN(em->totvert*sizeof(MVert), "loadeditMesh vert"); /* new Edge block */ if(em->totedge==0) medge= NULL; else medge= MEM_callocN(em->totedge*sizeof(MEdge), "loadeditMesh edge"); /* new Face block */ if(em->totface==0) mface= NULL; else mface= MEM_callocN(em->totface*sizeof(MFace), "loadeditMesh face"); /* lets save the old verts just in case we are actually working on * a key ... we now do processing of the keys at the end */ oldverts= me->mvert; ototvert= me->totvert; /* don't free this yet */ CustomData_set_layer(&me->vdata, CD_MVERT, NULL); /* free custom data */ CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->edata, me->totedge); CustomData_free(&me->fdata, me->totface); /* add new custom data */ me->totvert= em->totvert; me->totedge= em->totedge; me->totface= em->totface; CustomData_copy(&em->vdata, &me->vdata, CD_MASK_MESH, CD_CALLOC, me->totvert); CustomData_copy(&em->edata, &me->edata, CD_MASK_MESH, CD_CALLOC, me->totedge); CustomData_copy(&em->fdata, &me->fdata, CD_MASK_MESH, CD_CALLOC, me->totface); CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert); CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge); CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, mface, me->totface); mesh_update_customdata_pointers(me); /* the vertices, use ->tmp.l as counter */ eve= em->verts.first; a= 0; while(eve) { VECCOPY(mvert->co, eve->co); /* vertex normal */ normal_float_to_short_v3(mvert->no, eve->no); /* note: it used to remove me->dvert when it was not in use, cancelled that... annoying when you have a fresh vgroup */ CustomData_from_em_block(&em->vdata, &me->vdata, eve->data, a); eve->tmp.l = a++; /* counter */ mvert->flag= 0; mvert->flag |= (eve->f & SELECT); if (eve->h) mvert->flag |= ME_HIDE; mvert->bweight= (char)(255.0f*eve->bweight); eve= eve->next; mvert++; } /* the edges */ a= 0; eed= em->edges.first; while(eed) { medge->v1= (unsigned int) eed->v1->tmp.l; medge->v2= (unsigned int) eed->v2->tmp.l; medge->flag= (eed->f & SELECT) | ME_EDGERENDER; if(eed->f2<2) medge->flag |= ME_EDGEDRAW; if(eed->f2==0) medge->flag |= ME_LOOSEEDGE; if(eed->sharp) medge->flag |= ME_SHARP; if(eed->seam) medge->flag |= ME_SEAM; if(eed->h & EM_FGON) medge->flag |= ME_FGON; // different defines yes if(eed->h & 1) medge->flag |= ME_HIDE; medge->crease= (char)(255.0f*eed->crease); medge->bweight= (char)(255.0f*eed->bweight); CustomData_from_em_block(&em->edata, &me->edata, eed->data, a); eed->tmp.l = a++; medge++; eed= eed->next; } /* the faces */ a = 0; efa= em->faces.first; efa_act= EM_get_actFace(em, 0); i = 0; me->act_face = -1; while(efa) { mface= &((MFace *) me->mface)[i]; mface->v1= (unsigned int) efa->v1->tmp.l; mface->v2= (unsigned int) efa->v2->tmp.l; mface->v3= (unsigned int) efa->v3->tmp.l; if (efa->v4) mface->v4 = (unsigned int) efa->v4->tmp.l; mface->mat_nr= efa->mat_nr; mface->flag= efa->flag; /* bit 0 of flag is already taken for smooth... */ if(efa->h) { mface->flag |= ME_HIDE; mface->flag &= ~ME_FACE_SEL; } else { if(efa->f & 1) mface->flag |= ME_FACE_SEL; else mface->flag &= ~ME_FACE_SEL; } /* watch: efa->e1->f2==0 means loose edge */ if(efa->e1->f2==1) { efa->e1->f2= 2; } if(efa->e2->f2==1) { efa->e2->f2= 2; } if(efa->e3->f2==1) { efa->e3->f2= 2; } if(efa->e4 && efa->e4->f2==1) { efa->e4->f2= 2; } CustomData_from_em_block(&em->fdata, &me->fdata, efa->data, i); /* no index '0' at location 3 or 4 */ test_index_face(mface, &me->fdata, i, efa->v4?4:3); if (efa_act == efa) me->act_face = a; efa->tmp.l = a++; i++; efa= efa->next; } /* patch hook indices and vertex parents */ { Object *ob; ModifierData *md; EditVert **vertMap = NULL; int j; for (ob=G.main->object.first; ob; ob=ob->id.next) { if (ob->parent==obedit && ELEM(ob->partype, PARVERT1,PARVERT3)) { /* duplicate code from below, make it function later...? */ if (!vertMap) { vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap"); for (eve=em->verts.first; eve; eve=eve->next) { if (eve->keyindex!=-1) vertMap[eve->keyindex] = eve; } } if(ob->par1 < ototvert) { eve = vertMap[ob->par1]; if(eve) ob->par1= eve->tmp.l; } if(ob->par2 < ototvert) { eve = vertMap[ob->par2]; if(eve) ob->par2= eve->tmp.l; } if(ob->par3 < ototvert) { eve = vertMap[ob->par3]; if(eve) ob->par3= eve->tmp.l; } } if (ob->data==me) { for (md=ob->modifiers.first; md; md=md->next) { if (md->type==eModifierType_Hook) { HookModifierData *hmd = (HookModifierData*) md; if (!vertMap) { vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap"); for (eve=em->verts.first; eve; eve=eve->next) { if (eve->keyindex!=-1) vertMap[eve->keyindex] = eve; } } for (i=j=0; i<hmd->totindex; i++) { if(hmd->indexar[i] < ototvert) { eve = vertMap[hmd->indexar[i]]; if (eve) { hmd->indexar[j++] = eve->tmp.l; } } else j++; } hmd->totindex = j; } } } } if (vertMap) MEM_freeN(vertMap); } /* are there keys? */ if(me->key) { KeyBlock *currkey; KeyBlock *actkey= BLI_findlink(&me->key->block, em->shapenr-1); float (*ofs)[3] = NULL; /* editing the base key should update others */ if(me->key->type==KEY_RELATIVE && oldverts) { int act_is_basis = 0; /* find if this key is a basis for any others */ for(currkey = me->key->block.first; currkey; currkey= currkey->next) { if(em->shapenr-1 == currkey->relative) { act_is_basis = 1; break; } } if(act_is_basis) { /* active key is a base */ float (*fp)[3]= actkey->data; i=0; ofs= MEM_callocN(sizeof(float) * 3 * em->totvert, "currkey->data"); eve= em->verts.first; mvert = me->mvert; while(eve) { if(eve->keyindex>=0) { sub_v3_v3v3(ofs[i], mvert->co, fp[eve->keyindex]); } eve= eve->next; i++; mvert++; } } } /* Lets reorder the key data so that things line up roughly * with the way things were before editmode */ currkey = me->key->block.first; while(currkey) { int apply_offset = (ofs && (currkey != actkey) && (em->shapenr-1 == currkey->relative)); fp= newkey= MEM_callocN(me->key->elemsize*em->totvert, "currkey->data"); oldkey = currkey->data; eve= em->verts.first; i = 0; mvert = me->mvert; while(eve) { if (eve->keyindex >= 0 && eve->keyindex < currkey->totelem) { // valid old vertex if(currkey == actkey) { if(actkey == me->key->refkey) { VECCOPY(fp, mvert->co); } else { VECCOPY(fp, mvert->co); if(oldverts) { VECCOPY(mvert->co, oldverts[eve->keyindex].co); } } } else { if(oldkey) { VECCOPY(fp, oldkey + 3 * eve->keyindex); } } } else { VECCOPY(fp, mvert->co); } /* propagate edited basis offsets to other shapes */ if(apply_offset) { VECADD(fp, fp, ofs[i]); } fp+= 3; ++i; ++mvert; eve= eve->next; } currkey->totelem= em->totvert; if(currkey->data) MEM_freeN(currkey->data); currkey->data = newkey; currkey= currkey->next; } if(ofs) MEM_freeN(ofs); } if(oldverts) MEM_freeN(oldverts); i = 0; for(ese=em->selected.first; ese; ese=ese->next) i++; me->totselect = i; if(i==0) mselect= NULL; else mselect= MEM_callocN(i*sizeof(MSelect), "loadeditMesh selections"); if(me->mselect) MEM_freeN(me->mselect); me->mselect= mselect; for(ese=em->selected.first; ese; ese=ese->next){ mselect->type = ese->type; if(ese->type == EDITVERT) mselect->index = ((EditVert*)ese->data)->tmp.l; else if(ese->type == EDITEDGE) mselect->index = ((EditEdge*)ese->data)->tmp.l; else if(ese->type == EDITFACE) mselect->index = ((EditFace*)ese->data)->tmp.l; mselect++; } /* to be sure: clear ->tmp.l pointers */ eve= em->verts.first; while(eve) { eve->tmp.l = 0; eve= eve->next; } eed= em->edges.first; while(eed) { eed->tmp.l = 0; eed= eed->next; } efa= em->faces.first; while(efa) { efa->tmp.l = 0; efa= efa->next; } /* remake softbody of all users */ if(me->id.us>1) { Base *base; for(base= scene->base.first; base; base= base->next) if(base->object->data==me) base->object->recalc |= OB_RECALC_DATA; } mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); /* topology could be changed, ensure mdisps are ok */ multires_topology_changed(scene, obedit); }