Blender V5.0
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"
20#include "BKE_context.hh"
21#include "BKE_curves.hh"
22#include "BKE_customdata.hh"
23#include "BKE_deform.hh"
24#include "BKE_geometry_set.hh"
25#include "BKE_lib_id.hh"
26#include "BKE_mesh.hh"
27#include "BKE_object_deform.h"
28#include "BKE_paint.hh"
29#include "BKE_report.hh"
30
31#include "BLT_translation.hh"
32
33#include "RNA_access.hh"
34#include "RNA_define.hh"
35#include "RNA_enum_types.hh"
36
37#include "DEG_depsgraph.hh"
38
39#include "WM_api.hh"
40#include "WM_types.hh"
41
43#include "UI_resources.hh"
44
45#include "ED_geometry.hh"
46#include "ED_mesh.hh"
47#include "ED_object.hh"
48#include "ED_sculpt.hh"
49
50#include "geometry_intern.hh"
51
53
55{
56 switch (type) {
58 return "value_float";
60 return "value_float_vector_2d";
62 return "value_float_vector_3d";
65 return "value_color";
67 return "value_bool";
70 return "value_int";
73 return "value_int_vector_2d";
74 default:
76 return "";
77 }
78}
79
84
86{
87 static blender::float4 color_default(1);
88
89 RNA_def_float(&srna, "value_float", 0.0f, -FLT_MAX, FLT_MAX, "Value", "", -FLT_MAX, FLT_MAX);
91 "value_float_vector_2d",
92 2,
93 nullptr,
94 -FLT_MAX,
95 FLT_MAX,
96 "Value",
97 "",
98 -FLT_MAX,
99 FLT_MAX);
101 "value_float_vector_3d",
102 3,
103 nullptr,
104 -FLT_MAX,
105 FLT_MAX,
106 "Value",
107 "",
108 -FLT_MAX,
109 FLT_MAX);
110 RNA_def_int(&srna, "value_int", 0, INT_MIN, INT_MAX, "Value", "", INT_MIN, INT_MAX);
112 &srna, "value_int_vector_2d", 2, nullptr, INT_MIN, INT_MAX, "Value", "", INT_MIN, INT_MAX);
114 &srna, "value_color", 4, color_default, -FLT_MAX, FLT_MAX, "Value", "", 0.0f, 1.0f);
115 RNA_def_boolean(&srna, "value_bool", false, "Value", "");
116}
117
119 const bke::AttrType type,
120 void *buffer)
121{
122 const StringRefNull prop_name = rna_property_name_for_type(type);
123 switch (type) {
125 *static_cast<float *>(buffer) = RNA_float_get(&ptr, prop_name.c_str());
126 break;
128 RNA_float_get_array(&ptr, prop_name.c_str(), static_cast<float *>(buffer));
129 break;
131 RNA_float_get_array(&ptr, prop_name.c_str(), static_cast<float *>(buffer));
132 break;
134 RNA_float_get_array(&ptr, prop_name.c_str(), static_cast<float *>(buffer));
135 break;
137 ColorGeometry4f value;
138 RNA_float_get_array(&ptr, prop_name.c_str(), value);
139 *static_cast<ColorGeometry4b *>(buffer) = color::encode(value);
140 break;
141 }
143 *static_cast<bool *>(buffer) = RNA_boolean_get(&ptr, prop_name.c_str());
144 break;
146 *static_cast<int8_t *>(buffer) = RNA_int_get(&ptr, prop_name.c_str());
147 break;
149 *static_cast<int32_t *>(buffer) = RNA_int_get(&ptr, prop_name.c_str());
150 break;
152 int2 value;
153 RNA_int_get_array(&ptr, prop_name.c_str(), value);
154 *static_cast<short2 *>(buffer) = short2(value);
155 break;
156 }
158 RNA_int_get_array(&ptr, prop_name.c_str(), static_cast<int *>(buffer));
159 break;
160 default:
162 return {};
163 }
164 return GPointer(bke::attribute_type_to_cpp_type(type), buffer);
165}
166
168 PropertyRNA &prop,
169 const GPointer value)
170{
171 switch (bke::cpp_type_to_attribute_type(*value.type())) {
173 RNA_property_float_set(&ptr, &prop, *value.get<float>());
174 break;
176 RNA_property_float_set_array(&ptr, &prop, *value.get<float2>());
177 break;
179 RNA_property_float_set_array(&ptr, &prop, *value.get<float3>());
180 break;
183 break;
186 break;
188 RNA_property_boolean_set(&ptr, &prop, *value.get<bool>());
189 break;
191 RNA_property_int_set(&ptr, &prop, *value.get<int8_t>());
192 break;
194 RNA_property_int_set(&ptr, &prop, *value.get<int32_t>());
195 break;
197 RNA_property_int_set_array(&ptr, &prop, int2(*value.get<short2>()));
198 break;
200 RNA_property_int_set_array(&ptr, &prop, *value.get<int2>());
201 break;
202 default:
204 }
205}
206
207bool attribute_set_poll(bContext &C, const ID &object_data)
208{
209 AttributeOwner owner = AttributeOwner::from_id(&const_cast<ID &>(object_data));
210 const std::optional<StringRef> name = BKE_attributes_active_name_get(owner);
211 if (!name) {
212 CTX_wm_operator_poll_msg_set(&C, "No active attribute");
213 return false;
214 }
215
216 if (owner.type() != AttributeOwnerType::Mesh) {
217 bke::AttributeAccessor attributes = *owner.get_accessor();
218 std::optional<bke::AttributeMetaData> meta_data = attributes.lookup_meta_data(*name);
219 if (!meta_data) {
220 CTX_wm_operator_poll_msg_set(&C, "No active attribute");
221 return false;
222 }
223 if (ELEM(meta_data->data_type,
227 {
228 CTX_wm_operator_poll_msg_set(&C, "The active attribute has an unsupported type");
229 return false;
230 }
231 return true;
232 }
233
237 CTX_wm_operator_poll_msg_set(&C, "The active attribute has an unsupported type");
238 return false;
239 }
240 return true;
241}
242
243/*********************** Attribute Operators ************************/
244
246{
247 using namespace blender::bke;
248 const Object *ob = object::context_object(C);
249 const Main *bmain = CTX_data_main(C);
250 if (!ob || !BKE_id_is_editable(bmain, &ob->id)) {
251 return false;
252 }
253 const ID *data = (ob) ? static_cast<const ID *>(ob->data) : nullptr;
254 if (!data || !BKE_id_is_editable(bmain, data)) {
255 return false;
256 }
257 return AttributeAccessor::from_id(*data).has_value();
258}
259
261{
263 return false;
264 }
265
267 ID *data = (ob) ? static_cast<ID *>(ob->data) : nullptr;
269 if (BKE_attributes_active_name_get(owner) != std::nullopt) {
270 return true;
271 }
272
273 return false;
274}
275
277 PointerRNA * /*ptr*/,
278 PropertyRNA * /*prop*/,
279 bool *r_free)
280{
281 if (C == nullptr) {
283 }
284
286 if (ob == nullptr) {
288 }
289
290 const AttributeOwner owner = AttributeOwner::from_id(static_cast<ID *>(ob->data));
291 return rna_enum_attribute_domain_itemf(owner, false, r_free);
292}
293
295{
297 ID *id = static_cast<ID *>(ob->data);
298
299 char name[MAX_NAME];
300 RNA_string_get(op->ptr, "name", name);
301 eCustomDataType type = eCustomDataType(RNA_enum_get(op->ptr, "data_type"));
302 bke::AttrDomain domain = bke::AttrDomain(RNA_enum_get(op->ptr, "domain"));
304
305 if (owner.type() != AttributeOwnerType::Mesh) {
307 if (!accessor.domain_supported(bke::AttrDomain(domain))) {
308 BKE_report(op->reports, RPT_ERROR, "Attribute domain not supported by this geometry type");
309 return OPERATOR_CANCELLED;
310 }
311 bke::AttributeStorage &attributes = *owner.get_storage();
312 const int domain_size = accessor.domain_size(bke::AttrDomain(domain));
313
314 const CPPType &cpp_type = *bke::custom_data_type_to_cpp_type(type);
315 bke::Attribute &attr = attributes.add(
316 attributes.unique_name_calc(name),
317 bke::AttrDomain(domain),
319 bke::Attribute::ArrayData::from_default_value(cpp_type, domain_size));
320
321 BKE_attributes_active_set(owner, attr.name());
322
325
326 return OPERATOR_FINISHED;
327 }
328
329 CustomDataLayer *layer = BKE_attribute_new(owner, name, type, domain, op->reports);
330
331 if (layer == nullptr) {
332 return OPERATOR_CANCELLED;
333 }
334
335 BKE_attributes_active_set(owner, layer->name);
336
339
340 return OPERATOR_FINISHED;
341}
342
344 wmOperator *op,
345 const wmEvent *event)
346{
347 PropertyRNA *prop;
348 prop = RNA_struct_find_property(op->ptr, "name");
349 if (!RNA_property_is_set(op->ptr, prop)) {
350 RNA_property_string_set(op->ptr, prop, DATA_("Attribute"));
351 }
352 /* Set a valid default domain, in case Point domain is not supported. */
353 prop = RNA_struct_find_property(op->ptr, "domain");
354 if (!RNA_property_is_set(op->ptr, prop)) {
355 EnumPropertyItem *items;
356 int totitems;
357 bool free;
359 C, op->ptr, prop, const_cast<const EnumPropertyItem **>(&items), &totitems, &free);
360 if (totitems > 0) {
361 RNA_property_enum_set(op->ptr, prop, items[0].value);
362 }
363 if (free) {
364 MEM_freeN(items);
365 }
366 }
368 C, op, event, IFACE_("Add Attribute"), CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add"));
369}
370
372{
373 /* identifiers */
374 ot->name = "Add Attribute";
375 ot->description = "Add attribute to geometry";
376 ot->idname = "GEOMETRY_OT_attribute_add";
377
378 /* API callbacks. */
382
383 /* flags */
385
386 /* properties */
387 PropertyRNA *prop;
388
389 /* The default name of the new attribute can be translated if new data translation is enabled,
390 * but since the user can choose it at invoke time, the translation happens in the invoke
391 * callback instead of here. */
392 prop = RNA_def_string(ot->srna, "name", nullptr, MAX_NAME, "Name", "Name of new attribute");
394
395 prop = RNA_def_enum(ot->srna,
396 "domain",
399 "Domain",
400 "Type of element that attribute is stored on");
403
404 prop = RNA_def_enum(ot->srna,
405 "data_type",
408 "Data Type",
409 "Type of data stored in attribute");
411}
412
414{
416 ID *id = static_cast<ID *>(ob->data);
419
420 if (!BKE_attribute_remove(owner, name, op->reports)) {
421 return OPERATOR_CANCELLED;
422 }
423
424 int *active_index = BKE_attributes_active_index_p(owner);
425 if (*active_index > 0) {
426 *active_index -= 1;
427 }
428
431
432 return OPERATOR_FINISHED;
433}
434
436{
437 /* identifiers */
438 ot->name = "Remove Attribute";
439 ot->description = "Remove attribute from geometry";
440 ot->idname = "GEOMETRY_OT_attribute_remove";
441
442 /* API callbacks. */
445
446 /* flags */
448}
449
451{
453 ID *id = static_cast<ID *>(ob->data);
454
455 char name[MAX_NAME];
456 RNA_string_get(op->ptr, "name", name);
457 eCustomDataType type = eCustomDataType(RNA_enum_get(op->ptr, "data_type"));
458 bke::AttrDomain domain = bke::AttrDomain(RNA_enum_get(op->ptr, "domain"));
460 CustomDataLayer *layer = BKE_attribute_new(owner, name, type, domain, op->reports);
461
462 float color[4];
463 RNA_float_get_array(op->ptr, "color", color);
464
465 if (layer == nullptr) {
466 return OPERATOR_CANCELLED;
467 }
468
470
473 }
474
476
479
480 return OPERATOR_FINISHED;
481}
482
484 wmOperator *op,
485 const wmEvent *event)
486{
487 PropertyRNA *prop;
488 prop = RNA_struct_find_property(op->ptr, "name");
489 if (!RNA_property_is_set(op->ptr, prop)) {
490 RNA_property_string_set(op->ptr, prop, DATA_("Color"));
491 }
493 op,
494 event,
495 IFACE_("Add Color Attribute"),
497}
498
503
505{
507 return false;
508 }
509
511 ID *data = static_cast<ID *>(ob->data);
513 if (ob->type == OB_MESH) {
514 if (CTX_data_edit_object(C) != nullptr) {
515 CTX_wm_operator_poll_msg_set(C, "Operation is not allowed in edit mode");
516 return false;
517 }
518 }
519 if (BKE_attributes_active_name_get(owner) == std::nullopt) {
520 return false;
521 }
522 return true;
523}
524
527 const StringRef name,
528 const bke::AttrDomain dst_domain,
529 const bke::AttrType dst_type,
530 ReportList *reports)
531{
532 BLI_assert(attributes.contains(name));
533 if (ELEM(dst_type, bke::AttrType::String)) {
534 if (reports) {
535 BKE_report(reports, RPT_ERROR, "Cannot convert to the selected type");
536 }
537 return false;
538 }
539
540 const bool was_active = BKE_attributes_active_name_get(owner) == name;
541
542 const std::string name_copy = name;
543 const GVArray varray = *attributes.lookup_or_default(name_copy, dst_domain, dst_type);
544
545 const CPPType &cpp_type = varray.type();
546 void *new_data = MEM_mallocN_aligned(
547 varray.size() * cpp_type.size, cpp_type.alignment, __func__);
548 varray.materialize_to_uninitialized(new_data);
549 attributes.remove(name_copy);
550 if (!attributes.add(name_copy, dst_domain, dst_type, bke::AttributeInitMoveArray(new_data))) {
551 MEM_freeN(new_data);
552 }
553
554 if (was_active) {
555 /* The attribute active status is stored as an index. Changing the attribute's domain will
556 * change its index, so reassign the active attribute if necessary. */
557 BKE_attributes_active_set(owner, name_copy);
558 }
559
560 return true;
561}
562
564{
566 ID *ob_data = static_cast<ID *>(ob->data);
568 const std::string name = *BKE_attributes_active_name_get(owner);
569
570 if (ob->type == OB_MESH) {
572
573 Mesh *mesh = reinterpret_cast<Mesh *>(ob_data);
574 bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
575
576 switch (mode) {
578 if (!convert_attribute(owner,
579 attributes,
580 name,
581 bke::AttrDomain(RNA_enum_get(op->ptr, "domain")),
583 eCustomDataType(RNA_enum_get(op->ptr, "data_type"))),
584 op->reports))
585 {
586 return OPERATOR_CANCELLED;
587 }
588 break;
589 }
591 Array<float> src_weights(mesh->verts_num);
592 VArray<float> src_varray = *attributes.lookup_or_default<float>(
594 src_varray.materialize(src_weights);
595 attributes.remove(name);
596
598 const int defgroup_index = BLI_findindex(BKE_id_defgroup_list_get(&mesh->id), defgroup);
600 for (const int i : IndexRange(mesh->verts_num)) {
601 const float weight = src_weights[i];
602 if (weight > 0.0f) {
603 BKE_defvert_add_index_notest(dverts + i, defgroup_index, weight);
604 }
605 }
607 int *active_index = BKE_attributes_active_index_p(owner);
608 if (*active_index > 0) {
609 *active_index -= 1;
610 }
611 break;
612 }
613 }
616 }
617 else if (ob->type == OB_CURVES) {
618 Curves *curves_id = static_cast<Curves *>(ob->data);
619 bke::CurvesGeometry &curves = curves_id->geometry.wrap();
620 if (!convert_attribute(owner,
621 curves.attributes_for_write(),
622 name,
623 bke::AttrDomain(RNA_enum_get(op->ptr, "domain")),
625 eCustomDataType(RNA_enum_get(op->ptr, "data_type"))),
626 op->reports))
627 {
628 return OPERATOR_CANCELLED;
629 }
631 WM_main_add_notifier(NC_GEOM | ND_DATA, &curves_id->id);
632 }
633 else if (ob->type == OB_POINTCLOUD) {
634 PointCloud &pointcloud = *static_cast<PointCloud *>(ob->data);
635 if (!convert_attribute(owner,
636 pointcloud.attributes_for_write(),
637 name,
638 bke::AttrDomain(RNA_enum_get(op->ptr, "domain")),
640 eCustomDataType(RNA_enum_get(op->ptr, "data_type"))),
641 op->reports))
642 {
643 return OPERATOR_CANCELLED;
644 }
647 }
648
650
651 return OPERATOR_FINISHED;
652}
653
655{
656 uiLayout *layout = op->layout;
657 layout->use_property_split_set(true);
658 layout->use_property_decorate_set(false);
659
660 layout->prop(op->ptr, "name", UI_ITEM_NONE, std::nullopt, ICON_NONE);
661 layout->prop(op->ptr, "domain", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
662 layout->prop(op->ptr, "data_type", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
663 layout->prop(op->ptr, "color", UI_ITEM_NONE, std::nullopt, ICON_NONE);
664}
665
667{
668 /* identifiers */
669 ot->name = "Add Color Attribute";
670 ot->description = "Add color attribute to geometry";
671 ot->idname = "GEOMETRY_OT_color_attribute_add";
672
673 /* API callbacks. */
678
679 /* flags */
681
682 /* properties */
683 PropertyRNA *prop;
684
685 /* The default name of the new attribute can be translated if new data translation is enabled,
686 * but since the user can choose it at invoke time, the translation happens in the invoke
687 * callback instead of here. */
688 prop = RNA_def_string(
689 ot->srna, "name", nullptr, MAX_NAME, "Name", "Name of new color attribute");
691
692 prop = RNA_def_enum(ot->srna,
693 "domain",
696 "Domain",
697 "Type of element that attribute is stored on");
698
699 prop = RNA_def_enum(ot->srna,
700 "data_type",
703 "Data Type",
704 "Type of data stored in attribute");
705
706 static float default_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
707
708 prop = RNA_def_float_color(
709 ot->srna, "color", 4, nullptr, 0.0f, FLT_MAX, "Color", "Default fill color", 0.0f, 1.0f);
711 RNA_def_property_float_array_default(prop, default_color);
712}
713
715{
717 ID *id = static_cast<ID *>(ob->data);
718
719 char name[MAX_NAME];
720 RNA_string_get(op->ptr, "name", name);
721
724
727
728 return OPERATOR_FINISHED;
729 }
730
731 return OPERATOR_CANCELLED;
732}
733
735{
736 /* identifiers */
737 ot->name = "Set Render Color";
738 ot->description = "Set default color attribute used for rendering";
739 ot->idname = "GEOMETRY_OT_color_attribute_render_set";
740
741 /* API callbacks. */
744
745 /* flags */
747
748 /* properties */
749 PropertyRNA *prop;
750
751 prop = RNA_def_string(ot->srna, "name", "Color", MAX_NAME, "Name", "Name of color attribute");
753}
754
756{
758 ID *id = static_cast<ID *>(ob->data);
759 const std::string active_name = BKE_id_attributes_active_color_name(id).value_or("");
760 if (active_name.empty()) {
761 return OPERATOR_CANCELLED;
762 }
764 if (!BKE_attribute_remove(owner, active_name, op->reports)) {
765 return OPERATOR_CANCELLED;
766 }
767
770
771 return OPERATOR_FINISHED;
772}
773
775{
777 return false;
778 }
779
780 const Object *ob = object::context_object(C);
781 const ID *data = static_cast<ID *>(ob->data);
782
784 return true;
785 }
786
787 return false;
788}
789
791{
792 /* identifiers */
793 ot->name = "Remove Color Attribute";
794 ot->description = "Remove color attribute from geometry";
795 ot->idname = "GEOMETRY_OT_color_attribute_remove";
796
797 /* API callbacks. */
800
801 /* flags */
803}
804
806{
808 ID *id = static_cast<ID *>(ob->data);
809 const std::optional<StringRef> active_name = BKE_id_attributes_active_color_name(id);
810 if (!active_name) {
811 return OPERATOR_CANCELLED;
812 }
813
815 CustomDataLayer *new_layer = BKE_attribute_duplicate(owner, *active_name, op->reports);
816 if (new_layer == nullptr) {
817 return OPERATOR_CANCELLED;
818 }
819
821
824
825 return OPERATOR_FINISHED;
826}
827
829{
831 return false;
832 }
833 if (CTX_data_edit_object(C) != nullptr) {
834 CTX_wm_operator_poll_msg_set(C, "Operation is not allowed in edit mode");
835 return false;
836 }
837
838 const Object *ob = object::context_object(C);
839 const ID *data = static_cast<ID *>(ob->data);
840
842 return true;
843 }
844
845 return false;
846}
847
849{
850 /* identifiers */
851 ot->name = "Duplicate Color Attribute";
852 ot->description = "Duplicate color attribute";
853 ot->idname = "GEOMETRY_OT_color_attribute_duplicate";
854
855 /* API callbacks. */
858
859 /* flags */
861}
862
864 wmOperator *op,
865 const wmEvent * /*event*/)
866{
868 ID *id = static_cast<ID *>(ob->data);
871 const bke::AttributeMetaData meta_data = *accessor.lookup_meta_data(
873
874 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "domain");
875 if (!RNA_property_is_set(op->ptr, prop)) {
876 RNA_property_enum_set(op->ptr, prop, int(meta_data.domain));
877 }
878 prop = RNA_struct_find_property(op->ptr, "data_type");
879 if (!RNA_property_is_set(op->ptr, prop)) {
881 }
882
884 C, op, 300, IFACE_("Convert Attribute Domain"), IFACE_("Convert"));
885}
886
888{
889 uiLayout *layout = op->layout;
890 layout->use_property_split_set(true);
891 layout->use_property_decorate_set(false);
892
894 if (ob->type == OB_MESH) {
895 layout->prop(op->ptr, "mode", UI_ITEM_NONE, std::nullopt, ICON_NONE);
896 }
897
898 const ConvertAttributeMode mode = ob->type == OB_MESH ?
901
902 if (mode == ConvertAttributeMode::Generic) {
903 if (ob->type != OB_POINTCLOUD) {
904 layout->prop(op->ptr, "domain", UI_ITEM_NONE, std::nullopt, ICON_NONE);
905 }
906 layout->prop(op->ptr, "data_type", UI_ITEM_NONE, std::nullopt, ICON_NONE);
907 }
908}
909
911 {int(ConvertAttributeMode::Generic), "GENERIC", 0, "Generic", ""},
912 {int(ConvertAttributeMode::VertexGroup), "VERTEX_GROUP", 0, "Vertex Group", ""},
913 {0, nullptr, 0, nullptr, nullptr},
914};
915
917 PointerRNA * /*ptr*/,
918 PropertyRNA * /*prop*/,
919 bool *r_free)
920{
921 if (C == nullptr) {
923 }
924
926 if (ob == nullptr) {
928 }
929
930 if (ob->type == OB_MESH) {
931 *r_free = false;
933 }
934
935 EnumPropertyItem *items = nullptr;
936 int totitem = 0;
938 if (item.value == int(ConvertAttributeMode::Generic)) {
939 RNA_enum_item_add(&items, &totitem, &item);
940 }
941 }
942 RNA_enum_item_end(&items, &totitem);
943 *r_free = true;
944 return items;
945}
946
948{
950 return false;
951 }
952
953 if (CTX_data_edit_object(C) != nullptr) {
954 CTX_wm_operator_poll_msg_set(C, "Operation is not allowed in edit mode");
955 return false;
956 }
957
959 ID *id = static_cast<ID *>(ob->data);
960 if (GS(id->name) != ID_ME) {
961 return false;
962 }
963 const Mesh *mesh = static_cast<const Mesh *>(ob->data);
964 const char *name = mesh->active_color_attribute;
965 const bke::AttributeAccessor attributes = mesh->attributes();
966 const std::optional<bke::AttributeMetaData> meta_data = attributes.lookup_meta_data(name);
967 if (!meta_data) {
968 return false;
969 }
970 if (!(ATTR_DOMAIN_AS_MASK(meta_data->domain) & ATTR_DOMAIN_MASK_COLOR) ||
971 !(CD_TYPE_AS_MASK(*bke::attr_type_to_custom_data_type(meta_data->data_type)) &
973 {
974 return false;
975 }
976
977 return true;
978}
979
981{
983 Mesh *mesh = static_cast<Mesh *>(ob->data);
986 owner,
987 mesh->attributes_for_write(),
988 mesh->active_color_attribute,
989 bke::AttrDomain(RNA_enum_get(op->ptr, "domain")),
991 op->reports);
994 return OPERATOR_FINISHED;
995}
996
998 wmOperator *op,
999 const wmEvent * /*event*/)
1000{
1002 Mesh *mesh = static_cast<Mesh *>(ob->data);
1003 const char *name = mesh->active_color_attribute;
1004 const bke::AttributeMetaData meta_data = *mesh->attributes().lookup_meta_data(name);
1005
1006 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "domain");
1007 if (!RNA_property_is_set(op->ptr, prop)) {
1008 RNA_property_enum_set(op->ptr, prop, int(meta_data.domain));
1009 }
1010 prop = RNA_struct_find_property(op->ptr, "data_type");
1011 if (!RNA_property_is_set(op->ptr, prop)) {
1013 }
1014
1016 C, op, 300, IFACE_("Convert Color Attribute Domain"), IFACE_("Convert"));
1017}
1018
1020{
1021 uiLayout *layout = op->layout;
1022 layout->use_property_split_set(true);
1023 layout->use_property_decorate_set(false);
1024
1025 layout->prop(op->ptr, "domain", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
1026 layout->prop(op->ptr, "data_type", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
1027}
1028
1030{
1031 ot->name = "Convert Color Attribute";
1032 ot->description = "Change how the color attribute is stored";
1033 ot->idname = "GEOMETRY_OT_color_attribute_convert";
1034
1039
1040 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1041
1042 PropertyRNA *prop;
1043
1044 prop = RNA_def_enum(ot->srna,
1045 "domain",
1048 "Domain",
1049 "Type of element that attribute is stored on");
1051
1052 prop = RNA_def_enum(ot->srna,
1053 "data_type",
1056 "Data Type",
1057 "Type of data stored in attribute");
1059}
1060
1062{
1063 ot->name = "Convert Attribute";
1064 ot->description = "Change how the attribute is stored";
1065 ot->idname = "GEOMETRY_OT_attribute_convert";
1066
1071
1072 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1073
1074 PropertyRNA *prop;
1075
1076 prop = RNA_def_enum(ot->srna,
1077 "mode",
1080 "Mode",
1081 "");
1083
1084 prop = RNA_def_enum(ot->srna,
1085 "domain",
1088 "Domain",
1089 "Which geometry element to move the attribute to");
1091
1093 ot->srna, "data_type", rna_enum_attribute_type_items, CD_PROP_FLOAT, "Data Type", "");
1094}
1095
1096} // 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:382
std::optional< blender::StringRefNull > BKE_attributes_active_name_get(AttributeOwner &owner)
Definition attribute.cc:784
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:512
void BKE_attributes_active_set(AttributeOwner &owner, blender::StringRef name)
Definition attribute.cc:830
@ ATTR_DOMAIN_MASK_ALL
const struct CustomDataLayer * BKE_attribute_search(const AttributeOwner &owner, blender::StringRef name, eCustomDataMask type, AttrDomainMask domain_mask)
Definition attribute.cc:639
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:852
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:451
void BKE_id_attributes_active_color_set(struct ID *id, std::optional< blender::StringRef > name)
Definition attribute.cc:985
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.
eCustomDataMask CD_TYPE_AS_MASK(eCustomDataType type)
support for deformation groups and hooks.
bDeformGroup * BKE_object_defgroup_new(Object *ob, blender::StringRef name)
Definition deform.cc:48
void BKE_defvert_add_index_notest(MDeformVert *dv, int defgroup, float weight)
Definition deform.cc:856
const ListBase * BKE_id_defgroup_list_get(const ID *id)
Definition deform.cc:470
bool BKE_id_is_editable(const Main *bmain, const ID *id)
Definition lib_id.cc:2523
Functions for dealing with objects and deform verts, used by painting and tools.
struct MDeformVert * BKE_object_defgroup_data_create(struct ID *id)
@ RPT_ERROR
Definition BKE_report.hh:39
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
#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:1074
@ ID_ME
#define CD_MASK_PROP_ALL
#define CD_MASK_COLOR_ALL
@ CD_PROP_FLOAT
@ CD_PROP_COLOR
@ CD_PROP_QUATERNION
@ CD_PROP_STRING
@ CD_PROP_FLOAT4X4
#define MAX_NAME
Definition DNA_defs.h:50
@ 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:344
@ PROP_COLOR
Definition RNA_types.hh:260
#define C
Definition RandGen.cpp:29
@ UI_ITEM_R_EXPAND
#define UI_ITEM_NONE
#define NC_GEOM
Definition WM_types.hh:393
#define ND_DATA
Definition WM_types.hh:509
@ OPTYPE_INTERNAL
Definition WM_types.hh:202
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
BMesh const char void * data
AttributeOwnerType type() const
Definition attribute.cc:63
std::optional< blender::bke::MutableAttributeAccessor > get_accessor() const
Definition attribute.cc:126
static AttributeOwner from_id(ID *id)
Definition attribute.cc:44
blender::bke::AttributeStorage * get_storage() const
Definition attribute.cc:108
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
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, AttrType data_type, const void *default_value=nullptr) const
bool contains(StringRef attribute_id) const
static std::optional< AttributeAccessor > from_id(const ID &id)
bool domain_supported(const AttrDomain domain) const
int domain_size(const AttrDomain domain) const
std::optional< AttributeMetaData > lookup_meta_data(StringRef attribute_id) const
Attribute & add(std::string name, bke::AttrDomain domain, bke::AttrType data_type, Attribute::DataVariant data)
std::string unique_name_calc(StringRef name) const
bool add(const StringRef attribute_id, const AttrDomain domain, const AttrType data_type, const AttributeInit &initializer)
bool remove(const StringRef attribute_id)
#define GS(x)
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
std::optional< eCustomDataType > attr_type_to_custom_data_type(AttrType attr_type)
std::optional< AttrType > custom_data_type_to_attr_type(eCustomDataType data_type)
const CPPType * custom_data_type_to_cpp_type(eCustomDataType type)
AttrType cpp_type_to_attribute_type(const CPPType &type)
const CPPType & attribute_type_to_cpp_type(AttrType type)
BLI_INLINE ColorSceneLinear4f< Alpha > decode(const ColorSceneLinearByteEncoded4b< Alpha > &color)
Definition BLI_color.hh:77
BLI_INLINE ColorSceneLinearByteEncoded4b< Alpha > encode(const ColorSceneLinear4f< Alpha > &color)
Definition BLI_color.hh:50
static bool geometry_attributes_poll(bContext *C)
void GEOMETRY_OT_attribute_add(wmOperatorType *ot)
PropertyRNA * rna_property_for_type(PointerRNA &ptr, const bke::AttrType type)
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)
GPointer rna_property_for_attribute_type_retrieve_value(PointerRNA &ptr, const bke::AttrType type, void *buffer)
void GEOMETRY_OT_attribute_convert(wmOperatorType *ot)
StringRefNull rna_property_name_for_type(const bke::AttrType type)
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 *)
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)
bool convert_attribute(AttributeOwner &owner, bke::MutableAttributeAccessor attributes, const StringRef name, const bke::AttrDomain dst_domain, const bke::AttrType dst_type, ReportList *reports)
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)
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
VecBase< float, 3 > float3
blender::VecBase< int16_t, 2 > short2
ColorSceneLinearByteEncoded4b< eAlpha::Premultiplied > ColorGeometry4b
const char * name
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)
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)
std::string RNA_string_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:414
static ArrayData from_default_value(const CPPType &type, int64_t domain_size)
void use_property_decorate_set(bool is_sep)
void use_property_split_set(bool value)
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:4238
wmOperatorType * ot
Definition wm_files.cc:4237
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, std::optional< std::string > message)
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, std::optional< std::string > message)