Blender V5.0
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
8
9#include <cfloat>
10
11#include "BLI_utildefines.h"
12
13#include "BLT_translation.hh"
14
15#include "DNA_mesh_types.h"
16#include "DNA_modifier_types.h"
17#include "DNA_object_types.h"
18#include "DNA_screen_types.h"
19
20#include "BKE_customdata.hh"
21#include "BKE_data_transfer.h"
22#include "BKE_lib_id.hh"
23#include "BKE_lib_query.hh"
24#include "BKE_mesh.hh"
25#include "BKE_mesh_remap.hh"
26#include "BKE_modifier.hh"
27#include "BKE_report.hh"
28
30#include "UI_resources.hh"
31
32#include "RNA_access.hh"
33#include "RNA_prototypes.hh"
34
35#include "MEM_guardedalloc.h"
36
37#include "MOD_ui_common.hh"
38
39/**************************************
40 * Modifiers functions. *
41 **************************************/
42static void init_data(ModifierData *md)
43{
45 int i;
46
47 dtmd->ob_source = nullptr;
48 dtmd->data_types = 0;
49
54
55 dtmd->map_max_distance = 1.0f;
56 dtmd->map_ray_radius = 0.0f;
57
58 for (i = 0; i < DT_MULTILAYER_INDEX_MAX; i++) {
61 }
62
64 dtmd->mix_factor = 1.0f;
65 dtmd->defgrp_name[0] = '\0';
66
68}
69
70static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
71{
73
74 if (dtmd->defgrp_name[0] != '\0') {
75 /* We need vertex groups! */
76 r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
77 }
78
80}
81
82static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
83{
85 walk(user_data, ob, (ID **)&dtmd->ob_source, IDWALK_CB_NOP);
86}
87
89{
91 if (dtmd->ob_source != nullptr) {
92 CustomData_MeshMasks cddata_masks = {0};
94
96 ctx->node, dtmd->ob_source, DEG_OB_COMP_GEOMETRY, "DataTransfer Modifier");
97 DEG_add_customdata_mask(ctx->node, dtmd->ob_source, &cddata_masks);
98
101 ctx->node, dtmd->ob_source, DEG_OB_COMP_TRANSFORM, "DataTransfer Modifier");
102 DEG_add_depends_on_transform_relation(ctx->node, "DataTransfer Modifier");
103 }
104 }
105}
106
107static bool is_disabled(const Scene * /*scene*/, ModifierData *md, bool /*use_render_params*/)
108{
109 /* If no source object, bypass. */
111 /* The object type check is only needed here in case we have a placeholder
112 * object assigned (because the library containing the mesh is missing).
113 *
114 * In other cases it should be impossible to have a type mismatch.
115 */
116 return !dtmd->ob_source || dtmd->ob_source->type != OB_MESH;
117}
118
119#define DT_TYPES_AFFECT_MESH \
120 (DT_TYPE_BWEIGHT_VERT | DT_TYPE_BWEIGHT_EDGE | DT_TYPE_CREASE | DT_TYPE_SHARP_EDGE | \
121 DT_TYPE_LNOR | DT_TYPE_SHARP_FACE)
122
123static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *me_mod)
124{
126 Mesh *result = me_mod;
127 ReportList reports;
128
129 /* Only used to check whether we are operating on org data or not... */
130 const Mesh *mesh = static_cast<const Mesh *>(ctx->object->data);
131
132 Object *ob_source = dtmd->ob_source;
133
134 const bool invert_vgroup = (dtmd->flags & MOD_DATATRANSFER_INVERT_VGROUP) != 0;
135
136 const float max_dist = (dtmd->flags & MOD_DATATRANSFER_MAP_MAXDIST) ? dtmd->map_max_distance :
137 FLT_MAX;
138
139 SpaceTransform space_transform_data;
140 SpaceTransform *space_transform = (dtmd->flags & MOD_DATATRANSFER_OBSRC_TRANSFORM) ?
141 &space_transform_data :
142 nullptr;
143
144 if (space_transform) {
145 BLI_SPACE_TRANSFORM_SETUP(space_transform, ctx->object, ob_source);
146 }
147
148 const blender::Span<blender::float3> me_positions = mesh->vert_positions();
149 const blender::Span<blender::int2> me_edges = mesh->edges();
150 const blender::Span<blender::float3> result_positions = result->vert_positions();
151
152 const blender::Span<blender::int2> result_edges = result->edges();
153
154 if (((result == mesh) || (me_positions.data() == result_positions.data()) ||
155 (me_edges.data() == result_edges.data())) &&
157 {
158 /* We need to duplicate data here, otherwise setting custom normals, edges' sharpness, etc.,
159 * could modify org mesh, see #43671. */
160 result = (Mesh *)BKE_id_copy_ex(nullptr, &me_mod->id, nullptr, LIB_ID_COPY_LOCALIZE);
161 }
162
163 BKE_reports_init(&reports, RPT_STORE);
164
165 /* NOTE: no islands precision for now here. */
167 ob_source,
168 ctx->object,
169 result,
170 dtmd->data_types,
171 false,
172 dtmd->vmap_mode,
173 dtmd->emap_mode,
174 dtmd->lmap_mode,
175 dtmd->pmap_mode,
176 space_transform,
177 false,
178 max_dist,
179 dtmd->map_ray_radius,
180 0.0f,
181 dtmd->layers_select_src,
182 dtmd->layers_select_dst,
183 dtmd->mix_mode,
184 dtmd->mix_factor,
185 dtmd->defgrp_name,
186 invert_vgroup,
187 &reports))
188 {
189 result->runtime->is_original_bmesh = false;
190 }
191
192 if (BKE_reports_contain(&reports, RPT_ERROR)) {
193 const char *report_str = BKE_reports_string(&reports, RPT_ERROR);
194 BKE_modifier_set_error(ctx->object, md, "%s", report_str);
195 MEM_freeN(report_str);
196 }
197
198 BKE_reports_free(&reports);
199
200 return result;
201}
202
203static void panel_draw(const bContext * /*C*/, Panel *panel)
204{
205 uiLayout *sub, *row;
206 uiLayout *layout = panel->layout;
207
208 PointerRNA ob_ptr;
210
211 layout->use_property_split_set(true);
212
213 row = &layout->row(true);
214 row->prop(ptr, "object", UI_ITEM_NONE, IFACE_("Source"), ICON_NONE);
215 sub = &row->row(true);
216 sub->use_property_decorate_set(false);
217 sub->prop(ptr, "use_object_transform", UI_ITEM_NONE, "", ICON_ORIENTATION_GLOBAL);
218
219 layout->prop(ptr, "mix_mode", UI_ITEM_NONE, std::nullopt, ICON_NONE);
220
221 row = &layout->row(false);
222 row->active_set(!ELEM(RNA_enum_get(ptr, "mix_mode"),
226 row->prop(ptr, "mix_factor", UI_ITEM_NONE, std::nullopt, ICON_NONE);
227
228 modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", std::nullopt);
229
230 layout->op("OBJECT_OT_datalayout_transfer", IFACE_("Generate Data Layers"), ICON_NONE);
231
233}
234
235static void vertex_panel_draw_header(const bContext * /*C*/, Panel *panel)
236{
238 uiLayout *layout = panel->layout;
239
240 layout->prop(ptr, "use_vert_data", UI_ITEM_NONE, std::nullopt, 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 layout->active_set(use_vert_data);
251
252 layout->prop(ptr, "data_types_verts", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
253
254 layout->use_property_split_set(true);
255
256 layout->prop(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 layout->active_set(RNA_enum_get(ptr, "data_types_verts") & DT_TYPE_MDEFORMVERT);
266
267 layout->use_property_split_set(true);
268
269 layout->prop(
270 ptr, "layers_vgroup_select_src", UI_ITEM_NONE, IFACE_("Layer Selection"), ICON_NONE);
271 layout->prop(ptr, "layers_vgroup_select_dst", UI_ITEM_NONE, IFACE_("Layer Mapping"), ICON_NONE);
272}
273
274static void edge_panel_draw_header(const bContext * /*C*/, Panel *panel)
275{
276 uiLayout *layout = panel->layout;
277
279
280 layout->prop(ptr, "use_edge_data", UI_ITEM_NONE, std::nullopt, ICON_NONE);
281}
282
283static void edge_panel_draw(const bContext * /*C*/, Panel *panel)
284{
285 uiLayout *layout = panel->layout;
286
288
289 layout->active_set(RNA_boolean_get(ptr, "use_edge_data"));
290
291 layout->prop(ptr, "data_types_edges", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
292
293 layout->use_property_split_set(true);
294
295 layout->prop(ptr, "edge_mapping", UI_ITEM_NONE, IFACE_("Mapping"), ICON_NONE);
296}
297
298static void face_corner_panel_draw_header(const bContext * /*C*/, Panel *panel)
299{
300 uiLayout *layout = panel->layout;
301
303
304 layout->prop(ptr, "use_loop_data", UI_ITEM_NONE, std::nullopt, ICON_NONE);
305}
306
307static void face_corner_panel_draw(const bContext * /*C*/, Panel *panel)
308{
309 uiLayout *layout = panel->layout;
310
312
313 layout->active_set(RNA_boolean_get(ptr, "use_loop_data"));
314
315 layout->prop(ptr, "data_types_loops", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
316
317 layout->use_property_split_set(true);
318
319 layout->prop(ptr, "loop_mapping", UI_ITEM_NONE, IFACE_("Mapping"), ICON_NONE);
320}
321
322static void vert_vcol_panel_draw(const bContext * /*C*/, Panel *panel)
323{
324 uiLayout *layout = panel->layout;
325
327
328 layout->use_property_split_set(true);
329
330 layout->active_set(RNA_enum_get(ptr, "data_types_verts") &
332
333 layout->prop(
334 ptr, "layers_vcol_vert_select_src", UI_ITEM_NONE, IFACE_("Layer Selection"), ICON_NONE);
335 layout->prop(
336 ptr, "layers_vcol_vert_select_dst", UI_ITEM_NONE, IFACE_("Layer Mapping"), ICON_NONE);
337}
338
339static void face_corner_vcol_panel_draw(const bContext * /*C*/, Panel *panel)
340{
341 uiLayout *layout = panel->layout;
342
344
345 layout->use_property_split_set(true);
346
347 layout->active_set(RNA_enum_get(ptr, "data_types_loops") &
349
350 layout->prop(
351 ptr, "layers_vcol_loop_select_src", UI_ITEM_NONE, IFACE_("Layer Selection"), ICON_NONE);
352 layout->prop(
353 ptr, "layers_vcol_loop_select_dst", UI_ITEM_NONE, IFACE_("Layer Mapping"), ICON_NONE);
354}
355
356static void face_corner_uv_panel_draw(const bContext * /*C*/, Panel *panel)
357{
358 uiLayout *layout = panel->layout;
359
361
362 layout->use_property_split_set(true);
363
364 layout->active_set(RNA_enum_get(ptr, "data_types_loops") & DT_TYPE_UV);
365
366 layout->prop(ptr, "layers_uv_select_src", UI_ITEM_NONE, IFACE_("Layer Selection"), ICON_NONE);
367 layout->prop(ptr, "layers_uv_select_dst", UI_ITEM_NONE, IFACE_("Layer Mapping"), ICON_NONE);
368 layout->prop(ptr, "islands_precision", UI_ITEM_NONE, std::nullopt, ICON_NONE);
369}
370
371static void face_panel_draw_header(const bContext * /*C*/, Panel *panel)
372{
373 uiLayout *layout = panel->layout;
374
376
377 layout->prop(ptr, "use_poly_data", UI_ITEM_NONE, std::nullopt, ICON_NONE);
378}
379
380static void face_panel_draw(const bContext * /*C*/, Panel *panel)
381{
382 uiLayout *layout = panel->layout;
383
385
386 layout->active_set(RNA_boolean_get(ptr, "use_poly_data"));
387
388 layout->prop(ptr, "data_types_polys", UI_ITEM_NONE, std::nullopt, ICON_NONE);
389
390 layout->use_property_split_set(true);
391
392 layout->prop(ptr, "poly_mapping", UI_ITEM_NONE, IFACE_("Mapping"), ICON_NONE);
393}
394
395static void advanced_panel_draw(const bContext * /*C*/, Panel *panel)
396{
397 uiLayout *row, *sub;
398 uiLayout *layout = panel->layout;
399
401
402 layout->use_property_split_set(true);
403
404 row = &layout->row(true, IFACE_("Max Distance"));
405 row->prop(ptr, "use_max_distance", UI_ITEM_NONE, "", ICON_NONE);
406 sub = &row->row(true);
407 sub->active_set(RNA_boolean_get(ptr, "use_max_distance"));
408 sub->prop(ptr, "max_distance", UI_ITEM_NONE, "", ICON_NONE);
409
410 layout->prop(ptr, "ray_radius", UI_ITEM_NONE, std::nullopt, ICON_NONE);
411}
412
413static void panel_register(ARegionType *region_type)
414{
418 region_type, "vertex", "", vertex_panel_draw_header, vertex_panel_draw, panel_type);
419 modifier_subpanel_register(region_type,
420 "vertex_vgroup",
421 "Vertex Groups",
422 nullptr,
424 vertex_panel);
425
427 region_type, "vert_vcol", "Colors", nullptr, vert_vcol_panel_draw, vertex_panel);
428
430 region_type, "edge", "", edge_panel_draw_header, edge_panel_draw, panel_type);
431
432 PanelType *face_corner_panel = modifier_subpanel_register(region_type,
433 "face_corner",
434 "",
437 panel_type);
438 modifier_subpanel_register(region_type,
439 "face_corner_vcol",
440 "Colors",
441 nullptr,
443 face_corner_panel);
445 region_type, "face_corner_uv", "UVs", nullptr, face_corner_uv_panel_draw, face_corner_panel);
446
448 region_type, "face", "", face_panel_draw_header, face_panel_draw, panel_type);
450 region_type, "advanced", "Topology Mapping", nullptr, advanced_panel_draw, panel_type);
451}
452
453#undef DT_TYPES_AFFECT_MESH
454
456 /*idname*/ "DataTransfer",
457 /*name*/ N_("DataTransfer"),
458 /*struct_name*/ "DataTransferModifierData",
459 /*struct_size*/ sizeof(DataTransferModifierData),
460 /*srna*/ &RNA_DataTransferModifier,
464 /*icon*/ ICON_MOD_DATA_TRANSFER,
465
466 /*copy_data*/ BKE_modifier_copydata_generic,
467
468 /*deform_verts*/ nullptr,
469 /*deform_matrices*/ nullptr,
470 /*deform_verts_EM*/ nullptr,
471 /*deform_matrices_EM*/ nullptr,
472 /*modify_mesh*/ modify_mesh,
473 /*modify_geometry_set*/ nullptr,
474
475 /*init_data*/ init_data,
476 /*required_data_mask*/ required_data_mask,
477 /*free_data*/ nullptr,
478 /*is_disabled*/ is_disabled,
479 /*update_depsgraph*/ update_depsgraph,
480 /*depends_on_time*/ nullptr,
481 /*depends_on_normals*/ nullptr,
482 /*foreach_ID_link*/ foreach_ID_link,
483 /*foreach_tex_link*/ nullptr,
484 /*free_runtime_data*/ nullptr,
485 /*panel_register*/ panel_register,
486 /*blend_write*/ nullptr,
487 /*blend_read*/ nullptr,
488 /*foreach_cache*/ nullptr,
489 /*foreach_working_space_color*/ nullptr,
490};
CustomData interface, see also DNA_customdata_types.h.
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)
void BKE_object_data_transfer_dttypes_to_cdmask(int dtdata_types, struct CustomData_MeshMasks *r_data_masks)
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:777
@ LIB_ID_COPY_LOCALIZE
@ IDWALK_CB_NOP
void(*)(void *user_data, Object *ob, ID **idpoin, LibraryForeachIDCallbackFlag cb_flag) IDWalkFunc
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_SupportsMapping
@ eModifierTypeFlag_SupportsEditmode
@ eModifierTypeFlag_AcceptsMesh
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:383
@ RPT_STORE
Definition BKE_report.hh:56
@ RPT_ERROR
Definition BKE_report.hh:39
char * BKE_reports_string(ReportList *reports, eReportType level)
Definition report.cc:296
void BKE_reports_free(ReportList *reports)
Definition report.cc:97
void BKE_reports_init(ReportList *reports, int flag)
Definition report.cc:82
#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
@ DT_LAYERS_ALL_SRC
@ DT_LAYERS_NAME_DST
@ DT_MULTILAYER_INDEX_MAX
@ MREMAP_MODE_VERT_NEAREST
@ MREMAP_MODE_LOOP_NEAREST_POLYNOR
@ MREMAP_MODE_EDGE_NEAREST
@ MREMAP_MODE_POLY_NEAREST
@ DT_TYPE_MLOOPCOL_LOOP
@ DT_TYPE_UV
@ DT_TYPE_MPROPCOL_VERT
@ DT_TYPE_MLOOPCOL_VERT
@ DT_TYPE_MPROPCOL_LOOP
@ DT_TYPE_MDEFORMVERT
@ CDT_MIX_REPLACE_BELOW_THRESHOLD
@ CDT_MIX_REPLACE_ABOVE_THRESHOLD
@ CDT_MIX_TRANSFER
@ CDT_MIX_NOMIX
@ MOD_DATATRANSFER_OBSRC_TRANSFORM
@ MOD_DATATRANSFER_MAP_MAXDIST
@ MOD_DATATRANSFER_INVERT_VGROUP
@ eModifierType_DataTransfer
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 panel_register(ARegionType *region_type)
static void required_data_mask(ModifierData *, CustomData_MeshMasks *r_cddata_masks)
static void panel_draw(const bContext *, Panel *panel)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
Definition MOD_array.cc:862
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)
void modifier_vgroup_ui(uiLayout *layout, PointerRNA *ptr, PointerRNA *ob_ptr, const StringRefNull vgroup_prop, const std::optional< StringRefNull > invert_vgroup_prop, const std::optional< StringRefNull > text)
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
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_error_message_draw(uiLayout *layout, PointerRNA *ptr)
@ UI_ITEM_R_EXPAND
#define UI_ITEM_NONE
constexpr const T * data() const
Definition BLI_span.hh:215
static void update_depsgraph(tGraphSliderOp *gso)
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
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:414
struct uiLayout * layout
void use_property_decorate_set(bool is_sep)
void active_set(bool active)
uiLayout & row(bool align)
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, blender::wm::OpCallContext context, eUI_Item_Flag flag)
void use_property_split_set(bool value)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
i
Definition text_draw.cc:230
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4238