Blender V4.5
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
29#include "UI_interface.hh"
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;
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
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
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
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 uiLayoutSetPropSep(layout, 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 uiLayoutSetPropDecorate(sub, 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);
223 !ELEM(RNA_enum_get(ptr, "mix_mode"),
227 row->prop(ptr, "mix_factor", UI_ITEM_NONE, std::nullopt, ICON_NONE);
228
229 modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", std::nullopt);
230
231 layout->op("OBJECT_OT_datalayout_transfer", IFACE_("Generate Data Layers"), ICON_NONE);
232
234}
235
236static void vertex_panel_draw_header(const bContext * /*C*/, Panel *panel)
237{
239 uiLayout *layout = panel->layout;
240
241 layout->prop(ptr, "use_vert_data", UI_ITEM_NONE, std::nullopt, ICON_NONE);
242}
243
244static void vertex_panel_draw(const bContext * /*C*/, Panel *panel)
245{
246 uiLayout *layout = panel->layout;
247
249
250 bool use_vert_data = RNA_boolean_get(ptr, "use_vert_data");
251 uiLayoutSetActive(layout, use_vert_data);
252
253 layout->prop(ptr, "data_types_verts", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
254
255 uiLayoutSetPropSep(layout, true);
256
257 layout->prop(ptr, "vert_mapping", UI_ITEM_NONE, IFACE_("Mapping"), ICON_NONE);
258}
259
260static void vertex_vgroup_panel_draw(const bContext * /*C*/, Panel *panel)
261{
262 uiLayout *layout = panel->layout;
263
265
266 uiLayoutSetActive(layout, RNA_enum_get(ptr, "data_types_verts") & DT_TYPE_MDEFORMVERT);
267
268 uiLayoutSetPropSep(layout, true);
269
270 layout->prop(
271 ptr, "layers_vgroup_select_src", UI_ITEM_NONE, IFACE_("Layer Selection"), ICON_NONE);
272 layout->prop(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 layout->prop(ptr, "use_edge_data", UI_ITEM_NONE, std::nullopt, 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 layout->prop(ptr, "data_types_edges", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
293
294 uiLayoutSetPropSep(layout, true);
295
296 layout->prop(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 layout->prop(ptr, "use_loop_data", UI_ITEM_NONE, std::nullopt, 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 layout->prop(ptr, "data_types_loops", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
317
318 uiLayoutSetPropSep(layout, true);
319
320 layout->prop(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 layout->prop(
336 ptr, "layers_vcol_vert_select_src", UI_ITEM_NONE, IFACE_("Layer Selection"), ICON_NONE);
337 layout->prop(
338 ptr, "layers_vcol_vert_select_dst", UI_ITEM_NONE, IFACE_("Layer Mapping"), ICON_NONE);
339}
340
341static void face_corner_vcol_panel_draw(const bContext * /*C*/, Panel *panel)
342{
343 uiLayout *layout = panel->layout;
344
346
347 uiLayoutSetPropSep(layout, true);
348
349 uiLayoutSetActive(layout,
350 RNA_enum_get(ptr, "data_types_loops") &
352
353 layout->prop(
354 ptr, "layers_vcol_loop_select_src", UI_ITEM_NONE, IFACE_("Layer Selection"), ICON_NONE);
355 layout->prop(
356 ptr, "layers_vcol_loop_select_dst", UI_ITEM_NONE, IFACE_("Layer Mapping"), ICON_NONE);
357}
358
359static void face_corner_uv_panel_draw(const bContext * /*C*/, Panel *panel)
360{
361 uiLayout *layout = panel->layout;
362
364
365 uiLayoutSetPropSep(layout, true);
366
367 uiLayoutSetActive(layout, RNA_enum_get(ptr, "data_types_loops") & DT_TYPE_UV);
368
369 layout->prop(ptr, "layers_uv_select_src", UI_ITEM_NONE, IFACE_("Layer Selection"), ICON_NONE);
370 layout->prop(ptr, "layers_uv_select_dst", UI_ITEM_NONE, IFACE_("Layer Mapping"), ICON_NONE);
371 layout->prop(ptr, "islands_precision", UI_ITEM_NONE, std::nullopt, ICON_NONE);
372}
373
374static void face_panel_draw_header(const bContext * /*C*/, Panel *panel)
375{
376 uiLayout *layout = panel->layout;
377
379
380 layout->prop(ptr, "use_poly_data", UI_ITEM_NONE, std::nullopt, ICON_NONE);
381}
382
383static void face_panel_draw(const bContext * /*C*/, Panel *panel)
384{
385 uiLayout *layout = panel->layout;
386
388
389 uiLayoutSetActive(layout, RNA_boolean_get(ptr, "use_poly_data"));
390
391 layout->prop(ptr, "data_types_polys", UI_ITEM_NONE, std::nullopt, ICON_NONE);
392
393 uiLayoutSetPropSep(layout, true);
394
395 layout->prop(ptr, "poly_mapping", UI_ITEM_NONE, IFACE_("Mapping"), ICON_NONE);
396}
397
398static void advanced_panel_draw(const bContext * /*C*/, Panel *panel)
399{
400 uiLayout *row, *sub;
401 uiLayout *layout = panel->layout;
402
404
405 uiLayoutSetPropSep(layout, true);
406
407 row = &layout->row(true, IFACE_("Max Distance"));
408 row->prop(ptr, "use_max_distance", UI_ITEM_NONE, "", ICON_NONE);
409 sub = &row->row(true);
410 uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max_distance"));
411 sub->prop(ptr, "max_distance", UI_ITEM_NONE, "", ICON_NONE);
412
413 layout->prop(ptr, "ray_radius", UI_ITEM_NONE, std::nullopt, ICON_NONE);
414}
415
416static void panel_register(ARegionType *region_type)
417{
421 region_type, "vertex", "", vertex_panel_draw_header, vertex_panel_draw, panel_type);
422 modifier_subpanel_register(region_type,
423 "vertex_vgroup",
424 "Vertex Groups",
425 nullptr,
427 vertex_panel);
428
430 region_type, "vert_vcol", "Colors", nullptr, vert_vcol_panel_draw, vertex_panel);
431
433 region_type, "edge", "", edge_panel_draw_header, edge_panel_draw, panel_type);
434
435 PanelType *face_corner_panel = modifier_subpanel_register(region_type,
436 "face_corner",
437 "",
440 panel_type);
441 modifier_subpanel_register(region_type,
442 "face_corner_vcol",
443 "Colors",
444 nullptr,
446 face_corner_panel);
448 region_type, "face_corner_uv", "UVs", nullptr, face_corner_uv_panel_draw, face_corner_panel);
449
451 region_type, "face", "", face_panel_draw_header, face_panel_draw, panel_type);
453 region_type, "advanced", "Topology Mapping", nullptr, advanced_panel_draw, panel_type);
454}
455
456#undef DT_TYPES_AFFECT_MESH
457
459 /*idname*/ "DataTransfer",
460 /*name*/ N_("DataTransfer"),
461 /*struct_name*/ "DataTransferModifierData",
462 /*struct_size*/ sizeof(DataTransferModifierData),
463 /*srna*/ &RNA_DataTransferModifier,
467 /*icon*/ ICON_MOD_DATA_TRANSFER,
468
469 /*copy_data*/ BKE_modifier_copydata_generic,
470
471 /*deform_verts*/ nullptr,
472 /*deform_matrices*/ nullptr,
473 /*deform_verts_EM*/ nullptr,
474 /*deform_matrices_EM*/ nullptr,
475 /*modify_mesh*/ modify_mesh,
476 /*modify_geometry_set*/ nullptr,
477
478 /*init_data*/ init_data,
479 /*required_data_mask*/ required_data_mask,
480 /*free_data*/ nullptr,
481 /*is_disabled*/ is_disabled,
482 /*update_depsgraph*/ update_depsgraph,
483 /*depends_on_time*/ nullptr,
484 /*depends_on_normals*/ nullptr,
485 /*foreach_ID_link*/ foreach_ID_link,
486 /*foreach_tex_link*/ nullptr,
487 /*free_runtime_data*/ nullptr,
488 /*panel_register*/ panel_register,
489 /*blend_write*/ nullptr,
490 /*blend_read*/ nullptr,
491 /*foreach_cache*/ nullptr,
492};
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)
@ LIB_ID_COPY_LOCALIZE
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:767
@ 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:343
char * BKE_reports_string(ReportList *reports, eReportType level)
Definition report.cc:269
void BKE_reports_free(ReportList *reports)
Definition report.cc:70
void BKE_reports_init(ReportList *reports, int flag)
Definition report.cc:55
#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
@ MREMAP_MODE_VERT_NEAREST
@ MREMAP_MODE_LOOP_NEAREST_POLYNOR
@ MREMAP_MODE_EDGE_NEAREST
@ MREMAP_MODE_POLY_NEAREST
@ 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
@ DT_LAYERS_ALL_SRC
@ DT_LAYERS_NAME_DST
@ 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
void uiLayoutSetActive(uiLayout *layout, bool active)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
ReportList * reports
Definition WM_types.hh:1025
constexpr const T * data() const
Definition BLI_span.hh:215
#define CD_MASK_MDEFORMVERT
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:404
struct uiLayout * layout
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, wmOperatorCallContext context, eUI_Item_Flag flag)
uiLayout & row(bool align)
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:4226