Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * 00022 * Contributor(s): Blender Foundation 00023 * 00024 * ***** END GPL LICENSE BLOCK ***** 00025 */ 00026 00032 /* 00033 FILEFORMAT: IFF-style structure (but not IFF compatible!) 00034 00035 start file: 00036 BLENDER_V100 12 bytes (versie 1.00) 00037 V = big endian, v = little endian 00038 _ = 4 byte pointer, - = 8 byte pointer 00039 00040 datablocks: also see struct BHead 00041 <bh.code> 4 chars 00042 <bh.len> int, len data after BHead 00043 <bh.old> void, old pointer 00044 <bh.SDNAnr> int 00045 <bh.nr> int, in case of array: amount of structs 00046 data 00047 ... 00048 ... 00049 00050 Almost all data in Blender are structures. Each struct saved 00051 gets a BHead header. With BHead the struct can be linked again 00052 and compared with StructDNA . 00053 00054 WRITE 00055 00056 Preferred writing order: (not really a must, but why would you do it random?) 00057 Any case: direct data is ALWAYS after the lib block 00058 00059 (Local file data) 00060 - for each LibBlock 00061 - write LibBlock 00062 - write associated direct data 00063 (External file data) 00064 - per library 00065 - write library block 00066 - per LibBlock 00067 - write the ID of LibBlock 00068 - write TEST (128x128, blend file preview, optional) 00069 - write FileGlobal (some global vars) 00070 - write SDNA 00071 - write USER if filename is ~/X.XX/config/startup.blend 00072 */ 00073 00074 00075 #include <math.h> 00076 #include <fcntl.h> 00077 #include <stdio.h> 00078 #include <string.h> 00079 #include <stdlib.h> 00080 00081 #include "zlib.h" 00082 00083 #ifndef WIN32 00084 #include <unistd.h> 00085 #else 00086 #include "winsock2.h" 00087 #include <io.h> 00088 #include <process.h> // for getpid 00089 #include "BLI_winstuff.h" 00090 #endif 00091 00092 #include "DNA_anim_types.h" 00093 #include "DNA_armature_types.h" 00094 #include "DNA_actuator_types.h" 00095 #include "DNA_brush_types.h" 00096 #include "DNA_camera_types.h" 00097 #include "DNA_cloth_types.h" 00098 #include "DNA_constraint_types.h" 00099 #include "DNA_controller_types.h" 00100 #include "DNA_dynamicpaint_types.h" 00101 #include "DNA_genfile.h" 00102 #include "DNA_group_types.h" 00103 #include "DNA_gpencil_types.h" 00104 #include "DNA_fileglobal_types.h" 00105 #include "DNA_key_types.h" 00106 #include "DNA_lattice_types.h" 00107 #include "DNA_lamp_types.h" 00108 #include "DNA_meta_types.h" 00109 #include "DNA_mesh_types.h" 00110 #include "DNA_meshdata_types.h" 00111 #include "DNA_material_types.h" 00112 #include "DNA_node_types.h" 00113 #include "DNA_object_types.h" 00114 #include "DNA_object_force.h" 00115 #include "DNA_packedFile_types.h" 00116 #include "DNA_particle_types.h" 00117 #include "DNA_property_types.h" 00118 #include "DNA_scene_types.h" 00119 #include "DNA_sdna_types.h" 00120 #include "DNA_sequence_types.h" 00121 #include "DNA_sensor_types.h" 00122 #include "DNA_smoke_types.h" 00123 #include "DNA_space_types.h" 00124 #include "DNA_screen_types.h" 00125 #include "DNA_speaker_types.h" 00126 #include "DNA_sound_types.h" 00127 #include "DNA_text_types.h" 00128 #include "DNA_view3d_types.h" 00129 #include "DNA_vfont_types.h" 00130 #include "DNA_world_types.h" 00131 #include "DNA_windowmanager_types.h" 00132 #include "DNA_movieclip_types.h" 00133 00134 #include "MEM_guardedalloc.h" // MEM_freeN 00135 #include "BLI_blenlib.h" 00136 #include "BLI_linklist.h" 00137 #include "BLI_bpath.h" 00138 #include "BLI_math.h" 00139 #include "BLI_utildefines.h" 00140 00141 #include "BKE_action.h" 00142 #include "BKE_blender.h" 00143 #include "BKE_curve.h" 00144 #include "BKE_constraint.h" 00145 #include "BKE_global.h" // for G 00146 #include "BKE_library.h" // for set_listbasepointers 00147 #include "BKE_main.h" 00148 #include "BKE_node.h" 00149 #include "BKE_report.h" 00150 #include "BKE_sequencer.h" 00151 #include "BKE_utildefines.h" 00152 #include "BKE_modifier.h" 00153 #include "BKE_fcurve.h" 00154 #include "BKE_pointcache.h" 00155 00156 #include "BLO_writefile.h" 00157 #include "BLO_readfile.h" 00158 #include "BLO_undofile.h" 00159 00160 #include "readfile.h" 00161 00162 #include <errno.h> 00163 00164 /* ********* my write, buffered writing with minimum size chunks ************ */ 00165 00166 #define MYWRITE_BUFFER_SIZE 100000 00167 #define MYWRITE_MAX_CHUNK 32768 00168 00169 typedef struct { 00170 struct SDNA *sdna; 00171 00172 int file; 00173 unsigned char *buf; 00174 MemFile *compare, *current; 00175 00176 int tot, count, error, memsize; 00177 00178 #ifdef USE_BMESH_SAVE_AS_COMPAT 00179 char use_mesh_compat; /* option to save with older mesh format */ 00180 #endif 00181 } WriteData; 00182 00183 static WriteData *writedata_new(int file) 00184 { 00185 WriteData *wd= MEM_callocN(sizeof(*wd), "writedata"); 00186 00187 /* XXX, see note about this in readfile.c, remove 00188 * once we have an xp lock - zr 00189 */ 00190 00191 if (wd == NULL) return NULL; 00192 00193 wd->sdna= DNA_sdna_from_data(DNAstr, DNAlen, 0); 00194 00195 wd->file= file; 00196 00197 wd->buf= MEM_mallocN(MYWRITE_BUFFER_SIZE, "wd->buf"); 00198 00199 return wd; 00200 } 00201 00202 static void writedata_do_write(WriteData *wd, void *mem, int memlen) 00203 { 00204 if ((wd == NULL) || wd->error || (mem == NULL) || memlen < 1) return; 00205 if (wd->error) return; 00206 00207 /* memory based save */ 00208 if(wd->current) { 00209 add_memfilechunk(NULL, wd->current, mem, memlen); 00210 } 00211 else { 00212 if (write(wd->file, mem, memlen) != memlen) 00213 wd->error= 1; 00214 00215 } 00216 } 00217 00218 static void writedata_free(WriteData *wd) 00219 { 00220 DNA_sdna_free(wd->sdna); 00221 00222 MEM_freeN(wd->buf); 00223 MEM_freeN(wd); 00224 } 00225 00226 /***/ 00227 00235 #define MYWRITE_FLUSH NULL 00236 00237 static void mywrite( WriteData *wd, void *adr, int len) 00238 { 00239 if (wd->error) return; 00240 00241 /* flush helps compression for undo-save */ 00242 if(adr==MYWRITE_FLUSH) { 00243 if(wd->count) { 00244 writedata_do_write(wd, wd->buf, wd->count); 00245 wd->count= 0; 00246 } 00247 return; 00248 } 00249 00250 wd->tot+= len; 00251 00252 /* if we have a single big chunk, write existing data in 00253 * buffer and write out big chunk in smaller pieces */ 00254 if(len>MYWRITE_MAX_CHUNK) { 00255 if(wd->count) { 00256 writedata_do_write(wd, wd->buf, wd->count); 00257 wd->count= 0; 00258 } 00259 00260 do { 00261 int writelen= MIN2(len, MYWRITE_MAX_CHUNK); 00262 writedata_do_write(wd, adr, writelen); 00263 adr = (char*)adr + writelen; 00264 len -= writelen; 00265 } while(len > 0); 00266 00267 return; 00268 } 00269 00270 /* if data would overflow buffer, write out the buffer */ 00271 if(len+wd->count>MYWRITE_BUFFER_SIZE-1) { 00272 writedata_do_write(wd, wd->buf, wd->count); 00273 wd->count= 0; 00274 } 00275 00276 /* append data at end of buffer */ 00277 memcpy(&wd->buf[wd->count], adr, len); 00278 wd->count+= len; 00279 } 00280 00287 static WriteData *bgnwrite(int file, MemFile *compare, MemFile *current) 00288 { 00289 WriteData *wd= writedata_new(file); 00290 00291 if (wd == NULL) return NULL; 00292 00293 wd->compare= compare; 00294 wd->current= current; 00295 /* this inits comparing */ 00296 add_memfilechunk(compare, NULL, NULL, 0); 00297 00298 return wd; 00299 } 00300 00307 static int endwrite(WriteData *wd) 00308 { 00309 int err; 00310 00311 if (wd->count) { 00312 writedata_do_write(wd, wd->buf, wd->count); 00313 wd->count= 0; 00314 } 00315 00316 err= wd->error; 00317 writedata_free(wd); 00318 00319 return err; 00320 } 00321 00322 /* ********** WRITE FILE ****************** */ 00323 00324 static void writestruct(WriteData *wd, int filecode, const char *structname, int nr, void *adr) 00325 { 00326 BHead bh; 00327 short *sp; 00328 00329 if(adr==NULL || nr==0) return; 00330 00331 /* init BHead */ 00332 bh.code= filecode; 00333 bh.old= adr; 00334 bh.nr= nr; 00335 00336 bh.SDNAnr= DNA_struct_find_nr(wd->sdna, structname); 00337 if(bh.SDNAnr== -1) { 00338 printf("error: can't find SDNA code <%s>\n", structname); 00339 return; 00340 } 00341 sp= wd->sdna->structs[bh.SDNAnr]; 00342 00343 bh.len= nr*wd->sdna->typelens[sp[0]]; 00344 00345 if(bh.len==0) return; 00346 00347 mywrite(wd, &bh, sizeof(BHead)); 00348 mywrite(wd, adr, bh.len); 00349 } 00350 00351 static void writedata(WriteData *wd, int filecode, int len, void *adr) /* do not use for structs */ 00352 { 00353 BHead bh; 00354 00355 if(adr==NULL) return; 00356 if(len==0) return; 00357 00358 len+= 3; 00359 len-= ( len % 4); 00360 00361 /* init BHead */ 00362 bh.code= filecode; 00363 bh.old= adr; 00364 bh.nr= 1; 00365 bh.SDNAnr= 0; 00366 bh.len= len; 00367 00368 mywrite(wd, &bh, sizeof(BHead)); 00369 if(len) mywrite(wd, adr, len); 00370 } 00371 00372 /* *************** writing some direct data structs used in more code parts **************** */ 00373 /*These functions are used by blender's .blend system for file saving/loading.*/ 00374 void IDP_WriteProperty_OnlyData(IDProperty *prop, void *wd); 00375 void IDP_WriteProperty(IDProperty *prop, void *wd); 00376 00377 static void IDP_WriteArray(IDProperty *prop, void *wd) 00378 { 00379 /*REMEMBER to set totalen to len in the linking code!!*/ 00380 if (prop->data.pointer) { 00381 writedata(wd, DATA, MEM_allocN_len(prop->data.pointer), prop->data.pointer); 00382 00383 if(prop->subtype == IDP_GROUP) { 00384 IDProperty **array= prop->data.pointer; 00385 int a; 00386 00387 for(a=0; a<prop->len; a++) 00388 IDP_WriteProperty(array[a], wd); 00389 } 00390 } 00391 } 00392 00393 static void IDP_WriteIDPArray(IDProperty *prop, void *wd) 00394 { 00395 /*REMEMBER to set totalen to len in the linking code!!*/ 00396 if (prop->data.pointer) { 00397 IDProperty *array = prop->data.pointer; 00398 int a; 00399 00400 writestruct(wd, DATA, "IDProperty", prop->len, array); 00401 00402 for(a=0; a<prop->len; a++) 00403 IDP_WriteProperty_OnlyData(&array[a], wd); 00404 } 00405 } 00406 00407 static void IDP_WriteString(IDProperty *prop, void *wd) 00408 { 00409 /*REMEMBER to set totalen to len in the linking code!!*/ 00410 writedata(wd, DATA, prop->len+1, prop->data.pointer); 00411 } 00412 00413 static void IDP_WriteGroup(IDProperty *prop, void *wd) 00414 { 00415 IDProperty *loop; 00416 00417 for (loop=prop->data.group.first; loop; loop=loop->next) { 00418 IDP_WriteProperty(loop, wd); 00419 } 00420 } 00421 00422 /* Functions to read/write ID Properties */ 00423 void IDP_WriteProperty_OnlyData(IDProperty *prop, void *wd) 00424 { 00425 switch (prop->type) { 00426 case IDP_GROUP: 00427 IDP_WriteGroup(prop, wd); 00428 break; 00429 case IDP_STRING: 00430 IDP_WriteString(prop, wd); 00431 break; 00432 case IDP_ARRAY: 00433 IDP_WriteArray(prop, wd); 00434 break; 00435 case IDP_IDPARRAY: 00436 IDP_WriteIDPArray(prop, wd); 00437 break; 00438 } 00439 } 00440 00441 void IDP_WriteProperty(IDProperty *prop, void *wd) 00442 { 00443 writestruct(wd, DATA, "IDProperty", 1, prop); 00444 IDP_WriteProperty_OnlyData(prop, wd); 00445 } 00446 00447 static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers) 00448 { 00449 FModifier *fcm; 00450 00451 /* Modifiers */ 00452 for (fcm= fmodifiers->first; fcm; fcm= fcm->next) { 00453 FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); 00454 00455 /* Write the specific data */ 00456 if (fmi && fcm->data) { 00457 /* firstly, just write the plain fmi->data struct */ 00458 writestruct(wd, DATA, fmi->structName, 1, fcm->data); 00459 00460 /* do any modifier specific stuff */ 00461 switch (fcm->type) { 00462 case FMODIFIER_TYPE_GENERATOR: 00463 { 00464 FMod_Generator *data= (FMod_Generator *)fcm->data; 00465 00466 /* write coefficients array */ 00467 if (data->coefficients) 00468 writedata(wd, DATA, sizeof(float)*(data->arraysize), data->coefficients); 00469 } 00470 break; 00471 case FMODIFIER_TYPE_ENVELOPE: 00472 { 00473 FMod_Envelope *data= (FMod_Envelope *)fcm->data; 00474 00475 /* write envelope data */ 00476 if (data->data) 00477 writestruct(wd, DATA, "FCM_EnvelopeData", data->totvert, data->data); 00478 } 00479 break; 00480 case FMODIFIER_TYPE_PYTHON: 00481 { 00482 FMod_Python *data = (FMod_Python *)fcm->data; 00483 00484 /* Write ID Properties -- and copy this comment EXACTLY for easy finding 00485 of library blocks that implement this.*/ 00486 IDP_WriteProperty(data->prop, wd); 00487 } 00488 break; 00489 } 00490 } 00491 00492 /* Write the modifier */ 00493 writestruct(wd, DATA, "FModifier", 1, fcm); 00494 } 00495 } 00496 00497 static void write_fcurves(WriteData *wd, ListBase *fcurves) 00498 { 00499 FCurve *fcu; 00500 00501 for (fcu=fcurves->first; fcu; fcu=fcu->next) { 00502 /* F-Curve */ 00503 writestruct(wd, DATA, "FCurve", 1, fcu); 00504 00505 /* curve data */ 00506 if (fcu->bezt) 00507 writestruct(wd, DATA, "BezTriple", fcu->totvert, fcu->bezt); 00508 if (fcu->fpt) 00509 writestruct(wd, DATA, "FPoint", fcu->totvert, fcu->fpt); 00510 00511 if (fcu->rna_path) 00512 writedata(wd, DATA, strlen(fcu->rna_path)+1, fcu->rna_path); 00513 00514 /* driver data */ 00515 if (fcu->driver) { 00516 ChannelDriver *driver= fcu->driver; 00517 DriverVar *dvar; 00518 00519 writestruct(wd, DATA, "ChannelDriver", 1, driver); 00520 00521 /* variables */ 00522 for (dvar= driver->variables.first; dvar; dvar= dvar->next) { 00523 writestruct(wd, DATA, "DriverVar", 1, dvar); 00524 00525 DRIVER_TARGETS_USED_LOOPER(dvar) 00526 { 00527 if (dtar->rna_path) 00528 writedata(wd, DATA, strlen(dtar->rna_path)+1, dtar->rna_path); 00529 } 00530 DRIVER_TARGETS_LOOPER_END 00531 } 00532 } 00533 00534 /* write F-Modifiers */ 00535 write_fmodifiers(wd, &fcu->modifiers); 00536 } 00537 } 00538 00539 static void write_actions(WriteData *wd, ListBase *idbase) 00540 { 00541 bAction *act; 00542 bActionGroup *grp; 00543 TimeMarker *marker; 00544 00545 for(act=idbase->first; act; act= act->id.next) { 00546 if (act->id.us>0 || wd->current) { 00547 writestruct(wd, ID_AC, "bAction", 1, act); 00548 if (act->id.properties) IDP_WriteProperty(act->id.properties, wd); 00549 00550 write_fcurves(wd, &act->curves); 00551 00552 for (grp=act->groups.first; grp; grp=grp->next) { 00553 writestruct(wd, DATA, "bActionGroup", 1, grp); 00554 } 00555 00556 for (marker=act->markers.first; marker; marker=marker->next) { 00557 writestruct(wd, DATA, "TimeMarker", 1, marker); 00558 } 00559 } 00560 } 00561 00562 /* flush helps the compression for undo-save */ 00563 mywrite(wd, MYWRITE_FLUSH, 0); 00564 } 00565 00566 static void write_keyingsets(WriteData *wd, ListBase *list) 00567 { 00568 KeyingSet *ks; 00569 KS_Path *ksp; 00570 00571 for (ks= list->first; ks; ks= ks->next) { 00572 /* KeyingSet */ 00573 writestruct(wd, DATA, "KeyingSet", 1, ks); 00574 00575 /* Paths */ 00576 for (ksp= ks->paths.first; ksp; ksp= ksp->next) { 00577 /* Path */ 00578 writestruct(wd, DATA, "KS_Path", 1, ksp); 00579 00580 if (ksp->rna_path) 00581 writedata(wd, DATA, strlen(ksp->rna_path)+1, ksp->rna_path); 00582 } 00583 } 00584 } 00585 00586 static void write_nlastrips(WriteData *wd, ListBase *strips) 00587 { 00588 NlaStrip *strip; 00589 00590 for (strip= strips->first; strip; strip= strip->next) { 00591 /* write the strip first */ 00592 writestruct(wd, DATA, "NlaStrip", 1, strip); 00593 00594 /* write the strip's F-Curves and modifiers */ 00595 write_fcurves(wd, &strip->fcurves); 00596 write_fmodifiers(wd, &strip->modifiers); 00597 00598 /* write the strip's children */ 00599 write_nlastrips(wd, &strip->strips); 00600 } 00601 } 00602 00603 static void write_nladata(WriteData *wd, ListBase *nlabase) 00604 { 00605 NlaTrack *nlt; 00606 00607 /* write all the tracks */ 00608 for (nlt= nlabase->first; nlt; nlt= nlt->next) { 00609 /* write the track first */ 00610 writestruct(wd, DATA, "NlaTrack", 1, nlt); 00611 00612 /* write the track's strips */ 00613 write_nlastrips(wd, &nlt->strips); 00614 } 00615 } 00616 00617 static void write_animdata(WriteData *wd, AnimData *adt) 00618 { 00619 AnimOverride *aor; 00620 00621 /* firstly, just write the AnimData block */ 00622 writestruct(wd, DATA, "AnimData", 1, adt); 00623 00624 /* write drivers */ 00625 write_fcurves(wd, &adt->drivers); 00626 00627 /* write overrides */ 00628 // FIXME: are these needed? 00629 for (aor= adt->overrides.first; aor; aor= aor->next) { 00630 /* overrides consist of base data + rna_path */ 00631 writestruct(wd, DATA, "AnimOverride", 1, aor); 00632 writedata(wd, DATA, strlen(aor->rna_path)+1, aor->rna_path); 00633 } 00634 00635 // TODO write the remaps (if they are needed) 00636 00637 /* write NLA data */ 00638 write_nladata(wd, &adt->nla_tracks); 00639 } 00640 00641 static void write_curvemapping(WriteData *wd, CurveMapping *cumap) 00642 { 00643 int a; 00644 00645 writestruct(wd, DATA, "CurveMapping", 1, cumap); 00646 for(a=0; a<CM_TOT; a++) 00647 writestruct(wd, DATA, "CurveMapPoint", cumap->cm[a].totpoint, cumap->cm[a].curve); 00648 } 00649 00650 static void write_node_socket(WriteData *wd, bNodeSocket *sock) 00651 { 00652 bNodeSocketType *stype= ntreeGetSocketType(sock->type); 00653 00654 /* forward compatibility code, so older blenders still open */ 00655 sock->stack_type = 1; 00656 00657 if(sock->default_value) { 00658 bNodeSocketValueFloat *valfloat; 00659 bNodeSocketValueVector *valvector; 00660 bNodeSocketValueRGBA *valrgba; 00661 00662 switch (sock->type) { 00663 case SOCK_FLOAT: 00664 valfloat = sock->default_value; 00665 sock->ns.vec[0] = valfloat->value; 00666 sock->ns.min = valfloat->min; 00667 sock->ns.max = valfloat->max; 00668 break; 00669 case SOCK_VECTOR: 00670 valvector = sock->default_value; 00671 copy_v3_v3(sock->ns.vec, valvector->value); 00672 sock->ns.min = valvector->min; 00673 sock->ns.max = valvector->max; 00674 break; 00675 case SOCK_RGBA: 00676 valrgba = sock->default_value; 00677 copy_v4_v4(sock->ns.vec, valrgba->value); 00678 sock->ns.min = 0.0f; 00679 sock->ns.max = 1.0f; 00680 break; 00681 } 00682 } 00683 00684 /* actual socket writing */ 00685 writestruct(wd, DATA, "bNodeSocket", 1, sock); 00686 if (sock->default_value) 00687 writestruct(wd, DATA, stype->value_structname, 1, sock->default_value); 00688 } 00689 00690 /* this is only direct data, tree itself should have been written */ 00691 static void write_nodetree(WriteData *wd, bNodeTree *ntree) 00692 { 00693 bNode *node; 00694 bNodeSocket *sock; 00695 bNodeLink *link; 00696 00697 /* for link_list() speed, we write per list */ 00698 00699 if(ntree->adt) write_animdata(wd, ntree->adt); 00700 00701 for(node= ntree->nodes.first; node; node= node->next) 00702 writestruct(wd, DATA, "bNode", 1, node); 00703 00704 for(node= ntree->nodes.first; node; node= node->next) { 00705 for(sock= node->inputs.first; sock; sock= sock->next) 00706 write_node_socket(wd, sock); 00707 for(sock= node->outputs.first; sock; sock= sock->next) 00708 write_node_socket(wd, sock); 00709 00710 00711 if(node->storage && node->type!=NODE_DYNAMIC) { 00712 /* could be handlerized at some point, now only 1 exception still */ 00713 if(ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB)) 00714 write_curvemapping(wd, node->storage); 00715 else if(ntree->type==NTREE_COMPOSIT && ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) 00716 write_curvemapping(wd, node->storage); 00717 else if(ntree->type==NTREE_TEXTURE && (node->type==TEX_NODE_CURVE_RGB || node->type==TEX_NODE_CURVE_TIME) ) 00718 write_curvemapping(wd, node->storage); 00719 else if(ntree->type==NTREE_COMPOSIT && node->type==CMP_NODE_MOVIEDISTORTION) 00720 /* pass */ ; 00721 else 00722 writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage); 00723 } 00724 } 00725 00726 for(link= ntree->links.first; link; link= link->next) 00727 writestruct(wd, DATA, "bNodeLink", 1, link); 00728 00729 /* external sockets */ 00730 for(sock= ntree->inputs.first; sock; sock= sock->next) 00731 write_node_socket(wd, sock); 00732 for(sock= ntree->outputs.first; sock; sock= sock->next) 00733 write_node_socket(wd, sock); 00734 } 00735 00736 static void current_screen_compat(Main *mainvar, bScreen **screen) 00737 { 00738 wmWindowManager *wm; 00739 wmWindow *window; 00740 00741 /* find a global current screen in the first open window, to have 00742 * a reasonable default for reading in older versions */ 00743 wm= mainvar->wm.first; 00744 window= (wm)? wm->windows.first: NULL; 00745 *screen= (window)? window->screen: NULL; 00746 } 00747 00748 static void write_renderinfo(WriteData *wd, Main *mainvar) /* for renderdeamon */ 00749 { 00750 bScreen *curscreen; 00751 Scene *sce; 00752 int data[8]; 00753 00754 /* XXX in future, handle multiple windows with multiple screnes? */ 00755 current_screen_compat(mainvar, &curscreen); 00756 00757 for(sce= mainvar->scene.first; sce; sce= sce->id.next) { 00758 if(sce->id.lib==NULL && ( sce==curscreen->scene || (sce->r.scemode & R_BG_RENDER)) ) { 00759 data[0]= sce->r.sfra; 00760 data[1]= sce->r.efra; 00761 00762 memset(data+2, 0, sizeof(int)*6); 00763 BLI_strncpy((char *)(data+2), sce->id.name+2, sizeof(sce->id.name)-2); 00764 00765 writedata(wd, REND, 32, data); 00766 } 00767 } 00768 } 00769 00770 static void write_keymapitem(WriteData *wd, wmKeyMapItem *kmi) 00771 { 00772 writestruct(wd, DATA, "wmKeyMapItem", 1, kmi); 00773 if(kmi->properties) 00774 IDP_WriteProperty(kmi->properties, wd); 00775 } 00776 00777 static void write_userdef(WriteData *wd) 00778 { 00779 bTheme *btheme; 00780 wmKeyMap *keymap; 00781 wmKeyMapItem *kmi; 00782 wmKeyMapDiffItem *kmdi; 00783 bAddon *bext; 00784 uiStyle *style; 00785 00786 writestruct(wd, USER, "UserDef", 1, &U); 00787 00788 for(btheme= U.themes.first; btheme; btheme=btheme->next) 00789 writestruct(wd, DATA, "bTheme", 1, btheme); 00790 00791 for(keymap= U.user_keymaps.first; keymap; keymap=keymap->next) { 00792 writestruct(wd, DATA, "wmKeyMap", 1, keymap); 00793 00794 for(kmdi=keymap->diff_items.first; kmdi; kmdi=kmdi->next) { 00795 writestruct(wd, DATA, "wmKeyMapDiffItem", 1, kmdi); 00796 if(kmdi->remove_item) 00797 write_keymapitem(wd, kmdi->remove_item); 00798 if(kmdi->add_item) 00799 write_keymapitem(wd, kmdi->add_item); 00800 } 00801 00802 for(kmi=keymap->items.first; kmi; kmi=kmi->next) 00803 write_keymapitem(wd, kmi); 00804 } 00805 00806 for(bext= U.addons.first; bext; bext=bext->next) 00807 writestruct(wd, DATA, "bAddon", 1, bext); 00808 00809 for(style= U.uistyles.first; style; style= style->next) { 00810 writestruct(wd, DATA, "uiStyle", 1, style); 00811 } 00812 } 00813 00814 static void write_boid_state(WriteData *wd, BoidState *state) 00815 { 00816 BoidRule *rule = state->rules.first; 00817 //BoidCondition *cond = state->conditions.first; 00818 00819 writestruct(wd, DATA, "BoidState", 1, state); 00820 00821 for(; rule; rule=rule->next) { 00822 switch(rule->type) { 00823 case eBoidRuleType_Goal: 00824 case eBoidRuleType_Avoid: 00825 writestruct(wd, DATA, "BoidRuleGoalAvoid", 1, rule); 00826 break; 00827 case eBoidRuleType_AvoidCollision: 00828 writestruct(wd, DATA, "BoidRuleAvoidCollision", 1, rule); 00829 break; 00830 case eBoidRuleType_FollowLeader: 00831 writestruct(wd, DATA, "BoidRuleFollowLeader", 1, rule); 00832 break; 00833 case eBoidRuleType_AverageSpeed: 00834 writestruct(wd, DATA, "BoidRuleAverageSpeed", 1, rule); 00835 break; 00836 case eBoidRuleType_Fight: 00837 writestruct(wd, DATA, "BoidRuleFight", 1, rule); 00838 break; 00839 default: 00840 writestruct(wd, DATA, "BoidRule", 1, rule); 00841 break; 00842 } 00843 } 00844 //for(; cond; cond=cond->next) 00845 // writestruct(wd, DATA, "BoidCondition", 1, cond); 00846 } 00847 00848 /* update this also to readfile.c */ 00849 static const char *ptcache_data_struct[] = { 00850 "", // BPHYS_DATA_INDEX 00851 "", // BPHYS_DATA_LOCATION 00852 "", // BPHYS_DATA_VELOCITY 00853 "", // BPHYS_DATA_ROTATION 00854 "", // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST */ 00855 "", // BPHYS_DATA_SIZE: 00856 "", // BPHYS_DATA_TIMES: 00857 "BoidData" // case BPHYS_DATA_BOIDS: 00858 }; 00859 static const char *ptcache_extra_struct[] = { 00860 "", 00861 "ParticleSpring" 00862 }; 00863 static void write_pointcaches(WriteData *wd, ListBase *ptcaches) 00864 { 00865 PointCache *cache = ptcaches->first; 00866 int i; 00867 00868 for(; cache; cache=cache->next) { 00869 writestruct(wd, DATA, "PointCache", 1, cache); 00870 00871 if((cache->flag & PTCACHE_DISK_CACHE)==0) { 00872 PTCacheMem *pm = cache->mem_cache.first; 00873 00874 for(; pm; pm=pm->next) { 00875 PTCacheExtra *extra = pm->extradata.first; 00876 00877 writestruct(wd, DATA, "PTCacheMem", 1, pm); 00878 00879 for(i=0; i<BPHYS_TOT_DATA; i++) { 00880 if(pm->data[i] && pm->data_types & (1<<i)) { 00881 if(ptcache_data_struct[i][0]=='\0') 00882 writedata(wd, DATA, MEM_allocN_len(pm->data[i]), pm->data[i]); 00883 else 00884 writestruct(wd, DATA, ptcache_data_struct[i], pm->totpoint, pm->data[i]); 00885 } 00886 } 00887 00888 for(; extra; extra=extra->next) { 00889 if(ptcache_extra_struct[extra->type][0]=='\0') 00890 continue; 00891 writestruct(wd, DATA, "PTCacheExtra", 1, extra); 00892 writestruct(wd, DATA, ptcache_extra_struct[extra->type], extra->totdata, extra->data); 00893 } 00894 } 00895 } 00896 } 00897 } 00898 static void write_particlesettings(WriteData *wd, ListBase *idbase) 00899 { 00900 ParticleSettings *part; 00901 ParticleDupliWeight *dw; 00902 GroupObject *go; 00903 int a; 00904 00905 part= idbase->first; 00906 while(part) { 00907 if(part->id.us>0 || wd->current) { 00908 /* write LibData */ 00909 writestruct(wd, ID_PA, "ParticleSettings", 1, part); 00910 if (part->id.properties) IDP_WriteProperty(part->id.properties, wd); 00911 if (part->adt) write_animdata(wd, part->adt); 00912 writestruct(wd, DATA, "PartDeflect", 1, part->pd); 00913 writestruct(wd, DATA, "PartDeflect", 1, part->pd2); 00914 writestruct(wd, DATA, "EffectorWeights", 1, part->effector_weights); 00915 00916 dw = part->dupliweights.first; 00917 for(; dw; dw=dw->next) { 00918 /* update indices */ 00919 dw->index = 0; 00920 if(part->dup_group) { /* can be NULL if lining fails or set to None */ 00921 go = part->dup_group->gobject.first; 00922 while(go && go->ob != dw->ob) { 00923 go=go->next; 00924 dw->index++; 00925 } 00926 } 00927 writestruct(wd, DATA, "ParticleDupliWeight", 1, dw); 00928 } 00929 00930 if(part->boids && part->phystype == PART_PHYS_BOIDS) { 00931 BoidState *state = part->boids->states.first; 00932 00933 writestruct(wd, DATA, "BoidSettings", 1, part->boids); 00934 00935 for(; state; state=state->next) 00936 write_boid_state(wd, state); 00937 } 00938 if(part->fluid && part->phystype == PART_PHYS_FLUID){ 00939 writestruct(wd, DATA, "SPHFluidSettings", 1, part->fluid); 00940 } 00941 00942 for(a=0; a<MAX_MTEX; a++) { 00943 if(part->mtex[a]) writestruct(wd, DATA, "MTex", 1, part->mtex[a]); 00944 } 00945 } 00946 part= part->id.next; 00947 } 00948 } 00949 static void write_particlesystems(WriteData *wd, ListBase *particles) 00950 { 00951 ParticleSystem *psys= particles->first; 00952 ParticleTarget *pt; 00953 int a; 00954 00955 for(; psys; psys=psys->next) { 00956 writestruct(wd, DATA, "ParticleSystem", 1, psys); 00957 00958 if(psys->particles) { 00959 writestruct(wd, DATA, "ParticleData", psys->totpart ,psys->particles); 00960 00961 if(psys->particles->hair) { 00962 ParticleData *pa = psys->particles; 00963 00964 for(a=0; a<psys->totpart; a++, pa++) 00965 writestruct(wd, DATA, "HairKey", pa->totkey, pa->hair); 00966 } 00967 00968 if(psys->particles->boid && psys->part->phystype == PART_PHYS_BOIDS) 00969 writestruct(wd, DATA, "BoidParticle", psys->totpart, psys->particles->boid); 00970 00971 if(psys->part->fluid && psys->part->phystype == PART_PHYS_FLUID && (psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS)) 00972 writestruct(wd, DATA, "ParticleSpring", psys->tot_fluidsprings, psys->fluid_springs); 00973 } 00974 pt = psys->targets.first; 00975 for(; pt; pt=pt->next) 00976 writestruct(wd, DATA, "ParticleTarget", 1, pt); 00977 00978 if(psys->child) writestruct(wd, DATA, "ChildParticle", psys->totchild ,psys->child); 00979 00980 if(psys->clmd) { 00981 writestruct(wd, DATA, "ClothModifierData", 1, psys->clmd); 00982 writestruct(wd, DATA, "ClothSimSettings", 1, psys->clmd->sim_parms); 00983 writestruct(wd, DATA, "ClothCollSettings", 1, psys->clmd->coll_parms); 00984 } 00985 00986 write_pointcaches(wd, &psys->ptcaches); 00987 } 00988 } 00989 00990 static void write_properties(WriteData *wd, ListBase *lb) 00991 { 00992 bProperty *prop; 00993 00994 prop= lb->first; 00995 while(prop) { 00996 writestruct(wd, DATA, "bProperty", 1, prop); 00997 00998 if(prop->poin && prop->poin != &prop->data) 00999 writedata(wd, DATA, MEM_allocN_len(prop->poin), prop->poin); 01000 01001 prop= prop->next; 01002 } 01003 } 01004 01005 static void write_sensors(WriteData *wd, ListBase *lb) 01006 { 01007 bSensor *sens; 01008 01009 sens= lb->first; 01010 while(sens) { 01011 writestruct(wd, DATA, "bSensor", 1, sens); 01012 01013 writedata(wd, DATA, sizeof(void *)*sens->totlinks, sens->links); 01014 01015 switch(sens->type) { 01016 case SENS_NEAR: 01017 writestruct(wd, DATA, "bNearSensor", 1, sens->data); 01018 break; 01019 case SENS_MOUSE: 01020 writestruct(wd, DATA, "bMouseSensor", 1, sens->data); 01021 break; 01022 case SENS_TOUCH: 01023 writestruct(wd, DATA, "bTouchSensor", 1, sens->data); 01024 break; 01025 case SENS_KEYBOARD: 01026 writestruct(wd, DATA, "bKeyboardSensor", 1, sens->data); 01027 break; 01028 case SENS_PROPERTY: 01029 writestruct(wd, DATA, "bPropertySensor", 1, sens->data); 01030 break; 01031 case SENS_ARMATURE: 01032 writestruct(wd, DATA, "bArmatureSensor", 1, sens->data); 01033 break; 01034 case SENS_ACTUATOR: 01035 writestruct(wd, DATA, "bActuatorSensor", 1, sens->data); 01036 break; 01037 case SENS_DELAY: 01038 writestruct(wd, DATA, "bDelaySensor", 1, sens->data); 01039 break; 01040 case SENS_COLLISION: 01041 writestruct(wd, DATA, "bCollisionSensor", 1, sens->data); 01042 break; 01043 case SENS_RADAR: 01044 writestruct(wd, DATA, "bRadarSensor", 1, sens->data); 01045 break; 01046 case SENS_RANDOM: 01047 writestruct(wd, DATA, "bRandomSensor", 1, sens->data); 01048 break; 01049 case SENS_RAY: 01050 writestruct(wd, DATA, "bRaySensor", 1, sens->data); 01051 break; 01052 case SENS_MESSAGE: 01053 writestruct(wd, DATA, "bMessageSensor", 1, sens->data); 01054 break; 01055 case SENS_JOYSTICK: 01056 writestruct(wd, DATA, "bJoystickSensor", 1, sens->data); 01057 break; 01058 default: 01059 ; /* error: don't know how to write this file */ 01060 } 01061 01062 sens= sens->next; 01063 } 01064 } 01065 01066 static void write_controllers(WriteData *wd, ListBase *lb) 01067 { 01068 bController *cont; 01069 01070 cont= lb->first; 01071 while(cont) { 01072 writestruct(wd, DATA, "bController", 1, cont); 01073 01074 writedata(wd, DATA, sizeof(void *)*cont->totlinks, cont->links); 01075 01076 switch(cont->type) { 01077 case CONT_EXPRESSION: 01078 writestruct(wd, DATA, "bExpressionCont", 1, cont->data); 01079 break; 01080 case CONT_PYTHON: 01081 writestruct(wd, DATA, "bPythonCont", 1, cont->data); 01082 break; 01083 default: 01084 ; /* error: don't know how to write this file */ 01085 } 01086 01087 cont= cont->next; 01088 } 01089 } 01090 01091 static void write_actuators(WriteData *wd, ListBase *lb) 01092 { 01093 bActuator *act; 01094 01095 act= lb->first; 01096 while(act) { 01097 writestruct(wd, DATA, "bActuator", 1, act); 01098 01099 switch(act->type) { 01100 case ACT_ACTION: 01101 case ACT_SHAPEACTION: 01102 writestruct(wd, DATA, "bActionActuator", 1, act->data); 01103 break; 01104 case ACT_SOUND: 01105 writestruct(wd, DATA, "bSoundActuator", 1, act->data); 01106 break; 01107 case ACT_OBJECT: 01108 writestruct(wd, DATA, "bObjectActuator", 1, act->data); 01109 break; 01110 case ACT_IPO: 01111 writestruct(wd, DATA, "bIpoActuator", 1, act->data); 01112 break; 01113 case ACT_PROPERTY: 01114 writestruct(wd, DATA, "bPropertyActuator", 1, act->data); 01115 break; 01116 case ACT_CAMERA: 01117 writestruct(wd, DATA, "bCameraActuator", 1, act->data); 01118 break; 01119 case ACT_CONSTRAINT: 01120 writestruct(wd, DATA, "bConstraintActuator", 1, act->data); 01121 break; 01122 case ACT_EDIT_OBJECT: 01123 writestruct(wd, DATA, "bEditObjectActuator", 1, act->data); 01124 break; 01125 case ACT_SCENE: 01126 writestruct(wd, DATA, "bSceneActuator", 1, act->data); 01127 break; 01128 case ACT_GROUP: 01129 writestruct(wd, DATA, "bGroupActuator", 1, act->data); 01130 break; 01131 case ACT_RANDOM: 01132 writestruct(wd, DATA, "bRandomActuator", 1, act->data); 01133 break; 01134 case ACT_MESSAGE: 01135 writestruct(wd, DATA, "bMessageActuator", 1, act->data); 01136 break; 01137 case ACT_GAME: 01138 writestruct(wd, DATA, "bGameActuator", 1, act->data); 01139 break; 01140 case ACT_VISIBILITY: 01141 writestruct(wd, DATA, "bVisibilityActuator", 1, act->data); 01142 break; 01143 case ACT_2DFILTER: 01144 writestruct(wd, DATA, "bTwoDFilterActuator", 1, act->data); 01145 break; 01146 case ACT_PARENT: 01147 writestruct(wd, DATA, "bParentActuator", 1, act->data); 01148 break; 01149 case ACT_STATE: 01150 writestruct(wd, DATA, "bStateActuator", 1, act->data); 01151 break; 01152 case ACT_ARMATURE: 01153 writestruct(wd, DATA, "bArmatureActuator", 1, act->data); 01154 break; 01155 case ACT_STEERING: 01156 writestruct(wd, DATA, "bSteeringActuator", 1, act->data); 01157 break; 01158 default: 01159 ; /* error: don't know how to write this file */ 01160 } 01161 01162 act= act->next; 01163 } 01164 } 01165 01166 static void write_motionpath(WriteData *wd, bMotionPath *mpath) 01167 { 01168 /* sanity checks */ 01169 if (mpath == NULL) 01170 return; 01171 01172 /* firstly, just write the motionpath struct */ 01173 writestruct(wd, DATA, "bMotionPath", 1, mpath); 01174 01175 /* now write the array of data */ 01176 writestruct(wd, DATA, "bMotionPathVert", mpath->length, mpath->points); 01177 } 01178 01179 static void write_constraints(WriteData *wd, ListBase *conlist) 01180 { 01181 bConstraint *con; 01182 01183 for (con=conlist->first; con; con=con->next) { 01184 bConstraintTypeInfo *cti= constraint_get_typeinfo(con); 01185 01186 /* Write the specific data */ 01187 if (cti && con->data) { 01188 /* firstly, just write the plain con->data struct */ 01189 writestruct(wd, DATA, cti->structName, 1, con->data); 01190 01191 /* do any constraint specific stuff */ 01192 switch (con->type) { 01193 case CONSTRAINT_TYPE_PYTHON: 01194 { 01195 bPythonConstraint *data = (bPythonConstraint *)con->data; 01196 bConstraintTarget *ct; 01197 01198 /* write targets */ 01199 for (ct= data->targets.first; ct; ct= ct->next) 01200 writestruct(wd, DATA, "bConstraintTarget", 1, ct); 01201 01202 /* Write ID Properties -- and copy this comment EXACTLY for easy finding 01203 of library blocks that implement this.*/ 01204 IDP_WriteProperty(data->prop, wd); 01205 } 01206 break; 01207 case CONSTRAINT_TYPE_SPLINEIK: 01208 { 01209 bSplineIKConstraint *data= (bSplineIKConstraint*)con->data; 01210 01211 /* write points array */ 01212 writedata(wd, DATA, sizeof(float)*(data->numpoints), data->points); 01213 } 01214 break; 01215 } 01216 } 01217 01218 /* Write the constraint */ 01219 writestruct(wd, DATA, "bConstraint", 1, con); 01220 } 01221 } 01222 01223 static void write_pose(WriteData *wd, bPose *pose) 01224 { 01225 bPoseChannel *chan; 01226 bActionGroup *grp; 01227 01228 /* Write each channel */ 01229 if (!pose) 01230 return; 01231 01232 /* Write channels */ 01233 for (chan=pose->chanbase.first; chan; chan=chan->next) { 01234 /* Write ID Properties -- and copy this comment EXACTLY for easy finding 01235 of library blocks that implement this.*/ 01236 if (chan->prop) 01237 IDP_WriteProperty(chan->prop, wd); 01238 01239 write_constraints(wd, &chan->constraints); 01240 01241 write_motionpath(wd, chan->mpath); 01242 01243 /* prevent crashes with autosave, when a bone duplicated in editmode has not yet been assigned to its posechannel */ 01244 if (chan->bone) 01245 chan->selectflag= chan->bone->flag & BONE_SELECTED; /* gets restored on read, for library armatures */ 01246 01247 writestruct(wd, DATA, "bPoseChannel", 1, chan); 01248 } 01249 01250 /* Write groups */ 01251 for (grp=pose->agroups.first; grp; grp=grp->next) 01252 writestruct(wd, DATA, "bActionGroup", 1, grp); 01253 01254 /* write IK param */ 01255 if (pose->ikparam) { 01256 char *structname = (char *)get_ikparam_name(pose); 01257 if (structname) 01258 writestruct(wd, DATA, structname, 1, pose->ikparam); 01259 } 01260 01261 /* Write this pose */ 01262 writestruct(wd, DATA, "bPose", 1, pose); 01263 01264 } 01265 01266 static void write_defgroups(WriteData *wd, ListBase *defbase) 01267 { 01268 bDeformGroup *defgroup; 01269 01270 for (defgroup=defbase->first; defgroup; defgroup=defgroup->next) 01271 writestruct(wd, DATA, "bDeformGroup", 1, defgroup); 01272 } 01273 01274 static void write_modifiers(WriteData *wd, ListBase *modbase) 01275 { 01276 ModifierData *md; 01277 01278 if (modbase == NULL) return; 01279 for (md=modbase->first; md; md= md->next) { 01280 ModifierTypeInfo *mti = modifierType_getInfo(md->type); 01281 if (mti == NULL) return; 01282 01283 writestruct(wd, DATA, mti->structName, 1, md); 01284 01285 if (md->type==eModifierType_Hook) { 01286 HookModifierData *hmd = (HookModifierData*) md; 01287 01288 writedata(wd, DATA, sizeof(int)*hmd->totindex, hmd->indexar); 01289 } 01290 else if(md->type==eModifierType_Cloth) { 01291 ClothModifierData *clmd = (ClothModifierData*) md; 01292 01293 writestruct(wd, DATA, "ClothSimSettings", 1, clmd->sim_parms); 01294 writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms); 01295 writestruct(wd, DATA, "EffectorWeights", 1, clmd->sim_parms->effector_weights); 01296 write_pointcaches(wd, &clmd->ptcaches); 01297 } 01298 else if(md->type==eModifierType_Smoke) { 01299 SmokeModifierData *smd = (SmokeModifierData*) md; 01300 01301 if(smd->type & MOD_SMOKE_TYPE_DOMAIN) 01302 { 01303 if(smd->domain) 01304 { 01305 write_pointcaches(wd, &(smd->domain->ptcaches[0])); 01306 01307 /* create fake pointcache so that old blender versions can read it */ 01308 smd->domain->point_cache[1] = BKE_ptcache_add(&smd->domain->ptcaches[1]); 01309 smd->domain->point_cache[1]->flag |= PTCACHE_DISK_CACHE|PTCACHE_FAKE_SMOKE; 01310 smd->domain->point_cache[1]->step = 1; 01311 01312 write_pointcaches(wd, &(smd->domain->ptcaches[1])); 01313 } 01314 01315 writestruct(wd, DATA, "SmokeDomainSettings", 1, smd->domain); 01316 01317 if(smd->domain) { 01318 /* cleanup the fake pointcache */ 01319 BKE_ptcache_free_list(&smd->domain->ptcaches[1]); 01320 smd->domain->point_cache[1] = NULL; 01321 01322 writestruct(wd, DATA, "EffectorWeights", 1, smd->domain->effector_weights); 01323 } 01324 } 01325 else if(smd->type & MOD_SMOKE_TYPE_FLOW) 01326 writestruct(wd, DATA, "SmokeFlowSettings", 1, smd->flow); 01327 else if(smd->type & MOD_SMOKE_TYPE_COLL) 01328 writestruct(wd, DATA, "SmokeCollSettings", 1, smd->coll); 01329 } 01330 else if(md->type==eModifierType_Fluidsim) { 01331 FluidsimModifierData *fluidmd = (FluidsimModifierData*) md; 01332 01333 writestruct(wd, DATA, "FluidsimSettings", 1, fluidmd->fss); 01334 } 01335 else if(md->type==eModifierType_DynamicPaint) { 01336 DynamicPaintModifierData *pmd = (DynamicPaintModifierData*) md; 01337 01338 if(pmd->canvas) 01339 { 01340 DynamicPaintSurface *surface; 01341 writestruct(wd, DATA, "DynamicPaintCanvasSettings", 1, pmd->canvas); 01342 01343 /* write surfaces */ 01344 for (surface=pmd->canvas->surfaces.first; surface; surface=surface->next) 01345 writestruct(wd, DATA, "DynamicPaintSurface", 1, surface); 01346 /* write caches and effector weights */ 01347 for (surface=pmd->canvas->surfaces.first; surface; surface=surface->next) { 01348 write_pointcaches(wd, &(surface->ptcaches)); 01349 01350 writestruct(wd, DATA, "EffectorWeights", 1, surface->effector_weights); 01351 } 01352 } 01353 if(pmd->brush) 01354 { 01355 writestruct(wd, DATA, "DynamicPaintBrushSettings", 1, pmd->brush); 01356 writestruct(wd, DATA, "ColorBand", 1, pmd->brush->paint_ramp); 01357 writestruct(wd, DATA, "ColorBand", 1, pmd->brush->vel_ramp); 01358 } 01359 } 01360 else if (md->type==eModifierType_Collision) { 01361 01362 /* 01363 CollisionModifierData *collmd = (CollisionModifierData*) md; 01364 // TODO: CollisionModifier should use pointcache 01365 // + have proper reset events before enabling this 01366 writestruct(wd, DATA, "MVert", collmd->numverts, collmd->x); 01367 writestruct(wd, DATA, "MVert", collmd->numverts, collmd->xnew); 01368 writestruct(wd, DATA, "MFace", collmd->numfaces, collmd->mfaces); 01369 */ 01370 } 01371 else if (md->type==eModifierType_MeshDeform) { 01372 MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; 01373 int size = mmd->dyngridsize; 01374 01375 writestruct(wd, DATA, "MDefInfluence", mmd->totinfluence, mmd->bindinfluences); 01376 writedata(wd, DATA, sizeof(int)*(mmd->totvert+1), mmd->bindoffsets); 01377 writedata(wd, DATA, sizeof(float)*3*mmd->totcagevert, 01378 mmd->bindcagecos); 01379 writestruct(wd, DATA, "MDefCell", size*size*size, mmd->dyngrid); 01380 writestruct(wd, DATA, "MDefInfluence", mmd->totinfluence, mmd->dyninfluences); 01381 writedata(wd, DATA, sizeof(int)*mmd->totvert, mmd->dynverts); 01382 } 01383 else if (md->type==eModifierType_Warp) { 01384 WarpModifierData *tmd = (WarpModifierData*) md; 01385 if(tmd->curfalloff) { 01386 write_curvemapping(wd, tmd->curfalloff); 01387 } 01388 } 01389 else if (md->type==eModifierType_WeightVGEdit) { 01390 WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md; 01391 01392 if (wmd->cmap_curve) 01393 write_curvemapping(wd, wmd->cmap_curve); 01394 } 01395 } 01396 } 01397 01398 static void write_objects(WriteData *wd, ListBase *idbase) 01399 { 01400 Object *ob; 01401 01402 ob= idbase->first; 01403 while(ob) { 01404 if(ob->id.us>0 || wd->current) { 01405 /* write LibData */ 01406 writestruct(wd, ID_OB, "Object", 1, ob); 01407 01408 /*Write ID Properties -- and copy this comment EXACTLY for easy finding 01409 of library blocks that implement this.*/ 01410 if (ob->id.properties) IDP_WriteProperty(ob->id.properties, wd); 01411 01412 if (ob->adt) write_animdata(wd, ob->adt); 01413 01414 /* direct data */ 01415 writedata(wd, DATA, sizeof(void *)*ob->totcol, ob->mat); 01416 writedata(wd, DATA, sizeof(char)*ob->totcol, ob->matbits); 01417 /* write_effects(wd, &ob->effect); */ /* not used anymore */ 01418 write_properties(wd, &ob->prop); 01419 write_sensors(wd, &ob->sensors); 01420 write_controllers(wd, &ob->controllers); 01421 write_actuators(wd, &ob->actuators); 01422 01423 if (ob->type == OB_ARMATURE) { 01424 bArmature *arm = ob->data; 01425 if (arm && ob->pose && arm->act_bone) { 01426 BLI_strncpy(ob->pose->proxy_act_bone, arm->act_bone->name, sizeof(ob->pose->proxy_act_bone)); 01427 } 01428 } 01429 01430 write_pose(wd, ob->pose); 01431 write_defgroups(wd, &ob->defbase); 01432 write_constraints(wd, &ob->constraints); 01433 write_motionpath(wd, ob->mpath); 01434 01435 writestruct(wd, DATA, "PartDeflect", 1, ob->pd); 01436 writestruct(wd, DATA, "SoftBody", 1, ob->soft); 01437 if(ob->soft) { 01438 write_pointcaches(wd, &ob->soft->ptcaches); 01439 writestruct(wd, DATA, "EffectorWeights", 1, ob->soft->effector_weights); 01440 } 01441 writestruct(wd, DATA, "BulletSoftBody", 1, ob->bsoft); 01442 01443 write_particlesystems(wd, &ob->particlesystem); 01444 write_modifiers(wd, &ob->modifiers); 01445 } 01446 ob= ob->id.next; 01447 } 01448 01449 /* flush helps the compression for undo-save */ 01450 mywrite(wd, MYWRITE_FLUSH, 0); 01451 } 01452 01453 01454 static void write_vfonts(WriteData *wd, ListBase *idbase) 01455 { 01456 VFont *vf; 01457 PackedFile * pf; 01458 01459 vf= idbase->first; 01460 while(vf) { 01461 if(vf->id.us>0 || wd->current) { 01462 /* write LibData */ 01463 writestruct(wd, ID_VF, "VFont", 1, vf); 01464 if (vf->id.properties) IDP_WriteProperty(vf->id.properties, wd); 01465 01466 /* direct data */ 01467 01468 if (vf->packedfile) { 01469 pf = vf->packedfile; 01470 writestruct(wd, DATA, "PackedFile", 1, pf); 01471 writedata(wd, DATA, pf->size, pf->data); 01472 } 01473 } 01474 01475 vf= vf->id.next; 01476 } 01477 } 01478 01479 01480 static void write_keys(WriteData *wd, ListBase *idbase) 01481 { 01482 Key *key; 01483 KeyBlock *kb; 01484 01485 key= idbase->first; 01486 while(key) { 01487 if(key->id.us>0 || wd->current) { 01488 /* write LibData */ 01489 writestruct(wd, ID_KE, "Key", 1, key); 01490 if (key->id.properties) IDP_WriteProperty(key->id.properties, wd); 01491 01492 if (key->adt) write_animdata(wd, key->adt); 01493 01494 /* direct data */ 01495 kb= key->block.first; 01496 while(kb) { 01497 writestruct(wd, DATA, "KeyBlock", 1, kb); 01498 if(kb->data) writedata(wd, DATA, kb->totelem*key->elemsize, kb->data); 01499 kb= kb->next; 01500 } 01501 } 01502 01503 key= key->id.next; 01504 } 01505 /* flush helps the compression for undo-save */ 01506 mywrite(wd, MYWRITE_FLUSH, 0); 01507 } 01508 01509 static void write_cameras(WriteData *wd, ListBase *idbase) 01510 { 01511 Camera *cam; 01512 01513 cam= idbase->first; 01514 while(cam) { 01515 if(cam->id.us>0 || wd->current) { 01516 /* write LibData */ 01517 writestruct(wd, ID_CA, "Camera", 1, cam); 01518 if (cam->id.properties) IDP_WriteProperty(cam->id.properties, wd); 01519 01520 if (cam->adt) write_animdata(wd, cam->adt); 01521 } 01522 01523 cam= cam->id.next; 01524 } 01525 } 01526 01527 static void write_mballs(WriteData *wd, ListBase *idbase) 01528 { 01529 MetaBall *mb; 01530 MetaElem *ml; 01531 01532 mb= idbase->first; 01533 while(mb) { 01534 if(mb->id.us>0 || wd->current) { 01535 /* write LibData */ 01536 writestruct(wd, ID_MB, "MetaBall", 1, mb); 01537 if (mb->id.properties) IDP_WriteProperty(mb->id.properties, wd); 01538 01539 /* direct data */ 01540 writedata(wd, DATA, sizeof(void *)*mb->totcol, mb->mat); 01541 if (mb->adt) write_animdata(wd, mb->adt); 01542 01543 ml= mb->elems.first; 01544 while(ml) { 01545 writestruct(wd, DATA, "MetaElem", 1, ml); 01546 ml= ml->next; 01547 } 01548 } 01549 mb= mb->id.next; 01550 } 01551 } 01552 01553 static int amount_of_chars(char *str) 01554 { 01555 // Since the data is saved as UTF-8 to the cu->str 01556 // The cu->len is not same as the strlen(cu->str) 01557 return strlen(str); 01558 } 01559 01560 static void write_curves(WriteData *wd, ListBase *idbase) 01561 { 01562 Curve *cu; 01563 Nurb *nu; 01564 01565 cu= idbase->first; 01566 while(cu) { 01567 if(cu->id.us>0 || wd->current) { 01568 /* write LibData */ 01569 writestruct(wd, ID_CU, "Curve", 1, cu); 01570 01571 /* direct data */ 01572 writedata(wd, DATA, sizeof(void *)*cu->totcol, cu->mat); 01573 if (cu->id.properties) IDP_WriteProperty(cu->id.properties, wd); 01574 if (cu->adt) write_animdata(wd, cu->adt); 01575 01576 if(cu->vfont) { 01577 writedata(wd, DATA, amount_of_chars(cu->str)+1, cu->str); 01578 writestruct(wd, DATA, "CharInfo", cu->len+1, cu->strinfo); 01579 writestruct(wd, DATA, "TextBox", cu->totbox, cu->tb); 01580 } 01581 else { 01582 /* is also the order of reading */ 01583 nu= cu->nurb.first; 01584 while(nu) { 01585 writestruct(wd, DATA, "Nurb", 1, nu); 01586 nu= nu->next; 01587 } 01588 nu= cu->nurb.first; 01589 while(nu) { 01590 if(nu->type == CU_BEZIER) 01591 writestruct(wd, DATA, "BezTriple", nu->pntsu, nu->bezt); 01592 else { 01593 writestruct(wd, DATA, "BPoint", nu->pntsu*nu->pntsv, nu->bp); 01594 if(nu->knotsu) writedata(wd, DATA, KNOTSU(nu)*sizeof(float), nu->knotsu); 01595 if(nu->knotsv) writedata(wd, DATA, KNOTSV(nu)*sizeof(float), nu->knotsv); 01596 } 01597 nu= nu->next; 01598 } 01599 } 01600 } 01601 cu= cu->id.next; 01602 } 01603 01604 /* flush helps the compression for undo-save */ 01605 mywrite(wd, MYWRITE_FLUSH, 0); 01606 } 01607 01608 static void write_dverts(WriteData *wd, int count, MDeformVert *dvlist) 01609 { 01610 if (dvlist) { 01611 int i; 01612 01613 /* Write the dvert list */ 01614 writestruct(wd, DATA, "MDeformVert", count, dvlist); 01615 01616 /* Write deformation data for each dvert */ 01617 for (i=0; i<count; i++) { 01618 if (dvlist[i].dw) 01619 writestruct(wd, DATA, "MDeformWeight", dvlist[i].totweight, dvlist[i].dw); 01620 } 01621 } 01622 } 01623 01624 static void write_mdisps(WriteData *wd, int count, MDisps *mdlist, int external) 01625 { 01626 if(mdlist) { 01627 int i; 01628 01629 writestruct(wd, DATA, "MDisps", count, mdlist); 01630 if(!external) { 01631 for(i = 0; i < count; ++i) { 01632 if(mdlist[i].disps) 01633 writedata(wd, DATA, sizeof(float)*3*mdlist[i].totdisp, mdlist[i].disps); 01634 } 01635 } 01636 } 01637 } 01638 01639 static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data, int partial_type, int partial_count) 01640 { 01641 int i; 01642 01643 /* write external customdata (not for undo) */ 01644 if(data->external && !wd->current) 01645 CustomData_external_write(data, id, CD_MASK_MESH, count, 0); 01646 01647 writestruct(wd, DATA, "CustomDataLayer", data->maxlayer, data->layers); 01648 01649 for (i=0; i<data->totlayer; i++) { 01650 CustomDataLayer *layer= &data->layers[i]; 01651 const char *structname; 01652 int structnum, datasize; 01653 01654 if (layer->type == CD_MDEFORMVERT) { 01655 /* layer types that allocate own memory need special handling */ 01656 write_dverts(wd, count, layer->data); 01657 } 01658 else if (layer->type == CD_MDISPS) { 01659 write_mdisps(wd, count, layer->data, layer->flag & CD_FLAG_EXTERNAL); 01660 } 01661 else { 01662 CustomData_file_write_info(layer->type, &structname, &structnum); 01663 if (structnum) { 01664 /* when using partial visibility, the MEdge and MFace layers 01665 are smaller than the original, so their type and count is 01666 passed to make this work */ 01667 if (layer->type != partial_type) datasize= structnum*count; 01668 else datasize= structnum*partial_count; 01669 01670 writestruct(wd, DATA, structname, datasize, layer->data); 01671 } 01672 else 01673 printf("%s error: layer '%s':%d - can't be written to file\n", 01674 __func__, structname, layer->type); 01675 } 01676 } 01677 01678 if(data->external) 01679 writestruct(wd, DATA, "CustomDataExternal", 1, data->external); 01680 } 01681 01682 static void write_meshs(WriteData *wd, ListBase *idbase) 01683 { 01684 Mesh *mesh; 01685 01686 mesh= idbase->first; 01687 while(mesh) { 01688 if(mesh->id.us>0 || wd->current) { 01689 /* write LibData */ 01690 writestruct(wd, ID_ME, "Mesh", 1, mesh); 01691 01692 /* direct data */ 01693 if (mesh->id.properties) IDP_WriteProperty(mesh->id.properties, wd); 01694 if (mesh->adt) write_animdata(wd, mesh->adt); 01695 01696 writedata(wd, DATA, sizeof(void *)*mesh->totcol, mesh->mat); 01697 01698 write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, -1, 0); 01699 write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, -1, 0); 01700 write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, -1, 0); 01701 } 01702 mesh= mesh->id.next; 01703 } 01704 } 01705 01706 static void write_lattices(WriteData *wd, ListBase *idbase) 01707 { 01708 Lattice *lt; 01709 01710 lt= idbase->first; 01711 while(lt) { 01712 if(lt->id.us>0 || wd->current) { 01713 /* write LibData */ 01714 writestruct(wd, ID_LT, "Lattice", 1, lt); 01715 if (lt->id.properties) IDP_WriteProperty(lt->id.properties, wd); 01716 01717 /* write animdata */ 01718 if (lt->adt) write_animdata(wd, lt->adt); 01719 01720 /* direct data */ 01721 writestruct(wd, DATA, "BPoint", lt->pntsu*lt->pntsv*lt->pntsw, lt->def); 01722 01723 write_dverts(wd, lt->pntsu*lt->pntsv*lt->pntsw, lt->dvert); 01724 01725 } 01726 lt= lt->id.next; 01727 } 01728 } 01729 01730 static void write_previews(WriteData *wd, PreviewImage *prv) 01731 { 01732 if (prv) { 01733 short w = prv->w[1]; 01734 short h = prv->h[1]; 01735 unsigned int *rect = prv->rect[1]; 01736 /* don't write out large previews if not requested */ 01737 if (!(U.flag & USER_SAVE_PREVIEWS) ) { 01738 prv->w[1] = 0; 01739 prv->h[1] = 0; 01740 prv->rect[1] = NULL; 01741 } 01742 writestruct(wd, DATA, "PreviewImage", 1, prv); 01743 if (prv->rect[0]) writedata(wd, DATA, prv->w[0]*prv->h[0]*sizeof(unsigned int), prv->rect[0]); 01744 if (prv->rect[1]) writedata(wd, DATA, prv->w[1]*prv->h[1]*sizeof(unsigned int), prv->rect[1]); 01745 01746 /* restore preview, we still want to keep it in memory even if not saved to file */ 01747 if (!(U.flag & USER_SAVE_PREVIEWS) ) { 01748 prv->w[1] = w; 01749 prv->h[1] = h; 01750 prv->rect[1] = rect; 01751 } 01752 } 01753 } 01754 01755 static void write_images(WriteData *wd, ListBase *idbase) 01756 { 01757 Image *ima; 01758 PackedFile * pf; 01759 01760 01761 ima= idbase->first; 01762 while(ima) { 01763 if(ima->id.us>0 || wd->current) { 01764 /* write LibData */ 01765 writestruct(wd, ID_IM, "Image", 1, ima); 01766 if (ima->id.properties) IDP_WriteProperty(ima->id.properties, wd); 01767 01768 if (ima->packedfile) { 01769 pf = ima->packedfile; 01770 writestruct(wd, DATA, "PackedFile", 1, pf); 01771 writedata(wd, DATA, pf->size, pf->data); 01772 } 01773 01774 write_previews(wd, ima->preview); 01775 } 01776 ima= ima->id.next; 01777 } 01778 /* flush helps the compression for undo-save */ 01779 mywrite(wd, MYWRITE_FLUSH, 0); 01780 } 01781 01782 static void write_textures(WriteData *wd, ListBase *idbase) 01783 { 01784 Tex *tex; 01785 01786 tex= idbase->first; 01787 while(tex) { 01788 if(tex->id.us>0 || wd->current) { 01789 /* write LibData */ 01790 writestruct(wd, ID_TE, "Tex", 1, tex); 01791 if (tex->id.properties) IDP_WriteProperty(tex->id.properties, wd); 01792 01793 if (tex->adt) write_animdata(wd, tex->adt); 01794 01795 /* direct data */ 01796 if(tex->type == TEX_PLUGIN && tex->plugin) writestruct(wd, DATA, "PluginTex", 1, tex->plugin); 01797 if(tex->coba) writestruct(wd, DATA, "ColorBand", 1, tex->coba); 01798 if(tex->type == TEX_ENVMAP && tex->env) writestruct(wd, DATA, "EnvMap", 1, tex->env); 01799 if(tex->type == TEX_POINTDENSITY && tex->pd) { 01800 writestruct(wd, DATA, "PointDensity", 1, tex->pd); 01801 if(tex->pd->coba) writestruct(wd, DATA, "ColorBand", 1, tex->pd->coba); 01802 if(tex->pd->falloff_curve) write_curvemapping(wd, tex->pd->falloff_curve); 01803 } 01804 if(tex->type == TEX_VOXELDATA) writestruct(wd, DATA, "VoxelData", 1, tex->vd); 01805 if(tex->type == TEX_OCEAN && tex->ot) writestruct(wd, DATA, "OceanTex", 1, tex->ot); 01806 01807 /* nodetree is integral part of texture, no libdata */ 01808 if(tex->nodetree) { 01809 writestruct(wd, DATA, "bNodeTree", 1, tex->nodetree); 01810 write_nodetree(wd, tex->nodetree); 01811 } 01812 01813 write_previews(wd, tex->preview); 01814 } 01815 tex= tex->id.next; 01816 } 01817 01818 /* flush helps the compression for undo-save */ 01819 mywrite(wd, MYWRITE_FLUSH, 0); 01820 } 01821 01822 static void write_materials(WriteData *wd, ListBase *idbase) 01823 { 01824 Material *ma; 01825 int a; 01826 01827 ma= idbase->first; 01828 while(ma) { 01829 if(ma->id.us>0 || wd->current) { 01830 /* write LibData */ 01831 writestruct(wd, ID_MA, "Material", 1, ma); 01832 01833 /*Write ID Properties -- and copy this comment EXACTLY for easy finding 01834 of library blocks that implement this.*/ 01835 /*manually set head group property to IDP_GROUP, just in case it hadn't been 01836 set yet :) */ 01837 if (ma->id.properties) IDP_WriteProperty(ma->id.properties, wd); 01838 01839 if (ma->adt) write_animdata(wd, ma->adt); 01840 01841 for(a=0; a<MAX_MTEX; a++) { 01842 if(ma->mtex[a]) writestruct(wd, DATA, "MTex", 1, ma->mtex[a]); 01843 } 01844 01845 if(ma->ramp_col) writestruct(wd, DATA, "ColorBand", 1, ma->ramp_col); 01846 if(ma->ramp_spec) writestruct(wd, DATA, "ColorBand", 1, ma->ramp_spec); 01847 01848 /* nodetree is integral part of material, no libdata */ 01849 if(ma->nodetree) { 01850 writestruct(wd, DATA, "bNodeTree", 1, ma->nodetree); 01851 write_nodetree(wd, ma->nodetree); 01852 } 01853 01854 write_previews(wd, ma->preview); 01855 } 01856 ma= ma->id.next; 01857 } 01858 } 01859 01860 static void write_worlds(WriteData *wd, ListBase *idbase) 01861 { 01862 World *wrld; 01863 int a; 01864 01865 wrld= idbase->first; 01866 while(wrld) { 01867 if(wrld->id.us>0 || wd->current) { 01868 /* write LibData */ 01869 writestruct(wd, ID_WO, "World", 1, wrld); 01870 if (wrld->id.properties) IDP_WriteProperty(wrld->id.properties, wd); 01871 01872 if (wrld->adt) write_animdata(wd, wrld->adt); 01873 01874 for(a=0; a<MAX_MTEX; a++) { 01875 if(wrld->mtex[a]) writestruct(wd, DATA, "MTex", 1, wrld->mtex[a]); 01876 } 01877 01878 /* nodetree is integral part of lamps, no libdata */ 01879 if(wrld->nodetree) { 01880 writestruct(wd, DATA, "bNodeTree", 1, wrld->nodetree); 01881 write_nodetree(wd, wrld->nodetree); 01882 } 01883 01884 write_previews(wd, wrld->preview); 01885 } 01886 wrld= wrld->id.next; 01887 } 01888 } 01889 01890 static void write_lamps(WriteData *wd, ListBase *idbase) 01891 { 01892 Lamp *la; 01893 int a; 01894 01895 la= idbase->first; 01896 while(la) { 01897 if(la->id.us>0 || wd->current) { 01898 /* write LibData */ 01899 writestruct(wd, ID_LA, "Lamp", 1, la); 01900 if (la->id.properties) IDP_WriteProperty(la->id.properties, wd); 01901 01902 if (la->adt) write_animdata(wd, la->adt); 01903 01904 /* direct data */ 01905 for(a=0; a<MAX_MTEX; a++) { 01906 if(la->mtex[a]) writestruct(wd, DATA, "MTex", 1, la->mtex[a]); 01907 } 01908 01909 if(la->curfalloff) 01910 write_curvemapping(wd, la->curfalloff); 01911 01912 /* nodetree is integral part of lamps, no libdata */ 01913 if(la->nodetree) { 01914 writestruct(wd, DATA, "bNodeTree", 1, la->nodetree); 01915 write_nodetree(wd, la->nodetree); 01916 } 01917 01918 write_previews(wd, la->preview); 01919 01920 } 01921 la= la->id.next; 01922 } 01923 } 01924 01925 01926 static void write_scenes(WriteData *wd, ListBase *scebase) 01927 { 01928 Scene *sce; 01929 Base *base; 01930 Editing *ed; 01931 Sequence *seq; 01932 MetaStack *ms; 01933 Strip *strip; 01934 TimeMarker *marker; 01935 TransformOrientation *ts; 01936 SceneRenderLayer *srl; 01937 ToolSettings *tos; 01938 01939 sce= scebase->first; 01940 while(sce) { 01941 /* write LibData */ 01942 writestruct(wd, ID_SCE, "Scene", 1, sce); 01943 if (sce->id.properties) IDP_WriteProperty(sce->id.properties, wd); 01944 01945 if (sce->adt) write_animdata(wd, sce->adt); 01946 write_keyingsets(wd, &sce->keyingsets); 01947 01948 /* direct data */ 01949 base= sce->base.first; 01950 while(base) { 01951 writestruct(wd, DATA, "Base", 1, base); 01952 base= base->next; 01953 } 01954 01955 tos = sce->toolsettings; 01956 writestruct(wd, DATA, "ToolSettings", 1, tos); 01957 if(tos->vpaint) { 01958 writestruct(wd, DATA, "VPaint", 1, tos->vpaint); 01959 } 01960 if(tos->wpaint) { 01961 writestruct(wd, DATA, "VPaint", 1, tos->wpaint); 01962 } 01963 if(tos->sculpt) { 01964 writestruct(wd, DATA, "Sculpt", 1, tos->sculpt); 01965 } 01966 01967 // write_paint(wd, &tos->imapaint.paint); 01968 01969 ed= sce->ed; 01970 if(ed) { 01971 writestruct(wd, DATA, "Editing", 1, ed); 01972 01973 /* reset write flags too */ 01974 01975 SEQ_BEGIN(ed, seq) { 01976 if(seq->strip) seq->strip->done= 0; 01977 writestruct(wd, DATA, "Sequence", 1, seq); 01978 } 01979 SEQ_END 01980 01981 SEQ_BEGIN(ed, seq) { 01982 if(seq->strip && seq->strip->done==0) { 01983 /* write strip with 'done' at 0 because readfile */ 01984 01985 if(seq->plugin) writestruct(wd, DATA, "PluginSeq", 1, seq->plugin); 01986 if(seq->effectdata) { 01987 switch(seq->type){ 01988 case SEQ_COLOR: 01989 writestruct(wd, DATA, "SolidColorVars", 1, seq->effectdata); 01990 break; 01991 case SEQ_SPEED: 01992 writestruct(wd, DATA, "SpeedControlVars", 1, seq->effectdata); 01993 break; 01994 case SEQ_WIPE: 01995 writestruct(wd, DATA, "WipeVars", 1, seq->effectdata); 01996 break; 01997 case SEQ_GLOW: 01998 writestruct(wd, DATA, "GlowVars", 1, seq->effectdata); 01999 break; 02000 case SEQ_TRANSFORM: 02001 writestruct(wd, DATA, "TransformVars", 1, seq->effectdata); 02002 break; 02003 } 02004 } 02005 02006 strip= seq->strip; 02007 writestruct(wd, DATA, "Strip", 1, strip); 02008 if(seq->flag & SEQ_USE_CROP && strip->crop) { 02009 writestruct(wd, DATA, "StripCrop", 1, strip->crop); 02010 } 02011 if(seq->flag & SEQ_USE_TRANSFORM && strip->transform) { 02012 writestruct(wd, DATA, "StripTransform", 1, strip->transform); 02013 } 02014 if(seq->flag & SEQ_USE_PROXY && strip->proxy) { 02015 writestruct(wd, DATA, "StripProxy", 1, strip->proxy); 02016 } 02017 if(seq->flag & SEQ_USE_COLOR_BALANCE && strip->color_balance) { 02018 writestruct(wd, DATA, "StripColorBalance", 1, strip->color_balance); 02019 } 02020 if(seq->type==SEQ_IMAGE) 02021 writestruct(wd, DATA, "StripElem", MEM_allocN_len(strip->stripdata) / sizeof(struct StripElem), strip->stripdata); 02022 else if(seq->type==SEQ_MOVIE || seq->type==SEQ_RAM_SOUND || seq->type == SEQ_HD_SOUND) 02023 writestruct(wd, DATA, "StripElem", 1, strip->stripdata); 02024 02025 strip->done= 1; 02026 } 02027 } 02028 SEQ_END 02029 02030 /* new; meta stack too, even when its nasty restore code */ 02031 for(ms= ed->metastack.first; ms; ms= ms->next) { 02032 writestruct(wd, DATA, "MetaStack", 1, ms); 02033 } 02034 } 02035 02036 if (sce->r.avicodecdata) { 02037 writestruct(wd, DATA, "AviCodecData", 1, sce->r.avicodecdata); 02038 if (sce->r.avicodecdata->lpFormat) writedata(wd, DATA, sce->r.avicodecdata->cbFormat, sce->r.avicodecdata->lpFormat); 02039 if (sce->r.avicodecdata->lpParms) writedata(wd, DATA, sce->r.avicodecdata->cbParms, sce->r.avicodecdata->lpParms); 02040 } 02041 02042 if (sce->r.qtcodecdata) { 02043 writestruct(wd, DATA, "QuicktimeCodecData", 1, sce->r.qtcodecdata); 02044 if (sce->r.qtcodecdata->cdParms) writedata(wd, DATA, sce->r.qtcodecdata->cdSize, sce->r.qtcodecdata->cdParms); 02045 } 02046 if (sce->r.ffcodecdata.properties) { 02047 IDP_WriteProperty(sce->r.ffcodecdata.properties, wd); 02048 } 02049 02050 /* writing dynamic list of TimeMarkers to the blend file */ 02051 for(marker= sce->markers.first; marker; marker= marker->next) 02052 writestruct(wd, DATA, "TimeMarker", 1, marker); 02053 02054 /* writing dynamic list of TransformOrientations to the blend file */ 02055 for(ts = sce->transform_spaces.first; ts; ts = ts->next) 02056 writestruct(wd, DATA, "TransformOrientation", 1, ts); 02057 02058 for(srl= sce->r.layers.first; srl; srl= srl->next) 02059 writestruct(wd, DATA, "SceneRenderLayer", 1, srl); 02060 02061 if(sce->nodetree) { 02062 writestruct(wd, DATA, "bNodeTree", 1, sce->nodetree); 02063 write_nodetree(wd, sce->nodetree); 02064 } 02065 02066 sce= sce->id.next; 02067 } 02068 /* flush helps the compression for undo-save */ 02069 mywrite(wd, MYWRITE_FLUSH, 0); 02070 } 02071 02072 static void write_gpencils(WriteData *wd, ListBase *lb) 02073 { 02074 bGPdata *gpd; 02075 bGPDlayer *gpl; 02076 bGPDframe *gpf; 02077 bGPDstroke *gps; 02078 02079 for (gpd= lb->first; gpd; gpd= gpd->id.next) { 02080 if (gpd->id.us>0 || wd->current) { 02081 /* write gpd data block to file */ 02082 writestruct(wd, ID_GD, "bGPdata", 1, gpd); 02083 02084 /* write grease-pencil layers to file */ 02085 for (gpl= gpd->layers.first; gpl; gpl= gpl->next) { 02086 writestruct(wd, DATA, "bGPDlayer", 1, gpl); 02087 02088 /* write this layer's frames to file */ 02089 for (gpf= gpl->frames.first; gpf; gpf= gpf->next) { 02090 writestruct(wd, DATA, "bGPDframe", 1, gpf); 02091 02092 /* write strokes */ 02093 for (gps= gpf->strokes.first; gps; gps= gps->next) { 02094 writestruct(wd, DATA, "bGPDstroke", 1, gps); 02095 writestruct(wd, DATA, "bGPDspoint", gps->totpoints, gps->points); 02096 } 02097 } 02098 } 02099 } 02100 } 02101 } 02102 02103 static void write_windowmanagers(WriteData *wd, ListBase *lb) 02104 { 02105 wmWindowManager *wm; 02106 wmWindow *win; 02107 02108 for(wm= lb->first; wm; wm= wm->id.next) { 02109 writestruct(wd, ID_WM, "wmWindowManager", 1, wm); 02110 02111 for(win= wm->windows.first; win; win= win->next) 02112 writestruct(wd, DATA, "wmWindow", 1, win); 02113 } 02114 } 02115 02116 static void write_region(WriteData *wd, ARegion *ar, int spacetype) 02117 { 02118 writestruct(wd, DATA, "ARegion", 1, ar); 02119 02120 if(ar->regiondata) { 02121 switch(spacetype) { 02122 case SPACE_VIEW3D: 02123 if(ar->regiontype==RGN_TYPE_WINDOW) { 02124 RegionView3D *rv3d= ar->regiondata; 02125 writestruct(wd, DATA, "RegionView3D", 1, rv3d); 02126 02127 if(rv3d->localvd) 02128 writestruct(wd, DATA, "RegionView3D", 1, rv3d->localvd); 02129 if(rv3d->clipbb) 02130 writestruct(wd, DATA, "BoundBox", 1, rv3d->clipbb); 02131 02132 } 02133 else 02134 printf("regiondata write missing!\n"); 02135 break; 02136 default: 02137 printf("regiondata write missing!\n"); 02138 } 02139 } 02140 } 02141 02142 static void write_screens(WriteData *wd, ListBase *scrbase) 02143 { 02144 bScreen *sc; 02145 ScrArea *sa; 02146 ScrVert *sv; 02147 ScrEdge *se; 02148 02149 sc= scrbase->first; 02150 while(sc) { 02151 02152 /* write LibData */ 02153 /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */ 02154 writestruct(wd, ID_SCRN, "Screen", 1, sc); 02155 if (sc->id.properties) 02156 IDP_WriteProperty(sc->id.properties, wd); 02157 02158 /* direct data */ 02159 for(sv= sc->vertbase.first; sv; sv= sv->next) 02160 writestruct(wd, DATA, "ScrVert", 1, sv); 02161 02162 for(se= sc->edgebase.first; se; se= se->next) 02163 writestruct(wd, DATA, "ScrEdge", 1, se); 02164 02165 for(sa= sc->areabase.first; sa; sa= sa->next) { 02166 SpaceLink *sl; 02167 Panel *pa; 02168 ARegion *ar; 02169 02170 writestruct(wd, DATA, "ScrArea", 1, sa); 02171 02172 for(ar= sa->regionbase.first; ar; ar= ar->next) { 02173 write_region(wd, ar, sa->spacetype); 02174 02175 for(pa= ar->panels.first; pa; pa= pa->next) 02176 writestruct(wd, DATA, "Panel", 1, pa); 02177 } 02178 02179 sl= sa->spacedata.first; 02180 while(sl) { 02181 for(ar= sl->regionbase.first; ar; ar= ar->next) 02182 write_region(wd, ar, sl->spacetype); 02183 02184 if(sl->spacetype==SPACE_VIEW3D) { 02185 View3D *v3d= (View3D *) sl; 02186 BGpic *bgpic; 02187 writestruct(wd, DATA, "View3D", 1, v3d); 02188 for (bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next) 02189 writestruct(wd, DATA, "BGpic", 1, bgpic); 02190 if(v3d->localvd) writestruct(wd, DATA, "View3D", 1, v3d->localvd); 02191 } 02192 else if(sl->spacetype==SPACE_IPO) { 02193 SpaceIpo *sipo= (SpaceIpo *)sl; 02194 ListBase tmpGhosts = sipo->ghostCurves; 02195 02196 /* temporarily disable ghost curves when saving */ 02197 sipo->ghostCurves.first= sipo->ghostCurves.last= NULL; 02198 02199 writestruct(wd, DATA, "SpaceIpo", 1, sl); 02200 if(sipo->ads) writestruct(wd, DATA, "bDopeSheet", 1, sipo->ads); 02201 02202 /* reenable ghost curves */ 02203 sipo->ghostCurves= tmpGhosts; 02204 } 02205 else if(sl->spacetype==SPACE_BUTS) { 02206 writestruct(wd, DATA, "SpaceButs", 1, sl); 02207 } 02208 else if(sl->spacetype==SPACE_FILE) { 02209 SpaceFile *sfile= (SpaceFile *)sl; 02210 02211 writestruct(wd, DATA, "SpaceFile", 1, sl); 02212 if(sfile->params) 02213 writestruct(wd, DATA, "FileSelectParams", 1, sfile->params); 02214 } 02215 else if(sl->spacetype==SPACE_SEQ) { 02216 writestruct(wd, DATA, "SpaceSeq", 1, sl); 02217 } 02218 else if(sl->spacetype==SPACE_OUTLINER) { 02219 SpaceOops *so= (SpaceOops *)sl; 02220 02221 writestruct(wd, DATA, "SpaceOops", 1, so); 02222 02223 /* outliner */ 02224 if(so->treestore) { 02225 writestruct(wd, DATA, "TreeStore", 1, so->treestore); 02226 if(so->treestore->data) 02227 writestruct(wd, DATA, "TreeStoreElem", so->treestore->usedelem, so->treestore->data); 02228 } 02229 } 02230 else if(sl->spacetype==SPACE_IMAGE) { 02231 SpaceImage *sima= (SpaceImage *)sl; 02232 02233 writestruct(wd, DATA, "SpaceImage", 1, sl); 02234 if(sima->cumap) 02235 write_curvemapping(wd, sima->cumap); 02236 } 02237 else if(sl->spacetype==SPACE_TEXT) { 02238 writestruct(wd, DATA, "SpaceText", 1, sl); 02239 } 02240 else if(sl->spacetype==SPACE_SCRIPT) { 02241 SpaceScript *scr = (SpaceScript*)sl; 02242 scr->but_refs = NULL; 02243 writestruct(wd, DATA, "SpaceScript", 1, sl); 02244 } 02245 else if(sl->spacetype==SPACE_ACTION) { 02246 writestruct(wd, DATA, "SpaceAction", 1, sl); 02247 } 02248 else if(sl->spacetype==SPACE_NLA){ 02249 SpaceNla *snla= (SpaceNla *)sl; 02250 02251 writestruct(wd, DATA, "SpaceNla", 1, snla); 02252 if(snla->ads) writestruct(wd, DATA, "bDopeSheet", 1, snla->ads); 02253 } 02254 else if(sl->spacetype==SPACE_TIME){ 02255 writestruct(wd, DATA, "SpaceTime", 1, sl); 02256 } 02257 else if(sl->spacetype==SPACE_NODE){ 02258 writestruct(wd, DATA, "SpaceNode", 1, sl); 02259 } 02260 else if(sl->spacetype==SPACE_LOGIC){ 02261 writestruct(wd, DATA, "SpaceLogic", 1, sl); 02262 } 02263 else if(sl->spacetype==SPACE_CONSOLE) { 02264 SpaceConsole *con = (SpaceConsole*)sl; 02265 ConsoleLine *cl; 02266 02267 for (cl=con->history.first; cl; cl=cl->next) { 02268 /* 'len_alloc' is invalid on write, set from 'len' on read */ 02269 writestruct(wd, DATA, "ConsoleLine", 1, cl); 02270 writedata(wd, DATA, cl->len+1, cl->line); 02271 } 02272 writestruct(wd, DATA, "SpaceConsole", 1, sl); 02273 02274 } 02275 else if(sl->spacetype==SPACE_USERPREF) { 02276 writestruct(wd, DATA, "SpaceUserPref", 1, sl); 02277 } 02278 else if(sl->spacetype==SPACE_CLIP) { 02279 writestruct(wd, DATA, "SpaceClip", 1, sl); 02280 } 02281 02282 sl= sl->next; 02283 } 02284 } 02285 02286 sc= sc->id.next; 02287 } 02288 } 02289 02290 static void write_libraries(WriteData *wd, Main *main) 02291 { 02292 ListBase *lbarray[MAX_LIBARRAY]; 02293 ID *id; 02294 int a, tot, foundone; 02295 02296 for(; main; main= main->next) { 02297 02298 a=tot= set_listbasepointers(main, lbarray); 02299 02300 /* test: is lib being used */ 02301 foundone= 0; 02302 while(tot--) { 02303 for(id= lbarray[tot]->first; id; id= id->next) { 02304 if(id->us>0 && (id->flag & LIB_EXTERN)) { 02305 foundone= 1; 02306 break; 02307 } 02308 } 02309 if(foundone) break; 02310 } 02311 02312 if(foundone) { 02313 writestruct(wd, ID_LI, "Library", 1, main->curlib); 02314 02315 while(a--) { 02316 for(id= lbarray[a]->first; id; id= id->next) { 02317 if(id->us>0 && (id->flag & LIB_EXTERN)) { 02318 writestruct(wd, ID_ID, "ID", 1, id); 02319 } 02320 } 02321 } 02322 } 02323 } 02324 } 02325 02326 static void write_bone(WriteData *wd, Bone* bone) 02327 { 02328 Bone* cbone; 02329 02330 // PATCH for upward compatibility after 2.37+ armature recode 02331 bone->size[0]= bone->size[1]= bone->size[2]= 1.0f; 02332 02333 // Write this bone 02334 writestruct(wd, DATA, "Bone", 1, bone); 02335 02336 /* Write ID Properties -- and copy this comment EXACTLY for easy finding 02337 of library blocks that implement this.*/ 02338 if (bone->prop) 02339 IDP_WriteProperty(bone->prop, wd); 02340 02341 // Write Children 02342 cbone= bone->childbase.first; 02343 while(cbone) { 02344 write_bone(wd, cbone); 02345 cbone= cbone->next; 02346 } 02347 } 02348 02349 static void write_armatures(WriteData *wd, ListBase *idbase) 02350 { 02351 bArmature *arm; 02352 Bone *bone; 02353 02354 arm=idbase->first; 02355 while (arm) { 02356 if (arm->id.us>0 || wd->current) { 02357 writestruct(wd, ID_AR, "bArmature", 1, arm); 02358 if (arm->id.properties) IDP_WriteProperty(arm->id.properties, wd); 02359 02360 if (arm->adt) write_animdata(wd, arm->adt); 02361 02362 /* Direct data */ 02363 bone= arm->bonebase.first; 02364 while(bone) { 02365 write_bone(wd, bone); 02366 bone=bone->next; 02367 } 02368 } 02369 arm=arm->id.next; 02370 } 02371 02372 /* flush helps the compression for undo-save */ 02373 mywrite(wd, MYWRITE_FLUSH, 0); 02374 } 02375 02376 static void write_texts(WriteData *wd, ListBase *idbase) 02377 { 02378 Text *text; 02379 TextLine *tmp; 02380 TextMarker *mrk; 02381 02382 text= idbase->first; 02383 while(text) { 02384 if ( (text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) text->flags &= ~TXT_ISEXT; 02385 02386 /* write LibData */ 02387 writestruct(wd, ID_TXT, "Text", 1, text); 02388 if(text->name) writedata(wd, DATA, strlen(text->name)+1, text->name); 02389 if (text->id.properties) IDP_WriteProperty(text->id.properties, wd); 02390 02391 if(!(text->flags & TXT_ISEXT)) { 02392 /* now write the text data, in two steps for optimization in the readfunction */ 02393 tmp= text->lines.first; 02394 while (tmp) { 02395 writestruct(wd, DATA, "TextLine", 1, tmp); 02396 tmp= tmp->next; 02397 } 02398 02399 tmp= text->lines.first; 02400 while (tmp) { 02401 writedata(wd, DATA, tmp->len+1, tmp->line); 02402 tmp= tmp->next; 02403 } 02404 02405 /* write markers */ 02406 mrk= text->markers.first; 02407 while (mrk) { 02408 writestruct(wd, DATA, "TextMarker", 1, mrk); 02409 mrk= mrk->next; 02410 } 02411 } 02412 02413 02414 text= text->id.next; 02415 } 02416 02417 /* flush helps the compression for undo-save */ 02418 mywrite(wd, MYWRITE_FLUSH, 0); 02419 } 02420 02421 static void write_speakers(WriteData *wd, ListBase *idbase) 02422 { 02423 Speaker *spk; 02424 02425 spk= idbase->first; 02426 while(spk) { 02427 if(spk->id.us>0 || wd->current) { 02428 /* write LibData */ 02429 writestruct(wd, ID_SPK, "Speaker", 1, spk); 02430 if (spk->id.properties) IDP_WriteProperty(spk->id.properties, wd); 02431 02432 if (spk->adt) write_animdata(wd, spk->adt); 02433 } 02434 spk= spk->id.next; 02435 } 02436 } 02437 02438 static void write_sounds(WriteData *wd, ListBase *idbase) 02439 { 02440 bSound *sound; 02441 02442 PackedFile * pf; 02443 02444 sound= idbase->first; 02445 while(sound) { 02446 if(sound->id.us>0 || wd->current) { 02447 /* write LibData */ 02448 writestruct(wd, ID_SO, "bSound", 1, sound); 02449 if (sound->id.properties) IDP_WriteProperty(sound->id.properties, wd); 02450 02451 if (sound->packedfile) { 02452 pf = sound->packedfile; 02453 writestruct(wd, DATA, "PackedFile", 1, pf); 02454 writedata(wd, DATA, pf->size, pf->data); 02455 } 02456 } 02457 sound= sound->id.next; 02458 } 02459 02460 /* flush helps the compression for undo-save */ 02461 mywrite(wd, MYWRITE_FLUSH, 0); 02462 } 02463 02464 static void write_groups(WriteData *wd, ListBase *idbase) 02465 { 02466 Group *group; 02467 GroupObject *go; 02468 02469 for(group= idbase->first; group; group= group->id.next) { 02470 if(group->id.us>0 || wd->current) { 02471 /* write LibData */ 02472 writestruct(wd, ID_GR, "Group", 1, group); 02473 if (group->id.properties) IDP_WriteProperty(group->id.properties, wd); 02474 02475 go= group->gobject.first; 02476 while(go) { 02477 writestruct(wd, DATA, "GroupObject", 1, go); 02478 go= go->next; 02479 } 02480 } 02481 } 02482 } 02483 02484 static void write_nodetrees(WriteData *wd, ListBase *idbase) 02485 { 02486 bNodeTree *ntree; 02487 02488 for(ntree=idbase->first; ntree; ntree= ntree->id.next) { 02489 if (ntree->id.us>0 || wd->current) { 02490 writestruct(wd, ID_NT, "bNodeTree", 1, ntree); 02491 write_nodetree(wd, ntree); 02492 02493 if (ntree->id.properties) IDP_WriteProperty(ntree->id.properties, wd); 02494 02495 if (ntree->adt) write_animdata(wd, ntree->adt); 02496 } 02497 } 02498 } 02499 02500 static void write_brushes(WriteData *wd, ListBase *idbase) 02501 { 02502 Brush *brush; 02503 02504 for(brush=idbase->first; brush; brush= brush->id.next) { 02505 if(brush->id.us>0 || wd->current) { 02506 writestruct(wd, ID_BR, "Brush", 1, brush); 02507 if (brush->id.properties) IDP_WriteProperty(brush->id.properties, wd); 02508 02509 writestruct(wd, DATA, "MTex", 1, &brush->mtex); 02510 02511 if(brush->curve) 02512 write_curvemapping(wd, brush->curve); 02513 } 02514 } 02515 } 02516 02517 static void write_scripts(WriteData *wd, ListBase *idbase) 02518 { 02519 Script *script; 02520 02521 for(script=idbase->first; script; script= script->id.next) { 02522 if(script->id.us>0 || wd->current) { 02523 writestruct(wd, ID_SCRIPT, "Script", 1, script); 02524 if (script->id.properties) IDP_WriteProperty(script->id.properties, wd); 02525 } 02526 } 02527 } 02528 02529 static void write_movieTracks(WriteData *wd, ListBase *tracks) 02530 { 02531 MovieTrackingTrack *track; 02532 02533 track= tracks->first; 02534 while(track) { 02535 writestruct(wd, DATA, "MovieTrackingTrack", 1, track); 02536 02537 if(track->markers) 02538 writestruct(wd, DATA, "MovieTrackingMarker", track->markersnr, track->markers); 02539 02540 track= track->next; 02541 } 02542 } 02543 02544 static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction *reconstruction) 02545 { 02546 if(reconstruction->camnr) 02547 writestruct(wd, DATA, "MovieReconstructedCamera", reconstruction->camnr, reconstruction->cameras); 02548 } 02549 02550 static void write_movieclips(WriteData *wd, ListBase *idbase) 02551 { 02552 MovieClip *clip; 02553 02554 clip= idbase->first; 02555 while(clip) { 02556 if(clip->id.us>0 || wd->current) { 02557 MovieTracking *tracking= &clip->tracking; 02558 MovieTrackingObject *object; 02559 writestruct(wd, ID_MC, "MovieClip", 1, clip); 02560 02561 write_movieTracks(wd, &tracking->tracks); 02562 write_movieReconstruction(wd, &tracking->reconstruction); 02563 02564 object= tracking->objects.first; 02565 while(object) { 02566 writestruct(wd, DATA, "MovieTrackingObject", 1, object); 02567 02568 write_movieTracks(wd, &object->tracks); 02569 write_movieReconstruction(wd, &object->reconstruction); 02570 02571 object= object->next; 02572 } 02573 } 02574 02575 clip= clip->id.next; 02576 } 02577 02578 /* flush helps the compression for undo-save */ 02579 mywrite(wd, MYWRITE_FLUSH, 0); 02580 } 02581 02582 /* context is usually defined by WM, two cases where no WM is available: 02583 * - for forward compatibility, curscreen has to be saved 02584 * - for undofile, curscene needs to be saved */ 02585 static void write_global(WriteData *wd, int fileflags, Main *mainvar) 02586 { 02587 FileGlobal fg; 02588 bScreen *screen; 02589 char subvstr[8]; 02590 02591 /* prevent mem checkers from complaining */ 02592 fg.pads= fg.pad= 0; 02593 memset(fg.filename, 0, sizeof(fg.filename)); 02594 02595 current_screen_compat(mainvar, &screen); 02596 02597 /* XXX still remap G */ 02598 fg.curscreen= screen; 02599 fg.curscene= screen->scene; 02600 fg.displaymode= G.displaymode; 02601 fg.winpos= G.winpos; 02602 02603 /* prevent to save this, is not good convention, and feature with concerns... */ 02604 fg.fileflags= (fileflags & ~(G_FILE_NO_UI|G_FILE_RELATIVE_REMAP|G_FILE_MESH_COMPAT)); 02605 02606 fg.globalf= G.f; 02607 BLI_strncpy(fg.filename, mainvar->name, sizeof(fg.filename)); 02608 02609 sprintf(subvstr, "%4d", BLENDER_SUBVERSION); 02610 memcpy(fg.subvstr, subvstr, 4); 02611 02612 fg.subversion= BLENDER_SUBVERSION; 02613 fg.minversion= BLENDER_MINVERSION; 02614 fg.minsubversion= BLENDER_MINSUBVERSION; 02615 #ifdef WITH_BUILDINFO 02616 { 02617 extern char build_rev[]; 02618 fg.revision= atoi(build_rev); 02619 } 02620 #else 02621 fg.revision= 0; 02622 #endif 02623 writestruct(wd, GLOB, "FileGlobal", 1, &fg); 02624 } 02625 02626 /* preview image, first 2 values are width and height 02627 * second are an RGBA image (unsigned char) 02628 * note, this uses 'TEST' since new types will segfault on file load for older blender versions. 02629 */ 02630 static void write_thumb(WriteData *wd, int *img) 02631 { 02632 if(img) 02633 writedata(wd, TEST, (2 + img[0] * img[1]) * sizeof(int), img); 02634 } 02635 02636 /* if MemFile * there's filesave to memory */ 02637 static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFile *current, 02638 int write_user_block, int write_flags, int *thumb) 02639 { 02640 BHead bhead; 02641 ListBase mainlist; 02642 char buf[16]; 02643 WriteData *wd; 02644 02645 blo_split_main(&mainlist, mainvar); 02646 02647 wd= bgnwrite(handle, compare, current); 02648 02649 #ifdef USE_BMESH_SAVE_AS_COMPAT 02650 wd->use_mesh_compat = (write_flags & G_FILE_MESH_COMPAT) != 0; 02651 #endif 02652 02653 sprintf(buf, "BLENDER%c%c%.3d", (sizeof(void*)==8)?'-':'_', (ENDIAN_ORDER==B_ENDIAN)?'V':'v', BLENDER_VERSION); 02654 mywrite(wd, buf, 12); 02655 02656 write_renderinfo(wd, mainvar); 02657 write_thumb(wd, thumb); 02658 write_global(wd, write_flags, mainvar); 02659 02660 /* no UI save in undo */ 02661 if(current==NULL) { 02662 write_windowmanagers(wd, &mainvar->wm); 02663 write_screens (wd, &mainvar->screen); 02664 } 02665 write_movieclips (wd, &mainvar->movieclip); 02666 write_scenes (wd, &mainvar->scene); 02667 write_curves (wd, &mainvar->curve); 02668 write_mballs (wd, &mainvar->mball); 02669 write_images (wd, &mainvar->image); 02670 write_cameras (wd, &mainvar->camera); 02671 write_lamps (wd, &mainvar->lamp); 02672 write_lattices (wd, &mainvar->latt); 02673 write_vfonts (wd, &mainvar->vfont); 02674 write_keys (wd, &mainvar->key); 02675 write_worlds (wd, &mainvar->world); 02676 write_texts (wd, &mainvar->text); 02677 write_speakers (wd, &mainvar->speaker); 02678 write_sounds (wd, &mainvar->sound); 02679 write_groups (wd, &mainvar->group); 02680 write_armatures(wd, &mainvar->armature); 02681 write_actions (wd, &mainvar->action); 02682 write_objects (wd, &mainvar->object); 02683 write_materials(wd, &mainvar->mat); 02684 write_textures (wd, &mainvar->tex); 02685 write_meshs (wd, &mainvar->mesh); 02686 write_particlesettings(wd, &mainvar->particle); 02687 write_nodetrees(wd, &mainvar->nodetree); 02688 write_brushes (wd, &mainvar->brush); 02689 write_scripts (wd, &mainvar->script); 02690 write_gpencils (wd, &mainvar->gpencil); 02691 write_libraries(wd, mainvar->next); 02692 02693 if (write_user_block) { 02694 write_userdef(wd); 02695 } 02696 02697 /* dna as last, because (to be implemented) test for which structs are written */ 02698 writedata(wd, DNA1, wd->sdna->datalen, wd->sdna->data); 02699 02700 /* end of file */ 02701 memset(&bhead, 0, sizeof(BHead)); 02702 bhead.code= ENDB; 02703 mywrite(wd, &bhead, sizeof(BHead)); 02704 02705 blo_join_main(&mainlist); 02706 02707 return endwrite(wd); 02708 } 02709 02710 /* do reverse file history: .blend1 -> .blend2, .blend -> .blend1 */ 02711 /* return: success(0), failure(1) */ 02712 static int do_history(const char *name, ReportList *reports) 02713 { 02714 char tempname1[FILE_MAX], tempname2[FILE_MAX]; 02715 int hisnr= U.versions; 02716 02717 if(U.versions==0) return 0; 02718 if(strlen(name)<2) { 02719 BKE_report(reports, RPT_ERROR, "Unable to make version backup: filename too short"); 02720 return 1; 02721 } 02722 02723 while(hisnr > 1) { 02724 BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr-1); 02725 BLI_snprintf(tempname2, sizeof(tempname2), "%s%d", name, hisnr); 02726 02727 if(BLI_rename(tempname1, tempname2)) { 02728 BKE_report(reports, RPT_ERROR, "Unable to make version backup"); 02729 return 1; 02730 } 02731 hisnr--; 02732 } 02733 02734 /* is needed when hisnr==1 */ 02735 BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr); 02736 02737 if(BLI_rename(name, tempname1)) { 02738 BKE_report(reports, RPT_ERROR, "Unable to make version backup"); 02739 return 1; 02740 } 02741 02742 return 0; 02743 } 02744 02745 /* return: success (1) */ 02746 int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportList *reports, int *thumb) 02747 { 02748 char userfilename[FILE_MAX]; 02749 char tempname[FILE_MAX+1]; 02750 int file, err, write_user_block; 02751 02752 /* open temporary file, so we preserve the original in case we crash */ 02753 BLI_snprintf(tempname, sizeof(tempname), "%s@", filepath); 02754 02755 file = open(tempname,O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666); 02756 if(file == -1) { 02757 BKE_reportf(reports, RPT_ERROR, "Can't open file %s for writing: %s.", tempname, strerror(errno)); 02758 return 0; 02759 } 02760 02761 /* remapping of relative paths to new file location */ 02762 if(write_flags & G_FILE_RELATIVE_REMAP) { 02763 char dir1[FILE_MAX]; 02764 char dir2[FILE_MAX]; 02765 BLI_split_dir_part(filepath, dir1, sizeof(dir1)); 02766 BLI_split_dir_part(mainvar->name, dir2, sizeof(dir2)); 02767 02768 /* just incase there is some subtle difference */ 02769 BLI_cleanup_dir(mainvar->name, dir1); 02770 BLI_cleanup_dir(mainvar->name, dir2); 02771 02772 if(BLI_path_cmp(dir1, dir2)==0) { 02773 write_flags &= ~G_FILE_RELATIVE_REMAP; 02774 } 02775 else { 02776 if(G.relbase_valid) { 02777 /* blend may not have been saved before. Tn this case 02778 * we should not have any relative paths, but if there 02779 * is somehow, an invalid or empty G.main->name it will 02780 * print an error, dont try make the absolute in this case. */ 02781 makeFilesAbsolute(mainvar, G.main->name, NULL); 02782 } 02783 } 02784 } 02785 02786 BLI_make_file_string(G.main->name, userfilename, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE); 02787 write_user_block= (BLI_path_cmp(filepath, userfilename) == 0); 02788 02789 if(write_flags & G_FILE_RELATIVE_REMAP) 02790 makeFilesRelative(mainvar, filepath, NULL); /* note, making relative to something OTHER then G.main->name */ 02791 02792 /* actual file writing */ 02793 err= write_file_handle(mainvar, file, NULL,NULL, write_user_block, write_flags, thumb); 02794 close(file); 02795 02796 if (err) { 02797 BKE_report(reports, RPT_ERROR, strerror(errno)); 02798 remove(tempname); 02799 02800 return 0; 02801 } 02802 02803 /* file save to temporary file was successful */ 02804 /* now do reverse file history (move .blend1 -> .blend2, .blend -> .blend1) */ 02805 if (write_flags & G_FILE_HISTORY) { 02806 int err_hist = do_history(filepath, reports); 02807 if (err_hist) { 02808 BKE_report(reports, RPT_ERROR, "Version backup failed. File saved with @"); 02809 return 0; 02810 } 02811 } 02812 02813 if(write_flags & G_FILE_COMPRESS) { 02814 /* compressed files have the same ending as regular files... only from 2.4!!! */ 02815 char gzname[FILE_MAX+4]; 02816 int ret; 02817 02818 /* first write compressed to separate @.gz */ 02819 BLI_snprintf(gzname, sizeof(gzname), "%s@.gz", filepath); 02820 ret = BLI_file_gzip(tempname, gzname); 02821 02822 if(0==ret) { 02823 /* now rename to real file name, and delete temp @ file too */ 02824 if(BLI_rename(gzname, filepath) != 0) { 02825 BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @."); 02826 return 0; 02827 } 02828 02829 BLI_delete(tempname, 0, 0); 02830 } 02831 else if(-1==ret) { 02832 BKE_report(reports, RPT_ERROR, "Failed opening .gz file."); 02833 return 0; 02834 } 02835 else if(-2==ret) { 02836 BKE_report(reports, RPT_ERROR, "Failed opening .blend file for compression."); 02837 return 0; 02838 } 02839 } 02840 else if(BLI_rename(tempname, filepath) != 0) { 02841 BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @"); 02842 return 0; 02843 } 02844 02845 return 1; 02846 } 02847 02848 /* return: success (1) */ 02849 int BLO_write_file_mem(Main *mainvar, MemFile *compare, MemFile *current, int write_flags) 02850 { 02851 int err; 02852 02853 err= write_file_handle(mainvar, 0, compare, current, 0, write_flags, NULL); 02854 02855 if(err==0) return 1; 02856 return 0; 02857 }