svn merge -r39930:39947 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / blenloader / intern / writefile.c
index fa88a44977d7c7a96963d257dce78cd24948996b..c3f51dc6ce48466eff891c66002541d5b8bc277a 100644 (file)
@@ -123,6 +123,7 @@ Any case: direct data is ALWAYS after the lib block
 #include "DNA_smoke_types.h"
 #include "DNA_space_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_smoke_types.h"
 #include "DNA_space_types.h"
 #include "DNA_screen_types.h"
+#include "DNA_speaker_types.h"
 #include "DNA_sound_types.h"
 #include "DNA_text_types.h"
 #include "DNA_view3d_types.h"
 #include "DNA_sound_types.h"
 #include "DNA_text_types.h"
 #include "DNA_view3d_types.h"
@@ -641,6 +642,14 @@ static void write_curvemapping(WriteData *wd, CurveMapping *cumap)
                writestruct(wd, DATA, "CurveMapPoint", cumap->cm[a].totpoint, cumap->cm[a].curve);
 }
 
                writestruct(wd, DATA, "CurveMapPoint", cumap->cm[a].totpoint, cumap->cm[a].curve);
 }
 
+static void write_node_socket(WriteData *wd, bNodeSocket *sock)
+{
+       bNodeSocketType *stype= ntreeGetSocketType(sock->type);
+       writestruct(wd, DATA, "bNodeSocket", 1, sock);
+       if (sock->default_value)
+               writestruct(wd, DATA, stype->value_structname, 1, sock->default_value);
+}
+
 /* this is only direct data, tree itself should have been written */
 static void write_nodetree(WriteData *wd, bNodeTree *ntree)
 {
 /* this is only direct data, tree itself should have been written */
 static void write_nodetree(WriteData *wd, bNodeTree *ntree)
 {
@@ -656,6 +665,12 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
                writestruct(wd, DATA, "bNode", 1, node);
 
        for(node= ntree->nodes.first; node; node= node->next) {
                writestruct(wd, DATA, "bNode", 1, node);
 
        for(node= ntree->nodes.first; node; node= node->next) {
+               for(sock= node->inputs.first; sock; sock= sock->next)
+                       write_node_socket(wd, sock);
+               for(sock= node->outputs.first; sock; sock= sock->next)
+                       write_node_socket(wd, sock);
+
+               
                if(node->storage && node->type!=NODE_DYNAMIC) {
                        /* could be handlerized at some point, now only 1 exception still */
                        if(ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
                if(node->storage && node->type!=NODE_DYNAMIC) {
                        /* could be handlerized at some point, now only 1 exception still */
                        if(ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
@@ -664,13 +679,9 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
                                write_curvemapping(wd, node->storage);
                        else if(ntree->type==NTREE_TEXTURE && (node->type==TEX_NODE_CURVE_RGB || node->type==TEX_NODE_CURVE_TIME) )
                                write_curvemapping(wd, node->storage);
                                write_curvemapping(wd, node->storage);
                        else if(ntree->type==NTREE_TEXTURE && (node->type==TEX_NODE_CURVE_RGB || node->type==TEX_NODE_CURVE_TIME) )
                                write_curvemapping(wd, node->storage);
-                       else 
+                       else
                                writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
                }
                                writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
                }
-               for(sock= node->inputs.first; sock; sock= sock->next)
-                       writestruct(wd, DATA, "bNodeSocket", 1, sock);
-               for(sock= node->outputs.first; sock; sock= sock->next)
-                       writestruct(wd, DATA, "bNodeSocket", 1, sock);
        }
        
        for(link= ntree->links.first; link; link= link->next)
        }
        
        for(link= ntree->links.first; link; link= link->next)
@@ -678,9 +689,9 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
        
        /* external sockets */
        for(sock= ntree->inputs.first; sock; sock= sock->next)
        
        /* external sockets */
        for(sock= ntree->inputs.first; sock; sock= sock->next)
-               writestruct(wd, DATA, "bNodeSocket", 1, sock);
+               write_node_socket(wd, sock);
        for(sock= ntree->outputs.first; sock; sock= sock->next)
        for(sock= ntree->outputs.first; sock; sock= sock->next)
-               writestruct(wd, DATA, "bNodeSocket", 1, sock);
+               write_node_socket(wd, sock);
 }
 
 static void current_screen_compat(Main *mainvar, bScreen **screen)
 }
 
 static void current_screen_compat(Main *mainvar, bScreen **screen)
@@ -717,31 +728,48 @@ static void write_renderinfo(WriteData *wd, Main *mainvar)                /* for renderdeamon
        }
 }
 
        }
 }
 
+static void write_keymapitem(WriteData *wd, wmKeyMapItem *kmi)
+{
+       writestruct(wd, DATA, "wmKeyMapItem", 1, kmi);
+       if(kmi->properties)
+               IDP_WriteProperty(kmi->properties, wd);
+}
+
 static void write_userdef(WriteData *wd)
 {
        bTheme *btheme;
        wmKeyMap *keymap;
        wmKeyMapItem *kmi;
 static void write_userdef(WriteData *wd)
 {
        bTheme *btheme;
        wmKeyMap *keymap;
        wmKeyMapItem *kmi;
+       wmKeyMapDiffItem *kmdi;
        bAddon *bext;
        bAddon *bext;
-
+       uiStyle *style;
+       
        writestruct(wd, USER, "UserDef", 1, &U);
 
        for(btheme= U.themes.first; btheme; btheme=btheme->next)
                writestruct(wd, DATA, "bTheme", 1, btheme);
 
        writestruct(wd, USER, "UserDef", 1, &U);
 
        for(btheme= U.themes.first; btheme; btheme=btheme->next)
                writestruct(wd, DATA, "bTheme", 1, btheme);
 
-       for(keymap= U.keymaps.first; keymap; keymap=keymap->next) {
+       for(keymap= U.user_keymaps.first; keymap; keymap=keymap->next) {
                writestruct(wd, DATA, "wmKeyMap", 1, keymap);
 
                writestruct(wd, DATA, "wmKeyMap", 1, keymap);
 
-               for(kmi=keymap->items.first; kmi; kmi=kmi->next) {
-                       writestruct(wd, DATA, "wmKeyMapItem", 1, kmi);
-
-                       if(kmi->properties)
-                               IDP_WriteProperty(kmi->properties, wd);
+               for(kmdi=keymap->diff_items.first; kmdi; kmdi=kmdi->next) {
+                       writestruct(wd, DATA, "wmKeyMapDiffItem", 1, kmdi);
+                       if(kmdi->remove_item)
+                               write_keymapitem(wd, kmdi->remove_item);
+                       if(kmdi->add_item)
+                               write_keymapitem(wd, kmdi->add_item);
                }
                }
+
+               for(kmi=keymap->items.first; kmi; kmi=kmi->next)
+                       write_keymapitem(wd, kmi);
        }
 
        for(bext= U.addons.first; bext; bext=bext->next)
                writestruct(wd, DATA, "bAddon", 1, bext);
        }
 
        for(bext= U.addons.first; bext; bext=bext->next)
                writestruct(wd, DATA, "bAddon", 1, bext);
+       
+       for(style= U.uistyles.first; style; style= style->next) {
+               writestruct(wd, DATA, "uiStyle", 1, style);
+       }
 }
 
 static void write_boid_state(WriteData *wd, BoidState *state)
 }
 
 static void write_boid_state(WriteData *wd, BoidState *state)
@@ -832,6 +860,7 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
 {
        ParticleSettings *part;
        ParticleDupliWeight *dw;
 {
        ParticleSettings *part;
        ParticleDupliWeight *dw;
+       GroupObject *go;
        int a;
 
        part= idbase->first;
        int a;
 
        part= idbase->first;
@@ -846,8 +875,18 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
                        writestruct(wd, DATA, "EffectorWeights", 1, part->effector_weights);
 
                        dw = part->dupliweights.first;
                        writestruct(wd, DATA, "EffectorWeights", 1, part->effector_weights);
 
                        dw = part->dupliweights.first;
-                       for(; dw; dw=dw->next)
+                       for(; dw; dw=dw->next) {
+                               /* update indices */
+                               dw->index = 0;
+                               if(part->dup_group) { /* can be NULL if lining fails or set to None */
+                                       go = part->dup_group->gobject.first;
+                                       while(go && go->ob != dw->ob) {
+                                               go=go->next;
+                                               dw->index++;
+                                       }
+                               }
                                writestruct(wd, DATA, "ParticleDupliWeight", 1, dw);
                                writestruct(wd, DATA, "ParticleDupliWeight", 1, dw);
+                       }
 
                        if(part->boids && part->phystype == PART_PHYS_BOIDS) {
                                BoidState *state = part->boids->states.first;
 
                        if(part->boids && part->phystype == PART_PHYS_BOIDS) {
                                BoidState *state = part->boids->states.first;
@@ -904,7 +943,7 @@ static void write_particlesystems(WriteData *wd, ListBase *particles)
                        writestruct(wd, DATA, "ClothSimSettings", 1, psys->clmd->sim_parms);
                        writestruct(wd, DATA, "ClothCollSettings", 1, psys->clmd->coll_parms);
                }
                        writestruct(wd, DATA, "ClothSimSettings", 1, psys->clmd->sim_parms);
                        writestruct(wd, DATA, "ClothCollSettings", 1, psys->clmd->coll_parms);
                }
-               
+
                write_pointcaches(wd, &psys->ptcaches);
        }
 }
                write_pointcaches(wd, &psys->ptcaches);
        }
 }
@@ -1280,6 +1319,12 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
                                write_curvemapping(wd, tmd->curfalloff);
                        }
                }
                                write_curvemapping(wd, tmd->curfalloff);
                        }
                }
+               else if (md->type==eModifierType_WeightVGEdit) {
+                       WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
+
+                       if (wmd->cmap_curve)
+                               write_curvemapping(wd, wmd->cmap_curve);
+               }
        }
 }
 
        }
 }
 
@@ -2098,7 +2143,11 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
                                        writestruct(wd, DATA, "SpaceButs", 1, sl);
                                }
                                else if(sl->spacetype==SPACE_FILE) {
                                        writestruct(wd, DATA, "SpaceButs", 1, sl);
                                }
                                else if(sl->spacetype==SPACE_FILE) {
+                                       SpaceFile *sfile= (SpaceFile *)sl;
+
                                        writestruct(wd, DATA, "SpaceFile", 1, 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_SEQ) {
                                        writestruct(wd, DATA, "SpaceSeq", 1, sl);
@@ -2130,8 +2179,8 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
                                        writestruct(wd, DATA, "SpaceText", 1, sl);
                                }
                                else if(sl->spacetype==SPACE_SCRIPT) {
                                        writestruct(wd, DATA, "SpaceText", 1, sl);
                                }
                                else if(sl->spacetype==SPACE_SCRIPT) {
-                                       SpaceScript *sc = (SpaceScript*)sl;
-                                       sc->but_refs = NULL;
+                                       SpaceScript *scr = (SpaceScript*)sl;
+                                       scr->but_refs = NULL;
                                        writestruct(wd, DATA, "SpaceScript", 1, sl);
                                }
                                else if(sl->spacetype==SPACE_ACTION) {
                                        writestruct(wd, DATA, "SpaceScript", 1, sl);
                                }
                                else if(sl->spacetype==SPACE_ACTION) {
@@ -2310,6 +2359,23 @@ static void write_texts(WriteData *wd, ListBase *idbase)
        mywrite(wd, MYWRITE_FLUSH, 0);
 }
 
        mywrite(wd, MYWRITE_FLUSH, 0);
 }
 
+static void write_speakers(WriteData *wd, ListBase *idbase)
+{
+       Speaker *spk;
+
+       spk= idbase->first;
+       while(spk) {
+               if(spk->id.us>0 || wd->current) {
+                       /* write LibData */
+                       writestruct(wd, ID_SPK, "Speaker", 1, spk);
+                       if (spk->id.properties) IDP_WriteProperty(spk->id.properties, wd);
+
+                       if (spk->adt) write_animdata(wd, spk->adt);
+               }
+               spk= spk->id.next;
+       }
+}
+
 static void write_sounds(WriteData *wd, ListBase *idbase)
 {
        bSound *sound;
 static void write_sounds(WriteData *wd, ListBase *idbase)
 {
        bSound *sound;
@@ -2431,7 +2497,7 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
        fg.subversion= BLENDER_SUBVERSION;
        fg.minversion= BLENDER_MINVERSION;
        fg.minsubversion= BLENDER_MINSUBVERSION;
        fg.subversion= BLENDER_SUBVERSION;
        fg.minversion= BLENDER_MINVERSION;
        fg.minsubversion= BLENDER_MINSUBVERSION;
-#ifdef NAN_BUILDINFO
+#ifdef WITH_BUILDINFO
        {
                extern char build_rev[];
                fg.revision= atoi(build_rev);
        {
                extern char build_rev[];
                fg.revision= atoi(build_rev);
@@ -2488,6 +2554,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
        write_keys     (wd, &mainvar->key);
        write_worlds   (wd, &mainvar->world);
        write_texts    (wd, &mainvar->text);
        write_keys     (wd, &mainvar->key);
        write_worlds   (wd, &mainvar->world);
        write_texts    (wd, &mainvar->text);
+       write_speakers (wd, &mainvar->speaker);
        write_sounds   (wd, &mainvar->sound);
        write_groups   (wd, &mainvar->group);
        write_armatures(wd, &mainvar->armature);
        write_sounds   (wd, &mainvar->sound);
        write_groups   (wd, &mainvar->group);
        write_armatures(wd, &mainvar->armature);
@@ -2520,6 +2587,41 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
        return endwrite(wd);
 }
 
        return endwrite(wd);
 }
 
+/* do reverse file history: .blend1 -> .blend2, .blend -> .blend1 */
+/* return: success(0), failure(1) */
+static int do_history(const char *name, ReportList *reports)
+{
+       char tempname1[FILE_MAXDIR+FILE_MAXFILE], tempname2[FILE_MAXDIR+FILE_MAXFILE];
+       int hisnr= U.versions;
+       
+       if(U.versions==0) return 0;
+       if(strlen(name)<2) {
+               BKE_report(reports, RPT_ERROR, "Unable to make version backup: filename too short");
+               return 1;
+       }
+               
+       while(hisnr > 1) {
+               BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr-1);
+               BLI_snprintf(tempname2, sizeof(tempname2), "%s%d", name, hisnr);
+       
+               if(BLI_rename(tempname1, tempname2)) {
+                       BKE_report(reports, RPT_ERROR, "Unable to make version backup");
+                       return 1;
+               }       
+               hisnr--;
+       }
+
+       /* is needed when hisnr==1 */
+       BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr);
+
+       if(BLI_rename(name, tempname1)) {
+               BKE_report(reports, RPT_ERROR, "Unable to make version backup");
+               return 1;
+       }
+
+       return 0;
+}
+
 /* return: success (1) */
 int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportList *reports, int *thumb)
 {
 /* return: success (1) */
 int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportList *reports, int *thumb)
 {
@@ -2547,10 +2649,18 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL
                BLI_cleanup_dir(mainvar->name, dir1);
                BLI_cleanup_dir(mainvar->name, dir2);
 
                BLI_cleanup_dir(mainvar->name, dir1);
                BLI_cleanup_dir(mainvar->name, dir2);
 
-               if(strcmp(dir1, dir2)==0)
+               if(BLI_path_cmp(dir1, dir2)==0) {
                        write_flags &= ~G_FILE_RELATIVE_REMAP;
                        write_flags &= ~G_FILE_RELATIVE_REMAP;
-               else
-                       makeFilesAbsolute(mainvar, G.main->name, NULL);
+               }
+               else {
+                       if(G.relbase_valid) {
+                               /* blend may not have been saved before. Tn this case
+                                * we should not have any relative paths, but if there
+                                * is somehow, an invalid or empty G.main->name it will
+                                * print an error, dont try make the absolute in this case. */
+                               makeFilesAbsolute(mainvar, G.main->name, NULL);
+                       }
+               }
        }
 
        BLI_make_file_string(G.main->name, userfilename, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE);
        }
 
        BLI_make_file_string(G.main->name, userfilename, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE);
@@ -2563,45 +2673,52 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL
        err= write_file_handle(mainvar, file, NULL,NULL, write_user_block, write_flags, thumb);
        close(file);
 
        err= write_file_handle(mainvar, file, NULL,NULL, write_user_block, write_flags, thumb);
        close(file);
 
-       /* rename/compress */
-       if(!err) {
-               if(write_flags & G_FILE_COMPRESS) {
-                       /* compressed files have the same ending as regular files... only from 2.4!!! */
-                       char gzname[FILE_MAXDIR+FILE_MAXFILE+4];
-                       int ret;
+       if (err) {
+               BKE_report(reports, RPT_ERROR, strerror(errno));
+               remove(tempname);
 
 
-                       /* first write compressed to separate @.gz */
-                       BLI_snprintf(gzname, sizeof(gzname), "%s@.gz", filepath);
-                       ret = BLI_gzip(tempname, gzname);
-                       
-                       if(0==ret) {
-                               /* now rename to real file name, and delete temp @ file too */
-                               if(BLI_rename(gzname, filepath) != 0) {
-                                       BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @.");
-                                       return 0;
-                               }
+               return 0;
+       }
 
 
-                               BLI_delete(tempname, 0, 0);
-                       }
-                       else if(-1==ret) {
-                               BKE_report(reports, RPT_ERROR, "Failed opening .gz file.");
-                               return 0;
-                       }
-                       else if(-2==ret) {
-                               BKE_report(reports, RPT_ERROR, "Failed opening .blend file for compression.");
+       /* file save to temporary file was successful */
+       /* now do reverse file history (move .blend1 -> .blend2, .blend -> .blend1) */
+       if (write_flags & G_FILE_HISTORY) { 
+               int err_hist = do_history(filepath, reports);
+               if (err_hist) {
+                       BKE_report(reports, RPT_ERROR, "Version backup failed. File saved with @");
+                       return 0;
+               }
+       }
+
+       if(write_flags & G_FILE_COMPRESS) {
+               /* compressed files have the same ending as regular files... only from 2.4!!! */
+               char gzname[FILE_MAXDIR+FILE_MAXFILE+4];
+               int ret;
+
+               /* first write compressed to separate @.gz */
+               BLI_snprintf(gzname, sizeof(gzname), "%s@.gz", filepath);
+               ret = BLI_gzip(tempname, gzname);
+               
+               if(0==ret) {
+                       /* now rename to real file name, and delete temp @ file too */
+                       if(BLI_rename(gzname, filepath) != 0) {
+                               BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @.");
                                return 0;
                        }
                                return 0;
                        }
+
+                       BLI_delete(tempname, 0, 0);
                }
                }
-               else if(BLI_rename(tempname, filepath) != 0) {
-                       BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @");
+               else if(-1==ret) {
+                       BKE_report(reports, RPT_ERROR, "Failed opening .gz file.");
+                       return 0;
+               }
+               else if(-2==ret) {
+                       BKE_report(reports, RPT_ERROR, "Failed opening .blend file for compression.");
                        return 0;
                }
                        return 0;
                }
-               
        }
        }
-       else {
-               BKE_report(reports, RPT_ERROR, strerror(errno));
-               remove(tempname);
-
+       else if(BLI_rename(tempname, filepath) != 0) {
+               BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @");
                return 0;
        }
 
                return 0;
        }