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