This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/blenloader/intern/readfile.c
Ton Roosendaal f88a0a6efd Orange: more relative path code cleanup. Introduced a new call in the
blenlib to correctly convert a relative path to a clean new path:

BLI_cleanup_dir(const char *relabase, char *name);

Only works for directories now.
2005-12-14 13:21:32 +00:00

6260 lines
144 KiB
C

/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "zlib.h"
#ifdef WIN32
#include "winsock2.h"
#include "BLI_winstuff.h"
#endif
#include <stdio.h> // for printf fopen fwrite fclose sprintf FILE
#include <stdlib.h> // for getenv atoi
#include <fcntl.h> // for open
#include <string.h> // for strrchr strncmp strstr
#include <math.h> // for fabs
#ifndef WIN32
#include <unistd.h> // for read close
#include <sys/param.h> // for MAXPATHLEN
#else
#include <io.h> // for open close read
#endif
#include "nla.h"
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_ID.h"
#include "DNA_actuator_types.h"
#include "DNA_camera_types.h"
#include "DNA_controller_types.h"
#include "DNA_constraint_types.h"
#include "DNA_curve_types.h"
#include "DNA_effect_types.h"
#include "DNA_fileglobal_types.h"
#include "DNA_group_types.h"
#include "DNA_ipo_types.h"
#include "DNA_image_types.h"
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_lamp_types.h"
#include "DNA_meta_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_nla_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
#include "DNA_object_fluidsim.h" // NT
#include "DNA_oops_types.h"
#include "DNA_object_force.h"
#include "DNA_packedFile_types.h"
#include "DNA_property_types.h"
#include "DNA_text_types.h"
#include "DNA_view3d_types.h"
#include "DNA_screen_types.h"
#include "DNA_sensor_types.h"
#include "DNA_sdna_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_sound_types.h"
#include "DNA_space_types.h"
#include "DNA_texture_types.h"
#include "DNA_userdef_types.h"
#include "DNA_vfont_types.h"
#include "DNA_world_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BLI_storage_types.h" // for relname flags
#include "BKE_bad_level_calls.h" // for reopen_text build_seqar (from WHILE_SEQ) open_plugin_seq set_rects_butspace check_imasel_copy
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
#include "BKE_deform.h"
#include "BKE_depsgraph.h"
#include "BKE_effect.h" // for give_parteff
#include "BKE_global.h" // for G
#include "BKE_property.h" // for get_property
#include "BKE_lattice.h"
#include "BKE_library.h" // for wich_libbase
#include "BKE_main.h" // for Main
#include "BKE_mesh.h" // for ME_ defines (patching)
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_sca.h" // for init_actuator
#include "BKE_scene.h"
#include "BKE_softbody.h" // sbNew()
#include "BKE_texture.h" // for open_plugin_tex
#include "BKE_utildefines.h" // SWITCH_INT DATA ENDB DNA1 O_BINARY GLOB USER TEST REND
#include "BIF_butspace.h" // for do_versions, patching event codes
#include "BLO_readfile.h"
#include "BLO_undofile.h"
#include "BLO_readblenfile.h" // streaming read pipe, for BLO_readblenfile BLO_readblenfilememory
#include "readfile.h"
#include "genfile.h"
#include "mydevice.h"
#include "blendef.h"
#include <errno.h>
/*
Remark: still a weak point is the newadress() function, that doesnt solve reading from
multiple files at the same time
(added remark: oh, i thought that was solved? will look at that... (ton)
READ
- Existing Library (Main) push or free
- allocate new Main
- load file
- read SDNA
- for each LibBlock
- read LibBlock
- if a Library
- make a new Main
- attach ID's to it
- else
- read associated 'direct data'
- link direct data (internal and to LibBlock)
- read FileGlobal
- read USER data, only when indicated (file is ~/.B.blend)
- free file
- per Library (per Main)
- read file
- read SDNA
- find LibBlocks and attach IDs to Main
- if external LibBlock
- search all Main's
- or it's already read,
- or not read yet
- or make new Main
- per LibBlock
- read recursive
- read associated direct data
- link direct data (internal and to LibBlock)
- free file
- per Library with unread LibBlocks
- read file
- read SDNA
- per LibBlock
- read recursive
- read associated direct data
- link direct data (internal and to LibBlock)
- free file
- join all Mains
- link all LibBlocks and indirect pointers to libblocks
- initialize FileGlobal and copy pointers to Global
*/
/* also occurs in library.c */
/* GS reads the memory pointed at in a specific ordering. There are,
* however two definitions for it. I have jotted them down here, both,
* but I think the first one is actually used. The thing is that
* big-endian systems might read this the wrong way round. OTOH, we
* constructed the IDs that are read out with this macro explicitly as
* well. I expect we'll sort it out soon... */
/* from blendef: */
#define GS(a) (*((short *)(a)))
/* from misc_util: flip the bytes from x */
/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
// only used here in readfile.c
#define SWITCH_LONGINT(a) { \
char s_i, *p_i; \
p_i= (char *)&(a); \
s_i=p_i[0]; p_i[0]=p_i[7]; p_i[7]=s_i; \
s_i=p_i[1]; p_i[1]=p_i[6]; p_i[6]=s_i; \
s_i=p_i[2]; p_i[2]=p_i[5]; p_i[5]=s_i; \
s_i=p_i[3]; p_i[3]=p_i[4]; p_i[4]=s_i; }
// only used here in readfile.c
#define SWITCH_SHORT(a) { \
char s_i, *p_i; \
p_i= (char *)&(a); \
s_i=p_i[0]; p_i[0]=p_i[1]; p_i[1]=s_i; }
/***/
typedef struct OldNew {
void *old, *newp;
int nr;
} OldNew;
typedef struct OldNewMap {
OldNew *entries;
int nentries, entriessize;
int lasthit;
} OldNewMap;
/* local prototypes */
extern short freeN(void *vmemh); /* defined in util.h */
static OldNewMap *oldnewmap_new(void)
{
OldNewMap *onm= MEM_mallocN(sizeof(*onm), "OldNewMap");
onm->lasthit= 0;
onm->nentries= 0;
onm->entriessize= 1024;
onm->entries= MEM_mallocN(sizeof(*onm->entries)*onm->entriessize, "OldNewMap.entries");
return onm;
}
static void oldnewmap_insert(OldNewMap *onm, void *oldaddr, void *newaddr, int nr)
{
OldNew *entry;
if (onm->nentries==onm->entriessize) {
int osize= onm->entriessize;
OldNew *oentries= onm->entries;
onm->entriessize*= 2;
onm->entries= MEM_mallocN(sizeof(*onm->entries)*onm->entriessize, "OldNewMap.entries");
memcpy(onm->entries, oentries, sizeof(*oentries)*osize);
MEM_freeN(oentries);
}
entry= &onm->entries[onm->nentries++];
entry->old= oldaddr;
entry->newp= newaddr;
entry->nr= nr;
}
static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr)
{
int i;
if (onm->lasthit<onm->nentries-1) {
OldNew *entry= &onm->entries[++onm->lasthit];
if (entry->old==addr) {
entry->nr++;
return entry->newp;
}
}
for (i=0; i<onm->nentries; i++) {
OldNew *entry= &onm->entries[i];
if (entry->old==addr) {
onm->lasthit= i;
entry->nr++;
return entry->newp;
}
}
return NULL;
}
static void *oldnewmap_liblookup_and_inc(OldNewMap *onm, void *addr, void *lib)
{
int i;
if (onm->lasthit<onm->nentries-1) {
OldNew *entry= &onm->entries[++onm->lasthit];
if (entry->old==addr) {
ID *id= entry->newp;
if (id && (!lib || id->lib)) {
entry->nr++;
return entry->newp;
}
}
}
/* note; we go backwards over this list, to prevent a case that still needs fix;
if 1 library has blocks used both direct and indirect, it has two entries in this
table, and only the first entry gets remapped in change_lib_adr. */
for (i=onm->nentries-1; i>=0; i--) {
OldNew *entry= &onm->entries[i];
if (entry->old==addr) {
ID *id= entry->newp;
if (id && (!lib || id->lib)) {
entry->nr++;
//if(retval) printf("ack double hit for %s and %s\n", id->name, ((ID *)retval)->name);
return entry->newp;
}
}
}
return NULL;
}
static void *oldnewmap_typelookup_and_inc(OldNewMap *onm, void *addr, void *lib, short type)
{
int i;
if (onm->lasthit<onm->nentries-1) {
OldNew *entry= &onm->entries[++onm->lasthit];
if (entry->old==addr) {
ID *id= entry->newp;
if (id && (GS(id->name) == type) && (!lib || id->lib)) {
entry->nr++;
return entry->newp;
}
}
}
for (i=0; i<onm->nentries; i++) {
OldNew *entry= &onm->entries[i];
if (entry->old==addr) {
ID *id= entry->newp;
if (id && (GS(id->name) == type) && (!lib || id->lib)) {
entry->nr++;
return entry->newp;
}
}
}
return NULL;
}
static void oldnewmap_free_unused(OldNewMap *onm)
{
int i;
for (i=0; i<onm->nentries; i++) {
OldNew *entry= &onm->entries[i];
if (entry->nr==0) {
MEM_freeN(entry->newp);
entry->newp= NULL;
}
}
}
static void oldnewmap_clear(OldNewMap *onm)
{
onm->nentries= 0;
onm->lasthit= 0;
}
static void oldnewmap_free(OldNewMap *onm)
{
MEM_freeN(onm->entries);
MEM_freeN(onm);
}
/***/
static void read_libraries(FileData *basefd, ListBase *mainlist);
/* ************ help functions ***************** */
static void add_main_to_main(Main *mainvar, Main *from)
{
ListBase *lbarray[100], *fromarray[100]; // define in library.c too
int a;
a= set_listbasepointers(mainvar, lbarray);
a= set_listbasepointers(from, fromarray);
while(a--) {
addlisttolist(lbarray[a], fromarray[a]);
}
}
void blo_join_main(ListBase *mainlist)
{
Main *tojoin, *mainl= mainlist->first;
while ((tojoin= mainl->next)) {
add_main_to_main(mainl, tojoin);
BLI_remlink(mainlist, tojoin);
MEM_freeN(tojoin);
}
}
static void split_libdata(ListBase *lb, Main *first)
{
ListBase *lbn;
ID *id, *idnext;
Main *mainvar;
id= lb->first;
while(id) {
idnext= id->next;
if(id->lib) {
mainvar= first;
while(mainvar) {
if(mainvar->curlib==id->lib) {
lbn= wich_libbase(mainvar, GS(id->name));
BLI_remlink(lb, id);
BLI_addtail(lbn, id);
break;
}
mainvar= mainvar->next;
}
if(mainvar==0) printf("error split_libdata\n");
}
id= idnext;
}
}
void blo_split_main(ListBase *mainlist)
{
Main *mainl= mainlist->first;
ListBase *lbarray[30];
Library *lib;
int i;
for (lib= mainl->library.first; lib; lib= lib->id.next) {
Main *libmain= MEM_callocN(sizeof(Main), "libmain");
libmain->curlib= lib;
BLI_addtail(mainlist, libmain);
}
i= set_listbasepointers(mainl, lbarray);
while(i--)
split_libdata(lbarray[i], mainl->next);
}
static void cleanup_path(const char *relabase, char *name)
{
char filename[FILE_MAXFILE];
BLI_splitdirstring(name, filename);
BLI_cleanup_dir(relabase, name);
strcat(name, filename);
}
static Main *blo_find_main(ListBase *mainlist, char *name)
{
Main *m;
Library *lib;
char name1[FILE_MAXDIR+FILE_MAXFILE];
char libname1[FILE_MAXDIR+FILE_MAXFILE];
// printf("G.sce %s\n", G.sce);
/* everything in absolute paths now */
strcpy(name1, name);
cleanup_path(G.sce, name1);
// printf("original in %s\n", name);
// printf("converted in %s\n", name1);
for (m= mainlist->first; m; m= m->next) {
char *libname= (m->curlib)?m->curlib->name:m->name;
// printf("libname %s\n", libname);
strcpy(libname1, libname);
cleanup_path(G.sce, libname1);
// printf("libname1 %s\n", libname1, name1);
if (BLI_streq(name1, libname1)) {
printf("found library %s\n", libname);
return m;
}
}
m= MEM_callocN(sizeof(Main), "find_main");
BLI_addtail(mainlist, m);
lib= alloc_libblock(&m->library, ID_LI, "lib");
strcpy(lib->name, name);
m->curlib= lib;
printf("added new lib %s\n", name);
return m;
}
/* ************ FILE PARSING ****************** */
static void switch_endian_bh4(BHead4 *bhead)
{
/* the ID_.. codes */
if((bhead->code & 0xFFFF)==0) bhead->code >>=16;
if (bhead->code != ENDB) {
SWITCH_INT(bhead->len);
SWITCH_INT(bhead->SDNAnr);
SWITCH_INT(bhead->nr);
}
}
static void switch_endian_bh8(BHead8 *bhead)
{
/* the ID_.. codes */
if((bhead->code & 0xFFFF)==0) bhead->code >>=16;
if (bhead->code != ENDB) {
SWITCH_INT(bhead->len);
SWITCH_INT(bhead->SDNAnr);
SWITCH_INT(bhead->nr);
}
}
static void bh4_from_bh8(BHead *bhead, BHead8 *bhead8, int do_endian_swap)
{
BHead4 *bhead4 = (BHead4 *) bhead;
#if defined(WIN32) && !defined(FREE_WINDOWS)
__int64 old;
#else
long long old;
#endif
bhead4->code= bhead8->code;
bhead4->len= bhead8->len;
if (bhead4->code != ENDB) {
// why is this here ??
if (do_endian_swap) {
SWITCH_LONGINT(bhead8->old);
}
/* this patch is to avoid a long long being read from not-eight aligned positions
is necessary on SGI with -n32 compiling (no, is necessary on
any modern 64bit architecture) */
memcpy(&old, &bhead8->old, 8);
bhead4->old = (int) (old >> 3);
bhead4->SDNAnr= bhead8->SDNAnr;
bhead4->nr= bhead8->nr;
}
}
static void bh8_from_bh4(BHead *bhead, BHead4 *bhead4)
{
BHead8 *bhead8 = (BHead8 *) bhead;
bhead8->code= bhead4->code;
bhead8->len= bhead4->len;
if (bhead8->code != ENDB) {
bhead8->old= bhead4->old;
bhead8->SDNAnr= bhead4->SDNAnr;
bhead8->nr= bhead4->nr;
}
}
static BHeadN *get_bhead(FileData *fd)
{
BHead8 bhead8;
BHead4 bhead4;
BHead bhead;
BHeadN *new_bhead = 0;
int readsize;
if (fd) {
if ( ! fd->eof) {
// First read the bhead structure.
// Depending on the platform the file was written on this can
// be a big or little endian BHead4 or BHead8 structure.
// As usual 'ENDB' (the last *partial* bhead of the file)
// needs some special handling. We don't want to EOF just yet.
if (fd->flags & FD_FLAGS_FILE_POINTSIZE_IS_4) {
bhead4.code = DATA;
readsize = fd->read(fd, &bhead4, sizeof(bhead4));
if (readsize == sizeof(bhead4) || bhead4.code == ENDB) {
if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
switch_endian_bh4(&bhead4);
}
if (fd->flags & FD_FLAGS_POINTSIZE_DIFFERS) {
bh8_from_bh4(&bhead, &bhead4);
} else {
memcpy(&bhead, &bhead4, sizeof(bhead));
}
} else {
fd->eof = 1;
}
} else {
bhead8.code = DATA;
readsize = fd->read(fd, &bhead8, sizeof(bhead8));
if (readsize == sizeof(bhead8) || bhead8.code == ENDB) {
if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
switch_endian_bh8(&bhead8);
}
if (fd->flags & FD_FLAGS_POINTSIZE_DIFFERS) {
bh4_from_bh8(&bhead, &bhead8, (fd->flags & FD_FLAGS_SWITCH_ENDIAN));
} else {
memcpy(&bhead, &bhead8, sizeof(bhead));
}
} else {
fd->eof = 1;
}
}
// bhead now contains the (converted) bhead structure. Now read
// the associated data and put everything in a BHeadN (creative naming !)
if ( ! fd->eof) {
new_bhead = MEM_mallocN(sizeof(BHeadN) + bhead.len, "new_bhead");
if (new_bhead) {
new_bhead->next = new_bhead->prev = 0;
new_bhead->bhead = bhead;
readsize = fd->read(fd, new_bhead + 1, bhead.len);
if (readsize != bhead.len) {
fd->eof = 1;
MEM_freeN(new_bhead);
}
} else {
fd->eof = 1;
}
}
}
}
// We've read a new block. Now add it to the list
// of blocks.
if (new_bhead) {
BLI_addtail(&fd->listbase, new_bhead);
}
return(new_bhead);
}
BHead *blo_firstbhead(FileData *fd)
{
BHeadN *new_bhead;
BHead *bhead = 0;
// Rewind the file
// Read in a new block if necessary
new_bhead = fd->listbase.first;
if (new_bhead == 0) {
new_bhead = get_bhead(fd);
}
if (new_bhead) {
bhead = &new_bhead->bhead;
}
return(bhead);
}
BHead *blo_prevbhead(FileData *fd, BHead *thisblock)
{
BHeadN *bheadn= (BHeadN *) (((char *) thisblock) - (int) (&((BHeadN*)0)->bhead));
BHeadN *prev= bheadn->prev;
return prev?&prev->bhead:NULL;
}
BHead *blo_nextbhead(FileData *fd, BHead *thisblock)
{
BHeadN *new_bhead = 0;
BHead *bhead = 0;
if (thisblock) {
// bhead is actually a sub part of BHeadN
// We calculate the BHeadN pointer from the BHead pointer below
new_bhead = (BHeadN *) (((char *) thisblock) - (int) (&((BHeadN*)0)->bhead));
// get the next BHeadN. If it doesn't exist we read in the next one
new_bhead = new_bhead->next;
if (new_bhead == 0) {
new_bhead = get_bhead(fd);
}
}
if (new_bhead) {
// here we do the reverse:
// go from the BHeadN pointer to the BHead pointer
bhead = &new_bhead->bhead;
}
return(bhead);
}
static void decode_blender_header(FileData *fd)
{
char header[SIZEOFBLENDERHEADER], num[4];
int readsize;
// read in the header data
readsize = fd->read(fd, header, sizeof(header));
if (readsize == sizeof(header)) {
if(strncmp(header, "BLENDER", 7) == 0) {
int remove_this_endian_test= 1;
fd->flags |= FD_FLAGS_FILE_OK;
// what size are pointers in the file ?
if(header[7]=='_') {
fd->flags |= FD_FLAGS_FILE_POINTSIZE_IS_4;
if (sizeof(void *) != 4) {
fd->flags |= FD_FLAGS_POINTSIZE_DIFFERS;
}
} else {
if (sizeof(void *) != 8) {
fd->flags |= FD_FLAGS_POINTSIZE_DIFFERS;
}
}
// is the file saved in a different endian
// than we need ?
if (((((char*)&remove_this_endian_test)[0]==1)?L_ENDIAN:B_ENDIAN) != ((header[8]=='v')?L_ENDIAN:B_ENDIAN)) {
fd->flags |= FD_FLAGS_SWITCH_ENDIAN;
}
// get the version number
memcpy(num, header+9, 3);
num[3] = 0;
fd->fileversion = atoi(num);
}
}
}
static int read_file_dna(FileData *fd)
{
BHead *bhead;
for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
if (bhead->code==DNA1) {
int do_endian_swap= (fd->flags&FD_FLAGS_SWITCH_ENDIAN)?1:0;
fd->filesdna= dna_sdna_from_data(&bhead[1], bhead->len, do_endian_swap);
if (fd->filesdna)
fd->compflags= dna_get_structDNA_compareflags(fd->filesdna, fd->memsdna);
return 1;
} else if (bhead->code==ENDB)
break;
}
return 0;
}
static int fd_read_from_file(FileData *filedata, void *buffer, int size)
{
int readsize = read(filedata->filedes, buffer, size);
if (readsize < 0) {
readsize = EOF;
} else {
filedata->seek += readsize;
}
return (readsize);
}
static int fd_read_gzip_from_file(FileData *filedata, void *buffer, int size)
{
int readsize = gzread(filedata->gzfiledes, buffer, size);
if (readsize < 0) {
readsize = EOF;
} else {
filedata->seek += readsize;
}
return (readsize);
}
static int fd_read_from_memory(FileData *filedata, void *buffer, int size)
{
// don't read more bytes then there are available in the buffer
int readsize = MIN2(size, filedata->buffersize - filedata->seek);
memcpy(buffer, filedata->buffer + filedata->seek, readsize);
filedata->seek += readsize;
return (readsize);
}
static int fd_read_from_memfile(FileData *filedata, void *buffer, int size)
{
static unsigned int seek= 1<<30; /* the current position */
static unsigned int offset= 0; /* size of previous chunks */
static MemFileChunk *chunk=NULL;
if(size==0) return 0;
if(seek != filedata->seek) {
chunk= filedata->memfile->chunks.first;
seek= 0;
while(chunk) {
if(seek + chunk->size > (unsigned) filedata->seek) break;
seek+= chunk->size;
chunk= chunk->next;
}
offset= seek;
seek= filedata->seek;
}
if(chunk) {
/* first check if it's on the end if current chunk */
if( seek-offset == chunk->size) {
offset+= chunk->size;
chunk= chunk->next;
}
/* debug, should never happen */
if(chunk==NULL) {
printf("illegal read, chunk zero\n");
return 0;
}
else if( (seek-offset)+size > chunk->size) {
size= chunk->size - (seek-offset);
printf("chunk too large, clipped to %d\n", size);
}
memcpy(buffer, chunk->buf + (seek-offset), size);
filedata->seek += size;
seek+= size;
return (size);
}
return 0;
}
static FileData *filedata_new(void)
{
extern char DNAstr[]; /* DNA.c */
extern int DNAlen;
FileData *fd = MEM_callocN(sizeof(FileData), "FileData");
fd->filedes = -1;
fd->gzfiledes = NULL;
/* XXX, this doesn't need to be done all the time,
* but it keeps us reentrant, remove once we have
* a lib that provides a nice lock. - zr
*/
fd->memsdna = dna_sdna_from_data(DNAstr, DNAlen, 0);
fd->datamap = oldnewmap_new();
fd->globmap = oldnewmap_new();
fd->libmap = oldnewmap_new();
return fd;
}
static FileData *blo_decode_and_check(FileData *fd, BlendReadError *error_r)
{
decode_blender_header(fd);
if (fd->flags & FD_FLAGS_FILE_OK) {
if (!read_file_dna(fd)) {
*error_r = BRE_INCOMPLETE;
blo_freefiledata(fd);
fd= NULL;
}
} else {
*error_r = BRE_NOT_A_BLEND;
blo_freefiledata(fd);
fd= NULL;
}
return fd;
}
FileData *blo_openblenderfile(char *name, BlendReadError *error_r)
{
gzFile gzfile;
char name1[FILE_MAXDIR+FILE_MAXFILE];
/* relative path rescue... */
if(G.rt==111) {
int len= strlen(name);
printf("old %s\n", name);
while(len-- > 1) {
if(name[len]=='/' && name[len-1]=='/') {
strcpy(name, name+len-1);
printf("new %s\n", name);
break;
}
}
}
/* library files can have stringcodes */
strcpy(name1, name);
if(name[0]=='/' && name[1]=='/')
BLI_convertstringcode(name1, G.sce, 0);
else
strcpy(G.sce, name); // global... is set in blender.c setup_app_data too. should be part of Main immediate?
gzfile= gzopen(name1, "rb");
if (NULL == gzfile) {
*error_r = BRE_UNABLE_TO_OPEN;
return NULL;
} else {
FileData *fd = filedata_new();
fd->gzfiledes = gzfile;
BLI_strncpy(fd->filename, name, sizeof(fd->filename)); // now only in use by library append
fd->read = fd_read_gzip_from_file;
return blo_decode_and_check(fd, error_r);
}
}
FileData *blo_openblendermemory(void *mem, int memsize, BlendReadError *error_r)
{
if (!mem || memsize<SIZEOFBLENDERHEADER) {
*error_r = mem?BRE_UNABLE_TO_READ:BRE_UNABLE_TO_OPEN;
return NULL;
} else {
FileData *fd= filedata_new();
fd->buffer= mem;
fd->buffersize= memsize;
fd->read= fd_read_from_memory;
fd->flags|= FD_FLAGS_NOT_MY_BUFFER;
return blo_decode_and_check(fd, error_r);
}
}
FileData *blo_openblendermemfile(MemFile *memfile, BlendReadError *error_r)
{
if (!memfile) {
*error_r = BRE_UNABLE_TO_OPEN;
return NULL;
} else {
FileData *fd= filedata_new();
fd->memfile= memfile;
fd->read= fd_read_from_memfile;
fd->flags|= FD_FLAGS_NOT_MY_BUFFER;
return blo_decode_and_check(fd, error_r);
}
}
void blo_freefiledata(FileData *fd)
{
if (fd) {
if (fd->filedes != -1) {
close(fd->filedes);
}
if (fd->gzfiledes != NULL)
{
gzclose(fd->gzfiledes);
}
if (fd->buffer && !(fd->flags & FD_FLAGS_NOT_MY_BUFFER)) {
MEM_freeN(fd->buffer);
fd->buffer = 0;
}
// Free all BHeadN data blocks
BLI_freelistN(&fd->listbase);
if (fd->memsdna)
dna_freestructDNA(fd->memsdna);
if (fd->filesdna)
dna_freestructDNA(fd->filesdna);
if (fd->compflags)
MEM_freeN(fd->compflags);
if (fd->datamap)
oldnewmap_free(fd->datamap);
if (fd->globmap)
oldnewmap_free(fd->globmap);
if (fd->libmap && !(fd->flags & FD_FLAGS_NOT_MY_LIBMAP))
oldnewmap_free(fd->libmap);
MEM_freeN(fd);
}
}
/* ************ DIV ****************** */
int BLO_has_bfile_extension(char *str)
{
return (BLI_testextensie(str, ".ble") || BLI_testextensie(str, ".blend")||BLI_testextensie(str, ".blend.gz"));
}
/* ************** OLD POINTERS ******************* */
static void *newdataadr(FileData *fd, void *adr) /* only direct databocks */
{
return oldnewmap_lookup_and_inc(fd->datamap, adr);
}
static void *newglobadr(FileData *fd, void *adr) /* direct datablocks with global linking */
{
return oldnewmap_lookup_and_inc(fd->globmap, adr);
}
static void *newlibadr(FileData *fd, void *lib, void *adr) /* only lib data */
{
return oldnewmap_liblookup_and_inc(fd->libmap, adr, lib);
}
static void *newlibadr_us_type(FileData *fd, void *lib, short type, void *adr) /* only Lib data */
{
ID *id= oldnewmap_typelookup_and_inc(fd->libmap, adr, lib, type);
if (id) {
id->us++;
}
return id;
}
static void *newlibadr_us(FileData *fd, void *lib, void *adr) /* increases user number */
{
ID *id= newlibadr(fd, lib, adr);
if(id) {
id->us++;
}
return id;
}
static void change_libadr(FileData *fd, void *old, void *new)
{
int i;
/* changed one thing here, the old change_libadr
* only remapped addresses that had an id->lib,
* but that doesn't make sense to me... its an
* old pointer, period, it needs to be remapped. - zr
*/
/*
* Ton seemed to think it was necessary to look
* through all entries, and not return after finding
* a match, leaving this cryptic comment,
* // no return, maybe there can be more?
*
* That doesn't make sense to me either but I am
* too scared to remove it... it only would make
* sense if two distinct old address map to the
* same new address - obviously that shouldn't happen
* because memory addresses are unique.
*
* The only case it might happen is when two distinct
* libraries are mapped using the same table... this
* won't work to start with... At some point this
* all needs to be made sense of and made understandable,
* but I'm afraid I don't have time now. -zr
*
*/
/* the code is nasty, and needs a lot of energy to get into full understanding
again... i now translate dutch comments, maybe that gives me more insight!
But i guess it has to do with the assumption that 2 addresses can be allocated
in different sessions, and therefore be the same... like the remark in the top
of this c file (ton) */
for (i=0; i<fd->libmap->nentries; i++) {
OldNew *entry= &fd->libmap->entries[i];
if (old==entry->newp) {
entry->newp= new;
break;
}
}
}
/* ********** END OLD POINTERS ****************** */
/* ********** READ FILE ****************** */
static void switch_endian_structs(struct SDNA *filesdna, BHead *bhead)
{
int blocksize, nblocks;
char *data;
data= (char *)(bhead+1); /* BHEAD+DATA dependancy */
blocksize= filesdna->typelens[ filesdna->structs[bhead->SDNAnr][0] ];
nblocks= bhead->nr;
while(nblocks--) {
dna_switch_endian_struct(filesdna, bhead->SDNAnr, data);
data+= blocksize;
}
}
static void *read_struct(FileData *fd, BHead *bh, char *blockname)
{
void *temp= NULL;
if (bh->len) {
if (bh->SDNAnr && (fd->flags & FD_FLAGS_SWITCH_ENDIAN))
switch_endian_structs(fd->filesdna, bh);
if (fd->compflags[bh->SDNAnr]) { /* flag==0: doesn't exist anymore */
if(fd->compflags[bh->SDNAnr]==2) {
temp= dna_reconstruct(fd->memsdna, fd->filesdna, fd->compflags, bh->SDNAnr, bh->nr, (bh+1));
} else {
temp= MEM_mallocN(bh->len, blockname);
memcpy(temp, (bh+1), bh->len); /* BHEAD+DATA dependancy */
}
}
}
return temp;
}
static void link_list(FileData *fd, ListBase *lb) /* only direct data */
{
Link *ln, *prev;
if(lb->first==0) return;
lb->first= newdataadr(fd, lb->first);
ln= lb->first;
prev= 0;
while(ln) {
ln->next= newdataadr(fd, ln->next);
ln->prev= prev;
prev= ln;
ln= ln->next;
}
lb->last= prev;
}
static void link_glob_list(FileData *fd, ListBase *lb) /* for glob data */
{
Link *ln, *prev;
void *poin;
if(lb->first==0) return;
poin= newdataadr(fd, lb->first);
if(lb->first) {
oldnewmap_insert(fd->globmap, lb->first, poin, 0);
}
lb->first= poin;
ln= lb->first;
prev= 0;
while(ln) {
poin= newdataadr(fd, ln->next);
if(ln->next) {
oldnewmap_insert(fd->globmap, ln->next, poin, 0);
}
ln->next= poin;
ln->prev= prev;
prev= ln;
ln= ln->next;
}
lb->last= prev;
}
static void test_pointer_array(FileData *fd, void **mat)
{
#if defined(WIN32) && !defined(FREE_WINDOWS)
__int64 *lpoin, *lmat;
#else
long long *lpoin, *lmat;
#endif
int len, *ipoin, *imat;
/* manually convert the pointer array in
* the old dna format to a pointer array in
* the new dna format.
*/
if(*mat) {
len= MEM_allocN_len(*mat)/fd->filesdna->pointerlen;
if(fd->filesdna->pointerlen==8 && fd->memsdna->pointerlen==4) {
ipoin=imat= MEM_mallocN( len*4, "newmatar");
lpoin= *mat;
while(len-- > 0) {
if((fd->flags & FD_FLAGS_SWITCH_ENDIAN))
SWITCH_LONGINT(*lpoin);
*ipoin= (int) ((*lpoin) >> 3);
ipoin++;
lpoin++;
}
MEM_freeN(*mat);
*mat= imat;
}
if(fd->filesdna->pointerlen==4 && fd->memsdna->pointerlen==8) {
lpoin=lmat= MEM_mallocN( len*8, "newmatar");
ipoin= *mat;
while(len-- > 0) {
*lpoin= *ipoin;
ipoin++;
lpoin++;
}
MEM_freeN(*mat);
*mat= lmat;
}
}
}
/* ************ READ PACKEDFILE *************** */
static PackedFile *direct_link_packedfile(FileData *fd, PackedFile *oldpf)
{
PackedFile *pf= newdataadr(fd, oldpf);
if (pf) {
pf->data= newdataadr(fd, pf->data);
}
return pf;
}
/* ************ READ SCRIPTLINK *************** */
static void lib_link_scriptlink(FileData *fd, ID *id, ScriptLink *slink)
{
int i;
for(i=0; i<slink->totscript; i++) {
slink->scripts[i]= newlibadr(fd, id->lib, slink->scripts[i]);
}
}
static void direct_link_scriptlink(FileData *fd, ScriptLink *slink)
{
slink->scripts= newdataadr(fd, slink->scripts);
test_pointer_array(fd, (void **)&slink->scripts);
slink->flag= newdataadr(fd, slink->flag);
if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
int a;
for(a=0; a<slink->totscript; a++) {
SWITCH_SHORT(slink->flag[a]);
}
}
}
/* ************ READ ARMATURE ***************** */
static void lib_link_nlastrips(FileData *fd, ID *id, ListBase *striplist)
{
bActionStrip *strip;
for (strip=striplist->first; strip; strip=strip->next){
strip->object = newlibadr(fd, id->lib, strip->object);
strip->act = newlibadr_us(fd, id->lib, strip->act);
strip->ipo = newlibadr(fd, id->lib, strip->ipo);
}
}
static void lib_link_constraint_channels(FileData *fd, ID *id, ListBase *chanbase)
{
bConstraintChannel *chan;
for (chan=chanbase->first; chan; chan=chan->next){
chan->ipo = newlibadr_us(fd, id->lib, chan->ipo);
}
}
static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
{
bConstraint *con;
for (con = conlist->first; con; con=con->next) {
/* patch for error introduced by changing constraints (dunno how) */
/* if con->data type changes, dna cannot resolve the pointer! (ton) */
if(con->data==NULL) {
con->type= CONSTRAINT_TYPE_NULL;
}
switch (con->type) {
case CONSTRAINT_TYPE_ACTION:
{
bActionConstraint *data;
data= ((bActionConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
data->act = newlibadr(fd, id->lib, data->act);
}
break;
case CONSTRAINT_TYPE_LOCLIKE:
{
bLocateLikeConstraint *data;
data= ((bLocateLikeConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
};
break;
case CONSTRAINT_TYPE_ROTLIKE:
{
bRotateLikeConstraint *data;
data= ((bRotateLikeConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
};
break;
case CONSTRAINT_TYPE_KINEMATIC:
{
bKinematicConstraint *data;
data = ((bKinematicConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
}
break;
case CONSTRAINT_TYPE_TRACKTO:
{
bTrackToConstraint *data;
data = ((bTrackToConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
}
break;
case CONSTRAINT_TYPE_MINMAX:
{
bMinMaxConstraint *data;
data = ((bMinMaxConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
}
break;
case CONSTRAINT_TYPE_LOCKTRACK:
{
bLockTrackConstraint *data;
data= ((bLockTrackConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
};
break;
case CONSTRAINT_TYPE_FOLLOWPATH:
{
bFollowPathConstraint *data;
data= ((bFollowPathConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
};
break;
case CONSTRAINT_TYPE_DISTANCELIMIT:
{
bDistanceLimitConstraint *data;
data= ((bDistanceLimitConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
};
break;
case CONSTRAINT_TYPE_STRETCHTO:
{
bStretchToConstraint *data;
data= ((bStretchToConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
};
break;
case CONSTRAINT_TYPE_NULL:
break;
}
}
}
static void direct_link_constraints(FileData *fd, ListBase *lb)
{
bConstraint *cons;
link_list(fd, lb);
for (cons=lb->first; cons; cons=cons->next) {
cons->data = newdataadr(fd, cons->data);
}
}
static void lib_link_pose(FileData *fd, Object *ob, bPose *pose)
{
bPoseChannel *pchan;
bArmature *arm= ob->data;
if (!pose)
return;
for (pchan = pose->chanbase.first; pchan; pchan=pchan->next) {
lib_link_constraints(fd, (ID *)ob, &pchan->constraints);
// hurms... loop in a loop, but yah... later... (ton)
pchan->bone= get_named_bone(arm, pchan->name);
pchan->custom= newlibadr(fd, arm->id.lib, pchan->custom);
}
}
static void lib_link_armature(FileData *fd, Main *main)
{
bArmature *arm;
arm= main->armature.first;
while(arm) {
if(arm->id.flag & LIB_NEEDLINK) {
arm->id.flag -= LIB_NEEDLINK;
}
arm= arm->id.next;
}
}
static void lib_link_action(FileData *fd, Main *main)
{
bAction *act;
bActionChannel *chan;
act= main->action.first;
while(act) {
if(act->id.flag & LIB_NEEDLINK) {
act->id.flag -= LIB_NEEDLINK;
for (chan=act->chanbase.first; chan; chan=chan->next) {
chan->ipo= newlibadr_us(fd, act->id.lib, chan->ipo);
lib_link_constraint_channels(fd, &act->id, &chan->constraintChannels);
}
}
act= act->id.next;
}
}
static void direct_link_bones(FileData *fd, Bone* bone)
{
Bone *child;
bone->parent= newdataadr(fd, bone->parent);
link_list(fd, &bone->childbase);
for (child=bone->childbase.first; child; child=child->next) {
direct_link_bones(fd, child);
}
}
static void direct_link_action(FileData *fd, bAction *act)
{
bActionChannel *achan;
link_list(fd, &act->chanbase);
for (achan = act->chanbase.first; achan; achan=achan->next)
link_list(fd, &achan->constraintChannels);
}
static void direct_link_armature(FileData *fd, bArmature *arm)
{
Bone *bone;
link_list(fd, &arm->bonebase);
bone=arm->bonebase.first;
while (bone) {
direct_link_bones(fd, bone);
bone=bone->next;
}
}
/* ************ READ CAMERA ***************** */
static void lib_link_camera(FileData *fd, Main *main)
{
Camera *ca;
ca= main->camera.first;
while(ca) {
if(ca->id.flag & LIB_NEEDLINK) {
ca->ipo= newlibadr_us(fd, ca->id.lib, ca->ipo);
lib_link_scriptlink(fd, &ca->id, &ca->scriptlink);
ca->id.flag -= LIB_NEEDLINK;
}
ca= ca->id.next;
}
}
static void direct_link_camera(FileData *fd, Camera *ca)
{
direct_link_scriptlink(fd, &ca->scriptlink);
}
/* ************ READ LATTICE ***************** */
static void lib_link_latt(FileData *fd, Main *main)
{
Lattice *lt;
lt= main->latt.first;
while(lt) {
if(lt->id.flag & LIB_NEEDLINK) {
lt->ipo= newlibadr_us(fd, lt->id.lib, lt->ipo);
lt->key= newlibadr_us(fd, lt->id.lib, lt->key);
lt->id.flag -= LIB_NEEDLINK;
}
lt= lt->id.next;
}
}
static void direct_link_latt(FileData *fd, Lattice *lt)
{
lt->def= newdataadr(fd, lt->def);
}
/* ************ READ LAMP ***************** */
static void lib_link_lamp(FileData *fd, Main *main)
{
Lamp *la;
MTex *mtex;
int a;
la= main->lamp.first;
while(la) {
if(la->id.flag & LIB_NEEDLINK) {
for(a=0; a<MAX_MTEX; a++) {
mtex= la->mtex[a];
if(mtex) {
mtex->tex= newlibadr_us(fd, la->id.lib, mtex->tex);
mtex->object= newlibadr(fd, la->id.lib, mtex->object);
}
}
la->ipo= newlibadr_us(fd, la->id.lib, la->ipo);
lib_link_scriptlink(fd, &la->id, &la->scriptlink);
la->id.flag -= LIB_NEEDLINK;
}
la= la->id.next;
}
}
static void direct_link_lamp(FileData *fd, Lamp *la)
{
int a;
direct_link_scriptlink(fd, &la->scriptlink);
for(a=0; a<MAX_MTEX; a++) {
la->mtex[a]= newdataadr(fd, la->mtex[a]);
}
}
/* ************ READ keys ***************** */
static void lib_link_key(FileData *fd, Main *main)
{
Key *key;
key= main->key.first;
while(key) {
if(key->id.flag & LIB_NEEDLINK) {
key->ipo= newlibadr_us(fd, key->id.lib, key->ipo);
key->from= newlibadr(fd, key->id.lib, key->from);
key->id.flag -= LIB_NEEDLINK;
}
key= key->id.next;
}
}
static void switch_endian_keyblock(Key *key, KeyBlock *kb)
{
int elemsize, a, b;
char *data, *poin, *cp;
elemsize= key->elemsize;
data= kb->data;
for(a=0; a<kb->totelem; a++) {
cp= key->elemstr;
poin= data;
while( cp[0] ) { /* cp[0]==amount */
switch(cp[1]) { /* cp[1]= type */
case IPO_FLOAT:
case IPO_BPOINT:
case IPO_BEZTRIPLE:
b= cp[0];
while(b--) {
SWITCH_INT((*poin));
poin+= 4;
}
break;
}
cp+= 2;
}
data+= elemsize;
}
}
static void direct_link_key(FileData *fd, Key *key)
{
KeyBlock *kb;
link_list(fd, &(key->block));
key->refkey= newdataadr(fd, key->refkey);
kb= key->block.first;
while(kb) {
kb->data= newdataadr(fd, kb->data);
if(fd->flags & FD_FLAGS_SWITCH_ENDIAN)
switch_endian_keyblock(key, kb);
kb= kb->next;
}
}
/* ************ READ mball ***************** */
static void lib_link_mball(FileData *fd, Main *main)
{
MetaBall *mb;
int a;
mb= main->mball.first;
while(mb) {
if(mb->id.flag & LIB_NEEDLINK) {
for(a=0; a<mb->totcol; a++) mb->mat[a]= newlibadr_us(fd, mb->id.lib, mb->mat[a]);
mb->ipo= newlibadr_us(fd, mb->id.lib, mb->ipo);
mb->id.flag -= LIB_NEEDLINK;
}
mb= mb->id.next;
}
}
static void direct_link_mball(FileData *fd, MetaBall *mb)
{
mb->mat= newdataadr(fd, mb->mat);
test_pointer_array(fd, (void **)&mb->mat);
link_list(fd, &(mb->elems));
mb->disp.first= mb->disp.last= 0;
mb->bb= 0;
}
/* ************ READ WORLD ***************** */
static void lib_link_world(FileData *fd, Main *main)
{
World *wrld;
MTex *mtex;
int a;
wrld= main->world.first;
while(wrld) {
if(wrld->id.flag & LIB_NEEDLINK) {
wrld->ipo= newlibadr_us(fd, wrld->id.lib, wrld->ipo);
for(a=0; a<MAX_MTEX; a++) {
mtex= wrld->mtex[a];
if(mtex) {
mtex->tex= newlibadr_us(fd, wrld->id.lib, mtex->tex);
mtex->object= newlibadr(fd, wrld->id.lib, mtex->object);
}
}
lib_link_scriptlink(fd, &wrld->id, &wrld->scriptlink);
wrld->id.flag -= LIB_NEEDLINK;
}
wrld= wrld->id.next;
}
}
static void direct_link_world(FileData *fd, World *wrld)
{
int a;
direct_link_scriptlink(fd, &wrld->scriptlink);
for(a=0; a<MAX_MTEX; a++) {
wrld->mtex[a]= newdataadr(fd, wrld->mtex[a]);
}
}
/* ************ READ IPO ***************** */
static void lib_link_ipo(FileData *fd, Main *main)
{
Ipo *ipo;
ipo= main->ipo.first;
while(ipo) {
if(ipo->id.flag & LIB_NEEDLINK) {
IpoCurve *icu;
for(icu= ipo->curve.first; icu; icu= icu->next) {
if(icu->driver)
icu->driver->ob= newlibadr(fd, ipo->id.lib, icu->driver->ob);
}
ipo->id.flag -= LIB_NEEDLINK;
}
ipo= ipo->id.next;
}
}
static void direct_link_ipo(FileData *fd, Ipo *ipo)
{
IpoCurve *icu;
link_list(fd, &(ipo->curve));
icu= ipo->curve.first;
while(icu) {
icu->bezt= newdataadr(fd, icu->bezt);
icu->bp= newdataadr(fd, icu->bp);
icu->driver= newdataadr(fd, icu->driver);
icu= icu->next;
}
}
/* ************ READ VFONT ***************** */
static void lib_link_vfont(FileData *fd, Main *main)
{
VFont *vf;
vf= main->vfont.first;
while(vf) {
if(vf->id.flag & LIB_NEEDLINK) {
vf->id.flag -= LIB_NEEDLINK;
}
vf= vf->id.next;
}
}
static void direct_link_vfont(FileData *fd, VFont *vf)
{
vf->data= NULL;
vf->packedfile= direct_link_packedfile(fd, vf->packedfile);
}
/* ************ READ TEXT ****************** */
static void lib_link_text(FileData *fd, Main *main)
{
Text *text;
text= main->text.first;
while(text) {
if(text->id.flag & LIB_NEEDLINK) {
text->id.flag -= LIB_NEEDLINK;
}
text= text->id.next;
}
}
static void direct_link_text(FileData *fd, Text *text)
{
TextLine *ln;
text->name= newdataadr(fd, text->name);
text->undo_pos= -1;
text->undo_len= TXT_INIT_UNDO;
text->undo_buf= MEM_mallocN(text->undo_len, "undo buf");
text->compiled= NULL;
/*
if(text->flags & TXT_ISEXT) {
reopen_text(text);
} else {
*/
link_list(fd, &text->lines);
text->curl= newdataadr(fd, text->curl);
text->sell= newdataadr(fd, text->sell);
ln= text->lines.first;
while(ln) {
ln->line= newdataadr(fd, ln->line);
ln->format= NULL;
if (ln->len != (int) strlen(ln->line)) {
printf("Error loading text, line lengths differ\n");
ln->len = strlen(ln->line);
}
ln= ln->next;
}
text->flags = (text->flags|TXT_ISTMP) & ~TXT_ISEXT;
text->id.us= 1;
}
/* ************ READ IMAGE ***************** */
static void lib_link_image(FileData *fd, Main *main)
{
Image *ima;
ima= main->image.first;
while (ima) {
if(ima->id.flag & LIB_NEEDLINK) {
ima->id.flag -= LIB_NEEDLINK;
}
ima= ima->id.next;
}
}
static void direct_link_image(FileData *fd, Image *ima)
{
ima->ibuf= 0;
ima->anim= 0;
memset(ima->mipmap, 0, sizeof(ima->mipmap));
ima->repbind= 0;
ima->bindcode= 0;
ima->packedfile = direct_link_packedfile(fd, ima->packedfile);
ima->ok= 1;
}
/* ************ READ CURVE ***************** */
static void lib_link_curve(FileData *fd, Main *main)
{
Curve *cu;
int a;
cu= main->curve.first;
while(cu) {
if(cu->id.flag & LIB_NEEDLINK) {
for(a=0; a<cu->totcol; a++) cu->mat[a]= newlibadr_us(fd, cu->id.lib, cu->mat[a]);
cu->bevobj= newlibadr(fd, cu->id.lib, cu->bevobj);
cu->taperobj= newlibadr(fd, cu->id.lib, cu->taperobj);
cu->textoncurve= newlibadr(fd, cu->id.lib, cu->textoncurve);
cu->vfont= newlibadr_us(fd, cu->id.lib, cu->vfont);
cu->vfontb= newlibadr_us(fd, cu->id.lib, cu->vfontb);
cu->vfonti= newlibadr_us(fd, cu->id.lib, cu->vfonti);
cu->vfontbi= newlibadr_us(fd, cu->id.lib, cu->vfontbi);
cu->ipo= newlibadr_us(fd, cu->id.lib, cu->ipo);
cu->key= newlibadr_us(fd, cu->id.lib, cu->key);
cu->id.flag -= LIB_NEEDLINK;
}
cu= cu->id.next;
}
}
static void switch_endian_knots(Nurb *nu)
{
int len;
if(nu->knotsu) {
len= KNOTSU(nu);
while(len--) {
SWITCH_INT(nu->knotsu[len]);
}
}
if(nu->knotsv) {
len= KNOTSV(nu);
while(len--) {
SWITCH_INT(nu->knotsv[len]);
}
}
}
static void direct_link_curve(FileData *fd, Curve *cu)
{
Nurb *nu;
TextBox *tb;
cu->mat= newdataadr(fd, cu->mat);
test_pointer_array(fd, (void **)&cu->mat);
cu->str= newdataadr(fd, cu->str);
cu->strinfo= newdataadr(fd, cu->strinfo);
cu->tb= newdataadr(fd, cu->tb);
if(cu->vfont==0) link_list(fd, &(cu->nurb));
else {
cu->nurb.first=cu->nurb.last= 0;
tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "TextBoxread");
if (cu->tb) {
memcpy(tb, cu->tb, cu->totbox*sizeof(TextBox));
MEM_freeN(cu->tb);
cu->tb= tb;
} else {
cu->totbox = 1;
cu->actbox = 1;
cu->tb = tb;
cu->tb[0].w = cu->linewidth;
}
if (cu->wordspace == 0.0) cu->wordspace = 1.0;
}
cu->bev.first=cu->bev.last= 0;
cu->disp.first=cu->disp.last= 0;
cu->path= 0;
nu= cu->nurb.first;
while(nu) {
nu->bezt= newdataadr(fd, nu->bezt);
nu->bp= newdataadr(fd, nu->bp);
nu->knotsu= newdataadr(fd, nu->knotsu);
nu->knotsv= newdataadr(fd, nu->knotsv);
if (cu->vfont==0) nu->charidx= nu->mat_nr;
if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
switch_endian_knots(nu);
}
nu= nu->next;
}
cu->bb= NULL;
}
/* ************ READ TEX ***************** */
static void lib_link_texture(FileData *fd, Main *main)
{
Tex *tex;
tex= main->tex.first;
while(tex) {
if(tex->id.flag & LIB_NEEDLINK) {
tex->ima= newlibadr_us(fd, tex->id.lib, tex->ima);
tex->ipo= newlibadr_us(fd, tex->id.lib, tex->ipo);
if(tex->env) tex->env->object= newlibadr(fd, tex->id.lib, tex->env->object);
tex->id.flag -= LIB_NEEDLINK;
}
tex= tex->id.next;
}
}
static void direct_link_texture(FileData *fd, Tex *tex)
{
tex->plugin= newdataadr(fd, tex->plugin);
if(tex->plugin) {
tex->plugin->handle= 0;
open_plugin_tex(tex->plugin);
}
tex->coba= newdataadr(fd, tex->coba);
tex->env= newdataadr(fd, tex->env);
if(tex->env) {
tex->env->ima= 0;
memset(tex->env->cube, 0, 6*sizeof(void *));
tex->env->ok= 0;
}
}
/* ************ READ MATERIAL ***************** */
static void lib_link_material(FileData *fd, Main *main)
{
Material *ma;
MaterialLayer *ml;
MTex *mtex;
int a;
ma= main->mat.first;
while(ma) {
if(ma->id.flag & LIB_NEEDLINK) {
ma->ipo= newlibadr_us(fd, ma->id.lib, ma->ipo);
ma->group= newlibadr_us(fd, ma->id.lib, ma->group);
for(a=0; a<MAX_MTEX; a++) {
mtex= ma->mtex[a];
if(mtex) {
mtex->tex= newlibadr_us(fd, ma->id.lib, mtex->tex);
mtex->object= newlibadr(fd, ma->id.lib, mtex->object);
}
}
lib_link_scriptlink(fd, &ma->id, &ma->scriptlink);
for (ml=ma->layers.first; ml; ml=ml->next)
ml->mat= newlibadr_us(fd, ma->id.lib, ml->mat);
ma->id.flag -= LIB_NEEDLINK;
}
ma= ma->id.next;
}
}
static void direct_link_material(FileData *fd, Material *ma)
{
int a;
for(a=0; a<MAX_MTEX; a++) {
ma->mtex[a]= newdataadr(fd, ma->mtex[a]);
}
ma->ramp_col= newdataadr(fd, ma->ramp_col);
ma->ramp_spec= newdataadr(fd, ma->ramp_spec);
direct_link_scriptlink(fd, &ma->scriptlink);
link_list(fd, &ma->layers);
}
/* ************ READ MESH ***************** */
static void lib_link_mesh(FileData *fd, Main *main)
{
Mesh *me;
me= main->mesh.first;
while(me) {
if(me->id.flag & LIB_NEEDLINK) {
int i;
/* this check added for python created meshes */
if(me->mat) {
for(i=0; i<me->totcol; i++)
me->mat[i]= newlibadr_us(fd, me->id.lib, me->mat[i]);
}
else me->totcol= 0;
me->ipo= newlibadr_us(fd, me->id.lib, me->ipo);
me->key= newlibadr_us(fd, me->id.lib, me->key);
me->texcomesh= newlibadr_us(fd, me->id.lib, me->texcomesh);
if(me->tface) {
TFace *tfaces= me->tface;
for (i=0; i<me->totface; i++) {
TFace *tf= &tfaces[i];
tf->tpage= newlibadr(fd, me->id.lib, tf->tpage);
if(tf->tpage) {
Image *ima= tf->tpage;
if(ima->id.us==0)
ima->id.us= 1;
}
}
}
me->id.flag -= LIB_NEEDLINK;
}
me= me->id.next;
}
}
static void direct_link_dverts(FileData *fd, int count, MDeformVert *mdverts)
{
int i;
if (!mdverts)
return;
for (i=0; i<count; i++) {
mdverts[i].dw=newdataadr(fd, mdverts[i].dw);
if (!mdverts[i].dw)
mdverts[i].totweight=0;
}
}
static void direct_link_mesh(FileData *fd, Mesh *mesh)
{
mesh->mat= newdataadr(fd, mesh->mat);
test_pointer_array(fd, (void **)&mesh->mat);
mesh->mvert= newdataadr(fd, mesh->mvert);
mesh->medge= newdataadr(fd, mesh->medge);
mesh->mface= newdataadr(fd, mesh->mface);
mesh->tface= newdataadr(fd, mesh->tface);
mesh->mcol= newdataadr(fd, mesh->mcol);
mesh->msticky= newdataadr(fd, mesh->msticky);
mesh->dvert= newdataadr(fd, mesh->dvert);
direct_link_dverts(fd, mesh->totvert, mesh->dvert);
mesh->bb= NULL;
mesh->oc= 0;
mesh->dface= NULL;
if (mesh->tface) {
TFace *tfaces= mesh->tface;
int i;
for (i=0; i<mesh->totface; i++) {
TFace *tf= &tfaces[i];
if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
SWITCH_INT(tf->col[0]);
SWITCH_INT(tf->col[1]);
SWITCH_INT(tf->col[2]);
SWITCH_INT(tf->col[3]);
}
}
}
}
/* ************ READ OBJECT ***************** */
static void lib_link_modifiers__linkModifiers(void *userData, Object *ob, Object **obpoin)
{
FileData *fd = userData;
*obpoin = newlibadr(fd, ob->id.lib, *obpoin);
}
static void lib_link_modifiers(FileData *fd, Object *ob)
{
modifiers_foreachObjectLink(ob, lib_link_modifiers__linkModifiers, fd);
}
static void lib_link_object(FileData *fd, Main *main)
{
Object *ob;
PartEff *paf;
bSensor *sens;
bController *cont;
bActuator *act;
void *poin;
int warn=0, a;
ob= main->object.first;
while(ob) {
if(ob->id.flag & LIB_NEEDLINK) {
ob->parent= newlibadr(fd, ob->id.lib, ob->parent);
ob->track= newlibadr(fd, ob->id.lib, ob->track);
ob->ipo= newlibadr_us(fd, ob->id.lib, ob->ipo);
ob->action = newlibadr_us(fd, ob->id.lib, ob->action);
ob->dup_group= newlibadr_us(fd, ob->id.lib, ob->dup_group);
poin= ob->data;
ob->data= newlibadr_us(fd, ob->id.lib, ob->data);
if(ob->data==NULL && poin!=NULL) {
ob->type= OB_EMPTY;
warn= 1;
if(ob->id.lib) printf("Can't find obdata of %s lib %s\n", ob->id.name+2, ob->id.lib->name);
else printf("Object %s lost data. Lib:%x\n", ob->id.name+2, (unsigned int) ob->id.lib);
}
for(a=0; a<ob->totcol; a++) ob->mat[a]= newlibadr_us(fd, ob->id.lib, ob->mat[a]);
ob->id.flag -= LIB_NEEDLINK;
/* if id.us==0 a new base will be created later on */
/* WARNING! Also check expand_object(), should reflect the stuff below. */
lib_link_pose(fd, ob, ob->pose);
lib_link_constraints(fd, &ob->id, &ob->constraints);
lib_link_nlastrips(fd, &ob->id, &ob->nlastrips);
lib_link_constraint_channels(fd, &ob->id, &ob->constraintChannels);
for(paf= ob->effect.first; paf; paf= paf->next) {
if(paf->type==EFF_PARTICLE) {
paf->group= newlibadr_us(fd, ob->id.lib, paf->group);
}
}
sens= ob->sensors.first;
while(sens) {
if(ob->id.lib==NULL) { // done in expand_main
for(a=0; a<sens->totlinks; a++) {
sens->links[a]= newglobadr(fd, sens->links[a]);
}
}
if(sens->type==SENS_TOUCH) {
bTouchSensor *ts= sens->data;
ts->ma= newlibadr(fd, ob->id.lib, ts->ma);
}
else if(sens->type==SENS_MESSAGE) {
bMessageSensor *ms= sens->data;
ms->fromObject=
newlibadr(fd, ob->id.lib, ms->fromObject);
}
sens= sens->next;
}
cont= ob->controllers.first;
while(cont) {
if(ob->id.lib==NULL) { // done in expand_main
for(a=0; a<cont->totlinks; a++) {
cont->links[a]= newglobadr(fd, cont->links[a]);
}
}
if(cont->type==CONT_PYTHON) {
bPythonCont *pc= cont->data;
pc->text= newlibadr(fd, ob->id.lib, pc->text);
}
cont->slinks= NULL;
cont->totslinks= 0;
cont= cont->next;
}
act= ob->actuators.first;
while(act) {
if(act->type==ACT_SOUND) {
bSoundActuator *sa= act->data;
sa->sound= newlibadr_us(fd, ob->id.lib, sa->sound);
}
else if(act->type==ACT_CD) {
/* bCDActuator *cda= act->data; */
}
else if(act->type==ACT_GAME) {
/* bGameActuator *ga= act->data; */
}
else if(act->type==ACT_CAMERA) {
bCameraActuator *ca= act->data;
ca->ob= newlibadr(fd, ob->id.lib, ca->ob);
}
/* leave this one, it's obsolete but necessary to read for conversion */
else if(act->type==ACT_ADD_OBJECT) {
bAddObjectActuator *eoa= act->data;
if(eoa) eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob);
}
else if(act->type==ACT_EDIT_OBJECT) {
bEditObjectActuator *eoa= act->data;
if(eoa==NULL) {
init_actuator(act);
}
eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob);
eoa->me= newlibadr(fd, ob->id.lib, eoa->me);
}
else if(act->type==ACT_SCENE) {
bSceneActuator *sa= act->data;
sa->camera= newlibadr(fd, ob->id.lib, sa->camera);
sa->scene= newlibadr(fd, ob->id.lib, sa->scene);
}
else if(act->type==ACT_ACTION) {
bActionActuator *aa= act->data;
aa->act= newlibadr(fd, ob->id.lib, aa->act);
}
else if(act->type==ACT_PROPERTY) {
bPropertyActuator *pa= act->data;
pa->ob= newlibadr(fd, ob->id.lib, pa->ob);
}
else if(act->type==ACT_MESSAGE) {
bMessageActuator *ma= act->data;
ma->toObject= newlibadr(fd, ob->id.lib, ma->toObject);
}
act= act->next;
}
lib_link_scriptlink(fd, &ob->id, &ob->scriptlink);
lib_link_modifiers(fd, ob);
}
ob= ob->id.next;
}
if(warn) error("WARNING IN CONSOLE");
}
static void direct_link_pose(FileData *fd, bPose *pose) {
bPoseChannel *pchan;
if (!pose)
return;
link_list(fd, &pose->chanbase);
for (pchan = pose->chanbase.first; pchan; pchan=pchan->next) {
pchan->bone= NULL;
pchan->parent= newdataadr(fd, pchan->parent);
pchan->child= newdataadr(fd, pchan->child);
direct_link_constraints(fd, &pchan->constraints);
pchan->iktree.first= pchan->iktree.last= NULL;
pchan->path= NULL;
}
}
static void direct_link_modifiers(FileData *fd, ListBase *lb)
{
ModifierData *md;
link_list(fd, lb);
for (md=lb->first; md; md=md->next) {
md->error = NULL;
if (md->type==eModifierType_Subsurf) {
SubsurfModifierData *smd = (SubsurfModifierData*) md;
smd->emCache = smd->mCache = 0;
} else if (md->type==eModifierType_Hook) {
HookModifierData *hmd = (HookModifierData*) md;
hmd->indexar= newdataadr(fd, hmd->indexar);
if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
int a;
for(a=0; a<hmd->totindex; a++) {
SWITCH_INT(hmd->indexar[a]);
}
}
}
}
}
static void direct_link_object(FileData *fd, Object *ob)
{
PartEff *paf;
bProperty *prop;
bSensor *sens;
bController *cont;
bActuator *act;
int a;
ob->disp.first=ob->disp.last= NULL;
ob->pose= newdataadr(fd, ob->pose);
direct_link_pose(fd, ob->pose);
link_list(fd, &ob->defbase);
link_list(fd, &ob->nlastrips);
link_list(fd, &ob->constraintChannels);
direct_link_scriptlink(fd, &ob->scriptlink);
ob->mat= newdataadr(fd, ob->mat);
test_pointer_array(fd, (void **)&ob->mat);
/* do it here, below old data gets converted */
direct_link_modifiers(fd, &ob->modifiers);
link_list(fd, &ob->effect);
paf= ob->effect.first;
while(paf) {
if(paf->type==EFF_PARTICLE) {
paf->keys= NULL;
}
if(paf->type==EFF_WAVE) {
WaveEff *wav = (WaveEff*) paf;
PartEff *next = paf->next;
WaveModifierData *wmd = (WaveModifierData*) modifier_new(eModifierType_Wave);
wmd->damp = wav->damp;
wmd->flag = wav->flag;
wmd->height = wav->height;
wmd->lifetime = wav->lifetime;
wmd->narrow = wav->narrow;
wmd->speed = wav->speed;
wmd->startx = wav->startx;
wmd->starty = wav->startx;
wmd->timeoffs = wav->timeoffs;
wmd->width = wav->width;
BLI_addtail(&ob->modifiers, wmd);
BLI_remlink(&ob->effect, paf);
MEM_freeN(paf);
paf = next;
continue;
}
if(paf->type==EFF_BUILD) {
BuildEff *baf = (BuildEff*) paf;
PartEff *next = paf->next;
BuildModifierData *bmd = (BuildModifierData*) modifier_new(eModifierType_Build);
bmd->start = baf->sfra;
bmd->length = baf->len;
bmd->randomize = 0;
bmd->seed = 1;
BLI_addtail(&ob->modifiers, bmd);
BLI_remlink(&ob->effect, paf);
MEM_freeN(paf);
paf = next;
continue;
}
paf= paf->next;
}
ob->pd= newdataadr(fd, ob->pd);
ob->soft= newdataadr(fd, ob->soft);
if(ob->soft) {
SoftBody *sb= ob->soft;
sb->bpoint= NULL; // init pointers so it gets rebuilt nicely
sb->bspring= NULL;
sb->keys= newdataadr(fd, sb->keys);
test_pointer_array(fd, (void **)&sb->keys);
if(sb->keys) {
for(a=0; a<sb->totkey; a++) {
sb->keys[a]= newdataadr(fd, sb->keys[a]);
}
}
}
ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */
if(ob->fluidsimSettings) {
// reinit mesh pointers
ob->fluidsimSettings->orgMesh = NULL; //ob->data;
ob->fluidsimSettings->meshSurface = NULL;
ob->fluidsimSettings->meshBB = NULL;
}
link_list(fd, &ob->prop);
prop= ob->prop.first;
while(prop) {
prop->poin= newdataadr(fd, prop->poin);
if(prop->poin==0) prop->poin= &prop->data;
prop= prop->next;
}
link_list(fd, &ob->sensors);
sens= ob->sensors.first;
while(sens) {
sens->data= newdataadr(fd, sens->data);
sens->links= newdataadr(fd, sens->links);
test_pointer_array(fd, (void **)&sens->links);
sens= sens->next;
}
direct_link_constraints(fd, &ob->constraints);
link_glob_list(fd, &ob->controllers);
cont= ob->controllers.first;
while(cont) {
cont->data= newdataadr(fd, cont->data);
cont->links= newdataadr(fd, cont->links);
test_pointer_array(fd, (void **)&cont->links);
cont= cont->next;
}
link_glob_list(fd, &ob->actuators);
act= ob->actuators.first;
while(act) {
act->data= newdataadr(fd, act->data);
act= act->next;
}
link_list(fd, &ob->hooks);
while (ob->hooks.first) {
ObHook *hook = ob->hooks.first;
HookModifierData *hmd = (HookModifierData*) modifier_new(eModifierType_Hook);
hook->indexar= newdataadr(fd, hook->indexar);
if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
int a;
for(a=0; a<hook->totindex; a++) {
SWITCH_INT(hook->indexar[a]);
}
}
/* Do conversion here because if we have loaded
* a hook we need to make sure it gets converted
* and free'd, regardless of version.
*/
VECCOPY(hmd->cent, hook->cent);
hmd->falloff = hook->falloff;
hmd->force = hook->force;
hmd->indexar = hook->indexar;
hmd->object = hook->parent;
memcpy(hmd->parentinv, hook->parentinv, sizeof(hmd->parentinv));
hmd->totindex = hook->totindex;
BLI_addhead(&ob->modifiers, hmd);
BLI_remlink(&ob->hooks, hook);
MEM_freeN(hook);
}
ob->bb= NULL;
ob->derivedDeform= NULL;
ob->derivedFinal= NULL;
}
/* ************ READ SCENE ***************** */
static void lib_link_scene(FileData *fd, Main *main)
{
Scene *sce;
Base *base, *next;
Editing *ed;
Sequence *seq;
sce= main->scene.first;
while(sce) {
if(sce->id.flag & LIB_NEEDLINK) {
sce->id.us= 1;
sce->camera= newlibadr(fd, sce->id.lib, sce->camera);
sce->world= newlibadr_us(fd, sce->id.lib, sce->world);
sce->set= newlibadr(fd, sce->id.lib, sce->set);
sce->ima= newlibadr_us(fd, sce->id.lib, sce->ima);
base= sce->base.first;
while(base) {
next= base->next;
/* base->object= newlibadr_us(fd, sce->id.lib, base->object); */
base->object= newlibadr_us_type(fd, sce->id.lib, ID_OB, base->object);
/* when save during radiotool, needs cleared */
base->flag &= ~OB_RADIO;
if(base->object==0) {
printf("LIB ERROR: base removed\n");
BLI_remlink(&sce->base, base);
if(base==sce->basact) sce->basact= 0;
MEM_freeN(base);
}
base= next;
}
ed= sce->ed;
if(ed) {
WHILE_SEQ(&ed->seqbase) {
if(seq->ipo) seq->ipo= newlibadr_us(fd, sce->id.lib, seq->ipo);
if(seq->scene) seq->scene= newlibadr(fd, sce->id.lib, seq->scene);
if(seq->sound) {
seq->sound= newlibadr(fd, sce->id.lib, seq->sound);
if (seq->sound) {
seq->sound->id.us++;
seq->sound->flags |= SOUND_FLAGS_SEQUENCE;
}
}
seq->anim= 0;
}
END_SEQ
}
lib_link_scriptlink(fd, &sce->id, &sce->scriptlink);
sce->id.flag -= LIB_NEEDLINK;
}
sce= sce->id.next;
}
}
static void link_recurs_seq(FileData *fd, ListBase *lb)
{
Sequence *seq;
link_list(fd, lb);
seq= lb->first;
while(seq) {
if(seq->seqbase.first) link_recurs_seq(fd, &seq->seqbase);
seq= seq->next;
}
}
static void direct_link_scene(FileData *fd, Scene *sce)
{
Editing *ed;
Sequence *seq;
MetaStack *ms;
StripElem *se;
int a;
sce->theDag = NULL;
sce->dagisvalid = 0;
link_list(fd, &(sce->base));
sce->basact= newdataadr(fd, sce->basact);
sce->radio= newdataadr(fd, sce->radio);
sce->toolsettings= newdataadr(fd, sce->toolsettings);
if(sce->ed) {
ed= sce->ed= newdataadr(fd, sce->ed);
/* recursive link sequences, lb will be correctly initialized */
link_recurs_seq(fd, &ed->seqbase);
WHILE_SEQ(&ed->seqbase) {
seq->seq1= newdataadr(fd, seq->seq1);
seq->seq2= newdataadr(fd, seq->seq2);
seq->seq3= newdataadr(fd, seq->seq3);
/* a patch: after introduction of effects with 3 input strips */
if(seq->seq3==0) seq->seq3= seq->seq2;
seq->curelem= 0;
seq->plugin= newdataadr(fd, seq->plugin);
if(seq->plugin) open_plugin_seq(seq->plugin, seq->name+2);
seq->effectdata= newdataadr(fd, seq->effectdata);
seq->strip= newdataadr(fd, seq->strip);
if(seq->strip && seq->strip->done==0) {
seq->strip->done= 1;
/* standard: strips from effects/metas are not written, but are mallocced */
if(seq->type==SEQ_IMAGE) {
seq->strip->stripdata= newdataadr(fd, seq->strip->stripdata);
se= seq->strip->stripdata;
if(se) {
for(a=0; a<seq->strip->len; a++, se++) {
se->ok= 1;
se->ibuf= 0;
}
}
}
else if(seq->type==SEQ_MOVIE) {
/* only first stripelem is in file */
se= newdataadr(fd, seq->strip->stripdata);
if(se) {
seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
*seq->strip->stripdata= *se;
MEM_freeN(se);
se= seq->strip->stripdata;
for(a=0; a<seq->strip->len; a++, se++) {
se->ok= 1;
se->ibuf= 0;
se->nr= a + 1;
}
}
}
else if(seq->type==SEQ_SOUND) {
/* only first stripelem is in file */
se= newdataadr(fd, seq->strip->stripdata);
if(se) {
seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
*seq->strip->stripdata= *se;
MEM_freeN(se);
se= seq->strip->stripdata;
for(a=0; a<seq->strip->len; a++, se++) {
se->ok= 2; /* why? */
se->ibuf= 0;
se->nr= a + 1;
}
}
}
else if(seq->len>0)
seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
}
}
END_SEQ
/* link metastack, slight abuse of structs here, have to restore pointer to internal part in struct */
{
Sequence temp;
char *poin;
long offset;
/*int seted=0;*/ /*unused*/
offset= ((long)&(temp.seqbase)) - ((long)&temp);
/* root pointer */
poin= (char *)ed->seqbasep;
poin -= offset;
poin= newdataadr(fd, poin);
if(poin) ed->seqbasep= (ListBase *)(poin+offset);
else ed->seqbasep= &ed->seqbase;
/* stack */
link_list(fd, &(ed->metastack));
for(ms= ed->metastack.first; ms; ms= ms->next) {
ms->parseq= newdataadr(fd, ms->parseq);
poin= (char *)ms->oldbasep;
poin -= offset;
poin= newdataadr(fd, poin);
if(poin) ms->oldbasep= (ListBase *)(poin+offset);
else ms->oldbasep= &ed->seqbase;
}
}
}
direct_link_scriptlink(fd, &sce->scriptlink);
sce->r.avicodecdata = newdataadr(fd, sce->r.avicodecdata);
if (sce->r.avicodecdata) {
sce->r.avicodecdata->lpFormat = newdataadr(fd, sce->r.avicodecdata->lpFormat);
sce->r.avicodecdata->lpParms = newdataadr(fd, sce->r.avicodecdata->lpParms);
}
sce->r.qtcodecdata = newdataadr(fd, sce->r.qtcodecdata);
if (sce->r.qtcodecdata) {
sce->r.qtcodecdata->cdParms = newdataadr(fd, sce->r.qtcodecdata->cdParms);
}
link_list(fd, &(sce->markers));
}
/* ************ READ SCREEN ***************** */
/* note: file read without screens option G_FILE_NO_UI;
check lib pointers in call below */
static void lib_link_screen(FileData *fd, Main *main)
{
bScreen *sc;
ScrArea *sa;
sc= main->screen.first;
while(sc) {
if(sc->id.flag & LIB_NEEDLINK) {
sc->id.us= 1;
sc->scene= newlibadr(fd, sc->id.lib, sc->scene);
sa= sc->areabase.first;
while(sa) {
SpaceLink *sl;
sa->full= newlibadr(fd, sc->id.lib, sa->full);
/* space handler scriptlinks */
lib_link_scriptlink(fd, &sc->id, &sa->scriptlink);
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if(sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D*) sl;
v3d->camera= newlibadr(fd, sc->id.lib, v3d->camera);
if(v3d->bgpic) {
v3d->bgpic->ima= newlibadr_us(fd, sc->id.lib, v3d->bgpic->ima);
v3d->bgpic->tex= newlibadr_us(fd, sc->id.lib, v3d->bgpic->tex);
v3d->bgpic->rect= NULL;
}
if(v3d->localvd) {
v3d->localvd->camera= newlibadr(fd, sc->id.lib, v3d->localvd->camera);
}
}
else if(sl->spacetype==SPACE_IPO) {
SpaceIpo *sipo= (SpaceIpo *)sl;
sipo->editipo= 0;
if(sipo->blocktype==ID_SEQ) sipo->from= NULL; // no libdata
else sipo->from= newlibadr(fd, sc->id.lib, sipo->from);
sipo->ipokey.first= sipo->ipokey.last= 0;
sipo->ipo= newlibadr(fd, sc->id.lib, sipo->ipo);
}
else if(sl->spacetype==SPACE_BUTS) {
SpaceButs *sbuts= (SpaceButs *)sl;
sbuts->rect= NULL;
sbuts->lockpoin= NULL;
if(main->versionfile<132) set_rects_butspace(sbuts);
}
else if(sl->spacetype==SPACE_FILE) {
SpaceFile *sfile= (SpaceFile *)sl;
sfile->filelist= 0;
sfile->libfiledata= 0;
sfile->returnfunc= 0;
}
else if(sl->spacetype==SPACE_IMASEL) {
check_imasel_copy((SpaceImaSel *)sl);
}
else if(sl->spacetype==SPACE_ACTION) {
SpaceAction *saction= (SpaceAction *)sl;
saction->action = newlibadr(fd, sc->id.lib, saction->action);
}
else if(sl->spacetype==SPACE_IMAGE) {
SpaceImage *sima= (SpaceImage *)sl;
sima->image= newlibadr_us(fd, sc->id.lib, sima->image);
}
else if(sl->spacetype==SPACE_NLA){
/* SpaceNla *snla= (SpaceNla *)sl; */
}
else if(sl->spacetype==SPACE_TEXT) {
SpaceText *st= (SpaceText *)sl;
st->text= newlibadr(fd, sc->id.lib, st->text);
}
else if(sl->spacetype==SPACE_SCRIPT) {
SpaceScript *sc= (SpaceScript *)sl;
sc->script = NULL;
}
else if(sl->spacetype==SPACE_OOPS) {
SpaceOops *so= (SpaceOops *)sl;
Oops *oops;
TreeStoreElem *tselem;
int a;
oops= so->oops.first;
while(oops) {
oops->id= newlibadr(fd, NULL, oops->id);
oops= oops->next;
}
so->lockpoin= NULL;
so->tree.first= so->tree.last= NULL;
if(so->treestore) {
tselem= so->treestore->data;
for(a=0; a<so->treestore->usedelem; a++, tselem++) {
tselem->id= newlibadr(fd, NULL, tselem->id);
}
}
}
else if(sl->spacetype==SPACE_SOUND) {
SpaceSound *ssound= (SpaceSound *)sl;
ssound->sound= newlibadr_us(fd, sc->id.lib, ssound->sound);
}
}
sa= sa->next;
}
sc->id.flag -= LIB_NEEDLINK;
}
sc= sc->id.next;
}
}
static void *restore_pointer_by_name(Main *mainp, ID *id, int user)
{
ListBase *lb;
ID *idn=NULL;
if(id) {
lb= wich_libbase(mainp, GS(id->name));
if(lb) { // there's still risk of checking corrupt mem (freed Ids in oops)
idn= lb->first;
while(idn) {
if( strcmp(idn->name, id->name)==0) {
if(user && idn->us==0) idn->us++;
break;
}
idn= idn->next;
}
}
}
return idn;
}
/* called from kernel/blender.c */
/* used to link a file (without UI) to the current UI */
void lib_link_screen_restore(Main *newmain, Scene *curscene)
{
bScreen *sc;
ScrArea *sa;
sc= newmain->screen.first;
while(sc) {
sc->scene= curscene;
sa= sc->areabase.first;
while(sa) {
SpaceLink *sl;
if (sa->scriptlink.totscript) {
/* restore screen area script links */
ScriptLink *slink = &sa->scriptlink;
int script_idx;
for (script_idx = 0; script_idx < slink->totscript; script_idx++) {
slink->scripts[script_idx] = restore_pointer_by_name(newmain,
(ID *)slink->scripts[script_idx], 1);
}
}
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if(sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D*) sl;
v3d->camera= sc->scene->camera;
if(v3d->bgpic) {
v3d->bgpic->ima= restore_pointer_by_name(newmain, (ID *)v3d->bgpic->ima, 1);
v3d->bgpic->tex= restore_pointer_by_name(newmain, (ID *)v3d->bgpic->tex, 1);
if(v3d->bgpic->rect) freeN(v3d->bgpic->rect);
v3d->bgpic->rect= NULL;
}
if(v3d->localvd) {
Base *base;
v3d->localvd->camera= sc->scene->camera;
/* localview can become invalid during undo/redo steps, so we exit it when no could be found */
for(base= sc->scene->base.first; base; base= base->next) {
if(base->lay & v3d->lay) break;
}
if(base==NULL) {
v3d->lay= v3d->localvd->lay;
v3d->layact= v3d->localvd->layact;
MEM_freeN(v3d->localvd);
v3d->localvd= NULL;
v3d->localview= 0;
}
}
else if(v3d->scenelock) v3d->lay= sc->scene->lay;
/* not very nice, but could help */
if((v3d->layact & v3d->lay)==0) v3d->layact= v3d->lay;
}
else if(sl->spacetype==SPACE_IPO) {
SpaceIpo *sipo= (SpaceIpo *)sl;
if(sipo->blocktype==ID_SEQ) sipo->from= NULL; // no libdata
else sipo->from= restore_pointer_by_name(newmain, (ID *)sipo->from, 0);
// not free sipo->ipokey, creates dependency with src/
sipo->ipo= restore_pointer_by_name(newmain, (ID *)sipo->ipo, 0);
if(sipo->editipo) MEM_freeN(sipo->editipo);
sipo->editipo= NULL;
}
else if(sl->spacetype==SPACE_BUTS) {
SpaceButs *sbuts= (SpaceButs *)sl;
sbuts->lockpoin= NULL;
sbuts->cury= 0; // we leave rect, for nicer redraws
}
else if(sl->spacetype==SPACE_FILE) {
SpaceFile *sfile= (SpaceFile *)sl;
if(sfile->libfiledata)
BLO_blendhandle_close(sfile->libfiledata);
sfile->libfiledata= 0;
}
else if(sl->spacetype==SPACE_IMASEL) {
;
}
else if(sl->spacetype==SPACE_ACTION) {
SpaceAction *saction= (SpaceAction *)sl;
saction->action = restore_pointer_by_name(newmain, (ID *)saction->action, 1);
}
else if(sl->spacetype==SPACE_IMAGE) {
SpaceImage *sima= (SpaceImage *)sl;
sima->image= restore_pointer_by_name(newmain, (ID *)sima->image, 1);
}
else if(sl->spacetype==SPACE_NLA){
/* SpaceNla *snla= (SpaceNla *)sl; */
}
else if(sl->spacetype==SPACE_TEXT) {
SpaceText *st= (SpaceText *)sl;
st->text= restore_pointer_by_name(newmain, (ID *)st->text, 1);
if(st->text==NULL) st->text= newmain->text.first;
}
else if(sl->spacetype==SPACE_SCRIPT) {
SpaceScript *sc= (SpaceScript *)sl;
sc->script = NULL;
}
else if(sl->spacetype==SPACE_OOPS) {
SpaceOops *so= (SpaceOops *)sl;
Oops *oops;
int a;
oops= so->oops.first;
while(oops) {
oops->id= restore_pointer_by_name(newmain, (ID *)oops->id, 0);
oops= oops->next;
}
so->lockpoin= NULL;
if(so->treestore) {
TreeStore *ts= so->treestore;
TreeStoreElem *tselem=ts->data;
for(a=0; a<ts->usedelem; a++, tselem++) {
tselem->id= restore_pointer_by_name(newmain, tselem->id, 0);
}
}
}
else if(sl->spacetype==SPACE_SOUND) {
SpaceSound *ssound= (SpaceSound *)sl;
ssound->sound= restore_pointer_by_name(newmain, (ID *)ssound->sound, 1);
}
}
sa= sa->next;
}
sc= sc->id.next;
}
}
static void direct_link_screen(FileData *fd, bScreen *sc)
{
ScrArea *sa;
ScrVert *sv;
ScrEdge *se;
Oops *oops;
int a;
link_list(fd, &(sc->vertbase));
link_list(fd, &(sc->edgebase));
link_list(fd, &(sc->areabase));
sc->winakt= 0;
/* hacky patch... but people have been saving files with the verse-blender,
causing the handler to keep running for ever, with no means to disable it */
for(a=0; a<SCREEN_MAXHANDLER; a+=2) {
if( sc->handler[a]==SCREEN_HANDLER_VERSE) {
sc->handler[a]= 0;
break;
}
}
/* edges */
se= sc->edgebase.first;
while(se) {
se->v1= newdataadr(fd, se->v1);
se->v2= newdataadr(fd, se->v2);
if( (long)se->v1 > (long)se->v2) {
sv= se->v1;
se->v1= se->v2;
se->v2= sv;
}
if(se->v1==NULL) {
printf("error reading screen... file corrupt\n");
se->v1= se->v2;
}
se= se->next;
}
/* areas */
sa= sc->areabase.first;
while(sa) {
Panel *pa;
SpaceLink *sl;
link_list(fd, &(sa->spacedata));
link_list(fd, &(sa->panels));
for(pa= sa->panels.first; pa; pa=pa->next) {
pa->paneltab= newdataadr(fd, pa->paneltab);
pa->active= 0;
pa->sortcounter= 0;
}
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D*) sl;
v3d->bgpic= newdataadr(fd, v3d->bgpic);
v3d->localvd= newdataadr(fd, v3d->localvd);
v3d->afterdraw.first= v3d->afterdraw.last= NULL;
v3d->clipbb= newdataadr(fd, v3d->clipbb);
}
else if (sl->spacetype==SPACE_OOPS) {
SpaceOops *soops= (SpaceOops*) sl;
link_list(fd, &(soops->oops));
oops= soops->oops.first;
while(oops) {
oops->link.first= oops->link.last= 0;
oops= oops->next;
}
soops->treestore= newdataadr(fd, soops->treestore);
if(soops->treestore) {
soops->treestore->data= newdataadr(fd, soops->treestore->data);
/* we only saved what was used */
soops->treestore->totelem= soops->treestore->usedelem;
soops->storeflag |= SO_TREESTORE_CLEANUP; // at first draw
}
}
}
sa->v1= newdataadr(fd, sa->v1);
sa->v2= newdataadr(fd, sa->v2);
sa->v3= newdataadr(fd, sa->v3);
sa->v4= newdataadr(fd, sa->v4);
sa->win= sa->headwin= 0;
sa->uiblocks.first= sa->uiblocks.last= NULL;
/* space handler scriptlinks */
direct_link_scriptlink(fd, &sa->scriptlink);
sa= sa->next;
}
}
/* ********** READ LIBRARY *************** */
static void direct_link_library(FileData *fd, Library *lib, Main *main)
{
Main *newmain;
Library *libr;
for(newmain= fd->mainlist.first; newmain; newmain= newmain->next) {
if(newmain->curlib) {
if(strcmp(newmain->curlib->name, lib->name)==0) {
printf("Fixed error in file; multiple instances of lib:\n %s\n", lib->name);
change_libadr(fd, lib, newmain->curlib);
BLI_remlink(&main->library, lib);
MEM_freeN(lib);
return;
}
}
}
/* new main */
newmain= MEM_callocN(sizeof(Main), "directlink");
BLI_addtail(&fd->mainlist, newmain);
newmain->curlib= lib;
}
static void lib_link_library(FileData *fd, Main *main)
{
Library *lib;
lib= main->library.first;
while(lib) {
lib->id.us= 1;
lib= lib->id.next;
}
}
/* ************** READ SOUND ******************* */
static void direct_link_sound(FileData *fd, bSound *sound)
{
sound->sample = NULL;
sound->snd_sound = NULL;
sound->packedfile = direct_link_packedfile(fd, sound->packedfile);
sound->newpackedfile = direct_link_packedfile(fd, sound->newpackedfile);
}
static void lib_link_sound(FileData *fd, Main *main)
{
bSound *sound;
sound= main->sound.first;
while(sound) {
if(sound->id.flag & LIB_NEEDLINK) {
sound->id.flag -= LIB_NEEDLINK;
sound->ipo= newlibadr_us(fd, sound->id.lib, sound->ipo);
sound->stream = 0;
}
sound= sound->id.next;
}
}
/* ***************** READ GROUP *************** */
static void direct_link_group(FileData *fd, Group *group)
{
link_list(fd, &group->gobject);
}
static void lib_link_group(FileData *fd, Main *main)
{
Group *group= main->group.first;
GroupObject *go;
int add_us;
while(group) {
if(group->id.flag & LIB_NEEDLINK) {
group->id.flag -= LIB_NEEDLINK;
add_us= 0;
go= group->gobject.first;
while(go) {
go->ob= newlibadr(fd, group->id.lib, go->ob);
if(go->ob) {
/* if group has an object, it increments user... */
add_us= 1;
if(go->ob->id.us==0)
go->ob->id.us= 1;
}
go= go->next;
}
if(add_us) group->id.us++;
rem_from_group(group, NULL); /* removes NULL entries */
}
group= group->id.next;
}
}
/* ************** GENERAL & MAIN ******************** */
static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID **id_r)
{
/* this routine reads a libblock and its direct data. Use link functions
* to connect it all
*/
ID *id;
ListBase *lb;
char *str = NULL;
if(bhead->code==ID_ID) {
ID *linkedid= (ID *)(bhead + 1); /* BHEAD+DATA dependancy */
lb= wich_libbase(main, GS(linkedid->name));
}
else {
lb= wich_libbase(main, bhead->code);
}
/* read libblock */
id = read_struct(fd, bhead, "lib block");
if (id_r)
*id_r= id;
if (!id)
return blo_nextbhead(fd, bhead);
oldnewmap_insert(fd->libmap, bhead->old, id, 1);
BLI_addtail(lb, id);
/* clear first 8 bits */
id->flag= (id->flag & 0xFF00) | flag | LIB_NEEDLINK;
id->lib= main->curlib;
if(id->flag & LIB_FAKEUSER) id->us= 1;
else id->us= 0;
/* this case cannot be direct_linked: it's just the ID part */
if(bhead->code==ID_ID) {
return blo_nextbhead(fd, bhead);
}
bhead = blo_nextbhead(fd, bhead);
switch( GS(id->name) ) {
case ID_OB: str= "ID_OB"; break;
case ID_SCE: str= "ID_SCE"; break;
case ID_LI: str= "ID_LI"; break;
case ID_ME: str= "ID_ME"; break;
case ID_CU: str= "ID_CU"; break;
case ID_MB: str= "ID_MB"; break;
case ID_MA: str= "ID_MA"; break;
case ID_TE: str= "ID_TE"; break;
case ID_IM: str= "ID_IM"; break;
case ID_IK: str= "ID_IK"; break;
case ID_WV: str= "ID_WV"; break;
case ID_LT: str= "ID_LT"; break;
case ID_SE: str= "ID_SE"; break;
case ID_LF: str= "ID_LF"; break;
case ID_LA: str= "ID_LA"; break;
case ID_CA: str= "ID_CA"; break;
case ID_IP: str= "ID_IP"; break;
case ID_KE: str= "ID_KE"; break;
case ID_WO: str= "ID_WO"; break;
case ID_SCR: str= "ID_SCR"; break;
case ID_VF: str= "ID_VF"; break;
case ID_TXT : str= "ID_TXT"; break;
case ID_SO: str= "ID_SO"; break;
case ID_SAMPLE: str= "ID_SAMPLE"; break;
case ID_GR: str= "ID_GR"; break;
case ID_ID: str= "ID_ID"; break;
case ID_SEQ: str= "ID_SEQ"; break;
case ID_AR: str= "ID_AR"; break;
case ID_AC: str= "ID_AC"; break;
}
/* read all data */
while(bhead && bhead->code==DATA) {
void *data= read_struct(fd, bhead, str);
if (data) {
oldnewmap_insert(fd->datamap, bhead->old, data, 0);
}
bhead = blo_nextbhead(fd, bhead);
}
/* init pointers direct data */
switch( GS(id->name) ) {
case ID_SCR:
direct_link_screen(fd, (bScreen *)id);
break;
case ID_SCE:
direct_link_scene(fd, (Scene *)id);
break;
case ID_OB:
direct_link_object(fd, (Object *)id);
break;
case ID_ME:
direct_link_mesh(fd, (Mesh *)id);
break;
case ID_CU:
direct_link_curve(fd, (Curve *)id);
break;
case ID_MB:
direct_link_mball(fd, (MetaBall *)id);
break;
case ID_MA:
direct_link_material(fd, (Material *)id);
break;
case ID_TE:
direct_link_texture(fd, (Tex *)id);
break;
case ID_IM:
direct_link_image(fd, (Image *)id);
break;
case ID_LA:
direct_link_lamp(fd, (Lamp *)id);
break;
case ID_VF:
direct_link_vfont(fd, (VFont *)id);
break;
case ID_TXT:
direct_link_text(fd, (Text *)id);
break;
case ID_IP:
direct_link_ipo(fd, (Ipo *)id);
break;
case ID_KE:
direct_link_key(fd, (Key *)id);
break;
case ID_LT:
direct_link_latt(fd, (Lattice *)id);
break;
case ID_WO:
direct_link_world(fd, (World *)id);
break;
case ID_LI:
direct_link_library(fd, (Library *)id, main);
break;
case ID_CA:
direct_link_camera(fd, (Camera *)id);
break;
case ID_SO:
direct_link_sound(fd, (bSound *)id);
break;
case ID_GR:
direct_link_group(fd, (Group *)id);
break;
case ID_AR:
direct_link_armature(fd, (bArmature*)id);
break;
case ID_AC:
direct_link_action(fd, (bAction*)id);
break;
}
oldnewmap_free_unused(fd->datamap);
oldnewmap_clear(fd->datamap);
return (bhead);
}
static void link_global(FileData *fd, BlendFileData *bfd, FileGlobal *fg)
{
// this is nonsense... make it struct once (ton)
bfd->winpos= fg->winpos;
bfd->fileflags= fg->fileflags;
bfd->displaymode= fg->displaymode;
bfd->globalf= fg->globalf;
bfd->curscreen= newlibadr(fd, 0, fg->curscreen);
bfd->curscene= newlibadr(fd, 0, fg->curscene);
// this happens in files older than 2.35
if(bfd->curscene==NULL) {
if(bfd->curscreen) bfd->curscene= bfd->curscreen->scene;
}
}
static void vcol_to_fcol(Mesh *me)
{
MFace *mface;
unsigned int *mcol, *mcoln, *mcolmain;
int a;
if(me->totface==0 || me->mcol==0) return;
mcoln= mcolmain= MEM_mallocN(4*sizeof(int)*me->totface, "mcoln");
mcol = (unsigned int *)me->mcol;
mface= me->mface;
for(a=me->totface; a>0; a--, mface++) {
mcoln[0]= mcol[mface->v1];
mcoln[1]= mcol[mface->v2];
mcoln[2]= mcol[mface->v3];
mcoln[3]= mcol[mface->v4];
mcoln+= 4;
}
MEM_freeN(me->mcol);
me->mcol= (MCol *)mcolmain;
}
static int map_223_keybd_code_to_224_keybd_code(int code)
{
switch (code) {
case 312: return F12KEY;
case 159: return PADSLASHKEY;
case 161: return PAD0;
case 154: return PAD1;
case 150: return PAD2;
case 155: return PAD3;
case 151: return PAD4;
case 156: return PAD5;
case 152: return PAD6;
case 157: return PAD7;
case 153: return PAD8;
case 158: return PAD9;
default: return code;
}
}
static void bone_version_238(ListBase *lb)
{
Bone *bone;
for(bone= lb->first; bone; bone= bone->next) {
if(bone->rad_tail==0.0f && bone->rad_head==0.0f) {
bone->rad_head= 0.25f*bone->length;
bone->rad_tail= 0.1f*bone->length;
bone->dist-= bone->rad_head;
if(bone->dist<=0.0f) bone->dist= 0.0f;
}
bone_version_238(&bone->childbase);
}
}
static void bone_version_239(ListBase *lb)
{
Bone *bone;
for(bone= lb->first; bone; bone= bone->next) {
if(bone->layer==0)
bone->layer= 1;
bone_version_239(&bone->childbase);
}
}
static void do_versions(FileData *fd, Library *lib, Main *main)
{
/* WATCH IT!!!: pointers from libdata have not been converted */
if(main->versionfile == 100) {
/* tex->extend and tex->imageflag have changed: */
Tex *tex = main->tex.first;
while(tex) {
if(tex->id.flag & LIB_NEEDLINK) {
if(tex->extend==0) {
if(tex->xrepeat || tex->yrepeat) tex->extend= TEX_REPEAT;
else {
tex->extend= TEX_EXTEND;
tex->xrepeat= tex->yrepeat= 1;
}
}
if(tex->imaflag & TEX_ANIM5) {
tex->imaflag |= TEX_MORKPATCH;
tex->imaflag |= TEX_ANTIALI;
}
}
tex= tex->id.next;
}
}
if(main->versionfile <= 101) {
/* frame mapping */
Scene *sce = main->scene.first;
while(sce) {
sce->r.framapto= 100;
sce->r.images= 100;
sce->r.framelen= 1.0;
sce= sce->id.next;
}
}
if(main->versionfile <= 102) {
/* init halo's at 1.0 */
Material *ma = main->mat.first;
while(ma) {
ma->add= 1.0;
ma= ma->id.next;
}
}
if(main->versionfile <= 103) {
/* new variable in object: colbits */
Object *ob = main->object.first;
int a;
while(ob) {
ob->colbits= 0;
if(ob->totcol) {
for(a=0; a<ob->totcol; a++) {
if(ob->mat[a]) ob->colbits |= (1<<a);
}
}
ob= ob->id.next;
}
}
if(main->versionfile <= 104) {
/* timeoffs moved */
Object *ob = main->object.first;
while(ob) {
if(ob->transflag & 1) {
ob->transflag -= 1;
ob->ipoflag |= OB_OFFS_OB;
}
ob= ob->id.next;
}
}
if(main->versionfile <= 105) {
Object *ob = main->object.first;
while(ob) {
ob->dupon= 1; ob->dupoff= 0;
ob->dupsta= 1; ob->dupend= 100;
ob= ob->id.next;
}
}
if(main->versionfile <= 106) {
/* mcol changed */
Mesh *me = main->mesh.first;
while(me) {
if(me->mcol) vcol_to_fcol(me);
me= me->id.next;
}
}
if(main->versionfile <= 107) {
Object *ob;
Scene *sce = main->scene.first;
while(sce) {
sce->r.mode |= R_GAMMA;
sce= sce->id.next;
}
ob= main->object.first;
while(ob) {
ob->ipoflag |= OB_OFFS_PARENT;
if(ob->dt==0) ob->dt= OB_SOLID;
ob= ob->id.next;
}
}
if(main->versionfile <= 109) {
/* new variable: gridlines */
bScreen *sc = main->screen.first;
while(sc) {
ScrArea *sa= sc->areabase.first;
while(sa) {
SpaceLink *sl= sa->spacedata.first;
while (sl) {
if (sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D*) sl;
if (v3d->gridlines==0) v3d->gridlines= 20;
}
sl= sl->next;
}
sa= sa->next;
}
sc= sc->id.next;
}
}
if(main->versionfile <= 112) {
Mesh *me = main->mesh.first;
while(me) {
me->cubemapsize= 1.0;
me= me->id.next;
}
}
if(main->versionfile <= 113) {
Material *ma = main->mat.first;
while(ma) {
if(ma->flaresize==0.0) ma->flaresize= 1.0;
ma->subsize= 1.0;
ma->flareboost= 1.0;
ma= ma->id.next;
}
}
if(main->versionfile <= 134) {
Tex *tex = main->tex.first;
while (tex) {
if ((tex->rfac == 0.0) &&
(tex->gfac == 0.0) &&
(tex->bfac == 0.0)) {
tex->rfac = 1.0;
tex->gfac = 1.0;
tex->bfac = 1.0;
tex->filtersize = 1.0;
}
tex = tex->id.next;
}
}
if(main->versionfile <= 140) {
/* r-g-b-fac in texure */
Tex *tex = main->tex.first;
while (tex) {
if ((tex->rfac == 0.0) &&
(tex->gfac == 0.0) &&
(tex->bfac == 0.0)) {
tex->rfac = 1.0;
tex->gfac = 1.0;
tex->bfac = 1.0;
tex->filtersize = 1.0;
}
tex = tex->id.next;
}
}
if(main->versionfile <= 153) {
Scene *sce = main->scene.first;
while(sce) {
if(sce->r.blurfac==0.0) sce->r.blurfac= 1.0;
sce= sce->id.next;
}
}
if(main->versionfile <= 163) {
Scene *sce = main->scene.first;
while(sce) {
if(sce->r.frs_sec==0) sce->r.frs_sec= 25;
sce= sce->id.next;
}
}
if(main->versionfile <= 164) {
Mesh *me= main->mesh.first;
while(me) {
me->smoothresh= 30;
me= me->id.next;
}
}
if(main->versionfile <= 165) {
Mesh *me= main->mesh.first;
TFace *tface;
int nr;
char *cp;
while(me) {
if(me->tface) {
nr= me->totface;
tface= me->tface;
while(nr--) {
cp= (char *)&tface->col[0];
if(cp[1]>126) cp[1]= 255; else cp[1]*=2;
if(cp[2]>126) cp[2]= 255; else cp[2]*=2;
if(cp[3]>126) cp[3]= 255; else cp[3]*=2;
cp= (char *)&tface->col[1];
if(cp[1]>126) cp[1]= 255; else cp[1]*=2;
if(cp[2]>126) cp[2]= 255; else cp[2]*=2;
if(cp[3]>126) cp[3]= 255; else cp[3]*=2;
cp= (char *)&tface->col[2];
if(cp[1]>126) cp[1]= 255; else cp[1]*=2;
if(cp[2]>126) cp[2]= 255; else cp[2]*=2;
if(cp[3]>126) cp[3]= 255; else cp[3]*=2;
cp= (char *)&tface->col[3];
if(cp[1]>126) cp[1]= 255; else cp[1]*=2;
if(cp[2]>126) cp[2]= 255; else cp[2]*=2;
if(cp[3]>126) cp[3]= 255; else cp[3]*=2;
tface++;
}
}
me= me->id.next;
}
}
if(main->versionfile <= 169) {
Mesh *me= main->mesh.first;
while(me) {
if(me->subdiv==0) me->subdiv= 1;
me= me->id.next;
}
}
if(main->versionfile <= 169) {
bScreen *sc= main->screen.first;
while(sc) {
ScrArea *sa= sc->areabase.first;
while(sa) {
SpaceLink *sl= sa->spacedata.first;
while(sl) {
if(sl->spacetype==SPACE_IPO) {
SpaceIpo *sipo= (SpaceIpo*) sl;
sipo->v2d.max[0]= 15000.0;
}
sl= sl->next;
}
sa= sa->next;
}
sc= sc->id.next;
}
}
if(main->versionfile <= 170) {
Object *ob = main->object.first;
PartEff *paf;
while (ob) {
paf = give_parteff(ob);
if (paf) {
if (paf->staticstep == 0) {
paf->staticstep= 5;
}
}
ob = ob->id.next;
}
}
if(main->versionfile <= 171) {
bScreen *sc= main->screen.first;
while(sc) {
ScrArea *sa= sc->areabase.first;
while(sa) {
SpaceLink *sl= sa->spacedata.first;
while(sl) {
if(sl->spacetype==SPACE_TEXT) {
SpaceText *st= (SpaceText*) sl;
if(st->font_id>1) {
st->font_id= 0;
st->lheight= 13;
}
}
sl= sl->next;
}
sa= sa->next;
}
sc= sc->id.next;
}
}
if(main->versionfile <= 173) {
int a, b;
Mesh *me= main->mesh.first;
while(me) {
if(me->tface) {
TFace *tface= me->tface;
for(a=0; a<me->totface; a++, tface++) {
for(b=0; b<4; b++) {
tface->uv[b][0]/= 32767.0;
tface->uv[b][1]/= 32767.0;
}
}
}
me= me->id.next;
}
}
if(main->versionfile <= 191) {
bScreen *sc= main->screen.first;
Object *ob= main->object.first;
Material *ma = main->mat.first;
/* let faces have default add factor of 0.0 */
while(ma) {
if (!(ma->mode & MA_HALO)) ma->add = 0.0;
ma = ma->id.next;
}
while(ob) {
ob->mass= 1.0f;
ob->damping= 0.1f;
ob->quat[1]= 1.0f;
ob= ob->id.next;
}
while(sc) {
ScrArea *sa= sc->areabase.first;
while(sa) {
SpaceLink *sl= sa->spacedata.first;
while(sl) {
if(sl->spacetype==SPACE_BUTS) {
SpaceButs *sbuts= (SpaceButs*) sl;
sbuts->scaflag= BUTS_SENS_LINK|BUTS_SENS_ACT|BUTS_CONT_ACT|BUTS_ACT_ACT|BUTS_ACT_LINK;
}
sl= sl->next;
}
sa= sa->next;
}
sc= sc->id.next;
}
}
if(main->versionfile <= 193) {
Object *ob= main->object.first;
while(ob) {
ob->inertia= 1.0f;
ob->rdamping= 0.1f;
ob= ob->id.next;
}
}
if(main->versionfile <= 196) {
Mesh *me= main->mesh.first;
int a, b;
while(me) {
if(me->tface) {
TFace *tface= me->tface;
for(a=0; a<me->totface; a++, tface++) {
for(b=0; b<4; b++) {
tface->mode |= TF_DYNAMIC;
tface->mode &= ~TF_INVISIBLE;
}
}
}
me= me->id.next;
}
}
if(main->versionfile <= 200) {
Object *ob= main->object.first;
while(ob) {
ob->scaflag = ob->gameflag & (64+128+256+512+1024+2048);
/* 64 is do_fh */
ob->gameflag &= ~(128+256+512+1024+2048);
ob = ob->id.next;
}
}
if(main->versionfile <= 201) {
/* add-object + end-object are joined to edit-object actuator */
Object *ob = main->object.first;
bProperty *prop;
bActuator *act;
bIpoActuator *ia;
bEditObjectActuator *eoa;
bAddObjectActuator *aoa;
while (ob) {
act = ob->actuators.first;
while (act) {
if(act->type==ACT_IPO) {
ia= act->data;
prop= get_property(ob, ia->name);
if(prop) {
ia->type= ACT_IPO_FROM_PROP;
}
}
else if(act->type==ACT_ADD_OBJECT) {
aoa= act->data;
eoa= MEM_callocN(sizeof(bEditObjectActuator), "edit ob act");
eoa->type= ACT_EDOB_ADD_OBJECT;
eoa->ob= aoa->ob;
eoa->time= aoa->time;
MEM_freeN(aoa);
act->data= eoa;
act->type= act->otype= ACT_EDIT_OBJECT;
}
else if(act->type==ACT_END_OBJECT) {
eoa= MEM_callocN(sizeof(bEditObjectActuator), "edit ob act");
eoa->type= ACT_EDOB_END_OBJECT;
act->data= eoa;
act->type= act->otype= ACT_EDIT_OBJECT;
}
act= act->next;
}
ob = ob->id.next;
}
}
if(main->versionfile <= 202) {
/* add-object and end-object are joined to edit-object
* actuator */
Object *ob= main->object.first;
bActuator *act;
bObjectActuator *oa;
while(ob) {
act= ob->actuators.first;
while(act) {
if(act->type==ACT_OBJECT) {
oa= act->data;
oa->flag &= ~(ACT_TORQUE_LOCAL|ACT_DROT_LOCAL); /* this actuator didn't do local/glob rot before */
}
act= act->next;
}
ob= ob->id.next;
}
}
if(main->versionfile <= 204) {
/* patches for new physics */
Object *ob= main->object.first;
bActuator *act;
bObjectActuator *oa;
bSound *sound;
while(ob) {
/* please check this for demo20 files like
* original Egypt levels etc. converted
* rotation factor of 50 is not workable */
act= ob->actuators.first;
while(act) {
if(act->type==ACT_OBJECT) {
oa= act->data;
oa->forceloc[0]*= 25.0;
oa->forceloc[1]*= 25.0;
oa->forceloc[2]*= 25.0;
oa->forcerot[0]*= 10.0;
oa->forcerot[1]*= 10.0;
oa->forcerot[2]*= 10.0;
}
act= act->next;
}
ob= ob->id.next;
}
sound = main->sound.first;
while (sound) {
if (sound->volume < 0.01) {
sound->volume = 1.0;
}
sound = sound->id.next;
}
}
if(main->versionfile <= 205) {
/* patches for new physics */
Object *ob= main->object.first;
bActuator *act;
bSensor *sens;
bEditObjectActuator *oa;
bRaySensor *rs;
bCollisionSensor *cs;
while(ob) {
/* Set anisotropic friction off for old objects,
* values to 1.0. */
ob->gameflag &= ~OB_ANISOTROPIC_FRICTION;
ob->anisotropicFriction[0] = 1.0;
ob->anisotropicFriction[1] = 1.0;
ob->anisotropicFriction[2] = 1.0;
act= ob->actuators.first;
while(act) {
if(act->type==ACT_EDIT_OBJECT) {
/* Zero initial velocity for newly
* added objects */
oa= act->data;
oa->linVelocity[0] = 0.0;
oa->linVelocity[1] = 0.0;
oa->linVelocity[2] = 0.0;
oa->localflag = 0;
}
act= act->next;
}
sens= ob->sensors.first;
while (sens) {
/* Extra fields for radar sensors. */
if(sens->type == SENS_RADAR) {
bRadarSensor *s = sens->data;
s->range = 10000.0;
}
/* Pulsing: defaults for new sensors. */
if(sens->type != SENS_ALWAYS) {
sens->pulse = 0;
sens->freq = 0;
} else {
sens->pulse = 1;
}
/* Invert: off. */
sens->invert = 0;
/* Collision and ray: default = trigger
* on property. The material field can
* remain empty. */
if(sens->type == SENS_COLLISION) {
cs = (bCollisionSensor*) sens->data;
cs->mode = 0;
}
if(sens->type == SENS_RAY) {
rs = (bRaySensor*) sens->data;
rs->mode = 0;
}
sens = sens->next;
}
ob= ob->id.next;
}
/* have to check the exact multiplier */
}
if(main->versionfile <= 210) {
Scene *sce= main->scene.first;
while(sce) {
if(sce->r.postmul== 0.0) sce->r.postmul= 1.0;
if(sce->r.postgamma== 0.0) sce->r.postgamma= 1.0;
sce= sce->id.next;
}
}
if(main->versionfile <= 211) {
/* Render setting: per scene, the applicable gamma value
* can be set. Default is 1.0, which means no
* correction. */
bActuator *act;
bObjectActuator *oa;
Object *ob;
Scene *sce= main->scene.first;
while(sce) {
sce->r.gamma = 2.0;
sce= sce->id.next;
}
/* added alpha in obcolor */
ob= main->object.first;
while(ob) {
ob->col[3]= 1.0;
ob= ob->id.next;
}
/* added alpha in obcolor */
ob= main->object.first;
while(ob) {
act= ob->actuators.first;
while(act) {
if (act->type==ACT_OBJECT) {
/* multiply velocity with 50 in old files */
oa= act->data;
if (fabs(oa->linearvelocity[0]) >= 0.01f)
oa->linearvelocity[0] *= 50.0;
if (fabs(oa->linearvelocity[1]) >= 0.01f)
oa->linearvelocity[1] *= 50.0;
if (fabs(oa->linearvelocity[2]) >= 0.01f)
oa->linearvelocity[2] *= 50.0;
if (fabs(oa->angularvelocity[0])>=0.01f)
oa->angularvelocity[0] *= 50.0;
if (fabs(oa->angularvelocity[1])>=0.01f)
oa->angularvelocity[1] *= 50.0;
if (fabs(oa->angularvelocity[2])>=0.01f)
oa->angularvelocity[2] *= 50.0;
}
act= act->next;
}
ob= ob->id.next;
}
}
if(main->versionfile <= 212) {
bSound* sound;
bProperty *prop;
Object *ob;
Mesh *me;
sound = main->sound.first;
while (sound)
{
sound->max_gain = 1.0;
sound->min_gain = 0.0;
sound->distance = 1.0;
if (sound->attenuation > 0.0)
sound->flags |= SOUND_FLAGS_3D;
else
sound->flags &= ~SOUND_FLAGS_3D;
sound = sound->id.next;
}
ob = main->object.first;
while (ob) {
prop= ob->prop.first;
while(prop) {
if (prop->type == PROP_TIME) {
// convert old PROP_TIME values from int to float
*((float *)&prop->data) = (float) prop->data;
}
prop= prop->next;
}
ob = ob->id.next;
}
/* me->subdiv changed to reflect the actual reparametization
* better, and smeshes were removed - if it was a smesh make
* it a subsurf, and reset the subdiv level because subsurf
* takes a lot more work to calculate.
*/
for (me= main->mesh.first; me; me= me->id.next) {
if (me->flag&ME_SMESH) {
me->flag&= ~ME_SMESH;
me->flag|= ME_SUBSURF;
me->subdiv= 1;
} else {
if (me->subdiv<2)
me->subdiv= 1;
else
me->subdiv--;
}
}
}
if(main->versionfile <= 220) {
Object *ob;
Mesh *me;
ob = main->object.first;
/* adapt form factor in order to get the 'old' physics
* behaviour back...*/
while (ob) {
/* in future, distinguish between different
* object bounding shapes */
ob->formfactor = 0.4f;
/* patch form factor , note that inertia equiv radius
* of a rotation symmetrical obj */
if (ob->inertia != 1.0) {
ob->formfactor /= ob->inertia * ob->inertia;
}
ob = ob->id.next;
}
/* Began using alpha component of vertex colors, but
* old file vertex colors are undefined, reset them
* to be fully opaque. -zr
*/
for (me= main->mesh.first; me; me= me->id.next) {
if (me->mcol) {
int i;
for (i=0; i<me->totface*4; i++) {
MCol *mcol= &me->mcol[i];
mcol->a= 255;
}
}
if (me->tface) {
int i, j;
for (i=0; i<me->totface; i++) {
TFace *tf= &((TFace*) me->tface)[i];
for (j=0; j<4; j++) {
char *col= (char*) &tf->col[j];
col[0]= 255;
}
}
}
}
}
if(main->versionfile <= 221) {
Scene *sce= main->scene.first;
// new variables for std-alone player and runtime
while(sce) {
sce->r.xplay= 640;
sce->r.yplay= 480;
sce->r.freqplay= 60;
sce= sce->id.next;
}
}
if(main->versionfile <= 222) {
Scene *sce= main->scene.first;
// new variables for std-alone player and runtime
while(sce) {
sce->r.depth= 32;
sce= sce->id.next;
}
}
if(main->versionfile <= 223) {
VFont *vf;
Image *ima;
Object *ob;
for (vf= main->vfont.first; vf; vf= vf->id.next) {
if (BLI_streq(vf->name+strlen(vf->name)-6, ".Bfont")) {
strcpy(vf->name, "<builtin>");
}
}
/* Old textures animate at 25 FPS */
for (ima = main->image.first; ima; ima=ima->id.next){
ima->animspeed = 25;
}
/* Zr remapped some keyboard codes to be linear (stupid zr) */
for (ob= main->object.first; ob; ob= ob->id.next) {
bSensor *sens;
for (sens= ob->sensors.first; sens; sens= sens->next) {
if (sens->type==SENS_KEYBOARD) {
bKeyboardSensor *ks= sens->data;
ks->key= map_223_keybd_code_to_224_keybd_code(ks->key);
ks->qual= map_223_keybd_code_to_224_keybd_code(ks->qual);
ks->qual2= map_223_keybd_code_to_224_keybd_code(ks->qual2);
}
}
}
}
if(main->versionfile <= 224) {
bSound* sound;
Scene *sce;
Mesh *me;
bScreen *sc;
for (sound=main->sound.first; sound; sound=sound->id.next)
{
if (sound->packedfile) {
if (sound->newpackedfile == NULL) {
sound->newpackedfile = sound->packedfile;
}
sound->packedfile = NULL;
}
}
/* Make sure that old subsurf meshes don't have zero subdivision level for rendering */
for (me=main->mesh.first; me; me=me->id.next){
if ((me->flag & ME_SUBSURF) && (me->subdivr==0))
me->subdivr=me->subdiv;
}
for (sce= main->scene.first; sce; sce= sce->id.next) {
sce->r.stereomode = 1; // no stereo
}
/* some oldfile patch, moved from set_func_space */
for (sc= main->screen.first; sc; sc= sc->id.next) {
ScrArea *sa;
for (sa= sc->areabase.first; sa; sa= sa->next) {
SpaceLink *sl;
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_IPO) {
SpaceSeq *sseq= (SpaceSeq*) sl;
sseq->v2d.keeptot= 0;
}
}
}
}
}
if(main->versionfile <= 225) {
World *wo;
/* Use Sumo for old games */
for (wo = main->world.first; wo; wo= wo->id.next) {
wo->physicsEngine = 2;
}
}
if(main->versionfile <= 227) {
Scene *sce;
Material *ma;
bScreen *sc;
Object *ob;
/* As of now, this insures that the transition from the old Track system
to the new full constraint Track is painless for everyone. - theeth
*/
ob = main->object.first;
while (ob) {
ListBase *list;
list = &ob->constraints;
/* check for already existing TrackTo constraint
set their track and up flag correctly */
if (list){
bConstraint *curcon;
for (curcon = list->first; curcon; curcon=curcon->next){
if (curcon->type == CONSTRAINT_TYPE_TRACKTO){
bTrackToConstraint *data = curcon->data;
data->reserved1 = ob->trackflag;
data->reserved2 = ob->upflag;
}
}
}
if (ob->type == OB_ARMATURE) {
if (ob->pose){
bConstraint *curcon;
bPoseChannel *pchan;
for (pchan = ob->pose->chanbase.first;
pchan; pchan=pchan->next){
for (curcon = pchan->constraints.first;
curcon; curcon=curcon->next){
if (curcon->type == CONSTRAINT_TYPE_TRACKTO){
bTrackToConstraint *data = curcon->data;
data->reserved1 = ob->trackflag;
data->reserved2 = ob->upflag;
}
}
}
}
}
/* Change Ob->Track in real TrackTo constraint */
if (ob->track){
bConstraint *con;
bTrackToConstraint *data;
list = &ob->constraints;
if (list)
{
con = MEM_callocN(sizeof(bConstraint), "constraint");
strcpy (con->name, "AutoTrack");
unique_constraint_name(con, list);
con->flag |= CONSTRAINT_EXPAND;
con->enforce=1.0F;
con->type = CONSTRAINT_TYPE_TRACKTO;
data = (bTrackToConstraint *)
new_constraint_data(CONSTRAINT_TYPE_TRACKTO);
data->tar = ob->track;
data->reserved1 = ob->trackflag;
data->reserved2 = ob->upflag;
con->data= (void*) data;
BLI_addtail(list, con);
}
ob->track = 0;
}
ob = ob->id.next;
}
for (sce= main->scene.first; sce; sce= sce->id.next) {
sce->audio.mixrate = 44100;
sce->audio.flag |= AUDIO_SCRUB;
sce->r.mode |= R_ENVMAP;
}
// init new shader vars
for (ma= main->mat.first; ma; ma= ma->id.next) {
ma->refrac= 4.0f;
ma->roughness= 0.5f;
ma->param[0]= 0.5f;
ma->param[1]= 0.1f;
ma->param[2]= 0.1f;
ma->param[3]= 0.05f;
}
// patch for old wrong max view2d settings, allows zooming out more
for (sc= main->screen.first; sc; sc= sc->id.next) {
ScrArea *sa;
for (sa= sc->areabase.first; sa; sa= sa->next) {
SpaceLink *sl;
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_ACTION) {
SpaceAction *sac= (SpaceAction *) sl;
sac->v2d.max[0]= 32000;
}
else if (sl->spacetype==SPACE_NLA) {
SpaceNla *sla= (SpaceNla *) sl;
sla->v2d.max[0]= 32000;
}
}
}
}
}
if(main->versionfile <= 228) {
Scene *sce;
bScreen *sc;
Object *ob;
/* As of now, this insures that the transition from the old Track system
to the new full constraint Track is painless for everyone.*/
ob = main->object.first;
while (ob) {
ListBase *list;
list = &ob->constraints;
/* check for already existing TrackTo constraint
set their track and up flag correctly */
if (list){
bConstraint *curcon;
for (curcon = list->first; curcon; curcon=curcon->next){
if (curcon->type == CONSTRAINT_TYPE_TRACKTO){
bTrackToConstraint *data = curcon->data;
data->reserved1 = ob->trackflag;
data->reserved2 = ob->upflag;
}
}
}
if (ob->type == OB_ARMATURE) {
if (ob->pose){
bConstraint *curcon;
bPoseChannel *pchan;
for (pchan = ob->pose->chanbase.first;
pchan; pchan=pchan->next){
for (curcon = pchan->constraints.first;
curcon; curcon=curcon->next){
if (curcon->type == CONSTRAINT_TYPE_TRACKTO){
bTrackToConstraint *data = curcon->data;
data->reserved1 = ob->trackflag;
data->reserved2 = ob->upflag;
}
}
}
}
}
ob = ob->id.next;
}
for (sce= main->scene.first; sce; sce= sce->id.next) {
sce->r.mode |= R_ENVMAP;
}
// convert old mainb values for new button panels
for (sc= main->screen.first; sc; sc= sc->id.next) {
ScrArea *sa;
for (sa= sc->areabase.first; sa; sa= sa->next) {
SpaceLink *sl;
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_BUTS) {
SpaceButs *sbuts= (SpaceButs *) sl;
sbuts->v2d.maxzoom= 1.2f;
if(sbuts->mainb==BUTS_LAMP) {
sbuts->mainb= CONTEXT_SHADING;
sbuts->tab[CONTEXT_SHADING]= TAB_SHADING_LAMP;
}
else if(sbuts->mainb==BUTS_MAT) {
sbuts->mainb= CONTEXT_SHADING;
sbuts->tab[CONTEXT_SHADING]= TAB_SHADING_MAT;
}
else if(sbuts->mainb==BUTS_TEX) {
sbuts->mainb= CONTEXT_SHADING;
sbuts->tab[CONTEXT_SHADING]= TAB_SHADING_TEX;
}
else if(sbuts->mainb==BUTS_ANIM) {
sbuts->mainb= CONTEXT_OBJECT;
}
else if(sbuts->mainb==BUTS_WORLD) {
sbuts->mainb= CONTEXT_SCENE;
sbuts->tab[CONTEXT_SCENE]= TAB_SCENE_WORLD;
}
else if(sbuts->mainb==BUTS_RENDER) {
sbuts->mainb= CONTEXT_SCENE;
sbuts->tab[CONTEXT_SCENE]= TAB_SCENE_RENDER;
}
else if(sbuts->mainb==BUTS_GAME) {
sbuts->mainb= CONTEXT_LOGIC;
}
else if(sbuts->mainb==BUTS_FPAINT) {
sbuts->mainb= CONTEXT_EDITING;
}
else if(sbuts->mainb==BUTS_RADIO) {
sbuts->mainb= CONTEXT_SHADING;
sbuts->tab[CONTEXT_SHADING]= TAB_SHADING_RAD;
}
else if(sbuts->mainb==BUTS_CONSTRAINT) {
sbuts->mainb= CONTEXT_OBJECT;
}
else if(sbuts->mainb==BUTS_SCRIPT) {
sbuts->mainb= CONTEXT_OBJECT;
}
else if(sbuts->mainb==BUTS_EDIT) {
sbuts->mainb= CONTEXT_EDITING;
}
else sbuts->mainb= CONTEXT_SCENE;
}
}
}
}
}
/* ton: made this 230 instead of 229,
to be sure (tuho files) and this is a reliable check anyway
nevertheless, we might need to think over a fitness (initialize)
check apart from the do_versions() */
if(main->versionfile <= 230) {
bScreen *sc;
// new variable blockscale, for panels in any area
for (sc= main->screen.first; sc; sc= sc->id.next) {
ScrArea *sa;
for (sa= sc->areabase.first; sa; sa= sa->next) {
SpaceLink *sl;
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if(sl->blockscale==0.0) sl->blockscale= 0.7f;
/* added: 5x better zoom in for action */
if(sl->spacetype==SPACE_ACTION) {
SpaceAction *sac= (SpaceAction *)sl;
sac->v2d.maxzoom= 50;
}
}
}
}
}
if(main->versionfile <= 231) {
/* new bit flags for showing/hiding grid floor and axes */
bScreen *sc = main->screen.first;
while(sc) {
ScrArea *sa= sc->areabase.first;
while(sa) {
SpaceLink *sl= sa->spacedata.first;
while (sl) {
if (sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D*) sl;
if (v3d->gridflag==0) {
v3d->gridflag |= V3D_SHOW_X;
v3d->gridflag |= V3D_SHOW_Y;
v3d->gridflag |= V3D_SHOW_FLOOR;
v3d->gridflag &= ~V3D_SHOW_Z;
}
}
sl= sl->next;
}
sa= sa->next;
}
sc= sc->id.next;
}
}
if(main->versionfile <= 231) {
Material *ma= main->mat.first;
bScreen *sc = main->screen.first;
Scene *sce;
Lamp *la;
World *wrld;
while(ma) {
if(ma->fresnel_tra_i==0.0) ma->fresnel_tra_i= 1.25;
if(ma->fresnel_mir_i==0.0) ma->fresnel_mir_i= 1.25;
if(ma->ang==0.0) {
ma->ang= 1.0;
ma->ray_depth= 2;
ma->ray_depth_tra= 2;
ma->fresnel_tra= 0.0;
ma->fresnel_mir= 0.0;
}
else if(ma->ang<1.0) { // temporal, because of IOR & fresnel change
ma->ang= 1.0f/ma->ang;
ma->fresnel_tra= ma->ang;
ma->fresnel_mir= ma->ang;
}
ma= ma->id.next;
}
sce= main->scene.first;
while(sce) {
if(sce->r.gauss==0.0) sce->r.gauss= 1.0;
sce= sce->id.next;
}
la= main->lamp.first;
while(la) {
if(la->k==0.0) la->k= 1.0;
if(la->ray_samp==0) la->ray_samp= 1;
if(la->ray_sampy==0) la->ray_sampy= 1;
if(la->ray_sampz==0) la->ray_sampz= 1;
if(la->area_size==0.0) la->area_size= 1.0;
if(la->area_sizey==0.0) la->area_sizey= 1.0;
if(la->area_sizez==0.0) la->area_sizez= 1.0;
la= la->id.next;
}
wrld= main->world.first;
while(wrld) {
if(wrld->range==0.0) {
wrld->range= 1.0f/wrld->exposure;
}
wrld= wrld->id.next;
}
/* new bit flags for showing/hiding grid floor and axes */
while(sc) {
ScrArea *sa= sc->areabase.first;
while(sa) {
SpaceLink *sl= sa->spacedata.first;
while (sl) {
if (sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D*) sl;
if (v3d->gridflag==0) {
v3d->gridflag |= V3D_SHOW_X;
v3d->gridflag |= V3D_SHOW_Y;
v3d->gridflag |= V3D_SHOW_FLOOR;
v3d->gridflag &= ~V3D_SHOW_Z;
}
}
sl= sl->next;
}
sa= sa->next;
}
sc= sc->id.next;
}
}
if(main->versionfile <= 232) {
Tex *tex= main->tex.first;
World *wrld= main->world.first;
bScreen *sc;
Scene *sce;
while(tex) {
if((tex->flag & (TEX_CHECKER_ODD+TEX_CHECKER_EVEN))==0) {
tex->flag |= TEX_CHECKER_ODD;
}
/* copied from kernel texture.c */
if(tex->ns_outscale==0.0) {
/* musgrave */
tex->mg_H = 1.0f;
tex->mg_lacunarity = 2.0f;
tex->mg_octaves = 2.0f;
tex->mg_offset = 1.0f;
tex->mg_gain = 1.0f;
tex->ns_outscale = 1.0f;
/* distnoise */
tex->dist_amount = 1.0f;
/* voronoi */
tex->vn_w1 = 1.0f;
tex->vn_mexp = 2.5f;
}
tex= tex->id.next;
}
while(wrld) {
if(wrld->aodist==0.0) {
wrld->aodist= 10.0f;
wrld->aobias= 0.05f;
}
if(wrld->aosamp==0.0) wrld->aosamp= 5;
if(wrld->aoenergy==0.0) wrld->aoenergy= 1.0;
wrld= wrld->id.next;
}
// new variable blockscale, for panels in any area, do again because new
// areas didnt initialize it to 0.7 yet
for (sc= main->screen.first; sc; sc= sc->id.next) {
ScrArea *sa;
for (sa= sc->areabase.first; sa; sa= sa->next) {
SpaceLink *sl;
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if(sl->blockscale==0.0) sl->blockscale= 0.7f;
/* added: 5x better zoom in for nla */
if(sl->spacetype==SPACE_NLA) {
SpaceNla *snla= (SpaceNla *)sl;
snla->v2d.maxzoom= 50;
}
}
}
}
sce= main->scene.first;
while(sce) {
if(sce->r.ocres==0) sce->r.ocres= 64;
sce= sce->id.next;
}
}
if(main->versionfile <= 233) {
bScreen *sc;
Material *ma= main->mat.first;
Object *ob= main->object.first;
while(ma) {
if(ma->rampfac_col==0.0) ma->rampfac_col= 1.0;
if(ma->rampfac_spec==0.0) ma->rampfac_spec= 1.0;
if(ma->pr_lamp==0) ma->pr_lamp= 3;
ma= ma->id.next;
}
/* this should have been done loooong before! */
while(ob) {
if(ob->ipowin==0) ob->ipowin= ID_OB;
ob= ob->id.next;
}
for (sc= main->screen.first; sc; sc= sc->id.next) {
ScrArea *sa;
for (sa= sc->areabase.first; sa; sa= sa->next) {
SpaceLink *sl;
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if(sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D *)sl;
v3d->flag |= V3D_SELECT_OUTLINE;
}
}
}
}
}
if(main->versionfile <= 234) {
Scene *sce;
World *wo;
bScreen *sc;
int set_zbuf_sel=0;
// force sumo engine to be active
for (wo = main->world.first; wo; wo= wo->id.next) {
if(wo->physicsEngine==0) wo->physicsEngine = 2;
}
for (sce= main->scene.first; sce; sce= sce->id.next) {
if(sce->selectmode==0) {
sce->selectmode= SCE_SELECT_VERTEX;
set_zbuf_sel= 1;
}
}
for (sc= main->screen.first; sc; sc= sc->id.next) {
ScrArea *sa;
for (sa= sc->areabase.first; sa; sa= sa->next) {
SpaceLink *sl;
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if(sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D *)sl;
if(set_zbuf_sel) v3d->flag |= V3D_ZBUF_SELECT;
}
else if(sl->spacetype==SPACE_TEXT) {
SpaceText *st= (SpaceText *)sl;
if(st->tabnumber==0) st->tabnumber= 2;
}
}
}
}
}
if(main->versionfile <= 235) {
Tex *tex= main->tex.first;
Scene *sce= main->scene.first;
Sequence *seq;
Editing *ed;
while(tex) {
if(tex->nabla==0.0) tex->nabla= 0.025f;
tex= tex->id.next;
}
while(sce) {
sce->r.postsat= 1.0;
ed= sce->ed;
if(ed) {
WHILE_SEQ(&ed->seqbase) {
if(seq->type==SEQ_IMAGE || seq->type==SEQ_MOVIE) seq->flag |= SEQ_MAKE_PREMUL;
}
END_SEQ
}
sce= sce->id.next;
}
}
if(main->versionfile <= 236) {
Object *ob;
Scene *sce= main->scene.first;
Camera *cam= main->camera.first;
Material *ma;
bScreen *sc;
while(sce) {
sce->r.mode &= ~R_ZBLUR; // disabled for release
if(sce->r.postsat==0.0) sce->r.postsat= 1.0f;
if(sce->r.zgamma==0.0) {
sce->r.focus= 0.9f;
sce->r.zgamma= 1.0f;
sce->r.zsigma= 4.0f;
sce->r.zblur= 10.0f;
sce->r.zmin= 0.8f;
}
if(sce->editbutsize==0.0) sce->editbutsize= 0.1f;
sce= sce->id.next;
}
while(cam) {
if(cam->ortho_scale==0.0) {
cam->ortho_scale= 256.0f/cam->lens;
if(cam->type==CAM_ORTHO) printf("NOTE: ortho render has changed, tweak new Camera 'scale' value.\n");
}
cam= cam->id.next;
}
/* set manipulator type */
/* force oops draw if depgraph was set*/
/* set time line var */
for (sc= main->screen.first; sc; sc= sc->id.next) {
ScrArea *sa;
for (sa= sc->areabase.first; sa; sa= sa->next) {
SpaceLink *sl;
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if(sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D *)sl;
if(v3d->twtype==0) v3d->twtype= V3D_MANIP_TRANSLATE;
}
#ifndef SHOWDEPGRAPH
if(sl->spacetype==SPACE_OOPS) {
if ( ((SpaceOops *)sl)->type==SO_DEPSGRAPH)
((SpaceOops *)sl)->type=SO_OOPS;
}
#endif
if(sl->spacetype==SPACE_TIME) {
SpaceTime *stime= (SpaceTime *)sl;
if(stime->redraws==0)
stime->redraws= TIME_ALL_3D_WIN|TIME_ALL_ANIM_WIN;
}
}
}
}
// init new shader vars
for (ma= main->mat.first; ma; ma= ma->id.next) {
if(ma->darkness==0.0) {
ma->rms=0.1f;
ma->darkness=1.0f;
}
}
/* softbody init new vars */
for(ob= main->object.first; ob; ob= ob->id.next) {
if(ob->soft) {
if(ob->soft->defgoal==0.0) ob->soft->defgoal= 0.7f;
if(ob->soft->physics_speed==0.0) ob->soft->physics_speed= 1.0f;
if(ob->soft->interval==0) {
ob->soft->interval= 2;
ob->soft->sfra= 1;
ob->soft->efra= 100;
}
}
if(ob->soft && ob->soft->vertgroup==0) {
bDeformGroup *locGroup = get_named_vertexgroup(ob, "SOFTGOAL");
if(locGroup){
/* retrieve index for that group */
ob->soft->vertgroup = 1 + get_defgroup_num(ob, locGroup);
}
}
}
}
if(main->versionfile <= 237) {
bArmature *arm;
bConstraint *con;
Object *ob;
// armature recode checks
for(arm= main->armature.first; arm; arm= arm->id.next) {
where_is_armature(arm);
}
for(ob= main->object.first; ob; ob= ob->id.next) {
if(ob->parent) {
Object *parent= newlibadr(fd, lib, ob->parent);
if (parent && parent->type==OB_LATTICE)
ob->partype = PARSKEL;
}
// btw. armature_rebuild_pose is further only called on leave editmode
if(ob->type==OB_ARMATURE) {
if(ob->pose)
ob->pose->flag |= POSE_RECALC;
ob->recalc |= OB_RECALC; // cannot call stuff now (pointers!), done in setup_app_data
/* new generic xray option */
arm= newlibadr(fd, lib, ob->data);
if(arm->flag & ARM_DRAWXRAY) {
ob->dtx |= OB_DRAWXRAY;
}
} else if (ob->type==OB_MESH) {
Mesh *me = newlibadr(fd, lib, ob->data);
if ((me->flag&ME_SUBSURF)) {
SubsurfModifierData *smd = (SubsurfModifierData*) modifier_new(eModifierType_Subsurf);
smd->levels = MAX2(1, me->subdiv);
smd->renderLevels = MAX2(1, me->subdivr);
smd->subdivType = me->subsurftype;
smd->modifier.mode = 0;
if (me->subdiv!=0)
smd->modifier.mode |= 1;
if (me->subdivr!=0)
smd->modifier.mode |= 2;
if (me->flag&ME_OPT_EDGES)
smd->flags |= eSubsurfModifierFlag_ControlEdges;
BLI_addtail(&ob->modifiers, smd);
}
}
// follow path constraint needs to set the 'path' option in curves...
for(con=ob->constraints.first; con; con= con->next) {
if(con->type==CONSTRAINT_TYPE_FOLLOWPATH) {
bFollowPathConstraint *data = con->data;
Object *obc= newlibadr(fd, lib, data->tar);
if(obc && obc->type==OB_CURVE) {
Curve *cu= newlibadr(fd, lib, obc->data);
if(cu) cu->flag |= CU_PATH;
}
}
}
}
}
if(main->versionfile <= 238) {
Lattice *lt;
Object *ob;
bArmature *arm;
Mesh *me;
Key *key;
Scene *sce= main->scene.first;
while(sce){
if(sce->toolsettings == NULL){
sce->toolsettings = MEM_mallocN(sizeof(struct ToolSettings),"Tool Settings Struct");
sce->toolsettings->cornertype=0;
sce->toolsettings->degr = 90;
sce->toolsettings->step = 9;
sce->toolsettings->turn = 1;
sce->toolsettings->extr_offs = 1;
sce->toolsettings->doublimit = 0.001f;
sce->toolsettings->segments = 32;
sce->toolsettings->rings = 32;
sce->toolsettings->vertices = 32;
sce->toolsettings->editbutflag =1;
}
sce= sce->id.next;
}
for (lt=main->latt.first; lt; lt=lt->id.next) {
if (lt->fu==0.0 && lt->fv==0.0 && lt->fw==0.0) {
calc_lat_fudu(lt->flag, lt->pntsu, &lt->fu, &lt->du);
calc_lat_fudu(lt->flag, lt->pntsv, &lt->fv, &lt->dv);
calc_lat_fudu(lt->flag, lt->pntsw, &lt->fw, &lt->dw);
}
}
for(ob=main->object.first; ob; ob= ob->id.next) {
ModifierData *md;
PartEff *paf;
for (md=ob->modifiers.first; md; md=md->next) {
if (md->type==eModifierType_Subsurf) {
SubsurfModifierData *smd = (SubsurfModifierData*) md;
smd->flags &= ~(eSubsurfModifierFlag_Incremental|eSubsurfModifierFlag_DebugIncr);
}
}
if ((ob->softflag&OB_SB_ENABLE) && !modifiers_findByType(ob, eModifierType_Softbody)) {
if (ob->softflag&OB_SB_POSTDEF) {
md = ob->modifiers.first;
while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
md = md->next;
}
BLI_insertlinkbefore(&ob->modifiers, md, modifier_new(eModifierType_Softbody));
} else {
BLI_addhead(&ob->modifiers, modifier_new(eModifierType_Softbody));
}
ob->softflag &= ~OB_SB_ENABLE;
}
if(ob->pose) {
bPoseChannel *pchan;
bConstraint *con;
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
// note, pchan->bone is also lib-link stuff
if (pchan->limitmin[0] == 0.0f && pchan->limitmax[0] == 0.0f) {
pchan->limitmin[0]= pchan->limitmin[1]= pchan->limitmin[2]= -180.0f;
pchan->limitmax[0]= pchan->limitmax[1]= pchan->limitmax[2]= 180.0f;
for(con= pchan->constraints.first; con; con= con->next) {
if(con->type == CONSTRAINT_TYPE_KINEMATIC) {
bKinematicConstraint *data = (bKinematicConstraint*)con->data;
data->weight = 1.0f;
data->orientweight = 1.0f;
data->flag &= ~CONSTRAINT_IK_ROT;
/* enforce conversion from old IK_TOPARENT to rootbone index */
data->rootbone= -1;
/* update_pose_etc handles rootbone==-1 */
ob->pose->flag |= POSE_RECALC;
}
}
}
}
}
paf = give_parteff(ob);
if (paf) {
if(paf->disp == 0)
paf->disp = 100;
if(paf->speedtex == 0)
paf->speedtex = 8;
if(paf->omat == 0)
paf->omat = 1;
}
}
for(arm=main->armature.first; arm; arm= arm->id.next) {
bone_version_238(&arm->bonebase);
arm->deformflag |= ARM_DEF_VGROUP;
}
for(me=main->mesh.first; me; me= me->id.next) {
if (!me->medge) {
make_edges(me, 1); /* 1 = use mface->edcode */
} else {
mesh_strip_loose_faces(me);
}
}
for(key= main->key.first; key; key= key->id.next) {
KeyBlock *kb;
int index= 1;
/* trick to find out if we already introduced adrcode */
for(kb= key->block.first; kb; kb= kb->next)
if(kb->adrcode) break;
if(kb==NULL) {
for(kb= key->block.first; kb; kb= kb->next) {
if(kb==key->refkey) {
if(kb->name[0]==0)
strcpy(kb->name, "Basis");
}
else {
if(kb->name[0]==0)
sprintf(kb->name, "Key %d", index);
kb->adrcode= index++;
}
}
}
}
}
if(main->versionfile <= 239) {
bArmature *arm;
Object *ob;
Scene *sce= main->scene.first;
Camera *cam= main->camera.first;
Material *ma= main->mat.first;
int set_passepartout= 0;
/* deformflag is local in modifier now */
for(ob=main->object.first; ob; ob= ob->id.next) {
ModifierData *md;
for (md=ob->modifiers.first; md; md=md->next) {
if (md->type==eModifierType_Armature) {
ArmatureModifierData *amd = (ArmatureModifierData*) md;
if(amd->object && amd->deformflag==0) {
Object *oba= newlibadr(fd, lib, amd->object);
bArmature *arm= newlibadr(fd, lib, oba->data);
amd->deformflag= arm->deformflag;
}
}
}
}
/* updating stepsize for ghost drawing */
for(arm= main->armature.first; arm; arm= arm->id.next) {
if (arm->ghostsize==0) arm->ghostsize=1;
bone_version_239(&arm->bonebase);
if(arm->layer==0) arm->layer= 1;
}
for(;sce;sce= sce->id.next) {
/* make 'innervert' the default subdivide type, for backwards compat */
sce->toolsettings->cornertype=1;
if(sce->r.scemode & R_PASSEPARTOUT) {
set_passepartout= 1;
sce->r.scemode &= ~R_PASSEPARTOUT;
}
/* gauss is filter variable now */
if(sce->r.mode & R_GAUSS) {
sce->r.filtertype= R_FILTER_GAUSS;
sce->r.mode &= ~R_GAUSS;
}
}
for(;cam; cam= cam->id.next) {
if(set_passepartout)
cam->flag |= CAM_SHOWPASSEPARTOUT;
/* make sure old cameras have title safe on */
/* *** to be uncommented before 2.40 release! *** */
/*
if (!(cam->flag & CAM_SHOWTITLESAFE))
cam->flag |= CAM_SHOWTITLESAFE;
*/
/* set an appropriate camera passepartout alpha */
if (!(cam->passepartalpha)) cam->passepartalpha = 0.2f;
}
for(; ma; ma= ma->id.next) {
if(ma->strand_sta==0.0f) {
ma->strand_sta= ma->strand_end= 1.0f;
ma->mode |= MA_TANGENT_STR;
}
/* remove this test before 2.40 too! pad is set to denote check was done */
if(ma->pad==0) {
if(ma->mode & MA_TRACEBLE) ma->mode |= MA_SHADBUF;
ma->pad= 1;
}
/* orange stuff, so should be done for 2.40 too */
if(ma->layers.first==NULL) {
ma->ml_flag= ML_RENDER;
}
}
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */
/* don't forget to set version number in blender.c! */
}
static void lib_link_all(FileData *fd, Main *main)
{
lib_link_screen(fd, main);
lib_link_scene(fd, main);
lib_link_object(fd, main);
lib_link_curve(fd, main);
lib_link_mball(fd, main);
lib_link_material(fd, main);
lib_link_texture(fd, main);
lib_link_image(fd, main);
lib_link_ipo(fd, main);
lib_link_key(fd, main);
lib_link_world(fd, main);
lib_link_lamp(fd, main);
lib_link_latt(fd, main);
lib_link_text(fd, main);
lib_link_camera(fd, main);
lib_link_sound(fd, main);
lib_link_group(fd, main);
lib_link_armature(fd, main);
lib_link_action(fd, main);
lib_link_vfont(fd, main);
lib_link_mesh(fd, main); /* as last: tpage images with users at zero */
lib_link_library(fd, main); /* only init users */
}
static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
{
Link *link;
bfd->user= read_struct(fd, bhead, "user def");
bfd->user->themes.first= bfd->user->themes.last= NULL;
bhead = blo_nextbhead(fd, bhead);
/* read all attached data */
while(bhead && bhead->code==DATA) {
link= read_struct(fd, bhead, "user def data");
BLI_addtail(&bfd->user->themes, link);
bhead = blo_nextbhead(fd, bhead);
}
return bhead;
}
BlendFileData *blo_read_file_internal(FileData *fd, BlendReadError *error_r)
{
BHead *bhead= blo_firstbhead(fd);
BlendFileData *bfd;
FileGlobal *fg = (FileGlobal *)NULL;
bfd= MEM_callocN(sizeof(BlendFileData), "blendfiledata");
bfd->main= MEM_callocN(sizeof(Main), "main");
BLI_addtail(&fd->mainlist, bfd->main);
bfd->main->versionfile= fd->fileversion;
while(bhead) {
switch(bhead->code) {
case GLOB:
case DATA:
case DNA1:
case TEST:
case REND:
if (bhead->code==GLOB) {
fg= read_struct(fd, bhead, "REND");
}
bhead = blo_nextbhead(fd, bhead);
break;
case USER:
bhead= read_userdef(bfd, fd, bhead);
break;
case ENDB:
bhead = NULL;
break;
case ID_LI:
bhead = read_libblock(fd, bfd->main, bhead, LIB_LOCAL, NULL);
break;
case ID_ID:
/* always adds to the most recently loaded
* ID_LI block, see direct_link_library.
* this is part of the file format definition.
*/
bhead = read_libblock(fd, fd->mainlist.last, bhead, LIB_READ+LIB_EXTERN, NULL);
break;
default:
bhead = read_libblock(fd, bfd->main, bhead, LIB_LOCAL, NULL);
}
}
/* before read_libraries */
do_versions(fd, NULL, bfd->main);
read_libraries(fd, &fd->mainlist);
blo_join_main(&fd->mainlist);
lib_link_all(fd, bfd->main);
link_global(fd, bfd, fg); /* as last */
/* removed here: check for existance of curscreen/scene, moved to kernel setup_app */
MEM_freeN(fg);
return bfd;
}
/* ************* APPEND LIBRARY ************** */
static BHead *find_previous_lib(FileData *fd, BHead *bhead)
{
for (; bhead; bhead= blo_prevbhead(fd, bhead))
if (bhead->code==ID_LI)
break;
return bhead;
}
static BHead *find_bhead(FileData *fd, void *old)
{
BHead *bhead;
if (!old)
return NULL;
for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead))
if (bhead->old==old)
return bhead;
return NULL;
}
static ID *is_yet_read(Main *mainvar, BHead *bhead)
{
ListBase *lb;
ID *idtest, *id;
// BHEAD+DATA dependancy
idtest= (ID *)(bhead +1);
lb= wich_libbase(mainvar, GS(idtest->name));
if(lb) {
id= lb->first;
while(id) {
if( strcmp(id->name, idtest->name)==0 ) return id;
id= id->next;
}
}
return 0;
}
static void expand_doit(FileData *fd, Main *mainvar, void *old)
{
BHead *bhead;
ID *id;
bhead= find_bhead(fd, old);
if(bhead) {
/* from another library? */
if(bhead->code==ID_ID) {
BHead *bheadlib= find_previous_lib(fd, bhead);
if(bheadlib) {
// BHEAD+DATA dependancy
Library *lib= (Library *)(bheadlib+1);
/* we read the lib->name directly from the bhead, potential danger (64 bits?) */
mainvar= blo_find_main(&fd->mainlist, lib->name);
id= is_yet_read(mainvar, bhead);
if(id==0) {
read_libblock(fd, mainvar, bhead, LIB_READ+LIB_INDIRECT, NULL);
printf("expand: other lib %s\n", lib->name);
}
else {
oldnewmap_insert(fd->libmap, bhead->old, id, 1);
printf("expand: already linked: %s lib: %s\n", id->name, lib->name);
}
}
}
else {
id= is_yet_read(mainvar, bhead);
if(id==0) {
// BHEAD+DATA dependancy
id= (ID *)(bhead+1);
read_libblock(fd, mainvar, bhead, LIB_TESTIND, NULL);
}
else {
oldnewmap_insert(fd->libmap, bhead->old, id, 1);
/* printf("expand: already read %s\n", id->name); */
}
}
}
}
static void expand_group(FileData *fd, Main *mainvar, Group *group)
{
GroupObject *go;
for(go= group->gobject.first; go; go= go->next) {
expand_doit(fd, mainvar, go->ob);
}
}
static void expand_key(FileData *fd, Main *mainvar, Key *key)
{
expand_doit(fd, mainvar, key->ipo);
}
static void expand_texture(FileData *fd, Main *mainvar, Tex *tex)
{
expand_doit(fd, mainvar, tex->ima);
expand_doit(fd, mainvar, tex->ipo);
}
static void expand_material(FileData *fd, Main *mainvar, Material *ma)
{
MaterialLayer *ml;
int a;
for(a=0; a<MAX_MTEX; a++) {
if(ma->mtex[a]) {
expand_doit(fd, mainvar, ma->mtex[a]->tex);
expand_doit(fd, mainvar, ma->mtex[a]->object);
}
}
expand_doit(fd, mainvar, ma->ipo);
for (ml=ma->layers.first; ml; ml=ml->next) {
if(ml->mat)
expand_doit(fd, mainvar, ml->mat);
}
}
static void expand_lamp(FileData *fd, Main *mainvar, Lamp *la)
{
int a;
for(a=0; a<MAX_MTEX; a++) {
if(la->mtex[a]) {
expand_doit(fd, mainvar, la->mtex[a]->tex);
expand_doit(fd, mainvar, la->mtex[a]->object);
}
}
expand_doit(fd, mainvar, la->ipo);
}
static void expand_lattice(FileData *fd, Main *mainvar, Lattice *lt)
{
expand_doit(fd, mainvar, lt->ipo);
expand_doit(fd, mainvar, lt->key);
}
static void expand_world(FileData *fd, Main *mainvar, World *wrld)
{
int a;
for(a=0; a<MAX_MTEX; a++) {
if(wrld->mtex[a]) {
expand_doit(fd, mainvar, wrld->mtex[a]->tex);
expand_doit(fd, mainvar, wrld->mtex[a]->object);
}
}
expand_doit(fd, mainvar, wrld->ipo);
}
static void expand_mball(FileData *fd, Main *mainvar, MetaBall *mb)
{
int a;
for(a=0; a<mb->totcol; a++) {
expand_doit(fd, mainvar, mb->mat[a]);
}
}
static void expand_curve(FileData *fd, Main *mainvar, Curve *cu)
{
int a;
for(a=0; a<cu->totcol; a++) {
expand_doit(fd, mainvar, cu->mat[a]);
}
expand_doit(fd, mainvar, cu->vfont);
expand_doit(fd, mainvar, cu->vfontb);
expand_doit(fd, mainvar, cu->vfonti);
expand_doit(fd, mainvar, cu->vfontbi);
expand_doit(fd, mainvar, cu->key);
expand_doit(fd, mainvar, cu->ipo);
expand_doit(fd, mainvar, cu->bevobj);
expand_doit(fd, mainvar, cu->taperobj);
expand_doit(fd, mainvar, cu->textoncurve);
}
static void expand_mesh(FileData *fd, Main *mainvar, Mesh *me)
{
int a;
TFace *tface;
for(a=0; a<me->totcol; a++) {
expand_doit(fd, mainvar, me->mat[a]);
}
expand_doit(fd, mainvar, me->key);
expand_doit(fd, mainvar, me->texcomesh);
if(me->tface) {
tface= me->tface;
a= me->totface;
while(a--) {
if(tface->tpage) expand_doit(fd, mainvar, tface->tpage);
tface++;
}
}
}
static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
{
bConstraint *curcon;
for (curcon=lb->first; curcon; curcon=curcon->next) {
switch (curcon->type) {
case CONSTRAINT_TYPE_ACTION:
{
bActionConstraint *data = (bActionConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
expand_doit(fd, mainvar, data->act);
}
break;
case CONSTRAINT_TYPE_LOCLIKE:
{
bLocateLikeConstraint *data = (bLocateLikeConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
break;
}
case CONSTRAINT_TYPE_ROTLIKE:
{
bRotateLikeConstraint *data = (bRotateLikeConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
break;
}
case CONSTRAINT_TYPE_KINEMATIC:
{
bKinematicConstraint *data = (bKinematicConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
break;
}
case CONSTRAINT_TYPE_TRACKTO:
{
bTrackToConstraint *data = (bTrackToConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
break;
}
case CONSTRAINT_TYPE_MINMAX:
{
bMinMaxConstraint *data = (bMinMaxConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
break;
}
case CONSTRAINT_TYPE_LOCKTRACK:
{
bLockTrackConstraint *data = (bLockTrackConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
break;
}
case CONSTRAINT_TYPE_FOLLOWPATH:
{
bFollowPathConstraint *data = (bFollowPathConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
break;
}
case CONSTRAINT_TYPE_DISTANCELIMIT:
{
bDistanceLimitConstraint *data = (bDistanceLimitConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
break;
}
case CONSTRAINT_TYPE_STRETCHTO:
{
bStretchToConstraint *data = (bStretchToConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
break;
}
case CONSTRAINT_TYPE_NULL:
break;
default:
break;
}
}
}
static void expand_bones(FileData *fd, Main *mainvar, Bone *bone)
{
Bone *curBone;
for (curBone = bone->childbase.first; curBone; curBone=curBone->next) {
expand_bones(fd, mainvar, curBone);
}
}
static void expand_pose(FileData *fd, Main *mainvar, bPose *pose)
{
bPoseChannel *chan;
if (!pose)
return;
for (chan = pose->chanbase.first; chan; chan=chan->next) {
expand_constraints(fd, mainvar, &chan->constraints);
}
}
static void expand_armature(FileData *fd, Main *mainvar, bArmature *arm)
{
Bone *curBone;
for (curBone = arm->bonebase.first; curBone; curBone=curBone->next) {
expand_bones(fd, mainvar, curBone);
}
}
static void expand_constraint_channels(FileData *fd, Main *mainvar, ListBase *chanbase)
{
bConstraintChannel *chan;
for (chan=chanbase->first; chan; chan=chan->next){
expand_doit(fd, mainvar, chan->ipo);
}
}
static void expand_action(FileData *fd, Main *mainvar, bAction *act)
{
bActionChannel *chan;
for (chan=act->chanbase.first; chan; chan=chan->next) {
expand_doit(fd, mainvar, chan->ipo);
expand_constraint_channels(fd, mainvar, &chan->constraintChannels);
}
}
static void expand_modifier(FileData *fd, Main *mainvar, ModifierData *md)
{
if (md->type==eModifierType_Lattice) {
LatticeModifierData *lmd = (LatticeModifierData*) md;
expand_doit(fd, mainvar, lmd->object);
}
else if (md->type==eModifierType_Curve) {
CurveModifierData *cmd = (CurveModifierData*) md;
expand_doit(fd, mainvar, cmd->object);
}
}
static void expand_object(FileData *fd, Main *mainvar, Object *ob)
{
ModifierData *md;
bSensor *sens;
bController *cont;
bActuator *act;
bActionStrip *strip;
int a;
expand_doit(fd, mainvar, ob->data);
expand_doit(fd, mainvar, ob->ipo);
expand_doit(fd, mainvar, ob->action);
for (md=ob->modifiers.first; md; md=md->next) {
expand_modifier(fd, mainvar, md);
}
expand_pose(fd, mainvar, ob->pose);
expand_constraints(fd, mainvar, &ob->constraints);
expand_constraint_channels(fd, mainvar, &ob->constraintChannels);
for (strip=ob->nlastrips.first; strip; strip=strip->next){
expand_doit(fd, mainvar, strip->object);
expand_doit(fd, mainvar, strip->act);
expand_doit(fd, mainvar, strip->ipo);
}
for(a=0; a<ob->totcol; a++) {
expand_doit(fd, mainvar, ob->mat[a]);
}
sens= ob->sensors.first;
while(sens) {
for(a=0; a<sens->totlinks; a++) {
sens->links[a]= newglobadr(fd, sens->links[a]);
}
if(sens->type==SENS_TOUCH) {
bTouchSensor *ts= sens->data;
expand_doit(fd, mainvar, ts->ma);
}
else if(sens->type==SENS_MESSAGE) {
bMessageSensor *ms= sens->data;
expand_doit(fd, mainvar, ms->fromObject);
}
sens= sens->next;
}
cont= ob->controllers.first;
while(cont) {
for(a=0; a<cont->totlinks; a++) {
cont->links[a]= newglobadr(fd, cont->links[a]);
}
if(cont->type==CONT_PYTHON) {
bPythonCont *pc= cont->data;
expand_doit(fd, mainvar, pc->text);
}
cont= cont->next;
}
act= ob->actuators.first;
while(act) {
if(act->type==ACT_SOUND) {
bSoundActuator *sa= act->data;
expand_doit(fd, mainvar, sa->sound);
}
else if(act->type==ACT_CAMERA) {
bCameraActuator *ca= act->data;
expand_doit(fd, mainvar, ca->ob);
}
else if(act->type==ACT_EDIT_OBJECT) {
bEditObjectActuator *eoa= act->data;
if(eoa) {
expand_doit(fd, mainvar, eoa->ob);
expand_doit(fd, mainvar, eoa->me);
}
}
else if(act->type==ACT_SCENE) {
bSceneActuator *sa= act->data;
expand_doit(fd, mainvar, sa->camera);
expand_doit(fd, mainvar, sa->scene);
}
else if(act->type==ACT_ACTION) {
bActionActuator *aa= act->data;
expand_doit(fd, mainvar, aa->act);
}
else if(act->type==ACT_PROPERTY) {
bPropertyActuator *pa= act->data;
expand_doit(fd, mainvar, pa->ob);
}
else if(act->type==ACT_MESSAGE) {
bMessageActuator *ma= act->data;
expand_doit(fd, mainvar, ma->toObject);
}
act= act->next;
}
}
static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
{
Base *base;
base= sce->base.first;
while(base) {
expand_doit(fd, mainvar, base->object);
base= base->next;
}
expand_doit(fd, mainvar, sce->camera);
expand_doit(fd, mainvar, sce->world);
}
static void expand_camera(FileData *fd, Main *mainvar, Camera *ca)
{
expand_doit(fd, mainvar, ca->ipo);
}
static void expand_sound(FileData *fd, Main *mainvar, bSound *snd)
{
expand_doit(fd, mainvar, snd->ipo);
}
static void expand_main(FileData *fd, Main *mainvar)
{
ListBase *lbarray[30];
ID *id;
int a, doit= 1;
if(fd==0) return;
while(doit) {
doit= 0;
a= set_listbasepointers(mainvar, lbarray);
while(a--) {
id= lbarray[a]->first;
while(id) {
if(id->flag & LIB_TEST) {
switch(GS(id->name)) {
case ID_OB:
expand_object(fd, mainvar, (Object *)id);
break;
case ID_ME:
expand_mesh(fd, mainvar, (Mesh *)id);
break;
case ID_CU:
expand_curve(fd, mainvar, (Curve *)id);
break;
case ID_MB:
expand_mball(fd, mainvar, (MetaBall *)id);
break;
case ID_SCE:
expand_scene(fd, mainvar, (Scene *)id);
break;
case ID_MA:
expand_material(fd, mainvar, (Material *)id);
break;
case ID_TE:
expand_texture(fd, mainvar, (Tex *)id);
break;
case ID_WO:
expand_world(fd, mainvar, (World *)id);
break;
case ID_LT:
expand_lattice(fd, mainvar, (Lattice *)id);
break;
case ID_LA:
expand_lamp(fd, mainvar,(Lamp *)id);
break;
case ID_KE:
expand_key(fd, mainvar, (Key *)id);
break;
case ID_CA:
expand_camera(fd, mainvar, (Camera *)id);
break;
case ID_SO:
expand_sound(fd, mainvar, (bSound *)id);
break;
case ID_AR:
expand_armature(fd, mainvar, (bArmature *)id);
break;
case ID_AC:
expand_action(fd, mainvar, (bAction *)id);
break;
case ID_GR:
expand_group(fd, mainvar, (Group *)id);
break;
}
doit= 1;
id->flag -= LIB_TEST;
}
id= id->next;
}
}
}
}
static void give_base_to_objects(Scene *sce, ListBase *lb)
{
Object *ob;
Base *base;
/* give all objects which are LIB_EXTERN and LIB_NEEDLINK a base */
ob= lb->first;
while(ob) {
if(ob->id.us==0) {
if( ob->id.flag & LIB_INDIRECT ) {
base= MEM_callocN( sizeof(Base), "add_ext_base");
BLI_addtail(&(sce->base), base);
base->lay= ob->lay;
base->object= ob;
base->flag= ob->flag;
ob->id.us= 1;
ob->id.flag -= LIB_INDIRECT;
ob->id.flag |= LIB_EXTERN;
}
}
ob= ob->id.next;
}
}
static void append_named_part(FileData *fd, Main *mainvar, Scene *scene, char *name, int idcode, short flag)
{
Object *ob;
Base *base;
BHead *bhead;
ID *id;
int afbreek=0;
bhead = blo_firstbhead(fd);
while(bhead && afbreek==0) {
if(bhead->code==ENDB) afbreek= 1;
else if(bhead->code==idcode) {
// BHEAD+DATA dependancy
id= (ID *)(bhead+1);
if(strcmp(id->name+2, name)==0) {
id= is_yet_read(mainvar, bhead);
if(id==0) {
read_libblock(fd, mainvar, bhead, LIB_TESTEXT, NULL);
}
else {
printf("append: already linked\n");
oldnewmap_insert(fd->libmap, bhead->old, id, 1);
if(id->flag & LIB_INDIRECT) {
id->flag -= LIB_INDIRECT;
id->flag |= LIB_EXTERN;
}
}
if(idcode==ID_OB) { /* loose object: give a base */
base= MEM_callocN( sizeof(Base), "app_nam_part");
BLI_addtail(&scene->base, base);
if(id==0) ob= mainvar->object.last;
else ob= (Object *)id;
/* this is bad code... G.vd nor G.scene should be used on this level... */
if((flag & FILE_ACTIVELAY)) {
if(G.vd) ob->lay= G.vd->layact;
else ob->lay = G.scene->lay;
}
base->lay= ob->lay;
base->object= ob;
ob->id.us++;
if(flag & FILE_AUTOSELECT) {
base->flag |= SELECT;
base->object->flag = base->flag;
/* do NOT make base active here! screws up GUI stuff, if you want it do it on src/ level */
}
}
afbreek= 1;
}
}
bhead = blo_nextbhead(fd, bhead);
}
}
static void append_id_part(FileData *fd, Main *mainvar, ID *id, ID **id_r)
{
BHead *bhead;
for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
if (bhead->code == GS(id->name)) {
ID *idread= (ID *)(bhead+1); /* BHEAD+DATA dependancy */
if (BLI_streq(id->name, idread->name)) {
id->flag &= ~LIB_READ;
id->flag |= LIB_TEST;
// printf("read lib block %s\n", id->name);
read_libblock(fd, mainvar, bhead, id->flag, id_r);
break;
}
} else if (bhead->code==ENDB)
break;
}
}
/* this is a version of BLO_library_append needed by the BPython API, so
* scripts can load data from .blend files -- see Blender.Library module.*/
/* append to G.scene */
void BLO_script_library_append(BlendHandle *bh, char *dir, char *name, int idcode)
{
ListBase mainlist;
Main *mainl;
FileData *fd = (FileData *)bh;
char filename[FILE_MAXDIR+FILE_MAXFILE];
mainlist.first= mainlist.last= G.main;
G.main->next= NULL;
/* make copy of the 'last loaded filename', we need to restore it */
BLI_strncpy(filename, G.sce, sizeof(filename));
/* already opened file, to reconstruct relative paths */
BLI_strncpy(G.sce, fd->filename, sizeof(filename));
/* make mains */
blo_split_main(&mainlist);
/* which one do we need? */
mainl = blo_find_main(&mainlist, dir);
append_named_part(fd, mainl, G.scene, name, idcode, 0);
/* make main consistant */
expand_main(fd, mainl);
/* do this when expand found other libs */
read_libraries(fd, &mainlist);
blo_join_main(&mainlist);
G.main= mainlist.first;
lib_link_all(fd, G.main);
/* restore the 'last loaded filename' */
BLI_strncpy(G.sce, filename, sizeof(filename));
DAG_scene_sort(G.scene);
}
/* append to G.scene */
void BLO_library_append(SpaceFile *sfile, char *dir, int idcode)
{
FileData *fd= (FileData*) sfile->libfiledata;
Main *mainl;
Base *centerbase;
Object *ob;
float *curs,centerloc[3],vec[3],min[3],max[3];
int a, totsel=0,count=0;
char filename[FILE_MAXDIR+FILE_MAXFILE];
INIT_MINMAX(min, max);
/* are there files selected? */
for(a=0; a<sfile->totfile; a++) {
if(sfile->filelist[a].flags & ACTIVE) {
totsel++;
}
}
if(totsel==0) {
/* is the indicated file in the filelist? */
if(sfile->file[0]) {
for(a=0; a<sfile->totfile; a++) {
if( strcmp(sfile->filelist[a].relname, sfile->file)==0) break;
}
if(a==sfile->totfile) {
error("Wrong indicated name");
return;
}
}
else {
error("Nothing indicated");
return;
}
}
/* now we have or selected, or an indicated file */
/* make copy of the 'last loaded filename', we need to restore it */
BLI_strncpy(filename, G.sce, sizeof(filename));
BLI_strncpy(G.sce, G.main->name, sizeof(G.main->name)); // original file, to reconstruct relative paths for current append
if(sfile->flag & FILE_AUTOSELECT) scene_deselect_all(G.scene);
fd->mainlist.first= fd->mainlist.last= G.main;
G.main->next= NULL;
/* make mains */
blo_split_main(&fd->mainlist);
/* which one do we need? */
mainl = blo_find_main(&fd->mainlist, dir);
mainl->versionfile= fd->fileversion; // needed for do_version
if(totsel==0) {
append_named_part(fd, mainl, G.scene, sfile->file, idcode, sfile->flag);
}
else {
for(a=0; a<sfile->totfile; a++) {
if(sfile->filelist[a].flags & ACTIVE) {
append_named_part(fd, mainl, G.scene, sfile->filelist[a].relname, idcode, sfile->flag);
}
}
}
/* make main consistant */
expand_main(fd, mainl);
/* do this when expand found other libs */
read_libraries(fd, &fd->mainlist);
if(sfile->flag & FILE_STRINGCODE) {
/* uses old .blend file (*filename) as reference */
BLI_makestringcode(filename, mainl->curlib->name);
/* the caller checks for appended library, so we make sure names match */
BLI_strncpy(dir, mainl->curlib->name, sizeof(mainl->curlib->name));
}
blo_join_main(&fd->mainlist);
G.main= fd->mainlist.first;
lib_link_all(fd, G.main);
/* give a base to loose objects */
give_base_to_objects(G.scene, &(G.main->object));
/* has been removed... erm, why? (ton) */
/* 20040907: looks like they are give base already in append_named_part(); -Nathan L */
/* 20041208: put back. It only linked direct, not indirect objects (ton) */
/* patch to prevent switch_endian happens twice */
if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
blo_freefiledata((FileData*) sfile->libfiledata);
sfile->libfiledata= 0;
}
if(sfile->flag & FILE_ATCURSOR) {
centerbase= (G.scene->base.first);
while(centerbase) {
if(((centerbase)->flag & SELECT)) {
VECCOPY(vec, centerbase->object->loc);
DO_MINMAX(vec, min, max);
count++;
}
centerbase= centerbase->next;
}
if(count) {
centerloc[0]= (min[0]+max[0])/2;
centerloc[1]= (min[1]+max[1])/2;
centerloc[2]= (min[2]+max[2])/2;
curs = G.scene->cursor;
VECSUB(centerloc,curs,centerloc);
centerbase= (G.scene->base.first);
while(centerbase) {
if( ((centerbase)->flag & SELECT)) {
ob= centerbase->object;
ob->loc[0] += centerloc[0];
ob->loc[1] += centerloc[1];
ob->loc[2] += centerloc[2];
}
centerbase= centerbase->next;
}
}
}
/* restore the 'last loaded filename' */
BLI_strncpy(G.sce, filename, sizeof(filename));
DAG_scene_sort(G.scene);
}
/* ************* READ LIBRARY ************** */
static int mainvar_count_libread_blocks(Main *mainvar)
{
ListBase *lbarray[30];
int a, tot= 0;
a= set_listbasepointers(mainvar, lbarray);
while(a--) {
ID *id= lbarray[a]->first;
for (id= lbarray[a]->first; id; id= id->next)
if (id->flag & LIB_READ)
tot++;
}
return tot;
}
static void read_libraries(FileData *basefd, ListBase *mainlist)
{
Main *mainl= mainlist->first;
Main *mainptr;
ListBase *lbarray[30];
int a, doit= 1;
while(doit) {
doit= 0;
/* test 1: read libdata */
mainptr= mainl->next;
while(mainptr) {
int tot= mainvar_count_libread_blocks(mainptr);
//printf("found LIB_READ %s\n", mainptr->curlib->name);
if(tot) {
FileData *fd= mainptr->curlib->filedata;
if(fd==NULL) {
BlendReadError err;
printf("read lib %s\n", mainptr->curlib->name);
fd= blo_openblenderfile(mainptr->curlib->name, &err);
if (fd) {
if (fd->libmap)
oldnewmap_free(fd->libmap);
fd->libmap= basefd->libmap;
fd->flags|= FD_FLAGS_NOT_MY_LIBMAP;
mainptr->curlib->filedata= fd;
mainptr->versionfile= fd->fileversion;
}
else mainptr->curlib->filedata= NULL;
if (fd==NULL)
printf("ERROR: can't find lib %s \n", mainptr->curlib->name);
}
if(fd) {
doit= 1;
a= set_listbasepointers(mainptr, lbarray);
while(a--) {
ID *id= lbarray[a]->first;
while(id) {
ID *idn= id->next;
if(id->flag & LIB_READ) {
ID *realid= NULL;
BLI_remlink(lbarray[a], id);
append_id_part(fd, mainptr, id, &realid);
if (!realid)
printf("LIB ERROR: can't find %s\n", id->name);
change_libadr(fd, id, realid);
MEM_freeN(id);
}
id= idn;
}
}
expand_main(fd, mainptr);
/* dang FileData... now new libraries need to be appended to original filedata, it is not a good replacement for the old global (ton) */
while( fd->mainlist.first ) {
Main *mp= fd->mainlist.first;
BLI_remlink(&fd->mainlist, mp);
BLI_addtail(&basefd->mainlist, mp);
}
}
}
mainptr= mainptr->next;
}
}
mainptr= mainl->next;
while(mainptr) {
/* test if there are unread libblocks */
a= set_listbasepointers(mainptr, lbarray);
while(a--) {
ID *id= lbarray[a]->first;
while(id) {
ID *idn= id->next;
if(id->flag & LIB_READ) {
BLI_remlink(lbarray[a], id);
printf("LIB ERROR: can't find %s\n", id->name);
change_libadr(basefd, id, 0);
MEM_freeN(id);
}
id= idn;
}
}
/* some mains still have to be read, then
* versionfile is still zero! */
if(mainptr->versionfile) {
if(mainptr->curlib->filedata) // can be zero... with shift+f1 append
do_versions(mainptr->curlib->filedata, mainptr->curlib, mainptr);
else
do_versions(basefd, NULL, mainptr);
}
if(mainptr->curlib->filedata) blo_freefiledata(mainptr->curlib->filedata);
mainptr->curlib->filedata= NULL;
mainptr= mainptr->next;
}
}
/* reading runtime */
BlendFileData *blo_read_blendafterruntime(int file, int actualsize, BlendReadError *error_r)
{
BlendFileData *bfd = NULL;
FileData *fd = filedata_new();
fd->filedes = file;
fd->buffersize = actualsize;
fd->read = fd_read_from_file;
fd = blo_decode_and_check(fd, error_r);
if (!fd)
return NULL;
bfd= blo_read_file_internal(fd, error_r);
blo_freefiledata(fd);
return bfd;
}