Blender V4.3
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
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_mesh_mapping.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 int types[2] = {CD_PROP_COLOR, CD_PROP_BYTE_COLOR};
106 int idx = 0;
107 for (int i = 0; i < 2; i++) {
108 eCustomDataType type = eCustomDataType(types[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_object(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_object(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);
374 if (!ID_IS_EDITABLE(mesh) || ID_IS_OVERRIDE_LIBRARY(mesh)) {
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 }
409 if (ID_IS_EDITABLE(mesh) && !ID_IS_OVERRIDE_LIBRARY(mesh)) {
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 for (const PointerRNA &ptr : ctx_objects) {
490 Object *ob_dst = static_cast<Object *>(ptr.data);
491
492 if (reverse_transfer) {
493 std::swap(ob_src, ob_dst);
494 }
495
496 if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, reverse_transfer)) {
497 Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
498
499 if (space_transform) {
500 Object *ob_dst_eval = DEG_get_evaluated_object(depsgraph, ob_dst);
501 BLI_SPACE_TRANSFORM_SETUP(space_transform, ob_dst_eval, ob_src_eval);
502 }
503
505 ob_src_eval,
506 ob_dst,
507 data_type,
508 use_create,
509 map_vert_mode,
510 map_edge_mode,
511 map_loop_mode,
512 map_poly_mode,
513 space_transform,
514 use_auto_transform,
515 max_distance,
516 ray_radius,
517 islands_precision,
518 layers_select_src,
519 layers_select_dst,
520 mix_mode,
521 mix_factor,
522 nullptr,
523 false,
524 op->reports))
525 {
527 changed = true;
528 }
529 }
530
531 if (reverse_transfer) {
532 std::swap(ob_src, ob_dst);
533 }
534 }
535
536 if (changed) {
539 }
540
541#if 0 /* TODO */
542 /* NOTE: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */
543 return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
544#else
545 return OPERATOR_FINISHED;
546#endif
547}
548
549/* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */
550/* Note this context poll is only really partial,
551 * it cannot check for all possible invalid cases. */
553{
555 ID *data = static_cast<ID *>((ob) ? ob->data : nullptr);
556 return (ob != nullptr && ob->type == OB_MESH && data != nullptr);
557}
558
559/* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */
560static bool data_transfer_poll_property(const bContext * /*C*/,
561 wmOperator *op,
562 const PropertyRNA *prop)
563{
564 PointerRNA *ptr = op->ptr;
565 PropertyRNA *prop_other;
566
567 const char *prop_id = RNA_property_identifier(prop);
568 const int data_type = RNA_enum_get(ptr, "data_type");
569 bool use_auto_transform = false;
570 bool use_max_distance = false;
571 bool use_modifier = false;
572
573 if ((prop_other = RNA_struct_find_property(ptr, "use_auto_transform"))) {
574 use_auto_transform = RNA_property_boolean_get(ptr, prop_other);
575 }
576 if ((prop_other = RNA_struct_find_property(ptr, "use_max_distance"))) {
577 use_max_distance = RNA_property_boolean_get(ptr, prop_other);
578 }
579 if ((prop_other = RNA_struct_find_property(ptr, "modifier"))) {
580 use_modifier = RNA_property_is_set(ptr, prop_other);
581 }
582
583 if (STREQ(prop_id, "modifier")) {
584 return use_modifier;
585 }
586
587 if (use_modifier) {
588 /* Hide everything but 'modifier' property, if set. */
589 return false;
590 }
591
592 if (STREQ(prop_id, "use_object_transform")) {
593 if (use_auto_transform) {
594 return false;
595 }
596 }
597 else if (STREQ(prop_id, "max_distance")) {
598 if (!use_max_distance) {
599 return false;
600 }
601 }
602 else if (STREQ(prop_id, "islands_precision")) {
603 if (!DT_DATATYPE_IS_LOOP(data_type)) {
604 return false;
605 }
606 }
607 else if (STREQ(prop_id, "vert_mapping")) {
608 if (!DT_DATATYPE_IS_VERT(data_type)) {
609 return false;
610 }
611 }
612 else if (STREQ(prop_id, "edge_mapping")) {
613 if (!DT_DATATYPE_IS_EDGE(data_type)) {
614 return false;
615 }
616 }
617 else if (STREQ(prop_id, "loop_mapping")) {
618 if (!DT_DATATYPE_IS_LOOP(data_type)) {
619 return false;
620 }
621 }
622 else if (STREQ(prop_id, "poly_mapping")) {
623 if (!DT_DATATYPE_IS_FACE(data_type)) {
624 return false;
625 }
626 }
627 else if (STR_ELEM(prop_id, "layers_select_src", "layers_select_dst")) {
628 if (!DT_DATATYPE_IS_MULTILAYERS(data_type)) {
629 return false;
630 }
631 }
632
633 /* Else, show it! */
634 return true;
635}
636
637static std::string data_transfer_get_description(bContext * /*C*/,
638 wmOperatorType * /*ot*/,
640{
641 const bool reverse_transfer = RNA_boolean_get(ptr, "use_reverse_transfer");
642
643 if (reverse_transfer) {
644 return TIP_(
645 "Transfer data layer(s) (weights, edge sharp, etc.) from selected meshes to active one");
646 }
647
648 return "";
649}
650
652{
653 PropertyRNA *prop;
654
655 /* Identifiers. */
656 ot->name = "Transfer Mesh Data";
657 ot->idname = "OBJECT_OT_data_transfer";
658 ot->description =
659 "Transfer data layer(s) (weights, edge sharp, etc.) from active to selected meshes";
660
661 /* API callbacks. */
668
669 /* Flags. */
671
672 /* Properties. */
673 prop = RNA_def_boolean(ot->srna,
674 "use_reverse_transfer",
675 false,
676 "Reverse Transfer",
677 "Transfer from selected objects to active one");
679
681 "use_freeze",
682 false,
683 "Freeze Operator",
684 "Prevent changes to settings to re-run the operator, "
685 "handy to change several things at once with heavy geometry");
686
687 /* Data type to transfer. */
689 ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
691 "use_create",
692 true,
693 "Create Data",
694 "Add data layers on destination meshes if needed");
695
696 /* Mapping methods. */
698 "vert_mapping",
701 "Vertex Mapping",
702 "Method used to map source vertices to destination ones");
704 "edge_mapping",
707 "Edge Mapping",
708 "Method used to map source edges to destination ones");
710 "loop_mapping",
713 "Face Corner Mapping",
714 "Method used to map source faces' corners to destination ones");
716 "poly_mapping",
719 "Face Mapping",
720 "Method used to map source faces to destination ones");
721
722 /* Mapping options and filtering. */
724 ot->srna,
725 "use_auto_transform",
726 false,
727 "Auto Transform",
728 "Automatically compute transformation to get the best possible match between source and "
729 "destination meshes.\n"
730 "Warning: Results will never be as good as manual matching of objects");
732 "use_object_transform",
733 true,
734 "Object Transform",
735 "Evaluate source and destination meshes in global space");
737 "use_max_distance",
738 false,
739 "Only Neighbor Geometry",
740 "Source elements must be closer than given distance from destination one");
741 prop = RNA_def_float(
742 ot->srna,
743 "max_distance",
744 1.0f,
745 0.0f,
746 FLT_MAX,
747 "Max Distance",
748 "Maximum allowed distance between source and destination element, for non-topology mappings",
749 0.0f,
750 100.0f);
752 prop = RNA_def_float(
753 ot->srna,
754 "ray_radius",
755 0.0f,
756 0.0f,
757 FLT_MAX,
758 "Ray Radius",
759 "'Width' of rays (especially useful when raycasting against vertices or edges)",
760 0.0f,
761 10.0f);
763 prop = RNA_def_float(
764 ot->srna,
765 "islands_precision",
766 0.1f,
767 0.0f,
768 10.0f,
769 "Islands Precision",
770 "Factor controlling precision of islands handling (the higher, the better the results)",
771 0.0f,
772 1.0f);
774
775 /* How to handle multi-layers types of data. */
776 prop = RNA_def_enum(ot->srna,
777 "layers_select_src",
780 "Source Layers Selection",
781 "Which layers to transfer, in case of multi-layers types");
783
784 prop = RNA_def_enum(ot->srna,
785 "layers_select_dst",
788 "Destination Layers Matching",
789 "How to match source and destination layers");
791
792 prop = RNA_def_enum(ot->srna,
793 "mix_mode",
796 "Mix Mode",
797 "How to affect destination elements with source values");
800 ot->srna,
801 "mix_factor",
802 1.0f,
803 0.0f,
804 1.0f,
805 "Mix Factor",
806 "Factor to use when applying data to destination (exact behavior depends on mix mode)",
807 0.0f,
808 1.0f);
809}
810
811/******************************************************************************/
812/* NOTE: This operator is hybrid, it can work as a usual standalone Object operator,
813 * or as a DataTransfer modifier tool.
814 */
815
817{
818 return (edit_modifier_poll_generic(C, &RNA_DataTransferModifier, (1 << OB_MESH), true, false) ||
820}
821
823{
824 Object *ob_act = context_active_object(C);
827
829 op, ob_act, eModifierType_DataTransfer);
830
831 /* If we have a modifier, we transfer data layout from this modifier's source object to
832 * active one. Else, we transfer data layout from active object to all selected ones. */
833 if (dtmd) {
834 Object *ob_src = dtmd->ob_source;
835 Object *ob_dst = ob_act;
836
837 const bool use_delete = false; /* Never when used from modifier, for now. */
838
839 if (!ob_src || !ID_IS_EDITABLE(ob_dst) || ID_IS_OVERRIDE_LIBRARY(ob_dst)) {
840 return OPERATOR_CANCELLED;
841 }
842
843 Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
844
846 ob_src_eval,
847 ob_dst,
848 dtmd->data_types,
849 use_delete,
850 dtmd->layers_select_src,
851 dtmd->layers_select_dst);
852
854 }
855 else {
856 Object *ob_src = ob_act;
857
858 Vector<PointerRNA> ctx_objects;
859
860 const int data_type = RNA_enum_get(op->ptr, "data_type");
861 const bool use_delete = RNA_boolean_get(op->ptr, "use_delete");
862
863 const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
864 const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
865 int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
866 int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
867 const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
868
869 if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
870 layers_select_src[fromto_idx] = layers_src;
871 layers_select_dst[fromto_idx] = layers_dst;
872 }
873
874 Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
875
876 data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, false);
877
878 for (const PointerRNA &ptr : ctx_objects) {
879 Object *ob_dst = static_cast<Object *>(ptr.data);
880 if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, false)) {
882 ob_src_eval,
883 ob_dst,
884 data_type,
885 use_delete,
886 layers_select_src,
887 layers_select_dst);
888 }
889
891 }
892 }
893
896
897 return OPERATOR_FINISHED;
898}
899
900static int datalayout_transfer_invoke(bContext *C, wmOperator *op, const wmEvent *event)
901{
903 return datalayout_transfer_exec(C, op);
904 }
905 return WM_menu_invoke(C, op, event);
906}
907
909{
910 PropertyRNA *prop;
911
912 ot->name = "Transfer Mesh Data Layout";
913 ot->description = "Transfer layout of data layer(s) from active to selected meshes";
914 ot->idname = "OBJECT_OT_datalayout_transfer";
915
921
922 /* flags */
924
925 /* Properties. */
927
928 /* Data type to transfer. */
930 ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
932 "use_delete",
933 false,
934 "Exact Match",
935 "Also delete some data layers from destination if necessary, so that it matches "
936 "exactly source");
937
938 /* How to handle multi-layers types of data. */
939 prop = RNA_def_enum(ot->srna,
940 "layers_select_src",
943 "Source Layers Selection",
944 "Which layers to transfer, in case of multi-layers types");
946
947 prop = RNA_def_enum(ot->srna,
948 "layers_select_dst",
951 "Destination Layers Matching",
952 "How to match source and destination layers");
954}
955
956} // 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.
@ 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
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)
#define DT_DATATYPE_IS_MULTILAYERS(_dt)
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])
@ DT_LAYERS_ACTIVE_DST
@ DT_LAYERS_INDEX_DST
@ DT_LAYERS_NAME_DST
#define DT_DATATYPE_IS_LOOP(_dt)
@ DT_LAYERS_VGROUP_SRC_BONE_SELECT
@ DT_LAYERS_VGROUP_SRC_BONE_DEFORM
@ DT_LAYERS_ALL_SRC
@ DT_LAYERS_ACTIVE_SRC
#define DT_DATATYPE_IS_EDGE(_dt)
bool BKE_object_data_transfer_get_dttypes_capacity(int dtdata_types, bool *r_advanced_mixing, bool *r_threshold)
@ DT_MULTILAYER_INDEX_MAX
@ DT_MULTILAYER_INDEX_INVALID
#define DT_DATATYPE_IS_FACE(_dt)
@ 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
#define DT_DATATYPE_IS_VERT(_dt)
support for deformation groups and hooks.
bool BKE_object_supports_vertex_groups(const Object *ob)
Definition deform.cc:457
const ListBase * BKE_object_defgroup_list(const Object *ob)
Definition deform.cc:579
@ MREMAP_MODE_VERT_NEAREST
@ MREMAP_MODE_LOOP_NEAREST_POLYNOR
@ MREMAP_MODE_EDGE_NEAREST
@ MREMAP_MODE_POLY_NEAREST
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:125
#define BLI_SPACE_TRANSFORM_SETUP(data, local, target)
#define STR_ELEM(...)
Definition BLI_string.h:653
#define STREQ(a, b)
#define TIP_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:658
@ ID_TAG_DOIT
Definition DNA_ID.h:1003
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:683
#define CD_MASK_PROP_BYTE_COLOR
#define CD_MASK_PROP_COLOR
@ CD_PROP_BYTE_COLOR
@ CD_PROP_COLOR
@ CD_PROP_FLOAT2
@ eModifierType_DataTransfer
Object is a sort of wrapper for general info.
@ OB_MESH
@ PROP_SKIP_SAVE
Definition RNA_types.hh:245
@ PROP_HIDDEN
Definition RNA_types.hh:239
#define RNA_ENUM_ITEM_HEADING(name, description)
Definition RNA_types.hh:522
@ PROP_DISTANCE
Definition RNA_types.hh:159
@ PROP_FACTOR
Definition RNA_types.hh:154
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define ND_DRAW
Definition WM_types.hh:428
#define NC_OBJECT
Definition WM_types.hh:346
const Depsgraph * depsgraph
static const EnumPropertyItem * dt_layers_select_src_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *, bool *r_free)
static int data_transfer_exec(bContext *C, wmOperator *op)
bool edit_modifier_invoke_properties(bContext *C, wmOperator *op)
void OBJECT_OT_data_transfer(wmOperatorType *ot)
static int datalayout_transfer_exec(bContext *C, wmOperator *op)
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)
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 int datalayout_transfer_invoke(bContext *C, wmOperator *op, const wmEvent *event)
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:506
const char * name
Definition RNA_types.hh:510
Definition DNA_ID.h:413
int tag
Definition DNA_ID.h:434
char name[66]
Definition DNA_ID.h:425
void * first
CustomData corner_data
CustomData vert_data
void * data
Definition RNA_types.hh:42
struct bDeformGroup * next
const char * name
Definition WM_types.hh:990
bool(* poll_property)(const bContext *C, wmOperator *op, const PropertyRNA *prop) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1048
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
std::string(* get_description)(bContext *C, wmOperatorType *ot, PointerRNA *ptr)
Definition WM_types.hh:1074
const char * idname
Definition WM_types.hh:992
bool(* check)(bContext *C, wmOperator *op)
Definition WM_types.hh:1014
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
PropertyRNA * prop
Definition WM_types.hh:1092
StructRNA * srna
Definition WM_types.hh:1080
struct ReportList * reports
struct PointerRNA * ptr
#define N_(msgid)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4126
wmOperatorType * ot
Definition wm_files.cc:4125
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)