2.5
[blender.git] / source / blender / editors / mesh / editdeform.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  * Creator-specific support for vertex deformation groups
29  * Added: apply deform function (ton)
30  */
31
32 #include <string.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_cloth_types.h"
37 #include "DNA_curve_types.h"
38 #include "DNA_lattice_types.h"
39 #include "DNA_mesh_types.h"
40 #include "DNA_meshdata_types.h"
41 #include "DNA_modifier_types.h"
42 #include "DNA_object_types.h"
43 #include "DNA_object_force.h"
44 #include "DNA_scene_types.h"
45 #include "DNA_particle_types.h"
46
47 #include "BLI_blenlib.h"
48 #include "BLI_editVert.h"
49
50 #include "BKE_customdata.h"
51 #include "BKE_DerivedMesh.h"
52 #include "BKE_depsgraph.h"
53 #include "BKE_deform.h"
54 #include "BKE_displist.h"
55 #include "BKE_global.h"
56 #include "BKE_lattice.h"
57 #include "BKE_mesh.h"
58 #include "BKE_utildefines.h"
59
60 #include "ED_mesh.h"
61 #include "ED_view3d.h"
62 #include "mesh_intern.h"
63
64 /* XXX */
65 static void BIF_undo_push() {}
66 static void error() {}
67
68 /* only in editmode */
69 void sel_verts_defgroup (Object *obedit, int select)
70 {
71         EditVert *eve;
72         Object *ob;
73         int i;
74         MDeformVert *dvert;
75
76         ob= obedit;
77
78         if (!ob)
79                 return;
80
81         switch (ob->type){
82         case OB_MESH:
83         {
84                 Mesh *me= ob->data;
85                 
86                 for (eve=me->edit_mesh->verts.first; eve; eve=eve->next){
87                         dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT);
88
89                         if (dvert && dvert->totweight){
90                                 for (i=0; i<dvert->totweight; i++){
91                                         if (dvert->dw[i].def_nr == (ob->actdef-1)){
92                                                 if (select) eve->f |= SELECT;
93                                                 else eve->f &= ~SELECT;
94                                                 
95                                                 break;
96                                         }
97                                 }
98                         }
99                 }
100                 /* this has to be called, because this function operates on vertices only */
101                 if(select) EM_select_flush(me->edit_mesh);      // vertices to edges/faces
102                 else EM_deselect_flush(me->edit_mesh);
103         }
104                 break;
105         case OB_LATTICE:
106                 if(editLatt->dvert) {
107                         BPoint *bp;
108                         int a, tot;
109                         
110                         dvert= editLatt->dvert;
111
112                         tot= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
113                         for(a=0, bp= editLatt->def; a<tot; a++, bp++, dvert++) {
114                                 for (i=0; i<dvert->totweight; i++){
115                                         if (dvert->dw[i].def_nr == (ob->actdef-1)) {
116                                                 if(select) bp->f1 |= SELECT;
117                                                 else bp->f1 &= ~SELECT;
118                                                 
119                                                 break;
120                                         }
121                                 }
122                         }
123                 }       
124                 break;
125                 
126         default:
127                 break;
128         }
129 }
130
131 /* check if deform vertex has defgroup index */
132 MDeformWeight *get_defweight (MDeformVert *dv, int defgroup)
133 {
134         int i;
135         
136         if (!dv || defgroup<0)
137                 return NULL;
138         
139         for (i=0; i<dv->totweight; i++){
140                 if (dv->dw[i].def_nr == defgroup)
141                         return dv->dw+i;
142         }
143         return NULL;
144 }
145
146 /* Ensures that mv has a deform weight entry for
147    the specified defweight group */
148 /* Note this function is mirrored in editmesh_tools.c, for use for editvertices */
149 MDeformWeight *verify_defweight (MDeformVert *dv, int defgroup)
150 {
151         MDeformWeight *newdw;
152
153         /* do this check always, this function is used to check for it */
154         if (!dv || defgroup<0)
155                 return NULL;
156         
157         newdw = get_defweight (dv, defgroup);
158         if (newdw)
159                 return newdw;
160         
161         newdw = MEM_callocN (sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight");
162         if (dv->dw){
163                 memcpy (newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
164                 MEM_freeN (dv->dw);
165         }
166         dv->dw=newdw;
167         
168         dv->dw[dv->totweight].weight=0.0f;
169         dv->dw[dv->totweight].def_nr=defgroup;
170         /* Group index */
171         
172         dv->totweight++;
173
174         return dv->dw+(dv->totweight-1);
175 }
176
177 bDeformGroup *add_defgroup_name (Object *ob, char *name)
178 {
179         bDeformGroup    *defgroup;
180         
181         if (!ob)
182                 return NULL;
183         
184         defgroup = MEM_callocN (sizeof(bDeformGroup), "add deformGroup");
185
186         BLI_strncpy (defgroup->name, name, 32);
187
188         BLI_addtail(&ob->defbase, defgroup);
189         unique_vertexgroup_name(defgroup, ob);
190
191         ob->actdef = BLI_countlist(&ob->defbase);
192
193         return defgroup;
194 }
195
196 void add_defgroup (Object *ob) 
197 {
198         add_defgroup_name (ob, "Group");
199 }
200
201
202 void duplicate_defgroup ( Object *ob )
203 {
204         bDeformGroup *dg, *cdg;
205         char name[32], s[32];
206         MDeformWeight *org, *cpy;
207         MDeformVert *dvert;
208         Mesh *me;
209         int i, idg, icdg;
210
211         if (ob->type != OB_MESH)
212                 return;
213
214         dg = BLI_findlink (&ob->defbase, (ob->actdef-1));
215         if (!dg)
216                 return;
217         
218         if (strstr(dg->name, "_copy")) {
219                 BLI_strncpy (name, dg->name, 32); /* will be renamed _copy.001... etc */
220         } else {
221                 BLI_snprintf (name, 32, "%s_copy", dg->name);
222                 while (get_named_vertexgroup (ob, name)) {
223                         if ((strlen (name) + 6) > 32) {
224                                 error ("Error: the name for the new group is > 32 characters");
225                                 return;
226                         }
227                         strcpy (s, name);
228                         BLI_snprintf (name, 32, "%s_copy", s);
229                 }
230         }               
231
232         cdg = copy_defgroup (dg);
233         strcpy (cdg->name, name);
234         unique_vertexgroup_name(cdg, ob);
235         
236         BLI_addtail (&ob->defbase, cdg);
237
238         idg = (ob->actdef-1);
239         ob->actdef = BLI_countlist (&ob->defbase);
240         icdg = (ob->actdef-1);
241
242         me = get_mesh (ob);
243         if (!me->dvert)
244                 return;
245
246         for (i = 0; i < me->totvert; i++) {
247                 dvert = me->dvert+i;
248                 org = get_defweight (dvert, idg);
249                 if (org) {
250                         cpy = verify_defweight (dvert, icdg);
251                         cpy->weight = org->weight;
252                 }
253         }
254 }
255
256 static void del_defgroup_update_users(Object *ob, int id)
257 {
258         ExplodeModifierData *emd;
259         ModifierData *md;
260         ParticleSystem *psys;
261         ClothModifierData *clmd;
262         ClothSimSettings *clsim;
263         int a;
264
265         /* these cases don't use names to refer to vertex groups, so when
266          * they get deleted the numbers get out of sync, this corrects that */
267
268         if(ob->soft) {
269                 if(ob->soft->vertgroup == id)
270                         ob->soft->vertgroup= 0;
271                 else if(ob->soft->vertgroup > id)
272                         ob->soft->vertgroup--;
273         }
274
275         for(md=ob->modifiers.first; md; md=md->next) {
276                 if(md->type == eModifierType_Explode) {
277                         emd= (ExplodeModifierData*)md;
278
279                         if(emd->vgroup == id)
280                                 emd->vgroup= 0;
281                         else if(emd->vgroup > id)
282                                 emd->vgroup--;
283                 }
284                 else if(md->type == eModifierType_Cloth) {
285                         clmd= (ClothModifierData*)md;
286                         clsim= clmd->sim_parms;
287
288                         if(clsim) {
289                                 if(clsim->vgroup_mass == id)
290                                         clsim->vgroup_mass= 0;
291                                 else if(clsim->vgroup_mass > id)
292                                         clsim->vgroup_mass--;
293
294                                 if(clsim->vgroup_bend == id)
295                                         clsim->vgroup_bend= 0;
296                                 else if(clsim->vgroup_bend > id)
297                                         clsim->vgroup_bend--;
298
299                                 if(clsim->vgroup_struct == id)
300                                         clsim->vgroup_struct= 0;
301                                 else if(clsim->vgroup_struct > id)
302                                         clsim->vgroup_struct--;
303                         }
304                 }
305         }
306
307         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
308                 for(a=0; a<PSYS_TOT_VG; a++)
309                         if(psys->vgroup[a] == id)
310                                 psys->vgroup[a]= 0;
311                         else if(psys->vgroup[a] > id)
312                                 psys->vgroup[a]--;
313         }
314 }
315
316 void del_defgroup_in_object_mode ( Object *ob )
317 {
318         bDeformGroup *dg;
319         MDeformVert *dvert;
320         Mesh *me;
321         int i, e;
322
323         if ((!ob) || (ob->type != OB_MESH))
324                 return;
325
326         dg = BLI_findlink (&ob->defbase, (ob->actdef-1));
327         if (!dg)
328                 return;
329
330         me = get_mesh (ob);
331         if (me->dvert) {
332                 for (i = 0; i < me->totvert; i++) {
333                         dvert = me->dvert + i;
334                         if (dvert) {
335                                 if (get_defweight (dvert, (ob->actdef-1)))
336                                         remove_vert_defgroup (ob, dg, i);
337                         }
338                 }
339
340                 for (i = 0; i < me->totvert; i++) {
341                         dvert = me->dvert+i;
342                         if (dvert) {
343                                 for (e = 0; e < dvert->totweight; e++) {
344                                         if (dvert->dw[e].def_nr > (ob->actdef-1))
345                                                 dvert->dw[e].def_nr--;
346                                 }
347                         }
348                 }
349         }
350
351         del_defgroup_update_users(ob, ob->actdef);
352
353         /* Update the active deform index if necessary */
354         if (ob->actdef == BLI_countlist(&ob->defbase))
355                 ob->actdef--;
356   
357         /* Remove the group */
358         BLI_freelinkN (&ob->defbase, dg);
359 }
360
361 void del_defgroup (Object *ob)
362 {
363         bDeformGroup    *defgroup;
364         int                             i;
365
366         if (!ob)
367                 return;
368
369         if (!ob->actdef)
370                 return;
371
372         defgroup = BLI_findlink(&ob->defbase, ob->actdef-1);
373         if (!defgroup)
374                 return;
375
376         /* Make sure that no verts are using this group */
377         remove_verts_defgroup(ob, 1);
378
379         /* Make sure that any verts with higher indices are adjusted accordingly */
380         if(ob->type==OB_MESH) {
381                 Mesh *me= ob->data;
382                 EditMesh *em = me->edit_mesh;
383                 EditVert *eve;
384                 MDeformVert *dvert;
385                 
386                 for (eve=em->verts.first; eve; eve=eve->next){
387                         dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT);
388
389                         if (dvert)
390                                 for (i=0; i<dvert->totweight; i++)
391                                         if (dvert->dw[i].def_nr > (ob->actdef-1))
392                                                 dvert->dw[i].def_nr--;
393                 }
394         }
395         else {
396                 BPoint *bp;
397                 MDeformVert *dvert= editLatt->dvert;
398                 int a, tot;
399                 
400                 if (dvert) {
401                         tot= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
402                         for(a=0, bp= editLatt->def; a<tot; a++, bp++, dvert++) {
403                                 for (i=0; i<dvert->totweight; i++){
404                                         if (dvert->dw[i].def_nr > (ob->actdef-1))
405                                                 dvert->dw[i].def_nr--;
406                                 }
407                         }
408                 }
409         }
410
411         del_defgroup_update_users(ob, ob->actdef);
412
413         /* Update the active deform index if necessary */
414         if (ob->actdef==BLI_countlist(&ob->defbase))
415                 ob->actdef--;
416         
417         /* Remove the group */
418         BLI_freelinkN (&ob->defbase, defgroup);
419         
420         /* remove all dverts */
421         if(ob->actdef==0) {
422                 if(ob->type==OB_MESH) {
423                         Mesh *me= ob->data;
424                         CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
425                         me->dvert= NULL;
426                 }
427                 else {
428                         if (editLatt->dvert) {
429                                 MEM_freeN(editLatt->dvert);
430                                 editLatt->dvert= NULL;
431                         }
432                 }
433         }
434 }
435
436 void del_all_defgroups (Object *ob)
437 {
438         /* Sanity check */
439         if (ob == NULL)
440                 return;
441         
442         /* Remove all DVerts */
443         if (ob->type==OB_MESH) {
444                 Mesh *me= ob->data;
445                 CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
446                 me->dvert= NULL;
447         }
448         else {
449                 if (editLatt->dvert) {
450                         MEM_freeN(editLatt->dvert);
451                         editLatt->dvert= NULL;
452                 }
453         }
454         
455         /* Remove all DefGroups */
456         BLI_freelistN(&ob->defbase);
457         
458         /* Fix counters/indices */
459         ob->actdef= 0;
460 }
461
462 void create_dverts(ID *id)
463 {
464         /* create deform verts
465          */
466
467         if( GS(id->name)==ID_ME) {
468                 Mesh *me= (Mesh *)id;
469                 me->dvert= CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
470         }
471         else if( GS(id->name)==ID_LT) {
472                 Lattice *lt= (Lattice *)id;
473                 lt->dvert= MEM_callocN(sizeof(MDeformVert)*lt->pntsu*lt->pntsv*lt->pntsw, "lattice deformVert");
474         }
475 }
476
477 /* for mesh in object mode
478    lattice can be in editmode */
479 void remove_vert_def_nr (Object *ob, int def_nr, int vertnum)
480 {
481         /* This routine removes the vertex from the deform
482          * group with number def_nr.
483          *
484          * This routine is meant to be fast, so it is the
485          * responsibility of the calling routine to:
486          *   a) test whether ob is non-NULL
487          *   b) test whether ob is a mesh
488          *   c) calculate def_nr
489          */
490
491         MDeformWeight *newdw;
492         MDeformVert *dvert= NULL;
493         int i;
494
495         /* get the deform vertices corresponding to the
496          * vertnum
497          */
498         if(ob->type==OB_MESH) {
499                 if( ((Mesh*)ob->data)->dvert )
500                         dvert = ((Mesh*)ob->data)->dvert + vertnum;
501         }
502         else if(ob->type==OB_LATTICE) {
503                 Lattice *lt= ob->data;
504                 
505                 if(lt->editlatt) lt= lt->editlatt;
506                 if(lt->dvert)
507                         dvert = lt->dvert + vertnum;
508         }
509         
510         if(dvert==NULL)
511                 return;
512         
513         /* for all of the deform weights in the
514          * deform vert
515          */
516         for (i=dvert->totweight - 1 ; i>=0 ; i--){
517
518                 /* if the def_nr is the same as the one
519                  * for our weight group then remove it
520                  * from this deform vert.
521                  */
522                 if (dvert->dw[i].def_nr == def_nr) {
523                         dvert->totweight--;
524         
525                         /* if there are still other deform weights
526                          * attached to this vert then remove this
527                          * deform weight, and reshuffle the others
528                          */
529                         if (dvert->totweight) {
530                                 newdw = MEM_mallocN (sizeof(MDeformWeight)*(dvert->totweight), 
531                                                                          "deformWeight");
532                                 if (dvert->dw){
533                                         memcpy (newdw, dvert->dw, sizeof(MDeformWeight)*i);
534                                         memcpy (newdw+i, dvert->dw+i+1, 
535                                                         sizeof(MDeformWeight)*(dvert->totweight-i));
536                                         MEM_freeN (dvert->dw);
537                                 }
538                                 dvert->dw=newdw;
539                         }
540                         /* if there are no other deform weights
541                          * left then just remove the deform weight
542                          */
543                         else {
544                                 MEM_freeN (dvert->dw);
545                                 dvert->dw = NULL;
546                                 break;
547                         }
548                 }
549         }
550
551 }
552
553 /* for Mesh in Object mode */
554 /* allows editmode for Lattice */
555 void add_vert_defnr (Object *ob, int def_nr, int vertnum, 
556                            float weight, int assignmode)
557 {
558         /* add the vert to the deform group with the
559          * specified number
560          */
561         MDeformVert *dv= NULL;
562         MDeformWeight *newdw;
563         int     i;
564
565         /* get the vert */
566         if(ob->type==OB_MESH) {
567                 if(((Mesh*)ob->data)->dvert)
568                         dv = ((Mesh*)ob->data)->dvert + vertnum;
569         }
570         else if(ob->type==OB_LATTICE) {
571                 Lattice *lt= ob->data;
572                 
573                 if(lt->editlatt) lt= lt->editlatt;
574                         
575                 if(lt->dvert)
576                         dv = lt->dvert + vertnum;
577         }
578         
579         if(dv==NULL)
580                 return;
581         
582         /* Lets first check to see if this vert is
583          * already in the weight group -- if so
584          * lets update it
585          */
586         for (i=0; i<dv->totweight; i++){
587                 
588                 /* if this weight cooresponds to the
589                  * deform group, then add it using
590                  * the assign mode provided
591                  */
592                 if (dv->dw[i].def_nr == def_nr){
593                         
594                         switch (assignmode) {
595                         case WEIGHT_REPLACE:
596                                 dv->dw[i].weight=weight;
597                                 break;
598                         case WEIGHT_ADD:
599                                 dv->dw[i].weight+=weight;
600                                 if (dv->dw[i].weight >= 1.0)
601                                         dv->dw[i].weight = 1.0;
602                                 break;
603                         case WEIGHT_SUBTRACT:
604                                 dv->dw[i].weight-=weight;
605                                 /* if the weight is zero or less then
606                                  * remove the vert from the deform group
607                                  */
608                                 if (dv->dw[i].weight <= 0.0)
609                                         remove_vert_def_nr(ob, def_nr, vertnum);
610                                 break;
611                         }
612                         return;
613                 }
614         }
615
616         /* if the vert wasn't in the deform group then
617          * we must take a different form of action ...
618          */
619
620         switch (assignmode) {
621         case WEIGHT_SUBTRACT:
622                 /* if we are subtracting then we don't
623                  * need to do anything
624                  */
625                 return;
626
627         case WEIGHT_REPLACE:
628         case WEIGHT_ADD:
629                 /* if we are doing an additive assignment, then
630                  * we need to create the deform weight
631                  */
632                 newdw = MEM_callocN (sizeof(MDeformWeight)*(dv->totweight+1), 
633                                                          "deformWeight");
634                 if (dv->dw){
635                         memcpy (newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
636                         MEM_freeN (dv->dw);
637                 }
638                 dv->dw=newdw;
639     
640                 dv->dw[dv->totweight].weight=weight;
641                 dv->dw[dv->totweight].def_nr=def_nr;
642     
643                 dv->totweight++;
644                 break;
645         }
646 }
647
648 /* called while not in editmode */
649 void add_vert_to_defgroup (Object *ob, bDeformGroup *dg, int vertnum, 
650                            float weight, int assignmode)
651 {
652         /* add the vert to the deform group with the
653          * specified assign mode
654          */
655         int     def_nr;
656
657         /* get the deform group number, exit if
658          * it can't be found
659          */
660         def_nr = get_defgroup_num(ob, dg);
661         if (def_nr < 0) return;
662
663         /* if there's no deform verts then
664          * create some
665          */
666         if(ob->type==OB_MESH) {
667                 if (!((Mesh*)ob->data)->dvert)
668                         create_dverts(ob->data);
669         }
670         else if(ob->type==OB_LATTICE) {
671                 if (!((Lattice*)ob->data)->dvert)
672                         create_dverts(ob->data);
673         }
674
675         /* call another function to do the work
676          */
677         add_vert_defnr (ob, def_nr, vertnum, weight, assignmode);
678 }
679
680 /* Only available in editmode */
681 void assign_verts_defgroup (Object *obedit)
682 {
683         float editbutvweight;   /* XXX */
684         Object *ob;
685         EditVert *eve;
686         bDeformGroup *dg, *eg;
687         MDeformWeight *newdw;
688         MDeformVert *dvert;
689         int     i, done;
690         
691 // XXX  if(multires_level1_test()) return;
692
693         ob= obedit;
694
695         if (!ob)
696                 return;
697
698         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
699         if (!dg){
700                 error ("No vertex group is active");
701                 return;
702         }
703
704         switch (ob->type){
705         case OB_MESH:
706         {
707                 Mesh *me= ob->data;
708                 
709                 if (!CustomData_has_layer(&me->edit_mesh->vdata, CD_MDEFORMVERT))
710                         EM_add_data_layer(me->edit_mesh, &me->edit_mesh->vdata, CD_MDEFORMVERT);
711
712                 /* Go through the list of editverts and assign them */
713                 for (eve=me->edit_mesh->verts.first; eve; eve=eve->next){
714                         dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT);
715
716                         if (dvert && (eve->f & 1)){
717                                 done=0;
718                                 /* See if this vert already has a reference to this group */
719                                 /*              If so: Change its weight */
720                                 done=0;
721                                 for (i=0; i<dvert->totweight; i++){
722                                         eg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr);
723                                         /* Find the actual group */
724                                         if (eg==dg){
725                                                 dvert->dw[i].weight=editbutvweight;
726                                                 done=1;
727                                                 break;
728                                         }
729                                 }
730                                 /*              If not: Add the group and set its weight */
731                                 if (!done){
732                                         newdw = MEM_callocN (sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
733                                         if (dvert->dw){
734                                                 memcpy (newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
735                                                 MEM_freeN (dvert->dw);
736                                         }
737                                         dvert->dw=newdw;
738
739                                         dvert->dw[dvert->totweight].weight= editbutvweight;
740                                         dvert->dw[dvert->totweight].def_nr= ob->actdef-1;
741
742                                         dvert->totweight++;
743
744                                 }
745                         }
746                 }
747         }
748                 break;
749         case OB_LATTICE:
750                 {
751                         BPoint *bp;
752                         int a, tot;
753                         
754                         if(editLatt->dvert==NULL)
755                                 create_dverts(&editLatt->id);
756                         
757                         tot= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
758                         for(a=0, bp= editLatt->def; a<tot; a++, bp++) {
759                                 if(bp->f1 & SELECT)
760                                         add_vert_defnr (ob, ob->actdef-1, a, editbutvweight, WEIGHT_REPLACE);
761                         }
762                 }       
763                 break;
764         default:
765                 printf ("Assigning deformation groups to unknown object type\n");
766                 break;
767         }
768
769 }
770
771 /* mesh object mode, lattice can be in editmode */
772 void remove_vert_defgroup (Object *ob, bDeformGroup     *dg, int vertnum)
773 {
774         /* This routine removes the vertex from the specified
775          * deform group.
776          */
777
778         int def_nr;
779
780         /* if the object is NULL abort
781          */
782         if (!ob)
783                 return;
784
785         /* get the deform number that cooresponds
786          * to this deform group, and abort if it
787          * can not be found.
788          */
789         def_nr = get_defgroup_num(ob, dg);
790         if (def_nr < 0) return;
791
792         /* call another routine to do the work
793          */
794         remove_vert_def_nr (ob, def_nr, vertnum);
795 }
796
797 /* for mesh in object mode lattice can be in editmode */
798 static float get_vert_def_nr (Object *ob, int def_nr, int vertnum)
799 {
800         MDeformVert *dvert= NULL;
801         int i;
802
803         /* get the deform vertices corresponding to the
804          * vertnum
805          */
806         if(ob->type==OB_MESH) {
807                 if( ((Mesh*)ob->data)->dvert )
808                         dvert = ((Mesh*)ob->data)->dvert + vertnum;
809         }
810         else if(ob->type==OB_LATTICE) {
811                 Lattice *lt= ob->data;
812                 
813                 if(lt->editlatt) lt= lt->editlatt;
814                 
815                 if(lt->dvert)
816                         dvert = lt->dvert + vertnum;
817         }
818         
819         if(dvert==NULL)
820                 return 0.0f;
821         
822         for(i=dvert->totweight-1 ; i>=0 ; i--)
823                 if(dvert->dw[i].def_nr == def_nr)
824                         return dvert->dw[i].weight;
825
826         return 0.0f;
827 }
828
829 /* mesh object mode, lattice can be in editmode */
830 float get_vert_defgroup (Object *ob, bDeformGroup *dg, int vertnum)
831 {
832         int def_nr;
833
834         if(!ob)
835                 return 0.0f;
836
837         def_nr = get_defgroup_num(ob, dg);
838         if(def_nr < 0) return 0.0f;
839
840         return get_vert_def_nr (ob, def_nr, vertnum);
841 }
842
843 /* Only available in editmode */
844 /* removes from active defgroup, if allverts==0 only selected vertices */
845 void remove_verts_defgroup (Object *obedit, int allverts)
846 {
847         Object *ob;
848         EditVert *eve;
849         MDeformVert *dvert;
850         MDeformWeight *newdw;
851         bDeformGroup *dg, *eg;
852         int     i;
853         
854 // XXX  if(multires_level1_test()) return;
855
856         ob= obedit;
857
858         if (!ob)
859                 return;
860
861         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
862         if (!dg){
863                 error ("No vertex group is active");
864                 return;
865         }
866
867         switch (ob->type){
868         case OB_MESH:
869         {
870                 Mesh *me= ob->data;
871                 
872                 for (eve=me->edit_mesh->verts.first; eve; eve=eve->next){
873                         dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT);
874                 
875                         if (dvert && dvert->dw && ((eve->f & 1) || allverts)){
876                                 for (i=0; i<dvert->totweight; i++){
877                                         /* Find group */
878                                         eg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr);
879                                         if (eg == dg){
880                                                 dvert->totweight--;
881                                                 if (dvert->totweight){
882                                                         newdw = MEM_mallocN (sizeof(MDeformWeight)*(dvert->totweight), "deformWeight");
883                                                         
884                                                         if (dvert->dw){
885                                                                 memcpy (newdw, dvert->dw, sizeof(MDeformWeight)*i);
886                                                                 memcpy (newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i));
887                                                                 MEM_freeN (dvert->dw);
888                                                         }
889                                                         dvert->dw=newdw;
890                                                 }
891                                                 else{
892                                                         MEM_freeN (dvert->dw);
893                                                         dvert->dw=NULL;
894                                                         break;
895                                                 }
896                                         }
897                                 }
898                         }
899                 }
900         }
901                 break;
902         case OB_LATTICE:
903                 
904                 if(editLatt->dvert) {
905                         BPoint *bp;
906                         int a, tot= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
907                                 
908                         for(a=0, bp= editLatt->def; a<tot; a++, bp++) {
909                                 if(allverts || (bp->f1 & SELECT))
910                                         remove_vert_defgroup (ob, dg, a);
911                         }
912                 }
913                 break;
914                 
915         default:
916                 printf ("Removing deformation groups from unknown object type\n");
917                 break;
918         }
919 }
920
921 /* Only available in editmode */
922 /* removes from all defgroup, if allverts==0 only selected vertices */
923 void remove_verts_defgroups(Object *obedit, int allverts)
924 {
925         Object *ob;
926         int actdef, defCount;
927         
928 //  XXX if (multires_level1_test()) return;
929
930         ob= obedit;
931         if (ob == NULL) return;
932         
933         actdef= ob->actdef;
934         defCount= BLI_countlist(&ob->defbase);
935         
936         if (defCount == 0) {
937                 error("Object has no vertex groups");
938                 return;
939         }
940         
941         /* To prevent code redundancy, we just use remove_verts_defgroup, but that
942          * only operates on the active vgroup. So we iterate through all groups, by changing
943          * active group index
944          */
945         for (ob->actdef= 1; ob->actdef <= defCount; ob->actdef++)
946                 remove_verts_defgroup(ob, allverts);
947                 
948         ob->actdef= actdef;
949 }
950
951 void vertexgroup_select_by_name(Object *ob, char *name)
952 {
953         bDeformGroup *curdef;
954         int actdef= 1;
955         
956         if(ob==NULL) return;
957         
958         for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++){
959                 if (!strcmp(curdef->name, name)) {
960                         ob->actdef= actdef;
961                         return;
962                 }
963         }
964         ob->actdef=0;   // this signals on painting to create a new one, if a bone in posemode is selected */
965 }
966
967 /* This function provides a shortcut for adding/removing verts from 
968  * vertex groups. It is called by the Ctrl-G hotkey in EditMode for Meshes
969  * and Lattices. (currently only restricted to those two)
970  * It is only responsible for 
971  */
972 void vgroup_assign_with_menu(Object *ob)
973 {
974         int defCount;
975         int mode;
976         
977         /* prevent crashes */
978         if (ob==NULL) return;
979         
980         defCount= BLI_countlist(&ob->defbase);
981         
982         /* give user choices of adding to current/new or removing from current */
983 // XXX  if (defCount && ob->actdef)
984 //              mode = pupmenu("Vertex Groups %t|Add Selected to New Group %x1|Add Selected to Active Group %x2|Remove Selected from Active Group %x3|Remove Selected from All Groups %x4");
985 //      else
986 //              mode= pupmenu("Vertex Groups %t|Add Selected to New Group %x1");
987         
988         /* handle choices */
989         switch (mode) {
990                 case 1: /* add to new group */
991                         add_defgroup(ob);
992                         assign_verts_defgroup(ob);
993                         BIF_undo_push("Assign to vertex group");
994                         break;
995                 case 2: /* add to current group */
996                         assign_verts_defgroup(ob);
997                         BIF_undo_push("Assign to vertex group");
998                         break;
999                 case 3: /* remove from current group */
1000                         remove_verts_defgroup(ob, 0);
1001                         BIF_undo_push("Remove from vertex group");
1002                         break;
1003                 case 4: /* remove from all groups */
1004                         remove_verts_defgroups(ob, 0);
1005                         BIF_undo_push("Remove from all vertex groups");
1006                         break;
1007         }
1008 }
1009
1010 /* This function provides a shortcut for commonly used vertex group 
1011  * functions - change weight (not implemented), change active group, delete active group,
1012  * when Ctrl-Shift-G is used in EditMode, for Meshes and Lattices (only for now).
1013  */
1014 void vgroup_operation_with_menu(Object *ob)
1015 {
1016         int defCount;
1017         int mode;
1018         
1019         /* prevent crashes and useless cases */
1020         if (ob==NULL) return;
1021         
1022         defCount= BLI_countlist(&ob->defbase);
1023         if (defCount == 0) return;
1024         
1025         /* give user choices of adding to current/new or removing from current */
1026 // XXX  if (ob->actdef)
1027 //              mode = pupmenu("Vertex Groups %t|Change Active Group%x1|Delete Active Group%x2|Delete All Groups%x3");
1028 //      else
1029 //              mode= pupmenu("Vertex Groups %t|Change Active Group%x1|Delete All Groups%x3");
1030         
1031         /* handle choices */
1032         switch (mode) {
1033                 case 1: /* change active group*/
1034                         {
1035                                 char *menustr= NULL; // XXX get_vertexgroup_menustr(ob);
1036                                 short nr;
1037                                 
1038                                 if (menustr) {
1039 // XXX                                  nr= pupmenu(menustr);
1040                                         
1041                                         if ((nr >= 1) && (nr <= defCount)) 
1042                                                 ob->actdef= nr;
1043                                                 
1044                                         MEM_freeN(menustr);
1045                                 }
1046                         }
1047                         break;
1048                 case 2: /* delete active group  */
1049                         {
1050                                 del_defgroup(ob);
1051                                 BIF_undo_push("Delete vertex group");
1052                         }
1053                         break;
1054                 case 3: /* delete all groups */
1055                         {
1056                                 del_all_defgroups(ob);
1057                                 BIF_undo_push("Delete all vertex groups");
1058                         }
1059                         break;
1060         }
1061 }
1062
1063