diff options
Diffstat (limited to 'source/blender/blenloader/intern')
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 286 | ||||
-rw-r--r-- | source/blender/blenloader/intern/versioning_280.c | 133 | ||||
-rw-r--r-- | source/blender/blenloader/intern/versioning_defaults.c | 40 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 53 |
4 files changed, 405 insertions, 107 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index d22af275469..966cbce62db 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -53,6 +53,10 @@ /* allow readfile to use deprecated functionality */ #define DNA_DEPRECATED_ALLOW +/* Allow using DNA struct members that are marked as private for read/write. + * Note: Each header that uses this needs to define its own way of handling + * it. There's no generic implementation, direct use does nothing. */ +#define DNA_PRIVATE_READ_WRITE_ALLOW #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -99,10 +103,13 @@ #include "DNA_sound_types.h" #include "DNA_space_types.h" #include "DNA_vfont_types.h" +#include "DNA_workspace_types.h" #include "DNA_world_types.h" #include "DNA_movieclip_types.h" #include "DNA_mask_types.h" +#include "RNA_access.h" + #include "MEM_guardedalloc.h" #include "BLI_endian_switch.h" @@ -149,6 +156,7 @@ #include "BKE_outliner_treehash.h" #include "BKE_sound.h" #include "BKE_colortools.h" +#include "BKE_workspace.h" #include "DEG_depsgraph.h" @@ -2774,6 +2782,78 @@ static void direct_link_cachefile(FileData *fd, CacheFile *cache_file) direct_link_animdata(fd, cache_file->adt); } +/* ************ READ WORKSPACES *************** */ + +static void lib_link_workspaces(FileData *fd, Main *bmain) +{ + for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { + ListBase *layouts = BKE_workspace_layouts_get(workspace); + ID *id = (ID *)workspace; + + if ((id->tag & LIB_TAG_NEED_LINK) == 0) { + continue; + } + IDP_LibLinkProperty(id->properties, fd); + id_us_ensure_real(id); + + for (WorkSpaceLayout *layout = layouts->first; layout; layout = layout->next) { + bScreen *screen = newlibadr(fd, id->lib, BKE_workspace_layout_screen_get(layout)); + + if (screen) { + BKE_workspace_layout_screen_set(layout, screen); + + if (ID_IS_LINKED_DATABLOCK(id)) { + screen->winid = 0; + if (screen->temp) { + /* delete temp layouts when appending */ + BKE_workspace_layout_remove(bmain, workspace, layout); + } + } + } + } + + id->tag &= ~LIB_TAG_NEED_LINK; + } +} + +static void direct_link_workspace(FileData *fd, WorkSpace *workspace, const Main *main) +{ + link_list(fd, BKE_workspace_layouts_get(workspace)); + link_list(fd, &workspace->hook_layout_relations); + + for (WorkSpaceDataRelation *relation = workspace->hook_layout_relations.first; + relation; + relation = relation->next) + { + relation->parent = newglobadr(fd, relation->parent); /* data from window - need to access through global oldnew-map */ + relation->value = newdataadr(fd, relation->value); + } + + if (ID_IS_LINKED_DATABLOCK(&workspace->id)) { + /* Appending workspace so render layer is likely from a different scene. Unset + * now, when activating workspace later we set a valid one from current scene. */ + BKE_workspace_render_layer_set(workspace, NULL); + } + + /* Same issue/fix as in direct_link_scene_update_screen_data: Can't read workspace data + * when reading windows, so have to update windows after/when reading workspaces. */ + for (wmWindowManager *wm = main->wm.first; wm; wm = wm->id.next) { + for (wmWindow *win = wm->windows.first; win; win = win->next) { + WorkSpaceLayout *act_layout = newdataadr(fd, BKE_workspace_active_layout_get(win->workspace_hook)); + if (act_layout) { + BKE_workspace_active_layout_set(win->workspace_hook, act_layout); + } + } + } +} + +static void lib_link_workspace_instance_hook(FileData *fd, WorkSpaceInstanceHook *hook, ID *id) +{ + WorkSpace *workspace = BKE_workspace_active_get(hook); + BKE_workspace_active_set(hook, newlibadr(fd, id->lib, workspace)); +} + + /* ************ READ MOTION PATHS *************** */ /* direct data for cache */ @@ -5977,7 +6057,19 @@ static void direct_link_layer_collections(FileData *fd, ListBase *lb) } } -static void direct_link_scene(FileData *fd, Scene *sce) +static void direct_link_scene_update_screen_data( + FileData *fd, const Scene *scene, const ListBase *workspaces) +{ + for (WorkSpace *workspace = workspaces->first; workspace; workspace = workspace->id.next) { + SceneLayer *layer = newdataadr(fd, BKE_workspace_render_layer_get(workspace)); + /* only set when layer is from the scene we read */ + if (layer && (BLI_findindex(&scene->render_layers, layer) != -1)) { + BKE_workspace_render_layer_set(workspace, layer); + } + } +} + +static void direct_link_scene(FileData *fd, Scene *sce, Main *bmain) { Editing *ed; Sequence *seq; @@ -6250,7 +6342,8 @@ static void direct_link_scene(FileData *fd, Scene *sce) direct_link_scene_collection(fd, sce->collection); } - link_list(fd, &sce->render_layers); + /* insert into global old-new map for reading without UI (link_global accesses it again) */ + link_glob_list(fd, &sce->render_layers); for (sl = sce->render_layers.first; sl; sl = sl->next) { sl->stats = NULL; link_list(fd, &sl->object_bases); @@ -6277,6 +6370,8 @@ static void direct_link_scene(FileData *fd, Scene *sce) BKE_layer_collection_engine_settings_validate_scene(sce); BKE_scene_layer_engine_settings_validate_scene(sce); + + direct_link_scene_update_screen_data(fd, sce, &bmain->workspaces); } /* ************ READ WM ***************** */ @@ -6289,6 +6384,12 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) link_list(fd, &wm->windows); for (win = wm->windows.first; win; win = win->next) { + WorkSpaceInstanceHook *hook = win->workspace_hook; + + win->workspace_hook = newdataadr(fd, hook); + /* we need to restore a pointer to this later when reading workspaces, so store in global oldnew-map */ + oldnewmap_insert(fd->globmap, hook, win->workspace_hook, 0); + win->ghostwin = NULL; win->eventstate = NULL; win->curswin = NULL; @@ -6353,6 +6454,11 @@ static void lib_link_windowmanager(FileData *fd, Main *main) if (wm->id.tag & LIB_TAG_NEED_LINK) { /* Note: WM IDProperties are never written to file, hence no need to read/link them here. */ for (win = wm->windows.first; win; win = win->next) { + if (win->workspace_hook) { /* NULL for old files */ + lib_link_workspace_instance_hook(fd, win->workspace_hook, &wm->id); + } + win->scene = newlibadr(fd, wm->id.lib, win->scene); + /* deprecated, but needed for versioning (will be NULL'ed then) */ win->screen = newlibadr(fd, NULL, win->screen); } @@ -6438,13 +6544,9 @@ static void lib_link_screen(FileData *fd, Main *main) IDP_LibLinkProperty(sc->id.properties, fd); id_us_ensure_real(&sc->id); + /* deprecated, but needed for versioning (will be NULL'ed then) */ sc->scene = newlibadr(fd, sc->id.lib, sc->scene); - /* this should not happen, but apparently it does somehow. Until we figure out the cause, - * just assign first available scene */ - if (!sc->scene) - sc->scene = main->scene.first; - sc->animtimer = NULL; /* saved in rare cases */ sc->scrubbing = false; @@ -6752,56 +6854,59 @@ static void lib_link_clipboard_restore(struct IDNameLib_Map *id_map) BKE_sequencer_base_recursive_apply(&seqbase_clipboard, lib_link_seq_clipboard_cb, id_map); } -/* called from kernel/blender.c */ -/* used to link a file (without UI) to the current UI */ -/* note that it assumes the old pointers in UI are still valid, so old Main is not freed */ -void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene) +static void lib_link_workspace_scene_data_restore(wmWindow *win, Scene *scene) { - wmWindow *win; - wmWindowManager *wm; - bScreen *sc; - ScrArea *sa; + bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); - struct IDNameLib_Map *id_map = BKE_main_idmap_create(newmain); + for (ScrArea *area = screen->areabase.first; area; area = area->next) { + for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; - /* first windowmanager */ - for (wm = newmain->wm.first; wm; wm = wm->id.next) { - for (win= wm->windows.first; win; win= win->next) { - win->screen = restore_pointer_by_name(id_map, (ID *)win->screen, USER_REAL); - - if (win->screen == NULL) - win->screen = curscreen; - - win->screen->winid = win->winid; + if (v3d->camera == NULL || v3d->scenelock) { + v3d->camera = scene->camera; + } + + if (v3d->localvd) { + /*Base *base;*/ + + v3d->localvd->camera = scene->camera; + + /* localview can become invalid during undo/redo steps, so we exit it when no could be found */ +#if 0 /* XXX regionlocalview ? */ + for (base= sc->scene->base.first; base; base= base->next) { + if (base->lay & v3d->lay) break; + } + if (base==NULL) { + v3d->lay= v3d->localvd->lay; + v3d->layact= v3d->localvd->layact; + MEM_freeN(v3d->localvd); + v3d->localvd= NULL; + } +#endif + } + else if (v3d->scenelock) { + v3d->lay = scene->lay; + } + } } } - - - for (sc = newmain->screen.first; sc; sc = sc->id.next) { - Scene *oldscene = sc->scene; - - sc->scene= restore_pointer_by_name(id_map, (ID *)sc->scene, USER_REAL); - if (sc->scene == NULL) - sc->scene = curscene; - - /* keep cursor location through undo */ - copy_v3_v3(sc->scene->cursor, oldscene->cursor); - - for (sa = sc->areabase.first; sa; sa = sa->next) { - SpaceLink *sl; - - for (sl = sa->spacedata.first; sl; sl = sl->next) { +} + +static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map, Main *newmain, WorkSpaceLayout *layout) +{ + bScreen *screen = BKE_workspace_layout_screen_get(layout); + + /* avoid conflicts with 2.8x branch */ + { + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) { if (sl->spacetype == SPACE_VIEW3D) { View3D *v3d = (View3D *)sl; BGpic *bgpic; ARegion *ar; - if (v3d->scenelock) - v3d->camera = NULL; /* always get from scene */ - else - v3d->camera = restore_pointer_by_name(id_map, (ID *)v3d->camera, USER_REAL); - if (v3d->camera == NULL) - v3d->camera = sc->scene->camera; + v3d->camera = restore_pointer_by_name(id_map, (ID *)v3d->camera, USER_REAL); v3d->ob_centre = restore_pointer_by_name(id_map, (ID *)v3d->ob_centre, USER_REAL); for (bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next) { @@ -6812,27 +6917,6 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc id_us_plus((ID *)bgpic->clip); } } - if (v3d->localvd) { - /*Base *base;*/ - - v3d->localvd->camera = sc->scene->camera; - - /* localview can become invalid during undo/redo steps, so we exit it when no could be found */ -#if 0 /* XXX regionlocalview ? */ - for (base= sc->scene->base.first; base; base= base->next) { - if (base->lay & v3d->lay) break; - } - if (base==NULL) { - v3d->lay= v3d->localvd->lay; - v3d->layact= v3d->localvd->layact; - MEM_freeN(v3d->localvd); - v3d->localvd= NULL; - } -#endif - } - else if (v3d->scenelock) { - v3d->lay = sc->scene->lay; - } /* not very nice, but could help */ if ((v3d->layact & v3d->lay) == 0) v3d->layact = v3d->lay; @@ -7035,6 +7119,44 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc } } } +} + +/** + * Used to link a file (without UI) to the current UI. + * Note that it assumes the old pointers in UI are still valid, so old Main is not freed. + */ +void blo_lib_link_restore(Main *newmain, wmWindowManager *curwm, Scene *curscene, SceneLayer *cur_render_layer) +{ + struct IDNameLib_Map *id_map = BKE_main_idmap_create(newmain); + + for (WorkSpace *workspace = newmain->workspaces.first; workspace; workspace = workspace->id.next) { + ListBase *layouts = BKE_workspace_layouts_get(workspace); + + for (WorkSpaceLayout *layout = layouts->first; layout; layout = layout->next) { + lib_link_workspace_layout_restore(id_map, newmain, layout); + } + BKE_workspace_render_layer_set(workspace, cur_render_layer); + } + + for (wmWindow *win = curwm->windows.first; win; win = win->next) { + WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook); + ID *workspace_id = (ID *)workspace; + Scene *oldscene = win->scene; + + workspace = restore_pointer_by_name(id_map, workspace_id, USER_REAL); + BKE_workspace_active_set(win->workspace_hook, workspace); + win->scene = restore_pointer_by_name(id_map, (ID *)win->scene, USER_REAL); + if (win->scene == NULL) { + win->scene = curscene; + } + BKE_workspace_active_set(win->workspace_hook, workspace); + + /* keep cursor location through undo */ + copy_v3_v3(win->scene->cursor, oldscene->cursor); + lib_link_workspace_scene_data_restore(win, win->scene); + + BLI_assert(win->screen == NULL); + } /* update IDs stored in all possible clipboards */ lib_link_clipboard_restore(id_map); @@ -8146,6 +8268,7 @@ static const char *dataname(short id_code) case ID_MSK: return "Data from MSK"; case ID_LS: return "Data from LS"; case ID_CF: return "Data from CF"; + case ID_WS: return "Data from WS"; } return "Data from Lib Block"; @@ -8309,7 +8432,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short wrong_id = direct_link_screen(fd, (bScreen *)id); break; case ID_SCE: - direct_link_scene(fd, (Scene *)id); + direct_link_scene(fd, (Scene *)id, main); break; case ID_OB: direct_link_object(fd, (Object *)id); @@ -8404,6 +8527,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short case ID_CF: direct_link_cachefile(fd, (CacheFile *)id); break; + case ID_WS: + direct_link_workspace(fd, (WorkSpace *)id, main); + break; } oldnewmap_free_unused(fd->datamap); @@ -8449,7 +8575,8 @@ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead) bfd->curscreen = fg->curscreen; bfd->curscene = fg->curscene; - + bfd->cur_render_layer = fg->cur_render_layer; + MEM_freeN(fg); fd->globalf = bfd->globalf; @@ -8461,6 +8588,7 @@ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead) /* note, this has to be kept for reading older files... */ static void link_global(FileData *fd, BlendFileData *bfd) { + bfd->cur_render_layer = newglobadr(fd, bfd->cur_render_layer); bfd->curscreen = newlibadr(fd, NULL, bfd->curscreen); bfd->curscene = newlibadr(fd, NULL, bfd->curscene); // this happens in files older than 2.35 @@ -8580,6 +8708,7 @@ static void lib_link_all(FileData *fd, Main *main) lib_link_linestyle(fd, main); lib_link_gpencil(fd, main); lib_link_cachefiles(fd, main); + lib_link_workspaces(fd, main); lib_link_library(fd, main); /* only init users */ } @@ -8966,6 +9095,11 @@ static void expand_doit_library(void *fdhandle, Main *mainvar, void *old) } } else { + /* in 2.50+ file identifier for screens is patched, forward compatibility */ + if (bhead->code == ID_SCRN) { + bhead->code = ID_SCR; + } + id = is_yet_read(fd, mainvar, bhead); if (id == NULL) { read_libblock(fd, mainvar, bhead, LIB_TAG_TESTIND, NULL); @@ -9817,6 +9951,15 @@ static void expand_gpencil(FileData *fd, Main *mainvar, bGPdata *gpd) expand_animdata(fd, mainvar, gpd->adt); } +static void expand_workspace(FileData *fd, Main *mainvar, WorkSpace *workspace) +{ + ListBase *layouts = BKE_workspace_layouts_get(workspace); + + for (WorkSpaceLayout *layout = layouts->first; layout; layout = layout->next) { + expand_doit(fd, mainvar, BKE_workspace_layout_screen_get(layout)); + } +} + /** * Set the callback func used over all ID data found by \a BLO_expand_main func. * @@ -9931,6 +10074,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar) case ID_CF: expand_cachefile(fd, mainvar, (CacheFile *)id); break; + case ID_WS: + expand_workspace(fd, mainvar, (WorkSpace *)id); + break; } do_it = true; diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 3eeb0fc78e4..2d14238eb6f 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -45,6 +45,7 @@ #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_scene.h" +#include "BKE_workspace.h" #include "BLI_listbase.h" #include "BLI_mempool.h" @@ -55,6 +56,83 @@ #include "MEM_guardedalloc.h" + +static bScreen *screen_parent_find(const bScreen *screen) +{ + /* can avoid lookup if screen state isn't maximized/full (parent and child store the same state) */ + if (ELEM(screen->state, SCREENMAXIMIZED, SCREENFULL)) { + for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + if (sa->full && sa->full != screen) { + BLI_assert(sa->full->state == screen->state); + return sa->full; + } + } + } + + return NULL; +} + +static void do_version_workspaces_create_from_screens(Main *bmain) +{ + for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) { + const bScreen *screen_parent = screen_parent_find(screen); + WorkSpace *workspace; + + if (screen_parent) { + /* fullscreen with "Back to Previous" option, don't create + * a new workspace, add layout workspace containing parent */ + workspace = BLI_findstring( + &bmain->workspaces, screen_parent->id.name + 2, offsetof(ID, name) + 2); + } + else { + workspace = BKE_workspace_add(bmain, screen->id.name + 2); + } + BKE_workspace_layout_add(workspace, screen, screen->id.name + 2); + BKE_workspace_render_layer_set(workspace, screen->scene->render_layers.first); + } +} + +/** + * \brief After lib-link versioning for new workspace design. + * + * * Adds a workspace for (almost) each screen of the old file + * and adds the needed workspace-layout to wrap the screen. + * * Active screen isn't stored directly in window anymore, but in the active workspace. + * * Active scene isn't stored in screen anymore, but in window. + * * Create workspace instance hook for each window. + * + * \note Some of the created workspaces might be deleted again in case of reading the default startup.blend. + */ +static void do_version_workspaces_after_lib_link(Main *bmain) +{ + BLI_assert(BLI_listbase_is_empty(&bmain->workspaces)); + + do_version_workspaces_create_from_screens(bmain); + + for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) { + for (wmWindow *win = wm->windows.first; win; win = win->next) { + bScreen *screen_parent = screen_parent_find(win->screen); + bScreen *screen = screen_parent ? screen_parent : win->screen; + WorkSpace *workspace = BLI_findstring(&bmain->workspaces, screen->id.name + 2, offsetof(ID, name) + 2); + ListBase *layouts = BKE_workspace_layouts_get(workspace); + + win->workspace_hook = BKE_workspace_instance_hook_create(bmain); + + BKE_workspace_active_set(win->workspace_hook, workspace); + BKE_workspace_active_layout_set(win->workspace_hook, layouts->first); + + win->scene = screen->scene; + /* Deprecated from now on! */ + win->screen = NULL; + } + } + + for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) { + /* Deprecated from now on! */ + screen->scene = NULL; + } +} + void do_versions_after_linking_280(Main *main) { if (!MAIN_VERSION_ATLEAST(main, 280, 0)) { @@ -183,13 +261,18 @@ void do_versions_after_linking_280(Main *main) scene->basact = NULL; } } + } + if (!MAIN_VERSION_ATLEAST(main, 280, 0)) { for (bScreen *screen = main->screen.first; screen; screen = screen->id.next) { + /* same render-layer as do_version_workspaces_after_lib_link will activate, + * so same layer as BKE_scene_layer_context_active would return */ + SceneLayer *layer = screen->scene->render_layers.first; + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) { if (sl->spacetype == SPACE_OUTLINER) { SpaceOops *soutliner = (SpaceOops *)sl; - SceneLayer *layer = BKE_scene_layer_context_active(screen->scene); soutliner->outlinevis = SO_ACT_LAYER; @@ -213,6 +296,11 @@ void do_versions_after_linking_280(Main *main) } } } + + /* New workspace design */ + if (!MAIN_VERSION_ATLEAST(main, 280, 1)) { + do_version_workspaces_after_lib_link(main); + } } static void do_version_layer_collections_idproperties(ListBase *lb) @@ -254,34 +342,35 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main) } } } - } - if (!DNA_struct_elem_find(fd->filesdna, "GPUDOFSettings", "float", "ratio")) { - for (Camera *ca = main->camera.first; ca; ca = ca->id.next) { - ca->gpu_dof.ratio = 1.0f; + if (!MAIN_VERSION_ATLEAST(main, 280, 1)) { + if (!DNA_struct_elem_find(fd->filesdna, "GPUDOFSettings", "float", "ratio")) { + for (Camera *ca = main->camera.first; ca; ca = ca->id.next) { + ca->gpu_dof.ratio = 1.0f; + } } - } - if (!DNA_struct_elem_find(fd->filesdna, "SceneLayer", "IDProperty", "*properties")) { - for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { - for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { - IDPropertyTemplate val = {0}; - sl->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); - BKE_scene_layer_engine_settings_create(sl->properties); + if (!DNA_struct_elem_find(fd->filesdna, "SceneLayer", "IDProperty", "*properties")) { + for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { + for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { + IDPropertyTemplate val = {0}; + sl->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); + BKE_scene_layer_engine_settings_create(sl->properties); + } } } - } - /* MTexPoly now removed. */ - if (DNA_struct_find(fd->filesdna, "MTexPoly")) { - const int cd_mtexpoly = 15; /* CD_MTEXPOLY, deprecated */ - for (Mesh *me = main->mesh.first; me; me = me->id.next) { - /* If we have UV's, so this file will have MTexPoly layers too! */ - if (me->mloopuv != NULL) { - CustomData_update_typemap(&me->pdata); - CustomData_free_layers(&me->pdata, cd_mtexpoly, me->totpoly); - BKE_mesh_update_customdata_pointers(me, false); + /* MTexPoly now removed. */ + if (DNA_struct_find(fd->filesdna, "MTexPoly")) { + const int cd_mtexpoly = 15; /* CD_MTEXPOLY, deprecated */ + for (Mesh *me = main->mesh.first; me; me = me->id.next) { + /* If we have UV's, so this file will have MTexPoly layers too! */ + if (me->mloopuv != NULL) { + CustomData_update_typemap(&me->pdata); + CustomData_free_layers(&me->pdata, cd_mtexpoly, me->totpoly); + BKE_mesh_update_customdata_pointers(me, false); + } } } } diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index a38f122ec56..002af20bc3a 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -40,10 +40,12 @@ #include "DNA_mesh_types.h" #include "DNA_material_types.h" #include "DNA_object_types.h" +#include "DNA_workspace_types.h" #include "BKE_brush.h" #include "BKE_library.h" #include "BKE_main.h" +#include "BKE_workspace.h" #include "BLO_readfile.h" @@ -84,6 +86,32 @@ void BLO_update_defaults_userpref_blend(void) } /** + * New workspace design: Remove all screens/workspaces except of "Default" one and rename the workspace to "General". + * For compatibility, a new workspace has been created for each screen of old files, + * we only want one workspace and one screen in the default startup file however. + */ +static void update_defaults_startup_workspaces(Main *bmain) +{ + WorkSpace *workspace_default = NULL; + + for (WorkSpace *workspace = bmain->workspaces.first, *workspace_next; workspace; workspace = workspace_next) { + workspace_next = workspace->id.next; + + if (STREQ(workspace->id.name + 2, "Default")) { + /* don't rename within iterator, renaming causes listbase to be re-sorted */ + workspace_default = workspace; + } + else { + BKE_workspace_remove(bmain, workspace); + } + } + + /* rename "Default" workspace to "General" */ + BKE_libblock_rename(bmain, (ID *)workspace_default, "General"); + BLI_assert(BLI_listbase_count(BKE_workspace_layouts_get(workspace_default)) == 1); +} + +/** * Update defaults in startup.blend, without having to save and embed the file. * This function can be emptied each time the startup.blend is updated. */ void BLO_update_defaults_startup_blend(Main *bmain) @@ -181,20 +209,18 @@ void BLO_update_defaults_startup_blend(Main *bmain) linestyle->chain_count = 10; } - for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) { - ScrArea *area; - for (area = screen->areabase.first; area; area = area->next) { - SpaceLink *space_link; - ARegion *ar; + update_defaults_startup_workspaces(bmain); - for (space_link = area->spacedata.first; space_link; space_link = space_link->next) { + for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) { + for (ScrArea *area = screen->areabase.first; area; area = area->next) { + for (SpaceLink *space_link = area->spacedata.first; space_link; space_link = space_link->next) { if (space_link->spacetype == SPACE_CLIP) { SpaceClip *space_clip = (SpaceClip *) space_link; space_clip->flag &= ~SC_MANUAL_CALIBRATION; } } - for (ar = area->regionbase.first; ar; ar = ar->next) { + for (ARegion *ar = area->regionbase.first; ar; ar = ar->next) { /* Remove all stored panels, we want to use defaults (order, open/closed) as defined by UI code here! */ BLI_freelistN(&ar->panels); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 19f6b9f370d..82d2e37dce0 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -102,6 +102,10 @@ /* allow writefile to use deprecated functionality (for forward compatibility code) */ #define DNA_DEPRECATED_ALLOW +/* Allow using DNA struct members that are marked as private for read/write. + * Note: Each header that uses this needs to define its own way of handling + * it. There's no generic implementation, direct use does nothing. */ +#define DNA_PRIVATE_READ_WRITE_ALLOW #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -147,6 +151,7 @@ #include "DNA_vfont_types.h" #include "DNA_world_types.h" #include "DNA_windowmanager_types.h" +#include "DNA_workspace_types.h" #include "DNA_movieclip_types.h" #include "DNA_mask_types.h" @@ -173,6 +178,7 @@ #include "BKE_fcurve.h" #include "BKE_pointcache.h" #include "BKE_mesh.h" +#include "BKE_workspace.h" #ifdef USE_NODE_COMPAT_CUSTOMNODES #include "NOD_socket.h" /* for sock->default_value data */ @@ -1077,10 +1083,13 @@ static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree) * Take care using 'use_active_win', since we wont want the currently active window * to change which scene renders (currently only used for undo). */ -static void current_screen_compat(Main *mainvar, bScreen **r_screen, bool use_active_win) +static void current_screen_compat( + Main *mainvar, bool use_active_win, + bScreen **r_screen, Scene **r_scene, SceneLayer **r_render_layer) { wmWindowManager *wm; wmWindow *window = NULL; + WorkSpace *workspace; /* find a global current screen in the first open window, to have * a reasonable default for reading in older versions */ @@ -1104,8 +1113,11 @@ static void current_screen_compat(Main *mainvar, bScreen **r_screen, bool use_ac window = wm->windows.first; } } + workspace = (window) ? BKE_workspace_active_get(window->workspace_hook) : NULL; - *r_screen = (window) ? window->screen : NULL; + *r_screen = (window) ? BKE_workspace_active_screen_get(window->workspace_hook) : NULL; + *r_scene = (window) ? window->scene : NULL; + *r_render_layer = (window) ? BKE_workspace_render_layer_get(workspace) : NULL; } typedef struct RenderInfo { @@ -1121,13 +1133,11 @@ static void write_renderinfo(WriteData *wd, Main *mainvar) { bScreen *curscreen; Scene *sce, *curscene = NULL; + SceneLayer *render_layer; RenderInfo data; /* XXX in future, handle multiple windows with multiple screens? */ - current_screen_compat(mainvar, &curscreen, false); - if (curscreen) { - curscene = curscreen->scene; - } + current_screen_compat(mainvar, false, &curscreen, &curscene, &render_layer); for (sce = mainvar->scene.first; sce; sce = sce->id.next) { if (sce->id.lib == NULL && (sce == curscene || (sce->r.scemode & R_BG_RENDER))) { @@ -2842,8 +2852,19 @@ static void write_windowmanager(WriteData *wd, wmWindowManager *wm) write_iddata(wd, &wm->id); for (wmWindow *win = wm->windows.first; win; win = win->next) { + + /* update deprecated screen member (for so loading in 2.7x uses the correct screen) */ + win->screen = BKE_workspace_active_screen_get(win->workspace_hook); + if (win->screen) { + BLI_strncpy(win->screenname, win->screen->id.name + 2, sizeof(win->screenname)); + } + writestruct(wd, DATA, wmWindow, 1, win); + writestruct(wd, DATA, WorkSpaceInstanceHook, 1, win->workspace_hook); writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format); + + /* data is written, clear deprecated data again */ + win->screen = NULL; } } @@ -2984,6 +3005,7 @@ static void write_screen(WriteData *wd, bScreen *sc) View3D *v3d = (View3D *)sl; BGpic *bgpic; writestruct(wd, DATA, View3D, 1, v3d); + for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { writestruct(wd, DATA, BGpic, 1, bgpic); } @@ -3729,6 +3751,15 @@ static void write_cachefile(WriteData *wd, CacheFile *cache_file) } } +static void write_workspace(WriteData *wd, WorkSpace *workspace) +{ + ListBase *layouts = BKE_workspace_layouts_get(workspace); + + writestruct(wd, ID_WS, WorkSpace, 1, workspace); + writelist(wd, DATA, WorkSpaceLayout, layouts); + writelist(wd, DATA, WorkSpaceDataRelation, &workspace->hook_layout_relations); +} + /* Keep it last of write_foodata functions. */ static void write_libraries(WriteData *wd, Main *main) { @@ -3798,6 +3829,8 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar) const bool is_undo = (wd->current != NULL); FileGlobal fg; bScreen *screen; + Scene *scene; + SceneLayer *render_layer; char subvstr[8]; /* prevent mem checkers from complaining */ @@ -3805,11 +3838,12 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar) memset(fg.filename, 0, sizeof(fg.filename)); memset(fg.build_hash, 0, sizeof(fg.build_hash)); - current_screen_compat(mainvar, &screen, is_undo); + current_screen_compat(mainvar, is_undo, &screen, &scene, &render_layer); /* XXX still remap G */ fg.curscreen = screen; - fg.curscene = screen ? screen->scene : NULL; + fg.curscene = scene; + fg.cur_render_layer = render_layer; /* prevent to save this, is not good convention, and feature with concerns... */ fg.fileflags = (fileflags & ~G_FILE_FLAGS_RUNTIME); @@ -3905,6 +3939,9 @@ static bool write_file_handle( case ID_WM: write_windowmanager(wd, (wmWindowManager *)id); break; + case ID_WS: + write_workspace(wd, (WorkSpace *)id); + break; case ID_SCR: write_screen(wd, (bScreen *)id); break; |