Blender V4.5
geometry_attributes.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2020 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "MEM_guardedalloc.h"
10
11#include "DNA_mesh_types.h"
12#include "DNA_meshdata_types.h"
14
15#include "BLI_color.hh"
16#include "BLI_listbase.h"
17
18#include "BKE_attribute.hh"
19#include "BKE_context.hh"
20#include "BKE_curves.hh"
21#include "BKE_customdata.hh"
22#include "BKE_deform.hh"
23#include "BKE_geometry_set.hh"
24#include "BKE_lib_id.hh"
25#include "BKE_mesh.hh"
26#include "BKE_object_deform.h"
27#include "BKE_paint.hh"
28#include "BKE_report.hh"
29
30#include "BLT_translation.hh"
31
32#include "RNA_access.hh"
33#include "RNA_define.hh"
34#include "RNA_enum_types.hh"
35
36#include "DEG_depsgraph.hh"
37
38#include "WM_api.hh"
39#include "WM_types.hh"
40
41#include "UI_interface.hh"
42#include "UI_resources.hh"
43
44#include "ED_geometry.hh"
45#include "ED_mesh.hh"
46#include "ED_object.hh"
47#include "ED_sculpt.hh"
48
49#include "geometry_intern.hh"
50
52
54{
55 switch (type) {
56 case CD_PROP_FLOAT:
57 return "value_float";
58 case CD_PROP_FLOAT2:
59 return "value_float_vector_2d";
60 case CD_PROP_FLOAT3:
61 return "value_float_vector_3d";
62 case CD_PROP_COLOR:
64 return "value_color";
65 case CD_PROP_BOOL:
66 return "value_bool";
67 case CD_PROP_INT8:
68 case CD_PROP_INT32:
69 return "value_int";
72 return "value_int_vector_2d";
73 default:
75 return "";
76 }
77}
78
83
85{
86 static blender::float4 color_default(1);
87
88 RNA_def_float(&srna, "value_float", 0.0f, -FLT_MAX, FLT_MAX, "Value", "", -FLT_MAX, FLT_MAX);
90 "value_float_vector_2d",
91 2,
92 nullptr,
93 -FLT_MAX,
94 FLT_MAX,
95 "Value",
96 "",
97 -FLT_MAX,
98 FLT_MAX);
100 "value_float_vector_3d",
101 3,
102 nullptr,
103 -FLT_MAX,
104 FLT_MAX,
105 "Value",
106 "",
107 -FLT_MAX,
108 FLT_MAX);
109 RNA_def_int(&srna, "value_int", 0, INT_MIN, INT_MAX, "Value", "", INT_MIN, INT_MAX);
111 &srna, "value_int_vector_2d", 2, nullptr, INT_MIN, INT_MAX, "Value", "", INT_MIN, INT_MAX);
113 &srna, "value_color", 4, color_default, -FLT_MAX, FLT_MAX, "Value", "", 0.0f, 1.0f);
114 RNA_def_boolean(&srna, "value_bool", false, "Value", "");
115}
116
118 const eCustomDataType type,
119 void *buffer)
120{
121 const StringRefNull prop_name = rna_property_name_for_type(type);
122 switch (type) {
123 case CD_PROP_FLOAT:
124 *static_cast<float *>(buffer) = RNA_float_get(&ptr, prop_name.c_str());
125 break;
126 case CD_PROP_FLOAT2:
127 RNA_float_get_array(&ptr, prop_name.c_str(), static_cast<float *>(buffer));
128 break;
129 case CD_PROP_FLOAT3:
130 RNA_float_get_array(&ptr, prop_name.c_str(), static_cast<float *>(buffer));
131 break;
132 case CD_PROP_COLOR:
133 RNA_float_get_array(&ptr, prop_name.c_str(), static_cast<float *>(buffer));
134 break;
135 case CD_PROP_BYTE_COLOR: {
136 ColorGeometry4f value;
137 RNA_float_get_array(&ptr, prop_name.c_str(), value);
138 *static_cast<ColorGeometry4b *>(buffer) = value.encode();
139 break;
140 }
141 case CD_PROP_BOOL:
142 *static_cast<bool *>(buffer) = RNA_boolean_get(&ptr, prop_name.c_str());
143 break;
144 case CD_PROP_INT8:
145 *static_cast<int8_t *>(buffer) = RNA_int_get(&ptr, prop_name.c_str());
146 break;
147 case CD_PROP_INT32:
148 *static_cast<int32_t *>(buffer) = RNA_int_get(&ptr, prop_name.c_str());
149 break;
150 case CD_PROP_INT16_2D: {
151 int2 value;
152 RNA_int_get_array(&ptr, prop_name.c_str(), value);
153 *static_cast<short2 *>(buffer) = short2(value);
154 break;
155 }
156 case CD_PROP_INT32_2D:
157 RNA_int_get_array(&ptr, prop_name.c_str(), static_cast<int *>(buffer));
158 break;
159 default:
161 return {};
162 }
163 return GPointer(bke::custom_data_type_to_cpp_type(type), buffer);
164}
165
167 PropertyRNA &prop,
168 const GPointer value)
169{
170 switch (bke::cpp_type_to_custom_data_type(*value.type())) {
171 case CD_PROP_FLOAT:
172 RNA_property_float_set(&ptr, &prop, *value.get<float>());
173 break;
174 case CD_PROP_FLOAT2:
175 RNA_property_float_set_array(&ptr, &prop, *value.get<float2>());
176 break;
177 case CD_PROP_FLOAT3:
178 RNA_property_float_set_array(&ptr, &prop, *value.get<float3>());
179 break;
181 RNA_property_float_set_array(&ptr, &prop, value.get<ColorGeometry4b>()->decode());
182 break;
183 case CD_PROP_COLOR:
185 break;
186 case CD_PROP_BOOL:
187 RNA_property_boolean_set(&ptr, &prop, *value.get<bool>());
188 break;
189 case CD_PROP_INT8:
190 RNA_property_int_set(&ptr, &prop, *value.get<int8_t>());
191 break;
192 case CD_PROP_INT32:
193 RNA_property_int_set(&ptr, &prop, *value.get<int32_t>());
194 break;
195 case CD_PROP_INT16_2D:
196 RNA_property_int_set_array(&ptr, &prop, int2(*value.get<short2>()));
197 break;
198 case CD_PROP_INT32_2D:
199 RNA_property_int_set_array(&ptr, &prop, *value.get<int2>());
200 break;
201 default:
203 }
204}
205
206bool attribute_set_poll(bContext &C, const ID &object_data)
207{
208 AttributeOwner owner = AttributeOwner::from_id(&const_cast<ID &>(object_data));
209 const std::optional<StringRef> name = BKE_attributes_active_name_get(owner);
210 if (!name) {
211 CTX_wm_operator_poll_msg_set(&C, "No active attribute");
212 return false;
213 }
217 CTX_wm_operator_poll_msg_set(&C, "The active attribute has an unsupported type");
218 return false;
219 }
220 return true;
221}
222
223/*********************** Attribute Operators ************************/
224
226{
227 using namespace blender::bke;
228 const Object *ob = object::context_object(C);
229 const Main *bmain = CTX_data_main(C);
230 if (!ob || !BKE_id_is_editable(bmain, &ob->id)) {
231 return false;
232 }
233 const ID *data = (ob) ? static_cast<const ID *>(ob->data) : nullptr;
234 if (!data || !BKE_id_is_editable(bmain, data)) {
235 return false;
236 }
237 return AttributeAccessor::from_id(*data).has_value();
238}
239
241{
243 return false;
244 }
245
247 ID *data = (ob) ? static_cast<ID *>(ob->data) : nullptr;
249 if (BKE_attributes_active_name_get(owner) != std::nullopt) {
250 return true;
251 }
252
253 return false;
254}
255
257 PointerRNA * /*ptr*/,
258 PropertyRNA * /*prop*/,
259 bool *r_free)
260{
261 if (C == nullptr) {
263 }
264
266 if (ob == nullptr) {
268 }
269
270 const AttributeOwner owner = AttributeOwner::from_id(static_cast<ID *>(ob->data));
271 return rna_enum_attribute_domain_itemf(owner, false, r_free);
272}
273
275{
277 ID *id = static_cast<ID *>(ob->data);
278
279 char name[MAX_NAME];
280 RNA_string_get(op->ptr, "name", name);
281 eCustomDataType type = eCustomDataType(RNA_enum_get(op->ptr, "data_type"));
282 bke::AttrDomain domain = bke::AttrDomain(RNA_enum_get(op->ptr, "domain"));
284 CustomDataLayer *layer = BKE_attribute_new(owner, name, type, domain, op->reports);
285
286 if (layer == nullptr) {
287 return OPERATOR_CANCELLED;
288 }
289
290 BKE_attributes_active_set(owner, layer->name);
291
294
295 return OPERATOR_FINISHED;
296}
297
299 wmOperator *op,
300 const wmEvent *event)
301{
302 PropertyRNA *prop;
303 prop = RNA_struct_find_property(op->ptr, "name");
304 if (!RNA_property_is_set(op->ptr, prop)) {
305 RNA_property_string_set(op->ptr, prop, DATA_("Attribute"));
306 }
307 /* Set a valid default domain, in case Point domain is not supported. */
308 prop = RNA_struct_find_property(op->ptr, "domain");
309 if (!RNA_property_is_set(op->ptr, prop)) {
310 EnumPropertyItem *items;
311 int totitems;
312 bool free;
314 C, op->ptr, prop, const_cast<const EnumPropertyItem **>(&items), &totitems, &free);
315 if (totitems > 0) {
316 RNA_property_enum_set(op->ptr, prop, items[0].value);
317 }
318 if (free) {
319 MEM_freeN(items);
320 }
321 }
323 C, op, event, IFACE_("Add Attribute"), CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add"));
324}
325
327{
328 /* identifiers */
329 ot->name = "Add Attribute";
330 ot->description = "Add attribute to geometry";
331 ot->idname = "GEOMETRY_OT_attribute_add";
332
333 /* API callbacks. */
337
338 /* flags */
340
341 /* properties */
342 PropertyRNA *prop;
343
344 /* The default name of the new attribute can be translated if new data translation is enabled,
345 * but since the user can choose it at invoke time, the translation happens in the invoke
346 * callback instead of here. */
347 prop = RNA_def_string(ot->srna, "name", nullptr, MAX_NAME, "Name", "Name of new attribute");
349
350 prop = RNA_def_enum(ot->srna,
351 "domain",
354 "Domain",
355 "Type of element that attribute is stored on");
358
359 prop = RNA_def_enum(ot->srna,
360 "data_type",
363 "Data Type",
364 "Type of data stored in attribute");
366}
367
369{
371 ID *id = static_cast<ID *>(ob->data);
373 const StringRef name = *BKE_attributes_active_name_get(owner);
374
375 if (!BKE_attribute_remove(owner, name, op->reports)) {
376 return OPERATOR_CANCELLED;
377 }
378
379 int *active_index = BKE_attributes_active_index_p(owner);
380 if (*active_index > 0) {
381 *active_index -= 1;
382 }
383
386
387 return OPERATOR_FINISHED;
388}
389
391{
392 /* identifiers */
393 ot->name = "Remove Attribute";
394 ot->description = "Remove attribute from geometry";
395 ot->idname = "GEOMETRY_OT_attribute_remove";
396
397 /* API callbacks. */
400
401 /* flags */
403}
404
406{
408 ID *id = static_cast<ID *>(ob->data);
409
410 char name[MAX_NAME];
411 RNA_string_get(op->ptr, "name", name);
412 eCustomDataType type = eCustomDataType(RNA_enum_get(op->ptr, "data_type"));
413 bke::AttrDomain domain = bke::AttrDomain(RNA_enum_get(op->ptr, "domain"));
415 CustomDataLayer *layer = BKE_attribute_new(owner, name, type, domain, op->reports);
416
417 float color[4];
418 RNA_float_get_array(op->ptr, "color", color);
419
420 if (layer == nullptr) {
421 return OPERATOR_CANCELLED;
422 }
423
425
428 }
429
431
434
435 return OPERATOR_FINISHED;
436}
437
439 wmOperator *op,
440 const wmEvent *event)
441{
442 PropertyRNA *prop;
443 prop = RNA_struct_find_property(op->ptr, "name");
444 if (!RNA_property_is_set(op->ptr, prop)) {
445 RNA_property_string_set(op->ptr, prop, DATA_("Color"));
446 }
448 op,
449 event,
450 IFACE_("Add Color Attribute"),
452}
453
458
460{
462 return false;
463 }
464
466 ID *data = static_cast<ID *>(ob->data);
468 if (ob->type == OB_MESH) {
469 if (CTX_data_edit_object(C) != nullptr) {
470 CTX_wm_operator_poll_msg_set(C, "Operation is not allowed in edit mode");
471 return false;
472 }
473 }
474 if (BKE_attributes_active_name_get(owner) == std::nullopt) {
475 return false;
476 }
477 return true;
478}
479
482 const StringRef name,
483 const bke::AttrDomain dst_domain,
484 const eCustomDataType dst_type,
486{
487 BLI_assert(attributes.contains(name));
488 if (ELEM(dst_type, CD_PROP_STRING)) {
489 if (reports) {
490 BKE_report(reports, RPT_ERROR, "Cannot convert to the selected type");
491 }
492 return false;
493 }
494
495 const bool was_active = BKE_attributes_active_name_get(owner) == name;
496
497 const std::string name_copy = name;
498 const GVArray varray = *attributes.lookup_or_default(name_copy, dst_domain, dst_type);
499
500 const CPPType &cpp_type = varray.type();
501 void *new_data = MEM_mallocN_aligned(
502 varray.size() * cpp_type.size, cpp_type.alignment, __func__);
503 varray.materialize_to_uninitialized(new_data);
504 attributes.remove(name_copy);
505 if (!attributes.add(name_copy, dst_domain, dst_type, bke::AttributeInitMoveArray(new_data))) {
506 MEM_freeN(new_data);
507 }
508
509 if (was_active) {
510 /* The attribute active status is stored as an index. Changing the attribute's domain will
511 * change its index, so reassign the active attribute if necessary.*/
512 BKE_attributes_active_set(owner, name_copy);
513 }
514
515 return true;
516}
517
519{
521 ID *ob_data = static_cast<ID *>(ob->data);
523 const std::string name = *BKE_attributes_active_name_get(owner);
524
525 if (ob->type == OB_MESH) {
527
528 Mesh *mesh = reinterpret_cast<Mesh *>(ob_data);
529 bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
530
531 switch (mode) {
533 if (!convert_attribute(owner,
534 attributes,
535 name,
536 bke::AttrDomain(RNA_enum_get(op->ptr, "domain")),
537 eCustomDataType(RNA_enum_get(op->ptr, "data_type")),
538 op->reports))
539 {
540 return OPERATOR_CANCELLED;
541 }
542 break;
543 }
545 Array<float> src_weights(mesh->verts_num);
546 VArray<float> src_varray = *attributes.lookup_or_default<float>(
547 name, bke::AttrDomain::Point, 0.0f);
548 src_varray.materialize(src_weights);
549 attributes.remove(name);
550
551 bDeformGroup *defgroup = BKE_object_defgroup_new(ob, name);
552 const int defgroup_index = BLI_findindex(BKE_id_defgroup_list_get(&mesh->id), defgroup);
554 for (const int i : IndexRange(mesh->verts_num)) {
555 const float weight = src_weights[i];
556 if (weight > 0.0f) {
557 BKE_defvert_add_index_notest(dverts + i, defgroup_index, weight);
558 }
559 }
561 int *active_index = BKE_attributes_active_index_p(owner);
562 if (*active_index > 0) {
563 *active_index -= 1;
564 }
565 break;
566 }
567 }
570 }
571 else if (ob->type == OB_CURVES) {
572 Curves *curves_id = static_cast<Curves *>(ob->data);
573 bke::CurvesGeometry &curves = curves_id->geometry.wrap();
574 if (!convert_attribute(owner,
575 curves.attributes_for_write(),
576 name,
577 bke::AttrDomain(RNA_enum_get(op->ptr, "domain")),
578 eCustomDataType(RNA_enum_get(op->ptr, "data_type")),
579 op->reports))
580 {
581 return OPERATOR_CANCELLED;
582 }
584 WM_main_add_notifier(NC_GEOM | ND_DATA, &curves_id->id);
585 }
586 else if (ob->type == OB_POINTCLOUD) {
587 PointCloud &pointcloud = *static_cast<PointCloud *>(ob->data);
588 if (!convert_attribute(owner,
589 pointcloud.attributes_for_write(),
590 name,
591 bke::AttrDomain(RNA_enum_get(op->ptr, "domain")),
592 eCustomDataType(RNA_enum_get(op->ptr, "data_type")),
593 op->reports))
594 {
595 return OPERATOR_CANCELLED;
596 }
599 }
600
601 BKE_attributes_active_set(owner, name);
602
603 return OPERATOR_FINISHED;
604}
605
607{
608 uiLayout *layout = op->layout;
609 uiLayoutSetPropSep(layout, true);
610 uiLayoutSetPropDecorate(layout, false);
611
612 layout->prop(op->ptr, "name", UI_ITEM_NONE, std::nullopt, ICON_NONE);
613 layout->prop(op->ptr, "domain", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
614 layout->prop(op->ptr, "data_type", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
615 layout->prop(op->ptr, "color", UI_ITEM_NONE, std::nullopt, ICON_NONE);
616}
617
619{
620 /* identifiers */
621 ot->name = "Add Color Attribute";
622 ot->description = "Add color attribute to geometry";
623 ot->idname = "GEOMETRY_OT_color_attribute_add";
624
625 /* API callbacks. */
630
631 /* flags */
633
634 /* properties */
635 PropertyRNA *prop;
636
637 /* The default name of the new attribute can be translated if new data translation is enabled,
638 * but since the user can choose it at invoke time, the translation happens in the invoke
639 * callback instead of here. */
640 prop = RNA_def_string(
641 ot->srna, "name", nullptr, MAX_NAME, "Name", "Name of new color attribute");
643
644 prop = RNA_def_enum(ot->srna,
645 "domain",
648 "Domain",
649 "Type of element that attribute is stored on");
650
651 prop = RNA_def_enum(ot->srna,
652 "data_type",
655 "Data Type",
656 "Type of data stored in attribute");
657
658 static float default_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
659
660 prop = RNA_def_float_color(
661 ot->srna, "color", 4, nullptr, 0.0f, FLT_MAX, "Color", "Default fill color", 0.0f, 1.0f);
663 RNA_def_property_float_array_default(prop, default_color);
664}
665
667{
669 ID *id = static_cast<ID *>(ob->data);
670
671 char name[MAX_NAME];
672 RNA_string_get(op->ptr, "name", name);
673
674 if (BKE_id_attributes_color_find(id, name)) {
676
679
680 return OPERATOR_FINISHED;
681 }
682
683 return OPERATOR_CANCELLED;
684}
685
687{
688 /* identifiers */
689 ot->name = "Set Render Color";
690 ot->description = "Set default color attribute used for rendering";
691 ot->idname = "GEOMETRY_OT_color_attribute_render_set";
692
693 /* API callbacks. */
696
697 /* flags */
699
700 /* properties */
701 PropertyRNA *prop;
702
703 prop = RNA_def_string(ot->srna, "name", "Color", MAX_NAME, "Name", "Name of color attribute");
705}
706
708{
710 ID *id = static_cast<ID *>(ob->data);
711 const std::string active_name = BKE_id_attributes_active_color_name(id).value_or("");
712 if (active_name.empty()) {
713 return OPERATOR_CANCELLED;
714 }
716 if (!BKE_attribute_remove(owner, active_name, op->reports)) {
717 return OPERATOR_CANCELLED;
718 }
719
722
723 return OPERATOR_FINISHED;
724}
725
727{
729 return false;
730 }
731
732 const Object *ob = object::context_object(C);
733 const ID *data = static_cast<ID *>(ob->data);
734
736 return true;
737 }
738
739 return false;
740}
741
743{
744 /* identifiers */
745 ot->name = "Remove Color Attribute";
746 ot->description = "Remove color attribute from geometry";
747 ot->idname = "GEOMETRY_OT_color_attribute_remove";
748
749 /* API callbacks. */
752
753 /* flags */
755}
756
758{
760 ID *id = static_cast<ID *>(ob->data);
761 const std::optional<StringRef> active_name = BKE_id_attributes_active_color_name(id);
762 if (!active_name) {
763 return OPERATOR_CANCELLED;
764 }
765
767 CustomDataLayer *new_layer = BKE_attribute_duplicate(owner, *active_name, op->reports);
768 if (new_layer == nullptr) {
769 return OPERATOR_CANCELLED;
770 }
771
773
776
777 return OPERATOR_FINISHED;
778}
779
781{
783 return false;
784 }
785 if (CTX_data_edit_object(C) != nullptr) {
786 CTX_wm_operator_poll_msg_set(C, "Operation is not allowed in edit mode");
787 return false;
788 }
789
790 const Object *ob = object::context_object(C);
791 const ID *data = static_cast<ID *>(ob->data);
792
794 return true;
795 }
796
797 return false;
798}
799
801{
802 /* identifiers */
803 ot->name = "Duplicate Color Attribute";
804 ot->description = "Duplicate color attribute";
805 ot->idname = "GEOMETRY_OT_color_attribute_duplicate";
806
807 /* API callbacks. */
810
811 /* flags */
813}
814
816 wmOperator *op,
817 const wmEvent * /*event*/)
818{
820 ID *id = static_cast<ID *>(ob->data);
823 const bke::AttributeMetaData meta_data = *accessor.lookup_meta_data(
825
826 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "domain");
827 if (!RNA_property_is_set(op->ptr, prop)) {
828 RNA_property_enum_set(op->ptr, prop, int(meta_data.domain));
829 }
830 prop = RNA_struct_find_property(op->ptr, "data_type");
831 if (!RNA_property_is_set(op->ptr, prop)) {
832 RNA_property_enum_set(op->ptr, prop, meta_data.data_type);
833 }
834
836 C, op, 300, IFACE_("Convert Attribute Domain"), IFACE_("Convert"));
837}
838
840{
841 uiLayout *layout = op->layout;
842 uiLayoutSetPropSep(layout, true);
843 uiLayoutSetPropDecorate(layout, false);
844
846 if (ob->type == OB_MESH) {
847 layout->prop(op->ptr, "mode", UI_ITEM_NONE, std::nullopt, ICON_NONE);
848 }
849
850 const ConvertAttributeMode mode = ob->type == OB_MESH ?
853
854 if (mode == ConvertAttributeMode::Generic) {
855 if (ob->type != OB_POINTCLOUD) {
856 layout->prop(op->ptr, "domain", UI_ITEM_NONE, std::nullopt, ICON_NONE);
857 }
858 layout->prop(op->ptr, "data_type", UI_ITEM_NONE, std::nullopt, ICON_NONE);
859 }
860}
861
863 {int(ConvertAttributeMode::Generic), "GENERIC", 0, "Generic", ""},
864 {int(ConvertAttributeMode::VertexGroup), "VERTEX_GROUP", 0, "Vertex Group", ""},
865 {0, nullptr, 0, nullptr, nullptr},
866};
867
869 PointerRNA * /*ptr*/,
870 PropertyRNA * /*prop*/,
871 bool *r_free)
872{
873 if (C == nullptr) {
875 }
876
878 if (ob == nullptr) {
880 }
881
882 if (ob->type == OB_MESH) {
883 *r_free = false;
885 }
886
887 EnumPropertyItem *items = nullptr;
888 int totitem = 0;
890 if (item.value == int(ConvertAttributeMode::Generic)) {
891 RNA_enum_item_add(&items, &totitem, &item);
892 }
893 }
894 RNA_enum_item_end(&items, &totitem);
895 *r_free = true;
896 return items;
897}
898
900{
902 return false;
903 }
904
905 if (CTX_data_edit_object(C) != nullptr) {
906 CTX_wm_operator_poll_msg_set(C, "Operation is not allowed in edit mode");
907 return false;
908 }
909
911 ID *id = static_cast<ID *>(ob->data);
912 if (GS(id->name) != ID_ME) {
913 return false;
914 }
915 const Mesh *mesh = static_cast<const Mesh *>(ob->data);
916 const char *name = mesh->active_color_attribute;
917 const bke::AttributeAccessor attributes = mesh->attributes();
918 const std::optional<bke::AttributeMetaData> meta_data = attributes.lookup_meta_data(name);
919 if (!meta_data) {
920 return false;
921 }
922 if (!(ATTR_DOMAIN_AS_MASK(meta_data->domain) & ATTR_DOMAIN_MASK_COLOR) ||
923 !(CD_TYPE_AS_MASK(meta_data->data_type) & CD_MASK_COLOR_ALL))
924 {
925 return false;
926 }
927
928 return true;
929}
930
932{
934 Mesh *mesh = static_cast<Mesh *>(ob->data);
936 convert_attribute(owner,
937 mesh->attributes_for_write(),
938 mesh->active_color_attribute,
939 bke::AttrDomain(RNA_enum_get(op->ptr, "domain")),
940 eCustomDataType(RNA_enum_get(op->ptr, "data_type")),
941 op->reports);
944 return OPERATOR_FINISHED;
945}
946
948 wmOperator *op,
949 const wmEvent * /*event*/)
950{
952 Mesh *mesh = static_cast<Mesh *>(ob->data);
953 const char *name = mesh->active_color_attribute;
954 const bke::AttributeMetaData meta_data = *mesh->attributes().lookup_meta_data(name);
955
956 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "domain");
957 if (!RNA_property_is_set(op->ptr, prop)) {
958 RNA_property_enum_set(op->ptr, prop, int(meta_data.domain));
959 }
960 prop = RNA_struct_find_property(op->ptr, "data_type");
961 if (!RNA_property_is_set(op->ptr, prop)) {
962 RNA_property_enum_set(op->ptr, prop, meta_data.data_type);
963 }
964
966 C, op, 300, IFACE_("Convert Color Attribute Domain"), IFACE_("Convert"));
967}
968
970{
971 uiLayout *layout = op->layout;
972 uiLayoutSetPropSep(layout, true);
973 uiLayoutSetPropDecorate(layout, false);
974
975 layout->prop(op->ptr, "domain", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
976 layout->prop(op->ptr, "data_type", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
977}
978
980{
981 ot->name = "Convert Color Attribute";
982 ot->description = "Change how the color attribute is stored";
983 ot->idname = "GEOMETRY_OT_color_attribute_convert";
984
989
991
992 PropertyRNA *prop;
993
994 prop = RNA_def_enum(ot->srna,
995 "domain",
998 "Domain",
999 "Type of element that attribute is stored on");
1001
1002 prop = RNA_def_enum(ot->srna,
1003 "data_type",
1006 "Data Type",
1007 "Type of data stored in attribute");
1009}
1010
1012{
1013 ot->name = "Convert Attribute";
1014 ot->description = "Change how the attribute is stored";
1015 ot->idname = "GEOMETRY_OT_attribute_convert";
1016
1021
1022 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1023
1024 PropertyRNA *prop;
1025
1026 prop = RNA_def_enum(ot->srna,
1027 "mode",
1030 "Mode",
1031 "");
1033
1034 prop = RNA_def_enum(ot->srna,
1035 "domain",
1038 "Domain",
1039 "Which geometry element to move the attribute to");
1041
1043 ot->srna, "data_type", rna_enum_attribute_type_items, CD_PROP_FLOAT, "Data Type", "");
1044}
1045
1046} // namespace blender::ed::geometry
void BKE_id_attributes_default_color_set(struct ID *id, std::optional< blender::StringRef > name)
struct CustomDataLayer * BKE_attribute_new(AttributeOwner &owner, blender::StringRef name, eCustomDataType type, blender::bke::AttrDomain domain, struct ReportList *reports)
Definition attribute.cc:391
std::optional< blender::StringRefNull > BKE_attributes_active_name_get(AttributeOwner &owner)
Definition attribute.cc:802
std::optional< blender::StringRef > BKE_id_attributes_default_color_name(const struct ID *id)
bool BKE_attribute_remove(AttributeOwner &owner, blender::StringRef name, struct ReportList *reports)
Definition attribute.cc:523
void BKE_attributes_active_set(AttributeOwner &owner, blender::StringRef name)
Definition attribute.cc:838
@ ATTR_DOMAIN_MASK_ALL
const struct CustomDataLayer * BKE_attribute_search(const AttributeOwner &owner, blender::StringRef name, eCustomDataMask type, AttrDomainMask domain_mask)
Definition attribute.cc:657
const struct CustomDataLayer * BKE_id_attributes_color_find(const struct ID *id, blender::StringRef name)
int * BKE_attributes_active_index_p(AttributeOwner &owner)
Definition attribute.cc:853
std::optional< blender::StringRef > BKE_id_attributes_active_color_name(const struct ID *id)
#define ATTR_DOMAIN_MASK_COLOR
#define ATTR_DOMAIN_AS_MASK(domain)
struct CustomDataLayer * BKE_attribute_duplicate(AttributeOwner &owner, blender::StringRef name, struct ReportList *reports)
Definition attribute.cc:455
void BKE_id_attributes_active_color_set(struct ID *id, std::optional< blender::StringRef > name)
Definition attribute.cc:986
void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
Object * CTX_data_edit_object(const bContext *C)
Main * CTX_data_main(const bContext *C)
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
#define CD_TYPE_AS_MASK(_type)
support for deformation groups and hooks.
bDeformGroup * BKE_object_defgroup_new(Object *ob, blender::StringRef name)
Definition deform.cc:46
void BKE_defvert_add_index_notest(MDeformVert *dv, int defgroup, float weight)
Definition deform.cc:845
const ListBase * BKE_id_defgroup_list_get(const ID *id)
Definition deform.cc:459
bool BKE_id_is_editable(const Main *bmain, const ID *id)
Definition lib_id.cc:2503
Functions for dealing with objects and deform verts, used by painting and tools.
struct MDeformVert * BKE_object_defgroup_data_create(struct ID *id)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
void BLI_kdtree_nd_ free(KDTree *tree)
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
#define ELEM(...)
#define CTX_IFACE_(context, msgid)
#define BLT_I18NCONTEXT_OPERATOR_DEFAULT
#define IFACE_(msgid)
#define DATA_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:982
@ ID_ME
@ CD_PROP_BYTE_COLOR
@ CD_PROP_FLOAT
@ CD_PROP_FLOAT3
@ CD_PROP_INT32_2D
@ CD_PROP_COLOR
@ CD_PROP_QUATERNION
@ CD_PROP_INT32
@ CD_PROP_FLOAT2
@ CD_PROP_INT16_2D
@ CD_PROP_STRING
@ CD_PROP_FLOAT4X4
@ OB_MESH
@ OB_POINTCLOUD
@ OB_CURVES
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
Read Guarded memory(de)allocation.
const EnumPropertyItem * rna_enum_attribute_domain_itemf(const AttributeOwner &owner, bool include_instances, bool *r_free)
@ PROP_SKIP_SAVE
Definition RNA_types.hh:330
@ PROP_COLOR
Definition RNA_types.hh:248
#define C
Definition RandGen.cpp:29
@ UI_ITEM_R_EXPAND
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
#define NC_GEOM
Definition WM_types.hh:390
#define ND_DATA
Definition WM_types.hh:506
@ OPTYPE_INTERNAL
Definition WM_types.hh:202
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
ReportList * reports
Definition WM_types.hh:1025
BMesh const char void * data
static AttributeOwner from_id(ID *id)
Definition attribute.cc:43
ColorSceneLinearByteEncoded4b< Alpha > encode() const
Definition BLI_color.hh:168
const CPPType * type() const
const void * get() const
void materialize_to_uninitialized(void *dst) const
constexpr const char * c_str() const
void materialize(MutableSpan< T > r_span) const
bool contains(StringRef attribute_id) const
static std::optional< AttributeAccessor > from_id(const ID &id)
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
std::optional< AttributeMetaData > lookup_meta_data(StringRef attribute_id) const
bool remove(const StringRef attribute_id)
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
#define CD_MASK_PROP_ALL
#define CD_MASK_COLOR_ALL
#define MAX_NAME
#define GS(a)
void * MEM_mallocN_aligned(size_t len, size_t alignment, const char *str)
Definition mallocn.cc:138
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
eCustomDataType cpp_type_to_custom_data_type(const CPPType &type)
const CPPType * custom_data_type_to_cpp_type(eCustomDataType type)
GPointer rna_property_for_attribute_type_retrieve_value(PointerRNA &ptr, const eCustomDataType type, void *buffer)
static bool geometry_attributes_poll(bContext *C)
void GEOMETRY_OT_attribute_add(wmOperatorType *ot)
static const EnumPropertyItem * geometry_attribute_domain_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
static wmOperatorStatus geometry_color_attribute_add_exec(bContext *C, wmOperator *op)
static wmOperatorStatus geometry_color_attribute_set_render_exec(bContext *C, wmOperator *op)
static EnumPropertyItem convert_attribute_mode_items[]
void GEOMETRY_OT_color_attribute_add(wmOperatorType *ot)
static wmOperatorStatus geometry_color_attribute_duplicate_exec(bContext *C, wmOperator *op)
StringRefNull rna_property_name_for_type(const eCustomDataType type)
void GEOMETRY_OT_attribute_convert(wmOperatorType *ot)
void GEOMETRY_OT_color_attribute_duplicate(wmOperatorType *ot)
static void geometry_attribute_convert_ui(bContext *C, wmOperator *op)
void GEOMETRY_OT_color_attribute_convert(wmOperatorType *ot)
static bool geometry_attributes_remove_poll(bContext *C)
static wmOperatorStatus geometry_color_attribute_remove_exec(bContext *C, wmOperator *op)
static void geometry_color_attribute_convert_ui(bContext *, wmOperator *op)
void register_rna_properties_for_attribute_types(StructRNA &srna)
void GEOMETRY_OT_attribute_remove(wmOperatorType *ot)
void GEOMETRY_OT_color_attribute_render_set(wmOperatorType *ot)
void rna_property_for_attribute_type_set_value(PointerRNA &ptr, PropertyRNA &prop, const GPointer value)
bool attribute_set_poll(bContext &C, const ID &object_data)
static bool geometry_color_attributes_remove_poll(bContext *C)
static bool geometry_attribute_convert_poll(bContext *C)
static const EnumPropertyItem * geometry_attribute_convert_mode_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
static void geometry_color_attribute_add_ui(bContext *, wmOperator *op)
static wmOperatorStatus geometry_color_attribute_convert_invoke(bContext *C, wmOperator *op, const wmEvent *)
PropertyRNA * rna_property_for_type(PointerRNA &ptr, const eCustomDataType type)
static bool geometry_color_attribute_convert_poll(bContext *C)
static wmOperatorStatus geometry_color_attribute_convert_exec(bContext *C, wmOperator *op)
static wmOperatorStatus geometry_attribute_remove_exec(bContext *C, wmOperator *op)
static bool geometry_color_attributes_duplicate_poll(bContext *C)
static wmOperatorStatus geometry_attribute_add_exec(bContext *C, wmOperator *op)
static wmOperatorStatus geometry_attribute_convert_invoke(bContext *C, wmOperator *op, const wmEvent *)
void GEOMETRY_OT_color_attribute_remove(wmOperatorType *ot)
bool convert_attribute(AttributeOwner &owner, bke::MutableAttributeAccessor attributes, const StringRef name, const bke::AttrDomain dst_domain, const eCustomDataType dst_type, ReportList *reports)
static wmOperatorStatus geometry_attribute_convert_exec(bContext *C, wmOperator *op)
static wmOperatorStatus geometry_color_attribute_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static wmOperatorStatus geometry_attribute_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Object * context_object(const bContext *C)
bool object_active_color_fill(Object &ob, const float fill_color[4], bool only_selected)
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition BLI_color.hh:342
VecBase< float, 3 > float3
blender::VecBase< int16_t, 2 > short2
ColorSceneLinearByteEncoded4b< eAlpha::Premultiplied > ColorGeometry4b
Definition BLI_color.hh:343
void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
void RNA_int_get_array(PointerRNA *ptr, const char *name, int *values)
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)
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
int RNA_int_get(PointerRNA *ptr, const char *name)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
float RNA_float_get(PointerRNA *ptr, const char *name)
void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void RNA_property_enum_items(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
int RNA_enum_get(PointerRNA *ptr, const char *name)
void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
const EnumPropertyItem rna_enum_color_attribute_domain_items[]
const EnumPropertyItem rna_enum_attribute_domain_items[]
const EnumPropertyItem rna_enum_attribute_type_items[]
const EnumPropertyItem rna_enum_color_attribute_type_items[]
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_int_array(StructOrFunctionRNA *cont_, const char *identifier, const int len, const int *default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
PropertyRNA * RNA_def_float_color(StructOrFunctionRNA *cont_, const char *identifier, const int len, 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_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_enum_item_end(EnumPropertyItem **items, int *totitem)
PropertyRNA * RNA_def_float_array(StructOrFunctionRNA *cont_, const char *identifier, const int len, 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_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_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
void RNA_def_property_subtype(PropertyRNA *prop, PropertySubType subtype)
void RNA_def_property_float_array_default(PropertyRNA *prop, const float *array)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
const EnumPropertyItem rna_enum_dummy_NULL_items[]
Definition rna_rna.cc:26
#define FLT_MAX
Definition stdcycles.h:14
CurvesGeometry geometry
Definition DNA_ID.h:404
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
struct ReportList * reports
struct uiLayout * layout
struct PointerRNA * ptr
i
Definition text_draw.cc:230
void WM_main_add_notifier(uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4226
wmOperatorType * ot
Definition wm_files.cc:4225
wmOperatorStatus WM_operator_props_popup_confirm_ex(bContext *C, wmOperator *op, const wmEvent *, std::optional< std::string > title, std::optional< std::string > confirm_text, const bool cancel_default)
wmOperatorStatus WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, std::optional< std::string > title, std::optional< std::string > confirm_text, const bool cancel_default)