static int datalayout_transfer_exec(bContext *C, wmOperator *op)
{
	Scene *scene = CTX_data_scene(C);
	Object *ob_act = ED_object_active_context(C);
	DataTransferModifierData *dtmd;

	dtmd = (DataTransferModifierData *)edit_modifier_property_get(op, ob_act, eModifierType_DataTransfer);

	/* If we have a modifier, we transfer data layout from this modifier's source object to active one.
	 * Else, we transfer data layout from active object to all selected ones. */
	if (dtmd) {
		Object *ob_src = dtmd->ob_source;
		Object *ob_dst = ob_act;

		const bool use_delete = false;  /* Never when used from modifier, for now. */

		if (!ob_src) {
			return OPERATOR_CANCELLED;
		}

		BKE_object_data_transfer_layout(scene, ob_src, ob_dst, dtmd->data_types, use_delete,
		                                dtmd->layers_select_src, dtmd->layers_select_dst);

		DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
	}
	else {
		Object *ob_src = ob_act;

		ListBase ctx_objects;
		CollectionPointerLink *ctx_ob_dst;

		const int data_type = RNA_enum_get(op->ptr, "data_type");
		const bool use_delete = RNA_boolean_get(op->ptr, "use_delete");

		const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
		const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
		int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
		int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
		const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);

		if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
			layers_select_src[fromto_idx] = layers_src;
			layers_select_dst[fromto_idx] = layers_dst;
		}

		data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, false);

		for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) {
			Object *ob_dst = ctx_ob_dst->ptr.data;
			if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, false)) {
				BKE_object_data_transfer_layout(scene, ob_src, ob_dst, data_type, use_delete,
				                                layers_select_src, layers_select_dst);
			}

			DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
		}

		BLI_freelistN(&ctx_objects);
	}

	WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);

	return OPERATOR_FINISHED;
}
Exemplo n.º 2
0
/**
 * Transfer data *layout* of selected types from source to destination object.
 * By default, it only creates new data layers if needed on \a ob_dst.
 * 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(
        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])
{
	DerivedMesh *dm_src;
	Mesh *me_dst;
	int i;

	const bool use_create = true;  /* We always create needed layers here. */

	CustomDataMask dm_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 DM.*/
	dm_src_mask |= BKE_object_data_transfer_dttypes_to_cdmask(data_types);
	dm_src = mesh_get_derived_final(scene, ob_src, dm_src_mask);
	if (!dm_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, dm_src, NULL, me_dst, ME_VERT, cddata_type, 0, 0.0f, NULL,
			        num_elem_dst, use_create, use_delete, fromlayers, tolayers);
		}
		if (DT_DATATYPE_IS_EDGE(dtdata_type)) {
			const int num_elem_dst = me_dst->totedge;

			data_transfer_layersmapping_generate(
			        NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_EDGE, cddata_type, 0, 0.0f, NULL,
			        num_elem_dst, use_create, use_delete, fromlayers, tolayers);
		}
		if (DT_DATATYPE_IS_LOOP(dtdata_type)) {
			const int num_elem_dst = me_dst->totloop;

			data_transfer_layersmapping_generate(
			        NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_LOOP, cddata_type, 0, 0.0f, NULL,
			        num_elem_dst, use_create, use_delete, fromlayers, tolayers);
		}
		if (DT_DATATYPE_IS_POLY(dtdata_type)) {
			const int num_elem_dst = me_dst->totpoly;

			data_transfer_layersmapping_generate(
			        NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_POLY, cddata_type, 0, 0.0f, NULL,
			        num_elem_dst, use_create, use_delete, fromlayers, tolayers);
		}
	}
}
static int data_transfer_exec(bContext *C, wmOperator *op)
{
	Scene *scene = CTX_data_scene(C);
	Object *ob_src = ED_object_active_context(C);

	ListBase ctx_objects;
	CollectionPointerLink *ctx_ob_dst;

	bool changed = false;

	const bool is_frozen = RNA_boolean_get(op->ptr, "use_freeze");

	const bool reverse_transfer = RNA_boolean_get(op->ptr, "use_reverse_transfer");

	const int data_type = RNA_enum_get(op->ptr, "data_type");
	const bool use_create = RNA_boolean_get(op->ptr, "use_create");

	const int map_vert_mode = RNA_enum_get(op->ptr, "vert_mapping");
	const int map_edge_mode = RNA_enum_get(op->ptr, "edge_mapping");
	const int map_loop_mode = RNA_enum_get(op->ptr, "loop_mapping");
	const int map_poly_mode = RNA_enum_get(op->ptr, "poly_mapping");

	const bool use_auto_transform = RNA_boolean_get(op->ptr, "use_auto_transform");
	const bool use_object_transform = RNA_boolean_get(op->ptr, "use_object_transform");
	const bool use_max_distance = RNA_boolean_get(op->ptr, "use_max_distance");
	const float max_distance = use_max_distance ? RNA_float_get(op->ptr, "max_distance") : FLT_MAX;
	const float ray_radius = RNA_float_get(op->ptr, "ray_radius");
	const float islands_precision = RNA_float_get(op->ptr, "islands_precision");

	const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
	const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
	int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
	int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
	const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);

	const int mix_mode = RNA_enum_get(op->ptr, "mix_mode");
	const float mix_factor = RNA_float_get(op->ptr, "mix_factor");

	SpaceTransform space_transform_data;
	SpaceTransform *space_transform = (use_object_transform && !use_auto_transform) ? &space_transform_data : NULL;

	if (is_frozen) {
		BKE_report(op->reports, RPT_INFO,
		           "Operator is frozen, changes to its settings won't take effect until you unfreeze it");
		return OPERATOR_FINISHED;
	}

	if (reverse_transfer && ((ID *)(ob_src->data))->lib) {
		/* Do not transfer to linked data, not supported. */
		return OPERATOR_CANCELLED;
	}

	if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
		layers_select_src[fromto_idx] = layers_src;
		layers_select_dst[fromto_idx] = layers_dst;
	}

	data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, reverse_transfer);

	for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) {
		Object *ob_dst = ctx_ob_dst->ptr.data;

		if (reverse_transfer) {
			SWAP(Object *, ob_src, ob_dst);
		}

		if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, reverse_transfer)) {
			if (space_transform) {
				BLI_SPACE_TRANSFORM_SETUP(space_transform, ob_dst, ob_src);
			}

			if (BKE_object_data_transfer_mesh(
			        scene, ob_src, ob_dst, data_type, use_create,
			        map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode,
			        space_transform, use_auto_transform,
			        max_distance, ray_radius, islands_precision,
			        layers_select_src, layers_select_dst,
			        mix_mode, mix_factor, NULL, false, op->reports))
			{
				changed = true;
			}
		}

		DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);

		if (reverse_transfer) {
			SWAP(Object *, ob_src, ob_dst);
		}
	}

	BLI_freelistN(&ctx_objects);

	WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);

#if 0  /* TODO */
	/* Note: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */
	return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
#else
	(void)changed;
	return OPERATOR_FINISHED;
#endif
}
Exemplo n.º 4
0
bool BKE_object_data_transfer_dm(
        Scene *scene, Object *ob_src, Object *ob_dst, DerivedMesh *dm_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 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
#define LDATA 2
#define PDATA 3
#define DATAMAX 4

	DerivedMesh *dm_src;
	Mesh *me_dst, *me_src;
	bool dirty_nors_dst = true;  /* Assumed always true if not using a dm 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;

	const bool use_delete = false;  /* We never delete data layers from destination here. */

	CustomDataMask dm_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;
	me_src = ob_src->data;
	if (dm_dst) {
		dirty_nors_dst = (dm_dst->dirty & DM_DIRTY_NORMALS) != 0;
		use_create = false;  /* Never create needed custom layers on DM (modifier case). */
	}

	if (vgroup_name) {
		if (dm_dst) {
			mdef = dm_dst->getVertDataArray(dm_dst, CD_MDEFORMVERT);
		}
		else {
			mdef = CustomData_get_layer(&me_dst->vdata, CD_MDEFORMVERT);
		}
		if (mdef) {
			vg_idx = defgroup_name_index(ob_dst, vgroup_name);
		}
	}

	/* Get source DM.*/
	dm_src_mask |= BKE_object_data_transfer_dttypes_to_cdmask(data_types);
	/* XXX Hack! In case this is being evaluated from dm stack, we cannot compute final dm,
	 *     can lead to infinite recursion in case of dependency cycles of DataTransfer modifiers...
	 *     Issue is, this means we cannot be sure to have requested cd layers in source.
	 */
	dm_src = dm_dst ? ob_src->derivedFinal : mesh_get_derived_final(scene, ob_src, dm_src_mask);
	if (!dm_src) {
		return changed;
	}

	/* 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(ob_src, ob_dst, dm_src, dm_dst, me_dst,
		                                     dtdata_type, dirty_nors_dst,
		                                     (me_src->flag & ME_AUTOSMOOTH) != 0, me_src->smoothresh);

		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 = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
			const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;

			if (!geom_map_init[VDATA]) {
				const int num_verts_src = dm_src->getNumVerts(dm_src);

				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");
					return changed;
				}
				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");
					return changed;
				}

				BKE_mesh_remap_calc_verts_from_dm(
				        map_vert_mode, space_transform, max_distance, ray_radius,
				        verts_dst, num_verts_dst, dirty_nors_dst, dm_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, dm_src, dm_dst, me_dst, ME_VERT,
			        cddata_type, mix_mode, mix_factor, weights[VDATA],
			        num_verts_dst, use_create, use_delete, fromlayers, tolayers))
			{
				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 = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
			const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
			MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge;
			const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge;

			if (!geom_map_init[EDATA]) {
				const int num_edges_src = dm_src->getNumEdges(dm_src);

				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");
					return changed;
				}
				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");
					return changed;
				}

				BKE_mesh_remap_calc_edges_from_dm(
				        map_edge_mode, space_transform, max_distance, ray_radius,
				        verts_dst, num_verts_dst, edges_dst, num_edges_dst, dirty_nors_dst,
				        dm_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, dm_src, dm_dst, me_dst, ME_EDGE,
			        cddata_type, mix_mode, mix_factor, weights[EDATA],
			        num_edges_dst, use_create, use_delete, fromlayers, tolayers))
			{
				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 = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
			const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
			MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge;
			const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge;
			MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly;
			const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly;
			MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop;
			const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop;
			CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata;
			CustomData *ldata_dst = dm_dst ? dm_dst->getLoopDataLayout(dm_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 = dm_src->getNumLoops(dm_src);

				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");
					return changed;
				}
				if (ELEM(0, num_loops_dst, num_loops_src)) {
					BKE_report(reports, RPT_ERROR,
					           "Source or destination meshes do not have any polygons, cannot transfer loop data");
					return changed;
				}

				BKE_mesh_remap_calc_loops_from_dm(
				        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,
				        dm_src, (me_src->flag & ME_AUTOSMOOTH) != 0, me_src->smoothresh,
				        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, dm_src, dm_dst, me_dst, ME_LOOP,
			        cddata_type, mix_mode, mix_factor, weights[LDATA],
			        num_loops_dst, use_create, use_delete, fromlayers, tolayers))
			{
				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 = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
			const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
			MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly;
			const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly;
			MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop;
			const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop;
			CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata;

			if (!geom_map_init[PDATA]) {
				const int num_polys_src = dm_src->getNumPolys(dm_src);

				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");
					return changed;
				}
				if (ELEM(0, num_polys_dst, num_polys_src)) {
					BKE_report(reports, RPT_ERROR,
					           "Source or destination meshes do not have any polygons, cannot transfer poly data");
					return changed;
				}

				BKE_mesh_remap_calc_polys_from_dm(
				        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,
				        dm_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, dm_src, dm_dst, me_dst, ME_POLY,
			        cddata_type, mix_mode, mix_factor, weights[PDATA],
			        num_polys_dst, use_create, use_delete, fromlayers, tolayers))
			{
				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, dm_src, dm_dst, 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
#undef LDATA
#undef PDATA
#undef DATAMAX
}