WIP loading bmesh in trunk, some conversion functions for this purpose.
[blender.git] / source / blender / blenloader / intern / writefile.c
index b982630ec41fd29dfe308942cfb1b387ca9a7042..e9c14404057dcc361e17ab3f78133deb9dc460ff 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
@@ -99,6 +97,7 @@ Any case: direct data is ALWAYS after the lib block
 #include "DNA_cloth_types.h"
 #include "DNA_constraint_types.h"
 #include "DNA_controller_types.h"
+#include "DNA_dynamicpaint_types.h"
 #include "DNA_genfile.h"
 #include "DNA_group_types.h"
 #include "DNA_gpencil_types.h"
@@ -130,11 +129,13 @@ Any case: direct data is ALWAYS after the lib block
 #include "DNA_vfont_types.h"
 #include "DNA_world_types.h"
 #include "DNA_windowmanager_types.h"
+#include "DNA_movieclip_types.h"
 
 #include "MEM_guardedalloc.h" // MEM_freeN
 #include "BLI_blenlib.h"
 #include "BLI_linklist.h"
 #include "BLI_bpath.h"
+#include "BLI_math.h"
 #include "BLI_utildefines.h"
 
 #include "BKE_action.h"
@@ -173,6 +174,10 @@ typedef struct {
        MemFile *compare, *current;
        
        int tot, count, error, memsize;
+
+#ifdef USE_BMESH_SAVE_AS_COMPAT
+       char use_mesh_compat; /* option to save with older mesh format */
+#endif
 } WriteData;
 
 static WriteData *writedata_new(int file)
@@ -645,6 +650,38 @@ static void write_curvemapping(WriteData *wd, CurveMapping *cumap)
 static void write_node_socket(WriteData *wd, bNodeSocket *sock)
 {
        bNodeSocketType *stype= ntreeGetSocketType(sock->type);
+
+       /* forward compatibility code, so older blenders still open */
+       sock->stack_type = 1;
+
+       if(sock->default_value) {
+               bNodeSocketValueFloat *valfloat;
+               bNodeSocketValueVector *valvector;
+               bNodeSocketValueRGBA *valrgba;
+               
+               switch (sock->type) {
+               case SOCK_FLOAT:
+                       valfloat = sock->default_value;
+                       sock->ns.vec[0] = valfloat->value;
+                       sock->ns.min = valfloat->min;
+                       sock->ns.max = valfloat->max;
+                       break;
+               case SOCK_VECTOR:
+                       valvector = sock->default_value;
+                       copy_v3_v3(sock->ns.vec, valvector->value);
+                       sock->ns.min = valvector->min;
+                       sock->ns.max = valvector->max;
+                       break;
+               case SOCK_RGBA:
+                       valrgba = sock->default_value;
+                       copy_v4_v4(sock->ns.vec, valrgba->value);
+                       sock->ns.min = 0.0f;
+                       sock->ns.max = 1.0f;
+                       break;
+               }
+       }
+
+       /* actual socket writing */
        writestruct(wd, DATA, "bNodeSocket", 1, sock);
        if (sock->default_value)
                writestruct(wd, DATA, stype->value_structname, 1, sock->default_value);
@@ -679,6 +716,8 @@ 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);
+                       else if(ntree->type==NTREE_COMPOSIT && node->type==CMP_NODE_MOVIEDISTORTION)
+                               /* pass */ ;
                        else
                                writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
                }
@@ -839,7 +878,7 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches)
                                
                                for(i=0; i<BPHYS_TOT_DATA; i++) {
                                        if(pm->data[i] && pm->data_types & (1<<i)) {
-                                               if(strcmp(ptcache_data_struct[i], "")==0)
+                                               if(ptcache_data_struct[i][0]=='\0')
                                                        writedata(wd, DATA, MEM_allocN_len(pm->data[i]), pm->data[i]);
                                                else
                                                        writestruct(wd, DATA, ptcache_data_struct[i], pm->totpoint, pm->data[i]);
@@ -847,7 +886,7 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches)
                                }
 
                                for(; extra; extra=extra->next) {
-                                       if(strcmp(ptcache_extra_struct[extra->type], "")==0)
+                                       if(ptcache_extra_struct[extra->type][0]=='\0')
                                                continue;
                                        writestruct(wd, DATA, "PTCacheExtra", 1, extra);
                                        writestruct(wd, DATA, ptcache_extra_struct[extra->type], extra->totdata, extra->data);
@@ -1113,6 +1152,9 @@ static void write_actuators(WriteData *wd, ListBase *lb)
                case ACT_ARMATURE:
                        writestruct(wd, DATA, "bArmatureActuator", 1, act->data);
                        break;
+               case ACT_STEERING:
+                       writestruct(wd, DATA, "bSteeringActuator", 1, act->data);
+                       break;
                default:
                        ; /* error: don't know how to write this file */
                }
@@ -1289,6 +1331,31 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
                        FluidsimModifierData *fluidmd = (FluidsimModifierData*) md;
                        
                        writestruct(wd, DATA, "FluidsimSettings", 1, fluidmd->fss);
+               }
+               else if(md->type==eModifierType_DynamicPaint) {
+                       DynamicPaintModifierData *pmd = (DynamicPaintModifierData*) md;
+                       
+                       if(pmd->canvas)
+                       {
+                               DynamicPaintSurface *surface;
+                               writestruct(wd, DATA, "DynamicPaintCanvasSettings", 1, pmd->canvas);
+                               
+                               /* write surfaces */
+                               for (surface=pmd->canvas->surfaces.first; surface; surface=surface->next)
+                                       writestruct(wd, DATA, "DynamicPaintSurface", 1, surface);
+                               /* write caches and effector weights */
+                               for (surface=pmd->canvas->surfaces.first; surface; surface=surface->next) {
+                                       write_pointcaches(wd, &(surface->ptcaches));
+
+                                       writestruct(wd, DATA, "EffectorWeights", 1, surface->effector_weights);
+                               }
+                       }
+                       if(pmd->brush)
+                       {
+                               writestruct(wd, DATA, "DynamicPaintBrushSettings", 1, pmd->brush);
+                               writestruct(wd, DATA, "ColorBand", 1, pmd->brush->paint_ramp);
+                               writestruct(wd, DATA, "ColorBand", 1, pmd->brush->vel_ramp);
+                       }
                } 
                else if (md->type==eModifierType_Collision) {
                        
@@ -1319,6 +1386,12 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
                                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);
+               }
        }
 }
 
@@ -1597,7 +1670,8 @@ static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data,
                                writestruct(wd, DATA, structname, datasize, layer->data);
                        }
                        else
-                               printf("error: this CustomDataLayer must not be written to file\n");
+                               printf("%s error: layer '%s':%d - can't be written to file\n",
+                                      __func__, structname, layer->type);
                }
        }
 
@@ -1621,27 +1695,9 @@ static void write_meshs(WriteData *wd, ListBase *idbase)
 
                        writedata(wd, DATA, sizeof(void *)*mesh->totcol, mesh->mat);
 
-                       if(mesh->pv) {
-                               write_customdata(wd, &mesh->id, mesh->pv->totvert, &mesh->vdata, -1, 0);
-                               write_customdata(wd, &mesh->id, mesh->pv->totedge, &mesh->edata,
-                                       CD_MEDGE, mesh->totedge);
-                               write_customdata(wd, &mesh->id, mesh->pv->totface, &mesh->fdata,
-                                       CD_MFACE, mesh->totface);
-                       }
-                       else {
-                               write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, -1, 0);
-                               write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, -1, 0);
-                               write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, -1, 0);
-                       }
-
-                       /* PMV data */
-                       if(mesh->pv) {
-                               writestruct(wd, DATA, "PartialVisibility", 1, mesh->pv);
-                               writedata(wd, DATA, sizeof(unsigned int)*mesh->pv->totvert, mesh->pv->vert_map);
-                               writedata(wd, DATA, sizeof(int)*mesh->pv->totedge, mesh->pv->edge_map);
-                               writestruct(wd, DATA, "MFace", mesh->pv->totface, mesh->pv->old_faces);
-                               writestruct(wd, DATA, "MEdge", mesh->pv->totedge, mesh->pv->old_edges);
-                       }
+                       write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, -1, 0);
+                       write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, -1, 0);
+                       write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, -1, 0);
                }
                mesh= mesh->id.next;
        }
@@ -1745,7 +1801,8 @@ static void write_textures(WriteData *wd, ListBase *idbase)
                                if(tex->pd->coba) writestruct(wd, DATA, "ColorBand", 1, tex->pd->coba);
                                if(tex->pd->falloff_curve) write_curvemapping(wd, tex->pd->falloff_curve);
                        }
-                       if(tex->type == TEX_VOXELDATA && tex->vd) writestruct(wd, DATA, "VoxelData", 1, tex->vd);
+                       if(tex->type == TEX_VOXELDATA) writestruct(wd, DATA, "VoxelData", 1, tex->vd);
+                       if(tex->type == TEX_OCEAN && tex->ot) writestruct(wd, DATA, "OceanTex", 1, tex->ot);
                        
                        /* nodetree is integral part of texture, no libdata */
                        if(tex->nodetree) {
@@ -1817,6 +1874,12 @@ static void write_worlds(WriteData *wd, ListBase *idbase)
                        for(a=0; a<MAX_MTEX; a++) {
                                if(wrld->mtex[a]) writestruct(wd, DATA, "MTex", 1, wrld->mtex[a]);
                        }
+
+                       /* nodetree is integral part of lamps, no libdata */
+                       if(wrld->nodetree) {
+                               writestruct(wd, DATA, "bNodeTree", 1, wrld->nodetree);
+                               write_nodetree(wd, wrld->nodetree);
+                       }
                        
                        write_previews(wd, wrld->preview);
                }
@@ -1846,6 +1909,12 @@ static void write_lamps(WriteData *wd, ListBase *idbase)
                        if(la->curfalloff)
                                write_curvemapping(wd, la->curfalloff); 
                        
+                       /* nodetree is integral part of lamps, no libdata */
+                       if(la->nodetree) {
+                               writestruct(wd, DATA, "bNodeTree", 1, la->nodetree);
+                               write_nodetree(wd, la->nodetree);
+                       }
+
                        write_previews(wd, la->preview);
                        
                }
@@ -2165,10 +2234,6 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
                                        if(sima->cumap)
                                                write_curvemapping(wd, sima->cumap);
                                }
-                               else if(sl->spacetype==SPACE_IMASEL) {
-                                       // XXX: depreceated... do we still want to keep this?
-                                       writestruct(wd, DATA, "SpaceImaSel", 1, sl);
-                               }
                                else if(sl->spacetype==SPACE_TEXT) {
                                        writestruct(wd, DATA, "SpaceText", 1, sl);
                                }
@@ -2180,9 +2245,6 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
                                else if(sl->spacetype==SPACE_ACTION) {
                                        writestruct(wd, DATA, "SpaceAction", 1, sl);
                                }
-                               else if(sl->spacetype==SPACE_SOUND) {
-                                       writestruct(wd, DATA, "SpaceSound", 1, sl);
-                               }
                                else if(sl->spacetype==SPACE_NLA){
                                        SpaceNla *snla= (SpaceNla *)sl;
                                        
@@ -2213,6 +2275,9 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
                                else if(sl->spacetype==SPACE_USERPREF) {
                                        writestruct(wd, DATA, "SpaceUserPref", 1, sl);
                                }
+                               else if(sl->spacetype==SPACE_CLIP) {
+                                       writestruct(wd, DATA, "SpaceClip", 1, sl);
+                               }
 
                                sl= sl->next;
                        }
@@ -2224,7 +2289,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
 
 static void write_libraries(WriteData *wd, Main *main)
 {
-       ListBase *lbarray[30];
+       ListBase *lbarray[MAX_LIBARRAY];
        ID *id;
        int a, tot, foundone;
 
@@ -2461,6 +2526,38 @@ static void write_scripts(WriteData *wd, ListBase *idbase)
        }
 }
 
+static void write_movieclips(WriteData *wd, ListBase *idbase)
+{
+       MovieClip *clip;
+
+       clip= idbase->first;
+       while(clip) {
+               if(clip->id.us>0 || wd->current) {
+                       MovieTracking *tracking= &clip->tracking;
+                       MovieTrackingTrack *track;
+                       writestruct(wd, ID_MC, "MovieClip", 1, clip);
+
+                       if(tracking->reconstruction.camnr)
+                               writestruct(wd, DATA, "MovieReconstructedCamera", tracking->reconstruction.camnr, tracking->reconstruction.cameras);
+
+                       track= tracking->tracks.first;
+                       while(track) {
+                               writestruct(wd, DATA, "MovieTrackingTrack", 1, track);
+
+                               if(track->markers)
+                                       writestruct(wd, DATA, "MovieTrackingMarker", track->markersnr, track->markers);
+
+                               track= track->next;
+                       }
+               }
+
+               clip= clip->id.next;
+       }
+
+       /* flush helps the compression for undo-save */
+       mywrite(wd, MYWRITE_FLUSH, 0);
+}
+
 /* context is usually defined by WM, two cases where no WM is available:
  * - for forward compatibility, curscreen has to be saved
  * - for undofile, curscene needs to be saved */
@@ -2481,7 +2578,10 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
        fg.curscene= screen->scene;
        fg.displaymode= G.displaymode;
        fg.winpos= G.winpos;
-       fg.fileflags= (fileflags & ~(G_FILE_NO_UI|G_FILE_RELATIVE_REMAP));      // prevent to save this, is not good convention, and feature with concerns...
+
+       /* prevent to save this, is not good convention, and feature with concerns... */
+       fg.fileflags= (fileflags & ~(G_FILE_NO_UI|G_FILE_RELATIVE_REMAP|G_FILE_MESH_COMPAT));
+
        fg.globalf= G.f;
        BLI_strncpy(fg.filename, mainvar->name, sizeof(fg.filename));
 
@@ -2524,7 +2624,11 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
        blo_split_main(&mainlist, mainvar);
 
        wd= bgnwrite(handle, compare, current);
-       
+
+#ifdef USE_BMESH_SAVE_AS_COMPAT
+       wd->use_mesh_compat = (write_flags & G_FILE_MESH_COMPAT) != 0;
+#endif
+
        sprintf(buf, "BLENDER%c%c%.3d", (sizeof(void*)==8)?'-':'_', (ENDIAN_ORDER==B_ENDIAN)?'V':'v', BLENDER_VERSION);
        mywrite(wd, buf, 12);
 
@@ -2537,6 +2641,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
                write_windowmanagers(wd, &mainvar->wm);
                write_screens  (wd, &mainvar->screen);
        }
+       write_movieclips (wd, &mainvar->movieclip);
        write_scenes   (wd, &mainvar->scene);
        write_curves   (wd, &mainvar->curve);
        write_mballs   (wd, &mainvar->mball);
@@ -2585,7 +2690,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
 /* 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];
+       char tempname1[FILE_MAX], tempname2[FILE_MAX];
        int hisnr= U.versions;
        
        if(U.versions==0) return 0;
@@ -2619,8 +2724,8 @@ static int do_history(const char *name, ReportList *reports)
 /* return: success (1) */
 int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportList *reports, int *thumb)
 {
-       char userfilename[FILE_MAXDIR+FILE_MAXFILE];
-       char tempname[FILE_MAXDIR+FILE_MAXFILE+1];
+       char userfilename[FILE_MAX];
+       char tempname[FILE_MAX+1];
        int file, err, write_user_block;
 
        /* open temporary file, so we preserve the original in case we crash */
@@ -2634,10 +2739,10 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL
 
        /* remapping of relative paths to new file location */
        if(write_flags & G_FILE_RELATIVE_REMAP) {
-               char dir1[FILE_MAXDIR+FILE_MAXFILE];
-               char dir2[FILE_MAXDIR+FILE_MAXFILE];
-               BLI_split_dirfile(filepath, dir1, NULL);
-               BLI_split_dirfile(mainvar->name, dir2, NULL);
+               char dir1[FILE_MAX];
+               char dir2[FILE_MAX];
+               BLI_split_dir_part(filepath, dir1, sizeof(dir1));
+               BLI_split_dir_part(mainvar->name, dir2, sizeof(dir2));
 
                /* just incase there is some subtle difference */
                BLI_cleanup_dir(mainvar->name, dir1);
@@ -2686,12 +2791,12 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL
 
        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];
+               char gzname[FILE_MAX+4];
                int ret;
 
                /* first write compressed to separate @.gz */
                BLI_snprintf(gzname, sizeof(gzname), "%s@.gz", filepath);
-               ret = BLI_gzip(tempname, gzname);
+               ret = BLI_file_gzip(tempname, gzname);
                
                if(0==ret) {
                        /* now rename to real file name, and delete temp @ file too */