Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py13
-rw-r--r--source/blender/editors/geometry/CMakeLists.txt2
-rw-r--r--source/blender/editors/geometry/geometry_attributes.cc205
-rw-r--r--source/blender/editors/geometry/geometry_intern.hh5
-rw-r--r--source/blender/editors/geometry/geometry_ops.cc3
-rw-r--r--source/blender/makesrna/RNA_enum_types.h4
-rw-r--r--source/blender/makesrna/intern/rna_attribute.c9
7 files changed, 237 insertions, 4 deletions
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 49f196640d8..11e2cd84903 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -82,6 +82,14 @@ class MESH_MT_shape_key_context_menu(Menu):
layout.operator("object.shape_key_move", icon='TRIA_UP_BAR', text="Move to Top").type = 'TOP'
layout.operator("object.shape_key_move", icon='TRIA_DOWN_BAR', text="Move to Bottom").type = 'BOTTOM'
+class MESH_MT_attribute_context_menu(Menu):
+ bl_label = "Attribute Specials"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("geometry.attribute_convert")
+
class MESH_UL_vgroups(UIList):
def draw_item(self, _context, layout, _data, item, icon, _active_data_, _active_propname, _index):
@@ -615,6 +623,10 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
col.operator("geometry.attribute_add", icon='ADD', text="")
col.operator("geometry.attribute_remove", icon='REMOVE', text="")
+ col.separator()
+
+ col.menu("MESH_MT_attribute_context_menu", icon='DOWNARROW_HLT', text="")
+
self.draw_attribute_warnings(context, layout)
def draw_attribute_warnings(self, context, layout):
@@ -652,6 +664,7 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
classes = (
MESH_MT_vertex_group_context_menu,
MESH_MT_shape_key_context_menu,
+ MESH_MT_attribute_context_menu,
MESH_UL_vgroups,
MESH_UL_fmaps,
MESH_UL_shape_keys,
diff --git a/source/blender/editors/geometry/CMakeLists.txt b/source/blender/editors/geometry/CMakeLists.txt
index 65b9633da98..8c920915937 100644
--- a/source/blender/editors/geometry/CMakeLists.txt
+++ b/source/blender/editors/geometry/CMakeLists.txt
@@ -20,9 +20,11 @@ set(INC
../../blenkernel
../../blenlib
../../depsgraph
+ ../../functions
../../makesdna
../../makesrna
../../windowmanager
+ ../../../../intern/guardedalloc
)
set(INC_SYS
diff --git a/source/blender/editors/geometry/geometry_attributes.cc b/source/blender/editors/geometry/geometry_attributes.cc
index 9c0f6728701..56ecd108bba 100644
--- a/source/blender/editors/geometry/geometry_attributes.cc
+++ b/source/blender/editors/geometry/geometry_attributes.cc
@@ -21,8 +21,18 @@
* \ingroup edgeometry
*/
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+
#include "BKE_attribute.h"
#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_geometry_set.hh"
+#include "BKE_object_deform.h"
+#include "BKE_report.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -33,10 +43,19 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "UI_interface.h"
+#include "UI_resources.h"
+
#include "ED_object.h"
#include "geometry_intern.hh"
+namespace blender::ed::geometry {
+
+using fn::CPPType;
+using fn::GArray;
+using fn::GVArray;
+
/*********************** Attribute Operators ************************/
static bool geometry_attributes_poll(bContext *C)
@@ -76,7 +95,7 @@ static const EnumPropertyItem *geometry_attribute_domain_itemf(bContext *C,
return DummyRNA_NULL_items;
}
- return rna_enum_attribute_domain_itemf(static_cast<ID *>(ob->data), r_free);
+ return rna_enum_attribute_domain_itemf(static_cast<ID *>(ob->data), false, r_free);
}
static int geometry_attribute_add_exec(bContext *C, wmOperator *op)
@@ -180,3 +199,187 @@ void GEOMETRY_OT_attribute_remove(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+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;
+
+ 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
diff --git a/source/blender/editors/geometry/geometry_intern.hh b/source/blender/editors/geometry/geometry_intern.hh
index 14992476edd..30a2a1d6eb1 100644
--- a/source/blender/editors/geometry/geometry_intern.hh
+++ b/source/blender/editors/geometry/geometry_intern.hh
@@ -25,6 +25,11 @@
struct wmOperatorType;
+namespace blender::ed::geometry {
+
/* *** geometry_attributes.cc *** */
void GEOMETRY_OT_attribute_add(struct wmOperatorType *ot);
void GEOMETRY_OT_attribute_remove(struct wmOperatorType *ot);
+void GEOMETRY_OT_attribute_convert(struct wmOperatorType *ot);
+
+} // namespace blender::ed::geometry
diff --git a/source/blender/editors/geometry/geometry_ops.cc b/source/blender/editors/geometry/geometry_ops.cc
index ba8afe0e62f..8933b2a7f00 100644
--- a/source/blender/editors/geometry/geometry_ops.cc
+++ b/source/blender/editors/geometry/geometry_ops.cc
@@ -31,6 +31,9 @@
void ED_operatortypes_geometry(void)
{
+ using namespace blender::ed::geometry;
+
WM_operatortype_append(GEOMETRY_OT_attribute_add);
WM_operatortype_append(GEOMETRY_OT_attribute_remove);
+ WM_operatortype_append(GEOMETRY_OT_attribute_convert);
}
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index da07f1043a7..fcae1009c8b 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -35,7 +35,9 @@ struct bNodeType;
#define DEF_ENUM(id) extern const EnumPropertyItem id[];
#include "RNA_enum_items.h"
-extern const EnumPropertyItem *rna_enum_attribute_domain_itemf(struct ID *id, bool *r_free);
+extern const EnumPropertyItem *rna_enum_attribute_domain_itemf(struct ID *id,
+ bool include_instances,
+ bool *r_free);
/**
* For ID filters (#FILTER_ID_AC, #FILTER_ID_AR, ...) an int isn't enough. This version allows 64
diff --git a/source/blender/makesrna/intern/rna_attribute.c b/source/blender/makesrna/intern/rna_attribute.c
index 78c15444308..35da353a043 100644
--- a/source/blender/makesrna/intern/rna_attribute.c
+++ b/source/blender/makesrna/intern/rna_attribute.c
@@ -166,7 +166,9 @@ static int rna_Attribute_type_get(PointerRNA *ptr)
return layer->type;
}
-const EnumPropertyItem *rna_enum_attribute_domain_itemf(ID *id, bool *r_free)
+const EnumPropertyItem *rna_enum_attribute_domain_itemf(ID *id,
+ bool include_instances,
+ bool *r_free)
{
EnumPropertyItem *item = NULL;
const EnumPropertyItem *domain_item = NULL;
@@ -188,6 +190,9 @@ const EnumPropertyItem *rna_enum_attribute_domain_itemf(ID *id, bool *r_free)
if (id_type == ID_ME && ELEM(domain_item->value, ATTR_DOMAIN_CURVE)) {
continue;
}
+ if (!include_instances && domain_item->value == ATTR_DOMAIN_INSTANCE) {
+ continue;
+ }
if (domain_item->value == ATTR_DOMAIN_POINT && id_type == ID_ME) {
RNA_enum_item_add(&item, &totitem, &mesh_vertex_domain_item);
@@ -207,7 +212,7 @@ static const EnumPropertyItem *rna_Attribute_domain_itemf(bContext *UNUSED(C),
PropertyRNA *UNUSED(prop),
bool *r_free)
{
- return rna_enum_attribute_domain_itemf(ptr->owner_id, r_free);
+ return rna_enum_attribute_domain_itemf(ptr->owner_id, true, r_free);
}
static int rna_Attribute_domain_get(PointerRNA *ptr)