Initial revision
[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 "BLI_blenlib.h"
39 #include "BLI_editVert.h"
40
41 #include "DNA_mesh_types.h"
42 #include "DNA_object_types.h"
43
44 #include "BKE_global.h"
45 #include "BKE_deform.h"
46 #include "BKE_mesh.h"
47
48 #include "BIF_editdeform.h"
49 #include "BIF_toolbox.h"
50
51 void sel_verts_defgroup (int select)
52 {
53         EditVert                *eve;
54         Object                  *ob;
55         int                             i;
56
57         ob=G.obedit;
58
59         if (!ob)
60                 return;
61
62         switch (ob->type){
63         case OB_MESH:
64                 for (eve=G.edve.first; eve; eve=eve->next){
65                         if (eve->totweight){
66                                 for (i=0; i<eve->totweight; i++){
67                                         if (eve->dw[i].def_nr == (ob->actdef-1)){
68                                                 if (select) eve->f |= 1;
69                                                 else eve->f &= ~1;
70                                                 break;
71                                         }
72                                 }
73                         }
74                 }
75                 break;
76         default:
77                 break;
78         }
79
80 }
81
82 MDeformWeight *verify_defweight (MDeformVert *dv, int defgroup)
83 /* Ensures that mv has a deform weight entry for
84 the specified defweight group */
85 {
86         int     i;
87         MDeformWeight *newdw;
88
89         if (!dv)
90                 return NULL;
91
92         for (i=0; i<dv->totweight; i++){
93                 if (dv->dw[i].def_nr == defgroup)
94                         return dv->dw+i;
95         }
96
97         newdw = MEM_callocN (sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight");
98         if (dv->dw){
99                 memcpy (newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
100                 MEM_freeN (dv->dw);
101         }
102         dv->dw=newdw;
103         
104         dv->dw[dv->totweight].weight=0;
105         dv->dw[dv->totweight].def_nr=defgroup;
106         /* Group index */
107         
108         dv->totweight++;
109
110         return dv->dw+(dv->totweight-1);
111 }
112
113 void add_defgroup (Object *ob)
114 {
115         bDeformGroup    *defgroup;
116
117         if (!ob)
118                 return;
119
120         defgroup = MEM_callocN (sizeof(bDeformGroup), "deformGroup");
121         strcpy (defgroup->name, "Group");
122
123         BLI_addtail(&ob->defbase, defgroup);
124         unique_vertexgroup_name(defgroup, ob);
125
126         ob->actdef = BLI_countlist(&ob->defbase);
127 }
128
129 void del_defgroup (Object *ob)
130 {
131         bDeformGroup    *defgroup;
132         EditVert                *eve;
133         int                             i;
134
135
136         if (!ob)
137                 return;
138
139         if (!ob->actdef)
140                 return;
141
142         defgroup = BLI_findlink(&ob->defbase, ob->actdef-1);
143         if (!defgroup)
144                 return;
145
146         /* Make sure that no verts are using this group */
147         remove_verts_defgroup(1);
148
149         /* Make sure that any verts with higher indices are adjusted accordingly */
150         for (eve=G.edve.first; eve; eve=eve->next){
151                 for (i=0; i<eve->totweight; i++){
152                         if (eve->dw[i].def_nr > (ob->actdef-1))
153                                 eve->dw[i].def_nr--;
154                 }
155         }
156
157         /* Update the active material index if necessary */
158         if (ob->actdef==BLI_countlist(&ob->defbase))
159                 ob->actdef--;
160
161         /* Remove the group */
162         BLI_freelinkN (&ob->defbase, defgroup);
163 }
164
165 void assign_verts_defgroup (void)
166 /* Only available in editmode */
167 {
168         Object *ob;
169         EditVert *eve;
170         bDeformGroup    *dg, *eg;
171         extern float editbutvweight;    /* buttons.c */
172         int     i, done;
173         MDeformWeight *newdw;
174
175         ob=G.obedit;
176
177         if (!ob)
178                 return;
179
180         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
181         if (!dg){
182                 error ("No vertex group active");
183                 return;
184         }
185
186         switch (ob->type){
187         case OB_MESH:
188                 /* Go through the list of editverts and assign them */
189                 for (eve=G.edve.first; eve; eve=eve->next){
190                         if (eve->f & 1){
191                                 done=0;
192                                 /* See if this vert already has a reference to this group */
193                                 /*              If so: Change its weight */
194                                 done=0;
195                                 for (i=0; i<eve->totweight; i++){
196                                         eg = BLI_findlink (&ob->defbase, eve->dw[i].def_nr);
197                                         /* Find the actual group */
198                                         if (eg==dg){
199                                                 eve->dw[i].weight=editbutvweight;
200                                                 done=1;
201                                                 break;
202                                         }
203                                 }
204                                 /*              If not: Add the group and set its weight */
205                                 if (!done){
206                                         newdw = MEM_callocN (sizeof(MDeformWeight)*(eve->totweight+1), "deformWeight");
207                                         if (eve->dw){
208                                                 memcpy (newdw, eve->dw, sizeof(MDeformWeight)*eve->totweight);
209                                                 MEM_freeN (eve->dw);
210                                         }
211                                         eve->dw=newdw;
212
213                                         eve->dw[eve->totweight].weight=editbutvweight;
214                                         eve->dw[eve->totweight].def_nr=ob->actdef-1;
215
216                                         eve->totweight++;
217
218                                 }
219                         }
220                 }
221                 break;
222         default:
223                 printf ("Assigning deformation groups to unknown object type: Warn <reevan@blender.nl>\n");
224                 break;
225         }
226
227 }
228
229 void remove_verts_defgroup (int allverts)
230 /* Only available in editmode */
231 {
232         Object *ob;
233         EditVert *eve;
234         MDeformWeight *newdw;
235         bDeformGroup    *dg, *eg;
236         int     i;
237
238         ob=G.obedit;
239
240         if (!ob)
241                 return;
242
243         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
244         if (!dg){
245                 error ("No vertex group active");
246                 return;
247         }
248
249         switch (ob->type){
250         case OB_MESH:
251                 for (eve=G.edve.first; eve; eve=eve->next){
252                         if (eve->dw && ((eve->f & 1) || allverts)){
253                                 for (i=0; i<eve->totweight; i++){
254                                         /* Find group */
255                                         eg = BLI_findlink (&ob->defbase, eve->dw[i].def_nr);
256                                         if (eg == dg){
257                                                 eve->totweight--;
258                                                 if (eve->totweight){
259                                                         newdw = MEM_mallocN (sizeof(MDeformWeight)*(eve->totweight), "deformWeight");
260                                                         
261                                                         if (eve->dw){
262                                                                 memcpy (newdw, eve->dw, sizeof(MDeformWeight)*i);
263                                                                 memcpy (newdw+i, eve->dw+i+1, sizeof(MDeformWeight)*(eve->totweight-i));
264                                                                 MEM_freeN (eve->dw);
265                                                         }
266                                                         eve->dw=newdw;
267                                                 }
268                                                 else{
269                                                         MEM_freeN (eve->dw);
270                                                         eve->dw=NULL;
271                                                 }
272                                         }
273                                 }
274                         }
275                 }
276                 break;
277         default:
278                 printf ("Removing deformation groups from unknown object type: Warn <reevan@blender.nl>\n");
279                 break;
280         }
281 }
282
283 void verify_defgroups (Object *ob)
284 {
285                 /* Ensure the defbase & the dverts match */
286         switch (ob->type){
287         case OB_MESH:
288                 if (!ob->defbase.first){
289                         if (((Mesh*)ob->data)->dvert){
290                                 free_dverts(((Mesh*)ob->data)->dvert, ((Mesh*)ob->data)->totvert);
291                                 ((Mesh*)ob->data)->dvert=NULL;
292                         }
293                 }
294                 break;
295         default:
296                 break;
297         }
298 }
299
300 void unique_vertexgroup_name (bDeformGroup *dg, Object *ob)
301 {
302         char            tempname[64];
303         int                     number;
304         char            *dot;
305         int exists = 0;
306         bDeformGroup *curdef;
307         
308         if (!ob)
309                 return;
310         /* See if we even need to do this */
311         for (curdef = ob->defbase.first; curdef; curdef=curdef->next){
312                 if (dg!=curdef){
313                         if (!strcmp(curdef->name, dg->name)){
314                                 exists = 1;
315                                 break;
316                         }
317                 }
318         }
319         
320         if (!exists)
321                 return;
322
323         /*      Strip off the suffix */
324         dot=strchr(dg->name, '.');
325         if (dot)
326                 *dot=0;
327         
328         for (number = 1; number <=999; number++){
329                 sprintf (tempname, "%s.%03d", dg->name, number);
330                 
331                 exists = 0;
332                 for (curdef=ob->defbase.first; curdef; curdef=curdef->next){
333                         if (dg!=curdef){
334                                 if (!strcmp (curdef->name, tempname)){
335                                         exists = 1;
336                                         break;
337                                 }
338                         }
339                 }
340                 if (!exists){
341                         strcpy (dg->name, tempname);
342                         return;
343                 }
344         }       
345 }