Blender V4.5
object_data_transfer.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 "DNA_mesh_types.h"
10#include "DNA_modifier_types.h"
11#include "DNA_object_types.h"
12
13#include "BLI_math_matrix.h"
14#include "BLI_string.h"
15#include "BLI_utildefines.h"
16
17#include "BKE_context.hh"
18#include "BKE_customdata.hh"
19#include "BKE_data_transfer.h"
20#include "BKE_deform.hh"
21#include "BKE_library.hh"
22#include "BKE_mesh_remap.hh"
23#include "BKE_object.hh"
24#include "BKE_report.hh"
25
26#include "DEG_depsgraph.hh"
28
29#include "BLT_translation.hh"
30
31#include "RNA_access.hh"
32#include "RNA_define.hh"
33#include "RNA_enum_types.hh"
34#include "RNA_prototypes.hh"
35
36#include "WM_api.hh"
37#include "WM_types.hh"
38
39#include "ED_object.hh"
40
41#include "object_intern.hh"
42
43namespace blender::ed::object {
44
45/* All possible data to transfer.
46 * Note some are 'fake' ones, i.e. they are not hold by real CDLayers. */
47/* Not shared with modifier, since we use a usual enum here, not a multi-choice one. */
49 RNA_ENUM_ITEM_HEADING(N_("Vertex Data"), nullptr),
51 "VGROUP_WEIGHTS",
52 0,
53 "Vertex Group(s)",
54 "Transfer active or all vertex groups"},
55#if 0 /* XXX For now, would like to finish/merge work from 2014 GSOC first. */
56 {DT_TYPE_SHAPEKEY, "SHAPEKEYS", 0, "Shapekey(s)", "Transfer active or all shape keys"},
57#endif
58/* XXX When SkinModifier is enabled,
59 * it seems to erase its own CD_MVERT_SKIN layer from final DM :( */
60#if 0
61 {DT_TYPE_SKIN, "SKIN", 0, "Skin Weight", "Transfer skin weights"},
62#endif
63 {DT_TYPE_BWEIGHT_VERT, "BEVEL_WEIGHT_VERT", 0, "Bevel Weight", "Transfer bevel weights"},
65 "COLOR_VERTEX",
66 0,
67 "Colors",
68 "Color Attributes"},
69
70 RNA_ENUM_ITEM_HEADING(N_("Edge Data"), nullptr),
71 {DT_TYPE_SHARP_EDGE, "SHARP_EDGE", 0, "Sharp", "Transfer sharp mark"},
72 {DT_TYPE_SEAM, "SEAM", 0, "UV Seam", "Transfer UV seam mark"},
73 {DT_TYPE_CREASE, "CREASE", 0, "Subdivision Crease", "Transfer crease values"},
74 {DT_TYPE_BWEIGHT_EDGE, "BEVEL_WEIGHT_EDGE", 0, "Bevel Weight", "Transfer bevel weights"},
76 "FREESTYLE_EDGE",
77 0,
78 "Freestyle Mark",
79 "Transfer Freestyle edge mark"},
80
81 RNA_ENUM_ITEM_HEADING(N_("Face Corner Data"), nullptr),
82 {DT_TYPE_LNOR, "CUSTOM_NORMAL", 0, "Custom Normals", "Transfer custom normals"},
84 "COLOR_CORNER",
85 0,
86 "Colors",
87 "Color Attributes"},
88 {DT_TYPE_UV, "UV", 0, "UVs", "Transfer UV layers"},
89
90 RNA_ENUM_ITEM_HEADING(N_("Face Data"), nullptr),
91 {DT_TYPE_SHARP_FACE, "SMOOTH", 0, "Smooth", "Transfer flat/smooth mark"},
93 "FREESTYLE_FACE",
94 0,
95 "Freestyle Mark",
96 "Transfer Freestyle face mark"},
97 {0, nullptr, 0, nullptr, nullptr},
98};
99
100static void dt_add_vcol_layers(const CustomData *cdata,
101 eCustomDataMask mask,
102 EnumPropertyItem **r_item,
103 int *r_totitem)
104{
105 const int types[2] = {CD_PROP_COLOR, CD_PROP_BYTE_COLOR};
106 int idx = 0;
107 for (int i = 0; i < 2; i++) {
109
110 if (!(mask & CD_TYPE_AS_MASK(type))) {
111 continue;
112 }
113
114 int data_num = CustomData_number_of_layers(cdata, type);
115
116 RNA_enum_item_add_separator(r_item, r_totitem);
117
118 for (int j = 0; j < data_num; j++) {
119 EnumPropertyItem tmp_item = {0};
120 tmp_item.value = idx++;
121 tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(cdata, type, j);
122 RNA_enum_item_add(r_item, r_totitem, &tmp_item);
123 }
124 }
125}
126/* NOTE: #rna_enum_dt_layers_select_src_items enum is from rna_modifier.cc. */
129 PropertyRNA * /*prop*/,
130 bool *r_free)
131{
132 if (!C) { /* needed for docs and i18n tools */
134 }
135
136 EnumPropertyItem *item = nullptr, tmp_item = {0};
137 int totitem = 0;
138 const int data_type = RNA_enum_get(ptr, "data_type");
139
140 PropertyRNA *prop = RNA_struct_find_property(ptr, "use_reverse_transfer");
141 const bool reverse_transfer = prop != nullptr && RNA_property_boolean_get(ptr, prop);
142 const int layers_select_dst = reverse_transfer ? RNA_enum_get(ptr, "layers_select_src") :
143 RNA_enum_get(ptr, "layers_select_dst");
144
145 if (!reverse_transfer || layers_select_dst == DT_LAYERS_ACTIVE_DST || layers_select_dst >= 0) {
148 }
151
152 Object *ob_src = context_active_object(C);
153 if (ob_src == nullptr) {
154 RNA_enum_item_end(&item, &totitem);
155 *r_free = true;
156 return item;
157 }
158
159 if (data_type == DT_TYPE_MDEFORMVERT && BKE_object_supports_vertex_groups(ob_src)) {
160 if (BKE_object_pose_armature_get(ob_src)) {
165 }
166
167 const bDeformGroup *dg;
168 int i;
169
170 RNA_enum_item_add_separator(&item, &totitem);
171
172 const ListBase *defbase = BKE_object_defgroup_list(ob_src);
173 for (i = 0, dg = static_cast<const bDeformGroup *>(defbase->first); dg; i++, dg = dg->next) {
174 tmp_item.value = i;
175 tmp_item.identifier = tmp_item.name = dg->name;
176 RNA_enum_item_add(&item, &totitem, &tmp_item);
177 }
178 }
179 else if (data_type == DT_TYPE_SHAPEKEY) {
180 /* TODO */
181 }
182 else if (data_type == DT_TYPE_UV) {
184 const Object *ob_src_eval = DEG_get_evaluated(depsgraph, ob_src);
185 const Mesh *mesh_eval = BKE_object_get_evaluated_mesh_no_subsurf(ob_src_eval);
186 if (!mesh_eval) {
187 RNA_enum_item_end(&item, &totitem);
188 *r_free = true;
189 return item;
190 }
191 int data_num = CustomData_number_of_layers(&mesh_eval->corner_data, CD_PROP_FLOAT2);
192
193 RNA_enum_item_add_separator(&item, &totitem);
194
195 for (int i = 0; i < data_num; i++) {
196 tmp_item.value = i;
197 tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(
198 &mesh_eval->corner_data, CD_PROP_FLOAT2, i);
199 RNA_enum_item_add(&item, &totitem, &tmp_item);
200 }
201 }
202 else if (data_type & DT_TYPE_VCOL_ALL) {
204 const Object *ob_src_eval = DEG_get_evaluated(depsgraph, ob_src);
205 const Mesh *mesh_eval = BKE_object_get_evaluated_mesh_no_subsurf(ob_src_eval);
206 if (!mesh_eval) {
207 RNA_enum_item_end(&item, &totitem);
208 *r_free = true;
209 return item;
210 }
211
213 if (data_type & (DT_TYPE_MPROPCOL_VERT)) {
214 cddata_masks.vmask |= CD_MASK_PROP_COLOR;
215 }
216 if (data_type & (DT_TYPE_MLOOPCOL_VERT)) {
217 cddata_masks.vmask |= CD_MASK_PROP_BYTE_COLOR;
218 }
219
220 if (data_type & (DT_TYPE_MPROPCOL_LOOP)) {
221 cddata_masks.lmask |= CD_MASK_PROP_COLOR;
222 }
223 if (data_type & (DT_TYPE_MLOOPCOL_LOOP)) {
224 cddata_masks.lmask |= CD_MASK_PROP_BYTE_COLOR;
225 }
226
227 if (data_type & (DT_TYPE_MLOOPCOL_VERT | DT_TYPE_MPROPCOL_VERT)) {
228 dt_add_vcol_layers(&mesh_eval->vert_data, cddata_masks.vmask, &item, &totitem);
229 }
230 if (data_type & (DT_TYPE_MLOOPCOL_LOOP | DT_TYPE_MPROPCOL_LOOP)) {
231 dt_add_vcol_layers(&mesh_eval->corner_data, cddata_masks.lmask, &item, &totitem);
232 }
233 }
234
235 RNA_enum_item_end(&item, &totitem);
236 *r_free = true;
237
238 return item;
239}
240
241/* NOTE: #rna_enum_dt_layers_select_dst_items enum is from `rna_modifier.cc`. */
244 PropertyRNA * /*prop*/,
245 bool *r_free)
246{
247 if (!C) { /* needed for docs and i18n tools */
249 }
250
251 EnumPropertyItem *item = nullptr;
252 int totitem = 0;
253
254 PropertyRNA *prop = RNA_struct_find_property(ptr, "use_reverse_transfer");
255 const bool reverse_transfer = prop != nullptr && RNA_property_boolean_get(ptr, prop);
256 const int layers_select_src = reverse_transfer ? RNA_enum_get(ptr, "layers_select_dst") :
257 RNA_enum_get(ptr, "layers_select_src");
258
259 if (reverse_transfer || layers_select_src == DT_LAYERS_ACTIVE_SRC || layers_select_src >= 0) {
262 }
267
268 /* No 'specific' to-layers here, since we may transfer to several objects at once! */
269
270 RNA_enum_item_end(&item, &totitem);
271 *r_free = true;
272
273 return item;
274}
275
278 PropertyRNA *prop,
279 bool *r_free)
280{
281 const bool reverse_transfer = RNA_boolean_get(ptr, "use_reverse_transfer");
282
283 if (STREQ(RNA_property_identifier(prop), "layers_select_dst")) {
284 if (reverse_transfer) {
285 return dt_layers_select_src_itemf(C, ptr, prop, r_free);
286 }
287 return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
288 }
289 if (reverse_transfer) {
290 return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
291 }
292 return dt_layers_select_src_itemf(C, ptr, prop, r_free);
293}
294
295/* NOTE: rna_enum_dt_mix_mode_items enum is from `rna_modifier.cc`. */
298 PropertyRNA * /*prop*/,
299 bool *r_free)
300{
301 EnumPropertyItem *item = nullptr;
302 int totitem = 0;
303
304 const int dtdata_type = RNA_enum_get(ptr, "data_type");
305 bool support_advanced_mixing, support_threshold;
306
307 if (!C) { /* needed for docs and i18n tools */
309 }
310
312
314 dtdata_type, &support_advanced_mixing, &support_threshold);
315
316 if (support_threshold) {
321 }
322
323 if (support_advanced_mixing) {
324 RNA_enum_item_add_separator(&item, &totitem);
329 }
330
331 RNA_enum_item_end(&item, &totitem);
332 *r_free = true;
333
334 return item;
335}
336
337static bool data_transfer_check(bContext * /*C*/, wmOperator *op)
338{
339 const int layers_select_src = RNA_enum_get(op->ptr, "layers_select_src");
340 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "layers_select_dst");
341 const int layers_select_dst = RNA_property_enum_get(op->ptr, prop);
342
343 /* TODO: check for invalid layers_src select modes too! */
344
345 if ((layers_select_src != DT_LAYERS_ACTIVE_SRC) && (layers_select_dst == DT_LAYERS_ACTIVE_DST)) {
347 return true;
348 }
349
350 return false;
351}
352
353/* Helper, used by both data_transfer_exec and datalayout_transfer_exec. */
355 wmOperator *op,
356 Object *ob_src,
357 Vector<PointerRNA> *ctx_objects,
358 const bool reverse_transfer)
359{
361
362 if (reverse_transfer) {
363 return; /* Nothing else to do in this case... */
364 }
365
366 for (const PointerRNA &ptr : *ctx_objects) {
367 Object *ob = static_cast<Object *>(ptr.data);
368 Mesh *mesh;
369 if ((ob == ob_src) || (ob->type != OB_MESH)) {
370 continue;
371 }
372
373 mesh = static_cast<Mesh *>(ob->data);
375 /* Do not transfer to linked/override data, not supported. */
378 "Skipping object '%s', linked or override data '%s' cannot be modified",
379 ob->id.name + 2,
380 mesh->id.name + 2);
381 mesh->id.tag &= ~ID_TAG_DOIT;
382 continue;
383 }
384
385 mesh->id.tag |= ID_TAG_DOIT;
386 }
387}
388
389/* Helper, used by both data_transfer_exec and datalayout_transfer_exec. */
391 Object *ob_src,
392 Object *ob_dst,
393 const bool reverse_transfer)
394{
395 Mesh *mesh;
396 if ((ob_dst == ob_src) || (ob_src->type != OB_MESH) || (ob_dst->type != OB_MESH)) {
397 return false;
398 }
399
400 if (reverse_transfer) {
401 return true;
402 }
403
404 mesh = static_cast<Mesh *>(ob_dst->data);
405 if (mesh->id.tag & ID_TAG_DOIT) {
406 mesh->id.tag &= ~ID_TAG_DOIT;
407 return true;
408 }
410 /* Do not apply transfer operation more than once. */
411 /* XXX This is not nice regarding vgroups, which are half-Object data... :/ */
413 op->reports,
415 "Skipping object '%s', data '%s' has already been processed with a previous object",
416 ob_dst->id.name + 2,
417 mesh->id.name + 2);
418 }
419 return false;
420}
421
423{
424 Object *ob_src = context_active_object(C);
426
427 Vector<PointerRNA> ctx_objects;
428
429 bool changed = false;
430
431 const bool is_frozen = RNA_boolean_get(op->ptr, "use_freeze");
432
433 const bool reverse_transfer = RNA_boolean_get(op->ptr, "use_reverse_transfer");
434
435 const int data_type = RNA_enum_get(op->ptr, "data_type");
436 const bool use_create = RNA_boolean_get(op->ptr, "use_create");
437
438 const int map_vert_mode = RNA_enum_get(op->ptr, "vert_mapping");
439 const int map_edge_mode = RNA_enum_get(op->ptr, "edge_mapping");
440 const int map_loop_mode = RNA_enum_get(op->ptr, "loop_mapping");
441 const int map_poly_mode = RNA_enum_get(op->ptr, "poly_mapping");
442
443 const bool use_auto_transform = RNA_boolean_get(op->ptr, "use_auto_transform");
444 const bool use_object_transform = RNA_boolean_get(op->ptr, "use_object_transform");
445 const bool use_max_distance = RNA_boolean_get(op->ptr, "use_max_distance");
446 const float max_distance = use_max_distance ? RNA_float_get(op->ptr, "max_distance") : FLT_MAX;
447 const float ray_radius = RNA_float_get(op->ptr, "ray_radius");
448 const float islands_precision = RNA_float_get(op->ptr, "islands_precision");
449
450 int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
451 int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
452 int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
453 int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
454 const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
455
456 const int mix_mode = RNA_enum_get(op->ptr, "mix_mode");
457 const float mix_factor = RNA_float_get(op->ptr, "mix_factor");
458
459 SpaceTransform space_transform_data;
460 SpaceTransform *space_transform = (use_object_transform && !use_auto_transform) ?
461 &space_transform_data :
462 nullptr;
463
464 if (is_frozen) {
466 op->reports,
467 RPT_INFO,
468 "Operator is frozen, changes to its settings won't take effect until you unfreeze it");
469 return OPERATOR_FINISHED;
470 }
471
472 if (reverse_transfer && (!ID_IS_EDITABLE(ob_src->data) || ID_IS_OVERRIDE_LIBRARY(ob_src->data)))
473 {
474 /* Do not transfer to linked or override data, not supported. */
475 return OPERATOR_CANCELLED;
476 }
477
478 if (reverse_transfer) {
479 std::swap(layers_src, layers_dst);
480 }
481
482 if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
483 layers_select_src[fromto_idx] = layers_src;
484 layers_select_dst[fromto_idx] = layers_dst;
485 }
486
487 data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, reverse_transfer);
488
489 int invalid_count = 0;
490
491 for (const PointerRNA &ptr : ctx_objects) {
492 Object *ob_dst = static_cast<Object *>(ptr.data);
493
494 if (reverse_transfer) {
495 std::swap(ob_src, ob_dst);
496 }
497
498 if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, reverse_transfer)) {
499 Object *ob_src_eval = DEG_get_evaluated(depsgraph, ob_src);
500
501 if (space_transform) {
502 Object *ob_dst_eval = DEG_get_evaluated(depsgraph, ob_dst);
503 BLI_SPACE_TRANSFORM_SETUP(space_transform, ob_dst_eval, ob_src_eval);
504 }
505
507 ob_src_eval,
508 ob_dst,
509 data_type,
510 use_create,
511 map_vert_mode,
512 map_edge_mode,
513 map_loop_mode,
514 map_poly_mode,
515 space_transform,
516 use_auto_transform,
517 max_distance,
518 ray_radius,
519 islands_precision,
520 layers_select_src,
521 layers_select_dst,
522 mix_mode,
523 mix_factor,
524 nullptr,
525 false,
526 op->reports))
527 {
529 changed = true;
530 }
531 }
532 else {
533 /* Selected objects contains the active object, in this case `ob_src` is the same as
534 * `ob_dst`, so we don't treat this case as invaid. */
535 if (ob_src != ob_dst) {
536 invalid_count++;
537 }
538 }
539
540 if (reverse_transfer) {
541 std::swap(ob_src, ob_dst);
542 }
543 }
544
545 if (changed) {
548 }
549
550 if (invalid_count > 0) {
552 op->reports, RPT_WARNING, "Failed to transfer mesh data to %d objects", invalid_count);
553 }
554
555#if 0 /* TODO */
556 /* NOTE: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */
557 return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
558#else
559 return OPERATOR_FINISHED;
560#endif
561}
562
565{
566 /* Note this context poll is only really partial,
567 * it cannot check for all possible invalid cases. */
568
570 ID *data = static_cast<ID *>((ob) ? ob->data : nullptr);
571 return (ob != nullptr && ob->type == OB_MESH && data != nullptr);
572}
573
575static bool data_transfer_poll_property(const bContext * /*C*/,
576 wmOperator *op,
577 const PropertyRNA *prop)
578{
579 PointerRNA *ptr = op->ptr;
580 PropertyRNA *prop_other;
581
582 const char *prop_id = RNA_property_identifier(prop);
583 const int data_type = RNA_enum_get(ptr, "data_type");
584 bool use_auto_transform = false;
585 bool use_max_distance = false;
586 bool use_modifier = false;
587
588 if ((prop_other = RNA_struct_find_property(ptr, "use_auto_transform"))) {
589 use_auto_transform = RNA_property_boolean_get(ptr, prop_other);
590 }
591 if ((prop_other = RNA_struct_find_property(ptr, "use_max_distance"))) {
592 use_max_distance = RNA_property_boolean_get(ptr, prop_other);
593 }
594 if ((prop_other = RNA_struct_find_property(ptr, "modifier"))) {
595 use_modifier = RNA_property_is_set(ptr, prop_other);
596 }
597
598 if (STREQ(prop_id, "modifier")) {
599 return use_modifier;
600 }
601
602 if (use_modifier) {
603 /* Hide everything but 'modifier' property, if set. */
604 return false;
605 }
606
607 if (STREQ(prop_id, "use_object_transform")) {
608 if (use_auto_transform) {
609 return false;
610 }
611 }
612 else if (STREQ(prop_id, "max_distance")) {
613 if (!use_max_distance) {
614 return false;
615 }
616 }
617 else if (STREQ(prop_id, "islands_precision")) {
618 if (!DT_DATATYPE_IS_LOOP(data_type)) {
619 return false;
620 }
621 }
622 else if (STREQ(prop_id, "vert_mapping")) {
623 if (!DT_DATATYPE_IS_VERT(data_type)) {
624 return false;
625 }
626 }
627 else if (STREQ(prop_id, "edge_mapping")) {
628 if (!DT_DATATYPE_IS_EDGE(data_type)) {
629 return false;
630 }
631 }
632 else if (STREQ(prop_id, "loop_mapping")) {
633 if (!DT_DATATYPE_IS_LOOP(data_type)) {
634 return false;
635 }
636 }
637 else if (STREQ(prop_id, "poly_mapping")) {
638 if (!DT_DATATYPE_IS_FACE(data_type)) {
639 return false;
640 }
641 }
642 else if (STR_ELEM(prop_id, "layers_select_src", "layers_select_dst")) {
643 if (!DT_DATATYPE_IS_MULTILAYERS(data_type)) {
644 return false;
645 }
646 }
647
648 /* Else, show it! */
649 return true;
650}
651
652static std::string data_transfer_get_description(bContext * /*C*/,
653 wmOperatorType * /*ot*/,
655{
656 const bool reverse_transfer = RNA_boolean_get(ptr, "use_reverse_transfer");
657
658 if (reverse_transfer) {
659 return TIP_(
660 "Transfer data layer(s) (weights, edge sharp, etc.) from selected meshes to active one");
661 }
662
663 return "";
664}
665
667{
668 PropertyRNA *prop;
669
670 /* Identifiers. */
671 ot->name = "Transfer Mesh Data";
672 ot->idname = "OBJECT_OT_data_transfer";
673 ot->description =
674 "Transfer data layer(s) (weights, edge sharp, etc.) from active to selected meshes";
675
676 /* API callbacks. */
677 ot->poll = data_transfer_poll;
678 ot->poll_property = data_transfer_poll_property;
679 ot->invoke = WM_menu_invoke;
680 ot->exec = data_transfer_exec;
681 ot->check = data_transfer_check;
682 ot->get_description = data_transfer_get_description;
683
684 /* Flags. */
686
687 /* Properties. */
688 prop = RNA_def_boolean(ot->srna,
689 "use_reverse_transfer",
690 false,
691 "Reverse Transfer",
692 "Transfer from selected objects to active one");
694
695 RNA_def_boolean(ot->srna,
696 "use_freeze",
697 false,
698 "Freeze Operator",
699 "Prevent changes to settings to re-run the operator, "
700 "handy to change several things at once with heavy geometry");
701
702 /* Data type to transfer. */
703 ot->prop = RNA_def_enum(
704 ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
705 RNA_def_boolean(ot->srna,
706 "use_create",
707 true,
708 "Create Data",
709 "Add data layers on destination meshes if needed");
710
711 /* Mapping methods. */
712 RNA_def_enum(ot->srna,
713 "vert_mapping",
716 "Vertex Mapping",
717 "Method used to map source vertices to destination ones");
718 RNA_def_enum(ot->srna,
719 "edge_mapping",
722 "Edge Mapping",
723 "Method used to map source edges to destination ones");
724 RNA_def_enum(ot->srna,
725 "loop_mapping",
728 "Face Corner Mapping",
729 "Method used to map source faces' corners to destination ones");
730 RNA_def_enum(ot->srna,
731 "poly_mapping",
734 "Face Mapping",
735 "Method used to map source faces to destination ones");
736
737 /* Mapping options and filtering. */
739 ot->srna,
740 "use_auto_transform",
741 false,
742 "Auto Transform",
743 "Automatically compute transformation to get the best possible match between source and "
744 "destination meshes.\n"
745 "Warning: Results will never be as good as manual matching of objects");
746 RNA_def_boolean(ot->srna,
747 "use_object_transform",
748 true,
749 "Object Transform",
750 "Evaluate source and destination meshes in global space");
751 RNA_def_boolean(ot->srna,
752 "use_max_distance",
753 false,
754 "Only Neighbor Geometry",
755 "Source elements must be closer than given distance from destination one");
756 prop = RNA_def_float(
757 ot->srna,
758 "max_distance",
759 1.0f,
760 0.0f,
761 FLT_MAX,
762 "Max Distance",
763 "Maximum allowed distance between source and destination element, for non-topology mappings",
764 0.0f,
765 100.0f);
767 prop = RNA_def_float(
768 ot->srna,
769 "ray_radius",
770 0.0f,
771 0.0f,
772 FLT_MAX,
773 "Ray Radius",
774 "'Width' of rays (especially useful when raycasting against vertices or edges)",
775 0.0f,
776 10.0f);
778 prop = RNA_def_float(
779 ot->srna,
780 "islands_precision",
781 0.1f,
782 0.0f,
783 10.0f,
784 "Islands Precision",
785 "Factor controlling precision of islands handling (the higher, the better the results)",
786 0.0f,
787 1.0f);
789
790 /* How to handle multi-layers types of data. */
791 prop = RNA_def_enum(ot->srna,
792 "layers_select_src",
795 "Source Layers Selection",
796 "Which layers to transfer, in case of multi-layers types");
798
799 prop = RNA_def_enum(ot->srna,
800 "layers_select_dst",
803 "Destination Layers Matching",
804 "How to match source and destination layers");
806
807 prop = RNA_def_enum(ot->srna,
808 "mix_mode",
811 "Mix Mode",
812 "How to affect destination elements with source values");
815 ot->srna,
816 "mix_factor",
817 1.0f,
818 0.0f,
819 1.0f,
820 "Mix Factor",
821 "Factor to use when applying data to destination (exact behavior depends on mix mode)",
822 0.0f,
823 1.0f);
824}
825
826/******************************************************************************/
827/* NOTE: This operator is hybrid, it can work as a usual standalone Object operator,
828 * or as a DataTransfer modifier tool.
829 */
830
832{
833 return (edit_modifier_poll_generic(C, &RNA_DataTransferModifier, (1 << OB_MESH), true, false) ||
835}
836
838{
839 Object *ob_act = context_active_object(C);
842
844 op, ob_act, eModifierType_DataTransfer);
845
846 /* If we have a modifier, we transfer data layout from this modifier's source object to
847 * active one. Else, we transfer data layout from active object to all selected ones. */
848 if (dtmd) {
849 Object *ob_src = dtmd->ob_source;
850 Object *ob_dst = ob_act;
851
852 const bool use_delete = false; /* Never when used from modifier, for now. */
853
854 if (!ob_src || !ID_IS_EDITABLE(ob_dst) || ID_IS_OVERRIDE_LIBRARY(ob_dst)) {
855 return OPERATOR_CANCELLED;
856 }
857
858 Object *ob_src_eval = DEG_get_evaluated(depsgraph, ob_src);
859
861 ob_src_eval,
862 ob_dst,
863 dtmd->data_types,
864 use_delete,
865 dtmd->layers_select_src,
866 dtmd->layers_select_dst);
867
869 }
870 else {
871 Object *ob_src = ob_act;
872
873 Vector<PointerRNA> ctx_objects;
874
875 const int data_type = RNA_enum_get(op->ptr, "data_type");
876 const bool use_delete = RNA_boolean_get(op->ptr, "use_delete");
877
878 const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
879 const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
880 int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
881 int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
882 const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
883
884 if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
885 layers_select_src[fromto_idx] = layers_src;
886 layers_select_dst[fromto_idx] = layers_dst;
887 }
888
889 Object *ob_src_eval = DEG_get_evaluated(depsgraph, ob_src);
890
891 data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, false);
892
893 for (const PointerRNA &ptr : ctx_objects) {
894 Object *ob_dst = static_cast<Object *>(ptr.data);
895 if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, false)) {
897 ob_src_eval,
898 ob_dst,
899 data_type,
900 use_delete,
901 layers_select_src,
902 layers_select_dst);
903 }
904
906 }
907 }
908
911
912 return OPERATOR_FINISHED;
913}
914
916 wmOperator *op,
917 const wmEvent *event)
918{
920 return datalayout_transfer_exec(C, op);
921 }
922 return WM_menu_invoke(C, op, event);
923}
924
926{
927 PropertyRNA *prop;
928
929 ot->name = "Transfer Mesh Data Layout";
930 ot->description = "Transfer layout of data layer(s) from active to selected meshes";
931 ot->idname = "OBJECT_OT_datalayout_transfer";
932
934 ot->poll_property = data_transfer_poll_property;
937 ot->check = data_transfer_check;
938
939 /* flags */
941
942 /* Properties. */
944
945 /* Data type to transfer. */
946 ot->prop = RNA_def_enum(
947 ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
948 RNA_def_boolean(ot->srna,
949 "use_delete",
950 false,
951 "Exact Match",
952 "Also delete some data layers from destination if necessary, so that it matches "
953 "exactly source");
954
955 /* How to handle multi-layers types of data. */
956 prop = RNA_def_enum(ot->srna,
957 "layers_select_src",
960 "Source Layers Selection",
961 "Which layers to transfer, in case of multi-layers types");
963
964 prop = RNA_def_enum(ot->srna,
965 "layers_select_dst",
968 "Destination Layers Matching",
969 "How to match source and destination layers");
971}
972
973} // namespace blender::ed::object
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Main * CTX_data_main(const bContext *C)
bool CTX_data_selected_editable_objects(const bContext *C, blender::Vector< PointerRNA > *list)
CustomData interface, see also DNA_customdata_types.h.
const char * CustomData_get_layer_name(const CustomData *data, eCustomDataType type, int n)
const CustomData_MeshMasks CD_MASK_BAREMESH
int CustomData_number_of_layers(const CustomData *data, eCustomDataType type)
#define CD_TYPE_AS_MASK(_type)
int BKE_object_data_transfer_dttype_to_srcdst_index(int dtdata_type)
bool BKE_object_data_transfer_mesh(struct Depsgraph *depsgraph, struct Object *ob_src, struct Object *ob_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_layout(struct Depsgraph *depsgraph, struct Object *ob_src, struct Object *ob_dst, int data_types, bool use_delete, const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX])
bool BKE_object_data_transfer_get_dttypes_capacity(int dtdata_types, bool *r_advanced_mixing, bool *r_threshold)
support for deformation groups and hooks.
bool BKE_object_supports_vertex_groups(const Object *ob)
Definition deform.cc:452
const ListBase * BKE_object_defgroup_list(const Object *ob)
Definition deform.cc:574
General operations, lookup, etc. for blender objects.
Mesh * BKE_object_get_evaluated_mesh_no_subsurf(const Object *object_eval)
Object * BKE_object_pose_armature_get(Object *ob)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
#define BLI_SPACE_TRANSFORM_SETUP(data, local, target)
#define STR_ELEM(...)
Definition BLI_string.h:656
#define STREQ(a, b)
#define TIP_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:982
@ ID_TAG_DOIT
Definition DNA_ID.h:944
@ CD_PROP_BYTE_COLOR
@ CD_PROP_COLOR
@ CD_PROP_FLOAT2
@ DT_TYPE_VCOL_ALL
@ DT_TYPE_MLOOPCOL_LOOP
@ DT_TYPE_SKIN
@ DT_TYPE_UV
@ DT_TYPE_MPROPCOL_VERT
@ DT_TYPE_BWEIGHT_VERT
@ DT_TYPE_FREESTYLE_FACE
@ DT_TYPE_SHAPEKEY
@ DT_TYPE_CREASE
@ DT_TYPE_SEAM
@ DT_TYPE_MLOOPCOL_VERT
@ DT_TYPE_LNOR
@ DT_TYPE_MPROPCOL_LOOP
@ DT_TYPE_SHARP_FACE
@ DT_TYPE_MDEFORMVERT
@ DT_TYPE_BWEIGHT_EDGE
@ DT_TYPE_FREESTYLE_EDGE
@ DT_TYPE_SHARP_EDGE
@ DT_LAYERS_VGROUP_SRC_BONE_SELECT
@ DT_LAYERS_VGROUP_SRC_BONE_DEFORM
@ DT_LAYERS_ALL_SRC
@ DT_LAYERS_ACTIVE_SRC
#define DT_DATATYPE_IS_MULTILAYERS(_dt)
@ MREMAP_MODE_VERT_NEAREST
@ MREMAP_MODE_LOOP_NEAREST_POLYNOR
@ MREMAP_MODE_EDGE_NEAREST
@ MREMAP_MODE_POLY_NEAREST
@ CDT_MIX_SUB
@ CDT_MIX_REPLACE_BELOW_THRESHOLD
@ CDT_MIX_REPLACE_ABOVE_THRESHOLD
@ CDT_MIX_ADD
@ CDT_MIX_MUL
@ CDT_MIX_TRANSFER
@ CDT_MIX_MIX
#define DT_DATATYPE_IS_LOOP(_dt)
@ DT_LAYERS_ACTIVE_DST
@ DT_LAYERS_INDEX_DST
@ DT_LAYERS_NAME_DST
#define DT_DATATYPE_IS_EDGE(_dt)
#define DT_DATATYPE_IS_FACE(_dt)
#define DT_DATATYPE_IS_VERT(_dt)
@ DT_MULTILAYER_INDEX_MAX
@ DT_MULTILAYER_INDEX_INVALID
@ eModifierType_DataTransfer
Object is a sort of wrapper for general info.
@ OB_MESH
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ PROP_SKIP_SAVE
Definition RNA_types.hh:330
@ PROP_HIDDEN
Definition RNA_types.hh:324
#define RNA_ENUM_ITEM_HEADING(name, description)
Definition RNA_types.hh:639
@ PROP_DISTANCE
Definition RNA_types.hh:244
@ PROP_FACTOR
Definition RNA_types.hh:239
#define C
Definition RandGen.cpp:29
#define ND_DRAW
Definition WM_types.hh:458
#define NC_OBJECT
Definition WM_types.hh:376
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
BMesh const char void * data
BPy_StructRNA * depsgraph
#define CD_MASK_PROP_BYTE_COLOR
#define CD_MASK_PROP_COLOR
#define ID_IS_EDITABLE(_id)
#define ID_IS_OVERRIDE_LIBRARY(_id)
static char ** types
Definition makesdna.cc:71
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
static wmOperatorStatus datalayout_transfer_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem * dt_layers_select_src_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *, bool *r_free)
static wmOperatorStatus datalayout_transfer_invoke(bContext *C, wmOperator *op, const wmEvent *event)
bool edit_modifier_invoke_properties(bContext *C, wmOperator *op)
void OBJECT_OT_data_transfer(wmOperatorType *ot)
void OBJECT_OT_datalayout_transfer(wmOperatorType *ot)
static std::string data_transfer_get_description(bContext *, wmOperatorType *, PointerRNA *ptr)
bool edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag, bool is_editmode_allowed, bool is_liboverride_allowed)
ModifierData * edit_modifier_property_get(wmOperator *op, Object *ob, int type)
static wmOperatorStatus data_transfer_exec(bContext *C, wmOperator *op)
Object * context_active_object(const bContext *C)
static const EnumPropertyItem * dt_layers_select_dst_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *, bool *r_free)
static bool data_transfer_poll(bContext *C)
static const EnumPropertyItem DT_layer_items[]
static bool data_transfer_exec_is_object_valid(wmOperator *op, Object *ob_src, Object *ob_dst, const bool reverse_transfer)
static void dt_add_vcol_layers(const CustomData *cdata, eCustomDataMask mask, EnumPropertyItem **r_item, int *r_totitem)
static const EnumPropertyItem * dt_layers_select_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
static void data_transfer_exec_preprocess_objects(bContext *C, wmOperator *op, Object *ob_src, Vector< PointerRNA > *ctx_objects, const bool reverse_transfer)
static bool datalayout_transfer_poll(bContext *C)
static bool data_transfer_check(bContext *, wmOperator *op)
static const EnumPropertyItem * dt_mix_mode_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *, bool *r_free)
static bool data_transfer_poll_property(const bContext *, wmOperator *op, const PropertyRNA *prop)
void edit_modifier_properties(wmOperatorType *ot)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
float RNA_float_get(PointerRNA *ptr, const char *name)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
const char * RNA_property_identifier(const PropertyRNA *prop)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
void RNA_def_property_enum_funcs_runtime(PropertyRNA *prop, EnumPropertyGetFunc getfunc, EnumPropertySetFunc setfunc, EnumPropertyItemFunc itemfunc)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
void RNA_enum_item_add_separator(EnumPropertyItem **items, int *totitem)
void RNA_def_property_subtype(PropertyRNA *prop, PropertySubType subtype)
void RNA_enum_items_add_value(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item, int value)
const EnumPropertyItem rna_enum_dt_method_loop_items[]
const EnumPropertyItem rna_enum_dt_method_edge_items[]
const EnumPropertyItem rna_enum_dt_method_poly_items[]
const EnumPropertyItem rna_enum_dt_mix_mode_items[]
const EnumPropertyItem rna_enum_dt_layers_select_src_items[]
const EnumPropertyItem rna_enum_dt_method_vertex_items[]
const EnumPropertyItem rna_enum_dt_layers_select_dst_items[]
#define FLT_MAX
Definition stdcycles.h:14
const char * identifier
Definition RNA_types.hh:623
const char * name
Definition RNA_types.hh:627
Definition DNA_ID.h:404
char name[66]
Definition DNA_ID.h:415
void * first
CustomData corner_data
CustomData vert_data
struct bDeformGroup * next
struct ReportList * reports
struct PointerRNA * ptr
i
Definition text_draw.cc:230
#define N_(msgid)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4227
wmOperatorType * ot
Definition wm_files.cc:4226
wmOperatorStatus WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)