And more UI messages spell check.
[blender.git] / source / blender / blenkernel / intern / deform.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Reevan McKay
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/deform.c
29  *  \ingroup bke
30  */
31
32
33 #include <string.h>
34 #include <math.h>
35 #include <ctype.h>
36 #include <stdlib.h>
37
38 #include "MEM_guardedalloc.h"
39
40 #include "DNA_meshdata_types.h"
41 #include "DNA_object_types.h"
42
43 #include "BKE_deform.h"
44
45 #include "BLI_listbase.h"
46 #include "BLI_math.h"
47 #include "BLI_path_util.h"
48 #include "BLI_string.h"
49 #include "BLI_utildefines.h"
50
51
52 void defgroup_copy_list(ListBase *outbase, ListBase *inbase)
53 {
54         bDeformGroup *defgroup, *defgroupn;
55
56         outbase->first = outbase->last = NULL;
57
58         for (defgroup = inbase->first; defgroup; defgroup = defgroup->next) {
59                 defgroupn = defgroup_duplicate(defgroup);
60                 BLI_addtail(outbase, defgroupn);
61         }
62 }
63
64 bDeformGroup *defgroup_duplicate(bDeformGroup *ingroup)
65 {
66         bDeformGroup *outgroup;
67
68         if (!ingroup)
69                 return NULL;
70
71         outgroup = MEM_callocN(sizeof(bDeformGroup), "copy deformGroup");
72
73         /* For now, just copy everything over. */
74         memcpy(outgroup, ingroup, sizeof(bDeformGroup));
75
76         outgroup->next = outgroup->prev = NULL;
77
78         return outgroup;
79 }
80
81 /* copy & overwrite weights */
82 void defvert_copy(MDeformVert *dvert_dst, const MDeformVert *dvert_src)
83 {
84         if (dvert_dst->totweight == dvert_src->totweight) {
85                 if (dvert_src->totweight)
86                         memcpy(dvert_dst->dw, dvert_src->dw, dvert_src->totweight * sizeof(MDeformWeight));
87         }
88         else {
89                 if (dvert_dst->dw)
90                         MEM_freeN(dvert_dst->dw);
91
92                 if (dvert_src->totweight)
93                         dvert_dst->dw = MEM_dupallocN(dvert_src->dw);
94                 else
95                         dvert_dst->dw = NULL;
96
97                 dvert_dst->totweight = dvert_src->totweight;
98         }
99 }
100
101 /* copy an index from one dvert to another
102  * - do nothing if neither are set.
103  * - add destination weight if needed.
104  */
105 void defvert_copy_index(MDeformVert *dvert_dst, const MDeformVert *dvert_src, const int defgroup)
106 {
107         MDeformWeight *dw_src, *dw_dst;
108
109         dw_src = defvert_find_index(dvert_src, defgroup);
110
111         if (dw_src) {
112                 /* source is valid, verify destination */
113                 dw_dst = defvert_verify_index(dvert_dst, defgroup);
114                 dw_dst->weight = dw_src->weight;
115         }
116         else {
117                 /* source was NULL, assign zero, could also remove */
118                 dw_dst = defvert_find_index(dvert_dst, defgroup);
119
120                 if (dw_dst) {
121                         dw_dst->weight = 0.0f;
122                 }
123         }
124 }
125
126 /* only sync over matching weights, don't add or remove groups
127  * warning, loop within loop.
128  */
129 void defvert_sync(MDeformVert *dvert_dst, const MDeformVert *dvert_src, int use_verify)
130 {
131         if (dvert_src->totweight && dvert_dst->totweight) {
132                 int i;
133                 MDeformWeight *dw_src;
134                 for (i = 0, dw_src = dvert_src->dw; i < dvert_src->totweight; i++, dw_src++) {
135                         MDeformWeight *dw_dst;
136                         if (use_verify) dw_dst = defvert_verify_index(dvert_dst, dw_src->def_nr);
137                         else            dw_dst = defvert_find_index(dvert_dst, dw_src->def_nr);
138
139                         if (dw_dst) {
140                                 dw_dst->weight = dw_src->weight;
141                         }
142                 }
143         }
144 }
145
146 /* be sure all flip_map values are valid */
147 void defvert_sync_mapped(MDeformVert *dvert_dst, const MDeformVert *dvert_src,
148                          const int *flip_map, const int flip_map_len, const int use_verify)
149 {
150         if (dvert_src->totweight && dvert_dst->totweight) {
151                 int i;
152                 MDeformWeight *dw_src;
153                 for (i = 0, dw_src = dvert_src->dw; i < dvert_src->totweight; i++, dw_src++) {
154                         if (dw_src->def_nr < flip_map_len) {
155                                 MDeformWeight *dw_dst;
156                                 if (use_verify) dw_dst = defvert_verify_index(dvert_dst, flip_map[dw_src->def_nr]);
157                                 else            dw_dst = defvert_find_index(dvert_dst, flip_map[dw_src->def_nr]);
158
159                                 if (dw_dst) {
160                                         dw_dst->weight = dw_src->weight;
161                                 }
162                         }
163                 }
164         }
165 }
166
167 /* be sure all flip_map values are valid */
168 void defvert_remap(MDeformVert *dvert, int *map, const int map_len)
169 {
170         MDeformWeight *dw = dvert->dw;
171         unsigned int i;
172         for (i = dvert->totweight; i != 0; i--, dw++) {
173                 if (dw->def_nr < map_len) {
174                         dw->def_nr = map[dw->def_nr];
175
176                         /* just in case */
177                         BLI_assert(dw->def_nr >= 0);
178                 }
179         }
180 }
181
182 void defvert_normalize(MDeformVert *dvert)
183 {
184         if (dvert->totweight <= 0) {
185                 /* nothing */
186         }
187         else if (dvert->totweight == 1) {
188                 dvert->dw[0].weight = 1.0f;
189         }
190         else {
191                 MDeformWeight *dw;
192                 unsigned int i;
193                 float tot_weight = 0.0f;
194
195                 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
196                         tot_weight += dw->weight;
197                 }
198
199                 if (tot_weight > 0.0f) {
200                         float scalar = 1.0f / tot_weight;
201                         for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
202                                 dw->weight *= scalar;
203
204                                 /* in case of division errors with very low weights */
205                                 CLAMP(dw->weight, 0.0f, 1.0f);
206                         }
207                 }
208         }
209 }
210
211 void defvert_normalize_lock_single(MDeformVert *dvert, const int def_nr_lock)
212 {
213         if (dvert->totweight <= 0) {
214                 /* nothing */
215         }
216         else if (dvert->totweight == 1) {
217                 if (def_nr_lock != 0) {
218                         dvert->dw[0].weight = 1.0f;
219                 }
220         }
221         else {
222                 MDeformWeight *dw_lock = NULL;
223                 MDeformWeight *dw;
224                 unsigned int i;
225                 float tot_weight = 0.0f;
226                 float lock_iweight = 1.0f;
227
228                 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
229                         if (dw->def_nr != def_nr_lock) {
230                                 tot_weight += dw->weight;
231                         }
232                         else {
233                                 dw_lock = dw;
234                                 lock_iweight = (1.0f - dw_lock->weight);
235                                 CLAMP(lock_iweight, 0.0f, 1.0f);
236                         }
237                 }
238
239                 if (tot_weight > 0.0f) {
240                         /* paranoid, should be 1.0 but in case of float error clamp anyway */
241
242                         float scalar = (1.0f / tot_weight) * lock_iweight;
243                         for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
244                                 if (dw != dw_lock) {
245                                         dw->weight *= scalar;
246
247                                         /* in case of division errors with very low weights */
248                                         CLAMP(dw->weight, 0.0f, 1.0f);
249                                 }
250                         }
251                 }
252         }
253 }
254
255 void defvert_normalize_lock_map(MDeformVert *dvert, const char *lock_flags, const int defbase_tot)
256 {
257         if (dvert->totweight <= 0) {
258                 /* nothing */
259         }
260         else if (dvert->totweight == 1) {
261                 if (LIKELY(defbase_tot >= 1) && lock_flags[0]) {
262                         dvert->dw[0].weight = 1.0f;
263                 }
264         }
265         else {
266                 MDeformWeight *dw;
267                 unsigned int i;
268                 float tot_weight = 0.0f;
269                 float lock_iweight = 0.0f;
270
271                 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
272                         if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) {
273                                 tot_weight += dw->weight;
274                         }
275                         else {
276                                 /* invert after */
277                                 lock_iweight += dw->weight;
278                         }
279                 }
280
281                 lock_iweight = maxf(0.0f, 1.0f - lock_iweight);
282
283                 if (tot_weight > 0.0f) {
284                         /* paranoid, should be 1.0 but in case of float error clamp anyway */
285
286                         float scalar = (1.0f / tot_weight) * lock_iweight;
287                         for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
288                                 if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) {
289                                         dw->weight *= scalar;
290
291                                         /* in case of division errors with very low weights */
292                                         CLAMP(dw->weight, 0.0f, 1.0f);
293                                 }
294                         }
295                 }
296         }
297 }
298
299 void defvert_flip(MDeformVert *dvert, const int *flip_map, const int flip_map_len)
300 {
301         MDeformWeight *dw;
302         int i;
303
304         for (dw = dvert->dw, i = 0; i < dvert->totweight; dw++, i++) {
305                 if (dw->def_nr < flip_map_len) {
306                         if (flip_map[dw->def_nr] >= 0) {
307                                 dw->def_nr = flip_map[dw->def_nr];
308                         }
309                 }
310         }
311 }
312
313 void defvert_flip_merged(MDeformVert *dvert, const int *flip_map, const int flip_map_len)
314 {
315         MDeformWeight *dw, *dw_cpy;
316         float weight;
317         int i, totweight = dvert->totweight;
318
319         /* copy weights */
320         for (dw = dvert->dw, i = 0; i < totweight; dw++, i++) {
321                 if (dw->def_nr < flip_map_len) {
322                         if (flip_map[dw->def_nr] >= 0) {
323                                 /* error checkers complain of this but we'll never get NULL return */
324                                 dw_cpy = defvert_verify_index(dvert, flip_map[dw->def_nr]);
325                                 dw = &dvert->dw[i]; /* in case array got realloced */
326
327                                 /* distribute weights: if only one of the vertex groups was
328                                  * assigned this will halve the weights, otherwise it gets
329                                  * evened out. this keeps it proportional to other groups */
330                                 weight = 0.5f * (dw_cpy->weight + dw->weight);
331                                 dw_cpy->weight = weight;
332                                 dw->weight = weight;
333                         }
334                 }
335         }
336 }
337
338 bDeformGroup *defgroup_find_name(Object *ob, const char *name)
339 {
340         /* return a pointer to the deform group with this name
341          * or return NULL otherwise.
342          */
343         bDeformGroup *curdef;
344
345         for (curdef = ob->defbase.first; curdef; curdef = curdef->next) {
346                 if (!strcmp(curdef->name, name)) {
347                         return curdef;
348                 }
349         }
350         return NULL;
351 }
352
353 int defgroup_name_index(Object *ob, const char *name)
354 {
355         /* Return the location of the named deform group within the list of
356          * deform groups. This function is a combination of BLI_findlink and
357          * defgroup_find_name. The other two could be called instead, but that
358          * require looping over the vertexgroups twice.
359          */
360         bDeformGroup *curdef;
361         int def_nr;
362
363         if (name && name[0] != '\0') {
364                 for (curdef = ob->defbase.first, def_nr = 0; curdef; curdef = curdef->next, def_nr++) {
365                         if (!strcmp(curdef->name, name))
366                                 return def_nr;
367                 }
368         }
369
370         return -1;
371 }
372
373 /* note, must be freed */
374 int *defgroup_flip_map(Object *ob, int *flip_map_len, int use_default)
375 {
376         int defbase_tot = *flip_map_len = BLI_countlist(&ob->defbase);
377
378         if (defbase_tot == 0) {
379                 return NULL;
380         }
381         else {
382                 bDeformGroup *dg;
383                 char name[sizeof(dg->name)];
384                 int i, flip_num, *map = MEM_mallocN(defbase_tot * sizeof(int), __func__);
385
386                 for (i = 0; i < defbase_tot; i++) {
387                         map[i] = -1;
388                 }
389
390                 for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
391                         if (map[i] == -1) { /* may be calculated previously */
392
393                                 /* in case no valid value is found, use this */
394                                 if (use_default)
395                                         map[i] = i;
396
397                                 flip_side_name(name, dg->name, FALSE);
398                                 if (strcmp(name, dg->name)) {
399                                         flip_num = defgroup_name_index(ob, name);
400                                         if (flip_num >= 0) {
401                                                 map[i] = flip_num;
402                                                 map[flip_num] = i; /* save an extra lookup */
403                                         }
404                                 }
405                         }
406                 }
407                 return map;
408         }
409 }
410
411 /* note, must be freed */
412 int *defgroup_flip_map_single(Object *ob, int *flip_map_len, int use_default, int defgroup)
413 {
414         int defbase_tot = *flip_map_len = BLI_countlist(&ob->defbase);
415
416         if (defbase_tot == 0) {
417                 return NULL;
418         }
419         else {
420                 bDeformGroup *dg;
421                 char name[sizeof(dg->name)];
422                 int i, flip_num, *map = MEM_mallocN(defbase_tot * sizeof(int), __func__);
423
424                 for (i = 0; i < defbase_tot; i++) {
425                         map[i] = use_default ? i : -1;
426                 }
427
428                 dg = BLI_findlink(&ob->defbase, defgroup);
429
430                 flip_side_name(name, dg->name, FALSE);
431                 if (strcmp(name, dg->name)) {
432                         flip_num = defgroup_name_index(ob, name);
433
434                         if (flip_num >= 0) {
435                                 map[defgroup] = flip_num;
436                                 map[flip_num] = defgroup;
437                         }
438                 }
439
440                 return map;
441         }
442 }
443
444 int defgroup_flip_index(Object *ob, int index, int use_default)
445 {
446         bDeformGroup *dg = BLI_findlink(&ob->defbase, index);
447         int flip_index = -1;
448
449         if (dg) {
450                 char name[sizeof(dg->name)];
451                 flip_side_name(name, dg->name, 0);
452
453                 if (strcmp(name, dg->name))
454                         flip_index = defgroup_name_index(ob, name);
455         }
456
457         return (flip_index == -1 && use_default) ? index : flip_index;
458 }
459
460 static int defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob)
461 {
462         bDeformGroup *curdef;
463
464         for (curdef = ob->defbase.first; curdef; curdef = curdef->next) {
465                 if (dg != curdef) {
466                         if (!strcmp(curdef->name, name)) {
467                                 return 1;
468                         }
469                 }
470         }
471
472         return 0;
473 }
474
475 static int defgroup_unique_check(void *arg, const char *name)
476 {
477         struct {Object *ob; void *dg; } *data = arg;
478         return defgroup_find_name_dupe(name, data->dg, data->ob);
479 }
480
481 void defgroup_unique_name(bDeformGroup *dg, Object *ob)
482 {
483         struct {Object *ob; void *dg; } data;
484         data.ob = ob;
485         data.dg = dg;
486
487         BLI_uniquename_cb(defgroup_unique_check, &data, "Group", '.', dg->name, sizeof(dg->name));
488 }
489
490 static int is_char_sep(const char c)
491 {
492         return ELEM4(c, '.', ' ', '-', '_');
493 }
494
495 /* based on BLI_split_dirfile() / os.path.splitext(), "a.b.c" -> ("a.b", ".c") */
496
497 void BKE_deform_split_suffix(const char string[MAX_VGROUP_NAME], char body[MAX_VGROUP_NAME], char suf[MAX_VGROUP_NAME])
498 {
499         size_t len = BLI_strnlen(string, MAX_VGROUP_NAME);
500         size_t i;
501
502         body[0] = suf[0] = '\0';
503
504         for (i = len - 1; i > 1; i--) {
505                 if (is_char_sep(string[i])) {
506                         BLI_strncpy(body, string, i + 1);
507                         BLI_strncpy(suf, string + i,  (len + 1) - i);
508                         return;
509                 }
510         }
511
512         BLI_strncpy(body, string, len);
513 }
514
515 /* "a.b.c" -> ("a.", "b.c") */
516 void BKE_deform_split_prefix(const char string[MAX_VGROUP_NAME], char pre[MAX_VGROUP_NAME], char body[MAX_VGROUP_NAME])
517 {
518         size_t len = BLI_strnlen(string, MAX_VGROUP_NAME);
519         size_t i;
520
521         body[0] = pre[0] = '\0';
522
523         for (i = 1; i < len; i++) {
524                 if (is_char_sep(string[i])) {
525                         i++;
526                         BLI_strncpy(pre, string, i + 1);
527                         BLI_strncpy(body, string + i, (len + 1) - i);
528                         return;
529                 }
530         }
531
532         BLI_strncpy(body, string, len);
533 }
534
535 /* finds the best possible flipped name. For renaming; check for unique names afterwards */
536 /* if strip_number: removes number extensions
537  * note: don't use sizeof() for 'name' or 'from_name' */
538 void flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_NAME], int strip_number)
539 {
540         int     len;
541         char    prefix[MAX_VGROUP_NAME]  = "";   /* The part before the facing */
542         char    suffix[MAX_VGROUP_NAME]  = "";   /* The part after the facing */
543         char    replace[MAX_VGROUP_NAME] = "";   /* The replacement string */
544         char    number[MAX_VGROUP_NAME]  = "";   /* The number extension string */
545         char    *index = NULL;
546
547         /* always copy the name, since this can be called with an uninitialized string */
548         BLI_strncpy(name, from_name, MAX_VGROUP_NAME);
549
550         len = BLI_strnlen(from_name, MAX_VGROUP_NAME);
551         if (len < 3) {
552                 /* we don't do names like .R or .L */
553                 return;
554         }
555
556         /* We first check the case with a .### extension, let's find the last period */
557         if (isdigit(name[len - 1])) {
558                 index = strrchr(name, '.'); // last occurrence
559                 if (index && isdigit(index[1])) { // doesnt handle case bone.1abc2 correct..., whatever!
560                         if (strip_number == 0) {
561                                 BLI_strncpy(number, index, sizeof(number));
562                         }
563                         *index = 0;
564                         len = BLI_strnlen(name, MAX_VGROUP_NAME);
565                 }
566         }
567
568         BLI_strncpy(prefix, name, sizeof(prefix));
569
570         /* first case; separator . - _ with extensions r R l L  */
571         if (is_char_sep(name[len - 2])) {
572                 switch (name[len - 1]) {
573                         case 'l':
574                                 prefix[len - 1] = 0;
575                                 strcpy(replace, "r");
576                                 break;
577                         case 'r':
578                                 prefix[len - 1] = 0;
579                                 strcpy(replace, "l");
580                                 break;
581                         case 'L':
582                                 prefix[len - 1] = 0;
583                                 strcpy(replace, "R");
584                                 break;
585                         case 'R':
586                                 prefix[len - 1] = 0;
587                                 strcpy(replace, "L");
588                                 break;
589                 }
590         }
591         /* case; beginning with r R l L, with separator after it */
592         else if (is_char_sep(name[1])) {
593                 switch (name[0]) {
594                         case 'l':
595                                 strcpy(replace, "r");
596                                 BLI_strncpy(suffix, name + 1, sizeof(suffix));
597                                 prefix[0] = 0;
598                                 break;
599                         case 'r':
600                                 strcpy(replace, "l");
601                                 BLI_strncpy(suffix, name + 1, sizeof(suffix));
602                                 prefix[0] = 0;
603                                 break;
604                         case 'L':
605                                 strcpy(replace, "R");
606                                 BLI_strncpy(suffix, name + 1, sizeof(suffix));
607                                 prefix[0] = 0;
608                                 break;
609                         case 'R':
610                                 strcpy(replace, "L");
611                                 BLI_strncpy(suffix, name + 1, sizeof(suffix));
612                                 prefix[0] = 0;
613                                 break;
614                 }
615         }
616         else if (len > 5) {
617                 /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
618                 index = BLI_strcasestr(prefix, "right");
619                 if (index == prefix || index == prefix + len - 5) {
620                         if (index[0] == 'r')
621                                 strcpy(replace, "left");
622                         else {
623                                 if (index[1] == 'I')
624                                         strcpy(replace, "LEFT");
625                                 else
626                                         strcpy(replace, "Left");
627                         }
628                         *index = 0;
629                         BLI_strncpy(suffix, index + 5, sizeof(suffix));
630                 }
631                 else {
632                         index = BLI_strcasestr(prefix, "left");
633                         if (index == prefix || index == prefix + len - 4) {
634                                 if (index[0] == 'l')
635                                         strcpy(replace, "right");
636                                 else {
637                                         if (index[1] == 'E')
638                                                 strcpy(replace, "RIGHT");
639                                         else
640                                                 strcpy(replace, "Right");
641                                 }
642                                 *index = 0;
643                                 BLI_strncpy(suffix, index + 4, sizeof(suffix));
644                         }
645                 }
646         }
647
648         BLI_snprintf(name, MAX_VGROUP_NAME, "%s%s%s%s", prefix, replace, suffix, number);
649 }
650
651 float defvert_find_weight(const struct MDeformVert *dvert, const int defgroup)
652 {
653         MDeformWeight *dw = defvert_find_index(dvert, defgroup);
654         return dw ? dw->weight : 0.0f;
655 }
656
657 /* take care with this the rationale is:
658  * - if the object has no vertex group. act like vertex group isn't set and return 1.0,
659  * - if the vertex group exists but the 'defgroup' isn't found on this vertex, _still_ return 0.0
660  *
661  * This is a bit confusing, just saves some checks from the caller.
662  */
663 float defvert_array_find_weight_safe(const struct MDeformVert *dvert, const int index, const int defgroup)
664 {
665         if (defgroup == -1 || dvert == NULL)
666                 return 1.0f;
667
668         return defvert_find_weight(dvert + index, defgroup);
669 }
670
671
672 MDeformWeight *defvert_find_index(const MDeformVert *dvert, const int defgroup)
673 {
674         if (dvert && defgroup >= 0) {
675                 MDeformWeight *dw = dvert->dw;
676                 unsigned int i;
677
678                 for (i = dvert->totweight; i != 0; i--, dw++) {
679                         if (dw->def_nr == defgroup) {
680                                 return dw;
681                         }
682                 }
683         }
684
685         return NULL;
686 }
687
688 /* Ensures that mv has a deform weight entry for the specified defweight group */
689 /* Note this function is mirrored in editmesh_tools.c, for use for editvertices */
690 MDeformWeight *defvert_verify_index(MDeformVert *dvert, const int defgroup)
691 {
692         MDeformWeight *dw_new;
693
694         /* do this check always, this function is used to check for it */
695         if (!dvert || defgroup < 0)
696                 return NULL;
697
698         dw_new = defvert_find_index(dvert, defgroup);
699         if (dw_new)
700                 return dw_new;
701
702         dw_new = MEM_callocN(sizeof(MDeformWeight) * (dvert->totweight + 1), "deformWeight");
703         if (dvert->dw) {
704                 memcpy(dw_new, dvert->dw, sizeof(MDeformWeight) * dvert->totweight);
705                 MEM_freeN(dvert->dw);
706         }
707         dvert->dw = dw_new;
708         dw_new += dvert->totweight;
709         dw_new->weight = 0.0f;
710         dw_new->def_nr = defgroup;
711         /* Group index */
712
713         dvert->totweight++;
714
715         return dw_new;
716 }
717
718 /* TODO. merge with code above! */
719
720 /* Adds the given vertex to the specified vertex group, with given weight.
721  * warning, this does NOT check for existing, assume caller already knows its not there */
722 void defvert_add_index_notest(MDeformVert *dvert, int defgroup, const float weight)
723 {
724         MDeformWeight *dw_new;
725
726         /* do this check always, this function is used to check for it */
727         if (!dvert || defgroup < 0)
728                 return;
729
730         dw_new = MEM_callocN(sizeof(MDeformWeight) * (dvert->totweight + 1), "defvert_add_to group, new deformWeight");
731         if (dvert->dw) {
732                 memcpy(dw_new, dvert->dw, sizeof(MDeformWeight) * dvert->totweight);
733                 MEM_freeN(dvert->dw);
734         }
735         dvert->dw = dw_new;
736         dw_new += dvert->totweight;
737         dw_new->weight = weight;
738         dw_new->def_nr = defgroup;
739         dvert->totweight++;
740 }
741
742
743 /* Removes the given vertex from the vertex group.
744  * WARNING: This function frees the given MDeformWeight, do not use it afterward! */
745 void defvert_remove_group(MDeformVert *dvert, MDeformWeight *dw)
746 {
747         if (dvert && dw) {
748                 MDeformWeight *dw_new;
749                 int i = dw - dvert->dw;
750
751                 /* Security check! */
752                 if (i < 0 || i >= dvert->totweight) {
753                         return;
754                 }
755
756                 dvert->totweight--;
757                 /* If there are still other deform weights attached to this vert then remove
758                  * this deform weight, and reshuffle the others.
759                  */
760                 if (dvert->totweight) {
761                         dw_new = MEM_mallocN(sizeof(MDeformWeight) * (dvert->totweight), __func__);
762                         if (dvert->dw) {
763 #if 1           /* since we don't care about order, swap this with the last, save a memcpy */
764                                 if (i != dvert->totweight) {
765                                         dvert->dw[i] = dvert->dw[dvert->totweight];
766                                 }
767                                 memcpy(dw_new, dvert->dw, sizeof(MDeformWeight) * dvert->totweight);
768 #else
769                                 memcpy(dw_new, dvert->dw, sizeof(MDeformWeight) * i);
770                                 memcpy(dw_new + i, dvert->dw + i + 1, sizeof(MDeformWeight) * (dvert->totweight - i));
771 #endif
772                                 MEM_freeN(dvert->dw);
773                         }
774                         dvert->dw = dw_new;
775                 }
776                 else {
777                         /* If there are no other deform weights left then just remove this one. */
778                         MEM_freeN(dvert->dw);
779                         dvert->dw = NULL;
780                 }
781         }
782 }
783
784 void defvert_clear(MDeformVert *dvert)
785 {
786         if (dvert->dw) {
787                 MEM_freeN(dvert->dw);
788                 dvert->dw = NULL;
789         }
790
791         dvert->totweight = 0;
792 }