diff options
author | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-09-28 12:52:22 +0300 |
---|---|---|
committer | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-09-28 12:52:22 +0300 |
commit | 808b03da437043d7bb809a4d0e9e523bbfad95f9 (patch) | |
tree | 4a3ef1f74b09328b2e97bf827fa1fc700a9e2e41 /source/blender/blenkernel/intern/screen.c | |
parent | 5270ac5ed87fb5f9b5605fdc332f16ea0f7ee59d (diff) |
Cleanup: decentralize .blend I/O for space types
This adds callbacks to `SpaceType` to make each editor responsible to
manage their own .blend I/O, and moves relevant code from `screen.c`
to the editors files.
Differential Revision: D11069
Diffstat (limited to 'source/blender/blenkernel/intern/screen.c')
-rw-r--r-- | source/blender/blenkernel/intern/screen.c | 599 |
1 files changed, 9 insertions, 590 deletions
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 03f0c3ff1e9..8517995a0d8 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -1123,59 +1123,6 @@ static void write_uilist(BlendWriter *writer, uiList *ui_list) } } -static void write_space_outliner(BlendWriter *writer, const SpaceOutliner *space_outliner) -{ - BLI_mempool *ts = space_outliner->treestore; - - if (ts) { - const int elems = BLI_mempool_len(ts); - /* linearize mempool to array */ - TreeStoreElem *data = elems ? BLI_mempool_as_arrayN(ts, "TreeStoreElem") : NULL; - - if (data) { - BLO_write_struct(writer, SpaceOutliner, space_outliner); - - /* To store #TreeStore (instead of the mempool), two unique memory addresses are needed, - * which can be used to identify the data on read: - * 1) One for the #TreeStore data itself. - * 2) One for the array of #TreeStoreElem's inside #TreeStore (#TreeStore.data). - * - * For 1) we just use the mempool's address (#SpaceOutliner::treestore). - * For 2) we don't have such a direct choice. We can't just use the array's address from - * above, since that may not be unique over all Outliners. So instead use an address relative - * to 1). - */ - /* TODO the mempool could be moved to #SpaceOutliner_Runtime so that #SpaceOutliner could - * hold the #TreeStore directly. */ - - /* Address relative to the tree-store, as noted above. */ - void *data_addr = (void *)POINTER_OFFSET(ts, sizeof(void *)); - /* There should be plenty of memory addresses within the mempool data that we can point into, - * just double-check we don't potentially end up with a memory address that another DNA - * struct might use. Assumes BLI_mempool uses the guarded allocator. */ - BLI_assert(MEM_allocN_len(ts) >= sizeof(void *) * 2); - - TreeStore ts_flat = {0}; - ts_flat.usedelem = elems; - ts_flat.totelem = elems; - ts_flat.data = data_addr; - - BLO_write_struct_at_address(writer, TreeStore, ts, &ts_flat); - BLO_write_struct_array_at_address(writer, TreeStoreElem, elems, data_addr, data); - - MEM_freeN(data); - } - else { - SpaceOutliner space_outliner_flat = *space_outliner; - space_outliner_flat.treestore = NULL; - BLO_write_struct_at_address(writer, SpaceOutliner, space_outliner, &space_outliner_flat); - } - } - else { - BLO_write_struct(writer, SpaceOutliner, space_outliner); - } -} - static void write_panel_list(BlendWriter *writer, ListBase *lb) { LISTBASE_FOREACH (Panel *, panel, lb) { @@ -1208,146 +1155,9 @@ static void write_area(BlendWriter *writer, ScrArea *area) write_region(writer, region, sl->spacetype); } - if (sl->spacetype == SPACE_VIEW3D) { - View3D *v3d = (View3D *)sl; - BLO_write_struct(writer, View3D, v3d); - - if (v3d->localvd) { - BLO_write_struct(writer, View3D, v3d->localvd); - } - - BKE_screen_view3d_shading_blend_write(writer, &v3d->shading); - } - else if (sl->spacetype == SPACE_GRAPH) { - SpaceGraph *sipo = (SpaceGraph *)sl; - ListBase tmpGhosts = sipo->runtime.ghost_curves; - - /* temporarily disable ghost curves when saving */ - BLI_listbase_clear(&sipo->runtime.ghost_curves); - - BLO_write_struct(writer, SpaceGraph, sl); - if (sipo->ads) { - BLO_write_struct(writer, bDopeSheet, sipo->ads); - } - - /* reenable ghost curves */ - sipo->runtime.ghost_curves = tmpGhosts; - } - else if (sl->spacetype == SPACE_PROPERTIES) { - BLO_write_struct(writer, SpaceProperties, sl); - } - else if (sl->spacetype == SPACE_FILE) { - SpaceFile *sfile = (SpaceFile *)sl; - - BLO_write_struct(writer, SpaceFile, sl); - if (sfile->params) { - BLO_write_struct(writer, FileSelectParams, sfile->params); - } - if (sfile->asset_params) { - BLO_write_struct(writer, FileAssetSelectParams, sfile->asset_params); - } - } - else if (sl->spacetype == SPACE_SEQ) { - BLO_write_struct(writer, SpaceSeq, sl); - } - else if (sl->spacetype == SPACE_OUTLINER) { - SpaceOutliner *space_outliner = (SpaceOutliner *)sl; - write_space_outliner(writer, space_outliner); - } - else if (sl->spacetype == SPACE_IMAGE) { - BLO_write_struct(writer, SpaceImage, sl); - } - else if (sl->spacetype == SPACE_TEXT) { - BLO_write_struct(writer, SpaceText, sl); - } - else if (sl->spacetype == SPACE_SCRIPT) { - SpaceScript *scr = (SpaceScript *)sl; - scr->but_refs = NULL; - BLO_write_struct(writer, SpaceScript, sl); - } - else if (sl->spacetype == SPACE_ACTION) { - BLO_write_struct(writer, SpaceAction, sl); - } - else if (sl->spacetype == SPACE_NLA) { - SpaceNla *snla = (SpaceNla *)sl; - - BLO_write_struct(writer, SpaceNla, snla); - if (snla->ads) { - BLO_write_struct(writer, bDopeSheet, snla->ads); - } - } - else if (sl->spacetype == SPACE_NODE) { - SpaceNode *snode = (SpaceNode *)sl; - BLO_write_struct(writer, SpaceNode, snode); - - LISTBASE_FOREACH (bNodeTreePath *, path, &snode->treepath) { - BLO_write_struct(writer, bNodeTreePath, path); - } - } - else if (sl->spacetype == SPACE_CONSOLE) { - SpaceConsole *con = (SpaceConsole *)sl; - - LISTBASE_FOREACH (ConsoleLine *, cl, &con->history) { - /* 'len_alloc' is invalid on write, set from 'len' on read */ - BLO_write_struct(writer, ConsoleLine, cl); - BLO_write_raw(writer, (size_t)cl->len + 1, cl->line); - } - BLO_write_struct(writer, SpaceConsole, sl); - } - else if (sl->spacetype == SPACE_TOPBAR) { - BLO_write_struct(writer, SpaceTopBar, sl); - } - else if (sl->spacetype == SPACE_STATUSBAR) { - BLO_write_struct(writer, SpaceStatusBar, sl); - } - else if (sl->spacetype == SPACE_USERPREF) { - BLO_write_struct(writer, SpaceUserPref, sl); - } - else if (sl->spacetype == SPACE_CLIP) { - BLO_write_struct(writer, SpaceClip, sl); - } - else if (sl->spacetype == SPACE_INFO) { - BLO_write_struct(writer, SpaceInfo, sl); - } - else if (sl->spacetype == SPACE_SPREADSHEET) { - BLO_write_struct(writer, SpaceSpreadsheet, sl); - SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl; - - LISTBASE_FOREACH (SpreadsheetRowFilter *, row_filter, &sspreadsheet->row_filters) { - BLO_write_struct(writer, SpreadsheetRowFilter, row_filter); - BLO_write_string(writer, row_filter->value_string); - } - - LISTBASE_FOREACH (SpreadsheetColumn *, column, &sspreadsheet->columns) { - BLO_write_struct(writer, SpreadsheetColumn, column); - BLO_write_struct(writer, SpreadsheetColumnID, column->id); - BLO_write_string(writer, column->id->name); - /* While the display name is technically runtime data, we write it here, otherwise the row - * filters might not now their type if their region draws before the main region. - * This would ideally be cleared here. */ - BLO_write_string(writer, column->display_name); - } - LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) { - switch (context->type) { - case SPREADSHEET_CONTEXT_OBJECT: { - SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context; - BLO_write_struct(writer, SpreadsheetContextObject, object_context); - break; - } - case SPREADSHEET_CONTEXT_MODIFIER: { - SpreadsheetContextModifier *modifier_context = (SpreadsheetContextModifier *)context; - BLO_write_struct(writer, SpreadsheetContextModifier, modifier_context); - BLO_write_string(writer, modifier_context->modifier_name); - break; - } - case SPREADSHEET_CONTEXT_NODE: { - SpreadsheetContextNode *node_context = (SpreadsheetContextNode *)context; - BLO_write_struct(writer, SpreadsheetContextNode, node_context); - BLO_write_string(writer, node_context->node_name); - break; - } - } - } + SpaceType *space_type = BKE_spacetype_from_id(sl->spacetype); + if (space_type && space_type->blend_write) { + space_type->blend_write(writer, sl); } } } @@ -1523,225 +1333,9 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area) direct_link_region(reader, region, sl->spacetype); } - if (sl->spacetype == SPACE_VIEW3D) { - View3D *v3d = (View3D *)sl; - - memset(&v3d->runtime, 0x0, sizeof(v3d->runtime)); - - if (v3d->gpd) { - BLO_read_data_address(reader, &v3d->gpd); - BKE_gpencil_blend_read_data(reader, v3d->gpd); - } - BLO_read_data_address(reader, &v3d->localvd); - - /* render can be quite heavy, set to solid on load */ - if (v3d->shading.type == OB_RENDER) { - v3d->shading.type = OB_SOLID; - } - v3d->shading.prev_type = OB_SOLID; - - BKE_screen_view3d_shading_blend_read_data(reader, &v3d->shading); - - BKE_screen_view3d_do_versions_250(v3d, &sl->regionbase); - } - else if (sl->spacetype == SPACE_GRAPH) { - SpaceGraph *sipo = (SpaceGraph *)sl; - - BLO_read_data_address(reader, &sipo->ads); - memset(&sipo->runtime, 0x0, sizeof(sipo->runtime)); - } - else if (sl->spacetype == SPACE_NLA) { - SpaceNla *snla = (SpaceNla *)sl; - - BLO_read_data_address(reader, &snla->ads); - } - else if (sl->spacetype == SPACE_OUTLINER) { - SpaceOutliner *space_outliner = (SpaceOutliner *)sl; - - /* use #BLO_read_get_new_data_address_no_us and do not free old memory avoiding double - * frees and use of freed memory. this could happen because of a - * bug fixed in revision 58959 where the treestore memory address - * was not unique */ - TreeStore *ts = BLO_read_get_new_data_address_no_us(reader, space_outliner->treestore); - space_outliner->treestore = NULL; - if (ts) { - TreeStoreElem *elems = BLO_read_get_new_data_address_no_us(reader, ts->data); - - space_outliner->treestore = BLI_mempool_create( - sizeof(TreeStoreElem), ts->usedelem, 512, BLI_MEMPOOL_ALLOW_ITER); - if (ts->usedelem && elems) { - for (int i = 0; i < ts->usedelem; i++) { - TreeStoreElem *new_elem = BLI_mempool_alloc(space_outliner->treestore); - *new_elem = elems[i]; - } - } - /* we only saved what was used */ - space_outliner->storeflag |= SO_TREESTORE_CLEANUP; /* at first draw */ - } - space_outliner->tree.first = space_outliner->tree.last = NULL; - space_outliner->runtime = NULL; - } - else if (sl->spacetype == SPACE_IMAGE) { - SpaceImage *sima = (SpaceImage *)sl; - - sima->iuser.scene = NULL; - sima->scopes.waveform_1 = NULL; - sima->scopes.waveform_2 = NULL; - sima->scopes.waveform_3 = NULL; - sima->scopes.vecscope = NULL; - sima->scopes.ok = 0; - - /* WARNING: gpencil data is no longer stored directly in sima after 2.5 - * so sacrifice a few old files for now to avoid crashes with new files! - * committed: r28002 */ -#if 0 - sima->gpd = newdataadr(fd, sima->gpd); - if (sima->gpd) { - BKE_gpencil_blend_read_data(fd, sima->gpd); - } -#endif - } - else if (sl->spacetype == SPACE_NODE) { - SpaceNode *snode = (SpaceNode *)sl; - - if (snode->gpd) { - BLO_read_data_address(reader, &snode->gpd); - BKE_gpencil_blend_read_data(reader, snode->gpd); - } - - BLO_read_list(reader, &snode->treepath); - snode->edittree = NULL; - snode->runtime = NULL; - } - else if (sl->spacetype == SPACE_TEXT) { - SpaceText *st = (SpaceText *)sl; - memset(&st->runtime, 0x0, sizeof(st->runtime)); - } - else if (sl->spacetype == SPACE_SEQ) { - SpaceSeq *sseq = (SpaceSeq *)sl; - - /* grease pencil data is not a direct data and can't be linked from direct_link* - * functions, it should be linked from lib_link* functions instead - * - * otherwise it'll lead to lost grease data on open because it'll likely be - * read from file after all other users of grease pencil and newdataadr would - * simple return NULL here (sergey) - */ -#if 0 - if (sseq->gpd) { - sseq->gpd = newdataadr(fd, sseq->gpd); - BKE_gpencil_blend_read_data(fd, sseq->gpd); - } -#endif - sseq->scopes.reference_ibuf = NULL; - sseq->scopes.zebra_ibuf = NULL; - sseq->scopes.waveform_ibuf = NULL; - sseq->scopes.sep_waveform_ibuf = NULL; - sseq->scopes.vector_ibuf = NULL; - sseq->scopes.histogram_ibuf = NULL; - memset(&sseq->runtime, 0x0, sizeof(sseq->runtime)); - } - else if (sl->spacetype == SPACE_PROPERTIES) { - SpaceProperties *sbuts = (SpaceProperties *)sl; - - sbuts->path = NULL; - sbuts->texuser = NULL; - sbuts->mainbo = sbuts->mainb; - sbuts->mainbuser = sbuts->mainb; - sbuts->runtime = NULL; - } - else if (sl->spacetype == SPACE_CONSOLE) { - SpaceConsole *sconsole = (SpaceConsole *)sl; - - BLO_read_list(reader, &sconsole->scrollback); - BLO_read_list(reader, &sconsole->history); - - /* Comma expressions, (e.g. expr1, expr2, expr3) evaluate each expression, - * from left to right. the right-most expression sets the result of the comma - * expression as a whole. */ - LISTBASE_FOREACH_MUTABLE (ConsoleLine *, cl, &sconsole->history) { - BLO_read_data_address(reader, &cl->line); - if (cl->line) { - /* The allocated length is not written, so reset here. */ - cl->len_alloc = cl->len + 1; - } - else { - BLI_remlink(&sconsole->history, cl); - MEM_freeN(cl); - } - } - } - else if (sl->spacetype == SPACE_FILE) { - SpaceFile *sfile = (SpaceFile *)sl; - - /* this sort of info is probably irrelevant for reloading... - * plus, it isn't saved to files yet! - */ - sfile->folders_prev = sfile->folders_next = NULL; - BLI_listbase_clear(&sfile->folder_histories); - sfile->files = NULL; - sfile->layout = NULL; - sfile->op = NULL; - sfile->previews_timer = NULL; - sfile->tags = 0; - sfile->runtime = NULL; - BLO_read_data_address(reader, &sfile->params); - BLO_read_data_address(reader, &sfile->asset_params); - if (sfile->params) { - sfile->params->rename_id = NULL; - } - if (sfile->asset_params) { - sfile->asset_params->base_params.rename_id = NULL; - } - } - else if (sl->spacetype == SPACE_ACTION) { - SpaceAction *saction = (SpaceAction *)sl; - - memset(&saction->runtime, 0x0, sizeof(saction->runtime)); - } - else if (sl->spacetype == SPACE_CLIP) { - SpaceClip *sclip = (SpaceClip *)sl; - - sclip->scopes.track_search = NULL; - sclip->scopes.track_preview = NULL; - sclip->scopes.ok = 0; - } - else if (sl->spacetype == SPACE_SPREADSHEET) { - SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl; - - sspreadsheet->runtime = NULL; - BLO_read_list(reader, &sspreadsheet->row_filters); - LISTBASE_FOREACH (SpreadsheetRowFilter *, row_filter, &sspreadsheet->row_filters) { - BLO_read_data_address(reader, &row_filter->value_string); - } - BLO_read_list(reader, &sspreadsheet->columns); - LISTBASE_FOREACH (SpreadsheetColumn *, column, &sspreadsheet->columns) { - BLO_read_data_address(reader, &column->id); - BLO_read_data_address(reader, &column->id->name); - /* While the display name is technically runtime data, it is loaded here, otherwise the row - * filters might not now their type if their region draws before the main region. - * This would ideally be cleared here. */ - BLO_read_data_address(reader, &column->display_name); - } - - BLO_read_list(reader, &sspreadsheet->context_path); - LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) { - switch (context->type) { - case SPREADSHEET_CONTEXT_NODE: { - SpreadsheetContextNode *node_context = (SpreadsheetContextNode *)context; - BLO_read_data_address(reader, &node_context->node_name); - break; - } - case SPREADSHEET_CONTEXT_MODIFIER: { - SpreadsheetContextModifier *modifier_context = (SpreadsheetContextModifier *)context; - BLO_read_data_address(reader, &modifier_context->modifier_name); - break; - } - case SPREADSHEET_CONTEXT_OBJECT: { - break; - } - } - } + SpaceType *space_type = BKE_spacetype_from_id(sl->spacetype); + if (space_type && space_type->blend_read_data) { + space_type->blend_read_data(reader, sl); } } @@ -1785,185 +1379,10 @@ void BKE_screen_area_blend_read_lib(BlendLibReader *reader, ID *parent_id, ScrAr memset(&area->runtime, 0x0, sizeof(area->runtime)); LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { - switch (sl->spacetype) { - case SPACE_VIEW3D: { - View3D *v3d = (View3D *)sl; + SpaceType *space_type = BKE_spacetype_from_id(sl->spacetype); - BLO_read_id_address(reader, parent_id->lib, &v3d->camera); - BLO_read_id_address(reader, parent_id->lib, &v3d->ob_center); - - if (v3d->localvd) { - BLO_read_id_address(reader, parent_id->lib, &v3d->localvd->camera); - } - break; - } - case SPACE_GRAPH: { - SpaceGraph *sipo = (SpaceGraph *)sl; - bDopeSheet *ads = sipo->ads; - - if (ads) { - BLO_read_id_address(reader, parent_id->lib, &ads->source); - BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp); - } - break; - } - case SPACE_PROPERTIES: { - SpaceProperties *sbuts = (SpaceProperties *)sl; - BLO_read_id_address(reader, parent_id->lib, &sbuts->pinid); - if (sbuts->pinid == NULL) { - sbuts->flag &= ~SB_PIN_CONTEXT; - } - break; - } - case SPACE_FILE: { - SpaceFile *sfile = (SpaceFile *)sl; - sfile->tags |= FILE_TAG_REBUILD_MAIN_FILES; - break; - } - case SPACE_ACTION: { - SpaceAction *saction = (SpaceAction *)sl; - bDopeSheet *ads = &saction->ads; - - if (ads) { - BLO_read_id_address(reader, parent_id->lib, &ads->source); - BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp); - } - - BLO_read_id_address(reader, parent_id->lib, &saction->action); - break; - } - case SPACE_IMAGE: { - SpaceImage *sima = (SpaceImage *)sl; - - BLO_read_id_address(reader, parent_id->lib, &sima->image); - BLO_read_id_address(reader, parent_id->lib, &sima->mask_info.mask); - - /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data - * so fingers crossed this works fine! - */ - BLO_read_id_address(reader, parent_id->lib, &sima->gpd); - break; - } - case SPACE_SEQ: { - SpaceSeq *sseq = (SpaceSeq *)sl; - - /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data - * so fingers crossed this works fine! - */ - BLO_read_id_address(reader, parent_id->lib, &sseq->gpd); - break; - } - case SPACE_NLA: { - SpaceNla *snla = (SpaceNla *)sl; - bDopeSheet *ads = snla->ads; - - if (ads) { - BLO_read_id_address(reader, parent_id->lib, &ads->source); - BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp); - } - break; - } - case SPACE_TEXT: { - SpaceText *st = (SpaceText *)sl; - - BLO_read_id_address(reader, parent_id->lib, &st->text); - break; - } - case SPACE_SCRIPT: { - SpaceScript *scpt = (SpaceScript *)sl; - /*scpt->script = NULL; - 2.45 set to null, better re-run the script */ - if (scpt->script) { - BLO_read_id_address(reader, parent_id->lib, &scpt->script); - if (scpt->script) { - SCRIPT_SET_NULL(scpt->script); - } - } - break; - } - case SPACE_OUTLINER: { - SpaceOutliner *space_outliner = (SpaceOutliner *)sl; - - if (space_outliner->treestore) { - TreeStoreElem *tselem; - BLI_mempool_iter iter; - - BLI_mempool_iternew(space_outliner->treestore, &iter); - while ((tselem = BLI_mempool_iterstep(&iter))) { - BLO_read_id_address(reader, NULL, &tselem->id); - } - /* rebuild hash table, because it depends on ids too */ - space_outliner->storeflag |= SO_TREESTORE_REBUILD; - } - break; - } - case SPACE_NODE: { - SpaceNode *snode = (SpaceNode *)sl; - - /* node tree can be stored locally in id too, link this first */ - BLO_read_id_address(reader, parent_id->lib, &snode->id); - BLO_read_id_address(reader, parent_id->lib, &snode->from); - - bNodeTree *ntree = snode->id ? ntreeFromID(snode->id) : NULL; - if (ntree) { - snode->nodetree = ntree; - } - else { - BLO_read_id_address(reader, parent_id->lib, &snode->nodetree); - } - - bNodeTreePath *path; - for (path = snode->treepath.first; path; path = path->next) { - if (path == snode->treepath.first) { - /* first nodetree in path is same as snode->nodetree */ - path->nodetree = snode->nodetree; - } - else { - BLO_read_id_address(reader, parent_id->lib, &path->nodetree); - } - - if (!path->nodetree) { - break; - } - } - - /* remaining path entries are invalid, remove */ - bNodeTreePath *path_next; - for (; path; path = path_next) { - path_next = path->next; - - BLI_remlink(&snode->treepath, path); - MEM_freeN(path); - } - - /* edittree is just the last in the path, - * set this directly since the path may have been shortened above */ - if (snode->treepath.last) { - path = snode->treepath.last; - snode->edittree = path->nodetree; - } - else { - snode->edittree = NULL; - } - break; - } - case SPACE_CLIP: { - SpaceClip *sclip = (SpaceClip *)sl; - BLO_read_id_address(reader, parent_id->lib, &sclip->clip); - BLO_read_id_address(reader, parent_id->lib, &sclip->mask_info.mask); - break; - } - case SPACE_SPREADSHEET: { - SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl; - LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) { - if (context->type == SPREADSHEET_CONTEXT_OBJECT) { - BLO_read_id_address( - reader, parent_id->lib, &((SpreadsheetContextObject *)context)->object); - } - } - break; - } - default: - break; + if (space_type && space_type->blend_read_lib) { + space_type->blend_read_lib(reader, parent_id, sl); } } } |