/** * $Id:$ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * The contents of this file may be used under the terms of either the GNU * General Public License Version 2 or later (the "GPL", see * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or * later (the "BL", see http://www.blender.org/BL/ ) which has to be * bought from the Blender Foundation to become active, in which case the * above mentioned GPL option does not apply. * * The Original Code is Copyright (C) 2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ /* * * * readblender.c * * jan 96 * * */ #include "/usr/people/blend/blender.h" #include "/usr/people/blend/file.h" /* namaak globals om de boel te neppen */ Global G; /* ************************************ */ /* ************************************ */ /* ************************************ */ * * * LET OP: de routine newlibadr() is - in blender - gewijzigd. * Zou hier ook zo moeten!!! * /* ************************************ */ /* ************************************ */ /* ************************************ */ char *blender_filedata=0; /* kopieen uit readfile.c */ /* ************** AFHANDELING OUDE POINTERS ******************* */ typedef struct OldNew { void *old, *new; int nr; } OldNew; extern char *compflags; /* genfile.c */ void read_libraries(); OldNew *datablocks=0; OldNew *libblocks=0; int datacount= 0, maxdatacount=1024; int libcount= 0, maxlibcount=1024; void *disable_newlibadr=0; ListBase *wich_libbase(Main *main, short type) { switch( type ) { case ID_SCE: return &(main->scene); case ID_LI: return &(main->library); case ID_OB: return &(main->object); case ID_ME: return &(main->mesh); case ID_CU: return &(main->curve); case ID_MB: return &(main->mball); case ID_MA: return &(main->mat); case ID_TE: return &(main->tex); case ID_IM: return &(main->image); case ID_IK: return &(main->ika); case ID_WV: return &(main->wave); case ID_LT: return &(main->latt); case ID_LA: return &(main->lamp); case ID_CA: return &(main->camera); case ID_IP: return &(main->ipo); case ID_KE: return &(main->key); case ID_WO: return &(main->world); case ID_SCR: return &(main->screen); case ID_VF: return &(main->vfont); } return 0; } void add_data_adr(void *old, void *new) /* met dynamische malloc * (0, 1) doorgeven herinitialiseert en geeft ongebruikte blokken vrij * (0, 0) doorgeven geeft alles vrij */ { OldNew *temp; int a; if(old==0) { /* ongebruikte vrijgeven */ temp= datablocks; for(a=0; anr==0) freeN(temp->new); } if(new==0 && datablocks) { freeN(datablocks); datablocks= 0; maxdatacount= 1024; } datacount= 0; } else { if(datablocks==0) { datablocks= mallocN(maxdatacount*sizeof(OldNew), "OldNew"); } else if(datacount==maxdatacount) { maxdatacount*= 2; temp= mallocN(maxdatacount*sizeof(OldNew), "OldNew"); memcpy(temp, datablocks, maxdatacount*sizeof(OldNew)/2); freeN(datablocks); datablocks= temp; } temp= datablocks+datacount; temp->old= old; temp->new= new; temp->nr= 0; datacount++; } } void add_lib_adr(void *old, void *new) /* met dynamische malloc * (0, 0) doorgeven geeft alles vrij * Zet aantal users al op 1!!! */ { OldNew *temp=0; int a; if(disable_newlibadr) { disable_newlibadr= new; return; } if(old==0) { /* alles vrijgeven */ if(libblocks) freeN(libblocks); libblocks= 0; maxlibcount= 1024; libcount= 0; } else { if(libblocks==0) { libblocks= mallocN(maxlibcount*sizeof(OldNew), "OldNew"); } else if(libcount==maxlibcount) { maxlibcount*= 2; temp= mallocN(maxlibcount*sizeof(OldNew), "OldNew"); memcpy(temp, libblocks, maxlibcount*sizeof(OldNew)/2); freeN(libblocks); libblocks= temp; } temp= libblocks+libcount; temp->old= old; temp->new= new; temp->nr= 1; libcount++; } } void *newadr(void *adr) /* alleen direkte datablokken */ { static int lastone= 0; struct OldNew *onew; if(adr) { /* op goed geluk: eerst het volgende blok doen */ if(lastoneold==adr) { onew->nr++; return onew->new; } } lastone= 0; onew= datablocks; while(lastoneold==adr) { onew->nr++; return onew->new; } onew++; lastone++; } } return 0; } void *newlibadr(void *adr) /* alleen Lib datablokken */ { static int lastone= 0; struct OldNew *onew; if(adr) { /* op goed geluk: eerst het volgende blok doen */ if(lastoneold==adr) { onew->nr++; return onew->new; } } lastone= 0; onew= libblocks; while(lastoneold==adr) { onew->nr++; return onew->new; } onew++; lastone++; } } return 0; } void *newlibadr_us(void *adr) /* hoogt usernummer op */ { ID *id; id= newlibadr(adr); if(id) { id->us++; } return id; } void change_libadr(void *old, void *new) { struct OldNew *onew; int lastone= 0; onew= libblocks; while(lastonenew==old) { onew->new= new; return; /* return; kunnen er meer zijn? */ } onew++; lastone++; } } /* ********** END OUDE POINTERS ****************** */ /* ********** READ FILE ****************** */ void read_struct(BHead *bh) { void *temp= 0; if(bh->len) { if(compflags[bh->SDNAnr]) { /* flag==0: bestaat niet meer */ temp= mallocN(bh->len, "read_struct"); memcpy(temp, (bh+1), bh->len); if(compflags[bh->SDNAnr]==2) reconstruct(bh->SDNAnr, bh->nr, &temp); } } add_data_adr(bh->old, temp); } void *read_libstruct(BHead *bh) { void *temp= 0; if(bh->len) { if(compflags[bh->SDNAnr]) { /* flag==0: bestaat niet meer */ temp= mallocN(bh->len, "read_libstruct"); memcpy(temp, (bh+1), bh->len); if(compflags[bh->SDNAnr]==2) reconstruct(bh->SDNAnr, bh->nr, &temp); } } add_lib_adr(bh->old, temp); return temp; } /* ************** ALG & MAIN ******************** */ void direct_link_mesh(mesh) Mesh *mesh; { mesh->mat= newadr(mesh->mat); mesh->mface= newadr(mesh->mface); mesh->mvert= newadr(mesh->mvert); mesh->mcol= newadr(mesh->mcol); mesh->msticky= newadr(mesh->msticky); mesh->disp.first= mesh->disp.last= 0; mesh->bb= 0; } int read_libblock(Main *main, BHead *bhead, int flag) { /* deze routine leest libblock en direkte data. Met linkfunkties * alles aan elkaar hangen. */ ID *id; ListBase *lb; int skipdata; char *fd; if(bhead->code==ID_ID) { id= (ID *)(bhead + 1); lb= wich_libbase(main, GS(id->name)); /* printf("idid %s oldp %x\n", id->name, bhead->old); */ } else { lb= wich_libbase(main, bhead->code); } if(lb==0) { return bhead->len+sizeof(BHead); } fd= (char *)bhead; /* libblock inlezen */ id= read_libstruct(bhead); addtail(lb, id); id->flag= flag | LIB_NEEDLINK; id->lib= main->curlib; id->us= 0; /* deze mag niet door de direct_link molen: is alleen het ID deel */ if(bhead->code==ID_ID) { skipdata= bhead->len+sizeof(BHead); return skipdata; } skipdata= bhead->len+sizeof(BHead); fd+= bhead->len+sizeof(BHead); bhead= (BHead *)fd; /* alle data inlezen */ while(bhead->code==DATA) { read_struct(bhead); skipdata+= bhead->len+sizeof(BHead); fd+= bhead->len+sizeof(BHead); bhead= (BHead *)fd; } /* pointers directe data goedzetten */ switch( GS(id->name) ) { case ID_OB: /* direct_link_object(id); */ break; case ID_ME: direct_link_mesh(id); break; case ID_CU: /* direct_link_curve(id); */ break; case ID_MB: /* direct_link_mball(id); */ break; case ID_MA: /* direct_link_material(id); */ break; case ID_TE: /* direct_link_texture(id); */ break; } /* vrijgeven, herinitialiseren */ add_data_adr(0, (void *)1); return skipdata; } void read_file_dna(char *filedata) { BHead *bhead; int afbreek=0; char *fd; freestructDNA(&old_sdna); fd= filedata; while(afbreek==0) { bhead= (BHead *)fd; if(bhead->code==ENDB) afbreek= 1; else if(bhead->code==DNA1) { old_sdna.data= mallocN(bhead->len, "sdna"); memcpy(old_sdna.data, fd+sizeof(BHead), bhead->len); afbreek= 1; } fd+= bhead->len+sizeof(BHead); } init_structDNA(&old_sdna); set_compareflags_structDNA(); } ID *is_yet_read(Main *main, BHead *bhead) { ListBase *lb; ID *idtest, *id; idtest= (ID *)(bhead +1); lb= wich_libbase(main, GS(idtest->name)); if(lb) { id= lb->first; while(id) { if( strcmp(id->name, idtest->name)==0 ) return id; id= id->next; } } return 0; } void open_blender(char *name) { static int firsttime=1; extern char DNAstr[]; int len, file, version, temp, temp1, filelen; char str[12]; if(firsttime) { bzero(G, sizeof(Global)); G.main= callocN(sizeof(Main), "main"); bzero(&cur_sdna, sizeof(struct SDNA)); cur_sdna.data= DNAstr+4; cur_sdna.datalen= *( (int *)DNAstr); init_structDNA(&cur_sdna); firsttime= 0; } len= strlen(name); if(len<6) return; if( name[len-1]=='/' ) return; file= open(name, O_RDONLY); if(file<=0) { printf("Can't find file\n"); return; } filelen= lseek(file, 0, 2); /* seek end */ lseek(file, 0, 0); /* en weer terug */ read(file, &temp, 4); read(file, &temp1, 4); if(temp!=BLEN || temp1!=DER_) { close(file); printf("Idiot file!\n"); return; } read(file, &version, 4); str[0]= ( (char *)&version )[1]; str[1]= ( (char *)&version )[2]; str[2]= ( (char *)&version )[3]; str[3]= 0; G.versionfile= atoi(str); /* hele file inlezen */ filelen-= 12; blender_filedata= mallocN(filelen, "filedata"); read(file, blender_filedata, filelen); close(file); /* op zoek naar SDNA */ read_file_dna(blender_filedata); } void close_blender() { if(blender_filedata) { freeN(blender_filedata); blender_filedata= 0; } } void *append_part(int idcode, char *name) { BHead *bhead; ID *id=0; int afbreek=0; char *fd; fd= blender_filedata; if(fd==0) { printf("didn't open blenderfile\n"); return; } while(afbreek==0) { bhead= (BHead *)fd; if(bhead->code==ENDB) afbreek= 1; else if(bhead->code==idcode) { id= (ID *)(bhead+1); if(strcmp(id->name+2, name)==0) { id= is_yet_read(G.main, bhead); if(id==0) { read_libblock(G.main, bhead, LIB_TESTEXT); id= newlibadr(bhead->old); } afbreek= 1; } else id= 0; } fd+= bhead->len+sizeof(BHead); } /* losslingerende blokken vrijgeven */ add_data_adr(0, 0); add_lib_adr(0, 0); return id; } void test_read() { Mesh *me; open_blender("/data/rt.blend"); me= append_part(ID_ME, "mesh"); if(me) { PRINT3(d, d, x, me->totvert, me->totface, me->mface); } me= append_part(ID_ME, "Mesh"); if(me) { PRINT3(d, d, x, me->totvert, me->totface, me->mface); } me= append_part(ID_ME, "Dinges"); if(me) { PRINT3(d, d, x, me->totvert, me->totface, me->mface); } }