From a9f7bbc9f8f745d65ebf612a6b880782320831f7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 28 May 2016 22:23:39 +1000 Subject: PyRNA: Fix repr used /w arrays RNA arrays now display their index, with support for multi-dimensional arrays. --- source/blender/makesrna/RNA_access.h | 1 + source/blender/makesrna/intern/rna_access.c | 66 ++++++++++++++++++++++++++--- source/blender/python/intern/bpy_rna.c | 18 ++++++-- 3 files changed, 77 insertions(+), 8 deletions(-) (limited to 'source') diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 3a19211ab39..c3d25ed2972 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -979,6 +979,7 @@ bool RNA_path_resolve_elements(PointerRNA *ptr, const char *path, struct ListBas char *RNA_path_from_ID_to_struct(PointerRNA *ptr); char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop); +char *RNA_path_from_ID_to_property_index(PointerRNA *ptr, PropertyRNA *prop, int array_dim, int index); char *RNA_path_resolve_from_type_to_property( struct PointerRNA *ptr, struct PropertyRNA *prop, diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 97c71715349..c49a6197a4e 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -4642,7 +4642,47 @@ char *RNA_path_from_ID_to_struct(PointerRNA *ptr) return ptrpath; } -char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop) +static void rna_path_array_multi_from_flat_index( + const int dimsize[RNA_MAX_ARRAY_LENGTH], const int totdims, + const int index_dim, int index, + int r_index_multi[RNA_MAX_ARRAY_LENGTH]) +{ + int dimsize_step[RNA_MAX_ARRAY_LENGTH + 1]; + int i = totdims - 1; + dimsize_step[i + 1] = 1; + dimsize_step[i] = dimsize[i]; + while (--i != -1) { + dimsize_step[i] = dimsize[i] * dimsize_step[i + 1]; + } + while (++i != index_dim) { + int index_round = index / dimsize_step[i + 1]; + r_index_multi[i] = index_round; + index -= (index_round * dimsize_step[i + 1]); + } + BLI_assert(index == 0); +} + +static void rna_path_array_multi_string_from_flat_index( + PointerRNA *ptr, PropertyRNA *prop, int index_dim, int index, + char *index_str, int index_str_len) +{ + int dimsize[RNA_MAX_ARRAY_LENGTH]; + int totdims = RNA_property_array_dimension(ptr, prop, dimsize); + int index_multi[RNA_MAX_ARRAY_LENGTH]; + + rna_path_array_multi_from_flat_index(dimsize, totdims, index_dim, index, index_multi); + + for (int i = 0, offset = 0; (i < index_dim) && (offset < index_str_len); i++) { + offset += BLI_snprintf_rlen(&index_str[offset], index_str_len - offset, "[%d]", index_multi[i]); + } +} + +/** + * \param index_dim: The dimensiuon to show, 0 disables. 1 for 1d array, 2 for 2d. etc. + * \param index: The *flattened* index to use when \a ``index_dim > 0``, + * this is expanded when used with multi-dimensional arrays. + */ +char *RNA_path_from_ID_to_property_index(PointerRNA *ptr, PropertyRNA *prop, int index_dim, int index) { const bool is_rna = (prop->magic == RNA_MAGIC); const char *propname; @@ -4656,25 +4696,36 @@ char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop) propname = RNA_property_identifier(prop); + /* support indexing w/ multi-dimensional arrays */ + char index_str[RNA_MAX_ARRAY_LENGTH * 12 + 1]; + if (index_dim == 0) { + index_str[0] = '\0'; + } + else { + rna_path_array_multi_string_from_flat_index( + ptr, prop, index_dim, index, + index_str, sizeof(index_str)); + } + if (ptrpath) { if (is_rna) { - path = BLI_sprintfN("%s.%s", ptrpath, propname); + path = BLI_sprintfN("%s.%s%s", ptrpath, propname, index_str); } else { char propname_esc[MAX_IDPROP_NAME * 2]; BLI_strescape(propname_esc, propname, sizeof(propname_esc)); - path = BLI_sprintfN("%s[\"%s\"]", ptrpath, propname_esc); + path = BLI_sprintfN("%s[\"%s\"]%s", ptrpath, propname_esc, index_str); } MEM_freeN(ptrpath); } else if (RNA_struct_is_ID(ptr->type)) { if (is_rna) { - path = BLI_strdup(propname); + path = BLI_sprintfN("%s%s", propname, index_str); } else { char propname_esc[MAX_IDPROP_NAME * 2]; BLI_strescape(propname_esc, propname, sizeof(propname_esc)); - path = BLI_sprintfN("[\"%s\"]", propname_esc); + path = BLI_sprintfN("[\"%s\"]%s", propname_esc, index_str); } } else { @@ -4684,6 +4735,11 @@ char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop) return path; } +char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop) +{ + return RNA_path_from_ID_to_property_index(ptr, prop, 0, -1); +} + /** * \return the path to given ptr/prop from the closest ancestor of given type, if any (else return NULL). */ diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 33ac58dadb1..49b806347d6 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -973,7 +973,9 @@ static PyObject *pyrna_prop_str(BPy_PropertyRNA *self) RNA_property_identifier(self->prop)); } -static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self) +static PyObject *pyrna_prop_repr_ex( + BPy_PropertyRNA *self, + const int index_dim, const int index) { ID *id = self->ptr.id.data; PyObject *tmp_str; @@ -987,7 +989,8 @@ static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self) tmp_str = PyUnicode_FromString(id->name + 2); - path = RNA_path_from_ID_to_property(&self->ptr, self->prop); + path = RNA_path_from_ID_to_property_index(&self->ptr, self->prop, index_dim, index); + if (path) { const char *data_delim = (path[0] == '[') ? "" : "."; if (GS(id->name) == ID_NT) { /* nodetree paths are not accurate */ @@ -1015,6 +1018,15 @@ static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self) return ret; } +static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self) +{ + return pyrna_prop_repr_ex(self, 0, -1); +} + +static PyObject *pyrna_prop_array_repr(BPy_PropertyArrayRNA *self) +{ + return pyrna_prop_repr_ex((BPy_PropertyRNA *)self, self->arraydim, self->arrayoffset); +} static PyObject *pyrna_func_repr(BPy_FunctionRNA *self) { @@ -5841,7 +5853,7 @@ PyTypeObject pyrna_prop_array_Type = { NULL, /* getattrfunc tp_getattr; */ NULL, /* setattrfunc tp_setattr; */ NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - NULL, /* subclassed */ /* tp_repr */ + (reprfunc)pyrna_prop_array_repr, /* tp_repr */ /* Method suites for standard classes */ -- cgit v1.2.3