PyAPI: add function to get an RNA subclass
This is inconvenient in regular Python, add a class-method to perform the operation, eg: bpy.types.Node.bl_rna_find_subclass("CustomNodeType")
This commit is contained in:
@@ -3707,6 +3707,66 @@ static PyObject *pyrna_struct_type_recast(BPy_StructRNA *self)
|
|||||||
return pyrna_struct_CreatePyObject(&r_ptr);
|
return pyrna_struct_CreatePyObject(&r_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \note Return value is borrowed, caller must incref.
|
||||||
|
*/
|
||||||
|
static PyObject *pyrna_struct_bl_rna_find_subclass_recursive(PyObject *cls, const char *id)
|
||||||
|
{
|
||||||
|
PyObject *ret_test = NULL;
|
||||||
|
PyObject *subclasses = ((PyTypeObject *)cls)->tp_subclasses;
|
||||||
|
if (subclasses) {
|
||||||
|
/* Unfortunately we can't use the dict key because Python class names
|
||||||
|
* don't match the bl_idname used internally. */
|
||||||
|
BLI_assert(PyDict_CheckExact(subclasses));
|
||||||
|
PyObject *key = NULL;
|
||||||
|
Py_ssize_t pos = 0;
|
||||||
|
PyObject *value = NULL;
|
||||||
|
while (PyDict_Next(subclasses, &pos, &key, &value)) {
|
||||||
|
BLI_assert(PyWeakref_CheckRef(value));
|
||||||
|
PyObject *subcls = PyWeakref_GET_OBJECT(value);
|
||||||
|
if (subcls != Py_None) {
|
||||||
|
BPy_StructRNA *py_srna = (BPy_StructRNA *)PyDict_GetItem(
|
||||||
|
((PyTypeObject *)subcls)->tp_dict, bpy_intern_str_bl_rna);
|
||||||
|
if (py_srna) {
|
||||||
|
StructRNA *srna = py_srna->ptr.data;
|
||||||
|
if (STREQ(id, RNA_struct_identifier(srna))) {
|
||||||
|
ret_test = subcls;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret_test = pyrna_struct_bl_rna_find_subclass_recursive(subcls, id);
|
||||||
|
if (ret_test) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret_test;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(pyrna_struct_bl_rna_get_subclass_doc,
|
||||||
|
".. classmethod:: bl_rna_get_subclass(id, default=None)\n"
|
||||||
|
"\n"
|
||||||
|
" :arg id: The RNA type identifier.\n"
|
||||||
|
" :type vector: string\n"
|
||||||
|
" :return: The class or default when not found.\n"
|
||||||
|
" :rtype: type\n"
|
||||||
|
);
|
||||||
|
static PyObject *pyrna_struct_bl_rna_get_subclass(PyObject *cls, PyObject *args)
|
||||||
|
{
|
||||||
|
char *id;
|
||||||
|
PyObject *ret_default = Py_None;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "s|O:bl_rna_find_subclass", &id, &ret_default)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyObject *ret = pyrna_struct_bl_rna_find_subclass_recursive(cls, id);
|
||||||
|
if (ret == NULL) {
|
||||||
|
ret = ret_default;
|
||||||
|
}
|
||||||
|
return Py_INCREF_RET(ret);
|
||||||
|
}
|
||||||
|
|
||||||
static void pyrna_dir_members_py__add_keys(PyObject *list, PyObject *dict)
|
static void pyrna_dir_members_py__add_keys(PyObject *list, PyObject *dict)
|
||||||
{
|
{
|
||||||
PyObject *list_tmp;
|
PyObject *list_tmp;
|
||||||
@@ -5005,6 +5065,7 @@ static struct PyMethodDef pyrna_struct_methods[] = {
|
|||||||
{"path_resolve", (PyCFunction)pyrna_struct_path_resolve, METH_VARARGS, pyrna_struct_path_resolve_doc},
|
{"path_resolve", (PyCFunction)pyrna_struct_path_resolve, METH_VARARGS, pyrna_struct_path_resolve_doc},
|
||||||
{"path_from_id", (PyCFunction)pyrna_struct_path_from_id, METH_VARARGS, pyrna_struct_path_from_id_doc},
|
{"path_from_id", (PyCFunction)pyrna_struct_path_from_id, METH_VARARGS, pyrna_struct_path_from_id_doc},
|
||||||
{"type_recast", (PyCFunction)pyrna_struct_type_recast, METH_NOARGS, pyrna_struct_type_recast_doc},
|
{"type_recast", (PyCFunction)pyrna_struct_type_recast, METH_NOARGS, pyrna_struct_type_recast_doc},
|
||||||
|
{"bl_rna_get_subclass", (PyCFunction) pyrna_struct_bl_rna_get_subclass, METH_VARARGS | METH_CLASS, pyrna_struct_bl_rna_get_subclass_doc},
|
||||||
{"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL},
|
{"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL},
|
||||||
|
|
||||||
/* experimental */
|
/* experimental */
|
||||||
|
Reference in New Issue
Block a user