Blender V5.0
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 {DT_TYPE_BWEIGHT_VERT, "BEVEL_WEIGHT_VERT", 0, "Bevel Weight", "Transfer bevel weights"},
57 "COLOR_VERTEX",
58 0,
59 "Colors",
60 "Color Attributes"},
61
62 RNA_ENUM_ITEM_HEADING(N_("Edge Data"), nullptr),
63 {DT_TYPE_SHARP_EDGE, "SHARP_EDGE", 0, "Sharp", "Transfer sharp mark"},
64 {DT_TYPE_SEAM, "SEAM", 0, "UV Seam", "Transfer UV seam mark"},
65 {DT_TYPE_CREASE, "CREASE", 0, "Subdivision Crease", "Transfer crease values"},
66 {DT_TYPE_BWEIGHT_EDGE, "BEVEL_WEIGHT_EDGE", 0, "Bevel Weight", "Transfer bevel weights"},
68 "FREESTYLE_EDGE",
69 0,
70 "Freestyle Mark",
71 "Transfer Freestyle edge mark"},
72
73 RNA_ENUM_ITEM_HEADING(N_("Face Corner Data"), nullptr),
74 {DT_TYPE_LNOR, "CUSTOM_NORMAL", 0, "Custom Normals", "Transfer custom normals"},
76 "COLOR_CORNER",
77 0,
78 "Colors",
79 "Color Attributes"},
80 {DT_TYPE_UV, "UV", 0, "UVs", "Transfer UV layers"},
81
82 RNA_ENUM_ITEM_HEADING(N_("Face Data"), nullptr),
83 {DT_TYPE_SHARP_FACE, "SMOOTH", 0, "Smooth", "Transfer flat/smooth mark"},
85 "FREESTYLE_FACE",
86 0,
87 "Freestyle Mark",
88 "Transfer Freestyle face mark"},
89 {0, nullptr, 0, nullptr, nullptr},
90};
91
92static void dt_add_vcol_layers(const CustomData *cdata,
93 eCustomDataMask mask,
94 EnumPropertyItem **r_item,
95 int *r_totitem)
96{
97 const int types[2] = {CD_PROP_COLOR, CD_PROP_BYTE_COLOR};
98 int idx = 0;
99 for (int i = 0; i < 2; i++) {
101
102 if (!(mask & CD_TYPE_AS_MASK(type))) {
103 continue;
104 }
105
106 int data_num = CustomData_number_of_layers(cdata, type);
107
108 RNA_enum_item_add_separator(r_item, r_totitem);
109
110 for (int j = 0; j < data_num; j++) {
111 EnumPropertyItem tmp_item = {0};
112 tmp_item.value = idx++;
113 tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(cdata, type, j);
114 RNA_enum_item_add(r_item, r_totitem, &tmp_item);
115 }
116 }
117}
118/* NOTE: #rna_enum_dt_layers_select_src_items enum is from rna_modifier.cc. */
121 PropertyRNA * /*prop*/,
122 bool *r_free)
123{
124 if (!C) { /* needed for docs and i18n tools */
126 }
127
128 EnumPropertyItem *item = nullptr, tmp_item = {0};
129 int totitem = 0;
130 const int data_type = RNA_enum_get(ptr, "data_type");
131
132 PropertyRNA *prop = RNA_struct_find_property(ptr, "use_reverse_transfer");
133 const bool reverse_transfer = prop != nullptr && RNA_property_boolean_get(ptr, prop);
134 const int layers_select_dst = reverse_transfer ? RNA_enum_get(ptr, "layers_select_src") :
135 RNA_enum_get(ptr, "layers_select_dst");
136
137 if (!reverse_transfer || layers_select_dst == DT_LAYERS_ACTIVE_DST || layers_select_dst >= 0) {
140 }
143
144 Object *ob_src = context_active_object(C);
145 if (ob_src == nullptr) {
146 RNA_enum_item_end(&item, &totitem);
147 *r_free = true;
148 return item;
149 }
150
151 if (data_type == DT_TYPE_MDEFORMVERT && BKE_object_supports_vertex_groups(ob_src)) {
152 if (BKE_object_pose_armature_get(ob_src)) {
157 }
158
159 const bDeformGroup *dg;
160 int i;
161
162 RNA_enum_item_add_separator(&item, &totitem);
163
164 const ListBase *defbase = BKE_object_defgroup_list(ob_src);
165 for (i = 0, dg = static_cast<const bDeformGroup *>(defbase->first); dg; i++, dg = dg->next) {
166 tmp_item.value = i;
167 tmp_item.identifier = tmp_item.name = dg->name;
168 RNA_enum_item_add(&item, &totitem, &tmp_item);
169 }
170 }
171 else if (data_type == DT_TYPE_UV) {
173 const Object *ob_src_eval = DEG_get_evaluated(depsgraph, ob_src);
174 const Mesh *mesh_eval = BKE_object_get_evaluated_mesh_no_subsurf(ob_src_eval);
175 if (!mesh_eval) {
176 RNA_enum_item_end(&item, &totitem);
177 *r_free = true;
178 return item;
179 }
180 int data_num = CustomData_number_of_layers(&mesh_eval->corner_data, CD_PROP_FLOAT2);
181
182 RNA_enum_item_add_separator(&item, &totitem);
183
184 for (int i = 0; i < data_num; i++) {
185 tmp_item.value = i;
186 tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(
187 &mesh_eval->corner_data, CD_PROP_FLOAT2, i);
188 RNA_enum_item_add(&item, &totitem, &tmp_item);
189 }
190 }
191 else if (data_type & DT_TYPE_VCOL_ALL) {
193 const Object *ob_src_eval = DEG_get_evaluated(depsgraph, ob_src);
194 const Mesh *mesh_eval = BKE_object_get_evaluated_mesh_no_subsurf(ob_src_eval);
195 if (!mesh_eval) {
196 RNA_enum_item_end(&item, &totitem);
197 *r_free = true;
198 return item;
199 }
200
202 if (data_type & (DT_TYPE_MPROPCOL_VERT)) {
203 cddata_masks.vmask |= CD_MASK_PROP_COLOR;
204 }
205 if (data_type & (DT_TYPE_MLOOPCOL_VERT)) {
206 cddata_masks.vmask |= CD_MASK_PROP_BYTE_COLOR;
207 }
208
209 if (data_type & (DT_TYPE_MPROPCOL_LOOP)) {
210 cddata_masks.lmask |= CD_MASK_PROP_COLOR;
211 }
212 if (data_type & (DT_TYPE_MLOOPCOL_LOOP)) {
213 cddata_masks.lmask |= CD_MASK_PROP_BYTE_COLOR;
214 }
215
216 if (data_type & (DT_TYPE_MLOOPCOL_VERT | DT_TYPE_MPROPCOL_VERT)) {
217 dt_add_vcol_layers(&mesh_eval->vert_data, cddata_masks.vmask, &item, &totitem);
218 }
219 if (data_type & (DT_TYPE_MLOOPCOL_LOOP | DT_TYPE_MPROPCOL_LOOP)) {
220 dt_add_vcol_layers(&mesh_eval->corner_data, cddata_masks.lmask, &item, &totitem);
221 }
222 }
223
224 RNA_enum_item_end(&item, &totitem);
225 *r_free = true;
226
227 return item;
228}
229
230/* NOTE: #rna_enum_dt_layers_select_dst_items enum is from `rna_modifier.cc`. */
233 PropertyRNA * /*prop*/,
234 bool *r_free)
235{
236 if (!C) { /* needed for docs and i18n tools */
238 }
239
240 EnumPropertyItem *item = nullptr;
241 int totitem = 0;
242
243 PropertyRNA *prop = RNA_struct_find_property(ptr, "use_reverse_transfer");
244 const bool reverse_transfer = prop != nullptr && RNA_property_boolean_get(ptr, prop);
245 const int layers_select_src = reverse_transfer ? RNA_enum_get(ptr, "layers_select_dst") :
246 RNA_enum_get(ptr, "layers_select_src");
247
248 if (reverse_transfer || layers_select_src == DT_LAYERS_ACTIVE_SRC || layers_select_src >= 0) {
251 }
256
257 /* No 'specific' to-layers here, since we may transfer to several objects at once! */
258
259 RNA_enum_item_end(&item, &totitem);
260 *r_free = true;
261
262 return item;
263}
264
267 PropertyRNA *prop,
268 bool *r_free)
269{
270 const bool reverse_transfer = RNA_boolean_get(ptr, "use_reverse_transfer");
271
272 if (STREQ(RNA_property_identifier(prop), "layers_select_dst")) {
273 if (reverse_transfer) {
274 return dt_layers_select_src_itemf(C, ptr, prop, r_free);
275 }
276 return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
277 }
278 if (reverse_transfer) {
279 return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
280 }
281 return dt_layers_select_src_itemf(C, ptr, prop, r_free);
282}
283
284/* NOTE: rna_enum_dt_mix_mode_items enum is from `rna_modifier.cc`. */
287 PropertyRNA * /*prop*/,
288 bool *r_free)
289{
290 EnumPropertyItem *item = nullptr;
291 int totitem = 0;
292
293 const int dtdata_type = RNA_enum_get(ptr, "data_type");
294 bool support_advanced_mixing, support_threshold;
295
296 if (!C) { /* needed for docs and i18n tools */
298 }
299
301
303 dtdata_type, &support_advanced_mixing, &support_threshold);
304
305 if (support_threshold) {
310 }
311
312 if (support_advanced_mixing) {
313 RNA_enum_item_add_separator(&item, &totitem);
318 }
319
320 RNA_enum_item_end(&item, &totitem);
321 *r_free = true;
322
323 return item;
324}
325
326static bool data_transfer_check(bContext * /*C*/, wmOperator *op)
327{
328 const int layers_select_src = RNA_enum_get(op->ptr, "layers_select_src");
329 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "layers_select_dst");
330 const int layers_select_dst = RNA_property_enum_get(op->ptr, prop);
331
332 /* TODO: check for invalid layers_src select modes too! */
333
334 if ((layers_select_src != DT_LAYERS_ACTIVE_SRC) && (layers_select_dst == DT_LAYERS_ACTIVE_DST)) {
336 return true;
337 }
338
339 return false;
340}
341
342/* Helper, used by both data_transfer_exec and datalayout_transfer_exec. */
344 wmOperator *op,
345 Object *ob_src,
346 Vector<PointerRNA> *ctx_objects,
347 const bool reverse_transfer)
348{
350
351 if (reverse_transfer) {
352 return; /* Nothing else to do in this case... */
353 }
354
355 for (const PointerRNA &ptr : *ctx_objects) {
356 Object *ob = static_cast<Object *>(ptr.data);
357 Mesh *mesh;
358 if ((ob == ob_src) || (ob->type != OB_MESH)) {
359 continue;
360 }
361
362 mesh = static_cast<Mesh *>(ob->data);
364 /* Do not transfer to linked/override data, not supported. */
367 "Skipping object '%s', linked or override data '%s' cannot be modified",
368 ob->id.name + 2,
369 mesh->id.name + 2);
370 mesh->id.tag &= ~ID_TAG_DOIT;
371 continue;
372 }
373
374 mesh->id.tag |= ID_TAG_DOIT;
375 }
376}
377
378/* Helper, used by both data_transfer_exec and datalayout_transfer_exec. */
380 Object *ob_src,
381 Object *ob_dst,
382 const bool reverse_transfer)
383{
384 Mesh *mesh;
385 if ((ob_dst == ob_src) || (ob_src->type != OB_MESH) || (ob_dst->type != OB_MESH)) {
386 return false;
387 }
388
389 if (reverse_transfer) {
390 return true;
391 }
392
393 mesh = static_cast<Mesh *>(ob_dst->data);
394 if (mesh->id.tag & ID_TAG_DOIT) {
395 mesh->id.tag &= ~ID_TAG_DOIT;
396 return true;
397 }
399 /* Do not apply transfer operation more than once. */
400 /* XXX This is not nice regarding vgroups, which are half-Object data... :/ */
402 op->reports,
404 "Skipping object '%s', data '%s' has already been processed with a previous object",
405 ob_dst->id.name + 2,
406 mesh->id.name + 2);
407 }
408 return false;
409}
410
412{
413 Object *ob_src = context_active_object(C);
415
416 Vector<PointerRNA> ctx_objects;
417
418 bool changed = false;
419
420 const bool is_frozen = RNA_boolean_get(op->ptr, "use_freeze");
421
422 const bool reverse_transfer = RNA_boolean_get(op->ptr, "use_reverse_transfer");
423
424 const int data_type = RNA_enum_get(op->ptr, "data_type");
425 const bool use_create = RNA_boolean_get(op->ptr, "use_create");
426
427 const int map_vert_mode = RNA_enum_get(op->ptr, "vert_mapping");
428 const int map_edge_mode = RNA_enum_get(op->ptr, "edge_mapping");
429 const int map_loop_mode = RNA_enum_get(op->ptr, "loop_mapping");
430 const int map_poly_mode = RNA_enum_get(op->ptr, "poly_mapping");
431
432 const bool use_auto_transform = RNA_boolean_get(op->ptr, "use_auto_transform");
433 const bool use_object_transform = RNA_boolean_get(op->ptr, "use_object_transform");
434 const bool use_max_distance = RNA_boolean_get(op->ptr, "use_max_distance");
435 const float max_distance = use_max_distance ? RNA_float_get(op->ptr, "max_distance") : FLT_MAX;
436 const float ray_radius = RNA_float_get(op->ptr, "ray_radius");
437 const float islands_precision = RNA_float_get(op->ptr, "islands_precision");
438
439 int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
440 int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
441 int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
442 int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
443 const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
444
445 const int mix_mode = RNA_enum_get(op->ptr, "mix_mode");
446 const float mix_factor = RNA_float_get(op->ptr, "mix_factor");
447
448 SpaceTransform space_transform_data;
449 SpaceTransform *space_transform = (use_object_transform && !use_auto_transform) ?
450 &space_transform_data :
451 nullptr;
452
453 if (is_frozen) {
455 op->reports,
456 RPT_INFO,
457 "Operator is frozen, changes to its settings won't take effect until you unfreeze it");
458 return OPERATOR_FINISHED;
459 }
460
461 if (reverse_transfer && (!ID_IS_EDITABLE(ob_src->data) || ID_IS_OVERRIDE_LIBRARY(ob_src->data)))
462 {
463 /* Do not transfer to linked or override data, not supported. */
464 return OPERATOR_CANCELLED;
465 }
466
467 if (reverse_transfer) {
468 std::swap(layers_src, layers_dst);
469 }
470
471 if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
472 layers_select_src[fromto_idx] = layers_src;
473 layers_select_dst[fromto_idx] = layers_dst;
474 }
475
476 data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, reverse_transfer);
477
478 int invalid_count = 0;
479
480 for (const PointerRNA &ptr : ctx_objects) {
481 Object *ob_dst = static_cast<Object *>(ptr.data);
482
483 if (reverse_transfer) {
484 std::swap(ob_src, ob_dst);
485 }
486
487 if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, reverse_transfer)) {
488 Object *ob_src_eval = DEG_get_evaluated(depsgraph, ob_src);
489
490 if (space_transform) {
491 Object *ob_dst_eval = DEG_get_evaluated(depsgraph, ob_dst);
492 BLI_SPACE_TRANSFORM_SETUP(space_transform, ob_dst_eval, ob_src_eval);
493 }
494
496 ob_src_eval,
497 ob_dst,
498 data_type,
499 use_create,
500 map_vert_mode,
501 map_edge_mode,
502 map_loop_mode,
503 map_poly_mode,
504 space_transform,
505 use_auto_transform,
506 max_distance,
507 ray_radius,
508 islands_precision,
509 layers_select_src,
510 layers_select_dst,
511 mix_mode,
512 mix_factor,
513 nullptr,
514 false,
515 op->reports))
516 {
518 changed = true;
519 }
520 }
521 else {
522 /* Selected objects contains the active object, in this case `ob_src` is the same as
523 * `ob_dst`, so we don't treat this case as invalid. */
524 if (ob_src != ob_dst) {
525 invalid_count++;
526 }
527 }
528
529 if (reverse_transfer) {
530 std::swap(ob_src, ob_dst);
531 }
532 }
533
534 if (changed) {
537 }
538
539 if (invalid_count > 0) {
541 op->reports, RPT_WARNING, "Failed to transfer mesh data to %d objects", invalid_count);
542 }
543
544#if 0 /* TODO */
545 /* NOTE: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */
546 return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
547#else
548 return OPERATOR_FINISHED;
549#endif
550}
551
554{
555 /* Note this context poll is only really partial,
556 * it cannot check for all possible invalid cases. */
557
559 ID *data = static_cast<ID *>((ob) ? ob->data : nullptr);
560 return (ob != nullptr && ob->type == OB_MESH && data != nullptr);
561}
562
564static bool data_transfer_poll_property(const bContext * /*C*/,
565 wmOperator *op,
566 const PropertyRNA *prop)
567{
568 PointerRNA *ptr = op->ptr;
569 PropertyRNA *prop_other;
570
571 const char *prop_id = RNA_property_identifier(prop);
572 const int data_type = RNA_enum_get(ptr, "data_type");
573 bool use_auto_transform = false;
574 bool use_max_distance = false;
575 bool use_modifier = false;
576
577 if ((prop_other = RNA_struct_find_property(ptr, "use_auto_transform"))) {
578 use_auto_transform = RNA_property_boolean_get(ptr, prop_other);
579 }
580 if ((prop_other = RNA_struct_find_property(ptr, "use_max_distance"))) {
581 use_max_distance = RNA_property_boolean_get(ptr, prop_other);
582 }
583 if ((prop_other = RNA_struct_find_property(ptr, "modifier"))) {
584 use_modifier = RNA_property_is_set(ptr, prop_other);
585 }
586
587 if (STREQ(prop_id, "modifier")) {
588 return use_modifier;
589 }
590
591 if (use_modifier) {
592 /* Hide everything but 'modifier' property, if set. */
593 return false;
594 }
595
596 if (STREQ(prop_id, "use_object_transform")) {
597 if (use_auto_transform) {
598 return false;
599 }
600 }
601 else if (STREQ(prop_id, "max_distance")) {
602 if (!use_max_distance) {
603 return false;
604 }
605 }
606 else if (STREQ(prop_id, "islands_precision")) {
607 if (!DT_DATATYPE_IS_LOOP(data_type)) {
608 return false;
609 }
610 }
611 else if (STREQ(prop_id, "vert_mapping")) {
612 if (!DT_DATATYPE_IS_VERT(data_type)) {
613 return false;
614 }
615 }
616 else if (STREQ(prop_id, "edge_mapping")) {
617 if (!DT_DATATYPE_IS_EDGE(data_type)) {
618 return false;
619 }
620 }
621 else if (STREQ(prop_id, "loop_mapping")) {
622 if (!DT_DATATYPE_IS_LOOP(data_type)) {
623 return false;
624 }
625 }
626 else if (STREQ(prop_id, "poly_mapping")) {
627 if (!DT_DATATYPE_IS_FACE(data_type)) {
628 return false;
629 }
630 }
631 else if (STR_ELEM(prop_id, "layers_select_src", "layers_select_dst")) {
632 if (!DT_DATATYPE_IS_MULTILAYERS(data_type)) {
633 return false;
634 }
635 }
636
637 /* Else, show it! */
638 return true;
639}
640
641static std::string data_transfer_get_description(bContext * /*C*/,
642 wmOperatorType * /*ot*/,
644{
645 const bool reverse_transfer = RNA_boolean_get(ptr, "use_reverse_transfer");
646
647 if (reverse_transfer) {
648 return TIP_(
649 "Transfer data layer(s) (weights, edge sharp, etc.) from selected meshes to active one");
650 }
651
652 return "";
653}
654
656{
657 PropertyRNA *prop;
658
659 /* Identifiers. */
660 ot->name = "Transfer Mesh Data";
661 ot->idname = "OBJECT_OT_data_transfer";
662 ot->description =
663 "Transfer data layer(s) (weights, edge sharp, etc.) from active to selected meshes";
664
665 /* API callbacks. */
666 ot->poll = data_transfer_poll;
667 ot->poll_property = data_transfer_poll_property;
668 ot->invoke = WM_menu_invoke;
669 ot->exec = data_transfer_exec;
670 ot->check = data_transfer_check;
671 ot->get_description = data_transfer_get_description;
672
673 /* Flags. */
675
676 /* Properties. */
677 prop = RNA_def_boolean(ot->srna,
678 "use_reverse_transfer",
679 false,
680 "Reverse Transfer",
681 "Transfer from selected objects to active one");
683
684 RNA_def_boolean(ot->srna,
685 "use_freeze",
686 false,
687 "Freeze Operator",
688 "Prevent changes to settings to re-run the operator, "
689 "handy to change several things at once with heavy geometry");
690
691 /* Data type to transfer. */
692 ot->prop = RNA_def_enum(
693 ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
694 RNA_def_boolean(ot->srna,
695 "use_create",
696 true,
697 "Create Data",
698 "Add data layers on destination meshes if needed");
699
700 /* Mapping methods. */
701 RNA_def_enum(ot->srna,
702 "vert_mapping",
705 "Vertex Mapping",
706 "Method used to map source vertices to destination ones");
707 RNA_def_enum(ot->srna,
708 "edge_mapping",
711 "Edge Mapping",
712 "Method used to map source edges to destination ones");
713 RNA_def_enum(ot->srna,
714 "loop_mapping",
717 "Face Corner Mapping",
718 "Method used to map source faces' corners to destination ones");
719 RNA_def_enum(ot->srna,
720 "poly_mapping",
723 "Face Mapping",
724 "Method used to map source faces to destination ones");
725
726 /* Mapping options and filtering. */
728 ot->srna,
729 "use_auto_transform",
730 false,
731 "Auto Transform",
732 "Automatically compute transformation to get the best possible match between source and "
733 "destination meshes.\n"
734 "Warning: Results will never be as good as manual matching of objects");
735 RNA_def_boolean(ot->srna,
736 "use_object_transform",
737 true,
738 "Object Transform",
739 "Evaluate source and destination meshes in global space");
740 RNA_def_boolean(ot->srna,
741 "use_max_distance",
742 false,
743 "Only Neighbor Geometry",
744 "Source elements must be closer than given distance from destination one");
745 prop = RNA_def_float(
746 ot->srna,
747 "max_distance",
748 1.0f,
749 0.0f,
750 FLT_MAX,
751 "Max Distance",
752 "Maximum allowed distance between source and destination element, for non-topology mappings",
753 0.0f,
754 100.0f);
756 prop = RNA_def_float(
757 ot->srna,
758 "ray_radius",
759 0.0f,
760 0.0f,
761 FLT_MAX,
762 "Ray Radius",
763 "'Width' of rays (especially useful when raycasting against vertices or edges)",
764 0.0f,
765 10.0f);
767 prop = RNA_def_float(
768 ot->srna,
769 "islands_precision",
770 0.1f,
771 0.0f,
772 10.0f,
773 "Islands Precision",
774 "Factor controlling precision of islands handling (the higher, the better the results)",
775 0.0f,
776 1.0f);
778
779 /* How to handle multi-layers types of data. */
780 prop = RNA_def_enum(ot->srna,
781 "layers_select_src",
784 "Source Layers Selection",
785 "Which layers to transfer, in case of multi-layers types");
787 prop, nullptr, nullptr, dt_layers_select_itemf, nullptr, nullptr);
788
789 prop = RNA_def_enum(ot->srna,
790 "layers_select_dst",
793 "Destination Layers Matching",
794 "How to match source and destination layers");
796 prop, nullptr, nullptr, dt_layers_select_itemf, nullptr, nullptr);
797
798 prop = RNA_def_enum(ot->srna,
799 "mix_mode",
802 "Mix Mode",
803 "How to affect destination elements with source values");
804 RNA_def_property_enum_funcs_runtime(prop, nullptr, nullptr, dt_mix_mode_itemf, nullptr, nullptr);
806 ot->srna,
807 "mix_factor",
808 1.0f,
809 0.0f,
810 1.0f,
811 "Mix Factor",
812 "Factor to use when applying data to destination (exact behavior depends on mix mode)",
813 0.0f,
814 1.0f);
815}
816
817/******************************************************************************/
818/* NOTE: This operator is hybrid, it can work as a usual standalone Object operator,
819 * or as a DataTransfer modifier tool.
820 */
821
823{
824 return (edit_modifier_poll_generic(C, &RNA_DataTransferModifier, (1 << OB_MESH), true, false) ||
826}
827
829{
830 Object *ob_act = context_active_object(C);
833
835 op, ob_act, eModifierType_DataTransfer);
836
837 /* If we have a modifier, we transfer data layout from this modifier's source object to
838 * active one. Else, we transfer data layout from active object to all selected ones. */
839 if (dtmd) {
840 Object *ob_src = dtmd->ob_source;
841 Object *ob_dst = ob_act;
842
843 const bool use_delete = false; /* Never when used from modifier, for now. */
844
845 if (!ob_src || !ID_IS_EDITABLE(ob_dst) || ID_IS_OVERRIDE_LIBRARY(ob_dst)) {
846 return OPERATOR_CANCELLED;
847 }
848
849 Object *ob_src_eval = DEG_get_evaluated(depsgraph, ob_src);
850
852 ob_src_eval,
853 ob_dst,
854 dtmd->data_types,
855 use_delete,
856 dtmd->layers_select_src,
857 dtmd->layers_select_dst);
858
860 }
861 else {
862 Object *ob_src = ob_act;
863
864 Vector<PointerRNA> ctx_objects;
865
866 const int data_type = RNA_enum_get(op->ptr, "data_type");
867 const bool use_delete = RNA_boolean_get(op->ptr, "use_delete");
868
869 const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
870 const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
871 int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
872 int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
873 const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
874
875 if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
876 layers_select_src[fromto_idx] = layers_src;
877 layers_select_dst[fromto_idx] = layers_dst;
878 }
879
880 Object *ob_src_eval = DEG_get_evaluated(depsgraph, ob_src);
881
882 data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, false);
883
884 for (const PointerRNA &ptr : ctx_objects) {
885 Object *ob_dst = static_cast<Object *>(ptr.data);
886 if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, false)) {
888 ob_src_eval,
889 ob_dst,
890 data_type,
891 use_delete,
892 layers_select_src,
893 layers_select_dst);
894 }
895
897 }
898 }
899
902
903 return OPERATOR_FINISHED;
904}
905
907 wmOperator *op,
908 const wmEvent *event)
909{
911 return datalayout_transfer_exec(C, op);
912 }
913 return WM_menu_invoke(C, op, event);
914}
915
917{
918 PropertyRNA *prop;
919
920 ot->name = "Transfer Mesh Data Layout";
921 ot->description = "Transfer layout of data layer(s) from active to selected meshes";
922 ot->idname = "OBJECT_OT_datalayout_transfer";
923
925 ot->poll_property = data_transfer_poll_property;
928 ot->check = data_transfer_check;
929
930 /* flags */
932
933 /* Properties. */
935
936 /* Data type to transfer. */
937 ot->prop = RNA_def_enum(
938 ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
939 RNA_def_boolean(ot->srna,
940 "use_delete",
941 false,
942 "Exact Match",
943 "Also delete some data layers from destination if necessary, so that it matches "
944 "exactly source");
945
946 /* How to handle multi-layers types of data. */
947 prop = RNA_def_enum(ot->srna,
948 "layers_select_src",
951 "Source Layers Selection",
952 "Which layers to transfer, in case of multi-layers types");
954 prop, nullptr, nullptr, dt_layers_select_src_itemf, nullptr, nullptr);
955
956 prop = RNA_def_enum(ot->srna,
957 "layers_select_dst",
960 "Destination Layers Matching",
961 "How to match source and destination layers");
963 prop, nullptr, nullptr, dt_layers_select_dst_itemf, nullptr, nullptr);
964}
965
966} // 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.
eCustomDataMask CD_TYPE_AS_MASK(eCustomDataType type)
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)
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:463
const ListBase * BKE_object_defgroup_list(const Object *ob)
Definition deform.cc:585
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
@ RPT_INFO
Definition BKE_report.hh:35
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
#define BLI_SPACE_TRANSFORM_SETUP(data, local, target)
#define STR_ELEM(...)
Definition BLI_string.h:661
#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_TAG_DOIT
Definition DNA_ID.h:1036
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:705
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:730
#define CD_MASK_PROP_BYTE_COLOR
#define CD_MASK_PROP_COLOR
@ CD_PROP_BYTE_COLOR
@ CD_PROP_COLOR
@ CD_PROP_FLOAT2
@ 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)
@ DT_LAYERS_ACTIVE_DST
@ DT_LAYERS_INDEX_DST
@ DT_LAYERS_NAME_DST
@ DT_MULTILAYER_INDEX_MAX
@ DT_MULTILAYER_INDEX_INVALID
#define DT_DATATYPE_IS_LOOP(_dt)
@ MREMAP_MODE_VERT_NEAREST
@ MREMAP_MODE_LOOP_NEAREST_POLYNOR
@ MREMAP_MODE_EDGE_NEAREST
@ MREMAP_MODE_POLY_NEAREST
#define DT_DATATYPE_IS_EDGE(_dt)
@ DT_TYPE_VCOL_ALL
@ DT_TYPE_MLOOPCOL_LOOP
@ DT_TYPE_UV
@ DT_TYPE_MPROPCOL_VERT
@ DT_TYPE_BWEIGHT_VERT
@ DT_TYPE_FREESTYLE_FACE
@ 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
#define DT_DATATYPE_IS_FACE(_dt)
@ 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_VERT(_dt)
@ eModifierType_DataTransfer
Object is a sort of wrapper for general info.
@ OB_MESH
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ PROP_SKIP_SAVE
Definition RNA_types.hh:344
@ PROP_HIDDEN
Definition RNA_types.hh:338
#define RNA_ENUM_ITEM_HEADING(name, description)
Definition RNA_types.hh:673
@ PROP_DISTANCE
Definition RNA_types.hh:256
@ PROP_FACTOR
Definition RNA_types.hh:251
#define C
Definition RandGen.cpp:29
#define ND_DRAW
Definition WM_types.hh:461
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define NC_OBJECT
Definition WM_types.hh:379
BMesh const char void * data
BPy_StructRNA * depsgraph
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)
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_def_property_enum_funcs_runtime(PropertyRNA *prop, EnumPropertyGetFunc getfunc, EnumPropertySetFunc setfunc, EnumPropertyItemFunc itemfunc, EnumPropertyGetTransformFunc get_transform_fn, EnumPropertySetTransformFunc set_transform_fn)
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:657
const char * name
Definition RNA_types.hh:661
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
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:4238
wmOperatorType * ot
Definition wm_files.cc:4237
wmOperatorStatus WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)