From fc9ec1b9d80fb17d3cc5d3c63f8e4bb356fa7ebc Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 30 Oct 2020 15:27:57 +0100 Subject: Refactor: move Area .blend I/O to blenkernel There should be no functional changes. Eventually, it would be good to handle the different space types using callbacks. Ref T76372. --- source/blender/blenkernel/BKE_screen.h | 9 + source/blender/blenkernel/intern/screen.c | 787 ++++++++++++++++++++++++++++++ 2 files changed, 796 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 857d344cf7e..da87ff3e969 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -60,6 +60,7 @@ struct wmWindow; struct wmWindowManager; struct BlendWriter; struct BlendDataReader; +struct BlendLibReader; /* spacetype has everything stored to get an editor working, it gets initialized via * ED_spacetypes_init() in editors/space_api/spacetypes.c */ @@ -457,6 +458,14 @@ void BKE_screen_view3d_shading_blend_write(struct BlendWriter *writer, void BKE_screen_view3d_shading_blend_read_data(struct BlendDataReader *reader, struct View3DShading *shading); +void BKE_screen_area_map_blend_write(struct BlendWriter *writer, struct ScrAreaMap *area_map); +bool BKE_screen_area_map_blend_read_data(struct BlendDataReader *reader, + struct ScrAreaMap *area_map); +void BKE_screen_view3d_do_versions_250(struct View3D *v3d, ListBase *regions); +void BKE_screen_area_blend_read_lib(struct BlendLibReader *reader, + struct ID *parent_id, + struct ScrArea *area); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 098dbf6a84e..cfe52dd40e6 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -21,6 +21,9 @@ * \ingroup bke */ +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #ifdef WIN32 # include "BLI_winstuff.h" #endif @@ -49,6 +52,7 @@ #include "BLT_translation.h" +#include "BKE_gpencil.h" #include "BKE_icons.h" #include "BKE_idprop.h" #include "BKE_idtype.h" @@ -1128,3 +1132,786 @@ void BKE_screen_view3d_shading_blend_read_data(BlendDataReader *reader, View3DSh IDP_BlendDataRead(reader, &shading->prop); } } + +static void write_region(BlendWriter *writer, ARegion *region, int spacetype) +{ + BLO_write_struct(writer, ARegion, region); + + if (region->regiondata) { + if (region->flag & RGN_FLAG_TEMP_REGIONDATA) { + return; + } + + switch (spacetype) { + case SPACE_VIEW3D: + if (region->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3d = region->regiondata; + BLO_write_struct(writer, RegionView3D, rv3d); + + if (rv3d->localvd) { + BLO_write_struct(writer, RegionView3D, rv3d->localvd); + } + if (rv3d->clipbb) { + BLO_write_struct(writer, BoundBox, rv3d->clipbb); + } + } + else { + printf("regiondata write missing!\n"); + } + break; + default: + printf("regiondata write missing!\n"); + } + } +} + +static void write_uilist(BlendWriter *writer, uiList *ui_list) +{ + BLO_write_struct(writer, uiList, ui_list); + + if (ui_list->properties) { + IDP_BlendWrite(writer, ui_list->properties); + } +} + +static void write_space_outliner(BlendWriter *writer, SpaceOutliner *space_outliner) +{ + BLI_mempool *ts = space_outliner->treestore; + + if (ts) { + SpaceOutliner space_outliner_flat = *space_outliner; + + int elems = BLI_mempool_len(ts); + /* linearize mempool to array */ + TreeStoreElem *data = elems ? BLI_mempool_as_arrayN(ts, "TreeStoreElem") : NULL; + + if (data) { + /* In this block we use the memory location of the treestore + * but _not_ its data, the addresses in this case are UUID's, + * since we can't rely on malloc giving us different values each time. + */ + TreeStore ts_flat = {0}; + + /* we know the treestore is at least as big as a pointer, + * so offsetting works to give us a UUID. */ + void *data_addr = (void *)POINTER_OFFSET(ts, sizeof(void *)); + + ts_flat.usedelem = elems; + ts_flat.totelem = elems; + ts_flat.data = data_addr; + + BLO_write_struct(writer, SpaceOutliner, space_outliner); + + 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 { + 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) { + BLO_write_struct(writer, Panel, panel); + write_panel_list(writer, &panel->children); + } +} + +static void write_area_regions(BlendWriter *writer, ScrArea *area) +{ + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + write_region(writer, region, area->spacetype); + write_panel_list(writer, ®ion->panels); + + LISTBASE_FOREACH (PanelCategoryStack *, pc_act, ®ion->panels_category_active) { + BLO_write_struct(writer, PanelCategoryStack, pc_act); + } + + LISTBASE_FOREACH (uiList *, ui_list, ®ion->ui_lists) { + write_uilist(writer, ui_list); + } + + LISTBASE_FOREACH (uiPreview *, ui_preview, ®ion->ui_previews) { + BLO_write_struct(writer, uiPreview, ui_preview); + } + } + + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + LISTBASE_FOREACH (ARegion *, region, &sl->regionbase) { + 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); + } + } + 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); + } +#ifdef WITH_GLOBAL_AREA_WRITING + else if (sl->spacetype == SPACE_TOPBAR) { + BLO_write_struct(writer, SpaceTopBar, sl); + } + else if (sl->spacetype == SPACE_STATUSBAR) { + BLO_write_struct(writer, SpaceStatusBar, sl); + } +#endif + 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); + } + } +} + +void BKE_screen_area_map_blend_write(BlendWriter *writer, ScrAreaMap *area_map) +{ + BLO_write_struct_list(writer, ScrVert, &area_map->vertbase); + BLO_write_struct_list(writer, ScrEdge, &area_map->edgebase); + LISTBASE_FOREACH (ScrArea *, area, &area_map->areabase) { + area->butspacetype = area->spacetype; /* Just for compatibility, will be reset below. */ + + BLO_write_struct(writer, ScrArea, area); + +#ifdef WITH_GLOBAL_AREA_WRITING + BLO_write_struct(writer, ScrGlobalAreaData, area->global); +#endif + + write_area_regions(writer, area); + + area->butspacetype = SPACE_EMPTY; /* Unset again, was changed above. */ + } +} + +static void direct_link_panel_list(BlendDataReader *reader, ListBase *lb) +{ + BLO_read_list(reader, lb); + + LISTBASE_FOREACH (Panel *, panel, lb) { + panel->runtime_flag = 0; + panel->activedata = NULL; + panel->type = NULL; + panel->runtime.custom_data_ptr = NULL; + direct_link_panel_list(reader, &panel->children); + } +} + +static void direct_link_region(BlendDataReader *reader, ARegion *region, int spacetype) +{ + direct_link_panel_list(reader, ®ion->panels); + + BLO_read_list(reader, ®ion->panels_category_active); + + BLO_read_list(reader, ®ion->ui_lists); + + /* The area's search filter is runtime only, so we need to clear the active flag on read. */ + region->flag &= ~RGN_FLAG_SEARCH_FILTER_ACTIVE; + + LISTBASE_FOREACH (uiList *, ui_list, ®ion->ui_lists) { + ui_list->type = NULL; + ui_list->dyn_data = NULL; + BLO_read_data_address(reader, &ui_list->properties); + IDP_BlendDataRead(reader, &ui_list->properties); + } + + BLO_read_list(reader, ®ion->ui_previews); + + if (spacetype == SPACE_EMPTY) { + /* unknown space type, don't leak regiondata */ + region->regiondata = NULL; + } + else if (region->flag & RGN_FLAG_TEMP_REGIONDATA) { + /* Runtime data, don't use. */ + region->regiondata = NULL; + } + else { + BLO_read_data_address(reader, ®ion->regiondata); + if (region->regiondata) { + if (spacetype == SPACE_VIEW3D) { + RegionView3D *rv3d = region->regiondata; + + BLO_read_data_address(reader, &rv3d->localvd); + BLO_read_data_address(reader, &rv3d->clipbb); + + rv3d->depths = NULL; + rv3d->render_engine = NULL; + rv3d->sms = NULL; + rv3d->smooth_timer = NULL; + + rv3d->rflag &= ~(RV3D_NAVIGATING | RV3D_PAINTING); + rv3d->runtime_viewlock = 0; + } + } + } + + region->v2d.sms = NULL; + region->v2d.alpha_hor = region->v2d.alpha_vert = 255; /* visible by default */ + BLI_listbase_clear(®ion->panels_category); + BLI_listbase_clear(®ion->handlers); + BLI_listbase_clear(®ion->uiblocks); + region->headerstr = NULL; + region->visible = 0; + region->type = NULL; + region->do_draw = 0; + region->gizmo_map = NULL; + region->regiontimer = NULL; + region->draw_buffer = NULL; + memset(®ion->drawrct, 0, sizeof(region->drawrct)); +} + +/* for the saved 2.50 files without regiondata */ +/* and as patch for 2.48 and older */ +void BKE_screen_view3d_do_versions_250(View3D *v3d, ListBase *regions) +{ + LISTBASE_FOREACH (ARegion *, region, regions) { + if (region->regiontype == RGN_TYPE_WINDOW && region->regiondata == NULL) { + RegionView3D *rv3d; + + rv3d = region->regiondata = MEM_callocN(sizeof(RegionView3D), "region v3d patch"); + rv3d->persp = (char)v3d->persp; + rv3d->view = (char)v3d->view; + rv3d->dist = v3d->dist; + copy_v3_v3(rv3d->ofs, v3d->ofs); + copy_qt_qt(rv3d->viewquat, v3d->viewquat); + } + } + + /* this was not initialized correct always */ + if (v3d->gridsubdiv == 0) { + v3d->gridsubdiv = 10; + } +} + +static void direct_link_area(BlendDataReader *reader, ScrArea *area) +{ + BLO_read_list(reader, &(area->spacedata)); + BLO_read_list(reader, &(area->regionbase)); + + BLI_listbase_clear(&area->handlers); + area->type = NULL; /* spacetype callbacks */ + + /* Should always be unset so that rna_Area_type_get works correctly. */ + area->butspacetype = SPACE_EMPTY; + + area->region_active_win = -1; + + area->flag &= ~AREA_FLAG_ACTIVE_TOOL_UPDATE; + + BLO_read_data_address(reader, &area->global); + + /* if we do not have the spacetype registered we cannot + * free it, so don't allocate any new memory for such spacetypes. */ + if (!BKE_spacetype_exists(area->spacetype)) { + /* Hint for versioning code to replace deprecated space types. */ + area->butspacetype = area->spacetype; + + area->spacetype = SPACE_EMPTY; + } + + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + direct_link_region(reader, region, area->spacetype); + } + + /* accident can happen when read/save new file with older version */ + /* 2.50: we now always add spacedata for info */ + if (area->spacedata.first == NULL) { + SpaceInfo *sinfo = MEM_callocN(sizeof(SpaceInfo), "spaceinfo"); + area->spacetype = sinfo->spacetype = SPACE_INFO; + BLI_addtail(&area->spacedata, sinfo); + } + /* add local view3d too */ + else if (area->spacetype == SPACE_VIEW3D) { + BKE_screen_view3d_do_versions_250(area->spacedata.first, &area->regionbase); + } + + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + BLO_read_list(reader, &(sl->regionbase)); + + /* if we do not have the spacetype registered we cannot + * free it, so don't allocate any new memory for such spacetypes. */ + if (!BKE_spacetype_exists(sl->spacetype)) { + sl->spacetype = SPACE_EMPTY; + } + + LISTBASE_FOREACH (ARegion *, region, &sl->regionbase) { + direct_link_region(reader, region, sl->spacetype); + } + + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + + v3d->flag |= V3D_INVALID_BACKBUF; + + 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); + + /* Runtime data */ + v3d->runtime.properties_storage = NULL; + v3d->runtime.flag = 0; + + /* 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); + BLI_listbase_clear(&sipo->runtime.ghost_curves); + } + 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->treehash = NULL; + space_outliner->tree.first = space_outliner->tree.last = NULL; + } + else if (sl->spacetype == SPACE_IMAGE) { + SpaceImage *sima = (SpaceImage *)sl; + + sima->iuser.scene = NULL; + sima->iuser.ok = 1; + 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->iofsd = NULL; + BLI_listbase_clear(&snode->linkdrag); + } + else if (sl->spacetype == SPACE_TEXT) { + SpaceText *st = (SpaceText *)sl; + memset(&st->runtime, 0, 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; + } + 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 allocted 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; + sfile->files = NULL; + sfile->layout = NULL; + sfile->op = NULL; + sfile->previews_timer = NULL; + BLO_read_data_address(reader, &sfile->params); + } + else if (sl->spacetype == SPACE_CLIP) { + SpaceClip *sclip = (SpaceClip *)sl; + + sclip->scopes.track_search = NULL; + sclip->scopes.track_preview = NULL; + sclip->scopes.ok = 0; + } + } + + BLI_listbase_clear(&area->actionzones); + + BLO_read_data_address(reader, &area->v1); + BLO_read_data_address(reader, &area->v2); + BLO_read_data_address(reader, &area->v3); + BLO_read_data_address(reader, &area->v4); +} + +/** + * \return false on error. + */ +bool BKE_screen_area_map_blend_read_data(BlendDataReader *reader, ScrAreaMap *area_map) +{ + BLO_read_list(reader, &area_map->vertbase); + BLO_read_list(reader, &area_map->edgebase); + BLO_read_list(reader, &area_map->areabase); + LISTBASE_FOREACH (ScrArea *, area, &area_map->areabase) { + direct_link_area(reader, area); + } + + /* edges */ + LISTBASE_FOREACH (ScrEdge *, se, &area_map->edgebase) { + BLO_read_data_address(reader, &se->v1); + BLO_read_data_address(reader, &se->v2); + BKE_screen_sort_scrvert(&se->v1, &se->v2); + + if (se->v1 == NULL) { + BLI_remlink(&area_map->edgebase, se); + + return false; + } + } + + return true; +} + +void BKE_screen_area_blend_read_lib(BlendLibReader *reader, ID *parent_id, ScrArea *area) +{ + BLO_read_id_address(reader, parent_id->lib, &area->full); + + memset(&area->runtime, 0x0, sizeof(area->runtime)); + + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + switch (sl->spacetype) { + case SPACE_VIEW3D: { + View3D *v3d = (View3D *)sl; + + 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: + 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; + BLO_read_id_address(reader, NULL, &space_outliner->search_tse.id); + + 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); + } + if (space_outliner->treehash) { + /* 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; + } + default: + break; + } + } +} -- cgit v1.2.3