diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-09-07 20:18:39 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-09-07 20:18:39 +0300 |
commit | a133b7470974b1a6e327955a1cc4249375bc2386 (patch) | |
tree | d9432c2f7b949f6b65e0d0754c7e3c10737162cf /source/blender/python | |
parent | 1601089ece8a1f62c4c8d965fbef8073ccf0e0e5 (diff) | |
parent | 60020f57d7a80679a9493eef3915c205c9c6c246 (diff) |
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 2ffb2ba5291..1368b610b53 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -3716,6 +3716,66 @@ static PyObject *pyrna_struct_type_recast(BPy_StructRNA *self) 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_get_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) { PyObject *list_tmp; @@ -5014,6 +5074,7 @@ static struct PyMethodDef pyrna_struct_methods[] = { {"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}, {"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}, /* experimental */ |