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
2012-04-30 08:24:44 +00:00

14916 lines
396 KiB
C

/*
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
*
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*
*/
/** \file blender/blenloader/intern/readfile.c
* \ingroup blenloader
*/
#include "zlib.h"
#include <limits.h>
#include <stdio.h> // for printf fopen fwrite fclose sprintf FILE
#include <stdlib.h> // for getenv atoi
#include <stddef.h> // for offsetof
#include <fcntl.h> // for open
#include <string.h> // for strrchr strncmp strstr
#include <math.h> // for fabs
#include <stdarg.h> /* for va_start/end */
#ifndef WIN32
# include <unistd.h> // for read close
#else
# include <io.h> // for open close read
# include "winsock2.h"
# include "BLI_winstuff.h"
#endif
/* allow readfile to use deprecated functionality */
#define DNA_DEPRECATED_ALLOW
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_actuator_types.h"
#include "DNA_brush_types.h"
#include "DNA_camera_types.h"
#include "DNA_cloth_types.h"
#include "DNA_controller_types.h"
#include "DNA_constraint_types.h"
#include "DNA_dynamicpaint_types.h"
#include "DNA_effect_types.h"
#include "DNA_fileglobal_types.h"
#include "DNA_genfile.h"
#include "DNA_group_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_ipo_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_nla_types.h"
#include "DNA_node_types.h"
#include "DNA_object_fluidsim.h" // NT
#include "DNA_object_types.h"
#include "DNA_packedFile_types.h"
#include "DNA_particle_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_smoke_types.h"
#include "DNA_speaker_types.h"
#include "DNA_sound_types.h"
#include "DNA_space_types.h"
#include "DNA_vfont_types.h"
#include "DNA_world_types.h"
#include "DNA_movieclip_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
#include "BKE_anim.h"
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_brush.h"
#include "BKE_colortools.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_deform.h"
#include "BKE_effect.h"
#include "BKE_fcurve.h"
#include "BKE_global.h" // for G
#include "BKE_group.h"
#include "BKE_image.h"
#include "BKE_lattice.h"
#include "BKE_library.h" // for which_libbase
#include "BKE_idcode.h"
#include "BKE_material.h"
#include "BKE_main.h" // for Main
#include "BKE_mesh.h" // for ME_ defines (patching)
#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_node.h" // for tree type defines
#include "BKE_ocean.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_property.h" // for get_ob_property
#include "BKE_report.h"
#include "BKE_sca.h" // for init_actuator
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_sequencer.h"
#include "BKE_text.h" // for txt_extended_ascii_as_utf8
#include "BKE_texture.h" // for open_plugin_tex
#include "BKE_tracking.h"
#include "BKE_utildefines.h" // SWITCH_INT DATA ENDB DNA1 O_BINARY GLOB USER TEST REND
#include "BKE_sound.h"
#include "IMB_imbuf.h" // for proxy / timecode versioning stuff
#include "NOD_socket.h"
//XXX #include "BIF_butspace.h" // badlevel, for do_versions, patching event codes
//XXX #include "BIF_filelist.h" // badlevel too, where to move this? - elubie
//XXX #include "BIF_previewrender.h" // bedlelvel, for struct RenderInfo
#include "BLO_readfile.h"
#include "BLO_undofile.h"
#include "RE_engine.h"
#include "readfile.h"
#include "PIL_time.h"
#include <errno.h>
/*
Remark: still a weak point is the newaddress() 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 ~/X.XX/startup.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; }
/***/
typedef struct OldNew {
void *old, *newp;
int nr;
} OldNew;
typedef struct OldNewMap {
OldNew *entries;
int nentries, entriessize;
int sorted;
int lasthit;
} OldNewMap;
/* local prototypes */
static void *read_struct(FileData *fd, BHead *bh, const char *blockname);
static void direct_link_modifiers(FileData *fd, ListBase *lb);
static void convert_tface_mt(FileData *fd, Main *main);
/* this function ensures that reports are printed,
* in the case of libraray linking errors this is important!
*
* bit kludge but better then doubling up on prints,
* we could alternatively have a versions of a report function which foces printing - campbell
*/
static void BKE_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...)
{
char fixed_buf[1024]; /* should be long enough */
va_list args;
va_start(args, format);
vsnprintf(fixed_buf, sizeof(fixed_buf), format, args);
va_end(args);
fixed_buf[sizeof(fixed_buf) - 1] = '\0';
BKE_report(reports, type, fixed_buf);
if (G.background==0) {
printf("%s\n", fixed_buf);
}
}
static OldNewMap *oldnewmap_new(void)
{
OldNewMap *onm= MEM_callocN(sizeof(*onm), "OldNewMap");
onm->entriessize= 1024;
onm->entries= MEM_mallocN(sizeof(*onm->entries)*onm->entriessize, "OldNewMap.entries");
return onm;
}
static int verg_oldnewmap(const void *v1, const void *v2)
{
const struct OldNew *x1=v1, *x2=v2;
if ( x1->old > x2->old) return 1;
else if ( x1->old < x2->old) return -1;
return 0;
}
static void oldnewmap_sort(FileData *fd)
{
qsort(fd->libmap->entries, fd->libmap->nentries, sizeof(OldNew), verg_oldnewmap);
fd->libmap->sorted= 1;
}
/* nr is zero for data, and ID code for libdata */
static void oldnewmap_insert(OldNewMap *onm, void *oldaddr, void *newaddr, int nr)
{
OldNew *entry;
if (oldaddr==NULL || newaddr==NULL) return;
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 (addr==NULL) return NULL;
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;
}
/* for libdata, nr has ID code, no increment */
static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib)
{
int i;
if (addr==NULL) return NULL;
/* lasthit works fine for non-libdata, linking there is done in same sequence as writing */
if (onm->sorted) {
OldNew entry_s, *entry;
entry_s.old= addr;
entry= bsearch(&entry_s, onm->entries, onm->nentries, sizeof(OldNew), verg_oldnewmap);
if (entry) {
ID *id= entry->newp;
if (id && (!lib || id->lib)) {
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 && (!lib || id->lib)) {
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[MAX_LIBARRAY], *fromarray[MAX_LIBARRAY];
int a;
set_listbasepointers(mainvar, lbarray);
a= set_listbasepointers(from, fromarray);
while (a--) {
BLI_movelisttolist(lbarray[a], fromarray[a]);
}
}
void blo_join_main(ListBase *mainlist)
{
Main *tojoin, *mainl;
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= which_libbase(mainvar, GS(id->name));
BLI_remlink(lb, id);
BLI_addtail(lbn, id);
break;
}
mainvar= mainvar->next;
}
if (mainvar==NULL) printf("error split_libdata\n");
}
id= idnext;
}
}
void blo_split_main(ListBase *mainlist, Main *main)
{
ListBase *lbarray[MAX_LIBARRAY];
Library *lib;
int i;
mainlist->first= mainlist->last= main;
main->next= NULL;
if (main->library.first==NULL)
return;
for (lib= main->library.first; lib; lib= lib->id.next) {
Main *libmain= MEM_callocN(sizeof(Main), "libmain");
libmain->curlib= lib;
BLI_addtail(mainlist, libmain);
}
i= set_listbasepointers(main, lbarray);
while (i--)
split_libdata(lbarray[i], main->next);
}
/* removes things like /blah/blah/../../blah/ etc, then writes in *name the full path */
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 void read_file_version(FileData *fd, Main *main)
{
BHead *bhead;
for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
if (bhead->code==GLOB) {
FileGlobal *fg= read_struct(fd, bhead, "Global");
if (fg) {
main->subversionfile= fg->subversion;
main->minversionfile= fg->minversion;
main->minsubversionfile= fg->minsubversion;
MEM_freeN(fg);
}
else if (bhead->code==ENDB)
break;
}
}
}
static Main *blo_find_main(FileData *fd, ListBase *mainlist, const char *filepath, const char *relabase)
{
Main *m;
Library *lib;
char name1[FILE_MAX];
BLI_strncpy(name1, filepath, sizeof(name1));
cleanup_path(relabase, name1);
// printf("blo_find_main: original in %s\n", name);
// printf("blo_find_main: converted to %s\n", name1);
for (m= mainlist->first; m; m= m->next) {
char *libname= (m->curlib)?m->curlib->filepath:m->name;
if (BLI_path_cmp(name1, libname) == 0) {
if (G.debug & G_DEBUG) printf("blo_find_main: 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");
BLI_strncpy(lib->name, filepath, sizeof(lib->name));
BLI_strncpy(lib->filepath, name1, sizeof(lib->filepath));
m->curlib= lib;
read_file_version(fd, m);
if (G.debug & G_DEBUG) printf("blo_find_main: added new lib %s\n", filepath);
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) {
//perform a endian swap on 64bit pointers, otherwise the pointer might map to zero
//0x0000000000000000000012345678 would become 0x12345678000000000000000000000000
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 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)
{
BHeadN *new_bhead = NULL;
int readsize;
if (fd) {
if ( ! fd->eof) {
/* initializing to zero isn't strictly needed but shuts valgrind up
* since uninitialized memory gets compared */
BHead8 bhead8= {0};
BHead4 bhead4= {0};
BHead bhead= {0};
// 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;
bhead.len= 0;
}
}
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.len= 0;
}
}
/* make sure people are not trying to pass bad blend files */
if (bhead.len < 0) 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 = NULL;
new_bhead->bhead = bhead;
readsize = fd->read(fd, new_bhead + 1, bhead.len);
if (readsize != bhead.len) {
fd->eof = 1;
MEM_freeN(new_bhead);
new_bhead = NULL;
}
}
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 = NULL;
// Rewind the file
// Read in a new block if necessary
new_bhead = fd->listbase.first;
if (new_bhead == NULL) {
new_bhead = get_bhead(fd);
}
if (new_bhead) {
bhead = &new_bhead->bhead;
}
return(bhead);
}
BHead *blo_prevbhead(FileData *UNUSED(fd), BHead *thisblock)
{
BHeadN *bheadn= (BHeadN *) (((char *) thisblock) - GET_INT_FROM_POINTER( &((BHeadN*)0)->bhead) );
BHeadN *prev= bheadn->prev;
return prev?&prev->bhead:NULL;
}
BHead *blo_nextbhead(FileData *fd, BHead *thisblock)
{
BHeadN *new_bhead = NULL;
BHead *bhead = NULL;
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) - GET_INT_FROM_POINTER( &((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 == NULL) {
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_struct_get_compareflags(fd->filesdna, fd->memsdna);
/* used to retrieve ID names from (bhead+1) */
fd->id_name_offs= DNA_elem_offset(fd->filesdna, "ID", "char", "name[]");
}
return 1;
}
else if (bhead->code==ENDB)
break;
}
return 0;
}
static int fd_read_from_file(FileData *filedata, void *buffer, unsigned 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, unsigned 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, unsigned int size)
{
// don't read more bytes then there are available in the buffer
int readsize = (int)MIN2(size, (unsigned int)(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, unsigned int size)
{
static unsigned int seek= 1<<30; /* the current position */
static unsigned int offset= 0; /* size of previous chunks */
static MemFileChunk *chunk=NULL;
unsigned int chunkoffset, readsize, totread;
if (size==0) return 0;
if (seek != (unsigned int)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) {
totread= 0;
do {
/* 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;
}
chunkoffset= seek-offset;
readsize= size-totread;
/* data can be spread over multiple chunks, so clamp size
* to within this chunk, and then it will read further in
* the next chunk */
if (chunkoffset+readsize > chunk->size)
readsize= chunk->size-chunkoffset;
memcpy((char*)buffer+totread, chunk->buf+chunkoffset, readsize);
totread += readsize;
filedata->seek += readsize;
seek += readsize;
} while (totread < size);
return totread;
}
return 0;
}
static FileData *filedata_new(void)
{
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 re-entrant, 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, ReportList *reports)
{
decode_blender_header(fd);
if (fd->flags & FD_FLAGS_FILE_OK) {
if (!read_file_dna(fd)) {
BKE_reportf(reports, RPT_ERROR, "Failed to read blend file: \"%s\", incomplete", fd->relabase);
blo_freefiledata(fd);
fd= NULL;
}
}
else {
BKE_reportf(reports, RPT_ERROR, "Failed to read blend file: \"%s\", not a blend file", fd->relabase);
blo_freefiledata(fd);
fd= NULL;
}
return fd;
}
/* cannot be called with relative paths anymore! */
/* on each new library added, it now checks for the current FileData and expands relativeness */
FileData *blo_openblenderfile(const char *filepath, ReportList *reports)
{
gzFile gzfile;
errno= 0;
gzfile= BLI_gzopen(filepath, "rb");
if (gzfile == (gzFile)Z_NULL) {
BKE_reportf(reports, RPT_ERROR, "Unable to open \"%s\": %s.", filepath, errno ? strerror(errno) : "Unknown error reading file");
return NULL;
}
else {
FileData *fd = filedata_new();
fd->gzfiledes = gzfile;
fd->read = fd_read_gzip_from_file;
/* needed for library_append and read_libraries */
BLI_strncpy(fd->relabase, filepath, sizeof(fd->relabase));
return blo_decode_and_check(fd, reports);
}
}
FileData *blo_openblendermemory(void *mem, int memsize, ReportList *reports)
{
if (!mem || memsize<SIZEOFBLENDERHEADER) {
BKE_report(reports, RPT_ERROR, (mem)? "Unable to read": "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, reports);
}
}
FileData *blo_openblendermemfile(MemFile *memfile, ReportList *reports)
{
if (!memfile) {
BKE_report(reports, RPT_ERROR, "Unable to open blend <memory>");
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, reports);
}
}
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 = NULL;
}
// Free all BHeadN data blocks
BLI_freelistN(&fd->listbase);
if (fd->memsdna)
DNA_sdna_free(fd->memsdna);
if (fd->filesdna)
DNA_sdna_free(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->imamap)
oldnewmap_free(fd->imamap);
if (fd->movieclipmap)
oldnewmap_free(fd->movieclipmap);
if (fd->libmap && !(fd->flags & FD_FLAGS_NOT_MY_LIBMAP))
oldnewmap_free(fd->libmap);
if (fd->bheadmap)
MEM_freeN(fd->bheadmap);
MEM_freeN(fd);
}
}
/* ************ DIV ****************** */
int BLO_has_bfile_extension(const char *str)
{
return (BLI_testextensie(str, ".ble") || BLI_testextensie(str, ".blend") || BLI_testextensie(str, ".blend.gz"));
}
int BLO_is_a_library(const char *path, char *dir, char *group)
{
/* return ok when a blenderfile, in dir is the filename,
* in group the type of libdata
*/
int len;
char *fd;
strcpy(dir, path);
len= strlen(dir);
if (len<7) return 0;
if ( dir[len-1] != '/' && dir[len-1] != '\\') return 0;
group[0]= 0;
dir[len-1]= 0;
/* Find the last slash */
fd= BLI_last_slash(dir);
if (fd==NULL) return 0;
*fd= 0;
if (BLO_has_bfile_extension(fd+1)) {
/* the last part of the dir is a .blend file, no group follows */
*fd= '/'; /* put back the removed slash separating the dir and the .blend file name */
}
else {
char *gp = fd+1; // in case we have a .blend file, gp points to the group
/* Find the last slash */
fd= BLI_last_slash(dir);
if (!fd || !BLO_has_bfile_extension(fd+1)) return 0;
/* now we know that we are in a blend file and it is safe to
* assume that gp actually points to a group */
if (strcmp("Screen", gp)!=0)
BLI_strncpy(group, gp, GROUP_MAX);
}
return 1;
}
/* ************** 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 *newimaadr(FileData *fd, void *adr) /* used to restore image data after undo */
{
if (fd->imamap && adr)
return oldnewmap_lookup_and_inc(fd->imamap, adr);
return NULL;
}
static void *newmclipadr(FileData *fd, void *adr) /* used to restore movie clip data after undo */
{
if (fd->movieclipmap && adr)
return oldnewmap_lookup_and_inc(fd->movieclipmap, adr);
return NULL;
}
static void *newlibadr(FileData *fd, void *lib, void *adr) /* only lib data */
{
return oldnewmap_liblookup(fd->libmap, adr, lib);
}
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_idid_adr_fd(FileData *fd, void *old, void *new)
{
int i;
for (i=0; i<fd->libmap->nentries; i++) {
OldNew *entry= &fd->libmap->entries[i];
if (old==entry->newp && entry->nr==ID_ID) {
entry->newp= new;
if (new) entry->nr= GS( ((ID *)new)->name );
break;
}
}
}
static void change_idid_adr(ListBase *mainlist, FileData *basefd, void *old, void *new)
{
Main *mainptr;
for (mainptr= mainlist->first; mainptr; mainptr= mainptr->next) {
FileData *fd;
if (mainptr->curlib) fd= mainptr->curlib->filedata;
else fd= basefd;
if (fd) {
change_idid_adr_fd(fd, old, new);
}
}
}
/* lib linked proxy objects point to our local data, we need
* to clear that pointer before reading the undo memfile since
* the object might be removed, it is set again in reading
* if the local object still exists */
void blo_clear_proxy_pointers_from_lib(Main *oldmain)
{
Object *ob= oldmain->object.first;
for (;ob; ob= ob->id.next)
if (ob->id.lib)
ob->proxy_from= NULL;
}
void blo_make_image_pointer_map(FileData *fd, Main *oldmain)
{
Image *ima= oldmain->image.first;
Scene *sce= oldmain->scene.first;
int a;
fd->imamap= oldnewmap_new();
for (;ima; ima= ima->id.next) {
Link *ibuf= ima->ibufs.first;
for (; ibuf; ibuf= ibuf->next)
oldnewmap_insert(fd->imamap, ibuf, ibuf, 0);
if (ima->gputexture)
oldnewmap_insert(fd->imamap, ima->gputexture, ima->gputexture, 0);
for (a=0; a<IMA_MAX_RENDER_SLOT; a++)
if (ima->renders[a])
oldnewmap_insert(fd->imamap, ima->renders[a], ima->renders[a], 0);
}
for (; sce; sce= sce->id.next) {
if (sce->nodetree) {
bNode *node;
for (node= sce->nodetree->nodes.first; node; node= node->next)
oldnewmap_insert(fd->imamap, node->preview, node->preview, 0);
}
}
}
/* set old main image ibufs to zero if it has been restored */
/* this works because freeing old main only happens after this call */
void blo_end_image_pointer_map(FileData *fd, Main *oldmain)
{
OldNew *entry= fd->imamap->entries;
Image *ima= oldmain->image.first;
Scene *sce= oldmain->scene.first;
int i;
/* used entries were restored, so we put them to zero */
for (i=0; i<fd->imamap->nentries; i++, entry++) {
if (entry->nr>0)
entry->newp= NULL;
}
for (;ima; ima= ima->id.next) {
Link *ibuf, *next;
/* this mirrors direct_link_image */
for (ibuf= ima->ibufs.first; ibuf; ibuf= next) {
next= ibuf->next;
if (NULL==newimaadr(fd, ibuf)) { /* so was restored */
BLI_remlink(&ima->ibufs, ibuf);
ima->bindcode= 0;
ima->gputexture= NULL;
}
}
for (i=0; i<IMA_MAX_RENDER_SLOT; i++)
ima->renders[i]= newimaadr(fd, ima->renders[i]);
ima->gputexture= newimaadr(fd, ima->gputexture);
}
for (; sce; sce= sce->id.next) {
if (sce->nodetree) {
bNode *node;
for (node= sce->nodetree->nodes.first; node; node= node->next)
node->preview= newimaadr(fd, node->preview);
}
}
}
void blo_make_movieclip_pointer_map(FileData *fd, Main *oldmain)
{
MovieClip *clip= oldmain->movieclip.first;
Scene *sce= oldmain->scene.first;
fd->movieclipmap= oldnewmap_new();
for (;clip; clip= clip->id.next) {
if (clip->cache)
oldnewmap_insert(fd->movieclipmap, clip->cache, clip->cache, 0);
if (clip->tracking.camera.intrinsics)
oldnewmap_insert(fd->movieclipmap, clip->tracking.camera.intrinsics, clip->tracking.camera.intrinsics, 0);
}
for (; sce; sce= sce->id.next) {
if (sce->nodetree) {
bNode *node;
for (node= sce->nodetree->nodes.first; node; node= node->next)
if (node->type==CMP_NODE_MOVIEDISTORTION)
oldnewmap_insert(fd->movieclipmap, node->storage, node->storage, 0);
}
}
}
/* set old main movie clips caches to zero if it has been restored */
/* this works because freeing old main only happens after this call */
void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain)
{
OldNew *entry= fd->movieclipmap->entries;
MovieClip *clip= oldmain->movieclip.first;
Scene *sce= oldmain->scene.first;
int i;
/* used entries were restored, so we put them to zero */
for (i=0; i<fd->movieclipmap->nentries; i++, entry++) {
if (entry->nr>0)
entry->newp= NULL;
}
for (;clip; clip= clip->id.next) {
clip->cache= newmclipadr(fd, clip->cache);
clip->tracking.camera.intrinsics= newmclipadr(fd, clip->tracking.camera.intrinsics);
}
for (; sce; sce= sce->id.next) {
if (sce->nodetree) {
bNode *node;
for (node= sce->nodetree->nodes.first; node; node= node->next)
if (node->type==CMP_NODE_MOVIEDISTORTION)
node->storage= newmclipadr(fd, node->storage);
}
}
}
/* undo file support: add all library pointers in lookup */
void blo_add_library_pointer_map(ListBase *mainlist, FileData *fd)
{
Main *ptr= mainlist->first;
ListBase *lbarray[MAX_LIBARRAY];
for (ptr= ptr->next; ptr; ptr= ptr->next) {
int i= set_listbasepointers(ptr, lbarray);
while (i--) {
ID *id;
for (id= lbarray[i]->first; id; id= id->next)
oldnewmap_insert(fd->libmap, id, id, GS(id->name));
}
}
}
/* ********** END OLD POINTERS ****************** */
/* ********** READ FILE ****************** */
static void switch_endian_structs(struct SDNA *filesdna, BHead *bhead)
{
int blocksize, nblocks;
char *data;
data= (char *)(bhead+1);
blocksize= filesdna->typelens[ filesdna->structs[bhead->SDNAnr][0] ];
nblocks= bhead->nr;
while (nblocks--) {
DNA_struct_switch_endian(filesdna, bhead->SDNAnr, data);
data+= blocksize;
}
}
static void *read_struct(FileData *fd, BHead *bh, const char *blockname)
{
void *temp= NULL;
if (bh->len) {
/* switch is based on file dna */
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_struct_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);
}
}
}
return temp;
}
static void link_list(FileData *fd, ListBase *lb) /* only direct data */
{
Link *ln, *prev;
if (lb->first==NULL) return;
lb->first= newdataadr(fd, lb->first);
ln= lb->first;
prev= NULL;
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==NULL) return;
poin= newdataadr(fd, lb->first);
if (lb->first) {
oldnewmap_insert(fd->globmap, lb->first, poin, 0);
}
lb->first= poin;
ln= lb->first;
prev= NULL;
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 *ipoin, *imat;
size_t len;
/* 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 ID Properties *************** */
static void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, FileData *fd);
static void IDP_LibLinkProperty(IDProperty *prop, int switch_endian, FileData *fd);
static void IDP_DirectLinkIDPArray(IDProperty *prop, int switch_endian, FileData *fd)
{
IDProperty *array;
int i;
/*since we didn't save the extra buffer, set totallen to len.*/
prop->totallen = prop->len;
prop->data.pointer = newdataadr(fd, prop->data.pointer);
array= (IDProperty*) prop->data.pointer;
/* note!, idp-arrays didn't exist in 2.4x, so the pointer will be cleared
* theres not really anything we can do to correct this, at least don't crash */
if (array==NULL) {
prop->len= 0;
prop->totallen= 0;
}
for (i=0; i<prop->len; i++)
IDP_DirectLinkProperty(&array[i], switch_endian, fd);
}
static void IDP_DirectLinkArray(IDProperty *prop, int switch_endian, FileData *fd)
{
IDProperty **array;
int i;
/*since we didn't save the extra buffer, set totallen to len.*/
prop->totallen = prop->len;
prop->data.pointer = newdataadr(fd, prop->data.pointer);
if (prop->subtype == IDP_GROUP) {
test_pointer_array(fd, prop->data.pointer);
array= prop->data.pointer;
for (i=0; i<prop->len; i++)
IDP_DirectLinkProperty(array[i], switch_endian, fd);
}
else if (prop->subtype == IDP_DOUBLE) {
if (switch_endian) {
for (i=0; i<prop->len; i++) {
SWITCH_LONGINT(((double*)prop->data.pointer)[i]);
}
}
}
else {
if (switch_endian) {
for (i=0; i<prop->len; i++) {
SWITCH_INT(((int*)prop->data.pointer)[i]);
}
}
}
}
static void IDP_DirectLinkString(IDProperty *prop, FileData *fd)
{
/*since we didn't save the extra string buffer, set totallen to len.*/
prop->totallen = prop->len;
prop->data.pointer = newdataadr(fd, prop->data.pointer);
}
static void IDP_DirectLinkGroup(IDProperty *prop, int switch_endian, FileData *fd)
{
ListBase *lb = &prop->data.group;
IDProperty *loop;
link_list(fd, lb);
/*Link child id properties now*/
for (loop=prop->data.group.first; loop; loop=loop->next) {
IDP_DirectLinkProperty(loop, switch_endian, fd);
}
}
static void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, FileData *fd)
{
switch (prop->type) {
case IDP_GROUP:
IDP_DirectLinkGroup(prop, switch_endian, fd);
break;
case IDP_STRING:
IDP_DirectLinkString(prop, fd);
break;
case IDP_ARRAY:
IDP_DirectLinkArray(prop, switch_endian, fd);
break;
case IDP_IDPARRAY:
IDP_DirectLinkIDPArray(prop, switch_endian, fd);
break;
case IDP_DOUBLE:
/* erg, stupid doubles. since I'm storing them
* in the same field as int val; val2 in the
* IDPropertyData struct, they have to deal with
* endianness specifically
*
* in theory, val and val2 would've already been swapped
* if switch_endian is true, so we have to first unswap
* them then reswap them as a single 64-bit entity.
*/
if (switch_endian) {
SWITCH_INT(prop->data.val);
SWITCH_INT(prop->data.val2);
SWITCH_LONGINT(prop->data.val);
}
break;
}
}
/*stub function*/
static void IDP_LibLinkProperty(IDProperty *UNUSED(prop), int UNUSED(switch_endian), FileData *UNUSED(fd))
{
}
/* ************ READ CurveMapping *************** */
/* cuma itself has been read! */
static void direct_link_curvemapping(FileData *fd, CurveMapping *cumap)
{
int a;
/* flag seems to be able to hang? Maybe old files... not bad to clear anyway */
cumap->flag &= ~CUMA_PREMULLED;
for (a=0; a<CM_TOT; a++) {
cumap->cm[a].curve= newdataadr(fd, cumap->cm[a].curve);
cumap->cm[a].table= NULL;
cumap->cm[a].premultable= NULL;
}
}
/* ************ READ Brush *************** */
/* library brush linking after fileread */
static void lib_link_brush(FileData *fd, Main *main)
{
Brush *brush;
/* only link ID pointers */
for (brush= main->brush.first; brush; brush= brush->id.next) {
if (brush->id.flag & LIB_NEEDLINK) {
brush->id.flag -= LIB_NEEDLINK;
brush->mtex.tex= newlibadr_us(fd, brush->id.lib, brush->mtex.tex);
brush->clone.image= newlibadr_us(fd, brush->id.lib, brush->clone.image);
}
}
}
static void direct_link_brush(FileData *fd, Brush *brush)
{
/* brush itself has been read */
/* fallof curve */
brush->curve= newdataadr(fd, brush->curve);
if (brush->curve)
direct_link_curvemapping(fd, brush->curve);
else
brush_curve_preset(brush, CURVE_PRESET_SHARP);
brush->preview= NULL;
brush->icon_imbuf= NULL;
}
static void direct_link_script(FileData *UNUSED(fd), Script *script)
{
script->id.us = 1;
SCRIPT_SET_NULL(script);
}
/* ************ 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 IMAGE PREVIEW *************** */
static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_prv)
{
PreviewImage *prv= newdataadr(fd, old_prv);
if (prv) {
int i;
for (i=0; i < NUM_ICON_SIZES; ++i) {
if (prv->rect[i]) {
prv->rect[i] = newdataadr(fd, prv->rect[i]);
}
}
}
return prv;
}
/* ************ READ ANIMATION STUFF ***************** */
/* Legacy Data Support (for Version Patching) ----------------------------- */
// XXX depreceated - old animation system
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;
}
}
// XXX depreceated - old animation system
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;
}
}
// XXX depreceated - old animation system
static void lib_link_nlastrips(FileData *fd, ID *id, ListBase *striplist)
{
bActionStrip *strip;
bActionModifier *amod;
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);
for (amod= strip->modifiers.first; amod; amod= amod->next)
amod->ob= newlibadr(fd, id->lib, amod->ob);
}
}
// XXX depreceated - old animation system
static void direct_link_nlastrips(FileData *fd, ListBase *strips)
{
bActionStrip *strip;
link_list(fd, strips);
for (strip= strips->first; strip; strip= strip->next)
link_list(fd, &strip->modifiers);
}
// XXX depreceated - old animation system
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);
}
}
/* Data Linking ----------------------------- */
static void lib_link_fmodifiers(FileData *fd, ID *id, ListBase *list)
{
FModifier *fcm;
for (fcm= list->first; fcm; fcm= fcm->next) {
/* data for specific modifiers */
switch (fcm->type) {
case FMODIFIER_TYPE_PYTHON:
{
FMod_Python *data= (FMod_Python *)fcm->data;
data->script = newlibadr(fd, id->lib, data->script);
}
break;
}
}
}
static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list)
{
FCurve *fcu;
if (list == NULL)
return;
/* relink ID-block references... */
for (fcu= list->first; fcu; fcu= fcu->next) {
/* driver data */
if (fcu->driver) {
ChannelDriver *driver= fcu->driver;
DriverVar *dvar;
for (dvar= driver->variables.first; dvar; dvar= dvar->next) {
DRIVER_TARGETS_LOOPER(dvar)
{
/* only relink if still used */
if (tarIndex < dvar->num_targets)
dtar->id= newlibadr(fd, id->lib, dtar->id);
else
dtar->id= NULL;
}
DRIVER_TARGETS_LOOPER_END
}
}
/* modifiers */
lib_link_fmodifiers(fd, id, &fcu->modifiers);
}
}
/* NOTE: this assumes that link_list has already been called on the list */
static void direct_link_fmodifiers(FileData *fd, ListBase *list)
{
FModifier *fcm;
for (fcm= list->first; fcm; fcm= fcm->next) {
/* relink general data */
fcm->data = newdataadr(fd, fcm->data);
fcm->edata= NULL;
/* do relinking of data for specific types */
switch (fcm->type) {
case FMODIFIER_TYPE_GENERATOR:
{
FMod_Generator *data= (FMod_Generator *)fcm->data;
data->coefficients= newdataadr(fd, data->coefficients);
if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
unsigned int a;
for (a = 0; a < data->arraysize; a++)
SWITCH_INT(data->coefficients[a]);
}
}
break;
case FMODIFIER_TYPE_ENVELOPE:
{
FMod_Envelope *data= (FMod_Envelope *)fcm->data;
data->data= newdataadr(fd, data->data);
}
break;
case FMODIFIER_TYPE_PYTHON:
{
FMod_Python *data= (FMod_Python *)fcm->data;
data->prop = newdataadr(fd, data->prop);
IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
break;
}
}
}
/* NOTE: this assumes that link_list has already been called on the list */
static void direct_link_fcurves(FileData *fd, ListBase *list)
{
FCurve *fcu;
/* link F-Curve data to F-Curve again (non ID-libs) */
for (fcu= list->first; fcu; fcu= fcu->next) {
/* curve data */
fcu->bezt= newdataadr(fd, fcu->bezt);
fcu->fpt= newdataadr(fd, fcu->fpt);
/* rna path */
fcu->rna_path= newdataadr(fd, fcu->rna_path);
/* group */
fcu->grp= newdataadr(fd, fcu->grp);
/* driver */
fcu->driver= newdataadr(fd, fcu->driver);
if (fcu->driver) {
ChannelDriver *driver= fcu->driver;
DriverVar *dvar;
driver->expr_comp= NULL;
/* relink variables, targets and their paths */
link_list(fd, &driver->variables);
for (dvar= driver->variables.first; dvar; dvar= dvar->next) {
DRIVER_TARGETS_LOOPER(dvar)
{
/* only relink the targets being used */
if (tarIndex < dvar->num_targets)
dtar->rna_path= newdataadr(fd, dtar->rna_path);
else
dtar->rna_path= NULL;
}
DRIVER_TARGETS_LOOPER_END
}
}
/* modifiers */
link_list(fd, &fcu->modifiers);
direct_link_fmodifiers(fd, &fcu->modifiers);
}
}
static void lib_link_action(FileData *fd, Main *main)
{
bAction *act;
bActionChannel *chan;
for (act= main->action.first; act; act= act->id.next) {
if (act->id.flag & LIB_NEEDLINK) {
act->id.flag -= LIB_NEEDLINK;
// XXX depreceated - old animation system <<<
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);
}
// >>> XXX depreceated - old animation system
lib_link_fcurves(fd, &act->id, &act->curves);
}
}
}
static void direct_link_action(FileData *fd, bAction *act)
{
bActionChannel *achan; // XXX depreceated - old animation system
bActionGroup *agrp;
link_list(fd, &act->curves);
link_list(fd, &act->chanbase); // XXX depreceated - old animation system
link_list(fd, &act->groups);
link_list(fd, &act->markers);
// XXX depreceated - old animation system <<<
for (achan = act->chanbase.first; achan; achan=achan->next) {
achan->grp= newdataadr(fd, achan->grp);
link_list(fd, &achan->constraintChannels);
}
// >>> XXX depreceated - old animation system
direct_link_fcurves(fd, &act->curves);
for (agrp = act->groups.first; agrp; agrp= agrp->next) {
agrp->channels.first= newdataadr(fd, agrp->channels.first);
agrp->channels.last= newdataadr(fd, agrp->channels.last);
}
}
static void lib_link_nladata_strips(FileData *fd, ID *id, ListBase *list)
{
NlaStrip *strip;
for (strip= list->first; strip; strip= strip->next) {
/* check strip's children */
lib_link_nladata_strips(fd, id, &strip->strips);
/* check strip's F-Curves */
lib_link_fcurves(fd, id, &strip->fcurves);
/* reassign the counted-reference to action */
strip->act = newlibadr_us(fd, id->lib, strip->act);
/* fix action id-root (i.e. if it comes from a pre 2.57 .blend file) */
if ((strip->act) && (strip->act->idroot == 0))
strip->act->idroot = GS(id->name);
}
}
static void lib_link_nladata(FileData *fd, ID *id, ListBase *list)
{
NlaTrack *nlt;
/* we only care about the NLA strips inside the tracks */
for (nlt= list->first; nlt; nlt= nlt->next) {
lib_link_nladata_strips(fd, id, &nlt->strips);
}
}
/* This handles Animato NLA-Strips linking
* NOTE: this assumes that link_list has already been called on the list
*/
static void direct_link_nladata_strips(FileData *fd, ListBase *list)
{
NlaStrip *strip;
for (strip= list->first; strip; strip= strip->next) {
/* strip's child strips */
link_list(fd, &strip->strips);
direct_link_nladata_strips(fd, &strip->strips);
/* strip's F-Curves */
link_list(fd, &strip->fcurves);
direct_link_fcurves(fd, &strip->fcurves);
/* strip's F-Modifiers */
link_list(fd, &strip->modifiers);
direct_link_fmodifiers(fd, &strip->modifiers);
}
}
/* NOTE: this assumes that link_list has already been called on the list */
static void direct_link_nladata(FileData *fd, ListBase *list)
{
NlaTrack *nlt;
for (nlt= list->first; nlt; nlt= nlt->next) {
/* relink list of strips */
link_list(fd, &nlt->strips);
/* relink strip data */
direct_link_nladata_strips(fd, &nlt->strips);
}
}
/* ------- */
static void lib_link_keyingsets(FileData *fd, ID *id, ListBase *list)
{
KeyingSet *ks;
KS_Path *ksp;
/* here, we're only interested in the ID pointer stored in some of the paths */
for (ks= list->first; ks; ks= ks->next) {
for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
ksp->id= newlibadr(fd, id->lib, ksp->id);
}
}
}
/* NOTE: this assumes that link_list has already been called on the list */
static void direct_link_keyingsets(FileData *fd, ListBase *list)
{
KeyingSet *ks;
KS_Path *ksp;
/* link KeyingSet data to KeyingSet again (non ID-libs) */
for (ks= list->first; ks; ks= ks->next) {
/* paths */
link_list(fd, &ks->paths);
for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
/* rna path */
ksp->rna_path= newdataadr(fd, ksp->rna_path);
}
}
}
/* ------- */
static void lib_link_animdata(FileData *fd, ID *id, AnimData *adt)
{
if (adt == NULL)
return;
/* link action data */
adt->action= newlibadr_us(fd, id->lib, adt->action);
adt->tmpact= newlibadr_us(fd, id->lib, adt->tmpact);
/* fix action id-roots (i.e. if they come from a pre 2.57 .blend file) */
if ((adt->action) && (adt->action->idroot == 0))
adt->action->idroot = GS(id->name);
if ((adt->tmpact) && (adt->tmpact->idroot == 0))
adt->tmpact->idroot = GS(id->name);
/* link drivers */
lib_link_fcurves(fd, id, &adt->drivers);
/* overrides don't have lib-link for now, so no need to do anything */
/* link NLA-data */
lib_link_nladata(fd, id, &adt->nla_tracks);
}
static void direct_link_animdata(FileData *fd, AnimData *adt)
{
/* NOTE: must have called newdataadr already before doing this... */
if (adt == NULL)
return;
/* link drivers */
link_list(fd, &adt->drivers);
direct_link_fcurves(fd, &adt->drivers);
/* link overrides */
// TODO...
/* link NLA-data */
link_list(fd, &adt->nla_tracks);
direct_link_nladata(fd, &adt->nla_tracks);
/* relink active strip - even though strictly speaking this should only be used
* if we're in 'tweaking mode', we need to be able to have this loaded back for
* undo, but also since users may not exit tweakmode before saving (#24535)
*/
// TODO: it's not really nice that anyone should be able to save the file in this
// state, but it's going to be too hard to enforce this single case...
adt->actstrip= newdataadr(fd, adt->actstrip);
}
/* ************ READ MOTION PATHS *************** */
/* direct data for cache */
static void direct_link_motionpath(FileData *fd, bMotionPath *mpath)
{
/* sanity check */
if (mpath == NULL)
return;
/* relink points cache */
mpath->points= newdataadr(fd, mpath->points);
}
/* ************ READ NODE TREE *************** */
/* singe node tree (also used for material/scene trees), ntree is not NULL */
static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree)
{
bNode *node;
if (ntree->adt) lib_link_animdata(fd, &ntree->id, ntree->adt);
ntree->gpd= newlibadr_us(fd, id->lib, ntree->gpd);
for (node= ntree->nodes.first; node; node= node->next)
node->id= newlibadr_us(fd, id->lib, node->id);
}
/* library ntree linking after fileread */
static void lib_link_nodetree(FileData *fd, Main *main)
{
bNodeTree *ntree;
/* only link ID pointers */
for (ntree= main->nodetree.first; ntree; ntree= ntree->id.next) {
if (ntree->id.flag & LIB_NEEDLINK) {
ntree->id.flag -= LIB_NEEDLINK;
lib_link_ntree(fd, &ntree->id, ntree);
}
}
}
static void do_versions_socket_default_value(bNodeSocket *sock)
{
bNodeSocketValueFloat *valfloat;
bNodeSocketValueVector *valvector;
bNodeSocketValueRGBA *valrgba;
if (sock->default_value)
return;
switch (sock->type) {
case SOCK_FLOAT:
valfloat = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueFloat), "default socket value");
valfloat->value = sock->ns.vec[0];
valfloat->min = sock->ns.min;
valfloat->max = sock->ns.max;
valfloat->subtype = PROP_NONE;
break;
case SOCK_VECTOR:
valvector = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueVector), "default socket value");
copy_v3_v3(valvector->value, sock->ns.vec);
valvector->min = sock->ns.min;
valvector->max = sock->ns.max;
valvector->subtype = PROP_NONE;
break;
case SOCK_RGBA:
valrgba = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueRGBA), "default socket value");
copy_v4_v4(valrgba->value, sock->ns.vec);
break;
}
}
static void do_versions_nodetree_default_value(bNodeTree *ntree)
{
bNode *node;
bNodeSocket *sock;
for (node=ntree->nodes.first; node; node=node->next) {
for (sock=node->inputs.first; sock; sock=sock->next)
do_versions_socket_default_value(sock);
for (sock=node->outputs.first; sock; sock=sock->next)
do_versions_socket_default_value(sock);
}
for (sock=ntree->inputs.first; sock; sock=sock->next)
do_versions_socket_default_value(sock);
for (sock=ntree->outputs.first; sock; sock=sock->next)
do_versions_socket_default_value(sock);
}
static void lib_nodetree_init_types_cb(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
{
bNode *node;
ntreeInitTypes(ntree);
/* need to do this here instead of in do_versions, otherwise next function can crash */
do_versions_nodetree_default_value(ntree);
/* XXX could be replaced by do_versions for new nodes */
for (node=ntree->nodes.first; node; node=node->next)
node_verify_socket_templates(ntree, node);
}
/* updates group node socket own_index so that
* external links to/from the group node are preserved.
*/
static void lib_node_do_versions_group_indices(bNode *gnode)
{
bNodeTree *ngroup= (bNodeTree*)gnode->id;
bNode *intnode;
bNodeSocket *sock, *gsock, *intsock;
int found;
for (sock=gnode->outputs.first; sock; sock=sock->next) {
int old_index = sock->to_index;
for (gsock=ngroup->outputs.first; gsock; gsock=gsock->next) {
if (gsock->link && gsock->link->fromsock->own_index == old_index) {
sock->own_index = gsock->own_index;
break;
}
}
}
for (sock=gnode->inputs.first; sock; sock=sock->next) {
int old_index = sock->to_index;
/* can't use break in double loop */
found = 0;
for (intnode=ngroup->nodes.first; intnode && !found; intnode=intnode->next) {
for (intsock=intnode->inputs.first; intsock; intsock=intsock->next) {
if (intsock->own_index == old_index && intsock->link) {
sock->own_index = intsock->link->fromsock->own_index;
found = 1;
break;
}
}
}
}
}
/* updates external links for all group nodes in a tree */
static void lib_nodetree_do_versions_group_indices_cb(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
{
bNode *node;
for (node=ntree->nodes.first; node; node=node->next) {
if (node->type==NODE_GROUP) {
bNodeTree *ngroup= (bNodeTree*)node->id;
if (ngroup && (ngroup->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE))
lib_node_do_versions_group_indices(node);
}
}
}
/* make an update call for the tree */
static void lib_nodetree_do_versions_update_cb(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
{
if (ntree->update)
ntreeUpdateTree(ntree);
}
/* verify types for nodes and groups, all data has to be read */
/* open = 0: appending/linking, open = 1: open new file (need to clean out dynamic
* typedefs */
static void lib_verify_nodetree(Main *main, int UNUSED(open))
{
bNodeTree *ntree;
int i;
bNodeTreeType *ntreetype;
/* this crashes blender on undo/redo */
#if 0
if (open==1) {
reinit_nodesystem();
}
#endif
/* set node->typeinfo pointers */
for (i=0; i < NUM_NTREE_TYPES; ++i) {
ntreetype= ntreeGetType(i);
if (ntreetype && ntreetype->foreach_nodetree)
ntreetype->foreach_nodetree(main, NULL, lib_nodetree_init_types_cb);
}
for (ntree= main->nodetree.first; ntree; ntree= ntree->id.next)
lib_nodetree_init_types_cb(NULL, NULL, ntree);
{
int has_old_groups=0;
/* XXX this should actually be part of do_versions, but since we need
* finished library linking, it is not possible there. Instead in do_versions
* we have set the NTREE_DO_VERSIONS flag, so at this point we can do the
* actual group node updates.
*/
for (ntree= main->nodetree.first; ntree; ntree= ntree->id.next) {
if (ntree->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE) {
/* this adds copies and links from all unlinked internal sockets to group inputs/outputs. */
node_group_expose_all_sockets(ntree);
has_old_groups = 1;
}
}
if (has_old_groups) {
for (i=0; i < NUM_NTREE_TYPES; ++i) {
ntreetype= ntreeGetType(i);
if (ntreetype && ntreetype->foreach_nodetree)
ntreetype->foreach_nodetree(main, NULL, lib_nodetree_do_versions_group_indices_cb);
}
}
for (ntree= main->nodetree.first; ntree; ntree= ntree->id.next)
ntree->flag &= ~NTREE_DO_VERSIONS_GROUP_EXPOSE;
}
/* verify all group user nodes */
for (ntree= main->nodetree.first; ntree; ntree= ntree->id.next) {
ntreeVerifyNodes(main, &ntree->id);
}
/* make update calls where necessary */
{
for (ntree= main->nodetree.first; ntree; ntree= ntree->id.next)
if (ntree->update)
ntreeUpdateTree(ntree);
for (i=0; i < NUM_NTREE_TYPES; ++i) {
ntreetype= ntreeGetType(i);
if (ntreetype && ntreetype->foreach_nodetree)
ntreetype->foreach_nodetree(main, NULL, lib_nodetree_do_versions_update_cb);
}
}
}
static void direct_link_node_socket(FileData *fd, bNodeSocket *sock)
{
sock->link= newdataadr(fd, sock->link);
sock->storage= newdataadr(fd, sock->storage);
sock->default_value= newdataadr(fd, sock->default_value);
sock->cache= NULL;
}
/* ntree itself has been read! */
static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
{
/* note: writing and reading goes in sync, for speed */
bNode *node;
bNodeSocket *sock;
bNodeLink *link;
ntree->init= 0; /* to set callbacks and force setting types */
ntree->progress= NULL;
ntree->execdata= NULL;
ntree->adt= newdataadr(fd, ntree->adt);
direct_link_animdata(fd, ntree->adt);
link_list(fd, &ntree->nodes);
for (node= ntree->nodes.first; node; node= node->next) {
if (node->type == NODE_DYNAMIC) {
node->custom1= 0;
node->custom1= BSET(node->custom1, NODE_DYNAMIC_LOADED);
}
node->typeinfo= NULL;
link_list(fd, &node->inputs);
link_list(fd, &node->outputs);
if (node->type == CMP_NODE_MOVIEDISTORTION) {
node->storage= newmclipadr(fd, node->storage);
}
else
node->storage= newdataadr(fd, node->storage);
if (node->storage) {
/* could be handlerized at some point */
if (ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
direct_link_curvemapping(fd, node->storage);
else if (ntree->type==NTREE_COMPOSIT) {
if ( ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
direct_link_curvemapping(fd, node->storage);
else if (ELEM3(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
((ImageUser *)node->storage)->ok= 1;
}
else if ( ntree->type==NTREE_TEXTURE) {
if (node->type==TEX_NODE_CURVE_RGB || node->type==TEX_NODE_CURVE_TIME)
direct_link_curvemapping(fd, node->storage);
else if (node->type==TEX_NODE_IMAGE)
((ImageUser *)node->storage)->ok= 1;
}
}
}
link_list(fd, &ntree->links);
/* external sockets */
link_list(fd, &ntree->inputs);
link_list(fd, &ntree->outputs);
/* and we connect the rest */
for (node= ntree->nodes.first; node; node= node->next) {
node->parent = newdataadr(fd, node->parent);
node->preview= newimaadr(fd, node->preview);
node->lasty= 0;
for (sock= node->inputs.first; sock; sock= sock->next)
direct_link_node_socket(fd, sock);
for (sock= node->outputs.first; sock; sock= sock->next)
direct_link_node_socket(fd, sock);
}
for (sock= ntree->inputs.first; sock; sock= sock->next)
direct_link_node_socket(fd, sock);
for (sock= ntree->outputs.first; sock; sock= sock->next)
direct_link_node_socket(fd, sock);
for (link= ntree->links.first; link; link= link->next) {
link->fromnode= newdataadr(fd, link->fromnode);
link->tonode= newdataadr(fd, link->tonode);
link->fromsock= newdataadr(fd, link->fromsock);
link->tosock= newdataadr(fd, link->tosock);
}
/* type verification is in lib-link */
}
/* ************ READ ARMATURE ***************** */
/* temp struct used to transport needed info to lib_link_constraint_cb() */
typedef struct tConstraintLinkData {
FileData *fd;
ID *id;
} tConstraintLinkData;
/* callback function used to relink constraint ID-links */
static void lib_link_constraint_cb(bConstraint *UNUSED(con), ID **idpoin, void *userdata)
{
tConstraintLinkData *cld= (tConstraintLinkData *)userdata;
*idpoin = newlibadr(cld->fd, cld->id->lib, *idpoin);
}
static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
{
tConstraintLinkData cld;
bConstraint *con;
/* legacy fixes */
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;
}
/* own ipo, all constraints have it */
con->ipo= newlibadr_us(fd, id->lib, con->ipo); // XXX depreceated - old animation system
}
/* relink all ID-blocks used by the constraints */
cld.fd= fd;
cld.id= id;
id_loop_constraints(conlist, lib_link_constraint_cb, &cld);
}
static void direct_link_constraints(FileData *fd, ListBase *lb)
{
bConstraint *con;
link_list(fd, lb);
for (con=lb->first; con; con=con->next) {
con->data = newdataadr(fd, con->data);
switch (con->type) {
case CONSTRAINT_TYPE_PYTHON:
{
bPythonConstraint *data= con->data;
link_list(fd, &data->targets);
data->prop = newdataadr(fd, data->prop);
if (data->prop)
IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
break;
case CONSTRAINT_TYPE_SPLINEIK:
{
bSplineIKConstraint *data= con->data;
data->points= newdataadr(fd, data->points);
}
break;
case CONSTRAINT_TYPE_KINEMATIC:
{
con->lin_error = 0.f;
con->rot_error = 0.f;
}
case CONSTRAINT_TYPE_CHILDOF:
{
/* XXX version patch, in older code this flag wasn't always set, and is inherent to type */
if (con->ownspace == CONSTRAINT_SPACE_POSE)
con->flag |= CONSTRAINT_SPACEONCE;
}
break;
}
}
}
static void lib_link_pose(FileData *fd, Object *ob, bPose *pose)
{
bPoseChannel *pchan;
bArmature *arm= ob->data;
int rebuild;
if (!pose || !arm)
return;
/* always rebuild to match proxy or lib changes */
rebuild= ob->proxy || (ob->id.lib==NULL && arm->id.lib);
if (ob->proxy) {
/* sync proxy layer */
if (pose->proxy_layer)
arm->layer = pose->proxy_layer;
/* sync proxy active bone */
if (pose->proxy_act_bone[0]) {
Bone *bone = get_named_bone(arm, pose->proxy_act_bone);
if (bone)
arm->act_bone = bone;
}
}
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_us(fd, arm->id.lib, pchan->custom);
if (pchan->bone==NULL)
rebuild= 1;
else if (ob->id.lib==NULL && arm->id.lib) {
/* local pose selection copied to armature, bit hackish */
pchan->bone->flag &= ~BONE_SELECTED;
pchan->bone->flag |= pchan->selectflag;
}
}
if (rebuild) {
ob->recalc= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
pose->flag |= POSE_RECALC;
}
}
static void lib_link_armature(FileData *fd, Main *main)
{
bArmature *arm;
arm= main->armature.first;
while (arm) {
if (arm->id.flag & LIB_NEEDLINK) {
if (arm->adt) lib_link_animdata(fd, &arm->id, arm->adt);
arm->id.flag -= LIB_NEEDLINK;
}
arm= arm->id.next;
}
}
static void direct_link_bones(FileData *fd, Bone* bone)
{
Bone *child;
bone->parent= newdataadr(fd, bone->parent);
bone->prop= newdataadr(fd, bone->prop);
if (bone->prop)
IDP_DirectLinkProperty(bone->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
bone->flag &= ~BONE_DRAW_ACTIVE;
link_list(fd, &bone->childbase);
for (child=bone->childbase.first; child; child=child->next)
direct_link_bones(fd, child);
}
static void direct_link_armature(FileData *fd, bArmature *arm)
{
Bone *bone;
link_list(fd, &arm->bonebase);
arm->edbo= NULL;
arm->sketch = NULL;
arm->adt= newdataadr(fd, arm->adt);
direct_link_animdata(fd, arm->adt);
bone=arm->bonebase.first;
while (bone) {
direct_link_bones(fd, bone);
bone=bone->next;
}
arm->act_bone= newdataadr(fd, arm->act_bone);
arm->act_edbone= NULL;
}
/* ************ 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) {
if (ca->adt) lib_link_animdata(fd, &ca->id, ca->adt);
ca->ipo= newlibadr_us(fd, ca->id.lib, ca->ipo); // XXX depreceated - old animation system
ca->dof_ob= newlibadr_us(fd, ca->id.lib, ca->dof_ob);
ca->id.flag -= LIB_NEEDLINK;
}
ca= ca->id.next;
}
}
static void direct_link_camera(FileData *fd, Camera *ca)
{
ca->adt= newdataadr(fd, ca->adt);
direct_link_animdata(fd, ca->adt);
}
/* ************ 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) {
if (la->adt) lib_link_animdata(fd, &la->id, la->adt);
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); // XXX depreceated - old animation system
if (la->nodetree)
lib_link_ntree(fd, &la->id, la->nodetree);
la->id.flag -= LIB_NEEDLINK;
}
la= la->id.next;
}
}
static void direct_link_lamp(FileData *fd, Lamp *la)
{
int a;
la->adt= newdataadr(fd, la->adt);
direct_link_animdata(fd, la->adt);
for (a=0; a<MAX_MTEX; a++) {
la->mtex[a]= newdataadr(fd, la->mtex[a]);
}
la->curfalloff= newdataadr(fd, la->curfalloff);
if (la->curfalloff)
direct_link_curvemapping(fd, la->curfalloff);
la->nodetree= newdataadr(fd, la->nodetree);
if (la->nodetree)
direct_link_nodetree(fd, la->nodetree);
la->preview = direct_link_preview_image(fd, la->preview);
}
/* ************ READ keys ***************** */
static void lib_link_key(FileData *fd, Main *main)
{
Key *key;
key= main->key.first;
while (key) {
/*check if we need to generate unique ids for the shapekeys*/
if (!key->uidgen) {
KeyBlock *block;
key->uidgen = 1;
for (block=key->block.first; block; block=block->next) {
block->uid = key->uidgen++;
}
}
if (key->id.flag & LIB_NEEDLINK) {
if (key->adt) lib_link_animdata(fd, &key->id, key->adt);
key->ipo= newlibadr_us(fd, key->id.lib, key->ipo); // XXX depreceated - old animation system
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->adt= newdataadr(fd, key->adt);
direct_link_animdata(fd, key->adt);
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) {
if (mb->adt) lib_link_animdata(fd, &mb->id, mb->adt);
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); // XXX depreceated - old animation system
mb->id.flag -= LIB_NEEDLINK;
}
mb= mb->id.next;
}
}
static void direct_link_mball(FileData *fd, MetaBall *mb)
{
mb->adt= newdataadr(fd, mb->adt);
direct_link_animdata(fd, mb->adt);
mb->mat= newdataadr(fd, mb->mat);
test_pointer_array(fd, (void **)&mb->mat);
link_list(fd, &(mb->elems));
mb->disp.first= mb->disp.last= NULL;
mb->editelems= NULL;
mb->bb= NULL;
/* mb->edit_elems.first= mb->edit_elems.last= NULL;*/
mb->lastelem= NULL;
}
/* ************ 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) {
if (wrld->adt) lib_link_animdata(fd, &wrld->id, wrld->adt);
wrld->ipo= newlibadr_us(fd, wrld->id.lib, wrld->ipo); // XXX depreceated - old animation system
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);
}
}
if (wrld->nodetree)
lib_link_ntree(fd, &wrld->id, wrld->nodetree);
wrld->id.flag -= LIB_NEEDLINK;
}
wrld= wrld->id.next;
}
}
static void direct_link_world(FileData *fd, World *wrld)
{
int a;
wrld->adt= newdataadr(fd, wrld->adt);
direct_link_animdata(fd, wrld->adt);
for (a=0; a<MAX_MTEX; a++) {
wrld->mtex[a]= newdataadr(fd, wrld->mtex[a]);
}
wrld->nodetree= newdataadr(fd, wrld->nodetree);
if (wrld->nodetree)
direct_link_nodetree(fd, wrld->nodetree);
wrld->preview = direct_link_preview_image(fd, wrld->preview);
}
/* ************ READ VFONT ***************** */
static void lib_link_vfont(FileData *UNUSED(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 *UNUSED(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 0
if (text->flags & TXT_ISEXT) {
reopen_text(text);
}
else {
#endif
link_list(fd, &text->lines);
link_list(fd, &text->markers);
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_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) {
if (ima->id.properties) IDP_LibLinkProperty(ima->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
ima->id.flag -= LIB_NEEDLINK;
}
ima= ima->id.next;
}
}
static void link_ibuf_list(FileData *fd, ListBase *lb)
{
Link *ln, *prev;
if (lb->first==NULL) return;
lb->first= newimaadr(fd, lb->first);
ln= lb->first;
prev= NULL;
while (ln) {
ln->next= newimaadr(fd, ln->next);
ln->prev= prev;
prev= ln;
ln= ln->next;
}
lb->last= prev;
}
static void direct_link_image(FileData *fd, Image *ima)
{
/* for undo system, pointers could be restored */
if (fd->imamap)
link_ibuf_list(fd, &ima->ibufs);
else
ima->ibufs.first= ima->ibufs.last= NULL;
/* if not restored, we keep the binded opengl index */
if (ima->ibufs.first==NULL) {
ima->bindcode= 0;
ima->gputexture= NULL;
}
ima->anim= NULL;
ima->rr= NULL;
ima->repbind= NULL;
/* undo system, try to restore render buffers */
if (fd->imamap) {
int a;
for (a=0; a<IMA_MAX_RENDER_SLOT; a++)
ima->renders[a]= newimaadr(fd, ima->renders[a]);
}
else {
memset(ima->renders, 0, sizeof(ima->renders));
ima->last_render_slot= ima->render_slot;
}
ima->packedfile = direct_link_packedfile(fd, ima->packedfile);
ima->preview = direct_link_preview_image(fd, ima->preview);
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) {
if (cu->adt) lib_link_animdata(fd, &cu->id, cu->adt);
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); // XXX depreceated - old animation system
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->adt= newdataadr(fd, cu->adt);
direct_link_animdata(fd, cu->adt);
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 == NULL) link_list(fd, &(cu->nurb));
else {
cu->nurb.first=cu->nurb.last= NULL;
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.0f) cu->wordspace = 1.0f;
}
cu->bev.first=cu->bev.last= NULL;
cu->disp.first=cu->disp.last= NULL;
cu->editnurb= NULL;
cu->lastsel= NULL;
cu->path= NULL;
cu->editfont= NULL;
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 == NULL) 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) {
if (tex->adt) lib_link_animdata(fd, &tex->id, tex->adt);
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);
if (tex->pd)
tex->pd->object= newlibadr(fd, tex->id.lib, tex->pd->object);
if (tex->vd) tex->vd->object= newlibadr(fd, tex->id.lib, tex->vd->object);
if (tex->ot) tex->ot->object= newlibadr(fd, tex->id.lib, tex->ot->object);
if (tex->nodetree)
lib_link_ntree(fd, &tex->id, tex->nodetree);
tex->id.flag -= LIB_NEEDLINK;
}
tex= tex->id.next;
}
}
static void direct_link_texture(FileData *fd, Tex *tex)
{
tex->adt= newdataadr(fd, tex->adt);
direct_link_animdata(fd, tex->adt);
tex->plugin= newdataadr(fd, tex->plugin);
if (tex->plugin) {
tex->plugin->handle= NULL;
open_plugin_tex(tex->plugin);
/* initialize data for this instance, if an initialization
* function exists.
*/
if (tex->plugin->instance_init)
tex->plugin->instance_init((void *) tex->plugin->data);
}
tex->coba= newdataadr(fd, tex->coba);
tex->env= newdataadr(fd, tex->env);
if (tex->env) {
tex->env->ima= NULL;
memset(tex->env->cube, 0, 6*sizeof(void *));
tex->env->ok= 0;
}
tex->pd= newdataadr(fd, tex->pd);
if (tex->pd) {
tex->pd->point_tree = NULL;
tex->pd->coba= newdataadr(fd, tex->pd->coba);
tex->pd->falloff_curve= newdataadr(fd, tex->pd->falloff_curve);
if (tex->pd->falloff_curve) {
direct_link_curvemapping(fd, tex->pd->falloff_curve);
}
}
tex->vd= newdataadr(fd, tex->vd);
if (tex->vd) {
tex->vd->dataset = NULL;
tex->vd->ok = 0;
}
else {
if (tex->type == TEX_VOXELDATA)
tex->vd= MEM_callocN(sizeof(VoxelData), "direct_link_texture VoxelData");
}
tex->ot= newdataadr(fd, tex->ot);
tex->nodetree= newdataadr(fd, tex->nodetree);
if (tex->nodetree)
direct_link_nodetree(fd, tex->nodetree);
tex->preview = direct_link_preview_image(fd, tex->preview);
tex->iuser.ok= 1;
}
/* ************ READ MATERIAL ***************** */
static void lib_link_material(FileData *fd, Main *main)
{
Material *ma;
MTex *mtex;
int a;
ma= main->mat.first;
while (ma) {
if (ma->id.flag & LIB_NEEDLINK) {
if (ma->adt) lib_link_animdata(fd, &ma->id, ma->adt);
/* Link ID Properties -- and copy this comment EXACTLY for easy finding
* of library blocks that implement this.*/
if (ma->id.properties) IDP_LibLinkProperty(ma->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
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);
}
}
if (ma->nodetree)
lib_link_ntree(fd, &ma->id, ma->nodetree);
ma->id.flag -= LIB_NEEDLINK;
}
ma= ma->id.next;
}
}
static void direct_link_material(FileData *fd, Material *ma)
{
int a;
ma->adt= newdataadr(fd, ma->adt);
direct_link_animdata(fd, ma->adt);
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);
ma->nodetree= newdataadr(fd, ma->nodetree);
if (ma->nodetree)
direct_link_nodetree(fd, ma->nodetree);
ma->preview = direct_link_preview_image(fd, ma->preview);
ma->gpumaterial.first = ma->gpumaterial.last = NULL;
}
/* ************ READ PARTICLE SETTINGS ***************** */
/* update this also to writefile.c */
static const char *ptcache_data_struct[] = {
"", // BPHYS_DATA_INDEX
"", // BPHYS_DATA_LOCATION
"", // BPHYS_DATA_VELOCITY
"", // BPHYS_DATA_ROTATION
"", // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST */
"", // BPHYS_DATA_SIZE:
"", // BPHYS_DATA_TIMES:
"BoidData" // case BPHYS_DATA_BOIDS:
};
static void direct_link_pointcache(FileData *fd, PointCache *cache)
{
if ((cache->flag & PTCACHE_DISK_CACHE)==0) {
PTCacheMem *pm;
PTCacheExtra *extra;
int i;
link_list(fd, &cache->mem_cache);
pm = cache->mem_cache.first;
for (; pm; pm=pm->next) {
for (i=0; i<BPHYS_TOT_DATA; i++) {
pm->data[i] = newdataadr(fd, pm->data[i]);
/* the cache saves non-struct data without DNA */
if (pm->data[i] && ptcache_data_struct[i][0]=='\0' && (fd->flags & FD_FLAGS_SWITCH_ENDIAN)) {
int j, tot= (BKE_ptcache_data_size (i) * pm->totpoint)/4; /* data_size returns bytes */
int *poin= pm->data[i];
for (j= 0; j<tot; j++)
SWITCH_INT(poin[j]);
}
}
link_list(fd, &pm->extradata);
for (extra=pm->extradata.first; extra; extra=extra->next)
extra->data = newdataadr(fd, extra->data);
}
}
else
cache->mem_cache.first = cache->mem_cache.last = NULL;
cache->flag &= ~PTCACHE_SIMULATION_VALID;
cache->simframe= 0;
cache->edit= NULL;
cache->free_edit= NULL;
cache->cached_frames= NULL;
}
static void direct_link_pointcache_list(FileData *fd, ListBase *ptcaches, PointCache **ocache, int force_disk)
{
if (ptcaches->first) {
PointCache *cache= NULL;
link_list(fd, ptcaches);
for (cache=ptcaches->first; cache; cache=cache->next) {
direct_link_pointcache(fd, cache);
if (force_disk) {
cache->flag |= PTCACHE_DISK_CACHE;
cache->step = 1;
}
}
*ocache = newdataadr(fd, *ocache);
}
else if (*ocache) {
/* old "single" caches need to be linked too */
*ocache = newdataadr(fd, *ocache);
direct_link_pointcache(fd, *ocache);
if (force_disk) {
(*ocache)->flag |= PTCACHE_DISK_CACHE;
(*ocache)->step = 1;
}
ptcaches->first = ptcaches->last = *ocache;
}
}
static void lib_link_partdeflect(FileData *fd, ID *id, PartDeflect *pd)
{
if (pd && pd->tex)
pd->tex=newlibadr_us(fd, id->lib, pd->tex);
}
static void lib_link_particlesettings(FileData *fd, Main *main)
{
ParticleSettings *part;
ParticleDupliWeight *dw;
MTex *mtex;
int a;
part= main->particle.first;
while (part) {
if (part->id.flag & LIB_NEEDLINK) {
if (part->adt) lib_link_animdata(fd, &part->id, part->adt);
part->ipo= newlibadr_us(fd, part->id.lib, part->ipo); // XXX depreceated - old animation system
part->dup_ob = newlibadr(fd, part->id.lib, part->dup_ob);
part->dup_group = newlibadr(fd, part->id.lib, part->dup_group);
part->eff_group = newlibadr(fd, part->id.lib, part->eff_group);
part->bb_ob = newlibadr(fd, part->id.lib, part->bb_ob);
lib_link_partdeflect(fd, &part->id, part->pd);
lib_link_partdeflect(fd, &part->id, part->pd2);
if (part->effector_weights)
part->effector_weights->group = newlibadr(fd, part->id.lib, part->effector_weights->group);
if (part->dupliweights.first && part->dup_group) {
int index_ok = 0;
/* check for old files without indices (all indexes 0) */
dw = part->dupliweights.first;
if (part->dupliweights.first == part->dupliweights.last) {
/* special case for only one object in the group */
index_ok = 1;
}
else {
for (; dw; dw=dw->next) {
if (dw->index > 0) {
index_ok = 1;
break;
}
}
}
if (index_ok) {
/* if we have indexes, let's use them */
dw = part->dupliweights.first;
for (; dw; dw=dw->next) {
GroupObject *go = (GroupObject *)BLI_findlink(&part->dup_group->gobject, dw->index);
dw->ob = go ? go->ob : NULL;
}
}
else {
/* otherwise try to get objects from own library (won't work on library linked groups) */
for (; dw; dw=dw->next)
dw->ob = newlibadr(fd, part->id.lib, dw->ob);
}
}
else {
part->dupliweights.first = part->dupliweights.last = NULL;
}
if (part->boids) {
BoidState *state = part->boids->states.first;
BoidRule *rule;
for (; state; state=state->next) {
rule = state->rules.first;
for (; rule; rule=rule->next)
switch (rule->type) {
case eBoidRuleType_Goal:
case eBoidRuleType_Avoid:
{
BoidRuleGoalAvoid *brga = (BoidRuleGoalAvoid*)rule;
brga->ob = newlibadr(fd, part->id.lib, brga->ob);
break;
}
case eBoidRuleType_FollowLeader:
{
BoidRuleFollowLeader *brfl = (BoidRuleFollowLeader*)rule;
brfl->ob = newlibadr(fd, part->id.lib, brfl->ob);
break;
}
}
}
}
for (a=0; a<MAX_MTEX; a++) {
mtex= part->mtex[a];
if (mtex) {
mtex->tex = newlibadr_us(fd, part->id.lib, mtex->tex);
mtex->object = newlibadr(fd, part->id.lib, mtex->object);
}
}
part->id.flag -= LIB_NEEDLINK;
}
part= part->id.next;
}
}
static void direct_link_partdeflect(PartDeflect *pd)
{
if (pd) pd->rng=NULL;
}
static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
{
int a;
part->adt= newdataadr(fd, part->adt);
part->pd= newdataadr(fd, part->pd);
part->pd2= newdataadr(fd, part->pd2);
direct_link_animdata(fd, part->adt);
direct_link_partdeflect(part->pd);
direct_link_partdeflect(part->pd2);
part->effector_weights = newdataadr(fd, part->effector_weights);
if (!part->effector_weights)
part->effector_weights = BKE_add_effector_weights(part->eff_group);
link_list(fd, &part->dupliweights);
part->boids= newdataadr(fd, part->boids);
part->fluid= newdataadr(fd, part->fluid);
if (part->boids) {
BoidState *state;
link_list(fd, &part->boids->states);
for (state=part->boids->states.first; state; state=state->next) {
link_list(fd, &state->rules);
link_list(fd, &state->conditions);
link_list(fd, &state->actions);
}
}
for (a=0; a<MAX_MTEX; a++) {
part->mtex[a]= newdataadr(fd, part->mtex[a]);
}
}
static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase *particles)
{
ParticleSystem *psys, *psysnext;
for (psys=particles->first; psys; psys=psysnext) {
psysnext= psys->next;
psys->part = newlibadr_us(fd, id->lib, psys->part);
if (psys->part) {
ParticleTarget *pt = psys->targets.first;
for (; pt; pt=pt->next)
pt->ob=newlibadr(fd, id->lib, pt->ob);
psys->parent= newlibadr_us(fd, id->lib, psys->parent);
psys->target_ob = newlibadr(fd, id->lib, psys->target_ob);
if (psys->clmd) {
/* XXX - from reading existing code this seems correct but intended usage of
* pointcache should /w cloth should be added in 'ParticleSystem' - campbell */
psys->clmd->point_cache= psys->pointcache;
psys->clmd->ptcaches.first= psys->clmd->ptcaches.last= NULL;
psys->clmd->coll_parms->group= newlibadr(fd, id->lib, psys->clmd->coll_parms->group);
}
}
else {
/* particle modifier must be removed before particle system */
ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
BLI_remlink(&ob->modifiers, psmd);
modifier_free((ModifierData *)psmd);
BLI_remlink(particles, psys);
MEM_freeN(psys);
}
}
}
static void direct_link_particlesystems(FileData *fd, ListBase *particles)
{
ParticleSystem *psys;
ParticleData *pa;
int a;
for (psys=particles->first; psys; psys=psys->next) {
psys->particles=newdataadr(fd, psys->particles);
if (psys->particles && psys->particles->hair) {
for (a=0, pa=psys->particles; a<psys->totpart; a++, pa++)
pa->hair=newdataadr(fd, pa->hair);
}
if (psys->particles && psys->particles->keys) {
for (a=0, pa=psys->particles; a<psys->totpart; a++, pa++) {
pa->keys= NULL;
pa->totkey= 0;
}
psys->flag &= ~PSYS_KEYED;
}
if (psys->particles && psys->particles->boid) {
pa = psys->particles;
pa->boid = newdataadr(fd, pa->boid);
for (a=1, pa++; a<psys->totpart; a++, pa++)
pa->boid = (pa-1)->boid + 1;
}
else if (psys->particles) {
for (a=0, pa=psys->particles; a<psys->totpart; a++, pa++)
pa->boid = NULL;
}
psys->fluid_springs = newdataadr(fd, psys->fluid_springs);
psys->child = newdataadr(fd, psys->child);
psys->effectors = NULL;
link_list(fd, &psys->targets);
psys->edit = NULL;
psys->free_edit = NULL;
psys->pathcache = NULL;
psys->childcache = NULL;
psys->pathcachebufs.first = psys->pathcachebufs.last = NULL;
psys->childcachebufs.first = psys->childcachebufs.last = NULL;
psys->frand = NULL;
psys->pdd = NULL;
psys->renderdata = NULL;
direct_link_pointcache_list(fd, &psys->ptcaches, &psys->pointcache, 0);
if (psys->clmd) {
psys->clmd = newdataadr(fd, psys->clmd);
psys->clmd->clothObject = NULL;
psys->clmd->sim_parms= newdataadr(fd, psys->clmd->sim_parms);
psys->clmd->sim_parms->effector_weights = NULL;
psys->clmd->coll_parms= newdataadr(fd, psys->clmd->coll_parms);
if (psys->clmd->sim_parms) {
if (psys->clmd->sim_parms->presets > 10)
psys->clmd->sim_parms->presets = 0;
}
psys->hair_in_dm = psys->hair_out_dm = NULL;
psys->clmd->point_cache = psys->pointcache;
}
psys->tree = NULL;
psys->bvhtree = NULL;
}
return;
}
/* ************ READ MESH ***************** */
static void lib_link_mtface(FileData *fd, Mesh *me, MTFace *mtface, int totface)
{
MTFace *tf= mtface;
int i;
/* Add pseudo-references (not fake users!) to images used by texface. A
* little bogus; it would be better if each mesh consistently added one ref
* to each image it used. - z0r */
for (i=0; i<totface; i++, tf++) {
tf->tpage= newlibadr(fd, me->id.lib, tf->tpage);
if (tf->tpage && tf->tpage->id.us==0)
tf->tpage->id.us= 1;
}
}
static void lib_link_customdata_mtface(FileData *fd, Mesh *me, CustomData *fdata, int totface)
{
int i;
for (i=0; i<fdata->totlayer; i++) {
CustomDataLayer *layer = &fdata->layers[i];
if (layer->type == CD_MTFACE)
lib_link_mtface(fd, me, layer->data, totface);
}
}
static void lib_link_customdata_mtpoly(FileData *fd, Mesh *me, CustomData *pdata, int totface)
{
int i;
for (i=0; i<pdata->totlayer; i++) {
CustomDataLayer *layer = &pdata->layers[i];
if (layer->type == CD_MTEXPOLY) {
MTexPoly *tf= layer->data;
int i;
for (i=0; i<totface; i++, tf++) {
tf->tpage= newlibadr(fd, me->id.lib, tf->tpage);
if (tf->tpage && tf->tpage->id.us==0)
tf->tpage->id.us= 1;
}
}
}
}
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;
/* Link ID Properties -- and copy this comment EXACTLY for easy finding
* of library blocks that implement this.*/
if (me->id.properties) IDP_LibLinkProperty(me->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
if (me->adt) lib_link_animdata(fd, &me->id, me->adt);
/* 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);
lib_link_customdata_mtface(fd, me, &me->fdata, me->totface);
lib_link_customdata_mtpoly(fd, me, &me->pdata, me->totpoly);
if (me->mr && me->mr->levels.first)
lib_link_customdata_mtface(fd, me, &me->mr->fdata,
((MultiresLevel*)me->mr->levels.first)->totface);
/*check if we need to convert mfaces to mpolys*/
if (me->totface && !me->totpoly) {
/* temporarily switch main so that reading from
* external CustomData works */
Main *gmain = G.main;
G.main = main;
BKE_mesh_convert_mfaces_to_mpolys(me);
G.main = gmain;
}
/*
* Re-tessellate, even if the polys were just created from tessfaces, this
* is important because it:
* - fill the CD_POLYINDEX layer
* - gives consistency of tessface between loading from a file and
* converting an edited BMesh back into a mesh (i.e. it replaces
* quad tessfaces in a loaded mesh immediately, instead of lazily
* waiting until edit mode has been entered/exited, making it easier
* to recognize problems that would otherwise only show up after edits).
*/
#ifdef USE_TESSFACE_DEFAULT
BKE_mesh_tessface_calc(me);
#else
BKE_mesh_tessface_clear(me);
#endif
me->id.flag -= LIB_NEEDLINK;
}
me= me->id.next;
}
/* convert texface options to material */
convert_tface_mt(fd, main);
}
static void direct_link_dverts(FileData *fd, int count, MDeformVert *mdverts)
{
int i;
if (mdverts == NULL) {
return;
}
for (i= count; i > 0; i--, mdverts++) {
/*convert to vgroup allocation system*/
MDeformWeight *dw;
if (mdverts->dw && (dw= newdataadr(fd, mdverts->dw))) {
const ssize_t dw_len= mdverts->totweight * sizeof(MDeformWeight);
void *dw_tmp= MEM_mallocN(dw_len, "direct_link_dverts");
memcpy(dw_tmp, dw, dw_len);
mdverts->dw= dw_tmp;
MEM_freeN(dw);
}
else {
mdverts->dw= NULL;
mdverts->totweight= 0;
}
}
}
static void direct_link_mdisps(FileData *fd, int count, MDisps *mdisps, int external)
{
if (mdisps) {
int i;
for (i = 0; i < count; ++i) {
mdisps[i].disps = newdataadr(fd, mdisps[i].disps);
mdisps[i].hidden = newdataadr(fd, mdisps[i].hidden);
if (mdisps[i].totdisp && !mdisps[i].level) {
/* this calculation is only correct for loop mdisps;
* if loading pre-BMesh face mdisps this will be
* overwritten with the correct value in
* bm_corners_to_loops() */
float gridsize = sqrtf(mdisps[i].totdisp);
mdisps[i].level = (int)(logf(gridsize - 1.0f) / M_LN2) + 1;
}
if ( (fd->flags & FD_FLAGS_SWITCH_ENDIAN) && (mdisps[i].disps) ) {
/* DNA_struct_switch_endian doesn't do endian swap for (*disps)[] */
/* this does swap for data written at write_mdisps() - readfile.c */
int x;
float *tmpdisps= *mdisps[i].disps;
for (x=0;x<mdisps[i].totdisp*3;x++) {
SWITCH_INT(*tmpdisps);
tmpdisps++;
}
}
if (!external && !mdisps[i].disps)
mdisps[i].totdisp = 0;
}
}
}
/*this isn't really a public api function, so prototyped here*/
static void direct_link_customdata(FileData *fd, CustomData *data, int count)
{
int i = 0;
data->layers= newdataadr(fd, data->layers);
/* annoying workaround for bug [#31079] loading legacy files with
* no polygons _but_ have stale customdata */
if (UNLIKELY(count == 0 && data->layers == NULL && data->totlayer != 0)) {
memset(data, 0, sizeof(*data));
return;
}
data->external= newdataadr(fd, data->external);
while (i < data->totlayer) {
CustomDataLayer *layer = &data->layers[i];
if (layer->flag & CD_FLAG_EXTERNAL)
layer->flag &= ~CD_FLAG_IN_MEMORY;
if (CustomData_verify_versions(data, i)) {
layer->data = newdataadr(fd, layer->data);
if (layer->type == CD_MDISPS)
direct_link_mdisps(fd, count, layer->data, layer->flag & CD_FLAG_EXTERNAL);
i++;
}
}
CustomData_update_typemap(data);
}
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->mloop= newdataadr(fd, mesh->mloop);
mesh->mpoly= newdataadr(fd, mesh->mpoly);
mesh->tface= newdataadr(fd, mesh->tface);
mesh->mtface= newdataadr(fd, mesh->mtface);
mesh->mcol= newdataadr(fd, mesh->mcol);
mesh->msticky= newdataadr(fd, mesh->msticky);
mesh->dvert= newdataadr(fd, mesh->dvert);
mesh->mloopcol= newdataadr(fd, mesh->mloopcol);
mesh->mloopuv= newdataadr(fd, mesh->mloopuv);
mesh->mtpoly= newdataadr(fd, mesh->mtpoly);
mesh->mselect = newdataadr(fd, mesh->mselect);
/* animdata */
mesh->adt= newdataadr(fd, mesh->adt);
direct_link_animdata(fd, mesh->adt);
/* normally direct_link_dverts should be called in direct_link_customdata,
* but for backwards compat in do_versions to work we do it here */
direct_link_dverts(fd, mesh->totvert, mesh->dvert);
direct_link_customdata(fd, &mesh->vdata, mesh->totvert);
direct_link_customdata(fd, &mesh->edata, mesh->totedge);
direct_link_customdata(fd, &mesh->fdata, mesh->totface);
direct_link_customdata(fd, &mesh->ldata, mesh->totloop);
direct_link_customdata(fd, &mesh->pdata, mesh->totpoly);
#ifdef USE_BMESH_FORWARD_COMPAT
/* NEVER ENABLE THIS CODE INTO BMESH!
* THIS IS FOR LOADING BMESH INTO OLDER FILES ONLY */
mesh->mpoly= newdataadr(fd, mesh->mpoly);
mesh->mloop= newdataadr(fd, mesh->mloop);
direct_link_customdata(fd, &mesh->pdata, mesh->totpoly);
direct_link_customdata(fd, &mesh->ldata, mesh->totloop);
if (mesh->mpoly) {
/* be clever and load polygons as mfaces */
mesh->totface= mesh_mpoly_to_mface(&mesh->fdata, &mesh->ldata, &mesh->pdata,
mesh->totface, mesh->totloop, mesh->totpoly);
CustomData_free(&mesh->pdata, mesh->totpoly);
memset(&mesh->pdata, 0, sizeof(CustomData));
mesh->totpoly = 0;
CustomData_free(&mesh->ldata, mesh->totloop);
memset(&mesh->ldata, 0, sizeof(CustomData));
mesh->totloop = 0;
mesh_update_customdata_pointers(mesh);
}
#endif
mesh->bb= NULL;
mesh->edit_btmesh= NULL;
/* Multires data */
mesh->mr= newdataadr(fd, mesh->mr);
if (mesh->mr) {
MultiresLevel *lvl;
link_list(fd, &mesh->mr->levels);
lvl= mesh->mr->levels.first;
direct_link_customdata(fd, &mesh->mr->vdata, lvl->totvert);
direct_link_dverts(fd, lvl->totvert, CustomData_get(&mesh->mr->vdata, 0, CD_MDEFORMVERT));
direct_link_customdata(fd, &mesh->mr->fdata, lvl->totface);
mesh->mr->edge_flags= newdataadr(fd, mesh->mr->edge_flags);
mesh->mr->edge_creases= newdataadr(fd, mesh->mr->edge_creases);
mesh->mr->verts = newdataadr(fd, mesh->mr->verts);
/* If mesh has the same number of vertices as the
* highest multires level, load the current mesh verts
* into multires and discard the old data. Needed
* because some saved files either do not have a verts
* array, or the verts array contains out-of-date
* data. */
if (mesh->totvert == ((MultiresLevel*)mesh->mr->levels.last)->totvert) {
if (mesh->mr->verts)
MEM_freeN(mesh->mr->verts);
mesh->mr->verts = MEM_dupallocN(mesh->mvert);
}
for (; lvl; lvl= lvl->next) {
lvl->verts= newdataadr(fd, lvl->verts);
lvl->faces= newdataadr(fd, lvl->faces);
lvl->edges= newdataadr(fd, lvl->edges);
lvl->colfaces= newdataadr(fd, lvl->colfaces);
}
}
/* if multires is present but has no valid vertex data,
* there's no way to recover it; silently remove multires */
if (mesh->mr && !mesh->mr->verts) {
multires_free(mesh->mr);
mesh->mr = NULL;
}
if ((fd->flags & FD_FLAGS_SWITCH_ENDIAN) && mesh->tface) {
TFace *tf= mesh->tface;
int i;
for (i=0; i< (mesh->totface); i++, tf++) {
SWITCH_INT(tf->col[0]);
SWITCH_INT(tf->col[1]);
SWITCH_INT(tf->col[2]);
SWITCH_INT(tf->col[3]);
}
}
}
/* ************ 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) {
if (lt->adt) lib_link_animdata(fd, &lt->id, lt->adt);
lt->ipo= newlibadr_us(fd, lt->id.lib, lt->ipo); // XXX depreceated - old animation system
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);
lt->dvert= newdataadr(fd, lt->dvert);
direct_link_dverts(fd, lt->pntsu*lt->pntsv*lt->pntsw, lt->dvert);
lt->editlatt= NULL;
lt->adt = newdataadr(fd, lt->adt);
direct_link_animdata(fd, lt->adt);
}
/* ************ READ OBJECT ***************** */
static void lib_link_modifiers__linkModifiers(void *userData, Object *ob,
ID **idpoin)
{
FileData *fd = userData;
*idpoin = newlibadr(fd, ob->id.lib, *idpoin);
/* hardcoded bad exception; non-object modifier data gets user count (texture, displace) */
if (*idpoin && GS((*idpoin)->name)!=ID_OB)
(*idpoin)->us++;
}
static void lib_link_modifiers(FileData *fd, Object *ob)
{
modifiers_foreachIDLink(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) {
if (ob->id.properties) IDP_LibLinkProperty(ob->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
if (ob->adt) lib_link_animdata(fd, &ob->id, ob->adt);
// XXX depreceated - old animation system <<<
ob->ipo= newlibadr_us(fd, ob->id.lib, ob->ipo);
ob->action = newlibadr_us(fd, ob->id.lib, ob->action);
// >>> XXX depreceated - old animation system
ob->parent= newlibadr(fd, ob->id.lib, ob->parent);
ob->track= newlibadr(fd, ob->id.lib, ob->track);
ob->poselib= newlibadr_us(fd, ob->id.lib, ob->poselib);
ob->dup_group= newlibadr_us(fd, ob->id.lib, ob->dup_group);
ob->proxy= newlibadr_us(fd, ob->id.lib, ob->proxy);
if (ob->proxy) {
/* paranoia check, actually a proxy_from pointer should never be written... */
if (ob->proxy->id.lib==NULL) {
ob->proxy->proxy_from= NULL;
ob->proxy= NULL;
if (ob->id.lib)
printf("Proxy lost from object %s lib %s\n", ob->id.name+2, ob->id.lib->name);
else
printf("Proxy lost from object %s lib <NONE>\n", ob->id.name+2);
}
else {
/* this triggers object_update to always use a copy */
ob->proxy->proxy_from= ob;
/* force proxy updates after load/undo, a bit weak */
ob->recalc= ob->proxy->recalc= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
}
}
ob->proxy_group= newlibadr(fd, ob->id.lib, ob->proxy_group);
poin= ob->data;
ob->data= newlibadr_us(fd, ob->id.lib, ob->data);
if (ob->data==NULL && poin!=NULL) {
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.\n", ob->id.name+2);
ob->type= OB_EMPTY;
warn= 1;
if (ob->pose) {
free_pose(ob->pose);
ob->pose= NULL;
ob->mode &= ~OB_MODE_POSE;
}
}
for (a=0; a<ob->totcol; a++) ob->mat[a]= newlibadr_us(fd, ob->id.lib, ob->mat[a]);
/* When the object is local and the data is library its possible
* the material list size gets out of sync. [#22663] */
if (ob->data && ob->id.lib != ((ID *)ob->data)->lib) {
short *totcol_data= give_totcolp(ob);
/* Only expand so as not to loose any object materials that might be set. */
if (totcol_data && *totcol_data > ob->totcol) {
/* printf("'%s' %d -> %d\n", ob->id.name, ob->totcol, *totcol_data); */
resize_object_material(ob, *totcol_data);
}
}
ob->gpd= newlibadr_us(fd, ob->id.lib, ob->gpd);
ob->duplilist= NULL;
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);
// XXX depreceated - old animation system <<<
lib_link_constraint_channels(fd, &ob->id, &ob->constraintChannels);
lib_link_nlastrips(fd, &ob->id, &ob->nlastrips);
// >>> XXX depreceated - old animation system
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) {
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) {
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_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_OBJECT) {
bObjectActuator *oa= act->data;
if (oa==NULL) {
init_actuator(act);
}
else {
oa->reference= newlibadr(fd, ob->id.lib, oa->reference);
}
}
else if (act->type==ACT_EDIT_OBJECT) {
bEditObjectActuator *eoa= act->data;
if (eoa==NULL) {
init_actuator(act);
}
else {
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_SHAPEACTION) {
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);
}
else if (act->type==ACT_2DFILTER) {
bTwoDFilterActuator *_2dfa = act->data;
_2dfa->text= newlibadr(fd, ob->id.lib, _2dfa->text);
}
else if (act->type==ACT_PARENT) {
bParentActuator *parenta = act->data;
parenta->ob = newlibadr(fd, ob->id.lib, parenta->ob);
}
else if (act->type==ACT_STATE) {
/* bStateActuator *statea = act->data; */
}
else if (act->type==ACT_ARMATURE) {
bArmatureActuator *arma= act->data;
arma->target= newlibadr(fd, ob->id.lib, arma->target);
arma->subtarget= newlibadr(fd, ob->id.lib, arma->subtarget);
}
else if (act->type==ACT_STEERING) {
bSteeringActuator *steeringa = act->data;
steeringa->target = newlibadr(fd, ob->id.lib, steeringa->target);
steeringa->navmesh = newlibadr(fd, ob->id.lib, steeringa->navmesh);
}
act= act->next;
}
{
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
if (fluidmd && fluidmd->fss)
fluidmd->fss->ipo = newlibadr_us(fd, ob->id.lib, fluidmd->fss->ipo);
}
{
SmokeModifierData *smd = (SmokeModifierData *)modifiers_findByType(ob, eModifierType_Smoke);
if (smd && smd->type == MOD_SMOKE_TYPE_DOMAIN && smd->domain) {
smd->domain->flags |= MOD_SMOKE_FILE_LOAD; /* flag for refreshing the simulation after loading */
}
}
/* texture field */
if (ob->pd)
lib_link_partdeflect(fd, &ob->id, ob->pd);
if (ob->soft)
ob->soft->effector_weights->group = newlibadr(fd, ob->id.lib, ob->soft->effector_weights->group);
lib_link_particlesystems(fd, ob, &ob->id, &ob->particlesystem);
lib_link_modifiers(fd, ob);
}
ob= ob->id.next;
}
if (warn) {
BKE_report(fd->reports, RPT_WARNING, "Warning in console");
}
}
static void direct_link_pose(FileData *fd, bPose *pose)
{
bPoseChannel *pchan;
if (!pose)
return;
link_list(fd, &pose->chanbase);
link_list(fd, &pose->agroups);
pose->chanhash= NULL;
for (pchan = pose->chanbase.first; pchan; pchan=pchan->next) {
pchan->bone= NULL;
pchan->parent= newdataadr(fd, pchan->parent);
pchan->child= newdataadr(fd, pchan->child);
pchan->custom_tx= newdataadr(fd, pchan->custom_tx);
direct_link_constraints(fd, &pchan->constraints);
pchan->prop = newdataadr(fd, pchan->prop);
if (pchan->prop)
IDP_DirectLinkProperty(pchan->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
pchan->mpath= newdataadr(fd, pchan->mpath);
if (pchan->mpath)
direct_link_motionpath(fd, pchan->mpath);
pchan->iktree.first= pchan->iktree.last= NULL;
pchan->siktree.first= pchan->siktree.last= NULL;
/* in case this value changes in future, clamp else we get undefined behavior */
CLAMP(pchan->rotmode, ROT_MODE_MIN, ROT_MODE_MAX);
}
pose->ikdata = NULL;
if (pose->ikparam != NULL) {
pose->ikparam= newdataadr(fd, pose->ikparam);
}
}
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;
md->scene = NULL;
/* if modifiers disappear, or for upward compatibility */
if (NULL==modifierType_getInfo(md->type))
md->type= eModifierType_None;
if (md->type==eModifierType_Subsurf) {
SubsurfModifierData *smd = (SubsurfModifierData*) md;
smd->emCache = smd->mCache = NULL;
}
else if (md->type==eModifierType_Armature) {
ArmatureModifierData *amd = (ArmatureModifierData*) md;
amd->prevCos= NULL;
}
else if (md->type==eModifierType_Cloth) {
ClothModifierData *clmd = (ClothModifierData*) md;
clmd->clothObject = NULL;
clmd->sim_parms= newdataadr(fd, clmd->sim_parms);
clmd->coll_parms= newdataadr(fd, clmd->coll_parms);
direct_link_pointcache_list(fd, &clmd->ptcaches, &clmd->point_cache, 0);
if (clmd->sim_parms) {
if (clmd->sim_parms->presets > 10)
clmd->sim_parms->presets = 0;
clmd->sim_parms->reset = 0;
clmd->sim_parms->effector_weights = newdataadr(fd, clmd->sim_parms->effector_weights);
if (!clmd->sim_parms->effector_weights) {
clmd->sim_parms->effector_weights = BKE_add_effector_weights(NULL);
}
}
}
else if (md->type==eModifierType_Fluidsim) {
FluidsimModifierData *fluidmd = (FluidsimModifierData*) md;
fluidmd->fss= newdataadr(fd, fluidmd->fss);
if (fluidmd->fss) {
fluidmd->fss->fmd= fluidmd;
fluidmd->fss->meshVelocities = NULL;
}
}
else if (md->type==eModifierType_Smoke) {
SmokeModifierData *smd = (SmokeModifierData*) md;
if (smd->type==MOD_SMOKE_TYPE_DOMAIN) {
smd->flow = NULL;
smd->coll = NULL;
smd->domain = newdataadr(fd, smd->domain);
smd->domain->smd = smd;
smd->domain->fluid = NULL;
smd->domain->wt = NULL;
smd->domain->shadow = NULL;
smd->domain->tex = NULL;
smd->domain->tex_shadow = NULL;
smd->domain->tex_wt = NULL;
smd->domain->effector_weights = newdataadr(fd, smd->domain->effector_weights);
if (!smd->domain->effector_weights)
smd->domain->effector_weights = BKE_add_effector_weights(NULL);
direct_link_pointcache_list(fd, &(smd->domain->ptcaches[0]), &(smd->domain->point_cache[0]), 1);
/* Smoke uses only one cache from now on, so store pointer convert */
if (smd->domain->ptcaches[1].first || smd->domain->point_cache[1]) {
if (smd->domain->point_cache[1]) {
PointCache *cache = newdataadr(fd, smd->domain->point_cache[1]);
if (cache->flag & PTCACHE_FAKE_SMOKE)
; /* Smoke was already saved in "new format" and this cache is a fake one. */
else
printf("High resolution smoke cache not available due to pointcache update. Please reset the simulation.\n");
BKE_ptcache_free(cache);
}
smd->domain->ptcaches[1].first = NULL;
smd->domain->ptcaches[1].last = NULL;
smd->domain->point_cache[1] = NULL;
}
}
else if (smd->type==MOD_SMOKE_TYPE_FLOW) {
smd->domain = NULL;
smd->coll = NULL;
smd->flow = newdataadr(fd, smd->flow);
smd->flow->smd = smd;
smd->flow->psys = newdataadr(fd, smd->flow->psys);
}
else if (smd->type==MOD_SMOKE_TYPE_COLL) {
smd->flow = NULL;
smd->domain = NULL;
smd->coll = newdataadr(fd, smd->coll);
if (smd->coll) {
smd->coll->points = NULL;
smd->coll->numpoints = 0;
}
else
smd->type = 0;
}
}
else if (md->type==eModifierType_DynamicPaint) {
DynamicPaintModifierData *pmd = (DynamicPaintModifierData*) md;
if (pmd->canvas) {
pmd->canvas = newdataadr(fd, pmd->canvas);
pmd->canvas->pmd = pmd;
pmd->canvas->dm = NULL;
pmd->canvas->flags &= ~MOD_DPAINT_BAKING; /* just in case */
if (pmd->canvas->surfaces.first) {
DynamicPaintSurface *surface;
link_list(fd, &pmd->canvas->surfaces);
for (surface=pmd->canvas->surfaces.first; surface; surface=surface->next) {
surface->canvas = pmd->canvas;
surface->data = NULL;
direct_link_pointcache_list(fd, &(surface->ptcaches), &(surface->pointcache), 1);
if (!(surface->effector_weights = newdataadr(fd, surface->effector_weights)))
surface->effector_weights = BKE_add_effector_weights(NULL);
}
}
}
if (pmd->brush) {
pmd->brush = newdataadr(fd, pmd->brush);
pmd->brush->pmd = pmd;
pmd->brush->psys = newdataadr(fd, pmd->brush->psys);
pmd->brush->paint_ramp = newdataadr(fd, pmd->brush->paint_ramp);
pmd->brush->vel_ramp = newdataadr(fd, pmd->brush->vel_ramp);
pmd->brush->dm = NULL;
}
}
else if (md->type==eModifierType_Collision) {
CollisionModifierData *collmd = (CollisionModifierData*) md;
/*
// TODO: CollisionModifier should use pointcache
// + have proper reset events before enabling this
collmd->x = newdataadr(fd, collmd->x);
collmd->xnew = newdataadr(fd, collmd->xnew);
collmd->mfaces = newdataadr(fd, collmd->mfaces);
collmd->current_x = MEM_callocN(sizeof(MVert)*collmd->numverts, "current_x");
collmd->current_xnew = MEM_callocN(sizeof(MVert)*collmd->numverts, "current_xnew");
collmd->current_v = MEM_callocN(sizeof(MVert)*collmd->numverts, "current_v");
*/
collmd->x = NULL;
collmd->xnew = NULL;
collmd->current_x = NULL;
collmd->current_xnew = NULL;
collmd->current_v = NULL;
collmd->time_x = collmd->time_xnew = -1000;
collmd->numverts = 0;
collmd->bvhtree = NULL;
collmd->mfaces = NULL;
}
else if (md->type==eModifierType_Surface) {
SurfaceModifierData *surmd = (SurfaceModifierData*) md;
surmd->dm = NULL;
surmd->bvhtree = NULL;
surmd->x = NULL;
surmd->v = NULL;
surmd->numverts = 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]);
}
}
}
else if (md->type==eModifierType_ParticleSystem) {
ParticleSystemModifierData *psmd = (ParticleSystemModifierData*) md;
psmd->dm= NULL;
psmd->psys= newdataadr(fd, psmd->psys);
psmd->flag &= ~eParticleSystemFlag_psys_updated;
psmd->flag |= eParticleSystemFlag_file_loaded;
}
else if (md->type==eModifierType_Explode) {
ExplodeModifierData *psmd = (ExplodeModifierData*) md;
psmd->facepa=NULL;
}
else if (md->type==eModifierType_MeshDeform) {
MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
mmd->bindinfluences= newdataadr(fd, mmd->bindinfluences);
mmd->bindoffsets= newdataadr(fd, mmd->bindoffsets);
mmd->bindcagecos= newdataadr(fd, mmd->bindcagecos);
mmd->dyngrid= newdataadr(fd, mmd->dyngrid);
mmd->dyninfluences= newdataadr(fd, mmd->dyninfluences);
mmd->dynverts= newdataadr(fd, mmd->dynverts);
mmd->bindweights= newdataadr(fd, mmd->bindweights);
mmd->bindcos= newdataadr(fd, mmd->bindcos);
if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
int a;
if (mmd->bindoffsets)
for (a=0; a<mmd->totvert+1; a++)
SWITCH_INT(mmd->bindoffsets[a]);
if (mmd->bindcagecos)
for (a=0; a<mmd->totcagevert*3; a++)
SWITCH_INT(mmd->bindcagecos[a]);
if (mmd->dynverts)
for (a=0; a<mmd->totvert; a++)
SWITCH_INT(mmd->dynverts[a]);
if (mmd->bindweights)
for (a=0; a<mmd->totcagevert*mmd->totvert; a++)
SWITCH_INT(mmd->bindweights[a]);
if (mmd->bindcos)
for (a=0; a<mmd->totcagevert*3; a++)
SWITCH_INT(mmd->bindcos[a]);
}
}
else if (md->type==eModifierType_Ocean) {
OceanModifierData *omd = (OceanModifierData*) md;
omd->oceancache = NULL;
omd->ocean = NULL;
omd->refresh = (MOD_OCEAN_REFRESH_ADD|MOD_OCEAN_REFRESH_RESET|MOD_OCEAN_REFRESH_SIM);
}
else if (md->type==eModifierType_Warp) {
WarpModifierData *tmd = (WarpModifierData *) md;
tmd->curfalloff= newdataadr(fd, tmd->curfalloff);
if (tmd->curfalloff)
direct_link_curvemapping(fd, tmd->curfalloff);
}
else if (md->type==eModifierType_WeightVGEdit) {
WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
wmd->cmap_curve = newdataadr(fd, wmd->cmap_curve);
if (wmd->cmap_curve)
direct_link_curvemapping(fd, wmd->cmap_curve);
}
}
}
static void direct_link_object(FileData *fd, Object *ob)
{
PartEff *paf;
bProperty *prop;
bSensor *sens;
bController *cont;
bActuator *act;
/* weak weak... this was only meant as draw flag, now is used in give_base_to_objects too */
ob->flag &= ~OB_FROMGROUP;
/* loading saved files with editmode enabled works, but for undo we like
* to stay in object mode during undo presses so keep editmode disabled */
if (fd->memfile)
ob->mode &= ~(OB_MODE_EDIT|OB_MODE_PARTICLE_EDIT);
ob->disp.first=ob->disp.last= NULL;
ob->adt= newdataadr(fd, ob->adt);
direct_link_animdata(fd, ob->adt);
ob->pose= newdataadr(fd, ob->pose);
direct_link_pose(fd, ob->pose);
ob->mpath= newdataadr(fd, ob->mpath);
if (ob->mpath)
direct_link_motionpath(fd, ob->mpath);
link_list(fd, &ob->defbase);
// XXX depreceated - old animation system <<<
direct_link_nlastrips(fd, &ob->nlastrips);
link_list(fd, &ob->constraintChannels);
// >>> XXX depreceated - old animation system
ob->mat= newdataadr(fd, ob->mat);
test_pointer_array(fd, (void **)&ob->mat);
ob->matbits= newdataadr(fd, ob->matbits);
/* 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);
direct_link_partdeflect(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->scratch= NULL;
/* although not used anymore */
/* still have to be loaded to be compatible with old files */
sb->keys= newdataadr(fd, sb->keys);
test_pointer_array(fd, (void **)&sb->keys);
if (sb->keys) {
int a;
for (a=0; a<sb->totkey; a++) {
sb->keys[a]= newdataadr(fd, sb->keys[a]);
}
}
sb->effector_weights = newdataadr(fd, sb->effector_weights);
if (!sb->effector_weights)
sb->effector_weights = BKE_add_effector_weights(NULL);
direct_link_pointcache_list(fd, &sb->ptcaches, &sb->pointcache, 0);
}
ob->bsoft= newdataadr(fd, ob->bsoft);
ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */
link_list(fd, &ob->particlesystem);
direct_link_particlesystems(fd, &ob->particlesystem);
link_list(fd, &ob->prop);
prop= ob->prop.first;
while (prop) {
prop->poin= newdataadr(fd, prop->poin);
if (prop->poin==NULL) 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);
if (ob->init_state) {
/* if a known first state is specified, set it so that the game will start ok */
ob->state = ob->init_state;
}
else if (!ob->state) {
ob->state = 1;
}
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);
if (cont->state_mask == 0)
cont->state_mask = 1;
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 freed, regardless of version.
*/
copy_v3_v3(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);
modifier_unique_name(&ob->modifiers, (ModifierData*)hmd);
MEM_freeN(hook);
}
ob->customdata_mask= 0;
ob->bb= NULL;
ob->derivedDeform= NULL;
ob->derivedFinal= NULL;
ob->gpulamp.first= ob->gpulamp.last= NULL;
link_list(fd, &ob->pc_ids);
/* in case this value changes in future, clamp else we get undefined behavior */
CLAMP(ob->rotmode, ROT_MODE_MIN, ROT_MODE_MAX);
if (ob->sculpt) {
ob->sculpt= MEM_callocN(sizeof(SculptSession), "reload sculpt session");
}
}
/* ************ READ SCENE ***************** */
/* patch for missing scene IDs, can't be in do-versions */
static void composite_patch(bNodeTree *ntree, Scene *scene)
{
bNode *node;
for (node= ntree->nodes.first; node; node= node->next)
if (node->id==NULL && ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE))
node->id= &scene->id;
}
static void link_paint(FileData *fd, Scene *sce, Paint *p)
{
if (p) {
p->brush= newlibadr_us(fd, sce->id.lib, p->brush);
p->paint_cursor= NULL;
}
}
static void lib_link_scene(FileData *fd, Main *main)
{
Scene *sce;
Base *base, *next;
Sequence *seq;
SceneRenderLayer *srl;
TimeMarker *marker;
sce= main->scene.first;
while (sce) {
if (sce->id.flag & LIB_NEEDLINK) {
/* Link ID Properties -- and copy this comment EXACTLY for easy finding
* of library blocks that implement this.*/
if (sce->id.properties) IDP_LibLinkProperty(sce->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
if (sce->adt) lib_link_animdata(fd, &sce->id, sce->adt);
lib_link_keyingsets(fd, &sce->id, &sce->keyingsets);
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->gpd= newlibadr_us(fd, sce->id.lib, sce->gpd);
link_paint(fd, sce, &sce->toolsettings->sculpt->paint);
link_paint(fd, sce, &sce->toolsettings->vpaint->paint);
link_paint(fd, sce, &sce->toolsettings->wpaint->paint);
link_paint(fd, sce, &sce->toolsettings->imapaint.paint);
link_paint(fd, sce, &sce->toolsettings->uvsculpt->paint);
sce->toolsettings->skgen_template = newlibadr(fd, sce->id.lib, sce->toolsettings->skgen_template);
for (base= sce->base.first; base; base= next) {
next= base->next;
/* base->object= newlibadr_us(fd, sce->id.lib, base->object); */
base->object= newlibadr_us(fd, sce->id.lib, base->object);
if (base->object==NULL) {
BKE_reportf_wrap(fd->reports, RPT_ERROR,
"LIB ERROR: Object lost from scene:'%s\'\n",
sce->id.name+2);
BLI_remlink(&sce->base, base);
if (base==sce->basact) sce->basact= NULL;
MEM_freeN(base);
}
}
SEQ_BEGIN (sce->ed, seq) {
if (seq->ipo) seq->ipo= newlibadr_us(fd, sce->id.lib, seq->ipo);
seq->scene_sound = NULL;
if (seq->scene) {
seq->scene= newlibadr(fd, sce->id.lib, seq->scene);
if (seq->scene) {
seq->scene_sound = sound_scene_add_scene_sound_defaults(sce, seq);
}
}
if (seq->clip) {
seq->clip = newlibadr(fd, sce->id.lib, seq->clip);
seq->clip->id.us++;
}
if (seq->scene_camera) seq->scene_camera= newlibadr(fd, sce->id.lib, seq->scene_camera);
if (seq->sound) {
seq->scene_sound = NULL;
if (seq->type == SEQ_HD_SOUND)
seq->type = SEQ_SOUND;
else
seq->sound= newlibadr(fd, sce->id.lib, seq->sound);
if (seq->sound) {
seq->sound->id.us++;
seq->scene_sound = sound_add_scene_sound_defaults(sce, seq);
}
}
seq->anim= NULL;
}
SEQ_END
#ifdef DURIAN_CAMERA_SWITCH
for (marker= sce->markers.first; marker; marker= marker->next) {
if (marker->camera) {
marker->camera= newlibadr(fd, sce->id.lib, marker->camera);
}
}
#else
(void)marker;
#endif
seq_update_muting(sce->ed);
seq_update_sound_bounds_all(sce);
if (sce->nodetree) {
lib_link_ntree(fd, &sce->id, sce->nodetree);
composite_patch(sce->nodetree, sce);
}
for (srl= sce->r.layers.first; srl; srl= srl->next) {
srl->mat_override= newlibadr_us(fd, sce->id.lib, srl->mat_override);
srl->light_override= newlibadr_us(fd, sce->id.lib, srl->light_override);
}
/*Game Settings: Dome Warp Text*/
sce->gm.dome.warptext= newlibadr(fd, sce->id.lib, sce->gm.dome.warptext);
/* Motion Tracking */
sce->clip= newlibadr_us(fd, sce->id.lib, sce->clip);
sce->id.flag -= LIB_NEEDLINK;
}
sce= sce->id.next;
}
}
static void link_recurs_seq(FileData *fd, ListBase *lb)
{
Sequence *seq;
link_list(fd, lb);
for (seq=lb->first; seq; seq=seq->next)
if (seq->seqbase.first)
link_recurs_seq(fd, &seq->seqbase);
}
static void direct_link_paint(FileData *fd, Paint **paint)
{
/* TODO. is this needed */
(*paint)= newdataadr(fd, (*paint));
}
static void direct_link_scene(FileData *fd, Scene *sce)
{
Editing *ed;
Sequence *seq;
MetaStack *ms;
sce->theDag = NULL;
sce->dagisvalid = 0;
sce->obedit= NULL;
sce->stats= NULL;
sce->fps_info= NULL;
sce->customdata_mask_modal= 0;
sce->lay_updated = 0;
sound_create_scene(sce);
/* set users to one by default, not in lib-link, this will increase it for compo nodes */
sce->id.us= 1;
link_list(fd, &(sce->base));
sce->adt= newdataadr(fd, sce->adt);
direct_link_animdata(fd, sce->adt);
link_list(fd, &sce->keyingsets);
direct_link_keyingsets(fd, &sce->keyingsets);
sce->basact= newdataadr(fd, sce->basact);
sce->toolsettings= newdataadr(fd, sce->toolsettings);
if (sce->toolsettings) {
direct_link_paint(fd, (Paint**)&sce->toolsettings->sculpt);
direct_link_paint(fd, (Paint**)&sce->toolsettings->vpaint);
direct_link_paint(fd, (Paint**)&sce->toolsettings->wpaint);
direct_link_paint(fd, (Paint**)&sce->toolsettings->uvsculpt);
sce->toolsettings->imapaint.paintcursor= NULL;
sce->toolsettings->particle.paintcursor= NULL;
}
if (sce->ed) {
ListBase *old_seqbasep= &((Editing *)sce->ed)->seqbase;
ed= sce->ed= newdataadr(fd, sce->ed);
ed->act_seq= newdataadr(fd, ed->act_seq);
/* recursive link sequences, lb will be correctly initialized */
link_recurs_seq(fd, &ed->seqbase);
SEQ_BEGIN (ed, seq) {
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==NULL) seq->seq3= seq->seq2;
seq->plugin= newdataadr(fd, seq->plugin);
seq->effectdata= newdataadr(fd, seq->effectdata);
if (seq->type & SEQ_EFFECT)
seq->flag |= SEQ_EFFECT_NOT_LOADED;
if (seq->type == SEQ_SPEED) {
SpeedControlVars *s= seq->effectdata;
s->frameMap= NULL;
}
seq->strip= newdataadr(fd, seq->strip);
if (seq->strip && seq->strip->done==0) {
seq->strip->done= 1;
if (seq->type == SEQ_IMAGE ||
seq->type == SEQ_MOVIE ||
seq->type == SEQ_RAM_SOUND ||
seq->type == SEQ_HD_SOUND) {
seq->strip->stripdata = newdataadr(
fd, seq->strip->stripdata);
}
else {
seq->strip->stripdata = NULL;
}
if (seq->flag & SEQ_USE_CROP) {
seq->strip->crop = newdataadr(
fd, seq->strip->crop);
}
else {
seq->strip->crop = NULL;
}
if (seq->flag & SEQ_USE_TRANSFORM) {
seq->strip->transform = newdataadr(
fd, seq->strip->transform);
}
else {
seq->strip->transform = NULL;
}
if (seq->flag & SEQ_USE_PROXY) {
seq->strip->proxy = newdataadr(
fd, seq->strip->proxy);
seq->strip->proxy->anim = NULL;
}
else {
seq->strip->proxy = NULL;
}
if (seq->flag & SEQ_USE_COLOR_BALANCE) {
seq->strip->color_balance = newdataadr(
fd, seq->strip->color_balance);
}
else {
seq->strip->color_balance = NULL;
}
if (seq->strip->color_balance) {
// seq->strip->color_balance->gui = 0; // XXX - peter, is this relevant in 2.5?
}
}
}
SEQ_END
/* link metastack, slight abuse of structs here, have to restore pointer to internal part in struct */
{
Sequence temp;
char *poin;
intptr_t offset;
offset= ((intptr_t)&(temp.seqbase)) - ((intptr_t)&temp);
/* root pointer */
if (ed->seqbasep == old_seqbasep) {
ed->seqbasep= &ed->seqbase;
}
else {
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);
if (ms->oldbasep == old_seqbasep)
ms->oldbasep= &ed->seqbase;
else {
poin= (char *)ms->oldbasep;
poin -= offset;
poin= newdataadr(fd, poin);
if (poin) ms->oldbasep= (ListBase *)(poin+offset);
else ms->oldbasep= &ed->seqbase;
}
}
}
}
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);
}
if (sce->r.ffcodecdata.properties) {
sce->r.ffcodecdata.properties = newdataadr(
fd, sce->r.ffcodecdata.properties);
if (sce->r.ffcodecdata.properties) {
IDP_DirectLinkProperty(
sce->r.ffcodecdata.properties,
(fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
}
link_list(fd, &(sce->markers));
link_list(fd, &(sce->transform_spaces));
link_list(fd, &(sce->r.layers));
sce->nodetree= newdataadr(fd, sce->nodetree);
if (sce->nodetree)
direct_link_nodetree(fd, sce->nodetree);
}
/* ************ READ WM ***************** */
static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
{
wmWindow *win;
wm->id.us= 1;
link_list(fd, &(wm->windows));
for (win= wm->windows.first; win; win= win->next) {
win->ghostwin= NULL;
win->eventstate= NULL;
win->curswin= NULL;
win->tweak= NULL;
win->queue.first= win->queue.last= NULL;
win->handlers.first= win->handlers.last= NULL;
win->modalhandlers.first= win->modalhandlers.last= NULL;
win->subwindows.first= win->subwindows.last= NULL;
win->gesture.first= win->gesture.last= NULL;
win->drawdata= NULL;
win->drawmethod= -1;
win->drawfail= 0;
}
wm->timers.first= wm->timers.last= NULL;
wm->operators.first= wm->operators.last= NULL;
wm->paintcursors.first= wm->paintcursors.last= NULL;
wm->queue.first= wm->queue.last= NULL;
BKE_reports_init(&wm->reports, RPT_STORE);
wm->keyconfigs.first= wm->keyconfigs.last= NULL;
wm->defaultconf= NULL;
wm->addonconf= NULL;
wm->userconf= NULL;
wm->jobs.first= wm->jobs.last= NULL;
wm->drags.first= wm->drags.last= NULL;
wm->windrawable= NULL;
wm->winactive= NULL;
wm->initialized= 0;
wm->op_undo_depth= 0;
}
static void lib_link_windowmanager(FileData *fd, Main *main)
{
wmWindowManager *wm;
wmWindow *win;
for (wm= main->wm.first; wm; wm= wm->id.next) {
if (wm->id.flag & LIB_NEEDLINK) {
for (win= wm->windows.first; win; win= win->next)
win->screen= newlibadr(fd, NULL, win->screen);
wm->id.flag -= LIB_NEEDLINK;
}
}
}
/* ****************** READ GREASE PENCIL ***************** */
/* relinks grease-pencil data - used for direct_link and old file linkage */
static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
{
bGPDlayer *gpl;
bGPDframe *gpf;
bGPDstroke *gps;
/* we must firstly have some grease-pencil data to link! */
if (gpd == NULL)
return;
/* relink layers */
link_list(fd, &gpd->layers);
for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
/* relink frames */
link_list(fd, &gpl->frames);
gpl->actframe= newdataadr(fd, gpl->actframe);
for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
/* relink strokes (and their points) */
link_list(fd, &gpf->strokes);
for (gps= gpf->strokes.first; gps; gps= gps->next) {
gps->points= newdataadr(fd, gps->points);
}
}
}
}
/* ****************** READ SCREEN ***************** */
static void butspace_version_132(SpaceButs *buts)
{
buts->v2d.tot.xmin = 0.0f;
buts->v2d.tot.ymin = 0.0f;
buts->v2d.tot.xmax = 1279.0f;
buts->v2d.tot.ymax = 228.0f;
buts->v2d.min[0]= 256.0f;
buts->v2d.min[1]= 42.0f;
buts->v2d.max[0]= 2048.0f;
buts->v2d.max[1]= 450.0f;
buts->v2d.minzoom= 0.5f;
buts->v2d.maxzoom= 1.21f;
buts->v2d.scroll= 0;
buts->v2d.keepzoom= 1;
buts->v2d.keeptot= 1;
}
/* 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;
for (sc= main->screen.first; sc; sc= sc->id.next) {
if (sc->id.flag & LIB_NEEDLINK) {
sc->id.us= 1;
sc->scene= newlibadr(fd, sc->id.lib, sc->scene);
sc->animtimer= NULL; /* saved in rare cases */
sa= sc->areabase.first;
while (sa) {
SpaceLink *sl;
sa->full= newlibadr(fd, sc->id.lib, sa->full);
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D*) sl;
BGpic *bgpic = NULL;
v3d->camera= newlibadr(fd, sc->id.lib, v3d->camera);
v3d->ob_centre= newlibadr(fd, sc->id.lib, v3d->ob_centre);
/* should be do_versions but not easy adding into the listbase */
if (v3d->bgpic) {
v3d->bgpic= newlibadr(fd, sc->id.lib, v3d->bgpic);
BLI_addtail(&v3d->bgpicbase, bgpic);
v3d->bgpic= NULL;
}
for (bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next) {
bgpic->ima= newlibadr_us(fd, sc->id.lib, bgpic->ima);
bgpic->clip= newlibadr_us(fd, sc->id.lib, bgpic->clip);
}
if (v3d->localvd) {
v3d->localvd->camera= newlibadr(fd, sc->id.lib, v3d->localvd->camera);
}
}
else if (sl->spacetype==SPACE_IPO) {
SpaceIpo *sipo= (SpaceIpo *)sl;
bDopeSheet *ads= sipo->ads;
if (ads) {
ads->source= newlibadr(fd, sc->id.lib, ads->source);
ads->filter_grp= newlibadr(fd, sc->id.lib, ads->filter_grp);
}
}
else if (sl->spacetype==SPACE_BUTS) {
SpaceButs *sbuts= (SpaceButs *)sl;
sbuts->pinid= newlibadr(fd, sc->id.lib, sbuts->pinid);
sbuts->mainbo= sbuts->mainb;
sbuts->mainbuser= sbuts->mainb;
if (main->versionfile<132)
butspace_version_132(sbuts);
}
else if (sl->spacetype==SPACE_FILE) {
SpaceFile *sfile= (SpaceFile *)sl;
sfile->files= NULL;
sfile->op= NULL;
sfile->layout= NULL;
sfile->folders_prev= NULL;
sfile->folders_next= NULL;
}
else if (sl->spacetype==SPACE_ACTION) {
SpaceAction *saction= (SpaceAction *)sl;
bDopeSheet *ads= &saction->ads;
if (ads) {
ads->source= newlibadr(fd, sc->id.lib, ads->source);
ads->filter_grp= newlibadr(fd, sc->id.lib, ads->filter_grp);
}
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);
/* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
* so fingers crossed this works fine!
*/
sima->gpd= newlibadr_us(fd, sc->id.lib, sima->gpd);
}
else if (sl->spacetype==SPACE_NLA) {
SpaceNla *snla= (SpaceNla *)sl;
bDopeSheet *ads= snla->ads;
if (ads) {
ads->source= newlibadr(fd, sc->id.lib, ads->source);
ads->filter_grp= newlibadr(fd, sc->id.lib, ads->filter_grp);
}
}
else if (sl->spacetype==SPACE_TEXT) {
SpaceText *st= (SpaceText *)sl;
st->text= newlibadr(fd, sc->id.lib, st->text);
st->drawcache= NULL;
}
else if (sl->spacetype==SPACE_SCRIPT) {
SpaceScript *scpt= (SpaceScript *)sl;
/*scpt->script = NULL; - 2.45 set to null, better re-run the script */
if (scpt->script) {
scpt->script= newlibadr(fd, sc->id.lib, scpt->script);
if (scpt->script) {
SCRIPT_SET_NULL(scpt->script);
}
}
}
else if (sl->spacetype==SPACE_OUTLINER) {
SpaceOops *so= (SpaceOops *)sl;
TreeStoreElem *tselem;
int a;
so->tree.first= so->tree.last= NULL;
so->search_tse.id= newlibadr(fd, NULL, so->search_tse.id);
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_NODE) {
SpaceNode *snode= (SpaceNode *)sl;
snode->id= newlibadr(fd, sc->id.lib, snode->id);
snode->edittree= NULL;
if (ELEM3(snode->treetype, NTREE_COMPOSIT, NTREE_SHADER, NTREE_TEXTURE)) {
/* internal data, a bit patchy */
snode->nodetree= NULL;
if (snode->id) {
if (GS(snode->id->name)==ID_MA)
snode->nodetree= ((Material *)snode->id)->nodetree;
else if (GS(snode->id->name)==ID_WO)
snode->nodetree= ((World *)snode->id)->nodetree;
else if (GS(snode->id->name)==ID_LA)
snode->nodetree= ((Lamp *)snode->id)->nodetree;
else if (GS(snode->id->name)==ID_SCE)
snode->nodetree= ((Scene *)snode->id)->nodetree;
else if (GS(snode->id->name)==ID_TE)
snode->nodetree= ((Tex *)snode->id)->nodetree;
}
}
else {
snode->nodetree= newlibadr_us(fd, sc->id.lib, snode->nodetree);
}
snode->linkdrag.first = snode->linkdrag.last = NULL;
}
else if (sl->spacetype==SPACE_CLIP) {
SpaceClip *sclip= (SpaceClip *)sl;
sclip->clip= newlibadr_us(fd, sc->id.lib, sclip->clip);
sclip->scopes.track_preview = NULL;
sclip->scopes.ok = 0;
}
}
sa= sa->next;
}
sc->id.flag -= LIB_NEEDLINK;
}
}
}
/* Only for undo files, or to restore a screen after reading without UI... */
static void *restore_pointer_by_name(Main *mainp, ID *id, int user)
{
if (id) {
ListBase *lb= which_libbase(mainp, GS(id->name));
if (lb) { // there's still risk of checking corrupt mem (freed Ids in oops)
ID *idn= lb->first;
char *name= id->name+2;
while (idn) {
if (idn->name[2]==name[0] && strcmp(idn->name+2, name)==0) {
if (idn->lib==id->lib) {
if (user && idn->us==0) idn->us++;
break;
}
}
idn= idn->next;
}
return idn;
}
}
return NULL;
}
static int lib_link_seq_clipboard_cb(Sequence *seq, void *arg_pt)
{
Main *newmain = (Main *)arg_pt;
if (seq->sound) {
seq->sound = restore_pointer_by_name(newmain, (ID *)seq->sound, 0);
seq->sound->id.us++;
}
if (seq->scene)
seq->scene = restore_pointer_by_name(newmain, (ID *)seq->scene, 1);
if (seq->scene_camera)
seq->scene_camera = restore_pointer_by_name(newmain, (ID *)seq->scene_camera, 1);
return 1;
}
static void lib_link_clipboard_restore(Main *newmain)
{
/* update IDs stored in sequencer clipboard */
seqbase_recursive_apply(&seqbase_clipboard, lib_link_seq_clipboard_cb, newmain);
}
/* called from kernel/blender.c */
/* used to link a file (without UI) to the current UI */
/* note that it assumes the old pointers in UI are still valid, so old Main is not freed */
void lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene)
{
wmWindow *win;
wmWindowManager *wm;
bScreen *sc;
ScrArea *sa;
/* first windowmanager */
for (wm= newmain->wm.first; wm; wm= wm->id.next) {
for (win= wm->windows.first; win; win= win->next) {
win->screen= restore_pointer_by_name(newmain, (ID *)win->screen, 1);
if (win->screen==NULL)
win->screen= curscreen;
win->screen->winid= win->winid;
}
}
for (sc= newmain->screen.first; sc; sc= sc->id.next) {
Scene *oldscene= sc->scene;
sc->scene= restore_pointer_by_name(newmain, (ID *)sc->scene, 1);
if (sc->scene==NULL)
sc->scene= curscene;
/* keep cursor location through undo */
copy_v3_v3(sc->scene->cursor, oldscene->cursor);
sa= sc->areabase.first;
while (sa) {
SpaceLink *sl;
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D*) sl;
BGpic *bgpic;
ARegion *ar;
if (v3d->scenelock)
v3d->camera= NULL; /* always get from scene */
else
v3d->camera= restore_pointer_by_name(newmain, (ID *)v3d->camera, 1);
if (v3d->camera==NULL)
v3d->camera= sc->scene->camera;
v3d->ob_centre= restore_pointer_by_name(newmain, (ID *)v3d->ob_centre, 1);
for (bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next) {
bgpic->ima= restore_pointer_by_name(newmain, (ID *)bgpic->ima, 1);
bgpic->clip= restore_pointer_by_name(newmain, (ID *)bgpic->clip, 1);
}
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 */
/* XXX regionlocalview ?
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;
}
*/
}
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;
/* free render engines for now */
for (ar= sa->regionbase.first; ar; ar= ar->next) {
RegionView3D *rv3d= ar->regiondata;
if (rv3d && rv3d->render_engine) {
RE_engine_free(rv3d->render_engine);
rv3d->render_engine= NULL;
}
}
}
else if (sl->spacetype==SPACE_IPO) {
SpaceIpo *sipo= (SpaceIpo *)sl;
bDopeSheet *ads= sipo->ads;
if (ads) {
ads->source= restore_pointer_by_name(newmain, (ID *)ads->source, 1);
if (ads->filter_grp)
ads->filter_grp= restore_pointer_by_name(newmain, (ID *)ads->filter_grp, 0);
}
}
else if (sl->spacetype==SPACE_BUTS) {
SpaceButs *sbuts= (SpaceButs *)sl;
sbuts->pinid = restore_pointer_by_name(newmain, sbuts->pinid, 0);
//XXX if (sbuts->ri) sbuts->ri->curtile = 0;
}
else if (sl->spacetype==SPACE_FILE) {
SpaceFile *sfile= (SpaceFile *)sl;
sfile->op= NULL;
}
else if (sl->spacetype==SPACE_ACTION) {
SpaceAction *saction= (SpaceAction *)sl;
saction->action = restore_pointer_by_name(newmain, (ID *)saction->action, 1);
saction->ads.source= restore_pointer_by_name(newmain, (ID *)saction->ads.source, 1);
if (saction->ads.filter_grp)
saction->ads.filter_grp= restore_pointer_by_name(newmain, (ID *)saction->ads.filter_grp, 0);
}
else if (sl->spacetype==SPACE_IMAGE) {
SpaceImage *sima= (SpaceImage *)sl;
sima->image= restore_pointer_by_name(newmain, (ID *)sima->image, 1);
/* this will be freed, not worth attempting to find same scene,
* since it gets initialized later */
sima->iuser.scene = NULL;
sima->scopes.waveform_1 = NULL;
sima->scopes.waveform_2 = NULL;
sima->scopes.waveform_3 = NULL;
sima->scopes.vecscope = NULL;
sima->scopes.ok = 0;
/* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
* so assume that here we're doing for undo only...
*/
sima->gpd= restore_pointer_by_name(newmain, (ID *)sima->gpd, 1);
}
else if (sl->spacetype==SPACE_NLA) {
SpaceNla *snla= (SpaceNla *)sl;
bDopeSheet *ads= snla->ads;
if (ads) {
ads->source= restore_pointer_by_name(newmain, (ID *)ads->source, 1);
if (ads->filter_grp)
ads->filter_grp= restore_pointer_by_name(newmain, (ID *)ads->filter_grp, 0);
}
}
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 *scpt= (SpaceScript *)sl;
scpt->script= restore_pointer_by_name(newmain, (ID *)scpt->script, 1);
/*sc->script = NULL; - 2.45 set to null, better re-run the script */
if (scpt->script) {
SCRIPT_SET_NULL(scpt->script);
}
}
else if (sl->spacetype==SPACE_OUTLINER) {
SpaceOops *so= (SpaceOops *)sl;
int a;
so->search_tse.id= restore_pointer_by_name(newmain, so->search_tse.id, 0);
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_NODE) {
SpaceNode *snode= (SpaceNode *)sl;
snode->id= restore_pointer_by_name(newmain, snode->id, 1);
snode->edittree= NULL;
if (ELEM3(snode->treetype, NTREE_COMPOSIT, NTREE_SHADER, NTREE_TEXTURE)) {
snode->nodetree= NULL;
if (snode->id) {
if (GS(snode->id->name)==ID_MA)
snode->nodetree= ((Material *)snode->id)->nodetree;
else if (GS(snode->id->name)==ID_SCE)
snode->nodetree= ((Scene *)snode->id)->nodetree;
else if (GS(snode->id->name)==ID_TE)
snode->nodetree= ((Tex *)snode->id)->nodetree;
}
}
else {
snode->nodetree= restore_pointer_by_name(newmain, &snode->nodetree->id, 1);
}
}
else if (sl->spacetype==SPACE_CLIP) {
SpaceClip *sclip= (SpaceClip *)sl;
sclip->clip= restore_pointer_by_name(newmain, (ID *)sclip->clip, 1);
sclip->scopes.ok = 0;
}
}
sa= sa->next;
}
}
/* update IDs stored in all possible clipboards */
lib_link_clipboard_restore(newmain);
}
static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
{
Panel *pa;
link_list(fd, &(ar->panels));
for (pa= ar->panels.first; pa; pa=pa->next) {
pa->paneltab= newdataadr(fd, pa->paneltab);
pa->runtime_flag= 0;
pa->activedata= NULL;
pa->type= NULL;
}
ar->regiondata= newdataadr(fd, ar->regiondata);
if (ar->regiondata) {
if (spacetype==SPACE_VIEW3D) {
RegionView3D *rv3d= ar->regiondata;
rv3d->localvd= newdataadr(fd, rv3d->localvd);
rv3d->clipbb= newdataadr(fd, rv3d->clipbb);
rv3d->depths= NULL;
rv3d->ri= NULL;
rv3d->render_engine= NULL;
rv3d->sms= NULL;
rv3d->smooth_timer= NULL;
}
}
ar->v2d.tab_offset= NULL;
ar->v2d.tab_num= 0;
ar->v2d.tab_cur= 0;
ar->handlers.first= ar->handlers.last= NULL;
ar->uiblocks.first= ar->uiblocks.last= NULL;
ar->headerstr= NULL;
ar->swinid= 0;
ar->type= NULL;
ar->swap= 0;
ar->do_draw= 0;
memset(&ar->drawrct, 0, sizeof(ar->drawrct));
}
/* for the saved 2.50 files without regiondata */
/* and as patch for 2.48 and older */
static void view3d_split_250(View3D *v3d, ListBase *regions)
{
ARegion *ar;
for (ar= regions->first; ar; ar= ar->next) {
if (ar->regiontype==RGN_TYPE_WINDOW && ar->regiondata==NULL) {
RegionView3D *rv3d;
rv3d= ar->regiondata= MEM_callocN(sizeof(RegionView3D), "region v3d patch");
rv3d->persp= (char)v3d->persp;
rv3d->view= (char)v3d->view;
rv3d->dist= v3d->dist;
copy_v3_v3(rv3d->ofs, v3d->ofs);
copy_qt_qt(rv3d->viewquat, v3d->viewquat);
}
}
/* this was not initialized correct always */
if (v3d->twtype == 0)
v3d->twtype= V3D_MANIP_TRANSLATE;
}
static void direct_link_screen(FileData *fd, bScreen *sc)
{
ScrArea *sa;
ScrVert *sv;
ScrEdge *se;
int a;
link_list(fd, &(sc->vertbase));
link_list(fd, &(sc->edgebase));
link_list(fd, &(sc->areabase));
sc->regionbase.first= sc->regionbase.last= NULL;
sc->context= NULL;
sc->mainwin= sc->subwinactive= 0; /* indices */
sc->swap= 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 */
for (se= sc->edgebase.first; se; se= se->next) {
se->v1= newdataadr(fd, se->v1);
se->v2= newdataadr(fd, se->v2);
if ( (intptr_t)se->v1 > (intptr_t)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;
}
}
/* areas */
for (sa= sc->areabase.first; sa; sa= sa->next) {
SpaceLink *sl;
ARegion *ar;
link_list(fd, &(sa->spacedata));
link_list(fd, &(sa->regionbase));
sa->handlers.first= sa->handlers.last= NULL;
sa->type= NULL; /* spacetype callbacks */
for (ar= sa->regionbase.first; ar; ar= ar->next)
direct_link_region(fd, ar, sa->spacetype);
/* accident can happen when read/save new file with older version */
/* 2.50: we now always add spacedata for info */
if (sa->spacedata.first==NULL) {
SpaceInfo *sinfo= MEM_callocN(sizeof(SpaceInfo), "spaceinfo");
sa->spacetype= sinfo->spacetype= SPACE_INFO;
BLI_addtail(&sa->spacedata, sinfo);
}
/* add local view3d too */
else if (sa->spacetype==SPACE_VIEW3D)
view3d_split_250(sa->spacedata.first, &sa->regionbase);
for (sl= sa->spacedata.first; sl; sl= sl->next) {
link_list(fd, &(sl->regionbase));
for (ar= sl->regionbase.first; ar; ar= ar->next)
direct_link_region(fd, ar, sl->spacetype);
if (sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D*) sl;
BGpic *bgpic;
v3d->flag |= V3D_INVALID_BACKBUF;
link_list(fd, &(v3d->bgpicbase));
/* should be do_versions except this doesnt fit well there */
if (v3d->bgpic) {
bgpic= newdataadr(fd, v3d->bgpic);
BLI_addtail(&v3d->bgpicbase, bgpic);
v3d->bgpic= NULL;
}
for (bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next)
bgpic->iuser.ok= 1;
if (v3d->gpd) {
v3d->gpd= newdataadr(fd, v3d->gpd);
direct_link_gpencil(fd, v3d->gpd);
}
v3d->localvd= newdataadr(fd, v3d->localvd);
v3d->afterdraw_transp.first= v3d->afterdraw_transp.last= NULL;
v3d->afterdraw_xray.first= v3d->afterdraw_xray.last= NULL;
v3d->afterdraw_xraytransp.first= v3d->afterdraw_xraytransp.last= NULL;
v3d->properties_storage= NULL;
/* render can be quite heavy, set to wire on load */
if (v3d->drawtype == OB_RENDER)
v3d->drawtype = OB_WIRE;
view3d_split_250(v3d, &sl->regionbase);
}
else if (sl->spacetype==SPACE_IPO) {
SpaceIpo *sipo= (SpaceIpo*)sl;
sipo->ads= newdataadr(fd, sipo->ads);
sipo->ghostCurves.first= sipo->ghostCurves.last= NULL;
}
else if (sl->spacetype==SPACE_NLA) {
SpaceNla *snla= (SpaceNla*)sl;
snla->ads= newdataadr(fd, snla->ads);
}
else if (sl->spacetype==SPACE_OUTLINER) {
SpaceOops *soops= (SpaceOops*) sl;
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
}
}
else if (sl->spacetype==SPACE_IMAGE) {
SpaceImage *sima= (SpaceImage *)sl;
sima->cumap= newdataadr(fd, sima->cumap);
if (sima->cumap)
direct_link_curvemapping(fd, sima->cumap);
sima->iuser.scene= NULL;
sima->iuser.ok= 1;
sima->scopes.waveform_1 = NULL;
sima->scopes.waveform_2 = NULL;
sima->scopes.waveform_3 = NULL;
sima->scopes.vecscope = NULL;
sima->scopes.ok = 0;
/* WARNING: gpencil data is no longer stored directly in sima after 2.5
* so sacrifice a few old files for now to avoid crashes with new files!
* committed: r28002 */
#if 0
sima->gpd= newdataadr(fd, sima->gpd);
if (sima->gpd)
direct_link_gpencil(fd, sima->gpd);
#endif
}
else if (sl->spacetype==SPACE_NODE) {
SpaceNode *snode= (SpaceNode *)sl;
if (snode->gpd) {
snode->gpd= newdataadr(fd, snode->gpd);
direct_link_gpencil(fd, snode->gpd);
}
}
else if (sl->spacetype==SPACE_TIME) {
SpaceTime *stime= (SpaceTime *)sl;
stime->caches.first= stime->caches.last= NULL;
}
else if (sl->spacetype==SPACE_LOGIC) {
SpaceLogic *slogic= (SpaceLogic *)sl;
if (slogic->gpd) {
slogic->gpd= newdataadr(fd, slogic->gpd);
direct_link_gpencil(fd, slogic->gpd);
}
}
else if (sl->spacetype==SPACE_SEQ) {
SpaceSeq *sseq= (SpaceSeq *)sl;
if (sseq->gpd) {
sseq->gpd= newdataadr(fd, sseq->gpd);
direct_link_gpencil(fd, sseq->gpd);
}
}
else if (sl->spacetype==SPACE_BUTS) {
SpaceButs *sbuts= (SpaceButs *)sl;
sbuts->path= NULL;
sbuts->texuser= NULL;
}
else if (sl->spacetype==SPACE_CONSOLE) {
SpaceConsole *sconsole= (SpaceConsole *)sl;
ConsoleLine *cl, *cl_next;
link_list(fd, &sconsole->scrollback);
link_list(fd, &sconsole->history);
//for (cl= sconsole->scrollback.first; cl; cl= cl->next)
// cl->line= newdataadr(fd, cl->line);
/* comma expressions, (e.g. expr1, expr2, expr3) evalutate each expression,
* from left to right. the right-most expression sets the result of the comma
* expression as a whole*/
for (cl= sconsole->history.first; cl; cl= cl_next) {
cl_next= cl->next;
cl->line= newdataadr(fd, cl->line);
if (cl->line) {
/* the allocted length is not written, so reset here */
cl->len_alloc= cl->len + 1;
}
else {
BLI_remlink(&sconsole->history, cl);
MEM_freeN(cl);
}
}
}
else if (sl->spacetype==SPACE_FILE) {
SpaceFile *sfile= (SpaceFile *)sl;
/* this sort of info is probably irrelevant for reloading...
* plus, it isn't saved to files yet!
*/
sfile->folders_prev= sfile->folders_next= NULL;
sfile->files= NULL;
sfile->layout= NULL;
sfile->op= NULL;
sfile->params= newdataadr(fd, sfile->params);
}
}
sa->actionzones.first= sa->actionzones.last= NULL;
sa->v1= newdataadr(fd, sa->v1);
sa->v2= newdataadr(fd, sa->v2);
sa->v3= newdataadr(fd, sa->v3);
sa->v4= newdataadr(fd, sa->v4);
}
}
/* ********** READ LIBRARY *************** */
static void direct_link_library(FileData *fd, Library *lib, Main *main)
{
Main *newmain;
for (newmain= fd->mainlist.first; newmain; newmain= newmain->next) {
if (newmain->curlib) {
if (BLI_path_cmp(newmain->curlib->filepath, lib->filepath) == 0) {
BKE_reportf_wrap(fd->reports, RPT_WARNING,
"Library '%s', '%s' had multiple instances, save and reload!",
lib->name, lib->filepath);
change_idid_adr(&fd->mainlist, fd, lib, newmain->curlib);
// change_idid_adr_fd(fd, lib, newmain->curlib);
BLI_remlink(&main->library, lib);
MEM_freeN(lib);
return;
}
}
}
/* make sure we have full path in lib->filename */
BLI_strncpy(lib->filepath, lib->name, sizeof(lib->name));
cleanup_path(fd->relabase, lib->filepath);
// printf("direct_link_library: name %s\n", lib->name);
// printf("direct_link_library: filename %s\n", lib->filename);
/* new main */
newmain= MEM_callocN(sizeof(Main), "directlink");
BLI_addtail(&fd->mainlist, newmain);
newmain->curlib= lib;
lib->parent= NULL;
}
static void lib_link_library(FileData *UNUSED(fd), Main *main)
{
Library *lib;
for (lib= main->library.first; lib; lib= lib->id.next) {
lib->id.us= 1;
}
}
/* Always call this once you have loaded new library data to set the relative paths correctly in relation to the blend file */
static void fix_relpaths_library(const char *basepath, Main *main)
{
Library *lib;
/* BLO_read_from_memory uses a blank filename */
if (basepath==NULL || basepath[0] == '\0') {
for (lib= main->library.first; lib; lib= lib->id.next) {
/* when loading a linked lib into a file which has not been saved,
* there is nothing we can be relative to, so instead we need to make
* it absolute. This can happen when appending an object with a relative
* link into an unsaved blend file. See [#27405].
* The remap relative option will make it relative again on save - campbell */
if (strncmp(lib->name, "//", 2)==0) {
BLI_strncpy(lib->name, lib->filepath, sizeof(lib->name));
}
}
}
else {
for (lib= main->library.first; lib; lib= lib->id.next) {
/* Libraries store both relative and abs paths, recreate relative paths,
* relative to the blend file since indirectly linked libs will be relative to their direct linked library */
if (strncmp(lib->name, "//", 2)==0) { /* if this is relative to begin with? */
BLI_strncpy(lib->name, lib->filepath, sizeof(lib->name));
BLI_path_rel(lib->name, basepath);
}
}
}
}
/* ************ READ SPEAKER ***************** */
static void lib_link_speaker(FileData *fd, Main *main)
{
Speaker *spk;
spk= main->speaker.first;
while (spk) {
if (spk->id.flag & LIB_NEEDLINK) {
if (spk->adt) lib_link_animdata(fd, &spk->id, spk->adt);
spk->sound= newlibadr(fd, spk->id.lib, spk->sound);
if (spk->sound) {
spk->sound->id.us++;
}
spk->id.flag -= LIB_NEEDLINK;
}
spk= spk->id.next;
}
}
static void direct_link_speaker(FileData *fd, Speaker *spk)
{
spk->adt= newdataadr(fd, spk->adt);
direct_link_animdata(fd, spk->adt);
#if 0
spk->sound= newdataadr(fd, spk->sound);
direct_link_sound(fd, spk->sound);
#endif
}
/* ************** READ SOUND ******************* */
static void direct_link_sound(FileData *fd, bSound *sound)
{
sound->handle = NULL;
sound->playback_handle = NULL;
sound->waveform = NULL;
// versioning stuff, if there was a cache, then we enable caching:
if (sound->cache) {
sound->flags |= SOUND_FLAGS_CACHING;
sound->cache = 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); // XXX depreceated - old animation system
sound_load(main, sound);
}
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) {
go->ob->flag |= OB_FROMGROUP;
/* 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, NULL, NULL); /* removes NULL entries */
}
group= group->id.next;
}
}
/* ***************** READ MOVIECLIP *************** */
static void direct_link_movieReconstruction(FileData *fd, MovieTrackingReconstruction *reconstruction)
{
reconstruction->cameras= newdataadr(fd, reconstruction->cameras);
}
static void direct_link_movieTracks(FileData *fd, ListBase *tracksbase)
{
MovieTrackingTrack *track;
link_list(fd, tracksbase);
track= tracksbase->first;
while (track) {
track->markers= newdataadr(fd, track->markers);
track= track->next;
}
}
static void direct_link_movieclip(FileData *fd, MovieClip *clip)
{
MovieTracking *tracking= &clip->tracking;
MovieTrackingObject *object;
clip->adt= newdataadr(fd, clip->adt);
if (fd->movieclipmap) clip->cache= newmclipadr(fd, clip->cache);
else clip->cache= NULL;
if (fd->movieclipmap) clip->tracking.camera.intrinsics= newmclipadr(fd, clip->tracking.camera.intrinsics);
else clip->tracking.camera.intrinsics= NULL;
direct_link_movieTracks(fd, &tracking->tracks);
direct_link_movieReconstruction(fd, &tracking->reconstruction);
clip->tracking.act_track= newdataadr(fd, clip->tracking.act_track);
clip->anim= NULL;
clip->tracking_context= NULL;
clip->tracking.stats= NULL;
clip->tracking.stabilization.ok= 0;
clip->tracking.stabilization.scaleibuf= NULL;
clip->tracking.stabilization.rot_track= newdataadr(fd, clip->tracking.stabilization.rot_track);
link_list(fd, &tracking->objects);
object= tracking->objects.first;
while (object) {
direct_link_movieTracks(fd, &object->tracks);
direct_link_movieReconstruction(fd, &object->reconstruction);
object= object->next;
}
}
static void lib_link_movieclip(FileData *fd, Main *main)
{
MovieClip *clip;
clip= main->movieclip.first;
while (clip) {
if (clip->id.flag & LIB_NEEDLINK) {
if (clip->adt)
lib_link_animdata(fd, &clip->id, clip->adt);
clip->gpd= newlibadr_us(fd, clip->id.lib, clip->gpd);
clip->id.flag -= LIB_NEEDLINK;
}
clip= clip->id.next;
}
}
/* ************** GENERAL & MAIN ******************** */
static const char *dataname(short id_code)
{
switch ( id_code ) {
case ID_OB: return "Data from OB";
case ID_ME: return "Data from ME";
case ID_IP: return "Data from IP";
case ID_SCE: return "Data from SCE";
case ID_MA: return "Data from MA";
case ID_TE: return "Data from TE";
case ID_CU: return "Data from CU";
case ID_GR: return "Data from GR";
case ID_AR: return "Data from AR";
case ID_AC: return "Data from AC";
case ID_LI: return "Data from LI";
case ID_MB: return "Data from MB";
case ID_IM: return "Data from IM";
case ID_LT: return "Data from LT";
case ID_LA: return "Data from LA";
case ID_CA: return "Data from CA";
case ID_KE: return "Data from KE";
case ID_WO: return "Data from WO";
case ID_SCR: return "Data from SCR";
case ID_VF: return "Data from VF";
case ID_TXT : return "Data from TXT";
case ID_SPK: return "Data from SPK";
case ID_SO: return "Data from SO";
case ID_NT: return "Data from NT";
case ID_BR: return "Data from BR";
case ID_PA: return "Data from PA";
case ID_GD: return "Data from GD";
case ID_MC: return "Data from MC";
}
return "Data from Lib Block";
}
static BHead *read_data_into_oldnewmap(FileData *fd, BHead *bhead, const char *allocname)
{
bhead = blo_nextbhead(fd, bhead);
while (bhead && bhead->code==DATA) {
void *data;
#if 0
/* XXX DUMB DEBUGGING OPTION TO GIVE NAMES for guarded malloc errors */
short *sp= fd->filesdna->structs[bhead->SDNAnr];
char *tmp= malloc(100);
allocname = fd->filesdna->types[ sp[0] ];
strcpy(tmp, allocname);
data= read_struct(fd, bhead, tmp);
#else
data= read_struct(fd, bhead, allocname);
#endif
if (data) {
oldnewmap_insert(fd->datamap, bhead->old, data, 0);
}
bhead = blo_nextbhead(fd, bhead);
}
return bhead;
}
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;
const char *allocname;
/* 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, bhead->code); /* for ID_ID check */
/* do after read_struct, for dna reconstruct */
if (bhead->code==ID_ID) {
lb= which_libbase(main, GS(id->name));
}
else {
lb= which_libbase(main, bhead->code);
}
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;
id->icon_id = 0;
id->flag &= ~(LIB_ID_RECALC|LIB_ID_RECALC_DATA);
/* this case cannot be direct_linked: it's just the ID part */
if (bhead->code==ID_ID) {
return blo_nextbhead(fd, bhead);
}
/* need a name for the mallocN, just for debugging and sane prints on leaks */
allocname= dataname(GS(id->name));
/* read all data into fd->datamap */
bhead= read_data_into_oldnewmap(fd, bhead, allocname);
/* init pointers direct data */
switch (GS(id->name)) {
case ID_WM:
direct_link_windowmanager(fd, (wmWindowManager *)id);
break;
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_SPK:
direct_link_speaker(fd, (Speaker *)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;
case ID_NT:
direct_link_nodetree(fd, (bNodeTree*)id);
break;
case ID_BR:
direct_link_brush(fd, (Brush*)id);
break;
case ID_PA:
direct_link_particlesettings(fd, (ParticleSettings*)id);
break;
case ID_SCRIPT:
direct_link_script(fd, (Script*)id);
break;
case ID_GD:
direct_link_gpencil(fd, (bGPdata *)id);
break;
case ID_MC:
direct_link_movieclip(fd, (MovieClip *)id);
break;
}
/*link direct data of ID properties*/
if (id->properties) {
id->properties = newdataadr(fd, id->properties);
if (id->properties) { /* this case means the data was written incorrectly, it should not happen */
IDP_DirectLinkProperty(id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
}
oldnewmap_free_unused(fd->datamap);
oldnewmap_clear(fd->datamap);
return (bhead);
}
/* note, this has to be kept for reading older files... */
/* also version info is written here */
static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
{
FileGlobal *fg= read_struct(fd, bhead, "Global");
/* copy to bfd handle */
bfd->main->subversionfile= fg->subversion;
bfd->main->minversionfile= fg->minversion;
bfd->main->minsubversionfile= fg->minsubversion;
bfd->main->revision= fg->revision;
bfd->winpos= fg->winpos;
bfd->fileflags= fg->fileflags;
bfd->displaymode= fg->displaymode;
bfd->globalf= fg->globalf;
BLI_strncpy(bfd->filename, fg->filename, sizeof(bfd->filename));
if (G.fileflags & G_FILE_RECOVER)
BLI_strncpy(fd->relabase, fg->filename, sizeof(fd->relabase));
bfd->curscreen= fg->curscreen;
bfd->curscene= fg->curscene;
MEM_freeN(fg);
fd->globalf= bfd->globalf;
fd->fileflags= bfd->fileflags;
return blo_nextbhead(fd, bhead);
}
/* note, this has to be kept for reading older files... */
static void link_global(FileData *fd, BlendFileData *bfd)
{
bfd->curscreen= newlibadr(fd, NULL, bfd->curscreen);
bfd->curscene= newlibadr(fd, NULL, bfd->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==NULL) 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 311; /* F12KEY */
case 159: return 161; /* PADSLASHKEY */
case 161: return 150; /* PAD0 */
case 154: return 151; /* PAD1 */
case 150: return 152; /* PAD2 */
case 155: return 153; /* PAD3 */
case 151: return 154; /* PAD4 */
case 156: return 155; /* PAD5 */
case 152: return 156; /* PAD6 */
case 157: return 157; /* PAD7 */
case 153: return 158; /* PAD8 */
case 158: return 159; /* PAD9 */
default: return code;
}
}
static void do_version_bone_head_tail_237(Bone *bone)
{
Bone *child;
float vec[3];
/* head */
copy_v3_v3(bone->arm_head, bone->arm_mat[3]);
/* tail is in current local coord system */
copy_v3_v3(vec, bone->arm_mat[1]);
mul_v3_fl(vec, bone->length);
add_v3_v3v3(bone->arm_tail, bone->arm_head, vec);
for (child= bone->childbase.first; child; child= child->next)
do_version_bone_head_tail_237(child);
}
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 ntree_version_241(bNodeTree *ntree)
{
bNode *node;
if (ntree->type==NTREE_COMPOSIT) {
for (node= ntree->nodes.first; node; node= node->next) {
if (node->type==CMP_NODE_BLUR) {
if (node->storage==NULL) {
NodeBlurData *nbd= MEM_callocN(sizeof(NodeBlurData), "node blur patch");
nbd->sizex= node->custom1;
nbd->sizey= node->custom2;
nbd->filtertype= R_FILTER_QUAD;
node->storage= nbd;
}
}
else if (node->type==CMP_NODE_VECBLUR) {
if (node->storage==NULL) {
NodeBlurData *nbd= MEM_callocN(sizeof(NodeBlurData), "node blur patch");
nbd->samples= node->custom1;
nbd->maxspeed= node->custom2;
nbd->fac= 1.0f;
node->storage= nbd;
}
}
}
}
}
static void ntree_version_242(bNodeTree *ntree)
{
bNode *node;
if (ntree->type==NTREE_COMPOSIT) {
for (node= ntree->nodes.first; node; node= node->next) {
if (node->type==CMP_NODE_HUE_SAT) {
if (node->storage) {
NodeHueSat *nhs= node->storage;
if (nhs->val==0.0f) nhs->val= 1.0f;
}
}
}
}
else if (ntree->type==NTREE_SHADER) {
for (node= ntree->nodes.first; node; node= node->next)
if (node->type == SH_NODE_GEOMETRY && node->storage == NULL)
node->storage= MEM_callocN(sizeof(NodeGeometry), "NodeGeometry");
}
}
static void customdata_version_242(Mesh *me)
{
CustomDataLayer *layer;
MTFace *mtf;
MCol *mcol;
TFace *tf;
int a, mtfacen, mcoln;
if (!me->vdata.totlayer) {
CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, me->mvert, me->totvert);
if (me->msticky)
CustomData_add_layer(&me->vdata, CD_MSTICKY, CD_ASSIGN, me->msticky, me->totvert);
if (me->dvert)
CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_ASSIGN, me->dvert, me->totvert);
}
if (!me->edata.totlayer)
CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, me->medge, me->totedge);
if (!me->fdata.totlayer) {
CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, me->mface, me->totface);
if (me->tface) {
if (me->mcol)
MEM_freeN(me->mcol);
me->mcol= CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface);
me->mtface= CustomData_add_layer(&me->fdata, CD_MTFACE, CD_CALLOC, NULL, me->totface);
mtf= me->mtface;
mcol= me->mcol;
tf= me->tface;
for (a=0; a < me->totface; a++, mtf++, tf++, mcol+=4) {
memcpy(mcol, tf->col, sizeof(tf->col));
memcpy(mtf->uv, tf->uv, sizeof(tf->uv));
mtf->flag= tf->flag;
mtf->unwrap= tf->unwrap;
mtf->mode= tf->mode;
mtf->tile= tf->tile;
mtf->tpage= tf->tpage;
mtf->transp= tf->transp;
}
MEM_freeN(me->tface);
me->tface= NULL;
}
else if (me->mcol) {
me->mcol= CustomData_add_layer(&me->fdata, CD_MCOL, CD_ASSIGN, me->mcol, me->totface);
}
}
if (me->tface) {
MEM_freeN(me->tface);
me->tface= NULL;
}
for (a=0, mtfacen=0, mcoln=0; a < me->fdata.totlayer; a++) {
layer= &me->fdata.layers[a];
if (layer->type == CD_MTFACE) {
if (layer->name[0] == 0) {
if (mtfacen == 0) strcpy(layer->name, "UVMap");
else BLI_snprintf(layer->name, sizeof(layer->name), "UVMap.%.3d", mtfacen);
}
mtfacen++;
}
else if (layer->type == CD_MCOL) {
if (layer->name[0] == 0) {
if (mcoln == 0) strcpy(layer->name, "Col");
else BLI_snprintf(layer->name, sizeof(layer->name), "Col.%.3d", mcoln);
}
mcoln++;
}
}
mesh_update_customdata_pointers(me, TRUE);
}
/*only copy render texface layer from active*/
static void customdata_version_243(Mesh *me)
{
CustomDataLayer *layer;
int a;
for (a=0; a < me->fdata.totlayer; a++) {
layer= &me->fdata.layers[a];
layer->active_rnd = layer->active;
}
}
/* struct NodeImageAnim moved to ImageUser, and we make it default available */
static void do_version_ntree_242_2(bNodeTree *ntree)
{
bNode *node;
if (ntree->type==NTREE_COMPOSIT) {
for (node= ntree->nodes.first; node; node= node->next) {
if (ELEM3(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
/* only image had storage */
if (node->storage) {
NodeImageAnim *nia= node->storage;
ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "ima user node");
iuser->frames= nia->frames;
iuser->sfra= nia->sfra;
iuser->offset= nia->nr-1;
iuser->cycl= nia->cyclic;
iuser->fie_ima= 2;
iuser->ok= 1;
node->storage= iuser;
MEM_freeN(nia);
}
else {
ImageUser *iuser= node->storage= MEM_callocN(sizeof(ImageUser), "node image user");
iuser->sfra= 1;
iuser->fie_ima= 2;
iuser->ok= 1;
}
}
}
}
}
static void ntree_version_245(FileData *fd, Library *lib, bNodeTree *ntree)
{
bNode *node;
NodeTwoFloats *ntf;
ID *nodeid;
Image *image;
ImageUser *iuser;
if (ntree->type==NTREE_COMPOSIT) {
for (node= ntree->nodes.first; node; node= node->next) {
if (node->type == CMP_NODE_ALPHAOVER) {
if (!node->storage) {
ntf= MEM_callocN(sizeof(NodeTwoFloats), "NodeTwoFloats");
node->storage= ntf;
if (node->custom1)
ntf->x= 1.0f;
}
}
/* fix for temporary flag changes during 245 cycle */
nodeid= newlibadr(fd, lib, node->id);
if (node->storage && nodeid && GS(nodeid->name) == ID_IM) {
image= (Image*)nodeid;
iuser= node->storage;
if (iuser->flag & IMA_OLD_PREMUL) {
iuser->flag &= ~IMA_OLD_PREMUL;
iuser->flag |= IMA_DO_PREMUL;
}
if (iuser->flag & IMA_DO_PREMUL) {
image->flag &= ~IMA_OLD_PREMUL;
image->flag |= IMA_DO_PREMUL;
}
}
}
}
}
static void idproperties_fix_groups_lengths_recurse(IDProperty *prop)
{
IDProperty *loop;
int i;
for (loop=prop->data.group.first, i=0; loop; loop=loop->next, i++) {
if (loop->type == IDP_GROUP) idproperties_fix_groups_lengths_recurse(loop);
}
if (prop->len != i) {
printf("Found and fixed bad id property group length.\n");
prop->len = i;
}
}
static void idproperties_fix_group_lengths(ListBase idlist)
{
ID *id;
for (id=idlist.first; id; id=id->next) {
if (id->properties) {
idproperties_fix_groups_lengths_recurse(id->properties);
}
}
}
static void alphasort_version_246(FileData *fd, Library *lib, Mesh *me)
{
Material *ma;
MFace *mf;
MTFace *tf;
int a, b, texalpha;
/* verify we have a tface layer */
for (b=0; b<me->fdata.totlayer; b++)
if (me->fdata.layers[b].type == CD_MTFACE)
break;
if (b == me->fdata.totlayer)
return;
/* if we do, set alpha sort if the game engine did it before */
for (a=0, mf=me->mface; a<me->totface; a++, mf++) {
if (mf->mat_nr < me->totcol) {
ma= newlibadr(fd, lib, me->mat[mf->mat_nr]);
texalpha = 0;
/* we can't read from this if it comes from a library,
* because direct_link might not have happened on it,
* so ma->mtex is not pointing to valid memory yet */
if (ma && ma->id.lib)
ma= NULL;
for (b=0; ma && b<MAX_MTEX; b++)
if (ma->mtex && ma->mtex[b] && ma->mtex[b]->mapto & MAP_ALPHA)
texalpha = 1;
}
else {
ma= NULL;
texalpha = 0;
}
for (b=0; b<me->fdata.totlayer; b++) {
if (me->fdata.layers[b].type == CD_MTFACE) {
tf = ((MTFace*)me->fdata.layers[b].data) + a;
tf->mode &= ~TF_ALPHASORT;
if (ma && (ma->mode & MA_ZTRANSP))
if (ELEM(tf->transp, TF_ALPHA, TF_ADD) || (texalpha && (tf->transp != TF_CLIP)))
tf->mode |= TF_ALPHASORT;
}
}
}
}
/* 2.50 patch */
static void area_add_header_region(ScrArea *sa, ListBase *lb)
{
ARegion *ar= MEM_callocN(sizeof(ARegion), "area region from do_versions");
BLI_addtail(lb, ar);
ar->regiontype= RGN_TYPE_HEADER;
if (sa->headertype==HEADERDOWN)
ar->alignment= RGN_ALIGN_BOTTOM;
else
ar->alignment= RGN_ALIGN_TOP;
/* initialize view2d data for header region, to allow panning */
/* is copy from ui_view2d.c */
ar->v2d.keepzoom = (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_LIMITZOOM|V2D_KEEPASPECT);
ar->v2d.keepofs = V2D_LOCKOFS_Y;
ar->v2d.keeptot = V2D_KEEPTOT_STRICT;
ar->v2d.align = V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_NEG_Y;
ar->v2d.flag = (V2D_PIXELOFS_X|V2D_PIXELOFS_Y);
}
static void sequencer_init_preview_region(ARegion* ar)
{
// XXX a bit ugly still, copied from space_sequencer
/* NOTE: if you change values here, also change them in space_sequencer.c, sequencer_new */
ar->regiontype= RGN_TYPE_PREVIEW;
ar->alignment= RGN_ALIGN_TOP;
ar->flag |= RGN_FLAG_HIDDEN;
ar->v2d.keepzoom= V2D_KEEPASPECT | V2D_KEEPZOOM;
ar->v2d.minzoom= 0.00001f;
ar->v2d.maxzoom= 100000.0f;
ar->v2d.tot.xmin = -960.0f; /* 1920 width centered */
ar->v2d.tot.ymin = -540.0f; /* 1080 height centered */
ar->v2d.tot.xmax = 960.0f;
ar->v2d.tot.ymax = 540.0f;
ar->v2d.min[0]= 0.0f;
ar->v2d.min[1]= 0.0f;
ar->v2d.max[0]= 12000.0f;
ar->v2d.max[1]= 12000.0f;
ar->v2d.cur= ar->v2d.tot;
ar->v2d.align= V2D_ALIGN_FREE; // (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_NEG_Y);
ar->v2d.keeptot= V2D_KEEPTOT_FREE;
}
/* 2.50 patch */
static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
{
ARegion *ar;
ARegion *ar_main;
if (sl) {
/* first channels for ipo action nla... */
switch (sl->spacetype) {
case SPACE_IPO:
ar= MEM_callocN(sizeof(ARegion), "area region from do_versions");
BLI_addtail(lb, ar);
ar->regiontype= RGN_TYPE_CHANNELS;
ar->alignment= RGN_ALIGN_LEFT;
ar->v2d.scroll= (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM);
// for some reason, this doesn't seem to go auto like for NLA...
ar= MEM_callocN(sizeof(ARegion), "area region from do_versions");
BLI_addtail(lb, ar);
ar->regiontype= RGN_TYPE_UI;
ar->alignment= RGN_ALIGN_RIGHT;
ar->v2d.scroll= V2D_SCROLL_RIGHT;
ar->v2d.flag = RGN_FLAG_HIDDEN;
break;
case SPACE_ACTION:
ar= MEM_callocN(sizeof(ARegion), "area region from do_versions");
BLI_addtail(lb, ar);
ar->regiontype= RGN_TYPE_CHANNELS;
ar->alignment= RGN_ALIGN_LEFT;
ar->v2d.scroll= V2D_SCROLL_BOTTOM;
ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
break;
case SPACE_NLA:
ar= MEM_callocN(sizeof(ARegion), "area region from do_versions");
BLI_addtail(lb, ar);
ar->regiontype= RGN_TYPE_CHANNELS;
ar->alignment= RGN_ALIGN_LEFT;
ar->v2d.scroll= V2D_SCROLL_BOTTOM;
ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
// for some reason, some files still don't get this auto
ar= MEM_callocN(sizeof(ARegion), "area region from do_versions");
BLI_addtail(lb, ar);
ar->regiontype= RGN_TYPE_UI;
ar->alignment= RGN_ALIGN_RIGHT;
ar->v2d.scroll= V2D_SCROLL_RIGHT;
ar->v2d.flag = RGN_FLAG_HIDDEN;
break;
case SPACE_NODE:
ar= MEM_callocN(sizeof(ARegion), "nodetree area for node");
BLI_addtail(lb, ar);
ar->regiontype= RGN_TYPE_UI;
ar->alignment= RGN_ALIGN_LEFT;
ar->v2d.scroll = (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM);
ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
/* temporarily hide it */
ar->flag = RGN_FLAG_HIDDEN;
break;
case SPACE_FILE:
ar= MEM_callocN(sizeof(ARegion), "nodetree area for node");
BLI_addtail(lb, ar);
ar->regiontype= RGN_TYPE_CHANNELS;
ar->alignment= RGN_ALIGN_LEFT;
ar= MEM_callocN(sizeof(ARegion), "ui area for file");
BLI_addtail(lb, ar);
ar->regiontype= RGN_TYPE_UI;
ar->alignment= RGN_ALIGN_TOP;
break;
case SPACE_SEQ:
ar_main = (ARegion*)lb->first;
for (; ar_main; ar_main = ar_main->next) {
if (ar_main->regiontype == RGN_TYPE_WINDOW)
break;
}
ar= MEM_callocN(sizeof(ARegion), "preview area for sequencer");
BLI_insertlinkbefore(lb, ar_main, ar);
sequencer_init_preview_region(ar);
break;
case SPACE_VIEW3D:
/* toolbar */
ar= MEM_callocN(sizeof(ARegion), "toolbar for view3d");
BLI_addtail(lb, ar);
ar->regiontype= RGN_TYPE_TOOLS;
ar->alignment= RGN_ALIGN_LEFT;
ar->flag = RGN_FLAG_HIDDEN;
/* tool properties */
ar= MEM_callocN(sizeof(ARegion), "tool properties for view3d");
BLI_addtail(lb, ar);
ar->regiontype= RGN_TYPE_TOOL_PROPS;
ar->alignment= RGN_ALIGN_BOTTOM|RGN_SPLIT_PREV;
ar->flag = RGN_FLAG_HIDDEN;
/* buttons/list view */
ar= MEM_callocN(sizeof(ARegion), "buttons for view3d");
BLI_addtail(lb, ar);
ar->regiontype= RGN_TYPE_UI;
ar->alignment= RGN_ALIGN_RIGHT;
ar->flag = RGN_FLAG_HIDDEN;
#if 0
case SPACE_BUTS:
/* context UI region */
ar= MEM_callocN(sizeof(ARegion), "area region from do_versions");
BLI_addtail(lb, ar);
ar->regiontype= RGN_TYPE_UI;
ar->alignment= RGN_ALIGN_RIGHT;
break;
#endif
}
}
/* main region */
ar= MEM_callocN(sizeof(ARegion), "area region from do_versions");
BLI_addtail(lb, ar);
ar->winrct= sa->totrct;
ar->regiontype= RGN_TYPE_WINDOW;
if (sl) {
/* if active spacetype has view2d data, copy that over to main region */
/* and we split view3d */
switch (sl->spacetype) {
case SPACE_VIEW3D:
view3d_split_250((View3D *)sl, lb);
break;
case SPACE_OUTLINER:
{
SpaceOops *soops= (SpaceOops *)sl;
memcpy(&ar->v2d, &soops->v2d, sizeof(View2D));
ar->v2d.scroll &= ~V2D_SCROLL_LEFT;
ar->v2d.scroll |= (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM_O);
ar->v2d.align = (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_POS_Y);
ar->v2d.keepzoom |= (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_KEEPASPECT);
ar->v2d.keeptot = V2D_KEEPTOT_STRICT;
ar->v2d.minzoom= ar->v2d.maxzoom= 1.0f;
//ar->v2d.flag |= V2D_IS_INITIALISED;
}
break;
case SPACE_TIME:
{
SpaceTime *stime= (SpaceTime *)sl;
memcpy(&ar->v2d, &stime->v2d, sizeof(View2D));
ar->v2d.scroll |= (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
ar->v2d.align |= V2D_ALIGN_NO_NEG_Y;
ar->v2d.keepofs |= V2D_LOCKOFS_Y;
ar->v2d.keepzoom |= V2D_LOCKZOOM_Y;
ar->v2d.tot.ymin = ar->v2d.cur.ymin = -10.0;
ar->v2d.min[1]= ar->v2d.max[1]= 20.0;
}
break;
case SPACE_IPO:
{
SpaceIpo *sipo= (SpaceIpo *)sl;
memcpy(&ar->v2d, &sipo->v2d, sizeof(View2D));
/* init mainarea view2d */
ar->v2d.scroll |= (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
ar->v2d.scroll |= (V2D_SCROLL_LEFT|V2D_SCROLL_SCALE_VERTICAL);
ar->v2d.min[0]= FLT_MIN;
ar->v2d.min[1]= FLT_MIN;
ar->v2d.max[0]= MAXFRAMEF;
ar->v2d.max[1]= FLT_MAX;
//ar->v2d.flag |= V2D_IS_INITIALISED;
break;
}
case SPACE_NLA:
{
SpaceNla *snla= (SpaceNla *)sl;
memcpy(&ar->v2d, &snla->v2d, sizeof(View2D));
ar->v2d.tot.ymin = (float)(-sa->winy)/3.0f;
ar->v2d.tot.ymax = 0.0f;
ar->v2d.scroll |= (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
ar->v2d.align = V2D_ALIGN_NO_POS_Y;
ar->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL;
break;
}
case SPACE_ACTION:
{
SpaceAction *saction= (SpaceAction *)sl;
/* we totally reinit the view for the Action Editor, as some old instances had some weird cruft set */
ar->v2d.tot.xmin = -20.0f;
ar->v2d.tot.ymin = (float)(-sa->winy)/3.0f;
ar->v2d.tot.xmax = (float)((sa->winx > 120)? (sa->winx) : 120);
ar->v2d.tot.ymax = 0.0f;
ar->v2d.cur= ar->v2d.tot;
ar->v2d.min[0]= 0.0f;
ar->v2d.min[1]= 0.0f;
ar->v2d.max[0]= MAXFRAMEF;
ar->v2d.max[1]= FLT_MAX;
ar->v2d.minzoom= 0.01f;
ar->v2d.maxzoom= 50;
ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
ar->v2d.keepzoom= V2D_LOCKZOOM_Y;
ar->v2d.align= V2D_ALIGN_NO_POS_Y;
ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
/* for old files with ShapeKey editors open + an action set, clear the action as
* it doesn't make sense in the new system (i.e. violates concept that ShapeKey edit
* only shows ShapeKey-rooted actions only)
*/
if (saction->mode == SACTCONT_SHAPEKEY)
saction->action = NULL;
break;
}
case SPACE_SEQ:
{
SpaceSeq *sseq= (SpaceSeq *)sl;
memcpy(&ar->v2d, &sseq->v2d, sizeof(View2D));
ar->v2d.scroll |= (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
ar->v2d.scroll |= (V2D_SCROLL_LEFT|V2D_SCROLL_SCALE_VERTICAL);
ar->v2d.align= V2D_ALIGN_NO_NEG_Y;
ar->v2d.flag |= V2D_IS_INITIALISED;
break;
}
case SPACE_NODE:
{
SpaceNode *snode= (SpaceNode *)sl;
memcpy(&ar->v2d, &snode->v2d, sizeof(View2D));
ar->v2d.scroll= (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM);
ar->v2d.keepzoom= V2D_LIMITZOOM|V2D_KEEPASPECT;
break;
}
case SPACE_BUTS:
{
SpaceButs *sbuts= (SpaceButs *)sl;
memcpy(&ar->v2d, &sbuts->v2d, sizeof(View2D));
ar->v2d.scroll |= (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM);
break;
}
case SPACE_FILE:
{
// SpaceFile *sfile= (SpaceFile *)sl;
ar->v2d.tot.xmin = ar->v2d.tot.ymin = 0;
ar->v2d.tot.xmax = ar->winx;
ar->v2d.tot.ymax = ar->winy;
ar->v2d.cur = ar->v2d.tot;
ar->regiontype= RGN_TYPE_WINDOW;
ar->v2d.scroll = (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM_O);
ar->v2d.align = (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_POS_Y);
ar->v2d.keepzoom = (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_LIMITZOOM|V2D_KEEPASPECT);
break;
}
case SPACE_TEXT:
{
SpaceText *st= (SpaceText *)sl;
st->flags |= ST_FIND_WRAP;
}
//case SPACE_XXX: // FIXME... add other ones
// memcpy(&ar->v2d, &((SpaceXxx *)sl)->v2d, sizeof(View2D));
// break;
}
}
}
static void do_versions_windowmanager_2_50(bScreen *screen)
{
ScrArea *sa;
SpaceLink *sl;
/* add regions */
for (sa= screen->areabase.first; sa; sa= sa->next) {
/* we keep headertype variable to convert old files only */
if (sa->headertype)
area_add_header_region(sa, &sa->regionbase);
area_add_window_regions(sa, sa->spacedata.first, &sa->regionbase);
/* space imageselect is deprecated */
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_IMASEL)
sl->spacetype= SPACE_EMPTY; /* spacedata then matches */
}
/* space sound is deprecated */
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_SOUND)
sl->spacetype= SPACE_EMPTY; /* spacedata then matches */
}
/* it seems to be possible in 2.5 to have this saved, filewindow probably */
sa->butspacetype= sa->spacetype;
/* pushed back spaces also need regions! */
if (sa->spacedata.first) {
sl= sa->spacedata.first;
for (sl= sl->next; sl; sl= sl->next) {
if (sa->headertype)
area_add_header_region(sa, &sl->regionbase);
area_add_window_regions(sa, sl, &sl->regionbase);
}
}
}
}
static void versions_gpencil_add_main(ListBase *lb, ID *id, const char *name)
{
BLI_addtail(lb, id);
id->us= 1;
id->flag= LIB_FAKEUSER;
*( (short *)id->name )= ID_GD;
new_id(lb, id, name);
/* alphabetic insterion: is in new_id */
if (G.debug & G_DEBUG)
printf("Converted GPencil to ID: %s\n", id->name+2);
}
static void do_versions_gpencil_2_50(Main *main, bScreen *screen)
{
ScrArea *sa;
SpaceLink *sl;
/* add regions */
for (sa= screen->areabase.first; sa; sa= sa->next) {
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D*) sl;
if (v3d->gpd) {
versions_gpencil_add_main(&main->gpencil, (ID *)v3d->gpd, "GPencil View3D");
v3d->gpd= NULL;
}
}
else if (sl->spacetype==SPACE_NODE) {
SpaceNode *snode= (SpaceNode *)sl;
if (snode->gpd) {
versions_gpencil_add_main(&main->gpencil, (ID *)snode->gpd, "GPencil Node");
snode->gpd= NULL;
}
}
else if (sl->spacetype==SPACE_SEQ) {
SpaceSeq *sseq= (SpaceSeq *)sl;
if (sseq->gpd) {
versions_gpencil_add_main(&main->gpencil, (ID *)sseq->gpd, "GPencil Node");
sseq->gpd= NULL;
}
}
else if (sl->spacetype==SPACE_IMAGE) {
SpaceImage *sima= (SpaceImage *)sl;
#if 0 /* see comment on r28002 */
if (sima->gpd) {
versions_gpencil_add_main(&main->gpencil, (ID *)sima->gpd, "GPencil Image");
sima->gpd= NULL;
}
#else
sima->gpd= NULL;
#endif
}
}
}
}
/* deprecated, only keep this for readfile.c */
static PartEff *do_version_give_parteff_245(Object *ob)
{
PartEff *paf;
paf= ob->effect.first;
while (paf) {
if (paf->type==EFF_PARTICLE) return paf;
paf= paf->next;
}
return NULL;
}
static void do_version_free_effect_245(Effect *eff)
{
PartEff *paf;
if (eff->type==EFF_PARTICLE) {
paf= (PartEff *)eff;
if (paf->keys) MEM_freeN(paf->keys);
}
MEM_freeN(eff);
}
static void do_version_free_effects_245(ListBase *lb)
{
Effect *eff;
eff= lb->first;
while (eff) {
BLI_remlink(lb, eff);
do_version_free_effect_245(eff);
eff= lb->first;
}
}
static void do_version_mtex_factor_2_50(MTex **mtex_array, short idtype)
{
MTex *mtex;
float varfac, colfac;
int a, neg;
if (!mtex_array)
return;
for (a=0; a<MAX_MTEX; a++) {
if (mtex_array[a]) {
mtex= mtex_array[a];
neg= mtex->maptoneg;
varfac= mtex->varfac;
colfac= mtex->colfac;
if (neg & MAP_DISP) mtex->dispfac= -mtex->dispfac;
if (neg & MAP_NORM) mtex->norfac= -mtex->norfac;
if (neg & MAP_WARP) mtex->warpfac= -mtex->warpfac;
mtex->colspecfac= (neg & MAP_COLSPEC)? -colfac: colfac;
mtex->mirrfac= (neg & MAP_COLMIR)? -colfac: colfac;
mtex->alphafac= (neg & MAP_ALPHA)? -varfac: varfac;
mtex->difffac= (neg & MAP_REF)? -varfac: varfac;
mtex->specfac= (neg & MAP_SPEC)? -varfac: varfac;
mtex->emitfac= (neg & MAP_EMIT)? -varfac: varfac;
mtex->hardfac= (neg & MAP_HAR)? -varfac: varfac;
mtex->raymirrfac= (neg & MAP_RAYMIRR)? -varfac: varfac;
mtex->translfac= (neg & MAP_TRANSLU)? -varfac: varfac;
mtex->ambfac= (neg & MAP_AMB)? -varfac: varfac;
mtex->colemitfac= (neg & MAP_EMISSION_COL)? -colfac: colfac;
mtex->colreflfac= (neg & MAP_REFLECTION_COL)? -colfac: colfac;
mtex->coltransfac= (neg & MAP_TRANSMISSION_COL)? -colfac: colfac;
mtex->densfac= (neg & MAP_DENSITY)? -varfac: varfac;
mtex->scatterfac= (neg & MAP_SCATTERING)? -varfac: varfac;
mtex->reflfac= (neg & MAP_REFLECTION)? -varfac: varfac;
mtex->timefac= (neg & MAP_PA_TIME)? -varfac: varfac;
mtex->lengthfac= (neg & MAP_PA_LENGTH)? -varfac: varfac;
mtex->clumpfac= (neg & MAP_PA_CLUMP)? -varfac: varfac;
mtex->kinkfac= (neg & MAP_PA_KINK)? -varfac: varfac;
mtex->roughfac= (neg & MAP_PA_ROUGH)? -varfac: varfac;
mtex->padensfac= (neg & MAP_PA_DENS)? -varfac: varfac;
mtex->lifefac= (neg & MAP_PA_LIFE)? -varfac: varfac;
mtex->sizefac= (neg & MAP_PA_SIZE)? -varfac: varfac;
mtex->ivelfac= (neg & MAP_PA_IVEL)? -varfac: varfac;
mtex->shadowfac= (neg & LAMAP_SHAD)? -colfac: colfac;
mtex->zenupfac= (neg & WOMAP_ZENUP)? -colfac: colfac;
mtex->zendownfac= (neg & WOMAP_ZENDOWN)? -colfac: colfac;
mtex->blendfac= (neg & WOMAP_BLEND)? -varfac: varfac;
if (idtype == ID_MA)
mtex->colfac= (neg & MAP_COL)? -colfac: colfac;
else if (idtype == ID_LA)
mtex->colfac= (neg & LAMAP_COL)? -colfac: colfac;
else if (idtype == ID_WO)
mtex->colfac= (neg & WOMAP_HORIZ)? -colfac: colfac;
}
}
}
static void do_version_mdef_250(Main *main)
{
Object *ob;
ModifierData *md;
MeshDeformModifierData *mmd;
for (ob= main->object.first; ob; ob=ob->id.next) {
for (md=ob->modifiers.first; md; md=md->next) {
if (md->type == eModifierType_MeshDeform) {
mmd= (MeshDeformModifierData*)md;
if (mmd->bindcos) {
/* make bindcos NULL in order to trick older versions
* into thinking that the mesh was not bound yet */
mmd->bindcagecos= mmd->bindcos;
mmd->bindcos= NULL;
modifier_mdef_compact_influences(md);
}
}
}
}
}
static void do_version_constraints_radians_degrees_250(ListBase *lb)
{
bConstraint *con;
for (con=lb->first; con; con=con->next) {
if (con->type==CONSTRAINT_TYPE_RIGIDBODYJOINT) {
bRigidBodyJointConstraint *data = con->data;
data->axX *= (float)(M_PI/180.0);
data->axY *= (float)(M_PI/180.0);
data->axZ *= (float)(M_PI/180.0);
}
else if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
bKinematicConstraint *data = con->data;
data->poleangle *= (float)(M_PI/180.0);
}
else if (con->type==CONSTRAINT_TYPE_ROTLIMIT) {
bRotLimitConstraint *data = con->data;
data->xmin *= (float)(M_PI/180.0);
data->xmax *= (float)(M_PI/180.0);
data->ymin *= (float)(M_PI/180.0);
data->ymax *= (float)(M_PI/180.0);
data->zmin *= (float)(M_PI/180.0);
data->zmax *= (float)(M_PI/180.0);
}
}
}
/* NOTE: this version patch is intended for versions < 2.52.2, but was initially introduced in 2.27 already */
static void do_version_old_trackto_to_constraints(Object *ob)
{
/* create new trackto constraint from the relationship */
if (ob->track) {
bConstraint *con= add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
bTrackToConstraint *data = con->data;
/* copy tracking settings from the object */
data->tar = ob->track;
data->reserved1 = ob->trackflag;
data->reserved2 = ob->upflag;
}
/* clear old track setting */
ob->track = NULL;
}
static void do_versions_seq_unique_name_all_strips(
Scene * sce, ListBase *seqbasep)
{
Sequence * seq = seqbasep->first;
while (seq) {
seqbase_unique_name_recursive(&sce->ed->seqbase, seq);
if (seq->seqbase.first) {
do_versions_seq_unique_name_all_strips(
sce, &seq->seqbase);
}
seq=seq->next;
}
}
static void do_version_bone_roll_256(Bone *bone)
{
Bone *child;
float submat[3][3];
copy_m3_m4(submat, bone->arm_mat);
mat3_to_vec_roll(submat, NULL, &bone->arm_roll);
for (child = bone->childbase.first; child; child = child->next)
do_version_bone_roll_256(child);
}
static void do_versions_nodetree_dynamic_sockets(bNodeTree *ntree)
{
bNodeSocket *sock;
for (sock=ntree->inputs.first; sock; sock=sock->next)
sock->flag |= SOCK_DYNAMIC;
for (sock=ntree->outputs.first; sock; sock=sock->next)
sock->flag |= SOCK_DYNAMIC;
}
void convert_tface_mt(FileData *fd, Main *main)
{
Main *gmain;
/* this is a delayed do_version (so it can create new materials) */
if (main->versionfile < 259 || (main->versionfile == 259 && main->subversionfile < 3)) {
//XXX hack, material.c uses G.main all over the place, instead of main
// temporarily set G.main to the current main
gmain = G.main;
G.main = main;
if (!(do_version_tface(main, 1))) {
BKE_report(fd->reports, RPT_WARNING, "Texface conversion problem. Error in console");
}
//XXX hack, material.c uses G.main allover the place, instead of main
G.main = gmain;
}
}
static void do_versions_nodetree_image_default_alpha_output(bNodeTree *ntree)
{
bNode *node;
bNodeSocket *sock;
for (node=ntree->nodes.first; node; node=node->next) {
if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS)) {
/* default Image output value should have 0 alpha */
sock = node->outputs.first;
((bNodeSocketValueRGBA*)sock->default_value)->value[3] = 0.0f;
}
}
}
static void do_version_ntree_tex_mapping_260(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
{
bNode *node;
for (node=ntree->nodes.first; node; node=node->next) {
if (node->type == SH_NODE_MAPPING) {
TexMapping *tex_mapping;
tex_mapping= node->storage;
tex_mapping->projx= PROJ_X;
tex_mapping->projy= PROJ_Y;
tex_mapping->projz= PROJ_Z;
}
}
}
static void do_versions_nodetree_convert_angle(bNodeTree *ntree)
{
bNode *node;
for (node=ntree->nodes.first; node; node=node->next) {
if (node->type == CMP_NODE_ROTATE) {
/* Convert degrees to radians. */
bNodeSocket *sock = ((bNodeSocket*)node->inputs.first)->next;
((bNodeSocketValueFloat*)sock->default_value)->value = DEG2RADF(((bNodeSocketValueFloat*)sock->default_value)->value);
}
else if (node->type == CMP_NODE_DBLUR) {
/* Convert degrees to radians. */
NodeDBlurData *ndbd= node->storage;
ndbd->angle = DEG2RADF(ndbd->angle);
ndbd->spin = DEG2RADF(ndbd->spin);
}
else if (node->type == CMP_NODE_DEFOCUS) {
/* Convert degrees to radians. */
NodeDefocus *nqd = node->storage;
/* XXX DNA char to float conversion seems to map the char value into the [0.0f, 1.0f] range... */
nqd->rotation = DEG2RADF(nqd->rotation*255.0f);
}
else if (node->type == CMP_NODE_CHROMA_MATTE) {
/* Convert degrees to radians. */
NodeChroma *ndc = node->storage;
ndc->t1 = DEG2RADF(ndc->t1);
ndc->t2 = DEG2RADF(ndc->t2);
}
else if (node->type == CMP_NODE_GLARE) {
/* Convert degrees to radians. */
NodeGlare* ndg = node->storage;
/* XXX DNA char to float conversion seems to map the char value into the [0.0f, 1.0f] range... */
ndg->angle_ofs = DEG2RADF(ndg->angle_ofs*255.0f);
}
/* XXX TexMapping struct is used by other nodes too (at least node_composite_mapValue),
* but not the rot part...
*/
else if (node->type == SH_NODE_MAPPING) {
/* Convert degrees to radians. */
TexMapping* tmap = node->storage;
tmap->rot[0] = DEG2RADF(tmap->rot[0]);
tmap->rot[1] = DEG2RADF(tmap->rot[1]);
tmap->rot[2] = DEG2RADF(tmap->rot[2]);
}
}
}
void do_versions_image_settings_2_60(Scene *sce)
{
/* note: rd->subimtype is moved into individual settings now and no longer
* exists */
RenderData *rd= &sce->r;
ImageFormatData *imf= &sce->r.im_format;
/* we know no data loss happens here, the old values were in char range */
imf->imtype= (char)rd->imtype;
imf->planes= (char)rd->planes;
imf->compress= (char)rd->quality;
imf->quality= (char)rd->quality;
/* default, was stored in multiple places, may override later */
imf->depth= R_IMF_CHAN_DEPTH_8;
/* openexr */
imf->exr_codec = rd->quality & 7; /* strange but true! 0-4 are valid values, OPENEXR_COMPRESS */
switch (imf->imtype) {
case R_IMF_IMTYPE_OPENEXR:
imf->depth= (rd->subimtype & R_OPENEXR_HALF) ? R_IMF_CHAN_DEPTH_16 : R_IMF_CHAN_DEPTH_32;
if (rd->subimtype & R_PREVIEW_JPG) {
imf->flag |= R_IMF_FLAG_PREVIEW_JPG;
}
if (rd->subimtype & R_OPENEXR_ZBUF) {
imf->flag |= R_IMF_FLAG_ZBUF;
}
break;
case R_IMF_IMTYPE_TIFF:
if (rd->subimtype & R_TIFF_16BIT) {
imf->depth= R_IMF_CHAN_DEPTH_16;
}
break;
case R_IMF_IMTYPE_JP2:
if (rd->subimtype & R_JPEG2K_16BIT) {
imf->depth= R_IMF_CHAN_DEPTH_16;
}
else if (rd->subimtype & R_JPEG2K_12BIT) {
imf->depth= R_IMF_CHAN_DEPTH_12;
}
if (rd->subimtype & R_JPEG2K_YCC) {
imf->jp2_flag |= R_IMF_JP2_FLAG_YCC;
}
if (rd->subimtype & R_JPEG2K_CINE_PRESET) {
imf->jp2_flag |= R_IMF_JP2_FLAG_CINE_PRESET;
}
if (rd->subimtype & R_JPEG2K_CINE_48FPS) {
imf->jp2_flag |= R_IMF_JP2_FLAG_CINE_48;
}
break;
case R_IMF_IMTYPE_CINEON:
case R_IMF_IMTYPE_DPX:
if (rd->subimtype & R_CINEON_LOG) {
imf->cineon_flag |= R_IMF_CINEON_FLAG_LOG;
}
break;
}
}
/* socket use flags were only temporary before */
static void do_versions_nodetree_socket_use_flags_2_62(bNodeTree *ntree)
{
bNode *node;
bNodeSocket *sock;
bNodeLink *link;
for (node=ntree->nodes.first; node; node=node->next) {
for (sock=node->inputs.first; sock; sock=sock->next)
sock->flag &= ~SOCK_IN_USE;
for (sock=node->outputs.first; sock; sock=sock->next)
sock->flag &= ~SOCK_IN_USE;
}
for (sock=ntree->inputs.first; sock; sock=sock->next)
sock->flag &= ~SOCK_IN_USE;
for (sock=ntree->outputs.first; sock; sock=sock->next)
sock->flag &= ~SOCK_IN_USE;
for (link=ntree->links.first; link; link=link->next) {
link->fromsock->flag |= SOCK_IN_USE;
link->tosock->flag |= SOCK_IN_USE;
}
}
static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNodeTree *ntree)
{
bNode *node;
bNodeSocket *sock;
for (node=ntree->nodes.first; node; node=node->next) {
if (node->type==CMP_NODE_OUTPUT_FILE) {
/* previous CMP_NODE_OUTPUT_FILE nodes get converted to multi-file outputs */
NodeImageFile *old_data = node->storage;
NodeImageMultiFile *nimf= MEM_callocN(sizeof(NodeImageMultiFile), "node image multi file");
bNodeSocket *old_image = BLI_findlink(&node->inputs, 0);
bNodeSocket *old_z = BLI_findlink(&node->inputs, 1);
bNodeSocket *sock;
node->storage= nimf;
BLI_strncpy(nimf->base_path, old_data->name, sizeof(nimf->base_path));
nimf->format = old_data->im_format;
/* if z buffer is saved, change the image type to multilayer exr.
* XXX this is slightly messy, Z buffer was ignored before for anything but EXR and IRIS ...
* i'm just assuming here that IRIZ means IRIS with z buffer ...
*/
if (ELEM(old_data->im_format.imtype, R_IMF_IMTYPE_IRIZ, R_IMF_IMTYPE_OPENEXR)) {
nimf->format.imtype = R_IMF_IMTYPE_MULTILAYER;
sock = ntreeCompositOutputFileAddSocket(ntree, node, old_image->name, &nimf->format);
if (old_image->link) {
old_image->link->tosock = sock;
sock->link = old_image->link;
}
sock = ntreeCompositOutputFileAddSocket(ntree, node, old_z->name, &nimf->format);
if (old_z->link) {
old_z->link->tosock = sock;
sock->link = old_z->link;
}
}
else {
/* saves directly to base path, which is the old image output path */
sock = ntreeCompositOutputFileAddSocket(ntree, node, "", &nimf->format);
if (old_image->link) {
old_image->link->tosock = sock;
sock->link = old_image->link;
}
}
nodeRemoveSocket(ntree, node, old_image);
nodeRemoveSocket(ntree, node, old_z);
MEM_freeN(old_data);
}
else if (node->type==CMP_NODE_OUTPUT_MULTI_FILE__DEPRECATED) {
NodeImageMultiFile *nimf = node->storage;
/* CMP_NODE_OUTPUT_MULTI_FILE has been redeclared as CMP_NODE_OUTPUT_FILE */
node->type = CMP_NODE_OUTPUT_FILE;
/* initialize the node-wide image format from render data, if available */
if (sce)
nimf->format = sce->r.im_format;
/* transfer render format toggle to node format toggle */
for (sock=node->inputs.first; sock; sock=sock->next) {
NodeImageMultiFileSocket *simf = sock->storage;
simf->use_node_format = simf->use_render_format;
}
/* we do have preview now */
node->flag |= NODE_PREVIEW;
}
}
}
/* blue and red are swapped pre 2.62.1, be sane (red == red) now! */
static void do_versions_mesh_mloopcol_swap_2_62_1(Mesh *me)
{
CustomDataLayer *layer;
MLoopCol *mloopcol;
int a;
int i;
for (a = 0; a < me->ldata.totlayer; a++) {
layer = &me->ldata.layers[a];
if (layer->type == CD_MLOOPCOL) {
mloopcol = (MLoopCol *)layer->data;
for (i = 0; i < me->totloop; i++, mloopcol++) {
SWAP(char, mloopcol->r, mloopcol->b);
}
}
}
}
static void do_versions(FileData *fd, Library *lib, Main *main)
{
/* WATCH IT!!!: pointers from libdata have not been converted */
if (G.debug & G_DEBUG)
printf("read file %s\n Version %d sub %d svn r%d\n", fd->relabase, main->versionfile, main->subversionfile, main->revision);
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;
}
}
}
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 <= 113) {
Material *ma = main->mat.first;
while (ma) {
if (ma->flaresize==0.0f) ma->flaresize= 1.0f;
ma->subsize= 1.0f;
ma->flareboost= 1.0f;
ma= ma->id.next;
}
}
if (main->versionfile <= 134) {
Tex *tex = main->tex.first;
while (tex) {
if ((tex->rfac == 0.0f) &&
(tex->gfac == 0.0f) &&
(tex->bfac == 0.0f)) {
tex->rfac = 1.0f;
tex->gfac = 1.0f;
tex->bfac = 1.0f;
tex->filtersize = 1.0f;
}
tex = tex->id.next;
}
}
if (main->versionfile <= 140) {
/* r-g-b-fac in texture */
Tex *tex = main->tex.first;
while (tex) {
if ((tex->rfac == 0.0f) &&
(tex->gfac == 0.0f) &&
(tex->bfac == 0.0f)) {
tex->rfac = 1.0f;
tex->gfac = 1.0f;
tex->bfac = 1.0f;
tex->filtersize = 1.0f;
}
tex = tex->id.next;
}
}
if (main->versionfile <= 153) {
Scene *sce = main->scene.first;
while (sce) {
if (sce->r.blurfac==0.0f) sce->r.blurfac= 1.0f;
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 = do_version_give_parteff_245(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;
st->lheight= 12;
}
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.0f;
tface->uv[b][1]/= 32767.0f;
}
}
}
me= me->id.next;
}
}
if (main->versionfile <= 191) {
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;*/ /* quats arnt used yet */
ob= ob->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 & (OB_DO_FH|OB_ROT_FH|OB_ANISOTROPIC_FRICTION|OB_GHOST|OB_RIGID_BODY|OB_BOUNDS);
/* 64 is do_fh */
ob->gameflag &= ~(OB_ROT_FH|OB_ANISOTROPIC_FRICTION|OB_GHOST|OB_RIGID_BODY|OB_BOUNDS);
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_ob_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.0f;
oa->forceloc[1]*= 25.0f;
oa->forceloc[2]*= 25.0f;
oa->forcerot[0]*= 10.0f;
oa->forcerot[1]*= 10.0f;
oa->forcerot[2]*= 10.0f;
}
act= act->next;
}
ob= ob->id.next;
}
sound = main->sound.first;
while (sound) {
if (sound->volume < 0.01f) {
sound->volume = 1.0f;
}
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 <= 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;
/* 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 (fabsf(oa->linearvelocity[0]) >= 0.01f)
oa->linearvelocity[0] *= 50.0f;
if (fabsf(oa->linearvelocity[1]) >= 0.01f)
oa->linearvelocity[1] *= 50.0f;
if (fabsf(oa->linearvelocity[2]) >= 0.01f)
oa->linearvelocity[2] *= 50.0f;
if (fabsf(oa->angularvelocity[0])>=0.01f)
oa->angularvelocity[0] *= 50.0f;
if (fabsf(oa->angularvelocity[1])>=0.01f)
oa->angularvelocity[1] *= 50.0f;
if (fabsf(oa->angularvelocity[2])>=0.01f)
oa->angularvelocity[2] *= 50.0f;
}
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.0f)
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 == GPROP_TIME) {
// convert old GPROP_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
* behavior 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.0f) {
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 (strcmp(vf->name+strlen(vf->name)-6, ".Bfont")==0) {
strcpy(vf->name, FO_BUILTIN_NAME);
}
}
/* 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 */
do_version_old_trackto_to_constraints(ob);
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;
sbuts->align= 1; /* horizontal default */
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.0f) 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;
/* introduction of raytrace */
while (ma) {
if (ma->fresnel_tra_i==0.0f) ma->fresnel_tra_i= 1.25f;
if (ma->fresnel_mir_i==0.0f) ma->fresnel_mir_i= 1.25f;
ma->ang= 1.0;
ma->ray_depth= 2;
ma->ray_depth_tra= 2;
ma->fresnel_tra= 0.0;
ma->fresnel_mir= 0.0;
ma= ma->id.next;
}
sce= main->scene.first;
while (sce) {
if (sce->r.gauss==0.0f) sce->r.gauss= 1.0f;
sce= sce->id.next;
}
la= main->lamp.first;
while (la) {
if (la->k==0.0f) 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.0f) la->area_size= 1.0f;
if (la->area_sizey==0.0f) la->area_sizey= 1.0f;
if (la->area_sizez==0.0f) la->area_sizez= 1.0f;
la= la->id.next;
}
wrld= main->world.first;
while (wrld) {
if (wrld->range==0.0f) {
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.0f) {
/* 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.0f) {
wrld->aodist= 10.0f;
wrld->aobias= 0.05f;
}
if (wrld->aosamp==0) wrld->aosamp= 5;
if (wrld->aoenergy==0.0f) wrld->aoenergy= 1.0f;
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.0f) 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.0f) ma->rampfac_col= 1.0;
if (ma->rampfac_spec==0.0f) 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! */
#if 0 /* deprecated in 2.5+ */
while (ob) {
if (ob->ipowin==0) ob->ipowin= ID_OB;
ob= ob->id.next;
}
#endif
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) {
World *wo;
bScreen *sc;
// force sumo engine to be active
for (wo = main->world.first; wo; wo= wo->id.next) {
if (wo->physicsEngine==0) wo->physicsEngine = 2;
}
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_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.0f) tex->nabla= 0.025f;
tex= tex->id.next;
}
while (sce) {
ed= sce->ed;
if (ed) {
SEQ_BEGIN (sce->ed, seq) {
if (seq->type==SEQ_IMAGE || seq->type==SEQ_MOVIE)
seq->flag |= SEQ_MAKE_PREMUL;
}
SEQ_END
}
sce= sce->id.next;
}
}
if (main->versionfile <= 236) {
Object *ob;
Camera *cam= main->camera.first;
Material *ma;
bScreen *sc;
while (cam) {
if (cam->ortho_scale==0.0f) {
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;
}
}
}
}
// init new shader vars
for (ma= main->mat.first; ma; ma= ma->id.next) {
if (ma->darkness==0.0f) {
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.0f) ob->soft->defgoal= 0.7f;
if (ob->soft->physics_speed==0.0f) 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 = defgroup_find_name(ob, "SOFTGOAL");
if (locGroup) {
/* retrieve index for that group */
ob->soft->vertgroup = 1 + BLI_findindex(&ob->defbase, locGroup);
}
}
}
}
if (main->versionfile <= 237) {
bArmature *arm;
bConstraint *con;
Object *ob;
Bone *bone;
// armature recode checks
for (arm= main->armature.first; arm; arm= arm->id.next) {
where_is_armature(arm);
for (bone= arm->bonebase.first; bone; bone= bone->next)
do_version_bone_head_tail_237(bone);
}
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_OB|OB_RECALC_DATA|OB_RECALC_TIME; // 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);
modifier_unique_name(&ob->modifiers, (ModifierData*)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_callocN(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= sce->id.next;
}
for (lt=main->latt.first; lt; lt=lt->id.next) {
if (lt->fu==0.0f && lt->fv==0.0f && lt->fw==0.0f) {
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 = do_version_give_parteff_245(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;
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) {
BLI_snprintf(kb->name, sizeof(kb->name), "Key %d", index);
}
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);
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 */
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;
}
if (ma->mode & MA_TRACEBLE) ma->mode |= MA_SHADBUF;
}
}
if (main->versionfile <= 241) {
Object *ob;
Tex *tex;
Scene *sce;
World *wo;
Lamp *la;
Material *ma;
bArmature *arm;
bNodeTree *ntree;
for (wo = main->world.first; wo; wo= wo->id.next) {
/* Migrate to Bullet for games, except for the NaN versions */
/* People can still explicitly choose for Sumo (after 2.42 is out) */
if (main->versionfile > 225)
wo->physicsEngine = WOPHY_BULLET;
if (WO_AODIST == wo->aomode)
wo->aocolor= WO_AOPLAIN;
}
/* updating layers still */
for (arm= main->armature.first; arm; arm= arm->id.next) {
bone_version_239(&arm->bonebase);
if (arm->layer==0) arm->layer= 1;
}
for (sce= main->scene.first; sce; sce= sce->id.next) {
if (sce->audio.mixrate==0) sce->audio.mixrate= 44100;
if (sce->r.xparts<2) sce->r.xparts= 4;
if (sce->r.yparts<2) sce->r.yparts= 4;
/* adds default layer */
if (sce->r.layers.first==NULL)
scene_add_render_layer(sce, NULL);
else {
SceneRenderLayer *srl;
/* new layer flag for sky, was default for solid */
for (srl= sce->r.layers.first; srl; srl= srl->next) {
if (srl->layflag & SCE_LAY_SOLID)
srl->layflag |= SCE_LAY_SKY;
srl->passflag &= (SCE_PASS_COMBINED|SCE_PASS_Z|SCE_PASS_NORMAL|SCE_PASS_VECTOR);
}
}
/* node version changes */
if (sce->nodetree)
ntree_version_241(sce->nodetree);
/* uv calculation options moved to toolsettings */
if (sce->toolsettings->uvcalc_radius == 0.0f) {
sce->toolsettings->uvcalc_radius = 1.0f;
sce->toolsettings->uvcalc_cubesize = 1.0f;
sce->toolsettings->uvcalc_mapdir = 1;
sce->toolsettings->uvcalc_mapalign = 1;
sce->toolsettings->uvcalc_flag = UVCALC_FILLHOLES;
sce->toolsettings->unwrapper = 1;
}
if (sce->r.mode & R_PANORAMA) {
/* all these checks to ensure saved files with svn version keep working... */
if (sce->r.xsch < sce->r.ysch) {
Object *obc= newlibadr(fd, lib, sce->camera);
if (obc && obc->type==OB_CAMERA) {
Camera *cam= newlibadr(fd, lib, obc->data);
if (cam->lens>=10.0f) {
sce->r.xsch*= sce->r.xparts;
cam->lens*= (float)sce->r.ysch/(float)sce->r.xsch;
}
}
}
}
}
for (ntree= main->nodetree.first; ntree; ntree= ntree->id.next)
ntree_version_241(ntree);
for (la= main->lamp.first; la; la= la->id.next)
if (la->buffers==0)
la->buffers= 1;
for (tex= main->tex.first; tex; tex= tex->id.next) {
if (tex->env && tex->env->viewscale==0.0f)
tex->env->viewscale= 1.0f;
// tex->imaflag |= TEX_GAUSS_MIP;
}
/* for empty drawsize and drawtype */
for (ob=main->object.first; ob; ob= ob->id.next) {
if (ob->empty_drawsize==0.0f) {
ob->empty_drawtype = OB_ARROWS;
ob->empty_drawsize = 1.0;
}
}
for (ma= main->mat.first; ma; ma= ma->id.next) {
/* stucci returns intensity from now on */
int a;
for (a=0; a<MAX_MTEX; a++) {
if (ma->mtex[a] && ma->mtex[a]->tex) {
tex= newlibadr(fd, lib, ma->mtex[a]->tex);
if (tex && tex->type==TEX_STUCCI)
ma->mtex[a]->mapto &= ~(MAP_COL|MAP_SPEC|MAP_REF);
}
}
/* transmissivity defaults */
if (ma->tx_falloff==0.0f) ma->tx_falloff= 1.0f;
}
/* during 2.41 images with this name were used for viewer node output, lets fix that */
if (main->versionfile == 241) {
Image *ima;
for (ima= main->image.first; ima; ima= ima->id.next)
if (strcmp(ima->name, "Compositor")==0) {
strcpy(ima->id.name+2, "Viewer Node");
strcpy(ima->name, "Viewer Node");
}
}
}
if (main->versionfile <= 242) {
Scene *sce;
bScreen *sc;
Object *ob;
Curve *cu;
Material *ma;
Mesh *me;
Group *group;
Nurb *nu;
BezTriple *bezt;
BPoint *bp;
bNodeTree *ntree;
int a;
for (sc= main->screen.first; sc; sc= sc->id.next) {
ScrArea *sa;
sa= sc->areabase.first;
while (sa) {
SpaceLink *sl;
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D*) sl;
if (v3d->gridsubdiv == 0)
v3d->gridsubdiv = 10;
}
}
sa = sa->next;
}
}
for (sce= main->scene.first; sce; sce= sce->id.next) {
if (sce->toolsettings->select_thresh == 0.0f)
sce->toolsettings->select_thresh= 0.01f;
if (sce->toolsettings->clean_thresh == 0.0f)
sce->toolsettings->clean_thresh = 0.1f;
if (sce->r.threads==0) {
if (sce->r.mode & R_THREADS)
sce->r.threads= 2;
else
sce->r.threads= 1;
}
if (sce->nodetree)
ntree_version_242(sce->nodetree);
}
for (ntree= main->nodetree.first; ntree; ntree= ntree->id.next)
ntree_version_242(ntree);
/* add default radius values to old curve points */
for (cu= main->curve.first; cu; cu= cu->id.next) {
for (nu= cu->nurb.first; nu; nu= nu->next) {
if (nu) {
if (nu->bezt) {
for (bezt=nu->bezt, a=0; a<nu->pntsu; a++, bezt++) {
if (!bezt->radius) bezt->radius= 1.0;
}
}
else if (nu->bp) {
for (bp=nu->bp, a=0; a<nu->pntsu*nu->pntsv; a++, bp++) {
if (!bp->radius) bp->radius= 1.0;
}
}
}
}
}
for (ob = main->object.first; ob; ob= ob->id.next) {
ModifierData *md;
ListBase *list;
list = &ob->constraints;
/* check for already existing MinMax (floor) constraint
* and update the sticky flagging */
if (list) {
bConstraint *curcon;
for (curcon = list->first; curcon; curcon=curcon->next) {
switch (curcon->type) {
case CONSTRAINT_TYPE_MINMAX:
{
bMinMaxConstraint *data = curcon->data;
if (data->sticky==1)
data->flag |= MINMAX_STICKY;
else
data->flag &= ~MINMAX_STICKY;
}
break;
case CONSTRAINT_TYPE_ROTLIKE:
{
bRotateLikeConstraint *data = curcon->data;
/* version patch from buttons_object.c */
if (data->flag==0)
data->flag = ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z;
}
break;
}
}
}
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) {
switch (curcon->type) {
case CONSTRAINT_TYPE_MINMAX:
{
bMinMaxConstraint *data = curcon->data;
if (data->sticky==1)
data->flag |= MINMAX_STICKY;
else
data->flag &= ~MINMAX_STICKY;
}
break;
case CONSTRAINT_TYPE_KINEMATIC:
{
bKinematicConstraint *data = curcon->data;
if (!(data->flag & CONSTRAINT_IK_POS)) {
data->flag |= CONSTRAINT_IK_POS;
data->flag |= CONSTRAINT_IK_STRETCH;
}
}
break;
case CONSTRAINT_TYPE_ROTLIKE:
{
bRotateLikeConstraint *data = curcon->data;
/* version patch from buttons_object.c */
if (data->flag==0)
data->flag = ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z;
}
break;
}
}
}
}
}
/* copy old object level track settings to curve modifers */
for (md=ob->modifiers.first; md; md=md->next) {
if (md->type==eModifierType_Curve) {
CurveModifierData *cmd = (CurveModifierData*) md;
if (cmd->defaxis == 0) cmd->defaxis = ob->trackflag+1;
}
}
}
for (ma = main->mat.first; ma; ma= ma->id.next) {
if (ma->shad_alpha==0.0f)
ma->shad_alpha= 1.0f;
if (ma->nodetree)
ntree_version_242(ma->nodetree);
}
for (me=main->mesh.first; me; me=me->id.next)
customdata_version_242(me);
for (group= main->group.first; group; group= group->id.next)
if (group->layer==0)
group->layer= (1<<20)-1;
/* now, subversion control! */
if (main->subversionfile < 3) {
Image *ima;
Tex *tex;
/* Image refactor initialize */
for (ima= main->image.first; ima; ima= ima->id.next) {
ima->source= IMA_SRC_FILE;
ima->type= IMA_TYPE_IMAGE;
ima->gen_x= 256; ima->gen_y= 256;
ima->gen_type= 1;
if (0==strncmp(ima->id.name+2, "Viewer Node", sizeof(ima->id.name)-2)) {
ima->source= IMA_SRC_VIEWER;
ima->type= IMA_TYPE_COMPOSITE;
}
if (0==strncmp(ima->id.name+2, "Render Result", sizeof(ima->id.name)-2)) {
ima->source= IMA_SRC_VIEWER;
ima->type= IMA_TYPE_R_RESULT;
}
}
for (tex= main->tex.first; tex; tex= tex->id.next) {
if (tex->type==TEX_IMAGE && tex->ima) {
ima= newlibadr(fd, lib, tex->ima);
if (tex->imaflag & TEX_ANIM5_)
ima->source= IMA_SRC_MOVIE;
if (tex->imaflag & TEX_FIELDS_)
ima->flag |= IMA_FIELDS;
if (tex->imaflag & TEX_STD_FIELD_)
ima->flag |= IMA_STD_FIELD;
}
tex->iuser.frames= tex->frames;
tex->iuser.fie_ima= (char)tex->fie_ima;
tex->iuser.offset= tex->offset;
tex->iuser.sfra= tex->sfra;
tex->iuser.cycl= (tex->imaflag & TEX_ANIMCYCLIC_)!=0;
}
for (sce= main->scene.first; sce; sce= sce->id.next) {
if (sce->nodetree)
do_version_ntree_242_2(sce->nodetree);
}
for (ntree= main->nodetree.first; ntree; ntree= ntree->id.next)
do_version_ntree_242_2(ntree);
for (ma = main->mat.first; ma; ma= ma->id.next)
if (ma->nodetree)
do_version_ntree_242_2(ma->nodetree);
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_IMAGE)
((SpaceImage *)sl)->iuser.fie_ima= 2;
else if (sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D *)sl;
BGpic *bgpic;
for (bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next)
bgpic->iuser.fie_ima= 2;
}
}
}
}
}
if (main->subversionfile < 4) {
for (sce= main->scene.first; sce; sce= sce->id.next) {
sce->r.bake_mode= 1; /* prevent to include render stuff here */
sce->r.bake_filter= 2;
sce->r.bake_osa= 5;
sce->r.bake_flag= R_BAKE_CLEAR;
}
}
if (main->subversionfile < 5) {
for (sce= main->scene.first; sce; sce= sce->id.next) {
/* improved triangle to quad conversion settings */
if (sce->toolsettings->jointrilimit==0.0f)
sce->toolsettings->jointrilimit= 0.8f;
}
}
}
if (main->versionfile <= 243) {
Object *ob= main->object.first;
Material *ma;
for (ma=main->mat.first; ma; ma= ma->id.next) {
if (ma->sss_scale==0.0f) {
ma->sss_radius[0]= 1.0f;
ma->sss_radius[1]= 1.0f;
ma->sss_radius[2]= 1.0f;
ma->sss_col[0]= 0.8f;
ma->sss_col[1]= 0.8f;
ma->sss_col[2]= 0.8f;
ma->sss_error= 0.05f;
ma->sss_scale= 0.1f;
ma->sss_ior= 1.3f;
ma->sss_colfac= 1.0f;
ma->sss_texfac= 0.0f;
}
if (ma->sss_front==0 && ma->sss_back==0) {
ma->sss_front= 1.0f;
ma->sss_back= 1.0f;
}
if (ma->sss_col[0]==0 && ma->sss_col[1]==0 && ma->sss_col[2]==0) {
ma->sss_col[0]= ma->r;
ma->sss_col[1]= ma->g;
ma->sss_col[2]= ma->b;
}
}
for (; ob; ob= ob->id.next) {
bDeformGroup *curdef;
for (curdef= ob->defbase.first; curdef; curdef=curdef->next) {
/* replace an empty-string name with unique name */
if (curdef->name[0] == '\0') {
defgroup_unique_name(curdef, ob);
}
}
if (main->versionfile < 243 || main->subversionfile < 1) {
ModifierData *md;
/* translate old mirror modifier axis values to new flags */
for (md=ob->modifiers.first; md; md=md->next) {
if (md->type==eModifierType_Mirror) {
MirrorModifierData *mmd = (MirrorModifierData*) md;
switch (mmd->axis) {
case 0:
mmd->flag |= MOD_MIR_AXIS_X;
break;
case 1:
mmd->flag |= MOD_MIR_AXIS_Y;
break;
case 2:
mmd->flag |= MOD_MIR_AXIS_Z;
break;
}
mmd->axis = 0;
}
}
}
}
/* render layer added, this is not the active layer */
if (main->versionfile <= 243 || main->subversionfile < 2) {
Mesh *me;
for (me=main->mesh.first; me; me=me->id.next)
customdata_version_243(me);
}
}
if (main->versionfile <= 244) {
Scene *sce;
bScreen *sc;
Lamp *la;
World *wrld;
if (main->versionfile != 244 || main->subversionfile < 2) {
for (sce= main->scene.first; sce; sce= sce->id.next)
sce->r.mode |= R_SSS;
/* correct older action editors - incorrect scrolling */
for (sc= main->screen.first; sc; sc= sc->id.next) {
ScrArea *sa;
sa= sc->areabase.first;
while (sa) {
SpaceLink *sl;
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_ACTION) {
SpaceAction *saction= (SpaceAction*) sl;
saction->v2d.tot.ymin = -1000.0;
saction->v2d.tot.ymax = 0.0;
saction->v2d.cur.ymin = -75.0;
saction->v2d.cur.ymax = 5.0;
}
}
sa = sa->next;
}
}
}
if (main->versionfile != 244 || main->subversionfile < 3) {
/* constraints recode version patch used to be here. Moved to 245 now... */
for (wrld=main->world.first; wrld; wrld= wrld->id.next) {
if (wrld->mode & WO_AMB_OCC)
wrld->ao_samp_method = WO_AOSAMP_CONSTANT;
else
wrld->ao_samp_method = WO_AOSAMP_HAMMERSLEY;
wrld->ao_adapt_thresh = 0.005f;
}
for (la=main->lamp.first; la; la= la->id.next) {
if (la->type == LA_AREA)
la->ray_samp_method = LA_SAMP_CONSTANT;
else
la->ray_samp_method = LA_SAMP_HALTON;
la->adapt_thresh = 0.001f;
}
}
}
if (main->versionfile <= 245) {
Scene *sce;
Object *ob;
Image *ima;
Lamp *la;
Material *ma;
ParticleSettings *part;
World *wrld;
Mesh *me;
bNodeTree *ntree;
Tex *tex;
ModifierData *md;
ParticleSystem *psys;
/* unless the file was created 2.44.3 but not 2.45, update the constraints */
if ( !(main->versionfile==244 && main->subversionfile==3) &&
((main->versionfile<245) || (main->versionfile==245 && main->subversionfile==0)) )
{
for (ob = main->object.first; ob; ob= ob->id.next) {
ListBase *list;
list = &ob->constraints;
/* fix up constraints due to constraint recode changes (originally at 2.44.3) */
if (list) {
bConstraint *curcon;
for (curcon = list->first; curcon; curcon=curcon->next) {
/* old CONSTRAINT_LOCAL check -> convert to CONSTRAINT_SPACE_LOCAL */
if (curcon->flag & 0x20) {
curcon->ownspace = CONSTRAINT_SPACE_LOCAL;
curcon->tarspace = CONSTRAINT_SPACE_LOCAL;
}
switch (curcon->type) {
case CONSTRAINT_TYPE_LOCLIMIT:
{
bLocLimitConstraint *data= (bLocLimitConstraint *)curcon->data;
/* old limit without parent option for objects */
if (data->flag2)
curcon->ownspace = CONSTRAINT_SPACE_LOCAL;
}
break;
}
}
}
/* correctly initialize constinv matrix */
unit_m4(ob->constinv);
if (ob->type == OB_ARMATURE) {
if (ob->pose) {
bConstraint *curcon;
bPoseChannel *pchan;
for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
/* make sure constraints are all up to date */
for (curcon = pchan->constraints.first; curcon; curcon=curcon->next) {
/* old CONSTRAINT_LOCAL check -> convert to CONSTRAINT_SPACE_LOCAL */
if (curcon->flag & 0x20) {
curcon->ownspace = CONSTRAINT_SPACE_LOCAL;
curcon->tarspace = CONSTRAINT_SPACE_LOCAL;
}
switch (curcon->type) {
case CONSTRAINT_TYPE_ACTION:
{
bActionConstraint *data= (bActionConstraint *)curcon->data;
/* 'data->local' used to mean that target was in local-space */
if (data->local)
curcon->tarspace = CONSTRAINT_SPACE_LOCAL;
}
break;
}
}
/* correctly initialize constinv matrix */
unit_m4(pchan->constinv);
}
}
}
}
}
/* fix all versions before 2.45 */
if (main->versionfile != 245) {
/* repair preview from 242 - 244*/
for (ima= main->image.first; ima; ima= ima->id.next) {
ima->preview = NULL;
}
}
/* add point caches */
for (ob=main->object.first; ob; ob=ob->id.next) {
if (ob->soft && !ob->soft->pointcache)
ob->soft->pointcache= BKE_ptcache_add(&ob->soft->ptcaches);
for (psys=ob->particlesystem.first; psys; psys=psys->next) {
if (psys->pointcache) {
if (psys->pointcache->flag & PTCACHE_BAKED && (psys->pointcache->flag & PTCACHE_DISK_CACHE)==0) {
printf("Old memory cache isn't supported for particles, so re-bake the simulation!\n");
psys->pointcache->flag &= ~PTCACHE_BAKED;
}
}
else
psys->pointcache= BKE_ptcache_add(&psys->ptcaches);
}
for (md=ob->modifiers.first; md; md=md->next) {
if (md->type==eModifierType_Cloth) {
ClothModifierData *clmd = (ClothModifierData*) md;
if (!clmd->point_cache)
clmd->point_cache= BKE_ptcache_add(&clmd->ptcaches);
}
}
}
/* Copy over old per-level multires vertex data
* into a single vertex array in struct Multires */
for (me = main->mesh.first; me; me=me->id.next) {
if (me->mr && !me->mr->verts) {
MultiresLevel *lvl = me->mr->levels.last;
if (lvl) {
me->mr->verts = lvl->verts;
lvl->verts = NULL;
/* Don't need the other vert arrays */
for (lvl = lvl->prev; lvl; lvl = lvl->prev) {
MEM_freeN(lvl->verts);
lvl->verts = NULL;
}
}
}
}
if (main->versionfile != 245 || main->subversionfile < 1) {
for (la=main->lamp.first; la; la= la->id.next) {
if (la->mode & LA_QUAD) la->falloff_type = LA_FALLOFF_SLIDERS;
else la->falloff_type = LA_FALLOFF_INVLINEAR;
if (la->curfalloff == NULL) {
la->curfalloff = curvemapping_add(1, 0.0f, 1.0f, 1.0f, 0.0f);
curvemapping_initialize(la->curfalloff);
}
}
}
for (ma=main->mat.first; ma; ma= ma->id.next) {
if (ma->samp_gloss_mir == 0) {
ma->gloss_mir = ma->gloss_tra= 1.0f;
ma->aniso_gloss_mir = 1.0f;
ma->samp_gloss_mir = ma->samp_gloss_tra= 18;
ma->adapt_thresh_mir = ma->adapt_thresh_tra = 0.005f;
ma->dist_mir = 0.0f;
ma->fadeto_mir = MA_RAYMIR_FADETOSKY;
}
if (ma->strand_min == 0.0f)
ma->strand_min= 1.0f;
}
for (part=main->particle.first; part; part=part->id.next) {
if (part->ren_child_nbr==0)
part->ren_child_nbr= part->child_nbr;
if (part->simplify_refsize==0) {
part->simplify_refsize= 1920;
part->simplify_rate= 1.0f;
part->simplify_transition= 0.1f;
part->simplify_viewport= 0.8f;
}
}
for (wrld=main->world.first; wrld; wrld= wrld->id.next) {
if (wrld->ao_approx_error == 0.0f)
wrld->ao_approx_error= 0.25f;
}
for (sce= main->scene.first; sce; sce= sce->id.next) {
if (sce->nodetree)
ntree_version_245(fd, lib, sce->nodetree);
if (sce->r.simplify_shadowsamples == 0) {
sce->r.simplify_subsurf= 6;
sce->r.simplify_particles= 1.0f;
sce->r.simplify_shadowsamples= 16;
sce->r.simplify_aosss= 1.0f;
}
if (sce->r.cineongamma == 0) {
sce->r.cineonblack= 95;
sce->r.cineonwhite= 685;
sce->r.cineongamma= 1.7f;
}
}
for (ntree=main->nodetree.first; ntree; ntree= ntree->id.next)
ntree_version_245(fd, lib, ntree);
/* fix for temporary flag changes during 245 cycle */
for (ima= main->image.first; ima; ima= ima->id.next) {
if (ima->flag & IMA_OLD_PREMUL) {
ima->flag &= ~IMA_OLD_PREMUL;
ima->flag |= IMA_DO_PREMUL;
}
}
for (tex=main->tex.first; tex; tex=tex->id.next) {
if (tex->iuser.flag & IMA_OLD_PREMUL) {
tex->iuser.flag &= ~IMA_OLD_PREMUL;
tex->iuser.flag |= IMA_DO_PREMUL;
}
ima= newlibadr(fd, lib, tex->ima);
if (ima && (tex->iuser.flag & IMA_DO_PREMUL)) {
ima->flag &= ~IMA_OLD_PREMUL;
ima->flag |= IMA_DO_PREMUL;
}
}
}
/* sanity check for skgen
* */
{
Scene *sce;
for (sce=main->scene.first; sce; sce = sce->id.next) {
if (sce->toolsettings->skgen_subdivisions[0] == sce->toolsettings->skgen_subdivisions[1] ||
sce->toolsettings->skgen_subdivisions[0] == sce->toolsettings->skgen_subdivisions[2] ||
sce->toolsettings->skgen_subdivisions[1] == sce->toolsettings->skgen_subdivisions[2])
{
sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_CORRELATION;
sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH;
sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE;
}
}
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 2)) {
Image *ima;
/* initialize 1:1 Aspect */
for (ima= main->image.first; ima; ima= ima->id.next) {
ima->aspx = ima->aspy = 1.0f;
}
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 4)) {
bArmature *arm;
ModifierData *md;
Object *ob;
for (arm= main->armature.first; arm; arm= arm->id.next)
arm->deformflag |= ARM_DEF_B_BONE_REST;
for (ob = main->object.first; ob; ob= ob->id.next) {
for (md=ob->modifiers.first; md; md=md->next) {
if (md->type==eModifierType_Armature)
((ArmatureModifierData*)md)->deformflag |= ARM_DEF_B_BONE_REST;
}
}
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 5)) {
/* foreground color needs to be something other then black */
Scene *sce;
for (sce= main->scene.first; sce; sce=sce->id.next) {
sce->r.fg_stamp[0] = sce->r.fg_stamp[1] = sce->r.fg_stamp[2] = 0.8f;
sce->r.fg_stamp[3] = 1.0f; /* don't use text alpha yet */
sce->r.bg_stamp[3] = 0.25f; /* make sure the background has full alpha */
}
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 6)) {
Scene *sce;
/* fix frs_sec_base */
for (sce= main->scene.first; sce; sce= sce->id.next) {
if (sce->r.frs_sec_base == 0) {
sce->r.frs_sec_base = 1;
}
}
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 7)) {
Object *ob;
bPoseChannel *pchan;
bConstraint *con;
bConstraintTarget *ct;
for (ob = main->object.first; ob; ob= ob->id.next) {
if (ob->pose) {
for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
for (con=pchan->constraints.first; con; con=con->next) {
if (con->type == CONSTRAINT_TYPE_PYTHON) {
bPythonConstraint *data= (bPythonConstraint *)con->data;
if (data->tar) {
/* version patching needs to be done */
ct= MEM_callocN(sizeof(bConstraintTarget), "PyConTarget");
ct->tar = data->tar;
BLI_strncpy(ct->subtarget, data->subtarget, sizeof(ct->subtarget));
ct->space = con->tarspace;
BLI_addtail(&data->targets, ct);
data->tarnum++;
/* clear old targets to avoid problems */
data->tar = NULL;
data->subtarget[0]= '\0';
}
}
else if (con->type == CONSTRAINT_TYPE_LOCLIKE) {
bLocateLikeConstraint *data= (bLocateLikeConstraint *)con->data;
/* new headtail functionality makes Bone-Tip function obsolete */
if (data->flag & LOCLIKE_TIP)
con->headtail = 1.0f;
}
}
}
}
for (con=ob->constraints.first; con; con=con->next) {
if (con->type==CONSTRAINT_TYPE_PYTHON) {
bPythonConstraint *data= (bPythonConstraint *)con->data;
if (data->tar) {
/* version patching needs to be done */
ct= MEM_callocN(sizeof(bConstraintTarget), "PyConTarget");
ct->tar = data->tar;
BLI_strncpy(ct->subtarget, data->subtarget, sizeof(ct->subtarget));
ct->space = con->tarspace;
BLI_addtail(&data->targets, ct);
data->tarnum++;
/* clear old targets to avoid problems */
data->tar = NULL;
data->subtarget[0]= '\0';
}
}
else if (con->type == CONSTRAINT_TYPE_LOCLIKE) {
bLocateLikeConstraint *data= (bLocateLikeConstraint *)con->data;
/* new headtail functionality makes Bone-Tip function obsolete */
if (data->flag & LOCLIKE_TIP)
con->headtail = 1.0f;
}
}
if (ob->soft && ob->soft->keys) {
SoftBody *sb = ob->soft;
int k;
for (k=0; k<sb->totkey; k++) {
if (sb->keys[k])
MEM_freeN(sb->keys[k]);
}
MEM_freeN(sb->keys);
sb->keys = NULL;
sb->totkey = 0;
}
}
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 8)) {
Scene *sce;
Object *ob;
PartEff *paf=NULL;
for (ob = main->object.first; ob; ob= ob->id.next) {
if (ob->soft && ob->soft->keys) {
SoftBody *sb = ob->soft;
int k;
for (k=0; k<sb->totkey; k++) {
if (sb->keys[k])
MEM_freeN(sb->keys[k]);
}
MEM_freeN(sb->keys);
sb->keys = NULL;
sb->totkey = 0;
}
/* convert old particles to new system */
if ((paf = do_version_give_parteff_245(ob))) {
ParticleSystem *psys;
ModifierData *md;
ParticleSystemModifierData *psmd;
ParticleSettings *part;
/* create new particle system */
psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
part = psys->part = psys_new_settings("ParticleSettings", main);
/* needed for proper libdata lookup */
oldnewmap_insert(fd->libmap, psys->part, psys->part, 0);
part->id.lib= ob->id.lib;
part->id.us--;
part->id.flag |= (ob->id.flag & LIB_NEEDLINK);
psys->totpart=0;
psys->flag= PSYS_ENABLED|PSYS_CURRENT;
BLI_addtail(&ob->particlesystem, psys);
md= modifier_new(eModifierType_ParticleSystem);
BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", BLI_countlist(&ob->particlesystem));
psmd= (ParticleSystemModifierData*) md;
psmd->psys=psys;
BLI_addtail(&ob->modifiers, md);
/* convert settings from old particle system */
/* general settings */
part->totpart = MIN2(paf->totpart, 100000);
part->sta = paf->sta;
part->end = paf->end;
part->lifetime = paf->lifetime;
part->randlife = paf->randlife;
psys->seed = paf->seed;
part->disp = paf->disp;
part->omat = paf->mat[0];
part->hair_step = paf->totkey;
part->eff_group = paf->group;
/* old system didn't interpolate between keypoints at render time */
part->draw_step = part->ren_step = 0;
/* physics */
part->normfac = paf->normfac * 25.0f;
part->obfac = paf->obfac;
part->randfac = paf->randfac * 25.0f;
part->dampfac = paf->damp;
copy_v3_v3(part->acc, paf->force);
/* flags */
if (paf->stype & PAF_VECT) {
if (paf->flag & PAF_STATIC) {
/* new hair lifetime is always 100.0f */
float fac = paf->lifetime / 100.0f;
part->draw_as = PART_DRAW_PATH;
part->type = PART_HAIR;
psys->recalc |= PSYS_RECALC_REDO;
part->normfac *= fac;
part->randfac *= fac;
}
else {
part->draw_as = PART_DRAW_LINE;
part->draw |= PART_DRAW_VEL_LENGTH;
part->draw_line[1] = 0.04f;
}
}
part->rotmode = PART_ROT_VEL;
part->flag |= (paf->flag & PAF_BSPLINE) ? PART_HAIR_BSPLINE : 0;
part->flag |= (paf->flag & PAF_TRAND) ? PART_TRAND : 0;
part->flag |= (paf->flag & PAF_EDISTR) ? PART_EDISTR : 0;
part->flag |= (paf->flag & PAF_UNBORN) ? PART_UNBORN : 0;
part->flag |= (paf->flag & PAF_DIED) ? PART_DIED : 0;
part->from |= (paf->flag & PAF_FACE) ? PART_FROM_FACE : 0;
part->draw |= (paf->flag & PAF_SHOWE) ? PART_DRAW_EMITTER : 0;
psys->vgroup[PSYS_VG_DENSITY] = paf->vertgroup;
psys->vgroup[PSYS_VG_VEL] = paf->vertgroup_v;
psys->vgroup[PSYS_VG_LENGTH] = paf->vertgroup_v;
/* dupliobjects */
if (ob->transflag & OB_DUPLIVERTS) {
Object *dup = main->object.first;
for (; dup; dup= dup->id.next) {
if (ob == newlibadr(fd, lib, dup->parent)) {
part->dup_ob = dup;
ob->transflag |= OB_DUPLIPARTS;
ob->transflag &= ~OB_DUPLIVERTS;
part->draw_as = PART_DRAW_OB;
/* needed for proper libdata lookup */
oldnewmap_insert(fd->libmap, dup, dup, 0);
}
}
}
{
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
if (fluidmd && fluidmd->fss && fluidmd->fss->type == OB_FLUIDSIM_PARTICLE)
part->type = PART_FLUID;
}
do_version_free_effects_245(&ob->effect);
printf("Old particle system converted to new system.\n");
}
}
for (sce= main->scene.first; sce; sce=sce->id.next) {
ParticleEditSettings *pset= &sce->toolsettings->particle;
int a;
if (pset->brush[0].size == 0) {
pset->flag= PE_KEEP_LENGTHS|PE_LOCK_FIRST|PE_DEFLECT_EMITTER;
pset->emitterdist= 0.25f;
pset->totrekey= 5;
pset->totaddkey= 5;
pset->brushtype= PE_BRUSH_NONE;
for (a=0; a<PE_TOT_BRUSH; a++) {
pset->brush[a].strength= 50;
pset->brush[a].size= 50;
pset->brush[a].step= 10;
}
pset->brush[PE_BRUSH_CUT].strength= 100;
}
}
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 9)) {
Material *ma;
int a;
for (ma=main->mat.first; ma; ma= ma->id.next)
if (ma->mode & MA_NORMAP_TANG)
for (a=0; a<MAX_MTEX; a++)
if (ma->mtex[a] && ma->mtex[a]->tex)
ma->mtex[a]->normapspace = MTEX_NSPACE_TANGENT;
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 10)) {
Object *ob;
/* dupliface scale */
for (ob= main->object.first; ob; ob= ob->id.next)
ob->dupfacesca = 1.0f;
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 11)) {
Object *ob;
bActionStrip *strip;
/* nla-strips - scale */
for (ob= main->object.first; ob; ob= ob->id.next) {
for (strip= ob->nlastrips.first; strip; strip= strip->next) {
float length, actlength, repeat;
if (strip->flag & ACTSTRIP_USESTRIDE)
repeat= 1.0f;
else
repeat= strip->repeat;
length = strip->end-strip->start;
if (length == 0.0f) length= 1.0f;
actlength = strip->actend-strip->actstart;
strip->scale = length / (repeat * actlength);
if (strip->scale == 0.0f) strip->scale= 1.0f;
}
if (ob->soft) {
ob->soft->inpush = ob->soft->inspring;
ob->soft->shearstiff = 1.0f;
}
}
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 14)) {
Scene *sce;
Sequence *seq;
for (sce=main->scene.first; sce; sce=sce->id.next) {
SEQ_BEGIN (sce->ed, seq) {
if (seq->blend_mode == 0)
seq->blend_opacity = 100.0f;
}
SEQ_END
}
}
/*fix broken group lengths in id properties*/
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 15)) {
idproperties_fix_group_lengths(main->scene);
idproperties_fix_group_lengths(main->library);
idproperties_fix_group_lengths(main->object);
idproperties_fix_group_lengths(main->mesh);
idproperties_fix_group_lengths(main->curve);
idproperties_fix_group_lengths(main->mball);
idproperties_fix_group_lengths(main->mat);
idproperties_fix_group_lengths(main->tex);
idproperties_fix_group_lengths(main->image);
idproperties_fix_group_lengths(main->latt);
idproperties_fix_group_lengths(main->lamp);
idproperties_fix_group_lengths(main->camera);
idproperties_fix_group_lengths(main->ipo);
idproperties_fix_group_lengths(main->key);
idproperties_fix_group_lengths(main->world);
idproperties_fix_group_lengths(main->screen);
idproperties_fix_group_lengths(main->script);
idproperties_fix_group_lengths(main->vfont);
idproperties_fix_group_lengths(main->text);
idproperties_fix_group_lengths(main->sound);
idproperties_fix_group_lengths(main->group);
idproperties_fix_group_lengths(main->armature);
idproperties_fix_group_lengths(main->action);
idproperties_fix_group_lengths(main->nodetree);
idproperties_fix_group_lengths(main->brush);
idproperties_fix_group_lengths(main->particle);
}
/* sun/sky */
if (main->versionfile < 246) {
Object *ob;
bActuator *act;
/* dRot actuator change direction in 2.46 */
for (ob = main->object.first; ob; ob= ob->id.next) {
for (act= ob->actuators.first; act; act= act->next) {
if (act->type == ACT_OBJECT) {
bObjectActuator *ba= act->data;
ba->drot[0] = -ba->drot[0];
ba->drot[1] = -ba->drot[1];
ba->drot[2] = -ba->drot[2];
}
}
}
}
// convert fluids to modifier
if (main->versionfile < 246 || (main->versionfile == 246 && main->subversionfile < 1)) {
Object *ob;
for (ob = main->object.first; ob; ob= ob->id.next) {
if (ob->fluidsimSettings) {
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifier_new(eModifierType_Fluidsim);
BLI_addhead(&ob->modifiers, (ModifierData *)fluidmd);
MEM_freeN(fluidmd->fss);
fluidmd->fss = MEM_dupallocN(ob->fluidsimSettings);
fluidmd->fss->ipo = newlibadr_us(fd, ob->id.lib, ob->fluidsimSettings->ipo);
MEM_freeN(ob->fluidsimSettings);
fluidmd->fss->lastgoodframe = INT_MAX;
fluidmd->fss->flag = 0;
fluidmd->fss->meshVelocities = NULL;
}
}
}
if (main->versionfile < 246 || (main->versionfile == 246 && main->subversionfile < 1)) {
Mesh *me;
for (me=main->mesh.first; me; me= me->id.next)
alphasort_version_246(fd, lib, me);
}
if (main->versionfile < 246 || (main->versionfile == 246 && main->subversionfile < 1)) {
Object *ob;
for (ob = main->object.first; ob; ob= ob->id.next) {
if (ob->pd && (ob->pd->forcefield == PFIELD_WIND))
ob->pd->f_noise = 0.0f;
}
}
if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 2)) {
Object *ob;
for (ob = main->object.first; ob; ob= ob->id.next) {
ob->gameflag |= OB_COLLISION;
ob->margin = 0.06f;
}
}
if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 3)) {
Object *ob;
for (ob = main->object.first; ob; ob= ob->id.next) {
// Starting from subversion 3, ACTOR is a separate feature.
// Before it was conditioning all the other dynamic flags
if (!(ob->gameflag & OB_ACTOR))
ob->gameflag &= ~(OB_GHOST|OB_DYNAMIC|OB_RIGID_BODY|OB_SOFT_BODY|OB_COLLISION_RESPONSE);
/* suitable default for older files */
}
}
if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 5)) {
Lamp *la= main->lamp.first;
for (; la; la= la->id.next) {
la->skyblendtype= MA_RAMP_ADD;
la->skyblendfac= 1.0f;
}
}
/* set the curve radius interpolation to 2.47 default - easy */
if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 6)) {
Curve *cu;
Nurb *nu;
for (cu= main->curve.first; cu; cu= cu->id.next) {
for (nu= cu->nurb.first; nu; nu= nu->next) {
if (nu) {
nu->radius_interp = 3;
/* resolu and resolv are now used differently for surfaces
* rather than using the resolution to define the entire number of divisions,
* use it for the number of divisions per segment
*/
if (nu->pntsv > 1) {
nu->resolu = MAX2( 1, (int)(((float)nu->resolu / (float)nu->pntsu)+0.5f) );
nu->resolv = MAX2( 1, (int)(((float)nu->resolv / (float)nu->pntsv)+0.5f) );
}
}
}
}
}
/* direction constraint actuators were always local in previous version */
if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 7)) {
bActuator *act;
Object *ob;
for (ob = main->object.first; ob; ob= ob->id.next) {
for (act= ob->actuators.first; act; act= act->next) {
if (act->type == ACT_CONSTRAINT) {
bConstraintActuator *coa = act->data;
if (coa->type == ACT_CONST_TYPE_DIST) {
coa->flag |= ACT_CONST_LOCAL;
}
}
}
}
}
if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 9)) {
Lamp *la= main->lamp.first;
for (; la; la= la->id.next) {
la->sky_exposure= 1.0f;
}
}
/* BGE message actuators needed OB prefix, very confusing */
if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 10)) {
bActuator *act;
Object *ob;
for (ob = main->object.first; ob; ob= ob->id.next) {
for (act= ob->actuators.first; act; act= act->next) {
if (act->type == ACT_MESSAGE) {
bMessageActuator *msgAct = (bMessageActuator *) act->data;
if (BLI_strnlen(msgAct->toPropName, 3) > 2) {
/* strip first 2 chars, would have only worked if these were OB anyway */
memmove(msgAct->toPropName, msgAct->toPropName + 2, sizeof(msgAct->toPropName) - 2);
}
else {
msgAct->toPropName[0] = '\0';
}
}
}
}
}
if (main->versionfile < 248) {
Lamp *la;
for (la=main->lamp.first; la; la= la->id.next) {
if (la->atm_turbidity == 0.0f) {
la->sun_effect_type = 0;
la->horizon_brightness = 1.0f;
la->spread = 1.0f;
la->sun_brightness = 1.0f;
la->sun_size = 1.0f;
la->backscattered_light = 1.0f;
la->atm_turbidity = 2.0f;
la->atm_inscattering_factor = 1.0f;
la->atm_extinction_factor = 1.0f;
la->atm_distance_factor = 1.0f;
la->sun_intensity = 1.0f;
}
}
}
if (main->versionfile < 248 || (main->versionfile == 248 && main->subversionfile < 2)) {
Scene *sce;
/* Note, these will need to be added for painting */
for (sce= main->scene.first; sce; sce= sce->id.next) {
sce->toolsettings->imapaint.seam_bleed = 2;
sce->toolsettings->imapaint.normal_angle = 80;
/* initialize skeleton generation toolsettings */
sce->toolsettings->skgen_resolution = 250;
sce->toolsettings->skgen_threshold_internal = 0.1f;
sce->toolsettings->skgen_threshold_external = 0.1f;
sce->toolsettings->skgen_angle_limit = 30.0f;
sce->toolsettings->skgen_length_ratio = 1.3f;
sce->toolsettings->skgen_length_limit = 1.5f;
sce->toolsettings->skgen_correlation_limit = 0.98f;
sce->toolsettings->skgen_symmetry_limit = 0.1f;
sce->toolsettings->skgen_postpro = SKGEN_SMOOTH;
sce->toolsettings->skgen_postpro_passes = 3;
sce->toolsettings->skgen_options = SKGEN_FILTER_INTERNAL|SKGEN_FILTER_EXTERNAL|SKGEN_FILTER_SMART|SKGEN_SUB_CORRELATION|SKGEN_HARMONIC;
sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_CORRELATION;
sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH;
sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE;
sce->toolsettings->skgen_retarget_angle_weight = 1.0f;
sce->toolsettings->skgen_retarget_length_weight = 1.0f;
sce->toolsettings->skgen_retarget_distance_weight = 1.0f;
/* Skeleton Sketching */
sce->toolsettings->bone_sketching = 0;
sce->toolsettings->skgen_retarget_roll = SK_RETARGET_ROLL_VIEW;
}
}
if (main->versionfile < 248 || (main->versionfile == 248 && main->subversionfile < 3)) {
bScreen *sc;
/* adjust default settings for Animation Editors */
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) {
switch (sl->spacetype) {
case SPACE_ACTION:
{
SpaceAction *sact= (SpaceAction *)sl;
sact->mode= SACTCONT_DOPESHEET;
sact->autosnap= SACTSNAP_FRAME;
}
break;
case SPACE_IPO:
{
SpaceIpo *sipo= (SpaceIpo *)sl;
sipo->autosnap= SACTSNAP_FRAME;
}
break;
case SPACE_NLA:
{
SpaceNla *snla= (SpaceNla *)sl;
snla->autosnap= SACTSNAP_FRAME;
}
break;
}
}
}
}
}
if (main->versionfile < 248 || (main->versionfile == 248 && main->subversionfile < 3)) {
Object *ob;
/* Adjustments needed after Bullets update */
for (ob = main->object.first; ob; ob= ob->id.next) {
ob->damping *= 0.635f;
ob->rdamping = 0.1f + (0.8f * ob->rdamping);
}
}
if (main->versionfile < 248 || (main->versionfile == 248 && main->subversionfile < 4)) {
Scene *sce;
World *wrld;
/* Dome (Fisheye) default parameters */
for (sce= main->scene.first; sce; sce= sce->id.next) {
sce->r.domeangle = 180;
sce->r.domemode = 1;
sce->r.domeres = 4;
sce->r.domeresbuf = 1.0f;
sce->r.dometilt = 0;
}
/* DBVT culling by default */
for (wrld=main->world.first; wrld; wrld= wrld->id.next) {
wrld->mode |= WO_DBVT_CULLING;
wrld->occlusionRes = 128;
}
}
if (main->versionfile < 248 || (main->versionfile == 248 && main->subversionfile < 5)) {
Object *ob;
World *wrld;
for (ob = main->object.first; ob; ob= ob->id.next) {
ob->m_contactProcessingThreshold = 1.0f; //pad3 is used for m_contactProcessingThreshold
if (ob->parent) {
/* check if top parent has compound shape set and if yes, set this object
* to compound shaper as well (was the behavior before, now it's optional) */
Object *parent= newlibadr(fd, lib, ob->parent);
while (parent && parent != ob && parent->parent != NULL) {
parent = newlibadr(fd, lib, parent->parent);
}
if (parent) {
if (parent->gameflag & OB_CHILD)
ob->gameflag |= OB_CHILD;
}
}
}
for (wrld=main->world.first; wrld; wrld= wrld->id.next) {
wrld->ticrate = 60;
wrld->maxlogicstep = 5;
wrld->physubstep = 1;
wrld->maxphystep = 5;
}
}
// correct introduce of seed for wind force
if (main->versionfile < 249 && main->subversionfile < 1) {
Object *ob;
for (ob = main->object.first; ob; ob= ob->id.next) {
if (ob->pd)
ob->pd->seed = ((unsigned int)(ceil(PIL_check_seconds_timer()))+1) % 128;
}
}
if (main->versionfile < 249 && main->subversionfile < 2) {
Scene *sce= main->scene.first;
Sequence *seq;
Editing *ed;
while (sce) {
ed= sce->ed;
if (ed) {
SEQP_BEGIN (ed, seq) {
if (seq->strip && seq->strip->proxy) {
seq->strip->proxy->quality =90;
}
}
SEQ_END
}
sce= sce->id.next;
}
}
if (main->versionfile < 250) {
bScreen *screen;
Scene *scene;
Base *base;
Material *ma;
Camera *cam;
Mesh *me;
Curve *cu;
Scene *sce;
Tex *tx;
ParticleSettings *part;
Object *ob;
//PTCacheID *pid;
//ListBase pidlist;
bSound *sound;
Sequence *seq;
bActuator *act;
int a;
for (sound = main->sound.first; sound; sound = sound->id.next) {
if (sound->newpackedfile) {
sound->packedfile = sound->newpackedfile;
sound->newpackedfile = NULL;
}
}
for (ob = main->object.first; ob; ob= ob->id.next) {
for (act= ob->actuators.first; act; act= act->next) {
if (act->type == ACT_SOUND) {
bSoundActuator *sAct = (bSoundActuator*) act->data;
if (sAct->sound) {
sound = newlibadr(fd, lib, sAct->sound);
sAct->flag = sound->flags & SOUND_FLAGS_3D ? ACT_SND_3D_SOUND : 0;
sAct->pitch = sound->pitch;
sAct->volume = sound->volume;
sAct->sound3D.reference_distance = sound->distance;
sAct->sound3D.max_gain = sound->max_gain;
sAct->sound3D.min_gain = sound->min_gain;
sAct->sound3D.rolloff_factor = sound->attenuation;
}
else {
sAct->sound3D.reference_distance = 1.0f;
sAct->volume = 1.0f;
sAct->sound3D.max_gain = 1.0f;
sAct->sound3D.rolloff_factor = 1.0f;
}
sAct->sound3D.cone_inner_angle = 360.0f;
sAct->sound3D.cone_outer_angle = 360.0f;
sAct->sound3D.max_distance = FLT_MAX;
}
}
}
for (scene = main->scene.first; scene; scene = scene->id.next) {
if (scene->ed && scene->ed->seqbasep) {
SEQ_BEGIN (scene->ed, seq) {
if (seq->type == SEQ_HD_SOUND) {
char str[FILE_MAX];
BLI_join_dirfile(str, sizeof(str), seq->strip->dir, seq->strip->stripdata->name);
BLI_path_abs(str, main->name);
seq->sound = sound_new_file(main, str);
}
/* don't know, if anybody used that
* this way, but just in case, upgrade
* to new way... */
if ((seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) &&
!(seq->flag & SEQ_USE_PROXY_CUSTOM_DIR))
{
BLI_snprintf(seq->strip->proxy->dir,
FILE_MAXDIR, "%s/BL_proxy",
seq->strip->dir);
}
}
SEQ_END
}
}
for (screen= main->screen.first; screen; screen= screen->id.next) {
do_versions_windowmanager_2_50(screen);
do_versions_gpencil_2_50(main, screen);
}
/* shader, composite and texture node trees have id.name empty, put something in
* to have them show in RNA viewer and accessible otherwise.
*/
for (ma= main->mat.first; ma; ma= ma->id.next) {
if (ma->nodetree && ma->nodetree->id.name[0] == '\0')
strcpy(ma->nodetree->id.name, "NTShader Nodetree");
/* which_output 0 is now "not specified" */
for (a=0; a<MAX_MTEX; a++) {
if (ma->mtex[a]) {
tx= newlibadr(fd, lib, ma->mtex[a]->tex);
if (tx && tx->use_nodes)
ma->mtex[a]->which_output++;
}
}
}
/* and composite trees */
for (sce= main->scene.first; sce; sce= sce->id.next) {
if (sce->nodetree && sce->nodetree->id.name[0] == '\0')
strcpy(sce->nodetree->id.name, "NTCompositing Nodetree");
/* move to cameras */
if (sce->r.mode & R_PANORAMA) {
for (base=sce->base.first; base; base=base->next) {
ob= newlibadr(fd, lib, base->object);
if (ob->type == OB_CAMERA && !ob->id.lib) {
cam= newlibadr(fd, lib, ob->data);
cam->flag |= CAM_PANORAMA;
}
}
sce->r.mode &= ~R_PANORAMA;
}
}
/* and texture trees */
for (tx= main->tex.first; tx; tx= tx->id.next) {
bNode *node;
if (tx->nodetree) {
if (tx->nodetree->id.name[0] == '\0')
strcpy(tx->nodetree->id.name, "NTTexture Nodetree");
/* which_output 0 is now "not specified" */
for (node=tx->nodetree->nodes.first; node; node=node->next)
if (node->type == TEX_NODE_OUTPUT)
node->custom1++;
}
}
/* copy standard draw flag to meshes(used to be global, is not available here) */
for (me= main->mesh.first; me; me= me->id.next) {
me->drawflag= ME_DRAWEDGES|ME_DRAWFACES|ME_DRAWCREASES;
}
/* particle draw and render types */
for (part= main->particle.first; part; part= part->id.next) {
if (part->draw_as) {
if (part->draw_as == PART_DRAW_DOT) {
part->ren_as = PART_DRAW_HALO;
part->draw_as = PART_DRAW_REND;
}
else if (part->draw_as <= PART_DRAW_AXIS) {
part->ren_as = PART_DRAW_HALO;
}
else {
part->ren_as = part->draw_as;
part->draw_as = PART_DRAW_REND;
}
}
part->path_end = 1.0f;
part->clength = 1.0f;
}
/* set old pointcaches to have disk cache flag */
for (ob = main->object.first; ob; ob= ob->id.next) {
//BKE_ptcache_ids_from_object(&pidlist, ob);
//for (pid=pidlist.first; pid; pid=pid->next)
// pid->cache->flag |= PTCACHE_DISK_CACHE;
//BLI_freelistN(&pidlist);
}
/* type was a mixed flag & enum. move the 2d flag elsewhere */
for (cu = main->curve.first; cu; cu= cu->id.next) {
Nurb *nu;
for (nu= cu->nurb.first; nu; nu= nu->next) {
nu->flag |= (nu->type & CU_2D);
nu->type &= CU_TYPE;
}
}
}
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 1)) {
Object *ob;
Material *ma;
Tex *tex;
Scene *sce;
ToolSettings *ts;
//PTCacheID *pid;
//ListBase pidlist;
for (ob = main->object.first; ob; ob = ob->id.next) {
//BKE_ptcache_ids_from_object(&pidlist, ob);
//for (pid=pidlist.first; pid; pid=pid->next) {
// if (pid->ptcaches->first == NULL)
// pid->ptcaches->first = pid->ptcaches->last = pid->cache;
//}
//BLI_freelistN(&pidlist);
if (ob->type == OB_MESH) {
Mesh *me = newlibadr(fd, lib, ob->data);
void *olddata = ob->data;
ob->data = me;
/* XXX - library meshes crash on loading most yoFrankie levels,
* the multires pointer gets invalid - Campbell */
if (me && me->id.lib==NULL && me->mr && me->mr->level_count > 1) {
multires_load_old(ob, me);
}
ob->data = olddata;
}
if (ob->totcol && ob->matbits == NULL) {
int a;
ob->matbits= MEM_callocN(sizeof(char)*ob->totcol, "ob->matbits");
for (a=0; a<ob->totcol; a++)
ob->matbits[a]= ob->colbits & (1<<a);
}
}
/* texture filter */
for (tex = main->tex.first; tex; tex = tex->id.next) {
if (tex->afmax == 0)
tex->afmax= 8;
}
for (ma = main->mat.first; ma; ma = ma->id.next) {
int a;
if (ma->mode & MA_WIRE) {
ma->material_type= MA_TYPE_WIRE;
ma->mode &= ~MA_WIRE;
}
if (ma->mode & MA_HALO) {
ma->material_type= MA_TYPE_HALO;
ma->mode &= ~MA_HALO;
}
if (ma->mode & (MA_ZTRANSP|MA_RAYTRANSP)) {
ma->mode |= MA_TRANSP;
}
else {
/* ma->mode |= MA_ZTRANSP; */ /* leave ztransp as is even if its not used [#28113] */
ma->mode &= ~MA_TRANSP;
}
/* set new bump for unused slots */
for (a=0; a<MAX_MTEX; a++) {
if (ma->mtex[a]) {
tex= ma->mtex[a]->tex;
if (!tex) {
ma->mtex[a]->texflag |= MTEX_3TAP_BUMP;
ma->mtex[a]->texflag |= MTEX_BUMP_OBJECTSPACE;
}
else {
tex= (Tex*)newlibadr(fd, ma->id.lib, tex);
if (tex && tex->type == 0) { /* invalid type */
ma->mtex[a]->texflag |= MTEX_3TAP_BUMP;
ma->mtex[a]->texflag |= MTEX_BUMP_OBJECTSPACE;
}
}
}
}
/* volume rendering settings */
if (ma->vol.stepsize < 0.0001f) {
ma->vol.density = 1.0f;
ma->vol.emission = 0.0f;
ma->vol.scattering = 1.0f;
ma->vol.emission_col[0] = ma->vol.emission_col[1] = ma->vol.emission_col[2] = 1.0f;
ma->vol.density_scale = 1.0f;
ma->vol.depth_cutoff = 0.01f;
ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED;
ma->vol.stepsize = 0.2f;
ma->vol.shade_type = MA_VOL_SHADE_SHADED;
ma->vol.shadeflag |= MA_VOL_PRECACHESHADING;
ma->vol.precache_resolution = 50;
}
}
for (sce = main->scene.first; sce; sce = sce->id.next) {
ts= sce->toolsettings;
if (ts->normalsize == 0.0f || !ts->uv_selectmode || ts->vgroup_weight == 0.0f) {
ts->normalsize= 0.1f;
ts->selectmode= SCE_SELECT_VERTEX;
/* autokeying - setting should be taken from the user-prefs
* but the userprefs version may not have correct flags set
* (i.e. will result in blank box when enabled)
*/
ts->autokey_mode= U.autokey_mode;
if (ts->autokey_mode == 0)
ts->autokey_mode= 2; /* 'add/replace' but not on */
ts->uv_selectmode= UV_SELECT_VERTEX;
ts->vgroup_weight= 1.0f;
}
/* Game Settings */
//Dome
sce->gm.dome.angle = sce->r.domeangle;
sce->gm.dome.mode = sce->r.domemode;
sce->gm.dome.res = sce->r.domeres;
sce->gm.dome.resbuf = sce->r.domeresbuf;
sce->gm.dome.tilt = sce->r.dometilt;
sce->gm.dome.warptext = sce->r.dometext;
//Stand Alone
sce->gm.playerflag |= (sce->r.fullscreen?GAME_PLAYER_FULLSCREEN:0);
sce->gm.xplay = sce->r.xplay;
sce->gm.yplay = sce->r.yplay;
sce->gm.freqplay = sce->r.freqplay;
sce->gm.depth = sce->r.depth;
sce->gm.attrib = sce->r.attrib;
//Stereo
sce->gm.stereomode = sce->r.stereomode;
/* reassigning stereomode NO_STEREO and DOME to a separeted flag*/
if (sce->gm.stereomode == 1) { //1 = STEREO_NOSTEREO
sce->gm.stereoflag = STEREO_NOSTEREO;
sce->gm.stereomode = STEREO_ANAGLYPH;
}
else if (sce->gm.stereomode == 8) { //8 = STEREO_DOME
sce->gm.stereoflag = STEREO_DOME;
sce->gm.stereomode = STEREO_ANAGLYPH;
}
else
sce->gm.stereoflag = STEREO_ENABLED;
//Framing
sce->gm.framing = sce->framing;
sce->gm.xplay = sce->r.xplay;
sce->gm.yplay = sce->r.yplay;
sce->gm.freqplay= sce->r.freqplay;
sce->gm.depth= sce->r.depth;
//Physic (previously stored in world)
sce->gm.gravity =9.8f;
sce->gm.physicsEngine= WOPHY_BULLET;// Bullet by default
sce->gm.mode = WO_DBVT_CULLING; // DBVT culling by default
sce->gm.occlusionRes = 128;
sce->gm.ticrate = 60;
sce->gm.maxlogicstep = 5;
sce->gm.physubstep = 1;
sce->gm.maxphystep = 5;
}
}
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 2)) {
Scene *sce;
Object *ob;
for (sce = main->scene.first; sce; sce = sce->id.next) {
if (fd->fileflags & G_FILE_ENABLE_ALL_FRAMES)
sce->gm.flag |= GAME_ENABLE_ALL_FRAMES;
if (fd->fileflags & G_FILE_SHOW_DEBUG_PROPS)
sce->gm.flag |= GAME_SHOW_DEBUG_PROPS;
if (fd->fileflags & G_FILE_SHOW_FRAMERATE)
sce->gm.flag |= GAME_SHOW_FRAMERATE;
if (fd->fileflags & G_FILE_SHOW_PHYSICS)
sce->gm.flag |= GAME_SHOW_PHYSICS;
if (fd->fileflags & G_FILE_GLSL_NO_SHADOWS)
sce->gm.flag |= GAME_GLSL_NO_SHADOWS;
if (fd->fileflags & G_FILE_GLSL_NO_SHADERS)
sce->gm.flag |= GAME_GLSL_NO_SHADERS;
if (fd->fileflags & G_FILE_GLSL_NO_RAMPS)
sce->gm.flag |= GAME_GLSL_NO_RAMPS;
if (fd->fileflags & G_FILE_GLSL_NO_NODES)
sce->gm.flag |= GAME_GLSL_NO_NODES;
if (fd->fileflags & G_FILE_GLSL_NO_EXTRA_TEX)
sce->gm.flag |= GAME_GLSL_NO_EXTRA_TEX;
if (fd->fileflags & G_FILE_IGNORE_DEPRECATION_WARNINGS)
sce->gm.flag |= GAME_IGNORE_DEPRECATION_WARNINGS;
if (fd->fileflags & G_FILE_GAME_MAT_GLSL)
sce->gm.matmode= GAME_MAT_GLSL;
else if (fd->fileflags & G_FILE_GAME_MAT)
sce->gm.matmode= GAME_MAT_MULTITEX;
else
sce->gm.matmode= GAME_MAT_TEXFACE;
sce->gm.flag |= GAME_DISPLAY_LISTS;
}
for (ob = main->object.first; ob; ob = ob->id.next) {
if (ob->flag & 8192) // OB_POSEMODE = 8192
ob->mode |= OB_MODE_POSE;
}
}
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 4)) {
Scene *sce;
Object *ob;
Material *ma;
Lamp *la;
World *wo;
Tex *tex;
ParticleSettings *part;
int do_gravity = 0;
for (sce = main->scene.first; sce; sce = sce->id.next)
if (sce->unit.scale_length == 0.0f)
sce->unit.scale_length= 1.0f;
for (ob = main->object.first; ob; ob = ob->id.next) {
/* fluid-sim stuff */
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
if (fluidmd) fluidmd->fss->fmd = fluidmd;
/* rotation modes were added, but old objects would now default to being 'quaternion based' */
ob->rotmode= ROT_MODE_EUL;
}
for (ma = main->mat.first; ma; ma=ma->id.next) {
if (ma->vol.reflection == 0.f) {
ma->vol.reflection = 1.f;
ma->vol.transmission_col[0] = ma->vol.transmission_col[1] = ma->vol.transmission_col[2] = 1.0f;
ma->vol.reflection_col[0] = ma->vol.reflection_col[1] = ma->vol.reflection_col[2] = 1.0f;
}
do_version_mtex_factor_2_50(ma->mtex, ID_MA);
}
for (la = main->lamp.first; la; la=la->id.next)
do_version_mtex_factor_2_50(la->mtex, ID_LA);
for (wo = main->world.first; wo; wo=wo->id.next)
do_version_mtex_factor_2_50(wo->mtex, ID_WO);
for (tex = main->tex.first; tex; tex=tex->id.next)
if (tex->vd)
if (tex->vd->extend == 0)
tex->vd->extend = TEX_CLIP;
for (sce= main->scene.first; sce; sce= sce->id.next) {
if (sce->audio.main == 0.0f)
sce->audio.main = 1.0f;
sce->r.ffcodecdata.audio_mixrate = sce->audio.mixrate;
sce->r.ffcodecdata.audio_volume = sce->audio.main;
sce->audio.distance_model = 2;
sce->audio.doppler_factor = 1.0f;
sce->audio.speed_of_sound = 343.3f;
}
/* Add default gravity to scenes */
for (sce= main->scene.first; sce; sce= sce->id.next) {
if ((sce->physics_settings.flag & PHYS_GLOBAL_GRAVITY) == 0 &&
len_v3(sce->physics_settings.gravity) == 0.0f)
{
sce->physics_settings.gravity[0] = sce->physics_settings.gravity[1] = 0.0f;
sce->physics_settings.gravity[2] = -9.81f;
sce->physics_settings.flag = PHYS_GLOBAL_GRAVITY;
do_gravity = 1;
}
}
/* Assign proper global gravity weights for dynamics (only z-coordinate is taken into account) */
if (do_gravity) for (part= main->particle.first; part; part= part->id.next)
part->effector_weights->global_gravity = part->acc[2]/-9.81f;
for (ob = main->object.first; ob; ob = ob->id.next) {
ModifierData *md;
if (do_gravity) {
for (md= ob->modifiers.first; md; md= md->next) {
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
if (clmd)
clmd->sim_parms->effector_weights->global_gravity = clmd->sim_parms->gravity[2]/-9.81f;
}
if (ob->soft)
ob->soft->effector_weights->global_gravity = ob->soft->grav/9.81f;
}
/* Normal wind shape is plane */
if (ob->pd) {
if (ob->pd->forcefield == PFIELD_WIND)
ob->pd->shape = PFIELD_SHAPE_PLANE;
if (ob->pd->flag & PFIELD_PLANAR)
ob->pd->shape = PFIELD_SHAPE_PLANE;
else if (ob->pd->flag & PFIELD_SURFACE)
ob->pd->shape = PFIELD_SHAPE_SURFACE;
ob->pd->flag |= PFIELD_DO_LOCATION;
}
}
}
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 6)) {
Object *ob;
Lamp *la;
/* New variables for axis-angle rotations and/or quaternion rotations were added, and need proper initialization */
for (ob= main->object.first; ob; ob= ob->id.next) {
/* new variables for all objects */
ob->quat[0]= 1.0f;
ob->rotAxis[1]= 1.0f;
/* bones */
if (ob->pose) {
bPoseChannel *pchan;
for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
/* just need to initalise rotation axis properly... */
pchan->rotAxis[1]= 1.0f;
}
}
}
for (la = main->lamp.first; la; la=la->id.next)
la->compressthresh= 0.05f;
}
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 7)) {
Mesh *me;
Nurb *nu;
Lattice *lt;
Curve *cu;
Key *key;
float *data;
int a, tot;
/* shape keys are no longer applied to the mesh itself, but rather
* to the derivedmesh/displist, so here we ensure that the basis
* shape key is always set in the mesh coordinates. */
for (me= main->mesh.first; me; me= me->id.next) {
if ((key = newlibadr(fd, lib, me->key)) && key->refkey) {
data= key->refkey->data;
tot= MIN2(me->totvert, key->refkey->totelem);
for (a=0; a<tot; a++, data+=3)
copy_v3_v3(me->mvert[a].co, data);
}
}
for (lt= main->latt.first; lt; lt= lt->id.next) {
if ((key = newlibadr(fd, lib, lt->key)) && key->refkey) {
data= key->refkey->data;
tot= MIN2(lt->pntsu*lt->pntsv*lt->pntsw, key->refkey->totelem);
for (a=0; a<tot; a++, data+=3)
copy_v3_v3(lt->def[a].vec, data);
}
}
for (cu= main->curve.first; cu; cu= cu->id.next) {
if ((key = newlibadr(fd, lib, cu->key)) && key->refkey) {
data= key->refkey->data;
for (nu=cu->nurb.first; nu; nu=nu->next) {
if (nu->bezt) {
BezTriple *bezt = nu->bezt;
for (a=0; a<nu->pntsu; a++, bezt++) {
copy_v3_v3(bezt->vec[0], data); data+=3;
copy_v3_v3(bezt->vec[1], data); data+=3;
copy_v3_v3(bezt->vec[2], data); data+=3;
bezt->alfa= *data; data++;
}
}
else if (nu->bp) {
BPoint *bp = nu->bp;
for (a=0; a<nu->pntsu*nu->pntsv; a++, bp++) {
copy_v3_v3(bp->vec, data); data+=3;
bp->alfa= *data; data++;
}
}
}
}
}
}
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 8)) {
{
Scene *sce= main->scene.first;
while (sce) {
if (sce->r.frame_step==0)
sce->r.frame_step= 1;
if (sce->r.mblur_samples==0)
sce->r.mblur_samples = sce->r.osa;
if (sce->ed && sce->ed->seqbase.first) {
do_versions_seq_unique_name_all_strips(
sce, &sce->ed->seqbase);
}
sce= sce->id.next;
}
}
{
/* ensure all nodes have unique names */
bNodeTree *ntree= main->nodetree.first;
while (ntree) {
bNode *node=ntree->nodes.first;
while (node) {
nodeUniqueName(ntree, node);
node= node->next;
}
ntree= ntree->id.next;
}
}
{
Object *ob=main->object.first;
while (ob) {
/* shaded mode disabled for now */
if (ob->dt == OB_MATERIAL) ob->dt = OB_TEXTURE;
ob=ob->id.next;
}
}
{
bScreen *screen;
ScrArea *sa;
SpaceLink *sl;
for (screen= main->screen.first; screen; screen= screen->id.next) {
for (sa= screen->areabase.first; sa; sa= sa->next) {
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
if (v3d->drawtype == OB_MATERIAL) v3d->drawtype = OB_SOLID;
}
}
}
}
}
/* only convert old 2.50 files with color management */
if (main->versionfile == 250) {
Scene *sce=main->scene.first;
Material *ma=main->mat.first;
World *wo=main->world.first;
Tex *tex=main->tex.first;
int i, convert=0;
/* convert to new color management system:
* while previously colors were stored as srgb,
* now they are stored as linear internally,
* with screen gamma correction in certain places in the UI. */
/* don't know what scene is active, so we'll convert if any scene has it enabled... */
while (sce) {
if (sce->r.color_mgt_flag & R_COLOR_MANAGEMENT)
convert=1;
sce=sce->id.next;
}
if (convert) {
while (ma) {
if (ma->ramp_col) {
ColorBand *band = (ColorBand *)ma->ramp_col;
for (i=0; i<band->tot; i++) {
CBData *data = band->data + i;
srgb_to_linearrgb_v3_v3(&data->r, &data->r);
}
}
if (ma->ramp_spec) {
ColorBand *band = (ColorBand *)ma->ramp_spec;
for (i=0; i<band->tot; i++) {
CBData *data = band->data + i;
srgb_to_linearrgb_v3_v3(&data->r, &data->r);
}
}
srgb_to_linearrgb_v3_v3(&ma->r, &ma->r);
srgb_to_linearrgb_v3_v3(&ma->specr, &ma->specr);
srgb_to_linearrgb_v3_v3(&ma->mirr, &ma->mirr);
srgb_to_linearrgb_v3_v3(ma->sss_col, ma->sss_col);
ma=ma->id.next;
}
while (tex) {
if (tex->coba) {
ColorBand *band = (ColorBand *)tex->coba;
for (i=0; i<band->tot; i++) {
CBData *data = band->data + i;
srgb_to_linearrgb_v3_v3(&data->r, &data->r);
}
}
tex=tex->id.next;
}
while (wo) {
srgb_to_linearrgb_v3_v3(&wo->ambr, &wo->ambr);
srgb_to_linearrgb_v3_v3(&wo->horr, &wo->horr);
srgb_to_linearrgb_v3_v3(&wo->zenr, &wo->zenr);
wo=wo->id.next;
}
}
}
}
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 9)) {
Scene *sce;
Mesh *me;
Object *ob;
for (sce=main->scene.first; sce; sce=sce->id.next)
if (!sce->toolsettings->particle.selectmode)
sce->toolsettings->particle.selectmode= SCE_SELECT_PATH;
if (main->versionfile == 250 && main->subversionfile > 1) {
for (me=main->mesh.first; me; me=me->id.next)
multires_load_old_250(me);
for (ob=main->object.first; ob; ob=ob->id.next) {
MultiresModifierData *mmd = (MultiresModifierData *)modifiers_findByType(ob, eModifierType_Multires);
if (mmd) {
mmd->totlvl--;
mmd->lvl--;
mmd->sculptlvl= mmd->lvl;
mmd->renderlvl= mmd->lvl;
}
}
}
}
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 10)) {
Object *ob;
/* properly initialize hair clothsim data on old files */
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_Cloth) {
ClothModifierData *clmd = (ClothModifierData *)md;
if (clmd->sim_parms->velocity_smooth < 0.01f)
clmd->sim_parms->velocity_smooth = 0.f;
}
}
}
}
/* fix bad area setup in subversion 10 */
if (main->versionfile == 250 && main->subversionfile == 10) {
/* fix for new view type in sequencer */
bScreen *screen;
ScrArea *sa;
SpaceLink *sl;
/* remove all preview window in wrong spaces */
for (screen= main->screen.first; screen; screen= screen->id.next) {
for (sa= screen->areabase.first; sa; sa= sa->next) {
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype!=SPACE_SEQ) {
ARegion *ar;
ListBase *regionbase;
if (sl == sa->spacedata.first) {
regionbase = &sa->regionbase;
}
else {
regionbase = &sl->regionbase;
}
for ( ar = regionbase->first; ar; ar = ar->next) {
if (ar->regiontype == RGN_TYPE_PREVIEW)
break;
}
if (ar && (ar->regiontype == RGN_TYPE_PREVIEW)) {
SpaceType *st= BKE_spacetype_from_id(SPACE_SEQ);
BKE_area_region_free(st, ar);
BLI_freelinkN(regionbase, ar);
}
}
}
}
}
}
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 11)) {
{
/* fix for new view type in sequencer */
bScreen *screen;
ScrArea *sa;
SpaceLink *sl;
for (screen= main->screen.first; screen; screen= screen->id.next) {
for (sa= screen->areabase.first; sa; sa= sa->next) {
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_SEQ) {
ARegion *ar;
ARegion *ar_main;
ListBase *regionbase;
SpaceSeq *sseq = (SpaceSeq *)sl;
if (sl == sa->spacedata.first) {
regionbase = &sa->regionbase;
}
else {
regionbase = &sl->regionbase;
}
if (sseq->view == 0) sseq->view = SEQ_VIEW_SEQUENCE;
if (sseq->mainb == 0) sseq->mainb = SEQ_DRAW_IMG_IMBUF;
ar_main = (ARegion*)regionbase->first;
for (; ar_main; ar_main = ar_main->next) {
if (ar_main->regiontype == RGN_TYPE_WINDOW)
break;
}
ar= MEM_callocN(sizeof(ARegion), "preview area for sequencer");
BLI_insertlinkbefore(regionbase, ar_main, ar);
sequencer_init_preview_region(ar);
}
}
}
}
}
}
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 12)) {
Scene *sce;
Object *ob;
Brush *brush;
Material *ma;
/* game engine changes */
for (sce = main->scene.first; sce; sce = sce->id.next) {
sce->gm.eyeseparation = 0.10f;
}
/* anim viz changes */
for (ob= main->object.first; ob; ob= ob->id.next) {
/* initialize object defaults */
animviz_settings_init(&ob->avs);
/* if armature, copy settings for pose from armature data
* performing initialization where appropriate
*/
if (ob->pose && ob->data) {
bArmature *arm= newlibadr(fd, lib, ob->data);
if (arm) { /* XXX - why does this fail in some cases? */
bAnimVizSettings *avs= &ob->pose->avs;
/* ghosting settings ---------------- */
/* ranges */
avs->ghost_bc= avs->ghost_ac= arm->ghostep;
avs->ghost_sf= arm->ghostsf;
avs->ghost_ef= arm->ghostef;
if ((avs->ghost_sf == avs->ghost_ef) && (avs->ghost_sf == 0)) {
avs->ghost_sf= 1;
avs->ghost_ef= 100;
}
/* type */
if (arm->ghostep == 0)
avs->ghost_type= GHOST_TYPE_NONE;
else
avs->ghost_type= arm->ghosttype + 1;
/* stepsize */
avs->ghost_step= arm->ghostsize;
if (avs->ghost_step == 0)
avs->ghost_step= 1;
/* path settings --------------------- */
/* ranges */
avs->path_bc= arm->pathbc;
avs->path_ac= arm->pathac;
if ((avs->path_bc == avs->path_ac) && (avs->path_bc == 0))
avs->path_bc= avs->path_ac= 10;
avs->path_sf= arm->pathsf;
avs->path_ef= arm->pathef;
if ((avs->path_sf == avs->path_ef) && (avs->path_sf == 0)) {
avs->path_sf= 1;
avs->path_ef= 250;
}
/* flags */
if (arm->pathflag & ARM_PATH_FNUMS)
avs->path_viewflag |= MOTIONPATH_VIEW_FNUMS;
if (arm->pathflag & ARM_PATH_KFRAS)
avs->path_viewflag |= MOTIONPATH_VIEW_KFRAS;
if (arm->pathflag & ARM_PATH_KFNOS)
avs->path_viewflag |= MOTIONPATH_VIEW_KFNOS;
/* bake flags */
if (arm->pathflag & ARM_PATH_HEADS)
avs->path_bakeflag |= MOTIONPATH_BAKE_HEADS;
/* type */
if (arm->pathflag & ARM_PATH_ACFRA)
avs->path_type = MOTIONPATH_TYPE_ACFRA;
/* stepsize */
avs->path_step= arm->pathsize;
if (avs->path_step == 0)
avs->path_step= 1;
}
else
animviz_settings_init(&ob->pose->avs);
}
}
/* brush texture changes */
for (brush= main->brush.first; brush; brush= brush->id.next) {
default_mtex(&brush->mtex);
}
for (ma= main->mat.first; ma; ma= ma->id.next) {
if (ma->vol.ms_spread < 0.0001f) {
ma->vol.ms_spread = 0.2f;
ma->vol.ms_diff = 1.f;
ma->vol.ms_intensity = 1.f;
}
}
}
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 13)) {
/* NOTE: if you do more conversion, be sure to do it outside of this and
* increase subversion again, otherwise it will not be correct */
Object *ob;
/* convert degrees to radians for internal use */
for (ob=main->object.first; ob; ob=ob->id.next) {
bPoseChannel *pchan;
do_version_constraints_radians_degrees_250(&ob->constraints);
if (ob->pose) {
for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
pchan->limitmin[0] *= (float)(M_PI/180.0);
pchan->limitmin[1] *= (float)(M_PI/180.0);
pchan->limitmin[2] *= (float)(M_PI/180.0);
pchan->limitmax[0] *= (float)(M_PI/180.0);
pchan->limitmax[1] *= (float)(M_PI/180.0);
pchan->limitmax[2] *= (float)(M_PI/180.0);
do_version_constraints_radians_degrees_250(&pchan->constraints);
}
}
}
}
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 14)) {
/* fix for bad View2D extents for Animation Editors */
bScreen *screen;
ScrArea *sa;
SpaceLink *sl;
for (screen= main->screen.first; screen; screen= screen->id.next) {
for (sa= screen->areabase.first; sa; sa= sa->next) {
for (sl= sa->spacedata.first; sl; sl= sl->next) {
ListBase *regionbase;
ARegion *ar;
if (sl == sa->spacedata.first)
regionbase = &sa->regionbase;
else
regionbase = &sl->regionbase;
if (ELEM(sl->spacetype, SPACE_ACTION, SPACE_NLA)) {
for (ar = (ARegion*)regionbase->first; ar; ar = ar->next) {
if (ar->regiontype == RGN_TYPE_WINDOW) {
ar->v2d.cur.ymax = ar->v2d.tot.ymax = 0.0f;
ar->v2d.cur.ymin = ar->v2d.tot.ymin = (float)(-sa->winy) / 3.0f;
}
}
}
}
}
}
}
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 15)) {
World *wo;
Material *ma;
/* ambient default from 0.5f to 1.0f */
for (ma= main->mat.first; ma; ma=ma->id.next)
ma->amb *= 2.0f;
for (wo= main->world.first; wo; wo=wo->id.next) {
/* ao splitting into ao/env/indirect */
wo->ao_env_energy= wo->aoenergy;
wo->aoenergy= 1.0f;
if (wo->ao_indirect_bounces == 0)
wo->ao_indirect_bounces= 1;
else
wo->mode |= WO_INDIRECT_LIGHT;
if (wo->aomix == WO_AOSUB)
wo->ao_env_energy= -wo->ao_env_energy;
else if (wo->aomix == WO_AOADDSUB)
wo->mode |= WO_AMB_OCC;
wo->aomix= WO_AOMUL;
/* ambient default from 0.5f to 1.0f */
mul_v3_fl(&wo->ambr, 0.5f);
wo->ao_env_energy *= 0.5f;
}
}
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 17)) {
Scene *sce;
Sequence *seq;
Material *ma;
/* initialize to sane default so toggling on border shows something */
for (sce = main->scene.first; sce; sce = sce->id.next) {
if (sce->r.border.xmin == 0.0f && sce->r.border.ymin == 0.0f &&
sce->r.border.xmax == 0.0f && sce->r.border.ymax == 0.0f) {
sce->r.border.xmin = 0.0f;
sce->r.border.ymin = 0.0f;
sce->r.border.xmax = 1.0f;
sce->r.border.ymax = 1.0f;
}
if ((sce->r.ffcodecdata.flags & FFMPEG_MULTIPLEX_AUDIO) == 0)
sce->r.ffcodecdata.audio_codec = 0x0; // CODEC_ID_NONE
SEQ_BEGIN (sce->ed, seq) {
seq->volume = 1.0f;
}
SEQ_END
}
/* particle brush strength factor was changed from int to float */
for (sce= main->scene.first; sce; sce=sce->id.next) {
ParticleEditSettings *pset= &sce->toolsettings->particle;
int a;
for (a=0; a<PE_TOT_BRUSH; a++)
pset->brush[a].strength /= 100.0f;
}
for (ma = main->mat.first; ma; ma=ma->id.next)
if (ma->mode & MA_TRACEBLE)
ma->shade_flag |= MA_APPROX_OCCLUSION;
/* sequencer changes */
{
bScreen *screen;
ScrArea *sa;
SpaceLink *sl;
for (screen= main->screen.first; screen; screen= screen->id.next) {
for (sa= screen->areabase.first; sa; sa= sa->next) {
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_SEQ) {
ARegion *ar_preview;
ListBase *regionbase;
if (sl == sa->spacedata.first) {
regionbase = &sa->regionbase;
}
else {
regionbase = &sl->regionbase;
}
ar_preview = (ARegion*)regionbase->first;
for (; ar_preview; ar_preview = ar_preview->next) {
if (ar_preview->regiontype == RGN_TYPE_PREVIEW)
break;
}
if (ar_preview && (ar_preview->regiontype == RGN_TYPE_PREVIEW)) {
sequencer_init_preview_region(ar_preview);
}
}
}
}
}
} /* sequencer changes */
}
if (main->versionfile <= 251) { /* 2.5.1 had no subversions */
bScreen *sc;
/* Blender 2.5.2 - subversion 0 introduced a new setting: V3D_RENDER_OVERRIDE.
* This bit was used in the past for V3D_TRANSFORM_SNAP, which is now deprecated.
* Here we clear it for old files so they don't come in with V3D_RENDER_OVERRIDE set,
* which would cause cameras, lamps, etc to become invisible */
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->flag2 &= ~V3D_RENDER_OVERRIDE;
}
}
}
}
}
if (main->versionfile < 252 || (main->versionfile == 252 && main->subversionfile < 1)) {
Brush *brush;
Object *ob;
Scene *scene;
bNodeTree *ntree;
for (brush= main->brush.first; brush; brush= brush->id.next) {
if (brush->curve) brush->curve->preset = CURVE_PRESET_SMOOTH;
}
/* properly initialize active flag for fluidsim modifiers */
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_Fluidsim) {
FluidsimModifierData *fmd = (FluidsimModifierData *)md;
fmd->fss->flag |= OB_FLUIDSIM_ACTIVE;
fmd->fss->flag |= OB_FLUIDSIM_OVERRIDE_TIME;
}
}
}
/* adjustment to color balance node values */
for (scene= main->scene.first; scene; scene= scene->id.next) {
if (scene->nodetree) {
bNode *node=scene->nodetree->nodes.first;
while (node) {
if (node->type == CMP_NODE_COLORBALANCE) {
NodeColorBalance *n= (NodeColorBalance *)node->storage;
n->lift[0] += 1.f;
n->lift[1] += 1.f;
n->lift[2] += 1.f;
}
node= node->next;
}
}
}
/* check inside node groups too */
for (ntree= main->nodetree.first; ntree; ntree=ntree->id.next) {
bNode *node=ntree->nodes.first;
while (node) {
if (node->type == CMP_NODE_COLORBALANCE) {
NodeColorBalance *n= (NodeColorBalance *)node->storage;
n->lift[0] += 1.f;
n->lift[1] += 1.f;
n->lift[2] += 1.f;
}
node= node->next;
}
}
}
/* old-track -> constraints (this time we're really doing it!) */
if (main->versionfile < 252 || (main->versionfile == 252 && main->subversionfile < 2)) {
Object *ob;
for (ob = main->object.first; ob; ob = ob->id.next)
do_version_old_trackto_to_constraints(ob);
}
if (main->versionfile < 252 || (main->versionfile == 252 && main->subversionfile < 5)) {
bScreen *sc;
/* Image editor scopes */
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_IMAGE) {
SpaceImage *sima = (SpaceImage *)sl;
scopes_new(&sima->scopes);
}
}
}
}
}
if (main->versionfile < 253) {
Object *ob;
Scene *scene;
bScreen *sc;
Tex *tex;
Brush *brush;
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_NODE) {
SpaceNode *snode= (SpaceNode *)sl;
ListBase *regionbase;
ARegion *ar;
if (sl == sa->spacedata.first)
regionbase = &sa->regionbase;
else
regionbase = &sl->regionbase;
if (snode->v2d.minzoom > 0.09f)
snode->v2d.minzoom= 0.09f;
if (snode->v2d.maxzoom < 2.31f)
snode->v2d.maxzoom= 2.31f;
for (ar= regionbase->first; ar; ar= ar->next) {
if (ar->regiontype == RGN_TYPE_WINDOW) {
if (ar->v2d.minzoom > 0.09f)
ar->v2d.minzoom= 0.09f;
if (ar->v2d.maxzoom < 2.31f)
ar->v2d.maxzoom= 2.31f;
}
}
}
else if (sl->spacetype == SPACE_TIME) {
SpaceTime *stime= (SpaceTime *)sl;
/* enable all cache display */
stime->cache_display |= TIME_CACHE_DISPLAY;
stime->cache_display |= (TIME_CACHE_SOFTBODY|TIME_CACHE_PARTICLES);
stime->cache_display |= (TIME_CACHE_CLOTH|TIME_CACHE_SMOKE|TIME_CACHE_DYNAMICPAINT);
}
}
}
}
do_version_mdef_250(main);
/* parent type to modifier */
for (ob = main->object.first; ob; ob = ob->id.next) {
if (ob->parent) {
Object *parent= (Object *)newlibadr(fd, lib, ob->parent);
if (parent) { /* parent may not be in group */
if (parent->type==OB_ARMATURE && ob->partype==PARSKEL) {
ArmatureModifierData *amd;
bArmature *arm= (bArmature *)newlibadr(fd, lib, parent->data);
amd = (ArmatureModifierData*) modifier_new(eModifierType_Armature);
amd->object = ob->parent;
BLI_addtail((ListBase*)&ob->modifiers, amd);
amd->deformflag= arm->deformflag;
ob->partype = PAROBJECT;
}
else if (parent->type==OB_LATTICE && ob->partype==PARSKEL) {
LatticeModifierData *lmd;
lmd = (LatticeModifierData*) modifier_new(eModifierType_Lattice);
lmd->object = ob->parent;
BLI_addtail((ListBase*)&ob->modifiers, lmd);
ob->partype = PAROBJECT;
}
else if (parent->type==OB_CURVE && ob->partype==PARCURVE) {
CurveModifierData *cmd;
cmd = (CurveModifierData*) modifier_new(eModifierType_Curve);
cmd->object = ob->parent;
BLI_addtail((ListBase*)&ob->modifiers, cmd);
ob->partype = PAROBJECT;
}
}
}
}
/* initialize scene active layer */
for (scene= main->scene.first; scene; scene=scene->id.next) {
int i;
for (i=0; i<20; i++) {
if (scene->lay & (1<<i)) {
scene->layact= 1<<i;
break;
}
}
}
for (tex= main->tex.first; tex; tex= tex->id.next) {
/* if youre picky, this isn't correct until we do a version bump
* since you could set saturation to be 0.0*/
if (tex->saturation==0.0f)
tex->saturation= 1.0f;
}
{
Curve *cu;
for (cu= main->curve.first; cu; cu= cu->id.next) {
cu->smallcaps_scale= 0.75f;
}
}
for (scene= main->scene.first; scene; scene=scene->id.next) {
if (scene) {
Sequence *seq;
SEQ_BEGIN (scene->ed, seq) {
if (seq->sat==0.0f) {
seq->sat= 1.0f;
}
}
SEQ_END
}
}
/* GSOC 2010 Sculpt - New settings for Brush */
for (brush= main->brush.first; brush; brush= brush->id.next) {
/* Sanity Check */
// infinite number of dabs
if (brush->spacing == 0)
brush->spacing = 10;
// will have no effect
if (brush->alpha == 0)
brush->alpha = 0.5f;
// bad radius
if (brush->unprojected_radius == 0)
brush->unprojected_radius = 0.125f;
// unusable size
if (brush->size == 0)
brush->size = 35;
// can't see overlay
if (brush->texture_overlay_alpha == 0)
brush->texture_overlay_alpha = 33;
// same as draw brush
if (brush->crease_pinch_factor == 0)
brush->crease_pinch_factor = 0.5f;
// will sculpt no vertexes
if (brush->plane_trim == 0)
brush->plane_trim = 0.5f;
// same as smooth stroke off
if (brush->smooth_stroke_radius == 0)
brush->smooth_stroke_radius= 75;
// will keep cursor in one spot
if (brush->smooth_stroke_radius == 1)
brush->smooth_stroke_factor= 0.9f;
// same as dots
if (brush->rate == 0)
brush->rate = 0.1f;
/* New Settings */
if (main->versionfile < 252 || (main->versionfile == 252 && main->subversionfile < 5)) {
brush->flag |= BRUSH_SPACE_ATTEN; // explicitly enable adaptive space
// spacing was originally in pixels, convert it to percentage for new version
// size should not be zero due to sanity check above
brush->spacing = (int)(100*((float)brush->spacing) / ((float)brush->size));
if (brush->add_col[0] == 0 &&
brush->add_col[1] == 0 &&
brush->add_col[2] == 0)
{
brush->add_col[0] = 1.00f;
brush->add_col[1] = 0.39f;
brush->add_col[2] = 0.39f;
}
if (brush->sub_col[0] == 0 &&
brush->sub_col[1] == 0 &&
brush->sub_col[2] == 0)
{
brush->sub_col[0] = 0.39f;
brush->sub_col[1] = 0.39f;
brush->sub_col[2] = 1.00f;
}
}
}
}
/* GSOC Sculpt 2010 - Sanity check on Sculpt/Paint settings */
if (main->versionfile < 253) {
Scene *sce;
for (sce= main->scene.first; sce; sce= sce->id.next) {
if (sce->toolsettings->sculpt_paint_unified_alpha == 0)
sce->toolsettings->sculpt_paint_unified_alpha = 0.5f;
if (sce->toolsettings->sculpt_paint_unified_unprojected_radius == 0)
sce->toolsettings->sculpt_paint_unified_unprojected_radius = 0.125f;
if (sce->toolsettings->sculpt_paint_unified_size == 0)
sce->toolsettings->sculpt_paint_unified_size = 35;
}
}
if (main->versionfile < 253 || (main->versionfile == 253 && main->subversionfile < 1)) {
Object *ob;
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_Smoke) {
SmokeModifierData *smd = (SmokeModifierData *)md;
if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
smd->domain->vorticity = 2.0f;
smd->domain->time_scale = 1.0f;
if (!(smd->domain->flags & (1<<4)))
continue;
/* delete old MOD_SMOKE_INITVELOCITY flag */
smd->domain->flags &= ~(1<<4);
/* for now just add it to all flow objects in the scene */
{
Object *ob2;
for (ob2 = main->object.first; ob2; ob2 = ob2->id.next) {
ModifierData *md2;
for (md2= ob2->modifiers.first; md2; md2= md2->next) {
if (md2->type == eModifierType_Smoke) {
SmokeModifierData *smd2 = (SmokeModifierData *)md2;
if ((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) {
smd2->flow->flags |= MOD_SMOKE_FLOW_INITVELOCITY;
}
}
}
}
}
}
else if ((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) {
smd->flow->vel_multi = 1.0f;
}
}
}
}
}
if (main->versionfile < 255 || (main->versionfile == 255 && main->subversionfile < 1)) {
Brush *br;
ParticleSettings *part;
bScreen *sc;
Object *ob;
for (br= main->brush.first; br; br= br->id.next) {
if (br->ob_mode==0)
br->ob_mode= OB_MODE_ALL_PAINT;
}
for (part = main->particle.first; part; part = part->id.next) {
if (part->boids)
part->boids->pitch = 1.0f;
part->flag &= ~PART_HAIR_REGROW; /* this was a deprecated flag before */
part->kink_amp_clump = 1.f; /* keep old files looking similar */
}
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_INFO) {
SpaceInfo *sinfo= (SpaceInfo *)sl;
ARegion *ar;
sinfo->rpt_mask= INFO_RPT_OP;
for (ar= sa->regionbase.first; ar; ar= ar->next) {
if (ar->regiontype == RGN_TYPE_WINDOW) {
ar->v2d.scroll = (V2D_SCROLL_RIGHT);
ar->v2d.align = V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_NEG_Y; /* align bottom left */
ar->v2d.keepofs = V2D_LOCKOFS_X;
ar->v2d.keepzoom = (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_LIMITZOOM|V2D_KEEPASPECT);
ar->v2d.keeptot= V2D_KEEPTOT_BOUNDS;
ar->v2d.minzoom= ar->v2d.maxzoom= 1.0f;
}
}
}
}
}
}
/* fix rotation actuators for objects so they use real angles (radians)
* since before blender went opensource this strange scalar was used: (1 / 0.02) * 2 * math.pi/360 */
for (ob= main->object.first; ob; ob= ob->id.next) {
bActuator *act= ob->actuators.first;
while (act) {
if (act->type==ACT_OBJECT) {
/* multiply velocity with 50 in old files */
bObjectActuator *oa= act->data;
mul_v3_fl(oa->drot, 0.8726646259971648f);
}
act= act->next;
}
}
}
// init facing axis property of steering actuators
{
Object *ob;
for (ob = main->object.first; ob; ob = ob->id.next) {
bActuator *act;
for (act= ob->actuators.first; act; act= act->next) {
if (act->type==ACT_STEERING) {
bSteeringActuator* stact = act->data;
if (stact->facingaxis==0) {
stact->facingaxis=1;
}
}
}
}
}
if (main->versionfile < 255 || (main->versionfile == 255 && main->subversionfile < 3)) {
Object *ob;
/* ocean res is now squared, reset old ones - will be massive */
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_Ocean) {
OceanModifierData *omd = (OceanModifierData *)md;
omd->resolution = 7;
omd->oceancache = NULL;
}
}
}
}
if (main->versionfile < 256) {
bScreen *sc;
ScrArea *sa;
Key *key;
/* Fix for sample line scope initializing with no height */
for (sc= main->screen.first; sc; sc= sc->id.next) {
sa= sc->areabase.first;
while (sa) {
SpaceLink *sl;
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_IMAGE) {
SpaceImage *sima= (SpaceImage *)sl;
if (sima->sample_line_hist.height == 0 )
sima->sample_line_hist.height = 100;
}
}
sa= sa->next;
}
}
/* old files could have been saved with slidermin = slidermax = 0.0, but the UI in
* 2.4x would never reveal this to users as a dummy value always ended up getting used
* instead
*/
for (key = main->key.first; key; key = key->id.next) {
KeyBlock *kb;
for (kb = key->block.first; kb; kb = kb->next) {
if (IS_EQF(kb->slidermin, kb->slidermax) && IS_EQ(kb->slidermax, 0))
kb->slidermax = kb->slidermin + 1.0f;
}
}
}
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 1)) {
/* fix for bones that didn't have arm_roll before */
bArmature* arm;
Bone* bone;
Object *ob;
for (arm = main->armature.first; arm; arm = arm->id.next)
for (bone = arm->bonebase.first; bone; bone = bone->next)
do_version_bone_roll_256(bone);
/* fix for objects which have zero dquat's
* since this is multiplied with the quat rather than added */
for (ob= main->object.first; ob; ob= ob->id.next) {
if (is_zero_v4(ob->dquat)) {
unit_qt(ob->dquat);
}
if (is_zero_v3(ob->drotAxis) && ob->drotAngle == 0.0f) {
unit_axis_angle(ob->drotAxis, &ob->drotAngle);
}
}
}
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 2)) {
bNodeTree *ntree;
/* node sockets are not exposed automatically any more,
* this mimics the old behavior by adding all unlinked sockets to groups.
*/
for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) {
/* XXX Only setting a flag here. Actual adding of group sockets
* is done in lib_verify_nodetree, because at this point the internal
* nodes may not be up-to-date! (missing lib-link)
*/
ntree->flag |= NTREE_DO_VERSIONS_GROUP_EXPOSE;
}
}
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile <3)) {
bScreen *sc;
Brush *brush;
Object *ob;
ParticleSettings *part;
Material *mat;
int tex_nr, transp_tex;
for (mat = main->mat.first; mat; mat = mat->id.next) {
if (!(mat->mode & MA_TRANSP) && !(mat->material_type & MA_TYPE_VOLUME)) {
transp_tex= 0;
for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
if (!mat->mtex[tex_nr]) continue;
if (mat->mtex[tex_nr]->mapto & MAP_ALPHA) transp_tex= 1;
}
/* weak! material alpha could be animated */
if (mat->alpha < 1.0f || mat->fresnel_tra > 0.0f || transp_tex) {
mat->mode |= MA_TRANSP;
mat->mode &= ~(MA_ZTRANSP|MA_RAYTRANSP);
}
}
}
/* redraws flag in SpaceTime has been moved to Screen level */
for (sc = main->screen.first; sc; sc= sc->id.next) {
if (sc->redraws_flag == 0) {
/* just initialize to default? */
// XXX: we could also have iterated through areas, and taken them from the first timeline available...
sc->redraws_flag = TIME_ALL_3D_WIN|TIME_ALL_ANIM_WIN;
}
}
for (brush= main->brush.first; brush; brush= brush->id.next) {
if (brush->height == 0)
brush->height= 0.4f;
}
/* replace 'rim material' option for in offset*/
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_Solidify) {
SolidifyModifierData *smd = (SolidifyModifierData *)md;
if (smd->flag & MOD_SOLIDIFY_RIM_MATERIAL) {
smd->mat_ofs_rim= 1;
smd->flag &= ~MOD_SOLIDIFY_RIM_MATERIAL;
}
}
}
}
/* particle draw color from material */
for (part = main->particle.first; part; part = part->id.next) {
if (part->draw & PART_DRAW_MAT_COL)
part->draw_col = PART_DRAW_COL_MAT;
}
}
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 6)) {
Mesh *me;
for (me= main->mesh.first; me; me= me->id.next)
mesh_calc_normals_tessface(me->mvert, me->totvert, me->mface, me->totface, NULL);
}
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 2)) {
/* update blur area sizes from 0..1 range to 0..100 percentage */
Scene *scene;
bNode *node;
for (scene=main->scene.first; scene; scene=scene->id.next)
if (scene->nodetree)
for (node=scene->nodetree->nodes.first; node; node=node->next)
if (node->type==CMP_NODE_BLUR) {
NodeBlurData *nbd= node->storage;
nbd->percentx *= 100.0f;
nbd->percenty *= 100.0f;
}
}
if (main->versionfile < 258 || (main->versionfile == 258 && main->subversionfile < 1)) {
/* screen view2d settings were not properly initialized [#27164]
* v2d->scroll caused the bug but best reset other values too which are in old blend files only.
* need to make less ugly - possibly an iterator? */
bScreen *screen;
for (screen= main->screen.first; screen; screen= screen->id.next) {
ScrArea *sa;
/* add regions */
for (sa= screen->areabase.first; sa; sa= sa->next) {
SpaceLink *sl= sa->spacedata.first;
if (sl->spacetype==SPACE_IMAGE) {
ARegion *ar;
for (ar=sa->regionbase.first; ar; ar= ar->next) {
if (ar->regiontype == RGN_TYPE_WINDOW) {
View2D *v2d= &ar->v2d;
v2d->minzoom= v2d->maxzoom= v2d->scroll= v2d->keeptot= v2d->keepzoom= v2d->keepofs= v2d->align= 0;
}
}
}
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_IMAGE) {
ARegion *ar;
for (ar=sl->regionbase.first; ar; ar= ar->next) {
if (ar->regiontype == RGN_TYPE_WINDOW) {
View2D *v2d= &ar->v2d;
v2d->minzoom= v2d->maxzoom= v2d->scroll= v2d->keeptot= v2d->keepzoom= v2d->keepofs= v2d->align= 0;
}
}
}
}
}
}
{
/* Initialize texture point density curve falloff */
Tex *tex;
for (tex= main->tex.first; tex; tex= tex->id.next) {
if (tex->pd) {
if (tex->pd->falloff_speed_scale == 0.0f)
tex->pd->falloff_speed_scale = 100.0f;
if (!tex->pd->falloff_curve) {
tex->pd->falloff_curve = curvemapping_add(1, 0, 0, 1, 1);
tex->pd->falloff_curve->preset = CURVE_PRESET_LINE;
tex->pd->falloff_curve->cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
curvemap_reset(tex->pd->falloff_curve->cm, &tex->pd->falloff_curve->clipr, tex->pd->falloff_curve->preset, CURVEMAP_SLOPE_POSITIVE);
curvemapping_changed(tex->pd->falloff_curve, 0);
}
}
}
}
{
/* add default value for behind strength of camera actuator */
Object *ob;
bActuator *act;
for (ob = main->object.first; ob; ob= ob->id.next) {
for (act= ob->actuators.first; act; act= act->next) {
if (act->type == ACT_CAMERA) {
bCameraActuator *ba= act->data;
ba->damping = 1.0/32.0;
}
}
}
}
{
ParticleSettings *part;
for (part = main->particle.first; part; part = part->id.next) {
/* Initialize particle billboard scale */
part->bb_size[0] = part->bb_size[1] = 1.0f;
}
}
}
if (main->versionfile < 259 || (main->versionfile == 259 && main->subversionfile < 1)) {
{
Scene *scene;
Sequence *seq;
for (scene=main->scene.first; scene; scene=scene->id.next) {
scene->r.ffcodecdata.audio_channels = 2;
scene->audio.volume = 1.0f;
SEQ_BEGIN (scene->ed, seq) {
seq->pitch = 1.0f;
}
SEQ_END
}
}
{
bScreen *screen;
for (screen= main->screen.first; screen; screen= screen->id.next) {
ScrArea *sa;
/* add regions */
for (sa= screen->areabase.first; sa; sa= sa->next) {
SpaceLink *sl= sa->spacedata.first;
if (sl->spacetype==SPACE_SEQ) {
ARegion *ar;
for (ar=sa->regionbase.first; ar; ar= ar->next) {
if (ar->regiontype == RGN_TYPE_WINDOW) {
if (ar->v2d.min[1] == 4.0f)
ar->v2d.min[1]= 0.5f;
}
}
}
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype==SPACE_SEQ) {
ARegion *ar;
for (ar=sl->regionbase.first; ar; ar= ar->next) {
if (ar->regiontype == RGN_TYPE_WINDOW) {
if (ar->v2d.min[1] == 4.0f)
ar->v2d.min[1]= 0.5f;
}
}
}
}
}
}
}
{
/* Make "auto-clamped" handles a per-keyframe setting instead of per-FCurve
*
* We're only patching F-Curves in Actions here, since it is assumed that most
* drivers out there won't be using this (and if they are, they're in the minority).
* While we should aim to fix everything ideally, in practice it's far too hard
* to get to every animdata block, not to mention the performance hit that'd have
*/
bAction *act;
FCurve *fcu;
for (act = main->action.first; act; act = act->id.next) {
for (fcu = act->curves.first; fcu; fcu = fcu->next) {
BezTriple *bezt;
unsigned int i = 0;
/* only need to touch curves that had this flag set */
if ((fcu->flag & FCURVE_AUTO_HANDLES) == 0)
continue;
if ((fcu->totvert == 0) || (fcu->bezt == NULL))
continue;
/* only change auto-handles to auto-clamped */
for (bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
if (bezt->h1 == HD_AUTO) bezt->h1 = HD_AUTO_ANIM;
if (bezt->h2 == HD_AUTO) bezt->h2 = HD_AUTO_ANIM;
}
fcu->flag &= ~FCURVE_AUTO_HANDLES;
}
}
}
{
/* convert fcurve and shape action actuators to action actuators */
Object *ob;
bActuator *act;
bIpoActuator *ia;
bActionActuator *aa;
for (ob= main->object.first; ob; ob= ob->id.next) {
for (act= ob->actuators.first; act; act= act->next) {
if (act->type == ACT_IPO) {
// Create the new actuator
ia= act->data;
aa= MEM_callocN(sizeof(bActionActuator), "fcurve -> action actuator do_version");
// Copy values
aa->type = ia->type;
aa->flag = ia->flag;
aa->sta = ia->sta;
aa->end = ia->end;
BLI_strncpy(aa->name, ia->name, sizeof(aa->name));
BLI_strncpy(aa->frameProp, ia->frameProp, sizeof(aa->frameProp));
if (ob->adt)
aa->act = ob->adt->action;
// Get rid of the old actuator
MEM_freeN(ia);
// Assign the new actuator
act->data = aa;
act->type= act->otype= ACT_ACTION;
}
else if (act->type == ACT_SHAPEACTION) {
act->type = act->otype = ACT_ACTION;
}
}
}
}
}
if (main->versionfile < 259 || (main->versionfile == 259 && main->subversionfile < 2)) {
{
/* Convert default socket values from bNodeStack */
Scene *sce;
Material *mat;
Tex *tex;
bNodeTree *ntree;
for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) {
do_versions_nodetree_default_value(ntree);
ntree->update |= NTREE_UPDATE;
}
for (sce=main->scene.first; sce; sce=sce->id.next)
if (sce->nodetree) {
do_versions_nodetree_default_value(sce->nodetree);
sce->nodetree->update |= NTREE_UPDATE;
}
for (mat=main->mat.first; mat; mat=mat->id.next)
if (mat->nodetree) {
do_versions_nodetree_default_value(mat->nodetree);
mat->nodetree->update |= NTREE_UPDATE;
}
for (tex=main->tex.first; tex; tex=tex->id.next)
if (tex->nodetree) {
do_versions_nodetree_default_value(tex->nodetree);
tex->nodetree->update |= NTREE_UPDATE;
}
}
/* add SOCK_DYNAMIC flag to existing group sockets */
{
bNodeTree *ntree;
/* only need to do this for trees in main, local trees are not used as groups */
for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) {
do_versions_nodetree_dynamic_sockets(ntree);
ntree->update |= NTREE_UPDATE;
}
}
{
/* Initialize group tree nodetypes.
* These are used to distinguish tree types and
* associate them with specific node types for polling.
*/
bNodeTree *ntree;
/* all node trees in main->nodetree are considered groups */
for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
ntree->nodetype = NODE_GROUP;
}
}
if (main->versionfile < 259 || (main->versionfile == 259 && main->subversionfile < 4)) {
{
/* Adaptive time step for particle systems */
ParticleSettings *part;
for (part = main->particle.first; part; part = part->id.next) {
part->courant_target = 0.2f;
part->time_flag &= ~PART_TIME_AUTOSF;
}
}
{
/* set defaults for obstacle avoidance, recast data */
Scene *sce;
for (sce = main->scene.first; sce; sce = sce->id.next) {
if (sce->gm.levelHeight == 0.f)
sce->gm.levelHeight = 2.f;
if (sce->gm.recastData.cellsize == 0.0f)
sce->gm.recastData.cellsize = 0.3f;
if (sce->gm.recastData.cellheight == 0.0f)
sce->gm.recastData.cellheight = 0.2f;
if (sce->gm.recastData.agentmaxslope == 0.0f)
sce->gm.recastData.agentmaxslope = (float)M_PI/4;
if (sce->gm.recastData.agentmaxclimb == 0.0f)
sce->gm.recastData.agentmaxclimb = 0.9f;
if (sce->gm.recastData.agentheight == 0.0f)
sce->gm.recastData.agentheight = 2.0f;
if (sce->gm.recastData.agentradius == 0.0f)
sce->gm.recastData.agentradius = 0.6f;
if (sce->gm.recastData.edgemaxlen == 0.0f)
sce->gm.recastData.edgemaxlen = 12.0f;
if (sce->gm.recastData.edgemaxerror == 0.0f)
sce->gm.recastData.edgemaxerror = 1.3f;
if (sce->gm.recastData.regionminsize == 0.0f)
sce->gm.recastData.regionminsize = 8.f;
if (sce->gm.recastData.regionmergesize == 0.0f)
sce->gm.recastData.regionmergesize = 20.f;
if (sce->gm.recastData.vertsperpoly<3)
sce->gm.recastData.vertsperpoly = 6;
if (sce->gm.recastData.detailsampledist == 0.0f)
sce->gm.recastData.detailsampledist = 6.0f;
if (sce->gm.recastData.detailsamplemaxerror == 0.0f)
sce->gm.recastData.detailsamplemaxerror = 1.0f;
}
}
}
if (main->versionfile < 260) {
{
/* set default alpha value of Image outputs in image and render layer nodes to 0 */
Scene *sce;
bNodeTree *ntree;
for (sce=main->scene.first; sce; sce=sce->id.next) {
/* there are files with invalid audio_channels value, the real cause
* is unknown, but we fix it here anyway to avoid crashes */
if (sce->r.ffcodecdata.audio_channels == 0)
sce->r.ffcodecdata.audio_channels = 2;
if (sce->nodetree)
do_versions_nodetree_image_default_alpha_output(sce->nodetree);
}
for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
do_versions_nodetree_image_default_alpha_output(ntree);
}
{
/* support old particle dupliobject rotation settings */
ParticleSettings *part;
for (part=main->particle.first; part; part=part->id.next) {
if (ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
part->draw |= PART_DRAW_ROTATE_OB;
if (part->rotmode == 0)
part->rotmode = PART_ROT_VEL;
}
}
}
}
if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 1)) {
Object *ob;
for (ob= main->object.first; ob; ob= ob->id.next) {
ob->collision_boundtype= ob->boundtype;
}
{
Camera *cam;
for (cam= main->camera.first; cam; cam= cam->id.next) {
if (cam->sensor_x < 0.01f)
cam->sensor_x = DEFAULT_SENSOR_WIDTH;
if (cam->sensor_y < 0.01f)
cam->sensor_y = DEFAULT_SENSOR_HEIGHT;
}
}
}
if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 2)) {
bNodeTreeType *ntreetype= ntreeGetType(NTREE_SHADER);
if (ntreetype && ntreetype->foreach_nodetree)
ntreetype->foreach_nodetree(main, NULL, do_version_ntree_tex_mapping_260);
}
if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 4)) {
{
/* Convert node angles to radians! */
Scene *sce;
Material *mat;
bNodeTree *ntree;
for (sce=main->scene.first; sce; sce=sce->id.next) {
if (sce->nodetree)
do_versions_nodetree_convert_angle(sce->nodetree);
}
for (mat=main->mat.first; mat; mat=mat->id.next) {
if (mat->nodetree)
do_versions_nodetree_convert_angle(mat->nodetree);
}
for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
do_versions_nodetree_convert_angle(ntree);
}
{
/* Tomato compatibility code. */
bScreen *sc;
MovieClip *clip;
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->bundle_size==0.0f) {
v3d->bundle_size= 0.2f;
v3d->flag2 |= V3D_SHOW_RECONSTRUCTION;
}
else if (sl->spacetype==SPACE_CLIP) {
SpaceClip *sc= (SpaceClip *)sl;
if (sc->scopes.track_preview_height==0)
sc->scopes.track_preview_height= 120;
}
if (v3d->bundle_drawtype==0)
v3d->bundle_drawtype= OB_PLAINAXES;
}
}
}
}
for (clip= main->movieclip.first; clip; clip= clip->id.next) {
MovieTrackingTrack *track;
if (clip->aspx<1.0f) {
clip->aspx= 1.0f;
clip->aspy= 1.0f;
}
clip->proxy.build_tc_flag= IMB_TC_RECORD_RUN |
IMB_TC_FREE_RUN |
IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN;
if (clip->proxy.build_size_flag==0)
clip->proxy.build_size_flag= IMB_PROXY_25;
if (clip->proxy.quality==0)
clip->proxy.quality= 90;
if (clip->tracking.camera.pixel_aspect<0.01f)
clip->tracking.camera.pixel_aspect= 1.f;
track= clip->tracking.tracks.first;
while (track) {
if (track->pyramid_levels==0)
track->pyramid_levels= 2;
if (track->minimum_correlation==0.0f)
track->minimum_correlation= 0.75f;
track= track->next;
}
}
}
}
if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 6)) {
Scene *sce;
MovieClip *clip;
bScreen *sc;
for (sce = main->scene.first; sce; sce = sce->id.next) {
do_versions_image_settings_2_60(sce);
}
for (clip= main->movieclip.first; clip; clip= clip->id.next) {
MovieTrackingSettings *settings= &clip->tracking.settings;
if (settings->default_pyramid_levels==0) {
settings->default_tracker= TRACKER_KLT;
settings->default_pyramid_levels= 2;
settings->default_minimum_correlation= 0.75;
settings->default_pattern_size= 11;
settings->default_search_size= 51;
}
}
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->flag2&= ~V3D_RENDER_SHADOW;
}
}
}
}
{
Object *ob;
for (ob= main->object.first; ob; ob= ob->id.next) {
/* convert delta addition into delta scale */
int i;
for (i= 0; i < 3; i++) {
if ( (ob->dsize[i] == 0.0f) || /* simple case, user never touched dsize */
(ob->size[i] == 0.0f)) /* cant scale the dsize to give a non zero result, so fallback to 1.0f */
{
ob->dscale[i]= 1.0f;
}
else {
ob->dscale[i]= (ob->size[i] + ob->dsize[i]) / ob->size[i];
}
}
}
}
}
/* sigh, this dscale vs dsize version patching was not done right, fix for fix,
* this intentionally checks an exact subversion, also note this was never in a release,
* at some point this could be removed. */
else if (main->versionfile == 260 && main->subversionfile == 6) {
Object *ob;
for (ob = main->object.first; ob; ob= ob->id.next) {
if (is_zero_v3(ob->dscale)) {
fill_vn_fl(ob->dscale, 3, 1.0f);
}
}
}
if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 8)) {
Brush *brush;
for (brush= main->brush.first; brush; brush= brush->id.next) {
if (brush->sculpt_tool == SCULPT_TOOL_ROTATE)
brush->alpha= 1.0f;
}
}
if (main->versionfile < 261 || (main->versionfile == 261 && main->subversionfile < 1)) {
{
/* update use flags for node sockets (was only temporary before) */
Scene *sce;
Material *mat;
Tex *tex;
Lamp *lamp;
World *world;
bNodeTree *ntree;
for (sce=main->scene.first; sce; sce=sce->id.next)
if (sce->nodetree)
do_versions_nodetree_socket_use_flags_2_62(sce->nodetree);
for (mat=main->mat.first; mat; mat=mat->id.next)
if (mat->nodetree)
do_versions_nodetree_socket_use_flags_2_62(mat->nodetree);
for (tex=main->tex.first; tex; tex=tex->id.next)
if (tex->nodetree)
do_versions_nodetree_socket_use_flags_2_62(tex->nodetree);
for (lamp=main->lamp.first; lamp; lamp=lamp->id.next)
if (lamp->nodetree)
do_versions_nodetree_socket_use_flags_2_62(lamp->nodetree);
for (world=main->world.first; world; world=world->id.next)
if (world->nodetree)
do_versions_nodetree_socket_use_flags_2_62(world->nodetree);
for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
do_versions_nodetree_socket_use_flags_2_62(ntree);
}
{
/* Initialize BGE exit key to esc key */
Scene *scene;
for (scene= main->scene.first; scene; scene= scene->id.next) {
if (!scene->gm.exitkey)
scene->gm.exitkey = 218; // Blender key code for ESC
}
}
{
MovieClip *clip;
Object *ob;
for (clip= main->movieclip.first; clip; clip= clip->id.next) {
MovieTracking *tracking= &clip->tracking;
MovieTrackingObject *tracking_object= tracking->objects.first;
clip->proxy.build_tc_flag|= IMB_TC_RECORD_RUN_NO_GAPS;
if (!tracking->settings.object_distance)
tracking->settings.object_distance= 1.0f;
if (tracking->objects.first == NULL)
BKE_tracking_new_object(tracking, "Camera");
while (tracking_object) {
if (!tracking_object->scale)
tracking_object->scale= 1.0f;
tracking_object= tracking_object->next;
}
}
for (ob= main->object.first; ob; ob= ob->id.next) {
bConstraint *con;
for (con= ob->constraints.first; con; con=con->next) {
bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
if (!cti)
continue;
if (cti->type==CONSTRAINT_TYPE_OBJECTSOLVER) {
bObjectSolverConstraint *data= (bObjectSolverConstraint *)con->data;
if (data->invmat[3][3]==0.0f)
unit_m4(data->invmat);
}
}
}
}
{
/* Warn the user if he is using ["Text"] properties for Font objects */
Object *ob;
bProperty *prop;
for (ob= main->object.first; ob; ob= ob->id.next) {
if (ob->type == OB_FONT) {
prop = get_ob_property(ob, "Text");
if (prop) {
BKE_reportf_wrap(fd->reports, RPT_WARNING,
"Game property name conflict in object: \"%s\".\nText objects reserve the "
"[\"Text\"] game property to change their content through Logic Bricks.\n",
ob->id.name+2);
}
}
}
}
}
if (main->versionfile < 261 || (main->versionfile == 261 && main->subversionfile < 2)) {
{
/* convert Camera Actuator values to defines */
Object *ob;
bActuator *act;
for (ob = main->object.first; ob; ob= ob->id.next) {
for (act= ob->actuators.first; act; act= act->next) {
if (act->type == ACT_CAMERA) {
bCameraActuator *ba= act->data;
if (ba->axis==(float) 'x') ba->axis=OB_POSX;
else if (ba->axis==(float)'y') ba->axis=OB_POSY;
/* don't do an if/else to avoid imediate subversion bump*/
// ba->axis=((ba->axis == (float) 'x')?OB_POSX_X:OB_POSY);
}
}
}
}
{
/* convert deprecated sculpt_paint_unified_* fields to
* UnifiedPaintSettings */
Scene *scene;
for (scene= main->scene.first; scene; scene= scene->id.next) {
ToolSettings *ts= scene->toolsettings;
UnifiedPaintSettings *ups= &ts->unified_paint_settings;
ups->size= ts->sculpt_paint_unified_size;
ups->unprojected_radius= ts->sculpt_paint_unified_unprojected_radius;
ups->alpha= ts->sculpt_paint_unified_alpha;
ups->flag= ts->sculpt_paint_settings;
}
}
}
if (main->versionfile < 261 || (main->versionfile == 261 && main->subversionfile < 3)) {
{
/* convert extended ascii to utf-8 for text editor */
Text *text;
for (text= main->text.first; text; text= text->id.next)
if (!(text->flags & TXT_ISEXT)) {
TextLine *tl;
for (tl= text->lines.first; tl; tl= tl->next) {
int added= txt_extended_ascii_as_utf8(&tl->line);
tl->len+= added;
/* reset cursor position if line was changed */
if (added && tl == text->curl)
text->curc = 0;
}
}
}
{
/* set new dynamic paint values */
Object *ob;
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_DynamicPaint) {
DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
if (pmd->canvas) {
DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
for (; surface; surface=surface->next) {
surface->color_dry_threshold = 1.0f;
surface->influence_scale = 1.0f;
surface->radius_scale = 1.0f;
surface->flags |= MOD_DPAINT_USE_DRYING;
}
}
}
}
}
}
}
if (main->versionfile < 262) {
Object *ob;
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_Cloth) {
ClothModifierData *clmd = (ClothModifierData*) md;
if (clmd->sim_parms)
clmd->sim_parms->vel_damping = 1.0f;
}
}
}
}
if (main->versionfile < 263) {
/* set fluidsim rate. the version patch for this in 2.62 was wrong, so
* try to correct it, if rate is 0.0 that's likely not intentional */
Object *ob;
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_Fluidsim) {
FluidsimModifierData *fmd = (FluidsimModifierData *)md;
if (fmd->fss->animRate == 0.0f)
fmd->fss->animRate = 1.0f;
}
}
}
}
if (main->versionfile < 262 || (main->versionfile == 262 && main->subversionfile < 1)) {
/* update use flags for node sockets (was only temporary before) */
Scene *sce;
bNodeTree *ntree;
for (sce=main->scene.first; sce; sce=sce->id.next)
if (sce->nodetree)
do_versions_nodetree_multi_file_output_format_2_62_1(sce, sce->nodetree);
/* XXX can't associate with scene for group nodes, image format will stay uninitialized */
for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
do_versions_nodetree_multi_file_output_format_2_62_1(NULL, ntree);
}
/* only swap for pre-release bmesh merge which had MLoopCol red/blue swap */
if (main->versionfile == 262 && main->subversionfile == 1) {
{
Mesh *me;
for (me = main->mesh.first; me; me = me->id.next) {
do_versions_mesh_mloopcol_swap_2_62_1(me);
}
}
}
if (main->versionfile < 262 || (main->versionfile == 262 && main->subversionfile < 2)) {
{
/* Set new idname of keyingsets from their now "label-only" name. */
Scene *scene;
for (scene = main->scene.first; scene; scene = scene->id.next) {
KeyingSet *ks;
for (ks = scene->keyingsets.first; ks; ks = ks->next) {
if (!ks->idname[0])
BLI_strncpy(ks->idname, ks->name, sizeof(ks->idname));
}
}
}
}
if (main->versionfile < 262 || (main->versionfile == 262 && main->subversionfile < 3)) {
Object *ob;
ModifierData *md;
for (ob = main->object.first; ob; ob = ob->id.next) {
for (md=ob->modifiers.first; md; md=md->next) {
if (md->type == eModifierType_Lattice) {
LatticeModifierData *lmd = (LatticeModifierData *)md;
lmd->strength = 1.0f;
}
}
}
}
if (main->versionfile < 262 || (main->versionfile == 262 && main->subversionfile < 4)) {
/* Read Viscosity presets from older files */
Object *ob;
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_Fluidsim) {
FluidsimModifierData *fmd = (FluidsimModifierData *)md;
if (fmd->fss->viscosityMode == 3) {
fmd->fss->viscosityValue = 5.0;
fmd->fss->viscosityExponent = 5;
}
else if (fmd->fss->viscosityMode == 4) {
fmd->fss->viscosityValue = 2.0;
fmd->fss->viscosityExponent = 3;
}
}
}
}
}
if (main->versionfile < 263) {
/* Default for old files is to save particle rotations to pointcache */
ParticleSettings *part;
for (part = main->particle.first; part; part = part->id.next)
part->flag |= PART_ROTATIONS;
}
if (main->versionfile <= 263 && main->subversionfile == 0) {
Scene *scene;
Brush *brush;
/* For weight paint, each brush now gets its own weight;
unified paint settings also have weight. Update unified
paint settings and brushes with a default weight value. */
for (scene = main->scene.first; scene; scene = scene->id.next) {
ToolSettings *ts = scene->toolsettings;
if (ts) {
ts->unified_paint_settings.weight = ts->vgroup_weight;
ts->unified_paint_settings.flag |= UNIFIED_PAINT_WEIGHT;
}
}
for (brush = main->brush.first; brush; brush = brush->id.next) {
brush->weight = 0.5;
}
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
/* don't forget to set version number in blender.c! */
}
#if 0 // XXX: disabled for now... we still don't have this in the right place in the loading code for it to work
static void do_versions_after_linking(FileData *fd, Library *lib, Main *main)
{
/* old Animation System (using IPO's) needs to be converted to the new Animato system */
if (main->versionfile < 250)
do_versions_ipos_to_animato(main);
}
#endif
static void lib_link_all(FileData *fd, Main *main)
{
oldnewmap_sort(fd);
lib_link_windowmanager(fd, 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); // XXX depreceated... still needs to be maintained for version patches still
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_speaker(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_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */
lib_link_brush(fd, main);
lib_link_particlesettings(fd, main);
lib_link_movieclip(fd, main);
lib_link_mesh(fd, main); /* as last: tpage images with users at zero */
lib_link_library(fd, main); /* only init users */
}
static void direct_link_keymapitem(FileData *fd, wmKeyMapItem *kmi)
{
kmi->properties= newdataadr(fd, kmi->properties);
if (kmi->properties)
IDP_DirectLinkProperty(kmi->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
kmi->ptr= NULL;
kmi->flag &= ~KMI_UPDATE;
}
static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
{
UserDef *user;
wmKeyMap *keymap;
wmKeyMapItem *kmi;
wmKeyMapDiffItem *kmdi;
bfd->user= user= read_struct(fd, bhead, "user def");
/* read all data into fd->datamap */
bhead= read_data_into_oldnewmap(fd, bhead, "user def");
if (user->keymaps.first) {
/* backwards compatibility */
user->user_keymaps= user->keymaps;
user->keymaps.first= user->keymaps.last= NULL;
}
link_list(fd, &user->themes);
link_list(fd, &user->user_keymaps);
link_list(fd, &user->addons);
for (keymap=user->user_keymaps.first; keymap; keymap=keymap->next) {
keymap->modal_items= NULL;
keymap->poll = NULL;
keymap->flag &= ~KEYMAP_UPDATE;
link_list(fd, &keymap->diff_items);
link_list(fd, &keymap->items);
for (kmdi=keymap->diff_items.first; kmdi; kmdi=kmdi->next) {
kmdi->remove_item= newdataadr(fd, kmdi->remove_item);
kmdi->add_item= newdataadr(fd, kmdi->add_item);
if (kmdi->remove_item)
direct_link_keymapitem(fd, kmdi->remove_item);
if (kmdi->add_item)
direct_link_keymapitem(fd, kmdi->add_item);
}
for (kmi=keymap->items.first; kmi; kmi=kmi->next)
direct_link_keymapitem(fd, kmi);
}
// XXX
user->uifonts.first= user->uifonts.last= NULL;
link_list(fd, &user->uistyles);
/* free fd->datamap again */
oldnewmap_free_unused(fd->datamap);
oldnewmap_clear(fd->datamap);
return bhead;
}
BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
{
BHead *bhead= blo_firstbhead(fd);
BlendFileData *bfd;
bfd= MEM_callocN(sizeof(BlendFileData), "blendfiledata");
bfd->main= MEM_callocN(sizeof(Main), "readfile_Main");
BLI_addtail(&fd->mainlist, bfd->main);
bfd->main->versionfile= fd->fileversion;
bfd->type= BLENFILETYPE_BLEND;
BLI_strncpy(bfd->main->name, filepath, sizeof(bfd->main->name));
while (bhead) {
switch (bhead->code) {
case DATA:
case DNA1:
case TEST: /* used as preview since 2.5x */
case REND:
bhead = blo_nextbhead(fd, bhead);
break;
case GLOB:
bhead= read_global(bfd, fd, bhead);
break;
case USER:
bhead= read_userdef(bfd, fd, bhead);
break;
case ENDB:
bhead = NULL;
break;
case ID_LI:
/* skip library datablocks in undo, this works together with
* BLO_read_from_memfile, where the old main->library is restored
* overwriting the libraries from the memory file. previously
* it did not save ID_LI/ID_ID blocks in this case, but they are
* needed to make quit.blend recover them correctly. */
if (fd->memfile)
bhead= blo_nextbhead(fd, bhead);
else
bhead= read_libblock(fd, bfd->main, bhead, LIB_LOCAL, NULL);
break;
case ID_ID:
/* same as above */
if (fd->memfile)
bhead= blo_nextbhead(fd, bhead);
else
/* 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;
/* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
case ID_SCRN:
bhead->code= ID_SCR;
/* deliberate pass on to default */
default:
bhead = read_libblock(fd, bfd->main, bhead, LIB_LOCAL, NULL);
}
}
/* do before read_libraries, but skip undo case */
// if (fd->memfile==NULL) (the mesh shuffle hacks don't work yet? ton)
do_versions(fd, NULL, bfd->main);
read_libraries(fd, &fd->mainlist);
blo_join_main(&fd->mainlist);
lib_link_all(fd, bfd->main);
//do_versions_after_linking(fd, NULL, bfd->main); // XXX: not here (or even in this function at all)! this causes crashes on many files - Aligorith (July 04, 2010)
lib_verify_nodetree(bfd->main, TRUE);
fix_relpaths_library(fd->relabase, bfd->main); /* make all relative paths, relative to the open blend file */
link_global(fd, bfd); /* as last */
return bfd;
}
/* ************* APPEND LIBRARY ************** */
struct bheadsort {
BHead *bhead;
void *old;
};
static int verg_bheadsort(const void *v1, const void *v2)
{
const struct bheadsort *x1=v1, *x2=v2;
if ( x1->old > x2->old) return 1;
else if ( x1->old < x2->old) return -1;
return 0;
}
static void sort_bhead_old_map(FileData *fd)
{
BHead *bhead;
struct bheadsort *bhs;
int tot= 0;
for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead))
tot++;
fd->tot_bheadmap= tot;
if (tot==0) return;
bhs= fd->bheadmap= MEM_mallocN(tot*sizeof(struct bheadsort), "bheadsort");
for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead), bhs++) {
bhs->bhead= bhead;
bhs->old= bhead->old;
}
qsort(fd->bheadmap, tot, sizeof(struct bheadsort), verg_bheadsort);
}
static BHead *find_previous_lib(FileData *fd, BHead *bhead)
{
/* skip library datablocks in undo, see comment in read_libblock */
if (fd->memfile)
return NULL;
for (; bhead; bhead= blo_prevbhead(fd, bhead))
if (bhead->code==ID_LI)
break;
return bhead;
}
static BHead *find_bhead(FileData *fd, void *old)
{
#if 0
BHead *bhead;
#endif
struct bheadsort *bhs, bhs_s;
if (!old)
return NULL;
if (fd->bheadmap==NULL)
sort_bhead_old_map(fd);
bhs_s.old= old;
bhs= bsearch(&bhs_s, fd->bheadmap, fd->tot_bheadmap, sizeof(struct bheadsort), verg_bheadsort);
if (bhs)
return bhs->bhead;
#if 0
for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead))
if (bhead->old==old)
return bhead;
#endif
return NULL;
}
char *bhead_id_name(FileData *fd, BHead *bhead)
{
return ((char *)(bhead+1)) + fd->id_name_offs;
}
static ID *is_yet_read(FileData *fd, Main *mainvar, BHead *bhead)
{
const char *idname= bhead_id_name(fd, bhead);
/* which_libbase can be NULL, intentionally not using idname+2 */
return BLI_findstring(which_libbase(mainvar, GS(idname)), idname, offsetof(ID, name));
}
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) {
Library *lib= read_struct(fd, bheadlib, "Library");
Main *ptr= blo_find_main(fd, &fd->mainlist, lib->name, fd->relabase);
id= is_yet_read(fd, ptr, bhead);
if (id==NULL) {
read_libblock(fd, ptr, bhead, LIB_READ+LIB_INDIRECT, NULL);
// commented because this can print way too much
// if (G.debug & G_DEBUG) printf("expand_doit: other lib %s\n", lib->name);
/* for outliner dependency only */
ptr->curlib->parent= mainvar->curlib;
}
else {
/* The line below was commented by Ton (I assume), when Hos did the merge from the orange branch. rev 6568
* This line is NEEDED, the case is that you have 3 blend files...
* user.blend, lib.blend and lib_indirect.blend - if user.blend already references a "tree" from
* lib_indirect.blend but lib.blend does too, linking in a Scene or Group from lib.blend can result in an
* empty without the dupli group referenced. Once you save and reload the group would appier. - Campbell */
/* This crashes files, must look further into it */
/* Update: the issue is that in file reading, the oldnewmap is OK, but for existing data, it has to be
* inserted in the map to be found! */
if (id->flag & LIB_PRE_EXISTING)
oldnewmap_insert(fd->libmap, bhead->old, id, 1);
change_idid_adr_fd(fd, bhead->old, id);
// commented because this can print way too much
// if (G.debug & G_DEBUG) printf("expand_doit: already linked: %s lib: %s\n", id->name, lib->name);
}
MEM_freeN(lib);
}
}
else {
id= is_yet_read(fd, mainvar, bhead);
if (id==NULL) {
read_libblock(fd, mainvar, bhead, LIB_TESTIND, NULL);
}
else {
/* this is actually only needed on UI call? when ID was already read before, and another append
* happens which invokes same ID... in that case the lookup table needs this entry */
oldnewmap_insert(fd->libmap, bhead->old, id, 1);
// commented because this can print way too much
// if (G.debug & G_DEBUG) printf("expand: already read %s\n", id->name);
}
}
}
}
// XXX depreceated - old animation system
static void expand_ipo(FileData *fd, Main *mainvar, Ipo *ipo)
{
IpoCurve *icu;
for (icu= ipo->curve.first; icu; icu= icu->next) {
if (icu->driver)
expand_doit(fd, mainvar, icu->driver->ob);
}
}
// XXX depreceated - old animation system
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_fmodifiers(FileData *fd, Main *mainvar, ListBase *list)
{
FModifier *fcm;
for (fcm= list->first; fcm; fcm= fcm->next) {
/* library data for specific F-Modifier types */
switch (fcm->type) {
case FMODIFIER_TYPE_PYTHON:
{
FMod_Python *data= (FMod_Python *)fcm->data;
expand_doit(fd, mainvar, data->script);
}
break;
}
}
}
static void expand_fcurves(FileData *fd, Main *mainvar, ListBase *list)
{
FCurve *fcu;
for (fcu= list->first; fcu; fcu= fcu->next) {
/* Driver targets if there is a driver */
if (fcu->driver) {
ChannelDriver *driver= fcu->driver;
DriverVar *dvar;
for (dvar= driver->variables.first; dvar; dvar= dvar->next) {
DRIVER_TARGETS_LOOPER(dvar)
{
// TODO: only expand those that are going to get used?
expand_doit(fd, mainvar, dtar->id);
}
DRIVER_TARGETS_LOOPER_END
}
}
/* F-Curve Modifiers */
expand_fmodifiers(fd, mainvar, &fcu->modifiers);
}
}
static void expand_action(FileData *fd, Main *mainvar, bAction *act)
{
bActionChannel *chan;
// XXX depreceated - old animation system --------------
for (chan=act->chanbase.first; chan; chan=chan->next) {
expand_doit(fd, mainvar, chan->ipo);
expand_constraint_channels(fd, mainvar, &chan->constraintChannels);
}
// ---------------------------------------------------
/* F-Curves in Action */
expand_fcurves(fd, mainvar, &act->curves);
}
static void expand_keyingsets(FileData *fd, Main *mainvar, ListBase *list)
{
KeyingSet *ks;
KS_Path *ksp;
/* expand the ID-pointers in KeyingSets's paths */
for (ks= list->first; ks; ks= ks->next) {
for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
expand_doit(fd, mainvar, ksp->id);
}
}
}
static void expand_animdata_nlastrips(FileData *fd, Main *mainvar, ListBase *list)
{
NlaStrip *strip;
for (strip= list->first; strip; strip= strip->next) {
/* check child strips */
expand_animdata_nlastrips(fd, mainvar, &strip->strips);
/* check F-Curves */
expand_fcurves(fd, mainvar, &strip->fcurves);
/* check F-Modifiers */
expand_fmodifiers(fd, mainvar, &strip->modifiers);
/* relink referenced action */
expand_doit(fd, mainvar, strip->act);
}
}
static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt)
{
NlaTrack *nlt;
/* own action */
expand_doit(fd, mainvar, adt->action);
expand_doit(fd, mainvar, adt->tmpact);
/* drivers - assume that these F-Curves have driver data to be in this list... */
expand_fcurves(fd, mainvar, &adt->drivers);
/* nla-data - referenced actions */
for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next)
expand_animdata_nlastrips(fd, mainvar, &nlt->strips);
}
static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSettings *part)
{
int a;
expand_doit(fd, mainvar, part->dup_ob);
expand_doit(fd, mainvar, part->dup_group);
expand_doit(fd, mainvar, part->eff_group);
expand_doit(fd, mainvar, part->bb_ob);
if (part->adt)
expand_animdata(fd, mainvar, part->adt);
for (a=0; a<MAX_MTEX; a++) {
if (part->mtex[a]) {
expand_doit(fd, mainvar, part->mtex[a]->tex);
expand_doit(fd, mainvar, part->mtex[a]->object);
}
}
}
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); // XXX depreceated - old animation system
if (key->adt)
expand_animdata(fd, mainvar, key->adt);
}
static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
{
bNode *node;
if (ntree->adt)
expand_animdata(fd, mainvar, ntree->adt);
if (ntree->gpd)
expand_doit(fd, mainvar, ntree->gpd);
for (node= ntree->nodes.first; node; node= node->next)
if (node->id && node->type!=CMP_NODE_R_LAYERS)
expand_doit(fd, mainvar, node->id);
}
static void expand_texture(FileData *fd, Main *mainvar, Tex *tex)
{
expand_doit(fd, mainvar, tex->ima);
expand_doit(fd, mainvar, tex->ipo); // XXX depreceated - old animation system
if (tex->adt)
expand_animdata(fd, mainvar, tex->adt);
if (tex->nodetree)
expand_nodetree(fd, mainvar, tex->nodetree);
}
static void expand_brush(FileData *fd, Main *mainvar, Brush *brush)
{
expand_doit(fd, mainvar, brush->mtex.tex);
expand_doit(fd, mainvar, brush->clone.image);
}
static void expand_material(FileData *fd, Main *mainvar, Material *ma)
{
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); // XXX depreceated - old animation system
if (ma->adt)
expand_animdata(fd, mainvar, ma->adt);
if (ma->nodetree)
expand_nodetree(fd, mainvar, ma->nodetree);
if (ma->group)
expand_doit(fd, mainvar, ma->group);
}
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); // XXX depreceated - old animation system
if (la->adt)
expand_animdata(fd, mainvar, la->adt);
if (la->nodetree)
expand_nodetree(fd, mainvar, la->nodetree);
}
static void expand_lattice(FileData *fd, Main *mainvar, Lattice *lt)
{
expand_doit(fd, mainvar, lt->ipo); // XXX depreceated - old animation system
expand_doit(fd, mainvar, lt->key);
if (lt->adt)
expand_animdata(fd, mainvar, lt->adt);
}
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); // XXX depreceated - old animation system
if (wrld->adt)
expand_animdata(fd, mainvar, wrld->adt);
if (wrld->nodetree)
expand_nodetree(fd, mainvar, wrld->nodetree);
}
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]);
}
if (mb->adt)
expand_animdata(fd, mainvar, mb->adt);
}
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); // XXX depreceated - old animation system
expand_doit(fd, mainvar, cu->bevobj);
expand_doit(fd, mainvar, cu->taperobj);
expand_doit(fd, mainvar, cu->textoncurve);
if (cu->adt)
expand_animdata(fd, mainvar, cu->adt);
}
static void expand_mesh(FileData *fd, Main *mainvar, Mesh *me)
{
CustomDataLayer *layer;
MTFace *mtf;
TFace *tf;
int a, i;
if (me->adt)
expand_animdata(fd, mainvar, me->adt);
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) {
tf= me->tface;
for (i=0; i<me->totface; i++, tf++)
if (tf->tpage)
expand_doit(fd, mainvar, tf->tpage);
}
for (a=0; a<me->fdata.totlayer; a++) {
layer= &me->fdata.layers[a];
if (layer->type == CD_MTFACE) {
mtf= (MTFace*)layer->data;
for (i=0; i<me->totface; i++, mtf++)
if (mtf->tpage)
expand_doit(fd, mainvar, mtf->tpage);
}
}
}
/* temp struct used to transport needed info to expand_constraint_cb() */
typedef struct tConstraintExpandData {
FileData *fd;
Main *mainvar;
} tConstraintExpandData;
/* callback function used to expand constraint ID-links */
static void expand_constraint_cb(bConstraint *UNUSED(con), ID **idpoin, void *userdata)
{
tConstraintExpandData *ced= (tConstraintExpandData *)userdata;
expand_doit(ced->fd, ced->mainvar, *idpoin);
}
static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
{
tConstraintExpandData ced;
bConstraint *curcon;
/* relink all ID-blocks used by the constraints */
ced.fd= fd;
ced.mainvar= mainvar;
id_loop_constraints(lb, expand_constraint_cb, &ced);
/* depreceated manual expansion stuff */
for (curcon=lb->first; curcon; curcon=curcon->next) {
if (curcon->ipo)
expand_doit(fd, mainvar, curcon->ipo); // XXX depreceated - old animation system
}
}
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);
expand_doit(fd, mainvar, chan->custom);
}
}
static void expand_armature(FileData *fd, Main *mainvar, bArmature *arm)
{
Bone *curBone;
if (arm->adt)
expand_animdata(fd, mainvar, arm->adt);
for (curBone = arm->bonebase.first; curBone; curBone=curBone->next) {
expand_bones(fd, mainvar, curBone);
}
}
static void expand_object_expandModifiers(void *userData, Object *UNUSED(ob),
ID **idpoin)
{
struct { FileData *fd; Main *mainvar; } *data= userData;
FileData *fd= data->fd;
Main *mainvar= data->mainvar;
expand_doit(fd, mainvar, *idpoin);
}
static void expand_object(FileData *fd, Main *mainvar, Object *ob)
{
ParticleSystem *psys;
bSensor *sens;
bController *cont;
bActuator *act;
bActionStrip *strip;
PartEff *paf;
int a;
expand_doit(fd, mainvar, ob->data);
/* expand_object_expandModifier() */
if (ob->modifiers.first) {
struct { FileData *fd; Main *mainvar; } data;
data.fd= fd;
data.mainvar= mainvar;
modifiers_foreachIDLink(ob, expand_object_expandModifiers, (void *)&data);
}
expand_pose(fd, mainvar, ob->pose);
expand_doit(fd, mainvar, ob->poselib);
expand_constraints(fd, mainvar, &ob->constraints);
expand_doit(fd, mainvar, ob->gpd);
// XXX depreceated - old animation system (for version patching only)
expand_doit(fd, mainvar, ob->ipo);
expand_doit(fd, mainvar, ob->action);
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);
}
// XXX depreceated - old animation system (for version patching only)
if (ob->adt)
expand_animdata(fd, mainvar, ob->adt);
for (a=0; a<ob->totcol; a++) {
expand_doit(fd, mainvar, ob->mat[a]);
}
paf = do_version_give_parteff_245(ob);
if (paf && paf->group)
expand_doit(fd, mainvar, paf->group);
if (ob->dup_group)
expand_doit(fd, mainvar, ob->dup_group);
if (ob->proxy)
expand_doit(fd, mainvar, ob->proxy);
if (ob->proxy_group)
expand_doit(fd, mainvar, ob->proxy_group);
for (psys=ob->particlesystem.first; psys; psys=psys->next)
expand_doit(fd, mainvar, psys->part);
sens= ob->sensors.first;
while (sens) {
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) {
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_OBJECT) {
bObjectActuator *oa= act->data;
expand_doit(fd, mainvar, oa->reference);
}
else if (act->type==ACT_ADD_OBJECT) {
bAddObjectActuator *aoa= act->data;
expand_doit(fd, mainvar, aoa->ob);
}
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_2DFILTER) {
bTwoDFilterActuator *tdfa= act->data;
expand_doit(fd, mainvar, tdfa->text);
}
else if (act->type==ACT_ACTION) {
bActionActuator *aa= act->data;
expand_doit(fd, mainvar, aa->act);
}
else if (act->type==ACT_SHAPEACTION) {
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);
}
else if (act->type==ACT_PARENT) {
bParentActuator *pa= act->data;
expand_doit(fd, mainvar, pa->ob);
}
else if (act->type==ACT_ARMATURE) {
bArmatureActuator *arma= act->data;
expand_doit(fd, mainvar, arma->target);
}
else if (act->type==ACT_STEERING) {
bSteeringActuator *sta= act->data;
expand_doit(fd, mainvar, sta->target);
expand_doit(fd, mainvar, sta->navmesh);
}
act= act->next;
}
if (ob->pd && ob->pd->tex)
expand_doit(fd, mainvar, ob->pd->tex);
}
static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
{
Base *base;
SceneRenderLayer *srl;
for (base= sce->base.first; base; base= base->next) {
expand_doit(fd, mainvar, base->object);
}
expand_doit(fd, mainvar, sce->camera);
expand_doit(fd, mainvar, sce->world);
if (sce->adt)
expand_animdata(fd, mainvar, sce->adt);
expand_keyingsets(fd, mainvar, &sce->keyingsets);
if (sce->set)
expand_doit(fd, mainvar, sce->set);
if (sce->nodetree)
expand_nodetree(fd, mainvar, sce->nodetree);
for (srl= sce->r.layers.first; srl; srl= srl->next) {
expand_doit(fd, mainvar, srl->mat_override);
expand_doit(fd, mainvar, srl->light_override);
}
if (sce->r.dometext)
expand_doit(fd, mainvar, sce->gm.dome.warptext);
if (sce->gpd)
expand_doit(fd, mainvar, sce->gpd);
if (sce->ed) {
Sequence *seq;
SEQ_BEGIN (sce->ed, seq) {
if (seq->scene) expand_doit(fd, mainvar, seq->scene);
if (seq->scene_camera) expand_doit(fd, mainvar, seq->scene_camera);
if (seq->sound) expand_doit(fd, mainvar, seq->sound);
}
SEQ_END
}
#ifdef DURIAN_CAMERA_SWITCH
{
TimeMarker *marker;
for (marker= sce->markers.first; marker; marker= marker->next) {
if (marker->camera) {
expand_doit(fd, mainvar, marker->camera);
}
}
}
#endif
expand_doit(fd, mainvar, sce->clip);
}
static void expand_camera(FileData *fd, Main *mainvar, Camera *ca)
{
expand_doit(fd, mainvar, ca->ipo); // XXX depreceated - old animation system
if (ca->adt)
expand_animdata(fd, mainvar, ca->adt);
}
static void expand_speaker(FileData *fd, Main *mainvar, Speaker *spk)
{
expand_doit(fd, mainvar, spk->sound);
if (spk->adt)
expand_animdata(fd, mainvar, spk->adt);
}
static void expand_sound(FileData *fd, Main *mainvar, bSound *snd)
{
expand_doit(fd, mainvar, snd->ipo); // XXX depreceated - old animation system
}
static void expand_movieclip(FileData *fd, Main *mainvar, MovieClip *clip)
{
if (clip->adt)
expand_animdata(fd, mainvar, clip->adt);
}
static void expand_main(FileData *fd, Main *mainvar)
{
ListBase *lbarray[MAX_LIBARRAY];
ID *id;
int a, doit= 1;
if (fd==NULL) 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_SPK:
expand_speaker(fd, mainvar, (Speaker *)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); // XXX depreceated - old animation system
break;
case ID_GR:
expand_group(fd, mainvar, (Group *)id);
break;
case ID_NT:
expand_nodetree(fd, mainvar, (bNodeTree *)id);
break;
case ID_BR:
expand_brush(fd, mainvar, (Brush *)id);
break;
case ID_IP:
expand_ipo(fd, mainvar, (Ipo *)id); // XXX depreceated - old animation system
break;
case ID_PA:
expand_particlesettings(fd, mainvar, (ParticleSettings *)id);
break;
case ID_MC:
expand_movieclip(fd, mainvar, (MovieClip *)id);
break;
}
doit= 1;
id->flag -= LIB_TEST;
}
id= id->next;
}
}
}
}
static int object_in_any_scene(Main *mainvar, Object *ob)
{
Scene *sce;
for (sce= mainvar->scene.first; sce; sce= sce->id.next)
if (object_in_scene(ob, sce))
return 1;
return 0;
}
static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, const short idcode, const short is_link)
{
Object *ob;
Base *base;
const short is_group_append= (is_link==FALSE && idcode==ID_GR);
/* give all objects which are LIB_INDIRECT a base, or for a group when *lib has been set */
for (ob= mainvar->object.first; ob; ob= ob->id.next) {
if ( ob->id.flag & LIB_INDIRECT ) {
/* IF below is quite confusing!
* if we are appending, but this object wasnt just added along with a group,
* then this is already used indirectly in the scene somewhere else and we didnt just append it.
*
* (ob->id.flag & LIB_PRE_EXISTING)==0 means that this is a newly appended object - Campbell */
if (is_group_append==0 || (ob->id.flag & LIB_PRE_EXISTING)==0) {
int do_it= 0;
if (ob->id.us==0) {
do_it= 1;
}
else if (idcode==ID_GR) {
if (ob->id.us==1 && is_link==FALSE && ob->id.lib==lib) {
if ((ob->flag & OB_FROMGROUP) && object_in_any_scene(mainvar, ob)==0) {
do_it= 1;
}
}
}
else {
/* when appending, make sure any indirectly loaded objects
* get a base else they cant be accessed at all [#27437] */
if (ob->id.us==1 && is_link==FALSE && ob->id.lib==lib) {
/* we may be appending from a scene where we already
* have a linked object which is not in any scene [#27616] */
if ((ob->id.flag & LIB_PRE_EXISTING)==0) {
if (object_in_any_scene(mainvar, ob)==0) {
do_it= 1;
}
}
}
}
if (do_it) {
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;
}
}
}
}
}
static void give_base_to_groups(Main *mainvar, Scene *scene)
{
Group *group;
/* give all objects which are LIB_INDIRECT a base, or for a group when *lib has been set */
for (group= mainvar->group.first; group; group= group->id.next) {
if (((group->id.flag & LIB_INDIRECT)==0 && (group->id.flag & LIB_PRE_EXISTING)==0)) {
Base *base;
/* add_object(...) messes with the selection */
Object *ob= add_only_object(OB_EMPTY, group->id.name+2);
ob->type= OB_EMPTY;
ob->lay= scene->lay;
/* assign the base */
base= scene_add_base(scene, ob);
base->flag |= SELECT;
base->object->flag= base->flag;
ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
scene->basact= base;
/* assign the group */
ob->dup_group= group;
ob->transflag |= OB_DUPLIGROUP;
rename_id(&ob->id, group->id.name+2);
copy_v3_v3(ob->loc, scene->cursor);
}
}
}
/* returns true if the item was found
* but it may already have already been appended/linked */
static ID *append_named_part(Main *mainl, FileData *fd, const char *idname, const short idcode)
{
BHead *bhead;
ID *id= NULL;
int found=0;
for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
if (bhead->code==idcode) {
const char *idname_test= bhead_id_name(fd, bhead);
if (strcmp(idname_test + 2, idname)==0) {
found= 1;
id= is_yet_read(fd, mainl, bhead);
if (id==NULL) {
/* not read yet */
read_libblock(fd, mainl, bhead, LIB_TESTEXT, &id);
if (id) {
/* sort by name in list */
ListBase *lb= which_libbase(mainl, idcode);
id_sort_by_name(lb, id);
}
}
else {
/* already linked */
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;
}
}
break;
}
}
else if (bhead->code==ENDB) {
break;
}
}
/* if we found the id but the id is NULL, this is really bad */
BLI_assert((found != 0) == (id != NULL));
return found ? id : NULL;
}
static ID *append_named_part_ex(const bContext *C, Main *mainl, FileData *fd, const char *idname, const int idcode, const int flag)
{
ID *id= append_named_part(mainl, fd, idname, idcode);
if (id && (GS(id->name) == ID_OB)) { /* loose object: give a base */
Scene *scene= CTX_data_scene(C); /* can be NULL */
if (scene) {
Base *base;
Object *ob;
base= MEM_callocN(sizeof(Base), "app_nam_part");
BLI_addtail(&scene->base, base);
ob= (Object *)id;
/* link at active layer (view3d->lay if in context, else scene->lay */
if ((flag & FILE_ACTIVELAY)) {
View3D *v3d = CTX_wm_view3d(C);
ob->lay = v3d ? v3d->layact : scene->lay;
}
ob->mode= 0;
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 */
}
}
}
return id;
}
ID *BLO_library_append_named_part(Main *mainl, BlendHandle** bh, const char *idname, const int idcode)
{
FileData *fd= (FileData*)(*bh);
return append_named_part(mainl, fd, idname, idcode);
}
ID *BLO_library_append_named_part_ex(const bContext *C, Main *mainl, BlendHandle** bh, const char *idname, const int idcode, const short flag)
{
FileData *fd= (FileData*)(*bh);
return append_named_part_ex(C, mainl, fd, idname, idcode, flag);
}
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)) {
if (strcmp(id->name, bhead_id_name(fd, bhead))==0) {
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;
}
}
/* common routine to append/link something from a library */
static Main* library_append_begin(Main *mainvar, FileData **fd, const char *filepath)
{
Main *mainl;
/* make mains */
blo_split_main(&(*fd)->mainlist, mainvar);
/* which one do we need? */
mainl = blo_find_main(*fd, &(*fd)->mainlist, filepath, G.main->name);
/* needed for do_version */
mainl->versionfile= (*fd)->fileversion;
read_file_version(*fd, mainl);
return mainl;
}
Main* BLO_library_append_begin(Main *mainvar, BlendHandle** bh, const char *filepath)
{
FileData *fd= (FileData*)(*bh);
return library_append_begin(mainvar, &fd, filepath);
}
/* Context == NULL signifies not to do any scene manipulation */
static void library_append_end(const bContext *C, Main *mainl, FileData **fd, int idcode, short flag)
{
Main *mainvar;
Library *curlib;
/* make main consistent */
expand_main(*fd, mainl);
/* do this when expand found other libs */
read_libraries(*fd, &(*fd)->mainlist);
curlib= mainl->curlib;
/* make the lib path relative if required */
if (flag & FILE_RELPATH) {
/* use the full path, this could have been read by other library even */
BLI_strncpy(curlib->name, curlib->filepath, sizeof(curlib->name));
/* uses current .blend file as reference */
BLI_path_rel(curlib->name, G.main->name);
}
blo_join_main(&(*fd)->mainlist);
mainvar= (*fd)->mainlist.first;
mainl= NULL; /* blo_join_main free's mainl, cant use anymore */
lib_link_all(*fd, mainvar);
lib_verify_nodetree(mainvar, FALSE);
fix_relpaths_library(G.main->name, mainvar); /* make all relative paths, relative to the open blend file */
if (C) {
Scene *scene= CTX_data_scene(C);
/* give a base to loose objects. If group append, do it for objects too */
if (scene) {
const short is_link= (flag & FILE_LINK) != 0;
if (idcode==ID_SCE) {
/* don't instance anything when linking in scenes, assume the scene its self instances the data */
}
else {
give_base_to_objects(mainvar, scene, curlib, idcode, is_link);
if (flag & FILE_GROUP_INSTANCE) {
give_base_to_groups(mainvar, scene);
}
}
}
else {
printf("library_append_end, scene is NULL (objects wont get bases)\n");
}
}
/* has been removed... erm, why? s..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(*fd);
*fd = NULL;
}
}
void BLO_library_append_end(const bContext *C, struct Main *mainl, BlendHandle** bh, int idcode, short flag)
{
FileData *fd= (FileData*)(*bh);
library_append_end(C, mainl, &fd, idcode, flag);
*bh= (BlendHandle*)fd;
}
void *BLO_library_read_struct(FileData *fd, BHead *bh, const char *blockname)
{
return read_struct(fd, bh, blockname);
}
/* ************* READ LIBRARY ************** */
static int mainvar_count_libread_blocks(Main *mainvar)
{
ListBase *lbarray[MAX_LIBARRAY];
int a, tot= 0;
a= set_listbasepointers(mainvar, lbarray);
while (a--) {
ID *id;
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[MAX_LIBARRAY];
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) {
/* printf and reports for now... its important users know this */
BKE_reportf_wrap(basefd->reports, RPT_INFO,
"read library: '%s', '%s'\n",
mainptr->curlib->filepath, mainptr->curlib->name);
fd= blo_openblenderfile(mainptr->curlib->filepath, basefd->reports);
/* allow typing in a new lib path */
if (G.rt==-666) {
while (fd==NULL) {
char newlib_path[FILE_MAX] = { 0 };
printf("Missing library...'\n");
printf(" current file: %s\n", G.main->name);
printf(" absolute lib: %s\n", mainptr->curlib->filepath);
printf(" relative lib: %s\n", mainptr->curlib->name);
printf(" enter a new path:\n");
if (scanf("%s", newlib_path) > 0) {
BLI_strncpy(mainptr->curlib->name, newlib_path, sizeof(mainptr->curlib->name));
BLI_strncpy(mainptr->curlib->filepath, newlib_path, sizeof(mainptr->curlib->filepath));
cleanup_path(G.main->name, mainptr->curlib->filepath);
fd= blo_openblenderfile(mainptr->curlib->filepath, basefd->reports);
if (fd) {
printf("found: '%s', party on macuno!\n", mainptr->curlib->filepath);
}
}
}
}
if (fd) {
fd->reports= basefd->reports;
if (fd->libmap)
oldnewmap_free(fd->libmap);
fd->libmap = oldnewmap_new();
mainptr->curlib->filedata= fd;
mainptr->versionfile= fd->fileversion;
/* subversion */
read_file_version(fd, mainptr);
}
else mainptr->curlib->filedata= NULL;
if (fd==NULL) {
BKE_reportf_wrap(basefd->reports, RPT_ERROR,
"Can't find lib '%s'\n",
mainptr->curlib->filepath);
}
}
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) {
BKE_reportf_wrap(fd->reports, RPT_ERROR,
"LIB ERROR: %s:'%s' missing from '%s'\n",
BKE_idcode_to_name(GS(id->name)),
id->name+2, mainptr->curlib->filepath);
}
change_idid_adr(mainlist, basefd, 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;
}
}
/* test if there are unread libblocks */
for (mainptr= mainl->next; mainptr; mainptr= mainptr->next) {
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);
BKE_reportf_wrap(basefd->reports, RPT_ERROR,
"LIB ERROR: %s:'%s' unread libblock missing from '%s'\n",
BKE_idcode_to_name(GS(id->name)), id->name+2, mainptr->curlib->filepath);
change_idid_adr(mainlist, basefd, id, NULL);
MEM_freeN(id);
}
id= idn;
}
}
}
/* do versions, link, and free */
for (mainptr= mainl->next; mainptr; mainptr= mainptr->next) {
/* 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)
lib_link_all(mainptr->curlib->filedata, mainptr);
if (mainptr->curlib->filedata) blo_freefiledata(mainptr->curlib->filedata);
mainptr->curlib->filedata= NULL;
}
}
/* reading runtime */
BlendFileData *blo_read_blendafterruntime(int file, const char *name, int actualsize, ReportList *reports)
{
BlendFileData *bfd = NULL;
FileData *fd = filedata_new();
fd->filedes = file;
fd->buffersize = actualsize;
fd->read = fd_read_from_file;
/* needed for library_append and read_libraries */
BLI_strncpy(fd->relabase, name, sizeof(fd->relabase));
fd = blo_decode_and_check(fd, reports);
if (!fd)
return NULL;
fd->reports= reports;
bfd= blo_read_file_internal(fd, "");
blo_freefiledata(fd);
return bfd;
}