Blender  V2.59
customdata.c
Go to the documentation of this file.
00001 /*
00002 * $Id: customdata.c 38866 2011-07-31 02:24:06Z nicholasbishop $
00003 *
00004 * ***** BEGIN GPL LICENSE BLOCK *****
00005 *
00006 * This program is free software; you can redistribute it and/or
00007 * modify it under the terms of the GNU General Public License
00008 * as published by the Free Software Foundation; either version 2
00009 * of the License, or (at your option) any later version.
00010 *
00011 * This program is distributed in the hope that it will be useful,
00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 * GNU General Public License for more details.
00015 *
00016 * You should have received a copy of the GNU General Public License
00017 * along with this program; if not, write to the Free Software  Foundation,
00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019 *
00020 * The Original Code is Copyright (C) 2006 Blender Foundation.
00021 * All rights reserved.
00022 *
00023 * The Original Code is: all of this file.
00024 *
00025 * Contributor(s): Ben Batt <benbatt@gmail.com>
00026 *
00027 * ***** END GPL LICENSE BLOCK *****
00028 *
00029 * Implementation of CustomData.
00030 *
00031 * BKE_customdata.h contains the function prototypes for this file.
00032 *
00033 */
00034 
00040 #include <math.h>
00041 #include <string.h>
00042 #include <assert.h>
00043 
00044 #include "MEM_guardedalloc.h"
00045 
00046 #include "DNA_meshdata_types.h"
00047 #include "DNA_ID.h"
00048 
00049 #include "BLI_blenlib.h"
00050 #include "BLI_path_util.h"
00051 #include "BLI_linklist.h"
00052 #include "BLI_math.h"
00053 #include "BLI_mempool.h"
00054 #include "BLI_utildefines.h"
00055 
00056 #include "BKE_customdata.h"
00057 #include "BKE_customdata_file.h"
00058 #include "BKE_global.h"
00059 #include "BKE_main.h"
00060 #include "BKE_utildefines.h"
00061 #include "BKE_multires.h"
00062 
00063 /* number of layers to add when growing a CustomData object */
00064 #define CUSTOMDATA_GROW 5
00065 
00066 /********************* Layer type information **********************/
00067 typedef struct LayerTypeInfo {
00068         int size;          /* the memory size of one element of this layer's data */
00069         const char *structname;  /* name of the struct used, for file writing */
00070         int structnum;     /* number of structs per element, for file writing */
00071         const char *defaultname; /* default layer name */
00072 
00073         /* a function to copy count elements of this layer's data
00074          * (deep copy if appropriate)
00075          * if NULL, memcpy is used
00076          */
00077         void (*copy)(const void *source, void *dest, int count);
00078 
00079         /* a function to free any dynamically allocated components of this
00080          * layer's data (note the data pointer itself should not be freed)
00081          * size should be the size of one element of this layer's data (e.g.
00082          * LayerTypeInfo.size)
00083          */
00084         void (*free)(void *data, int count, int size);
00085 
00086         /* a function to interpolate between count source elements of this
00087          * layer's data and store the result in dest
00088          * if weights == NULL or sub_weights == NULL, they should default to 1
00089          *
00090          * weights gives the weight for each element in sources
00091          * sub_weights gives the sub-element weights for each element in sources
00092          *    (there should be (sub element count)^2 weights per element)
00093          * count gives the number of elements in sources
00094          */
00095         void (*interp)(void **sources, float *weights, float *sub_weights,
00096                                    int count, void *dest);
00097 
00098         /* a function to swap the data in corners of the element */
00099         void (*swap)(void *data, const int *corner_indices);
00100 
00101         /* a function to set a layer's data to default values. if NULL, the
00102            default is assumed to be all zeros */
00103         void (*set_default)(void *data, int count);
00104 
00105         /* a function to read data from a cdf file */
00106         int (*read)(CDataFile *cdf, void *data, int count);
00107 
00108         /* a function to write data to a cdf file */
00109         int (*write)(CDataFile *cdf, void *data, int count);
00110 
00111         /* a function to determine file size */
00112         size_t (*filesize)(CDataFile *cdf, void *data, int count);
00113 
00114         /* a function to validate layer contents depending on
00115          * sub-elements count
00116          */
00117         void (*validate)(void *source, int sub_elements);
00118 } LayerTypeInfo;
00119 
00120 static void layerCopy_mdeformvert(const void *source, void *dest,
00121                                                                   int count)
00122 {
00123         int i, size = sizeof(MDeformVert);
00124 
00125         memcpy(dest, source, count * size);
00126 
00127         for(i = 0; i < count; ++i) {
00128                 MDeformVert *dvert = (MDeformVert *)((char *)dest + i * size);
00129 
00130                 if(dvert->totweight) {
00131                         MDeformWeight *dw = MEM_callocN(dvert->totweight * sizeof(*dw),
00132                                                                                         "layerCopy_mdeformvert dw");
00133 
00134                         memcpy(dw, dvert->dw, dvert->totweight * sizeof(*dw));
00135                         dvert->dw = dw;
00136                 }
00137                 else
00138                         dvert->dw = NULL;
00139         }
00140 }
00141 
00142 static void layerFree_mdeformvert(void *data, int count, int size)
00143 {
00144         int i;
00145 
00146         for(i = 0; i < count; ++i) {
00147                 MDeformVert *dvert = (MDeformVert *)((char *)data + i * size);
00148 
00149                 if(dvert->dw) {
00150                         MEM_freeN(dvert->dw);
00151                         dvert->dw = NULL;
00152                         dvert->totweight = 0;
00153                 }
00154         }
00155 }
00156 
00157 static void linklist_free_simple(void *link)
00158 {
00159         MEM_freeN(link);
00160 }
00161 
00162 static void layerInterp_mdeformvert(void **sources, float *weights,
00163                                                                         float *UNUSED(sub_weights), int count, void *dest)
00164 {
00165         MDeformVert *dvert = dest;
00166         LinkNode *dest_dw = NULL; /* a list of lists of MDeformWeight pointers */
00167         LinkNode *node;
00168         int i, j, totweight;
00169 
00170         if(count <= 0) return;
00171 
00172         /* build a list of unique def_nrs for dest */
00173         totweight = 0;
00174         for(i = 0; i < count; ++i) {
00175                 MDeformVert *source = sources[i];
00176                 float interp_weight = weights ? weights[i] : 1.0f;
00177 
00178                 for(j = 0; j < source->totweight; ++j) {
00179                         MDeformWeight *dw = &source->dw[j];
00180 
00181                         for(node = dest_dw; node; node = node->next) {
00182                                 MDeformWeight *tmp_dw = (MDeformWeight *)node->link;
00183 
00184                                 if(tmp_dw->def_nr == dw->def_nr) {
00185                                         tmp_dw->weight += dw->weight * interp_weight;
00186                                         break;
00187                                 }
00188                         }
00189 
00190                         /* if this def_nr is not in the list, add it */
00191                         if(!node) {
00192                                 MDeformWeight *tmp_dw = MEM_callocN(sizeof(*tmp_dw),
00193                                                                                         "layerInterp_mdeformvert tmp_dw");
00194                                 tmp_dw->def_nr = dw->def_nr;
00195                                 tmp_dw->weight = dw->weight * interp_weight;
00196                                 BLI_linklist_prepend(&dest_dw, tmp_dw);
00197                                 totweight++;
00198                         }
00199                 }
00200         }
00201 
00202         /* now we know how many unique deform weights there are, so realloc */
00203         if(dvert->dw) MEM_freeN(dvert->dw);
00204 
00205         if(totweight) {
00206                 dvert->dw = MEM_callocN(sizeof(*dvert->dw) * totweight,
00207                                                                 "layerInterp_mdeformvert dvert->dw");
00208                 dvert->totweight = totweight;
00209 
00210                 for(i = 0, node = dest_dw; node; node = node->next, ++i)
00211                         dvert->dw[i] = *((MDeformWeight *)node->link);
00212         }
00213         else
00214                 memset(dvert, 0, sizeof(*dvert));
00215 
00216         BLI_linklist_free(dest_dw, linklist_free_simple);
00217 }
00218 
00219 
00220 static void layerInterp_msticky(void **sources, float *weights,
00221                                                                 float *UNUSED(sub_weights), int count, void *dest)
00222 {
00223         float co[2], w;
00224         MSticky *mst;
00225         int i;
00226 
00227         co[0] = co[1] = 0.0f;
00228         for(i = 0; i < count; i++) {
00229                 w = weights ? weights[i] : 1.0f;
00230                 mst = (MSticky*)sources[i];
00231 
00232                 co[0] += w*mst->co[0];
00233                 co[1] += w*mst->co[1];
00234         }
00235 
00236         mst = (MSticky*)dest;
00237         mst->co[0] = co[0];
00238         mst->co[1] = co[1];
00239 }
00240 
00241 
00242 static void layerCopy_tface(const void *source, void *dest, int count)
00243 {
00244         const MTFace *source_tf = (const MTFace*)source;
00245         MTFace *dest_tf = (MTFace*)dest;
00246         int i;
00247 
00248         for(i = 0; i < count; ++i)
00249                 dest_tf[i] = source_tf[i];
00250 }
00251 
00252 static void layerInterp_tface(void **sources, float *weights,
00253                                                           float *sub_weights, int count, void *dest)
00254 {
00255         MTFace *tf = dest;
00256         int i, j, k;
00257         float uv[4][2];
00258         float *sub_weight;
00259 
00260         if(count <= 0) return;
00261 
00262         memset(uv, 0, sizeof(uv));
00263 
00264         sub_weight = sub_weights;
00265         for(i = 0; i < count; ++i) {
00266                 float weight = weights ? weights[i] : 1;
00267                 MTFace *src = sources[i];
00268 
00269                 for(j = 0; j < 4; ++j) {
00270                         if(sub_weights) {
00271                                 for(k = 0; k < 4; ++k, ++sub_weight) {
00272                                         float w = (*sub_weight) * weight;
00273                                         float *tmp_uv = src->uv[k];
00274 
00275                                         uv[j][0] += tmp_uv[0] * w;
00276                                         uv[j][1] += tmp_uv[1] * w;
00277                                 }
00278                         } else {
00279                                 uv[j][0] += src->uv[j][0] * weight;
00280                                 uv[j][1] += src->uv[j][1] * weight;
00281                         }
00282                 }
00283         }
00284 
00285         *tf = *(MTFace *)sources[0];
00286         for(j = 0; j < 4; ++j) {
00287                 tf->uv[j][0] = uv[j][0];
00288                 tf->uv[j][1] = uv[j][1];
00289         }
00290 }
00291 
00292 static void layerSwap_tface(void *data, const int *corner_indices)
00293 {
00294         MTFace *tf = data;
00295         float uv[4][2];
00296         static const short pin_flags[4] =
00297                 { TF_PIN1, TF_PIN2, TF_PIN3, TF_PIN4 };
00298         static const char sel_flags[4] =
00299                 { TF_SEL1, TF_SEL2, TF_SEL3, TF_SEL4 };
00300         short unwrap = tf->unwrap & ~(TF_PIN1 | TF_PIN2 | TF_PIN3 | TF_PIN4);
00301         char flag = tf->flag & ~(TF_SEL1 | TF_SEL2 | TF_SEL3 | TF_SEL4);
00302         int j;
00303 
00304         for(j = 0; j < 4; ++j) {
00305                 int source_index = corner_indices[j];
00306 
00307                 uv[j][0] = tf->uv[source_index][0];
00308                 uv[j][1] = tf->uv[source_index][1];
00309 
00310                 // swap pinning flags around
00311                 if(tf->unwrap & pin_flags[source_index]) {
00312                         unwrap |= pin_flags[j];
00313                 }
00314 
00315                 // swap selection flags around
00316                 if(tf->flag & sel_flags[source_index]) {
00317                         flag |= sel_flags[j];
00318                 }
00319         }
00320 
00321         memcpy(tf->uv, uv, sizeof(tf->uv));
00322         tf->unwrap = unwrap;
00323         tf->flag = flag;
00324 }
00325 
00326 static void layerDefault_tface(void *data, int count)
00327 {
00328         static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}, NULL,
00329                                                            0, 0, TF_DYNAMIC, 0, 0};
00330         MTFace *tf = (MTFace*)data;
00331         int i;
00332 
00333         for(i = 0; i < count; i++)
00334                 tf[i] = default_tf;
00335 }
00336 
00337 static void layerCopy_origspace_face(const void *source, void *dest, int count)
00338 {
00339         const OrigSpaceFace *source_tf = (const OrigSpaceFace*)source;
00340         OrigSpaceFace *dest_tf = (OrigSpaceFace*)dest;
00341         int i;
00342 
00343         for(i = 0; i < count; ++i)
00344                 dest_tf[i] = source_tf[i];
00345 }
00346 
00347 static void layerInterp_origspace_face(void **sources, float *weights,
00348                                                           float *sub_weights, int count, void *dest)
00349 {
00350         OrigSpaceFace *osf = dest;
00351         int i, j, k;
00352         float uv[4][2];
00353         float *sub_weight;
00354 
00355         if(count <= 0) return;
00356 
00357         memset(uv, 0, sizeof(uv));
00358 
00359         sub_weight = sub_weights;
00360         for(i = 0; i < count; ++i) {
00361                 float weight = weights ? weights[i] : 1;
00362                 OrigSpaceFace *src = sources[i];
00363 
00364                 for(j = 0; j < 4; ++j) {
00365                         if(sub_weights) {
00366                                 for(k = 0; k < 4; ++k, ++sub_weight) {
00367                                         float w = (*sub_weight) * weight;
00368                                         float *tmp_uv = src->uv[k];
00369 
00370                                         uv[j][0] += tmp_uv[0] * w;
00371                                         uv[j][1] += tmp_uv[1] * w;
00372                                 }
00373                         } else {
00374                                 uv[j][0] += src->uv[j][0] * weight;
00375                                 uv[j][1] += src->uv[j][1] * weight;
00376                         }
00377                 }
00378         }
00379 
00380         *osf = *(OrigSpaceFace *)sources[0];
00381         for(j = 0; j < 4; ++j) {
00382                 osf->uv[j][0] = uv[j][0];
00383                 osf->uv[j][1] = uv[j][1];
00384         }
00385 }
00386 
00387 static void layerSwap_origspace_face(void *data, const int *corner_indices)
00388 {
00389         OrigSpaceFace *osf = data;
00390         float uv[4][2];
00391         int j;
00392 
00393         for(j = 0; j < 4; ++j) {
00394                 uv[j][0] = osf->uv[corner_indices[j]][0];
00395                 uv[j][1] = osf->uv[corner_indices[j]][1];
00396         }
00397         memcpy(osf->uv, uv, sizeof(osf->uv));
00398 }
00399 
00400 static void layerDefault_origspace_face(void *data, int count)
00401 {
00402         static OrigSpaceFace default_osf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}};
00403         OrigSpaceFace *osf = (OrigSpaceFace*)data;
00404         int i;
00405 
00406         for(i = 0; i < count; i++)
00407                 osf[i] = default_osf;
00408 }
00409 
00410 static void layerSwap_mdisps(void *data, const int *ci)
00411 {
00412         MDisps *s = data;
00413         float (*d)[3] = NULL;
00414         int corners, cornersize, S;
00415 
00416         if(s->disps) {
00417                 int nverts= (ci[1] == 3) ? 4 : 3; /* silly way to know vertex count of face */
00418                 corners= multires_mdisp_corners(s);
00419                 cornersize= s->totdisp/corners;
00420 
00421                 if(corners!=nverts) {
00422                         /* happens when face changed vertex count in edit mode
00423                            if it happened, just forgot displacement */
00424 
00425                         MEM_freeN(s->disps);
00426                         s->totdisp= (s->totdisp/corners)*nverts;
00427                         s->disps= MEM_callocN(s->totdisp*sizeof(float)*3, "mdisp swap");
00428                         return;
00429                 }
00430 
00431                 d= MEM_callocN(sizeof(float) * 3 * s->totdisp, "mdisps swap");
00432 
00433                 for(S = 0; S < corners; S++)
00434                         memcpy(d + cornersize*S, s->disps + cornersize*ci[S], cornersize*3*sizeof(float));
00435                 
00436                 MEM_freeN(s->disps);
00437                 s->disps= d;
00438         }
00439 }
00440 
00441 static void layerInterp_mdisps(void **sources, float *UNUSED(weights),
00442                                 float *sub_weights, int count, void *dest)
00443 {
00444         MDisps *d = dest;
00445         MDisps *s = NULL;
00446         int st, stl;
00447         int i, x, y;
00448         int side, S, dst_corners, src_corners;
00449         float crn_weight[4][2];
00450         float (*sw)[4] = (void*)sub_weights;
00451         float (*disps)[3], (*out)[3];
00452 
00453         /* happens when flipping normals of newly created mesh */
00454         if(!d->totdisp)
00455                 return;
00456 
00457         s = sources[0];
00458         dst_corners = multires_mdisp_corners(d);
00459         src_corners = multires_mdisp_corners(s);
00460 
00461         if(sub_weights && count == 2 && src_corners == 3) {
00462                 src_corners = multires_mdisp_corners(sources[1]);
00463 
00464                 /* special case -- converting two triangles to quad */
00465                 if(src_corners == 3 && dst_corners == 4) {
00466                         MDisps tris[2];
00467                         int vindex[4] = {0};
00468 
00469                         for(i = 0; i < 2; i++)
00470                                 for(y = 0; y < 4; y++)
00471                                         for(x = 0; x < 4; x++)
00472                                                 if(sw[x+i*4][y])
00473                                                         vindex[x] = y;
00474 
00475                         for(i = 0; i < 2; i++) {
00476                                 float sw_m4[4][4] = {{0}};
00477                                 int a = 7 & ~(1 << vindex[i*2] | 1 << vindex[i*2+1]);
00478 
00479                                 sw_m4[0][vindex[i*2+1]] = 1;
00480                                 sw_m4[1][vindex[i*2]] = 1;
00481 
00482                                 for(x = 0; x < 3; x++)
00483                                         if(a & (1 << x))
00484                                                 sw_m4[2][x] = 1;
00485 
00486                                 tris[i] = *((MDisps*)sources[i]);
00487                                 tris[i].disps = MEM_dupallocN(tris[i].disps);
00488                                 layerInterp_mdisps(&sources[i], NULL, (float*)sw_m4, 1, &tris[i]);
00489                         }
00490 
00491                         mdisp_join_tris(d, &tris[0], &tris[1]);
00492 
00493                         for(i = 0; i < 2; i++)
00494                                 MEM_freeN(tris[i].disps);
00495 
00496                         return;
00497                 }
00498         }
00499 
00500         /* For now, some restrictions on the input */
00501         if(count != 1 || !sub_weights) {
00502                 for(i = 0; i < d->totdisp; ++i)
00503                         zero_v3(d->disps[i]);
00504 
00505                 return;
00506         }
00507 
00508         /* Initialize the destination */
00509         disps = MEM_callocN(3*d->totdisp*sizeof(float), "iterp disps");
00510 
00511         side = sqrt(d->totdisp / dst_corners);
00512         st = (side<<1)-1;
00513         stl = st - 1;
00514 
00515         sw= (void*)sub_weights;
00516         for(i = 0; i < 4; ++i) {
00517                 crn_weight[i][0] = 0 * sw[i][0] + stl * sw[i][1] + stl * sw[i][2] + 0 * sw[i][3];
00518                 crn_weight[i][1] = 0 * sw[i][0] + 0 * sw[i][1] + stl * sw[i][2] + stl * sw[i][3];
00519         }
00520 
00521         multires_mdisp_smooth_bounds(s);
00522 
00523         out = disps;
00524         for(S = 0; S < dst_corners; S++) {
00525                 float base[2], axis_x[2], axis_y[2];
00526 
00527                 mdisp_apply_weight(S, dst_corners, 0, 0, st, crn_weight, &base[0], &base[1]);
00528                 mdisp_apply_weight(S, dst_corners, side-1, 0, st, crn_weight, &axis_x[0], &axis_x[1]);
00529                 mdisp_apply_weight(S, dst_corners, 0, side-1, st, crn_weight, &axis_y[0], &axis_y[1]);
00530 
00531                 sub_v2_v2(axis_x, base);
00532                 sub_v2_v2(axis_y, base);
00533                 normalize_v2(axis_x);
00534                 normalize_v2(axis_y);
00535 
00536                 for(y = 0; y < side; ++y) {
00537                         for(x = 0; x < side; ++x, ++out) {
00538                                 int crn;
00539                                 float face_u, face_v, crn_u, crn_v;
00540 
00541                                 mdisp_apply_weight(S, dst_corners, x, y, st, crn_weight, &face_u, &face_v);
00542                                 crn = mdisp_rot_face_to_quad_crn(src_corners, st, face_u, face_v, &crn_u, &crn_v);
00543 
00544                                 old_mdisps_bilinear((*out), &s->disps[crn*side*side], side, crn_u, crn_v);
00545                                 mdisp_flip_disp(crn, dst_corners, axis_x, axis_y, *out);
00546                         }
00547                 }
00548         }
00549 
00550         MEM_freeN(d->disps);
00551         d->disps = disps;
00552 }
00553 
00554 static void layerCopy_mdisps(const void *source, void *dest, int count)
00555 {
00556         int i;
00557         const MDisps *s = source;
00558         MDisps *d = dest;
00559 
00560         for(i = 0; i < count; ++i) {
00561                 if(s[i].disps) {
00562                         d[i].disps = MEM_dupallocN(s[i].disps);
00563                         d[i].totdisp = s[i].totdisp;
00564                 }
00565                 else {
00566                         d[i].disps = NULL;
00567                         d[i].totdisp = 0;
00568                 }
00569                 
00570         }
00571 }
00572 
00573 static void layerValidate_mdisps(void *data, int sub_elements)
00574 {
00575         MDisps *disps = data;
00576         if(disps->disps) {
00577                 int corners = multires_mdisp_corners(disps);
00578 
00579                 if(corners != sub_elements) {
00580                         MEM_freeN(disps->disps);
00581                         disps->totdisp = disps->totdisp / corners * sub_elements;
00582                         disps->disps = MEM_callocN(3*disps->totdisp*sizeof(float), "layerValidate_mdisps");
00583                 }
00584         }
00585 }
00586 
00587 static void layerFree_mdisps(void *data, int count, int UNUSED(size))
00588 {
00589         int i;
00590         MDisps *d = data;
00591 
00592         for(i = 0; i < count; ++i) {
00593                 if(d[i].disps)
00594                         MEM_freeN(d[i].disps);
00595                 d[i].disps = NULL;
00596                 d[i].totdisp = 0;
00597         }
00598 }
00599 
00600 static int layerRead_mdisps(CDataFile *cdf, void *data, int count)
00601 {
00602         MDisps *d = data;
00603         int i;
00604 
00605         for(i = 0; i < count; ++i) {
00606                 if(!d[i].disps)
00607                         d[i].disps = MEM_callocN(sizeof(float)*3*d[i].totdisp, "mdisps read");
00608 
00609                 if(!cdf_read_data(cdf, d[i].totdisp*3*sizeof(float), d[i].disps)) {
00610                         printf("failed to read multires displacement %d/%d %d\n", i, count, d[i].totdisp);
00611                         return 0;
00612                 }
00613         }
00614 
00615         return 1;
00616 }
00617 
00618 static int layerWrite_mdisps(CDataFile *cdf, void *data, int count)
00619 {
00620         MDisps *d = data;
00621         int i;
00622 
00623         for(i = 0; i < count; ++i) {
00624                 if(!cdf_write_data(cdf, d[i].totdisp*3*sizeof(float), d[i].disps)) {
00625                         printf("failed to write multires displacement %d/%d %d\n", i, count, d[i].totdisp);
00626                         return 0;
00627                 }
00628         }
00629 
00630         return 1;
00631 }
00632 
00633 static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), void *data, int count)
00634 {
00635         MDisps *d = data;
00636         size_t size = 0;
00637         int i;
00638 
00639         for(i = 0; i < count; ++i)
00640                 size += d[i].totdisp*3*sizeof(float);
00641 
00642         return size;
00643 }
00644 
00645 /* --------- */
00646 
00647 static void layerDefault_mloopcol(void *data, int count)
00648 {
00649         static MLoopCol default_mloopcol = {255,255,255,255};
00650         MLoopCol *mlcol = (MLoopCol*)data;
00651         int i;
00652         for(i = 0; i < count; i++)
00653                 mlcol[i] = default_mloopcol;
00654 
00655 }
00656 
00657 static void layerInterp_mloopcol(void **sources, float *weights,
00658                                 float *sub_weights, int count, void *dest)
00659 {
00660         MLoopCol *mc = dest;
00661         int i;
00662         float *sub_weight;
00663         struct {
00664                 float a;
00665                 float r;
00666                 float g;
00667                 float b;
00668         } col;
00669         col.a = col.r = col.g = col.b = 0;
00670 
00671         sub_weight = sub_weights;
00672         for(i = 0; i < count; ++i){
00673                 float weight = weights ? weights[i] : 1;
00674                 MLoopCol *src = sources[i];
00675                 if(sub_weights){
00676                         col.a += src->a * (*sub_weight) * weight;
00677                         col.r += src->r * (*sub_weight) * weight;
00678                         col.g += src->g * (*sub_weight) * weight;
00679                         col.b += src->b * (*sub_weight) * weight;
00680                         sub_weight++;           
00681                 } else {
00682                         col.a += src->a * weight;
00683                         col.r += src->r * weight;
00684                         col.g += src->g * weight;
00685                         col.b += src->b * weight;
00686                 }
00687         }
00688         
00689         /* Subdivide smooth or fractal can cause problems without clamping
00690          * although weights should also not cause this situation */
00691         CLAMP(col.a, 0.0f, 255.0f);
00692         CLAMP(col.r, 0.0f, 255.0f);
00693         CLAMP(col.g, 0.0f, 255.0f);
00694         CLAMP(col.b, 0.0f, 255.0f);
00695         
00696         mc->a = (int)col.a;
00697         mc->r = (int)col.r;
00698         mc->g = (int)col.g;
00699         mc->b = (int)col.b;
00700 }
00701 static void layerInterp_mloopuv(void **sources, float *weights,
00702                                 float *sub_weights, int count, void *dest)
00703 {
00704         MLoopUV *mluv = dest;
00705         int i;
00706         float *sub_weight;
00707         struct {
00708                 float u;
00709                 float v;
00710         }uv;
00711         uv.u = uv.v = 0.0;
00712 
00713         sub_weight = sub_weights;
00714         for(i = 0; i < count; ++i){
00715                 float weight = weights ? weights[i] : 1;
00716                 MLoopUV *src = sources[i];
00717                 if(sub_weights){
00718                         uv.u += src->uv[0] * (*sub_weight) * weight;
00719                         uv.v += src->uv[1] * (*sub_weight) * weight;
00720                         sub_weight++;           
00721                 } else {
00722                         uv.u += src->uv[0] * weight;
00723                         uv.v += src->uv[1] * weight;
00724                 }
00725         }
00726         mluv->uv[0] = uv.u;
00727         mluv->uv[1] = uv.v;
00728 }
00729 
00730 static void layerInterp_mcol(void **sources, float *weights,
00731                                                          float *sub_weights, int count, void *dest)
00732 {
00733         MCol *mc = dest;
00734         int i, j, k;
00735         struct {
00736                 float a;
00737                 float r;
00738                 float g;
00739                 float b;
00740         } col[4];
00741         float *sub_weight;
00742 
00743         if(count <= 0) return;
00744 
00745         memset(col, 0, sizeof(col));
00746         
00747         sub_weight = sub_weights;
00748         for(i = 0; i < count; ++i) {
00749                 float weight = weights ? weights[i] : 1;
00750 
00751                 for(j = 0; j < 4; ++j) {
00752                         if(sub_weights) {
00753                                 MCol *src = sources[i];
00754                                 for(k = 0; k < 4; ++k, ++sub_weight, ++src) {
00755                                         col[j].a += src->a * (*sub_weight) * weight;
00756                                         col[j].r += src->r * (*sub_weight) * weight;
00757                                         col[j].g += src->g * (*sub_weight) * weight;
00758                                         col[j].b += src->b * (*sub_weight) * weight;
00759                                 }
00760                         } else {
00761                                 MCol *src = sources[i];
00762                                 col[j].a += src[j].a * weight;
00763                                 col[j].r += src[j].r * weight;
00764                                 col[j].g += src[j].g * weight;
00765                                 col[j].b += src[j].b * weight;
00766                         }
00767                 }
00768         }
00769 
00770         for(j = 0; j < 4; ++j) {
00771                 
00772                 /* Subdivide smooth or fractal can cause problems without clamping
00773                  * although weights should also not cause this situation */
00774                 CLAMP(col[j].a, 0.0f, 255.0f);
00775                 CLAMP(col[j].r, 0.0f, 255.0f);
00776                 CLAMP(col[j].g, 0.0f, 255.0f);
00777                 CLAMP(col[j].b, 0.0f, 255.0f);
00778                 
00779                 mc[j].a = (int)col[j].a;
00780                 mc[j].r = (int)col[j].r;
00781                 mc[j].g = (int)col[j].g;
00782                 mc[j].b = (int)col[j].b;
00783         }
00784 }
00785 
00786 static void layerSwap_mcol(void *data, const int *corner_indices)
00787 {
00788         MCol *mcol = data;
00789         MCol col[4];
00790         int j;
00791 
00792         for(j = 0; j < 4; ++j)
00793                 col[j] = mcol[corner_indices[j]];
00794 
00795         memcpy(mcol, col, sizeof(col));
00796 }
00797 
00798 static void layerDefault_mcol(void *data, int count)
00799 {
00800         static MCol default_mcol = {255, 255, 255, 255};
00801         MCol *mcol = (MCol*)data;
00802         int i;
00803 
00804         for(i = 0; i < 4*count; i++)
00805                 mcol[i] = default_mcol;
00806 }
00807 
00808 
00809 
00810 static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
00811         {sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL},
00812         {sizeof(MSticky), "MSticky", 1, NULL, NULL, NULL, layerInterp_msticky, NULL,
00813          NULL},
00814         {sizeof(MDeformVert), "MDeformVert", 1, NULL, layerCopy_mdeformvert,
00815          layerFree_mdeformvert, layerInterp_mdeformvert, NULL, NULL},
00816         {sizeof(MEdge), "MEdge", 1, NULL, NULL, NULL, NULL, NULL, NULL},
00817         {sizeof(MFace), "MFace", 1, NULL, NULL, NULL, NULL, NULL, NULL},
00818         {sizeof(MTFace), "MTFace", 1, "UVTex", layerCopy_tface, NULL,
00819          layerInterp_tface, layerSwap_tface, layerDefault_tface},
00820         /* 4 MCol structs per face */
00821         {sizeof(MCol)*4, "MCol", 4, "Col", NULL, NULL, layerInterp_mcol,
00822          layerSwap_mcol, layerDefault_mcol},
00823         {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
00824         /* 3 floats per normal vector */
00825         {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
00826         {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
00827         {sizeof(MFloatProperty), "MFloatProperty",1,"Float",NULL,NULL,NULL,NULL},
00828         {sizeof(MIntProperty), "MIntProperty",1,"Int",NULL,NULL,NULL,NULL},
00829         {sizeof(MStringProperty), "MStringProperty",1,"String",NULL,NULL,NULL,NULL},
00830         {sizeof(OrigSpaceFace), "OrigSpaceFace", 1, "UVTex", layerCopy_origspace_face, NULL,
00831          layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face},
00832         {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
00833         {sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL},
00834         {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL},
00835         {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol},
00836         {sizeof(float)*4*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
00837         {sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps,
00838          layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, layerRead_mdisps, layerWrite_mdisps,
00839          layerFilesize_mdisps, layerValidate_mdisps},
00840         {sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol,
00841          layerSwap_mcol, layerDefault_mcol},
00842          {sizeof(MCol)*4, "MCol", 4, "IDCol", NULL, NULL, layerInterp_mcol,
00843          layerSwap_mcol, layerDefault_mcol},
00844          {sizeof(MCol)*4, "MCol", 4, "TexturedCol", NULL, NULL, layerInterp_mcol,
00845          layerSwap_mcol, layerDefault_mcol},
00846         {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}
00847 };
00848 
00849 static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
00850         /*   0-4 */ "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace",
00851         /*   5-9 */ "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags",
00852         /* 10-14 */ "CDMFloatProperty", "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco",
00853         /* 15-19 */ "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent", "CDMDisps",
00854         /* 20-23 */"CDWeightMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco"
00855 };
00856 
00857 const CustomDataMask CD_MASK_BAREMESH =
00858         CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE;
00859 const CustomDataMask CD_MASK_MESH =
00860         CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE |
00861         CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL |
00862         CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS;
00863 const CustomDataMask CD_MASK_EDITMESH =
00864         CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE |
00865         CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS;
00866 const CustomDataMask CD_MASK_DERIVEDMESH =
00867         CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE |
00868         CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_CLOTH_ORCO |
00869         CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT | CD_MASK_WEIGHT_MCOL;
00870 const CustomDataMask CD_MASK_BMESH = 
00871         CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR;
00872 const CustomDataMask CD_MASK_FACECORNERS =
00873         CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
00874         CD_MASK_MLOOPCOL;
00875 
00876 
00877 static const LayerTypeInfo *layerType_getInfo(int type)
00878 {
00879         if(type < 0 || type >= CD_NUMTYPES) return NULL;
00880 
00881         return &LAYERTYPEINFO[type];
00882 }
00883 
00884 static const char *layerType_getName(int type)
00885 {
00886         if(type < 0 || type >= CD_NUMTYPES) return NULL;
00887 
00888         return LAYERTYPENAMES[type];
00889 }
00890 
00891 /********************* CustomData functions *********************/
00892 static void customData_update_offsets(CustomData *data);
00893 
00894 static CustomDataLayer *customData_add_layer__internal(CustomData *data,
00895         int type, int alloctype, void *layerdata, int totelem, const char *name);
00896 
00897 void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
00898                                           CustomDataMask mask, int alloctype, int totelem)
00899 {
00900         /*const LayerTypeInfo *typeInfo;*/
00901         CustomDataLayer *layer, *newlayer;
00902         int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0, lastflag = 0;
00903 
00904         for(i = 0; i < source->totlayer; ++i) {
00905                 layer = &source->layers[i];
00906                 /*typeInfo = layerType_getInfo(layer->type);*/ /*UNUSED*/
00907 
00908                 type = layer->type;
00909 
00910                 if (type != lasttype) {
00911                         number = 0;
00912                         lastactive = layer->active;
00913                         lastrender = layer->active_rnd;
00914                         lastclone = layer->active_clone;
00915                         lastmask = layer->active_mask;
00916                         lasttype = type;
00917                         lastflag = layer->flag;
00918                 }
00919                 else
00920                         number++;
00921 
00922                 if(lastflag & CD_FLAG_NOCOPY) continue;
00923                 else if(!((int)mask & (int)(1 << (int)type))) continue;
00924                 else if(number < CustomData_number_of_layers(dest, type)) continue;
00925 
00926                 if((alloctype == CD_ASSIGN) && (lastflag & CD_FLAG_NOFREE))
00927                         newlayer = customData_add_layer__internal(dest, type, CD_REFERENCE,
00928                                 layer->data, totelem, layer->name);
00929                 else
00930                         newlayer = customData_add_layer__internal(dest, type, alloctype,
00931                                 layer->data, totelem, layer->name);
00932                 
00933                 if(newlayer) {
00934                         newlayer->active = lastactive;
00935                         newlayer->active_rnd = lastrender;
00936                         newlayer->active_clone = lastclone;
00937                         newlayer->active_mask = lastmask;
00938                         newlayer->flag |= lastflag & (CD_FLAG_EXTERNAL|CD_FLAG_IN_MEMORY);
00939                 }
00940         }
00941 }
00942 
00943 void CustomData_copy(const struct CustomData *source, struct CustomData *dest,
00944                                          CustomDataMask mask, int alloctype, int totelem)
00945 {
00946         memset(dest, 0, sizeof(*dest));
00947 
00948         if(source->external)
00949                 dest->external= MEM_dupallocN(source->external);
00950 
00951         CustomData_merge(source, dest, mask, alloctype, totelem);
00952 }
00953 
00954 static void customData_free_layer__internal(CustomDataLayer *layer, int totelem)
00955 {
00956         const LayerTypeInfo *typeInfo;
00957 
00958         if(!(layer->flag & CD_FLAG_NOFREE) && layer->data) {
00959                 typeInfo = layerType_getInfo(layer->type);
00960 
00961                 if(typeInfo->free)
00962                         typeInfo->free(layer->data, totelem, typeInfo->size);
00963 
00964                 if(layer->data)
00965                         MEM_freeN(layer->data);
00966         }
00967 }
00968 
00969 static void CustomData_external_free(CustomData *data)
00970 {
00971         if(data->external) {
00972                 MEM_freeN(data->external);
00973                 data->external= NULL;
00974         }
00975 }
00976 
00977 void CustomData_free(CustomData *data, int totelem)
00978 {
00979         int i;
00980 
00981         for(i = 0; i < data->totlayer; ++i)
00982                 customData_free_layer__internal(&data->layers[i], totelem);
00983 
00984         if(data->layers)
00985                 MEM_freeN(data->layers);
00986         
00987         CustomData_external_free(data);
00988         
00989         memset(data, 0, sizeof(*data));
00990 }
00991 
00992 static void customData_update_offsets(CustomData *data)
00993 {
00994         const LayerTypeInfo *typeInfo;
00995         int i, offset = 0;
00996 
00997         for(i = 0; i < data->totlayer; ++i) {
00998                 typeInfo = layerType_getInfo(data->layers[i].type);
00999 
01000                 data->layers[i].offset = offset;
01001                 offset += typeInfo->size;
01002         }
01003 
01004         data->totsize = offset;
01005 }
01006 
01007 int CustomData_get_layer_index(const CustomData *data, int type)
01008 {
01009         int i; 
01010 
01011         for(i=0; i < data->totlayer; ++i)
01012                 if(data->layers[i].type == type)
01013                         return i;
01014 
01015         return -1;
01016 }
01017 
01018 int CustomData_get_named_layer_index(const CustomData *data, int type, const char *name)
01019 {
01020         int i;
01021 
01022         for(i=0; i < data->totlayer; ++i)
01023                 if(data->layers[i].type == type && strcmp(data->layers[i].name, name)==0)
01024                         return i;
01025 
01026         return -1;
01027 }
01028 
01029 int CustomData_get_active_layer_index(const CustomData *data, int type)
01030 {
01031         int i;
01032 
01033         for(i=0; i < data->totlayer; ++i)
01034                 if(data->layers[i].type == type)
01035                         return i + data->layers[i].active;
01036 
01037         return -1;
01038 }
01039 
01040 int CustomData_get_render_layer_index(const CustomData *data, int type)
01041 {
01042         int i;
01043 
01044         for(i=0; i < data->totlayer; ++i)
01045                 if(data->layers[i].type == type)
01046                         return i + data->layers[i].active_rnd;
01047 
01048         return -1;
01049 }
01050 
01051 int CustomData_get_clone_layer_index(const CustomData *data, int type)
01052 {
01053         int i;
01054 
01055         for(i=0; i < data->totlayer; ++i)
01056                 if(data->layers[i].type == type)
01057                         return i + data->layers[i].active_clone;
01058 
01059         return -1;
01060 }
01061 
01062 int CustomData_get_stencil_layer_index(const CustomData *data, int type)
01063 {
01064         int i;
01065 
01066         for(i=0; i < data->totlayer; ++i)
01067                 if(data->layers[i].type == type)
01068                         return i + data->layers[i].active_mask;
01069 
01070         return -1;
01071 }
01072 
01073 int CustomData_get_active_layer(const CustomData *data, int type)
01074 {
01075         int i;
01076 
01077         for(i=0; i < data->totlayer; ++i)
01078                 if(data->layers[i].type == type)
01079                         return data->layers[i].active;
01080 
01081         return -1;
01082 }
01083 
01084 int CustomData_get_render_layer(const CustomData *data, int type)
01085 {
01086         int i;
01087 
01088         for(i=0; i < data->totlayer; ++i)
01089                 if(data->layers[i].type == type)
01090                         return data->layers[i].active_rnd;
01091 
01092         return -1;
01093 }
01094 
01095 int CustomData_get_clone_layer(const CustomData *data, int type)
01096 {
01097         int i;
01098 
01099         for(i=0; i < data->totlayer; ++i)
01100                 if(data->layers[i].type == type)
01101                         return data->layers[i].active_clone;
01102 
01103         return -1;
01104 }
01105 
01106 int CustomData_get_stencil_layer(const CustomData *data, int type)
01107 {
01108         int i;
01109 
01110         for(i=0; i < data->totlayer; ++i)
01111                 if(data->layers[i].type == type)
01112                         return data->layers[i].active_mask;
01113 
01114         return -1;
01115 }
01116 
01117 void CustomData_set_layer_active(CustomData *data, int type, int n)
01118 {
01119         int i;
01120 
01121         for(i=0; i < data->totlayer; ++i)
01122                 if(data->layers[i].type == type)
01123                         data->layers[i].active = n;
01124 }
01125 
01126 void CustomData_set_layer_render(CustomData *data, int type, int n)
01127 {
01128         int i;
01129 
01130         for(i=0; i < data->totlayer; ++i)
01131                 if(data->layers[i].type == type)
01132                         data->layers[i].active_rnd = n;
01133 }
01134 
01135 void CustomData_set_layer_clone(CustomData *data, int type, int n)
01136 {
01137         int i;
01138 
01139         for(i=0; i < data->totlayer; ++i)
01140                 if(data->layers[i].type == type)
01141                         data->layers[i].active_clone = n;
01142 }
01143 
01144 void CustomData_set_layer_stencil(CustomData *data, int type, int n)
01145 {
01146         int i;
01147 
01148         for(i=0; i < data->totlayer; ++i)
01149                 if(data->layers[i].type == type)
01150                         data->layers[i].active_mask = n;
01151 }
01152 
01153 /* for using with an index from CustomData_get_active_layer_index and CustomData_get_render_layer_index */
01154 void CustomData_set_layer_active_index(CustomData *data, int type, int n)
01155 {
01156         int i;
01157 
01158         for(i=0; i < data->totlayer; ++i)
01159                 if(data->layers[i].type == type)
01160                         data->layers[i].active = n-i;
01161 }
01162 
01163 void CustomData_set_layer_render_index(CustomData *data, int type, int n)
01164 {
01165         int i;
01166 
01167         for(i=0; i < data->totlayer; ++i)
01168                 if(data->layers[i].type == type)
01169                         data->layers[i].active_rnd = n-i;
01170 }
01171 
01172 void CustomData_set_layer_clone_index(CustomData *data, int type, int n)
01173 {
01174         int i;
01175 
01176         for(i=0; i < data->totlayer; ++i)
01177                 if(data->layers[i].type == type)
01178                         data->layers[i].active_clone = n-i;
01179 }
01180 
01181 void CustomData_set_layer_stencil_index(CustomData *data, int type, int n)
01182 {
01183         int i;
01184 
01185         for(i=0; i < data->totlayer; ++i)
01186                 if(data->layers[i].type == type)
01187                         data->layers[i].active_mask = n-i;
01188 }
01189 
01190 void CustomData_set_layer_flag(struct CustomData *data, int type, int flag)
01191 {
01192         int i;
01193 
01194         for(i=0; i < data->totlayer; ++i)
01195                 if(data->layers[i].type == type)
01196                         data->layers[i].flag |= flag;
01197 }
01198 
01199 static int customData_resize(CustomData *data, int amount)
01200 {
01201         CustomDataLayer *tmp = MEM_callocN(sizeof(*tmp)*(data->maxlayer + amount),
01202                                                                            "CustomData->layers");
01203         if(!tmp) return 0;
01204 
01205         data->maxlayer += amount;
01206         if (data->layers) {
01207                 memcpy(tmp, data->layers, sizeof(*tmp) * data->totlayer);
01208                 MEM_freeN(data->layers);
01209         }
01210         data->layers = tmp;
01211 
01212         return 1;
01213 }
01214 
01215 static CustomDataLayer *customData_add_layer__internal(CustomData *data,
01216         int type, int alloctype, void *layerdata, int totelem, const char *name)
01217 {
01218         const LayerTypeInfo *typeInfo= layerType_getInfo(type);
01219         int size = typeInfo->size * totelem, flag = 0, index = data->totlayer;
01220         void *newlayerdata;
01221 
01222         if (!typeInfo->defaultname && CustomData_has_layer(data, type))
01223                 return &data->layers[CustomData_get_layer_index(data, type)];
01224 
01225         if((alloctype == CD_ASSIGN) || (alloctype == CD_REFERENCE)) {
01226                 newlayerdata = layerdata;
01227         }
01228         else {
01229                 newlayerdata = MEM_callocN(size, layerType_getName(type));
01230                 if(!newlayerdata)
01231                         return NULL;
01232         }
01233 
01234         if (alloctype == CD_DUPLICATE) {
01235                 if(typeInfo->copy)
01236                         typeInfo->copy(layerdata, newlayerdata, totelem);
01237                 else
01238                         memcpy(newlayerdata, layerdata, size);
01239         }
01240         else if (alloctype == CD_DEFAULT) {
01241                 if(typeInfo->set_default)
01242                         typeInfo->set_default((char*)newlayerdata, totelem);
01243         }
01244         else if (alloctype == CD_REFERENCE)
01245                 flag |= CD_FLAG_NOFREE;
01246 
01247         if(index >= data->maxlayer) {
01248                 if(!customData_resize(data, CUSTOMDATA_GROW)) {
01249                         if(newlayerdata != layerdata)
01250                                 MEM_freeN(newlayerdata);
01251                         return NULL;
01252                 }
01253         }
01254         
01255         data->totlayer++;
01256 
01257         /* keep layers ordered by type */
01258         for( ; index > 0 && data->layers[index - 1].type > type; --index)
01259                 data->layers[index] = data->layers[index - 1];
01260 
01261         data->layers[index].type = type;
01262         data->layers[index].flag = flag;
01263         data->layers[index].data = newlayerdata;
01264         if(name || (name=typeInfo->defaultname)) {
01265                 BLI_strncpy(data->layers[index].name, name, 32);
01266                 CustomData_set_layer_unique_name(data, index);
01267         }
01268         else
01269                 data->layers[index].name[0] = '\0';
01270 
01271         if(index > 0 && data->layers[index-1].type == type) {
01272                 data->layers[index].active = data->layers[index-1].active;
01273                 data->layers[index].active_rnd = data->layers[index-1].active_rnd;
01274                 data->layers[index].active_clone = data->layers[index-1].active_clone;
01275                 data->layers[index].active_mask = data->layers[index-1].active_mask;
01276         } else {
01277                 data->layers[index].active = 0;
01278                 data->layers[index].active_rnd = 0;
01279                 data->layers[index].active_clone = 0;
01280                 data->layers[index].active_mask = 0;
01281         }
01282         
01283         customData_update_offsets(data);
01284 
01285         return &data->layers[index];
01286 }
01287 
01288 void *CustomData_add_layer(CustomData *data, int type, int alloctype,
01289                                                    void *layerdata, int totelem)
01290 {
01291         CustomDataLayer *layer;
01292         const LayerTypeInfo *typeInfo= layerType_getInfo(type);
01293         
01294         layer = customData_add_layer__internal(data, type, alloctype, layerdata,
01295                                                                                    totelem, typeInfo->defaultname);
01296 
01297         if(layer)
01298                 return layer->data;
01299 
01300         return NULL;
01301 }
01302 
01303 /*same as above but accepts a name*/
01304 void *CustomData_add_layer_named(CustomData *data, int type, int alloctype,
01305                                                    void *layerdata, int totelem, const char *name)
01306 {
01307         CustomDataLayer *layer;
01308         
01309         layer = customData_add_layer__internal(data, type, alloctype, layerdata,
01310                                                                                    totelem, name);
01311 
01312         if(layer)
01313                 return layer->data;
01314 
01315         return NULL;
01316 }
01317 
01318 
01319 int CustomData_free_layer(CustomData *data, int type, int totelem, int index)
01320 {
01321         int i;
01322         
01323         if (index < 0) return 0;
01324 
01325         customData_free_layer__internal(&data->layers[index], totelem);
01326 
01327         for (i=index+1; i < data->totlayer; ++i)
01328                 data->layers[i-1] = data->layers[i];
01329 
01330         data->totlayer--;
01331 
01332         /* if layer was last of type in array, set new active layer */
01333         if ((index >= data->totlayer) || (data->layers[index].type != type)) {
01334                 i = CustomData_get_layer_index(data, type);
01335                 
01336                 if (i >= 0)
01337                         for (; i < data->totlayer && data->layers[i].type == type; i++) {
01338                                 data->layers[i].active--;
01339                                 data->layers[i].active_rnd--;
01340                                 data->layers[i].active_clone--;
01341                                 data->layers[i].active_mask--;
01342                         }
01343         }
01344 
01345         if (data->totlayer <= data->maxlayer-CUSTOMDATA_GROW)
01346                 customData_resize(data, -CUSTOMDATA_GROW);
01347 
01348         customData_update_offsets(data);
01349 
01350         return 1;
01351 }
01352 
01353 int CustomData_free_layer_active(CustomData *data, int type, int totelem)
01354 {
01355         int index = 0;
01356         index = CustomData_get_active_layer_index(data, type);
01357         if (index < 0) return 0;
01358         return CustomData_free_layer(data, type, totelem, index);
01359 }
01360 
01361 
01362 void CustomData_free_layers(CustomData *data, int type, int totelem)
01363 {
01364         while (CustomData_has_layer(data, type))
01365                 CustomData_free_layer_active(data, type, totelem);
01366 }
01367 
01368 int CustomData_has_layer(const CustomData *data, int type)
01369 {
01370         return (CustomData_get_layer_index(data, type) != -1);
01371 }
01372 
01373 int CustomData_number_of_layers(const CustomData *data, int type)
01374 {
01375         int i, number = 0;
01376 
01377         for(i = 0; i < data->totlayer; i++)
01378                 if(data->layers[i].type == type)
01379                         number++;
01380         
01381         return number;
01382 }
01383 
01384 void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type)
01385 {
01386         CustomDataLayer *layer;
01387         int layer_index;
01388 
01389         /* get the layer index of the first layer of type */
01390         layer_index = CustomData_get_active_layer_index(data, type);
01391         if(layer_index < 0) return NULL;
01392 
01393         layer = &data->layers[layer_index];
01394 
01395         if (layer->flag & CD_FLAG_NOFREE) {
01396                 layer->data = MEM_dupallocN(layer->data);
01397                 layer->flag &= ~CD_FLAG_NOFREE;
01398         }
01399 
01400         return layer->data;
01401 }
01402 
01403 void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
01404                                                                                                   int type, const char *name)
01405 {
01406         CustomDataLayer *layer;
01407         int layer_index;
01408 
01409         /* get the layer index of the desired layer */
01410         layer_index = CustomData_get_named_layer_index(data, type, name);
01411         if(layer_index < 0) return NULL;
01412 
01413         layer = &data->layers[layer_index];
01414 
01415         if (layer->flag & CD_FLAG_NOFREE) {
01416                 layer->data = MEM_dupallocN(layer->data);
01417                 layer->flag &= ~CD_FLAG_NOFREE;
01418         }
01419 
01420         return layer->data;
01421 }
01422 
01423 void CustomData_free_temporary(CustomData *data, int totelem)
01424 {
01425         CustomDataLayer *layer;
01426         int i, j;
01427 
01428         for(i = 0, j = 0; i < data->totlayer; ++i) {
01429                 layer = &data->layers[i];
01430 
01431                 if (i != j)
01432                         data->layers[j] = data->layers[i];
01433 
01434                 if ((layer->flag & CD_FLAG_TEMPORARY) == CD_FLAG_TEMPORARY)
01435                         customData_free_layer__internal(layer, totelem);
01436                 else
01437                         j++;
01438         }
01439 
01440         data->totlayer = j;
01441 
01442         if(data->totlayer <= data->maxlayer-CUSTOMDATA_GROW)
01443                 customData_resize(data, -CUSTOMDATA_GROW);
01444 
01445         customData_update_offsets(data);
01446 }
01447 
01448 void CustomData_set_only_copy(const struct CustomData *data,
01449                                                           CustomDataMask mask)
01450 {
01451         int i;
01452 
01453         for(i = 0; i < data->totlayer; ++i)
01454                 if(!((int)mask & (int)(1 << (int)data->layers[i].type)))
01455                         data->layers[i].flag |= CD_FLAG_NOCOPY;
01456 }
01457 
01458 void CustomData_copy_data(const CustomData *source, CustomData *dest,
01459                                                   int source_index, int dest_index, int count)
01460 {
01461         const LayerTypeInfo *typeInfo;
01462         int src_i, dest_i;
01463         int src_offset;
01464         int dest_offset;
01465 
01466         /* copies a layer at a time */
01467         dest_i = 0;
01468         for(src_i = 0; src_i < source->totlayer; ++src_i) {
01469 
01470                 /* find the first dest layer with type >= the source type
01471                  * (this should work because layers are ordered by type)
01472                  */
01473                 while(dest_i < dest->totlayer
01474                           && dest->layers[dest_i].type < source->layers[src_i].type)
01475                         ++dest_i;
01476 
01477                 /* if there are no more dest layers, we're done */
01478                 if(dest_i >= dest->totlayer) return;
01479 
01480                 /* if we found a matching layer, copy the data */
01481                 if(dest->layers[dest_i].type == source->layers[src_i].type) {
01482                         char *src_data = source->layers[src_i].data;
01483                         char *dest_data = dest->layers[dest_i].data;
01484 
01485                         typeInfo = layerType_getInfo(source->layers[src_i].type);
01486 
01487                         src_offset = source_index * typeInfo->size;
01488                         dest_offset = dest_index * typeInfo->size;
01489 
01490                         if(typeInfo->copy)
01491                                 typeInfo->copy(src_data + src_offset,
01492                                                                 dest_data + dest_offset,
01493                                                                 count);
01494                         else
01495                                 memcpy(dest_data + dest_offset,
01496                                            src_data + src_offset,
01497                                            count * typeInfo->size);
01498 
01499                         /* if there are multiple source & dest layers of the same type,
01500                          * we don't want to copy all source layers to the same dest, so
01501                          * increment dest_i
01502                          */
01503                         ++dest_i;
01504                 }
01505         }
01506 }
01507 
01508 void CustomData_free_elem(CustomData *data, int index, int count)
01509 {
01510         int i;
01511         const LayerTypeInfo *typeInfo;
01512 
01513         for(i = 0; i < data->totlayer; ++i) {
01514                 if(!(data->layers[i].flag & CD_FLAG_NOFREE)) {
01515                         typeInfo = layerType_getInfo(data->layers[i].type);
01516 
01517                         if(typeInfo->free) {
01518                                 int offset = typeInfo->size * index;
01519 
01520                                 typeInfo->free((char *)data->layers[i].data + offset,
01521                                                            count, typeInfo->size);
01522                         }
01523                 }
01524         }
01525 }
01526 
01527 #define SOURCE_BUF_SIZE 100
01528 
01529 void CustomData_interp(const CustomData *source, CustomData *dest,
01530                                            int *src_indices, float *weights, float *sub_weights,
01531                                            int count, int dest_index)
01532 {
01533         int src_i, dest_i;
01534         int dest_offset;
01535         int j;
01536         void *source_buf[SOURCE_BUF_SIZE];
01537         void **sources = source_buf;
01538 
01539         /* slow fallback in case we're interpolating a ridiculous number of
01540          * elements
01541          */
01542         if(count > SOURCE_BUF_SIZE)
01543                 sources = MEM_callocN(sizeof(*sources) * count,
01544                                                           "CustomData_interp sources");
01545 
01546         /* interpolates a layer at a time */
01547         dest_i = 0;
01548         for(src_i = 0; src_i < source->totlayer; ++src_i) {
01549                 const LayerTypeInfo *typeInfo= layerType_getInfo(source->layers[src_i].type);
01550                 if(!typeInfo->interp) continue;
01551 
01552                 /* find the first dest layer with type >= the source type
01553                  * (this should work because layers are ordered by type)
01554                  */
01555                 while(dest_i < dest->totlayer
01556                           && dest->layers[dest_i].type < source->layers[src_i].type)
01557                         ++dest_i;
01558 
01559                 /* if there are no more dest layers, we're done */
01560                 if(dest_i >= dest->totlayer) return;
01561 
01562                 /* if we found a matching layer, copy the data */
01563                 if(dest->layers[dest_i].type == source->layers[src_i].type) {
01564                         void *src_data = source->layers[src_i].data;
01565 
01566                         for(j = 0; j < count; ++j)
01567                                 sources[j] = (char *)src_data
01568                                                          + typeInfo->size * src_indices[j];
01569 
01570                         dest_offset = dest_index * typeInfo->size;
01571 
01572                         typeInfo->interp(sources, weights, sub_weights, count,
01573                                                    (char *)dest->layers[dest_i].data + dest_offset);
01574 
01575                         /* if there are multiple source & dest layers of the same type,
01576                          * we don't want to copy all source layers to the same dest, so
01577                          * increment dest_i
01578                          */
01579                         ++dest_i;
01580                 }
01581         }
01582 
01583         if(count > SOURCE_BUF_SIZE) MEM_freeN(sources);
01584 }
01585 
01586 void CustomData_swap(struct CustomData *data, int index, const int *corner_indices)
01587 {
01588         const LayerTypeInfo *typeInfo;
01589         int i;
01590 
01591         for(i = 0; i < data->totlayer; ++i) {
01592                 typeInfo = layerType_getInfo(data->layers[i].type);
01593 
01594                 if(typeInfo->swap) {
01595                         int offset = typeInfo->size * index;
01596 
01597                         typeInfo->swap((char *)data->layers[i].data + offset, corner_indices);
01598                 }
01599         }
01600 }
01601 
01602 void *CustomData_get(const CustomData *data, int index, int type)
01603 {
01604         int offset;
01605         int layer_index;
01606         
01607         /* get the layer index of the active layer of type */
01608         layer_index = CustomData_get_active_layer_index(data, type);
01609         if(layer_index < 0) return NULL;
01610 
01611         /* get the offset of the desired element */
01612         offset = layerType_getInfo(type)->size * index;
01613 
01614         return (char *)data->layers[layer_index].data + offset;
01615 }
01616 
01617 void *CustomData_get_layer(const CustomData *data, int type)
01618 {
01619         /* get the layer index of the active layer of type */
01620         int layer_index = CustomData_get_active_layer_index(data, type);
01621         if(layer_index < 0) return NULL;
01622 
01623         return data->layers[layer_index].data;
01624 }
01625 
01626 void *CustomData_get_layer_n(const CustomData *data, int type, int n)
01627 {
01628         /* get the layer index of the active layer of type */
01629         int layer_index = CustomData_get_layer_index(data, type);
01630         if(layer_index < 0) return NULL;
01631 
01632         return data->layers[layer_index+n].data;
01633 }
01634 
01635 void *CustomData_get_layer_named(const struct CustomData *data, int type,
01636                                                                  const char *name)
01637 {
01638         int layer_index = CustomData_get_named_layer_index(data, type, name);
01639         if(layer_index < 0) return NULL;
01640 
01641         return data->layers[layer_index].data;
01642 }
01643 
01644 void *CustomData_set_layer(const CustomData *data, int type, void *ptr)
01645 {
01646         /* get the layer index of the first layer of type */
01647         int layer_index = CustomData_get_active_layer_index(data, type);
01648 
01649         if(layer_index < 0) return NULL;
01650 
01651         data->layers[layer_index].data = ptr;
01652 
01653         return ptr;
01654 }
01655 
01656 void *CustomData_set_layer_n(const struct CustomData *data, int type, int n, void *ptr)
01657 {
01658         /* get the layer index of the first layer of type */
01659         int layer_index = CustomData_get_layer_index(data, type);
01660         if(layer_index < 0) return NULL;
01661 
01662         data->layers[layer_index+n].data = ptr;
01663 
01664         return ptr;
01665 }
01666 
01667 void CustomData_set(const CustomData *data, int index, int type, void *source)
01668 {
01669         void *dest = CustomData_get(data, index, type);
01670         const LayerTypeInfo *typeInfo = layerType_getInfo(type);
01671 
01672         if(!dest) return;
01673 
01674         if(typeInfo->copy)
01675                 typeInfo->copy(source, dest, 1);
01676         else
01677                 memcpy(dest, source, typeInfo->size);
01678 }
01679 
01680 /* EditMesh functions */
01681 
01682 void CustomData_em_free_block(CustomData *data, void **block)
01683 {
01684         const LayerTypeInfo *typeInfo;
01685         int i;
01686 
01687         if(!*block) return;
01688 
01689         for(i = 0; i < data->totlayer; ++i) {
01690                 if(!(data->layers[i].flag & CD_FLAG_NOFREE)) {
01691                         typeInfo = layerType_getInfo(data->layers[i].type);
01692 
01693                         if(typeInfo->free) {
01694                                 int offset = data->layers[i].offset;
01695                                 typeInfo->free((char*)*block + offset, 1, typeInfo->size);
01696                         }
01697                 }
01698         }
01699 
01700         MEM_freeN(*block);
01701         *block = NULL;
01702 }
01703 
01704 static void CustomData_em_alloc_block(CustomData *data, void **block)
01705 {
01706         /* TODO: optimize free/alloc */
01707 
01708         if (*block)
01709                 CustomData_em_free_block(data, block);
01710 
01711         if (data->totsize > 0)
01712                 *block = MEM_callocN(data->totsize, "CustomData EM block");
01713         else
01714                 *block = NULL;
01715 }
01716 
01717 void CustomData_em_copy_data(const CustomData *source, CustomData *dest,
01718                                                         void *src_block, void **dest_block)
01719 {
01720         const LayerTypeInfo *typeInfo;
01721         int dest_i, src_i;
01722 
01723         if (!*dest_block)
01724                 CustomData_em_alloc_block(dest, dest_block);
01725         
01726         /* copies a layer at a time */
01727         dest_i = 0;
01728         for(src_i = 0; src_i < source->totlayer; ++src_i) {
01729 
01730                 /* find the first dest layer with type >= the source type
01731                  * (this should work because layers are ordered by type)
01732                  */
01733                 while(dest_i < dest->totlayer
01734                           && dest->layers[dest_i].type < source->layers[src_i].type)
01735                         ++dest_i;
01736 
01737                 /* if there are no more dest layers, we're done */
01738                 if(dest_i >= dest->totlayer) return;
01739 
01740                 /* if we found a matching layer, copy the data */
01741                 if(dest->layers[dest_i].type == source->layers[src_i].type &&
01742                         strcmp(dest->layers[dest_i].name, source->layers[src_i].name) == 0) {
01743                         char *src_data = (char*)src_block + source->layers[src_i].offset;
01744                         char *dest_data = (char*)*dest_block + dest->layers[dest_i].offset;
01745 
01746                         typeInfo = layerType_getInfo(source->layers[src_i].type);
01747 
01748                         if(typeInfo->copy)
01749                                 typeInfo->copy(src_data, dest_data, 1);
01750                         else
01751                                 memcpy(dest_data, src_data, typeInfo->size);
01752 
01753                         /* if there are multiple source & dest layers of the same type,
01754                          * we don't want to copy all source layers to the same dest, so
01755                          * increment dest_i
01756                          */
01757                         ++dest_i;
01758                 }
01759         }
01760 }
01761 
01762 void CustomData_em_validate_data(CustomData *data, void *block, int sub_elements)
01763 {
01764         int i;
01765         for(i = 0; i < data->totlayer; i++) {
01766                 const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
01767                 char *leayer_data = (char*)block + data->layers[i].offset;
01768 
01769                 if(typeInfo->validate)
01770                         typeInfo->validate(leayer_data, sub_elements);
01771         }
01772 }
01773 
01774 void *CustomData_em_get(const CustomData *data, void *block, int type)
01775 {
01776         int layer_index;
01777         
01778         /* get the layer index of the first layer of type */
01779         layer_index = CustomData_get_active_layer_index(data, type);
01780         if(layer_index < 0) return NULL;
01781 
01782         return (char *)block + data->layers[layer_index].offset;
01783 }
01784 
01785 void *CustomData_em_get_n(const CustomData *data, void *block, int type, int n)
01786 {
01787         int layer_index;
01788         
01789         /* get the layer index of the first layer of type */
01790         layer_index = CustomData_get_layer_index(data, type);
01791         if(layer_index < 0) return NULL;
01792 
01793         return (char *)block + data->layers[layer_index+n].offset;
01794 }
01795 
01796 void CustomData_em_set(CustomData *data, void *block, int type, void *source)
01797 {
01798         void *dest = CustomData_em_get(data, block, type);
01799         const LayerTypeInfo *typeInfo = layerType_getInfo(type);
01800 
01801         if(!dest) return;
01802 
01803         if(typeInfo->copy)
01804                 typeInfo->copy(source, dest, 1);
01805         else
01806                 memcpy(dest, source, typeInfo->size);
01807 }
01808 
01809 void CustomData_em_set_n(CustomData *data, void *block, int type, int n, void *source)
01810 {
01811         void *dest = CustomData_em_get_n(data, block, type, n);
01812         const LayerTypeInfo *typeInfo = layerType_getInfo(type);
01813 
01814         if(!dest) return;
01815 
01816         if(typeInfo->copy)
01817                 typeInfo->copy(source, dest, 1);
01818         else
01819                 memcpy(dest, source, typeInfo->size);
01820 }
01821 
01822 void CustomData_em_interp(CustomData *data, void **src_blocks, float *weights,
01823                                                   float *sub_weights, int count, void *dest_block)
01824 {
01825         int i, j;
01826         void *source_buf[SOURCE_BUF_SIZE];
01827         void **sources = source_buf;
01828 
01829         /* slow fallback in case we're interpolating a ridiculous number of
01830          * elements
01831          */
01832         if(count > SOURCE_BUF_SIZE)
01833                 sources = MEM_callocN(sizeof(*sources) * count,
01834                                                           "CustomData_interp sources");
01835 
01836         /* interpolates a layer at a time */
01837         for(i = 0; i < data->totlayer; ++i) {
01838                 CustomDataLayer *layer = &data->layers[i];
01839                 const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
01840 
01841                 if(typeInfo->interp) {
01842                         for(j = 0; j < count; ++j)
01843                                 sources[j] = (char *)src_blocks[j] + layer->offset;
01844 
01845                         typeInfo->interp(sources, weights, sub_weights, count,
01846                                                           (char *)dest_block + layer->offset);
01847                 }
01848         }
01849 
01850         if(count > SOURCE_BUF_SIZE) MEM_freeN(sources);
01851 }
01852 
01853 void CustomData_em_set_default(CustomData *data, void **block)
01854 {
01855         const LayerTypeInfo *typeInfo;
01856         int i;
01857 
01858         if (!*block)
01859                 CustomData_em_alloc_block(data, block);
01860 
01861         for(i = 0; i < data->totlayer; ++i) {
01862                 int offset = data->layers[i].offset;
01863 
01864                 typeInfo = layerType_getInfo(data->layers[i].type);
01865 
01866                 if(typeInfo->set_default)
01867                         typeInfo->set_default((char*)*block + offset, 1);
01868         }
01869 }
01870 
01871 void CustomData_to_em_block(const CustomData *source, CustomData *dest,
01872                                                         int src_index, void **dest_block)
01873 {
01874         const LayerTypeInfo *typeInfo;
01875         int dest_i, src_i, src_offset;
01876 
01877         if (!*dest_block)
01878                 CustomData_em_alloc_block(dest, dest_block);
01879         
01880         /* copies a layer at a time */
01881         dest_i = 0;
01882         for(src_i = 0; src_i < source->totlayer; ++src_i) {
01883 
01884                 /* find the first dest layer with type >= the source type
01885                  * (this should work because layers are ordered by type)
01886                  */
01887                 while(dest_i < dest->totlayer
01888                           && dest->layers[dest_i].type < source->layers[src_i].type)
01889                         ++dest_i;
01890 
01891                 /* if there are no more dest layers, we're done */
01892                 if(dest_i >= dest->totlayer) return;
01893 
01894                 /* if we found a matching layer, copy the data */
01895                 if(dest->layers[dest_i].type == source->layers[src_i].type) {
01896                         int offset = dest->layers[dest_i].offset;
01897                         char *src_data = source->layers[src_i].data;
01898                         char *dest_data = (char*)*dest_block + offset;
01899 
01900                         typeInfo = layerType_getInfo(dest->layers[dest_i].type);
01901                         src_offset = src_index * typeInfo->size;
01902 
01903                         if(typeInfo->copy)
01904                                 typeInfo->copy(src_data + src_offset, dest_data, 1);
01905                         else
01906                                 memcpy(dest_data, src_data + src_offset, typeInfo->size);
01907 
01908                         /* if there are multiple source & dest layers of the same type,
01909                          * we don't want to copy all source layers to the same dest, so
01910                          * increment dest_i
01911                          */
01912                         ++dest_i;
01913                 }
01914         }
01915 }
01916 
01917 void CustomData_from_em_block(const CustomData *source, CustomData *dest,
01918                                                           void *src_block, int dest_index)
01919 {
01920         const LayerTypeInfo *typeInfo;
01921         int dest_i, src_i, dest_offset;
01922 
01923         /* copies a layer at a time */
01924         dest_i = 0;
01925         for(src_i = 0; src_i < source->totlayer; ++src_i) {
01926 
01927                 /* find the first dest layer with type >= the source type
01928                  * (this should work because layers are ordered by type)
01929                  */
01930                 while(dest_i < dest->totlayer
01931                           && dest->layers[dest_i].type < source->layers[src_i].type)
01932                         ++dest_i;
01933 
01934                 /* if there are no more dest layers, we're done */
01935                 if(dest_i >= dest->totlayer) return;
01936 
01937                 /* if we found a matching layer, copy the data */
01938                 if(dest->layers[dest_i].type == source->layers[src_i].type) {
01939                         int offset = source->layers[src_i].offset;
01940                         char *src_data = (char*)src_block + offset;
01941                         char *dest_data = dest->layers[dest_i].data;
01942 
01943                         typeInfo = layerType_getInfo(dest->layers[dest_i].type);
01944                         dest_offset = dest_index * typeInfo->size;
01945 
01946                         if(typeInfo->copy)
01947                                 typeInfo->copy(src_data, dest_data + dest_offset, 1);
01948                         else
01949                                 memcpy(dest_data + dest_offset, src_data, typeInfo->size);
01950 
01951                         /* if there are multiple source & dest layers of the same type,
01952                          * we don't want to copy all source layers to the same dest, so
01953                          * increment dest_i
01954                          */
01955                         ++dest_i;
01956                 }
01957         }
01958 
01959 }
01960 
01961 /*Bmesh functions*/
01962 /*needed to convert to/from different face reps*/
01963 void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata)
01964 {
01965         int i;
01966         for(i=0; i < fdata->totlayer; i++){
01967                 if(fdata->layers[i].type == CD_MTFACE){
01968                         CustomData_add_layer(pdata, CD_MTEXPOLY, CD_CALLOC, &(fdata->layers[i].name), 0);
01969                         CustomData_add_layer(ldata, CD_MLOOPUV, CD_CALLOC, &(fdata->layers[i].name), 0);
01970                 }
01971                 else if(fdata->layers[i].type == CD_MCOL)
01972                         CustomData_add_layer(ldata, CD_MLOOPCOL, CD_CALLOC, &(fdata->layers[i].name), 0);
01973         }               
01974 }
01975 void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, int total){
01976         int i;
01977         for(i=0; i < pdata->totlayer; i++){
01978                 if(pdata->layers[i].type == CD_MTEXPOLY)
01979                         CustomData_add_layer(fdata, CD_MTFACE, CD_CALLOC, &(pdata->layers[i].name), total);
01980         }
01981         for(i=0; i < ldata->totlayer; i++){
01982                 if(ldata->layers[i].type == CD_MLOOPCOL)
01983                         CustomData_add_layer(fdata, CD_MCOL, CD_CALLOC, &(ldata->layers[i].name), total);
01984         }
01985 }
01986 
01987 
01988 void CustomData_bmesh_init_pool(CustomData *data, int allocsize){
01989         if(data->totlayer)data->pool = BLI_mempool_create(data->totsize, allocsize, allocsize, 0);
01990 }
01991 
01992 void CustomData_bmesh_free_block(CustomData *data, void **block)
01993 {
01994         const LayerTypeInfo *typeInfo;
01995         int i;
01996 
01997         if(!*block) return;
01998         for(i = 0; i < data->totlayer; ++i) {
01999                 if(!(data->layers[i].flag & CD_FLAG_NOFREE)) {
02000                         typeInfo = layerType_getInfo(data->layers[i].type);
02001 
02002                         if(typeInfo->free) {
02003                                 int offset = data->layers[i].offset;
02004                                 typeInfo->free((char*)*block + offset, 1, typeInfo->size);
02005                         }
02006                 }
02007         }
02008 
02009         BLI_mempool_free(data->pool, *block);
02010         *block = NULL;
02011 }
02012 
02013 static void CustomData_bmesh_alloc_block(CustomData *data, void **block)
02014 {
02015 
02016         if (*block)
02017                 CustomData_bmesh_free_block(data, block);
02018 
02019         if (data->totsize > 0)
02020                 *block = BLI_mempool_calloc(data->pool);
02021         else
02022                 *block = NULL;
02023 }
02024 
02025 void CustomData_bmesh_copy_data(const CustomData *source, CustomData *dest,
02026                                                         void *src_block, void **dest_block)
02027 {
02028         const LayerTypeInfo *typeInfo;
02029         int dest_i, src_i;
02030 
02031         if (!*dest_block)
02032                 CustomData_bmesh_alloc_block(dest, dest_block);
02033         
02034         /* copies a layer at a time */
02035         dest_i = 0;
02036         for(src_i = 0; src_i < source->totlayer; ++src_i) {
02037 
02038                 /* find the first dest layer with type >= the source type
02039                  * (this should work because layers are ordered by type)
02040                  */
02041                 while(dest_i < dest->totlayer
02042                           && dest->layers[dest_i].type < source->layers[src_i].type)
02043                         ++dest_i;
02044 
02045                 /* if there are no more dest layers, we're done */
02046                 if(dest_i >= dest->totlayer) return;
02047 
02048                 /* if we found a matching layer, copy the data */
02049                 if(dest->layers[dest_i].type == source->layers[src_i].type &&
02050                         strcmp(dest->layers[dest_i].name, source->layers[src_i].name) == 0) {
02051                         char *src_data = (char*)src_block + source->layers[src_i].offset;
02052                         char *dest_data = (char*)*dest_block + dest->layers[dest_i].offset;
02053 
02054                         typeInfo = layerType_getInfo(source->layers[src_i].type);
02055 
02056                         if(typeInfo->copy)
02057                                 typeInfo->copy(src_data, dest_data, 1);
02058                         else
02059                                 memcpy(dest_data, src_data, typeInfo->size);
02060 
02061                         /* if there are multiple source & dest layers of the same type,
02062                          * we don't want to copy all source layers to the same dest, so
02063                          * increment dest_i
02064                          */
02065                         ++dest_i;
02066                 }
02067         }
02068 }
02069 
02070 /*Bmesh Custom Data Functions. Should replace editmesh ones with these as well, due to more effecient memory alloc*/
02071 void *CustomData_bmesh_get(const CustomData *data, void *block, int type)
02072 {
02073         int layer_index;
02074         
02075         /* get the layer index of the first layer of type */
02076         layer_index = CustomData_get_active_layer_index(data, type);
02077         if(layer_index < 0) return NULL;
02078 
02079         return (char *)block + data->layers[layer_index].offset;
02080 }
02081 
02082 void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int n)
02083 {
02084         int layer_index;
02085         
02086         /* get the layer index of the first layer of type */
02087         layer_index = CustomData_get_layer_index(data, type);
02088         if(layer_index < 0) return NULL;
02089 
02090         return (char *)block + data->layers[layer_index+n].offset;
02091 }
02092 
02093 void CustomData_bmesh_set(const CustomData *data, void *block, int type, void *source)
02094 {
02095         void *dest = CustomData_bmesh_get(data, block, type);
02096         const LayerTypeInfo *typeInfo = layerType_getInfo(type);
02097 
02098         if(!dest) return;
02099 
02100         if(typeInfo->copy)
02101                 typeInfo->copy(source, dest, 1);
02102         else
02103                 memcpy(dest, source, typeInfo->size);
02104 }
02105 
02106 void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, void *source)
02107 {
02108         void *dest = CustomData_bmesh_get_n(data, block, type, n);
02109         const LayerTypeInfo *typeInfo = layerType_getInfo(type);
02110 
02111         if(!dest) return;
02112 
02113         if(typeInfo->copy)
02114                 typeInfo->copy(source, dest, 1);
02115         else
02116                 memcpy(dest, source, typeInfo->size);
02117 }
02118 
02119 void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights,
02120                                                   float *sub_weights, int count, void *dest_block)
02121 {
02122         int i, j;
02123         void *source_buf[SOURCE_BUF_SIZE];
02124         void **sources = source_buf;
02125 
02126         /* slow fallback in case we're interpolating a ridiculous number of
02127          * elements
02128          */
02129         if(count > SOURCE_BUF_SIZE)
02130                 sources = MEM_callocN(sizeof(*sources) * count,
02131                                                           "CustomData_interp sources");
02132 
02133         /* interpolates a layer at a time */
02134         for(i = 0; i < data->totlayer; ++i) {
02135                 CustomDataLayer *layer = &data->layers[i];
02136                 const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
02137                 if(typeInfo->interp) {
02138                         for(j = 0; j < count; ++j)
02139                                 sources[j] = (char *)src_blocks[j] + layer->offset;
02140 
02141                         typeInfo->interp(sources, weights, sub_weights, count,
02142                                                           (char *)dest_block + layer->offset);
02143                 }
02144         }
02145 
02146         if(count > SOURCE_BUF_SIZE) MEM_freeN(sources);
02147 }
02148 
02149 void CustomData_bmesh_set_default(CustomData *data, void **block)
02150 {
02151         const LayerTypeInfo *typeInfo;
02152         int i;
02153 
02154         if (!*block)
02155                 CustomData_bmesh_alloc_block(data, block);
02156 
02157         for(i = 0; i < data->totlayer; ++i) {
02158                 int offset = data->layers[i].offset;
02159 
02160                 typeInfo = layerType_getInfo(data->layers[i].type);
02161 
02162                 if(typeInfo->set_default)
02163                         typeInfo->set_default((char*)*block + offset, 1);
02164         }
02165 }
02166 
02167 void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest,
02168                                                         int src_index, void **dest_block)
02169 {
02170         const LayerTypeInfo *typeInfo;
02171         int dest_i, src_i, src_offset;
02172 
02173         if (!*dest_block)
02174                 CustomData_bmesh_alloc_block(dest, dest_block);
02175         
02176         /* copies a layer at a time */
02177         dest_i = 0;
02178         for(src_i = 0; src_i < source->totlayer; ++src_i) {
02179 
02180                 /* find the first dest layer with type >= the source type
02181                  * (this should work because layers are ordered by type)
02182                  */
02183                 while(dest_i < dest->totlayer
02184                           && dest->layers[dest_i].type < source->layers[src_i].type)
02185                         ++dest_i;
02186 
02187                 /* if there are no more dest layers, we're done */
02188                 if(dest_i >= dest->totlayer) return;
02189 
02190                 /* if we found a matching layer, copy the data */
02191                 if(dest->layers[dest_i].type == source->layers[src_i].type) {
02192                         int offset = dest->layers[dest_i].offset;
02193                         char *src_data = source->layers[src_i].data;
02194                         char *dest_data = (char*)*dest_block + offset;
02195 
02196                         typeInfo = layerType_getInfo(dest->layers[dest_i].type);
02197                         src_offset = src_index * typeInfo->size;
02198 
02199                         if(typeInfo->copy)
02200                                 typeInfo->copy(src_data + src_offset, dest_data, 1);
02201                         else
02202                                 memcpy(dest_data, src_data + src_offset, typeInfo->size);
02203 
02204                         /* if there are multiple source & dest layers of the same type,
02205                          * we don't want to copy all source layers to the same dest, so
02206                          * increment dest_i
02207                          */
02208                         ++dest_i;
02209                 }
02210         }
02211 }
02212 
02213 void CustomData_from_bmesh_block(const CustomData *source, CustomData *dest,
02214                                                           void *src_block, int dest_index)
02215 {
02216         const LayerTypeInfo *typeInfo;
02217         int dest_i, src_i, dest_offset;
02218 
02219         /* copies a layer at a time */
02220         dest_i = 0;
02221         for(src_i = 0; src_i < source->totlayer; ++src_i) {
02222 
02223                 /* find the first dest layer with type >= the source type
02224                  * (this should work because layers are ordered by type)
02225                  */
02226                 while(dest_i < dest->totlayer
02227                           && dest->layers[dest_i].type < source->layers[src_i].type)
02228                         ++dest_i;
02229 
02230                 /* if there are no more dest layers, we're done */
02231                 if(dest_i >= dest->totlayer) return;
02232 
02233                 /* if we found a matching layer, copy the data */
02234                 if(dest->layers[dest_i].type == source->layers[src_i].type) {
02235                         int offset = source->layers[src_i].offset;
02236                         char *src_data = (char*)src_block + offset;
02237                         char *dest_data = dest->layers[dest_i].data;
02238 
02239                         typeInfo = layerType_getInfo(dest->layers[dest_i].type);
02240                         dest_offset = dest_index * typeInfo->size;
02241 
02242                         if(typeInfo->copy)
02243                                 typeInfo->copy(src_data, dest_data + dest_offset, 1);
02244                         else
02245                                 memcpy(dest_data + dest_offset, src_data, typeInfo->size);
02246 
02247                         /* if there are multiple source & dest layers of the same type,
02248                          * we don't want to copy all source layers to the same dest, so
02249                          * increment dest_i
02250                          */
02251                         ++dest_i;
02252                 }
02253         }
02254 
02255 }
02256 
02257 void CustomData_file_write_info(int type, const char **structname, int *structnum)
02258 {
02259         const LayerTypeInfo *typeInfo = layerType_getInfo(type);
02260 
02261         *structname = typeInfo->structname;
02262         *structnum = typeInfo->structnum;
02263 }
02264 
02265 int CustomData_sizeof(int type)
02266 {
02267         const LayerTypeInfo *typeInfo = layerType_getInfo(type);
02268 
02269         return typeInfo->size;
02270 }
02271 
02272 const char *CustomData_layertype_name(int type)
02273 {
02274         return layerType_getName(type);
02275 }
02276 
02277 static int  CustomData_is_property_layer(int type)
02278 {
02279         if((type == CD_PROP_FLT) || (type == CD_PROP_INT) || (type == CD_PROP_STR))
02280                 return 1;
02281         return 0;
02282 }
02283 
02284 static int cd_layer_find_dupe(CustomData *data, const char *name, int type, int index)
02285 {
02286         int i;
02287         /* see if there is a duplicate */
02288         for(i=0; i<data->totlayer; i++) {
02289                 if(i != index) {
02290                         CustomDataLayer *layer= &data->layers[i];
02291                         
02292                         if(CustomData_is_property_layer(type)) {
02293                                 if(CustomData_is_property_layer(layer->type) && strcmp(layer->name, name)==0) {
02294                                         return 1;
02295                                 }
02296                         }
02297                         else{
02298                                 if(i!=index && layer->type==type && strcmp(layer->name, name)==0) {
02299                                         return 1;
02300                                 }
02301                         }
02302                 }
02303         }
02304         
02305         return 0;
02306 }
02307 
02308 static int customdata_unique_check(void *arg, const char *name)
02309 {
02310         struct {CustomData *data; int type; int index;} *data_arg= arg;
02311         return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg->index);
02312 }
02313 
02314 void CustomData_set_layer_unique_name(CustomData *data, int index)
02315 {       
02316         CustomDataLayer *nlayer= &data->layers[index];
02317         const LayerTypeInfo *typeInfo= layerType_getInfo(nlayer->type);
02318 
02319         struct {CustomData *data; int type; int index;} data_arg;
02320         data_arg.data= data;
02321         data_arg.type= nlayer->type;
02322         data_arg.index= index;
02323 
02324         if (!typeInfo->defaultname)
02325                 return;
02326         
02327         BLI_uniquename_cb(customdata_unique_check, &data_arg, typeInfo->defaultname, '.', nlayer->name, sizeof(nlayer->name));
02328 }
02329 
02330 int CustomData_verify_versions(struct CustomData *data, int index)
02331 {
02332         const LayerTypeInfo *typeInfo;
02333         CustomDataLayer *layer = &data->layers[index];
02334         int i, keeplayer = 1;
02335 
02336         if (layer->type >= CD_NUMTYPES) {
02337                 keeplayer = 0; /* unknown layer type from future version */
02338         }
02339         else {
02340                 typeInfo = layerType_getInfo(layer->type);
02341 
02342                 if (!typeInfo->defaultname && (index > 0) &&
02343                         data->layers[index-1].type == layer->type)
02344                         keeplayer = 0; /* multiple layers of which we only support one */
02345         }
02346 
02347         if (!keeplayer) {
02348                 for (i=index+1; i < data->totlayer; ++i)
02349                         data->layers[i-1] = data->layers[i];
02350                 data->totlayer--;
02351         }
02352 
02353         return keeplayer;
02354 }
02355 
02356 /****************************** External Files *******************************/
02357 
02358 static void customdata_external_filename(char filename[FILE_MAX], ID *id, CustomDataExternal *external)
02359 {
02360         char *path = (id->lib)? id->lib->filepath: G.main->name;
02361 
02362         BLI_strncpy(filename, external->filename, FILE_MAX);
02363         BLI_path_abs(filename, path);
02364 }
02365 
02366 void CustomData_external_reload(CustomData *data, ID *UNUSED(id), CustomDataMask mask, int totelem)
02367 {
02368         CustomDataLayer *layer;
02369         const LayerTypeInfo *typeInfo;
02370         int i;
02371 
02372         for(i=0; i<data->totlayer; i++) {
02373                 layer = &data->layers[i];
02374                 typeInfo = layerType_getInfo(layer->type);
02375 
02376                 if(!(mask & (1<<layer->type)));
02377                 else if((layer->flag & CD_FLAG_EXTERNAL) && (layer->flag & CD_FLAG_IN_MEMORY)) {
02378                         if(typeInfo->free)
02379                                 typeInfo->free(layer->data, totelem, typeInfo->size);
02380                         layer->flag &= ~CD_FLAG_IN_MEMORY;
02381                 }
02382         }
02383 }
02384 
02385 void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int totelem)
02386 {
02387         CustomDataExternal *external= data->external;
02388         CustomDataLayer *layer;
02389         CDataFile *cdf;
02390         CDataFileLayer *blay;
02391         char filename[FILE_MAX];
02392         const LayerTypeInfo *typeInfo;
02393         int i, update = 0;
02394 
02395         if(!external)
02396                 return;
02397         
02398         for(i=0; i<data->totlayer; i++) {
02399                 layer = &data->layers[i];
02400                 typeInfo = layerType_getInfo(layer->type);
02401 
02402                 if(!(mask & (1<<layer->type)));
02403                 else if(layer->flag & CD_FLAG_IN_MEMORY);
02404                 else if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read)
02405                         update= 1;
02406         }
02407 
02408         if(!update)
02409                 return;
02410 
02411         customdata_external_filename(filename, id, external);
02412 
02413         cdf= cdf_create(CDF_TYPE_MESH);
02414         if(!cdf_read_open(cdf, filename)) {
02415                 fprintf(stderr, "Failed to read %s layer from %s.\n", layerType_getName(layer->type), filename);
02416                 return;
02417         }
02418 
02419         for(i=0; i<data->totlayer; i++) {
02420                 layer = &data->layers[i];
02421                 typeInfo = layerType_getInfo(layer->type);
02422 
02423                 if(!(mask & (1<<layer->type)));
02424                 else if(layer->flag & CD_FLAG_IN_MEMORY);
02425                 else if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) {
02426                         blay= cdf_layer_find(cdf, layer->type, layer->name);
02427 
02428                         if(blay) {
02429                                 if(cdf_read_layer(cdf, blay)) {
02430                                         if(typeInfo->read(cdf, layer->data, totelem));
02431                                         else break;
02432                                         layer->flag |= CD_FLAG_IN_MEMORY;
02433                                 }
02434                                 else
02435                                         break;
02436                         }
02437                 }
02438         }
02439 
02440         cdf_read_close(cdf);
02441         cdf_free(cdf);
02442 }
02443 
02444 void CustomData_external_write(CustomData *data, ID *id, CustomDataMask mask, int totelem, int free)
02445 {
02446         CustomDataExternal *external= data->external;
02447         CustomDataLayer *layer;
02448         CDataFile *cdf;
02449         CDataFileLayer *blay;
02450         const LayerTypeInfo *typeInfo;
02451         int i, update = 0;
02452         char filename[FILE_MAX];
02453 
02454         if(!external)
02455                 return;
02456 
02457         /* test if there is anything to write */
02458         for(i=0; i<data->totlayer; i++) {
02459                 layer = &data->layers[i];
02460                 typeInfo = layerType_getInfo(layer->type);
02461 
02462                 if(!(mask & (1<<layer->type)));
02463                 else if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write)
02464                         update= 1;
02465         }
02466 
02467         if(!update)
02468                 return;
02469 
02470         /* make sure data is read before we try to write */
02471         CustomData_external_read(data, id, mask, totelem);
02472         customdata_external_filename(filename, id, external);
02473 
02474         cdf= cdf_create(CDF_TYPE_MESH);
02475 
02476         for(i=0; i<data->totlayer; i++) {
02477                 layer = &data->layers[i];
02478                 typeInfo = layerType_getInfo(layer->type);
02479 
02480                 if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->filesize) {
02481                         if(layer->flag & CD_FLAG_IN_MEMORY) {
02482                                 cdf_layer_add(cdf, layer->type, layer->name,
02483                                         typeInfo->filesize(cdf, layer->data, totelem));
02484                         }
02485                         else {
02486                                 cdf_free(cdf);
02487                                 return; /* read failed for a layer! */
02488                         }
02489                 }
02490         }
02491 
02492         if(!cdf_write_open(cdf, filename)) {
02493                 fprintf(stderr, "Failed to open %s for writing.\n", filename);
02494                 return;
02495         }
02496 
02497         for(i=0; i<data->totlayer; i++) {
02498                 layer = &data->layers[i];
02499                 typeInfo = layerType_getInfo(layer->type);
02500 
02501                 if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
02502                         blay= cdf_layer_find(cdf, layer->type, layer->name);
02503 
02504                         if(cdf_write_layer(cdf, blay)) {
02505                                 if(typeInfo->write(cdf, layer->data, totelem));
02506                                 else break;
02507                         }
02508                         else
02509                                 break;
02510                 }
02511         }
02512 
02513         if(i != data->totlayer) {
02514                 fprintf(stderr, "Failed to write data to %s.\n", filename);
02515                 cdf_free(cdf);
02516                 return;
02517         }
02518 
02519         for(i=0; i<data->totlayer; i++) {
02520                 layer = &data->layers[i];
02521                 typeInfo = layerType_getInfo(layer->type);
02522 
02523                 if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
02524                         if(free) {
02525                                 if(typeInfo->free)
02526                                         typeInfo->free(layer->data, totelem, typeInfo->size);
02527                                 layer->flag &= ~CD_FLAG_IN_MEMORY;
02528                         }
02529                 }
02530         }
02531 
02532         cdf_write_close(cdf);
02533         cdf_free(cdf);
02534 }
02535 
02536 void CustomData_external_add(CustomData *data, ID *UNUSED(id), int type, int UNUSED(totelem), const char *filename)
02537 {
02538         CustomDataExternal *external= data->external;
02539         CustomDataLayer *layer;
02540         int layer_index;
02541 
02542         layer_index = CustomData_get_active_layer_index(data, type);
02543         if(layer_index < 0) return;
02544 
02545         layer = &data->layers[layer_index];
02546 
02547         if(layer->flag & CD_FLAG_EXTERNAL)
02548                 return;
02549 
02550         if(!external) {
02551                 external= MEM_callocN(sizeof(CustomDataExternal), "CustomDataExternal");
02552                 data->external= external;
02553         }
02554         BLI_strncpy(external->filename, filename, sizeof(external->filename));
02555 
02556         layer->flag |= CD_FLAG_EXTERNAL|CD_FLAG_IN_MEMORY;
02557 }
02558 
02559 void CustomData_external_remove(CustomData *data, ID *id, int type, int totelem)
02560 {
02561         CustomDataExternal *external= data->external;
02562         CustomDataLayer *layer;
02563         //char filename[FILE_MAX];
02564         int layer_index; // i, remove_file;
02565 
02566         layer_index = CustomData_get_active_layer_index(data, type);
02567         if(layer_index < 0) return;
02568 
02569         layer = &data->layers[layer_index];
02570 
02571         if(!external)
02572                 return;
02573 
02574         if(layer->flag & CD_FLAG_EXTERNAL) {
02575                 if(!(layer->flag & CD_FLAG_IN_MEMORY))
02576                         CustomData_external_read(data, id, (1<<layer->type), totelem);
02577 
02578                 layer->flag &= ~CD_FLAG_EXTERNAL;
02579 
02580 #if 0
02581                 remove_file= 1;
02582                 for(i=0; i<data->totlayer; i++)
02583                         if(data->layers[i].flag & CD_FLAG_EXTERNAL)
02584                                 remove_file= 0;
02585 
02586                 if(remove_file) {
02587                         customdata_external_filename(filename, id, external);
02588                         cdf_remove(filename);
02589                         CustomData_external_free(data);
02590                 }
02591 #endif
02592         }
02593 }
02594 
02595 int CustomData_external_test(CustomData *data, int type)
02596 {
02597         CustomDataLayer *layer;
02598         int layer_index;
02599 
02600         layer_index = CustomData_get_active_layer_index(data, type);
02601         if(layer_index < 0) return 0;
02602 
02603         layer = &data->layers[layer_index];
02604         return (layer->flag & CD_FLAG_EXTERNAL);
02605 }
02606 
02607 #if 0
02608 void CustomData_external_remove_object(CustomData *data, ID *id)
02609 {
02610         CustomDataExternal *external= data->external;
02611         char filename[FILE_MAX];
02612 
02613         if(!external)
02614                 return;
02615 
02616         customdata_external_filename(filename, id, external);
02617         cdf_remove(filename);
02618         CustomData_external_free(data);
02619 }
02620 #endif
02621