PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args) { const char *path, *path_full; int index = -1; PYRNA_STRUCT_CHECK_OBJ(self); if (!PyArg_ParseTuple(args, "s|i:driver_add", &path, &index)) return NULL; if (pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_add():", path, &path_full, &index) == -1) { return NULL; } else { PyObject *ret = NULL; ReportList reports; int result; BKE_reports_init(&reports, RPT_STORE); result = ANIM_add_driver(&reports, (ID *)self->ptr.id.data, path_full, index, CREATEDRIVER_WITH_FMODIFIER, DRIVER_TYPE_PYTHON); if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) return NULL; if (result) { ID *id = self->ptr.id.data; AnimData *adt = BKE_animdata_from_id(id); FCurve *fcu; PointerRNA tptr; if (index == -1) { /* all, use a list */ int i = 0; ret = PyList_New(0); while ((fcu = list_find_fcurve(&adt->drivers, path_full, i++))) { RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr); PyList_APPEND(ret, pyrna_struct_CreatePyObject(&tptr)); } } else { fcu = list_find_fcurve(&adt->drivers, path_full, index); RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr); ret = pyrna_struct_CreatePyObject(&tptr); } WM_event_add_notifier(BPy_GetContext(), NC_ANIMATION | ND_FCURVES_ORDER, NULL); } else { /* XXX, should be handled by reports, */ PyErr_SetString(PyExc_TypeError, "bpy_struct.driver_add(): failed because of an internal error"); return NULL; } MEM_freeN((void *)path_full); return ret; } }
PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args) { const char *path, *path_full; int index = -1; PYRNA_STRUCT_CHECK_OBJ(self); if (!PyArg_ParseTuple(args, "s|i:driver_remove", &path, &index)) return NULL; if (pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_remove():", path, &path_full, &index) == -1) { return NULL; } else { short result; ReportList reports; BKE_reports_init(&reports, RPT_STORE); result = ANIM_remove_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0); MEM_freeN((void *)path_full); if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) return NULL; WM_event_add_notifier(BPy_GetContext(), NC_ANIMATION | ND_FCURVES_ORDER, NULL); return PyBool_FromLong(result); } }
/* internal use for insert and delete */ static int pyrna_struct_keyframe_parse( PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix, const char **path_full, int *index, float *cfra, const char **group_name, int *options) /* return values */ { static const char *kwlist[] = {"data_path", "index", "frame", "group", "options", NULL}; PyObject *pyoptions = NULL; const char *path; /* note, parse_str MUST start with 's|ifsO!' */ if (!PyArg_ParseTupleAndKeywords(args, kw, parse_str, (char **)kwlist, &path, index, cfra, group_name, &PySet_Type, &pyoptions)) { return -1; } if (pyrna_struct_anim_args_parse(ptr, error_prefix, path, path_full, index) == -1) return -1; if (*cfra == FLT_MAX) *cfra = CTX_data_scene(BPy_GetContext())->r.cfra; /* flag may be null (no option currently for remove keyframes e.g.). */ if (options) { if (pyoptions && (pyrna_set_to_enum_bitfield(rna_enum_keying_flag_items, pyoptions, options, error_prefix) == -1)) { return -1; } *options |= INSERTKEY_NO_USERPREF; } return 0; /* success */ }
static PyObject *M_Blensorintern_copy_zbuf(PyObject *UNUSED(self), PyObject *obj) { PyObject *result; float *outbuffer; int outbuffer_len; struct ID *id; bContext *C; BPy_StructRNA *blender_obj = NULL; int status = 0; int idx; status = pyrna_id_FromPyObject(obj, &id); if (status) { blender_obj = (BPy_StructRNA *) obj; } C = (bContext *)BPy_GetContext(); blensor_Image_copy_zbuf((Image *)blender_obj->ptr.data, C, &outbuffer_len, &outbuffer); printf ("Size of buffer %d",outbuffer_len); result = PyTuple_New(outbuffer_len); for (idx = 0; idx < outbuffer_len; idx++) { PyTuple_SetItem(result, idx, PyFloat_FromDouble(outbuffer[idx])); } MEM_freeN(outbuffer); return result; }
static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { Main *bmain = CTX_data_main(BPy_GetContext()); BPy_Library *ret; const char *filename = NULL; bool is_rel = false, is_link = false; static const char *_keywords[] = {"filepath", "link", "relative", NULL}; static _PyArg_Parser _parser = {"s|O&O&:load", _keywords, 0}; if (!_PyArg_ParseTupleAndKeywordsFast( args, kw, &_parser, &filename, PyC_ParseBool, &is_link, PyC_ParseBool, &is_rel)) { return NULL; } ret = PyObject_New(BPy_Library, &bpy_lib_Type); BLI_strncpy(ret->relpath, filename, sizeof(ret->relpath)); BLI_strncpy(ret->abspath, filename, sizeof(ret->abspath)); BLI_path_abs(ret->abspath, BKE_main_blendfile_path(bmain)); ret->blo_handle = NULL; ret->flag = ((is_link ? FILE_LINK : 0) | (is_rel ? FILE_RELPATH : 0)); ret->dict = _PyDict_NewPresized(MAX_LIBARRAY); return (PyObject *)ret; }
static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args) { wmOperatorType *ot; PointerRNA ptr; char *opname; PyObject *kw = NULL; /* optional args */ int all_args = 1; int macro_args = 1; int error_val = 0; char *buf = NULL; PyObject *pybuf; bContext *C = (bContext *)BPy_GetContext(); if (C == NULL) { PyErr_SetString(PyExc_RuntimeError, "Context is None, cant get the string representation of this object."); return NULL; } if (!PyArg_ParseTuple(args, "s|O!ii:_bpy.ops.as_string", &opname, &PyDict_Type, &kw, &all_args, ¯o_args)) return NULL; ot = WM_operatortype_find(opname, true); if (ot == NULL) { PyErr_Format(PyExc_AttributeError, "_bpy.ops.as_string: operator \"%.200s\" " "could not be found", opname); return NULL; } /* WM_operator_properties_create(&ptr, opname); */ /* Save another lookup */ RNA_pointer_create(NULL, ot->srna, NULL, &ptr); if (kw && PyDict_Size(kw)) error_val = pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: "); if (error_val == 0) buf = WM_operator_pystring_ex(C, NULL, all_args, macro_args, ot, &ptr); WM_operator_properties_free(&ptr); if (error_val == -1) { return NULL; } if (buf) { pybuf = PyUnicode_FromString(buf); MEM_freeN(buf); } else { pybuf = PyUnicode_FromString(""); } return pybuf; }
static PyObject *bpy_atexit(PyObject *UNUSED(self), PyObject *UNUSED(args), PyObject *UNUSED(kw)) { /* close down enough of blender at least not to crash */ struct bContext *C= BPy_GetContext(); WM_exit_ext(C, 0); Py_RETURN_NONE; }
static PyObject *M_Blensorintern_scan(PyObject *UNUSED(self), PyObject *args) { int raycount, elements_per_ray, keep_render_setup; int shading; float maximum_distance; char *ray_ptr_str, *return_ptr_str; bContext *C; PyObject *result; if (!PyArg_ParseTuple(args, "IfIIIss", &raycount, &maximum_distance, &elements_per_ray, &keep_render_setup, &shading, &ray_ptr_str, &return_ptr_str)) return 0; C = (bContext *)BPy_GetContext(); screen_blensor_exec(C, raycount, elements_per_ray, keep_render_setup, shading, maximum_distance, ray_ptr_str, return_ptr_str); result = Py_BuildValue("i",0); return result; }
static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args) { wmOperatorType *ot; char *opname; PyObject *context_dict = NULL; /* optional args */ PyObject *context_dict_back; char *context_str = NULL; PyObject *ret; int context = WM_OP_EXEC_DEFAULT; /* XXX Todo, work out a better solution for passing on context, * could make a tuple from self and pack the name and Context into it... */ bContext *C = (bContext *)BPy_GetContext(); if (C == NULL) { PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators"); return NULL; } if (!PyArg_ParseTuple(args, "s|Os:_bpy.ops.poll", &opname, &context_dict, &context_str)) return NULL; ot = WM_operatortype_find(opname, true); if (ot == NULL) { PyErr_Format(PyExc_AttributeError, "Polling operator \"bpy.ops.%s\" error, " "could not be found", opname); return NULL; } if (context_str) { if (RNA_enum_value_from_id(operator_context_items, context_str, &context) == 0) { char *enum_str = BPy_enum_as_string(operator_context_items); PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s.poll\" error, " "expected a string enum in (%.200s)", opname, enum_str); MEM_freeN(enum_str); return NULL; } } if (context_dict == NULL || context_dict == Py_None) { context_dict = NULL; } else if (!PyDict_Check(context_dict)) { PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s.poll\" error, " "custom context expected a dict or None, got a %.200s", opname, Py_TYPE(context_dict)->tp_name); return NULL; } context_dict_back = CTX_py_dict_get(C); CTX_py_dict_set(C, (void *)context_dict); Py_XINCREF(context_dict); /* so we done loose it */ /* main purpose of thsi function */ ret = WM_operator_poll_context((bContext *)C, ot, context) ? Py_True : Py_False; /* restore with original context dict, probably NULL but need this for nested operator calls */ Py_XDECREF(context_dict); CTX_py_dict_set(C, (void *)context_dict_back); Py_INCREF(ret); return ret; }
static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args) { wmOperatorType *ot; int error_val = 0; PointerRNA ptr; int operator_ret = OPERATOR_CANCELLED; char *opname; char *context_str = NULL; PyObject *kw = NULL; /* optional args */ PyObject *context_dict = NULL; /* optional args */ PyObject *context_dict_back; /* note that context is an int, python does the conversion in this case */ int context = WM_OP_EXEC_DEFAULT; int is_undo = false; /* XXX Todo, work out a better solution for passing on context, * could make a tuple from self and pack the name and Context into it... */ bContext *C = (bContext *)BPy_GetContext(); if (C == NULL) { PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators"); return NULL; } if (!PyArg_ParseTuple(args, "sO|O!si:_bpy.ops.call", &opname, &context_dict, &PyDict_Type, &kw, &context_str, &is_undo)) { return NULL; } ot = WM_operatortype_find(opname, true); if (ot == NULL) { PyErr_Format(PyExc_AttributeError, "Calling operator \"bpy.ops.%s\" error, " "could not be found", opname); return NULL; } if (!pyrna_write_check()) { PyErr_Format(PyExc_RuntimeError, "Calling operator \"bpy.ops.%s\" error, " "can't modify blend data in this state (drawing/rendering)", opname); return NULL; } if (context_str) { if (RNA_enum_value_from_id(operator_context_items, context_str, &context) == 0) { char *enum_str = BPy_enum_as_string(operator_context_items); PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s\" error, " "expected a string enum in (%.200s)", opname, enum_str); MEM_freeN(enum_str); return NULL; } } if (context_dict == NULL || context_dict == Py_None) { context_dict = NULL; } else if (!PyDict_Check(context_dict)) { PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s\" error, " "custom context expected a dict or None, got a %.200s", opname, Py_TYPE(context_dict)->tp_name); return NULL; } context_dict_back = CTX_py_dict_get(C); CTX_py_dict_set(C, (void *)context_dict); Py_XINCREF(context_dict); /* so we done loose it */ if (WM_operator_poll_context((bContext *)C, ot, context) == false) { const char *msg = CTX_wm_operator_poll_msg_get(C); PyErr_Format(PyExc_RuntimeError, "Operator bpy.ops.%.200s.poll() %.200s", opname, msg ? msg : "failed, context is incorrect"); CTX_wm_operator_poll_msg_set(C, NULL); /* better set to NULL else it could be used again */ error_val = -1; } else { WM_operator_properties_create_ptr(&ptr, ot); WM_operator_properties_sanitize(&ptr, 0); if (kw && PyDict_Size(kw)) error_val = pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: "); if (error_val == 0) { ReportList *reports; reports = MEM_mallocN(sizeof(ReportList), "wmOperatorReportList"); BKE_reports_init(reports, RPT_STORE | RPT_OP_HOLD); /* own so these don't move into global reports */ #ifdef BPY_RELEASE_GIL /* release GIL, since a thread could be started from an operator * that updates a driver */ /* note: I have not seen any examples of code that does this * so it may not be officially supported but seems to work ok. */ { PyThreadState *ts = PyEval_SaveThread(); #endif operator_ret = WM_operator_call_py(C, ot, context, &ptr, reports, is_undo); #ifdef BPY_RELEASE_GIL /* regain GIL */ PyEval_RestoreThread(ts); } #endif error_val = BPy_reports_to_error(reports, PyExc_RuntimeError, false); /* operator output is nice to have in the terminal/console too */ if (reports->list.first) { char *report_str = BKE_reports_string(reports, 0); /* all reports */ if (report_str) { PySys_WriteStdout("%s\n", report_str); MEM_freeN(report_str); } } BKE_reports_clear(reports); if ((reports->flag & RPT_FREE) == 0) { MEM_freeN(reports); } } WM_operator_properties_free(&ptr); #if 0 /* if there is some way to know an operator takes args we should use this */ { /* no props */ if (kw != NULL) { PyErr_Format(PyExc_AttributeError, "Operator \"%s\" does not take any args", opname); return NULL; } WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL); } #endif } /* restore with original context dict, probably NULL but need this for nested operator calls */ Py_XDECREF(context_dict); CTX_py_dict_set(C, (void *)context_dict_back); if (error_val == -1) { return NULL; } /* when calling bpy.ops.wm.read_factory_settings() bpy.data's main pointer is freed by clear_globals(), * further access will crash blender. setting context is not needed in this case, only calling because this * function corrects bpy.data (internal Main pointer) */ BPY_modules_update(C); /* needed for when WM_OT_read_factory_settings us called from within a script */ bpy_import_main_set(CTX_data_main(C)); /* return operator_ret as a bpy enum */ return pyrna_enum_bitfield_to_py(operator_return_items, operator_ret); }
static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) { Main *bmain = CTX_data_main(BPy_GetContext()); Main *mainl = NULL; int err = 0; flag_all_listbases_ids(LIB_PRE_EXISTING, 1); /* here appending/linking starts */ mainl = BLO_library_append_begin(bmain, &(self->blo_handle), self->relpath); { int i = 0, code; while ((code = BKE_idcode_iter_step(&i))) { if (BKE_idcode_is_linkable(code)) { const char *name_plural = BKE_idcode_to_name_plural(code); PyObject *ls = PyDict_GetItemString(self->dict, name_plural); // printf("lib: %s\n", name_plural); if (ls && PyList_Check(ls)) { /* loop */ Py_ssize_t size = PyList_GET_SIZE(ls); Py_ssize_t i; PyObject *item; const char *item_str; for (i = 0; i < size; i++) { item = PyList_GET_ITEM(ls, i); item_str = _PyUnicode_AsString(item); // printf(" %s\n", item_str); if (item_str) { ID *id = BLO_library_append_named_part(mainl, &(self->blo_handle), item_str, code); if (id) { #ifdef USE_RNA_DATABLOCKS PointerRNA id_ptr; RNA_id_pointer_create(id, &id_ptr); Py_DECREF(item); item = pyrna_struct_CreatePyObject(&id_ptr); #endif } else { bpy_lib_exit_warn_idname(self, name_plural, item_str); /* just warn for now */ /* err = -1; */ #ifdef USE_RNA_DATABLOCKS item = Py_None; Py_INCREF(item); #endif } /* ID or None */ } else { /* XXX, could complain about this */ bpy_lib_exit_warn_type(self, item); PyErr_Clear(); #ifdef USE_RNA_DATABLOCKS item = Py_None; Py_INCREF(item); #endif } #ifdef USE_RNA_DATABLOCKS PyList_SET_ITEM(ls, i, item); #endif } } } } } if (err == -1) { /* exception raised above, XXX, this leaks some memory */ BLO_blendhandle_close(self->blo_handle); self->blo_handle = NULL; flag_all_listbases_ids(LIB_PRE_EXISTING, 0); return NULL; } else { Library *lib = mainl->curlib; /* newly added lib, assign before append end */ BLO_library_append_end(NULL, mainl, &(self->blo_handle), 0, self->flag); BLO_blendhandle_close(self->blo_handle); self->blo_handle = NULL; { /* copied from wm_operator.c */ /* mark all library linked objects to be updated */ recalc_all_library_objects(G.main); /* append, rather than linking */ if ((self->flag & FILE_LINK) == 0) { BKE_library_make_local(bmain, lib, 1); } } flag_all_listbases_ids(LIB_PRE_EXISTING, 0); Py_RETURN_NONE; } }
/***************************************************************************** * Description: Creates the bpy module and adds it to sys.modules for importing *****************************************************************************/ void BPy_init_modules(void) { extern BPy_StructRNA *bpy_context_module; extern int bpy_lib_init(PyObject *); PointerRNA ctx_ptr; PyObject *mod; /* Needs to be first since this dir is needed for future modules */ char *modpath= BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, "modules"); if (modpath) { // printf("bpy: found module path '%s'.\n", modpath); PyObject *sys_path= PySys_GetObject("path"); /* borrow */ PyObject *py_modpath= PyUnicode_FromString(modpath); PyList_Insert(sys_path, 0, py_modpath); /* add first */ Py_DECREF(py_modpath); } else { printf("bpy: couldnt find 'scripts/modules', blender probably wont start.\n"); } /* stand alone utility modules not related to blender directly */ IDProp_Init_Types(); /* not actually a submodule, just types */ mod= PyModule_New("_bpy"); /* add the module so we can import it */ PyDict_SetItemString(PyImport_GetModuleDict(), "_bpy", mod); Py_DECREF(mod); /* run first, initializes rna types */ BPY_rna_init(); PyModule_AddObject(mod, "types", BPY_rna_types()); /* needs to be first so bpy_types can run */ PyModule_AddObject(mod, "StructMetaPropGroup", (PyObject *)&pyrna_struct_meta_idprop_Type); /* metaclass for idprop types, bpy_types.py needs access */ bpy_lib_init(mod); /* adds '_bpy._library_load', must be called before 'bpy_types' which uses it */ bpy_import_test("bpy_types"); PyModule_AddObject(mod, "data", BPY_rna_module()); /* imports bpy_types by running this */ bpy_import_test("bpy_types"); PyModule_AddObject(mod, "props", BPY_rna_props()); PyModule_AddObject(mod, "ops", BPY_operator_module()); /* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */ PyModule_AddObject(mod, "app", BPY_app_struct()); /* bpy context */ RNA_pointer_create(NULL, &RNA_Context, (void *)BPy_GetContext(), &ctx_ptr); bpy_context_module= (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ctx_ptr); /* odd that this is needed, 1 ref on creation and another for the module * but without we get a crash on exit */ Py_INCREF(bpy_context_module); PyModule_AddObject(mod, "context", (PyObject *)bpy_context_module); /* utility func's that have nowhere else to go */ PyModule_AddObject(mod, meth_bpy_script_paths.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_script_paths, NULL)); PyModule_AddObject(mod, meth_bpy_blend_paths.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_blend_paths, NULL)); PyModule_AddObject(mod, meth_bpy_user_resource.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_user_resource, NULL)); PyModule_AddObject(mod, meth_bpy_resource_path.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_resource_path, NULL)); /* register funcs (bpy_rna.c) */ PyModule_AddObject(mod, meth_bpy_register_class.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_register_class, NULL)); PyModule_AddObject(mod, meth_bpy_unregister_class.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_unregister_class, NULL)); /* add our own modules dir, this is a python package */ bpy_package_py= bpy_import_test("bpy"); }
static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) { Main *bmain = CTX_data_main(BPy_GetContext()); Main *mainl = NULL; int err = 0; BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, true); /* here appending/linking starts */ mainl = BLO_library_link_begin(bmain, &(self->blo_handle), self->relpath); { int idcode_step = 0, idcode; while ((idcode = BKE_idcode_iter_step(&idcode_step))) { if (BKE_idcode_is_linkable(idcode)) { const char *name_plural = BKE_idcode_to_name_plural(idcode); PyObject *ls = PyDict_GetItemString(self->dict, name_plural); // printf("lib: %s\n", name_plural); if (ls && PyList_Check(ls)) { /* loop */ Py_ssize_t size = PyList_GET_SIZE(ls); Py_ssize_t i; PyObject *item; const char *item_str; for (i = 0; i < size; i++) { item = PyList_GET_ITEM(ls, i); item_str = _PyUnicode_AsString(item); // printf(" %s\n", item_str); if (item_str) { ID *id = BLO_library_link_named_part(mainl, &(self->blo_handle), idcode, item_str); if (id) { #ifdef USE_RNA_DATABLOCKS /* swap name for pointer to the id */ Py_DECREF(item); item = PyCapsule_New((void *)id, NULL, NULL); #endif } else { bpy_lib_exit_warn_idname(self, name_plural, item_str); /* just warn for now */ /* err = -1; */ #ifdef USE_RNA_DATABLOCKS item = Py_INCREF_RET(Py_None); #endif } /* ID or None */ } else { /* XXX, could complain about this */ bpy_lib_exit_warn_type(self, item); PyErr_Clear(); #ifdef USE_RNA_DATABLOCKS item = Py_INCREF_RET(Py_None); #endif } #ifdef USE_RNA_DATABLOCKS PyList_SET_ITEM(ls, i, item); #endif } } } } } if (err == -1) { /* exception raised above, XXX, this leaks some memory */ BLO_blendhandle_close(self->blo_handle); self->blo_handle = NULL; BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, false); return NULL; } else { Library *lib = mainl->curlib; /* newly added lib, assign before append end */ BLO_library_link_end(mainl, &(self->blo_handle), self->flag, NULL, NULL); BLO_blendhandle_close(self->blo_handle); self->blo_handle = NULL; /* copied from wm_operator.c */ { /* mark all library linked objects to be updated */ BKE_main_lib_objects_recalc_all(G.main); /* append, rather than linking */ if ((self->flag & FILE_LINK) == 0) { BKE_library_make_local(bmain, lib, true); } } BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, false); /* finally swap the capsules for real bpy objects * important since BLO_library_append_end initializes NodeTree types used by srna->refine */ { int idcode_step = 0, idcode; while ((idcode = BKE_idcode_iter_step(&idcode_step))) { if (BKE_idcode_is_linkable(idcode)) { const char *name_plural = BKE_idcode_to_name_plural(idcode); PyObject *ls = PyDict_GetItemString(self->dict, name_plural); if (ls && PyList_Check(ls)) { Py_ssize_t size = PyList_GET_SIZE(ls); Py_ssize_t i; PyObject *item; for (i = 0; i < size; i++) { item = PyList_GET_ITEM(ls, i); if (PyCapsule_CheckExact(item)) { PointerRNA id_ptr; ID *id; id = PyCapsule_GetPointer(item, NULL); Py_DECREF(item); RNA_id_pointer_create(id, &id_ptr); item = pyrna_struct_CreatePyObject(&id_ptr); PyList_SET_ITEM(ls, i, item); } } } } } } Py_RETURN_NONE; } }