static int object_hook_index_array(Object *obedit, int *tot, int **indexar, char *name, float *cent_r) { *indexar= NULL; *tot= 0; name[0]= 0; switch(obedit->type) { case OB_MESH: { Mesh *me= obedit->data; EditMesh *em = BKE_mesh_get_editmesh(me); /* check selected vertices first */ if( return_editmesh_indexar(em, tot, indexar, cent_r)) { BKE_mesh_end_editmesh(me, em); return 1; } else { int ret = return_editmesh_vgroup(obedit, em, name, cent_r); BKE_mesh_end_editmesh(me, em); return ret; } } case OB_CURVE: case OB_SURF: return return_editcurve_indexar(obedit, tot, indexar, cent_r); case OB_LATTICE: { Lattice *lt= obedit->data; return return_editlattice_indexar(lt->editlatt->latt, tot, indexar, cent_r); } default: return 0; } }
/* return 1: success */ static int mesh_separate_loose(wmOperator *op, Main *bmain, Scene *scene, Base *editbase) { Mesh *me; EditMesh *em; int doit= 1; me= editbase->object->data; em= BKE_mesh_get_editmesh(me); if(me->key) { error("Can't separate with vertex keys"); BKE_mesh_end_editmesh(me, em); return 0; } EM_clear_flag_all(em, SELECT); while(doit) { /* Select a random vert to start with */ EditVert *eve; int tot; /* check if all verts that are visible have been done */ for(eve=em->verts.first; eve; eve= eve->next) if(!eve->h) break; if(eve==NULL) break; /* only hidden verts left, quit early */ /* first non hidden vert */ eve->f |= SELECT; selectconnected_mesh_all(em); /* don't separate the very last part */ for(eve=em->verts.first; eve; eve= eve->next) if((eve->f & SELECT)==0) break; if(eve==NULL) break; tot= BLI_countlist(&em->verts); /* and now separate */ doit= mesh_separate_selected(op, bmain, scene, editbase); /* with hidden verts this can happen */ if(tot == BLI_countlist(&em->verts)) break; } BKE_mesh_end_editmesh(me, em); return 1; }
static int clear_fgon_exec(bContext *C, wmOperator *op) { Object *obedit= CTX_data_edit_object(C); EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); if( make_fgon(em, op, 0) ) { DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED; }
static int navmesh_face_add_exec(bContext *C, wmOperator *UNUSED(op)) { Object *obedit= CTX_data_edit_object(C); EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); EditFace *ef; if(CustomData_has_layer(&em->fdata, CD_RECAST)) { int targetPolyIdx= findFreeNavPolyIndex(em); if(targetPolyIdx>0) { /* set target poly idx to selected faces */ ef= (EditFace*)em->faces.last; while(ef) { if(ef->f & SELECT) { int *recastDataBlock= (int*)CustomData_em_get(&em->fdata, ef->data, CD_RECAST); *recastDataBlock= targetPolyIdx; } ef= ef->prev; } } } 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; }
/* removes from active defgroup, if allverts==0 only selected vertices */ static void vgroup_active_remove_verts(Object *ob, int allverts) { EditVert *eve; MDeformVert *dvert; MDeformWeight *newdw; bDeformGroup *dg, *eg; int i; dg=BLI_findlink(&ob->defbase, ob->actdef-1); if(!dg) return; if(ob->type == OB_MESH) { Mesh *me= ob->data; EditMesh *em = BKE_mesh_get_editmesh(me); for(eve=em->verts.first; eve; eve=eve->next){ dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); if(dvert && dvert->dw && ((eve->f & 1) || allverts)){ for(i=0; i<dvert->totweight; i++){ /* Find group */ eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr); if(eg == dg){ dvert->totweight--; if(dvert->totweight){ newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), "deformWeight"); if(dvert->dw){ memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i); memcpy(newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i)); MEM_freeN(dvert->dw); } dvert->dw=newdw; } else{ MEM_freeN(dvert->dw); dvert->dw=NULL; break; } } } } } BKE_mesh_end_editmesh(me, em); } else if(ob->type == OB_LATTICE) { Lattice *lt= vgroup_edit_lattice(ob); if(lt->dvert) { BPoint *bp; int a, tot= lt->pntsu*lt->pntsv*lt->pntsw; for(a=0, bp= lt->def; a<tot; a++, bp++) { if(allverts || (bp->f1 & SELECT)) ED_vgroup_vert_remove(ob, dg, a); } } } }
/* only in editmode */ static void vgroup_select_verts(Object *ob, int select) { EditVert *eve; MDeformVert *dvert; int i; if(ob->type == OB_MESH) { Mesh *me= ob->data; EditMesh *em = BKE_mesh_get_editmesh(me); for(eve=em->verts.first; eve; eve=eve->next){ dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); if(dvert && dvert->totweight){ for(i=0; i<dvert->totweight; i++){ if(dvert->dw[i].def_nr == (ob->actdef-1)){ if(select) eve->f |= SELECT; else eve->f &= ~SELECT; break; } } } } /* this has to be called, because this function operates on vertices only */ if(select) EM_select_flush(em); // vertices to edges/faces else EM_deselect_flush(em); BKE_mesh_end_editmesh(me, em); } else if(ob->type == OB_LATTICE) { Lattice *lt= vgroup_edit_lattice(ob); if(lt->dvert) { BPoint *bp; int a, tot; dvert= lt->dvert; tot= lt->pntsu*lt->pntsv*lt->pntsw; for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) { for(i=0; i<dvert->totweight; i++){ if(dvert->dw[i].def_nr == (ob->actdef-1)) { if(select) bp->f1 |= SELECT; else bp->f1 &= ~SELECT; break; } } } } } }
static int addedgeface_mesh_exec(bContext *C, wmOperator *op) { Object *obedit= CTX_data_edit_object(C); EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); addedgeface_mesh(em, op); DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; }
static int mesh_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob= CTX_data_edit_object(C); EditMesh *em= BKE_mesh_get_editmesh(ob->data); adduplicateflag(em, SELECT); BKE_mesh_end_editmesh(ob->data, em); DAG_id_tag_update(ob->data, 0); WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); return OPERATOR_FINISHED; }
static void act_vert_def(Object *ob, EditVert **eve, MDeformVert **dvert) { if(ob && ob->mode & OB_MODE_EDIT && ob->type==OB_MESH && ob->defbase.first) { Mesh *me= ob->data; EditMesh *em = BKE_mesh_get_editmesh(me); EditSelection *ese = ((EditSelection*)em->selected.last); if(ese && ese->type == EDITVERT) { *eve= (EditVert*)ese->data; *dvert= CustomData_em_get(&em->vdata, (*eve)->data, CD_MDEFORMVERT); return; } BKE_mesh_end_editmesh(me, em); } *eve= NULL; *dvert= NULL; }
static void select_editmesh_hook(Object *ob, HookModifierData *hmd) { Mesh *me= ob->data; EditMesh *em= BKE_mesh_get_editmesh(me); EditVert *eve; int index=0, nr=0; if (hmd->indexar == NULL) return; for(eve= em->verts.first; eve; eve= eve->next, nr++) { if(nr==hmd->indexar[index]) { eve->f |= SELECT; if(index < hmd->totindex-1) index++; } } EM_select_flush(em); BKE_mesh_end_editmesh(me, em); }
void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C) { Object *obedit = CTX_data_edit_object(C); uiBlock *block= uiLayoutGetBlock(layout); uiBlockSetHandleFunc(block, do_view3d_header_buttons, NULL); if(obedit && (obedit->type == OB_MESH)) { EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); uiLayout *row; row= uiLayoutRow(layout, 1); block= uiLayoutGetBlock(row); uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, 0,0,UI_UNIT_X,UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode"); uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, 0,0,UI_UNIT_X,UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Edge select mode"); uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, 0,0,UI_UNIT_X,UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Face select mode"); BKE_mesh_end_editmesh(obedit->data, em); } }
/* return 1: success */ static int mesh_separate_material(wmOperator *op, Main *bmain, Scene *scene, Base *editbase) { Mesh *me= editbase->object->data; EditMesh *em= BKE_mesh_get_editmesh(me); unsigned char curr_mat; for (curr_mat = 1; curr_mat < editbase->object->totcol; ++curr_mat) { /* clear selection, we're going to use that to select material group */ EM_clear_flag_all(em, SELECT); /* select the material */ EM_select_by_material(em, curr_mat); /* and now separate */ if(em->totfacesel > 0) { mesh_separate_selected(op, bmain, scene, editbase); } } BKE_mesh_end_editmesh(me, em); return 1; }
static void draw_uvs_shadow(SpaceImage *sima, Object *obedit) { EditMesh *em; EditFace *efa; MTFace *tf; em= BKE_mesh_get_editmesh((Mesh*)obedit->data); /* draws the grey mesh when painting */ glColor3ub(112, 112, 112); for(efa= em->faces.first; efa; efa= efa->next) { tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); glBegin(GL_LINE_LOOP); glVertex2fv(tf->uv[0]); glVertex2fv(tf->uv[1]); glVertex2fv(tf->uv[2]); if(efa->v4) glVertex2fv(tf->uv[3]); glEnd(); } BKE_mesh_end_editmesh(obedit->data, em); }
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; }
/* only in editmode */ static void vgroup_assign_verts(Object *ob, float weight) { EditVert *eve; bDeformGroup *dg, *eg; MDeformWeight *newdw; MDeformVert *dvert; int i, done; dg=BLI_findlink(&ob->defbase, ob->actdef-1); if(!dg) return; if(ob->type == OB_MESH) { Mesh *me= ob->data; EditMesh *em = BKE_mesh_get_editmesh(me); if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) EM_add_data_layer(em, &em->vdata, CD_MDEFORMVERT); /* Go through the list of editverts and assign them */ for(eve=em->verts.first; eve; eve=eve->next){ dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); if(dvert && (eve->f & 1)){ done=0; /* See if this vert already has a reference to this group */ /* If so: Change its weight */ done=0; for(i=0; i<dvert->totweight; i++){ eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr); /* Find the actual group */ if(eg==dg){ dvert->dw[i].weight= weight; done=1; break; } } /* If not: Add the group and set its weight */ if(!done){ newdw = MEM_callocN(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight"); if(dvert->dw){ memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight); MEM_freeN(dvert->dw); } dvert->dw=newdw; dvert->dw[dvert->totweight].weight= weight; dvert->dw[dvert->totweight].def_nr= ob->actdef-1; dvert->totweight++; } } } BKE_mesh_end_editmesh(me, em); } else if(ob->type == OB_LATTICE) { Lattice *lt= vgroup_edit_lattice(ob); BPoint *bp; int a, tot; if(lt->dvert==NULL) ED_vgroup_data_create(<->id); tot= lt->pntsu*lt->pntsv*lt->pntsw; for(a=0, bp= lt->def; a<tot; a++, bp++) { if(bp->f1 & SELECT) ED_vgroup_nr_vert_add(ob, ob->actdef-1, a, weight, WEIGHT_REPLACE); } } }
static void vgroup_delete_edit_mode(Object *ob) { bDeformGroup *defgroup; int i; if(!ob->actdef) return; defgroup = BLI_findlink(&ob->defbase, ob->actdef-1); if(!defgroup) return; /* Make sure that no verts are using this group */ vgroup_active_remove_verts(ob, 1); /* Make sure that any verts with higher indices are adjusted accordingly */ if(ob->type==OB_MESH) { Mesh *me= ob->data; EditMesh *em = BKE_mesh_get_editmesh(me); EditVert *eve; MDeformVert *dvert; for(eve=em->verts.first; eve; eve=eve->next){ dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); if(dvert) for(i=0; i<dvert->totweight; i++) if(dvert->dw[i].def_nr > (ob->actdef-1)) dvert->dw[i].def_nr--; } BKE_mesh_end_editmesh(me, em); } else if(ob->type==OB_LATTICE) { Lattice *lt= vgroup_edit_lattice(ob); BPoint *bp; MDeformVert *dvert= lt->dvert; int a, tot; if(dvert) { tot= lt->pntsu*lt->pntsv*lt->pntsw; for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) { for(i=0; i<dvert->totweight; i++){ if(dvert->dw[i].def_nr > (ob->actdef-1)) dvert->dw[i].def_nr--; } } } } vgroup_delete_update_users(ob, ob->actdef); /* Update the active deform index if necessary */ if(ob->actdef==BLI_countlist(&ob->defbase)) ob->actdef--; /* Remove the group */ BLI_freelinkN (&ob->defbase, defgroup); /* remove all dverts */ if(ob->actdef==0) { if(ob->type==OB_MESH) { Mesh *me= ob->data; CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert); me->dvert= NULL; } else if(ob->type==OB_LATTICE) { Lattice *lt= vgroup_edit_lattice(ob); if(lt->dvert) { MEM_freeN(lt->dvert); lt->dvert= NULL; } } } }
/* is used for both read and write... */ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float lim) { uiBlock *block= (layout)? uiLayoutAbsoluteBlock(layout): NULL; MDeformVert *dvert=NULL; TransformProperties *tfp; float median[6], ve_median[6]; int tot, totw, totweight, totedge, totradius; char defstr[320]; median[0]= median[1]= median[2]= median[3]= median[4]= median[5]= 0.0; tot= totw= totweight= totedge= totradius= 0; defstr[0]= 0; /* make sure we got storage */ if(v3d->properties_storage==NULL) v3d->properties_storage= MEM_callocN(sizeof(TransformProperties), "TransformProperties"); tfp= v3d->properties_storage; if(ob->type==OB_MESH) { Mesh *me= ob->data; EditMesh *em = BKE_mesh_get_editmesh(me); EditVert *eve, *evedef=NULL; EditEdge *eed; eve= em->verts.first; while(eve) { if(eve->f & SELECT) { evedef= eve; tot++; add_v3_v3(median, eve->co); } eve= eve->next; } eed= em->edges.first; while(eed) { if((eed->f & SELECT)) { totedge++; median[3]+= eed->crease; } eed= eed->next; } /* check for defgroups */ if(evedef) dvert= CustomData_em_get(&em->vdata, evedef->data, CD_MDEFORMVERT); if(tot==1 && dvert && dvert->totweight) { bDeformGroup *dg; int i, max=1, init=1; char str[320]; for (i=0; i<dvert->totweight; i++){ dg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr); if(dg) { max+= BLI_snprintf(str, sizeof(str), "%s %%x%d|", dg->name, dvert->dw[i].def_nr); if(max<320) strcat(defstr, str); } if(tfp->curdef==dvert->dw[i].def_nr) { init= 0; tfp->defweightp= &dvert->dw[i].weight; } } if(init) { // needs new initialized tfp->curdef= dvert->dw[0].def_nr; tfp->defweightp= &dvert->dw[0].weight; } } BKE_mesh_end_editmesh(me, em); } else if(ob->type==OB_CURVE || ob->type==OB_SURF) { Curve *cu= ob->data; Nurb *nu; BPoint *bp; BezTriple *bezt; int a; ListBase *nurbs= ED_curve_editnurbs(cu); nu= nurbs->first; while(nu) { if(nu->type == CU_BEZIER) { bezt= nu->bezt; a= nu->pntsu; while(a--) { if(bezt->f2 & SELECT) { add_v3_v3(median, bezt->vec[1]); tot++; median[4]+= bezt->weight; totweight++; median[5]+= bezt->radius; totradius++; } else { if(bezt->f1 & SELECT) { add_v3_v3(median, bezt->vec[0]); tot++; } if(bezt->f3 & SELECT) { add_v3_v3(median, bezt->vec[2]); tot++; } } bezt++; } } else { bp= nu->bp; a= nu->pntsu*nu->pntsv; while(a--) { if(bp->f1 & SELECT) { add_v3_v3(median, bp->vec); median[3]+= bp->vec[3]; totw++; tot++; median[4]+= bp->weight; totweight++; median[5]+= bp->radius; totradius++; } bp++; } } nu= nu->next; } } else if(ob->type==OB_LATTICE) { Lattice *lt= ob->data; BPoint *bp; int a; a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw; bp= lt->editlatt->latt->def; while(a--) { if(bp->f1 & SELECT) { add_v3_v3(median, bp->vec); tot++; median[4]+= bp->weight; totweight++; } bp++; } } if(tot==0) { uiDefBut(block, LABEL, 0, "Nothing selected",0, 130, 200, 20, NULL, 0, 0, 0, 0, ""); return; } median[0] /= (float)tot; median[1] /= (float)tot; median[2] /= (float)tot; if(totedge) median[3] /= (float)totedge; else if(totw) median[3] /= (float)totw; if(totweight) median[4] /= (float)totweight; if(totradius) median[5] /= (float)totradius; if(v3d->flag & V3D_GLOBAL_STATS) mul_m4_v3(ob->obmat, median); if(block) { // buttons uiBut *but; memcpy(tfp->ve_median, median, sizeof(tfp->ve_median)); uiBlockBeginAlign(block); if(tot==1) { uiDefBut(block, LABEL, 0, "Vertex:", 0, 130, 200, 20, NULL, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:", 0, 110, 200, 20, &(tfp->ve_median[0]), -lim, lim, 10, 3, ""); uiButSetUnitType(but, PROP_UNIT_LENGTH); but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Y:", 0, 90, 200, 20, &(tfp->ve_median[1]), -lim, lim, 10, 3, ""); uiButSetUnitType(but, PROP_UNIT_LENGTH); but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Z:", 0, 70, 200, 20, &(tfp->ve_median[2]), -lim, lim, 10, 3, ""); uiButSetUnitType(but, PROP_UNIT_LENGTH); if(totw==1) { uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:", 0, 50, 200, 20, &(tfp->ve_median[3]), 0.01, 100.0, 1, 3, ""); uiBlockBeginAlign(block); uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 0, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values"); uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 100, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values"); uiBlockEndAlign(block); if(totweight) uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 0, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 1, 3, ""); if(totradius) uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:", 0, 0, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 1, 3, "Radius of curve CPs"); } else { uiBlockBeginAlign(block); uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 0, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values"); uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 100, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values"); uiBlockEndAlign(block); if(totweight) uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 20, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, ""); if(totradius) uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:", 0, 20, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 10, 3, "Radius of curve CPs"); } } else { uiDefBut(block, LABEL, 0, "Median:", 0, 130, 200, 20, NULL, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:", 0, 110, 200, 20, &(tfp->ve_median[0]), -lim, lim, 10, 3, ""); uiButSetUnitType(but, PROP_UNIT_LENGTH); but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Y:", 0, 90, 200, 20, &(tfp->ve_median[1]), -lim, lim, 10, 3, ""); uiButSetUnitType(but, PROP_UNIT_LENGTH); but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Z:", 0, 70, 200, 20, &(tfp->ve_median[2]), -lim, lim, 10, 3, ""); uiButSetUnitType(but, PROP_UNIT_LENGTH); if(totw==tot) { uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:", 0, 50, 200, 20, &(tfp->ve_median[3]), 0.01, 100.0, 1, 3, ""); uiBlockEndAlign(block); uiBlockBeginAlign(block); uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 0, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values"); uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 100, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values"); uiBlockEndAlign(block); if(totweight) uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 0, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "Weight is used for SoftBody Goal"); if(totradius) uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:", 0, 0, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 10, 3, "Radius of curve CPs"); uiBlockEndAlign(block); } else { uiBlockBeginAlign(block); uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 0, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values"); uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 100, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values"); uiBlockEndAlign(block); if(totweight) uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 20, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 1, 3, "Weight is used for SoftBody Goal"); if(totradius) uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:", 0, 0, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 1, 3, "Radius of curve CPs"); uiBlockEndAlign(block); } } if(totedge==1) uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Crease:", 0, 20, 200, 20, &(tfp->ve_median[3]), 0.0, 1.0, 1, 3, ""); else if(totedge>1) uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Mean Crease:", 0, 20, 200, 20, &(tfp->ve_median[3]), 0.0, 1.0, 1, 3, ""); } else { // apply memcpy(ve_median, tfp->ve_median, sizeof(tfp->ve_median)); if(v3d->flag & V3D_GLOBAL_STATS) { invert_m4_m4(ob->imat, ob->obmat); mul_m4_v3(ob->imat, median); mul_m4_v3(ob->imat, ve_median); } sub_v3_v3v3(median, ve_median, median); median[3]= ve_median[3]-median[3]; median[4]= ve_median[4]-median[4]; median[5]= ve_median[5]-median[5]; if(ob->type==OB_MESH) { Mesh *me= ob->data; EditMesh *em = BKE_mesh_get_editmesh(me); /* allow for some rounding error becasue of matrix transform */ if(len_v3(median) > 0.000001f) { EditVert *eve; for(eve= em->verts.first; eve; eve= eve->next) { if(eve->f & SELECT) { add_v3_v3(eve->co, median); } } recalc_editnormals(em); } if(median[3] != 0.0f) { EditEdge *eed; const float fixed_crease= (ve_median[3] <= 0.0f ? 0.0f : (ve_median[3] >= 1.0f ? 1.0f : FLT_MAX)); if(fixed_crease != FLT_MAX) { /* simple case */ for(eed= em->edges.first; eed; eed= eed->next) { if(eed->f & SELECT) { eed->crease= fixed_crease; } } } else { /* scale crease to target median */ float median_new= ve_median[3]; float median_orig= ve_median[3] - median[3]; /* previous median value */ /* incase of floating point error */ CLAMP(median_orig, 0.0f, 1.0f); CLAMP(median_new, 0.0f, 1.0f); if(median_new < median_orig) { /* scale down */ const float sca= median_new / median_orig; for(eed= em->edges.first; eed; eed= eed->next) { if(eed->f & SELECT) { eed->crease *= sca; CLAMP(eed->crease, 0.0f, 1.0f); } } } else { /* scale up */ const float sca= (1.0f - median_new) / (1.0f - median_orig); for(eed= em->edges.first; eed; eed= eed->next) { if(eed->f & SELECT) { eed->crease = 1.0f - ((1.0f - eed->crease) * sca); CLAMP(eed->crease, 0.0f, 1.0f); } } } } } BKE_mesh_end_editmesh(me, em); } else if(ob->type==OB_CURVE || ob->type==OB_SURF) { Curve *cu= ob->data; Nurb *nu; BPoint *bp; BezTriple *bezt; int a; ListBase *nurbs= ED_curve_editnurbs(cu); nu= nurbs->first; while(nu) { if(nu->type == CU_BEZIER) { bezt= nu->bezt; a= nu->pntsu; while(a--) { if(bezt->f2 & SELECT) { add_v3_v3(bezt->vec[0], median); add_v3_v3(bezt->vec[1], median); add_v3_v3(bezt->vec[2], median); bezt->weight+= median[4]; bezt->radius+= median[5]; } else { if(bezt->f1 & SELECT) { add_v3_v3(bezt->vec[0], median); } if(bezt->f3 & SELECT) { add_v3_v3(bezt->vec[2], median); } } bezt++; } } else { bp= nu->bp; a= nu->pntsu*nu->pntsv; while(a--) { if(bp->f1 & SELECT) { add_v3_v3(bp->vec, median); bp->vec[3]+= median[3]; bp->weight+= median[4]; bp->radius+= median[5]; } bp++; } } test2DNurb(nu); testhandlesNurb(nu); /* test for bezier too */ nu= nu->next; } } else if(ob->type==OB_LATTICE) { Lattice *lt= ob->data; BPoint *bp; int a; a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw; bp= lt->editlatt->latt->def; while(a--) { if(bp->f1 & SELECT) { add_v3_v3(bp->vec, median); bp->weight+= median[4]; } bp++; } } // ED_undo_push(C, "Transform properties"); } }
static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) { wmWindow *win= CTX_wm_window(C); ToolSettings *ts= CTX_data_tool_settings(C); ScrArea *sa= CTX_wm_area(C); View3D *v3d= sa->spacedata.first; Object *obedit = CTX_data_edit_object(C); EditMesh *em= NULL; int ctrl= win->eventstate->ctrl, shift= win->eventstate->shift; PointerRNA props_ptr; if(obedit && obedit->type==OB_MESH) { em= BKE_mesh_get_editmesh((Mesh *)obedit->data); } /* watch it: if sa->win does not exist, check that when calling direct drawing routines */ switch(event) { case B_REDR: ED_area_tag_redraw(sa); break; case B_MODESELECT: WM_operator_properties_create(&props_ptr, "OBJECT_OT_mode_set"); RNA_enum_set(&props_ptr, "mode", v3d->modeselect); WM_operator_name_call(C, "OBJECT_OT_mode_set", WM_OP_EXEC_REGION_WIN, &props_ptr); WM_operator_properties_free(&props_ptr); break; case B_SEL_VERT: if(em) { if(shift==0 || em->selectmode==0) em->selectmode= SCE_SELECT_VERTEX; ts->selectmode= em->selectmode; EM_selectmode_set(em); WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); ED_undo_push(C, "Selectmode Set: Vertex"); } break; case B_SEL_EDGE: if(em) { if(shift==0 || em->selectmode==0){ if( (em->selectmode ^ SCE_SELECT_EDGE) == SCE_SELECT_VERTEX){ if(ctrl) EM_convertsel(em, SCE_SELECT_VERTEX,SCE_SELECT_EDGE); } em->selectmode = SCE_SELECT_EDGE; } ts->selectmode= em->selectmode; EM_selectmode_set(em); WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); ED_undo_push(C, "Selectmode Set: Edge"); } break; case B_SEL_FACE: if(em) { if( shift==0 || em->selectmode==0){ if( ((em->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || ((em->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)){ if(ctrl) EM_convertsel(em, (em->selectmode ^ SCE_SELECT_FACE),SCE_SELECT_FACE); } em->selectmode = SCE_SELECT_FACE; } ts->selectmode= em->selectmode; EM_selectmode_set(em); WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); ED_undo_push(C, "Selectmode Set: Face"); } break; case B_MAN_TRANS: if( shift==0 || v3d->twtype==0) { v3d->twtype= V3D_MANIP_TRANSLATE; } ED_area_tag_redraw(sa); break; case B_MAN_ROT: if( shift==0 || v3d->twtype==0) { v3d->twtype= V3D_MANIP_ROTATE; } ED_area_tag_redraw(sa); break; case B_MAN_SCALE: if( shift==0 || v3d->twtype==0) { v3d->twtype= V3D_MANIP_SCALE; } ED_area_tag_redraw(sa); break; case B_NDOF: ED_area_tag_redraw(sa); break; case B_MAN_MODE: ED_area_tag_redraw(sa); break; default: break; } if(obedit && obedit->type==OB_MESH) BKE_mesh_end_editmesh(obedit->data, em); }
static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int level, int animated) { Object *ob, *ob_iter; Mesh *me= par->data; Base *base = NULL; DerivedMesh *dm; struct vertexDupliData vdd; Scene *sce = NULL; Group *group = NULL; GroupObject * go = NULL; EditMesh *em; float vec[3], no[3], pmat[4][4]; int lay, totvert, a, oblay; Mat4CpyMat4(pmat, par->obmat); /* simple preventing of too deep nested groups */ if(level>MAX_DUPLI_RECUR) return; em = BKE_mesh_get_editmesh(me); if(em) { dm= editmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); BKE_mesh_end_editmesh(me, em); } else dm= mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH); if(G.rendering) { vdd.orco= (float(*)[3])get_mesh_orco_verts(par); transform_mesh_orco_verts(me, vdd.orco, me->totvert, 0); } else vdd.orco= NULL; totvert = dm->getNumVerts(dm); /* having to loop on scene OR group objects is NOT FUN */ if (GS(id->name) == ID_SCE) { sce = (Scene *)id; lay= sce->lay; base= sce->base.first; } else { group = (Group *)id; lay= group->layer; go = group->gobject.first; } /* Start looping on Scene OR Group objects */ while (base || go) { if (sce) { ob_iter= base->object; oblay = base->lay; } else { ob_iter= go->ob; oblay = ob_iter->lay; } if (lay & oblay && scene->obedit!=ob_iter) { ob=ob_iter->parent; while(ob) { if(ob==par) { ob = ob_iter; /* End Scene/Group object loop, below is generic */ /* par_space_mat - only used for groups so we can modify the space dupli's are in when par_space_mat is NULL ob->obmat can be used instead of ob__obmat */ if(par_space_mat) Mat4MulMat4(vdd.obmat, ob->obmat, par_space_mat); else Mat4CpyMat4(vdd.obmat, ob->obmat); vdd.id= id; vdd.level= level; vdd.animated= animated; vdd.lb= lb; vdd.ob= ob; vdd.scene= scene; vdd.par= par; Mat4CpyMat4(vdd.pmat, pmat); /* mballs have a different dupli handling */ if(ob->type!=OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ if(par->mode & OB_MODE_EDIT) { dm->foreachMappedVert(dm, vertex_dupli__mapFunc, (void*) &vdd); } else { for(a=0; a<totvert; a++) { dm->getVertCo(dm, a, vec); dm->getVertNo(dm, a, no); vertex_dupli__mapFunc(&vdd, a, vec, no, NULL); } } break; } ob= ob->parent; } } if (sce) base= base->next; /* scene loop */ else go= go->next; /* group loop */ } if(vdd.orco) MEM_freeN(vdd.orco); dm->release(dm); }
/* return 1: success */ static int mesh_separate_selected(wmOperator *op, Main *bmain, Scene *scene, Base *editbase) { EditMesh *em, *emnew; EditVert *eve, *v1; EditEdge *eed, *e1; EditFace *efa, *f1; Object *obedit; Mesh *me, *menew; Base *basenew; if(editbase==NULL) return 0; obedit= editbase->object; me= obedit->data; em= BKE_mesh_get_editmesh(me); if(me->key) { BKE_report(op->reports, RPT_WARNING, "Can't separate mesh with shape keys"); BKE_mesh_end_editmesh(me, em); return 0; } if(em->selected.first) BLI_freelistN(&(em->selected)); /* clear the selection order */ EM_selectmode_set(em); // enforce full consistent selection flags EM_stats_update(em); if(em->totvertsel==0) { BKE_mesh_end_editmesh(me, em); return 0; } /* we are going to work as follows: * 1. add a linked duplicate object: this will be the new one, we remember old pointer * 2. give new object empty mesh and put in editmode * 3: do a split if needed on current editmesh. * 4. copy over: all NOT selected verts, edges, faces * 5. call load_editMesh() on the new object */ /* 1 */ basenew= ED_object_add_duplicate(bmain, scene, editbase, 0); /* 0 = fully linked */ ED_base_object_select(basenew, BA_DESELECT); /* 2 */ basenew->object->data= menew= add_mesh(me->id.name+2); /* empty */ assign_matarar(basenew->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */ me->id.us--; make_editMesh(scene, basenew->object); emnew= menew->edit_mesh; CustomData_copy(&em->vdata, &emnew->vdata, CD_MASK_EDITMESH, CD_DEFAULT, 0); CustomData_copy(&em->edata, &emnew->edata, CD_MASK_EDITMESH, CD_DEFAULT, 0); CustomData_copy(&em->fdata, &emnew->fdata, CD_MASK_EDITMESH, CD_DEFAULT, 0); /* 3 */ /* SPLIT: first make duplicate */ adduplicateflag(em, SELECT); /* SPLIT: old faces have 3x flag 128 set, delete these ones */ delfaceflag(em, 128); /* since we do tricky things with verts/edges/faces, this makes sure all is selected coherent */ EM_selectmode_set(em); /* 4 */ /* move over: everything that is selected */ for(eve= em->verts.first; eve; eve= v1) { v1= eve->next; if(eve->f & SELECT) { BLI_remlink(&em->verts, eve); BLI_addtail(&emnew->verts, eve); } } for(eed= em->edges.first; eed; eed= e1) { e1= eed->next; if(eed->f & SELECT) { BLI_remlink(&em->edges, eed); BLI_addtail(&emnew->edges, eed); } } for(efa= em->faces.first; efa; efa= f1) { f1= efa->next; if (efa == em->act_face && (efa->f & SELECT)) { EM_set_actFace(em, NULL); } if(efa->f & SELECT) { BLI_remlink(&em->faces, efa); BLI_addtail(&emnew->faces, efa); } } /* 5 */ load_editMesh(scene, basenew->object); free_editMesh(emnew); MEM_freeN(menew->edit_mesh); menew->edit_mesh= NULL; /* copy settings */ menew->texflag= me->texflag; menew->drawflag= me->drawflag; menew->flag= me->flag; menew->editflag= me->editflag; menew->smoothresh= me->smoothresh; /* hashedges are invalid now, make new! */ editMesh_set_hash(em); DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); DAG_id_tag_update(&basenew->object->id, OB_RECALC_DATA); BKE_mesh_end_editmesh(me, em); return 1; }
static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int seg, int subdiv, float dia, float depth, int ext, int fill) { /* * type - for the type of shape * dia - the radius for cone,sphere cylinder etc. * depth - * ext - extrude * fill - end capping, and option to fill in circle * cent[3] - center of the data. * */ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); EditVert *eve, *v1=NULL, *v2, *v3, *v4=NULL, *vtop, *vdown; float phi, phid, vec[3]; float q[4], cmat[3][3], nor[3]= {0.0, 0.0, 0.0}; short a, b; EM_clear_flag_all(em, SELECT); phid= 2.0f*(float)M_PI/tot; phi= .25f*(float)M_PI; switch(type) { case PRIM_GRID: /* grid */ /* clear flags */ eve= em->verts.first; while(eve) { eve->f= 0; eve= eve->next; } /* one segment first: the X axis */ phi = (2*dia)/(float)(tot-1); phid = (2*dia)/(float)(seg-1); for(a=tot-1;a>=0;a--) { vec[0] = (phi*a) - dia; vec[1]= - dia; vec[2]= 0.0f; eve= addvertlist(em, vec, NULL); eve->f= 1+2+4; if(a < tot -1) addedgelist(em, eve->prev, eve, NULL); } /* extrude and translate */ vec[0]= vec[2]= 0.0; vec[1]= phid; for(a=0;a<seg-1;a++) { extrudeflag_vert(obedit, em, 2, nor, 0); // nor unused translateflag(em, 2, vec); } /* and now do imat */ eve= em->verts.first; while(eve) { if(eve->f & SELECT) { mul_m4_v3(mat,eve->co); } eve= eve->next; } recalc_editnormals(em); break; case PRIM_UVSPHERE: /* UVsphere */ /* clear all flags */ eve= em->verts.first; while(eve) { eve->f= 0; eve= eve->next; } /* one segment first */ phi= 0; phid/=2; for(a=0; a<=tot; a++) { vec[0]= dia*sinf(phi); vec[1]= 0.0; vec[2]= dia*cosf(phi); eve= addvertlist(em, vec, NULL); eve->f= 1+2+4; if(a==0) v1= eve; else addedgelist(em, eve, eve->prev, NULL); phi+= phid; } /* extrude and rotate */ phi= M_PI/seg; q[0]= cos(phi); q[3]= sin(phi); q[1]=q[2]= 0; quat_to_mat3( cmat,q); for(a=0; a<seg; a++) { extrudeflag_vert(obedit, em, 2, nor, 0); // nor unused rotateflag(em, 2, v1->co, cmat); } removedoublesflag(em, 4, 0, 0.0001); /* and now do imat */ eve= em->verts.first; while(eve) { if(eve->f & SELECT) { mul_m4_v3(mat,eve->co); } eve= eve->next; } recalc_editnormals(em); break; case PRIM_ICOSPHERE: /* Icosphere */ { EditVert *eva[12]; EditEdge *eed; /* clear all flags */ eve= em->verts.first; while(eve) { eve->f= 0; eve= eve->next; } dia/=200; for(a=0;a<12;a++) { vec[0]= dia*icovert[a][0]; vec[1]= dia*icovert[a][1]; vec[2]= dia*icovert[a][2]; eva[a]= addvertlist(em, vec, NULL); eva[a]->f= 1+2; } for(a=0;a<20;a++) { EditFace *evtemp; v1= eva[ icoface[a][0] ]; v2= eva[ icoface[a][1] ]; v3= eva[ icoface[a][2] ]; evtemp = addfacelist(em, v1, v2, v3, 0, NULL, NULL); evtemp->e1->f = 1+2; evtemp->e2->f = 1+2; evtemp->e3->f = 1+2; } dia*=200; for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0, B_SPHERE,1, SUBDIV_CORNER_PATH, 0); /* and now do imat */ eve= em->verts.first; while(eve) { if(eve->f & 2) { mul_m4_v3(mat,eve->co); } eve= eve->next; } // Clear the flag 2 from the edges for(eed=em->edges.first;eed;eed=eed->next){ if(eed->f & 2){ eed->f &= !2; } } } break; case PRIM_MONKEY: /* Monkey */ { //extern int monkeyo, monkeynv, monkeynf; //extern signed char monkeyf[][4]; //extern signed char monkeyv[][3]; EditVert **tv= MEM_mallocN(sizeof(*tv)*monkeynv*2, "tv"); int i; for (i=0; i<monkeynv; i++) { float v[3]; v[0]= (monkeyv[i][0]+127)/128.0, v[1]= monkeyv[i][1]/128.0, v[2]= monkeyv[i][2]/128.0; tv[i]= addvertlist(em, v, NULL); tv[i]->f |= SELECT; tv[monkeynv+i]= (fabs(v[0]= -v[0])<0.001)?tv[i]:addvertlist(em, v, NULL); tv[monkeynv+i]->f |= SELECT; } for (i=0; i<monkeynf; i++) { addfacelist(em, tv[monkeyf[i][0]+i-monkeyo], tv[monkeyf[i][1]+i-monkeyo], tv[monkeyf[i][2]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeyf[i][3]+i-monkeyo]:NULL, NULL, NULL); addfacelist(em, tv[monkeynv+monkeyf[i][2]+i-monkeyo], tv[monkeynv+monkeyf[i][1]+i-monkeyo], tv[monkeynv+monkeyf[i][0]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeynv+monkeyf[i][3]+i-monkeyo]:NULL, NULL, NULL); } MEM_freeN(tv); /* and now do imat */ for(eve= em->verts.first; eve; eve= eve->next) { if(eve->f & SELECT) { mul_m4_v3(mat,eve->co); } } recalc_editnormals(em); } break; default: /* all types except grid, sphere... */ if(type==PRIM_CONE); else if(ext==0) depth= 0.0f; /* first vertex at 0° for circular objects */ if( ELEM3(type, PRIM_CIRCLE,PRIM_CYLINDER,PRIM_CONE) ) phi = 0.0f; vtop= vdown= v1= v2= 0; for(b=0; b<=ext; b++) { for(a=0; a<tot; a++) { vec[0]= dia*sinf(phi); vec[1]= dia*cosf(phi); vec[2]= b?depth:-depth; mul_m4_v3(mat, vec); eve= addvertlist(em, vec, NULL); eve->f= SELECT; if(a==0) { if(b==0) v1= eve; else v2= eve; } phi+=phid; } } /* center vertices */ /* type PRIM_CONE can only have 1 one side filled * if the cone has no capping, dont add vtop */ if(type == PRIM_CONE || (fill && !ELEM(type, PRIM_PLANE, PRIM_CUBE))) { vec[0]= vec[1]= 0.0f; vec[2]= type==PRIM_CONE ? depth : -depth; mul_m4_v3(mat, vec); vdown= addvertlist(em, vec, NULL); if((ext || type==PRIM_CONE) && fill) { vec[0]= vec[1]= 0.0f; vec[2]= type==PRIM_CONE ? -depth : depth; mul_m4_v3(mat,vec); vtop= addvertlist(em, vec, NULL); } } else { vdown= v1; vtop= v2; } if(vtop) vtop->f= SELECT; if(vdown) vdown->f= SELECT; /* top and bottom face */ if(fill || type==PRIM_CONE) { if(tot==4 && ELEM(type, PRIM_PLANE, PRIM_CUBE)) { v3= v1->next->next; if(ext) v4= v2->next->next; addfacelist(em, v3, v1->next, v1, v3->next, NULL, NULL); if(ext) addfacelist(em, v2, v2->next, v4, v4->next, NULL, NULL); } else { v3= v1; v4= v2; for(a=1; a<tot; a++) { addfacelist(em, vdown, v3, v3->next, 0, NULL, NULL); v3= v3->next; if(ext && fill) { addfacelist(em, vtop, v4, v4->next, 0, NULL, NULL); v4= v4->next; } } if(!ELEM(type, PRIM_PLANE, PRIM_CUBE)) { addfacelist(em, vdown, v3, v1, 0, NULL, NULL); if(ext) addfacelist(em, vtop, v4, v2, 0, NULL, NULL); } } } else if(type==PRIM_CIRCLE) { /* we need edges for a circle */ v3= v1; for(a=1;a<tot;a++) { addedgelist(em, v3, v3->next, NULL); v3= v3->next; } addedgelist(em, v3, v1, NULL); } /* side faces */ if(ext) { v3= v1; v4= v2; for(a=1; a<tot; a++) { addfacelist(em, v3, v3->next, v4->next, v4, NULL, NULL); v3= v3->next; v4= v4->next; } addfacelist(em, v3, v1, v2, v4, NULL, NULL); } else if(fill && type==PRIM_CONE) { /* add the bottom flat area of the cone * if capping is disabled dont bother */ v3= v1; for(a=1; a<tot; a++) { addfacelist(em, vtop, v3->next, v3, 0, NULL, NULL); v3= v3->next; } addfacelist(em, vtop, v1, v3, 0, NULL, NULL); } } EM_stats_update(em); /* simple selection flush OK, based on fact it's a single model */ EM_select_flush(em); /* flushes vertex -> edge -> face selection */ if(!ELEM5(type, PRIM_GRID, PRIM_PLANE, PRIM_ICOSPHERE, PRIM_UVSPHERE, PRIM_MONKEY)) EM_recalc_normal_direction(em, FALSE, TRUE); /* otherwise monkey has eyes in wrong direction */ BKE_mesh_end_editmesh(obedit->data, em); }
static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int level, int animated) { Object *ob, *ob_iter; Base *base = NULL; DupliObject *dob; DerivedMesh *dm; Mesh *me= par->data; MTFace *mtface; MFace *mface; MVert *mvert; float pmat[4][4], imat[3][3], (*orco)[3] = NULL, w; int lay, oblay, totface, a; Scene *sce = NULL; Group *group = NULL; GroupObject *go = NULL; EditMesh *em; float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */ /* simple preventing of too deep nested groups */ if(level>MAX_DUPLI_RECUR) return; Mat4CpyMat4(pmat, par->obmat); em = BKE_mesh_get_editmesh(me); if(em) { int totvert; dm= editmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); totface= dm->getNumFaces(dm); mface= MEM_mallocN(sizeof(MFace)*totface, "mface temp"); dm->copyFaceArray(dm, mface); totvert= dm->getNumVerts(dm); mvert= MEM_mallocN(sizeof(MVert)*totvert, "mvert temp"); dm->copyVertArray(dm, mvert); BKE_mesh_end_editmesh(me, em); } else { dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH); totface= dm->getNumFaces(dm); mface= dm->getFaceArray(dm); mvert= dm->getVertArray(dm); } if(G.rendering) { orco= (float(*)[3])get_mesh_orco_verts(par); transform_mesh_orco_verts(me, orco, me->totvert, 0); mtface= me->mtface; } else { orco= NULL; mtface= NULL; } /* having to loop on scene OR group objects is NOT FUN */ if (GS(id->name) == ID_SCE) { sce = (Scene *)id; lay= sce->lay; base= sce->base.first; } else { group = (Group *)id; lay= group->layer; go = group->gobject.first; } /* Start looping on Scene OR Group objects */ while (base || go) { if (sce) { ob_iter= base->object; oblay = base->lay; } else { ob_iter= go->ob; oblay = ob_iter->lay; } if (lay & oblay && scene->obedit!=ob_iter) { ob=ob_iter->parent; while(ob) { if(ob==par) { ob = ob_iter; /* End Scene/Group object loop, below is generic */ /* par_space_mat - only used for groups so we can modify the space dupli's are in when par_space_mat is NULL ob->obmat can be used instead of ob__obmat */ if(par_space_mat) Mat4MulMat4(ob__obmat, ob->obmat, par_space_mat); else Mat4CpyMat4(ob__obmat, ob->obmat); Mat3CpyMat4(imat, ob->parentinv); /* mballs have a different dupli handling */ if(ob->type!=OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ for(a=0; a<totface; a++) { int mv1 = mface[a].v1; int mv2 = mface[a].v2; int mv3 = mface[a].v3; int mv4 = mface[a].v4; float *v1= mvert[mv1].co; float *v2= mvert[mv2].co; float *v3= mvert[mv3].co; float *v4= (mv4)? mvert[mv4].co: NULL; float cent[3], quat[4], mat[3][3], mat3[3][3], tmat[4][4], obmat[4][4]; /* translation */ if(v4) CalcCent4f(cent, v1, v2, v3, v4); else CalcCent3f(cent, v1, v2, v3); Mat4MulVecfl(pmat, cent); VecSubf(cent, cent, pmat[3]); VecAddf(cent, cent, ob__obmat[3]); Mat4CpyMat4(obmat, ob__obmat); VECCOPY(obmat[3], cent); /* rotation */ triatoquat(v1, v2, v3, quat); QuatToMat3(quat, mat); /* scale */ if(par->transflag & OB_DUPLIFACES_SCALE) { float size= v4?AreaQ3Dfl(v1, v2, v3, v4):AreaT3Dfl(v1, v2, v3); size= sqrt(size) * par->dupfacesca; Mat3MulFloat(mat[0], size); } Mat3CpyMat3(mat3, mat); Mat3MulMat3(mat, imat, mat3); Mat4CpyMat4(tmat, obmat); Mat4MulMat43(obmat, tmat, mat); dob= new_dupli_object(lb, ob, obmat, lay, a, OB_DUPLIFACES, animated); if(G.rendering) { w= (mv4)? 0.25f: 1.0f/3.0f; if(orco) { VECADDFAC(dob->orco, dob->orco, orco[mv1], w); VECADDFAC(dob->orco, dob->orco, orco[mv2], w); VECADDFAC(dob->orco, dob->orco, orco[mv3], w); if(mv4) VECADDFAC(dob->orco, dob->orco, orco[mv4], w); } if(mtface) { dob->uv[0] += w*mtface[a].uv[0][0]; dob->uv[1] += w*mtface[a].uv[0][1]; dob->uv[0] += w*mtface[a].uv[1][0]; dob->uv[1] += w*mtface[a].uv[1][1]; dob->uv[0] += w*mtface[a].uv[2][0]; dob->uv[1] += w*mtface[a].uv[2][1]; if(mv4) { dob->uv[0] += w*mtface[a].uv[3][0]; dob->uv[1] += w*mtface[a].uv[3][1]; } } } if(ob->transflag & OB_DUPLI) { float tmpmat[4][4]; Mat4CpyMat4(tmpmat, ob->obmat); Mat4CpyMat4(ob->obmat, obmat); /* pretend we are really this mat */ object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, level+1, animated); Mat4CpyMat4(ob->obmat, tmpmat); } } break; } ob= ob->parent; } } if (sce) base= base->next; /* scene loop */ else go= go->next; /* group loop */ } if(par->mode & OB_MODE_EDIT) { MEM_freeN(mface); MEM_freeN(mvert); } if(orco) MEM_freeN(orco); dm->release(dm); }
static void meshdeformModifier_do( ModifierData *md, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; struct Mesh *me= (mmd->object)? mmd->object->data: NULL; struct EditMesh *em = (me)? BKE_mesh_get_editmesh(me): NULL; DerivedMesh *tmpdm, *cagedm; MDeformVert *dvert = NULL; MDefInfluence *influences; int *offsets; float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4]; float weight, totweight, fac, co[3], (*dco)[3], (*bindcagecos)[3]; int a, b, totvert, totcagevert, defgrp_index; float (*cagecos)[3]; if(!mmd->object || (!mmd->bindcagecos && !mmd->bindfunc)) return; /* get cage derivedmesh */ if(em) { tmpdm= editmesh_get_derived_cage_and_final(md->scene, ob, em, &cagedm, 0); if(tmpdm) tmpdm->release(tmpdm); BKE_mesh_end_editmesh(me, em); } else cagedm= mmd->object->derivedFinal; /* if we don't have one computed, use derivedmesh from data * without any modifiers */ if(!cagedm) { cagedm= get_dm(mmd->object, NULL, NULL, NULL, 0); if(cagedm) cagedm->needsFree= 1; } if(!cagedm) { modifier_setError(md, "Can't get mesh from cage object."); return; } /* compute matrices to go in and out of cage object space */ invert_m4_m4(imat, mmd->object->obmat); mult_m4_m4m4(cagemat, imat, ob->obmat); mult_m4_m4m4(cmat, mmd->bindmat, cagemat); invert_m4_m4(iobmat, cmat); copy_m3_m4(icagemat, iobmat); /* bind weights if needed */ if(!mmd->bindcagecos) { static int recursive = 0; /* progress bar redraw can make this recursive .. */ if(!recursive) { recursive = 1; mmd->bindfunc(md->scene, mmd, (float*)vertexCos, numVerts, cagemat); recursive = 0; } } /* verify we have compatible weights */ totvert= numVerts; totcagevert= cagedm->getNumVerts(cagedm); if(mmd->totvert != totvert) { modifier_setError(md, "Verts changed from %d to %d.", mmd->totvert, totvert); cagedm->release(cagedm); return; } else if (mmd->totcagevert != totcagevert) { modifier_setError(md, "Cage verts changed from %d to %d.", mmd->totcagevert, totcagevert); cagedm->release(cagedm); return; } else if (mmd->bindcagecos == NULL) { modifier_setError(md, "Bind data missing."); cagedm->release(cagedm); return; } cagecos= MEM_callocN(sizeof(*cagecos)*totcagevert, "meshdeformModifier vertCos"); /* setup deformation data */ cagedm->getVertCos(cagedm, cagecos); influences= mmd->bindinfluences; offsets= mmd->bindoffsets; bindcagecos= (float(*)[3])mmd->bindcagecos; dco= MEM_callocN(sizeof(*dco)*totcagevert, "MDefDco"); for(a=0; a<totcagevert; a++) { /* get cage vertex in world space with binding transform */ copy_v3_v3(co, cagecos[a]); if(G.rt != 527) { mul_m4_v3(mmd->bindmat, co); /* compute difference with world space bind coord */ sub_v3_v3v3(dco[a], co, bindcagecos[a]); } else copy_v3_v3(dco[a], co); } modifier_get_vgroup(ob, dm, mmd->defgrp_name, &dvert, &defgrp_index); /* do deformation */ fac= 1.0f; for(b=0; b<totvert; b++) { if(mmd->flag & MOD_MDEF_DYNAMIC_BIND) if(!mmd->dynverts[b]) continue; if(dvert) { fac= defvert_find_weight(&dvert[b], defgrp_index); if (mmd->flag & MOD_MDEF_INVERT_VGROUP) { fac= 1.0f - fac; } if (fac <= 0.0f) { continue; } } if(mmd->flag & MOD_MDEF_DYNAMIC_BIND) { /* transform coordinate into cage's local space */ mul_v3_m4v3(co, cagemat, vertexCos[b]); totweight= meshdeform_dynamic_bind(mmd, dco, co); } else { totweight= 0.0f; zero_v3(co); for(a=offsets[b]; a<offsets[b+1]; a++) { weight= influences[a].weight; madd_v3_v3fl(co, dco[influences[a].vertex], weight); totweight += weight; } } if(totweight > 0.0f) { mul_v3_fl(co, fac/totweight); mul_m3_v3(icagemat, co); if(G.rt != 527) add_v3_v3(vertexCos[b], co); else copy_v3_v3(vertexCos[b], co); } } /* release cage derivedmesh */ MEM_freeN(dco); MEM_freeN(cagecos); cagedm->release(cagedm); }
static Object* createRepresentation(bContext *C, struct recast_polyMesh *pmesh, struct recast_polyMeshDetail *dmesh, Base* base) { float co[3], rot[3]; EditMesh *em; int i,j, k; unsigned short* v; int face[3]; Scene *scene= CTX_data_scene(C); Object* obedit; int createob= base==NULL; int nverts, nmeshes, nvp; unsigned short *verts, *polys; unsigned int *meshes; float bmin[3], cs, ch, *dverts; unsigned char *tris; zero_v3(co); zero_v3(rot); if(createob) { /* create new object */ obedit= ED_object_add_type(C, OB_MESH, co, rot, FALSE, 1); } else { obedit= base->object; scene_select_base(scene, base); copy_v3_v3(obedit->loc, co); copy_v3_v3(obedit->rot, rot); } ED_object_enter_editmode(C, EM_DO_UNDO|EM_IGNORE_LAYER); em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); if(!createob) { /* clear */ 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)); } /* create verts for polygon mesh */ verts= recast_polyMeshGetVerts(pmesh, &nverts); recast_polyMeshGetBoundbox(pmesh, bmin, NULL); recast_polyMeshGetCell(pmesh, &cs, &ch); for(i= 0; i<nverts; i++) { v= &verts[3*i]; co[0]= bmin[0] + v[0]*cs; co[1]= bmin[1] + v[1]*ch; co[2]= bmin[2] + v[2]*cs; SWAP(float, co[1], co[2]); addvertlist(em, co, NULL); } /* create custom data layer to save polygon idx */ CustomData_add_layer_named(&em->fdata, CD_RECAST, CD_CALLOC, NULL, 0, "createRepresentation recastData"); /* create verts and faces for detailed mesh */ meshes= recast_polyMeshDetailGetMeshes(dmesh, &nmeshes); polys= recast_polyMeshGetPolys(pmesh, NULL, &nvp); dverts= recast_polyMeshDetailGetVerts(dmesh, NULL); tris= recast_polyMeshDetailGetTris(dmesh, NULL); for(i= 0; i<nmeshes; i++) { int uniquevbase= em->totvert; unsigned int vbase= meshes[4*i+0]; unsigned short ndv= meshes[4*i+1]; unsigned short tribase= meshes[4*i+2]; unsigned short trinum= meshes[4*i+3]; const unsigned short* p= &polys[i*nvp*2]; int nv= 0; for(j= 0; j < nvp; ++j) { if(p[j]==0xffff) break; nv++; } /* create unique verts */ for(j= nv; j<ndv; j++) { copy_v3_v3(co, &dverts[3*(vbase + j)]); SWAP(float, co[1], co[2]); addvertlist(em, co, NULL); } EM_init_index_arrays(em, 1, 0, 0); /* create faces */ for(j= 0; j<trinum; j++) { unsigned char* tri= &tris[4*(tribase+j)]; EditFace* newFace; int* polygonIdx; for(k= 0; k<3; k++) { if(tri[k]<nv) face[k]= p[tri[k]]; /* shared vertex */ else face[k]= uniquevbase+tri[k]-nv; /* unique vertex */ } newFace= addfacelist(em, EM_get_vert_for_index(face[0]), EM_get_vert_for_index(face[2]), EM_get_vert_for_index(face[1]), NULL, NULL, NULL); /* set navigation polygon idx to the custom layer */ polygonIdx= (int*)CustomData_em_get(&em->fdata, newFace->data, CD_RECAST); *polygonIdx= i+1; /* add 1 to avoid zero idx */ } EM_free_index_arrays(); } recast_destroyPolyMesh(pmesh); recast_destroyPolyMeshDetail(dmesh); BKE_mesh_end_editmesh((Mesh*)obedit->data, em); DAG_id_tag_update((ID*)obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); ED_object_exit_editmode(C, EM_FREEDATA); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit); if(createob) { obedit->gameflag&= ~OB_COLLISION; obedit->gameflag|= OB_NAVMESH; obedit->body_type= OB_BODY_TYPE_NAVMESH; rename_id((ID *)obedit, "Navmesh"); } BKE_mesh_ensure_navmesh(obedit->data); return obedit; }
/* draws uv's in the image space */ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) { ToolSettings *ts; Mesh *me= obedit->data; EditMesh *em; EditFace *efa, *efa_act; MTFace *tf, *activetf = NULL; DerivedMesh *finaldm, *cagedm; char col1[4], col2[4]; float pointsize; int drawfaces, interpedges, lastsel, sel; Image *ima= sima->image; em= BKE_mesh_get_editmesh(me); activetf= EM_get_active_mtface(em, &efa_act, NULL, 0); /* will be set to NULL if hidden */ ts= scene->toolsettings; drawfaces= draw_uvs_face_check(scene); if(ts->uv_flag & UV_SYNC_SELECTION) interpedges= (ts->selectmode & SCE_SELECT_VERTEX); else interpedges= (ts->uv_selectmode == UV_SELECT_VERTEX); /* draw other uvs */ if(sima->flag & SI_DRAW_OTHER) draw_uvs_other(sima, scene, obedit, activetf); /* 1. draw shadow mesh */ if(sima->flag & SI_DRAWSHADOW) { /* first try existing derivedmesh */ if(!draw_uvs_dm_shadow(em->derivedFinal)) { /* create one if it does not exist */ cagedm = editmesh_get_derived_cage_and_final(scene, obedit, em, &finaldm, CD_MASK_BAREMESH|CD_MASK_MTFACE); /* when sync selection is enabled, all faces are drawn (except for hidden) * so if cage is the same as the final, theres no point in drawing this */ if(!((ts->uv_flag & UV_SYNC_SELECTION) && (cagedm == finaldm))) draw_uvs_dm_shadow(finaldm); /* release derivedmesh again */ if(cagedm != finaldm) cagedm->release(cagedm); finaldm->release(finaldm); } } /* 2. draw colored faces */ if(sima->flag & SI_DRAW_STRETCH) { draw_uvs_stretch(sima, scene, em, activetf); } else if(me->drawflag & ME_DRAWFACES) { /* draw transparent faces */ UI_GetThemeColor4ubv(TH_FACE, col1); UI_GetThemeColor4ubv(TH_FACE_SELECT, col2); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); for(efa= em->faces.first; efa; efa= efa->next) { tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); if(uvedit_face_visible(scene, ima, efa, tf)) { efa->tmp.p = tf; if(tf==activetf) continue; /* important the temp pointer is set above */ if(uvedit_face_selected(scene, efa, tf)) glColor4ubv((GLubyte *)col2); else glColor4ubv((GLubyte *)col1); glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); glVertex2fv(tf->uv[0]); glVertex2fv(tf->uv[1]); glVertex2fv(tf->uv[2]); if(efa->v4) glVertex2fv(tf->uv[3]); glEnd(); } else { if(tf == activetf) activetf= NULL; efa->tmp.p = NULL; } } glDisable(GL_BLEND); } else { /* would be nice to do this within a draw loop but most below are optional, so it would involve too many checks */ for(efa= em->faces.first; efa; efa= efa->next) { tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); if(uvedit_face_visible(scene, ima, efa, tf)) { efa->tmp.p = tf; } else { if(tf == activetf) activetf= NULL; efa->tmp.p = NULL; } } } /* 3. draw active face stippled */ if(activetf) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); UI_ThemeColor4(TH_EDITMESH_ACTIVE); glEnable(GL_POLYGON_STIPPLE); glPolygonStipple(stipple_quarttone); glBegin(efa_act->v4? GL_QUADS: GL_TRIANGLES); glVertex2fv(activetf->uv[0]); glVertex2fv(activetf->uv[1]); glVertex2fv(activetf->uv[2]); if(efa_act->v4) glVertex2fv(activetf->uv[3]); glEnd(); glDisable(GL_POLYGON_STIPPLE); glDisable(GL_BLEND); } /* 4. draw edges */ if(sima->flag & SI_SMOOTH_UV) { glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } switch(sima->dt_uv) { case SI_UVDT_DASH: for(efa= em->faces.first; efa; efa= efa->next) { tf= (MTFace *)efa->tmp.p; /* visible faces cached */ if(tf) { cpack(0x111111); glBegin(GL_LINE_LOOP); glVertex2fv(tf->uv[0]); glVertex2fv(tf->uv[1]); glVertex2fv(tf->uv[2]); if(efa->v4) glVertex2fv(tf->uv[3]); glEnd(); setlinestyle(2); cpack(0x909090); glBegin(GL_LINE_STRIP); glVertex2fv(tf->uv[0]); glVertex2fv(tf->uv[1]); glEnd(); glBegin(GL_LINE_STRIP); glVertex2fv(tf->uv[0]); if(efa->v4) glVertex2fv(tf->uv[3]); else glVertex2fv(tf->uv[2]); glEnd(); glBegin(GL_LINE_STRIP); glVertex2fv(tf->uv[1]); glVertex2fv(tf->uv[2]); if(efa->v4) glVertex2fv(tf->uv[3]); glEnd(); setlinestyle(0); } } break; case SI_UVDT_BLACK: /* black/white */ case SI_UVDT_WHITE: if(sima->dt_uv==SI_UVDT_WHITE) glColor3f(1.0f, 1.0f, 1.0f); else glColor3f(0.0f, 0.0f, 0.0f); for(efa= em->faces.first; efa; efa= efa->next) { tf= (MTFace *)efa->tmp.p; /* visible faces cached */ if(tf) { glBegin(GL_LINE_LOOP); glVertex2fv(tf->uv[0]); glVertex2fv(tf->uv[1]); glVertex2fv(tf->uv[2]); if(efa->v4) glVertex2fv(tf->uv[3]); glEnd(); } } break; case SI_UVDT_OUTLINE: glLineWidth(3); cpack(0x0); for(efa= em->faces.first; efa; efa= efa->next) { tf= (MTFace *)efa->tmp.p; /* visible faces cached */ if(tf) { glBegin(GL_LINE_LOOP); glVertex2fv(tf->uv[0]); glVertex2fv(tf->uv[1]); glVertex2fv(tf->uv[2]); if(efa->v4) glVertex2fv(tf->uv[3]); glEnd(); } } glLineWidth(1); col2[0] = col2[1] = col2[2] = 192; col2[3] = 255; glColor4ubv((unsigned char *)col2); if(me->drawflag & ME_DRAWEDGES) { UI_GetThemeColor4ubv(TH_VERTEX_SELECT, col1); lastsel = sel = 0; if(interpedges) { glShadeModel(GL_SMOOTH); for(efa= em->faces.first; efa; efa= efa->next) { tf= (MTFace *)efa->tmp.p; /* visible faces cached */ if(tf) { glBegin(GL_LINE_LOOP); sel = (uvedit_uv_selected(scene, efa, tf, 0)? 1 : 0); if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } glVertex2fv(tf->uv[0]); sel = uvedit_uv_selected(scene, efa, tf, 1)? 1 : 0; if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } glVertex2fv(tf->uv[1]); sel = uvedit_uv_selected(scene, efa, tf, 2)? 1 : 0; if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } glVertex2fv(tf->uv[2]); if(efa->v4) { sel = uvedit_uv_selected(scene, efa, tf, 3)? 1 : 0; if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } glVertex2fv(tf->uv[3]); } glEnd(); } } glShadeModel(GL_FLAT); } else { for(efa= em->faces.first; efa; efa= efa->next) { tf= (MTFace *)efa->tmp.p; /* visible faces cached */ if(tf) { glBegin(GL_LINES); sel = (uvedit_edge_selected(scene, efa, tf, 0)? 1 : 0); if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } glVertex2fv(tf->uv[0]); glVertex2fv(tf->uv[1]); sel = uvedit_edge_selected(scene, efa, tf, 1)? 1 : 0; if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } glVertex2fv(tf->uv[1]); glVertex2fv(tf->uv[2]); sel = uvedit_edge_selected(scene, efa, tf, 2)? 1 : 0; if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } glVertex2fv(tf->uv[2]); if(efa->v4) { glVertex2fv(tf->uv[3]); sel = uvedit_edge_selected(scene, efa, tf, 3)? 1 : 0; if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } glVertex2fv(tf->uv[3]); } glVertex2fv(tf->uv[0]); glEnd(); } } } } else { /* no nice edges */ for(efa= em->faces.first; efa; efa= efa->next) { tf= (MTFace *)efa->tmp.p; /* visible faces cached */ if(tf) { glBegin(GL_LINE_LOOP); glVertex2fv(tf->uv[0]); glVertex2fv(tf->uv[1]); glVertex2fv(tf->uv[2]); if(efa->v4) glVertex2fv(tf->uv[3]); glEnd(); } } } break; } if(sima->flag & SI_SMOOTH_UV) { glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); } /* 5. draw face centers */ if(drawfaces) { float cent[2]; pointsize = UI_GetThemeValuef(TH_FACEDOT_SIZE); glPointSize(pointsize); // TODO - drawobject.c changes this value after - Investigate! /* unselected faces */ UI_ThemeColor(TH_WIRE); bglBegin(GL_POINTS); for(efa= em->faces.first; efa; efa= efa->next) { tf= (MTFace *)efa->tmp.p; /* visible faces cached */ if(tf && !uvedit_face_selected(scene, efa, tf)) { uv_center(tf->uv, cent, efa->v4 != NULL); bglVertex2fv(cent); } } bglEnd(); /* selected faces */ UI_ThemeColor(TH_FACE_DOT); bglBegin(GL_POINTS); for(efa= em->faces.first; efa; efa= efa->next) { tf= (MTFace *)efa->tmp.p; /* visible faces cached */ if(tf && uvedit_face_selected(scene, efa, tf)) { uv_center(tf->uv, cent, efa->v4 != NULL); bglVertex2fv(cent); } } bglEnd(); } /* 6. draw uv vertices */ if(drawfaces != 2) { /* 2 means Mesh Face Mode */ /* unselected uvs */ UI_ThemeColor(TH_VERTEX); pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE); glPointSize(pointsize); bglBegin(GL_POINTS); for(efa= em->faces.first; efa; efa= efa->next) { tf= (MTFace *)efa->tmp.p; /* visible faces cached */ if(tf) { if(!uvedit_uv_selected(scene, efa, tf, 0)) bglVertex2fv(tf->uv[0]); if(!uvedit_uv_selected(scene, efa, tf, 1)) bglVertex2fv(tf->uv[1]); if(!uvedit_uv_selected(scene, efa, tf, 2)) bglVertex2fv(tf->uv[2]); if(efa->v4 && !uvedit_uv_selected(scene, efa, tf, 3)) bglVertex2fv(tf->uv[3]); } } bglEnd(); /* pinned uvs */ /* give odd pointsizes odd pin pointsizes */ glPointSize(pointsize*2 + (((int)pointsize % 2)? (-1): 0)); cpack(0xFF); bglBegin(GL_POINTS); for(efa= em->faces.first; efa; efa= efa->next) { tf= (MTFace *)efa->tmp.p; /* visible faces cached */ if(tf) { if(tf->unwrap & TF_PIN1) bglVertex2fv(tf->uv[0]); if(tf->unwrap & TF_PIN2) bglVertex2fv(tf->uv[1]); if(tf->unwrap & TF_PIN3) bglVertex2fv(tf->uv[2]); if(efa->v4 && (tf->unwrap & TF_PIN4)) bglVertex2fv(tf->uv[3]); } } bglEnd(); /* selected uvs */ UI_ThemeColor(TH_VERTEX_SELECT); glPointSize(pointsize); bglBegin(GL_POINTS); for(efa= em->faces.first; efa; efa= efa->next) { tf= (MTFace *)efa->tmp.p; /* visible faces cached */ if(tf) { if(uvedit_uv_selected(scene, efa, tf, 0)) bglVertex2fv(tf->uv[0]); if(uvedit_uv_selected(scene, efa, tf, 1)) bglVertex2fv(tf->uv[1]); if(uvedit_uv_selected(scene, efa, tf, 2)) bglVertex2fv(tf->uv[2]); if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) bglVertex2fv(tf->uv[3]); } } bglEnd(); } glPointSize(1.0); BKE_mesh_end_editmesh(obedit->data, em); }