diff options
Diffstat (limited to 'source/blender/blenloader')
-rw-r--r-- | source/blender/blenloader/BLO_readfile.h | 30 | ||||
-rw-r--r-- | source/blender/blenloader/BLO_runtime.h | 53 | ||||
-rw-r--r-- | source/blender/blenloader/BLO_writefile.h | 2 | ||||
-rw-r--r-- | source/blender/blenloader/CMakeLists.txt | 10 | ||||
-rw-r--r-- | source/blender/blenloader/SConscript | 2 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readblenentry.c | 61 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 407 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.h | 4 | ||||
-rw-r--r-- | source/blender/blenloader/intern/runtime.c | 145 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 154 |
10 files changed, 612 insertions, 256 deletions
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 22083eda1c8..85d4b936c51 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -49,6 +49,8 @@ struct SpaceFile; struct SpaceImaSel; struct UserDef; struct bContext; +struct BHead; +struct FileData; typedef struct BlendHandle BlendHandle; @@ -79,12 +81,12 @@ typedef struct BlendFileData { * returns NULL and sets a report in the list if * it cannot open the file. * - * @param file The path of the file to open. + * @param filepath The path of the file to open. * @param reports If the return value is NULL, errors * indicating the cause of the failure. * @return The data of the file. */ -BlendFileData* BLO_read_from_file(const char *file, struct ReportList *reports); +BlendFileData* BLO_read_from_file(const char *filepath, struct ReportList *reports); /** * Open a blender file from memory. The function @@ -209,22 +211,38 @@ int BLO_has_bfile_extension(char *str); */ int BLO_is_a_library(const char *path, char *dir, char *group); -struct Main* BLO_library_append_begin(const struct bContext *C, BlendHandle** bh, char *dir); +struct Main* BLO_library_append_begin(const struct bContext *C, BlendHandle** bh, const char *filepath); + /** * Link/Append a named datablock from an external blend file. * + * @param mainl The main database to link from (not the active one). + * @param bh The blender file handle. + * @param idname The name of the datablock (without the 2 char ID prefix) + * @param idcode The kind of datablock to link. + * @return the appended ID when found. + */ +struct ID *BLO_library_append_named_part(struct Main *mainl, BlendHandle** bh, const char *idname, const int idcode); + +/** + * Link/Append a named datablock from an external blend file. + * optionally instance the object in the scene when the flags are set. + * * @param C The context, when NULL instancing object in the scene isnt done. * @param mainl The main database to link from (not the active one). * @param bh The blender file handle. - * @param name The name of the datablock (without the 2 char ID prefix) + * @param idname The name of the datablock (without the 2 char ID prefix) * @param idcode The kind of datablock to link. * @param flag Options for linking, used for instancing. - * @return Boolean, 0 when the datablock could not be found. + * @return the appended ID when found. */ -int BLO_library_append_named_part(const struct bContext *C, struct Main *mainl, BlendHandle** bh, const char *name, int idcode, short flag); +struct ID *BLO_library_append_named_part_ex(const struct bContext *C, struct Main *mainl, BlendHandle** bh, const char *idname, const int idcode, const short flag); + void BLO_library_append_end(const struct bContext *C, struct Main *mainl, BlendHandle** bh, int idcode, short flag); +void *BLO_library_read_struct(struct FileData *fd, struct BHead *bh, const char *blockname); + /* deprecated */ #if 1 void BLO_script_library_append(BlendHandle **bh, char *dir, char *name, int idcode, short flag, struct Main *mainvar, struct Scene *scene, struct ReportList *reports); diff --git a/source/blender/blenloader/BLO_runtime.h b/source/blender/blenloader/BLO_runtime.h new file mode 100644 index 00000000000..920b14e92fa --- /dev/null +++ b/source/blender/blenloader/BLO_runtime.h @@ -0,0 +1,53 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 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. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#ifndef BLO_RUNTIME_H +#define BLO_RUNTIME_H + +/** \file BLO_runtime.h + * \ingroup blenloader + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct BlendFileData; +struct ReportList; + +int BLO_is_a_runtime(char *file); +struct BlendFileData *BLO_read_runtime(char *file, struct ReportList *reports); + +#ifdef __cplusplus +} +#endif + +#endif /* BLO_RUNTIME_H */ + diff --git a/source/blender/blenloader/BLO_writefile.h b/source/blender/blenloader/BLO_writefile.h index 651928aa6a1..5c41350a463 100644 --- a/source/blender/blenloader/BLO_writefile.h +++ b/source/blender/blenloader/BLO_writefile.h @@ -39,7 +39,7 @@ struct MemFile; struct Main; struct ReportList; -extern int BLO_write_file(struct Main *mainvar, char *dir, int write_flags, struct ReportList *reports, int *thumb); +extern int BLO_write_file(struct Main *mainvar, const char *filepath, int write_flags, struct ReportList *reports, int *thumb); extern int BLO_write_file_mem(struct Main *mainvar, struct MemFile *compare, struct MemFile *current, int write_flags); extern int BLO_write_runtime(struct Main *mainvar, const char *file, char *exename, struct ReportList *reports); diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt index 4d8ac9bc4b6..be15b191c8a 100644 --- a/source/blender/blenloader/CMakeLists.txt +++ b/source/blender/blenloader/CMakeLists.txt @@ -26,23 +26,27 @@ set(INC . - ../blenlib ../blenkernel + ../blenlib ../makesdna - ../readblenfile ../makesrna ../render/extern/include ../../../intern/guardedalloc +) + +set(INC_SYS ${ZLIB_INCLUDE_DIRS} ) set(SRC intern/readblenentry.c intern/readfile.c + intern/runtime.c intern/undofile.c intern/writefile.c BLO_readfile.h + BLO_runtime.h BLO_soundfile.h BLO_sys_types.h BLO_undofile.h @@ -54,4 +58,4 @@ if(WITH_BUILDINFO) add_definitions(-DNAN_BUILDINFO) endif() -blender_add_lib(bf_blenloader "${SRC}" "${INC}") +blender_add_lib(bf_blenloader "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/blenloader/SConscript b/source/blender/blenloader/SConscript index 695d17f0638..be9908d84e6 100644 --- a/source/blender/blenloader/SConscript +++ b/source/blender/blenloader/SConscript @@ -4,7 +4,7 @@ Import ('env') sources = env.Glob('intern/*.c') incs = '. #/intern/guardedalloc ../blenlib ../blenkernel' -incs += ' ../makesdna ../readblenfile ../editors/include' +incs += ' ../makesdna ../editors/include' incs += ' ../render/extern/include ../makesrna' incs += ' ' + env['BF_ZLIB_INC'] diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index 39fab1929da..4ce5685ff18 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -62,8 +62,6 @@ #include "readfile.h" -#include "BLO_readblenfile.h" - #include "BLO_sys_types.h" // needed for intptr_t #ifdef _WIN32 @@ -150,15 +148,14 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to LinkNode *previews= NULL; BHead *bhead; int looking=0; - int npreviews = 0; PreviewImage* prv = NULL; PreviewImage* new_prv = NULL; int tot= 0; for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) { if (bhead->code==ofblocktype) { - ID *id= (ID*) (bhead+1); - switch(GS(id->name)) + char *idname= bhead_id_name(fd, bhead); + switch(GS(idname)) { case ID_MA: /* fall through */ case ID_TE: /* fall through */ @@ -176,31 +173,29 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to } else if (bhead->code==DATA) { if (looking) { if (bhead->SDNAnr == DNA_struct_find_nr(fd->filesdna, "PreviewImage") ) { - prv = (PreviewImage*) (bhead+1); - npreviews = 0; - memcpy(new_prv, prv, sizeof(PreviewImage)); - if (prv->rect[0]) { - unsigned int *rect = NULL; - // int rectlen = 0; - new_prv->rect[0] = MEM_callocN(new_prv->w[0]*new_prv->h[0]*sizeof(unsigned int), "prvrect"); - bhead= blo_nextbhead(fd, bhead); - rect = (unsigned int*)(bhead+1); - // rectlen = new_prv->w[0]*new_prv->h[0]*sizeof(unsigned int); - memcpy(new_prv->rect[0], rect, bhead->len); - } else { - new_prv->rect[0] = NULL; - } - - if (prv->rect[1]) { - unsigned int *rect = NULL; - // int rectlen = 0; - new_prv->rect[1] = MEM_callocN(new_prv->w[1]*new_prv->h[1]*sizeof(unsigned int), "prvrect"); - bhead= blo_nextbhead(fd, bhead); - rect = (unsigned int*)(bhead+1); - // rectlen = new_prv->w[1]*new_prv->h[1]*sizeof(unsigned int); - memcpy(new_prv->rect[1], rect, bhead->len); - } else { - new_prv->rect[1] = NULL; + prv = BLO_library_read_struct(fd, bhead, "PreviewImage"); + if (prv) { + memcpy(new_prv, prv, sizeof(PreviewImage)); + if (prv->rect[0]) { + unsigned int *rect = NULL; + new_prv->rect[0] = MEM_callocN(new_prv->w[0]*new_prv->h[0]*sizeof(unsigned int), "prvrect"); + bhead= blo_nextbhead(fd, bhead); + rect = (unsigned int*)(bhead+1); + memcpy(new_prv->rect[0], rect, bhead->len); + } else { + new_prv->rect[0] = NULL; + } + + if (prv->rect[1]) { + unsigned int *rect = NULL; + new_prv->rect[1] = MEM_callocN(new_prv->w[1]*new_prv->h[1]*sizeof(unsigned int), "prvrect"); + bhead= blo_nextbhead(fd, bhead); + rect = (unsigned int*)(bhead+1); + memcpy(new_prv->rect[1], rect, bhead->len); + } else { + new_prv->rect[1] = NULL; + } + MEM_freeN(prv); } } } @@ -253,15 +248,15 @@ void BLO_blendhandle_close(BlendHandle *bh) { /**********/ -BlendFileData *BLO_read_from_file(const char *file, ReportList *reports) +BlendFileData *BLO_read_from_file(const char *filepath, ReportList *reports) { BlendFileData *bfd = NULL; FileData *fd; - fd = blo_openblenderfile(file, reports); + fd = blo_openblenderfile(filepath, reports); if (fd) { fd->reports= reports; - bfd= blo_read_file_internal(fd, file); + bfd= blo_read_file_internal(fd, filepath); blo_freefiledata(fd); } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9ff30916eff..1099823a8b1 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -76,6 +76,7 @@ #include "DNA_node_types.h" #include "DNA_object_fluidsim.h" // NT #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" @@ -138,7 +139,6 @@ //XXX #include "BIF_previewrender.h" // bedlelvel, for struct RenderInfo #include "BLO_readfile.h" #include "BLO_undofile.h" -#include "BLO_readblenfile.h" // streaming read pipe, for BLO_readblenfile BLO_readblenfilememory #include "readfile.h" @@ -489,13 +489,13 @@ static void read_file_version(FileData *fd, Main *main) } -static Main *blo_find_main(FileData *fd, ListBase *mainlist, const char *name, const char *relabase) +static Main *blo_find_main(FileData *fd, ListBase *mainlist, const char *filepath, const char *relabase) { Main *m; Library *lib; char name1[FILE_MAXDIR+FILE_MAXFILE]; - strncpy(name1, name, sizeof(name1)-1); + 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); @@ -513,14 +513,14 @@ static Main *blo_find_main(FileData *fd, ListBase *mainlist, const char *name, c BLI_addtail(mainlist, m); lib= alloc_libblock(&m->library, ID_LI, "lib"); - strncpy(lib->name, name, sizeof(lib->name)-1); + strncpy(lib->name, filepath, sizeof(lib->name)-1); BLI_strncpy(lib->filepath, name1, sizeof(lib->filepath)); m->curlib= lib; read_file_version(fd, m); - if(G.f & G_DEBUG) printf("blo_find_main: added new lib %s\n", name); + if(G.f & G_DEBUG) printf("blo_find_main: added new lib %s\n", filepath); return m; } @@ -946,14 +946,14 @@ static FileData *blo_decode_and_check(FileData *fd, ReportList *reports) /* 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 *name, ReportList *reports) +FileData *blo_openblenderfile(const char *filepath, ReportList *reports) { gzFile gzfile; errno= 0; - gzfile= gzopen(name, "rb"); + gzfile= gzopen(filepath, "rb"); if (gzfile == (gzFile)Z_NULL) { - BKE_reportf(reports, RPT_ERROR, "Unable to open \"%s\": %s.", name, errno ? strerror(errno) : "Unknown error reading file"); + 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(); @@ -961,7 +961,7 @@ FileData *blo_openblenderfile(const char *name, ReportList *reports) fd->read = fd_read_gzip_from_file; /* needed for library_append and read_libraries */ - BLI_strncpy(fd->relabase, name, sizeof(fd->relabase)); + BLI_strncpy(fd->relabase, filepath, sizeof(fd->relabase)); return blo_decode_and_check(fd, reports); } @@ -1084,7 +1084,7 @@ int BLO_is_a_library(const char *path, char *dir, char *group) /* now we know that we are in a blend file and it is safe to assume that gp actually points to a group */ - if (BLI_streq("Screen", gp)==0) + if (strcmp("Screen", gp)!=0) BLI_strncpy(group, gp, GROUP_MAX); } return 1; @@ -1585,7 +1585,7 @@ static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_p if (prv) { int i; - for (i=0; i < PREVIEW_MIPMAPS; ++i) { + for (i=0; i < NUM_ICON_SIZES; ++i) { if (prv->rect[i]) { prv->rect[i] = newdataadr(fd, prv->rect[i]); } @@ -1738,6 +1738,12 @@ static void direct_link_fmodifiers(FileData *fd, ListBase *list) 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: @@ -2089,7 +2095,7 @@ static void lib_nodetree_do_versions_group(bNodeTree *ntree) for (node=ntree->nodes.first; node; node=node->next) { if (node->type==NODE_GROUP) { bNodeTree *ngroup= (bNodeTree*)node->id; - if (ngroup->flag & NTREE_DO_VERSIONS) + if (ngroup && (ngroup->flag & NTREE_DO_VERSIONS)) lib_node_do_versions_group(node); } } @@ -2117,7 +2123,7 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open)) } { - int has_old_groups=0; + /*int has_old_groups=0;*/ /*UNUSED*/ /* 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 @@ -2127,7 +2133,7 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open)) if (ntree->flag & NTREE_DO_VERSIONS) { /* this adds copies and links from all unlinked internal sockets to group inputs/outputs. */ nodeGroupExposeAllSockets(ntree); - has_old_groups = 1; + /*has_old_groups = 1;*/ /*UNUSED*/ } } /* now verify all types in material trees, groups are set OK now */ @@ -3157,9 +3163,37 @@ static void lib_link_particlesettings(FileData *fd, Main *main) if(part->effector_weights) part->effector_weights->group = newlibadr(fd, part->id.lib, part->effector_weights->group); - dw = part->dupliweights.first; - for(; dw; dw=dw->next) - dw->ob = newlibadr(fd, part->id.lib, dw->ob); + if(part->dupliweights.first) { + 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); + } + } if(part->boids) { BoidState *state = part->boids->states.first; @@ -3534,6 +3568,18 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh) 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); @@ -3543,16 +3589,11 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh) } } - /* Gracefully handle corrupted mesh */ + /* 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) { - /* If totals match, simply load the current mesh verts into multires */ - if(mesh->totvert == ((MultiresLevel*)mesh->mr->levels.last)->totvert) - mesh->mr->verts = MEM_dupallocN(mesh->mvert); - else { - /* Otherwise, we can't recover the data, silently remove multires */ - multires_free(mesh->mr); - mesh->mr = NULL; - } + multires_free(mesh->mr); + mesh->mr = NULL; } if((fd->flags & FD_FLAGS_SWITCH_ENDIAN) && mesh->tface) { @@ -3839,26 +3880,10 @@ static void lib_link_object(FileData *fd, Main *main) if(smd && smd->type == MOD_SMOKE_TYPE_DOMAIN && smd->domain) { - smd->domain->coll_group = newlibadr_us(fd, ob->id.lib, smd->domain->coll_group); - smd->domain->eff_group = newlibadr_us(fd, ob->id.lib, smd->domain->eff_group); - smd->domain->fluid_group = newlibadr_us(fd, ob->id.lib, smd->domain->fluid_group); - - smd->domain->effector_weights->group = newlibadr(fd, ob->id.lib, smd->domain->effector_weights->group); - smd->domain->flags |= MOD_SMOKE_FILE_LOAD; /* flag for refreshing the simulation after loading */ } } - { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - - if(clmd) - { - clmd->sim_parms->effector_weights->group = newlibadr(fd, ob->id.lib, clmd->sim_parms->effector_weights->group); - clmd->coll_parms->group= newlibadr(fd, ob->id.lib, clmd->coll_parms->group); - } - } - /* texture field */ if(ob->pd) lib_link_partdeflect(fd, &ob->id, ob->pd); @@ -3969,7 +3994,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) fluidmd->fss= newdataadr(fd, fluidmd->fss); fluidmd->fss->fmd= fluidmd; - fluidmd->fss->meshSurfNormals = NULL; + fluidmd->fss->meshVelocities = NULL; } else if (md->type==eModifierType_Smoke) { SmokeModifierData *smd = (SmokeModifierData*) md; @@ -4142,9 +4167,8 @@ static void direct_link_object(FileData *fd, Object *ob) bActuator *act; PythonComponent *pc; ComponentProperty *cprop; - int a; - /* weak weak... this was only meant as draw flag, now is used in give_base too */ + /* 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 @@ -4242,6 +4266,7 @@ static void direct_link_object(FileData *fd, Object *ob) 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]); } @@ -4349,6 +4374,7 @@ static void direct_link_object(FileData *fd, Object *ob) MEM_freeN(hook); } + ob->customdata_mask= 0; ob->bb= NULL; ob->derivedDeform= NULL; ob->derivedFinal= NULL; @@ -4856,7 +4882,6 @@ static void lib_link_screen(FileData *fd, Main *main) else if(sl->spacetype==SPACE_FILE) { SpaceFile *sfile= (SpaceFile *)sl; sfile->files= NULL; - sfile->params= NULL; sfile->op= NULL; sfile->layout= NULL; sfile->folders_prev= NULL; @@ -5469,7 +5494,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc) sfile->files= NULL; sfile->layout= NULL; sfile->op= NULL; - sfile->params= NULL; + sfile->params= newdataadr(fd, sfile->params); } } @@ -5529,20 +5554,31 @@ static void lib_link_library(FileData *UNUSED(fd), Main *main) } } -/* Always call this once you havbe loaded new library data to set the relative paths correctly in relation to the blend file */ +/* 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') - return; - - 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? */ - strncpy(lib->name, lib->filepath, sizeof(lib->name)); - BLI_path_rel(lib->name, basepath); + 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) { + 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? */ + strncpy(lib->name, lib->filepath, sizeof(lib->name)); + BLI_path_rel(lib->name, basepath); + } } } } @@ -5659,11 +5695,10 @@ static BHead *read_data_into_oldnewmap(FileData *fd, BHead *bhead, const char *a while(bhead && bhead->code==DATA) { void *data; #if 0 - /* XXX DUMB DEBUGGING OPTION TO GIVE NAMES for guarded malloc errors */ + /* XXX DUMB DEBUGGING OPTION TO GIVE NAMES for guarded malloc errors */ short *sp= fd->filesdna->structs[bhead->SDNAnr]; - char *allocname = fd->filesdna->types[ sp[0] ]; char *tmp= malloc(100); - + allocname = fd->filesdna->types[ sp[0] ]; strcpy(tmp, allocname); data= read_struct(fd, bhead, tmp); #else @@ -6281,7 +6316,7 @@ static void area_add_header_region(ScrArea *sa, ListBase *lb) BLI_addtail(lb, ar); ar->regiontype= RGN_TYPE_HEADER; - if(sa->headertype==1) + if(sa->headertype==HEADERDOWN) ar->alignment= RGN_ALIGN_BOTTOM; else ar->alignment= RGN_ALIGN_TOP; @@ -8385,7 +8420,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) ArmatureModifierData *amd = (ArmatureModifierData*) md; if(amd->object && amd->deformflag==0) { Object *oba= newlibadr(fd, lib, amd->object); - bArmature *arm= newlibadr(fd, lib, oba->data); + arm= newlibadr(fd, lib, oba->data); amd->deformflag= arm->deformflag; } } @@ -8532,7 +8567,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) int a; for(a=0; a<MAX_MTEX; a++) { if(ma->mtex[a] && ma->mtex[a]->tex) { - Tex *tex= newlibadr(fd, lib, 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); } @@ -8724,7 +8759,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) /* now, subversion control! */ if(main->subversionfile < 3) { - bScreen *sc; Image *ima; Tex *tex; @@ -9641,7 +9675,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) fluidmd->fss->lastgoodframe = INT_MAX; fluidmd->fss->flag = 0; - fluidmd->fss->meshSurfNormals = NULL; + fluidmd->fss->meshVelocities = NULL; } } } @@ -9700,7 +9734,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) nu->radius_interp = 3; /* resolu and resolv are now used differently for surfaces - * rather then using the resolution to define the entire number of divisions, + * 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) { @@ -10140,7 +10174,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) ToolSettings *ts; //PTCacheID *pid; //ListBase pidlist; - int a; for(ob = main->object.first; ob; ob = ob->id.next) { //BKE_ptcache_ids_from_object(&pidlist, ob); @@ -10179,6 +10212,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } 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; @@ -10264,8 +10298,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) sce->gm.attrib = sce->r.attrib; //Stereo - sce->gm.xsch = sce->r.xsch; - sce->gm.ysch = sce->r.ysch; sce->gm.stereomode = sce->r.stereomode; /* reassigning stereomode NO_STEREO and DOME to a separeted flag*/ if (sce->gm.stereomode == 1){ //1 = STEREO_NOSTEREO @@ -11505,7 +11537,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) do_version_bone_roll_256(bone); /* fix for objects which have zero dquat's - * since this is multiplied with the quat rather then added */ + * 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); @@ -11612,9 +11644,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - /* put compatibility code here until next subversion bump */ - - { + 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? */ @@ -11666,6 +11696,35 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } } + + { + /* 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; + } + } + } + + /* put compatibility code here until next subversion bump */ + + { + } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ @@ -11748,7 +11807,8 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) // XXX user->uifonts.first= user->uifonts.last= NULL; - user->uistyles.first= user->uistyles.last= NULL; + + link_list(fd, &user->uistyles); /* free fd->datamap again */ oldnewmap_free_unused(fd->datamap); @@ -11757,7 +11817,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) return bhead; } -BlendFileData *blo_read_file_internal(FileData *fd, const char *filename) +BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) { BHead *bhead= blo_firstbhead(fd); BlendFileData *bfd; @@ -11769,7 +11829,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filename) bfd->main->versionfile= fd->fileversion; bfd->type= BLENFILETYPE_BLEND; - strncpy(bfd->main->name, filename, sizeof(bfd->main->name)-1); + strncpy(bfd->main->name, filepath, sizeof(bfd->main->name)-1); while(bhead) { switch(bhead->code) { @@ -12208,6 +12268,9 @@ static void expand_material(FileData *fd, Main *mainvar, Material *ma) 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) @@ -12722,11 +12785,11 @@ static int object_in_any_scene(Main *mainvar, Object *ob) return 0; } -/* when *lib set, it also does objects that were in the appended group */ -static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, int is_group_append) +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) { @@ -12742,12 +12805,32 @@ static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, int is int do_it= 0; - if(ob->id.us==0) + if(ob->id.us==0) { do_it= 1; - else if(ob->id.us==1 && lib) - if(ob->id.lib==lib && (ob->flag & OB_FROMGROUP) && object_in_any_scene(mainvar, ob)==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); @@ -12764,7 +12847,6 @@ static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, int is } } -/* when *lib set, it also does objects that were in the appended group */ static void give_base_to_groups(Main *mainvar, Scene *scene) { Group *group; @@ -12796,29 +12878,22 @@ static void give_base_to_groups(Main *mainvar, Scene *scene) } /* returns true if the item was found - * but it may already have already been appended/linked */ -static int append_named_part(const bContext *C, Main *mainl, FileData *fd, const char *name, int idcode, short flag) +* but it may already have already been appended/linked */ +static ID *append_named_part(Main *mainl, FileData *fd, const char *idname, const short idcode) { - Scene *scene= CTX_data_scene(C); - Object *ob; - Base *base; BHead *bhead; - ID *id; - int endloop=0; + ID *id= NULL; int found=0; - bhead = blo_firstbhead(fd); - while(bhead && endloop==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(bhead->code==ENDB) endloop= 1; - else if(bhead->code==idcode) { - char *idname= bhead_id_name(fd, bhead); - - if(strcmp(idname+2, name)==0) { + if(strcmp(idname_test + 2, idname)==0) { found= 1; id= is_yet_read(fd, mainl, bhead); if(id==NULL) { - read_libblock(fd, mainl, bhead, LIB_TESTEXT, NULL); + read_libblock(fd, mainl, bhead, LIB_TESTEXT, &id); } else { printf("append: already linked\n"); @@ -12829,47 +12904,67 @@ static int append_named_part(const bContext *C, Main *mainl, FileData *fd, const } } - if(idcode==ID_OB && scene) { /* loose object: give a base */ - base= MEM_callocN( sizeof(Base), "app_nam_part"); - BLI_addtail(&scene->base, base); - - if(id==NULL) ob= mainl->object.last; - else 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); - if (v3d) { - ob->lay = v3d->layact; - } else { - ob->lay = 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 */ - } - } - endloop= 1; + break; } } + else if(bhead->code==ENDB) { + break; + } + } - bhead = blo_nextbhead(fd, bhead); + /* 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 found; + 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); } -int BLO_library_append_named_part(const bContext *C, Main *mainl, BlendHandle** bh, const char *name, int idcode, short flag) +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(C, mainl, fd, name, idcode, flag); + 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) @@ -12878,8 +12973,8 @@ static void append_id_part(FileData *fd, Main *mainvar, ID *id, ID **id_r) for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) { if (bhead->code == GS(id->name)) { - - if (BLI_streq(id->name, bhead_id_name(fd, bhead))) { + + 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); @@ -12894,7 +12989,7 @@ static void append_id_part(FileData *fd, Main *mainvar, ID *id, ID **id_r) /* common routine to append/link something from a library */ -static Main* library_append_begin(const bContext *C, FileData **fd, char *dir) +static Main* library_append_begin(const bContext *C, FileData **fd, const char *filepath) { Main *mainvar= CTX_data_main(C); Main *mainl; @@ -12903,7 +12998,7 @@ static Main* library_append_begin(const bContext *C, FileData **fd, char *dir) blo_split_main(&(*fd)->mainlist, mainvar); /* which one do we need? */ - mainl = blo_find_main(*fd, &(*fd)->mainlist, dir, G.main->name); + mainl = blo_find_main(*fd, &(*fd)->mainlist, filepath, G.main->name); /* needed for do_version */ mainl->versionfile= (*fd)->fileversion; @@ -12912,10 +13007,10 @@ static Main* library_append_begin(const bContext *C, FileData **fd, char *dir) return mainl; } -Main* BLO_library_append_begin(const bContext *C, BlendHandle** bh, char *dir) +Main* BLO_library_append_begin(const bContext *C, BlendHandle** bh, const char *filepath) { FileData *fd= (FileData*)(*bh); - return library_append_begin(C, &fd, dir); + return library_append_begin(C, &fd, filepath); } static void append_do_cursor(Scene *scene, Library *curlib, short flag) @@ -13000,23 +13095,21 @@ static void library_append_end(const bContext *C, Main *mainl, FileData **fd, in /* 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) { /* dont instance anything when linking in scenes, assume the scene its self instances the data */ } - else if(idcode==ID_GR) { - if (flag & FILE_LINK) { - give_base_to_objects(mainvar, scene, NULL, 0); - } else { - give_base_to_objects(mainvar, scene, curlib, 1); - } + else { + give_base_to_objects(mainvar, scene, curlib, idcode, is_link); if (flag & FILE_GROUP_INSTANCE) { give_base_to_groups(mainvar, scene); } - } else { - give_base_to_objects(mainvar, scene, NULL, 0); } } + 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) */ @@ -13037,30 +13130,10 @@ void BLO_library_append_end(const bContext *C, struct Main *mainl, BlendHandle** *bh= (BlendHandle*)fd; } -/* this is a version of BLO_library_append needed by the BPython API, so - * scripts can load data from .blend files -- see Blender.Library module.*/ -/* append to scene */ -/* this should probably be moved into the Python code anyway */ -/* tentatively removed, Python should be able to use the split functions too: */ -/* BLO_library_append_begin, BLO_library_append_end, BLO_library_append_named_part */ -#if 0 -void BLO_script_library_append(BlendHandle **bh, char *dir, const char *name, - int idcode, short flag, Main *mainvar, Scene *scene, ReportList *reports) +void *BLO_library_read_struct(FileData *fd, BHead *bh, const char *blockname) { - FileData *fd= (FileData*)(*bh); - - /* try to append the requested object */ - fd->reports= reports; - library_append(mainvar, scene, name, dir, idcode, 0, &fd, NULL, 0, flag ); - if(fd) fd->reports= NULL; - - /* do we need to do this? */ - if(scene) - DAG_scene_sort(bmain, scene); - - *bh= (BlendHandle*)fd; + return read_struct(fd, bh, blockname); } -#endif /* ************* READ LIBRARY ************** */ diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index b409e456fe6..d4e42ccde16 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -113,9 +113,9 @@ struct Main; void blo_join_main(ListBase *mainlist); void blo_split_main(ListBase *mainlist, struct Main *main); -BlendFileData *blo_read_file_internal(FileData *fd, const char *filename); +BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath); -FileData *blo_openblenderfile(const char *name, struct ReportList *reports); +FileData *blo_openblenderfile(const char *filepath, struct ReportList *reports); FileData *blo_openblendermemory(void *buffer, int buffersize, struct ReportList *reports); FileData *blo_openblendermemfile(struct MemFile *memfile, struct ReportList *reports); diff --git a/source/blender/blenloader/intern/runtime.c b/source/blender/blenloader/intern/runtime.c new file mode 100644 index 00000000000..f5308b5ea5c --- /dev/null +++ b/source/blender/blenloader/intern/runtime.c @@ -0,0 +1,145 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 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. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** + * \file runtime.c + * \brief This file handles the loading of .blend files embedded in runtimes + * \ingroup blenloader + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> + +#ifdef WIN32 +#include <io.h> // read, open +#include "BLI_winstuff.h" +#else // ! WIN32 +#include <unistd.h> // read +#endif + +#include "BLO_readfile.h" +#include "BLO_runtime.h" + +#include "BKE_blender.h" +#include "BKE_report.h" +#include "BKE_utildefines.h" + +#include "BLI_blenlib.h" + +/* Runtime reading */ + +static int handle_read_msb_int(int handle) +{ + unsigned char buf[4]; + + if(read(handle, buf, 4) != 4) + return -1; + + return (buf[0]<<24) + (buf[1]<<16) + (buf[2]<<8) + (buf[3]<<0); +} + +int BLO_is_a_runtime(char *path) +{ + int res= 0, fd= open(path, O_BINARY|O_RDONLY, 0); + int datastart; + char buf[8]; + + if(fd==-1) + goto cleanup; + + lseek(fd, -12, SEEK_END); + + datastart= handle_read_msb_int(fd); + + if(datastart==-1) + goto cleanup; + else if(read(fd, buf, 8)!=8) + goto cleanup; + else if(memcmp(buf, "BRUNTIME", 8)!=0) + goto cleanup; + else + res= 1; + +cleanup: + if(fd!=-1) + close(fd); + + return res; +} + +BlendFileData *BLO_read_runtime(char *path, ReportList *reports) +{ + BlendFileData *bfd= NULL; + size_t actualsize; + int fd, datastart; + char buf[8]; + + fd= open(path, O_BINARY|O_RDONLY, 0); + + if(fd==-1) { + BKE_reportf(reports, RPT_ERROR, "Unable to open \"%s\": %s.", path, strerror(errno)); + goto cleanup; + } + + actualsize= BLI_filesize(fd); + + lseek(fd, -12, SEEK_END); + + datastart= handle_read_msb_int(fd); + + if(datastart==-1) { + BKE_reportf(reports, RPT_ERROR, "Unable to read \"%s\" (problem seeking)", path); + goto cleanup; + } + else if(read(fd, buf, 8)!=8) { + BKE_reportf(reports, RPT_ERROR, "Unable to read \"%s\" (truncated header)", path); + goto cleanup; + } + else if(memcmp(buf, "BRUNTIME", 8)!=0) { + BKE_reportf(reports, RPT_ERROR, "Unable to read \"%s\" (not a blend file)", path); + goto cleanup; + } + else { + //printf("starting to read runtime from %s at datastart %d\n", path, datastart); + lseek(fd, datastart, SEEK_SET); + bfd = blo_read_blendafterruntime(fd, path, actualsize-datastart, reports); + fd= -1; // file was closed in blo_read_blendafterruntime() + } + +cleanup: + if(fd!=-1) + close(fd); + + return bfd; +} + diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 28074b52322..3f2abd8355c 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -724,7 +724,8 @@ static void write_userdef(WriteData *wd) wmKeyMap *keymap; wmKeyMapItem *kmi; bAddon *bext; - + uiStyle *style; + writestruct(wd, USER, "UserDef", 1, &U); for(btheme= U.themes.first; btheme; btheme=btheme->next) @@ -743,6 +744,10 @@ static void write_userdef(WriteData *wd) for(bext= U.addons.first; bext; bext=bext->next) writestruct(wd, DATA, "bAddon", 1, bext); + + for(style= U.uistyles.first; style; style= style->next) { + writestruct(wd, DATA, "uiStyle", 1, style); + } } static void write_boid_state(WriteData *wd, BoidState *state) @@ -833,6 +838,7 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase) { ParticleSettings *part; ParticleDupliWeight *dw; + GroupObject *go; int a; part= idbase->first; @@ -847,8 +853,16 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase) writestruct(wd, DATA, "EffectorWeights", 1, part->effector_weights); dw = part->dupliweights.first; - for(; dw; dw=dw->next) + for(; dw; dw=dw->next) { + /* update indices */ + dw->index = 0; + go = part->dup_group->gobject.first; + while(go && go->ob != dw->ob) { + go=go->next; + dw->index++; + } writestruct(wd, DATA, "ParticleDupliWeight", 1, dw); + } if(part->boids && part->phystype == PART_PHYS_BOIDS) { BoidState *state = part->boids->states.first; @@ -2130,7 +2144,11 @@ static void write_screens(WriteData *wd, ListBase *scrbase) writestruct(wd, DATA, "SpaceButs", 1, sl); } else if(sl->spacetype==SPACE_FILE) { + SpaceFile *sfile= (SpaceFile *)sl; + writestruct(wd, DATA, "SpaceFile", 1, sl); + if(sfile->params) + writestruct(wd, DATA, "FileSelectParams", 1, sfile->params); } else if(sl->spacetype==SPACE_SEQ) { writestruct(wd, DATA, "SpaceSeq", 1, sl); @@ -2162,8 +2180,8 @@ static void write_screens(WriteData *wd, ListBase *scrbase) writestruct(wd, DATA, "SpaceText", 1, sl); } else if(sl->spacetype==SPACE_SCRIPT) { - SpaceScript *sc = (SpaceScript*)sl; - sc->but_refs = NULL; + SpaceScript *scr = (SpaceScript*)sl; + scr->but_refs = NULL; writestruct(wd, DATA, "SpaceScript", 1, sl); } else if(sl->spacetype==SPACE_ACTION) { @@ -2552,15 +2570,50 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil return endwrite(wd); } +/* do reverse file history: .blend1 -> .blend2, .blend -> .blend1 */ +/* return: success(0), failure(1) */ +static int do_history(const char *name, ReportList *reports) +{ + char tempname1[FILE_MAXDIR+FILE_MAXFILE], tempname2[FILE_MAXDIR+FILE_MAXFILE]; + int hisnr= U.versions; + + if(U.versions==0) return 0; + if(strlen(name)<2) { + BKE_report(reports, RPT_ERROR, "Unable to make version backup: filename too short"); + return 1; + } + + while(hisnr > 1) { + BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr-1); + BLI_snprintf(tempname2, sizeof(tempname2), "%s%d", name, hisnr); + + if(BLI_rename(tempname1, tempname2)) { + BKE_report(reports, RPT_ERROR, "Unable to make version backup"); + return 1; + } + hisnr--; + } + + /* is needed when hisnr==1 */ + BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr); + + if(BLI_rename(name, tempname1)) { + BKE_report(reports, RPT_ERROR, "Unable to make version backup"); + return 1; + } + + return 0; +} + /* return: success (1) */ -int BLO_write_file(Main *mainvar, char *dir, int write_flags, ReportList *reports, int *thumb) +int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportList *reports, int *thumb) { char userfilename[FILE_MAXDIR+FILE_MAXFILE]; char tempname[FILE_MAXDIR+FILE_MAXFILE+1]; int file, err, write_user_block; /* open temporary file, so we preserve the original in case we crash */ - BLI_snprintf(tempname, sizeof(tempname), "%s@", dir); + BLI_snprintf(tempname, sizeof(tempname), "%s@", filepath); file = open(tempname,O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666); if(file == -1) { @@ -2572,68 +2625,83 @@ int BLO_write_file(Main *mainvar, char *dir, int write_flags, ReportList *report if(write_flags & G_FILE_RELATIVE_REMAP) { char dir1[FILE_MAXDIR+FILE_MAXFILE]; char dir2[FILE_MAXDIR+FILE_MAXFILE]; - BLI_split_dirfile(dir, dir1, NULL); + BLI_split_dirfile(filepath, dir1, NULL); BLI_split_dirfile(mainvar->name, dir2, NULL); /* just incase there is some subtle difference */ BLI_cleanup_dir(mainvar->name, dir1); BLI_cleanup_dir(mainvar->name, dir2); - if(strcmp(dir1, dir2)==0) + if(BLI_path_cmp(dir1, dir2)==0) { write_flags &= ~G_FILE_RELATIVE_REMAP; - else - makeFilesAbsolute(mainvar, G.main->name, NULL); + } + else { + if(G.relbase_valid) { + /* blend may not have been saved before. Tn this case + * we should not have any relative paths, but if there + * is somehow, an invalid or empty G.main->name it will + * print an error, dont try make the absolute in this case. */ + makeFilesAbsolute(mainvar, G.main->name, NULL); + } + } } BLI_make_file_string(G.main->name, userfilename, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE); - write_user_block= (BLI_path_cmp(dir, userfilename) == 0); + write_user_block= (BLI_path_cmp(filepath, userfilename) == 0); if(write_flags & G_FILE_RELATIVE_REMAP) - makeFilesRelative(mainvar, dir, NULL); /* note, making relative to something OTHER then G.main->name */ + makeFilesRelative(mainvar, filepath, NULL); /* note, making relative to something OTHER then G.main->name */ /* actual file writing */ err= write_file_handle(mainvar, file, NULL,NULL, write_user_block, write_flags, thumb); close(file); - /* rename/compress */ - if(!err) { - if(write_flags & G_FILE_COMPRESS) { - /* compressed files have the same ending as regular files... only from 2.4!!! */ - char gzname[FILE_MAXDIR+FILE_MAXFILE+4]; - int ret; + if (err) { + BKE_report(reports, RPT_ERROR, strerror(errno)); + remove(tempname); - /* first write compressed to separate @.gz */ - BLI_snprintf(gzname, sizeof(gzname), "%s@.gz", dir); - ret = BLI_gzip(tempname, gzname); - - if(0==ret) { - /* now rename to real file name, and delete temp @ file too */ - if(BLI_rename(gzname, dir) != 0) { - BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @."); - return 0; - } + return 0; + } - BLI_delete(tempname, 0, 0); - } - else if(-1==ret) { - BKE_report(reports, RPT_ERROR, "Failed opening .gz file."); - return 0; - } - else if(-2==ret) { - BKE_report(reports, RPT_ERROR, "Failed opening .blend file for compression."); + /* file save to temporary file was successful */ + /* now do reverse file history (move .blend1 -> .blend2, .blend -> .blend1) */ + if (write_flags & G_FILE_HISTORY) { + int err_hist = do_history(filepath, reports); + if (err_hist) { + BKE_report(reports, RPT_ERROR, "Version backup failed. File saved with @"); + return 0; + } + } + + if(write_flags & G_FILE_COMPRESS) { + /* compressed files have the same ending as regular files... only from 2.4!!! */ + char gzname[FILE_MAXDIR+FILE_MAXFILE+4]; + int ret; + + /* first write compressed to separate @.gz */ + BLI_snprintf(gzname, sizeof(gzname), "%s@.gz", filepath); + ret = BLI_gzip(tempname, gzname); + + if(0==ret) { + /* now rename to real file name, and delete temp @ file too */ + if(BLI_rename(gzname, filepath) != 0) { + BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @."); return 0; } + + BLI_delete(tempname, 0, 0); } - else if(BLI_rename(tempname, dir) != 0) { - BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @"); + else if(-1==ret) { + BKE_report(reports, RPT_ERROR, "Failed opening .gz file."); + return 0; + } + else if(-2==ret) { + BKE_report(reports, RPT_ERROR, "Failed opening .blend file for compression."); return 0; } - } - else { - BKE_report(reports, RPT_ERROR, strerror(errno)); - remove(tempname); - + else if(BLI_rename(tempname, filepath) != 0) { + BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @"); return 0; } |