Blender  V2.59
object_vgroup.c
Go to the documentation of this file.
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= &lt->def[i1];
01143                                                 bp_mirr= &lt->def[i2];
01144 
01145                                                 sel= bp->f1 & SELECT;
01146                                                 sel_mirr= bp_mirr->f1 & SELECT;
01147 
01148                                                 if(sel || sel_mirr) {
01149                                                         dvert= &lt->dvert[i1];
01150                                                         dvert_mirr= &lt->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(&lt->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 }