Blender V4.3
MOD_datatransfer.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2014 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BLI_utildefines.h"
10
11#include "BLT_translation.hh"
12
13#include "DNA_mesh_types.h"
14#include "DNA_modifier_types.h"
15#include "DNA_object_types.h"
16#include "DNA_screen_types.h"
17
18#include "BKE_customdata.hh"
19#include "BKE_data_transfer.h"
20#include "BKE_lib_id.hh"
21#include "BKE_lib_query.hh"
22#include "BKE_mesh.hh"
23#include "BKE_mesh_mapping.hh"
24#include "BKE_mesh_remap.hh"
25#include "BKE_modifier.hh"
26#include "BKE_report.hh"
27
28#include "UI_interface.hh"
29#include "UI_resources.hh"
30
31#include "RNA_access.hh"
32#include "RNA_prototypes.hh"
33
34#include "MEM_guardedalloc.h"
35
36#include "MOD_ui_common.hh"
37
38/**************************************
39 * Modifiers functions. *
40 **************************************/
41static void init_data(ModifierData *md)
42{
44 int i;
45
46 dtmd->ob_source = nullptr;
47 dtmd->data_types = 0;
48
53
54 dtmd->map_max_distance = 1.0f;
55 dtmd->map_ray_radius = 0.0f;
56
57 for (i = 0; i < DT_MULTILAYER_INDEX_MAX; i++) {
60 }
61
63 dtmd->mix_factor = 1.0f;
64 dtmd->defgrp_name[0] = '\0';
65
67}
68
69static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
70{
72
73 if (dtmd->defgrp_name[0] != '\0') {
74 /* We need vertex groups! */
75 r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
76 }
77
79}
80
81static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
82{
84 walk(user_data, ob, (ID **)&dtmd->ob_source, IDWALK_CB_NOP);
85}
86
88{
90 if (dtmd->ob_source != nullptr) {
91 CustomData_MeshMasks cddata_masks = {0};
93
95 ctx->node, dtmd->ob_source, DEG_OB_COMP_GEOMETRY, "DataTransfer Modifier");
96 DEG_add_customdata_mask(ctx->node, dtmd->ob_source, &cddata_masks);
97
100 ctx->node, dtmd->ob_source, DEG_OB_COMP_TRANSFORM, "DataTransfer Modifier");
101 DEG_add_depends_on_transform_relation(ctx->node, "DataTransfer Modifier");
102 }
103 }
104}
105
106static bool is_disabled(const Scene * /*scene*/, ModifierData *md, bool /*use_render_params*/)
107{
108 /* If no source object, bypass. */
110 /* The object type check is only needed here in case we have a placeholder
111 * object assigned (because the library containing the mesh is missing).
112 *
113 * In other cases it should be impossible to have a type mismatch.
114 */
115 return !dtmd->ob_source || dtmd->ob_source->type != OB_MESH;
116}
117
118#define DT_TYPES_AFFECT_MESH \
119 (DT_TYPE_BWEIGHT_VERT | DT_TYPE_BWEIGHT_EDGE | DT_TYPE_CREASE | DT_TYPE_SHARP_EDGE | \
120 DT_TYPE_LNOR | DT_TYPE_SHARP_FACE)
121
122static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *me_mod)
123{
125 Mesh *result = me_mod;
126 ReportList reports;
127
128 /* Only used to check whether we are operating on org data or not... */
129 const Mesh *mesh = static_cast<const Mesh *>(ctx->object->data);
130
131 Object *ob_source = dtmd->ob_source;
132
133 const bool invert_vgroup = (dtmd->flags & MOD_DATATRANSFER_INVERT_VGROUP) != 0;
134
135 const float max_dist = (dtmd->flags & MOD_DATATRANSFER_MAP_MAXDIST) ? dtmd->map_max_distance :
136 FLT_MAX;
137
138 SpaceTransform space_transform_data;
139 SpaceTransform *space_transform = (dtmd->flags & MOD_DATATRANSFER_OBSRC_TRANSFORM) ?
140 &space_transform_data :
141 nullptr;
142
143 if (space_transform) {
144 BLI_SPACE_TRANSFORM_SETUP(space_transform, ctx->object, ob_source);
145 }
146
147 const blender::Span<blender::float3> me_positions = mesh->vert_positions();
148 const blender::Span<blender::int2> me_edges = mesh->edges();
149 const blender::Span<blender::float3> result_positions = result->vert_positions();
150
151 const blender::Span<blender::int2> result_edges = result->edges();
152
153 if (((result == mesh) || (me_positions.data() == result_positions.data()) ||
154 (me_edges.data() == result_edges.data())) &&
156 {
157 /* We need to duplicate data here, otherwise setting custom normals, edges' sharpness, etc.,
158 * could modify org mesh, see #43671. */
159 result = (Mesh *)BKE_id_copy_ex(nullptr, &me_mod->id, nullptr, LIB_ID_COPY_LOCALIZE);
160 }
161
162 BKE_reports_init(&reports, RPT_STORE);
163
164 /* NOTE: no islands precision for now here. */
166 ob_source,
167 ctx->object,
168 result,
169 dtmd->data_types,
170 false,
171 dtmd->vmap_mode,
172 dtmd->emap_mode,
173 dtmd->lmap_mode,
174 dtmd->pmap_mode,
175 space_transform,
176 false,
177 max_dist,
178 dtmd->map_ray_radius,
179 0.0f,
180 dtmd->layers_select_src,
181 dtmd->layers_select_dst,
182 dtmd->mix_mode,
183 dtmd->mix_factor,
184 dtmd->defgrp_name,
185 invert_vgroup,
186 &reports))
187 {
188 result->runtime->is_original_bmesh = false;
189 }
190
191 if (BKE_reports_contain(&reports, RPT_ERROR)) {
192 const char *report_str = BKE_reports_string(&reports, RPT_ERROR);
193 BKE_modifier_set_error(ctx->object, md, "%s", report_str);
194 MEM_freeN((void *)report_str);
195 }
196
197 BKE_reports_free(&reports);
198
199 return result;
200}
201
202static void panel_draw(const bContext * /*C*/, Panel *panel)
203{
204 uiLayout *sub, *row;
205 uiLayout *layout = panel->layout;
206
207 PointerRNA ob_ptr;
209
210 uiLayoutSetPropSep(layout, true);
211
212 row = uiLayoutRow(layout, true);
213 uiItemR(row, ptr, "object", UI_ITEM_NONE, IFACE_("Source"), ICON_NONE);
214 sub = uiLayoutRow(row, true);
215 uiLayoutSetPropDecorate(sub, false);
216 uiItemR(sub, ptr, "use_object_transform", UI_ITEM_NONE, "", ICON_ORIENTATION_GLOBAL);
217
218 uiItemR(layout, ptr, "mix_mode", UI_ITEM_NONE, nullptr, ICON_NONE);
219
220 row = uiLayoutRow(layout, false);
222 !ELEM(RNA_enum_get(ptr, "mix_mode"),
226 uiItemR(row, ptr, "mix_factor", UI_ITEM_NONE, nullptr, ICON_NONE);
227
228 modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", nullptr);
229
230 uiItemO(layout, IFACE_("Generate Data Layers"), ICON_NONE, "OBJECT_OT_datalayout_transfer");
231
232 modifier_panel_end(layout, ptr);
233}
234
235static void vertex_panel_draw_header(const bContext * /*C*/, Panel *panel)
236{
238 uiLayout *layout = panel->layout;
239
240 uiItemR(layout, ptr, "use_vert_data", UI_ITEM_NONE, nullptr, ICON_NONE);
241}
242
243static void vertex_panel_draw(const bContext * /*C*/, Panel *panel)
244{
245 uiLayout *layout = panel->layout;
246
248
249 bool use_vert_data = RNA_boolean_get(ptr, "use_vert_data");
250 uiLayoutSetActive(layout, use_vert_data);
251
252 uiItemR(layout, ptr, "data_types_verts", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
253
254 uiLayoutSetPropSep(layout, true);
255
256 uiItemR(layout, ptr, "vert_mapping", UI_ITEM_NONE, IFACE_("Mapping"), ICON_NONE);
257}
258
259static void vertex_vgroup_panel_draw(const bContext * /*C*/, Panel *panel)
260{
261 uiLayout *layout = panel->layout;
262
264
265 uiLayoutSetActive(layout, RNA_enum_get(ptr, "data_types_verts") & DT_TYPE_MDEFORMVERT);
266
267 uiLayoutSetPropSep(layout, true);
268
269 uiItemR(
270 layout, ptr, "layers_vgroup_select_src", UI_ITEM_NONE, IFACE_("Layer Selection"), ICON_NONE);
271 uiItemR(
272 layout, ptr, "layers_vgroup_select_dst", UI_ITEM_NONE, IFACE_("Layer Mapping"), ICON_NONE);
273}
274
275static void edge_panel_draw_header(const bContext * /*C*/, Panel *panel)
276{
277 uiLayout *layout = panel->layout;
278
280
281 uiItemR(layout, ptr, "use_edge_data", UI_ITEM_NONE, nullptr, ICON_NONE);
282}
283
284static void edge_panel_draw(const bContext * /*C*/, Panel *panel)
285{
286 uiLayout *layout = panel->layout;
287
289
290 uiLayoutSetActive(layout, RNA_boolean_get(ptr, "use_edge_data"));
291
292 uiItemR(layout, ptr, "data_types_edges", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
293
294 uiLayoutSetPropSep(layout, true);
295
296 uiItemR(layout, ptr, "edge_mapping", UI_ITEM_NONE, IFACE_("Mapping"), ICON_NONE);
297}
298
299static void face_corner_panel_draw_header(const bContext * /*C*/, Panel *panel)
300{
301 uiLayout *layout = panel->layout;
302
304
305 uiItemR(layout, ptr, "use_loop_data", UI_ITEM_NONE, nullptr, ICON_NONE);
306}
307
308static void face_corner_panel_draw(const bContext * /*C*/, Panel *panel)
309{
310 uiLayout *layout = panel->layout;
311
313
314 uiLayoutSetActive(layout, RNA_boolean_get(ptr, "use_loop_data"));
315
316 uiItemR(layout, ptr, "data_types_loops", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
317
318 uiLayoutSetPropSep(layout, true);
319
320 uiItemR(layout, ptr, "loop_mapping", UI_ITEM_NONE, IFACE_("Mapping"), ICON_NONE);
321}
322
323static void vert_vcol_panel_draw(const bContext * /*C*/, Panel *panel)
324{
325 uiLayout *layout = panel->layout;
326
328
329 uiLayoutSetPropSep(layout, true);
330
331 uiLayoutSetActive(layout,
332 RNA_enum_get(ptr, "data_types_verts") &
334
335 uiItemR(layout,
336 ptr,
337 "layers_vcol_vert_select_src",
339 IFACE_("Layer Selection"),
340 ICON_NONE);
341 uiItemR(layout,
342 ptr,
343 "layers_vcol_vert_select_dst",
345 IFACE_("Layer Mapping"),
346 ICON_NONE);
347}
348
349static void face_corner_vcol_panel_draw(const bContext * /*C*/, Panel *panel)
350{
351 uiLayout *layout = panel->layout;
352
354
355 uiLayoutSetPropSep(layout, true);
356
357 uiLayoutSetActive(layout,
358 RNA_enum_get(ptr, "data_types_loops") &
360
361 uiItemR(layout,
362 ptr,
363 "layers_vcol_loop_select_src",
365 IFACE_("Layer Selection"),
366 ICON_NONE);
367 uiItemR(layout,
368 ptr,
369 "layers_vcol_loop_select_dst",
371 IFACE_("Layer Mapping"),
372 ICON_NONE);
373}
374
375static void face_corner_uv_panel_draw(const bContext * /*C*/, Panel *panel)
376{
377 uiLayout *layout = panel->layout;
378
380
381 uiLayoutSetPropSep(layout, true);
382
383 uiLayoutSetActive(layout, RNA_enum_get(ptr, "data_types_loops") & DT_TYPE_UV);
384
385 uiItemR(layout, ptr, "layers_uv_select_src", UI_ITEM_NONE, IFACE_("Layer Selection"), ICON_NONE);
386 uiItemR(layout, ptr, "layers_uv_select_dst", UI_ITEM_NONE, IFACE_("Layer Mapping"), ICON_NONE);
387 uiItemR(layout, ptr, "islands_precision", UI_ITEM_NONE, nullptr, ICON_NONE);
388}
389
390static void face_panel_draw_header(const bContext * /*C*/, Panel *panel)
391{
392 uiLayout *layout = panel->layout;
393
395
396 uiItemR(layout, ptr, "use_poly_data", UI_ITEM_NONE, nullptr, ICON_NONE);
397}
398
399static void face_panel_draw(const bContext * /*C*/, Panel *panel)
400{
401 uiLayout *layout = panel->layout;
402
404
405 uiLayoutSetActive(layout, RNA_boolean_get(ptr, "use_poly_data"));
406
407 uiItemR(layout, ptr, "data_types_polys", UI_ITEM_NONE, nullptr, ICON_NONE);
408
409 uiLayoutSetPropSep(layout, true);
410
411 uiItemR(layout, ptr, "poly_mapping", UI_ITEM_NONE, IFACE_("Mapping"), ICON_NONE);
412}
413
414static void advanced_panel_draw(const bContext * /*C*/, Panel *panel)
415{
416 uiLayout *row, *sub;
417 uiLayout *layout = panel->layout;
418
420
421 uiLayoutSetPropSep(layout, true);
422
423 row = uiLayoutRowWithHeading(layout, true, IFACE_("Max Distance"));
424 uiItemR(row, ptr, "use_max_distance", UI_ITEM_NONE, "", ICON_NONE);
425 sub = uiLayoutRow(row, true);
426 uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max_distance"));
427 uiItemR(sub, ptr, "max_distance", UI_ITEM_NONE, "", ICON_NONE);
428
429 uiItemR(layout, ptr, "ray_radius", UI_ITEM_NONE, nullptr, ICON_NONE);
430}
431
432static void panel_register(ARegionType *region_type)
433{
437 region_type, "vertex", "", vertex_panel_draw_header, vertex_panel_draw, panel_type);
438 modifier_subpanel_register(region_type,
439 "vertex_vgroup",
440 "Vertex Groups",
441 nullptr,
443 vertex_panel);
444
446 region_type, "vert_vcol", "Colors", nullptr, vert_vcol_panel_draw, vertex_panel);
447
449 region_type, "edge", "", edge_panel_draw_header, edge_panel_draw, panel_type);
450
451 PanelType *face_corner_panel = modifier_subpanel_register(region_type,
452 "face_corner",
453 "",
456 panel_type);
457 modifier_subpanel_register(region_type,
458 "face_corner_vcol",
459 "Colors",
460 nullptr,
462 face_corner_panel);
464 region_type, "face_corner_uv", "UVs", nullptr, face_corner_uv_panel_draw, face_corner_panel);
465
467 region_type, "face", "", face_panel_draw_header, face_panel_draw, panel_type);
469 region_type, "advanced", "Topology Mapping", nullptr, advanced_panel_draw, panel_type);
470}
471
472#undef DT_TYPES_AFFECT_MESH
473
475 /*idname*/ "DataTransfer",
476 /*name*/ N_("DataTransfer"),
477 /*struct_name*/ "DataTransferModifierData",
478 /*struct_size*/ sizeof(DataTransferModifierData),
479 /*srna*/ &RNA_DataTransferModifier,
483 /*icon*/ ICON_MOD_DATA_TRANSFER,
484
485 /*copy_data*/ BKE_modifier_copydata_generic,
486
487 /*deform_verts*/ nullptr,
488 /*deform_matrices*/ nullptr,
489 /*deform_verts_EM*/ nullptr,
490 /*deform_matrices_EM*/ nullptr,
491 /*modify_mesh*/ modify_mesh,
492 /*modify_geometry_set*/ nullptr,
493
494 /*init_data*/ init_data,
495 /*required_data_mask*/ required_data_mask,
496 /*free_data*/ nullptr,
497 /*is_disabled*/ is_disabled,
498 /*update_depsgraph*/ update_depsgraph,
499 /*depends_on_time*/ nullptr,
500 /*depends_on_normals*/ nullptr,
501 /*foreach_ID_link*/ foreach_ID_link,
502 /*foreach_tex_link*/ nullptr,
503 /*free_runtime_data*/ nullptr,
504 /*panel_register*/ panel_register,
505 /*blend_write*/ nullptr,
506 /*blend_read*/ nullptr,
507 /*foreach_cache*/ nullptr,
508};
CustomData interface, see also DNA_customdata_types.h.
@ CDT_MIX_REPLACE_BELOW_THRESHOLD
@ CDT_MIX_REPLACE_ABOVE_THRESHOLD
@ CDT_MIX_TRANSFER
@ CDT_MIX_NOMIX
bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, struct Object *ob_src, struct Object *ob_dst, struct Mesh *me_dst, int data_types, bool use_create, int map_vert_mode, int map_edge_mode, int map_loop_mode, int map_face_mode, struct SpaceTransform *space_transform, bool auto_transform, float max_distance, float ray_radius, float islands_handling_precision, const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX], int mix_mode, float mix_factor, const char *vgroup_name, bool invert_vgroup, struct ReportList *reports)
@ DT_LAYERS_NAME_DST
@ DT_LAYERS_ALL_SRC
@ DT_MULTILAYER_INDEX_MAX
@ DT_TYPE_MLOOPCOL_LOOP
@ DT_TYPE_UV
@ DT_TYPE_MPROPCOL_VERT
@ DT_TYPE_MLOOPCOL_VERT
@ DT_TYPE_MPROPCOL_LOOP
@ DT_TYPE_MDEFORMVERT
void BKE_object_data_transfer_dttypes_to_cdmask(int dtdata_types, struct CustomData_MeshMasks *r_data_masks)
@ LIB_ID_COPY_LOCALIZE
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:760
@ IDWALK_CB_NOP
@ MREMAP_MODE_VERT_NEAREST
@ MREMAP_MODE_LOOP_NEAREST_POLYNOR
@ MREMAP_MODE_EDGE_NEAREST
@ MREMAP_MODE_POLY_NEAREST
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_SupportsMapping
@ eModifierTypeFlag_SupportsEditmode
@ eModifierTypeFlag_AcceptsMesh
void(*)(void *user_data, Object *ob, ID **idpoin, int cb_flag) IDWalkFunc
void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
bool BKE_reports_contain(ReportList *reports, eReportType level)
Definition report.cc:342
char * BKE_reports_string(ReportList *reports, eReportType level)
Definition report.cc:268
void BKE_reports_free(ReportList *reports)
Definition report.cc:69
void BKE_reports_init(ReportList *reports, int flag)
Definition report.cc:54
#define BLI_SPACE_TRANSFORM_SETUP(data, local, target)
#define ELEM(...)
#define IFACE_(msgid)
void DEG_add_depends_on_transform_relation(DepsNodeHandle *node_handle, const char *description)
void DEG_add_customdata_mask(DepsNodeHandle *handle, Object *object, const CustomData_MeshMasks *masks)
void DEG_add_object_relation(DepsNodeHandle *node_handle, Object *object, eDepsObjectComponentType component, const char *description)
@ DEG_OB_COMP_GEOMETRY
@ DEG_OB_COMP_TRANSFORM
#define CD_MASK_MDEFORMVERT
struct DataTransferModifierData DataTransferModifierData
@ eModifierType_DataTransfer
@ MOD_DATATRANSFER_OBSRC_TRANSFORM
@ MOD_DATATRANSFER_MAP_MAXDIST
@ MOD_DATATRANSFER_INVERT_VGROUP
Object is a sort of wrapper for general info.
@ OB_MESH
static bool is_disabled
Read Guarded memory(de)allocation.
static void init_data(ModifierData *md)
static void edge_panel_draw_header(const bContext *, Panel *panel)
static void face_corner_panel_draw_header(const bContext *, Panel *panel)
static void vertex_panel_draw_header(const bContext *, Panel *panel)
static void panel_register(ARegionType *region_type)
#define DT_TYPES_AFFECT_MESH
static void vertex_panel_draw(const bContext *, Panel *panel)
static void face_corner_panel_draw(const bContext *, Panel *panel)
static void face_corner_vcol_panel_draw(const bContext *, Panel *panel)
static void vertex_vgroup_panel_draw(const bContext *, Panel *panel)
static void face_corner_uv_panel_draw(const bContext *, Panel *panel)
static void face_panel_draw_header(const bContext *, Panel *panel)
static void vert_vcol_panel_draw(const bContext *, Panel *panel)
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *me_mod)
static void advanced_panel_draw(const bContext *, Panel *panel)
static void face_panel_draw(const bContext *, Panel *panel)
static void panel_draw(const bContext *, Panel *panel)
static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
ModifierTypeInfo modifierType_DataTransfer
static void edge_panel_draw(const bContext *, Panel *panel)
static void update_depsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_vgroup_ui(uiLayout *layout, PointerRNA *ptr, PointerRNA *ob_ptr, const char *vgroup_prop, const char *invert_vgroup_prop, const char *text)
void uiLayoutSetActive(uiLayout *layout, bool active)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
#define UI_ITEM_NONE
void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_EXPAND
constexpr const T * data() const
Definition BLI_span.hh:216
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
#define FLT_MAX
Definition stdcycles.h:14
Definition DNA_ID.h:413
struct uiLayout * layout
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4126