45#define USE_RNA_DATABLOCKS
47#ifdef USE_RNA_DATABLOCKS
63 for (
int i = 0;
i < bool_flags_num;
i++) {
65 if (bool_flags[
i].value) {
121# pragma clang diagnostic push
122# pragma clang diagnostic ignored "-Wcast-function-type"
124# pragma GCC diagnostic push
125# pragma GCC diagnostic ignored "-Wcast-function-type"
132 {
"__dir__", (PyCFunction)
bpy_lib_dir, METH_NOARGS},
138# pragma clang diagnostic pop
140# pragma GCC diagnostic pop
146 Py_XDECREF(
self->dict);
151 PyVarObject_HEAD_INIT(
nullptr, 0)
167 PyObject_GenericGetAttr,
212 "reuse_local_id=False, "
213 "assets_only=False, "
214 "clear_asset_data=False, "
215 "create_liboverrides=False, "
216 "reuse_liboverrides=False, "
217 "create_liboverrides_runtime=False)\n"
219 " Returns a context manager which exposes 2 library objects on entering.\n"
220 " Each object has attributes matching bpy.data which are lists of strings to be linked.\n"
222 " :arg filepath: The path to a blend file.\n"
223 " :type filepath: str | bytes\n"
224 " :arg link: When False reference to the original file is lost.\n"
225 " :type link: bool\n"
226 " :arg pack: If True, and ``link`` is also True, pack linked data-blocks into the current "
228 " :type pack: bool\n"
229 " :arg relative: When True the path is stored relative to the open blend file.\n"
230 " :type relative: bool\n"
231 " :arg set_fake: If True, set fake user on appended IDs.\n"
232 " :type set_fake: bool\n"
233 " :arg recursive: If True, also make indirect dependencies of appended libraries local.\n"
234 " :type recursive: bool\n"
235 " :arg reuse_local_id: If True,"
236 "try to re-use previously appended matching ID on new append.\n"
237 " :type reuse_local_id: bool\n"
238 " :arg assets_only: If True, only list data-blocks marked as assets.\n"
239 " :type assets_only: bool\n"
240 " :arg clear_asset_data: If True, "
241 "clear the asset data on append (it is always kept for linked data).\n"
242 " :type clear_asset_data: bool\n"
243 " :arg create_liboverrides: If True and ``link`` is True, liboverrides will\n"
244 " be created for linked data.\n"
245 " :type create_liboverrides: bool\n"
246 " :arg reuse_liboverrides: If True and ``create_liboverride`` is True,\n"
247 " search for existing liboverride first.\n"
248 " :type reuse_liboverrides: bool\n"
249 " :arg create_liboverrides_runtime: If True and ``create_liboverride`` is True,\n"
250 " create (or search for existing) runtime liboverride.\n"
251 " :type create_liboverrides_runtime: bool\n");
275 bool create_liboverrides =
false;
281 } liboverride_flag_vars;
283 static const char *_keywords[] = {
293 "create_liboverrides",
294 "reuse_liboverrides",
295 "create_liboverrides_runtime",
298 static _PyArg_Parser _parser = {
318 if (!_PyArg_ParseTupleAndKeywordsFast(args,
328 &flag_vars.is_relative,
330 &flag_vars.recursive,
334 &flag_vars.reuse_local_id,
336 &flag_vars.assets_only,
338 &flag_vars.clear_asset_data,
340 &create_liboverrides,
342 &liboverride_flag_vars.reuse_liboverrides,
344 &liboverride_flag_vars.create_liboverrides_runtime))
354 STRNCPY(filepath_abs, filepath_rel);
358 if (blendfile_path[0]) {
366 char filepath_abs_normalized[
FILE_MAX];
367 STRNCPY(filepath_abs_normalized, filepath_abs);
369 if (
BLI_path_cmp(filepath_abs_normalized, blendfile_path) == 0) {
370 PyErr_SetString(PyExc_ValueError,
"Cannot load from the current blend file.");
375 if (flag_vars.is_link.value) {
377 if (flag_vars.set_fake.value) {
378 PyErr_SetString(PyExc_ValueError,
"`link` must be False if `set_fake` is True");
381 if (flag_vars.recursive.value) {
382 PyErr_SetString(PyExc_ValueError,
"`link` must be False if `recursive` is True");
385 if (flag_vars.reuse_local_id.value) {
386 PyErr_SetString(PyExc_ValueError,
"`link` must be False if `reuse_local_id` is True");
389 if (flag_vars.clear_asset_data.value) {
390 PyErr_SetString(PyExc_ValueError,
"`link` must be False if `clear_asset_data` is True");
396 if (create_liboverrides) {
397 PyErr_SetString(PyExc_ValueError,
"`link` is False but `create_liboverrides` is True");
400 if (flag_vars.is_pack.value) {
401 PyErr_SetString(PyExc_ValueError,
"`pack` must be False if `link` is False");
406 if (create_liboverrides) {
408 if (flag_vars.is_pack.value) {
409 PyErr_SetString(PyExc_ValueError,
"`create_liboverrides` must be False if `pack` is True");
415 if (liboverride_flag_vars.reuse_liboverrides.value) {
416 PyErr_SetString(PyExc_ValueError,
417 "`create_liboverrides` is False but `reuse_liboverrides` is True");
420 if (liboverride_flag_vars.create_liboverrides_runtime.value) {
421 PyErr_SetString(PyExc_ValueError,
422 "`create_liboverrides` is False but `create_liboverrides_runtime` is True");
433 ret->bmain_is_temp = (bmain != bmain_base);
435 ret->blo_handle =
nullptr;
440 ret->create_liboverrides = create_liboverrides;
441 ret->liboverride_flags = create_liboverrides ?
443 reinterpret_cast<const BoolFlagPair *
>(&liboverride_flag_vars),
444 sizeof(liboverride_flag_vars) /
sizeof(
BoolFlagPair))) :
449 return (PyObject *)
ret;
457 PyObject *list = PyList_New(names_num);
462 PyList_SET_ITEM(list,
i, PyUnicode_FromString((
char *)
l->link));
476 memset(bf_reports, 0,
sizeof(*bf_reports));
481 if (
self->blo_handle ==
nullptr) {
483 PyErr_Format(PyExc_IOError,
"load: %s failed to open blend file",
self->abspath);
489 PyObject *dict_dst =
self->dict;
490 int dict_num_offset = 0;
495 dict_num_offset += 1;
499 PyObject *
str = PyUnicode_FromString(name_plural);
502 PyDict_SetItem(dict_dst,
str, item = PyList_New(0));
518 PyObject *identifier = PyUnicode_FromString(
"version");
524 PyDict_SetItem(dict_src, identifier, version);
531 PyDict_SetItem(dict_dst, identifier, version);
541 self_src->
dict = dict_src;
552 PyObject *
ret = PyTuple_New(2);
558 const char *name_plural,
561 PyObject *exc, *val, *tb;
562 PyErr_Fetch(&exc, &val, &tb);
563 if (PyErr_WarnFormat(PyExc_UserWarning,
565 "load: '%s' does not contain %s[\"%s\"]",
571 if (PyErr_ExceptionMatches(PyExc_Warning)) {
572 PyErr_WriteUnraisable((PyObject *)
self);
575 PyErr_Restore(exc, val, tb);
580 PyObject *exc, *val, *tb;
581 PyErr_Fetch(&exc, &val, &tb);
582 if (PyErr_WarnFormat(PyExc_UserWarning,
584 "load: '%s' expected a string type, not a %.200s",
586 Py_TYPE(item)->tp_name))
589 if (PyErr_ExceptionMatches(PyExc_Warning)) {
590 PyErr_WriteUnraisable((PyObject *)
self);
593 PyErr_Restore(exc, val, tb);
617 ID *liboverride_id =
data.py_library->create_liboverrides ?
627 PyObject *item_src = PyList_GET_ITEM(
data.py_list, py_list_index);
631 if (liboverride_id !=
nullptr) {
635 else if (new_id !=
nullptr) {
640 const char *item_idname = PyUnicode_AsUTF8(item_src);
645 py_item = Py_NewRef(Py_None);
648 PyList_SET_ITEM(
data.py_list, py_list_index, py_item);
660 const bool create_liboverrides =
self->create_liboverrides;
663 BLI_assert(!do_append || !create_liboverrides);
676 self->blo_handle =
nullptr;
686 PyObject *ls = PyDict_GetItemString(
self->dict, name_plural);
688 if (ls ==
nullptr || !PyList_Check(ls)) {
692 const Py_ssize_t
size = PyList_GET_SIZE(ls);
698 for (Py_ssize_t
i = 0;
i <
size;
i++) {
699 PyObject *item_src = PyList_GET_ITEM(ls,
i);
700 const char *item_idname = PyUnicode_AsUTF8(item_src);
706 if (item_idname !=
nullptr) {
716#ifdef USE_RNA_DATABLOCKS
718 PyObject *py_item = Py_NewRef(Py_None);
719 PyList_SET_ITEM(ls,
i, py_item);
732 else if (do_append) {
735 else if (create_liboverrides) {
742#ifdef USE_RNA_DATABLOCKS
749 PyObject *ls = PyDict_GetItemString(
self->dict, name_plural);
751 if (ls ==
nullptr || !PyList_Check(ls)) {
755 const Py_ssize_t
size = PyList_GET_SIZE(ls);
763 iter_data.
idcode = idcode;
787 return PyDict_Keys(
self->dict);
792# pragma clang diagnostic push
793# pragma clang diagnostic ignored "-Wcast-function-type"
795# pragma GCC diagnostic push
796# pragma GCC diagnostic ignored "-Wcast-function-type"
803 METH_VARARGS | METH_KEYWORDS,
809# pragma clang diagnostic pop
811# pragma GCC diagnostic pop
#define BLENDER_FILE_SUBVERSION
#define BLENDER_FILE_VERSION
void BKE_blendfile_link_append_context_finalize(BlendfileLinkAppendContext *lapp_context)
void BKE_blendfile_link_append_context_item_foreach(BlendfileLinkAppendContext *lapp_context, blender::FunctionRef< bool(BlendfileLinkAppendContext *lapp_context, BlendfileLinkAppendContextItem *item)> callback_function, eBlendfileLinkAppendForeachItemFlag flag)
@ BKE_LIBLINK_OVERRIDE_USE_EXISTING_LIBOVERRIDES
@ BKE_LIBLINK_OVERRIDE_CREATE_RUNTIME
@ BKE_LIBLINK_OVERRIDE_INIT
void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *reports)
void BKE_blendfile_link_pack(BlendfileLinkAppendContext *lapp_context, ReportList *reports)
void BKE_blendfile_link_append_context_library_add(BlendfileLinkAppendContext *lapp_context, const char *libname, BlendHandle *blo_handle)
BlendfileLinkAppendContextItem * BKE_blendfile_link_append_context_item_add(BlendfileLinkAppendContext *lapp_context, const char *idname, short idcode, void *userdata)
void BKE_blendfile_link_append_context_free(BlendfileLinkAppendContext *lapp_context)
void BKE_blendfile_append(BlendfileLinkAppendContext *lapp_context, ReportList *reports)
void BKE_blendfile_override(BlendfileLinkAppendContext *lapp_context, const eBKELibLinkOverride flags, ReportList *reports)
void BKE_blendfile_link_append_context_item_library_index_enable(BlendfileLinkAppendContext *lapp_context, BlendfileLinkAppendContextItem *item, int library_index)
BlendfileLinkAppendContext * BKE_blendfile_link_append_context_new(LibraryLink_Params *params)
short BKE_blendfile_link_append_context_item_idcode_get(BlendfileLinkAppendContext *lapp_context, BlendfileLinkAppendContextItem *item)
ID * BKE_blendfile_link_append_context_item_liboverrideid_get(BlendfileLinkAppendContext *lapp_context, BlendfileLinkAppendContextItem *item)
@ BKE_BLENDFILE_LINK_APPEND_FOREACH_ITEM_FLAG_DO_DIRECT
void * BKE_blendfile_link_append_context_item_userdata_get(BlendfileLinkAppendContext *lapp_context, BlendfileLinkAppendContextItem *item)
void BKE_blendfile_link_append_context_init_done(BlendfileLinkAppendContext *lapp_context)
ID * BKE_blendfile_link_append_context_item_newid_get(BlendfileLinkAppendContext *lapp_context, BlendfileLinkAppendContextItem *item)
Main * CTX_data_main(const bContext *C)
bool BKE_idtype_idcode_is_linkable(short idcode)
short BKE_idtype_idcode_iter_step(int *idtype_index)
const char * BKE_idtype_idcode_to_name_plural(short idcode)
void BKE_main_id_tag_all(Main *mainvar, int tag, bool value)
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
@ RPT_PRINT_HANDLED_BY_OWNER
void BKE_reports_free(ReportList *reports)
void BKE_reports_clear(ReportList *reports)
void BKE_reports_init(ReportList *reports, int flag)
void BLI_linklist_freeN(LinkNode *list)
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
int BLI_path_normalize(char *path) ATTR_NONNULL(1)
char * STRNCPY(char(&dst)[N], const char *src)
#define POINTER_FROM_INT(i)
#define UNUSED_VARS_NDEBUG(...)
#define POINTER_AS_INT(i)
external readfile function prototypes.
@ BLO_LIBLINK_APPEND_RECURSIVE
@ BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR
@ BLO_LIBLINK_APPEND_SET_FAKEUSER
@ BLO_LIBLINK_APPEND_LOCAL_ID_REUSE
void BLO_library_link_params_init(LibraryLink_Params *params, Main *bmain, int flag, int id_tag_extra)
BlendHandle * BLO_blendhandle_from_file(const char *filepath, BlendFileReadReport *reports)
blender::int3 BLO_blendhandle_get_version(const BlendHandle *bh)
LinkNode * BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, bool use_assets_only, int *r_tot_names)
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMLoop * l
short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool clear)
struct bContext * BPY_context_get()
PyMethodDef BPY_library_load_method_def
static void bpy_lib_dealloc(BPy_Library *self)
static PyObject * bpy_lib_exit(BPy_Library *self, PyObject *args)
static PyMethodDef bpy_lib_methods[]
static uint32_t bool_flag_pair_as_flag(const BoolFlagPair *bool_flags, int bool_flags_num)
static PyObject * bpy_lib_enter(BPy_Library *self)
static PyObject * _bpy_names(BPy_Library *self, int blocktype)
static PyObject * bpy_lib_dir(BPy_Library *self)
static bool bpy_lib_exit_lapp_context_items_cb(BlendfileLinkAppendContext *lapp_context, BlendfileLinkAppendContextItem *item, LibExitLappContextItemsIterData &data)
static PyObject * bpy_lib_load(BPy_PropertyRNA *self, PyObject *args, PyObject *kw)
static constexpr Py_ssize_t bpy_library_dict_num
int BPY_library_load_type_ready()
static void bpy_lib_exit_warn_type(BPy_Library *self, PyObject *item)
static PyTypeObject bpy_lib_Type
static void bpy_lib_exit_warn_idname(BPy_Library *self, const char *name_plural, const char *idname)
PyDoc_STRVAR(bpy_lib_load_doc, ".. method:: load(" "filepath, " "*, " "link=False, " "relative=False, " "set_fake=False, " "recursive=False, " "reuse_local_id=False, " "assets_only=False, " "clear_asset_data=False, " "create_liboverrides=False, " "reuse_liboverrides=False, " "create_liboverrides_runtime=False)\n" "\n" " Returns a context manager which exposes 2 library objects on entering.\n" " Each object has attributes matching bpy.data which are lists of strings to be linked.\n" "\n" " :arg filepath: The path to a blend file.\n" " :type filepath: str | bytes\n" " :arg link: When False reference to the original file is lost.\n" " :type link: bool\n" " :arg pack: If True, and ``link`` is also True, pack linked data-blocks into the current " "blend-file.\n" " :type pack: bool\n" " :arg relative: When True the path is stored relative to the open blend file.\n" " :type relative: bool\n" " :arg set_fake: If True, set fake user on appended IDs.\n" " :type set_fake: bool\n" " :arg recursive: If True, also make indirect dependencies of appended libraries local.\n" " :type recursive: bool\n" " :arg reuse_local_id: If True," "try to re-use previously appended matching ID on new append.\n" " :type reuse_local_id: bool\n" " :arg assets_only: If True, only list data-blocks marked as assets.\n" " :type assets_only: bool\n" " :arg clear_asset_data: If True, " "clear the asset data on append (it is always kept for linked data).\n" " :type clear_asset_data: bool\n" " :arg create_liboverrides: If True and ``link`` is True, liboverrides will\n" " be created for linked data.\n" " :type create_liboverrides: bool\n" " :arg reuse_liboverrides: If True and ``create_liboverride`` is True,\n" " search for existing liboverride first.\n" " :type reuse_liboverrides: bool\n" " :arg create_liboverrides_runtime: If True and ``create_liboverride`` is True,\n" " create (or search for existing) runtime liboverride.\n" " :type create_liboverrides_runtime: bool\n")
PyObject * pyrna_struct_CreatePyObject(PointerRNA *ptr)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
VecBase< int32_t, 3 > int3
int PyC_ParseUnicodeAsBytesAndSize(PyObject *o, void *p)
PyObject * PyC_Tuple_PackArray_I32(const int *array, uint len)
int PyC_ParseBool(PyObject *o, void *p)
header-only compatibility defines.
#define PY_ARG_PARSER_HEAD_COMPAT()
#define PyTuple_SET_ITEMS(op_arg,...)
PointerRNA RNA_id_pointer_create(ID *id)
eBKELibLinkOverride liboverride_flags
BlendFileReadReport bf_reports
PyObject_HEAD char relpath[FILE_MAX]