RNA: face-map access

Currently RNA doesn't give us a good way of accessing singleton layers,
for now expose as a layer list (skin & paint-pask do this too).

Noted in T47811 that this should be changed.
This commit is contained in:
Campbell Barton 2017-07-20 18:37:30 +10:00
parent 819f3b37da
commit f5f34a9aa6
Notes: blender-bot 2023-02-14 06:57:56 +01:00
Referenced by issue #52127, Combed hair from 2.78 not showing when appending
3 changed files with 207 additions and 2 deletions

View File

@ -91,6 +91,9 @@ struct Mesh *BKE_mesh_copy(struct Main *bmain, const struct Mesh *me);
void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd);
void BKE_mesh_ensure_skin_customdata(struct Mesh *me);
bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me);
bool BKE_mesh_clear_facemap_customdata(struct Mesh *me);
void BKE_mesh_make_local(struct Main *bmain, struct Mesh *me, const bool lib_local);
void BKE_mesh_boundbox_calc(struct Mesh *me, float r_loc[3], float r_size[3]);
void BKE_mesh_texspace_calc(struct Mesh *me);

View File

@ -387,6 +387,48 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me)
}
}
bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me)
{
BMesh *bm = me->edit_btmesh ? me->edit_btmesh->bm : NULL;
bool changed = false;
if (bm) {
if (!CustomData_has_layer(&bm->pdata, CD_FACEMAP)) {
BM_data_layer_add(bm, &bm->pdata, CD_FACEMAP);
changed = true;
}
}
else {
if (!CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
CustomData_add_layer(&me->pdata,
CD_FACEMAP,
CD_DEFAULT,
NULL,
me->totpoly);
changed = true;
}
}
return changed;
}
bool BKE_mesh_clear_facemap_customdata(struct Mesh *me)
{
BMesh *bm = me->edit_btmesh ? me->edit_btmesh->bm : NULL;
bool changed = false;
if (bm) {
if (CustomData_has_layer(&bm->pdata, CD_FACEMAP)) {
BM_data_layer_free(bm, &bm->pdata, CD_FACEMAP);
changed = true;
}
}
else {
if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
CustomData_free_layers(&me->pdata, CD_FACEMAP, me->totpoly);
changed = true;
}
}
return changed;
}
/* this ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or
* mloopcol and mcol) have the same relative active/render/clone/mask indices.
*

View File

@ -186,12 +186,10 @@ static void rna_MeshEdgeLayer_name_set(PointerRNA *ptr, const char *value)
rna_cd_layer_name_set(rna_mesh_edata(ptr), (CustomDataLayer *)ptr->data, value);
}
#endif
#if 0
static void rna_MeshPolyLayer_name_set(PointerRNA *ptr, const char *value)
{
rna_cd_layer_name_set(rna_mesh_pdata(ptr), (CustomDataLayer *)ptr->data, value);
}
#endif
static void rna_MeshLoopLayer_name_set(PointerRNA *ptr, const char *value)
{
rna_cd_layer_name_set(rna_mesh_ldata(ptr), (CustomDataLayer *)ptr->data, value);
@ -1176,6 +1174,75 @@ static int rna_MeshPaintMaskLayer_data_length(PointerRNA *ptr)
/* End paint mask */
/* Face maps */
DEFINE_CUSTOMDATA_LAYER_COLLECTION(face_map, pdata, CD_FACEMAP)
DEFINE_CUSTOMDATA_LAYER_COLLECTION_ACTIVEITEM(face_map, pdata, CD_FACEMAP, active, MeshFaceMapLayer)
static char *rna_MeshFaceMapLayer_path(PointerRNA *ptr)
{
CustomDataLayer *cdl = ptr->data;
char name_esc[sizeof(cdl->name) * 2];
BLI_strescape(name_esc, cdl->name, sizeof(name_esc));
return BLI_sprintfN("face_maps[\"%s\"]", name_esc);
}
static void rna_MeshFaceMapLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me = rna_mesh(ptr);
CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
rna_iterator_array_begin(iter, layer->data, sizeof(int), me->totpoly, 0, NULL);
}
static int rna_MeshFaceMapLayer_data_length(PointerRNA *ptr)
{
Mesh *me = rna_mesh(ptr);
return me->totpoly;
}
static PointerRNA rna_Mesh_face_map_new(struct Mesh *me, ReportList *reports, const char *name)
{
if (BKE_mesh_ensure_facemap_customdata(me) == false) {
BKE_report(reports, RPT_ERROR, "Currently only single face-map layers are supported");
return PointerRNA_NULL;
}
CustomData *pdata = rna_mesh_pdata_helper(me);
int index = CustomData_get_layer_index(pdata, CD_FACEMAP);
BLI_assert(index != -1);
CustomDataLayer *cdl = &pdata->layers[index];
rna_cd_layer_name_set(pdata, cdl, name);
PointerRNA ptr;
RNA_pointer_create(&me->id, &RNA_MeshFaceMapLayer, cdl, &ptr);
return ptr;
}
static void rna_Mesh_face_map_remove(struct Mesh *me, ReportList *reports, struct CustomDataLayer *layer)
{
/* just for sanity check */
{
CustomData *pdata = rna_mesh_pdata_helper(me);
int index = CustomData_get_layer_index(pdata, CD_FACEMAP);
if (index != -1) {
CustomDataLayer *layer_test = &pdata->layers[index];
if (layer != layer_test) {
/* don't show name, its likely freed memory */
BKE_report(reports, RPT_ERROR, "FaceMap not in mesh");
return;
}
}
}
if (BKE_mesh_clear_facemap_customdata(me) == false) {
BKE_reportf(reports, RPT_ERROR, "Error removing face-map");
}
}
/* End face maps */
static int rna_MeshTessFace_verts_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
{
MFace *face = (MFace *)ptr->data;
@ -1608,6 +1675,12 @@ void rna_MeshStringProperty_s_set(PointerRNA *ptr, const char *value)
MStringProperty *ms = (MStringProperty *)ptr->data;
BLI_strncpy(ms->s, value, sizeof(ms->s));
}
static char *rna_MeshFaceMap_path(PointerRNA *ptr)
{
return rna_PolyCustomData_data_path(ptr, "face_maps", CD_FACEMAP);
}
/***************************************/
static int rna_Mesh_tot_vert_get(PointerRNA *ptr)
@ -1796,6 +1869,10 @@ static void UNUSED_FUNCTION(rna_mesh_unused)(void)
(void)rna_Mesh_vertex_color_render_index_get;
(void)rna_Mesh_vertex_color_render_index_set;
(void)rna_Mesh_vertex_color_render_set;
(void)rna_Mesh_face_map_index_range;
(void)rna_Mesh_face_map_active_index_set;
(void)rna_Mesh_face_map_active_index_get;
(void)rna_Mesh_face_map_active_set;
/* end unused function block */
}
@ -3091,6 +3168,79 @@ static void rna_def_paint_mask(BlenderRNA *brna, PropertyRNA *UNUSED(cprop))
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
}
static void rna_def_face_map(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "MeshFaceMapLayer", NULL);
RNA_def_struct_ui_text(srna, "Mesh Face Map Layer", "Per-face map index");
RNA_def_struct_sdna(srna, "CustomDataLayer");
RNA_def_struct_path_func(srna, "rna_MeshFaceMapLayer_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_MeshPolyLayer_name_set");
RNA_def_property_ui_text(prop, "Name", "Name of face-map layer");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshFaceMap");
RNA_def_property_ui_text(prop, "Data", "");
RNA_def_property_collection_funcs(prop, "rna_MeshFaceMapLayer_data_begin", "rna_iterator_array_next",
"rna_iterator_array_end", "rna_iterator_array_get",
"rna_MeshFaceMapLayer_data_length", NULL, NULL, NULL);
/* FaceMap struct */
srna = RNA_def_struct(brna, "MeshFaceMap", NULL);
RNA_def_struct_sdna(srna, "MIntProperty");
RNA_def_struct_ui_text(srna, "Int Property", "");
RNA_def_struct_path_func(srna, "rna_MeshFaceMap_path");
prop = RNA_def_property(srna, "value", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "i");
RNA_def_property_ui_text(prop, "Value", "");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
}
static void rna_def_face_maps(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
PropertyRNA *prop;
RNA_def_property_srna(cprop, "MeshFaceMapLayers");
srna = RNA_def_struct(brna, "MeshFaceMapLayers", NULL);
RNA_def_struct_ui_text(srna, "Mesh Face Map Layer", "Per-face map index");
RNA_def_struct_sdna(srna, "Mesh");
RNA_def_struct_ui_text(srna, "Mesh FaceMaps", "Collection of mesh face-maps");
/* add this since we only ever have one layer anyway, don't bother with active_index */
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshFaceMapLayer");
RNA_def_property_pointer_funcs(prop, "rna_Mesh_face_map_active_get",
NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Active FaceMap Layer", "");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
FunctionRNA *func;
PropertyRNA *parm;
func = RNA_def_function(srna, "new", "rna_Mesh_face_map_new");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Add a float property layer to Mesh");
RNA_def_string(func, "name", "Face Map", 0, "", "Face map name");
parm = RNA_def_pointer(func, "layer", "MeshFaceMapLayer", "", "The newly created layer");
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_Mesh_face_map_remove");
RNA_def_function_ui_description(func, "Remove a face map layer");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "layer", "MeshFaceMapLayer", "", "The layer to remove");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
}
static void rna_def_mesh(BlenderRNA *brna)
{
StructRNA *srna;
@ -3250,6 +3400,15 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "String Property Layers", "");
rna_def_polygon_string_layers(brna, prop);
/* face-maps */
prop = RNA_def_property(srna, "face_maps", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "pdata.layers", "pdata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_face_maps_begin", NULL, NULL, NULL,
"rna_Mesh_face_maps_length", NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "MeshFaceMapLayer");
RNA_def_property_ui_text(prop, "FaceMap", "");
rna_def_face_maps(brna, prop);
/* Skin vertices */
prop = RNA_def_property(srna, "skin_vertices", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer");
@ -3523,6 +3682,7 @@ void RNA_def_mesh(BlenderRNA *brna)
rna_def_mcol(brna);
rna_def_mloopcol(brna);
rna_def_mproperties(brna);
rna_def_face_map(brna);
}
#endif