Copying scripts from 2.4x without 2.5x changes
[blender.git] / source / blender / editors / object / object_vgroup.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <string.h>
31
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_cloth_types.h"
35 #include "DNA_curve_types.h"
36 #include "DNA_lattice_types.h"
37 #include "DNA_mesh_types.h"
38 #include "DNA_meshdata_types.h"
39 #include "DNA_modifier_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_object_force.h"
42 #include "DNA_scene_types.h"
43 #include "DNA_particle_types.h"
44 #include "DNA_windowmanager_types.h"
45
46 #include "BLI_blenlib.h"
47 #include "BLI_editVert.h"
48
49 #include "BKE_context.h"
50 #include "BKE_customdata.h"
51 #include "BKE_deform.h"
52 #include "BKE_depsgraph.h"
53 #include "BKE_DerivedMesh.h"
54 #include "BKE_displist.h"
55 #include "BKE_global.h"
56 #include "BKE_lattice.h"
57 #include "BKE_mesh.h"
58 #include "BKE_paint.h"
59 #include "BKE_utildefines.h"
60
61 #include "RNA_access.h"
62 #include "RNA_define.h"
63
64 #include "WM_api.h"
65 #include "WM_types.h"
66
67 #include "ED_mesh.h"
68 #include "ED_view3d.h"
69
70 #include "UI_interface.h"
71
72 #include "object_intern.h"
73
74 /************************ Exported Functions **********************/
75
76 static Lattice *vgroup_edit_lattice(Object *ob)
77 {
78         if(ob->type==OB_LATTICE) {
79                 Lattice *lt= ob->data;
80                 return (lt->editlatt)? lt->editlatt: lt;
81         }
82
83         return NULL;
84 }
85
86 /* check if deform vertex has defgroup index */
87 MDeformWeight *ED_vgroup_weight_get(MDeformVert *dv, int defgroup)
88 {
89         int i;
90         
91         if(!dv || defgroup<0)
92                 return NULL;
93         
94         for(i=0; i<dv->totweight; i++)
95                 if(dv->dw[i].def_nr == defgroup)
96                         return dv->dw+i;
97
98         return NULL;
99 }
100
101 /* Ensures that mv has a deform weight entry for the specified defweight group */
102 /* Note this function is mirrored in editmesh_tools.c, for use for editvertices */
103 MDeformWeight *ED_vgroup_weight_verify(MDeformVert *dv, int defgroup)
104 {
105         MDeformWeight *newdw;
106
107         /* do this check always, this function is used to check for it */
108         if(!dv || defgroup<0)
109                 return NULL;
110         
111         newdw = ED_vgroup_weight_get(dv, defgroup);
112         if(newdw)
113                 return newdw;
114         
115         newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight");
116         if(dv->dw) {
117                 memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
118                 MEM_freeN(dv->dw);
119         }
120         dv->dw=newdw;
121         
122         dv->dw[dv->totweight].weight=0.0f;
123         dv->dw[dv->totweight].def_nr=defgroup;
124         /* Group index */
125         
126         dv->totweight++;
127
128         return dv->dw+(dv->totweight-1);
129 }
130
131 bDeformGroup *ED_vgroup_add_name(Object *ob, char *name)
132 {
133         bDeformGroup *defgroup;
134         
135         if(!ob)
136                 return NULL;
137         
138         defgroup = MEM_callocN(sizeof(bDeformGroup), "add deformGroup");
139
140         BLI_strncpy(defgroup->name, name, 32);
141
142         BLI_addtail(&ob->defbase, defgroup);
143         unique_vertexgroup_name(defgroup, ob);
144
145         ob->actdef = BLI_countlist(&ob->defbase);
146
147         return defgroup;
148 }
149
150 bDeformGroup *ED_vgroup_add(Object *ob) 
151 {
152         return ED_vgroup_add_name(ob, "Group");
153 }
154
155 void ED_vgroup_data_create(ID *id)
156 {
157         /* create deform verts */
158
159         if(GS(id->name)==ID_ME) {
160                 Mesh *me= (Mesh *)id;
161                 me->dvert= CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
162         }
163         else if(GS(id->name)==ID_LT) {
164                 Lattice *lt= (Lattice *)id;
165                 lt->dvert= MEM_callocN(sizeof(MDeformVert)*lt->pntsu*lt->pntsv*lt->pntsw, "lattice deformVert");
166         }
167 }
168
169 /* for mesh in object mode
170    lattice can be in editmode */
171 void ED_vgroup_nr_vert_remove(Object *ob, int def_nr, int vertnum)
172 {
173         /* This routine removes the vertex from the deform
174          * group with number def_nr.
175          *
176          * This routine is meant to be fast, so it is the
177          * responsibility of the calling routine to:
178          *   a) test whether ob is non-NULL
179          *   b) test whether ob is a mesh
180          *   c) calculate def_nr
181          */
182
183         MDeformWeight *newdw;
184         MDeformVert *dvert= NULL;
185         int i;
186
187         /* get the deform vertices corresponding to the
188          * vertnum
189          */
190         if(ob->type==OB_MESH) {
191                 if(((Mesh*)ob->data)->dvert)
192                         dvert = ((Mesh*)ob->data)->dvert + vertnum;
193         }
194         else if(ob->type==OB_LATTICE) {
195                 Lattice *lt= vgroup_edit_lattice(ob);
196                 
197                 if(lt->dvert)
198                         dvert = lt->dvert + vertnum;
199         }
200         
201         if(dvert==NULL)
202                 return;
203         
204         /* for all of the deform weights in the
205          * deform vert
206          */
207         for(i=dvert->totweight - 1 ; i>=0 ; i--){
208
209                 /* if the def_nr is the same as the one
210                  * for our weight group then remove it
211                  * from this deform vert.
212                  */
213                 if(dvert->dw[i].def_nr == def_nr) {
214                         dvert->totweight--;
215         
216                         /* if there are still other deform weights
217                          * attached to this vert then remove this
218                          * deform weight, and reshuffle the others
219                          */
220                         if(dvert->totweight) {
221                                 newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), 
222                                                                          "deformWeight");
223                                 if(dvert->dw){
224                                         memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
225                                         memcpy(newdw+i, dvert->dw+i+1, 
226                                                         sizeof(MDeformWeight)*(dvert->totweight-i));
227                                         MEM_freeN(dvert->dw);
228                                 }
229                                 dvert->dw=newdw;
230                         }
231                         /* if there are no other deform weights
232                          * left then just remove the deform weight
233                          */
234                         else {
235                                 MEM_freeN(dvert->dw);
236                                 dvert->dw = NULL;
237                                 break;
238                         }
239                 }
240         }
241
242 }
243
244 /* for Mesh in Object mode */
245 /* allows editmode for Lattice */
246 void ED_vgroup_nr_vert_add(Object *ob, int def_nr, int vertnum, float weight, int assignmode)
247 {
248         /* add the vert to the deform group with the
249          * specified number
250          */
251         MDeformVert *dv= NULL;
252         MDeformWeight *newdw;
253         int     i;
254
255         /* get the vert */
256         if(ob->type==OB_MESH) {
257                 if(((Mesh*)ob->data)->dvert)
258                         dv = ((Mesh*)ob->data)->dvert + vertnum;
259         }
260         else if(ob->type==OB_LATTICE) {
261                 Lattice *lt= vgroup_edit_lattice(ob);
262                 
263                 if(lt->dvert)
264                         dv = lt->dvert + vertnum;
265         }
266         
267         if(dv==NULL)
268                 return;
269         
270         /* Lets first check to see if this vert is
271          * already in the weight group -- if so
272          * lets update it
273          */
274         for(i=0; i<dv->totweight; i++){
275                 
276                 /* if this weight cooresponds to the
277                  * deform group, then add it using
278                  * the assign mode provided
279                  */
280                 if(dv->dw[i].def_nr == def_nr){
281                         
282                         switch(assignmode) {
283                         case WEIGHT_REPLACE:
284                                 dv->dw[i].weight=weight;
285                                 break;
286                         case WEIGHT_ADD:
287                                 dv->dw[i].weight+=weight;
288                                 if(dv->dw[i].weight >= 1.0)
289                                         dv->dw[i].weight = 1.0;
290                                 break;
291                         case WEIGHT_SUBTRACT:
292                                 dv->dw[i].weight-=weight;
293                                 /* if the weight is zero or less then
294                                  * remove the vert from the deform group
295                                  */
296                                 if(dv->dw[i].weight <= 0.0)
297                                         ED_vgroup_nr_vert_remove(ob, def_nr, vertnum);
298                                 break;
299                         }
300                         return;
301                 }
302         }
303
304         /* if the vert wasn't in the deform group then
305          * we must take a different form of action ...
306          */
307
308         switch(assignmode) {
309         case WEIGHT_SUBTRACT:
310                 /* if we are subtracting then we don't
311                  * need to do anything
312                  */
313                 return;
314
315         case WEIGHT_REPLACE:
316         case WEIGHT_ADD:
317                 /* if we are doing an additive assignment, then
318                  * we need to create the deform weight
319                  */
320                 newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), 
321                                                          "deformWeight");
322                 if(dv->dw){
323                         memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
324                         MEM_freeN(dv->dw);
325                 }
326                 dv->dw=newdw;
327     
328                 dv->dw[dv->totweight].weight=weight;
329                 dv->dw[dv->totweight].def_nr=def_nr;
330     
331                 dv->totweight++;
332                 break;
333         }
334 }
335
336 /* called while not in editmode */
337 void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, int assignmode)
338 {
339         /* add the vert to the deform group with the
340          * specified assign mode
341          */
342         int     def_nr;
343
344         /* get the deform group number, exit if
345          * it can't be found
346          */
347         def_nr = get_defgroup_num(ob, dg);
348         if(def_nr < 0) return;
349
350         /* if there's no deform verts then
351          * create some
352          */
353         if(ob->type==OB_MESH) {
354                 if(!((Mesh*)ob->data)->dvert)
355                         ED_vgroup_data_create(ob->data);
356         }
357         else if(ob->type==OB_LATTICE) {
358                 if(!((Lattice*)ob->data)->dvert)
359                         ED_vgroup_data_create(ob->data);
360         }
361
362         /* call another function to do the work
363          */
364         ED_vgroup_nr_vert_add(ob, def_nr, vertnum, weight, assignmode);
365 }
366
367 /* mesh object mode, lattice can be in editmode */
368 void ED_vgroup_vert_remove(Object *ob, bDeformGroup     *dg, int vertnum)
369 {
370         /* This routine removes the vertex from the specified
371          * deform group.
372          */
373
374         int def_nr;
375
376         /* if the object is NULL abort
377          */
378         if(!ob)
379                 return;
380
381         /* get the deform number that cooresponds
382          * to this deform group, and abort if it
383          * can not be found.
384          */
385         def_nr = get_defgroup_num(ob, dg);
386         if(def_nr < 0) return;
387
388         /* call another routine to do the work
389          */
390         ED_vgroup_nr_vert_remove(ob, def_nr, vertnum);
391 }
392
393 static float get_vert_def_nr(Object *ob, int def_nr, int vertnum)
394 {
395         MDeformVert *dvert= NULL;
396         EditVert *eve;
397         Mesh *me;
398         int i;
399
400         /* get the deform vertices corresponding to the vertnum */
401         if(ob->type==OB_MESH) {
402                 me= ob->data;
403
404                 if(me->edit_mesh) {
405                         eve= BLI_findlink(&me->edit_mesh->verts, vertnum);
406                         if(!eve) return 0.0f;
407                         dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT);
408                 }
409                 else
410                         dvert = me->dvert + vertnum;
411         }
412         else if(ob->type==OB_LATTICE) {
413                 Lattice *lt= vgroup_edit_lattice(ob);
414                 
415                 if(lt->dvert)
416                         dvert = lt->dvert + vertnum;
417         }
418         
419         if(dvert==NULL)
420                 return 0.0f;
421         
422         for(i=dvert->totweight-1 ; i>=0 ; i--)
423                 if(dvert->dw[i].def_nr == def_nr)
424                         return dvert->dw[i].weight;
425
426         return 0.0f;
427 }
428
429 float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum)
430 {
431         int def_nr;
432
433         if(!ob) return 0.0f;
434
435         def_nr = get_defgroup_num(ob, dg);
436         if(def_nr < 0) return 0.0f;
437
438         return get_vert_def_nr(ob, def_nr, vertnum);
439 }
440
441 void ED_vgroup_select_by_name(Object *ob, char *name)
442 {
443         bDeformGroup *curdef;
444         int actdef= 1;
445         
446         for(curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++){
447                 if(!strcmp(curdef->name, name)) {
448                         ob->actdef= actdef;
449                         return;
450                 }
451         }
452
453         ob->actdef=0;   // this signals on painting to create a new one, if a bone in posemode is selected */
454 }
455
456 /********************** Operator Implementations *********************/
457
458 /* only in editmode */
459 static void vgroup_select_verts(Object *ob, int select)
460 {
461         EditVert *eve;
462         MDeformVert *dvert;
463         int i;
464
465         if(ob->type == OB_MESH) {
466                 Mesh *me= ob->data;
467                 EditMesh *em = BKE_mesh_get_editmesh(me);
468
469                 for(eve=em->verts.first; eve; eve=eve->next){
470                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
471
472                         if(dvert && dvert->totweight){
473                                 for(i=0; i<dvert->totweight; i++){
474                                         if(dvert->dw[i].def_nr == (ob->actdef-1)){
475                                                 if(select) eve->f |= SELECT;
476                                                 else eve->f &= ~SELECT;
477                                                 
478                                                 break;
479                                         }
480                                 }
481                         }
482                 }
483                 /* this has to be called, because this function operates on vertices only */
484                 if(select) EM_select_flush(em); // vertices to edges/faces
485                 else EM_deselect_flush(em);
486
487                 BKE_mesh_end_editmesh(me, em);
488         }
489         else if(ob->type == OB_LATTICE) {
490                 Lattice *lt= vgroup_edit_lattice(ob);
491                 
492                 if(lt->dvert) {
493                         BPoint *bp;
494                         int a, tot;
495                         
496                         dvert= lt->dvert;
497
498                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
499                         for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
500                                 for(i=0; i<dvert->totweight; i++){
501                                         if(dvert->dw[i].def_nr == (ob->actdef-1)) {
502                                                 if(select) bp->f1 |= SELECT;
503                                                 else bp->f1 &= ~SELECT;
504                                                 
505                                                 break;
506                                         }
507                                 }
508                         }
509                 }
510         }
511 }
512
513 static void vgroup_duplicate(Object *ob)
514 {
515         bDeformGroup *dg, *cdg;
516         char name[32], s[32];
517         MDeformWeight *org, *cpy;
518         MDeformVert *dvert, *dvert_array=NULL;
519         int i, idg, icdg, dvert_tot=0;
520
521         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
522         if(!dg)
523                 return;
524         
525         if(strstr(dg->name, "_copy")) {
526                 BLI_strncpy(name, dg->name, 32); /* will be renamed _copy.001... etc */
527         }
528         else {
529                 BLI_snprintf(name, 32, "%s_copy", dg->name);
530                 while(get_named_vertexgroup(ob, name)) {
531                         if((strlen(name) + 6) > 32) {
532                                 printf("Internal error: the name for the new vertex group is > 32 characters");
533                                 return;
534                         }
535                         strcpy(s, name);
536                         BLI_snprintf(name, 32, "%s_copy", s);
537                 }
538         }               
539
540         cdg = copy_defgroup(dg);
541         strcpy(cdg->name, name);
542         unique_vertexgroup_name(cdg, ob);
543         
544         BLI_addtail(&ob->defbase, cdg);
545
546         idg = (ob->actdef-1);
547         ob->actdef = BLI_countlist(&ob->defbase);
548         icdg = (ob->actdef-1);
549
550         if(ob->type == OB_MESH) {
551                 Mesh *me = get_mesh(ob);
552                 dvert_array= me->dvert;
553                 dvert_tot= me->totvert;
554         }
555         else if(ob->type == OB_LATTICE) {
556                 Lattice *lt= (Lattice *)ob->data;
557                 dvert_array= lt->dvert;
558                 dvert_tot= lt->pntsu*lt->pntsv*lt->pntsw;
559         }
560         
561         if(!dvert_array)
562                 return;
563
564         for(i = 0; i < dvert_tot; i++) {
565                 dvert = dvert_array+i;
566                 org = ED_vgroup_weight_get(dvert, idg);
567                 if(org) {
568                         float weight = org->weight;
569                         /* ED_vgroup_weight_verify re-allocs org so need to store the weight first */
570                         cpy = ED_vgroup_weight_verify(dvert, icdg);
571                         cpy->weight = weight;
572                 }
573         }
574 }
575
576 static void vgroup_delete_update_users(Object *ob, int id)
577 {
578         ExplodeModifierData *emd;
579         ModifierData *md;
580         ParticleSystem *psys;
581         ClothModifierData *clmd;
582         ClothSimSettings *clsim;
583         int a;
584
585         /* these cases don't use names to refer to vertex groups, so when
586          * they get deleted the numbers get out of sync, this corrects that */
587
588         if(ob->soft) {
589                 if(ob->soft->vertgroup == id)
590                         ob->soft->vertgroup= 0;
591                 else if(ob->soft->vertgroup > id)
592                         ob->soft->vertgroup--;
593         }
594
595         for(md=ob->modifiers.first; md; md=md->next) {
596                 if(md->type == eModifierType_Explode) {
597                         emd= (ExplodeModifierData*)md;
598
599                         if(emd->vgroup == id)
600                                 emd->vgroup= 0;
601                         else if(emd->vgroup > id)
602                                 emd->vgroup--;
603                 }
604                 else if(md->type == eModifierType_Cloth) {
605                         clmd= (ClothModifierData*)md;
606                         clsim= clmd->sim_parms;
607
608                         if(clsim) {
609                                 if(clsim->vgroup_mass == id)
610                                         clsim->vgroup_mass= 0;
611                                 else if(clsim->vgroup_mass > id)
612                                         clsim->vgroup_mass--;
613
614                                 if(clsim->vgroup_bend == id)
615                                         clsim->vgroup_bend= 0;
616                                 else if(clsim->vgroup_bend > id)
617                                         clsim->vgroup_bend--;
618
619                                 if(clsim->vgroup_struct == id)
620                                         clsim->vgroup_struct= 0;
621                                 else if(clsim->vgroup_struct > id)
622                                         clsim->vgroup_struct--;
623                         }
624                 }
625         }
626
627         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
628                 for(a=0; a<PSYS_TOT_VG; a++)
629                         if(psys->vgroup[a] == id)
630                                 psys->vgroup[a]= 0;
631                         else if(psys->vgroup[a] > id)
632                                 psys->vgroup[a]--;
633         }
634 }
635
636 static void vgroup_delete_object_mode(Object *ob)
637 {
638         bDeformGroup *dg;
639         MDeformVert *dvert, *dvert_array=NULL;
640         int i, e, dvert_tot=0;
641
642         if(ob->type == OB_MESH) {
643                 Mesh *me = get_mesh(ob);
644                 dvert_array= me->dvert;
645                 dvert_tot= me->totvert;
646         }
647         else if(ob->type == OB_LATTICE) {
648                 Lattice *lt= (Lattice *)ob->data;
649                 dvert_array= lt->dvert;
650                 dvert_tot= lt->pntsu*lt->pntsv*lt->pntsw;
651         }
652         
653         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
654         if(!dg)
655                 return;
656         
657         if(dvert_array) {
658                 for(i = 0; i < dvert_tot; i++) {
659                         dvert = dvert_array + i;
660                         if(dvert) {
661                                 if(ED_vgroup_weight_get(dvert, (ob->actdef-1)))
662                                         ED_vgroup_vert_remove(ob, dg, i);
663                         }
664                 }
665
666                 for(i = 0; i < dvert_tot; i++) {
667                         dvert = dvert_array+i;
668                         if(dvert) {
669                                 for(e = 0; e < dvert->totweight; e++) {
670                                         if(dvert->dw[e].def_nr > (ob->actdef-1))
671                                                 dvert->dw[e].def_nr--;
672                                 }
673                         }
674                 }
675         }
676
677         vgroup_delete_update_users(ob, ob->actdef);
678
679         /* Update the active deform index if necessary */
680         if(ob->actdef == BLI_countlist(&ob->defbase))
681                 ob->actdef--;
682   
683         /* Remove the group */
684         BLI_freelinkN(&ob->defbase, dg);
685 }
686
687 /* only in editmode */
688 /* removes from active defgroup, if allverts==0 only selected vertices */
689 static void vgroup_active_remove_verts(Object *ob, int allverts)
690 {
691         EditVert *eve;
692         MDeformVert *dvert;
693         MDeformWeight *newdw;
694         bDeformGroup *dg, *eg;
695         int     i;
696
697         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
698         if(!dg)
699                 return;
700
701         if(ob->type == OB_MESH) {
702                 Mesh *me= ob->data;
703                 EditMesh *em = BKE_mesh_get_editmesh(me);
704
705                 for(eve=em->verts.first; eve; eve=eve->next){
706                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
707                 
708                         if(dvert && dvert->dw && ((eve->f & 1) || allverts)){
709                                 for(i=0; i<dvert->totweight; i++){
710                                         /* Find group */
711                                         eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
712                                         if(eg == dg){
713                                                 dvert->totweight--;
714                                                 if(dvert->totweight){
715                                                         newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), "deformWeight");
716                                                         
717                                                         if(dvert->dw){
718                                                                 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
719                                                                 memcpy(newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i));
720                                                                 MEM_freeN(dvert->dw);
721                                                         }
722                                                         dvert->dw=newdw;
723                                                 }
724                                                 else{
725                                                         MEM_freeN(dvert->dw);
726                                                         dvert->dw=NULL;
727                                                         break;
728                                                 }
729                                         }
730                                 }
731                         }
732                 }
733                 BKE_mesh_end_editmesh(me, em);
734         }
735         else if(ob->type == OB_LATTICE) {
736                 Lattice *lt= vgroup_edit_lattice(ob);
737                 
738                 if(lt->dvert) {
739                         BPoint *bp;
740                         int a, tot= lt->pntsu*lt->pntsv*lt->pntsw;
741                                 
742                         for(a=0, bp= lt->def; a<tot; a++, bp++) {
743                                 if(allverts || (bp->f1 & SELECT))
744                                         ED_vgroup_vert_remove(ob, dg, a);
745                         }
746                 }
747         }
748 }
749
750 static void vgroup_delete_edit_mode(Object *ob)
751 {
752         bDeformGroup *defgroup;
753         int i;
754
755         if(!ob->actdef)
756                 return;
757
758         defgroup = BLI_findlink(&ob->defbase, ob->actdef-1);
759         if(!defgroup)
760                 return;
761
762         /* Make sure that no verts are using this group */
763         vgroup_active_remove_verts(ob, 1);
764
765         /* Make sure that any verts with higher indices are adjusted accordingly */
766         if(ob->type==OB_MESH) {
767                 Mesh *me= ob->data;
768                 EditMesh *em = BKE_mesh_get_editmesh(me);
769                 EditVert *eve;
770                 MDeformVert *dvert;
771                 
772                 for(eve=em->verts.first; eve; eve=eve->next){
773                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
774
775                         if(dvert)
776                                 for(i=0; i<dvert->totweight; i++)
777                                         if(dvert->dw[i].def_nr > (ob->actdef-1))
778                                                 dvert->dw[i].def_nr--;
779                 }
780                 BKE_mesh_end_editmesh(me, em);
781         }
782         else if(ob->type==OB_LATTICE) {
783                 Lattice *lt= vgroup_edit_lattice(ob);
784                 BPoint *bp;
785                 MDeformVert *dvert= lt->dvert;
786                 int a, tot;
787                 
788                 if(dvert) {
789                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
790                         for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
791                                 for(i=0; i<dvert->totweight; i++){
792                                         if(dvert->dw[i].def_nr > (ob->actdef-1))
793                                                 dvert->dw[i].def_nr--;
794                                 }
795                         }
796                 }
797         }
798
799         vgroup_delete_update_users(ob, ob->actdef);
800
801         /* Update the active deform index if necessary */
802         if(ob->actdef==BLI_countlist(&ob->defbase))
803                 ob->actdef--;
804         
805         /* Remove the group */
806         BLI_freelinkN (&ob->defbase, defgroup);
807         
808         /* remove all dverts */
809         if(ob->actdef==0) {
810                 if(ob->type==OB_MESH) {
811                         Mesh *me= ob->data;
812                         CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
813                         me->dvert= NULL;
814                 }
815                 else if(ob->type==OB_LATTICE) {
816                         Lattice *lt= vgroup_edit_lattice(ob);
817                         if(lt->dvert) {
818                                 MEM_freeN(lt->dvert);
819                                 lt->dvert= NULL;
820                         }
821                 }
822         }
823 }
824
825 static int vgroup_object_in_edit_mode(Object *ob)
826 {
827         if(ob->type == OB_MESH)
828                 return (((Mesh*)ob->data)->edit_mesh != NULL);
829         else if(ob->type == OB_LATTICE)
830                 return (((Lattice*)ob->data)->editlatt != NULL);
831         
832         return 0;
833 }
834
835 static void vgroup_delete(Object *ob)
836 {
837         if(vgroup_object_in_edit_mode(ob))
838                 vgroup_delete_edit_mode(ob);
839         else
840                 vgroup_delete_object_mode(ob);
841 }
842
843 static void vgroup_delete_all(Object *ob)
844 {
845         /* Remove all DVerts */
846         if(ob->type==OB_MESH) {
847                 Mesh *me= ob->data;
848                 CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
849                 me->dvert= NULL;
850         }
851         else if(ob->type==OB_LATTICE) {
852                 Lattice *lt= vgroup_edit_lattice(ob);
853                 if(lt->dvert) {
854                         MEM_freeN(lt->dvert);
855                         lt->dvert= NULL;
856                 }
857         }
858         
859         /* Remove all DefGroups */
860         BLI_freelistN(&ob->defbase);
861         
862         /* Fix counters/indices */
863         ob->actdef= 0;
864 }
865
866 /* only in editmode */
867 static void vgroup_assign_verts(Object *ob, float weight)
868 {
869         EditVert *eve;
870         bDeformGroup *dg, *eg;
871         MDeformWeight *newdw;
872         MDeformVert *dvert;
873         int     i, done;
874
875         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
876
877         if(ob->type == OB_MESH) {
878                 Mesh *me= ob->data;
879                 EditMesh *em = BKE_mesh_get_editmesh(me);
880
881                 if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT))
882                         EM_add_data_layer(em, &em->vdata, CD_MDEFORMVERT);
883
884                 /* Go through the list of editverts and assign them */
885                 for(eve=em->verts.first; eve; eve=eve->next){
886                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
887
888                         if(dvert && (eve->f & 1)){
889                                 done=0;
890                                 /* See if this vert already has a reference to this group */
891                                 /*              If so: Change its weight */
892                                 done=0;
893                                 for(i=0; i<dvert->totweight; i++){
894                                         eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
895                                         /* Find the actual group */
896                                         if(eg==dg){
897                                                 dvert->dw[i].weight= weight;
898                                                 done=1;
899                                                 break;
900                                         }
901                                 }
902                                 /*              If not: Add the group and set its weight */
903                                 if(!done){
904                                         newdw = MEM_callocN(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
905                                         if(dvert->dw){
906                                                 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
907                                                 MEM_freeN(dvert->dw);
908                                         }
909                                         dvert->dw=newdw;
910
911                                         dvert->dw[dvert->totweight].weight= weight;
912                                         dvert->dw[dvert->totweight].def_nr= ob->actdef-1;
913
914                                         dvert->totweight++;
915
916                                 }
917                         }
918                 }
919                 BKE_mesh_end_editmesh(me, em);
920         }
921         else if(ob->type == OB_LATTICE) {
922                 Lattice *lt= vgroup_edit_lattice(ob);
923                 BPoint *bp;
924                 int a, tot;
925                 
926                 if(lt->dvert==NULL)
927                         ED_vgroup_data_create(&lt->id);
928                 
929                 tot= lt->pntsu*lt->pntsv*lt->pntsw;
930                 for(a=0, bp= lt->def; a<tot; a++, bp++) {
931                         if(bp->f1 & SELECT)
932                                 ED_vgroup_nr_vert_add(ob, ob->actdef-1, a, weight, WEIGHT_REPLACE);
933                 }
934         }
935 }
936
937 /* only in editmode */
938 /* removes from all defgroup, if allverts==0 only selected vertices */
939 static void vgroup_remove_verts(Object *ob, int allverts)
940 {
941         int actdef, defCount;
942         
943         actdef= ob->actdef;
944         defCount= BLI_countlist(&ob->defbase);
945         
946         if(defCount == 0)
947                 return;
948         
949         /* To prevent code redundancy, we just use vgroup_active_remove_verts, but that
950          * only operates on the active vgroup. So we iterate through all groups, by changing
951          * active group index
952          */
953         for(ob->actdef= 1; ob->actdef <= defCount; ob->actdef++)
954                 vgroup_active_remove_verts(ob, allverts);
955                 
956         ob->actdef= actdef;
957 }
958
959 /********************** vertex group operators *********************/
960
961 static int vertex_group_poll(bContext *C)
962 {
963         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
964         ID *data= (ob)? ob->data: NULL;
965         return (ob && !ob->id.lib && ELEM(ob->type, OB_MESH, OB_LATTICE) && data && !data->lib);
966 }
967
968 static int vertex_group_poll_edit(bContext *C)
969 {
970         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
971         ID *data= (ob)? ob->data: NULL;
972
973         if(!(ob && !ob->id.lib && data && !data->lib))
974                 return 0;
975
976         return vgroup_object_in_edit_mode(ob);
977 }
978
979 static int vertex_group_add_exec(bContext *C, wmOperator *op)
980 {
981         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
982
983         ED_vgroup_add(ob);
984         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
985         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
986         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
987         
988         return OPERATOR_FINISHED;
989 }
990
991 void OBJECT_OT_vertex_group_add(wmOperatorType *ot)
992 {
993         /* identifiers */
994         ot->name= "Add Vertex Group";
995         ot->idname= "OBJECT_OT_vertex_group_add";
996         
997         /* api callbacks */
998         ot->poll= vertex_group_poll;
999         ot->exec= vertex_group_add_exec;
1000
1001         /* flags */
1002         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1003 }
1004
1005 static int vertex_group_remove_exec(bContext *C, wmOperator *op)
1006 {
1007         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1008
1009         if(RNA_boolean_get(op->ptr, "all"))
1010                 vgroup_delete_all(ob);
1011         else
1012                 vgroup_delete(ob);
1013
1014         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1015         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1016         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1017         
1018         return OPERATOR_FINISHED;
1019 }
1020
1021 void OBJECT_OT_vertex_group_remove(wmOperatorType *ot)
1022 {
1023         /* identifiers */
1024         ot->name= "Remove Vertex Group";
1025         ot->idname= "OBJECT_OT_vertex_group_remove";
1026         
1027         /* api callbacks */
1028         ot->poll= vertex_group_poll;
1029         ot->exec= vertex_group_remove_exec;
1030
1031         /* flags */
1032         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1033
1034         /* properties */
1035         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups.");
1036 }
1037
1038 static int vertex_group_assign_exec(bContext *C, wmOperator *op)
1039 {
1040         ToolSettings *ts= CTX_data_tool_settings(C);
1041         Object *ob= CTX_data_edit_object(C);
1042
1043         if(RNA_boolean_get(op->ptr, "new"))
1044                 ED_vgroup_add(ob);
1045
1046         vgroup_assign_verts(ob, ts->vgroup_weight);
1047         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1048         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1049         
1050         return OPERATOR_FINISHED;
1051 }
1052
1053 void OBJECT_OT_vertex_group_assign(wmOperatorType *ot)
1054 {
1055         /* identifiers */
1056         ot->name= "Assign Vertex Group";
1057         ot->idname= "OBJECT_OT_vertex_group_assign";
1058         
1059         /* api callbacks */
1060         ot->poll= vertex_group_poll_edit;
1061         ot->exec= vertex_group_assign_exec;
1062
1063         /* flags */
1064         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1065
1066         /* properties */
1067         RNA_def_boolean(ot->srna, "new", 0, "New", "Assign vertex to new vertex group.");
1068 }
1069
1070 static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
1071 {
1072         Object *ob= CTX_data_edit_object(C);
1073
1074         vgroup_remove_verts(ob, 0);
1075         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1076         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1077
1078         return OPERATOR_FINISHED;
1079 }
1080
1081 void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot)
1082 {
1083         /* identifiers */
1084         ot->name= "Remove from Vertex Group";
1085         ot->idname= "OBJECT_OT_vertex_group_remove_from";
1086
1087         /* api callbacks */
1088         ot->poll= vertex_group_poll_edit;
1089         ot->exec= vertex_group_remove_from_exec;
1090
1091         /* flags */
1092         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1093
1094         /* properties */
1095         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups.");
1096 }
1097
1098 static int vertex_group_select_exec(bContext *C, wmOperator *op)
1099 {
1100         Object *ob= CTX_data_edit_object(C);
1101
1102         if(!ob || ob->id.lib)
1103                 return OPERATOR_CANCELLED;
1104
1105         vgroup_select_verts(ob, 1);
1106         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
1107
1108         return OPERATOR_FINISHED;
1109 }
1110
1111 void OBJECT_OT_vertex_group_select(wmOperatorType *ot)
1112 {
1113         /* identifiers */
1114         ot->name= "Select Vertex Group";
1115         ot->idname= "OBJECT_OT_vertex_group_select";
1116
1117         /* api callbacks */
1118         ot->poll= vertex_group_poll_edit;
1119         ot->exec= vertex_group_select_exec;
1120
1121         /* flags */
1122         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1123 }
1124
1125 static int vertex_group_deselect_exec(bContext *C, wmOperator *op)
1126 {
1127         Object *ob= CTX_data_edit_object(C);
1128
1129         vgroup_select_verts(ob, 0);
1130         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
1131
1132         return OPERATOR_FINISHED;
1133 }
1134
1135 void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot)
1136 {
1137         /* identifiers */
1138         ot->name= "Deselect Vertex Group";
1139         ot->idname= "OBJECT_OT_vertex_group_deselect";
1140
1141         /* api callbacks */
1142         ot->poll= vertex_group_poll_edit;
1143         ot->exec= vertex_group_deselect_exec;
1144
1145         /* flags */
1146         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1147 }
1148
1149 static int vertex_group_copy_exec(bContext *C, wmOperator *op)
1150 {
1151         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1152
1153         vgroup_duplicate(ob);
1154         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1155         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1156         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1157
1158         return OPERATOR_FINISHED;
1159 }
1160
1161 void OBJECT_OT_vertex_group_copy(wmOperatorType *ot)
1162 {
1163         /* identifiers */
1164         ot->name= "Copy Vertex Group";
1165         ot->idname= "OBJECT_OT_vertex_group_copy";
1166
1167         /* api callbacks */
1168         ot->poll= vertex_group_poll;
1169         ot->exec= vertex_group_copy_exec;
1170
1171         /* flags */
1172         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1173 }
1174
1175 static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *op)
1176 {
1177         Scene *scene= CTX_data_scene(C);
1178         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1179         Base *base;
1180         int retval= OPERATOR_CANCELLED;
1181
1182         for(base=scene->base.first; base; base= base->next) {
1183                 if(base->object->type==ob->type) {
1184                         if(base->object!=ob && base->object->data==ob->data) {
1185                                 BLI_freelistN(&base->object->defbase);
1186                                 BLI_duplicatelist(&base->object->defbase, &ob->defbase);
1187                                 base->object->actdef= ob->actdef;
1188
1189                                 DAG_id_flush_update(&base->object->id, OB_RECALC_DATA);
1190                                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, base->object);
1191                                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data);
1192
1193                                 retval = OPERATOR_FINISHED;
1194                         }
1195                 }
1196         }
1197
1198         return retval;
1199 }
1200
1201 void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
1202 {
1203         /* identifiers */
1204         ot->name= "Copy Vertex Group to Linked";
1205         ot->idname= "OBJECT_OT_vertex_group_copy_to_linked";
1206
1207         /* api callbacks */
1208         ot->poll= vertex_group_poll;
1209         ot->exec= vertex_group_copy_to_linked_exec;
1210
1211         /* flags */
1212         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1213 }
1214
1215 static EnumPropertyItem vgroup_items[]= {
1216         {0, NULL, 0, NULL, NULL}};
1217
1218 static int set_active_group_exec(bContext *C, wmOperator *op)
1219 {
1220         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1221         int nr= RNA_enum_get(op->ptr, "group");
1222
1223         ob->actdef= nr+1;
1224
1225         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1226         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1227
1228         return OPERATOR_FINISHED;
1229 }
1230
1231 static EnumPropertyItem *vgroup_itemf(bContext *C, PointerRNA *ptr, int *free)
1232 {       
1233         Object *ob;
1234         EnumPropertyItem tmp = {0, "", 0, "", ""};
1235         EnumPropertyItem *item= NULL;
1236         bDeformGroup *def;
1237         int a, totitem= 0;
1238         
1239         if(!C || !(ob = CTX_data_pointer_get_type(C, "object", &RNA_Object).data)) /* needed for docs */
1240                 return vgroup_items;
1241         
1242         for(a=0, def=ob->defbase.first; def; def=def->next, a++) {
1243                 tmp.value= a;
1244                 tmp.identifier= def->name;
1245                 tmp.name= def->name;
1246                 RNA_enum_item_add(&item, &totitem, &tmp);
1247         }
1248
1249         RNA_enum_item_end(&item, &totitem);
1250
1251         *free= 1;
1252
1253         return item;
1254 }
1255
1256 void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
1257 {
1258         PropertyRNA *prop;
1259
1260         /* identifiers */
1261         ot->name= "Set Active Vertex Group";
1262         ot->idname= "OBJECT_OT_vertex_group_set_active";
1263
1264         /* api callbacks */
1265         ot->poll= vertex_group_poll;
1266         ot->exec= set_active_group_exec;
1267         ot->invoke= WM_menu_invoke;
1268
1269         /* flags */
1270         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1271
1272         /* properties */
1273         prop= RNA_def_enum(ot->srna, "group", vgroup_items, 0, "Group", "Vertex group to set as active.");
1274         RNA_def_enum_funcs(prop, vgroup_itemf);
1275 }
1276
1277 static int vertex_group_menu_exec(bContext *C, wmOperator *op)
1278 {
1279         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1280         uiPopupMenu *pup;
1281         uiLayout *layout;
1282
1283         pup= uiPupMenuBegin(C, "Vertex Groups", 0);
1284         layout= uiPupMenuLayout(pup);
1285         uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
1286
1287         if(vgroup_object_in_edit_mode(ob)) {
1288                 uiItemBooleanO(layout, "Assign to New Group", 0, "OBJECT_OT_vertex_group_assign", "new", 1);
1289
1290                 if(BLI_countlist(&ob->defbase) && ob->actdef) {
1291                         uiItemO(layout, "Assign to Group", 0, "OBJECT_OT_vertex_group_assign");
1292                         uiItemO(layout, "Remove from Group", 0, "OBJECT_OT_vertex_group_remove_from");
1293                         uiItemBooleanO(layout, "Remove from All", 0, "OBJECT_OT_vertex_group_remove_from", "all", 1);
1294                 }
1295         }
1296
1297         if(BLI_countlist(&ob->defbase) && ob->actdef) {
1298                 if(vgroup_object_in_edit_mode(ob))
1299                         uiItemS(layout);
1300
1301                 uiItemO(layout, "Set Active Group", 0, "OBJECT_OT_vertex_group_set_active");
1302                 uiItemO(layout, "Remove Group", 0, "OBJECT_OT_vertex_group_remove");
1303                 uiItemBooleanO(layout, "Remove All Groups", 0, "OBJECT_OT_vertex_group_remove", "all", 1);
1304         }
1305
1306         uiPupMenuEnd(C, pup);
1307
1308         return OPERATOR_FINISHED;
1309 }
1310
1311 void OBJECT_OT_vertex_group_menu(wmOperatorType *ot)
1312 {
1313         /* identifiers */
1314         ot->name= "Vertex Group Menu";
1315         ot->idname= "OBJECT_OT_vertex_group_menu";
1316
1317         /* api callbacks */
1318         ot->poll= vertex_group_poll;
1319         ot->exec= vertex_group_menu_exec;
1320 }
1321