diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/blenkernel/intern/data_transfer.c | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/blenkernel/intern/data_transfer.c')
-rw-r--r-- | source/blender/blenkernel/intern/data_transfer.c | 3038 |
1 files changed, 1740 insertions, 1298 deletions
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index 779128bfb3f..41e8cfe188d 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -51,428 +51,490 @@ static CLG_LogRef LOG = {"bke.data_transfer"}; -void BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types, CustomData_MeshMasks *r_data_masks) +void BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types, + CustomData_MeshMasks *r_data_masks) { - for (int i = 0; i < DT_TYPE_MAX; i++) { - const int dtdata_type = 1 << i; - int cddata_type; - - if (!(dtdata_types & dtdata_type)) { - continue; - } - - cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type); - if (!(cddata_type & CD_FAKE)) { - if (DT_DATATYPE_IS_VERT(dtdata_type)) { - r_data_masks->vmask |= 1LL << cddata_type; - } - else if (DT_DATATYPE_IS_EDGE(dtdata_type)) { - r_data_masks->emask |= 1LL << cddata_type; - } - else if (DT_DATATYPE_IS_LOOP(dtdata_type)) { - r_data_masks->lmask |= 1LL << cddata_type; - } - else if (DT_DATATYPE_IS_POLY(dtdata_type)) { - r_data_masks->pmask |= 1LL << cddata_type; - } - } - else if (cddata_type == CD_FAKE_MDEFORMVERT) { - r_data_masks->vmask |= CD_MASK_MDEFORMVERT; /* Exception for vgroups :/ */ - } - else if (cddata_type == CD_FAKE_UV) { - r_data_masks->lmask |= CD_MASK_MLOOPUV; - } - else if (cddata_type == CD_FAKE_LNOR) { - r_data_masks->vmask |= CD_MASK_NORMAL; - r_data_masks->lmask |= CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL; - } - } + for (int i = 0; i < DT_TYPE_MAX; i++) { + const int dtdata_type = 1 << i; + int cddata_type; + + if (!(dtdata_types & dtdata_type)) { + continue; + } + + cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type); + if (!(cddata_type & CD_FAKE)) { + if (DT_DATATYPE_IS_VERT(dtdata_type)) { + r_data_masks->vmask |= 1LL << cddata_type; + } + else if (DT_DATATYPE_IS_EDGE(dtdata_type)) { + r_data_masks->emask |= 1LL << cddata_type; + } + else if (DT_DATATYPE_IS_LOOP(dtdata_type)) { + r_data_masks->lmask |= 1LL << cddata_type; + } + else if (DT_DATATYPE_IS_POLY(dtdata_type)) { + r_data_masks->pmask |= 1LL << cddata_type; + } + } + else if (cddata_type == CD_FAKE_MDEFORMVERT) { + r_data_masks->vmask |= CD_MASK_MDEFORMVERT; /* Exception for vgroups :/ */ + } + else if (cddata_type == CD_FAKE_UV) { + r_data_masks->lmask |= CD_MASK_MLOOPUV; + } + else if (cddata_type == CD_FAKE_LNOR) { + r_data_masks->vmask |= CD_MASK_NORMAL; + r_data_masks->lmask |= CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL; + } + } } /* Check what can do each layer type (if it is actually handled by transferdata, if it supports advanced mixing... */ -bool BKE_object_data_transfer_get_dttypes_capacity( - const int dtdata_types, bool *r_advanced_mixing, bool *r_threshold) +bool BKE_object_data_transfer_get_dttypes_capacity(const int dtdata_types, + bool *r_advanced_mixing, + bool *r_threshold) { - int i; - bool ret = false; - - *r_advanced_mixing = false; - *r_threshold = false; - - for (i = 0; (i < DT_TYPE_MAX) && !(ret && *r_advanced_mixing && *r_threshold); i++) { - const int dtdata_type = 1 << i; - - if (!(dtdata_types & dtdata_type)) { - continue; - } - - switch (dtdata_type) { - /* Vertex data */ - case DT_TYPE_MDEFORMVERT: - *r_advanced_mixing = true; - *r_threshold = true; - ret = true; - break; - case DT_TYPE_SKIN: - *r_threshold = true; - ret = true; - break; - case DT_TYPE_BWEIGHT_VERT: - ret = true; - break; - /* Edge data */ - case DT_TYPE_SHARP_EDGE: - *r_threshold = true; - ret = true; - break; - case DT_TYPE_SEAM: - *r_threshold = true; - ret = true; - break; - case DT_TYPE_CREASE: - ret = true; - break; - case DT_TYPE_BWEIGHT_EDGE: - ret = true; - break; - case DT_TYPE_FREESTYLE_EDGE: - *r_threshold = true; - ret = true; - break; - /* Loop/Poly data */ - case DT_TYPE_UV: - ret = true; - break; - case DT_TYPE_VCOL: - *r_advanced_mixing = true; - *r_threshold = true; - ret = true; - break; - case DT_TYPE_LNOR: - *r_advanced_mixing = true; - ret = true; - break; - case DT_TYPE_SHARP_FACE: - *r_threshold = true; - ret = true; - break; - case DT_TYPE_FREESTYLE_FACE: - *r_threshold = true; - ret = true; - break; - } - } - - return ret; + int i; + bool ret = false; + + *r_advanced_mixing = false; + *r_threshold = false; + + for (i = 0; (i < DT_TYPE_MAX) && !(ret && *r_advanced_mixing && *r_threshold); i++) { + const int dtdata_type = 1 << i; + + if (!(dtdata_types & dtdata_type)) { + continue; + } + + switch (dtdata_type) { + /* Vertex data */ + case DT_TYPE_MDEFORMVERT: + *r_advanced_mixing = true; + *r_threshold = true; + ret = true; + break; + case DT_TYPE_SKIN: + *r_threshold = true; + ret = true; + break; + case DT_TYPE_BWEIGHT_VERT: + ret = true; + break; + /* Edge data */ + case DT_TYPE_SHARP_EDGE: + *r_threshold = true; + ret = true; + break; + case DT_TYPE_SEAM: + *r_threshold = true; + ret = true; + break; + case DT_TYPE_CREASE: + ret = true; + break; + case DT_TYPE_BWEIGHT_EDGE: + ret = true; + break; + case DT_TYPE_FREESTYLE_EDGE: + *r_threshold = true; + ret = true; + break; + /* Loop/Poly data */ + case DT_TYPE_UV: + ret = true; + break; + case DT_TYPE_VCOL: + *r_advanced_mixing = true; + *r_threshold = true; + ret = true; + break; + case DT_TYPE_LNOR: + *r_advanced_mixing = true; + ret = true; + break; + case DT_TYPE_SHARP_FACE: + *r_threshold = true; + ret = true; + break; + case DT_TYPE_FREESTYLE_FACE: + *r_threshold = true; + ret = true; + break; + } + } + + return ret; } int BKE_object_data_transfer_get_dttypes_item_types(const int dtdata_types) { - int i, ret = 0; - - for (i = 0; (i < DT_TYPE_MAX) && (ret ^ (ME_VERT | ME_EDGE | ME_LOOP | ME_POLY)); i++) { - const int dtdata_type = 1 << i; - - if (!(dtdata_types & dtdata_type)) { - continue; - } - - if (DT_DATATYPE_IS_VERT(dtdata_type)) { - ret |= ME_VERT; - } - if (DT_DATATYPE_IS_EDGE(dtdata_type)) { - ret |= ME_EDGE; - } - if (DT_DATATYPE_IS_LOOP(dtdata_type)) { - ret |= ME_LOOP; - } - if (DT_DATATYPE_IS_POLY(dtdata_type)) { - ret |= ME_POLY; - } - } - - return ret; + int i, ret = 0; + + for (i = 0; (i < DT_TYPE_MAX) && (ret ^ (ME_VERT | ME_EDGE | ME_LOOP | ME_POLY)); i++) { + const int dtdata_type = 1 << i; + + if (!(dtdata_types & dtdata_type)) { + continue; + } + + if (DT_DATATYPE_IS_VERT(dtdata_type)) { + ret |= ME_VERT; + } + if (DT_DATATYPE_IS_EDGE(dtdata_type)) { + ret |= ME_EDGE; + } + if (DT_DATATYPE_IS_LOOP(dtdata_type)) { + ret |= ME_LOOP; + } + if (DT_DATATYPE_IS_POLY(dtdata_type)) { + ret |= ME_POLY; + } + } + + return ret; } int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type) { - switch (dtdata_type) { - case DT_TYPE_MDEFORMVERT: - return CD_FAKE_MDEFORMVERT; - case DT_TYPE_SHAPEKEY: - return CD_FAKE_SHAPEKEY; - case DT_TYPE_SKIN: - return CD_MVERT_SKIN; - case DT_TYPE_BWEIGHT_VERT: - return CD_FAKE_BWEIGHT; - - case DT_TYPE_SHARP_EDGE: - return CD_FAKE_SHARP; - case DT_TYPE_SEAM: - return CD_FAKE_SEAM; - case DT_TYPE_CREASE: - return CD_FAKE_CREASE; - case DT_TYPE_BWEIGHT_EDGE: - return CD_FAKE_BWEIGHT; - case DT_TYPE_FREESTYLE_EDGE: - return CD_FREESTYLE_EDGE; - - case DT_TYPE_UV: - return CD_FAKE_UV; - case DT_TYPE_SHARP_FACE: - return CD_FAKE_SHARP; - case DT_TYPE_FREESTYLE_FACE: - return CD_FREESTYLE_FACE; - - case DT_TYPE_VCOL: - return CD_MLOOPCOL; - case DT_TYPE_LNOR: - return CD_FAKE_LNOR; - - default: - BLI_assert(0); - } - return 0; /* Should never be reached! */ + switch (dtdata_type) { + case DT_TYPE_MDEFORMVERT: + return CD_FAKE_MDEFORMVERT; + case DT_TYPE_SHAPEKEY: + return CD_FAKE_SHAPEKEY; + case DT_TYPE_SKIN: + return CD_MVERT_SKIN; + case DT_TYPE_BWEIGHT_VERT: + return CD_FAKE_BWEIGHT; + + case DT_TYPE_SHARP_EDGE: + return CD_FAKE_SHARP; + case DT_TYPE_SEAM: + return CD_FAKE_SEAM; + case DT_TYPE_CREASE: + return CD_FAKE_CREASE; + case DT_TYPE_BWEIGHT_EDGE: + return CD_FAKE_BWEIGHT; + case DT_TYPE_FREESTYLE_EDGE: + return CD_FREESTYLE_EDGE; + + case DT_TYPE_UV: + return CD_FAKE_UV; + case DT_TYPE_SHARP_FACE: + return CD_FAKE_SHARP; + case DT_TYPE_FREESTYLE_FACE: + return CD_FREESTYLE_FACE; + + case DT_TYPE_VCOL: + return CD_MLOOPCOL; + case DT_TYPE_LNOR: + return CD_FAKE_LNOR; + + default: + BLI_assert(0); + } + return 0; /* Should never be reached! */ } int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type) { - switch (dtdata_type) { - case DT_TYPE_MDEFORMVERT: - return DT_MULTILAYER_INDEX_MDEFORMVERT; - case DT_TYPE_SHAPEKEY: - return DT_MULTILAYER_INDEX_SHAPEKEY; - case DT_TYPE_UV: - return DT_MULTILAYER_INDEX_UV; - case DT_TYPE_VCOL: - return DT_MULTILAYER_INDEX_VCOL; - default: - return DT_MULTILAYER_INDEX_INVALID; - } + switch (dtdata_type) { + case DT_TYPE_MDEFORMVERT: + return DT_MULTILAYER_INDEX_MDEFORMVERT; + case DT_TYPE_SHAPEKEY: + return DT_MULTILAYER_INDEX_SHAPEKEY; + case DT_TYPE_UV: + return DT_MULTILAYER_INDEX_UV; + case DT_TYPE_VCOL: + return DT_MULTILAYER_INDEX_VCOL; + default: + return DT_MULTILAYER_INDEX_INVALID; + } } /* ********** */ /* Generic pre/post processing, only used by custom loop normals currently. */ -static void data_transfer_dtdata_type_preprocess( - Mesh *me_src, Mesh *me_dst, - const int dtdata_type, const bool dirty_nors_dst) +static void data_transfer_dtdata_type_preprocess(Mesh *me_src, + Mesh *me_dst, + const int dtdata_type, + const bool dirty_nors_dst) { - if (dtdata_type == DT_TYPE_LNOR) { - /* Compute custom normals into regular loop normals, which will be used for the transfer. */ - MVert *verts_dst = me_dst->mvert; - const int num_verts_dst = me_dst->totvert; - MEdge *edges_dst = me_dst->medge; - const int num_edges_dst = me_dst->totedge; - MPoly *polys_dst = me_dst->mpoly; - const int num_polys_dst = me_dst->totpoly; - MLoop *loops_dst = me_dst->mloop; - const int num_loops_dst = me_dst->totloop; - CustomData *pdata_dst = &me_dst->pdata; - CustomData *ldata_dst = &me_dst->ldata; - - const bool use_split_nors_dst = (me_dst->flag & ME_AUTOSMOOTH) != 0; - const float split_angle_dst = me_dst->smoothresh; - - /* This should be ensured by cddata_masks we pass to code generating/giving us me_src now. */ - BLI_assert(CustomData_get_layer(&me_src->ldata, CD_NORMAL) != NULL); - BLI_assert(CustomData_get_layer(&me_src->pdata, CD_NORMAL) != NULL); - (void)me_src; - - float (*poly_nors_dst)[3]; - float (*loop_nors_dst)[3]; - short (*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL); - - /* Cache poly nors into a temp CDLayer. */ - poly_nors_dst = CustomData_get_layer(pdata_dst, CD_NORMAL); - const bool do_poly_nors_dst = (poly_nors_dst == NULL); - if (do_poly_nors_dst) { - poly_nors_dst = CustomData_add_layer(pdata_dst, CD_NORMAL, CD_CALLOC, NULL, num_polys_dst); - CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY); - } - if (dirty_nors_dst || do_poly_nors_dst) { - BKE_mesh_calc_normals_poly( - verts_dst, NULL, num_verts_dst, loops_dst, polys_dst, - num_loops_dst, num_polys_dst, poly_nors_dst, true); - } - /* Cache loop nors into a temp CDLayer. */ - loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL); - const bool do_loop_nors_dst = (loop_nors_dst == NULL); - if (do_loop_nors_dst) { - loop_nors_dst = CustomData_add_layer(ldata_dst, CD_NORMAL, CD_CALLOC, NULL, num_loops_dst); - CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY); - } - if (dirty_nors_dst || do_loop_nors_dst) { - BKE_mesh_normals_loop_split( - verts_dst, num_verts_dst, edges_dst, num_edges_dst, - loops_dst, loop_nors_dst, num_loops_dst, - polys_dst, (const float (*)[3])poly_nors_dst, num_polys_dst, - use_split_nors_dst, split_angle_dst, NULL, custom_nors_dst, NULL); - } - } + if (dtdata_type == DT_TYPE_LNOR) { + /* Compute custom normals into regular loop normals, which will be used for the transfer. */ + MVert *verts_dst = me_dst->mvert; + const int num_verts_dst = me_dst->totvert; + MEdge *edges_dst = me_dst->medge; + const int num_edges_dst = me_dst->totedge; + MPoly *polys_dst = me_dst->mpoly; + const int num_polys_dst = me_dst->totpoly; + MLoop *loops_dst = me_dst->mloop; + const int num_loops_dst = me_dst->totloop; + CustomData *pdata_dst = &me_dst->pdata; + CustomData *ldata_dst = &me_dst->ldata; + + const bool use_split_nors_dst = (me_dst->flag & ME_AUTOSMOOTH) != 0; + const float split_angle_dst = me_dst->smoothresh; + + /* This should be ensured by cddata_masks we pass to code generating/giving us me_src now. */ + BLI_assert(CustomData_get_layer(&me_src->ldata, CD_NORMAL) != NULL); + BLI_assert(CustomData_get_layer(&me_src->pdata, CD_NORMAL) != NULL); + (void)me_src; + + float(*poly_nors_dst)[3]; + float(*loop_nors_dst)[3]; + short(*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL); + + /* Cache poly nors into a temp CDLayer. */ + poly_nors_dst = CustomData_get_layer(pdata_dst, CD_NORMAL); + const bool do_poly_nors_dst = (poly_nors_dst == NULL); + if (do_poly_nors_dst) { + poly_nors_dst = CustomData_add_layer(pdata_dst, CD_NORMAL, CD_CALLOC, NULL, num_polys_dst); + CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY); + } + if (dirty_nors_dst || do_poly_nors_dst) { + BKE_mesh_calc_normals_poly(verts_dst, + NULL, + num_verts_dst, + loops_dst, + polys_dst, + num_loops_dst, + num_polys_dst, + poly_nors_dst, + true); + } + /* Cache loop nors into a temp CDLayer. */ + loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL); + const bool do_loop_nors_dst = (loop_nors_dst == NULL); + if (do_loop_nors_dst) { + loop_nors_dst = CustomData_add_layer(ldata_dst, CD_NORMAL, CD_CALLOC, NULL, num_loops_dst); + CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY); + } + if (dirty_nors_dst || do_loop_nors_dst) { + BKE_mesh_normals_loop_split(verts_dst, + num_verts_dst, + edges_dst, + num_edges_dst, + loops_dst, + loop_nors_dst, + num_loops_dst, + polys_dst, + (const float(*)[3])poly_nors_dst, + num_polys_dst, + use_split_nors_dst, + split_angle_dst, + NULL, + custom_nors_dst, + NULL); + } + } } -static void data_transfer_dtdata_type_postprocess( - Object *UNUSED(ob_src), Object *UNUSED(ob_dst), Mesh *UNUSED(me_src), Mesh *me_dst, - const int dtdata_type, const bool changed) +static void data_transfer_dtdata_type_postprocess(Object *UNUSED(ob_src), + Object *UNUSED(ob_dst), + Mesh *UNUSED(me_src), + Mesh *me_dst, + const int dtdata_type, + const bool changed) { - if (dtdata_type == DT_TYPE_LNOR) { - /* Bake edited destination loop normals into custom normals again. */ - MVert *verts_dst = me_dst->mvert; - const int num_verts_dst = me_dst->totvert; - MEdge *edges_dst = me_dst->medge; - const int num_edges_dst = me_dst->totedge; - MPoly *polys_dst = me_dst->mpoly; - const int num_polys_dst = me_dst->totpoly; - MLoop *loops_dst = me_dst->mloop; - const int num_loops_dst = me_dst->totloop; - CustomData *pdata_dst = &me_dst->pdata; - CustomData *ldata_dst = &me_dst->ldata; - - const float (*poly_nors_dst)[3] = CustomData_get_layer(pdata_dst, CD_NORMAL); - float (*loop_nors_dst)[3] = CustomData_get_layer(ldata_dst, CD_NORMAL); - short (*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL); - - BLI_assert(poly_nors_dst); - - if (!changed) { - return; - } - - if (!custom_nors_dst) { - custom_nors_dst = CustomData_add_layer(ldata_dst, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, num_loops_dst); - } - - /* Note loop_nors_dst contains our custom normals as transferred from source... */ - BKE_mesh_normals_loop_custom_set(verts_dst, num_verts_dst, edges_dst, num_edges_dst, - loops_dst, loop_nors_dst, num_loops_dst, - polys_dst, poly_nors_dst, num_polys_dst, - custom_nors_dst); - } + if (dtdata_type == DT_TYPE_LNOR) { + /* Bake edited destination loop normals into custom normals again. */ + MVert *verts_dst = me_dst->mvert; + const int num_verts_dst = me_dst->totvert; + MEdge *edges_dst = me_dst->medge; + const int num_edges_dst = me_dst->totedge; + MPoly *polys_dst = me_dst->mpoly; + const int num_polys_dst = me_dst->totpoly; + MLoop *loops_dst = me_dst->mloop; + const int num_loops_dst = me_dst->totloop; + CustomData *pdata_dst = &me_dst->pdata; + CustomData *ldata_dst = &me_dst->ldata; + + const float(*poly_nors_dst)[3] = CustomData_get_layer(pdata_dst, CD_NORMAL); + float(*loop_nors_dst)[3] = CustomData_get_layer(ldata_dst, CD_NORMAL); + short(*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL); + + BLI_assert(poly_nors_dst); + + if (!changed) { + return; + } + + if (!custom_nors_dst) { + custom_nors_dst = CustomData_add_layer( + ldata_dst, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, num_loops_dst); + } + + /* Note loop_nors_dst contains our custom normals as transferred from source... */ + BKE_mesh_normals_loop_custom_set(verts_dst, + num_verts_dst, + edges_dst, + num_edges_dst, + loops_dst, + loop_nors_dst, + num_loops_dst, + polys_dst, + poly_nors_dst, + num_polys_dst, + custom_nors_dst); + } } /* ********** */ static MeshRemapIslandsCalc data_transfer_get_loop_islands_generator(const int cddata_type) { - switch (cddata_type) { - case CD_FAKE_UV: - return BKE_mesh_calc_islands_loop_poly_edgeseam; - default: - break; - } - return NULL; + switch (cddata_type) { + case CD_FAKE_UV: + return BKE_mesh_calc_islands_loop_poly_edgeseam; + default: + break; + } + return NULL; } -float data_transfer_interp_float_do( - const int mix_mode, const float val_dst, const float val_src, const float mix_factor) +float data_transfer_interp_float_do(const int mix_mode, + const float val_dst, + const float val_src, + const float mix_factor) { - float val_ret; - - if (((mix_mode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && (val_dst < mix_factor)) || - (mix_mode == CDT_MIX_REPLACE_BELOW_THRESHOLD && (val_dst > mix_factor)))) - { - return val_dst; /* Do not affect destination. */ - } - - switch (mix_mode) { - case CDT_MIX_REPLACE_ABOVE_THRESHOLD: - case CDT_MIX_REPLACE_BELOW_THRESHOLD: - return val_src; - case CDT_MIX_MIX: - val_ret = (val_dst + val_src) * 0.5f; - break; - case CDT_MIX_ADD: - val_ret = val_dst + val_src; - break; - case CDT_MIX_SUB: - val_ret = val_dst - val_src; - break; - case CDT_MIX_MUL: - val_ret = val_dst * val_src; - break; - case CDT_MIX_TRANSFER: - default: - val_ret = val_src; - break; - } - return interpf(val_ret, val_dst, mix_factor); + float val_ret; + + if (((mix_mode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && (val_dst < mix_factor)) || + (mix_mode == CDT_MIX_REPLACE_BELOW_THRESHOLD && (val_dst > mix_factor)))) { + return val_dst; /* Do not affect destination. */ + } + + switch (mix_mode) { + case CDT_MIX_REPLACE_ABOVE_THRESHOLD: + case CDT_MIX_REPLACE_BELOW_THRESHOLD: + return val_src; + case CDT_MIX_MIX: + val_ret = (val_dst + val_src) * 0.5f; + break; + case CDT_MIX_ADD: + val_ret = val_dst + val_src; + break; + case CDT_MIX_SUB: + val_ret = val_dst - val_src; + break; + case CDT_MIX_MUL: + val_ret = val_dst * val_src; + break; + case CDT_MIX_TRANSFER: + default: + val_ret = val_src; + break; + } + return interpf(val_ret, val_dst, mix_factor); } -static void data_transfer_interp_char( - const CustomDataTransferLayerMap *laymap, void *dest, - const void **sources, const float *weights, const int count, const float mix_factor) +static void data_transfer_interp_char(const CustomDataTransferLayerMap *laymap, + void *dest, + const void **sources, + const float *weights, + const int count, + const float mix_factor) { - const char **data_src = (const char **)sources; - char *data_dst = (char *)dest; + const char **data_src = (const char **)sources; + char *data_dst = (char *)dest; - const int mix_mode = laymap->mix_mode; - float val_src = 0.0f; - const float val_dst = (float)(*data_dst) / 255.0f; + const int mix_mode = laymap->mix_mode; + float val_src = 0.0f; + const float val_dst = (float)(*data_dst) / 255.0f; - int i; + int i; - for (i = count; i--;) { - val_src += ((float)(*data_src[i]) / 255.0f) * weights[i]; - } + for (i = count; i--;) { + val_src += ((float)(*data_src[i]) / 255.0f) * weights[i]; + } - val_src = data_transfer_interp_float_do(mix_mode, val_dst, val_src, mix_factor); + val_src = data_transfer_interp_float_do(mix_mode, val_dst, val_src, mix_factor); - CLAMP(val_src, 0.0f, 1.0f); + CLAMP(val_src, 0.0f, 1.0f); - *data_dst = (char)(val_src * 255.0f); + *data_dst = (char)(val_src * 255.0f); } /* Helpers to match sources and destinations data layers (also handles 'conversions' in CD_FAKE cases). */ -void data_transfer_layersmapping_add_item( - ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights, - const void *data_src, void *data_dst, const int data_src_n, const int data_dst_n, - const size_t elem_size, const size_t data_size, const size_t data_offset, const uint64_t data_flag, - cd_datatransfer_interp interp, void *interp_data) +void data_transfer_layersmapping_add_item(ListBase *r_map, + const int cddata_type, + const int mix_mode, + const float mix_factor, + const float *mix_weights, + const void *data_src, + void *data_dst, + const int data_src_n, + const int data_dst_n, + const size_t elem_size, + const size_t data_size, + const size_t data_offset, + const uint64_t data_flag, + cd_datatransfer_interp interp, + void *interp_data) { - CustomDataTransferLayerMap *item = MEM_mallocN(sizeof(*item), __func__); + CustomDataTransferLayerMap *item = MEM_mallocN(sizeof(*item), __func__); - BLI_assert(data_dst != NULL); + BLI_assert(data_dst != NULL); - item->data_type = cddata_type; - item->mix_mode = mix_mode; - item->mix_factor = mix_factor; - item->mix_weights = mix_weights; + item->data_type = cddata_type; + item->mix_mode = mix_mode; + item->mix_factor = mix_factor; + item->mix_weights = mix_weights; - item->data_src = data_src; - item->data_dst = data_dst; - item->data_src_n = data_src_n; - item->data_dst_n = data_dst_n; - item->elem_size = elem_size; + item->data_src = data_src; + item->data_dst = data_dst; + item->data_src_n = data_src_n; + item->data_dst_n = data_dst_n; + item->elem_size = elem_size; - item->data_size = data_size; - item->data_offset = data_offset; - item->data_flag = data_flag; + item->data_size = data_size; + item->data_offset = data_offset; + item->data_flag = data_flag; - item->interp = interp; - item->interp_data = interp_data; + item->interp = interp; + item->interp_data = interp_data; - BLI_addtail(r_map, item); + BLI_addtail(r_map, item); } -static void data_transfer_layersmapping_add_item_cd( - ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights, - void *data_src, void *data_dst, cd_datatransfer_interp interp, void *interp_data) +static void data_transfer_layersmapping_add_item_cd(ListBase *r_map, + const int cddata_type, + const int mix_mode, + const float mix_factor, + const float *mix_weights, + void *data_src, + void *data_dst, + cd_datatransfer_interp interp, + void *interp_data) { - uint64_t data_flag = 0; - - if (cddata_type == CD_FREESTYLE_EDGE) { - data_flag = FREESTYLE_EDGE_MARK; - } - else if (cddata_type == CD_FREESTYLE_FACE) { - data_flag = FREESTYLE_FACE_MARK; - } - - data_transfer_layersmapping_add_item( - r_map, cddata_type, mix_mode, mix_factor, mix_weights, data_src, data_dst, - 0, 0, 0, 0, 0, data_flag, interp, interp_data); + uint64_t data_flag = 0; + + if (cddata_type == CD_FREESTYLE_EDGE) { + data_flag = FREESTYLE_EDGE_MARK; + } + else if (cddata_type == CD_FREESTYLE_FACE) { + data_flag = FREESTYLE_FACE_MARK; + } + + data_transfer_layersmapping_add_item(r_map, + cddata_type, + mix_mode, + mix_factor, + mix_weights, + data_src, + data_dst, + 0, + 0, + 0, + 0, + 0, + data_flag, + interp, + interp_data); } /* Note: All those layer mapping handlers return false *only* if they were given invalid parameters. @@ -481,506 +543,681 @@ static void data_transfer_layersmapping_add_item_cd( * to given parameters. */ -static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst( - ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights, - const int num_elem_dst, const bool use_create, const bool use_delete, - CustomData *cd_src, CustomData *cd_dst, const bool use_dupref_dst, - const int tolayers, bool *use_layers_src, const int num_layers_src, - cd_datatransfer_interp interp, void *interp_data) +static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map, + const int cddata_type, + const int mix_mode, + const float mix_factor, + const float *mix_weights, + const int num_elem_dst, + const bool use_create, + const bool use_delete, + CustomData *cd_src, + CustomData *cd_dst, + const bool use_dupref_dst, + const int tolayers, + bool *use_layers_src, + const int num_layers_src, + cd_datatransfer_interp interp, + void *interp_data) { - void *data_src, *data_dst = NULL; - int idx_src = num_layers_src; - int idx_dst, tot_dst = CustomData_number_of_layers(cd_dst, cddata_type); - bool *data_dst_to_delete = NULL; - - if (!use_layers_src) { - /* No source at all, we can only delete all dest if requested... */ - if (use_delete) { - idx_dst = tot_dst; - while (idx_dst--) { - CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, idx_dst); - } - } - return true; - } - - switch (tolayers) { - case DT_LAYERS_INDEX_DST: - idx_dst = tot_dst; - - /* Find last source actually used! */ - while (idx_src-- && !use_layers_src[idx_src]); - idx_src++; - - if (idx_dst < idx_src) { - if (use_create) { - /* Create as much data layers as necessary! */ - for (; idx_dst < idx_src; idx_dst++) { - CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst); - } - } - else { - /* Otherwise, just try to map what we can with existing dst data layers. */ - idx_src = idx_dst; - } - } - else if (use_delete && idx_dst > idx_src) { - while (idx_dst-- > idx_src) { - CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, idx_dst); - } - } - if (r_map) { - while (idx_src--) { - if (!use_layers_src[idx_src]) { - continue; - } - data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src); - /* If dest is a evaluated mesh (fro; ;odifier), we do not want to overwrite cdlayers of orig mesh! */ - if (use_dupref_dst) { - data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_src, num_elem_dst); - } - else { - data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_src); - } - data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights, - data_src, data_dst, interp, interp_data); - } - } - break; - case DT_LAYERS_NAME_DST: - if (use_delete) { - if (tot_dst) { - data_dst_to_delete = MEM_mallocN(sizeof(*data_dst_to_delete) * (size_t)tot_dst, __func__); - memset(data_dst_to_delete, true, sizeof(*data_dst_to_delete) * (size_t)tot_dst); - } - } - - while (idx_src--) { - const char *name; - - if (!use_layers_src[idx_src]) { - continue; - } - - name = CustomData_get_layer_name(cd_src, cddata_type, idx_src); - data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src); - - if ((idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name)) == -1) { - if (use_create) { - CustomData_add_layer_named(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst, name); - idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name); - } - else { - /* If we are not allowed to create missing dst data layers, just skip matching src one. */ - continue; - } - } - else if (data_dst_to_delete) { - data_dst_to_delete[idx_dst] = false; - } - if (r_map) { - /* If dest is a evaluated mesh (from modifier), we do not want to overwrite cdlayers of orig mesh! */ - if (use_dupref_dst) { - data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst); - } - else { - data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst); - } - data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights, - data_src, data_dst, interp, interp_data); - } - } - - if (data_dst_to_delete) { - /* Note: This won't affect newly created layers, if any, since tot_dst has not been updated! - * Also, looping backward ensures us we do not suffer from index shifting when deleting a layer. - */ - for (idx_dst = tot_dst; idx_dst--;) { - if (data_dst_to_delete[idx_dst]) { - CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, idx_dst); - } - } - - MEM_freeN(data_dst_to_delete); - } - break; - default: - return false; - } - - return true; + void *data_src, *data_dst = NULL; + int idx_src = num_layers_src; + int idx_dst, tot_dst = CustomData_number_of_layers(cd_dst, cddata_type); + bool *data_dst_to_delete = NULL; + + if (!use_layers_src) { + /* No source at all, we can only delete all dest if requested... */ + if (use_delete) { + idx_dst = tot_dst; + while (idx_dst--) { + CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, idx_dst); + } + } + return true; + } + + switch (tolayers) { + case DT_LAYERS_INDEX_DST: + idx_dst = tot_dst; + + /* Find last source actually used! */ + while (idx_src-- && !use_layers_src[idx_src]) + ; + idx_src++; + + if (idx_dst < idx_src) { + if (use_create) { + /* Create as much data layers as necessary! */ + for (; idx_dst < idx_src; idx_dst++) { + CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst); + } + } + else { + /* Otherwise, just try to map what we can with existing dst data layers. */ + idx_src = idx_dst; + } + } + else if (use_delete && idx_dst > idx_src) { + while (idx_dst-- > idx_src) { + CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, idx_dst); + } + } + if (r_map) { + while (idx_src--) { + if (!use_layers_src[idx_src]) { + continue; + } + data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src); + /* If dest is a evaluated mesh (fro; ;odifier), we do not want to overwrite cdlayers of orig mesh! */ + if (use_dupref_dst) { + data_dst = CustomData_duplicate_referenced_layer_n( + cd_dst, cddata_type, idx_src, num_elem_dst); + } + else { + data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_src); + } + data_transfer_layersmapping_add_item_cd(r_map, + cddata_type, + mix_mode, + mix_factor, + mix_weights, + data_src, + data_dst, + interp, + interp_data); + } + } + break; + case DT_LAYERS_NAME_DST: + if (use_delete) { + if (tot_dst) { + data_dst_to_delete = MEM_mallocN(sizeof(*data_dst_to_delete) * (size_t)tot_dst, + __func__); + memset(data_dst_to_delete, true, sizeof(*data_dst_to_delete) * (size_t)tot_dst); + } + } + + while (idx_src--) { + const char *name; + + if (!use_layers_src[idx_src]) { + continue; + } + + name = CustomData_get_layer_name(cd_src, cddata_type, idx_src); + data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src); + + if ((idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name)) == -1) { + if (use_create) { + CustomData_add_layer_named(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst, name); + idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name); + } + else { + /* If we are not allowed to create missing dst data layers, just skip matching src one. */ + continue; + } + } + else if (data_dst_to_delete) { + data_dst_to_delete[idx_dst] = false; + } + if (r_map) { + /* If dest is a evaluated mesh (from modifier), we do not want to overwrite cdlayers of orig mesh! */ + if (use_dupref_dst) { + data_dst = CustomData_duplicate_referenced_layer_n( + cd_dst, cddata_type, idx_dst, num_elem_dst); + } + else { + data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst); + } + data_transfer_layersmapping_add_item_cd(r_map, + cddata_type, + mix_mode, + mix_factor, + mix_weights, + data_src, + data_dst, + interp, + interp_data); + } + } + + if (data_dst_to_delete) { + /* Note: This won't affect newly created layers, if any, since tot_dst has not been updated! + * Also, looping backward ensures us we do not suffer from index shifting when deleting a layer. + */ + for (idx_dst = tot_dst; idx_dst--;) { + if (data_dst_to_delete[idx_dst]) { + CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, idx_dst); + } + } + + MEM_freeN(data_dst_to_delete); + } + break; + default: + return false; + } + + return true; } -static bool data_transfer_layersmapping_cdlayers( - ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights, - const int num_elem_dst, const bool use_create, const bool use_delete, - CustomData *cd_src, CustomData *cd_dst, const bool use_dupref_dst, - const int fromlayers, const int tolayers, - cd_datatransfer_interp interp, void *interp_data) +static bool data_transfer_layersmapping_cdlayers(ListBase *r_map, + const int cddata_type, + const int mix_mode, + const float mix_factor, + const float *mix_weights, + const int num_elem_dst, + const bool use_create, + const bool use_delete, + CustomData *cd_src, + CustomData *cd_dst, + const bool use_dupref_dst, + const int fromlayers, + const int tolayers, + cd_datatransfer_interp interp, + void *interp_data) { - int idx_src, idx_dst; - void *data_src, *data_dst = NULL; - - if (CustomData_layertype_is_singleton(cddata_type)) { - if (!(data_src = CustomData_get_layer(cd_src, cddata_type))) { - if (use_delete) { - CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, 0); - } - return true; - } - - data_dst = CustomData_get_layer(cd_dst, cddata_type); - if (!data_dst) { - if (!use_create) { - return true; - } - data_dst = CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst); - } - else if (use_dupref_dst && r_map) { - /* If dest is a evaluated mesh (from modifier), we do not want to overwrite cdlayers of orig mesh! */ - data_dst = CustomData_duplicate_referenced_layer(cd_dst, cddata_type, num_elem_dst); - } - - if (r_map) { - data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights, - data_src, data_dst, interp, interp_data); - } - } - else if (fromlayers == DT_LAYERS_ACTIVE_SRC || fromlayers >= 0) { - /* Note: use_delete has not much meaning in this case, ignored. */ - - if (fromlayers >= 0) { /* Real-layer index */ - idx_src = fromlayers; - } - else { - if ((idx_src = CustomData_get_active_layer(cd_src, cddata_type)) == -1) { - return true; - } - } - data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src); - if (!data_src) { - return true; - } - - if (tolayers >= 0) { /* Real-layer index */ - idx_dst = tolayers; - /* If dest is a evaluated mesh (from modifier), we do not want to overwrite cdlayers of orig mesh! */ - if (use_dupref_dst && r_map) { - data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst); - } - else { - data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst); - } - } - else if (tolayers == DT_LAYERS_ACTIVE_DST) { - if ((idx_dst = CustomData_get_active_layer(cd_dst, cddata_type)) == -1) { - if (!use_create) { - return true; - } - data_dst = CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst); - } - else { - /* If dest is a evaluated mesh (from modifier), we do not want to overwrite cdlayers of orig mesh! */ - if (use_dupref_dst && r_map) { - data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst); - } - else { - data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst); - } - } - } - else if (tolayers == DT_LAYERS_INDEX_DST) { - int num = CustomData_number_of_layers(cd_dst, cddata_type); - idx_dst = idx_src; - if (num <= idx_dst) { - if (!use_create) { - return true; - } - /* Create as much data layers as necessary! */ - for (; num <= idx_dst; num++) { - CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst); - } - } - /* If dest is a evaluated mesh (from modifier), we do not want to overwrite cdlayers of orig mesh! */ - if (use_dupref_dst && r_map) { - data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst); - } - else { - data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst); - } - } - else if (tolayers == DT_LAYERS_NAME_DST) { - const char *name = CustomData_get_layer_name(cd_src, cddata_type, idx_src); - if ((idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name)) == -1) { - if (!use_create) { - return true; - } - CustomData_add_layer_named(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst, name); - idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name); - } - /* If dest is a evaluated mesh (from modifier), we do not want to overwrite cdlayers of orig mesh! */ - if (use_dupref_dst && r_map) { - data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst); - } - else { - data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst); - } - } - else { - return false; - } - - if (!data_dst) { - return false; - } - - if (r_map) { - data_transfer_layersmapping_add_item_cd( - r_map, cddata_type, mix_mode, mix_factor, mix_weights, data_src, data_dst, interp, interp_data); - } - } - else if (fromlayers == DT_LAYERS_ALL_SRC) { - int num_src = CustomData_number_of_layers(cd_src, cddata_type); - bool *use_layers_src = num_src ? MEM_mallocN(sizeof(*use_layers_src) * (size_t)num_src, __func__) : NULL; - bool ret; - - if (use_layers_src) { - memset(use_layers_src, true, sizeof(*use_layers_src) * num_src); - } - - ret = data_transfer_layersmapping_cdlayers_multisrc_to_dst( - r_map, cddata_type, mix_mode, mix_factor, mix_weights, - num_elem_dst, use_create, use_delete, cd_src, cd_dst, use_dupref_dst, - tolayers, use_layers_src, num_src, - interp, interp_data); - - if (use_layers_src) { - MEM_freeN(use_layers_src); - } - return ret; - } - else { - return false; - } - - return true; + int idx_src, idx_dst; + void *data_src, *data_dst = NULL; + + if (CustomData_layertype_is_singleton(cddata_type)) { + if (!(data_src = CustomData_get_layer(cd_src, cddata_type))) { + if (use_delete) { + CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, 0); + } + return true; + } + + data_dst = CustomData_get_layer(cd_dst, cddata_type); + if (!data_dst) { + if (!use_create) { + return true; + } + data_dst = CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst); + } + else if (use_dupref_dst && r_map) { + /* If dest is a evaluated mesh (from modifier), we do not want to overwrite cdlayers of orig mesh! */ + data_dst = CustomData_duplicate_referenced_layer(cd_dst, cddata_type, num_elem_dst); + } + + if (r_map) { + data_transfer_layersmapping_add_item_cd(r_map, + cddata_type, + mix_mode, + mix_factor, + mix_weights, + data_src, + data_dst, + interp, + interp_data); + } + } + else if (fromlayers == DT_LAYERS_ACTIVE_SRC || fromlayers >= 0) { + /* Note: use_delete has not much meaning in this case, ignored. */ + + if (fromlayers >= 0) { /* Real-layer index */ + idx_src = fromlayers; + } + else { + if ((idx_src = CustomData_get_active_layer(cd_src, cddata_type)) == -1) { + return true; + } + } + data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src); + if (!data_src) { + return true; + } + + if (tolayers >= 0) { /* Real-layer index */ + idx_dst = tolayers; + /* If dest is a evaluated mesh (from modifier), we do not want to overwrite cdlayers of orig mesh! */ + if (use_dupref_dst && r_map) { + data_dst = CustomData_duplicate_referenced_layer_n( + cd_dst, cddata_type, idx_dst, num_elem_dst); + } + else { + data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst); + } + } + else if (tolayers == DT_LAYERS_ACTIVE_DST) { + if ((idx_dst = CustomData_get_active_layer(cd_dst, cddata_type)) == -1) { + if (!use_create) { + return true; + } + data_dst = CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst); + } + else { + /* If dest is a evaluated mesh (from modifier), we do not want to overwrite cdlayers of orig mesh! */ + if (use_dupref_dst && r_map) { + data_dst = CustomData_duplicate_referenced_layer_n( + cd_dst, cddata_type, idx_dst, num_elem_dst); + } + else { + data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst); + } + } + } + else if (tolayers == DT_LAYERS_INDEX_DST) { + int num = CustomData_number_of_layers(cd_dst, cddata_type); + idx_dst = idx_src; + if (num <= idx_dst) { + if (!use_create) { + return true; + } + /* Create as much data layers as necessary! */ + for (; num <= idx_dst; num++) { + CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst); + } + } + /* If dest is a evaluated mesh (from modifier), we do not want to overwrite cdlayers of orig mesh! */ + if (use_dupref_dst && r_map) { + data_dst = CustomData_duplicate_referenced_layer_n( + cd_dst, cddata_type, idx_dst, num_elem_dst); + } + else { + data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst); + } + } + else if (tolayers == DT_LAYERS_NAME_DST) { + const char *name = CustomData_get_layer_name(cd_src, cddata_type, idx_src); + if ((idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name)) == -1) { + if (!use_create) { + return true; + } + CustomData_add_layer_named(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst, name); + idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name); + } + /* If dest is a evaluated mesh (from modifier), we do not want to overwrite cdlayers of orig mesh! */ + if (use_dupref_dst && r_map) { + data_dst = CustomData_duplicate_referenced_layer_n( + cd_dst, cddata_type, idx_dst, num_elem_dst); + } + else { + data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst); + } + } + else { + return false; + } + + if (!data_dst) { + return false; + } + + if (r_map) { + data_transfer_layersmapping_add_item_cd(r_map, + cddata_type, + mix_mode, + mix_factor, + mix_weights, + data_src, + data_dst, + interp, + interp_data); + } + } + else if (fromlayers == DT_LAYERS_ALL_SRC) { + int num_src = CustomData_number_of_layers(cd_src, cddata_type); + bool *use_layers_src = num_src ? + MEM_mallocN(sizeof(*use_layers_src) * (size_t)num_src, __func__) : + NULL; + bool ret; + + if (use_layers_src) { + memset(use_layers_src, true, sizeof(*use_layers_src) * num_src); + } + + ret = data_transfer_layersmapping_cdlayers_multisrc_to_dst(r_map, + cddata_type, + mix_mode, + mix_factor, + mix_weights, + num_elem_dst, + use_create, + use_delete, + cd_src, + cd_dst, + use_dupref_dst, + tolayers, + use_layers_src, + num_src, + interp, + interp_data); + + if (use_layers_src) { + MEM_freeN(use_layers_src); + } + return ret; + } + else { + return false; + } + + return true; } -static bool data_transfer_layersmapping_generate( - ListBase *r_map, Object *ob_src, Object *ob_dst, Mesh *me_src, Mesh *me_dst, - const int elem_type, int cddata_type, int mix_mode, float mix_factor, const float *mix_weights, - const int num_elem_dst, const bool use_create, const bool use_delete, const int fromlayers, const int tolayers, - SpaceTransform *space_transform) +static bool data_transfer_layersmapping_generate(ListBase *r_map, + Object *ob_src, + Object *ob_dst, + Mesh *me_src, + Mesh *me_dst, + const int elem_type, + int cddata_type, + int mix_mode, + float mix_factor, + const float *mix_weights, + const int num_elem_dst, + const bool use_create, + const bool use_delete, + const int fromlayers, + const int tolayers, + SpaceTransform *space_transform) { - CustomData *cd_src, *cd_dst; - - cd_datatransfer_interp interp = NULL; - void *interp_data = NULL; - - if (elem_type == ME_VERT) { - if (!(cddata_type & CD_FAKE)) { - cd_src = &me_src->vdata; - cd_dst = &me_dst->vdata; - - if (!data_transfer_layersmapping_cdlayers(r_map, cddata_type, mix_mode, mix_factor, mix_weights, - num_elem_dst, use_create, use_delete, - cd_src, cd_dst, me_dst != ob_dst->data, - fromlayers, tolayers, - interp, interp_data)) - { - /* We handle specific source selection cases here. */ - return false; - } - return true; - } - else if (cddata_type == CD_FAKE_BWEIGHT) { - const size_t elem_size = sizeof(*((MVert *)NULL)); - const size_t data_size = sizeof(((MVert *)NULL)->bweight); - const size_t data_offset = offsetof(MVert, bweight); - const uint64_t data_flag = 0; - - if (!(me_src->cd_flag & ME_CDFLAG_VERT_BWEIGHT)) { - if (use_delete) { - me_dst->cd_flag &= ~ME_CDFLAG_VERT_BWEIGHT; - } - return true; - } - me_dst->cd_flag |= ME_CDFLAG_VERT_BWEIGHT; - if (r_map) { - data_transfer_layersmapping_add_item(r_map, cddata_type, mix_mode, mix_factor, mix_weights, - me_src->mvert, me_dst->mvert, - me_src->totvert, me_dst->totvert, - elem_size, data_size, data_offset, data_flag, - data_transfer_interp_char, interp_data); - } - return true; - } - else if (cddata_type == CD_FAKE_MDEFORMVERT) { - bool ret; - - cd_src = &me_src->vdata; - cd_dst = &me_dst->vdata; - - ret = data_transfer_layersmapping_vgroups(r_map, mix_mode, mix_factor, mix_weights, - num_elem_dst, use_create, use_delete, - ob_src, ob_dst, cd_src, cd_dst, me_dst != ob_dst->data, - fromlayers, tolayers); - - /* Mesh stores its dvert in a specific pointer too. :( */ - me_dst->dvert = CustomData_get_layer(&me_dst->vdata, CD_MDEFORMVERT); - return ret; - } - else if (cddata_type == CD_FAKE_SHAPEKEY) { - /* TODO: leaving shapekeys aside for now, quite specific case, since we can't access them from MVert :/ */ - return false; - } - } - else if (elem_type == ME_EDGE) { - if (!(cddata_type & CD_FAKE)) { /* Unused for edges, currently... */ - cd_src = &me_src->edata; - cd_dst = &me_dst->edata; - - if (!data_transfer_layersmapping_cdlayers(r_map, cddata_type, mix_mode, mix_factor, mix_weights, - num_elem_dst, use_create, use_delete, - cd_src, cd_dst, me_dst != ob_dst->data, - fromlayers, tolayers, - interp, interp_data)) - { - /* We handle specific source selection cases here. */ - return false; - } - return true; - } - else if (cddata_type == CD_FAKE_CREASE) { - const size_t elem_size = sizeof(*((MEdge *)NULL)); - const size_t data_size = sizeof(((MEdge *)NULL)->crease); - const size_t data_offset = offsetof(MEdge, crease); - const uint64_t data_flag = 0; - - if (!(me_src->cd_flag & ME_CDFLAG_EDGE_CREASE)) { - if (use_delete && !me_dst) { - me_dst->cd_flag &= ~ME_CDFLAG_EDGE_CREASE; - } - return true; - } - me_dst->cd_flag |= ME_CDFLAG_EDGE_CREASE; - if (r_map) { - data_transfer_layersmapping_add_item(r_map, cddata_type, mix_mode, mix_factor, mix_weights, - me_src->medge, me_dst->medge, - me_src->totedge, me_dst->totedge, - elem_size, data_size, data_offset, data_flag, - data_transfer_interp_char, interp_data); - } - return true; - } - else if (cddata_type == CD_FAKE_BWEIGHT) { - const size_t elem_size = sizeof(*((MEdge *)NULL)); - const size_t data_size = sizeof(((MEdge *)NULL)->bweight); - const size_t data_offset = offsetof(MEdge, bweight); - const uint64_t data_flag = 0; - - if (!(me_src->cd_flag & ME_CDFLAG_EDGE_BWEIGHT)) { - if (use_delete && !me_dst) { - me_dst->cd_flag &= ~ME_CDFLAG_EDGE_BWEIGHT; - } - return true; - } - me_dst->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; - if (r_map) { - data_transfer_layersmapping_add_item(r_map, cddata_type, mix_mode, mix_factor, mix_weights, - me_src->medge, me_dst->medge, - me_src->totedge, me_dst->totedge, - elem_size, data_size, data_offset, data_flag, - data_transfer_interp_char, interp_data); - } - return true; - } - else if (r_map && ELEM(cddata_type, CD_FAKE_SHARP, CD_FAKE_SEAM)) { - const size_t elem_size = sizeof(*((MEdge *)NULL)); - const size_t data_size = sizeof(((MEdge *)NULL)->flag); - const size_t data_offset = offsetof(MEdge, flag); - const uint64_t data_flag = (cddata_type == CD_FAKE_SHARP) ? ME_SHARP : ME_SEAM; - - data_transfer_layersmapping_add_item( - r_map, cddata_type, mix_mode, mix_factor, mix_weights, - me_src->medge, me_dst->medge, - me_src->totedge, me_dst->totedge, - elem_size, data_size, data_offset, data_flag, NULL, interp_data); - return true; - } - else { - return false; - } - } - else if (elem_type == ME_LOOP) { - if (cddata_type == CD_FAKE_UV) { - cddata_type = CD_MLOOPUV; - } - else if (cddata_type == CD_FAKE_LNOR) { - /* Preprocess should have generated it, Postprocess will convert it back to CD_CUSTOMLOOPNORMAL. */ - cddata_type = CD_NORMAL; - interp_data = space_transform; - interp = customdata_data_transfer_interp_normal_normals; - } - - if (!(cddata_type & CD_FAKE)) { - cd_src = &me_src->ldata; - cd_dst = &me_dst->ldata; - - if (!data_transfer_layersmapping_cdlayers( - r_map, cddata_type, mix_mode, mix_factor, mix_weights, - num_elem_dst, use_create, use_delete, cd_src, cd_dst, me_dst != ob_dst->data, - fromlayers, tolayers, - interp, interp_data)) - { - /* We handle specific source selection cases here. */ - return false; - } - return true; - } - else { - return false; - } - } - else if (elem_type == ME_POLY) { - if (cddata_type == CD_FAKE_UV) { - cddata_type = CD_MLOOPUV; - } - - if (!(cddata_type & CD_FAKE)) { - cd_src = &me_src->pdata; - cd_dst = &me_dst->pdata; - - if (!data_transfer_layersmapping_cdlayers( - r_map, cddata_type, mix_mode, mix_factor, mix_weights, - num_elem_dst, use_create, use_delete, cd_src, cd_dst, me_dst != ob_dst->data, - fromlayers, tolayers, - interp, interp_data)) - { - /* We handle specific source selection cases here. */ - return false; - } - return true; - } - else if (r_map && cddata_type == CD_FAKE_SHARP) { - const size_t elem_size = sizeof(*((MPoly *)NULL)); - const size_t data_size = sizeof(((MPoly *)NULL)->flag); - const size_t data_offset = offsetof(MPoly, flag); - const uint64_t data_flag = ME_SMOOTH; - - data_transfer_layersmapping_add_item( - r_map, cddata_type, mix_mode, mix_factor, mix_weights, - me_src->mpoly, me_dst->mpoly, - me_src->totpoly, me_dst->totpoly, - elem_size, data_size, data_offset, data_flag, NULL, interp_data); - return true; - } - else { - return false; - } - } - - return false; + CustomData *cd_src, *cd_dst; + + cd_datatransfer_interp interp = NULL; + void *interp_data = NULL; + + if (elem_type == ME_VERT) { + if (!(cddata_type & CD_FAKE)) { + cd_src = &me_src->vdata; + cd_dst = &me_dst->vdata; + + if (!data_transfer_layersmapping_cdlayers(r_map, + cddata_type, + mix_mode, + mix_factor, + mix_weights, + num_elem_dst, + use_create, + use_delete, + cd_src, + cd_dst, + me_dst != ob_dst->data, + fromlayers, + tolayers, + interp, + interp_data)) { + /* We handle specific source selection cases here. */ + return false; + } + return true; + } + else if (cddata_type == CD_FAKE_BWEIGHT) { + const size_t elem_size = sizeof(*((MVert *)NULL)); + const size_t data_size = sizeof(((MVert *)NULL)->bweight); + const size_t data_offset = offsetof(MVert, bweight); + const uint64_t data_flag = 0; + + if (!(me_src->cd_flag & ME_CDFLAG_VERT_BWEIGHT)) { + if (use_delete) { + me_dst->cd_flag &= ~ME_CDFLAG_VERT_BWEIGHT; + } + return true; + } + me_dst->cd_flag |= ME_CDFLAG_VERT_BWEIGHT; + if (r_map) { + data_transfer_layersmapping_add_item(r_map, + cddata_type, + mix_mode, + mix_factor, + mix_weights, + me_src->mvert, + me_dst->mvert, + me_src->totvert, + me_dst->totvert, + elem_size, + data_size, + data_offset, + data_flag, + data_transfer_interp_char, + interp_data); + } + return true; + } + else if (cddata_type == CD_FAKE_MDEFORMVERT) { + bool ret; + + cd_src = &me_src->vdata; + cd_dst = &me_dst->vdata; + + ret = data_transfer_layersmapping_vgroups(r_map, + mix_mode, + mix_factor, + mix_weights, + num_elem_dst, + use_create, + use_delete, + ob_src, + ob_dst, + cd_src, + cd_dst, + me_dst != ob_dst->data, + fromlayers, + tolayers); + + /* Mesh stores its dvert in a specific pointer too. :( */ + me_dst->dvert = CustomData_get_layer(&me_dst->vdata, CD_MDEFORMVERT); + return ret; + } + else if (cddata_type == CD_FAKE_SHAPEKEY) { + /* TODO: leaving shapekeys aside for now, quite specific case, since we can't access them from MVert :/ */ + return false; + } + } + else if (elem_type == ME_EDGE) { + if (!(cddata_type & CD_FAKE)) { /* Unused for edges, currently... */ + cd_src = &me_src->edata; + cd_dst = &me_dst->edata; + + if (!data_transfer_layersmapping_cdlayers(r_map, + cddata_type, + mix_mode, + mix_factor, + mix_weights, + num_elem_dst, + use_create, + use_delete, + cd_src, + cd_dst, + me_dst != ob_dst->data, + fromlayers, + tolayers, + interp, + interp_data)) { + /* We handle specific source selection cases here. */ + return false; + } + return true; + } + else if (cddata_type == CD_FAKE_CREASE) { + const size_t elem_size = sizeof(*((MEdge *)NULL)); + const size_t data_size = sizeof(((MEdge *)NULL)->crease); + const size_t data_offset = offsetof(MEdge, crease); + const uint64_t data_flag = 0; + + if (!(me_src->cd_flag & ME_CDFLAG_EDGE_CREASE)) { + if (use_delete && !me_dst) { + me_dst->cd_flag &= ~ME_CDFLAG_EDGE_CREASE; + } + return true; + } + me_dst->cd_flag |= ME_CDFLAG_EDGE_CREASE; + if (r_map) { + data_transfer_layersmapping_add_item(r_map, + cddata_type, + mix_mode, + mix_factor, + mix_weights, + me_src->medge, + me_dst->medge, + me_src->totedge, + me_dst->totedge, + elem_size, + data_size, + data_offset, + data_flag, + data_transfer_interp_char, + interp_data); + } + return true; + } + else if (cddata_type == CD_FAKE_BWEIGHT) { + const size_t elem_size = sizeof(*((MEdge *)NULL)); + const size_t data_size = sizeof(((MEdge *)NULL)->bweight); + const size_t data_offset = offsetof(MEdge, bweight); + const uint64_t data_flag = 0; + + if (!(me_src->cd_flag & ME_CDFLAG_EDGE_BWEIGHT)) { + if (use_delete && !me_dst) { + me_dst->cd_flag &= ~ME_CDFLAG_EDGE_BWEIGHT; + } + return true; + } + me_dst->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; + if (r_map) { + data_transfer_layersmapping_add_item(r_map, + cddata_type, + mix_mode, + mix_factor, + mix_weights, + me_src->medge, + me_dst->medge, + me_src->totedge, + me_dst->totedge, + elem_size, + data_size, + data_offset, + data_flag, + data_transfer_interp_char, + interp_data); + } + return true; + } + else if (r_map && ELEM(cddata_type, CD_FAKE_SHARP, CD_FAKE_SEAM)) { + const size_t elem_size = sizeof(*((MEdge *)NULL)); + const size_t data_size = sizeof(((MEdge *)NULL)->flag); + const size_t data_offset = offsetof(MEdge, flag); + const uint64_t data_flag = (cddata_type == CD_FAKE_SHARP) ? ME_SHARP : ME_SEAM; + + data_transfer_layersmapping_add_item(r_map, + cddata_type, + mix_mode, + mix_factor, + mix_weights, + me_src->medge, + me_dst->medge, + me_src->totedge, + me_dst->totedge, + elem_size, + data_size, + data_offset, + data_flag, + NULL, + interp_data); + return true; + } + else { + return false; + } + } + else if (elem_type == ME_LOOP) { + if (cddata_type == CD_FAKE_UV) { + cddata_type = CD_MLOOPUV; + } + else if (cddata_type == CD_FAKE_LNOR) { + /* Preprocess should have generated it, Postprocess will convert it back to CD_CUSTOMLOOPNORMAL. */ + cddata_type = CD_NORMAL; + interp_data = space_transform; + interp = customdata_data_transfer_interp_normal_normals; + } + + if (!(cddata_type & CD_FAKE)) { + cd_src = &me_src->ldata; + cd_dst = &me_dst->ldata; + + if (!data_transfer_layersmapping_cdlayers(r_map, + cddata_type, + mix_mode, + mix_factor, + mix_weights, + num_elem_dst, + use_create, + use_delete, + cd_src, + cd_dst, + me_dst != ob_dst->data, + fromlayers, + tolayers, + interp, + interp_data)) { + /* We handle specific source selection cases here. */ + return false; + } + return true; + } + else { + return false; + } + } + else if (elem_type == ME_POLY) { + if (cddata_type == CD_FAKE_UV) { + cddata_type = CD_MLOOPUV; + } + + if (!(cddata_type & CD_FAKE)) { + cd_src = &me_src->pdata; + cd_dst = &me_dst->pdata; + + if (!data_transfer_layersmapping_cdlayers(r_map, + cddata_type, + mix_mode, + mix_factor, + mix_weights, + num_elem_dst, + use_create, + use_delete, + cd_src, + cd_dst, + me_dst != ob_dst->data, + fromlayers, + tolayers, + interp, + interp_data)) { + /* We handle specific source selection cases here. */ + return false; + } + return true; + } + else if (r_map && cddata_type == CD_FAKE_SHARP) { + const size_t elem_size = sizeof(*((MPoly *)NULL)); + const size_t data_size = sizeof(((MPoly *)NULL)->flag); + const size_t data_offset = offsetof(MPoly, flag); + const uint64_t data_flag = ME_SMOOTH; + + data_transfer_layersmapping_add_item(r_map, + cddata_type, + mix_mode, + mix_factor, + mix_weights, + me_src->mpoly, + me_dst->mpoly, + me_src->totpoly, + me_dst->totpoly, + elem_size, + data_size, + data_offset, + data_flag, + NULL, + interp_data); + return true; + } + else { + return false; + } + } + + return false; } /** @@ -989,90 +1226,161 @@ static bool data_transfer_layersmapping_generate( * If \a use_delete is true, it will also delete data layers on \a ob_dst that do not match those from \a ob_src, * to get (as much as possible) exact copy of source data layout. */ -void BKE_object_data_transfer_layout( - struct Depsgraph *depsgraph, Scene *scene, - Object *ob_src, Object *ob_dst, const int data_types, const bool use_delete, - const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX]) +void BKE_object_data_transfer_layout(struct Depsgraph *depsgraph, + Scene *scene, + Object *ob_src, + Object *ob_dst, + const int data_types, + const bool use_delete, + const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], + const int tolayers_select[DT_MULTILAYER_INDEX_MAX]) { - Mesh *me_src; - Mesh *me_dst; - int i; - - const bool use_create = true; /* We always create needed layers here. */ - - CustomData_MeshMasks me_src_mask = CD_MASK_BAREMESH; - - BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH)); - - me_dst = ob_dst->data; - - /* Get source evaluated mesh.*/ - BKE_object_data_transfer_dttypes_to_cdmask(data_types, &me_src_mask); - me_src = mesh_get_eval_final(depsgraph, scene, ob_src, &me_src_mask); - if (!me_src) { - return; - } - - /* Check all possible data types. */ - for (i = 0; i < DT_TYPE_MAX; i++) { - const int dtdata_type = 1 << i; - int cddata_type; - int fromlayers, tolayers, fromto_idx; - - if (!(data_types & dtdata_type)) { - continue; - } - - cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type); - - fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(dtdata_type); - if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) { - fromlayers = fromlayers_select[fromto_idx]; - tolayers = tolayers_select[fromto_idx]; - } - else { - fromlayers = tolayers = 0; - } - - if (DT_DATATYPE_IS_VERT(dtdata_type)) { - const int num_elem_dst = me_dst->totvert; - - data_transfer_layersmapping_generate( - NULL, ob_src, ob_dst, me_src, me_dst, ME_VERT, cddata_type, 0, 0.0f, NULL, - num_elem_dst, use_create, use_delete, fromlayers, tolayers, NULL); - } - if (DT_DATATYPE_IS_EDGE(dtdata_type)) { - const int num_elem_dst = me_dst->totedge; - - data_transfer_layersmapping_generate( - NULL, ob_src, ob_dst, me_src, me_dst, ME_EDGE, cddata_type, 0, 0.0f, NULL, - num_elem_dst, use_create, use_delete, fromlayers, tolayers, NULL); - } - if (DT_DATATYPE_IS_LOOP(dtdata_type)) { - const int num_elem_dst = me_dst->totloop; - - data_transfer_layersmapping_generate( - NULL, ob_src, ob_dst, me_src, me_dst, ME_LOOP, cddata_type, 0, 0.0f, NULL, - num_elem_dst, use_create, use_delete, fromlayers, tolayers, NULL); - } - if (DT_DATATYPE_IS_POLY(dtdata_type)) { - const int num_elem_dst = me_dst->totpoly; - - data_transfer_layersmapping_generate( - NULL, ob_src, ob_dst, me_src, me_dst, ME_POLY, cddata_type, 0, 0.0f, NULL, - num_elem_dst, use_create, use_delete, fromlayers, tolayers, NULL); - } - } + Mesh *me_src; + Mesh *me_dst; + int i; + + const bool use_create = true; /* We always create needed layers here. */ + + CustomData_MeshMasks me_src_mask = CD_MASK_BAREMESH; + + BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH)); + + me_dst = ob_dst->data; + + /* Get source evaluated mesh.*/ + BKE_object_data_transfer_dttypes_to_cdmask(data_types, &me_src_mask); + me_src = mesh_get_eval_final(depsgraph, scene, ob_src, &me_src_mask); + if (!me_src) { + return; + } + + /* Check all possible data types. */ + for (i = 0; i < DT_TYPE_MAX; i++) { + const int dtdata_type = 1 << i; + int cddata_type; + int fromlayers, tolayers, fromto_idx; + + if (!(data_types & dtdata_type)) { + continue; + } + + cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type); + + fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(dtdata_type); + if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) { + fromlayers = fromlayers_select[fromto_idx]; + tolayers = tolayers_select[fromto_idx]; + } + else { + fromlayers = tolayers = 0; + } + + if (DT_DATATYPE_IS_VERT(dtdata_type)) { + const int num_elem_dst = me_dst->totvert; + + data_transfer_layersmapping_generate(NULL, + ob_src, + ob_dst, + me_src, + me_dst, + ME_VERT, + cddata_type, + 0, + 0.0f, + NULL, + num_elem_dst, + use_create, + use_delete, + fromlayers, + tolayers, + NULL); + } + if (DT_DATATYPE_IS_EDGE(dtdata_type)) { + const int num_elem_dst = me_dst->totedge; + + data_transfer_layersmapping_generate(NULL, + ob_src, + ob_dst, + me_src, + me_dst, + ME_EDGE, + cddata_type, + 0, + 0.0f, + NULL, + num_elem_dst, + use_create, + use_delete, + fromlayers, + tolayers, + NULL); + } + if (DT_DATATYPE_IS_LOOP(dtdata_type)) { + const int num_elem_dst = me_dst->totloop; + + data_transfer_layersmapping_generate(NULL, + ob_src, + ob_dst, + me_src, + me_dst, + ME_LOOP, + cddata_type, + 0, + 0.0f, + NULL, + num_elem_dst, + use_create, + use_delete, + fromlayers, + tolayers, + NULL); + } + if (DT_DATATYPE_IS_POLY(dtdata_type)) { + const int num_elem_dst = me_dst->totpoly; + + data_transfer_layersmapping_generate(NULL, + ob_src, + ob_dst, + me_src, + me_dst, + ME_POLY, + cddata_type, + 0, + 0.0f, + NULL, + num_elem_dst, + use_create, + use_delete, + fromlayers, + tolayers, + NULL); + } + } } -bool BKE_object_data_transfer_ex( - struct Depsgraph *depsgraph, Scene *scene, Object *ob_src, Object *ob_dst, Mesh *me_dst, - const int data_types, bool use_create, const int map_vert_mode, const int map_edge_mode, - const int map_loop_mode, const int map_poly_mode, SpaceTransform *space_transform, const bool auto_transform, - const float max_distance, const float ray_radius, const float islands_handling_precision, - const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX], - const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup, - ReportList *reports) +bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, + Scene *scene, + Object *ob_src, + Object *ob_dst, + Mesh *me_dst, + const int data_types, + bool use_create, + const int map_vert_mode, + const int map_edge_mode, + const int map_loop_mode, + const int map_poly_mode, + SpaceTransform *space_transform, + const bool auto_transform, + const float max_distance, + const float ray_radius, + const float islands_handling_precision, + const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], + const int tolayers_select[DT_MULTILAYER_INDEX_MAX], + const int mix_mode, + const float mix_factor, + const char *vgroup_name, + const bool invert_vgroup, + ReportList *reports) { #define VDATA 0 #define EDATA 1 @@ -1080,352 +1388,456 @@ bool BKE_object_data_transfer_ex( #define PDATA 3 #define DATAMAX 4 - SpaceTransform auto_space_transform; - - Mesh *me_src; - bool dirty_nors_dst = true; /* Assumed always true if not using an evaluated mesh as destination. */ - int i; - - MDeformVert *mdef = NULL; - int vg_idx = -1; - float *weights[DATAMAX] = {NULL}; - - MeshPairRemap geom_map[DATAMAX] = {{0}}; - bool geom_map_init[DATAMAX] = {0}; - ListBase lay_map = {NULL}; - bool changed = false; - bool is_modifier = false; - - const bool use_delete = false; /* We never delete data layers from destination here. */ - - CustomData_MeshMasks me_src_mask = CD_MASK_BAREMESH; - - BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH)); - - if (me_dst) { - dirty_nors_dst = (me_dst->runtime.cd_dirty_vert & CD_NORMAL) != 0; - /* Never create needed custom layers on passed destination mesh - * (assumed to *not* be ob_dst->data, aka modifier case). */ - use_create = false; - is_modifier = true; - } - else { - me_dst = ob_dst->data; - } - - if (vgroup_name) { - mdef = CustomData_get_layer(&me_dst->vdata, CD_MDEFORMVERT); - if (mdef) { - vg_idx = defgroup_name_index(ob_dst, vgroup_name); - } - } - - /* Get source evaluated mesh.*/ - BKE_object_data_transfer_dttypes_to_cdmask(data_types, &me_src_mask); - BKE_mesh_remap_calc_source_cddata_masks_from_map_modes( - map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode, &me_src_mask); - if (is_modifier) { - me_src = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_src, false); - - if (me_src == NULL || !CustomData_MeshMasks_are_matching(&ob_src->runtime.last_data_mask, &me_src_mask)) { - CLOG_WARN(&LOG, "Data Transfer: source mesh data is not ready - dependency cycle?"); - return changed; - } - } - else { - me_src = mesh_get_eval_final(depsgraph, scene, ob_src, &me_src_mask); - } - if (!me_src) { - return changed; - } - - if (auto_transform) { - if (space_transform == NULL) { - space_transform = &auto_space_transform; - } - - BKE_mesh_remap_find_best_match_from_mesh(me_dst->mvert, me_dst->totvert, me_src, space_transform); - } - - /* Check all possible data types. - * Note item mappings and dest mix weights are cached. */ - for (i = 0; i < DT_TYPE_MAX; i++) { - const int dtdata_type = 1 << i; - int cddata_type; - int fromlayers, tolayers, fromto_idx; - - if (!(data_types & dtdata_type)) { - continue; - } - - data_transfer_dtdata_type_preprocess(me_src, me_dst, dtdata_type, dirty_nors_dst); - - cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type); - - fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(dtdata_type); - if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) { - fromlayers = fromlayers_select[fromto_idx]; - tolayers = tolayers_select[fromto_idx]; - } - else { - fromlayers = tolayers = 0; - } - - if (DT_DATATYPE_IS_VERT(dtdata_type)) { - MVert *verts_dst = me_dst->mvert; - const int num_verts_dst = me_dst->totvert; - - if (!geom_map_init[VDATA]) { - const int num_verts_src = me_src->totvert; - - if ((map_vert_mode == MREMAP_MODE_TOPOLOGY) && (num_verts_dst != num_verts_src)) { - BKE_report(reports, RPT_ERROR, - "Source and destination meshes do not have the same amount of vertices, " - "'Topology' mapping cannot be used in this case"); - continue; - } - if ((map_vert_mode & MREMAP_USE_EDGE) && (me_src->totedge == 0)) { - BKE_report(reports, RPT_ERROR, - "Source mesh doesn't have any edges, " - "None of the 'Edge' mappings can be used in this case"); - continue; - } - if ((map_vert_mode & MREMAP_USE_POLY) && (me_src->totpoly == 0)) { - BKE_report(reports, RPT_ERROR, - "Source mesh doesn't have any faces, " - "None of the 'Face' mappings can be used in this case"); - continue; - } - if (ELEM(0, num_verts_dst, num_verts_src)) { - BKE_report(reports, RPT_ERROR, - "Source or destination meshes do not have any vertices, cannot transfer vertex data"); - continue; - } - - BKE_mesh_remap_calc_verts_from_mesh( - map_vert_mode, space_transform, max_distance, ray_radius, - verts_dst, num_verts_dst, dirty_nors_dst, me_src, &geom_map[VDATA]); - geom_map_init[VDATA] = true; - } - - if (mdef && vg_idx != -1 && !weights[VDATA]) { - weights[VDATA] = MEM_mallocN(sizeof(*(weights[VDATA])) * (size_t)num_verts_dst, __func__); - BKE_defvert_extract_vgroup_to_vertweights(mdef, vg_idx, num_verts_dst, weights[VDATA], invert_vgroup); - } - - if (data_transfer_layersmapping_generate( - &lay_map, ob_src, ob_dst, me_src, me_dst, ME_VERT, - cddata_type, mix_mode, mix_factor, weights[VDATA], - num_verts_dst, use_create, use_delete, fromlayers, tolayers, space_transform)) - { - CustomDataTransferLayerMap *lay_mapit; - - changed = (lay_map.first != NULL); - - for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) { - CustomData_data_transfer(&geom_map[VDATA], lay_mapit); - } - - BLI_freelistN(&lay_map); - } - } - if (DT_DATATYPE_IS_EDGE(dtdata_type)) { - MVert *verts_dst = me_dst->mvert; - const int num_verts_dst = me_dst->totvert; - MEdge *edges_dst = me_dst->medge; - const int num_edges_dst = me_dst->totedge; - - if (!geom_map_init[EDATA]) { - const int num_edges_src = me_src->totedge; - - if ((map_edge_mode == MREMAP_MODE_TOPOLOGY) && (num_edges_dst != num_edges_src)) { - BKE_report(reports, RPT_ERROR, - "Source and destination meshes do not have the same amount of edges, " - "'Topology' mapping cannot be used in this case"); - continue; - } - if ((map_edge_mode & MREMAP_USE_POLY) && (me_src->totpoly == 0)) { - BKE_report(reports, RPT_ERROR, - "Source mesh doesn't have any faces, " - "None of the 'Face' mappings can be used in this case"); - continue; - } - if (ELEM(0, num_edges_dst, num_edges_src)) { - BKE_report(reports, RPT_ERROR, - "Source or destination meshes do not have any edges, cannot transfer edge data"); - continue; - } - - BKE_mesh_remap_calc_edges_from_mesh( - map_edge_mode, space_transform, max_distance, ray_radius, - verts_dst, num_verts_dst, edges_dst, num_edges_dst, dirty_nors_dst, - me_src, &geom_map[EDATA]); - geom_map_init[EDATA] = true; - } - - if (mdef && vg_idx != -1 && !weights[EDATA]) { - weights[EDATA] = MEM_mallocN(sizeof(*weights[EDATA]) * (size_t)num_edges_dst, __func__); - BKE_defvert_extract_vgroup_to_edgeweights( - mdef, vg_idx, num_verts_dst, edges_dst, num_edges_dst, - weights[EDATA], invert_vgroup); - } - - if (data_transfer_layersmapping_generate( - &lay_map, ob_src, ob_dst, me_src, me_dst, ME_EDGE, - cddata_type, mix_mode, mix_factor, weights[EDATA], - num_edges_dst, use_create, use_delete, fromlayers, tolayers, space_transform)) - { - CustomDataTransferLayerMap *lay_mapit; - - changed = (lay_map.first != NULL); - - for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) { - CustomData_data_transfer(&geom_map[EDATA], lay_mapit); - } - - BLI_freelistN(&lay_map); - } - } - if (DT_DATATYPE_IS_LOOP(dtdata_type)) { - MVert *verts_dst = me_dst->mvert; - const int num_verts_dst = me_dst->totvert; - MEdge *edges_dst = me_dst->medge; - const int num_edges_dst = me_dst->totedge; - MPoly *polys_dst = me_dst->mpoly; - const int num_polys_dst = me_dst->totpoly; - MLoop *loops_dst = me_dst->mloop; - const int num_loops_dst = me_dst->totloop; - CustomData *pdata_dst = &me_dst->pdata; - CustomData *ldata_dst = &me_dst->ldata; - - MeshRemapIslandsCalc island_callback = data_transfer_get_loop_islands_generator(cddata_type); - - if (!geom_map_init[LDATA]) { - const int num_loops_src = me_src->totloop; - - if ((map_loop_mode == MREMAP_MODE_TOPOLOGY) && (num_loops_dst != num_loops_src)) { - BKE_report(reports, RPT_ERROR, - "Source and destination meshes do not have the same amount of face corners, " - "'Topology' mapping cannot be used in this case"); - continue; - } - if ((map_loop_mode & MREMAP_USE_EDGE) && (me_src->totedge == 0)) { - BKE_report(reports, RPT_ERROR, - "Source mesh doesn't have any edges, " - "None of the 'Edge' mappings can be used in this case"); - continue; - } - if (ELEM(0, num_loops_dst, num_loops_src)) { - BKE_report(reports, RPT_ERROR, - "Source or destination meshes do not have any faces, cannot transfer corner data"); - continue; - } - - BKE_mesh_remap_calc_loops_from_mesh( - map_loop_mode, space_transform, max_distance, ray_radius, - verts_dst, num_verts_dst, edges_dst, num_edges_dst, - loops_dst, num_loops_dst, polys_dst, num_polys_dst, - ldata_dst, pdata_dst, - (me_dst->flag & ME_AUTOSMOOTH) != 0, me_dst->smoothresh, dirty_nors_dst, - me_src, - island_callback, islands_handling_precision, &geom_map[LDATA]); - geom_map_init[LDATA] = true; - } - - if (mdef && vg_idx != -1 && !weights[LDATA]) { - weights[LDATA] = MEM_mallocN(sizeof(*weights[LDATA]) * (size_t)num_loops_dst, __func__); - BKE_defvert_extract_vgroup_to_loopweights( - mdef, vg_idx, num_verts_dst, loops_dst, num_loops_dst, - weights[LDATA], invert_vgroup); - } - - if (data_transfer_layersmapping_generate( - &lay_map, ob_src, ob_dst, me_src, me_dst, ME_LOOP, - cddata_type, mix_mode, mix_factor, weights[LDATA], - num_loops_dst, use_create, use_delete, fromlayers, tolayers, space_transform)) - { - CustomDataTransferLayerMap *lay_mapit; - - changed = (lay_map.first != NULL); - - for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) { - CustomData_data_transfer(&geom_map[LDATA], lay_mapit); - } - - BLI_freelistN(&lay_map); - } - } - if (DT_DATATYPE_IS_POLY(dtdata_type)) { - MVert *verts_dst = me_dst->mvert; - const int num_verts_dst = me_dst->totvert; - MPoly *polys_dst = me_dst->mpoly; - const int num_polys_dst = me_dst->totpoly; - MLoop *loops_dst = me_dst->mloop; - const int num_loops_dst = me_dst->totloop; - CustomData *pdata_dst = &me_dst->pdata; - - if (!geom_map_init[PDATA]) { - const int num_polys_src = me_src->totpoly; - - if ((map_poly_mode == MREMAP_MODE_TOPOLOGY) && (num_polys_dst != num_polys_src)) { - BKE_report(reports, RPT_ERROR, - "Source and destination meshes do not have the same amount of faces, " - "'Topology' mapping cannot be used in this case"); - continue; - } - if ((map_poly_mode & MREMAP_USE_EDGE) && (me_src->totedge == 0)) { - BKE_report(reports, RPT_ERROR, - "Source mesh doesn't have any edges, " - "None of the 'Edge' mappings can be used in this case"); - continue; - } - if (ELEM(0, num_polys_dst, num_polys_src)) { - BKE_report(reports, RPT_ERROR, - "Source or destination meshes do not have any faces, cannot transfer face data"); - continue; - } - - BKE_mesh_remap_calc_polys_from_mesh( - map_poly_mode, space_transform, max_distance, ray_radius, - verts_dst, num_verts_dst, loops_dst, num_loops_dst, - polys_dst, num_polys_dst, pdata_dst, dirty_nors_dst, - me_src, &geom_map[PDATA]); - geom_map_init[PDATA] = true; - } - - if (mdef && vg_idx != -1 && !weights[PDATA]) { - weights[PDATA] = MEM_mallocN(sizeof(*weights[PDATA]) * (size_t)num_polys_dst, __func__); - BKE_defvert_extract_vgroup_to_polyweights( - mdef, vg_idx, num_verts_dst, loops_dst, num_loops_dst, - polys_dst, num_polys_dst, weights[PDATA], invert_vgroup); - } - - if (data_transfer_layersmapping_generate( - &lay_map, ob_src, ob_dst, me_src, me_dst, ME_POLY, - cddata_type, mix_mode, mix_factor, weights[PDATA], - num_polys_dst, use_create, use_delete, fromlayers, tolayers, space_transform)) - { - CustomDataTransferLayerMap *lay_mapit; - - changed = (lay_map.first != NULL); - - for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) { - CustomData_data_transfer(&geom_map[PDATA], lay_mapit); - } - - BLI_freelistN(&lay_map); - } - } - - data_transfer_dtdata_type_postprocess(ob_src, ob_dst, me_src, me_dst, dtdata_type, changed); - } - - for (i = 0; i < DATAMAX; i++) { - BKE_mesh_remap_free(&geom_map[i]); - MEM_SAFE_FREE(weights[i]); - } - - return changed; + SpaceTransform auto_space_transform; + + Mesh *me_src; + bool dirty_nors_dst = + true; /* Assumed always true if not using an evaluated mesh as destination. */ + int i; + + MDeformVert *mdef = NULL; + int vg_idx = -1; + float *weights[DATAMAX] = {NULL}; + + MeshPairRemap geom_map[DATAMAX] = {{0}}; + bool geom_map_init[DATAMAX] = {0}; + ListBase lay_map = {NULL}; + bool changed = false; + bool is_modifier = false; + + const bool use_delete = false; /* We never delete data layers from destination here. */ + + CustomData_MeshMasks me_src_mask = CD_MASK_BAREMESH; + + BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH)); + + if (me_dst) { + dirty_nors_dst = (me_dst->runtime.cd_dirty_vert & CD_NORMAL) != 0; + /* Never create needed custom layers on passed destination mesh + * (assumed to *not* be ob_dst->data, aka modifier case). */ + use_create = false; + is_modifier = true; + } + else { + me_dst = ob_dst->data; + } + + if (vgroup_name) { + mdef = CustomData_get_layer(&me_dst->vdata, CD_MDEFORMVERT); + if (mdef) { + vg_idx = defgroup_name_index(ob_dst, vgroup_name); + } + } + + /* Get source evaluated mesh.*/ + BKE_object_data_transfer_dttypes_to_cdmask(data_types, &me_src_mask); + BKE_mesh_remap_calc_source_cddata_masks_from_map_modes( + map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode, &me_src_mask); + if (is_modifier) { + me_src = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_src, false); + + if (me_src == NULL || + !CustomData_MeshMasks_are_matching(&ob_src->runtime.last_data_mask, &me_src_mask)) { + CLOG_WARN(&LOG, "Data Transfer: source mesh data is not ready - dependency cycle?"); + return changed; + } + } + else { + me_src = mesh_get_eval_final(depsgraph, scene, ob_src, &me_src_mask); + } + if (!me_src) { + return changed; + } + + if (auto_transform) { + if (space_transform == NULL) { + space_transform = &auto_space_transform; + } + + BKE_mesh_remap_find_best_match_from_mesh( + me_dst->mvert, me_dst->totvert, me_src, space_transform); + } + + /* Check all possible data types. + * Note item mappings and dest mix weights are cached. */ + for (i = 0; i < DT_TYPE_MAX; i++) { + const int dtdata_type = 1 << i; + int cddata_type; + int fromlayers, tolayers, fromto_idx; + + if (!(data_types & dtdata_type)) { + continue; + } + + data_transfer_dtdata_type_preprocess(me_src, me_dst, dtdata_type, dirty_nors_dst); + + cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type); + + fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(dtdata_type); + if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) { + fromlayers = fromlayers_select[fromto_idx]; + tolayers = tolayers_select[fromto_idx]; + } + else { + fromlayers = tolayers = 0; + } + + if (DT_DATATYPE_IS_VERT(dtdata_type)) { + MVert *verts_dst = me_dst->mvert; + const int num_verts_dst = me_dst->totvert; + + if (!geom_map_init[VDATA]) { + const int num_verts_src = me_src->totvert; + + if ((map_vert_mode == MREMAP_MODE_TOPOLOGY) && (num_verts_dst != num_verts_src)) { + BKE_report(reports, + RPT_ERROR, + "Source and destination meshes do not have the same amount of vertices, " + "'Topology' mapping cannot be used in this case"); + continue; + } + if ((map_vert_mode & MREMAP_USE_EDGE) && (me_src->totedge == 0)) { + BKE_report(reports, + RPT_ERROR, + "Source mesh doesn't have any edges, " + "None of the 'Edge' mappings can be used in this case"); + continue; + } + if ((map_vert_mode & MREMAP_USE_POLY) && (me_src->totpoly == 0)) { + BKE_report(reports, + RPT_ERROR, + "Source mesh doesn't have any faces, " + "None of the 'Face' mappings can be used in this case"); + continue; + } + if (ELEM(0, num_verts_dst, num_verts_src)) { + BKE_report(reports, + RPT_ERROR, + "Source or destination meshes do not have any vertices, cannot transfer " + "vertex data"); + continue; + } + + BKE_mesh_remap_calc_verts_from_mesh(map_vert_mode, + space_transform, + max_distance, + ray_radius, + verts_dst, + num_verts_dst, + dirty_nors_dst, + me_src, + &geom_map[VDATA]); + geom_map_init[VDATA] = true; + } + + if (mdef && vg_idx != -1 && !weights[VDATA]) { + weights[VDATA] = MEM_mallocN(sizeof(*(weights[VDATA])) * (size_t)num_verts_dst, __func__); + BKE_defvert_extract_vgroup_to_vertweights( + mdef, vg_idx, num_verts_dst, weights[VDATA], invert_vgroup); + } + + if (data_transfer_layersmapping_generate(&lay_map, + ob_src, + ob_dst, + me_src, + me_dst, + ME_VERT, + cddata_type, + mix_mode, + mix_factor, + weights[VDATA], + num_verts_dst, + use_create, + use_delete, + fromlayers, + tolayers, + space_transform)) { + CustomDataTransferLayerMap *lay_mapit; + + changed = (lay_map.first != NULL); + + for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) { + CustomData_data_transfer(&geom_map[VDATA], lay_mapit); + } + + BLI_freelistN(&lay_map); + } + } + if (DT_DATATYPE_IS_EDGE(dtdata_type)) { + MVert *verts_dst = me_dst->mvert; + const int num_verts_dst = me_dst->totvert; + MEdge *edges_dst = me_dst->medge; + const int num_edges_dst = me_dst->totedge; + + if (!geom_map_init[EDATA]) { + const int num_edges_src = me_src->totedge; + + if ((map_edge_mode == MREMAP_MODE_TOPOLOGY) && (num_edges_dst != num_edges_src)) { + BKE_report(reports, + RPT_ERROR, + "Source and destination meshes do not have the same amount of edges, " + "'Topology' mapping cannot be used in this case"); + continue; + } + if ((map_edge_mode & MREMAP_USE_POLY) && (me_src->totpoly == 0)) { + BKE_report(reports, + RPT_ERROR, + "Source mesh doesn't have any faces, " + "None of the 'Face' mappings can be used in this case"); + continue; + } + if (ELEM(0, num_edges_dst, num_edges_src)) { + BKE_report( + reports, + RPT_ERROR, + "Source or destination meshes do not have any edges, cannot transfer edge data"); + continue; + } + + BKE_mesh_remap_calc_edges_from_mesh(map_edge_mode, + space_transform, + max_distance, + ray_radius, + verts_dst, + num_verts_dst, + edges_dst, + num_edges_dst, + dirty_nors_dst, + me_src, + &geom_map[EDATA]); + geom_map_init[EDATA] = true; + } + + if (mdef && vg_idx != -1 && !weights[EDATA]) { + weights[EDATA] = MEM_mallocN(sizeof(*weights[EDATA]) * (size_t)num_edges_dst, __func__); + BKE_defvert_extract_vgroup_to_edgeweights( + mdef, vg_idx, num_verts_dst, edges_dst, num_edges_dst, weights[EDATA], invert_vgroup); + } + + if (data_transfer_layersmapping_generate(&lay_map, + ob_src, + ob_dst, + me_src, + me_dst, + ME_EDGE, + cddata_type, + mix_mode, + mix_factor, + weights[EDATA], + num_edges_dst, + use_create, + use_delete, + fromlayers, + tolayers, + space_transform)) { + CustomDataTransferLayerMap *lay_mapit; + + changed = (lay_map.first != NULL); + + for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) { + CustomData_data_transfer(&geom_map[EDATA], lay_mapit); + } + + BLI_freelistN(&lay_map); + } + } + if (DT_DATATYPE_IS_LOOP(dtdata_type)) { + MVert *verts_dst = me_dst->mvert; + const int num_verts_dst = me_dst->totvert; + MEdge *edges_dst = me_dst->medge; + const int num_edges_dst = me_dst->totedge; + MPoly *polys_dst = me_dst->mpoly; + const int num_polys_dst = me_dst->totpoly; + MLoop *loops_dst = me_dst->mloop; + const int num_loops_dst = me_dst->totloop; + CustomData *pdata_dst = &me_dst->pdata; + CustomData *ldata_dst = &me_dst->ldata; + + MeshRemapIslandsCalc island_callback = data_transfer_get_loop_islands_generator(cddata_type); + + if (!geom_map_init[LDATA]) { + const int num_loops_src = me_src->totloop; + + if ((map_loop_mode == MREMAP_MODE_TOPOLOGY) && (num_loops_dst != num_loops_src)) { + BKE_report(reports, + RPT_ERROR, + "Source and destination meshes do not have the same amount of face corners, " + "'Topology' mapping cannot be used in this case"); + continue; + } + if ((map_loop_mode & MREMAP_USE_EDGE) && (me_src->totedge == 0)) { + BKE_report(reports, + RPT_ERROR, + "Source mesh doesn't have any edges, " + "None of the 'Edge' mappings can be used in this case"); + continue; + } + if (ELEM(0, num_loops_dst, num_loops_src)) { + BKE_report( + reports, + RPT_ERROR, + "Source or destination meshes do not have any faces, cannot transfer corner data"); + continue; + } + + BKE_mesh_remap_calc_loops_from_mesh(map_loop_mode, + space_transform, + max_distance, + ray_radius, + verts_dst, + num_verts_dst, + edges_dst, + num_edges_dst, + loops_dst, + num_loops_dst, + polys_dst, + num_polys_dst, + ldata_dst, + pdata_dst, + (me_dst->flag & ME_AUTOSMOOTH) != 0, + me_dst->smoothresh, + dirty_nors_dst, + me_src, + island_callback, + islands_handling_precision, + &geom_map[LDATA]); + geom_map_init[LDATA] = true; + } + + if (mdef && vg_idx != -1 && !weights[LDATA]) { + weights[LDATA] = MEM_mallocN(sizeof(*weights[LDATA]) * (size_t)num_loops_dst, __func__); + BKE_defvert_extract_vgroup_to_loopweights( + mdef, vg_idx, num_verts_dst, loops_dst, num_loops_dst, weights[LDATA], invert_vgroup); + } + + if (data_transfer_layersmapping_generate(&lay_map, + ob_src, + ob_dst, + me_src, + me_dst, + ME_LOOP, + cddata_type, + mix_mode, + mix_factor, + weights[LDATA], + num_loops_dst, + use_create, + use_delete, + fromlayers, + tolayers, + space_transform)) { + CustomDataTransferLayerMap *lay_mapit; + + changed = (lay_map.first != NULL); + + for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) { + CustomData_data_transfer(&geom_map[LDATA], lay_mapit); + } + + BLI_freelistN(&lay_map); + } + } + if (DT_DATATYPE_IS_POLY(dtdata_type)) { + MVert *verts_dst = me_dst->mvert; + const int num_verts_dst = me_dst->totvert; + MPoly *polys_dst = me_dst->mpoly; + const int num_polys_dst = me_dst->totpoly; + MLoop *loops_dst = me_dst->mloop; + const int num_loops_dst = me_dst->totloop; + CustomData *pdata_dst = &me_dst->pdata; + + if (!geom_map_init[PDATA]) { + const int num_polys_src = me_src->totpoly; + + if ((map_poly_mode == MREMAP_MODE_TOPOLOGY) && (num_polys_dst != num_polys_src)) { + BKE_report(reports, + RPT_ERROR, + "Source and destination meshes do not have the same amount of faces, " + "'Topology' mapping cannot be used in this case"); + continue; + } + if ((map_poly_mode & MREMAP_USE_EDGE) && (me_src->totedge == 0)) { + BKE_report(reports, + RPT_ERROR, + "Source mesh doesn't have any edges, " + "None of the 'Edge' mappings can be used in this case"); + continue; + } + if (ELEM(0, num_polys_dst, num_polys_src)) { + BKE_report( + reports, + RPT_ERROR, + "Source or destination meshes do not have any faces, cannot transfer face data"); + continue; + } + + BKE_mesh_remap_calc_polys_from_mesh(map_poly_mode, + space_transform, + max_distance, + ray_radius, + verts_dst, + num_verts_dst, + loops_dst, + num_loops_dst, + polys_dst, + num_polys_dst, + pdata_dst, + dirty_nors_dst, + me_src, + &geom_map[PDATA]); + geom_map_init[PDATA] = true; + } + + if (mdef && vg_idx != -1 && !weights[PDATA]) { + weights[PDATA] = MEM_mallocN(sizeof(*weights[PDATA]) * (size_t)num_polys_dst, __func__); + BKE_defvert_extract_vgroup_to_polyweights(mdef, + vg_idx, + num_verts_dst, + loops_dst, + num_loops_dst, + polys_dst, + num_polys_dst, + weights[PDATA], + invert_vgroup); + } + + if (data_transfer_layersmapping_generate(&lay_map, + ob_src, + ob_dst, + me_src, + me_dst, + ME_POLY, + cddata_type, + mix_mode, + mix_factor, + weights[PDATA], + num_polys_dst, + use_create, + use_delete, + fromlayers, + tolayers, + space_transform)) { + CustomDataTransferLayerMap *lay_mapit; + + changed = (lay_map.first != NULL); + + for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) { + CustomData_data_transfer(&geom_map[PDATA], lay_mapit); + } + + BLI_freelistN(&lay_map); + } + } + + data_transfer_dtdata_type_postprocess(ob_src, ob_dst, me_src, me_dst, dtdata_type, changed); + } + + for (i = 0; i < DATAMAX; i++) { + BKE_mesh_remap_free(&geom_map[i]); + MEM_SAFE_FREE(weights[i]); + } + + return changed; #undef VDATA #undef EDATA @@ -1434,20 +1846,50 @@ bool BKE_object_data_transfer_ex( #undef DATAMAX } -bool BKE_object_data_transfer_mesh( - struct Depsgraph *depsgraph, Scene *scene, Object *ob_src, Object *ob_dst, const int data_types, - const bool use_create, const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, - const int map_poly_mode, SpaceTransform *space_transform, const bool auto_transform, - const float max_distance, const float ray_radius, const float islands_handling_precision, - const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX], - const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup, - ReportList *reports) +bool BKE_object_data_transfer_mesh(struct Depsgraph *depsgraph, + Scene *scene, + Object *ob_src, + Object *ob_dst, + const int data_types, + const bool use_create, + const int map_vert_mode, + const int map_edge_mode, + const int map_loop_mode, + const int map_poly_mode, + SpaceTransform *space_transform, + const bool auto_transform, + const float max_distance, + const float ray_radius, + const float islands_handling_precision, + const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], + const int tolayers_select[DT_MULTILAYER_INDEX_MAX], + const int mix_mode, + const float mix_factor, + const char *vgroup_name, + const bool invert_vgroup, + ReportList *reports) { - return BKE_object_data_transfer_ex( - depsgraph, scene, ob_src, ob_dst, NULL, data_types, use_create, - map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode, - space_transform, auto_transform, - max_distance, ray_radius, islands_handling_precision, - fromlayers_select, tolayers_select, - mix_mode, mix_factor, vgroup_name, invert_vgroup, reports); + return BKE_object_data_transfer_ex(depsgraph, + scene, + ob_src, + ob_dst, + NULL, + data_types, + use_create, + map_vert_mode, + map_edge_mode, + map_loop_mode, + map_poly_mode, + space_transform, + auto_transform, + max_distance, + ray_radius, + islands_handling_precision, + fromlayers_select, + tolayers_select, + mix_mode, + mix_factor, + vgroup_name, + invert_vgroup, + reports); } |