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:
authorBrecht Van Lommel <brecht@blender.org>2020-07-03 16:30:04 +0300
committerBrecht Van Lommel <brecht@blender.org>2020-09-09 18:01:17 +0300
commit565510bd7fd87ae146cabafb27f1dfd550450f58 (patch)
tree57ff84b2aa4ba7e5c1dc0511be858d6b3bf156e6
parenta5db981b0ea044313239c3cc2ee92d19a8f682ea (diff)
Geometry: add .attributes in the Python API for Mesh, Hair and Point Cloud
This puts all generic float/int/vector/color/string geometry attributes in a new .attributes property. For meshes it provides a more general API for existing attributes, for point clouds attributes will be used as an essential part of particle nodes. This patch was implemented by @lichtwerk, with further changes by me. It's still a work in progress, but posting here to show what is going on and for early feedback. Ref T76659 Differential Revision: https://developer.blender.org/D8200
-rw-r--r--source/blender/blenkernel/BKE_attribute.h82
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/intern/attribute.c291
-rw-r--r--source/blender/blenkernel/intern/customdata.c56
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h10
-rw-r--r--source/blender/makesdna/DNA_hair_types.h2
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h3
-rw-r--r--source/blender/makesdna/DNA_pointcloud_types.h2
-rw-r--r--source/blender/makesrna/RNA_access.h12
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt1
-rw-r--r--source/blender/makesrna/intern/makesrna.c1
-rw-r--r--source/blender/makesrna/intern/rna_attribute.c662
-rw-r--r--source/blender/makesrna/intern/rna_hair.c4
-rw-r--r--source/blender/makesrna/intern/rna_internal.h8
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c3
-rw-r--r--source/blender/makesrna/intern/rna_pointcloud.c2
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_customdata.c87
17 files changed, 1187 insertions, 41 deletions
diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h
new file mode 100644
index 00000000000..9eba13ef7c4
--- /dev/null
+++ b/source/blender/blenkernel/BKE_attribute.h
@@ -0,0 +1,82 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ * \brief Generic geometry attributes built on CustomData.
+ */
+
+#pragma once
+
+#include "BLI_sys_types.h"
+
+#include "BKE_customdata.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct CustomData;
+struct CustomDataLayer;
+struct ID;
+struct PointerRNA;
+struct ReportList;
+
+/* Attribute.domain */
+typedef enum AttributeDomain {
+ ATTR_DOMAIN_VERTEX = 0, /* Mesh Vertex */
+ ATTR_DOMAIN_EDGE = 1, /* Mesh Edge */
+ ATTR_DOMAIN_CORNER = 2, /* Mesh Corner */
+ ATTR_DOMAIN_POLYGON = 3, /* Mesh Polygon */
+
+ ATTR_DOMAIN_POINT = 4, /* Hair or PointCloud Point */
+ ATTR_DOMAIN_CURVE = 5, /* Hair Curve */
+
+ ATTR_DOMAIN_NUM
+} AttributeDomain;
+
+/* Attributes */
+
+struct CustomDataLayer *BKE_id_attribute_new(struct ID *id,
+ const char *name,
+ const int type,
+ const AttributeDomain domain,
+ struct ReportList *reports);
+void BKE_id_attribute_remove(struct ID *id,
+ struct CustomDataLayer *layer,
+ struct ReportList *reports);
+
+AttributeDomain BKE_id_attribute_domain(struct ID *id, struct CustomDataLayer *layer);
+int BKE_id_attribute_data_length(struct ID *id, struct CustomDataLayer *layer);
+bool BKE_id_attribute_rename(struct ID *id,
+ struct CustomDataLayer *layer,
+ const char *new_name,
+ struct ReportList *reports);
+
+int BKE_id_attributes_length(struct ID *id, const CustomDataMask mask);
+
+struct CustomDataLayer *BKE_id_attributes_active_get(struct ID *id);
+void BKE_id_attributes_active_set(struct ID *id, struct CustomDataLayer *layer);
+int *BKE_id_attributes_active_index_p(struct ID *id);
+
+CustomData *BKE_id_attributes_iterator_next_domain(struct ID *id, struct CustomDataLayer *layers);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index bf3077b7743..cf43d0fe845 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -77,6 +77,7 @@ set(SRC
intern/armature.c
intern/armature_deform.c
intern/armature_update.c
+ intern/attribute.c
intern/autoexec.c
intern/blender.c
intern/blender_copybuffer.c
@@ -267,6 +268,7 @@ set(SRC
BKE_animsys.h
BKE_appdir.h
BKE_armature.h
+ BKE_attribute.h
BKE_autoexec.h
BKE_blender.h
BKE_blender_copybuffer.h
diff --git a/source/blender/blenkernel/intern/attribute.c b/source/blender/blenkernel/intern/attribute.c
new file mode 100644
index 00000000000..49c255fc065
--- /dev/null
+++ b/source/blender/blenkernel/intern/attribute.c
@@ -0,0 +1,291 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * Implementation of generic geometry attributes management. This is built
+ * on top of CustomData, which manages individual domains.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ID.h"
+#include "DNA_customdata_types.h"
+#include "DNA_hair_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_pointcloud_types.h"
+
+#include "BLI_string_utf8.h"
+
+#include "BKE_attribute.h"
+#include "BKE_customdata.h"
+#include "BKE_report.h"
+
+#include "RNA_access.h"
+
+typedef struct DomainInfo {
+ CustomData *customdata;
+ int length;
+} DomainInfo;
+
+static void get_domains(ID *id, DomainInfo info[ATTR_DOMAIN_NUM])
+{
+ memset(info, 0, sizeof(DomainInfo) * ATTR_DOMAIN_NUM);
+
+ switch (GS(id->name)) {
+ case ID_PT: {
+ PointCloud *pointcloud = (PointCloud *)id;
+ info[ATTR_DOMAIN_POINT].customdata = &pointcloud->pdata;
+ info[ATTR_DOMAIN_POINT].length = pointcloud->totpoint;
+ break;
+ }
+ case ID_ME: {
+ Mesh *mesh = (Mesh *)id;
+ info[ATTR_DOMAIN_VERTEX].customdata = &mesh->vdata;
+ info[ATTR_DOMAIN_VERTEX].length = mesh->totvert;
+ info[ATTR_DOMAIN_EDGE].customdata = &mesh->edata;
+ info[ATTR_DOMAIN_EDGE].length = mesh->totedge;
+ info[ATTR_DOMAIN_CORNER].customdata = &mesh->ldata;
+ info[ATTR_DOMAIN_CORNER].length = mesh->totloop;
+ info[ATTR_DOMAIN_POLYGON].customdata = &mesh->pdata;
+ info[ATTR_DOMAIN_POLYGON].length = mesh->totpoly;
+ break;
+ }
+ case ID_HA: {
+ Hair *hair = (Hair *)id;
+ info[ATTR_DOMAIN_POINT].customdata = &hair->pdata;
+ info[ATTR_DOMAIN_POINT].length = hair->totpoint;
+ info[ATTR_DOMAIN_CURVE].customdata = &hair->cdata;
+ info[ATTR_DOMAIN_CURVE].length = hair->totcurve;
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static CustomData *attribute_customdata_find(ID *id, CustomDataLayer *layer)
+{
+ DomainInfo info[ATTR_DOMAIN_NUM];
+ get_domains(id, info);
+
+ for (AttributeDomain domain = 0; domain < ATTR_DOMAIN_NUM; domain++) {
+ CustomData *customdata = info[domain].customdata;
+ if (customdata && ARRAY_HAS_ITEM(layer, customdata->layers, customdata->totlayer)) {
+ return customdata;
+ }
+ }
+
+ return NULL;
+}
+
+bool BKE_id_attribute_rename(ID *id,
+ CustomDataLayer *layer,
+ const char *new_name,
+ ReportList *reports)
+{
+ CustomData *customdata = attribute_customdata_find(id, layer);
+ if (customdata == NULL) {
+ BKE_report(reports, RPT_ERROR, "Attribute is not part of this geometry");
+ return false;
+ }
+
+ BLI_strncpy_utf8(layer->name, new_name, sizeof(layer->name));
+ CustomData_set_layer_unique_name(customdata, layer - customdata->layers);
+ return true;
+}
+
+CustomDataLayer *BKE_id_attribute_new(
+ ID *id, const char *name, const int type, const AttributeDomain domain, ReportList *reports)
+{
+ DomainInfo info[ATTR_DOMAIN_NUM];
+ get_domains(id, info);
+
+ CustomData *customdata = info[domain].customdata;
+ if (customdata == NULL) {
+ BKE_report(reports, RPT_ERROR, "Attribute domain not supported by this geometry type");
+ return NULL;
+ }
+
+ CustomData_add_layer_named(customdata, type, CD_DEFAULT, NULL, info[domain].length, name);
+ const int index = CustomData_get_named_layer_index(customdata, type, name);
+ return (index == -1) ? NULL : &(customdata->layers[index]);
+}
+
+void BKE_id_attribute_remove(ID *id, CustomDataLayer *layer, ReportList *reports)
+{
+ CustomData *customdata = attribute_customdata_find(id, layer);
+ const int index = (customdata) ?
+ CustomData_get_named_layer_index(customdata, layer->type, layer->name) :
+ -1;
+
+ if (index == -1) {
+ BKE_report(reports, RPT_ERROR, "Attribute is not part of this geometry");
+ return;
+ }
+
+ const int length = BKE_id_attribute_data_length(id, layer);
+ CustomData_free_layer(customdata, layer->type, length, index);
+}
+
+int BKE_id_attributes_length(ID *id, const CustomDataMask mask)
+{
+ DomainInfo info[ATTR_DOMAIN_NUM];
+ get_domains(id, info);
+
+ int length = 0;
+
+ for (AttributeDomain domain = 0; domain < ATTR_DOMAIN_NUM; domain++) {
+ CustomData *customdata = info[domain].customdata;
+ if (customdata) {
+ length += CustomData_number_of_layers_typemask(customdata, mask);
+ }
+ }
+
+ return length;
+}
+
+AttributeDomain BKE_id_attribute_domain(ID *id, CustomDataLayer *layer)
+{
+ DomainInfo info[ATTR_DOMAIN_NUM];
+ get_domains(id, info);
+
+ for (AttributeDomain domain = 0; domain < ATTR_DOMAIN_NUM; domain++) {
+ CustomData *customdata = info[domain].customdata;
+ if (customdata && ARRAY_HAS_ITEM(layer, customdata->layers, customdata->totlayer)) {
+ return domain;
+ }
+ }
+
+ BLI_assert(!"Custom data layer not found in geometry");
+ return ATTR_DOMAIN_NUM;
+}
+
+int BKE_id_attribute_data_length(ID *id, CustomDataLayer *layer)
+{
+ DomainInfo info[ATTR_DOMAIN_NUM];
+ get_domains(id, info);
+
+ for (AttributeDomain domain = 0; domain < ATTR_DOMAIN_NUM; domain++) {
+ CustomData *customdata = info[domain].customdata;
+ if (customdata && ARRAY_HAS_ITEM(layer, customdata->layers, customdata->totlayer)) {
+ return info[domain].length;
+ }
+ }
+
+ BLI_assert(!"Custom data layer not found in geometry");
+ return 0;
+}
+
+CustomDataLayer *BKE_id_attributes_active_get(ID *id)
+{
+ int active_index = *BKE_id_attributes_active_index_p(id);
+ if (active_index > BKE_id_attributes_length(id, CD_MASK_PROP_ALL)) {
+ active_index = 0;
+ }
+
+ DomainInfo info[ATTR_DOMAIN_NUM];
+ get_domains(id, info);
+
+ int index = 0;
+
+ for (AttributeDomain domain = 0; domain < ATTR_DOMAIN_NUM; domain++) {
+ CustomData *customdata = info[domain].customdata;
+ if (customdata) {
+ for (int i = 0; i < customdata->totlayer; i++) {
+ CustomDataLayer *layer = &customdata->layers[i];
+ if (CD_MASK_PROP_ALL & CD_TYPE_AS_MASK(layer->type)) {
+ if (index == active_index) {
+ return layer;
+ }
+ index++;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+void BKE_id_attributes_active_set(ID *id, CustomDataLayer *active_layer)
+{
+ DomainInfo info[ATTR_DOMAIN_NUM];
+ get_domains(id, info);
+
+ int index = 0;
+
+ for (AttributeDomain domain = 0; domain < ATTR_DOMAIN_NUM; domain++) {
+ CustomData *customdata = info[domain].customdata;
+ if (customdata) {
+ for (int i = 0; i < customdata->totlayer; i++) {
+ CustomDataLayer *layer = &customdata->layers[i];
+ if (layer == active_layer) {
+ *BKE_id_attributes_active_index_p(id) = index;
+ return;
+ }
+ if (CD_MASK_PROP_ALL & CD_TYPE_AS_MASK(layer->type)) {
+ index++;
+ }
+ }
+ }
+ }
+}
+
+int *BKE_id_attributes_active_index_p(ID *id)
+{
+ switch (GS(id->name)) {
+ case ID_PT: {
+ return &((PointCloud *)id)->attributes_active_index;
+ }
+ case ID_ME: {
+ return &((Mesh *)id)->attributes_active_index;
+ }
+ case ID_HA: {
+ return &((Hair *)id)->attributes_active_index;
+ }
+ default:
+ return NULL;
+ }
+}
+
+CustomData *BKE_id_attributes_iterator_next_domain(ID *id, CustomDataLayer *layers)
+{
+ DomainInfo info[ATTR_DOMAIN_NUM];
+ get_domains(id, info);
+
+ bool use_next = (layers == NULL);
+
+ for (AttributeDomain domain = 0; domain < ATTR_DOMAIN_NUM; domain++) {
+ CustomData *customdata = info[domain].customdata;
+ if (customdata && customdata->layers) {
+ if (customdata->layers == layers) {
+ use_next = true;
+ }
+ else if (use_next) {
+ return customdata;
+ }
+ }
+ }
+
+ return NULL;
+}
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index b10d910cd66..7c244ed8f58 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -33,7 +33,6 @@
#include "DNA_customdata_types.h"
#include "DNA_hair_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_pointcloud_types.h"
#include "BLI_bitmap.h"
#include "BLI_endian_switch.h"
@@ -1976,43 +1975,42 @@ const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX = {
};
const CustomData_MeshMasks CD_MASK_MESH = {
.vmask = (CD_MASK_MVERT | CD_MASK_MDEFORMVERT | CD_MASK_MVERT_SKIN | CD_MASK_PAINT_MASK |
- CD_MASK_GENERIC_DATA | CD_MASK_PROP_COLOR),
- .emask = (CD_MASK_MEDGE | CD_MASK_FREESTYLE_EDGE | CD_MASK_GENERIC_DATA),
+ CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR),
+ .emask = (CD_MASK_MEDGE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
.fmask = 0,
.lmask = (CD_MASK_MLOOP | CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL |
- CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_GENERIC_DATA),
+ CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
.pmask = (CD_MASK_MPOLY | CD_MASK_RECAST | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE |
- CD_MASK_GENERIC_DATA | CD_MASK_SCULPT_FACE_SETS),
+ CD_MASK_PROP_ALL | CD_MASK_SCULPT_FACE_SETS),
};
const CustomData_MeshMasks CD_MASK_EDITMESH = {
.vmask = (CD_MASK_MDEFORMVERT | CD_MASK_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY |
- CD_MASK_SHAPE_KEYINDEX | CD_MASK_GENERIC_DATA | CD_MASK_PROP_COLOR),
- .emask = (CD_MASK_GENERIC_DATA),
+ CD_MASK_SHAPE_KEYINDEX | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR),
+ .emask = (CD_MASK_PROP_ALL),
.fmask = 0,
.lmask = (CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_CUSTOMLOOPNORMAL |
- CD_MASK_GRID_PAINT_MASK | CD_MASK_GENERIC_DATA),
- .pmask = (CD_MASK_RECAST | CD_MASK_FACEMAP | CD_MASK_GENERIC_DATA | CD_MASK_SCULPT_FACE_SETS),
+ CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
+ .pmask = (CD_MASK_RECAST | CD_MASK_FACEMAP | CD_MASK_PROP_ALL | CD_MASK_SCULPT_FACE_SETS),
};
const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
.vmask = (CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT | CD_MASK_SHAPEKEY | CD_MASK_MVERT_SKIN |
- CD_MASK_ORCO | CD_MASK_CLOTH_ORCO | CD_MASK_GENERIC_DATA | CD_MASK_PROP_COLOR),
- .emask = (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_GENERIC_DATA),
+ CD_MASK_ORCO | CD_MASK_CLOTH_ORCO | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR),
+ .emask = (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
.fmask = (CD_MASK_ORIGINDEX | CD_MASK_ORIGSPACE | CD_MASK_PREVIEW_MCOL | CD_MASK_TANGENT),
.lmask = (CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_CUSTOMLOOPNORMAL |
CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP |
- CD_MASK_GENERIC_DATA), /* XXX MISSING CD_MASK_MLOOPTANGENT ? */
+ CD_MASK_PROP_ALL), /* XXX MISSING CD_MASK_MLOOPTANGENT ? */
.pmask = (CD_MASK_ORIGINDEX | CD_MASK_RECAST | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP |
- CD_MASK_GENERIC_DATA | CD_MASK_SCULPT_FACE_SETS),
+ CD_MASK_PROP_ALL | CD_MASK_SCULPT_FACE_SETS),
};
const CustomData_MeshMasks CD_MASK_BMESH = {
.vmask = (CD_MASK_MDEFORMVERT | CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY |
- CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK | CD_MASK_GENERIC_DATA |
- CD_MASK_PROP_COLOR),
- .emask = (CD_MASK_BWEIGHT | CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_GENERIC_DATA),
+ CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR),
+ .emask = (CD_MASK_BWEIGHT | CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
.fmask = 0,
.lmask = (CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_CUSTOMLOOPNORMAL |
- CD_MASK_GRID_PAINT_MASK | CD_MASK_GENERIC_DATA),
- .pmask = (CD_MASK_RECAST | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_GENERIC_DATA |
+ CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
+ .pmask = (CD_MASK_RECAST | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL |
CD_MASK_SCULPT_FACE_SETS),
};
/**
@@ -2031,18 +2029,18 @@ const CustomData_MeshMasks CD_MASK_EVERYTHING = {
.vmask = (CD_MASK_MVERT | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_NORMAL |
CD_MASK_MDEFORMVERT | CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_ORCO |
CD_MASK_CLOTH_ORCO | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK |
- CD_MASK_GENERIC_DATA | CD_MASK_PROP_COLOR),
+ CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR),
.emask = (CD_MASK_MEDGE | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_BWEIGHT |
- CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_GENERIC_DATA),
+ CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
.fmask = (CD_MASK_MFACE | CD_MASK_ORIGINDEX | CD_MASK_NORMAL | CD_MASK_MTFACE | CD_MASK_MCOL |
CD_MASK_ORIGSPACE | CD_MASK_TANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_PREVIEW_MCOL |
- CD_MASK_GENERIC_DATA),
+ CD_MASK_PROP_ALL),
.lmask = (CD_MASK_MLOOP | CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL |
CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_CUSTOMLOOPNORMAL |
CD_MASK_MLOOPTANGENT | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP |
- CD_MASK_GRID_PAINT_MASK | CD_MASK_GENERIC_DATA),
+ CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
.pmask = (CD_MASK_MPOLY | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_NORMAL |
- CD_MASK_RECAST | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_GENERIC_DATA |
+ CD_MASK_RECAST | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL |
CD_MASK_SCULPT_FACE_SETS),
};
@@ -4306,14 +4304,6 @@ int CustomData_layertype_layers_max(const int type)
return typeInfo->layers_max();
}
-static bool CustomData_is_property_layer(int type)
-{
- if ((type == CD_PROP_FLOAT) || (type == CD_PROP_INT32) || (type == CD_PROP_STRING)) {
- return true;
- }
- return false;
-}
-
static bool cd_layer_find_dupe(CustomData *data, const char *name, int type, int index)
{
/* see if there is a duplicate */
@@ -4321,8 +4311,8 @@ static bool cd_layer_find_dupe(CustomData *data, const char *name, int type, int
if (i != index) {
CustomDataLayer *layer = &data->layers[i];
- if (CustomData_is_property_layer(type)) {
- if (CustomData_is_property_layer(layer->type) && STREQ(layer->name, name)) {
+ if (CD_TYPE_AS_MASK(type) & CD_MASK_PROP_ALL) {
+ if ((CD_TYPE_AS_MASK(layer->type) & CD_MASK_PROP_ALL) && STREQ(layer->name, name)) {
return true;
}
}
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
index 2990fa85c27..51b233449bf 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -209,17 +209,17 @@ typedef enum CustomDataType {
#define CD_MASK_PROP_FLOAT3 (1ULL << CD_PROP_FLOAT3)
#define CD_MASK_PROP_FLOAT2 (1ULL << CD_PROP_FLOAT2)
-/** Data types that may be defined for all mesh elements types. */
-#define CD_MASK_GENERIC_DATA \
- (CD_MASK_PROP_FLOAT | CD_MASK_PROP_INT32 | CD_MASK_PROP_STRING | CD_MASK_PROP_FLOAT3 | \
- CD_MASK_PROP_FLOAT2)
-
/** Multires loop data. */
#define CD_MASK_MULTIRES_GRIDS (CD_MASK_MDISPS | CD_GRID_PAINT_MASK)
/* All data layers. */
#define CD_MASK_ALL (~0LL)
+/* All generic attributes. */
+#define CD_MASK_PROP_ALL \
+ (CD_MASK_PROP_FLOAT | CD_MASK_PROP_FLOAT2 | CD_MASK_PROP_FLOAT3 | CD_MASK_PROP_INT32 | \
+ CD_MASK_PROP_COLOR | CD_MASK_PROP_STRING | CD_MASK_MLOOPCOL)
+
typedef struct CustomData_MeshMasks {
uint64_t vmask;
uint64_t emask;
diff --git a/source/blender/makesdna/DNA_hair_types.h b/source/blender/makesdna/DNA_hair_types.h
index d120e61cfef..27799560395 100644
--- a/source/blender/makesdna/DNA_hair_types.h
+++ b/source/blender/makesdna/DNA_hair_types.h
@@ -56,6 +56,8 @@ typedef struct Hair {
/* Custom Data */
struct CustomData pdata;
struct CustomData cdata;
+ int attributes_active_index;
+ int _pad3;
/* Material */
struct Material **mat;
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index a6aef5b08ad..abfa3cc1b2e 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -191,6 +191,9 @@ typedef struct Mesh {
int totpoly, totloop;
/* END BMESH ONLY */
+ int attributes_active_index;
+ int _pad3;
+
/* the last selected vertex/edge/face are used for the active face however
* this means the active face must always be selected, this is to keep track
* of the last selected face and is similar to the old active face flag where
diff --git a/source/blender/makesdna/DNA_pointcloud_types.h b/source/blender/makesdna/DNA_pointcloud_types.h
index d3b687c2c68..86cff098096 100644
--- a/source/blender/makesdna/DNA_pointcloud_types.h
+++ b/source/blender/makesdna/DNA_pointcloud_types.h
@@ -38,6 +38,8 @@ typedef struct PointCloud {
/* Custom Data */
struct CustomData pdata;
+ int attributes_active_index;
+ int _pad4;
/* Material */
struct Material **mat;
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 6acd9d16f80..8ee10047750 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -67,6 +67,8 @@ extern StructRNA RNA_ArmatureGpencilModifier;
extern StructRNA RNA_ArmatureModifier;
extern StructRNA RNA_ArrayGpencilModifier;
extern StructRNA RNA_ArrayModifier;
+extern StructRNA RNA_Attribute;
+extern StructRNA RNA_AttributeGroup;
extern StructRNA RNA_BackgroundImage;
extern StructRNA RNA_BevelModifier;
extern StructRNA RNA_BezierSplinePoint;
@@ -93,6 +95,8 @@ extern StructRNA RNA_BrushCapabilitiesVertexPaint;
extern StructRNA RNA_BrushTextureSlot;
extern StructRNA RNA_BuildGpencilModifier;
extern StructRNA RNA_BuildModifier;
+extern StructRNA RNA_ByteColorAttribute;
+extern StructRNA RNA_ByteColorAttributeValue;
extern StructRNA RNA_CacheFile;
extern StructRNA RNA_Camera;
extern StructRNA RNA_CameraDOFSettings;
@@ -247,6 +251,10 @@ extern StructRNA RNA_FaceMap;
extern StructRNA RNA_FieldSettings;
extern StructRNA RNA_FileBrowserFSMenuEntry;
extern StructRNA RNA_FileSelectParams;
+extern StructRNA RNA_FloatAttribute;
+extern StructRNA RNA_FloatAttributeValue;
+extern StructRNA RNA_FloatColorAttribute;
+extern StructRNA RNA_FloatColorAttributeValue;
extern StructRNA RNA_FloatProperty;
extern StructRNA RNA_FloorConstraint;
extern StructRNA RNA_FluidDomainSettings;
@@ -292,6 +300,8 @@ extern StructRNA RNA_ImagePreview;
extern StructRNA RNA_ImageSequence;
extern StructRNA RNA_ImageTexture;
extern StructRNA RNA_ImageUser;
+extern StructRNA RNA_IntAttribute;
+extern StructRNA RNA_IntAttributeValue;
extern StructRNA RNA_IntProperty;
extern StructRNA RNA_Itasc;
extern StructRNA RNA_Key;
@@ -588,6 +598,8 @@ extern StructRNA RNA_SplinePoint;
extern StructRNA RNA_SpotLight;
extern StructRNA RNA_Stereo3dDisplay;
extern StructRNA RNA_StretchToConstraint;
+extern StructRNA RNA_StringAttribute;
+extern StructRNA RNA_StringAttributeValue;
extern StructRNA RNA_StringProperty;
extern StructRNA RNA_Struct;
extern StructRNA RNA_StucciTexture;
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 303005a0f9e..0387f83d695 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -30,6 +30,7 @@ set(DEFSRC
rna_animation.c
rna_animviz.c
rna_armature.c
+ rna_attribute.c
rna_boid.c
rna_brush.c
rna_cachefile.c
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index a81bd4d0832..f1086ab69bc 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -4276,6 +4276,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_animation.c", "rna_animation_api.c", RNA_def_animation},
{"rna_animviz.c", NULL, RNA_def_animviz},
{"rna_armature.c", "rna_armature_api.c", RNA_def_armature},
+ {"rna_attribute.c", NULL, RNA_def_attribute},
{"rna_boid.c", NULL, RNA_def_boid},
{"rna_brush.c", NULL, RNA_def_brush},
{"rna_cachefile.c", NULL, RNA_def_cachefile},
diff --git a/source/blender/makesrna/intern/rna_attribute.c b/source/blender/makesrna/intern/rna_attribute.c
new file mode 100644
index 00000000000..a0bb5f67a08
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_attribute.c
@@ -0,0 +1,662 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup RNA
+ */
+
+#include <stdlib.h>
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
+#include "DNA_customdata_types.h"
+#include "DNA_hair_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_pointcloud_types.h"
+
+#include "BKE_attribute.h"
+#include "BKE_customdata.h"
+
+#include "WM_types.h"
+
+static const EnumPropertyItem rna_enum_attribute_type_items[] = {
+ {CD_PROP_FLOAT, "FLOAT", 0, "Float", "Floating point value"},
+ {CD_PROP_INT32, "INT", 0, "Integer", "32 bit integer"},
+ {CD_PROP_FLOAT3, "FLOAT_VECTOR", 0, "Vector", "3D vector with floating point values"},
+ {CD_PROP_COLOR, "FLOAT_COLOR", 0, "Float Color", "RGBA color with floating point precisions"},
+ {CD_MLOOPCOL, "BYTE_COLOR", 0, "Byte Color", "RGBA color with 8-bit precision"},
+ {CD_PROP_STRING, "STRING", 0, "String", "Text string"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static const EnumPropertyItem rna_enum_attribute_domain_items[] = {
+ /* Not implement yet
+ {ATTR_DOMAIN_GEOMETRY, "GEOMETRY", 0, "Geometry", "Attribute on (whole) geometry"}, */
+ {ATTR_DOMAIN_VERTEX, "VERTEX", 0, "Vertex", "Attribute on mesh vertex"},
+ {ATTR_DOMAIN_EDGE, "EDGE", 0, "Edge", "Attribute on mesh edge"},
+ {ATTR_DOMAIN_CORNER, "CORNER", 0, "Corner", "Attribute on mesh polygon corner"},
+ {ATTR_DOMAIN_POLYGON, "POLYGON", 0, "Polygon", "Attribute on mesh polygons"},
+ /* Not implement yet
+ {ATTR_DOMAIN_GRIDS, "GRIDS", 0, "Grids", "Attribute on mesh multires grids"}, */
+ {ATTR_DOMAIN_POINT, "POINT", 0, "Point", "Attribute on point"},
+ {ATTR_DOMAIN_CURVE, "CURVE", 0, "Curve", "Attribute on hair curve"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+#ifdef RNA_RUNTIME
+
+# include "BLI_math.h"
+
+# include "DEG_depsgraph.h"
+
+# include "WM_api.h"
+
+/* Attribute */
+
+static char *rna_Attribute_path(PointerRNA *ptr)
+{
+ CustomDataLayer *layer = ptr->data;
+ return BLI_sprintfN("attributes['%s']", layer->name);
+}
+
+static void rna_Attribute_name_set(PointerRNA *ptr, const char *value)
+{
+ BKE_id_attribute_rename(ptr->owner_id, ptr->data, value, NULL);
+}
+
+static int rna_Attribute_type_get(PointerRNA *ptr)
+{
+ CustomDataLayer *layer = ptr->data;
+ return layer->type;
+}
+
+static const EnumPropertyItem *rna_Attribute_domain_itemf(bContext *UNUSED(C),
+ PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ EnumPropertyItem *item = NULL;
+ const EnumPropertyItem *domain_item = NULL;
+ ID *id = ptr->owner_id;
+ const ID_Type id_type = GS(id->name);
+ int totitem = 0, a;
+
+ for (a = 0; rna_enum_attribute_domain_items[a].identifier; a++) {
+ domain_item = &rna_enum_attribute_domain_items[a];
+
+ if (id_type == ID_PT && !ELEM(domain_item->value, ATTR_DOMAIN_POINT)) {
+ continue;
+ }
+ if (id_type == ID_HA && !ELEM(domain_item->value, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE)) {
+ continue;
+ }
+ if (id_type == ID_ME && ELEM(domain_item->value, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE)) {
+ continue;
+ }
+
+ RNA_enum_item_add(&item, &totitem, domain_item);
+ }
+ RNA_enum_item_end(&item, &totitem);
+
+ *r_free = true;
+ return item;
+}
+
+static int rna_Attribute_domain_get(PointerRNA *ptr)
+{
+ return BKE_id_attribute_domain(ptr->owner_id, ptr->data);
+}
+
+static void rna_Attribute_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ ID *id = ptr->owner_id;
+ CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
+
+ int length = BKE_id_attribute_data_length(id, layer);
+ size_t struct_size;
+
+ switch (layer->type) {
+ case CD_PROP_FLOAT:
+ struct_size = sizeof(MFloatProperty);
+ break;
+ case CD_PROP_INT32:
+ struct_size = sizeof(MIntProperty);
+ break;
+ case CD_PROP_FLOAT3:
+ struct_size = sizeof(float[3]);
+ break;
+ case CD_PROP_COLOR:
+ struct_size = sizeof(MPropCol);
+ break;
+ case CD_MLOOPCOL:
+ struct_size = sizeof(MLoopCol);
+ break;
+ case CD_PROP_STRING:
+ struct_size = sizeof(MStringProperty);
+ break;
+ default:
+ struct_size = 0;
+ length = 0;
+ break;
+ }
+
+ rna_iterator_array_begin(iter, layer->data, struct_size, length, 0, NULL);
+}
+
+static int rna_Attribute_data_length(PointerRNA *ptr)
+{
+ ID *id = ptr->owner_id;
+ CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
+ return BKE_id_attribute_data_length(id, layer);
+}
+
+static void rna_Attribute_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ ID *id = ptr->owner_id;
+
+ /* cheating way for importers to avoid slow updates */
+ if (id->us > 0) {
+ DEG_id_tag_update(id, 0);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, id);
+ }
+}
+
+/* Color Attribute */
+
+static void rna_ByteColorAttributeValue_color_get(PointerRNA *ptr, float *values)
+{
+ MLoopCol *mlcol = (MLoopCol *)ptr->data;
+ srgb_to_linearrgb_uchar4(values, &mlcol->r);
+}
+
+static void rna_ByteColorAttributeValue_color_set(PointerRNA *ptr, const float *values)
+{
+ MLoopCol *mlcol = (MLoopCol *)ptr->data;
+ linearrgb_to_srgb_uchar4(&mlcol->r, values);
+}
+
+/* Attribute Group */
+
+static PointerRNA rna_AttributeGroup_new(
+ ID *id, ReportList *reports, const char *name, const int type, const int domain)
+{
+ CustomDataLayer *layer = BKE_id_attribute_new(id, name, type, domain, reports);
+ DEG_id_tag_update(id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, id);
+
+ PointerRNA ptr;
+ RNA_pointer_create(id, &RNA_Attribute, layer, &ptr);
+ return ptr;
+}
+
+static void rna_AttributeGroup_remove(ID *id, ReportList *reports, PointerRNA *attribute_ptr)
+{
+ CustomDataLayer *layer = (CustomDataLayer *)attribute_ptr->data;
+ BKE_id_attribute_remove(id, layer, reports);
+ RNA_POINTER_INVALIDATE(attribute_ptr);
+
+ DEG_id_tag_update(id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, id);
+}
+
+static int rna_Attributes_layer_skip(CollectionPropertyIterator *UNUSED(iter), void *data)
+{
+ CustomDataLayer *layer = (CustomDataLayer *)data;
+ return !(CD_TYPE_AS_MASK(layer->type) & CD_MASK_PROP_ALL);
+}
+
+/* Attributes are spread over multiple domains in separate CustomData, we use repeated
+ * array iterators to loop over all. */
+static void rna_AttributeGroup_next_domain(ID *id,
+ CollectionPropertyIterator *iter,
+ int(skip)(CollectionPropertyIterator *iter, void *data))
+{
+ do {
+ CustomDataLayer *prev_layers = (CustomDataLayer *)iter->internal.array.endptr -
+ iter->internal.array.length;
+ CustomData *customdata = BKE_id_attributes_iterator_next_domain(id, prev_layers);
+ if (customdata == NULL) {
+ return;
+ }
+ rna_iterator_array_begin(
+ iter, customdata->layers, sizeof(CustomDataLayer), customdata->totlayer, false, skip);
+ } while (!iter->valid);
+}
+
+void rna_AttributeGroup_iterator_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ memset(&iter->internal.array, 0, sizeof(iter->internal.array));
+ rna_AttributeGroup_next_domain(ptr->owner_id, iter, rna_Attributes_layer_skip);
+}
+
+void rna_AttributeGroup_iterator_next(CollectionPropertyIterator *iter)
+{
+ rna_iterator_array_next(iter);
+
+ if (!iter->valid) {
+ ID *id = iter->parent.owner_id;
+ rna_AttributeGroup_next_domain(id, iter, rna_Attributes_layer_skip);
+ }
+}
+
+PointerRNA rna_AttributeGroup_iterator_get(CollectionPropertyIterator *iter)
+{
+ /* refine to the proper type */
+ StructRNA *type;
+ CustomDataLayer *layer = rna_iterator_array_get(iter);
+
+ switch (layer->type) {
+ case CD_PROP_FLOAT:
+ type = &RNA_FloatAttribute;
+ break;
+ case CD_PROP_INT32:
+ type = &RNA_IntAttribute;
+ break;
+ case CD_PROP_FLOAT3:
+ type = &RNA_FloatVectorAttribute;
+ break;
+ case CD_PROP_COLOR:
+ type = &RNA_FloatColorAttribute;
+ break;
+ case CD_MLOOPCOL:
+ type = &RNA_ByteColorAttribute;
+ break;
+ case CD_PROP_STRING:
+ type = &RNA_StringAttribute;
+ break;
+ default:
+ return PointerRNA_NULL;
+ }
+
+ return rna_pointer_inherit_refine(&iter->parent, type, layer);
+}
+
+int rna_AttributeGroup_length(PointerRNA *ptr)
+{
+ return BKE_id_attributes_length(ptr->owner_id, CD_MASK_PROP_ALL);
+}
+
+static int rna_AttributeGroup_active_index_get(PointerRNA *ptr)
+{
+ return *BKE_id_attributes_active_index_p(ptr->owner_id);
+}
+
+static PointerRNA rna_AttributeGroup_active_get(PointerRNA *ptr)
+{
+ ID *id = ptr->owner_id;
+ CustomDataLayer *layer = BKE_id_attributes_active_get(id);
+
+ PointerRNA attribute_ptr;
+ RNA_pointer_create(id, &RNA_Attribute, layer, &attribute_ptr);
+ return attribute_ptr;
+}
+
+static void rna_AttributeGroup_active_set(PointerRNA *ptr,
+ PointerRNA attribute_ptr,
+ ReportList *UNUSED(reports))
+{
+ ID *id = ptr->owner_id;
+ CustomDataLayer *layer = attribute_ptr.data;
+ BKE_id_attributes_active_set(id, layer);
+}
+
+static void rna_AttributeGroup_active_index_set(PointerRNA *ptr, int value)
+{
+ *BKE_id_attributes_active_index_p(ptr->owner_id) = value;
+}
+
+static void rna_AttributeGroup_active_index_range(
+ PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+{
+ *min = 0;
+ *max = BKE_id_attributes_length(ptr->owner_id, CD_MASK_PROP_ALL);
+
+ *softmin = *min;
+ *softmax = *max;
+}
+
+static void rna_AttributeGroup_update_active(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ rna_Attribute_update_data(bmain, scene, ptr);
+}
+
+#else
+
+static void rna_def_attribute_float(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "FloatAttribute", "Attribute");
+ RNA_def_struct_sdna(srna, "CustomDataLayer");
+ RNA_def_struct_ui_text(srna, "Float Attribute", "Geometry attribute with floating point values");
+
+ prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "FloatAttributeValue");
+ RNA_def_property_collection_funcs(prop,
+ "rna_Attribute_data_begin",
+ "rna_iterator_array_next",
+ "rna_iterator_array_end",
+ "rna_iterator_array_get",
+ "rna_Attribute_data_length",
+ NULL,
+ NULL,
+ NULL);
+
+ srna = RNA_def_struct(brna, "FloatAttributeValue", NULL);
+ RNA_def_struct_sdna(srna, "MFloatProperty");
+ RNA_def_struct_ui_text(
+ srna, "Float Attribute Value", "Floating point value in geometry attribute");
+ prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "f");
+ RNA_def_property_update(prop, 0, "rna_Attribute_update_data");
+}
+
+static void rna_def_attribute_float_vector(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ /* Float Vector Attribute */
+ srna = RNA_def_struct(brna, "FloatVectorAttribute", "Attribute");
+ RNA_def_struct_sdna(srna, "CustomDataLayer");
+ RNA_def_struct_ui_text(
+ srna, "Float Vector Attribute", "Vector geometry attribute, with floating point precision");
+
+ prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "FloatVectorAttributeValue");
+ RNA_def_property_collection_funcs(prop,
+ "rna_Attribute_data_begin",
+ "rna_iterator_array_next",
+ "rna_iterator_array_end",
+ "rna_iterator_array_get",
+ "rna_Attribute_data_length",
+ NULL,
+ NULL,
+ NULL);
+
+ /* Float Vector Attribute Value */
+ srna = RNA_def_struct(brna, "FloatVectorAttributeValue", NULL);
+ RNA_def_struct_sdna(srna, "vec3f");
+ RNA_def_struct_ui_text(
+ srna, "Float Vector Attribute Value", "Vector value in geometry attribute");
+
+ prop = RNA_def_property(srna, "vector", PROP_FLOAT, PROP_DIRECTION);
+ RNA_def_property_ui_text(prop, "Vector", "3D vector");
+ RNA_def_property_float_sdna(prop, NULL, "x");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_update(prop, 0, "rna_Attribute_update_data");
+}
+
+static void rna_def_attribute_float_color(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ /* Float Color Attribute */
+ srna = RNA_def_struct(brna, "FloatColorAttribute", "Attribute");
+ RNA_def_struct_sdna(srna, "CustomDataLayer");
+ RNA_def_struct_ui_text(
+ srna, "Float Color Attribute", "Color geometry attribute, with floating point precision");
+
+ prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "FloatColorAttributeValue");
+ RNA_def_property_collection_funcs(prop,
+ "rna_Attribute_data_begin",
+ "rna_iterator_array_next",
+ "rna_iterator_array_end",
+ "rna_iterator_array_get",
+ "rna_Attribute_data_length",
+ NULL,
+ NULL,
+ NULL);
+
+ /* Float Color Attribute Value */
+ srna = RNA_def_struct(brna, "FloatColorAttributeValue", NULL);
+ RNA_def_struct_sdna(srna, "MPropCol");
+ RNA_def_struct_ui_text(srna, "Float Color Attribute Value", "Color value in geometry attribute");
+
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_ui_text(prop, "Color", "RGBA color in scene linear color space");
+ RNA_def_property_float_sdna(prop, NULL, "color");
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_update(prop, 0, "rna_Attribute_update_data");
+}
+
+static void rna_def_attribute_byte_color(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ /* Byte Color Attribute */
+ srna = RNA_def_struct(brna, "ByteColorAttribute", "Attribute");
+ RNA_def_struct_sdna(srna, "CustomDataLayer");
+ RNA_def_struct_ui_text(
+ srna, "Byte Color Attribute", "Color geometry attribute, with 8-bit precision");
+
+ prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "ByteColorAttributeValue");
+ RNA_def_property_collection_funcs(prop,
+ "rna_Attribute_data_begin",
+ "rna_iterator_array_next",
+ "rna_iterator_array_end",
+ "rna_iterator_array_get",
+ "rna_Attribute_data_length",
+ NULL,
+ NULL,
+ NULL);
+
+ /* Byte Color Attribute Value */
+ srna = RNA_def_struct(brna, "ByteColorAttributeValue", NULL);
+ RNA_def_struct_sdna(srna, "MLoopCol");
+ RNA_def_struct_ui_text(srna, "Byte Color Attribute Value", "Color value in geometry attribute");
+
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_float_funcs(prop,
+ "rna_ByteColorAttributeValue_color_get",
+ "rna_ByteColorAttributeValue_color_set",
+ NULL);
+ RNA_def_property_ui_text(prop, "Color", "RGBA color in scene linear color space");
+ RNA_def_property_update(prop, 0, "rna_Attribute_update_data");
+}
+
+static void rna_def_attribute_int(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "IntAttribute", "Attribute");
+ RNA_def_struct_sdna(srna, "CustomDataLayer");
+ RNA_def_struct_ui_text(srna, "Int Attribute", "Integer geometry attribute");
+
+ prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "IntAttributeValue");
+ RNA_def_property_collection_funcs(prop,
+ "rna_Attribute_data_begin",
+ "rna_iterator_array_next",
+ "rna_iterator_array_end",
+ "rna_iterator_array_get",
+ "rna_Attribute_data_length",
+ NULL,
+ NULL,
+ NULL);
+
+ srna = RNA_def_struct(brna, "IntAttributeValue", NULL);
+ RNA_def_struct_sdna(srna, "MIntProperty");
+ RNA_def_struct_ui_text(srna, "Integer Attribute Value", "Integer value in geometry attribute");
+ prop = RNA_def_property(srna, "value", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "i");
+ RNA_def_property_update(prop, 0, "rna_Attribute_update_data");
+}
+
+static void rna_def_attribute_string(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "StringAttribute", "Attribute");
+ RNA_def_struct_sdna(srna, "CustomDataLayer");
+ RNA_def_struct_ui_text(srna, "String Attribute", "String geometry attribute");
+
+ prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "StringAttributeValue");
+ RNA_def_property_collection_funcs(prop,
+ "rna_Attribute_data_begin",
+ "rna_iterator_array_next",
+ "rna_iterator_array_end",
+ "rna_iterator_array_get",
+ "rna_Attribute_data_length",
+ NULL,
+ NULL,
+ NULL);
+
+ srna = RNA_def_struct(brna, "StringAttributeValue", NULL);
+ RNA_def_struct_sdna(srna, "MStringProperty");
+ RNA_def_struct_ui_text(srna, "String Attribute Value", "String value in geometry attribute");
+ prop = RNA_def_property(srna, "value", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "s");
+ RNA_def_property_update(prop, 0, "rna_Attribute_update_data");
+}
+
+static void rna_def_attribute(BlenderRNA *brna)
+{
+ PropertyRNA *prop;
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, "Attribute", NULL);
+ RNA_def_struct_sdna(srna, "CustomDataLayer");
+ RNA_def_struct_ui_text(srna, "Attribute", "Geometry attribute");
+ RNA_def_struct_path_func(srna, "rna_Attribute_path");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Attribute_name_set");
+ RNA_def_property_ui_text(prop, "Name", "Name of the Attribute");
+ RNA_def_struct_name_property(srna, prop);
+
+ prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, rna_enum_attribute_type_items);
+ RNA_def_property_enum_funcs(prop, "rna_Attribute_type_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Data Type", "Type of data stored in attribute");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "domain", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_enum_attribute_domain_items);
+ RNA_def_property_enum_funcs(
+ prop, "rna_Attribute_domain_get", NULL, "rna_Attribute_domain_itemf");
+ RNA_def_property_ui_text(prop, "Domain", "Domain of the Attribute");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ /* types */
+ rna_def_attribute_float(brna);
+ rna_def_attribute_float_vector(brna);
+ rna_def_attribute_float_color(brna);
+ rna_def_attribute_byte_color(brna);
+ rna_def_attribute_int(brna);
+ rna_def_attribute_string(brna);
+}
+
+/* Mesh/PointCloud/Hair.attributes */
+static void rna_def_attribute_group(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ srna = RNA_def_struct(brna, "AttributeGroup", NULL);
+ RNA_def_struct_ui_text(srna, "Attribute Group", "Group of geometry attributes");
+ RNA_def_struct_sdna(srna, "ID");
+
+ /* API */
+ func = RNA_def_function(srna, "new", "rna_AttributeGroup_new");
+ RNA_def_function_ui_description(func, "Add an attribute");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_string(func, "name", "Attribute", 0, "", "Attribute name");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_enum(
+ func, "type", rna_enum_attribute_type_items, CD_PROP_FLOAT, "Type", "Attribute type");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_enum(func,
+ "domain",
+ rna_enum_attribute_domain_items,
+ ATTR_DOMAIN_VERTEX,
+ "Domain",
+ "Attribute domain");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "attribute", "Attribute", "", "New geometry attribute");
+ RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_AttributeGroup_remove");
+ RNA_def_function_ui_description(func, "Remove an attribute");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "attribute", "Attribute", "", "Geometry Attribute");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
+
+ /* Active */
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Attribute");
+ RNA_def_property_pointer_funcs(
+ prop, "rna_AttributeGroup_active_get", "rna_AttributeGroup_active_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
+ RNA_def_property_ui_text(prop, "Active Attribute", "Active attribute");
+ RNA_def_property_update(prop, 0, "rna_AttributeGroup_update_active");
+
+ prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_int_funcs(prop,
+ "rna_AttributeGroup_active_index_get",
+ "rna_AttributeGroup_active_index_set",
+ "rna_AttributeGroup_active_index_range");
+ RNA_def_property_update(prop, 0, "rna_AttributeGroup_update_active");
+}
+
+void rna_def_attributes_common(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ /* Attributes */
+ prop = RNA_def_property(srna, "attributes", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_funcs(prop,
+ "rna_AttributeGroup_iterator_begin",
+ "rna_AttributeGroup_iterator_next",
+ "rna_iterator_array_end",
+ "rna_AttributeGroup_iterator_get",
+ "rna_AttributeGroup_length",
+ NULL,
+ NULL,
+ NULL);
+ RNA_def_property_struct_type(prop, "Attribute");
+ RNA_def_property_ui_text(prop, "Attributes", "Geometry attributes");
+ RNA_def_property_srna(prop, "AttributeGroup");
+}
+
+void RNA_def_attribute(BlenderRNA *brna)
+{
+ rna_def_attribute(brna);
+ rna_def_attribute_group(brna);
+}
+#endif
diff --git a/source/blender/makesrna/intern/rna_hair.c b/source/blender/makesrna/intern/rna_hair.c
index f6dc93323fe..4ca66c6b583 100644
--- a/source/blender/makesrna/intern/rna_hair.c
+++ b/source/blender/makesrna/intern/rna_hair.c
@@ -34,6 +34,7 @@
# include "BLI_math_vector.h"
+# include "BKE_attribute.h"
# include "BKE_hair.h"
# include "DEG_depsgraph.h"
@@ -224,6 +225,9 @@ static void rna_def_hair(BlenderRNA *brna)
RNA_def_property_collection_funcs(
prop, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "rna_IDMaterials_assign_int");
+ /* attributes */
+ rna_def_attributes_common(srna);
+
/* common */
rna_def_animdata_common(srna);
}
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index ad43202d850..eaf4e8866f9 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -151,6 +151,7 @@ void RNA_def_action(struct BlenderRNA *brna);
void RNA_def_animation(struct BlenderRNA *brna);
void RNA_def_animviz(struct BlenderRNA *brna);
void RNA_def_armature(struct BlenderRNA *brna);
+void RNA_def_attribute(struct BlenderRNA *brna);
void RNA_def_boid(struct BlenderRNA *brna);
void RNA_def_brush(struct BlenderRNA *brna);
void RNA_def_cachefile(struct BlenderRNA *brna);
@@ -221,6 +222,13 @@ void RNA_def_xr(struct BlenderRNA *brna);
/* Common Define functions */
+void rna_def_attributes_common(struct StructRNA *srna);
+
+void rna_AttributeGroup_iterator_begin(CollectionPropertyIterator *iter, PointerRNA *ptr);
+void rna_AttributeGroup_iterator_next(CollectionPropertyIterator *iter);
+PointerRNA rna_AttributeGroup_iterator_get(CollectionPropertyIterator *iter);
+int rna_AttributeGroup_length(PointerRNA *ptr);
+
void rna_def_animdata_common(struct StructRNA *srna);
bool rna_AnimaData_override_apply(struct Main *bmain,
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index bb5ec0d6835..346946dfb0d 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -3200,6 +3200,9 @@ static void rna_def_mesh(BlenderRNA *brna)
rna_def_paint_mask(brna, prop);
/* End paint mask */
+ /* Attributes */
+ rna_def_attributes_common(srna);
+
/* Remesh */
prop = RNA_def_property(srna, "remesh_voxel_size", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "remesh_voxel_size");
diff --git a/source/blender/makesrna/intern/rna_pointcloud.c b/source/blender/makesrna/intern/rna_pointcloud.c
index 4e3243ae80f..90ff69b2a8a 100644
--- a/source/blender/makesrna/intern/rna_pointcloud.c
+++ b/source/blender/makesrna/intern/rna_pointcloud.c
@@ -156,6 +156,8 @@ static void rna_def_pointcloud(BlenderRNA *brna)
RNA_def_property_collection_funcs(
prop, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "rna_IDMaterials_assign_int");
+ rna_def_attributes_common(srna);
+
/* common */
rna_def_animdata_common(srna);
}
diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c
index a9a9a3ad5d9..a74be2b580e 100644
--- a/source/blender/python/bmesh/bmesh_py_types_customdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c
@@ -84,6 +84,15 @@ PyDoc_STRVAR(bpy_bmlayeraccess_collection__float_doc,
"Generic float custom-data layer.\n\ntype: :class:`BMLayerCollection`");
PyDoc_STRVAR(bpy_bmlayeraccess_collection__int_doc,
"Generic int custom-data layer.\n\ntype: :class:`BMLayerCollection`");
+PyDoc_STRVAR(bpy_bmlayeraccess_collection__float_vector_doc,
+ "Generic 3D vector with float precision custom-data layer.\n\ntype: "
+ ":class:`BMLayerCollection`");
+PyDoc_STRVAR(bpy_bmlayeraccess_collection__float_color_doc,
+ "Generic RGBA color with float precision custom-data layer.\n\ntype: "
+ ":class:`BMLayerCollection`");
+PyDoc_STRVAR(bpy_bmlayeraccess_collection__color_doc,
+ "Generic RGBA color with 8-bit precision custom-data layer.\n\ntype: "
+ ":class:`BMLayerCollection`");
PyDoc_STRVAR(bpy_bmlayeraccess_collection__string_doc,
"Generic string custom-data layer (exposed as bytes, 255 max length).\n\ntype: "
":class:`BMLayerCollection`");
@@ -102,8 +111,6 @@ PyDoc_STRVAR(bpy_bmlayeraccess_collection__crease_doc,
PyDoc_STRVAR(
bpy_bmlayeraccess_collection__uv_doc,
"Accessor for :class:`BMLoopUV` UV (as a 2D Vector).\n\ntype: :class:`BMLayerCollection`");
-PyDoc_STRVAR(bpy_bmlayeraccess_collection__color_doc,
- "Accessor for vertex color layer.\n\ntype: :class:`BMLayerCollection`");
PyDoc_STRVAR(bpy_bmlayeraccess_collection__skin_doc,
"Accessor for skin layer.\n\ntype: :class:`BMLayerCollection`");
PyDoc_STRVAR(bpy_bmlayeraccess_collection__paint_mask_doc,
@@ -188,6 +195,21 @@ static PyGetSetDef bpy_bmlayeraccess_vert_getseters[] = {
(setter)NULL,
bpy_bmlayeraccess_collection__int_doc,
(void *)CD_PROP_INT32},
+ {"float_vector",
+ (getter)bpy_bmlayeraccess_collection_get,
+ (setter)NULL,
+ bpy_bmlayeraccess_collection__float_vector_doc,
+ (void *)CD_PROP_FLOAT3},
+ {"float_color",
+ (getter)bpy_bmlayeraccess_collection_get,
+ (setter)NULL,
+ bpy_bmlayeraccess_collection__float_color_doc,
+ (void *)CD_PROP_COLOR},
+ {"color",
+ (getter)bpy_bmlayeraccess_collection_get,
+ (setter)NULL,
+ bpy_bmlayeraccess_collection__color_doc,
+ (void *)CD_MLOOPCOL},
{"string",
(getter)bpy_bmlayeraccess_collection_get,
(setter)NULL,
@@ -229,6 +251,21 @@ static PyGetSetDef bpy_bmlayeraccess_edge_getseters[] = {
(setter)NULL,
bpy_bmlayeraccess_collection__int_doc,
(void *)CD_PROP_INT32},
+ {"float_vector",
+ (getter)bpy_bmlayeraccess_collection_get,
+ (setter)NULL,
+ bpy_bmlayeraccess_collection__float_vector_doc,
+ (void *)CD_PROP_FLOAT3},
+ {"float_color",
+ (getter)bpy_bmlayeraccess_collection_get,
+ (setter)NULL,
+ bpy_bmlayeraccess_collection__float_color_doc,
+ (void *)CD_PROP_COLOR},
+ {"color",
+ (getter)bpy_bmlayeraccess_collection_get,
+ (setter)NULL,
+ bpy_bmlayeraccess_collection__color_doc,
+ (void *)CD_MLOOPCOL},
{"string",
(getter)bpy_bmlayeraccess_collection_get,
(setter)NULL,
@@ -267,6 +304,21 @@ static PyGetSetDef bpy_bmlayeraccess_face_getseters[] = {
(setter)NULL,
bpy_bmlayeraccess_collection__int_doc,
(void *)CD_PROP_INT32},
+ {"float_vector",
+ (getter)bpy_bmlayeraccess_collection_get,
+ (setter)NULL,
+ bpy_bmlayeraccess_collection__float_vector_doc,
+ (void *)CD_PROP_FLOAT3},
+ {"float_color",
+ (getter)bpy_bmlayeraccess_collection_get,
+ (setter)NULL,
+ bpy_bmlayeraccess_collection__float_color_doc,
+ (void *)CD_PROP_COLOR},
+ {"color",
+ (getter)bpy_bmlayeraccess_collection_get,
+ (setter)NULL,
+ bpy_bmlayeraccess_collection__color_doc,
+ (void *)CD_MLOOPCOL},
{"string",
(getter)bpy_bmlayeraccess_collection_get,
(setter)NULL,
@@ -300,12 +352,21 @@ static PyGetSetDef bpy_bmlayeraccess_loop_getseters[] = {
(setter)NULL,
bpy_bmlayeraccess_collection__int_doc,
(void *)CD_PROP_INT32},
+ {"float_vector",
+ (getter)bpy_bmlayeraccess_collection_get,
+ (setter)NULL,
+ bpy_bmlayeraccess_collection__float_vector_doc,
+ (void *)CD_PROP_FLOAT3},
+ {"float_color",
+ (getter)bpy_bmlayeraccess_collection_get,
+ (setter)NULL,
+ bpy_bmlayeraccess_collection__float_color_doc,
+ (void *)CD_PROP_COLOR},
{"string",
(getter)bpy_bmlayeraccess_collection_get,
(setter)NULL,
bpy_bmlayeraccess_collection__string_doc,
(void *)CD_PROP_STRING},
-
{"uv",
(getter)bpy_bmlayeraccess_collection_get,
(setter)NULL,
@@ -1072,6 +1133,14 @@ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer)
ret = PyLong_FromLong(*(int *)value);
break;
}
+ case CD_PROP_FLOAT3: {
+ ret = Vector_CreatePyObject_wrap((float *)value, 3, NULL);
+ break;
+ }
+ case CD_PROP_COLOR: {
+ ret = Vector_CreatePyObject_wrap((float *)value, 4, NULL);
+ break;
+ }
case CD_PROP_STRING: {
MStringProperty *mstring = value;
ret = PyBytes_FromStringAndSize(mstring->s, mstring->s_len);
@@ -1150,6 +1219,18 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj
}
break;
}
+ case CD_PROP_FLOAT3: {
+ if (mathutils_array_parse((float *)value, 3, 3, py_value, "BMElem Float Vector") == -1) {
+ ret = -1;
+ }
+ break;
+ }
+ case CD_PROP_COLOR: {
+ if (mathutils_array_parse((float *)value, 4, 4, py_value, "BMElem Float Color") == -1) {
+ ret = -1;
+ }
+ break;
+ }
case CD_PROP_STRING: {
MStringProperty *mstring = value;
char *tmp_val;