LEFT | RIGHT |
1 /* | 1 /* |
2 * ***** BEGIN GPL LICENSE BLOCK ***** | 2 * ***** BEGIN GPL LICENSE BLOCK ***** |
3 * | 3 * |
4 * This program is free software; you can redistribute it and/or | 4 * This program is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU General Public License | 5 * modify it under the terms of the GNU General Public License |
6 * as published by the Free Software Foundation; either version 2 | 6 * as published by the Free Software Foundation; either version 2 |
7 * of the License, or (at your option) any later version. | 7 * of the License, or (at your option) any later version. |
8 * | 8 * |
9 * This program is distributed in the hope that it will be useful, | 9 * This program is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
985 madd_v3_v3fl(co, in[i], weights[i]); | 985 madd_v3_v3fl(co, in[i], weights[i]); |
986 } | 986 } |
987 } | 987 } |
988 else { | 988 else { |
989 for (i = 0; i < count; ++i) { | 989 for (i = 0; i < count; ++i) { |
990 add_v3_v3(co, in[i]); | 990 add_v3_v3(co, in[i]); |
991 } | 991 } |
992 } | 992 } |
993 } | 993 } |
994 | 994 |
995 static void layerDefault_mvert_skin(void *data, int count) | |
996 { | |
997 MVertSkin *vs = data; | |
998 int i; | |
999 ········ | |
1000 for(i = 0; i < count; i++) { | |
1001 vs[i].radius[0] = 0.25f; | |
1002 vs[i].radius[1] = 0.25f; | |
1003 vs[i].radius[2] = 0.25f; | |
1004 vs[i].flag = 0; | |
1005 } | |
1006 } | |
1007 · | |
1008 static void layerInterp_mvert_skin(void **sources, float *weights, | |
1009 float *UNUSED
(sub_weights), | |
1010 int count, vo
id *dest) | |
1011 { | |
1012 float radius[3], w; | |
1013 MVertSkin *vs; | |
1014 int i; | |
1015 | |
1016 zero_v3(radius); | |
1017 for(i = 0; i < count; i++) { | |
1018 w = weights ? weights[i] : 1.0f; | |
1019 vs = sources[i]; | |
1020 | |
1021 madd_v3_v3fl(radius, vs->radius, w); | |
1022 } | |
1023 | |
1024 vs = dest; | |
1025 copy_v3_v3(vs->radius, radius); | |
1026 vs->flag &= ~MVERT_SKIN_ROOT; | |
1027 } | |
1028 | |
1029 static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { | 995 static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { |
1030 /* 0: CD_MVERT */ | 996 /* 0: CD_MVERT */ |
1031 {sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL}, | 997 {sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL}, |
1032 /* 1: CD_MSTICKY */ | |
1033 {sizeof(MSticky), "MSticky", 1, NULL, NULL, NULL, layerInterp_msticky, N
ULL, | |
1034 NULL}, | |
1035 /* 2: CD_MDEFORMVERT */ | |
1036 {sizeof(MDeformVert), "MDeformVert", 1, NULL, layerCopy_mdeformvert, | |
1037 layerFree_mdeformvert, layerInterp_mdeformvert, NULL, NULL}, | |
1038 /* 3: CD_MEDGE */ | |
1039 {sizeof(MEdge), "MEdge", 1, NULL, NULL, NULL, NULL, NULL, NULL}, | |
1040 /* 4: CD_MFACE */ | |
1041 {sizeof(MFace), "MFace", 1, NULL, NULL, NULL, NULL, NULL, NULL}, | |
1042 /* 5: CD_MTFACE */ | |
1043 {sizeof(MTFace), "MTFace", 1, "UVMap", layerCopy_tface, NULL, | |
1044 layerInterp_tface, layerSwap_tface, layerDefault_tface}, | |
1045 /* 6: CD_MCOL */ | |
1046 /* 4 MCol structs per face */ | |
1047 {sizeof(MCol) * 4, "MCol", 4, "Col", NULL, NULL, layerInterp_mcol, | |
1048 layerSwap_mcol, layerDefault_mcol}, | |
1049 /* 7: CD_ORIGINDEX */ | |
1050 {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, | |
1051 /* 8: CD_NORMAL */ | |
1052 /* 3 floats per normal vector */ | |
1053 {sizeof(float) * 3, "vec3f", 1, NULL, NULL, NULL, NULL, NULL, NULL}, | |
1054 /* 9: CD_POLYINDEX */ | |
1055 {sizeof(int), "MIntProperty", 1, NULL, NULL, NULL, NULL, NULL, NULL}, | |
1056 /* 10: CD_PROP_FLT */ | |
1057 {sizeof(MFloatProperty), "MFloatProperty", 1, "Float", layerCopy_propFlo
at, NULL, NULL, NULL}, | |
1058 /* 11: CD_PROP_INT */ | |
1059 {sizeof(MIntProperty), "MIntProperty", 1, "Int", layerCopy_propInt, NULL
, NULL, NULL}, | |
1060 /* 12: CD_PROP_STR */ | |
1061 {sizeof(MStringProperty), "MStringProperty", 1, "String", layerCopy_prop
String, NULL, NULL, NULL}, | |
1062 /* 13: CD_ORIGSPACE */ | |
1063 {sizeof(OrigSpaceFace), "OrigSpaceFace", 1, "UVMap", layerCopy_origspace
_face, NULL, | |
1064 layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_orig
space_face}, | |
1065 /* 14: CD_ORCO */ | |
1066 {sizeof(float) * 3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, | |
1067 /* 15: CD_MTEXPOLY */ | |
1068 /* note, when we expose the UV Map / TexFace split to the user, change t
his back to face Texture */ | |
1069 {sizeof(MTexPoly), "MTexPoly", 1, "UVMap" /* "Face Texture" */, NULL, NU
LL, NULL, NULL, NULL}, | |
1070 /* 16: CD_MLOOPUV */ | |
1071 {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloo
puv, NULL, NULL, | |
1072 layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv,· | |
1073 layerAdd_mloopuv, layerDoMinMax_mloopuv, layerCopyValue_mloopuv}, | |
1074 /* 17: CD_MLOOPCOL */ | |
1075 {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopco
l, NULL,· | |
1076 layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, lay
erInitMinMax_mloopcol,· | |
1077 layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, | |
1078 /* 18: CD_TANGENT */ | |
1079 {sizeof(float) * 4 * 4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, | |
1080 /* 19: CD_MDISPS */ | |
1081 {sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps, | |
1082 layerFree_mdisps, NULL, layerSwap_mdisps, NULL, | |
1083 NULL, NULL, NULL, NULL, NULL, NULL,· | |
1084 layerRead_mdisps, layerWrite_mdisps, layerFilesize_mdisps}, | |
1085 /* 20: CD_PREVIEW_MCOL */ | |
1086 {sizeof(MCol) * 4, "MCol", 4, "PreviewCol", NULL, NULL, layerInterp_mcol
, | |
1087 layerSwap_mcol, layerDefault_mcol}, | |
1088 /* 21: CD_ID_MCOL */ | |
1089 {sizeof(MCol) * 4, "MCol", 4, "IDCol", NULL, NULL, layerInterp_mcol, | |
1090 layerSwap_mcol, layerDefault_mcol}, | |
1091 /* 22: CD_TEXTURE_MCOL */ | |
1092 {sizeof(MCol) * 4, "MCol", 4, "TexturedCol", NULL, NULL, layerInterp_mco
l, | |
1093 layerSwap_mcol, layerDefault_mcol}, | |
1094 /* 23: CD_CLOTH_ORCO */ | |
1095 {sizeof(float) * 3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, | |
1096 /* 24: CD_RECAST */ | |
1097 {sizeof(MRecast), "MRecast", 1, "Recast", NULL, NULL, NULL, NULL}, | |
1098 | |
1099 /* BMESH ONLY */ | |
1100 /* 25: CD_MPOLY */ | |
1101 {sizeof(MPoly), "MPoly", 1, "NGon Face", NULL, NULL, NULL, NULL, NULL}, | |
1102 /* 26: CD_MLOOP */ | |
1103 {sizeof(MLoop), "MLoop", 1, "NGon Face-Vertex", NULL, NULL, NULL, NULL,
NULL}, | |
1104 /* 27: CD_SHAPE_KEYINDEX */ | |
1105 {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, | |
1106 /* 28: CD_SHAPEKEY */ | |
1107 {sizeof(float) * 3, "", 0, "ShapeKey", NULL, NULL, layerInterp_shapekey}
, | |
1108 /* 29: CD_BWEIGHT */ | |
1109 {sizeof(float), "", 0, "BevelWeight", NULL, NULL, layerInterp_bweight}, | |
1110 /* 30: CD_CREASE */ | |
1111 {sizeof(float), "", 0, "SubSurfCrease", NULL, NULL, layerInterp_bweight}
, | |
1112 /* 31: CD_ORIGSPACE_MLOOP */ | |
1113 {sizeof(OrigSpaceLoop), "OrigSpaceLoop", 1, "OS Loop", NULL, NULL, layer
Interp_mloop_origspace, NULL, NULL, | |
1114 layerEqual_mloop_origspace, layerMultiply_mloop_origspace, layerInitMin
Max_mloop_origspace, | |
1115 layerAdd_mloop_origspace, layerDoMinMax_mloop_origspace, layerCopyValue
_mloop_origspace}, | |
1116 /* 32: CD_PREVIEW_MLOOPCOL */ | |
1117 {sizeof(MLoopCol), "MLoopCol", 1, "PreviewLoopCol", NULL, NULL, layerInt
erp_mloopcol, NULL, | |
1118 layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, lay
erInitMinMax_mloopcol, | |
1119 layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, | |
1120 /* 33: CD_BM_ELEM_PYPTR */ | |
1121 {sizeof(void *), "", 1, NULL, layerCopy_bmesh_elem_py_ptr, | |
1122 layerFree_bmesh_elem_py_ptr, NULL, NULL, NULL}, | |
1123 | |
1124 /* END BMESH ONLY */ | |
1125 | |
1126 /* 34: CD_PAINT_MASK */ | |
1127 {sizeof(float), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, | |
1128 /* 35: CD_GRID_PAINT_MASK */ | |
1129 {sizeof(GridPaintMask), "GridPaintMask", 1, NULL, layerCopy_grid_paint_m
ask, | |
1130 layerFree_grid_paint_mask, NULL, NULL, NULL}, | |
1131 /* 36: CD_SKIN_NODE */ | |
1132 {sizeof(MVertSkin), "MVertSkin", 1, "Skin", NULL, NULL, | |
1133 layerInterp_mvert_skin, NULL, layerDefault_mvert_skin} | |
1134 }; | |
1135 | |
1136 /* note, numbers are from trunk and need updating for bmesh */ | |
1137 | |
1138 static const char *LAYERTYPENAMES[CD_NUMTYPES] = { | |
1139 /* 0-4 */ "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace
", | |
1140 /* 5-9 */ "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags", | |
1141 /* 10-14 */ "CDMFloatProperty", "CDMIntProperty", "CDMStringProperty", "
CDOrigSpace", "CDOrco", | |
1142 /* 15-19 */ "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent", "CDMDi
sps", | |
1143 /* 20-24 */ "CDPreviewMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco",
"CDMRecast", | |
1144 | |
1145 /* BMESH ONLY */ | |
1146 /* 25-29 */ "CDMPoly", "CDMLoop", "CDShapeKeyIndex", "CDShapeKey", "CDBe
velWeight", | |
1147 /* 30-34 */ "CDSubSurfCrease", "CDOrigSpaceLoop", "CDPreviewLoopCol", "C
DBMElemPyPtr", "CDPaintMask", | |
1148 /* 35-36 */ "CDGridPaintMask", "CDMVertSkin" | |
1149 }; | |
1150 | |
1151 | |
1152 const CustomDataMask CD_MASK_BAREMESH = | |
1153 CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MLOOP | CD_MASK_MPOL
Y | CD_MASK_BWEIGHT; | |
1154 const CustomDataMask CD_MASK_MESH = | |
1155 CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | | |
1156 CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL | | |
1157 CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS | | |
1158 CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MPOLY | CD_MASK_MLOOP | | |
1159 CD_MASK_MTEXPOLY | CD_MASK_NORMAL | CD_MASK_RECAST | CD_MASK_PAINT_MASK | | |
1160 CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN; | |
1161 const CustomDataMask CD_MASK_EDITMESH = | |
1162 CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MLOOPUV | | |
1163 CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_SHAPE_KEYINDEX | | |
1164 CD_MASK_MCOL | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | | |
1165 CD_MASK_MDISPS | CD_MASK_SHAPEKEY | CD_MASK_RECAST | CD_MASK_PAINT_MASK | | |
1166 CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN; | |
1167 const CustomDataMask CD_MASK_DERIVEDMESH = | |
1168 CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | | |
1169 CD_MASK_MCOL | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_CLOTH_ORCO | | |
1170 CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_PREVIEW_MLOO
PCOL | | |
1171 CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORIGSPACE_MLOOP | CD_MASK_ORC
O | CD_MASK_TANGENT | | |
1172 CD_MASK_PREVIEW_MCOL | CD_MASK_NORMAL | CD_MASK_SHAPEKEY | CD_MASK_RECAST | | |
1173 CD_MASK_ORIGINDEX | CD_MASK_POLYINDEX | CD_MASK_MVERT_SKIN; | |
1174 const CustomDataMask CD_MASK_BMESH = | |
1175 CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | | |
1176 CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT
| | |
1177 CD_MASK_PROP_STR | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_MDISP
S | | |
1178 CD_MASK_CREASE | CD_MASK_BWEIGHT | CD_MASK_RECAST | CD_MASK_PAINT_MASK | | |
1179 CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN; | |
1180 const CustomDataMask CD_MASK_FACECORNERS = | |
1181 CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | | |
1182 CD_MASK_MLOOPCOL; | |
1183 | |
1184 static const LayerTypeInfo *layerType_getInfo(int type) | |
1185 { | |
1186 if (type < 0 || type >= CD_NUMTYPES) return NULL; | |
1187 | |
1188 return &LAYERTYPEINFO[type]; | |
1189 } | |
1190 | |
1191 static const char *layerType_getName(int type) | |
1192 { | |
1193 if (type < 0 || type >= CD_NUMTYPES) return NULL; | |
1194 | |
1195 return LAYERTYPENAMES[type]; | |
1196 } | |
1197 | |
1198 /********************* CustomData functions *********************/ | |
1199 static void customData_update_offsets(CustomData *data); | |
1200 | |
1201 static CustomDataLayer *customData_add_layer__internal(CustomData *data, | |
1202 int type, int alloctype,
void *layerdata, int totelem, const char *name); | |
1203 | |
1204 void CustomData_update_typemap(CustomData *data) | |
1205 { | |
1206 int i, lasttype = -1; | |
1207 | |
1208 /* since we cant do in a pre-processor do here as an assert */ | |
1209 BLI_assert(sizeof(data->typemap) / sizeof(int) >= CD_NUMTYPES); | |
1210 | |
1211 for (i = 0; i < CD_NUMTYPES; i++) { | |
1212 data->typemap[i] = -1; | |
1213 } | |
1214 | |
1215 for (i = 0; i < data->totlayer; i++) { | |
1216 if (data->layers[i].type != lasttype) { | |
1217 data->typemap[data->layers[i].type] = i; | |
1218 } | |
1219 lasttype = data->layers[i].type; | |
1220 } | |
1221 } | |
1222 | |
1223 void CustomData_merge(const struct CustomData *source, struct CustomData *dest, | |
1224 CustomDataMask mask, int alloctype, int totelem) | |
1225 { | |
1226 /*const LayerTypeInfo *typeInfo;*/ | |
1227 CustomDataLayer *layer, *newlayer; | |
1228 void *data; | |
1229 int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0,
lastclone = 0, lastmask = 0, lastflag = 0; | |
1230 | |
1231 for (i = 0; i < source->totlayer; ++i) { | |
1232 layer = &source->layers[i]; | |
1233 /*typeInfo = layerType_getInfo(layer->type);*/ /*UNUSED*/ | |
1234 | |
1235 type = layer->type; | |
1236 | |
1237 if (type != lasttype) { | |
1238 number = 0; | |
1239 lastactive = layer->active; | |
1240 lastrender = layer->active_rnd; | |
1241 lastclone = layer->active_clone; | |
1242 lastmask = layer->active_mask; | |
1243 lasttype = type; | |
1244 lastflag = layer->flag; | |
1245 } | |
1246 else | |
1247 number++; | |
1248 | |
1249 if (lastflag & CD_FLAG_NOCOPY) continue; | |
1250 else if (!(mask & CD_TYPE_AS_MASK(type))) continue; | |
1251 else if (number < CustomData_number_of_layers(dest, type)) conti
nue; | |
1252 | |
1253 switch (alloctype) { | |
1254 case CD_ASSIGN: | |
1255 case CD_REFERENCE: | |
1256 case CD_DUPLICATE: | |
1257 data = layer->data; | |
1258 break; | |
1259 default: | |
1260 data = NULL; | |
1261 break; | |
1262 } | |
1263 | |
1264 if ((alloctype == CD_ASSIGN) && (lastflag & CD_FLAG_NOFREE)) | |
1265 newlayer = customData_add_layer__internal(dest, type, CD
_REFERENCE, | |
1266 data, totelem,
layer->name); | |
1267 else | |
1268 newlayer = customData_add_layer__internal(dest, type, al
loctype, | |
1269 data, totelem,
layer->name); | |
1270 ················ | |
1271 if (newlayer) { | |
1272 newlayer->uid = layer->uid; | |
1273 ························ | |
1274 newlayer->active = lastactive; | |
1275 newlayer->active_rnd = lastrender; | |
1276 newlayer->active_clone = lastclone; | |
1277 newlayer->active_mask = lastmask; | |
1278 newlayer->flag |= lastflag & (CD_FLAG_EXTERNAL | CD_FLAG
_IN_MEMORY); | |
1279 } | |
1280 } | |
1281 | |
1282 CustomData_update_typemap(dest); | |
1283 } | |
1284 | |
1285 void CustomData_copy(const struct CustomData *source, struct CustomData *dest, | |
1286 CustomDataMask mask, int alloctype, int totelem) | |
1287 { | |
1288 memset(dest, 0, sizeof(*dest)); | |
1289 | |
1290 if (source->external) | |
1291 dest->external = MEM_dupallocN(source->external); | |
1292 | |
1293 CustomData_merge(source, dest, mask, alloctype, totelem); | |
1294 } | |
1295 | |
1296 static void customData_free_layer__internal(CustomDataLayer *layer, int totelem) | |
1297 { | |
1298 const LayerTypeInfo *typeInfo; | |
1299 | |
1300 if (!(layer->flag & CD_FLAG_NOFREE) && layer->data) { | |
1301 typeInfo = layerType_getInfo(layer->type); | |
1302 | |
1303 if (typeInfo->free) | |
1304 typeInfo->free(layer->data, totelem, typeInfo->size); | |
1305 | |
1306 if (layer->data) | |
1307 MEM_freeN(layer->data); | |
1308 } | |
1309 } | |
1310 | |
1311 static void CustomData_external_free(CustomData *data) | |
1312 { | |
1313 if (data->external) { | |
1314 MEM_freeN(data->external); | |
1315 data->external = NULL; | |
1316 } | |
1317 } | |
1318 | |
1319 void CustomData_free(CustomData *data, int totelem) | |
1320 { | |
1321 int i; | |
1322 | |
1323 for (i = 0; i < data->totlayer; ++i) | |
1324 customData_free_layer__internal(&data->layers[i], totelem); | |
1325 | |
1326 if (data->layers) | |
1327 MEM_freeN(data->layers); | |
1328 ········ | |
1329 CustomData_external_free(data); | |
1330 ········ | |
1331 memset(data, 0, sizeof(*data)); | |
1332 } | |
1333 | |
1334 static void customData_update_offsets(CustomData *data) | |
1335 { | |
1336 const LayerTypeInfo *typeInfo; | |
1337 int i, offset = 0; | |
1338 | |
1339 for (i = 0; i < data->totlayer; ++i) { | |
1340 typeInfo = layerType_getInfo(data->layers[i].type); | |
1341 | |
1342 data->layers[i].offset = offset; | |
1343 offset += typeInfo->size; | |
1344 } | |
1345 | |
1346 data->totsize = offset; | |
1347 CustomData_update_typemap(data); | |
1348 } | |
1349 | |
1350 int CustomData_get_layer_index(const CustomData *data, int type) | |
1351 { | |
1352 int i;· | |
1353 | |
1354 for (i = 0; i < data->totlayer; ++i) | |
1355 if (data->layers[i].type == type) | |
1356 return i; | |
1357 | |
1358 return -1; | |
1359 } | |
1360 | |
1361 int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n) | |
1362 { | |
1363 int i = CustomData_get_layer_index(data, type); | |
1364 | |
1365 if (i != -1) { | |
1366 i = (data->layers[i + n].type == type) ? (i + n) : (-1); | |
1367 } | |
1368 | |
1369 return i; | |
1370 } | |
1371 | |
1372 int CustomData_get_named_layer_index(const CustomData *data, int type, const cha
r *name) | |
1373 { | |
1374 int i; | |
1375 | |
1376 for (i = 0; i < data->totlayer; ++i) | |
1377 if (data->layers[i].type == type && strcmp(data->layers[i].name,
name) == 0) | |
1378 return i; | |
1379 | |
1380 return -1; | |
1381 } | |
1382 | |
1383 int CustomData_get_active_layer_index(const CustomData *data, int type) | |
1384 { | |
1385 if (!data->totlayer) | |
1386 return -1; | |
1387 | |
1388 if (data->typemap[type] != -1) { | |
1389 return data->typemap[type] + data->layers[data->typemap[type]].a
ctive; | |
1390 } | |
1391 | |
1392 return -1; | |
1393 } | |
1394 | |
1395 int CustomData_get_render_layer_index(const CustomData *data, int type) | |
1396 { | |
1397 int i; | |
1398 | |
1399 for (i = 0; i < data->totlayer; ++i) | |
1400 if (data->layers[i].type == type) | |
1401 return i + data->layers[i].active_rnd; | |
1402 | |
1403 return -1; | |
1404 } | |
1405 | |
1406 int CustomData_get_clone_layer_index(const CustomData *data, int type) | |
1407 { | |
1408 int i; | |
1409 | |
1410 for (i = 0; i < data->totlayer; ++i) | |
1411 if (data->layers[i].type == type) | |
1412 return i + data->layers[i].active_clone; | |
1413 | |
1414 return -1; | |
1415 } | |
1416 | |
1417 int CustomData_get_stencil_layer_index(const CustomData *data, int type) | |
1418 { | |
1419 int i; | |
1420 | |
1421 for (i = 0; i < data->totlayer; ++i) | |
1422 if (data->layers[i].type == type) | |
1423 return i + data->layers[i].active_mask; | |
1424 | |
1425 return -1; | |
1426 } | |
1427 | |
1428 int CustomData_get_active_layer(const CustomData *data, int type) | |
1429 { | |
1430 int i; | |
1431 | |
1432 for (i = 0; i < data->totlayer; ++i) | |
1433 if (data->layers[i].type == type) | |
1434 return data->layers[i].active; | |
1435 | |
1436 return -1; | |
1437 } | |
1438 | |
1439 int CustomData_get_render_layer(const CustomData *data, int type) | |
1440 { | |
1441 int i; | |
1442 | |
1443 for (i = 0; i < data->totlayer; ++i) | |
1444 if (data->layers[i].type == type) | |
1445 return data->layers[i].active_rnd; | |
1446 | |
1447 return -1; | |
1448 } | |
1449 | |
1450 int CustomData_get_clone_layer(const CustomData *data, int type) | |
1451 { | |
1452 int i; | |
1453 | |
1454 for (i = 0; i < data->totlayer; ++i) | |
1455 if (data->layers[i].type == type) | |
1456 return data->layers[i].active_clone; | |
1457 | |
1458 return -1; | |
1459 } | |
1460 | |
1461 int CustomData_get_stencil_layer(const CustomData *data, int type) | |
1462 { | |
1463 int i; | |
1464 | |
1465 for (i = 0; i < data->totlayer; ++i) | |
1466 if (data->layers[i].type == type) | |
1467 return data->layers[i].active_mask; | |
1468 | |
1469 return -1; | |
1470 } | |
1471 | |
1472 void CustomData_set_layer_active(CustomData *data, int type, int n) | |
1473 { | |
1474 int i; | |
1475 | |
1476 for (i = 0; i < data->totlayer; ++i) | |
1477 if (data->layers[i].type == type) | |
1478 data->layers[i].active = n; | |
1479 } | |
1480 | |
1481 void CustomData_set_layer_render(CustomData *data, int type, int n) | |
1482 { | |
1483 int i; | |
1484 | |
1485 for (i = 0; i < data->totlayer; ++i) | |
1486 if (data->layers[i].type == type) | |
1487 data->layers[i].active_rnd = n; | |
1488 } | |
1489 | |
1490 void CustomData_set_layer_clone(CustomData *data, int type, int n) | |
1491 { | |
1492 int i; | |
1493 | |
1494 for (i = 0; i < data->totlayer; ++i) | |
1495 if (data->layers[i].type == type) | |
1496 data->layers[i].active_clone = n; | |
1497 } | |
1498 | |
1499 void CustomData_set_layer_stencil(CustomData *data, int type, int n) | |
1500 { | |
1501 int i; | |
1502 | |
1503 for (i = 0; i < data->totlayer; ++i) | |
1504 if (data->layers[i].type == type) | |
1505 data->layers[i].active_mask = n; | |
1506 } | |
1507 | |
1508 /* for using with an index from CustomData_get_active_layer_index and CustomData
_get_render_layer_index */ | |
1509 void CustomData_set_layer_active_index(CustomData *data, int type, int n) | |
1510 { | |
1511 int i; | |
1512 | |
1513 for (i = 0; i < data->totlayer; ++i) | |
1514 if (data->layers[i].type == type) | |
1515 data->layers[i].active = n - i; | |
1516 } | |
1517 | |
1518 void CustomData_set_layer_render_index(CustomData *data, int type, int n) | |
1519 { | |
1520 int i; | |
1521 | |
1522 for (i = 0; i < data->totlayer; ++i) | |
1523 if (data->layers[i].type == type) | |
1524 data->layers[i].active_rnd = n - i; | |
1525 } | |
1526 | |
1527 void CustomData_set_layer_clone_index(CustomData *data, int type, int n) | |
1528 { | |
1529 int i; | |
1530 | |
1531 for (i = 0; i < data->totlayer; ++i) | |
1532 if (data->layers[i].type == type) | |
1533 data->layers[i].active_clone = n - i; | |
1534 } | |
1535 | |
1536 void CustomData_set_layer_stencil_index(CustomData *data, int type, int n) | |
1537 { | |
1538 int i; | |
1539 | |
1540 for (i = 0; i < data->totlayer; ++i) | |
1541 if (data->layers[i].type == type) | |
1542 data->layers[i].active_mask = n - i; | |
1543 } | |
1544 | |
1545 void CustomData_set_layer_flag(struct CustomData *data, int type, int flag) | |
1546 { | |
1547 int i; | |
1548 | |
1549 for (i = 0; i < data->totlayer; ++i) | |
1550 if (data->layers[i].type == type) | |
1551 data->layers[i].flag |= flag; | |
1552 } | |
1553 | |
1554 static int customData_resize(CustomData *data, int amount) | |
1555 { | |
1556 CustomDataLayer *tmp = MEM_callocN(sizeof(*tmp) * (data->maxlayer + amou
nt), | |
1557 "CustomData->layers"); | |
1558 if (!tmp) return 0; | |
1559 | |
1560 data->maxlayer += amount; | |
1561 if (data->layers) { | |
1562 memcpy(tmp, data->layers, sizeof(*tmp) * data->totlayer); | |
1563 MEM_freeN(data->layers); | |
1564 } | |
1565 data->layers = tmp; | |
1566 | |
1567 return 1; | |
1568 } | |
1569 | |
1570 static CustomDataLayer *customData_add_layer__internal(CustomData *data, | |
1571 int type, int alloctype,
void *layerdata, int totelem, const char *name) | |
1572 { | |
1573 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
1574 int size = typeInfo->size * totelem, flag = 0, index = data->totlayer; | |
1575 void *newlayerdata = NULL; | |
1576 | |
1577 /* Passing a layerdata to copy from with an alloctype that won't copy is | |
1578 * most likely a bug */ | |
1579 BLI_assert(!layerdata || | |
1580 (alloctype == CD_ASSIGN) || | |
1581 (alloctype == CD_DUPLICATE) || | |
1582 (alloctype == CD_REFERENCE)); | |
1583 | |
1584 if (!typeInfo->defaultname && CustomData_has_layer(data, type)) | |
1585 return &data->layers[CustomData_get_layer_index(data, type)]; | |
1586 | |
1587 if ((alloctype == CD_ASSIGN) || (alloctype == CD_REFERENCE)) { | |
1588 newlayerdata = layerdata; | |
1589 } | |
1590 else if (size > 0) { | |
1591 newlayerdata = MEM_callocN(size, layerType_getName(type)); | |
1592 if (!newlayerdata) | |
1593 return NULL; | |
1594 } | |
1595 | |
1596 if (alloctype == CD_DUPLICATE && layerdata) { | |
1597 if (typeInfo->copy) | |
1598 typeInfo->copy(layerdata, newlayerdata, totelem); | |
1599 else | |
1600 memcpy(newlayerdata, layerdata, size); | |
1601 } | |
1602 else if (alloctype == CD_DEFAULT) { | |
1603 if (typeInfo->set_default) | |
1604 typeInfo->set_default((char *)newlayerdata, totelem); | |
1605 } | |
1606 else if (alloctype == CD_REFERENCE) | |
1607 flag |= CD_FLAG_NOFREE; | |
1608 | |
1609 if (index >= data->maxlayer) { | |
1610 if (!customData_resize(data, CUSTOMDATA_GROW)) { | |
1611 if (newlayerdata != layerdata) | |
1612 MEM_freeN(newlayerdata); | |
1613 return NULL; | |
1614 } | |
1615 } | |
1616 ········ | |
1617 data->totlayer++; | |
1618 | |
1619 /* keep layers ordered by type */ | |
1620 for (; index > 0 && data->layers[index - 1].type > type; --index) | |
1621 data->layers[index] = data->layers[index - 1]; | |
1622 | |
1623 data->layers[index].type = type; | |
1624 data->layers[index].flag = flag; | |
1625 data->layers[index].data = newlayerdata; | |
1626 | |
1627 if (name || (name = typeInfo->defaultname)) { | |
1628 BLI_strncpy(data->layers[index].name, name, sizeof(data->layers[
index].name)); | |
1629 CustomData_set_layer_unique_name(data, index); | |
1630 } | |
1631 else | |
1632 data->layers[index].name[0] = '\0'; | |
1633 | |
1634 if (index > 0 && data->layers[index - 1].type == type) { | |
1635 data->layers[index].active = data->layers[index - 1].active; | |
1636 data->layers[index].active_rnd = data->layers[index - 1].active_
rnd; | |
1637 data->layers[index].active_clone = data->layers[index - 1].activ
e_clone; | |
1638 data->layers[index].active_mask = data->layers[index - 1].active
_mask; | |
1639 } | |
1640 else { | |
1641 data->layers[index].active = 0; | |
1642 data->layers[index].active_rnd = 0; | |
1643 data->layers[index].active_clone = 0; | |
1644 data->layers[index].active_mask = 0; | |
1645 } | |
1646 ········ | |
1647 customData_update_offsets(data); | |
1648 | |
1649 return &data->layers[index]; | |
1650 } | |
1651 | |
1652 void *CustomData_add_layer(CustomData *data, int type, int alloctype, | |
1653 void *layerdata, int totelem) | |
1654 { | |
1655 CustomDataLayer *layer; | |
1656 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
1657 ········ | |
1658 layer = customData_add_layer__internal(data, type, alloctype, layerdata, | |
1659 totelem, typeInfo->defaultname); | |
1660 CustomData_update_typemap(data); | |
1661 | |
1662 if (layer) | |
1663 return layer->data; | |
1664 | |
1665 return NULL; | |
1666 } | |
1667 | |
1668 /*same as above but accepts a name*/ | |
1669 void *CustomData_add_layer_named(CustomData *data, int type, int alloctype, | |
1670 void *layerdata, int totelem, const char *name) | |
1671 { | |
1672 CustomDataLayer *layer; | |
1673 ········ | |
1674 layer = customData_add_layer__internal(data, type, alloctype, layerdata, | |
1675 totelem, name); | |
1676 CustomData_update_typemap(data); | |
1677 | |
1678 if (layer) | |
1679 return layer->data; | |
1680 | |
1681 return NULL; | |
1682 } | |
1683 | |
1684 | |
1685 int CustomData_free_layer(CustomData *data, int type, int totelem, int index) | |
1686 { | |
1687 int i; | |
1688 ········ | |
1689 if (index < 0) return 0; | |
1690 | |
1691 customData_free_layer__internal(&data->layers[index], totelem); | |
1692 | |
1693 for (i = index + 1; i < data->totlayer; ++i) | |
1694 data->layers[i - 1] = data->layers[i]; | |
1695 | |
1696 data->totlayer--; | |
1697 | |
1698 /* if layer was last of type in array, set new active layer */ | |
1699 if ((index >= data->totlayer) || (data->layers[index].type != type)) { | |
1700 i = CustomData_get_layer_index(data, type); | |
1701 ················ | |
1702 if (i >= 0) | |
1703 for (; i < data->totlayer && data->layers[i].type == typ
e; i++) { | |
1704 data->layers[i].active--; | |
1705 data->layers[i].active_rnd--; | |
1706 data->layers[i].active_clone--; | |
1707 data->layers[i].active_mask--; | |
1708 } | |
1709 } | |
1710 | |
1711 if (data->totlayer <= data->maxlayer - CUSTOMDATA_GROW) | |
1712 customData_resize(data, -CUSTOMDATA_GROW); | |
1713 | |
1714 customData_update_offsets(data); | |
1715 CustomData_update_typemap(data); | |
1716 | |
1717 return 1; | |
1718 } | |
1719 | |
1720 int CustomData_free_layer_active(CustomData *data, int type, int totelem) | |
1721 { | |
1722 int index = 0; | |
1723 index = CustomData_get_active_layer_index(data, type); | |
1724 if (index < 0) return 0; | |
1725 return CustomData_free_layer(data, type, totelem, index); | |
1726 } | |
1727 | |
1728 | |
1729 void CustomData_free_layers(CustomData *data, int type, int totelem) | |
1730 { | |
1731 while (CustomData_has_layer(data, type)) | |
1732 CustomData_free_layer_active(data, type, totelem); | |
1733 } | |
1734 | |
1735 int CustomData_has_layer(const CustomData *data, int type) | |
1736 { | |
1737 return (CustomData_get_layer_index(data, type) != -1); | |
1738 } | |
1739 | |
1740 int CustomData_number_of_layers(const CustomData *data, int type) | |
1741 { | |
1742 int i, number = 0; | |
1743 | |
1744 for (i = 0; i < data->totlayer; i++) | |
1745 if (data->layers[i].type == type) | |
1746 number++; | |
1747 ········ | |
1748 return number; | |
1749 } | |
1750 | |
1751 void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int t
ype, const int totelem) | |
1752 { | |
1753 CustomDataLayer *layer; | |
1754 int layer_index; | |
1755 | |
1756 /* get the layer index of the first layer of type */ | |
1757 layer_index = CustomData_get_active_layer_index(data, type); | |
1758 if (layer_index < 0) return NULL; | |
1759 | |
1760 layer = &data->layers[layer_index]; | |
1761 | |
1762 if (layer->flag & CD_FLAG_NOFREE) { | |
1763 /* MEM_dupallocN won't work in case of complex layers, like e.g. | |
1764 * CD_MDEFORMVERT, which has pointers to allocated data... | |
1765 * So in case a custom copy function is defined, use it! | |
1766 */ | |
1767 const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); | |
1768 | |
1769 if (typeInfo->copy) { | |
1770 char *dest_data = MEM_mallocN(typeInfo->size * totelem,
"CD duplicate ref layer"); | |
1771 typeInfo->copy(layer->data, dest_data, totelem); | |
1772 layer->data = dest_data; | |
1773 } | |
1774 else | |
1775 layer->data = MEM_dupallocN(layer->data); | |
1776 | |
1777 layer->flag &= ~CD_FLAG_NOFREE; | |
1778 } | |
1779 | |
1780 return layer->data; | |
1781 } | |
1782 | |
1783 void *CustomData_duplicate_referenced_layer_named(struct CustomData *data, | |
1784 const int type, const char *na
me, const int totelem) | |
1785 { | |
1786 CustomDataLayer *layer; | |
1787 int layer_index; | |
1788 | |
1789 /* get the layer index of the desired layer */ | |
1790 layer_index = CustomData_get_named_layer_index(data, type, name); | |
1791 if (layer_index < 0) return NULL; | |
1792 | |
1793 layer = &data->layers[layer_index]; | |
1794 | |
1795 if (layer->flag & CD_FLAG_NOFREE) { | |
1796 /* MEM_dupallocN won't work in case of complex layers, like e.g. | |
1797 * CD_MDEFORMVERT, which has pointers to allocated data... | |
1798 * So in case a custom copy function is defined, use it! | |
1799 */ | |
1800 const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); | |
1801 | |
1802 if (typeInfo->copy) { | |
1803 char *dest_data = MEM_mallocN(typeInfo->size * totelem,
"CD duplicate ref layer"); | |
1804 typeInfo->copy(layer->data, dest_data, totelem); | |
1805 layer->data = dest_data; | |
1806 } | |
1807 else | |
1808 layer->data = MEM_dupallocN(layer->data); | |
1809 | |
1810 layer->flag &= ~CD_FLAG_NOFREE; | |
1811 } | |
1812 | |
1813 return layer->data; | |
1814 } | |
1815 | |
1816 int CustomData_is_referenced_layer(struct CustomData *data, int type) | |
1817 { | |
1818 CustomDataLayer *layer; | |
1819 int layer_index; | |
1820 | |
1821 /* get the layer index of the first layer of type */ | |
1822 layer_index = CustomData_get_active_layer_index(data, type); | |
1823 if (layer_index < 0) return 0; | |
1824 | |
1825 layer = &data->layers[layer_index]; | |
1826 | |
1827 return (layer->flag & CD_FLAG_NOFREE) != 0; | |
1828 } | |
1829 | |
1830 void CustomData_free_temporary(CustomData *data, int totelem) | |
1831 { | |
1832 CustomDataLayer *layer; | |
1833 int i, j; | |
1834 | |
1835 for (i = 0, j = 0; i < data->totlayer; ++i) { | |
1836 layer = &data->layers[i]; | |
1837 | |
1838 if (i != j) | |
1839 data->layers[j] = data->layers[i]; | |
1840 | |
1841 if ((layer->flag & CD_FLAG_TEMPORARY) == CD_FLAG_TEMPORARY) | |
1842 customData_free_layer__internal(layer, totelem); | |
1843 else | |
1844 j++; | |
1845 } | |
1846 | |
1847 data->totlayer = j; | |
1848 | |
1849 if (data->totlayer <= data->maxlayer - CUSTOMDATA_GROW) | |
1850 customData_resize(data, -CUSTOMDATA_GROW); | |
1851 | |
1852 customData_update_offsets(data); | |
1853 } | |
1854 | |
1855 void CustomData_set_only_copy(const struct CustomData *data, | |
1856 CustomDataMask mask) | |
1857 { | |
1858 int i; | |
1859 | |
1860 for (i = 0; i < data->totlayer; ++i) | |
1861 if (!(mask & CD_TYPE_AS_MASK(data->layers[i].type))) | |
1862 data->layers[i].flag |= CD_FLAG_NOCOPY; | |
1863 } | |
1864 | |
1865 void CustomData_copy_elements(int type, void *source, void *dest, int count) | |
1866 { | |
1867 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
1868 | |
1869 if (typeInfo->copy) | |
1870 typeInfo->copy(source, dest, count); | |
1871 else | |
1872 memcpy(dest, source, typeInfo->size * count); | |
1873 } | |
1874 | |
1875 void CustomData_copy_data(const CustomData *source, CustomData *dest, | |
1876 int source_index, int dest_index, int count) | |
1877 { | |
1878 const LayerTypeInfo *typeInfo; | |
1879 int src_i, dest_i; | |
1880 int src_offset; | |
1881 int dest_offset; | |
1882 | |
1883 /* copies a layer at a time */ | |
1884 dest_i = 0; | |
1885 for (src_i = 0; src_i < source->totlayer; ++src_i) { | |
1886 | |
1887 /* find the first dest layer with type >= the source type | |
1888 * (this should work because layers are ordered by type) | |
1889 */ | |
1890 while (dest_i < dest->totlayer && dest->layers[dest_i].type < so
urce->layers[src_i].type) { | |
1891 ++dest_i; | |
1892 } | |
1893 | |
1894 /* if there are no more dest layers, we're done */ | |
1895 if (dest_i >= dest->totlayer) return; | |
1896 | |
1897 /* if we found a matching layer, copy the data */ | |
1898 if (dest->layers[dest_i].type == source->layers[src_i].type) { | |
1899 char *src_data = source->layers[src_i].data; | |
1900 char *dest_data = dest->layers[dest_i].data; | |
1901 | |
1902 typeInfo = layerType_getInfo(source->layers[src_i].type)
; | |
1903 | |
1904 src_offset = source_index * typeInfo->size; | |
1905 dest_offset = dest_index * typeInfo->size; | |
1906 ························ | |
1907 if (!src_data || !dest_data) { | |
1908 if (src_data != NULL && dest_data != NULL) { | |
1909 printf("%s: warning null data for %s typ
e (%p --> %p), skipping\n", | |
1910 __func__, layerType_getName(sourc
e->layers[src_i].type), | |
1911 (void *)src_data, (void *)dest_da
ta); | |
1912 } | |
1913 continue; | |
1914 } | |
1915 ························ | |
1916 if (typeInfo->copy) | |
1917 typeInfo->copy(src_data + src_offset, | |
1918 dest_data + dest_offset, | |
1919 count); | |
1920 else | |
1921 memcpy(dest_data + dest_offset, | |
1922 src_data + src_offset, | |
1923 count * typeInfo->size); | |
1924 | |
1925 /* if there are multiple source & dest layers of the sam
e type, | |
1926 * we don't want to copy all source layers to the same d
est, so | |
1927 * increment dest_i | |
1928 */ | |
1929 ++dest_i; | |
1930 } | |
1931 } | |
1932 } | |
1933 | |
1934 void CustomData_free_elem(CustomData *data, int index, int count) | |
1935 { | |
1936 int i; | |
1937 const LayerTypeInfo *typeInfo; | |
1938 | |
1939 for (i = 0; i < data->totlayer; ++i) { | |
1940 if (!(data->layers[i].flag & CD_FLAG_NOFREE)) { | |
1941 typeInfo = layerType_getInfo(data->layers[i].type); | |
1942 | |
1943 if (typeInfo->free) { | |
1944 int offset = typeInfo->size * index; | |
1945 | |
1946 typeInfo->free((char *)data->layers[i].data + of
fset, | |
1947 count, typeInfo->size); | |
1948 } | |
1949 } | |
1950 } | |
1951 } | |
1952 | |
1953 #define SOURCE_BUF_SIZE 100 | |
1954 | |
1955 void CustomData_interp(const CustomData *source, CustomData *dest, | |
1956 int *src_indices, float *weights, float *sub_weights, | |
1957 int count, int dest_index) | |
1958 { | |
1959 int src_i, dest_i; | |
1960 int dest_offset; | |
1961 int j; | |
1962 void *source_buf[SOURCE_BUF_SIZE]; | |
1963 void **sources = source_buf; | |
1964 | |
1965 /* slow fallback in case we're interpolating a ridiculous number of | |
1966 * elements | |
1967 */ | |
1968 if (count > SOURCE_BUF_SIZE) | |
1969 sources = MEM_callocN(sizeof(*sources) * count, | |
1970 "CustomData_interp sources"); | |
1971 | |
1972 /* interpolates a layer at a time */ | |
1973 dest_i = 0; | |
1974 for (src_i = 0; src_i < source->totlayer; ++src_i) { | |
1975 const LayerTypeInfo *typeInfo = layerType_getInfo(source->layers
[src_i].type); | |
1976 if (!typeInfo->interp) continue; | |
1977 | |
1978 /* find the first dest layer with type >= the source type | |
1979 * (this should work because layers are ordered by type) | |
1980 */ | |
1981 while (dest_i < dest->totlayer && dest->layers[dest_i].type < so
urce->layers[src_i].type) { | |
1982 ++dest_i; | |
1983 } | |
1984 | |
1985 /* if there are no more dest layers, we're done */ | |
1986 if (dest_i >= dest->totlayer) return; | |
1987 | |
1988 /* if we found a matching layer, copy the data */ | |
1989 if (dest->layers[dest_i].type == source->layers[src_i].type) { | |
1990 void *src_data = source->layers[src_i].data; | |
1991 | |
1992 for (j = 0; j < count; ++j) | |
1993 sources[j] = (char *)src_data + typeInfo->size *
src_indices[j]; | |
1994 | |
1995 dest_offset = dest_index * typeInfo->size; | |
1996 | |
1997 typeInfo->interp(sources, weights, sub_weights, count, | |
1998 (char *)dest->layers[dest_i].data + des
t_offset); | |
1999 | |
2000 /* if there are multiple source & dest layers of the sam
e type, | |
2001 * we don't want to copy all source layers to the same d
est, so | |
2002 * increment dest_i | |
2003 */ | |
2004 ++dest_i; | |
2005 } | |
2006 } | |
2007 | |
2008 if (count > SOURCE_BUF_SIZE) MEM_freeN(sources); | |
2009 } | |
2010 | |
2011 void CustomData_swap(struct CustomData *data, int index, const int *corner_indic
es) | |
2012 { | |
2013 const LayerTypeInfo *typeInfo; | |
2014 int i; | |
2015 | |
2016 for (i = 0; i < data->totlayer; ++i) { | |
2017 typeInfo = layerType_getInfo(data->layers[i].type); | |
2018 | |
2019 if (typeInfo->swap) { | |
2020 int offset = typeInfo->size * index; | |
2021 | |
2022 typeInfo->swap((char *)data->layers[i].data + offset, co
rner_indices); | |
2023 } | |
2024 } | |
2025 } | |
2026 | |
2027 void *CustomData_get(const CustomData *data, int index, int type) | |
2028 { | |
2029 int offset; | |
2030 int layer_index; | |
2031 ········ | |
2032 /* get the layer index of the active layer of type */ | |
2033 layer_index = CustomData_get_active_layer_index(data, type); | |
2034 if (layer_index < 0) return NULL; | |
2035 | |
2036 /* get the offset of the desired element */ | |
2037 offset = layerType_getInfo(type)->size * index; | |
2038 | |
2039 return (char *)data->layers[layer_index].data + offset; | |
2040 } | |
2041 | |
2042 void *CustomData_get_n(const CustomData *data, int type, int index, int n) | |
2043 { | |
2044 int layer_index; | |
2045 int offset; | |
2046 | |
2047 /* get the layer index of the first layer of type */ | |
2048 layer_index = data->typemap[type]; | |
2049 if (layer_index < 0) return NULL; | |
2050 | |
2051 offset = layerType_getInfo(type)->size * index; | |
2052 return (char *)data->layers[layer_index + n].data + offset; | |
2053 } | |
2054 | |
2055 void *CustomData_get_layer(const CustomData *data, int type) | |
2056 { | |
2057 /* get the layer index of the active layer of type */ | |
2058 int layer_index = CustomData_get_active_layer_index(data, type); | |
2059 if (layer_index < 0) return NULL; | |
2060 | |
2061 return data->layers[layer_index].data; | |
2062 } | |
2063 | |
2064 void *CustomData_get_layer_n(const CustomData *data, int type, int n) | |
2065 { | |
2066 /* get the layer index of the active layer of type */ | |
2067 int layer_index = CustomData_get_layer_index_n(data, type, n); | |
2068 if (layer_index < 0) return NULL; | |
2069 | |
2070 return data->layers[layer_index].data; | |
2071 } | |
2072 | |
2073 void *CustomData_get_layer_named(const struct CustomData *data, int type, | |
2074 const char *name) | |
2075 { | |
2076 int layer_index = CustomData_get_named_layer_index(data, type, name); | |
2077 if (layer_index < 0) return NULL; | |
2078 | |
2079 return data->layers[layer_index].data; | |
2080 } | |
2081 | |
2082 | |
2083 int CustomData_set_layer_name(const CustomData *data, int type, int n, const cha
r *name) | |
2084 { | |
2085 /* get the layer index of the first layer of type */ | |
2086 int layer_index = CustomData_get_layer_index_n(data, type, n); | |
2087 | |
2088 if (layer_index < 0) return 0; | |
2089 if (!name) return 0; | |
2090 ········ | |
2091 strcpy(data->layers[layer_index].name, name); | |
2092 ········ | |
2093 return 1; | |
2094 } | |
2095 | |
2096 void *CustomData_set_layer(const CustomData *data, int type, void *ptr) | |
2097 { | |
2098 /* get the layer index of the first layer of type */ | |
2099 int layer_index = CustomData_get_active_layer_index(data, type); | |
2100 | |
2101 if (layer_index < 0) return NULL; | |
2102 | |
2103 data->layers[layer_index].data = ptr; | |
2104 | |
2105 return ptr; | |
2106 } | |
2107 | |
2108 void *CustomData_set_layer_n(const struct CustomData *data, int type, int n, voi
d *ptr) | |
2109 { | |
2110 /* get the layer index of the first layer of type */ | |
2111 int layer_index = CustomData_get_layer_index_n(data, type, n); | |
2112 if (layer_index < 0) return NULL; | |
2113 | |
2114 data->layers[layer_index].data = ptr; | |
2115 | |
2116 return ptr; | |
2117 } | |
2118 | |
2119 void CustomData_set(const CustomData *data, int index, int type, void *source) | |
2120 { | |
2121 void *dest = CustomData_get(data, index, type); | |
2122 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
2123 | |
2124 if (!dest) return; | |
2125 | |
2126 if (typeInfo->copy) | |
2127 typeInfo->copy(source, dest, 1); | |
2128 else | |
2129 memcpy(dest, source, typeInfo->size); | |
2130 } | |
2131 | |
2132 /*Bmesh functions*/ | |
2133 /*needed to convert to/from different face reps*/ | |
2134 void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *l
data, | |
2135 int totloop, int totpoly) | |
2136 { | |
2137 int i; | |
2138 for (i = 0; i < fdata->totlayer; i++) { | |
2139 if (fdata->layers[i].type == CD_MTFACE) { | |
2140 CustomData_add_layer_named(pdata, CD_MTEXPOLY, CD_CALLOC
, NULL, totpoly, fdata->layers[i].name); | |
2141 CustomData_add_layer_named(ldata, CD_MLOOPUV, CD_CALLOC,
NULL, totloop, fdata->layers[i].name); | |
2142 } | |
2143 else if (fdata->layers[i].type == CD_MCOL) { | |
2144 CustomData_add_layer_named(ldata, CD_MLOOPCOL, CD_CALLOC
, NULL, totloop, fdata->layers[i].name); | |
2145 } | |
2146 else if (fdata->layers[i].type == CD_MDISPS) { | |
2147 CustomData_add_layer_named(ldata, CD_MDISPS, CD_CALLOC,
NULL, totloop, fdata->layers[i].name); | |
2148 } | |
2149 } | |
2150 } | |
2151 | |
2152 void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData
*ldata, int total) | |
2153 { | |
2154 int i; | |
2155 for (i = 0; i < pdata->totlayer; i++) { | |
2156 if (pdata->layers[i].type == CD_MTEXPOLY) { | |
2157 CustomData_add_layer_named(fdata, CD_MTFACE, CD_CALLOC,
NULL, total, pdata->layers[i].name); | |
2158 } | |
2159 } | |
2160 for (i = 0; i < ldata->totlayer; i++) { | |
2161 if (ldata->layers[i].type == CD_MLOOPCOL) { | |
2162 CustomData_add_layer_named(fdata, CD_MCOL, CD_CALLOC, NU
LL, total, ldata->layers[i].name); | |
2163 } | |
2164 else if (ldata->layers[i].type == CD_PREVIEW_MLOOPCOL) { | |
2165 CustomData_add_layer_named(fdata, CD_PREVIEW_MCOL, CD_CA
LLOC, NULL, total, ldata->layers[i].name); | |
2166 } | |
2167 else if (ldata->layers[i].type == CD_ORIGSPACE_MLOOP) { | |
2168 CustomData_add_layer_named(fdata, CD_ORIGSPACE, CD_CALLO
C, NULL, total, ldata->layers[i].name); | |
2169 } | |
2170 } | |
2171 | |
2172 CustomData_bmesh_update_active_layers(fdata, pdata, ldata); | |
2173 } | |
2174 | |
2175 void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *pdata,
CustomData *ldata) | |
2176 { | |
2177 int act; | |
2178 | |
2179 if (CustomData_has_layer(pdata, CD_MTEXPOLY)) { | |
2180 act = CustomData_get_active_layer(pdata, CD_MTEXPOLY); | |
2181 CustomData_set_layer_active(ldata, CD_MLOOPUV, act); | |
2182 CustomData_set_layer_active(fdata, CD_MTFACE, act); | |
2183 | |
2184 act = CustomData_get_render_layer(pdata, CD_MTEXPOLY); | |
2185 CustomData_set_layer_render(ldata, CD_MLOOPUV, act); | |
2186 CustomData_set_layer_render(fdata, CD_MTFACE, act); | |
2187 | |
2188 act = CustomData_get_clone_layer(pdata, CD_MTEXPOLY); | |
2189 CustomData_set_layer_clone(ldata, CD_MLOOPUV, act); | |
2190 CustomData_set_layer_clone(fdata, CD_MTFACE, act); | |
2191 | |
2192 act = CustomData_get_stencil_layer(pdata, CD_MTEXPOLY); | |
2193 CustomData_set_layer_stencil(ldata, CD_MLOOPUV, act); | |
2194 CustomData_set_layer_stencil(fdata, CD_MTFACE, act); | |
2195 } | |
2196 | |
2197 if (CustomData_has_layer(ldata, CD_MLOOPCOL)) { | |
2198 act = CustomData_get_active_layer(ldata, CD_MLOOPCOL); | |
2199 CustomData_set_layer_active(fdata, CD_MCOL, act); | |
2200 | |
2201 act = CustomData_get_render_layer(ldata, CD_MLOOPCOL); | |
2202 CustomData_set_layer_render(fdata, CD_MCOL, act); | |
2203 | |
2204 act = CustomData_get_clone_layer(ldata, CD_MLOOPCOL); | |
2205 CustomData_set_layer_clone(fdata, CD_MCOL, act); | |
2206 | |
2207 act = CustomData_get_stencil_layer(ldata, CD_MLOOPCOL); | |
2208 CustomData_set_layer_stencil(fdata, CD_MCOL, act); | |
2209 } | |
2210 } | |
2211 | |
2212 void CustomData_bmesh_init_pool(CustomData *data, int totelem, const char htype) | |
2213 { | |
2214 int chunksize; | |
2215 | |
2216 /* Dispose old pools before calling here to avoid leaks */ | |
2217 BLI_assert(data->pool == NULL); | |
2218 | |
2219 switch (htype) { | |
2220 case BM_VERT: chunksize = bm_mesh_chunksize_default.totvert; br
eak; | |
2221 case BM_EDGE: chunksize = bm_mesh_chunksize_default.totedge; br
eak; | |
2222 case BM_LOOP: chunksize = bm_mesh_chunksize_default.totloop; br
eak; | |
2223 case BM_FACE: chunksize = bm_mesh_chunksize_default.totface; br
eak; | |
2224 default: | |
2225 BLI_assert(0); | |
2226 chunksize = 512; | |
2227 break; | |
2228 } | |
2229 | |
2230 /* If there are no layers, no pool is needed just yet */ | |
2231 if (data->totlayer) { | |
2232 data->pool = BLI_mempool_create(data->totsize, totelem, chunksiz
e, BLI_MEMPOOL_SYSMALLOC); | |
2233 } | |
2234 } | |
2235 | |
2236 void CustomData_bmesh_merge(CustomData *source, CustomData *dest,· | |
2237 CustomDataMask mask, int alloctype, BMesh *bm, const
char htype) | |
2238 { | |
2239 BMHeader *h; | |
2240 BMIter iter; | |
2241 CustomData destold; | |
2242 void *tmp; | |
2243 int t; | |
2244 | |
2245 /* copy old layer description so that old data can be copied into | |
2246 * the new allocation */ | |
2247 destold = *dest; | |
2248 if (destold.layers) destold.layers = MEM_dupallocN(destold.layers); | |
2249 ········ | |
2250 CustomData_merge(source, dest, mask, alloctype, 0); | |
2251 dest->pool = NULL; | |
2252 CustomData_bmesh_init_pool(dest, 512, htype); | |
2253 | |
2254 switch (htype) { | |
2255 case BM_VERT: | |
2256 t = BM_VERTS_OF_MESH; break; | |
2257 case BM_EDGE: | |
2258 t = BM_EDGES_OF_MESH; break; | |
2259 case BM_LOOP: | |
2260 t = BM_LOOPS_OF_FACE; break; | |
2261 case BM_FACE: | |
2262 t = BM_FACES_OF_MESH; break; | |
2263 default: /* should never happen */ | |
2264 BLI_assert(!"invalid type given"); | |
2265 t = BM_VERTS_OF_MESH; | |
2266 } | |
2267 | |
2268 if (t != BM_LOOPS_OF_FACE) { | |
2269 /*ensure all current elements follow new customdata layout*/ | |
2270 BM_ITER_MESH (h, &iter, bm, t) { | |
2271 tmp = NULL; | |
2272 CustomData_bmesh_copy_data(&destold, dest, h->data, &tmp
); | |
2273 CustomData_bmesh_free_block(&destold, &h->data); | |
2274 h->data = tmp; | |
2275 } | |
2276 } | |
2277 else { | |
2278 BMFace *f; | |
2279 BMLoop *l; | |
2280 BMIter liter; | |
2281 | |
2282 /*ensure all current elements follow new customdata layout*/ | |
2283 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { | |
2284 BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { | |
2285 tmp = NULL; | |
2286 CustomData_bmesh_copy_data(&destold, dest, l->he
ad.data, &tmp); | |
2287 CustomData_bmesh_free_block(&destold, &l->head.d
ata); | |
2288 l->head.data = tmp; | |
2289 } | |
2290 } | |
2291 } | |
2292 | |
2293 if (destold.pool) BLI_mempool_destroy(destold.pool); | |
2294 if (destold.layers) MEM_freeN(destold.layers); | |
2295 } | |
2296 | |
2297 void CustomData_bmesh_free_block(CustomData *data, void **block) | |
2298 { | |
2299 const LayerTypeInfo *typeInfo; | |
2300 int i; | |
2301 | |
2302 if (!*block) return; | |
2303 for (i = 0; i < data->totlayer; ++i) { | |
2304 if (!(data->layers[i].flag & CD_FLAG_NOFREE)) { | |
2305 typeInfo = layerType_getInfo(data->layers[i].type); | |
2306 | |
2307 if (typeInfo->free) { | |
2308 int offset = data->layers[i].offset; | |
2309 typeInfo->free((char *)*block + offset, 1, typeI
nfo->size); | |
2310 } | |
2311 } | |
2312 } | |
2313 | |
2314 if (data->totsize) | |
2315 BLI_mempool_free(data->pool, *block); | |
2316 | |
2317 *block = NULL; | |
2318 } | |
2319 | |
2320 static void CustomData_bmesh_alloc_block(CustomData *data, void **block) | |
2321 { | |
2322 | |
2323 if (*block) | |
2324 CustomData_bmesh_free_block(data, block); | |
2325 | |
2326 if (data->totsize > 0) | |
2327 *block = BLI_mempool_alloc(data->pool); | |
2328 else | |
2329 *block = NULL; | |
2330 } | |
2331 | |
2332 void CustomData_bmesh_copy_data(const CustomData *source, CustomData *dest, | |
2333 void *src_block, void **dest_block) | |
2334 { | |
2335 const LayerTypeInfo *typeInfo; | |
2336 int dest_i, src_i; | |
2337 | |
2338 if (!*dest_block) { | |
2339 CustomData_bmesh_alloc_block(dest, dest_block); | |
2340 if (*dest_block) | |
2341 memset(*dest_block, 0, dest->totsize); | |
2342 } | |
2343 ········ | |
2344 /* copies a layer at a time */ | |
2345 dest_i = 0; | |
2346 for (src_i = 0; src_i < source->totlayer; ++src_i) { | |
2347 | |
2348 /* find the first dest layer with type >= the source type | |
2349 * (this should work because layers are ordered by type) | |
2350 */ | |
2351 while (dest_i < dest->totlayer && dest->layers[dest_i].type < so
urce->layers[src_i].type) { | |
2352 ++dest_i; | |
2353 } | |
2354 | |
2355 /* if there are no more dest layers, we're done */ | |
2356 if (dest_i >= dest->totlayer) return; | |
2357 | |
2358 /* if we found a matching layer, copy the data */ | |
2359 if (dest->layers[dest_i].type == source->layers[src_i].type && | |
2360 strcmp(dest->layers[dest_i].name, source->layers[src_i].name
) == 0) { | |
2361 char *src_data = (char *)src_block + source->layers[src_
i].offset; | |
2362 char *dest_data = (char *)*dest_block + dest->layers[des
t_i].offset; | |
2363 | |
2364 typeInfo = layerType_getInfo(source->layers[src_i].type)
; | |
2365 | |
2366 if (typeInfo->copy) | |
2367 typeInfo->copy(src_data, dest_data, 1); | |
2368 else | |
2369 memcpy(dest_data, src_data, typeInfo->size); | |
2370 | |
2371 /* if there are multiple source & dest layers of the sam
e type, | |
2372 * we don't want to copy all source layers to the same d
est, so | |
2373 * increment dest_i | |
2374 */ | |
2375 ++dest_i; | |
2376 } | |
2377 } | |
2378 } | |
2379 | |
2380 /*Bmesh Custom Data Functions. Should replace editmesh ones with these as well,
due to more effecient memory alloc*/ | |
2381 void *CustomData_bmesh_get(const CustomData *data, void *block, int type) | |
2382 { | |
2383 int layer_index; | |
2384 ········ | |
2385 /* get the layer index of the first layer of type */ | |
2386 layer_index = CustomData_get_active_layer_index(data, type); | |
2387 if (layer_index < 0) return NULL; | |
2388 | |
2389 return (char *)block + data->layers[layer_index].offset; | |
2390 } | |
2391 | |
2392 void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int
n) | |
2393 { | |
2394 int layer_index; | |
2395 ········ | |
2396 /* get the layer index of the first layer of type */ | |
2397 layer_index = CustomData_get_layer_index(data, type); | |
2398 if (layer_index < 0) return NULL; | |
2399 | |
2400 return (char *)block + data->layers[layer_index + n].offset; | |
2401 } | |
2402 | |
2403 /*gets from the layer at physical index n, note: doesn't check type.*/ | |
2404 void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n) | |
2405 { | |
2406 if (n < 0 || n >= data->totlayer) return NULL; | |
2407 | |
2408 return (char *)block + data->layers[n].offset; | |
2409 } | |
2410 | |
2411 int CustomData_layer_has_math(struct CustomData *data, int layer_n) | |
2412 { | |
2413 const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[layer_n].
type); | |
2414 ········ | |
2415 if (typeInfo->equal && typeInfo->add && typeInfo->multiply &&· | |
2416 typeInfo->initminmax && typeInfo->dominmax) | |
2417 { | |
2418 return 1; | |
2419 } | |
2420 ········ | |
2421 return 0; | |
2422 } | |
2423 | |
2424 /* copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to | |
2425 * another, while not overwriting anything else (e.g. flags)*/ | |
2426 void CustomData_data_copy_value(int type, void *source, void *dest) | |
2427 { | |
2428 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
2429 | |
2430 if (!dest) return; | |
2431 | |
2432 if (typeInfo->copyvalue) | |
2433 typeInfo->copyvalue(source, dest); | |
2434 else | |
2435 memcpy(dest, source, typeInfo->size); | |
2436 } | |
2437 | |
2438 int CustomData_data_equals(int type, void *data1, void *data2) | |
2439 { | |
2440 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
2441 | |
2442 if (typeInfo->equal) | |
2443 return typeInfo->equal(data1, data2); | |
2444 else return !memcmp(data1, data2, typeInfo->size); | |
2445 } | |
2446 | |
2447 void CustomData_data_initminmax(int type, void *min, void *max) | |
2448 { | |
2449 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
2450 | |
2451 if (typeInfo->initminmax) | |
2452 typeInfo->initminmax(min, max); | |
2453 } | |
2454 | |
2455 | |
2456 void CustomData_data_dominmax(int type, void *data, void *min, void *max) | |
2457 { | |
2458 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
2459 | |
2460 if (typeInfo->dominmax) | |
2461 typeInfo->dominmax(data, min, max); | |
2462 } | |
2463 | |
2464 | |
2465 void CustomData_data_multiply(int type, void *data, float fac) | |
2466 { | |
2467 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
2468 | |
2469 if (typeInfo->multiply) | |
2470 typeInfo->multiply(data, fac); | |
2471 } | |
2472 | |
2473 | |
2474 void CustomData_data_add(int type, void *data1, void *data2) | |
2475 { | |
2476 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
2477 | |
2478 if (typeInfo->add) | |
2479 typeInfo->add(data1, data2); | |
2480 } | |
2481 | |
2482 void CustomData_bmesh_set(const CustomData *data, void *block, int type, void *s
ource) | |
2483 { | |
2484 void *dest = CustomData_bmesh_get(data, block, type); | |
2485 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
2486 | |
2487 if (!dest) return; | |
2488 | |
2489 if (typeInfo->copy) | |
2490 typeInfo->copy(source, dest, 1); | |
2491 else | |
2492 memcpy(dest, source, typeInfo->size); | |
2493 } | |
2494 | |
2495 void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, void
*source) | |
2496 { | |
2497 void *dest = CustomData_bmesh_get_n(data, block, type, n); | |
2498 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
2499 | |
2500 if (!dest) return; | |
2501 | |
2502 if (typeInfo->copy) | |
2503 typeInfo->copy(source, dest, 1); | |
2504 else | |
2505 memcpy(dest, source, typeInfo->size); | |
2506 } | |
2507 | |
2508 void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, void *so
urce) | |
2509 { | |
2510 void *dest = CustomData_bmesh_get_layer_n(data, block, n); | |
2511 const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type); | |
2512 | |
2513 if (!dest) return; | |
2514 | |
2515 if (typeInfo->copy) | |
2516 typeInfo->copy(source, dest, 1); | |
2517 else | |
2518 memcpy(dest, source, typeInfo->size); | |
2519 } | |
2520 | |
2521 void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights
, | |
2522 float *sub_weights, int count, void *dest_block) | |
2523 { | |
2524 int i, j; | |
2525 void *source_buf[SOURCE_BUF_SIZE]; | |
2526 void **sources = source_buf; | |
2527 | |
2528 /* slow fallback in case we're interpolating a ridiculous number of | |
2529 * elements | |
2530 */ | |
2531 if (count > SOURCE_BUF_SIZE) | |
2532 sources = MEM_callocN(sizeof(*sources) * count, | |
2533 "CustomData_interp sources"); | |
2534 | |
2535 /* interpolates a layer at a time */ | |
2536 for (i = 0; i < data->totlayer; ++i) { | |
2537 CustomDataLayer *layer = &data->layers[i]; | |
2538 const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); | |
2539 if (typeInfo->interp) { | |
2540 for (j = 0; j < count; ++j) | |
2541 sources[j] = (char *)src_blocks[j] + layer->offs
et; | |
2542 | |
2543 typeInfo->interp(sources, weights, sub_weights, count, | |
2544 (char *)dest_block + layer->offset); | |
2545 } | |
2546 } | |
2547 | |
2548 if (count > SOURCE_BUF_SIZE) MEM_freeN(sources); | |
2549 } | |
2550 | |
2551 void CustomData_bmesh_set_default(CustomData *data, void **block) | |
2552 { | |
2553 const LayerTypeInfo *typeInfo; | |
2554 int i; | |
2555 | |
2556 if (!*block) | |
2557 CustomData_bmesh_alloc_block(data, block); | |
2558 | |
2559 for (i = 0; i < data->totlayer; ++i) { | |
2560 int offset = data->layers[i].offset; | |
2561 | |
2562 typeInfo = layerType_getInfo(data->layers[i].type); | |
2563 | |
2564 if (typeInfo->set_default) | |
2565 typeInfo->set_default((char *)*block + offset, 1); | |
2566 else memset((char *)*block + offset, 0, typeInfo->size); | |
2567 } | |
2568 } | |
2569 | |
2570 void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest, | |
2571 int src_index, void **dest_block) | |
2572 { | |
2573 const LayerTypeInfo *typeInfo; | |
2574 int dest_i, src_i, src_offset; | |
2575 | |
2576 if (!*dest_block) | |
2577 CustomData_bmesh_alloc_block(dest, dest_block); | |
2578 ········ | |
2579 /* copies a layer at a time */ | |
2580 dest_i = 0; | |
2581 for (src_i = 0; src_i < source->totlayer; ++src_i) { | |
2582 | |
2583 /* find the first dest layer with type >= the source type | |
2584 * (this should work because layers are ordered by type) | |
2585 */ | |
2586 while (dest_i < dest->totlayer && dest->layers[dest_i].type < so
urce->layers[src_i].type) { | |
2587 ++dest_i; | |
2588 } | |
2589 | |
2590 /* if there are no more dest layers, we're done */ | |
2591 if (dest_i >= dest->totlayer) return; | |
2592 | |
2593 /* if we found a matching layer, copy the data */ | |
2594 if (dest->layers[dest_i].type == source->layers[src_i].type) { | |
2595 int offset = dest->layers[dest_i].offset; | |
2596 char *src_data = source->layers[src_i].data; | |
2597 char *dest_data = (char *)*dest_block + offset; | |
2598 | |
2599 typeInfo = layerType_getInfo(dest->layers[dest_i].type); | |
2600 src_offset = src_index * typeInfo->size; | |
2601 | |
2602 if (typeInfo->copy) | |
2603 typeInfo->copy(src_data + src_offset, dest_data,
1); | |
2604 else | |
2605 memcpy(dest_data, src_data + src_offset, typeInf
o->size); | |
2606 | |
2607 /* if there are multiple source & dest layers of the sam
e type, | |
2608 * we don't want to copy all source layers to the same d
est, so | |
2609 * increment dest_i | |
2610 */ | |
2611 ++dest_i; | |
2612 } | |
2613 } | |
2614 } | |
2615 | |
2616 void CustomData_from_bmesh_block(const CustomData *source, CustomData *dest, | |
2617 void *src_block, int dest_index) | |
2618 { | |
2619 const LayerTypeInfo *typeInfo; | |
2620 int dest_i, src_i, dest_offset; | |
2621 | |
2622 /* copies a layer at a time */ | |
2623 dest_i = 0; | |
2624 for (src_i = 0; src_i < source->totlayer; ++src_i) { | |
2625 | |
2626 /* find the first dest layer with type >= the source type | |
2627 * (this should work because layers are ordered by type) | |
2628 */ | |
2629 while (dest_i < dest->totlayer && dest->layers[dest_i].type < so
urce->layers[src_i].type) { | |
2630 ++dest_i; | |
2631 } | |
2632 | |
2633 /* if there are no more dest layers, we're done */ | |
2634 if (dest_i >= dest->totlayer) return; | |
2635 | |
2636 /* if we found a matching layer, copy the data */ | |
2637 if (dest->layers[dest_i].type == source->layers[src_i].type) { | |
2638 int offset = source->layers[src_i].offset; | |
2639 char *src_data = (char *)src_block + offset; | |
2640 char *dest_data = dest->layers[dest_i].data; | |
2641 | |
2642 typeInfo = layerType_getInfo(dest->layers[dest_i].type); | |
2643 dest_offset = dest_index * typeInfo->size; | |
2644 | |
2645 if (typeInfo->copy) | |
2646 typeInfo->copy(src_data, dest_data + dest_offset
, 1); | |
2647 else | |
2648 memcpy(dest_data + dest_offset, src_data, typeIn
fo->size); | |
2649 | |
2650 /* if there are multiple source & dest layers of the sam
e type, | |
2651 * we don't want to copy all source layers to the same d
est, so | |
2652 * increment dest_i | |
2653 */ | |
2654 ++dest_i; | |
2655 } | |
2656 } | |
2657 | |
2658 } | |
2659 | |
2660 void CustomData_file_write_info(int type, const char **structname, int *structnu
m) | |
2661 { | |
2662 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
2663 | |
2664 *structname = typeInfo->structname; | |
2665 *structnum = typeInfo->structnum; | |
2666 } | |
2667 | |
2668 int CustomData_sizeof(int type) | |
2669 { | |
2670 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
2671 | |
2672 return typeInfo->size; | |
2673 } | |
2674 | |
2675 const char *CustomData_layertype_name(int type) | |
2676 { | |
2677 return layerType_getName(type); | |
2678 } | |
2679 | |
2680 | |
2681 /** | |
2682 * Can only ever be one of these. | |
2683 */ | |
2684 int CustomData_layertype_is_singleton(int type) | |
2685 { | |
2686 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
2687 return typeInfo->defaultname == NULL; | |
2688 } | |
2689 | |
2690 static int CustomData_is_property_layer(int type) | |
2691 { | |
2692 if ((type == CD_PROP_FLT) || (type == CD_PROP_INT) || (type == CD_PROP_S
TR)) | |
2693 return 1; | |
2694 return 0; | |
2695 } | |
2696 | |
2697 static int cd_layer_find_dupe(CustomData *data, const char *name, int type, int
index) | |
2698 { | |
2699 int i; | |
2700 /* see if there is a duplicate */ | |
2701 for (i = 0; i < data->totlayer; i++) { | |
2702 if (i != index) { | |
2703 CustomDataLayer *layer = &data->layers[i]; | |
2704 ························ | |
2705 if (CustomData_is_property_layer(type)) { | |
2706 if (CustomData_is_property_layer(layer->type) &&
strcmp(layer->name, name) == 0) { | |
2707 return 1; | |
2708 } | |
2709 } | |
2710 else { | |
2711 if (i != index && layer->type == type && strcmp(
layer->name, name) == 0) { | |
2712 return 1; | |
2713 } | |
2714 } | |
2715 } | |
2716 } | |
2717 ········ | |
2718 return 0; | |
2719 } | |
2720 | |
2721 static int customdata_unique_check(void *arg, const char *name) | |
2722 { | |
2723 struct {CustomData *data; int type; int index; } *data_arg = arg; | |
2724 return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg
->index); | |
2725 } | |
2726 | |
2727 void CustomData_set_layer_unique_name(CustomData *data, int index) | |
2728 {······· | |
2729 CustomDataLayer *nlayer = &data->layers[index]; | |
2730 const LayerTypeInfo *typeInfo = layerType_getInfo(nlayer->type); | |
2731 | |
2732 struct {CustomData *data; int type; int index; } data_arg; | |
2733 data_arg.data = data; | |
2734 data_arg.type = nlayer->type; | |
2735 data_arg.index = index; | |
2736 | |
2737 if (!typeInfo->defaultname) | |
2738 return; | |
2739 ········ | |
2740 BLI_uniquename_cb(customdata_unique_check, &data_arg, typeInfo->defaultn
ame, '.', nlayer->name, sizeof(nlayer->name)); | |
2741 } | |
2742 | |
2743 void CustomData_validate_layer_name(const CustomData *data, int type, char *name
, char *outname) | |
2744 { | |
2745 int index = -1; | |
2746 | |
2747 /* if a layer name was given, try to find that layer */ | |
2748 if (name[0]) | |
2749 index = CustomData_get_named_layer_index(data, type, name); | |
2750 | |
2751 if (index < 0) { | |
2752 /* either no layer was specified, or the layer we want has been | |
2753 * deleted, so assign the active layer to name | |
2754 */ | |
2755 index = CustomData_get_active_layer_index(data, type); | |
2756 strcpy(outname, data->layers[index].name); | |
2757 } | |
2758 else | |
2759 strcpy(outname, name); | |
2760 } | |
2761 | |
2762 int CustomData_verify_versions(struct CustomData *data, int index) | |
2763 { | |
2764 const LayerTypeInfo *typeInfo; | |
2765 CustomDataLayer *layer = &data->layers[index]; | |
2766 int i, keeplayer = 1; | |
2767 | |
2768 if (layer->type >= CD_NUMTYPES) { | |
2769 keeplayer = 0; /* unknown layer type from future version */ | |
2770 } | |
2771 else { | |
2772 typeInfo = layerType_getInfo(layer->type); | |
2773 | |
2774 if (!typeInfo->defaultname && (index > 0) && | |
2775 data->layers[index - 1].type == layer->type) | |
2776 { | |
2777 keeplayer = 0; /* multiple layers of which we only suppo
rt one */ | |
2778 } | |
2779 } | |
2780 | |
2781 if (!keeplayer) { | |
2782 for (i = index + 1; i < data->totlayer; ++i) | |
2783 data->layers[i - 1] = data->layers[i]; | |
2784 data->totlayer--; | |
2785 } | |
2786 | |
2787 return keeplayer; | |
2788 } | |
2789 | |
2790 /****************************** External Files *******************************/ | |
2791 | |
2792 static void customdata_external_filename(char filename[FILE_MAX], ID *id, Custom
DataExternal *external) | |
2793 { | |
2794 BLI_strncpy(filename, external->filename, FILE_MAX); | |
2795 BLI_path_abs(filename, ID_BLEND_PATH(G.main, id)); | |
2796 } | |
2797 | |
2798 void CustomData_external_reload(CustomData *data, ID *UNUSED(id), CustomDataMask
mask, int totelem) | |
2799 { | |
2800 CustomDataLayer *layer; | |
2801 const LayerTypeInfo *typeInfo; | |
2802 int i; | |
2803 | |
2804 for (i = 0; i < data->totlayer; i++) { | |
2805 layer = &data->layers[i]; | |
2806 typeInfo = layerType_getInfo(layer->type); | |
2807 | |
2808 if (!(mask & CD_TYPE_AS_MASK(layer->type))) ; | |
2809 else if ((layer->flag & CD_FLAG_EXTERNAL) && (layer->flag & CD_F
LAG_IN_MEMORY)) { | |
2810 if (typeInfo->free) | |
2811 typeInfo->free(layer->data, totelem, typeInfo->s
ize); | |
2812 layer->flag &= ~CD_FLAG_IN_MEMORY; | |
2813 } | |
2814 } | |
2815 } | |
2816 | |
2817 void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int
totelem) | |
2818 { | |
2819 CustomDataExternal *external = data->external; | |
2820 CustomDataLayer *layer; | |
2821 CDataFile *cdf; | |
2822 CDataFileLayer *blay; | |
2823 char filename[FILE_MAX]; | |
2824 const LayerTypeInfo *typeInfo; | |
2825 int i, update = 0; | |
2826 | |
2827 if (!external) | |
2828 return; | |
2829 ········ | |
2830 for (i = 0; i < data->totlayer; i++) { | |
2831 layer = &data->layers[i]; | |
2832 typeInfo = layerType_getInfo(layer->type); | |
2833 | |
2834 if (!(mask & CD_TYPE_AS_MASK(layer->type))) ; | |
2835 else if (layer->flag & CD_FLAG_IN_MEMORY) ; | |
2836 else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) | |
2837 update = 1; | |
2838 } | |
2839 | |
2840 if (!update) | |
2841 return; | |
2842 | |
2843 customdata_external_filename(filename, id, external); | |
2844 | |
2845 cdf = cdf_create(CDF_TYPE_MESH); | |
2846 if (!cdf_read_open(cdf, filename)) { | |
2847 fprintf(stderr, "Failed to read %s layer from %s.\n", layerType_
getName(layer->type), filename); | |
2848 return; | |
2849 } | |
2850 | |
2851 for (i = 0; i < data->totlayer; i++) { | |
2852 layer = &data->layers[i]; | |
2853 typeInfo = layerType_getInfo(layer->type); | |
2854 | |
2855 if (!(mask & CD_TYPE_AS_MASK(layer->type))) ; | |
2856 else if (layer->flag & CD_FLAG_IN_MEMORY) ; | |
2857 else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) { | |
2858 blay = cdf_layer_find(cdf, layer->type, layer->name); | |
2859 | |
2860 if (blay) { | |
2861 if (cdf_read_layer(cdf, blay)) { | |
2862 if (typeInfo->read(cdf, layer->data, tot
elem)) ; | |
2863 else break; | |
2864 layer->flag |= CD_FLAG_IN_MEMORY; | |
2865 } | |
2866 else | |
2867 break; | |
2868 } | |
2869 } | |
2870 } | |
2871 | |
2872 cdf_read_close(cdf); | |
2873 cdf_free(cdf); | |
2874 } | |
2875 | |
2876 void CustomData_external_write(CustomData *data, ID *id, CustomDataMask mask, in
t totelem, int free) | |
2877 { | |
2878 CustomDataExternal *external = data->external; | |
2879 CustomDataLayer *layer; | |
2880 CDataFile *cdf; | |
2881 CDataFileLayer *blay; | |
2882 const LayerTypeInfo *typeInfo; | |
2883 int i, update = 0; | |
2884 char filename[FILE_MAX]; | |
2885 | |
2886 if (!external) | |
2887 return; | |
2888 | |
2889 /* test if there is anything to write */ | |
2890 for (i = 0; i < data->totlayer; i++) { | |
2891 layer = &data->layers[i]; | |
2892 typeInfo = layerType_getInfo(layer->type); | |
2893 | |
2894 if (!(mask & CD_TYPE_AS_MASK(layer->type))) ; | |
2895 else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) | |
2896 update = 1; | |
2897 } | |
2898 | |
2899 if (!update) | |
2900 return; | |
2901 | |
2902 /* make sure data is read before we try to write */ | |
2903 CustomData_external_read(data, id, mask, totelem); | |
2904 customdata_external_filename(filename, id, external); | |
2905 | |
2906 cdf = cdf_create(CDF_TYPE_MESH); | |
2907 | |
2908 for (i = 0; i < data->totlayer; i++) { | |
2909 layer = &data->layers[i]; | |
2910 typeInfo = layerType_getInfo(layer->type); | |
2911 | |
2912 if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->filesize) { | |
2913 if (layer->flag & CD_FLAG_IN_MEMORY) { | |
2914 cdf_layer_add(cdf, layer->type, layer->name, | |
2915 typeInfo->filesize(cdf, layer->dat
a, totelem)); | |
2916 } | |
2917 else { | |
2918 cdf_free(cdf); | |
2919 return; /* read failed for a layer! */ | |
2920 } | |
2921 } | |
2922 } | |
2923 | |
2924 if (!cdf_write_open(cdf, filename)) { | |
2925 fprintf(stderr, "Failed to open %s for writing.\n", filename); | |
2926 return; | |
2927 } | |
2928 | |
2929 for (i = 0; i < data->totlayer; i++) { | |
2930 layer = &data->layers[i]; | |
2931 typeInfo = layerType_getInfo(layer->type); | |
2932 | |
2933 if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) { | |
2934 blay = cdf_layer_find(cdf, layer->type, layer->name); | |
2935 | |
2936 if (cdf_write_layer(cdf, blay)) { | |
2937 if (typeInfo->write(cdf, layer->data, totelem))
; | |
2938 else break; | |
2939 } | |
2940 else | |
2941 break; | |
2942 } | |
2943 } | |
2944 | |
2945 if (i != data->totlayer) { | |
2946 fprintf(stderr, "Failed to write data to %s.\n", filename); | |
2947 cdf_free(cdf); | |
2948 return; | |
2949 } | |
2950 | |
2951 for (i = 0; i < data->totlayer; i++) { | |
2952 layer = &data->layers[i]; | |
2953 typeInfo = layerType_getInfo(layer->type); | |
2954 | |
2955 if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) { | |
2956 if (free) { | |
2957 if (typeInfo->free) | |
2958 typeInfo->free(layer->data, totelem, typ
eInfo->size); | |
2959 layer->flag &= ~CD_FLAG_IN_MEMORY; | |
2960 } | |
2961 } | |
2962 } | |
2963 | |
2964 cdf_write_close(cdf); | |
2965 cdf_free(cdf); | |
2966 } | |
2967 | |
2968 void CustomData_external_add(CustomData *data, ID *UNUSED(id), int type, int UNU
SED(totelem), const char *filename) | |
2969 { | |
2970 CustomDataExternal *external = data->external; | |
2971 CustomDataLayer *layer; | |
2972 int layer_index; | |
2973 | |
2974 layer_index = CustomData_get_active_layer_index(data, type); | |
2975 if (layer_index < 0) return; | |
2976 | |
2977 layer = &data->layers[layer_index]; | |
2978 | |
2979 if (layer->flag & CD_FLAG_EXTERNAL) | |
2980 return; | |
2981 | |
2982 if (!external) { | |
2983 external = MEM_callocN(sizeof(CustomDataExternal), "CustomDataEx
ternal"); | |
2984 data->external = external; | |
2985 } | |
2986 BLI_strncpy(external->filename, filename, sizeof(external->filename)); | |
2987 | |
2988 layer->flag |= CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY; | |
2989 } | |
2990 | |
2991 void CustomData_external_remove(CustomData *data, ID *id, int type, int totelem) | |
2992 { | |
2993 CustomDataExternal *external = data->external; | |
2994 CustomDataLayer *layer; | |
2995 //char filename[FILE_MAX]; | |
2996 int layer_index; // i, remove_file; | |
2997 | |
2998 layer_index = CustomData_get_active_layer_index(data, type); | |
2999 if (layer_index < 0) return; | |
3000 | |
3001 layer = &data->layers[layer_index]; | |
3002 | |
3003 if (!external) | |
3004 return; | |
3005 | |
3006 if (layer->flag & CD_FLAG_EXTERNAL) { | |
3007 if (!(layer->flag & CD_FLAG_IN_MEMORY)) | |
3008 CustomData_external_read(data, id, CD_TYPE_AS_MASK(layer
->type), totelem); | |
3009 | |
3010 layer->flag &= ~CD_FLAG_EXTERNAL; | |
3011 | |
3012 #if 0 | |
3013 remove_file = 1; | |
3014 for (i = 0; i < data->totlayer; i++) | |
3015 if (data->layers[i].flag & CD_FLAG_EXTERNAL) | |
3016 remove_file = 0; | |
3017 | |
3018 if (remove_file) { | |
3019 customdata_external_filename(filename, id, external); | |
3020 cdf_remove(filename); | |
3021 CustomData_external_free(data); | |
3022 } | |
3023 #endif | |
3024 } | |
3025 } | |
3026 | |
3027 int CustomData_external_test(CustomData *data, int type) | |
3028 { | |
3029 CustomDataLayer *layer; | |
3030 int layer_index; | |
3031 | |
3032 layer_index = CustomData_get_active_layer_index(data, type); | |
3033 if (layer_index < 0) return 0; | |
3034 | |
3035 layer = &data->layers[layer_index]; | |
3036 return (layer->flag & CD_FLAG_EXTERNAL); | |
3037 } | |
3038 | |
3039 #if 0 | |
3040 void CustomData_external_remove_object(CustomData *data, ID *id) | |
3041 { | |
3042 CustomDataExternal *external = data->external; | |
3043 char filename[FILE_MAX]; | |
3044 | |
3045 if (!external) | |
3046 return; | |
3047 | |
3048 customdata_external_filename(filename, id, external); | |
3049 cdf_remove(filename); | |
3050 CustomData_external_free(data); | |
3051 } | |
3052 #endif | |
3053 | |
LEFT | RIGHT |