/* frees all editmode stuff */ void ED_editors_exit(bContext *C) { Main *bmain= CTX_data_main(C); Scene *sce; if(!bmain) return; /* frees all editmode undos */ undo_editmode_clear(); ED_undo_paint_free(); for(sce=bmain->scene.first; sce; sce= sce->id.next) { if(sce->obedit) { Object *ob= sce->obedit; /* global in meshtools... */ mesh_octree_table(NULL, NULL, NULL, 'e'); mesh_mirrtopo_table(NULL, 'e'); if(ob) { if(ob->type==OB_MESH) { Mesh *me= ob->data; if(me->edit_mesh) { free_editMesh(me->edit_mesh); MEM_freeN(me->edit_mesh); me->edit_mesh= NULL; } } else if(ob->type==OB_ARMATURE) { ED_armature_edit_free(ob); } else if(ob->type==OB_FONT) { // free_editText(); } // else if(ob->type==OB_MBALL) // BLI_freelistN(&editelems); // free_editLatt(); // free_posebuf(); // XXX this is still a global... } } else if(sce->basact && sce->basact->object) { Object *ob= sce->basact->object; /* if weight-painting is on, free mesh octree data */ if(ob->mode & OB_MODE_WEIGHT_PAINT) { mesh_octree_table(NULL, NULL, NULL, 'e'); mesh_mirrtopo_table(NULL, 'e'); } } } }
/* if end, ob can be NULL */ intptr_t mesh_octree_table(Object *ob, EditMesh *em, float *co, char mode) { MocNode **bt; if(mode=='u') { /* use table */ if(MeshOctree.table==NULL) mesh_octree_table(ob, em, NULL, 's'); if(MeshOctree.table) { Mesh *me= ob->data; bt= MeshOctree.table + mesh_octree_get_base_offs(co, MeshOctree.offs, MeshOctree.div); if(em) return mesh_octree_find_index(bt, NULL, co); else return mesh_octree_find_index(bt, me->mvert, co); } return -1; } else if(mode=='s') { /* start table */ Mesh *me= ob->data; float min[3], max[3]; /* we compute own bounding box and don't reuse ob->bb because * we are using the undeformed coordinates*/ INIT_MINMAX(min, max); if(em && me->edit_mesh==em) { EditVert *eve; for(eve= em->verts.first; eve; eve= eve->next) DO_MINMAX(eve->co, min, max) }
/* frees all editmode stuff */ void ED_editors_exit(bContext *C) { Main *bmain= CTX_data_main(C); Scene *sce; if(!bmain) return; /* frees all editmode undos */ undo_editmode_clear(); ED_undo_paint_free(); for(sce=bmain->scene.first; sce; sce= sce->id.next) { if(sce->obedit) { Object *ob= sce->obedit; if(ob) { if(ob->type==OB_MESH) { Mesh *me= ob->data; if(me->edit_mesh) { free_editMesh(me->edit_mesh); MEM_freeN(me->edit_mesh); me->edit_mesh= NULL; } } else if(ob->type==OB_ARMATURE) { ED_armature_edit_free(ob); } } } } /* global in meshtools... */ mesh_octree_table(NULL, NULL, NULL, 'e'); mesh_mirrtopo_table(NULL, 'e'); }
static int object_shape_key_mirror(bContext *C, Object *ob) { KeyBlock *kb; Key *key; key= ob_get_key(ob); if(key==NULL) return 0; kb= BLI_findlink(&key->block, ob->shapenr-1); if(kb) { int i1, i2; float *fp1, *fp2; float tvec[3]; char *tag_elem= MEM_callocN(sizeof(char) * kb->totelem, "shape_key_mirror"); if(ob->type==OB_MESH) { Mesh *me= ob->data; MVert *mv; mesh_octree_table(ob, NULL, NULL, 's'); for(i1=0, mv=me->mvert; i1<me->totvert; i1++, mv++) { i2= mesh_get_x_mirror_vert(ob, i1); if(i2==i1) { fp1= ((float *)kb->data) + i1*3; fp1[0] = -fp1[0]; tag_elem[i1]= 1; } else if(i2 != -1) { if(tag_elem[i1]==0 && tag_elem[i2]==0) { fp1= ((float *)kb->data) + i1*3; fp2= ((float *)kb->data) + i2*3; copy_v3_v3(tvec, fp1); copy_v3_v3(fp1, fp2); copy_v3_v3(fp2, tvec); /* flip x axis */ fp1[0] = -fp1[0]; fp2[0] = -fp2[0]; } tag_elem[i1]= tag_elem[i2]= 1; } } mesh_octree_table(ob, NULL, NULL, 'e'); } else if (ob->type == OB_LATTICE) { Lattice *lt= ob->data; int i1, i2; float *fp1, *fp2; int u, v, w; /* half but found up odd value */ const int pntsu_half = (((lt->pntsu / 2) + (lt->pntsu % 2))) ; /* currently editmode isnt supported by mesh so * ignore here for now too */ /* if(lt->editlatt) lt= lt->editlatt->latt; */ for(w=0; w<lt->pntsw; w++) { for(v=0; v<lt->pntsv; v++) { for(u=0; u<pntsu_half; u++) { int u_inv= (lt->pntsu - 1) - u; float tvec[3]; if(u == u_inv) { i1= LT_INDEX(lt, u, v, w); fp1= ((float *)kb->data) + i1*3; fp1[0]= -fp1[0]; } else { i1= LT_INDEX(lt, u, v, w); i2= LT_INDEX(lt, u_inv, v, w); fp1= ((float *)kb->data) + i1*3; fp2= ((float *)kb->data) + i2*3; copy_v3_v3(tvec, fp1); copy_v3_v3(fp1, fp2); copy_v3_v3(fp2, tvec); fp1[0]= -fp1[0]; fp2[0]= -fp2[0]; } } } } } MEM_freeN(tag_elem); } DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); return 1; }
void ED_object_exit_editmode(bContext *C, int flag) { /* Note! only in exceptional cases should 'EM_DO_UNDO' NOT be in the flag */ Scene *scene= CTX_data_scene(C); Object *obedit= CTX_data_edit_object(C); int freedata = flag & EM_FREEDATA; if (obedit==NULL) return; if (flag & EM_WAITCURSOR) waitcursor(1); if (obedit->type==OB_MESH) { Mesh *me= obedit->data; // if (EM_texFaceCheck()) if (me->edit_btmesh->bm->totvert>MESH_MAX_VERTS) { error("Too many vertices"); return; } EDBM_mesh_load(obedit); if (freedata) { EDBM_mesh_free(me->edit_btmesh); MEM_freeN(me->edit_btmesh); me->edit_btmesh= NULL; } if (obedit->restore_mode & OB_MODE_WEIGHT_PAINT) { mesh_octree_table(NULL, NULL, NULL, 'e'); mesh_mirrtopo_table(NULL, 'e'); } } else if (obedit->type==OB_ARMATURE) { ED_armature_from_edit(obedit); if (freedata) ED_armature_edit_free(obedit); } else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { load_editNurb(obedit); if (freedata) free_editNurb(obedit); } else if (obedit->type==OB_FONT && freedata) { load_editText(obedit); if (freedata) free_editText(obedit); } else if (obedit->type==OB_LATTICE) { load_editLatt(obedit); if (freedata) free_editLatt(obedit); } else if (obedit->type==OB_MBALL) { load_editMball(obedit); if (freedata) free_editMball(obedit); } /* freedata only 0 now on file saves and render */ if (freedata) { ListBase pidlist; PTCacheID *pid; /* for example; displist make is different in editmode */ scene->obedit= NULL; // XXX for context /* flag object caches as outdated */ BKE_ptcache_ids_from_object(&pidlist, obedit, NULL, 0); for (pid=pidlist.first; pid; pid=pid->next) { if (pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */ pid->cache->flag |= PTCACHE_OUTDATED; } BLI_freelistN(&pidlist); BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED); /* also flush ob recalc, doesn't take much overhead, but used for particles */ DAG_id_tag_update(&obedit->id, OB_RECALC_OB|OB_RECALC_DATA); if (flag & EM_DO_UNDO) ED_undo_push(C, "Editmode"); if (flag & EM_WAITCURSOR) waitcursor(0); WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, scene); obedit->mode &= ~OB_MODE_EDIT; } }
/* do not free editmesh itself here */ void free_editMesh(EditMesh *em) { if(em==NULL) return; if(em->verts.first) free_vertlist(em, &em->verts); if(em->edges.first) free_edgelist(em, &em->edges); if(em->faces.first) free_facelist(em, &em->faces); if(em->selected.first) BLI_freelistN(&(em->selected)); CustomData_free(&em->vdata, 0); CustomData_free(&em->fdata, 0); if(em->derivedFinal) { if (em->derivedFinal!=em->derivedCage) { em->derivedFinal->needsFree= 1; em->derivedFinal->release(em->derivedFinal); } em->derivedFinal= NULL; } if(em->derivedCage) { em->derivedCage->needsFree= 1; em->derivedCage->release(em->derivedCage); em->derivedCage= NULL; } /* DEBUG: hashtabs are slowest part of enter/exit editmode. here a testprint */ #if 0 if(em->hashedgetab) { HashEdge *he, *hen; int a, used=0, max=0, nr; he= em->hashedgetab; for(a=0; a<EDHASHSIZE; a++, he++) { if(he->eed) used++; hen= he->next; nr= 0; while(hen) { nr++; hen= hen->next; } if(max<nr) max= nr; } printf("hastab used %d max %d\n", used, max); } #endif if(em->hashedgetab) MEM_freeN(em->hashedgetab); em->hashedgetab= NULL; if(em->allverts) MEM_freeN(em->allverts); if(em->alledges) MEM_freeN(em->alledges); if(em->allfaces) MEM_freeN(em->allfaces); em->allverts= em->curvert= NULL; em->alledges= em->curedge= NULL; em->allfaces= em->curface= NULL; mesh_octree_table(NULL, NULL, NULL, 'e'); mesh_mirrtopo_table(NULL, 'e'); em->totvert= em->totedge= em->totface= 0; em->act_face = NULL; }