- replaced G.{edve,eded,edvl} with G.editMesh, atm just a structure to
[blender.git] / source / blender / src / editdeform.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  * Creator-specific support for vertex deformation groups
32  */
33
34 #include <string.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "DNA_mesh_types.h"
39 #include "DNA_meshdata_types.h"
40 #include "DNA_object_types.h"
41
42 #include "BLI_blenlib.h"
43 #include "BLI_editVert.h"
44
45 #include "BKE_global.h"
46 #include "BKE_deform.h"
47 #include "BKE_mesh.h"
48
49 #include "BIF_editdeform.h"
50 #include "BIF_toolbox.h"
51
52 #include "BSE_edit.h"
53
54 #ifdef HAVE_CONFIG_H
55 #include <config.h>
56 #endif
57
58 void sel_verts_defgroup (int select)
59 {
60         EditMesh *em = G.editMesh;
61         EditVert                *eve;
62         Object                  *ob;
63         int                             i;
64
65         ob=G.obedit;
66
67         if (!ob)
68                 return;
69
70         switch (ob->type){
71         case OB_MESH:
72                 for (eve=em->verts.first; eve; eve=eve->next){
73                         if (eve->totweight){
74                                 for (i=0; i<eve->totweight; i++){
75                                         if (eve->dw[i].def_nr == (ob->actdef-1)){
76                                                 if (select) eve->f |= 1;
77                                                 else eve->f &= ~1;
78                                                 break;
79                                         }
80                                 }
81                         }
82                 }
83                 break;
84         default:
85                 break;
86         }
87         countall();
88
89 }
90
91 MDeformWeight *verify_defweight (MDeformVert *dv, int defgroup)
92 /* Ensures that mv has a deform weight entry for
93 the specified defweight group */
94 {
95         int     i;
96         MDeformWeight *newdw;
97
98         if (!dv)
99                 return NULL;
100
101         for (i=0; i<dv->totweight; i++){
102                 if (dv->dw[i].def_nr == defgroup)
103                         return dv->dw+i;
104         }
105
106         newdw = MEM_callocN (sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight");
107         if (dv->dw){
108                 memcpy (newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
109                 MEM_freeN (dv->dw);
110         }
111         dv->dw=newdw;
112         
113         dv->dw[dv->totweight].weight=0;
114         dv->dw[dv->totweight].def_nr=defgroup;
115         /* Group index */
116         
117         dv->totweight++;
118
119         return dv->dw+(dv->totweight-1);
120 }
121
122 void add_defgroup (Object *ob) {
123         add_defgroup_name (ob, "Group");
124 }
125
126 bDeformGroup *add_defgroup_name (Object *ob, char *name)
127 {
128         bDeformGroup    *defgroup;
129         
130         if (!ob)
131                 return NULL;
132         
133         defgroup = MEM_callocN (sizeof(bDeformGroup), "deformGroup");
134
135         /* I think there should be some length
136          * checking here -- don't know why NaN
137          * never checks name lengths (see
138          * unique_vertexgroup_name, for example).
139          */
140         strcpy (defgroup->name, name);
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 void del_defgroup (Object *ob)
151 {
152         EditMesh *em = G.editMesh;
153         bDeformGroup    *defgroup;
154         EditVert                *eve;
155         int                             i;
156
157
158         if (!ob)
159                 return;
160
161         if (!ob->actdef)
162                 return;
163
164         defgroup = BLI_findlink(&ob->defbase, ob->actdef-1);
165         if (!defgroup)
166                 return;
167
168         /* Make sure that no verts are using this group */
169         remove_verts_defgroup(1);
170
171         /* Make sure that any verts with higher indices are adjusted accordingly */
172         for (eve=em->verts.first; eve; eve=eve->next){
173                 for (i=0; i<eve->totweight; i++){
174                         if (eve->dw[i].def_nr > (ob->actdef-1))
175                                 eve->dw[i].def_nr--;
176                 }
177         }
178
179         /* Update the active material index if necessary */
180         if (ob->actdef==BLI_countlist(&ob->defbase))
181                 ob->actdef--;
182
183         /* Remove the group */
184         BLI_freelinkN (&ob->defbase, defgroup);
185 }
186
187 void create_dverts(Mesh *me)
188 {
189         /* create deform verts for the mesh
190          */
191         int i;
192
193         me->dvert= MEM_mallocN(sizeof(MDeformVert)*me->totvert, "deformVert");
194         for (i=0; i < me->totvert; ++i) {
195                 me->dvert[i].totweight = 0;
196                 me->dvert[i].dw        = NULL;
197         }
198 }
199
200 int  get_defgroup_num (Object *ob, bDeformGroup *dg)
201 {
202         /* Fetch the location of this deform group
203          * within the linked list of deform groups.
204          * (this number is stored in the deform
205          * weights of the deform verts to link them
206          * to this deform group) deform deform
207          * deform blah blah deform
208          */
209
210         bDeformGroup    *eg;
211         int def_nr;
212
213         eg = ob->defbase.first;
214         def_nr = 0;
215
216         /* loop through all deform groups
217          */
218         while (eg != NULL){
219
220                 /* if the current deform group is
221                  * the one we are after, return
222                  * def_nr
223                  */
224                 if (eg == dg){
225                         break;
226                 }
227                 ++def_nr;
228                 eg = eg->next;
229         }
230
231         /* if there was no deform group found then
232          * return -1 (should set up a nice symbolic
233          * constant for this)
234          */
235         if (eg == NULL) return -1;
236         
237         return def_nr;
238     
239 }
240
241
242 void remove_vert_def_nr (Object *ob, int def_nr, int vertnum)
243 {
244         /* This routine removes the vertex from the deform
245          * group with number def_nr.
246          *
247          * This routine is meant to be fast, so it is the
248          * responsibility of the calling routine to:
249          *   a) test whether ob is non-NULL
250          *   b) test whether ob is a mesh
251          *   c) calculate def_nr
252          */
253
254         MDeformWeight *newdw;
255         MDeformVert *dvert;
256         int i;
257
258         /* if this mesh has no deform mesh abort
259          */
260         if (!((Mesh*)ob->data)->dvert) return;
261
262         /* get the deform mesh cooresponding to the
263          * vertnum
264          */
265         dvert = ((Mesh*)ob->data)->dvert + vertnum;
266
267         /* for all of the deform weights in the
268          * deform vert
269          */
270         for (i=dvert->totweight - 1 ; i>=0 ; i--){
271
272                 /* if the def_nr is the same as the one
273                  * for our weight group then remove it
274                  * from this deform vert.
275                  */
276                 if (dvert->dw[i].def_nr == def_nr) {
277                         dvert->totweight--;
278         
279                         /* if there are still other deform weights
280                          * attached to this vert then remove this
281                          * deform weight, and reshuffle the others
282                          */
283                         if (dvert->totweight) {
284                                 newdw = MEM_mallocN (sizeof(MDeformWeight)*(dvert->totweight), 
285                                                                          "deformWeight");
286                                 if (dvert->dw){
287                                         memcpy (newdw, dvert->dw, sizeof(MDeformWeight)*i);
288                                         memcpy (newdw+i, dvert->dw+i+1, 
289                                                         sizeof(MDeformWeight)*(dvert->totweight-i));
290                                         MEM_freeN (dvert->dw);
291                                 }
292                                 dvert->dw=newdw;
293                         }
294                         /* if there are no other deform weights
295                          * left then just remove the deform weight
296                          */
297                         else {
298                                 MEM_freeN (dvert->dw);
299                                 dvert->dw = NULL;
300                         }
301                 }
302         }
303
304 }
305
306 void add_vert_defnr (Object *ob, int def_nr, int vertnum, 
307                            float weight, int assignmode)
308 {
309         /* add the vert to the deform group with the
310          * specified number
311          */
312
313         MDeformVert *dv;
314         MDeformWeight *newdw;
315         int     i;
316
317         /* get the vert
318          */
319         dv = ((Mesh*)ob->data)->dvert + vertnum;
320
321         /* Lets first check to see if this vert is
322          * already in the weight group -- if so
323          * lets update it
324          */
325         for (i=0; i<dv->totweight; i++){
326                 
327                 /* if this weight cooresponds to the
328                  * deform group, then add it using
329                  * the assign mode provided
330                  */
331                 if (dv->dw[i].def_nr == def_nr){
332                         
333                         switch (assignmode) {
334                         case WEIGHT_REPLACE:
335                                 dv->dw[i].weight=weight;
336                                 break;
337                         case WEIGHT_ADD:
338                                 dv->dw[i].weight+=weight;
339                                 if (dv->dw[i].weight >= 1.0)
340                                         dv->dw[i].weight = 1.0;
341                                 break;
342                         case WEIGHT_SUBTRACT:
343                                 dv->dw[i].weight-=weight;
344                                 /* if the weight is zero or less then
345                                  * remove the vert from the deform group
346                                  */
347                                 if (dv->dw[i].weight <= 0.0)
348                                         remove_vert_def_nr(ob, def_nr, vertnum);
349                                 break;
350                         }
351                         return;
352                 }
353         }
354
355         /* if the vert wasn't in the deform group then
356          * we must take a different form of action ...
357          */
358
359         switch (assignmode) {
360         case WEIGHT_SUBTRACT:
361                 /* if we are subtracting then we don't
362                  * need to do anything
363                  */
364                 return;
365
366         case WEIGHT_REPLACE:
367         case WEIGHT_ADD:
368                 /* if we are doing an additive assignment, then
369                  * we need to create the deform weight
370                  */
371                 newdw = MEM_callocN (sizeof(MDeformWeight)*(dv->totweight+1), 
372                                                          "deformWeight");
373                 if (dv->dw){
374                         memcpy (newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
375                         MEM_freeN (dv->dw);
376                 }
377                 dv->dw=newdw;
378     
379                 dv->dw[dv->totweight].weight=weight;
380                 dv->dw[dv->totweight].def_nr=def_nr;
381     
382                 dv->totweight++;
383                 break;
384         }
385 }
386
387 void add_vert_to_defgroup (Object *ob, bDeformGroup *dg, int vertnum, 
388                            float weight, int assignmode)
389 {
390         /* add the vert to the deform group with the
391          * specified assign mode
392          */
393         int     def_nr;
394
395         /* get the deform group number, exit if
396          * it can't be found
397          */
398         def_nr = get_defgroup_num(ob, dg);
399         if (def_nr < 0) return;
400
401         /* if this mesh has no deform verts then
402          * create some
403          */
404         if (!((Mesh*)ob->data)->dvert) {
405                 create_dverts((Mesh*)ob->data);
406         }
407
408         /* call another function to do the work
409          */
410         add_vert_defnr (ob, def_nr, vertnum, weight, assignmode);
411 }
412
413
414 void assign_verts_defgroup (void)
415 /* Only available in editmode */
416 {
417         EditMesh *em = G.editMesh;
418         Object *ob;
419         EditVert *eve;
420         bDeformGroup    *dg, *eg;
421         extern float editbutvweight;    /* buttons.c */
422         int     i, done;
423         MDeformWeight *newdw;
424
425         ob=G.obedit;
426
427         if (!ob)
428                 return;
429
430         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
431         if (!dg){
432                 error ("No vertex group active");
433                 return;
434         }
435
436         switch (ob->type){
437         case OB_MESH:
438                 /* Go through the list of editverts and assign them */
439                 for (eve=em->verts.first; eve; eve=eve->next){
440                         if (eve->f & 1){
441                                 done=0;
442                                 /* See if this vert already has a reference to this group */
443                                 /*              If so: Change its weight */
444                                 done=0;
445                                 for (i=0; i<eve->totweight; i++){
446                                         eg = BLI_findlink (&ob->defbase, eve->dw[i].def_nr);
447                                         /* Find the actual group */
448                                         if (eg==dg){
449                                                 eve->dw[i].weight=editbutvweight;
450                                                 done=1;
451                                                 break;
452                                         }
453                                 }
454                                 /*              If not: Add the group and set its weight */
455                                 if (!done){
456                                         newdw = MEM_callocN (sizeof(MDeformWeight)*(eve->totweight+1), "deformWeight");
457                                         if (eve->dw){
458                                                 memcpy (newdw, eve->dw, sizeof(MDeformWeight)*eve->totweight);
459                                                 MEM_freeN (eve->dw);
460                                         }
461                                         eve->dw=newdw;
462
463                                         eve->dw[eve->totweight].weight=editbutvweight;
464                                         eve->dw[eve->totweight].def_nr=ob->actdef-1;
465
466                                         eve->totweight++;
467
468                                 }
469                         }
470                 }
471                 break;
472         default:
473                 printf ("Assigning deformation groups to unknown object type\n");
474                 break;
475         }
476
477 }
478
479 void remove_vert_defgroup (Object *ob, bDeformGroup     *dg, int vertnum)
480 {
481         /* This routine removes the vertex from the specified
482          * deform group.
483          */
484
485         int def_nr;
486
487         /* if the object is NULL abort
488          */
489         if (!ob)
490                 return;
491
492         /* if this isn't a mesh abort
493          */
494         if (ob->type != OB_MESH) return;
495
496         /* get the deform number that cooresponds
497          * to this deform group, and abort if it
498          * can not be found.
499          */
500         def_nr = get_defgroup_num(ob, dg);
501         if (def_nr < 0) return;
502
503         /* call another routine to do the work
504          */
505         remove_vert_def_nr (ob, def_nr, vertnum);
506 }
507
508 void remove_verts_defgroup (int allverts)
509 /* Only available in editmode */
510 {
511         EditMesh *em = G.editMesh;
512         Object *ob;
513         EditVert *eve;
514         MDeformWeight *newdw;
515         bDeformGroup    *dg, *eg;
516         int     i;
517
518         ob=G.obedit;
519
520         if (!ob)
521                 return;
522
523         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
524         if (!dg){
525                 error ("No vertex group active");
526                 return;
527         }
528
529         switch (ob->type){
530         case OB_MESH:
531                 for (eve=em->verts.first; eve; eve=eve->next){
532                         if (eve->dw && ((eve->f & 1) || allverts)){
533                                 for (i=0; i<eve->totweight; i++){
534                                         /* Find group */
535                                         eg = BLI_findlink (&ob->defbase, eve->dw[i].def_nr);
536                                         if (eg == dg){
537                                                 eve->totweight--;
538                                                 if (eve->totweight){
539                                                         newdw = MEM_mallocN (sizeof(MDeformWeight)*(eve->totweight), "deformWeight");
540                                                         
541                                                         if (eve->dw){
542                                                                 memcpy (newdw, eve->dw, sizeof(MDeformWeight)*i);
543                                                                 memcpy (newdw+i, eve->dw+i+1, sizeof(MDeformWeight)*(eve->totweight-i));
544                                                                 MEM_freeN (eve->dw);
545                                                         }
546                                                         eve->dw=newdw;
547                                                 }
548                                                 else{
549                                                         MEM_freeN (eve->dw);
550                                                         eve->dw=NULL;
551                                                 }
552                                         }
553                                 }
554                         }
555                 }
556                 break;
557         default:
558                 printf ("Removing deformation groups from unknown object type\n");
559                 break;
560         }
561 }
562
563 void verify_defgroups (Object *ob)
564 {
565         /* Ensure the defbase & the dverts match */
566         switch (ob->type){
567         case OB_MESH:
568
569                 /* I'm pretty sure this means "If there are no
570                  * deform groups defined, yet there are deform
571                  * vertices, then delete the deform vertices
572                  */
573                 if (!ob->defbase.first){
574                         if (((Mesh*)ob->data)->dvert){
575                                 free_dverts(((Mesh*)ob->data)->dvert, 
576                                                         ((Mesh*)ob->data)->totvert);
577                                 ((Mesh*)ob->data)->dvert=NULL;
578                         }
579                 }
580                 break;
581         default:
582                 break;
583         }
584 }
585
586 bDeformGroup *get_named_vertexgroup(Object *ob, char *name)
587 {
588         /* return a pointer to the deform group with this name
589          * or return NULL otherwise.
590          */
591         bDeformGroup *curdef;
592
593         for (curdef = ob->defbase.first; curdef; curdef=curdef->next){
594                 if (!strcmp(curdef->name, name)){
595                         return curdef;
596                 }
597         }
598         return NULL;
599 }
600
601
602 void unique_vertexgroup_name (bDeformGroup *dg, Object *ob)
603 {
604         char            tempname[64];
605         int                     number;
606         char            *dot;
607         int exists = 0;
608         bDeformGroup *curdef;
609         
610         if (!ob)
611                 return;
612         /* See if we even need to do this */
613         for (curdef = ob->defbase.first; curdef; curdef=curdef->next){
614                 if (dg!=curdef){
615                         if (!strcmp(curdef->name, dg->name)){
616                                 exists = 1;
617                                 break;
618                         }
619                 }
620         }
621         
622         if (!exists)
623                 return;
624
625         /*      Strip off the suffix */
626         dot=strchr(dg->name, '.');
627         if (dot)
628                 *dot=0;
629         
630         for (number = 1; number <=999; number++){
631                 sprintf (tempname, "%s.%03d", dg->name, number);
632                 
633                 exists = 0;
634                 for (curdef=ob->defbase.first; curdef; curdef=curdef->next){
635                         if (dg!=curdef){
636                                 if (!strcmp (curdef->name, tempname)){
637                                         exists = 1;
638                                         break;
639                                 }
640                         }
641                 }
642                 if (!exists){
643                         strcpy (dg->name, tempname);
644                         return;
645                 }
646         }       
647 }