|
Blender
V2.59
|
00001 /* 00002 * $Id: object_vgroup.c 37304 2011-06-07 18:48:22Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): none yet. 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 */ 00029 00035 #include <string.h> 00036 #include <stddef.h> 00037 #include <math.h> 00038 #include <assert.h> 00039 00040 #include "MEM_guardedalloc.h" 00041 00042 #include "DNA_cloth_types.h" 00043 #include "DNA_curve_types.h" 00044 #include "DNA_lattice_types.h" 00045 #include "DNA_meshdata_types.h" 00046 #include "DNA_modifier_types.h" 00047 #include "DNA_object_types.h" 00048 #include "DNA_object_force.h" 00049 #include "DNA_scene_types.h" 00050 #include "DNA_particle_types.h" 00051 00052 #include "BLI_blenlib.h" 00053 #include "BLI_editVert.h" 00054 #include "BLI_utildefines.h" 00055 00056 #include "BKE_context.h" 00057 #include "BKE_customdata.h" 00058 #include "BKE_deform.h" 00059 #include "BKE_depsgraph.h" 00060 #include "BKE_global.h" 00061 #include "BKE_mesh.h" 00062 #include "BKE_report.h" 00063 00064 #include "RNA_access.h" 00065 #include "RNA_define.h" 00066 00067 #include "WM_api.h" 00068 #include "WM_types.h" 00069 00070 #include "ED_mesh.h" 00071 00072 #include "UI_resources.h" 00073 00074 #include "object_intern.h" 00075 00076 /************************ Exported Functions **********************/ 00077 static void vgroup_remap_update_users(Object *ob, int *map); 00078 static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *defgroup); 00079 static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg); 00080 static void vgroup_delete_all(Object *ob); 00081 00082 static Lattice *vgroup_edit_lattice(Object *ob) 00083 { 00084 Lattice *lt= ob->data; 00085 BLI_assert(ob->type==OB_LATTICE); 00086 return (lt->editlatt)? lt->editlatt->latt: lt; 00087 } 00088 00089 int ED_vgroup_object_is_edit_mode(Object *ob) 00090 { 00091 if(ob->type == OB_MESH) 00092 return (((Mesh*)ob->data)->edit_mesh != NULL); 00093 else if(ob->type == OB_LATTICE) 00094 return (((Lattice*)ob->data)->editlatt != NULL); 00095 00096 return 0; 00097 } 00098 00099 bDeformGroup *ED_vgroup_add_name(Object *ob, const char *name) 00100 { 00101 bDeformGroup *defgroup; 00102 00103 if(!ob || !ELEM(ob->type, OB_MESH, OB_LATTICE)) 00104 return NULL; 00105 00106 defgroup = MEM_callocN(sizeof(bDeformGroup), "add deformGroup"); 00107 00108 BLI_strncpy(defgroup->name, name, sizeof(defgroup->name)); 00109 00110 BLI_addtail(&ob->defbase, defgroup); 00111 defgroup_unique_name(defgroup, ob); 00112 00113 ob->actdef = BLI_countlist(&ob->defbase); 00114 00115 return defgroup; 00116 } 00117 00118 bDeformGroup *ED_vgroup_add(Object *ob) 00119 { 00120 return ED_vgroup_add_name(ob, "Group"); 00121 } 00122 00123 void ED_vgroup_delete(Object *ob, bDeformGroup *defgroup) 00124 { 00125 bDeformGroup *dg = (bDeformGroup *)ob->defbase.first; 00126 00127 while (dg) { 00128 if (dg == defgroup) 00129 break; 00130 dg = dg->next; 00131 } 00132 00133 if (dg == NULL) 00134 return; 00135 00136 if(ED_vgroup_object_is_edit_mode(ob)) 00137 vgroup_delete_edit_mode(ob, dg); 00138 else 00139 vgroup_delete_object_mode(ob, dg); 00140 } 00141 00142 int ED_vgroup_data_create(ID *id) 00143 { 00144 /* create deform verts */ 00145 00146 if(GS(id->name)==ID_ME) { 00147 Mesh *me= (Mesh *)id; 00148 me->dvert= CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert); 00149 return TRUE; 00150 } 00151 else if(GS(id->name)==ID_LT) { 00152 Lattice *lt= (Lattice *)id; 00153 lt->dvert= MEM_callocN(sizeof(MDeformVert)*lt->pntsu*lt->pntsv*lt->pntsw, "lattice deformVert"); 00154 return TRUE; 00155 } 00156 else { 00157 return FALSE; 00158 } 00159 } 00160 00161 static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_tot) 00162 { 00163 *dvert_tot = 0; 00164 *dvert_arr = NULL; 00165 00166 if(id) { 00167 switch(GS(id->name)) { 00168 case ID_ME: 00169 { 00170 Mesh *me = (Mesh *)id; 00171 00172 if(me->edit_mesh) { 00173 EditMesh *em = me->edit_mesh; 00174 EditVert *eve; 00175 int i; 00176 00177 if (!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) { 00178 return 0; 00179 } 00180 00181 i= BLI_countlist(&em->verts); 00182 00183 *dvert_arr= MEM_mallocN(sizeof(void*)*i, "vgroup parray from me"); 00184 *dvert_tot = i; 00185 00186 i = 0; 00187 for (eve=em->verts.first; eve; eve=eve->next, i++) { 00188 (*dvert_arr)[i] = CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); 00189 } 00190 00191 return 1; 00192 } 00193 else if(me->dvert) { 00194 int i; 00195 00196 *dvert_tot= me->totvert; 00197 *dvert_arr= MEM_mallocN(sizeof(void*)*me->totvert, "vgroup parray from me"); 00198 00199 for (i=0; i<me->totvert; i++) { 00200 (*dvert_arr)[i] = me->dvert + i; 00201 } 00202 00203 return 1; 00204 } 00205 else { 00206 return 0; 00207 } 00208 } 00209 case ID_LT: 00210 { 00211 int i=0; 00212 00213 Lattice *lt= (Lattice *)id; 00214 lt= (lt->editlatt)? lt->editlatt->latt: lt; 00215 00216 if(lt->dvert) { 00217 *dvert_tot= lt->pntsu*lt->pntsv*lt->pntsw; 00218 *dvert_arr= MEM_mallocN(sizeof(void*)*(*dvert_tot), "vgroup parray from me"); 00219 00220 for (i=0; i<*dvert_tot; i++) { 00221 (*dvert_arr)[i] = lt->dvert + i; 00222 } 00223 00224 return 1; 00225 } 00226 else { 00227 return 0; 00228 } 00229 } 00230 } 00231 } 00232 00233 return 0; 00234 } 00235 00236 /* returns true if the id type supports weights */ 00237 int ED_vgroup_give_array(ID *id, MDeformVert **dvert_arr, int *dvert_tot) 00238 { 00239 if(id) { 00240 switch(GS(id->name)) { 00241 case ID_ME: 00242 { 00243 Mesh *me = (Mesh *)id; 00244 *dvert_arr= me->dvert; 00245 *dvert_tot= me->totvert; 00246 return TRUE; 00247 } 00248 case ID_LT: 00249 { 00250 Lattice *lt= (Lattice *)id; 00251 lt= (lt->editlatt)? lt->editlatt->latt: lt; 00252 *dvert_arr= lt->dvert; 00253 *dvert_tot= lt->pntsu*lt->pntsv*lt->pntsw; 00254 return TRUE; 00255 } 00256 } 00257 } 00258 00259 *dvert_arr= NULL; 00260 *dvert_tot= 0; 00261 return FALSE; 00262 } 00263 00264 /* matching index only */ 00265 int ED_vgroup_copy_array(Object *ob, Object *ob_from) 00266 { 00267 MDeformVert **dvert_array_from, **dvf; 00268 MDeformVert **dvert_array, **dv; 00269 int dvert_tot_from; 00270 int dvert_tot; 00271 int i; 00272 int totdef_from= BLI_countlist(&ob_from->defbase); 00273 int totdef= BLI_countlist(&ob->defbase); 00274 short new_vgroup= FALSE; 00275 00276 ED_vgroup_give_parray(ob_from->data, &dvert_array_from, &dvert_tot_from); 00277 ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot); 00278 00279 if((dvert_array == NULL) && (dvert_array_from != NULL) && ED_vgroup_data_create(ob->data)) { 00280 ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot); 00281 new_vgroup= TRUE; 00282 } 00283 00284 if(ob==ob_from || dvert_tot==0 || (dvert_tot != dvert_tot_from) || dvert_array_from==NULL || dvert_array==NULL) { 00285 if (dvert_array) MEM_freeN(dvert_array); 00286 if (dvert_array_from) MEM_freeN(dvert_array_from); 00287 00288 if(new_vgroup == TRUE) { 00289 /* free the newly added vgroup since it wasn't compatible */ 00290 vgroup_delete_all(ob); 00291 } 00292 return 0; 00293 } 00294 00295 /* do the copy */ 00296 BLI_freelistN(&ob->defbase); 00297 BLI_duplicatelist(&ob->defbase, &ob_from->defbase); 00298 ob->actdef= ob_from->actdef; 00299 00300 if(totdef_from < totdef) { 00301 /* correct vgroup indices because the number of vgroups is being reduced. */ 00302 int *remap= MEM_mallocN(sizeof(int) * (totdef + 1), "ED_vgroup_copy_array"); 00303 for(i=0; i<=totdef_from; i++) remap[i]= i; 00304 for(; i<=totdef; i++) remap[i]= 0; /* can't use these, so disable */ 00305 00306 vgroup_remap_update_users(ob, remap); 00307 MEM_freeN(remap); 00308 } 00309 00310 dvf= dvert_array_from; 00311 dv= dvert_array; 00312 00313 for(i=0; i<dvert_tot; i++, dvf++, dv++) { 00314 if((*dv)->dw) 00315 MEM_freeN((*dv)->dw); 00316 00317 *(*dv)= *(*dvf); 00318 00319 if((*dv)->dw) 00320 (*dv)->dw= MEM_dupallocN((*dv)->dw); 00321 } 00322 00323 MEM_freeN(dvert_array); 00324 MEM_freeN(dvert_array_from); 00325 00326 return 1; 00327 } 00328 00329 /* for mesh in object mode 00330 lattice can be in editmode */ 00331 static void ED_vgroup_nr_vert_remove(Object *ob, int def_nr, int vertnum) 00332 { 00333 /* This routine removes the vertex from the deform 00334 * group with number def_nr. 00335 * 00336 * This routine is meant to be fast, so it is the 00337 * responsibility of the calling routine to: 00338 * a) test whether ob is non-NULL 00339 * b) test whether ob is a mesh 00340 * c) calculate def_nr 00341 */ 00342 00343 MDeformWeight *newdw; 00344 MDeformVert *dvert= NULL; 00345 int i, tot; 00346 00347 /* get the deform vertices corresponding to the 00348 * vertnum 00349 */ 00350 ED_vgroup_give_array(ob->data, &dvert, &tot); 00351 00352 if(dvert==NULL) 00353 return; 00354 00355 dvert+= vertnum; 00356 00357 /* for all of the deform weights in the 00358 * deform vert 00359 */ 00360 for(i=dvert->totweight - 1 ; i>=0 ; i--){ 00361 00362 /* if the def_nr is the same as the one 00363 * for our weight group then remove it 00364 * from this deform vert. 00365 */ 00366 if(dvert->dw[i].def_nr == def_nr) { 00367 dvert->totweight--; 00368 00369 /* if there are still other deform weights 00370 * attached to this vert then remove this 00371 * deform weight, and reshuffle the others 00372 */ 00373 if(dvert->totweight) { 00374 newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), 00375 "deformWeight"); 00376 if(dvert->dw){ 00377 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i); 00378 memcpy(newdw+i, dvert->dw+i+1, 00379 sizeof(MDeformWeight)*(dvert->totweight-i)); 00380 MEM_freeN(dvert->dw); 00381 } 00382 dvert->dw=newdw; 00383 } 00384 /* if there are no other deform weights 00385 * left then just remove the deform weight 00386 */ 00387 else { 00388 MEM_freeN(dvert->dw); 00389 dvert->dw = NULL; 00390 break; 00391 } 00392 } 00393 } 00394 00395 } 00396 00397 /* for Mesh in Object mode */ 00398 /* allows editmode for Lattice */ 00399 static void ED_vgroup_nr_vert_add(Object *ob, int def_nr, int vertnum, float weight, int assignmode) 00400 { 00401 /* add the vert to the deform group with the 00402 * specified number 00403 */ 00404 MDeformVert *dv= NULL; 00405 MDeformWeight *newdw; 00406 int i, tot; 00407 00408 /* get the vert */ 00409 ED_vgroup_give_array(ob->data, &dv, &tot); 00410 00411 if(dv==NULL) 00412 return; 00413 00414 /* check that vertnum is valid before trying to get the relevant dvert */ 00415 if ((vertnum < 0) || (vertnum >= tot)) 00416 return; 00417 else 00418 dv += vertnum; 00419 00420 /* Lets first check to see if this vert is 00421 * already in the weight group -- if so 00422 * lets update it 00423 */ 00424 for(i=0; i<dv->totweight; i++){ 00425 00426 /* if this weight cooresponds to the 00427 * deform group, then add it using 00428 * the assign mode provided 00429 */ 00430 if(dv->dw[i].def_nr == def_nr){ 00431 00432 switch(assignmode) { 00433 case WEIGHT_REPLACE: 00434 dv->dw[i].weight=weight; 00435 break; 00436 case WEIGHT_ADD: 00437 dv->dw[i].weight+=weight; 00438 if(dv->dw[i].weight >= 1.0f) 00439 dv->dw[i].weight = 1.0f; 00440 break; 00441 case WEIGHT_SUBTRACT: 00442 dv->dw[i].weight-=weight; 00443 /* if the weight is zero or less then 00444 * remove the vert from the deform group 00445 */ 00446 if(dv->dw[i].weight <= 0.0f) 00447 ED_vgroup_nr_vert_remove(ob, def_nr, vertnum); 00448 break; 00449 } 00450 return; 00451 } 00452 } 00453 00454 /* if the vert wasn't in the deform group then 00455 * we must take a different form of action ... 00456 */ 00457 00458 switch(assignmode) { 00459 case WEIGHT_SUBTRACT: 00460 /* if we are subtracting then we don't 00461 * need to do anything 00462 */ 00463 return; 00464 00465 case WEIGHT_REPLACE: 00466 case WEIGHT_ADD: 00467 /* if we are doing an additive assignment, then 00468 * we need to create the deform weight 00469 */ 00470 newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), 00471 "deformWeight"); 00472 if(dv->dw){ 00473 memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight); 00474 MEM_freeN(dv->dw); 00475 } 00476 dv->dw=newdw; 00477 00478 dv->dw[dv->totweight].weight=weight; 00479 dv->dw[dv->totweight].def_nr=def_nr; 00480 00481 dv->totweight++; 00482 break; 00483 } 00484 } 00485 00486 /* called while not in editmode */ 00487 void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, int assignmode) 00488 { 00489 /* add the vert to the deform group with the 00490 * specified assign mode 00491 */ 00492 int def_nr; 00493 00494 MDeformVert *dv= NULL; 00495 int tot; 00496 00497 /* get the deform group number, exit if 00498 * it can't be found 00499 */ 00500 def_nr = defgroup_find_index(ob, dg); 00501 if(def_nr < 0) return; 00502 00503 /* if there's no deform verts then create some, 00504 */ 00505 if(ED_vgroup_give_array(ob->data, &dv, &tot) && dv==NULL) 00506 ED_vgroup_data_create(ob->data); 00507 00508 /* call another function to do the work 00509 */ 00510 ED_vgroup_nr_vert_add(ob, def_nr, vertnum, weight, assignmode); 00511 } 00512 00513 /* mesh object mode, lattice can be in editmode */ 00514 void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum) 00515 { 00516 /* This routine removes the vertex from the specified 00517 * deform group. 00518 */ 00519 const int def_nr= defgroup_find_index(ob, dg); 00520 if(def_nr < 0) 00521 return; 00522 00523 ED_vgroup_nr_vert_remove(ob, def_nr, vertnum); 00524 } 00525 00526 static float get_vert_def_nr(Object *ob, int def_nr, int vertnum) 00527 { 00528 MDeformVert *dvert= NULL; 00529 EditVert *eve; 00530 Mesh *me; 00531 int i; 00532 00533 /* get the deform vertices corresponding to the vertnum */ 00534 if(ob->type==OB_MESH) { 00535 me= ob->data; 00536 00537 if(me->edit_mesh) { 00538 eve= BLI_findlink(&me->edit_mesh->verts, vertnum); 00539 if(!eve) { 00540 return 0.0f; 00541 } 00542 dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT); 00543 vertnum= 0; 00544 } 00545 else { 00546 if(vertnum >= me->totvert) { 00547 return 0.0f; 00548 } 00549 dvert = me->dvert; 00550 } 00551 } 00552 else if(ob->type==OB_LATTICE) { 00553 Lattice *lt= vgroup_edit_lattice(ob); 00554 00555 if(lt->dvert) { 00556 if(vertnum >= lt->pntsu*lt->pntsv*lt->pntsw) { 00557 return 0.0f; 00558 } 00559 dvert = lt->dvert; 00560 } 00561 } 00562 00563 if(dvert==NULL) 00564 return -1; 00565 00566 dvert += vertnum; 00567 00568 for(i=dvert->totweight-1 ; i>=0 ; i--) 00569 if(dvert->dw[i].def_nr == def_nr) 00570 return dvert->dw[i].weight; 00571 00572 return -1; 00573 } 00574 00575 float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum) 00576 { 00577 int def_nr; 00578 00579 if(!ob) return -1; 00580 00581 def_nr = defgroup_find_index(ob, dg); 00582 if(def_nr < 0) return -1; 00583 00584 return get_vert_def_nr(ob, def_nr, vertnum); 00585 } 00586 00587 void ED_vgroup_select_by_name(Object *ob, const char *name) 00588 { /* note: ob->actdef==0 signals on painting to create a new one, if a bone in posemode is selected */ 00589 ob->actdef= defgroup_name_index(ob, name) + 1; 00590 } 00591 00592 /********************** Operator Implementations *********************/ 00593 00594 /* only in editmode */ 00595 static void vgroup_select_verts(Object *ob, int select) 00596 { 00597 EditVert *eve; 00598 MDeformVert *dvert; 00599 int i; 00600 00601 if(ob->type == OB_MESH) { 00602 Mesh *me= ob->data; 00603 EditMesh *em = BKE_mesh_get_editmesh(me); 00604 00605 for(eve=em->verts.first; eve; eve=eve->next){ 00606 dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); 00607 00608 if(dvert && dvert->totweight){ 00609 for(i=0; i<dvert->totweight; i++){ 00610 if(dvert->dw[i].def_nr == (ob->actdef-1)){ 00611 if(!eve->h) { 00612 if(select) eve->f |= SELECT; 00613 else eve->f &= ~SELECT; 00614 } 00615 break; 00616 } 00617 } 00618 } 00619 } 00620 /* this has to be called, because this function operates on vertices only */ 00621 if(select) EM_select_flush(em); // vertices to edges/faces 00622 else EM_deselect_flush(em); 00623 00624 BKE_mesh_end_editmesh(me, em); 00625 } 00626 else if(ob->type == OB_LATTICE) { 00627 Lattice *lt= vgroup_edit_lattice(ob); 00628 00629 if(lt->dvert) { 00630 BPoint *bp; 00631 int a, tot; 00632 00633 dvert= lt->dvert; 00634 00635 tot= lt->pntsu*lt->pntsv*lt->pntsw; 00636 for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) { 00637 for(i=0; i<dvert->totweight; i++){ 00638 if(dvert->dw[i].def_nr == (ob->actdef-1)) { 00639 if(select) bp->f1 |= SELECT; 00640 else bp->f1 &= ~SELECT; 00641 00642 break; 00643 } 00644 } 00645 } 00646 } 00647 } 00648 } 00649 00650 static void vgroup_duplicate(Object *ob) 00651 { 00652 bDeformGroup *dg, *cdg; 00653 char name[sizeof(dg->name)]; 00654 MDeformWeight *org, *cpy; 00655 MDeformVert *dvert, **dvert_array=NULL; 00656 int i, idg, icdg, dvert_tot=0; 00657 00658 dg = BLI_findlink(&ob->defbase, (ob->actdef-1)); 00659 if(!dg) 00660 return; 00661 00662 if(!strstr(dg->name, "_copy")) { 00663 BLI_snprintf(name, sizeof(name), "%s_copy", dg->name); 00664 } 00665 else { 00666 BLI_snprintf(name, sizeof(name), "%s", dg->name); 00667 } 00668 00669 cdg = defgroup_duplicate(dg); 00670 strcpy(cdg->name, name); 00671 defgroup_unique_name(cdg, ob); 00672 00673 BLI_addtail(&ob->defbase, cdg); 00674 00675 idg = (ob->actdef-1); 00676 ob->actdef = BLI_countlist(&ob->defbase); 00677 icdg = (ob->actdef-1); 00678 00679 ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot); 00680 00681 if(!dvert_array) 00682 return; 00683 00684 for(i = 0; i < dvert_tot; i++) { 00685 dvert = dvert_array[i]; 00686 org = defvert_find_index(dvert, idg); 00687 if(org) { 00688 float weight = org->weight; 00689 /* defvert_verify_index re-allocs org so need to store the weight first */ 00690 cpy = defvert_verify_index(dvert, icdg); 00691 cpy->weight = weight; 00692 } 00693 } 00694 00695 MEM_freeN(dvert_array); 00696 } 00697 00698 static void vgroup_normalize(Object *ob) 00699 { 00700 bDeformGroup *dg; 00701 MDeformWeight *dw; 00702 MDeformVert *dvert, **dvert_array=NULL; 00703 int i, def_nr, dvert_tot=0; 00704 00705 ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot); 00706 00707 dg = BLI_findlink(&ob->defbase, (ob->actdef-1)); 00708 00709 if(dg) { 00710 float weight_max = 0.0f; 00711 00712 def_nr= ob->actdef-1; 00713 00714 for(i = 0; i < dvert_tot; i++) { 00715 dvert = dvert_array[i]; 00716 dw = defvert_find_index(dvert, def_nr); 00717 if(dw) { 00718 weight_max = MAX2(dw->weight, weight_max); 00719 } 00720 } 00721 00722 if(weight_max > 0.0f) { 00723 for(i = 0; i < dvert_tot; i++) { 00724 dvert = dvert_array[i]; 00725 dw = defvert_find_index(dvert, def_nr); 00726 if(dw) { 00727 dw->weight /= weight_max; 00728 00729 /* incase of division errors with very low weights */ 00730 CLAMP(dw->weight, 0.0f, 1.0f); 00731 } 00732 } 00733 } 00734 } 00735 00736 if (dvert_array) MEM_freeN(dvert_array); 00737 } 00738 00739 static void vgroup_levels(Object *ob, float offset, float gain) 00740 { 00741 bDeformGroup *dg; 00742 MDeformWeight *dw; 00743 MDeformVert *dvert, **dvert_array=NULL; 00744 int i, def_nr, dvert_tot=0; 00745 00746 ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot); 00747 00748 dg = BLI_findlink(&ob->defbase, (ob->actdef-1)); 00749 00750 if(dg) { 00751 def_nr= ob->actdef-1; 00752 00753 for(i = 0; i < dvert_tot; i++) { 00754 dvert = dvert_array[i]; 00755 dw = defvert_find_index(dvert, def_nr); 00756 if(dw) { 00757 dw->weight = gain * (dw->weight + offset); 00758 00759 CLAMP(dw->weight, 0.0f, 1.0f); 00760 } 00761 } 00762 } 00763 00764 if (dvert_array) MEM_freeN(dvert_array); 00765 } 00766 00767 /* TODO - select between groups */ 00768 static void vgroup_normalize_all(Object *ob, int lock_active) 00769 { 00770 MDeformWeight *dw, *dw_act; 00771 MDeformVert *dvert, **dvert_array=NULL; 00772 int i, dvert_tot=0; 00773 float tot_weight; 00774 00775 ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot); 00776 00777 if(dvert_array) { 00778 if(lock_active) { 00779 int def_nr= ob->actdef-1; 00780 00781 for(i = 0; i < dvert_tot; i++) { 00782 float lock_iweight= 1.0f; 00783 int j; 00784 00785 tot_weight= 0.0f; 00786 dw_act= NULL; 00787 dvert = dvert_array[i]; 00788 00789 j= dvert->totweight; 00790 while(j--) { 00791 dw= dvert->dw + j; 00792 00793 if(dw->def_nr==def_nr) { 00794 dw_act= dw; 00795 lock_iweight = (1.0f - dw_act->weight); 00796 } 00797 else { 00798 tot_weight += dw->weight; 00799 } 00800 } 00801 00802 if(tot_weight) { 00803 j= dvert->totweight; 00804 while(j--) { 00805 dw= dvert->dw + j; 00806 if(dw == dw_act) { 00807 if (dvert->totweight==1) { 00808 dw_act->weight= 1.0f; /* no other weights, set to 1.0 */ 00809 } 00810 } else { 00811 if(dw->weight > 0.0f) 00812 dw->weight = (dw->weight / tot_weight) * lock_iweight; 00813 } 00814 00815 /* incase of division errors with very low weights */ 00816 CLAMP(dw->weight, 0.0f, 1.0f); 00817 } 00818 } 00819 } 00820 } 00821 else { 00822 for(i = 0; i < dvert_tot; i++) { 00823 int j; 00824 tot_weight= 0.0f; 00825 dvert = dvert_array[i]; 00826 00827 j= dvert->totweight; 00828 while(j--) { 00829 dw= dvert->dw + j; 00830 tot_weight += dw->weight; 00831 } 00832 00833 if(tot_weight) { 00834 j= dvert->totweight; 00835 while(j--) { 00836 dw= dvert->dw + j; 00837 dw->weight /= tot_weight; 00838 00839 /* incase of division errors with very low weights */ 00840 CLAMP(dw->weight, 0.0f, 1.0f); 00841 } 00842 } 00843 } 00844 } 00845 } 00846 00847 if (dvert_array) MEM_freeN(dvert_array); 00848 } 00849 00850 00851 static void vgroup_invert(Object *ob, int auto_assign, int auto_remove) 00852 { 00853 bDeformGroup *dg; 00854 MDeformWeight *dw; 00855 MDeformVert *dvert, **dvert_array=NULL; 00856 int i, def_nr, dvert_tot=0; 00857 00858 ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot); 00859 00860 dg = BLI_findlink(&ob->defbase, (ob->actdef-1)); 00861 00862 if(dg) { 00863 def_nr= ob->actdef-1; 00864 00865 00866 for(i = 0; i < dvert_tot; i++) { 00867 dvert = dvert_array[i]; 00868 00869 if(auto_assign) { 00870 dw= defvert_verify_index(dvert, def_nr); 00871 } else { 00872 dw= defvert_find_index(dvert, def_nr); 00873 } 00874 00875 if(dw) { 00876 dw->weight = 1.0f-dw->weight; 00877 00878 if(auto_remove && dw->weight <= 0.0f) { 00879 /* could have a faster function for this */ 00880 ED_vgroup_nr_vert_remove(ob, def_nr, i); 00881 } 00882 } 00883 } 00884 } 00885 00886 if (dvert_array) MEM_freeN(dvert_array); 00887 } 00888 00889 static void vgroup_blend(Object *ob) 00890 { 00891 bDeformGroup *dg; 00892 MDeformWeight *dw; 00893 MDeformVert *dvert_array=NULL, *dvert; 00894 int i, def_nr, dvert_tot=0; 00895 00896 EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)ob->data)); 00897 // ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot); 00898 00899 if(em==NULL) 00900 return; 00901 00902 dg = BLI_findlink(&ob->defbase, (ob->actdef-1)); 00903 00904 if(dg) { 00905 int sel1, sel2; 00906 int i1, i2; 00907 00908 EditEdge *eed; 00909 EditVert *eve; 00910 float *vg_weights; 00911 float *vg_users; 00912 00913 def_nr= ob->actdef-1; 00914 00915 i= 0; 00916 for(eve= em->verts.first; eve; eve= eve->next) 00917 eve->tmp.l= i++; 00918 00919 dvert_tot= i; 00920 00921 vg_weights= MEM_callocN(sizeof(float)*dvert_tot, "vgroup_blend_f"); 00922 vg_users= MEM_callocN(sizeof(int)*dvert_tot, "vgroup_blend_i"); 00923 00924 for(eed= em->edges.first; eed; eed= eed->next) { 00925 sel1= eed->v1->f & SELECT; 00926 sel2= eed->v2->f & SELECT; 00927 00928 if(sel1 != sel2) { 00929 /* i1 is always the selected one */ 00930 if(sel1==TRUE && sel2==FALSE) { 00931 i1= eed->v1->tmp.l; 00932 i2= eed->v2->tmp.l; 00933 eve= eed->v2; 00934 } 00935 else { 00936 i2= eed->v1->tmp.l; 00937 i1= eed->v2->tmp.l; 00938 eve= eed->v1; 00939 } 00940 00941 vg_users[i1]++; 00942 00943 /* TODO, we may want object mode blending */ 00944 if(em) dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); 00945 else dvert= dvert_array+i2; 00946 00947 dw= defvert_find_index(dvert, def_nr); 00948 00949 if(dw) { 00950 vg_weights[i1] += dw->weight; 00951 } 00952 } 00953 } 00954 00955 i= 0; 00956 for(eve= em->verts.first; eve; eve= eve->next) { 00957 if(eve->f & SELECT && vg_users[i] > 0) { 00958 /* TODO, we may want object mode blending */ 00959 if(em) dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); 00960 else dvert= dvert_array+i; 00961 00962 dw= defvert_verify_index(dvert, def_nr); 00963 dw->weight= vg_weights[i] / (float)vg_users[i]; 00964 } 00965 00966 i++; 00967 } 00968 MEM_freeN(vg_weights); 00969 MEM_freeN(vg_users); 00970 } 00971 } 00972 00973 static void vgroup_clean(Object *ob, float eul, int keep_single) 00974 { 00975 bDeformGroup *dg; 00976 MDeformWeight *dw; 00977 MDeformVert *dvert, **dvert_array=NULL; 00978 int i, def_nr, dvert_tot=0; 00979 00980 ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot); 00981 00982 /* only the active group */ 00983 dg = BLI_findlink(&ob->defbase, (ob->actdef-1)); 00984 if(dg) { 00985 def_nr= ob->actdef-1; 00986 00987 for(i = 0; i < dvert_tot; i++) { 00988 dvert = dvert_array[i]; 00989 00990 dw= defvert_find_index(dvert, def_nr); 00991 00992 if(dw) { 00993 if(dw->weight <= eul) 00994 if(keep_single==FALSE || dvert->totweight > 1) 00995 ED_vgroup_nr_vert_remove(ob, def_nr, i); 00996 } 00997 } 00998 } 00999 01000 if (dvert_array) MEM_freeN(dvert_array); 01001 } 01002 01003 static void vgroup_clean_all(Object *ob, float eul, int keep_single) 01004 { 01005 01006 MDeformWeight *dw; 01007 MDeformVert *dvert, **dvert_array=NULL; 01008 int i, dvert_tot=0; 01009 01010 ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot); 01011 01012 if(dvert_array) { 01013 for(i = 0; i < dvert_tot; i++) { 01014 int j; 01015 dvert = dvert_array[i]; 01016 j= dvert->totweight; 01017 01018 while(j--) { 01019 01020 if(keep_single && dvert->totweight == 1) 01021 break; 01022 01023 dw= dvert->dw + j; 01024 01025 if(dw->weight <= eul) 01026 ED_vgroup_nr_vert_remove(ob, dw->def_nr, i); 01027 01028 } 01029 } 01030 } 01031 01032 if (dvert_array) MEM_freeN(dvert_array); 01033 } 01034 01035 01036 static void dvert_mirror_op(MDeformVert *dvert, MDeformVert *dvert_mirr, 01037 const char sel, const char sel_mirr, 01038 const int *flip_map, 01039 const short mirror_weights, const short flip_vgroups) 01040 { 01041 BLI_assert(sel || sel_mirr); 01042 01043 if(sel_mirr && sel) { 01044 /* swap */ 01045 if(mirror_weights) 01046 SWAP(MDeformVert, *dvert, *dvert_mirr); 01047 if(flip_vgroups) { 01048 defvert_flip(dvert, flip_map); 01049 defvert_flip(dvert_mirr, flip_map); 01050 } 01051 } 01052 else { 01053 /* dvert should always be the target */ 01054 if(sel_mirr) { 01055 SWAP(MDeformVert *, dvert, dvert_mirr); 01056 } 01057 01058 if(mirror_weights) 01059 defvert_copy(dvert, dvert_mirr); 01060 if(flip_vgroups) { 01061 defvert_flip(dvert, flip_map); 01062 } 01063 } 01064 } 01065 01066 void ED_vgroup_mirror(Object *ob, const short mirror_weights, const short flip_vgroups) 01067 { 01068 #define VGROUP_MIRR_OP dvert_mirror_op(dvert, dvert_mirr, sel, sel_mirr, flip_map, mirror_weights, flip_vgroups) 01069 01070 EditVert *eve, *eve_mirr; 01071 MDeformVert *dvert, *dvert_mirr; 01072 short sel, sel_mirr; 01073 int *flip_map; 01074 01075 if(mirror_weights==0 && flip_vgroups==0) 01076 return; 01077 01078 flip_map= defgroup_flip_map(ob, 0); 01079 01080 /* only the active group */ 01081 if(ob->type == OB_MESH) { 01082 Mesh *me= ob->data; 01083 EditMesh *em = BKE_mesh_get_editmesh(me); 01084 01085 01086 if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) { 01087 MEM_freeN(flip_map); 01088 return; 01089 } 01090 01091 EM_cache_x_mirror_vert(ob, em); 01092 01093 /* Go through the list of editverts and assign them */ 01094 for(eve=em->verts.first; eve; eve=eve->next){ 01095 if((eve_mirr=eve->tmp.v)) { 01096 sel= eve->f & SELECT; 01097 sel_mirr= eve_mirr->f & SELECT; 01098 01099 if((sel || sel_mirr) && (eve != eve_mirr)) { 01100 dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); 01101 dvert_mirr= CustomData_em_get(&em->vdata, eve_mirr->data, CD_MDEFORMVERT); 01102 if(dvert && dvert_mirr) { 01103 VGROUP_MIRR_OP; 01104 } 01105 } 01106 01107 eve->tmp.v= eve_mirr->tmp.v= NULL; 01108 } 01109 } 01110 01111 BKE_mesh_end_editmesh(me, em); 01112 } 01113 else if (ob->type == OB_LATTICE) { 01114 Lattice *lt= ob->data; 01115 int i1, i2; 01116 int u, v, w; 01117 int pntsu_half; 01118 /* half but found up odd value */ 01119 01120 if(lt->editlatt) lt= lt->editlatt->latt; 01121 01122 if(lt->pntsu == 1 || lt->dvert == NULL) { 01123 MEM_freeN(flip_map); 01124 return; 01125 } 01126 01127 /* unlike editmesh we know that by only looping over the first hald of 01128 * the 'u' indicies it will cover all points except the middle which is 01129 * ok in this case */ 01130 pntsu_half= lt->pntsu / 2; 01131 01132 for(w=0; w<lt->pntsw; w++) { 01133 for(v=0; v<lt->pntsv; v++) { 01134 for(u=0; u<pntsu_half; u++) { 01135 int u_inv= (lt->pntsu - 1) - u; 01136 if(u != u_inv) { 01137 BPoint *bp, *bp_mirr; 01138 01139 i1= LT_INDEX(lt, u, v, w); 01140 i2= LT_INDEX(lt, u_inv, v, w); 01141 01142 bp= <->def[i1]; 01143 bp_mirr= <->def[i2]; 01144 01145 sel= bp->f1 & SELECT; 01146 sel_mirr= bp_mirr->f1 & SELECT; 01147 01148 if(sel || sel_mirr) { 01149 dvert= <->dvert[i1]; 01150 dvert_mirr= <->dvert[i2]; 01151 01152 VGROUP_MIRR_OP; 01153 } 01154 } 01155 } 01156 } 01157 } 01158 } 01159 01160 MEM_freeN(flip_map); 01161 01162 #undef VGROUP_MIRR_OP 01163 } 01164 01165 static void vgroup_remap_update_users(Object *ob, int *map) 01166 { 01167 ExplodeModifierData *emd; 01168 ModifierData *md; 01169 ParticleSystem *psys; 01170 ClothModifierData *clmd; 01171 ClothSimSettings *clsim; 01172 int a; 01173 01174 /* these cases don't use names to refer to vertex groups, so when 01175 * they get deleted the numbers get out of sync, this corrects that */ 01176 01177 if(ob->soft) 01178 ob->soft->vertgroup= map[ob->soft->vertgroup]; 01179 01180 for(md=ob->modifiers.first; md; md=md->next) { 01181 if(md->type == eModifierType_Explode) { 01182 emd= (ExplodeModifierData*)md; 01183 emd->vgroup= map[emd->vgroup]; 01184 } 01185 else if(md->type == eModifierType_Cloth) { 01186 clmd= (ClothModifierData*)md; 01187 clsim= clmd->sim_parms; 01188 01189 if(clsim) { 01190 clsim->vgroup_mass= map[clsim->vgroup_mass]; 01191 clsim->vgroup_bend= map[clsim->vgroup_bend]; 01192 clsim->vgroup_struct= map[clsim->vgroup_struct]; 01193 } 01194 } 01195 } 01196 01197 for(psys=ob->particlesystem.first; psys; psys=psys->next) { 01198 for(a=0; a<PSYS_TOT_VG; a++) 01199 psys->vgroup[a]= map[psys->vgroup[a]]; 01200 } 01201 } 01202 01203 01204 static void vgroup_delete_update_users(Object *ob, int id) 01205 { 01206 int i, tot= BLI_countlist(&ob->defbase) + 1; 01207 int *map= MEM_mallocN(sizeof(int) * tot, "vgroup del"); 01208 01209 map[id]= map[0]= 0; 01210 for(i=1; i<id; i++) map[i]=i; 01211 for(i=id+1; i<tot; i++) map[i]=i-1; 01212 01213 vgroup_remap_update_users(ob, map); 01214 MEM_freeN(map); 01215 } 01216 01217 01218 static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg) 01219 { 01220 MDeformVert *dvert_array=NULL; 01221 int i, e, dvert_tot=0; 01222 const int dg_index= BLI_findindex(&ob->defbase, dg); 01223 01224 assert(dg_index > -1); 01225 01226 ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot); 01227 01228 if(dvert_array) { 01229 MDeformVert *dvert; 01230 for(i= 0, dvert= dvert_array; i < dvert_tot; i++, dvert++) { 01231 ED_vgroup_vert_remove(ob, dg, i); /* ok if the dg isnt in this dvert, will continue silently */ 01232 } 01233 01234 for(i= 0, dvert= dvert_array; i < dvert_tot; i++, dvert++) { 01235 for(e = 0; e < dvert->totweight; e++) { 01236 if(dvert->dw[e].def_nr > dg_index) { 01237 dvert->dw[e].def_nr--; 01238 } 01239 } 01240 } 01241 } 01242 01243 vgroup_delete_update_users(ob, dg_index + 1); 01244 01245 /* Remove the group */ 01246 BLI_freelinkN(&ob->defbase, dg); 01247 01248 /* Update the active deform index if necessary */ 01249 if(ob->actdef > dg_index) 01250 ob->actdef--; 01251 if(ob->actdef < 1 && ob->defbase.first) 01252 ob->actdef= 1; 01253 01254 } 01255 01256 /* only in editmode */ 01257 /* removes from active defgroup, if allverts==0 only selected vertices */ 01258 static void vgroup_active_remove_verts(Object *ob, const int allverts, bDeformGroup *dg) 01259 { 01260 EditVert *eve; 01261 MDeformVert *dvert; 01262 MDeformWeight *newdw; 01263 bDeformGroup *eg; 01264 int i; 01265 01266 if(ob->type == OB_MESH) { 01267 Mesh *me= ob->data; 01268 EditMesh *em = BKE_mesh_get_editmesh(me); 01269 01270 for(eve=em->verts.first; eve; eve=eve->next){ 01271 dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); 01272 01273 if(dvert && dvert->dw && ((eve->f & SELECT) || allverts)){ 01274 for(i=0; i<dvert->totweight; i++){ 01275 /* Find group */ 01276 eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr); 01277 if(eg == dg){ 01278 dvert->totweight--; 01279 if(dvert->totweight){ 01280 newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), "deformWeight"); 01281 01282 if(dvert->dw){ 01283 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i); 01284 memcpy(newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i)); 01285 MEM_freeN(dvert->dw); 01286 } 01287 dvert->dw=newdw; 01288 } 01289 else{ 01290 MEM_freeN(dvert->dw); 01291 dvert->dw=NULL; 01292 break; 01293 } 01294 } 01295 } 01296 } 01297 } 01298 BKE_mesh_end_editmesh(me, em); 01299 } 01300 else if(ob->type == OB_LATTICE) { 01301 Lattice *lt= vgroup_edit_lattice(ob); 01302 01303 if(lt->dvert) { 01304 BPoint *bp; 01305 int a, tot= lt->pntsu*lt->pntsv*lt->pntsw; 01306 01307 for(a=0, bp= lt->def; a<tot; a++, bp++) { 01308 if(allverts || (bp->f1 & SELECT)) 01309 ED_vgroup_vert_remove(ob, dg, a); 01310 } 01311 } 01312 } 01313 } 01314 01315 static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *dg) 01316 { 01317 int i; 01318 const int dg_index= BLI_findindex(&ob->defbase, dg); 01319 01320 assert(dg_index > -1); 01321 01322 /* Make sure that no verts are using this group */ 01323 vgroup_active_remove_verts(ob, TRUE, dg); 01324 01325 /* Make sure that any verts with higher indices are adjusted accordingly */ 01326 if(ob->type==OB_MESH) { 01327 Mesh *me= ob->data; 01328 EditMesh *em = BKE_mesh_get_editmesh(me); 01329 EditVert *eve; 01330 MDeformVert *dvert; 01331 01332 for(eve=em->verts.first; eve; eve=eve->next){ 01333 dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); 01334 01335 if(dvert) 01336 for(i=0; i<dvert->totweight; i++) 01337 if(dvert->dw[i].def_nr > dg_index) 01338 dvert->dw[i].def_nr--; 01339 } 01340 BKE_mesh_end_editmesh(me, em); 01341 } 01342 else if(ob->type==OB_LATTICE) { 01343 Lattice *lt= vgroup_edit_lattice(ob); 01344 BPoint *bp; 01345 MDeformVert *dvert= lt->dvert; 01346 int a, tot; 01347 01348 if(dvert) { 01349 tot= lt->pntsu*lt->pntsv*lt->pntsw; 01350 for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) { 01351 for(i=0; i<dvert->totweight; i++){ 01352 if(dvert->dw[i].def_nr > dg_index) 01353 dvert->dw[i].def_nr--; 01354 } 01355 } 01356 } 01357 } 01358 01359 vgroup_delete_update_users(ob, dg_index + 1); 01360 01361 /* Remove the group */ 01362 BLI_freelinkN (&ob->defbase, dg); 01363 01364 /* Update the active deform index if necessary */ 01365 if(ob->actdef > dg_index) 01366 ob->actdef--; 01367 if(ob->actdef < 1 && ob->defbase.first) 01368 ob->actdef= 1; 01369 01370 /* remove all dverts */ 01371 if(ob->defbase.first == NULL) { 01372 if(ob->type==OB_MESH) { 01373 Mesh *me= ob->data; 01374 CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert); 01375 me->dvert= NULL; 01376 } 01377 else if(ob->type==OB_LATTICE) { 01378 Lattice *lt= vgroup_edit_lattice(ob); 01379 if(lt->dvert) { 01380 MEM_freeN(lt->dvert); 01381 lt->dvert= NULL; 01382 } 01383 } 01384 } 01385 } 01386 01387 static int vgroup_object_in_edit_mode(Object *ob) 01388 { 01389 if(ob->type == OB_MESH) 01390 return (((Mesh*)ob->data)->edit_mesh != NULL); 01391 else if(ob->type == OB_LATTICE) 01392 return (((Lattice*)ob->data)->editlatt != NULL); 01393 01394 return 0; 01395 } 01396 01397 static void vgroup_delete(Object *ob) 01398 { 01399 bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef-1); 01400 if(!dg) 01401 return; 01402 01403 if(vgroup_object_in_edit_mode(ob)) 01404 vgroup_delete_edit_mode(ob, dg); 01405 else 01406 vgroup_delete_object_mode(ob, dg); 01407 } 01408 01409 static void vgroup_delete_all(Object *ob) 01410 { 01411 /* Remove all DVerts */ 01412 if(ob->type==OB_MESH) { 01413 Mesh *me= ob->data; 01414 CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert); 01415 me->dvert= NULL; 01416 } 01417 else if(ob->type==OB_LATTICE) { 01418 Lattice *lt= vgroup_edit_lattice(ob); 01419 if(lt->dvert) { 01420 MEM_freeN(lt->dvert); 01421 lt->dvert= NULL; 01422 } 01423 } 01424 01425 /* Remove all DefGroups */ 01426 BLI_freelistN(&ob->defbase); 01427 01428 /* Fix counters/indices */ 01429 ob->actdef= 0; 01430 } 01431 01432 /* only in editmode */ 01433 static void vgroup_assign_verts(Object *ob, float weight) 01434 { 01435 EditVert *eve; 01436 bDeformGroup *dg, *eg; 01437 MDeformWeight *newdw; 01438 MDeformVert *dvert; 01439 int i, done; 01440 01441 dg=BLI_findlink(&ob->defbase, ob->actdef-1); 01442 if(!dg) 01443 return; 01444 01445 if(ob->type == OB_MESH) { 01446 Mesh *me= ob->data; 01447 EditMesh *em = BKE_mesh_get_editmesh(me); 01448 01449 if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) 01450 EM_add_data_layer(em, &em->vdata, CD_MDEFORMVERT, NULL); 01451 01452 /* Go through the list of editverts and assign them */ 01453 for(eve=em->verts.first; eve; eve=eve->next){ 01454 dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); 01455 01456 if(dvert && (eve->f & SELECT)){ 01457 /* See if this vert already has a reference to this group */ 01458 /* If so: Change its weight */ 01459 done=0; 01460 for(i=0; i<dvert->totweight; i++){ 01461 eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr); 01462 /* Find the actual group */ 01463 if(eg==dg){ 01464 dvert->dw[i].weight= weight; 01465 done=1; 01466 break; 01467 } 01468 } 01469 /* If not: Add the group and set its weight */ 01470 if(!done){ 01471 newdw = MEM_callocN(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight"); 01472 if(dvert->dw){ 01473 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight); 01474 MEM_freeN(dvert->dw); 01475 } 01476 dvert->dw=newdw; 01477 01478 dvert->dw[dvert->totweight].weight= weight; 01479 dvert->dw[dvert->totweight].def_nr= ob->actdef-1; 01480 01481 dvert->totweight++; 01482 01483 } 01484 } 01485 } 01486 BKE_mesh_end_editmesh(me, em); 01487 } 01488 else if(ob->type == OB_LATTICE) { 01489 Lattice *lt= vgroup_edit_lattice(ob); 01490 BPoint *bp; 01491 int a, tot; 01492 01493 if(lt->dvert==NULL) 01494 ED_vgroup_data_create(<->id); 01495 01496 tot= lt->pntsu*lt->pntsv*lt->pntsw; 01497 for(a=0, bp= lt->def; a<tot; a++, bp++) { 01498 if(bp->f1 & SELECT) 01499 ED_vgroup_nr_vert_add(ob, ob->actdef-1, a, weight, WEIGHT_REPLACE); 01500 } 01501 } 01502 } 01503 01504 /* only in editmode */ 01505 /* removes from all defgroup, if allverts==0 only selected vertices */ 01506 static void vgroup_remove_verts(Object *ob, int allverts) 01507 { 01508 /* To prevent code redundancy, we just use vgroup_active_remove_verts, but that 01509 * only operates on the active vgroup. So we iterate through all groups, by changing 01510 * active group index 01511 */ 01512 bDeformGroup *dg; 01513 for(dg= ob->defbase.first; dg; dg= dg->next) { 01514 vgroup_active_remove_verts(ob, allverts, dg); 01515 } 01516 } 01517 01518 /********************** vertex group operators *********************/ 01519 01520 static int vertex_group_poll(bContext *C) 01521 { 01522 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01523 ID *data= (ob)? ob->data: NULL; 01524 return (ob && !ob->id.lib && ELEM(ob->type, OB_MESH, OB_LATTICE) && data && !data->lib); 01525 } 01526 01527 static int vertex_group_poll_edit(bContext *C) 01528 { 01529 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01530 ID *data= (ob)? ob->data: NULL; 01531 01532 if(!(ob && !ob->id.lib && data && !data->lib)) 01533 return 0; 01534 01535 return vgroup_object_in_edit_mode(ob); 01536 } 01537 01538 static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op)) 01539 { 01540 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01541 01542 ED_vgroup_add(ob); 01543 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01544 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); 01545 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); 01546 01547 return OPERATOR_FINISHED; 01548 } 01549 01550 void OBJECT_OT_vertex_group_add(wmOperatorType *ot) 01551 { 01552 /* identifiers */ 01553 ot->name= "Add Vertex Group"; 01554 ot->idname= "OBJECT_OT_vertex_group_add"; 01555 01556 /* api callbacks */ 01557 ot->poll= vertex_group_poll; 01558 ot->exec= vertex_group_add_exec; 01559 01560 /* flags */ 01561 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01562 } 01563 01564 static int vertex_group_remove_exec(bContext *C, wmOperator *op) 01565 { 01566 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01567 01568 if(RNA_boolean_get(op->ptr, "all")) 01569 vgroup_delete_all(ob); 01570 else 01571 vgroup_delete(ob); 01572 01573 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01574 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); 01575 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); 01576 01577 return OPERATOR_FINISHED; 01578 } 01579 01580 void OBJECT_OT_vertex_group_remove(wmOperatorType *ot) 01581 { 01582 /* identifiers */ 01583 ot->name= "Remove Vertex Group"; 01584 ot->idname= "OBJECT_OT_vertex_group_remove"; 01585 01586 /* api callbacks */ 01587 ot->poll= vertex_group_poll; 01588 ot->exec= vertex_group_remove_exec; 01589 01590 /* flags */ 01591 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01592 01593 /* properties */ 01594 RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups."); 01595 } 01596 01597 static int vertex_group_assign_exec(bContext *C, wmOperator *op) 01598 { 01599 ToolSettings *ts= CTX_data_tool_settings(C); 01600 Object *ob= CTX_data_edit_object(C); 01601 01602 if(RNA_boolean_get(op->ptr, "new")) 01603 ED_vgroup_add(ob); 01604 01605 vgroup_assign_verts(ob, ts->vgroup_weight); 01606 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01607 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); 01608 01609 return OPERATOR_FINISHED; 01610 } 01611 01612 void OBJECT_OT_vertex_group_assign(wmOperatorType *ot) 01613 { 01614 /* identifiers */ 01615 ot->name= "Assign Vertex Group"; 01616 ot->idname= "OBJECT_OT_vertex_group_assign"; 01617 01618 /* api callbacks */ 01619 ot->poll= vertex_group_poll_edit; 01620 ot->exec= vertex_group_assign_exec; 01621 01622 /* flags */ 01623 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01624 01625 /* properties */ 01626 RNA_def_boolean(ot->srna, "new", 0, "New", "Assign vertex to new vertex group."); 01627 } 01628 01629 static int vertex_group_remove_from_exec(bContext *C, wmOperator *op) 01630 { 01631 Object *ob= CTX_data_edit_object(C); 01632 01633 if(RNA_boolean_get(op->ptr, "all")) 01634 vgroup_remove_verts(ob, 0); 01635 else { 01636 bDeformGroup *dg= BLI_findlink(&ob->defbase, ob->actdef - 1); 01637 01638 if(dg == NULL) { 01639 return OPERATOR_CANCELLED; 01640 } 01641 01642 vgroup_active_remove_verts(ob, FALSE, dg); 01643 } 01644 01645 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01646 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); 01647 01648 return OPERATOR_FINISHED; 01649 } 01650 01651 void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot) 01652 { 01653 /* identifiers */ 01654 ot->name= "Remove from Vertex Group"; 01655 ot->idname= "OBJECT_OT_vertex_group_remove_from"; 01656 01657 /* api callbacks */ 01658 ot->poll= vertex_group_poll_edit; 01659 ot->exec= vertex_group_remove_from_exec; 01660 01661 /* flags */ 01662 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01663 01664 /* properties */ 01665 RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups."); 01666 } 01667 01668 static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op)) 01669 { 01670 Object *ob= CTX_data_edit_object(C); 01671 01672 if(!ob || ob->id.lib) 01673 return OPERATOR_CANCELLED; 01674 01675 vgroup_select_verts(ob, 1); 01676 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data); 01677 01678 return OPERATOR_FINISHED; 01679 } 01680 01681 void OBJECT_OT_vertex_group_select(wmOperatorType *ot) 01682 { 01683 /* identifiers */ 01684 ot->name= "Select Vertex Group"; 01685 ot->idname= "OBJECT_OT_vertex_group_select"; 01686 01687 /* api callbacks */ 01688 ot->poll= vertex_group_poll_edit; 01689 ot->exec= vertex_group_select_exec; 01690 01691 /* flags */ 01692 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01693 } 01694 01695 static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op)) 01696 { 01697 Object *ob= CTX_data_edit_object(C); 01698 01699 vgroup_select_verts(ob, 0); 01700 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data); 01701 01702 return OPERATOR_FINISHED; 01703 } 01704 01705 void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot) 01706 { 01707 /* identifiers */ 01708 ot->name= "Deselect Vertex Group"; 01709 ot->idname= "OBJECT_OT_vertex_group_deselect"; 01710 01711 /* api callbacks */ 01712 ot->poll= vertex_group_poll_edit; 01713 ot->exec= vertex_group_deselect_exec; 01714 01715 /* flags */ 01716 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01717 } 01718 01719 static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op)) 01720 { 01721 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01722 01723 vgroup_duplicate(ob); 01724 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01725 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); 01726 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); 01727 01728 return OPERATOR_FINISHED; 01729 } 01730 01731 void OBJECT_OT_vertex_group_copy(wmOperatorType *ot) 01732 { 01733 /* identifiers */ 01734 ot->name= "Copy Vertex Group"; 01735 ot->idname= "OBJECT_OT_vertex_group_copy"; 01736 01737 /* api callbacks */ 01738 ot->poll= vertex_group_poll; 01739 ot->exec= vertex_group_copy_exec; 01740 01741 /* flags */ 01742 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01743 } 01744 01745 static int vertex_group_levels_exec(bContext *C, wmOperator *op) 01746 { 01747 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01748 01749 float offset= RNA_float_get(op->ptr,"offset"); 01750 float gain= RNA_float_get(op->ptr,"gain"); 01751 01752 vgroup_levels(ob, offset, gain); 01753 01754 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01755 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); 01756 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); 01757 01758 return OPERATOR_FINISHED; 01759 } 01760 01761 void OBJECT_OT_vertex_group_levels(wmOperatorType *ot) 01762 { 01763 /* identifiers */ 01764 ot->name= "Vertex Group Levels"; 01765 ot->idname= "OBJECT_OT_vertex_group_levels"; 01766 01767 /* api callbacks */ 01768 ot->poll= vertex_group_poll; 01769 ot->exec= vertex_group_levels_exec; 01770 01771 /* flags */ 01772 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01773 01774 RNA_def_float(ot->srna, "offset", 0.f, -1.0, 1.0, "Offset", "Value to add to weights.", -1.0f, 1.f); 01775 RNA_def_float(ot->srna, "gain", 1.f, 0.f, FLT_MAX, "Gain", "Value to multiply weights by.", 0.0f, 10.f); 01776 } 01777 01778 static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op)) 01779 { 01780 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01781 01782 vgroup_normalize(ob); 01783 01784 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01785 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); 01786 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); 01787 01788 return OPERATOR_FINISHED; 01789 } 01790 01791 void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot) 01792 { 01793 /* identifiers */ 01794 ot->name= "Normalize Vertex Group"; 01795 ot->idname= "OBJECT_OT_vertex_group_normalize"; 01796 01797 /* api callbacks */ 01798 ot->poll= vertex_group_poll; 01799 ot->exec= vertex_group_normalize_exec; 01800 01801 /* flags */ 01802 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01803 } 01804 01805 static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op) 01806 { 01807 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01808 int lock_active= RNA_boolean_get(op->ptr,"lock_active"); 01809 01810 vgroup_normalize_all(ob, lock_active); 01811 01812 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01813 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); 01814 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); 01815 01816 return OPERATOR_FINISHED; 01817 } 01818 01819 void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot) 01820 { 01821 /* identifiers */ 01822 ot->name= "Normalize All Vertex Groups"; 01823 ot->idname= "OBJECT_OT_vertex_group_normalize_all"; 01824 01825 /* api callbacks */ 01826 ot->poll= vertex_group_poll; 01827 ot->exec= vertex_group_normalize_all_exec; 01828 01829 /* flags */ 01830 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01831 01832 RNA_def_boolean(ot->srna, "lock_active", TRUE, "Lock Active", "Keep the values of the active group while normalizing others."); 01833 } 01834 01835 static int vertex_group_invert_exec(bContext *C, wmOperator *op) 01836 { 01837 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01838 int auto_assign= RNA_boolean_get(op->ptr,"auto_assign"); 01839 int auto_remove= RNA_boolean_get(op->ptr,"auto_remove"); 01840 01841 vgroup_invert(ob, auto_assign, auto_remove); 01842 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01843 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); 01844 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); 01845 01846 return OPERATOR_FINISHED; 01847 } 01848 01849 void OBJECT_OT_vertex_group_invert(wmOperatorType *ot) 01850 { 01851 /* identifiers */ 01852 ot->name= "Invert Vertex Group"; 01853 ot->idname= "OBJECT_OT_vertex_group_invert"; 01854 01855 /* api callbacks */ 01856 ot->poll= vertex_group_poll; 01857 ot->exec= vertex_group_invert_exec; 01858 01859 /* flags */ 01860 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01861 01862 RNA_def_boolean(ot->srna, "auto_assign", TRUE, "Add Weights", "Add verts from groups that have zero weight before inverting."); 01863 RNA_def_boolean(ot->srna, "auto_remove", TRUE, "Remove Weights", "Remove verts from groups that have zero weight after inverting."); 01864 } 01865 01866 01867 static int vertex_group_blend_exec(bContext *C, wmOperator *UNUSED(op)) 01868 { 01869 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01870 01871 vgroup_blend(ob); 01872 01873 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01874 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); 01875 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); 01876 01877 return OPERATOR_FINISHED; 01878 } 01879 01880 void OBJECT_OT_vertex_group_blend(wmOperatorType *ot) 01881 { 01882 /* identifiers */ 01883 ot->name= "Blend Vertex Group"; 01884 ot->idname= "OBJECT_OT_vertex_group_blend"; 01885 ot->description= ""; 01886 01887 /* api callbacks */ 01888 ot->poll= vertex_group_poll; 01889 ot->exec= vertex_group_blend_exec; 01890 01891 /* flags */ 01892 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01893 } 01894 01895 01896 static int vertex_group_clean_exec(bContext *C, wmOperator *op) 01897 { 01898 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01899 01900 float limit= RNA_float_get(op->ptr,"limit"); 01901 int all_groups= RNA_boolean_get(op->ptr,"all_groups"); 01902 int keep_single= RNA_boolean_get(op->ptr,"keep_single"); 01903 01904 if(all_groups) vgroup_clean_all(ob, limit, keep_single); 01905 else vgroup_clean(ob, limit, keep_single); 01906 01907 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01908 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); 01909 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); 01910 01911 return OPERATOR_FINISHED; 01912 } 01913 01914 void OBJECT_OT_vertex_group_clean(wmOperatorType *ot) 01915 { 01916 /* identifiers */ 01917 ot->name= "Clean Vertex Group"; 01918 ot->idname= "OBJECT_OT_vertex_group_clean"; 01919 ot->description= "Remove Vertex Group assignments which aren't required"; 01920 01921 /* api callbacks */ 01922 ot->poll= vertex_group_poll; 01923 ot->exec= vertex_group_clean_exec; 01924 01925 /* flags */ 01926 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01927 01928 RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, 1.0, "Limit", "Remove weights under this limit.", 0.001f, 0.99f); 01929 RNA_def_boolean(ot->srna, "all_groups", FALSE, "All Groups", "Clean all vertex groups."); 01930 RNA_def_boolean(ot->srna, "keep_single", FALSE, "Keep Single", "Keep verts assigned to at least one group when cleaning."); 01931 } 01932 01933 01934 static int vertex_group_mirror_exec(bContext *C, wmOperator *op) 01935 { 01936 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01937 01938 ED_vgroup_mirror(ob, RNA_boolean_get(op->ptr,"mirror_weights"), RNA_boolean_get(op->ptr,"flip_group_names")); 01939 01940 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01941 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); 01942 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); 01943 01944 return OPERATOR_FINISHED; 01945 } 01946 01947 void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot) 01948 { 01949 /* identifiers */ 01950 ot->name= "Mirror Vertex Group"; 01951 ot->idname= "OBJECT_OT_vertex_group_mirror"; 01952 ot->description= "Mirror all vertex groups, flip weights and/or names, editing only selected vertices, flipping when both sides are selected otherwise copy from unselected"; 01953 01954 /* api callbacks */ 01955 ot->poll= vertex_group_poll_edit; 01956 ot->exec= vertex_group_mirror_exec; 01957 01958 /* flags */ 01959 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01960 01961 /* properties */ 01962 RNA_def_boolean(ot->srna, "mirror_weights", TRUE, "Mirror Weights", "Mirror weights."); 01963 RNA_def_boolean(ot->srna, "flip_group_names", TRUE, "Flip Groups", "Flip vertex group names."); 01964 01965 } 01966 01967 static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op)) 01968 { 01969 Scene *scene= CTX_data_scene(C); 01970 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 01971 Base *base; 01972 int retval= OPERATOR_CANCELLED; 01973 01974 for(base=scene->base.first; base; base= base->next) { 01975 if(base->object->type==ob->type) { 01976 if(base->object!=ob && base->object->data==ob->data) { 01977 BLI_freelistN(&base->object->defbase); 01978 BLI_duplicatelist(&base->object->defbase, &ob->defbase); 01979 base->object->actdef= ob->actdef; 01980 01981 DAG_id_tag_update(&base->object->id, OB_RECALC_DATA); 01982 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, base->object); 01983 WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data); 01984 01985 retval = OPERATOR_FINISHED; 01986 } 01987 } 01988 } 01989 01990 return retval; 01991 } 01992 01993 void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot) 01994 { 01995 /* identifiers */ 01996 ot->name= "Copy Vertex Groups to Linked"; 01997 ot->idname= "OBJECT_OT_vertex_group_copy_to_linked"; 01998 ot->description= "Copy Vertex Groups to all users of the same Geometry data"; 01999 02000 /* api callbacks */ 02001 ot->poll= vertex_group_poll; 02002 ot->exec= vertex_group_copy_to_linked_exec; 02003 02004 /* flags */ 02005 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02006 } 02007 02008 static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op) 02009 { 02010 Object *obact= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 02011 int change= 0; 02012 int fail= 0; 02013 02014 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) 02015 { 02016 if(obact != ob) { 02017 if(ED_vgroup_copy_array(ob, obact)) change++; 02018 else fail++; 02019 } 02020 } 02021 CTX_DATA_END; 02022 02023 if((change == 0 && fail == 0) || fail) { 02024 BKE_reportf(op->reports, RPT_ERROR, "Copy to VGroups to Selected warning done %d, failed %d, object data must have matching indicies", change, fail); 02025 } 02026 02027 return OPERATOR_FINISHED; 02028 } 02029 02030 02031 void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot) 02032 { 02033 /* identifiers */ 02034 ot->name= "Copy Vertex Group to Selected"; 02035 ot->idname= "OBJECT_OT_vertex_group_copy_to_selected"; 02036 ot->description= "Copy Vertex Groups to other selected objects with matching indices"; 02037 02038 /* api callbacks */ 02039 ot->poll= vertex_group_poll; 02040 ot->exec= vertex_group_copy_to_selected_exec; 02041 02042 /* flags */ 02043 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02044 } 02045 02046 static EnumPropertyItem vgroup_items[]= { 02047 {0, NULL, 0, NULL, NULL}}; 02048 02049 static int set_active_group_exec(bContext *C, wmOperator *op) 02050 { 02051 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 02052 int nr= RNA_enum_get(op->ptr, "group"); 02053 02054 ob->actdef= nr+1; 02055 02056 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 02057 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob); 02058 02059 return OPERATOR_FINISHED; 02060 } 02061 02062 static EnumPropertyItem *vgroup_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free) 02063 { 02064 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 02065 EnumPropertyItem tmp = {0, "", 0, "", ""}; 02066 EnumPropertyItem *item= NULL; 02067 bDeformGroup *def; 02068 int a, totitem= 0; 02069 02070 if(!ob) 02071 return vgroup_items; 02072 02073 for(a=0, def=ob->defbase.first; def; def=def->next, a++) { 02074 tmp.value= a; 02075 tmp.icon= ICON_GROUP_VERTEX; 02076 tmp.identifier= def->name; 02077 tmp.name= def->name; 02078 RNA_enum_item_add(&item, &totitem, &tmp); 02079 } 02080 02081 RNA_enum_item_end(&item, &totitem); 02082 *free= 1; 02083 02084 return item; 02085 } 02086 02087 void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot) 02088 { 02089 PropertyRNA *prop; 02090 02091 /* identifiers */ 02092 ot->name= "Set Active Vertex Group"; 02093 ot->idname= "OBJECT_OT_vertex_group_set_active"; 02094 ot->description= "Set the active vertex group"; 02095 02096 /* api callbacks */ 02097 ot->poll= vertex_group_poll; 02098 ot->exec= set_active_group_exec; 02099 ot->invoke= WM_menu_invoke; 02100 02101 /* flags */ 02102 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02103 02104 /* properties */ 02105 prop= RNA_def_enum(ot->srna, "group", vgroup_items, 0, "Group", "Vertex group to set as active."); 02106 RNA_def_enum_funcs(prop, vgroup_itemf); 02107 ot->prop= prop; 02108 } 02109 02110 /*creates the name_array parameter for vgroup_do_remap, call this before fiddling 02111 with the order of vgroups then call vgroup_do_remap after*/ 02112 static char *vgroup_init_remap(Object *ob) 02113 { 02114 bDeformGroup *def; 02115 int def_tot = BLI_countlist(&ob->defbase); 02116 char *name_array= MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * def_tot, "sort vgroups"); 02117 char *name; 02118 02119 name= name_array; 02120 for(def = ob->defbase.first; def; def=def->next) { 02121 BLI_strncpy(name, def->name, MAX_VGROUP_NAME); 02122 name += MAX_VGROUP_NAME; 02123 } 02124 02125 return name_array; 02126 } 02127 02128 static int vgroup_do_remap(Object *ob, char *name_array, wmOperator *op) 02129 { 02130 MDeformVert *dvert= NULL; 02131 bDeformGroup *def; 02132 int def_tot = BLI_countlist(&ob->defbase); 02133 int *sort_map_update= MEM_mallocN(MAX_VGROUP_NAME * sizeof(int) * def_tot + 1, "sort vgroups"); /* needs a dummy index at the start*/ 02134 int *sort_map= sort_map_update + 1; 02135 char *name; 02136 int i; 02137 02138 name= name_array; 02139 for(def= ob->defbase.first, i=0; def; def=def->next, i++){ 02140 sort_map[i]= BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name)); 02141 name += MAX_VGROUP_NAME; 02142 } 02143 02144 if(ob->mode == OB_MODE_EDIT) { 02145 if(ob->type==OB_MESH) { 02146 EditMesh *em = BKE_mesh_get_editmesh(ob->data); 02147 EditVert *eve; 02148 02149 for(eve=em->verts.first; eve; eve=eve->next){ 02150 dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); 02151 if(dvert && dvert->totweight){ 02152 defvert_remap(dvert, sort_map); 02153 } 02154 } 02155 } 02156 else { 02157 BKE_report(op->reports, RPT_ERROR, "Editmode lattice isnt supported yet."); 02158 MEM_freeN(sort_map_update); 02159 return OPERATOR_CANCELLED; 02160 } 02161 } 02162 else { 02163 int dvert_tot=0; 02164 02165 ED_vgroup_give_array(ob->data, &dvert, &dvert_tot); 02166 02167 /*create as necassary*/ 02168 while(dvert && dvert_tot--) { 02169 if(dvert->totweight) 02170 defvert_remap(dvert, sort_map); 02171 dvert++; 02172 } 02173 } 02174 02175 /* update users */ 02176 for(i=0; i<def_tot; i++) 02177 sort_map[i]++; 02178 02179 sort_map_update[0]= 0; 02180 vgroup_remap_update_users(ob, sort_map_update); 02181 02182 ob->actdef= sort_map_update[ob->actdef]; 02183 02184 MEM_freeN(sort_map_update); 02185 02186 return OPERATOR_FINISHED; 02187 } 02188 02189 static int vgroup_sort(void *def_a_ptr, void *def_b_ptr) 02190 { 02191 bDeformGroup *def_a= (bDeformGroup *)def_a_ptr; 02192 bDeformGroup *def_b= (bDeformGroup *)def_b_ptr; 02193 02194 return BLI_natstrcmp(def_a->name, def_b->name); 02195 } 02196 02197 static int vertex_group_sort_exec(bContext *C, wmOperator *op) 02198 { 02199 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 02200 char *name_array; 02201 int ret; 02202 02203 /*init remapping*/ 02204 name_array = vgroup_init_remap(ob); 02205 02206 /*sort vgroup names*/ 02207 BLI_sortlist(&ob->defbase, vgroup_sort); 02208 02209 /*remap vgroup data to map to correct names*/ 02210 ret = vgroup_do_remap(ob, name_array, op); 02211 02212 if (ret != OPERATOR_CANCELLED) { 02213 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 02214 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob); 02215 } 02216 02217 if (name_array) MEM_freeN(name_array); 02218 02219 return ret; 02220 } 02221 02222 void OBJECT_OT_vertex_group_sort(wmOperatorType *ot) 02223 { 02224 ot->name= "Sort Vertex Groups"; 02225 ot->idname= "OBJECT_OT_vertex_group_sort"; 02226 ot->description= "Sorts vertex groups alphabetically"; 02227 02228 /* api callbacks */ 02229 ot->poll= vertex_group_poll; 02230 ot->exec= vertex_group_sort_exec; 02231 02232 /* flags */ 02233 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02234 } 02235 02236 static int vgroup_move_exec(bContext *C, wmOperator *op) 02237 { 02238 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 02239 bDeformGroup *def; 02240 char *name_array; 02241 int dir= RNA_enum_get(op->ptr, "direction"), ret; 02242 02243 def = BLI_findlink(&ob->defbase, ob->actdef - 1); 02244 if (!def) { 02245 return OPERATOR_CANCELLED; 02246 } 02247 02248 name_array = vgroup_init_remap(ob); 02249 02250 if (dir == 1) { /*up*/ 02251 void *prev = def->prev; 02252 02253 BLI_remlink(&ob->defbase, def); 02254 BLI_insertlinkbefore(&ob->defbase, prev, def); 02255 } else { /*down*/ 02256 void *next = def->next; 02257 02258 BLI_remlink(&ob->defbase, def); 02259 BLI_insertlinkafter(&ob->defbase, next, def); 02260 } 02261 02262 ret = vgroup_do_remap(ob, name_array, op); 02263 02264 if (name_array) MEM_freeN(name_array); 02265 02266 if (ret != OPERATOR_CANCELLED) { 02267 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 02268 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob); 02269 } 02270 02271 return ret; 02272 } 02273 02274 void OBJECT_OT_vertex_group_move(wmOperatorType *ot) 02275 { 02276 static EnumPropertyItem vgroup_slot_move[] = { 02277 {1, "UP", 0, "Up", ""}, 02278 {-1, "DOWN", 0, "Down", ""}, 02279 {0, NULL, 0, NULL, NULL} 02280 }; 02281 02282 /* identifiers */ 02283 ot->name= "Move Vertex Group"; 02284 ot->idname= "OBJECT_OT_vertex_group_move"; 02285 02286 /* api callbacks */ 02287 ot->poll= vertex_group_poll; 02288 ot->exec= vgroup_move_exec; 02289 02290 /* flags */ 02291 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02292 02293 RNA_def_enum(ot->srna, "direction", vgroup_slot_move, 0, "Direction", "Direction to move, UP or DOWN"); 02294 }