Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Mon, 10 Dec 2018 01:44:24 +0000 (12:44 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Mon, 10 Dec 2018 01:44:24 +0000 (12:44 +1100)
1  2 
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/space_action/space_action.c
source/blender/editors/space_graph/graph_draw.c
source/blender/editors/space_graph/graph_edit.c
source/blender/editors/space_graph/space_graph.c
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_space_types.h
source/blender/makesrna/intern/rna_space.c

@@@ -6525,666 -6270,6 +6525,666 @@@ static void direct_link_scene(FileData 
        sce->preview = direct_link_preview_image(fd, sce->preview);
  
        direct_link_curvemapping(fd, &sce->r.mblur_shutter_curve);
-                       BLI_listbase_clear(&sipo->ghostCurves);
 +
 +#ifdef USE_COLLECTION_COMPAT_28
 +      /* this runs before the very first doversion */
 +      if (sce->collection) {
 +              sce->collection = newdataadr(fd, sce->collection);
 +              direct_link_scene_collection(fd, sce->collection);
 +      }
 +#endif
 +
 +      if (sce->master_collection) {
 +              sce->master_collection = newdataadr(fd, sce->master_collection);
 +              direct_link_collection(fd, sce->master_collection);
 +              /* Needed because this is an ID outside of Main. */
 +              sce->master_collection->id.py_instance = NULL;
 +      }
 +
 +      /* insert into global old-new map for reading without UI (link_global accesses it again) */
 +      link_glob_list(fd, &sce->view_layers);
 +      for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
 +              direct_link_view_layer(fd, view_layer);
 +      }
 +
 +      if (fd->memfile) {
 +              /* If it's undo try to recover the cache. */
 +              if (fd->scenemap) sce->eevee.light_cache = newsceadr(fd, sce->eevee.light_cache);
 +              else sce->eevee.light_cache = NULL;
 +      }
 +      else {
 +              /* else try to read the cache from file. */
 +              sce->eevee.light_cache = newdataadr(fd, sce->eevee.light_cache);
 +              if (sce->eevee.light_cache) {
 +                      direct_link_lightcache(fd, sce->eevee.light_cache);
 +              }
 +      }
 +
 +      sce->layer_properties = newdataadr(fd, sce->layer_properties);
 +      IDP_DirectLinkGroup_OrFree(&sce->layer_properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
 +}
 +
 +/* ****************** READ GREASE PENCIL ***************** */
 +
 +/* relink's grease pencil data's refs */
 +static void lib_link_gpencil(FileData *fd, Main *main)
 +{
 +      /* Relink all datablock linked by GP datablock */
 +      for (bGPdata *gpd = main->gpencil.first; gpd; gpd = gpd->id.next) {
 +              if (gpd->id.tag & LIB_TAG_NEED_LINK) {
 +                      /* Layers */
 +                      for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
 +                              /* Layer -> Parent References */
 +                              gpl->parent = newlibadr(fd, gpd->id.lib, gpl->parent);
 +                      }
 +
 +                      /* Datablock Stuff */
 +                      IDP_LibLinkProperty(gpd->id.properties, fd);
 +                      lib_link_animdata(fd, &gpd->id, gpd->adt);
 +
 +                      /* materials */
 +                      for (int a = 0; a < gpd->totcol; a++) {
 +                              gpd->mat[a] = newlibadr_us(fd, gpd->id.lib, gpd->mat[a]);
 +                      }
 +
 +                      gpd->id.tag &= ~LIB_TAG_NEED_LINK;
 +              }
 +      }
 +}
 +
 +/* relinks grease-pencil data - used for direct_link and old file linkage */
 +static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
 +{
 +      bGPDlayer *gpl;
 +      bGPDframe *gpf;
 +      bGPDstroke *gps;
 +      bGPDpalette *palette;
 +
 +      /* we must firstly have some grease-pencil data to link! */
 +      if (gpd == NULL)
 +              return;
 +
 +      /* relink animdata */
 +      gpd->adt = newdataadr(fd, gpd->adt);
 +      direct_link_animdata(fd, gpd->adt);
 +
 +      /* relink palettes (old palettes deprecated, only to convert old files) */
 +      link_list(fd, &gpd->palettes);
 +      if (gpd->palettes.first != NULL) {
 +              for (palette = gpd->palettes.first; palette; palette = palette->next) {
 +                      link_list(fd, &palette->colors);
 +              }
 +      }
 +
 +      /* materials */
 +      gpd->mat = newdataadr(fd, gpd->mat);
 +      test_pointer_array(fd, (void **)&gpd->mat);
 +
 +      /* relink layers */
 +      link_list(fd, &gpd->layers);
 +
 +      for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
 +              /* relink frames */
 +              link_list(fd, &gpl->frames);
 +
 +              gpl->actframe = newdataadr(fd, gpl->actframe);
 +
 +              gpl->runtime.icon_id = 0;
 +
 +              for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
 +                      /* relink strokes (and their points) */
 +                      link_list(fd, &gpf->strokes);
 +
 +                      for (gps = gpf->strokes.first; gps; gps = gps->next) {
 +                              /* relink stroke points array */
 +                              gps->points = newdataadr(fd, gps->points);
 +
 +                              /* relink weight data */
 +                              if (gps->dvert) {
 +                                      gps->dvert = newdataadr(fd, gps->dvert);
 +                                      direct_link_dverts(fd, gps->totpoints, gps->dvert);
 +                              }
 +
 +                              /* the triangulation is not saved, so need to be recalculated */
 +                              gps->triangles = NULL;
 +                              gps->tot_triangles = 0;
 +                              gps->flag |= GP_STROKE_RECALC_CACHES;
 +                      }
 +              }
 +      }
 +}
 +
 +/* *********** READ AREA **************** */
 +
 +static void direct_link_panel_list(FileData *fd, ListBase *lb)
 +{
 +      link_list(fd, lb);
 +
 +      for (Panel *pa = lb->first; pa; pa = pa->next) {
 +              pa->paneltab = newdataadr(fd, pa->paneltab);
 +              pa->runtime_flag = 0;
 +              pa->activedata = NULL;
 +              pa->type = NULL;
 +              direct_link_panel_list(fd, &pa->children);
 +      }
 +}
 +
 +static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
 +{
 +      uiList *ui_list;
 +
 +      direct_link_panel_list(fd, &ar->panels);
 +
 +      link_list(fd, &ar->panels_category_active);
 +
 +      link_list(fd, &ar->ui_lists);
 +
 +      for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next) {
 +              ui_list->type = NULL;
 +              ui_list->dyn_data = NULL;
 +              ui_list->properties = newdataadr(fd, ui_list->properties);
 +              IDP_DirectLinkGroup_OrFree(&ui_list->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
 +      }
 +
 +      link_list(fd, &ar->ui_previews);
 +
 +      if (spacetype == SPACE_EMPTY) {
 +              /* unkown space type, don't leak regiondata */
 +              ar->regiondata = NULL;
 +      }
 +      else if (ar->flag & RGN_FLAG_TEMP_REGIONDATA) {
 +              /* Runtime data, don't use. */
 +              ar->regiondata = NULL;
 +      }
 +      else {
 +              ar->regiondata = newdataadr(fd, ar->regiondata);
 +              if (ar->regiondata) {
 +                      if (spacetype == SPACE_VIEW3D) {
 +                              RegionView3D *rv3d = ar->regiondata;
 +
 +                              rv3d->localvd = newdataadr(fd, rv3d->localvd);
 +                              rv3d->clipbb = newdataadr(fd, rv3d->clipbb);
 +
 +                              rv3d->depths = NULL;
 +                              rv3d->gpuoffscreen = NULL;
 +                              rv3d->render_engine = NULL;
 +                              rv3d->sms = NULL;
 +                              rv3d->smooth_timer = NULL;
 +                      }
 +              }
 +      }
 +
 +      ar->v2d.tab_offset = NULL;
 +      ar->v2d.tab_num = 0;
 +      ar->v2d.tab_cur = 0;
 +      ar->v2d.sms = NULL;
 +      ar->v2d.alpha_hor = ar->v2d.alpha_vert = 255; /* visible by default */
 +      BLI_listbase_clear(&ar->panels_category);
 +      BLI_listbase_clear(&ar->handlers);
 +      BLI_listbase_clear(&ar->uiblocks);
 +      ar->headerstr = NULL;
 +      ar->visible = 0;
 +      ar->type = NULL;
 +      ar->do_draw = 0;
 +      ar->gizmo_map = NULL;
 +      ar->regiontimer = NULL;
 +      ar->draw_buffer = NULL;
 +      memset(&ar->drawrct, 0, sizeof(ar->drawrct));
 +}
 +
 +static void direct_link_area(FileData *fd, ScrArea *area)
 +{
 +      SpaceLink *sl;
 +      ARegion *ar;
 +
 +      link_list(fd, &(area->spacedata));
 +      link_list(fd, &(area->regionbase));
 +
 +      BLI_listbase_clear(&area->handlers);
 +      area->type = NULL;  /* spacetype callbacks */
 +      area->butspacetype = SPACE_EMPTY; /* Should always be unset so that rna_Area_type_get works correctly */
 +      area->region_active_win = -1;
 +
 +      area->flag &= ~AREA_FLAG_ACTIVE_TOOL_UPDATE;
 +
 +      area->global = newdataadr(fd, 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)) {
 +              area->butspacetype = area->spacetype; /* Hint for versioning code to replace deprecated space types. */
 +              area->spacetype = SPACE_EMPTY;
 +      }
 +
 +      for (ar = area->regionbase.first; ar; ar = ar->next) {
 +              direct_link_region(fd, ar, 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) {
 +              blo_do_versions_view3d_split_250(area->spacedata.first, &area->regionbase);
 +      }
 +
 +      for (sl = area->spacedata.first; sl; sl = sl->next) {
 +              link_list(fd, &(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;
 +
 +              for (ar = sl->regionbase.first; ar; ar = ar->next)
 +                      direct_link_region(fd, ar, sl->spacetype);
 +
 +              if (sl->spacetype == SPACE_VIEW3D) {
 +                      View3D *v3d = (View3D *)sl;
 +
 +                      v3d->flag |= V3D_INVALID_BACKBUF;
 +
 +                      if (v3d->gpd) {
 +                              v3d->gpd = newdataadr(fd, v3d->gpd);
 +                              direct_link_gpencil(fd, v3d->gpd);
 +                      }
 +                      v3d->localvd = newdataadr(fd, v3d->localvd);
 +                      v3d->properties_storage = NULL;
 +
 +                      /* 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;
 +
 +                      if (v3d->fx_settings.dof)
 +                              v3d->fx_settings.dof = newdataadr(fd, v3d->fx_settings.dof);
 +                      if (v3d->fx_settings.ssao)
 +                              v3d->fx_settings.ssao = newdataadr(fd, v3d->fx_settings.ssao);
 +
 +                      blo_do_versions_view3d_split_250(v3d, &sl->regionbase);
 +              }
 +              else if (sl->spacetype == SPACE_IPO) {
 +                      SpaceIpo *sipo = (SpaceIpo *)sl;
 +
 +                      sipo->ads = newdataadr(fd, sipo->ads);
++                      BLI_listbase_clear(&sipo->runtime.ghost_curves);
 +              }
 +              else if (sl->spacetype == SPACE_NLA) {
 +                      SpaceNla *snla = (SpaceNla *)sl;
 +
 +                      snla->ads = newdataadr(fd, snla->ads);
 +              }
 +              else if (sl->spacetype == SPACE_OUTLINER) {
 +                      SpaceOops *soops = (SpaceOops *)sl;
 +
 +                      /* use newdataadr_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 = newdataadr_no_us(fd, soops->treestore);
 +                      soops->treestore = NULL;
 +                      if (ts) {
 +                              TreeStoreElem *elems = newdataadr_no_us(fd, ts->data);
 +
 +                              soops->treestore = BLI_mempool_create(sizeof(TreeStoreElem), ts->usedelem,
 +                                                                    512, BLI_MEMPOOL_ALLOW_ITER);
 +                              if (ts->usedelem && elems) {
 +                                      int i;
 +                                      for (i = 0; i < ts->usedelem; i++) {
 +                                              TreeStoreElem *new_elem = BLI_mempool_alloc(soops->treestore);
 +                                              *new_elem = elems[i];
 +                                      }
 +                              }
 +                              /* we only saved what was used */
 +                              soops->storeflag |= SO_TREESTORE_CLEANUP;   // at first draw
 +                      }
 +                      soops->treehash = NULL;
 +                      soops->tree.first = soops->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)
 +                              direct_link_gpencil(fd, sima->gpd);
 +#endif
 +              }
 +              else if (sl->spacetype == SPACE_NODE) {
 +                      SpaceNode *snode = (SpaceNode *)sl;
 +
 +                      if (snode->gpd) {
 +                              snode->gpd = newdataadr(fd, snode->gpd);
 +                              direct_link_gpencil(fd, snode->gpd);
 +                      }
 +
 +                      link_list(fd, &snode->treepath);
 +                      snode->edittree = NULL;
 +                      snode->iofsd = NULL;
 +                      BLI_listbase_clear(&snode->linkdrag);
 +              }
 +              else if (sl->spacetype == SPACE_TEXT) {
 +                      SpaceText *st = (SpaceText *)sl;
 +
 +                      st->drawcache = NULL;
 +                      st->scroll_accum[0] = 0.0f;
 +                      st->scroll_accum[1] = 0.0f;
 +              }
 +              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);
 +                              direct_link_gpencil(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;
 +                      sseq->compositor = NULL;
 +              }
 +              else if (sl->spacetype == SPACE_BUTS) {
 +                      SpaceButs *sbuts = (SpaceButs *)sl;
 +
 +                      sbuts->path = NULL;
 +                      sbuts->texuser = NULL;
 +                      sbuts->mainbo = sbuts->mainb;
 +                      sbuts->mainbuser = sbuts->mainb;
 +              }
 +              else if (sl->spacetype == SPACE_CONSOLE) {
 +                      SpaceConsole *sconsole = (SpaceConsole *)sl;
 +                      ConsoleLine *cl, *cl_next;
 +
 +                      link_list(fd, &sconsole->scrollback);
 +                      link_list(fd, &sconsole->history);
 +
 +                      //for (cl= sconsole->scrollback.first; cl; cl= cl->next)
 +                      //      cl->line= newdataadr(fd, cl->line);
 +
 +                      /* 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*/
 +                      for (cl = sconsole->history.first; cl; cl = cl_next) {
 +                              cl_next = cl->next;
 +                              cl->line = newdataadr(fd, 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;
 +                      sfile->params = newdataadr(fd, 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);
 +
 +      area->v1 = newdataadr(fd, area->v1);
 +      area->v2 = newdataadr(fd, area->v2);
 +      area->v3 = newdataadr(fd, area->v3);
 +      area->v4 = newdataadr(fd, area->v4);
 +}
 +
 +static void lib_link_area(FileData *fd, ID *parent_id, ScrArea *area)
 +{
 +      area->full = newlibadr(fd, parent_id->lib, area->full);
 +
 +      memset(&area->runtime, 0x0, sizeof(area->runtime));
 +
 +      for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) {
 +              switch (sl->spacetype) {
 +                      case SPACE_VIEW3D:
 +                      {
 +                              View3D *v3d = (View3D *)sl;
 +
 +                              v3d->camera = newlibadr(fd, parent_id->lib, v3d->camera);
 +                              v3d->ob_centre = newlibadr(fd, parent_id->lib, v3d->ob_centre);
 +
 +                              if (v3d->localvd) {
 +                                      v3d->localvd->camera = newlibadr(fd, parent_id->lib, v3d->localvd->camera);
 +                              }
 +                              break;
 +                      }
 +                      case SPACE_IPO:
 +                      {
 +                              SpaceIpo *sipo = (SpaceIpo *)sl;
 +                              bDopeSheet *ads = sipo->ads;
 +
 +                              if (ads) {
 +                                      ads->source = newlibadr(fd, parent_id->lib, ads->source);
 +                                      ads->filter_grp = newlibadr(fd, parent_id->lib, ads->filter_grp);
 +                              }
 +                              break;
 +                      }
 +                      case SPACE_BUTS:
 +                      {
 +                              SpaceButs *sbuts = (SpaceButs *)sl;
 +                              sbuts->pinid = newlibadr(fd, 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) {
 +                                      ads->source = newlibadr(fd, parent_id->lib, ads->source);
 +                                      ads->filter_grp = newlibadr(fd, parent_id->lib, ads->filter_grp);
 +                              }
 +
 +                              saction->action = newlibadr(fd, parent_id->lib, saction->action);
 +                              break;
 +                      }
 +                      case SPACE_IMAGE:
 +                      {
 +                              SpaceImage *sima = (SpaceImage *)sl;
 +
 +                              sima->image = newlibadr_real_us(fd, parent_id->lib, sima->image);
 +                              sima->mask_info.mask = newlibadr_real_us(fd, 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!
 +                               */
 +                              sima->gpd = newlibadr_us(fd, 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!
 +                               */
 +                              sseq->gpd = newlibadr_us(fd, parent_id->lib, sseq->gpd);
 +                              break;
 +                      }
 +                      case SPACE_NLA:
 +                      {
 +                              SpaceNla *snla = (SpaceNla *)sl;
 +                              bDopeSheet *ads = snla->ads;
 +
 +                              if (ads) {
 +                                      ads->source = newlibadr(fd, parent_id->lib, ads->source);
 +                                      ads->filter_grp = newlibadr(fd, parent_id->lib, ads->filter_grp);
 +                              }
 +                              break;
 +                      }
 +                      case SPACE_TEXT:
 +                      {
 +                              SpaceText *st = (SpaceText *)sl;
 +
 +                              st->text = newlibadr(fd, 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) {
 +                                      scpt->script = newlibadr(fd, parent_id->lib, scpt->script);
 +                                      if (scpt->script) {
 +                                              SCRIPT_SET_NULL(scpt->script);
 +                                      }
 +                              }
 +                              break;
 +                      }
 +                      case SPACE_OUTLINER:
 +                      {
 +                              SpaceOops *so = (SpaceOops *)sl;
 +                              so->search_tse.id = newlibadr(fd, NULL, so->search_tse.id);
 +
 +                              if (so->treestore) {
 +                                      TreeStoreElem *tselem;
 +                                      BLI_mempool_iter iter;
 +
 +                                      BLI_mempool_iternew(so->treestore, &iter);
 +                                      while ((tselem = BLI_mempool_iterstep(&iter))) {
 +                                              tselem->id = newlibadr(fd, NULL, tselem->id);
 +                                      }
 +                                      if (so->treehash) {
 +                                              /* rebuild hash table, because it depends on ids too */
 +                                              so->storeflag |= SO_TREESTORE_REBUILD;
 +                                      }
 +                              }
 +                              break;
 +                      }
 +                      case SPACE_NODE:
 +                      {
 +                              SpaceNode *snode = (SpaceNode *)sl;
 +                              bNodeTreePath *path, *path_next;
 +                              bNodeTree *ntree;
 +
 +                              /* node tree can be stored locally in id too, link this first */
 +                              snode->id = newlibadr(fd, parent_id->lib, snode->id);
 +                              snode->from = newlibadr(fd, parent_id->lib, snode->from);
 +
 +                              ntree = snode->id ? ntreeFromID(snode->id) : NULL;
 +                              snode->nodetree = ntree ? ntree : newlibadr_us(fd, parent_id->lib, snode->nodetree);
 +
 +                              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
 +                                              path->nodetree = newlibadr_us(fd, parent_id->lib, path->nodetree);
 +
 +                                      if (!path->nodetree)
 +                                              break;
 +                              }
 +
 +                              /* remaining path entries are invalid, remove */
 +                              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;
 +                              sclip->clip = newlibadr_real_us(fd, parent_id->lib, sclip->clip);
 +                              sclip->mask_info.mask = newlibadr_real_us(fd, parent_id->lib, sclip->mask_info.mask);
 +                              break;
 +                      }
 +                      default:
 +                              break;
 +              }
 +      }
 +}
 +
 +/**
 + * \return false on error.
 + */
 +static bool direct_link_area_map(FileData *fd, ScrAreaMap *area_map)
 +{
 +      link_list(fd, &area_map->vertbase);
 +      link_list(fd, &area_map->edgebase);
 +      link_list(fd, &area_map->areabase);
 +      for (ScrArea *area = area_map->areabase.first; area; area = area->next) {
 +              direct_link_area(fd, area);
 +      }
 +
 +      /* edges */
 +      for (ScrEdge *se = area_map->edgebase.first; se; se = se->next) {
 +              se->v1 = newdataadr(fd, se->v1);
 +              se->v2 = newdataadr(fd, se->v2);
 +              BKE_screen_sort_scrvert(&se->v1, &se->v2);
 +
 +              if (se->v1 == NULL) {
 +                      BLI_remlink(&area_map->edgebase, se);
 +
 +                      return false;
 +              }
 +      }
 +
 +      return true;
  }
  
  /* ************ READ WM ***************** */
@@@ -2829,210 -2826,167 +2829,210 @@@ static void write_soops(WriteData *wd, 
        }
  }
  
 -static void write_screen(WriteData *wd, bScreen *sc)
 +static void write_panel_list(WriteData *wd, ListBase *lb)
  {
 -      /* write LibData */
 -      /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
 -      writestruct(wd, ID_SCRN, bScreen, 1, sc);
 -      write_iddata(wd, &sc->id);
 -
 -      /* direct data */
 -      for (ScrVert *sv = sc->vertbase.first; sv; sv = sv->next) {
 -              writestruct(wd, DATA, ScrVert, 1, sv);
 +      for (Panel *pa = lb->first; pa; pa = pa->next) {
 +              writestruct(wd, DATA, Panel, 1, pa);
 +              write_panel_list(wd, &pa->children);
        }
 +}
  
 -      for (ScrEdge *se = sc->edgebase.first; se; se = se->next) {
 -              writestruct(wd, DATA, ScrEdge, 1, se);
 -      }
 +static void write_area_regions(WriteData *wd, ScrArea *area)
 +{
 +      for (ARegion *region = area->regionbase.first; region; region = region->next) {
 +              write_region(wd, region, area->spacetype);
 +              write_panel_list(wd, &region->panels);
  
 -      for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
 -              SpaceLink *sl;
 -              Panel *pa;
 -              uiList *ui_list;
 -              uiPreview *ui_preview;
 -              PanelCategoryStack *pc_act;
 -              ARegion *ar;
 +              for (PanelCategoryStack *pc_act = region->panels_category_active.first; pc_act; pc_act = pc_act->next) {
 +                      writestruct(wd, DATA, PanelCategoryStack, 1, pc_act);
 +              }
 +
 +              for (uiList *ui_list = region->ui_lists.first; ui_list; ui_list = ui_list->next) {
 +                      write_uilist(wd, ui_list);
 +              }
  
 -              writestruct(wd, DATA, ScrArea, 1, sa);
 +              for (uiPreview *ui_preview = region->ui_previews.first; ui_preview; ui_preview = ui_preview->next) {
 +                      writestruct(wd, DATA, uiPreview, 1, ui_preview);
 +              }
 +      }
 +
 +      for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) {
 +              for (ARegion *region = sl->regionbase.first; region; region = region->next) {
 +                      write_region(wd, region, sl->spacetype);
 +              }
  
 -              for (ar = sa->regionbase.first; ar; ar = ar->next) {
 -                      write_region(wd, ar, sa->spacetype);
 +              if (sl->spacetype == SPACE_VIEW3D) {
 +                      View3D *v3d = (View3D *)sl;
 +                      writestruct(wd, DATA, View3D, 1, v3d);
  
 -                      for (pa = ar->panels.first; pa; pa = pa->next) {
 -                              writestruct(wd, DATA, Panel, 1, pa);
 +                      if (v3d->localvd) {
 +                              writestruct(wd, DATA, View3D, 1, v3d->localvd);
                        }
  
 -                      for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) {
 -                              writestruct(wd, DATA, PanelCategoryStack, 1, pc_act);
 +                      if (v3d->fx_settings.ssao) {
 +                              writestruct(wd, DATA, GPUSSAOSettings, 1, v3d->fx_settings.ssao);
                        }
-                       ListBase tmpGhosts = sipo->ghostCurves;
 +                      if (v3d->fx_settings.dof) {
 +                              writestruct(wd, DATA, GPUDOFSettings, 1, v3d->fx_settings.dof);
 +                      }
 +              }
 +              else if (sl->spacetype == SPACE_IPO) {
 +                      SpaceIpo *sipo = (SpaceIpo *)sl;
++                      ListBase tmpGhosts = sipo->runtime.ghost_curves;
  
 -                      for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next) {
 -                              write_uilist(wd, ui_list);
 +                      /* temporarily disable ghost curves when saving */
-                       sipo->ghostCurves.first = sipo->ghostCurves.last = NULL;
++                      BLI_listbase_clear(&sipo->runtime.ghost_curves);
 +
 +                      writestruct(wd, DATA, SpaceIpo, 1, sl);
 +                      if (sipo->ads) {
 +                              writestruct(wd, DATA, bDopeSheet, 1, sipo->ads);
                        }
  
 -                      for (ui_preview = ar->ui_previews.first; ui_preview; ui_preview = ui_preview->next) {
 -                              writestruct(wd, DATA, uiPreview, 1, ui_preview);
 +                      /* reenable ghost curves */
-                       sipo->ghostCurves = tmpGhosts;
++                      sipo->runtime.ghost_curves = tmpGhosts;
 +              }
 +              else if (sl->spacetype == SPACE_BUTS) {
 +                      writestruct(wd, DATA, SpaceButs, 1, sl);
 +              }
 +              else if (sl->spacetype == SPACE_FILE) {
 +                      SpaceFile *sfile = (SpaceFile *)sl;
 +
 +                      writestruct(wd, DATA, SpaceFile, 1, sl);
 +                      if (sfile->params) {
 +                              writestruct(wd, DATA, FileSelectParams, 1, sfile->params);
                        }
                }
 +              else if (sl->spacetype == SPACE_SEQ) {
 +                      writestruct(wd, DATA, SpaceSeq, 1, sl);
 +              }
 +              else if (sl->spacetype == SPACE_OUTLINER) {
 +                      SpaceOops *so = (SpaceOops *)sl;
 +                      write_soops(wd, so);
 +              }
 +              else if (sl->spacetype == SPACE_IMAGE) {
 +                      writestruct(wd, DATA, SpaceImage, 1, sl);
 +              }
 +              else if (sl->spacetype == SPACE_TEXT) {
 +                      writestruct(wd, DATA, SpaceText, 1, sl);
 +              }
 +              else if (sl->spacetype == SPACE_SCRIPT) {
 +                      SpaceScript *scr = (SpaceScript *)sl;
 +                      scr->but_refs = NULL;
 +                      writestruct(wd, DATA, SpaceScript, 1, sl);
 +              }
 +              else if (sl->spacetype == SPACE_ACTION) {
 +                      writestruct(wd, DATA, SpaceAction, 1, sl);
 +              }
 +              else if (sl->spacetype == SPACE_NLA) {
 +                      SpaceNla *snla = (SpaceNla *)sl;
  
 -              for (sl = sa->spacedata.first; sl; sl = sl->next) {
 -                      for (ar = sl->regionbase.first; ar; ar = ar->next) {
 -                              write_region(wd, ar, sl->spacetype);
 +                      writestruct(wd, DATA, SpaceNla, 1, snla);
 +                      if (snla->ads) {
 +                              writestruct(wd, DATA, bDopeSheet, 1, snla->ads);
                        }
 +              }
 +              else if (sl->spacetype == SPACE_NODE) {
 +                      SpaceNode *snode = (SpaceNode *)sl;
 +                      bNodeTreePath *path;
 +                      writestruct(wd, DATA, SpaceNode, 1, snode);
  
 -                      if (sl->spacetype == SPACE_VIEW3D) {
 -                              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);
 -                              }
 -                              if (v3d->localvd) {
 -                                      writestruct(wd, DATA, View3D, 1, v3d->localvd);
 -                              }
 +                      for (path = snode->treepath.first; path; path = path->next) {
 +                              writestruct(wd, DATA, bNodeTreePath, 1, path);
 +                      }
 +              }
 +              else if (sl->spacetype == SPACE_CONSOLE) {
 +                      SpaceConsole *con = (SpaceConsole *)sl;
 +                      ConsoleLine *cl;
  
 -                              if (v3d->fx_settings.ssao) {
 -                                      writestruct(wd, DATA, GPUSSAOSettings, 1, v3d->fx_settings.ssao);
 -                              }
 -                              if (v3d->fx_settings.dof) {
 -                                      writestruct(wd, DATA, GPUDOFSettings, 1, v3d->fx_settings.dof);
 -                              }
 +                      for (cl = con->history.first; cl; cl = cl->next) {
 +                              /* 'len_alloc' is invalid on write, set from 'len' on read */
 +                              writestruct(wd, DATA, ConsoleLine, 1, cl);
 +                              writedata(wd, DATA, cl->len + 1, cl->line);
                        }
 -                      else if (sl->spacetype == SPACE_IPO) {
 -                              SpaceIpo *sipo = (SpaceIpo *)sl;
 -                              ListBase tmpGhosts = sipo->runtime.ghost_curves;
 +                      writestruct(wd, DATA, SpaceConsole, 1, sl);
 +              }
 +#ifdef WITH_GLOBAL_AREA_WRITING
 +              else if (sl->spacetype == SPACE_TOPBAR) {
 +                      writestruct(wd, DATA, SpaceTopBar, 1, sl);
 +              }
 +              else if (sl->spacetype == SPACE_STATUSBAR) {
 +                      writestruct(wd, DATA, SpaceStatusBar, 1, sl);
 +              }
 +#endif
 +              else if (sl->spacetype == SPACE_USERPREF) {
 +                      writestruct(wd, DATA, SpaceUserPref, 1, sl);
 +              }
 +              else if (sl->spacetype == SPACE_CLIP) {
 +                      writestruct(wd, DATA, SpaceClip, 1, sl);
 +              }
 +              else if (sl->spacetype == SPACE_INFO) {
 +                      writestruct(wd, DATA, SpaceInfo, 1, sl);
 +              }
 +      }
 +}
  
 -                              /* temporarily disable ghost curves when saving */
 -                              BLI_listbase_clear(&sipo->runtime.ghost_curves);
 +static void write_area_map(WriteData *wd, ScrAreaMap *area_map)
 +{
 +      writelist(wd, DATA, ScrVert, &area_map->vertbase);
 +      writelist(wd, DATA, ScrEdge, &area_map->edgebase);
 +      for (ScrArea *area = area_map->areabase.first; area; area = area->next) {
 +              area->butspacetype = area->spacetype; /* Just for compatibility, will be reset below. */
  
 -                              writestruct(wd, DATA, SpaceIpo, 1, sl);
 -                              if (sipo->ads) {
 -                                      writestruct(wd, DATA, bDopeSheet, 1, sipo->ads);
 -                              }
 +              writestruct(wd, DATA, ScrArea, 1, area);
  
 -                              /* reenable ghost curves */
 -                              sipo->runtime.ghost_curves = tmpGhosts;
 -                      }
 -                      else if (sl->spacetype == SPACE_BUTS) {
 -                              writestruct(wd, DATA, SpaceButs, 1, sl);
 -                      }
 -                      else if (sl->spacetype == SPACE_FILE) {
 -                              SpaceFile *sfile = (SpaceFile *)sl;
 +#ifdef WITH_GLOBAL_AREA_WRITING
 +              writestruct(wd, DATA, ScrGlobalAreaData, 1, area->global);
 +#endif
  
 -                              writestruct(wd, DATA, SpaceFile, 1, sl);
 -                              if (sfile->params) {
 -                                      writestruct(wd, DATA, FileSelectParams, 1, sfile->params);
 -                              }
 -                      }
 -                      else if (sl->spacetype == SPACE_SEQ) {
 -                              writestruct(wd, DATA, SpaceSeq, 1, sl);
 -                      }
 -                      else if (sl->spacetype == SPACE_OUTLINER) {
 -                              SpaceOops *so = (SpaceOops *)sl;
 -                              write_soops(wd, so);
 -                      }
 -                      else if (sl->spacetype == SPACE_IMAGE) {
 -                              writestruct(wd, DATA, SpaceImage, 1, sl);
 -                      }
 -                      else if (sl->spacetype == SPACE_TEXT) {
 -                              writestruct(wd, DATA, SpaceText, 1, sl);
 -                      }
 -                      else if (sl->spacetype == SPACE_SCRIPT) {
 -                              SpaceScript *scr = (SpaceScript *)sl;
 -                              scr->but_refs = NULL;
 -                              writestruct(wd, DATA, SpaceScript, 1, sl);
 -                      }
 -                      else if (sl->spacetype == SPACE_ACTION) {
 -                              writestruct(wd, DATA, SpaceAction, 1, sl);
 -                      }
 -                      else if (sl->spacetype == SPACE_NLA) {
 -                              SpaceNla *snla = (SpaceNla *)sl;
 +              write_area_regions(wd, area);
  
 -                              writestruct(wd, DATA, SpaceNla, 1, snla);
 -                              if (snla->ads) {
 -                                      writestruct(wd, DATA, bDopeSheet, 1, snla->ads);
 -                              }
 -                      }
 -                      else if (sl->spacetype == SPACE_TIME) {
 -                              writestruct(wd, DATA, SpaceTime, 1, sl);
 -                      }
 -                      else if (sl->spacetype == SPACE_NODE) {
 -                              SpaceNode *snode = (SpaceNode *)sl;
 -                              bNodeTreePath *path;
 -                              writestruct(wd, DATA, SpaceNode, 1, snode);
 +              area->butspacetype = SPACE_EMPTY; /* Unset again, was changed above. */
 +      }
 +}
  
 -                              for (path = snode->treepath.first; path; path = path->next) {
 -                                      writestruct(wd, DATA, bNodeTreePath, 1, path);
 -                              }
 -                      }
 -                      else if (sl->spacetype == SPACE_LOGIC) {
 -                              writestruct(wd, DATA, SpaceLogic, 1, sl);
 -                      }
 -                      else if (sl->spacetype == SPACE_CONSOLE) {
 -                              SpaceConsole *con = (SpaceConsole *)sl;
 -                              ConsoleLine *cl;
 +static void write_windowmanager(WriteData *wd, wmWindowManager *wm)
 +{
 +      writestruct(wd, ID_WM, wmWindowManager, 1, wm);
 +      write_iddata(wd, &wm->id);
  
 -                              for (cl = con->history.first; cl; cl = cl->next) {
 -                                      /* 'len_alloc' is invalid on write, set from 'len' on read */
 -                                      writestruct(wd, DATA, ConsoleLine, 1, cl);
 -                                      writedata(wd, DATA, cl->len + 1, cl->line);
 -                              }
 -                              writestruct(wd, DATA, SpaceConsole, 1, sl);
 +      for (wmWindow *win = wm->windows.first; win; win = win->next) {
 +#ifndef WITH_GLOBAL_AREA_WRITING
 +              /* Don't write global areas yet, while we make changes to them. */
 +              ScrAreaMap global_areas = win->global_areas;
 +              memset(&win->global_areas, 0, sizeof(win->global_areas));
 +#endif
  
 -                      }
 -                      else if (sl->spacetype == SPACE_USERPREF) {
 -                              writestruct(wd, DATA, SpaceUserPref, 1, sl);
 -                      }
 -                      else if (sl->spacetype == SPACE_CLIP) {
 -                              writestruct(wd, DATA, SpaceClip, 1, sl);
 -                      }
 -                      else if (sl->spacetype == SPACE_INFO) {
 -                              writestruct(wd, DATA, SpaceInfo, 1, sl);
 -                      }
 -              }
 +              /* update deprecated screen member (for so loading in 2.7x uses the correct screen) */
 +              win->screen = BKE_workspace_active_screen_get(win->workspace_hook);
 +
 +              writestruct(wd, DATA, wmWindow, 1, win);
 +              writestruct(wd, DATA, WorkSpaceInstanceHook, 1, win->workspace_hook);
 +              writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format);
 +
 +#ifdef WITH_GLOBAL_AREA_WRITING
 +              write_area_map(wd, &win->global_areas);
 +#else
 +              win->global_areas = global_areas;
 +#endif
 +
 +              /* data is written, clear deprecated data again */
 +              win->screen = NULL;
 +      }
 +}
 +
 +static void write_screen(WriteData *wd, bScreen *sc)
 +{
 +      /* Screens are reference counted, only saved if used by a workspace. */
 +      if (sc->id.us > 0 || wd->use_memfile) {
 +              /* write LibData */
 +              /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
 +              writestruct(wd, ID_SCRN, bScreen, 1, sc);
 +              write_iddata(wd, &sc->id);
 +
 +              write_previews(wd, sc->preview);
 +
 +              /* direct data */
 +              write_area_map(wd, AREAMAP_FROM_SCREEN(sc));
        }
  }
  
@@@ -569,43 -440,16 +568,43 @@@ static void action_listener
                        }
                        break;
                case NC_SCENE:
 -                      switch (wmn->data) {
 -                              case ND_OB_ACTIVE:  /* selection changed, so force refresh to flush (needs flag set to do syncing) */
 -                              case ND_OB_SELECT:
 -                                      saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
 -                                      ED_area_tag_refresh(sa);
 -                                      break;
 +                      if (saction->mode == SACTCONT_TIMELINE) {
 +                              switch (wmn->data) {
 +                                      case ND_RENDER_RESULT:
 +                                              ED_area_tag_redraw(sa);
 +                                              break;
 +                                      case ND_OB_ACTIVE:
 +                                      case ND_FRAME:
 +                                              ED_area_tag_refresh(sa);
 +                                              break;
 +                                      case ND_FRAME_RANGE:
 +                                      {
 +                                              ARegion *ar;
 +                                              Scene *scene = wmn->reference;
 +
 +                                              for (ar = sa->regionbase.first; ar; ar = ar->next) {
 +                                                      if (ar->regiontype == RGN_TYPE_WINDOW) {
 +                                                              ar->v2d.tot.xmin = (float)(SFRA - 4);
 +                                                              ar->v2d.tot.xmax = (float)(EFRA + 4);
 +                                                              break;
 +                                                      }
 +                                              }
 +                                              break;
 +                                      }
 +                              }
 +                      }
 +                      else {
 +                              switch (wmn->data) {
 +                                      case ND_OB_ACTIVE:  /* selection changed, so force refresh to flush (needs flag set to do syncing) */
 +                                      case ND_OB_SELECT:
-                                               saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
++                                              saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
 +                                              ED_area_tag_refresh(sa);
 +                                              break;
  
 -                              default: /* just redrawing the view will do */
 -                                      ED_area_tag_redraw(sa);
 -                                      break;
 +                                      default: /* just redrawing the view will do */
 +                                              ED_area_tag_redraw(sa);
 +                                              break;
 +                              }
                        }
                        break;
                case NC_OBJECT:
                                case ND_SPACE_DOPESHEET:
                                        ED_area_tag_redraw(sa);
                                        break;
 +                              case ND_SPACE_TIME:
 +                                      ED_area_tag_redraw(sa);
 +                                      break;
                                case ND_SPACE_CHANGED:
-                                       saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
+                                       saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
                                        ED_area_tag_refresh(sa);
                                        break;
                        }
@@@ -961,28 -925,15 +961,28 @@@ void graph_draw_ghost_curves(bAnimConte
        FCurve *fcu;
  
        /* draw with thick dotted lines */
 -      setlinestyle(10);
 -      glLineWidth(3.0f);
 +      GPU_line_width(3.0f);
  
        /* anti-aliased lines for less jagged appearance */
 -      if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH);
 -      glEnable(GL_BLEND);
 +      if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
 +              GPU_line_smooth(true);
 +      }
 +      GPU_blend(true);
 +
 +      const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
 +
 +      immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
 +
 +      float viewport_size[4];
 +      GPU_viewport_size_get_f(viewport_size);
 +      immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
 +
 +      immUniform1i("colors_len", 0);  /* Simple dashes. */
 +      immUniform1f("dash_width", 20.0f);
 +      immUniform1f("dash_factor", 0.5f);
  
-       /* the ghost curves are simply sampled F-Curves stored in sipo->ghostCurves */
-       for (fcu = sipo->ghostCurves.first; fcu; fcu = fcu->next) {
+       /* the ghost curves are simply sampled F-Curves stored in sipo->runtime.ghost_curves */
+       for (fcu = sipo->runtime.ghost_curves.first; fcu; fcu = fcu->next) {
                /* set whatever color the curve has set
                 * - this is set by the function which creates these
                 * - draw with a fixed opacity of 2
@@@ -706,16 -667,11 +711,18 @@@ typedef struct SpaceAction 
        bAction     *action;        /* the currently active action */
        bDopeSheet ads;             /* the currently active context (when not showing action) */
  
 -      char mode, autosnap;        /* mode: editing context; autosnap: automatic keyframe snapping mode   */
 -      short flag;                 /* flag: bitmapped settings; */
        float timeslide;            /* for Time-Slide transform mode drawing - current frame? */
  
 +      short flag;
 +      /* Editing context */
 +      char mode;
 +      /* Storage for sub-space types. */
 +      char mode_prev;
 +      char autosnap;              /* automatic keyframe snapping mode   */
 +      char cache_display;         /* (eTimeline_Cache_Flag) */
 +      char _pad1[6];
++
+       SpaceAction_Runtime runtime;
  } SpaceAction;
  
  /* SpaceAction flag */
@@@ -741,15 -697,16 +748,20 @@@ typedef enum eSAction_Flag 
        /* don't perform realtime updates */
        SACTION_NOREALTIMEUPDATES = (1 << 10),
        /* move markers as well as keyframes */
 -      SACTION_MARKERS_MOVE = (1 << 11)
 +      SACTION_MARKERS_MOVE = (1 << 11),
 +      /* show interpolation type */
 +      SACTION_SHOW_INTERPOLATION = (1 << 12),
 +      /* show extremes */
 +      SACTION_SHOW_EXTREMES = (1 << 13),
  } eSAction_Flag;
  
+ /* SpaceAction_Runtime.flag */
+ typedef enum eSAction_Runtime_Flag {
+       /** Temporary flag to force channel selections to be synced with main */
+       SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC = (1 << 0),
+ } eSAction_Runtime_Flag;
  /* SpaceAction Mode Settings */
  typedef enum eAnimEdit_Context {
        /* action on the active object */
@@@ -1573,32 -1384,8 +1573,32 @@@ static void rna_SpaceDopeSheetEditor_mo
                        saction->action = NULL;
        }
  
 +      /* Collapse (and show) summary channel and hide channel list for timeline */
 +      if (saction->mode == SACTCONT_TIMELINE) {
 +              saction->ads.flag |= ADS_FLAG_SUMMARY_COLLAPSED;
 +              saction->ads.filterflag |= ADS_FILTER_SUMMARY;
 +      }
 +
 +      if (sa && sa->spacedata.first == saction) {
 +              ARegion *channels_region = BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS);
 +              if (channels_region) {
 +                      if (saction->mode == SACTCONT_TIMELINE) {
 +                              channels_region->flag |= RGN_FLAG_HIDDEN;
 +                      }
 +                      else {
 +                              channels_region->flag &= ~RGN_FLAG_HIDDEN;
 +                      }
 +                      ED_region_visibility_change_update(C, channels_region);
 +              }
 +      }
 +
        /* recalculate extents of channel list */
-       saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
+       saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
 +
 +      /* store current mode as "old mode", so that returning from other editors doesn't always reset to "Action Editor" */
 +      if (saction->mode != SACTCONT_TIMELINE) {
 +              saction->mode_prev = saction->mode;
 +      }
  }
  
  /* Space Graph Editor */