| 
									
										
										
										
											2022-02-11 09:07:11 +11:00
										 |  |  | /* SPDX-License-Identifier: GPL-2.0-or-later
 | 
					
						
							|  |  |  |  * Copyright 2020 Blender Foundation. All rights reserved. */ | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup edgeometry | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-21 12:47:35 +01:00
										 |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_mesh_types.h"
 | 
					
						
							|  |  |  | #include "DNA_meshdata_types.h"
 | 
					
						
							|  |  |  | #include "DNA_scene_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  | #include "BKE_attribute.h"
 | 
					
						
							|  |  |  | #include "BKE_context.h"
 | 
					
						
							| 
									
										
										
										
											2022-01-21 12:47:35 +01:00
										 |  |  | #include "BKE_deform.h"
 | 
					
						
							|  |  |  | #include "BKE_geometry_set.hh"
 | 
					
						
							|  |  |  | #include "BKE_object_deform.h"
 | 
					
						
							|  |  |  | #include "BKE_report.h"
 | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "RNA_access.h"
 | 
					
						
							|  |  |  | #include "RNA_define.h"
 | 
					
						
							|  |  |  | #include "RNA_enum_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DEG_depsgraph.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "WM_api.h"
 | 
					
						
							|  |  |  | #include "WM_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-21 12:47:35 +01:00
										 |  |  | #include "UI_interface.h"
 | 
					
						
							|  |  |  | #include "UI_resources.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  | #include "ED_object.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-14 12:53:19 +01:00
										 |  |  | #include "geometry_intern.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-21 12:47:35 +01:00
										 |  |  | namespace blender::ed::geometry { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using fn::GArray; | 
					
						
							|  |  |  | using fn::GVArray; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  | /*********************** Attribute Operators ************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool geometry_attributes_poll(bContext *C) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Object *ob = ED_object_context(C); | 
					
						
							| 
									
										
										
										
											2022-01-14 12:53:19 +01:00
										 |  |  |   ID *data = (ob) ? static_cast<ID *>(ob->data) : nullptr; | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  |   return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data)) && | 
					
						
							|  |  |  |          BKE_id_attributes_supported(data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 10:10:57 +02:00
										 |  |  | static bool geometry_attributes_remove_poll(bContext *C) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (!geometry_attributes_poll(C)) { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Object *ob = ED_object_context(C); | 
					
						
							| 
									
										
										
										
											2022-01-14 12:53:19 +01:00
										 |  |  |   ID *data = (ob) ? static_cast<ID *>(ob->data) : nullptr; | 
					
						
							|  |  |  |   if (BKE_id_attributes_active_get(data) != nullptr) { | 
					
						
							| 
									
										
										
										
											2021-07-22 10:10:57 +02:00
										 |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  | static const EnumPropertyItem *geometry_attribute_domain_itemf(bContext *C, | 
					
						
							|  |  |  |                                                                PointerRNA *UNUSED(ptr), | 
					
						
							|  |  |  |                                                                PropertyRNA *UNUSED(prop), | 
					
						
							|  |  |  |                                                                bool *r_free) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-01-14 12:53:19 +01:00
										 |  |  |   if (C == nullptr) { | 
					
						
							| 
									
										
										
										
											2021-05-25 17:46:17 +02:00
										 |  |  |     return DummyRNA_NULL_items; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  |   Object *ob = ED_object_context(C); | 
					
						
							| 
									
										
										
										
											2022-01-14 12:53:19 +01:00
										 |  |  |   if (ob == nullptr) { | 
					
						
							| 
									
										
										
										
											2021-05-25 17:46:17 +02:00
										 |  |  |     return DummyRNA_NULL_items; | 
					
						
							| 
									
										
										
										
											2021-03-25 08:41:30 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-21 12:47:35 +01:00
										 |  |  |   return rna_enum_attribute_domain_itemf(static_cast<ID *>(ob->data), false, r_free); | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int geometry_attribute_add_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Object *ob = ED_object_context(C); | 
					
						
							| 
									
										
										
										
											2022-01-14 12:53:19 +01:00
										 |  |  |   ID *id = static_cast<ID *>(ob->data); | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   char name[MAX_NAME]; | 
					
						
							|  |  |  |   RNA_string_get(op->ptr, "name", name); | 
					
						
							|  |  |  |   CustomDataType type = (CustomDataType)RNA_enum_get(op->ptr, "data_type"); | 
					
						
							|  |  |  |   AttributeDomain domain = (AttributeDomain)RNA_enum_get(op->ptr, "domain"); | 
					
						
							|  |  |  |   CustomDataLayer *layer = BKE_id_attribute_new(id, name, type, domain, op->reports); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-14 12:53:19 +01:00
										 |  |  |   if (layer == nullptr) { | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  |     return OPERATOR_CANCELLED; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   BKE_id_attributes_active_set(id, layer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DEG_id_tag_update(id, ID_RECALC_GEOMETRY); | 
					
						
							|  |  |  |   WM_main_add_notifier(NC_GEOM | ND_DATA, id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GEOMETRY_OT_attribute_add(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* identifiers */ | 
					
						
							|  |  |  |   ot->name = "Add Geometry Attribute"; | 
					
						
							|  |  |  |   ot->description = "Add attribute to geometry"; | 
					
						
							|  |  |  |   ot->idname = "GEOMETRY_OT_attribute_add"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* api callbacks */ | 
					
						
							|  |  |  |   ot->poll = geometry_attributes_poll; | 
					
						
							|  |  |  |   ot->exec = geometry_attribute_add_exec; | 
					
						
							|  |  |  |   ot->invoke = WM_operator_props_popup_confirm; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* flags */ | 
					
						
							|  |  |  |   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* properties */ | 
					
						
							|  |  |  |   PropertyRNA *prop; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   prop = RNA_def_string(ot->srna, "name", "Attribute", MAX_NAME, "Name", "Name of new attribute"); | 
					
						
							|  |  |  |   RNA_def_property_flag(prop, PROP_SKIP_SAVE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   prop = RNA_def_enum(ot->srna, | 
					
						
							|  |  |  |                       "domain", | 
					
						
							|  |  |  |                       rna_enum_attribute_domain_items, | 
					
						
							|  |  |  |                       ATTR_DOMAIN_POINT, | 
					
						
							|  |  |  |                       "Domain", | 
					
						
							|  |  |  |                       "Type of element that attribute is stored on"); | 
					
						
							|  |  |  |   RNA_def_enum_funcs(prop, geometry_attribute_domain_itemf); | 
					
						
							|  |  |  |   RNA_def_property_flag(prop, PROP_SKIP_SAVE); | 
					
						
							| 
									
										
										
										
											2021-06-28 16:52:49 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   prop = RNA_def_enum(ot->srna, | 
					
						
							|  |  |  |                       "data_type", | 
					
						
							|  |  |  |                       rna_enum_attribute_type_items, | 
					
						
							|  |  |  |                       CD_PROP_FLOAT, | 
					
						
							|  |  |  |                       "Data Type", | 
					
						
							|  |  |  |                       "Type of data stored in attribute"); | 
					
						
							|  |  |  |   RNA_def_property_flag(prop, PROP_SKIP_SAVE); | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int geometry_attribute_remove_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Object *ob = ED_object_context(C); | 
					
						
							| 
									
										
										
										
											2022-01-14 12:53:19 +01:00
										 |  |  |   ID *id = static_cast<ID *>(ob->data); | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  |   CustomDataLayer *layer = BKE_id_attributes_active_get(id); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-14 12:53:19 +01:00
										 |  |  |   if (layer == nullptr) { | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  |     return OPERATOR_CANCELLED; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!BKE_id_attribute_remove(id, layer, op->reports)) { | 
					
						
							|  |  |  |     return OPERATOR_CANCELLED; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-28 16:52:49 +02:00
										 |  |  |   int *active_index = BKE_id_attributes_active_index_p(id); | 
					
						
							|  |  |  |   if (*active_index > 0) { | 
					
						
							|  |  |  |     *active_index -= 1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  |   DEG_id_tag_update(id, ID_RECALC_GEOMETRY); | 
					
						
							|  |  |  |   WM_main_add_notifier(NC_GEOM | ND_DATA, id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GEOMETRY_OT_attribute_remove(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* identifiers */ | 
					
						
							|  |  |  |   ot->name = "Remove Geometry Attribute"; | 
					
						
							|  |  |  |   ot->description = "Remove attribute from geometry"; | 
					
						
							|  |  |  |   ot->idname = "GEOMETRY_OT_attribute_remove"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* api callbacks */ | 
					
						
							|  |  |  |   ot->exec = geometry_attribute_remove_exec; | 
					
						
							| 
									
										
										
										
											2021-07-22 10:10:57 +02:00
										 |  |  |   ot->poll = geometry_attributes_remove_poll; | 
					
						
							| 
									
										
										
										
											2020-08-19 18:12:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* flags */ | 
					
						
							|  |  |  |   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-01-21 12:47:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | enum class ConvertAttributeMode { | 
					
						
							|  |  |  |   Generic, | 
					
						
							|  |  |  |   UVMap, | 
					
						
							|  |  |  |   VertexGroup, | 
					
						
							|  |  |  |   VertexColor, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool geometry_attribute_convert_poll(bContext *C) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (!geometry_attributes_poll(C)) { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Object *ob = ED_object_context(C); | 
					
						
							|  |  |  |   ID *data = static_cast<ID *>(ob->data); | 
					
						
							|  |  |  |   if (GS(data->name) != ID_ME) { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   CustomDataLayer *layer = BKE_id_attributes_active_get(data); | 
					
						
							|  |  |  |   if (layer == nullptr) { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int geometry_attribute_convert_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Object *ob = ED_object_context(C); | 
					
						
							|  |  |  |   ID *ob_data = static_cast<ID *>(ob->data); | 
					
						
							|  |  |  |   CustomDataLayer *layer = BKE_id_attributes_active_get(ob_data); | 
					
						
							|  |  |  |   const std::string name = layer->name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const ConvertAttributeMode mode = static_cast<ConvertAttributeMode>( | 
					
						
							|  |  |  |       RNA_enum_get(op->ptr, "mode")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Mesh *mesh = reinterpret_cast<Mesh *>(ob_data); | 
					
						
							|  |  |  |   MeshComponent mesh_component; | 
					
						
							|  |  |  |   mesh_component.replace(mesh, GeometryOwnershipType::Editable); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* General conversion steps are always the same:
 | 
					
						
							|  |  |  |    * 1. Convert old data to right domain and data type. | 
					
						
							|  |  |  |    * 2. Copy the data into a new array so that it does not depend on the old attribute anymore. | 
					
						
							|  |  |  |    * 3. Delete the old attribute. | 
					
						
							|  |  |  |    * 4. Create a new attribute based on the previously copied data. */ | 
					
						
							|  |  |  |   switch (mode) { | 
					
						
							|  |  |  |     case ConvertAttributeMode::Generic: { | 
					
						
							|  |  |  |       const AttributeDomain dst_domain = static_cast<AttributeDomain>( | 
					
						
							|  |  |  |           RNA_enum_get(op->ptr, "domain")); | 
					
						
							|  |  |  |       const CustomDataType dst_type = static_cast<CustomDataType>( | 
					
						
							|  |  |  |           RNA_enum_get(op->ptr, "data_type")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (ELEM(dst_type, CD_PROP_STRING, CD_MLOOPCOL)) { | 
					
						
							|  |  |  |         BKE_report(op->reports, RPT_ERROR, "Cannot convert to the selected type"); | 
					
						
							|  |  |  |         return OPERATOR_CANCELLED; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       GVArray src_varray = mesh_component.attribute_get_for_read(name, dst_domain, dst_type); | 
					
						
							|  |  |  |       const CPPType &cpp_type = src_varray.type(); | 
					
						
							|  |  |  |       void *new_data = MEM_malloc_arrayN(src_varray.size(), cpp_type.size(), __func__); | 
					
						
							|  |  |  |       src_varray.materialize_to_uninitialized(new_data); | 
					
						
							|  |  |  |       mesh_component.attribute_try_delete(name); | 
					
						
							|  |  |  |       mesh_component.attribute_try_create(name, dst_domain, dst_type, AttributeInitMove(new_data)); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case ConvertAttributeMode::UVMap: { | 
					
						
							|  |  |  |       MLoopUV *dst_uvs = static_cast<MLoopUV *>( | 
					
						
							|  |  |  |           MEM_calloc_arrayN(mesh->totloop, sizeof(MLoopUV), __func__)); | 
					
						
							|  |  |  |       VArray<float2> src_varray = mesh_component.attribute_get_for_read<float2>( | 
					
						
							|  |  |  |           name, ATTR_DOMAIN_CORNER, {0.0f, 0.0f}); | 
					
						
							|  |  |  |       for (const int i : IndexRange(mesh->totloop)) { | 
					
						
							|  |  |  |         copy_v2_v2(dst_uvs[i].uv, src_varray[i]); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       mesh_component.attribute_try_delete(name); | 
					
						
							|  |  |  |       CustomData_add_layer_named( | 
					
						
							|  |  |  |           &mesh->ldata, CD_MLOOPUV, CD_ASSIGN, dst_uvs, mesh->totloop, name.c_str()); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case ConvertAttributeMode::VertexColor: { | 
					
						
							|  |  |  |       MLoopCol *dst_colors = static_cast<MLoopCol *>( | 
					
						
							|  |  |  |           MEM_calloc_arrayN(mesh->totloop, sizeof(MLoopCol), __func__)); | 
					
						
							|  |  |  |       VArray<ColorGeometry4f> src_varray = mesh_component.attribute_get_for_read<ColorGeometry4f>( | 
					
						
							|  |  |  |           name, ATTR_DOMAIN_CORNER, ColorGeometry4f{0.0f, 0.0f, 0.0f, 1.0f}); | 
					
						
							|  |  |  |       for (const int i : IndexRange(mesh->totloop)) { | 
					
						
							|  |  |  |         ColorGeometry4b encoded_color = src_varray[i].encode(); | 
					
						
							|  |  |  |         copy_v4_v4_uchar(&dst_colors[i].r, &encoded_color.r); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       mesh_component.attribute_try_delete(name); | 
					
						
							|  |  |  |       CustomData_add_layer_named( | 
					
						
							|  |  |  |           &mesh->ldata, CD_MLOOPCOL, CD_ASSIGN, dst_colors, mesh->totloop, name.c_str()); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case ConvertAttributeMode::VertexGroup: { | 
					
						
							|  |  |  |       Array<float> src_weights(mesh->totvert); | 
					
						
							|  |  |  |       VArray<float> src_varray = mesh_component.attribute_get_for_read<float>( | 
					
						
							|  |  |  |           name, ATTR_DOMAIN_POINT, 0.0f); | 
					
						
							|  |  |  |       src_varray.materialize(src_weights); | 
					
						
							|  |  |  |       mesh_component.attribute_try_delete(name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       bDeformGroup *defgroup = BKE_object_defgroup_new(ob, name.c_str()); | 
					
						
							|  |  |  |       const int defgroup_index = BLI_findindex(BKE_id_defgroup_list_get(&mesh->id), defgroup); | 
					
						
							|  |  |  |       MDeformVert *dverts = BKE_object_defgroup_data_create(&mesh->id); | 
					
						
							|  |  |  |       for (const int i : IndexRange(mesh->totvert)) { | 
					
						
							|  |  |  |         const float weight = src_weights[i]; | 
					
						
							|  |  |  |         if (weight > 0.0f) { | 
					
						
							|  |  |  |           BKE_defvert_add_index_notest(dverts + i, defgroup_index, weight); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int *active_index = BKE_id_attributes_active_index_p(&mesh->id); | 
					
						
							|  |  |  |   if (*active_index > 0) { | 
					
						
							|  |  |  |     *active_index -= 1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY); | 
					
						
							|  |  |  |   WM_main_add_notifier(NC_GEOM | ND_DATA, &mesh->id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void geometry_attribute_convert_ui(bContext *UNUSED(C), wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   uiLayout *layout = op->layout; | 
					
						
							| 
									
										
										
										
											2022-01-28 10:03:07 -06:00
										 |  |  |   uiLayoutSetPropSep(layout, true); | 
					
						
							|  |  |  |   uiLayoutSetPropDecorate(layout, false); | 
					
						
							| 
									
										
										
										
											2022-01-21 12:47:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   uiItemR(layout, op->ptr, "mode", 0, nullptr, ICON_NONE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const ConvertAttributeMode mode = static_cast<ConvertAttributeMode>( | 
					
						
							|  |  |  |       RNA_enum_get(op->ptr, "mode")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (mode == ConvertAttributeMode::Generic) { | 
					
						
							|  |  |  |     uiItemR(layout, op->ptr, "domain", 0, nullptr, ICON_NONE); | 
					
						
							|  |  |  |     uiItemR(layout, op->ptr, "data_type", 0, nullptr, ICON_NONE); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int geometry_attribute_convert_invoke(bContext *C, | 
					
						
							|  |  |  |                                              wmOperator *op, | 
					
						
							|  |  |  |                                              const wmEvent *UNUSED(event)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return WM_operator_props_dialog_popup(C, op, 300); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GEOMETRY_OT_attribute_convert(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   ot->name = "Convert Attribute"; | 
					
						
							|  |  |  |   ot->description = "Change how the attribute is stored"; | 
					
						
							|  |  |  |   ot->idname = "GEOMETRY_OT_attribute_convert"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ot->invoke = geometry_attribute_convert_invoke; | 
					
						
							|  |  |  |   ot->exec = geometry_attribute_convert_exec; | 
					
						
							|  |  |  |   ot->poll = geometry_attribute_convert_poll; | 
					
						
							|  |  |  |   ot->ui = geometry_attribute_convert_ui; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static EnumPropertyItem mode_items[] = { | 
					
						
							|  |  |  |       {int(ConvertAttributeMode::Generic), "GENERIC", 0, "Generic", ""}, | 
					
						
							|  |  |  |       {int(ConvertAttributeMode::UVMap), "UV_MAP", 0, "UV Map", ""}, | 
					
						
							|  |  |  |       {int(ConvertAttributeMode::VertexGroup), "VERTEX_GROUP", 0, "Vertex Group", ""}, | 
					
						
							|  |  |  |       {int(ConvertAttributeMode::VertexColor), "VERTEX_COLOR", 0, "Vertex Color", ""}, | 
					
						
							|  |  |  |       {0, nullptr, 0, nullptr, nullptr}, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PropertyRNA *prop; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   RNA_def_enum( | 
					
						
							|  |  |  |       ot->srna, "mode", mode_items, static_cast<int>(ConvertAttributeMode::Generic), "Mode", ""); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   prop = RNA_def_enum(ot->srna, | 
					
						
							|  |  |  |                       "domain", | 
					
						
							|  |  |  |                       rna_enum_attribute_domain_items, | 
					
						
							|  |  |  |                       ATTR_DOMAIN_POINT, | 
					
						
							|  |  |  |                       "Domain", | 
					
						
							|  |  |  |                       "Which geometry element to move the attribute to"); | 
					
						
							|  |  |  |   RNA_def_enum_funcs(prop, geometry_attribute_domain_itemf); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   RNA_def_enum( | 
					
						
							|  |  |  |       ot->srna, "data_type", rna_enum_attribute_type_items, CD_PROP_FLOAT, "Data Type", ""); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }  // namespace blender::ed::geometry
 |