diff options
Diffstat (limited to 'source/blender/blenloader/intern/writefile.c')
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 522 |
1 files changed, 290 insertions, 232 deletions
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 3a63230018e..bf52866d8c8 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -129,6 +129,7 @@ Any case: direct data is ALWAYS after the lib block #include "BLI_blenlib.h" #include "BLI_linklist.h" #include "BLI_bpath.h" +#include "BLI_utildefines.h" #include "BKE_action.h" #include "BKE_blender.h" @@ -140,9 +141,10 @@ Any case: direct data is ALWAYS after the lib block #include "BKE_node.h" #include "BKE_report.h" #include "BKE_sequencer.h" -#include "BKE_utildefines.h" // for defines +#include "BKE_utildefines.h" #include "BKE_modifier.h" #include "BKE_fcurve.h" +#include "BKE_pointcache.h" #include "BLO_writefile.h" #include "BLO_readfile.h" @@ -310,7 +312,7 @@ static int endwrite(WriteData *wd) /* ********** WRITE FILE ****************** */ -static void writestruct(WriteData *wd, int filecode, char *structname, int nr, void *adr) +static void writestruct(WriteData *wd, int filecode, const char *structname, int nr, void *adr) { BHead bh; short *sp; @@ -362,7 +364,6 @@ static void writedata(WriteData *wd, int filecode, int len, void *adr) /* do not /*These functions are used by blender's .blend system for file saving/loading.*/ void IDP_WriteProperty_OnlyData(IDProperty *prop, void *wd); void IDP_WriteProperty(IDProperty *prop, void *wd); -static void write_animdata(WriteData *wd, AnimData *adt); // XXX code needs reshuffling, but not before NLA SoC is merged back into 2.5 static void IDP_WriteArray(IDProperty *prop, void *wd) { @@ -434,6 +435,200 @@ void IDP_WriteProperty(IDProperty *prop, void *wd) IDP_WriteProperty_OnlyData(prop, wd); } +static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers) +{ + FModifier *fcm; + + /* Modifiers */ + for (fcm= fmodifiers->first; fcm; fcm= fcm->next) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* Write the specific data */ + if (fmi && fcm->data) { + /* firstly, just write the plain fmi->data struct */ + writestruct(wd, DATA, fmi->structName, 1, fcm->data); + + /* do any modifier specific stuff */ + switch (fcm->type) { + case FMODIFIER_TYPE_GENERATOR: + { + FMod_Generator *data= (FMod_Generator *)fcm->data; + + /* write coefficients array */ + if (data->coefficients) + writedata(wd, DATA, sizeof(float)*(data->arraysize), data->coefficients); + } + break; + case FMODIFIER_TYPE_ENVELOPE: + { + FMod_Envelope *data= (FMod_Envelope *)fcm->data; + + /* write envelope data */ + if (data->data) + writedata(wd, DATA, sizeof(FCM_EnvelopeData)*(data->totvert), data->data); + } + break; + case FMODIFIER_TYPE_PYTHON: + { + FMod_Python *data = (FMod_Python *)fcm->data; + + /* Write ID Properties -- and copy this comment EXACTLY for easy finding + of library blocks that implement this.*/ + IDP_WriteProperty(data->prop, wd); + } + break; + } + } + + /* Write the modifier */ + writestruct(wd, DATA, "FModifier", 1, fcm); + } +} + +static void write_fcurves(WriteData *wd, ListBase *fcurves) +{ + FCurve *fcu; + + for (fcu=fcurves->first; fcu; fcu=fcu->next) { + /* F-Curve */ + writestruct(wd, DATA, "FCurve", 1, fcu); + + /* curve data */ + if (fcu->bezt) + writestruct(wd, DATA, "BezTriple", fcu->totvert, fcu->bezt); + if (fcu->fpt) + writestruct(wd, DATA, "FPoint", fcu->totvert, fcu->fpt); + + if (fcu->rna_path) + writedata(wd, DATA, strlen(fcu->rna_path)+1, fcu->rna_path); + + /* driver data */ + if (fcu->driver) { + ChannelDriver *driver= fcu->driver; + DriverVar *dvar; + + writestruct(wd, DATA, "ChannelDriver", 1, driver); + + /* variables */ + for (dvar= driver->variables.first; dvar; dvar= dvar->next) { + writestruct(wd, DATA, "DriverVar", 1, dvar); + + DRIVER_TARGETS_USED_LOOPER(dvar) + { + if (dtar->rna_path) + writedata(wd, DATA, strlen(dtar->rna_path)+1, dtar->rna_path); + } + DRIVER_TARGETS_LOOPER_END + } + } + + /* write F-Modifiers */ + write_fmodifiers(wd, &fcu->modifiers); + } +} + +static void write_actions(WriteData *wd, ListBase *idbase) +{ + bAction *act; + bActionGroup *grp; + TimeMarker *marker; + + for(act=idbase->first; act; act= act->id.next) { + if (act->id.us>0 || wd->current) { + writestruct(wd, ID_AC, "bAction", 1, act); + if (act->id.properties) IDP_WriteProperty(act->id.properties, wd); + + write_fcurves(wd, &act->curves); + + for (grp=act->groups.first; grp; grp=grp->next) { + writestruct(wd, DATA, "bActionGroup", 1, grp); + } + + for (marker=act->markers.first; marker; marker=marker->next) { + writestruct(wd, DATA, "TimeMarker", 1, marker); + } + } + } + + /* flush helps the compression for undo-save */ + mywrite(wd, MYWRITE_FLUSH, 0); +} + +static void write_keyingsets(WriteData *wd, ListBase *list) +{ + KeyingSet *ks; + KS_Path *ksp; + + for (ks= list->first; ks; ks= ks->next) { + /* KeyingSet */ + writestruct(wd, DATA, "KeyingSet", 1, ks); + + /* Paths */ + for (ksp= ks->paths.first; ksp; ksp= ksp->next) { + /* Path */ + writestruct(wd, DATA, "KS_Path", 1, ksp); + + if (ksp->rna_path) + writedata(wd, DATA, strlen(ksp->rna_path)+1, ksp->rna_path); + } + } +} + +static void write_nlastrips(WriteData *wd, ListBase *strips) +{ + NlaStrip *strip; + + for (strip= strips->first; strip; strip= strip->next) { + /* write the strip first */ + writestruct(wd, DATA, "NlaStrip", 1, strip); + + /* write the strip's F-Curves and modifiers */ + write_fcurves(wd, &strip->fcurves); + write_fmodifiers(wd, &strip->modifiers); + + /* write the strip's children */ + write_nlastrips(wd, &strip->strips); + } +} + +static void write_nladata(WriteData *wd, ListBase *nlabase) +{ + NlaTrack *nlt; + + /* write all the tracks */ + for (nlt= nlabase->first; nlt; nlt= nlt->next) { + /* write the track first */ + writestruct(wd, DATA, "NlaTrack", 1, nlt); + + /* write the track's strips */ + write_nlastrips(wd, &nlt->strips); + } +} + +static void write_animdata(WriteData *wd, AnimData *adt) +{ + AnimOverride *aor; + + /* firstly, just write the AnimData block */ + writestruct(wd, DATA, "AnimData", 1, adt); + + /* write drivers */ + write_fcurves(wd, &adt->drivers); + + /* write overrides */ + // FIXME: are these needed? + for (aor= adt->overrides.first; aor; aor= aor->next) { + /* overrides consist of base data + rna_path */ + writestruct(wd, DATA, "AnimOverride", 1, aor); + writedata(wd, DATA, strlen(aor->rna_path)+1, aor->rna_path); + } + + // TODO write the remaps (if they are needed) + + /* write NLA data */ + write_nladata(wd, &adt->nla_tracks); +} + static void write_curvemapping(WriteData *wd, CurveMapping *cumap) { int a; @@ -506,7 +701,7 @@ static void write_renderinfo(WriteData *wd, Main *mainvar) /* for renderdeamon data[1]= sce->r.efra; memset(data+2, 0, sizeof(int)*6); - strncpy((char *)(data+2), sce->id.name+2, 21); + BLI_strncpy((char *)(data+2), sce->id.name+2, sizeof(sce->id.name)-2); writedata(wd, REND, 32, data); } @@ -573,9 +768,22 @@ static void write_boid_state(WriteData *wd, BoidState *state) //for(; cond; cond=cond->next) // writestruct(wd, DATA, "BoidCondition", 1, cond); } -/* TODO: replace *cache with *cachelist once it's coded */ -#define PTCACHE_WRITE_PSYS 0 -#define PTCACHE_WRITE_CLOTH 1 + +/* update this also to readfile.c */ +static const char *ptcache_data_struct[] = { + "", // BPHYS_DATA_INDEX + "", // BPHYS_DATA_LOCATION + "", // BPHYS_DATA_VELOCITY + "", // BPHYS_DATA_ROTATION + "", // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST */ + "", // BPHYS_DATA_SIZE: + "", // BPHYS_DATA_TIMES: + "BoidData" // case BPHYS_DATA_BOIDS: +}; +static const char *ptcache_extra_struct[] = { + "", + "ParticleSpring" +}; static void write_pointcaches(WriteData *wd, ListBase *ptcaches) { PointCache *cache = ptcaches->first; @@ -588,13 +796,24 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches) PTCacheMem *pm = cache->mem_cache.first; for(; pm; pm=pm->next) { + PTCacheExtra *extra = pm->extradata.first; + writestruct(wd, DATA, "PTCacheMem", 1, pm); - if(pm->index_array) - writedata(wd, DATA, MEM_allocN_len(pm->index_array), pm->index_array); for(i=0; i<BPHYS_TOT_DATA; i++) { - if(pm->data[i] && pm->data_types & (1<<i)) - writedata(wd, DATA, MEM_allocN_len(pm->data[i]), pm->data[i]); + if(pm->data[i] && pm->data_types & (1<<i)) { + if(strcmp(ptcache_data_struct[i], "")==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]); + } + } + + for(; extra; extra=extra->next) { + if(strcmp(ptcache_extra_struct[extra->type], "")==0) + continue; + writestruct(wd, DATA, "PTCacheExtra", 1, extra); + writestruct(wd, DATA, ptcache_extra_struct[extra->type], extra->totdata, extra->data); } } } @@ -656,6 +875,9 @@ static void write_particlesystems(WriteData *wd, ListBase *particles) if(psys->particles->boid && psys->part->phystype == PART_PHYS_BOIDS) writestruct(wd, DATA, "BoidParticle", psys->totpart, psys->particles->boid); + + if(psys->part->fluid && psys->part->phystype == PART_PHYS_FLUID && (psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS)) + writestruct(wd, DATA, "ParticleSpring", psys->tot_fluidsprings, psys->fluid_springs); } pt = psys->targets.first; for(; pt; pt=pt->next) @@ -849,200 +1071,6 @@ static void write_actuators(WriteData *wd, ListBase *lb) } } -static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers) -{ - FModifier *fcm; - - /* Modifiers */ - for (fcm= fmodifiers->first; fcm; fcm= fcm->next) { - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - - /* Write the specific data */ - if (fmi && fcm->data) { - /* firstly, just write the plain fmi->data struct */ - writestruct(wd, DATA, fmi->structName, 1, fcm->data); - - /* do any modifier specific stuff */ - switch (fcm->type) { - case FMODIFIER_TYPE_GENERATOR: - { - FMod_Generator *data= (FMod_Generator *)fcm->data; - - /* write coefficients array */ - if (data->coefficients) - writedata(wd, DATA, sizeof(float)*(data->arraysize), data->coefficients); - } - break; - case FMODIFIER_TYPE_ENVELOPE: - { - FMod_Envelope *data= (FMod_Envelope *)fcm->data; - - /* write envelope data */ - if (data->data) - writedata(wd, DATA, sizeof(FCM_EnvelopeData)*(data->totvert), data->data); - } - break; - case FMODIFIER_TYPE_PYTHON: - { - FMod_Python *data = (FMod_Python *)fcm->data; - - /* Write ID Properties -- and copy this comment EXACTLY for easy finding - of library blocks that implement this.*/ - IDP_WriteProperty(data->prop, wd); - } - break; - } - } - - /* Write the modifier */ - writestruct(wd, DATA, "FModifier", 1, fcm); - } -} - -static void write_fcurves(WriteData *wd, ListBase *fcurves) -{ - FCurve *fcu; - - for (fcu=fcurves->first; fcu; fcu=fcu->next) { - /* F-Curve */ - writestruct(wd, DATA, "FCurve", 1, fcu); - - /* curve data */ - if (fcu->bezt) - writestruct(wd, DATA, "BezTriple", fcu->totvert, fcu->bezt); - if (fcu->fpt) - writestruct(wd, DATA, "FPoint", fcu->totvert, fcu->fpt); - - if (fcu->rna_path) - writedata(wd, DATA, strlen(fcu->rna_path)+1, fcu->rna_path); - - /* driver data */ - if (fcu->driver) { - ChannelDriver *driver= fcu->driver; - DriverVar *dvar; - - writestruct(wd, DATA, "ChannelDriver", 1, driver); - - /* variables */ - for (dvar= driver->variables.first; dvar; dvar= dvar->next) { - writestruct(wd, DATA, "DriverVar", 1, dvar); - - DRIVER_TARGETS_USED_LOOPER(dvar) - { - if (dtar->rna_path) - writedata(wd, DATA, strlen(dtar->rna_path)+1, dtar->rna_path); - } - DRIVER_TARGETS_LOOPER_END - } - } - - /* write F-Modifiers */ - write_fmodifiers(wd, &fcu->modifiers); - } -} - -static void write_actions(WriteData *wd, ListBase *idbase) -{ - bAction *act; - bActionGroup *grp; - TimeMarker *marker; - - for(act=idbase->first; act; act= act->id.next) { - if (act->id.us>0 || wd->current) { - writestruct(wd, ID_AC, "bAction", 1, act); - if (act->id.properties) IDP_WriteProperty(act->id.properties, wd); - - write_fcurves(wd, &act->curves); - - for (grp=act->groups.first; grp; grp=grp->next) { - writestruct(wd, DATA, "bActionGroup", 1, grp); - } - - for (marker=act->markers.first; marker; marker=marker->next) { - writestruct(wd, DATA, "TimeMarker", 1, marker); - } - } - } - - /* flush helps the compression for undo-save */ - mywrite(wd, MYWRITE_FLUSH, 0); -} - -static void write_keyingsets(WriteData *wd, ListBase *list) -{ - KeyingSet *ks; - KS_Path *ksp; - - for (ks= list->first; ks; ks= ks->next) { - /* KeyingSet */ - writestruct(wd, DATA, "KeyingSet", 1, ks); - - /* Paths */ - for (ksp= ks->paths.first; ksp; ksp= ksp->next) { - /* Path */ - writestruct(wd, DATA, "KS_Path", 1, ksp); - - if (ksp->rna_path) - writedata(wd, DATA, strlen(ksp->rna_path)+1, ksp->rna_path); - } - } -} - -static void write_nlastrips(WriteData *wd, ListBase *strips) -{ - NlaStrip *strip; - - for (strip= strips->first; strip; strip= strip->next) { - /* write the strip first */ - writestruct(wd, DATA, "NlaStrip", 1, strip); - - /* write the strip's F-Curves and modifiers */ - write_fcurves(wd, &strip->fcurves); - write_fmodifiers(wd, &strip->modifiers); - - /* write the strip's children */ - write_nlastrips(wd, &strip->strips); - } -} - -static void write_nladata(WriteData *wd, ListBase *nlabase) -{ - NlaTrack *nlt; - - /* write all the tracks */ - for (nlt= nlabase->first; nlt; nlt= nlt->next) { - /* write the track first */ - writestruct(wd, DATA, "NlaTrack", 1, nlt); - - /* write the track's strips */ - write_nlastrips(wd, &nlt->strips); - } -} - -static void write_animdata(WriteData *wd, AnimData *adt) -{ - AnimOverride *aor; - - /* firstly, just write the AnimData block */ - writestruct(wd, DATA, "AnimData", 1, adt); - - /* write drivers */ - write_fcurves(wd, &adt->drivers); - - /* write overrides */ - // FIXME: are these needed? - for (aor= adt->overrides.first; aor; aor= aor->next) { - /* overrides consist of base data + rna_path */ - writestruct(wd, DATA, "AnimOverride", 1, aor); - writedata(wd, DATA, strlen(aor->rna_path)+1, aor->rna_path); - } - - // TODO write the remaps (if they are needed) - - /* write NLA data */ - write_nladata(wd, &adt->nla_tracks); -} - static void write_motionpath(WriteData *wd, bMotionPath *mpath) { /* sanity checks */ @@ -1180,19 +1208,32 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) if(smd->type & MOD_SMOKE_TYPE_DOMAIN) { + if(smd->domain) + { + write_pointcaches(wd, &(smd->domain->ptcaches[0])); + + /* create fake pointcache so that old blender versions can read it */ + smd->domain->point_cache[1] = BKE_ptcache_add(&smd->domain->ptcaches[1]); + smd->domain->point_cache[1]->flag |= PTCACHE_DISK_CACHE; + smd->domain->point_cache[1]->step = 1; + + write_pointcaches(wd, &(smd->domain->ptcaches[1])); + } + writestruct(wd, DATA, "SmokeDomainSettings", 1, smd->domain); - writestruct(wd, DATA, "EffectorWeights", 1, smd->domain->effector_weights); + + if(smd->domain) { + /* cleanup the fake pointcache */ + BKE_ptcache_free_list(&smd->domain->ptcaches[1]); + smd->domain->point_cache[1] = NULL; + + writestruct(wd, DATA, "EffectorWeights", 1, smd->domain->effector_weights); + } } else if(smd->type & MOD_SMOKE_TYPE_FLOW) writestruct(wd, DATA, "SmokeFlowSettings", 1, smd->flow); else if(smd->type & MOD_SMOKE_TYPE_COLL) writestruct(wd, DATA, "SmokeCollSettings", 1, smd->coll); - - if((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) - { - write_pointcaches(wd, &(smd->domain->ptcaches[0])); - write_pointcaches(wd, &(smd->domain->ptcaches[1])); - } } else if(md->type==eModifierType_Fluidsim) { FluidsimModifierData *fluidmd = (FluidsimModifierData*) md; @@ -1478,7 +1519,7 @@ static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data, for (i=0; i<data->totlayer; i++) { CustomDataLayer *layer= &data->layers[i]; - char *structname; + const char *structname; int structnum, datasize; if (layer->type == CD_MDEFORMVERT) { @@ -1560,7 +1601,10 @@ static void write_lattices(WriteData *wd, ListBase *idbase) /* write LibData */ writestruct(wd, ID_LT, "Lattice", 1, lt); if (lt->id.properties) IDP_WriteProperty(lt->id.properties, wd); - + + /* write animdata */ + if (lt->adt) write_animdata(wd, lt->adt); + /* direct data */ writestruct(wd, DATA, "BPoint", lt->pntsu*lt->pntsv*lt->pntsw, lt->def); @@ -1907,21 +1951,23 @@ static void write_gpencils(WriteData *wd, ListBase *lb) bGPDstroke *gps; for (gpd= lb->first; gpd; gpd= gpd->id.next) { - /* write gpd data block to file */ - writestruct(wd, ID_GD, "bGPdata", 1, gpd); - - /* write grease-pencil layers to file */ - for (gpl= gpd->layers.first; gpl; gpl= gpl->next) { - writestruct(wd, DATA, "bGPDlayer", 1, gpl); + if (gpd->id.us>0 || wd->current) { + /* write gpd data block to file */ + writestruct(wd, ID_GD, "bGPdata", 1, gpd); - /* write this layer's frames to file */ - for (gpf= gpl->frames.first; gpf; gpf= gpf->next) { - writestruct(wd, DATA, "bGPDframe", 1, gpf); + /* write grease-pencil layers to file */ + for (gpl= gpd->layers.first; gpl; gpl= gpl->next) { + writestruct(wd, DATA, "bGPDlayer", 1, gpl); - /* write strokes */ - for (gps= gpf->strokes.first; gps; gps= gps->next) { - writestruct(wd, DATA, "bGPDstroke", 1, gps); - writestruct(wd, DATA, "bGPDspoint", gps->totpoints, gps->points); + /* write this layer's frames to file */ + for (gpf= gpl->frames.first; gpf; gpf= gpf->next) { + writestruct(wd, DATA, "bGPDframe", 1, gpf); + + /* write strokes */ + for (gps= gpf->strokes.first; gps; gps= gps->next) { + writestruct(wd, DATA, "bGPDstroke", 1, gps); + writestruct(wd, DATA, "bGPDspoint", gps->totpoints, gps->points); + } } } } @@ -2096,6 +2142,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase) ConsoleLine *cl; 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); } @@ -2345,6 +2392,10 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar) bScreen *screen; char subvstr[8]; + /* prevent mem checkers from complaining */ + fg.pads= fg.pad= 0; + memset(fg.filename, 0, sizeof(fg.filename)); + current_screen_compat(mainvar, &screen); /* XXX still remap G */ @@ -2362,7 +2413,14 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar) fg.subversion= BLENDER_SUBVERSION; fg.minversion= BLENDER_MINVERSION; fg.minsubversion= BLENDER_MINSUBVERSION; - fg.pads= 0; /* prevent mem checkers from complaining */ +#ifdef NAN_BUILDINFO + { + extern char build_rev[]; + fg.revision= atoi(build_rev); + } +#else + fg.revision= 0; +#endif writestruct(wd, GLOB, "FileGlobal", 1, &fg); } @@ -2474,14 +2532,14 @@ int BLO_write_file(Main *mainvar, char *dir, int write_flags, ReportList *report if(strcmp(dir1, dir2)==0) write_flags &= ~G_FILE_RELATIVE_REMAP; else - makeFilesAbsolute(G.sce, NULL); + makeFilesAbsolute(mainvar, G.main->name, NULL); } - BLI_make_file_string(G.sce, 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); write_user_block= BLI_streq(dir, userfilename); if(write_flags & G_FILE_RELATIVE_REMAP) - makeFilesRelative(dir, NULL); /* note, making relative to something OTHER then G.sce */ + makeFilesRelative(mainvar, dir, NULL); /* note, making relative to something OTHER then G.main->name */ /* actual file writing */ err= write_file_handle(mainvar, file, NULL,NULL, write_user_block, write_flags, thumb); @@ -2533,7 +2591,7 @@ int BLO_write_file(Main *mainvar, char *dir, int write_flags, ReportList *report } /* return: success (1) */ -int BLO_write_file_mem(Main *mainvar, MemFile *compare, MemFile *current, int write_flags, ReportList *reports) +int BLO_write_file_mem(Main *mainvar, MemFile *compare, MemFile *current, int write_flags) { int err; |