forked from bartvdbraak/blender
Second itteration of global undo system. Now based on:
- file-to-memory save - incremental difference steps (compression) everthing has been tightly coded to use minimum of memcpy or allocs. In fact this system works with a single full buffer (=file) in memory, and undosteps as differences from it. Speed gain is factor 4-8 faster. I've added it in CTRL+ALT+T timer menu for a test. Please note the gain is especially in the undo-storing, not in retrieving undo. Also new: file read option to skip UI read (file menu). This now also is default for the undo system.
This commit is contained in:
parent
61e4707bdb
commit
bf83f6ddd8
@ -41,11 +41,13 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
struct ListBase;
|
||||
struct MemFile;
|
||||
|
||||
#define BLENDER_VERSION 234
|
||||
|
||||
int BKE_read_file(char *dir, void *type_r);
|
||||
int BKE_read_file_from_memory(char* filebuf, int filelength, void *type_r);
|
||||
int BKE_read_file_from_memfile(struct MemFile *memfile);
|
||||
|
||||
void duplicatelist(struct ListBase *list1, struct ListBase *list2);
|
||||
void free_blender(void);
|
||||
|
@ -202,6 +202,8 @@ typedef struct Global {
|
||||
#define G_FILE_LOCK_BIT 7
|
||||
#define G_FILE_SIGN_BIT 8
|
||||
#define G_FILE_PUBLISH_BIT 9
|
||||
#define G_FILE_NO_UI_BIT 10
|
||||
|
||||
|
||||
#define G_AUTOPACK (1 << G_AUTOPACK_BIT)
|
||||
#define G_FILE_COMPRESS (1 << G_FILE_COMPRESS_BIT)
|
||||
@ -213,6 +215,7 @@ typedef struct Global {
|
||||
#define G_FILE_LOCK (1 << G_FILE_LOCK_BIT)
|
||||
#define G_FILE_SIGN (1 << G_FILE_SIGN_BIT)
|
||||
#define G_FILE_PUBLISH (1 << G_FILE_PUBLISH_BIT)
|
||||
#define G_FILE_NO_UI (1 << G_FILE_NO_UI_BIT)
|
||||
|
||||
/* G.windowstate */
|
||||
#define G_WINDOWSTATE_USERDEF 0
|
||||
|
@ -81,6 +81,7 @@
|
||||
|
||||
#include "BLI_editVert.h"
|
||||
|
||||
#include "BLO_undofile.h"
|
||||
#include "BLO_readfile.h" /* for BLO_read_file */
|
||||
|
||||
#include "BKE_bad_level_calls.h" // for freeAllRad editNurb free_editMesh free_editText free_editArmature
|
||||
@ -223,7 +224,8 @@ void initglobals(void)
|
||||
|
||||
/***/
|
||||
|
||||
static void clear_global(void) {
|
||||
static void clear_global(void)
|
||||
{
|
||||
extern short winqueue_break; /* screen.c */
|
||||
|
||||
freeAllRad();
|
||||
@ -261,8 +263,36 @@ static void clear_global(void) {
|
||||
G.f &= ~(G_WEIGHTPAINT + G_VERTEXPAINT + G_FACESELECT);
|
||||
}
|
||||
|
||||
static void setup_app_data(BlendFileData *bfd, char *filename) {
|
||||
static void setup_app_data(BlendFileData *bfd, char *filename)
|
||||
{
|
||||
Object *ob;
|
||||
bScreen *curscreen= NULL;
|
||||
Scene *curscene= NULL;
|
||||
char mode;
|
||||
|
||||
/* 'u' = undo save, 'n' = no UI load */
|
||||
if(bfd->main->screen.first==NULL) mode= 'u';
|
||||
else if(G.fileflags & G_FILE_NO_UI) mode= 'n';
|
||||
else mode= 0;
|
||||
|
||||
/* no load screens? */
|
||||
if(mode) {
|
||||
/* comes from readfile.c */
|
||||
extern void lib_link_screen_restore(Main *, char, Scene *);
|
||||
|
||||
SWAP(ListBase, G.main->screen, bfd->main->screen);
|
||||
|
||||
/* we re-use current screen */
|
||||
curscreen= G.curscreen;
|
||||
/* but use new Scene pointer */
|
||||
curscene= bfd->curscene;
|
||||
if(curscene==NULL) curscene= bfd->main->scene.first;
|
||||
/* and we enforce curscene to be in current screen */
|
||||
curscreen->scene= curscene;
|
||||
|
||||
/* clear_global will free G.main, here we can still restore pointers */
|
||||
lib_link_screen_restore(bfd->main, mode, curscene);
|
||||
}
|
||||
|
||||
clear_global();
|
||||
|
||||
@ -286,11 +316,19 @@ static void setup_app_data(BlendFileData *bfd, char *filename) {
|
||||
if(U.mixbufsize==0) U.mixbufsize= 2048;
|
||||
}
|
||||
|
||||
R.winpos= bfd->winpos;
|
||||
R.displaymode= bfd->displaymode;
|
||||
G.curscreen= bfd->curscreen;
|
||||
G.fileflags= bfd->fileflags;
|
||||
|
||||
/* case G_FILE_NO_UI or no screens in file */
|
||||
if(mode) {
|
||||
G.curscreen= curscreen;
|
||||
G.scene= curscene;
|
||||
}
|
||||
else {
|
||||
R.winpos= bfd->winpos;
|
||||
R.displaymode= bfd->displaymode;
|
||||
G.fileflags= bfd->fileflags;
|
||||
G.curscreen= bfd->curscreen;
|
||||
G.scene= G.curscreen->scene;
|
||||
}
|
||||
|
||||
/* special cases, override loaded flags: */
|
||||
if (G.f & G_DEBUG) bfd->globalf |= G_DEBUG;
|
||||
else bfd->globalf &= ~G_DEBUG;
|
||||
@ -298,7 +336,6 @@ static void setup_app_data(BlendFileData *bfd, char *filename) {
|
||||
else bfd->globalf &= ~G_SCENESCRIPT;
|
||||
|
||||
G.f= bfd->globalf;
|
||||
G.scene= G.curscreen->scene;
|
||||
|
||||
/* few DispLists, but do text_to_curve */
|
||||
// this should be removed!!! But first a better displist system (ton)
|
||||
@ -330,7 +367,8 @@ static void setup_app_data(BlendFileData *bfd, char *filename) {
|
||||
MEM_freeN(bfd);
|
||||
}
|
||||
|
||||
int BKE_read_file(char *dir, void *type_r) {
|
||||
int BKE_read_file(char *dir, void *type_r)
|
||||
{
|
||||
BlendReadError bre;
|
||||
BlendFileData *bfd;
|
||||
|
||||
@ -376,3 +414,25 @@ int BKE_read_file_from_memory(char* filebuf, int filelength, void *type_r)
|
||||
|
||||
return (bfd?1:0);
|
||||
}
|
||||
|
||||
int BKE_read_file_from_memfile(MemFile *memfile)
|
||||
{
|
||||
BlendReadError bre;
|
||||
BlendFileData *bfd;
|
||||
|
||||
if (!G.background)
|
||||
waitcursor(1);
|
||||
|
||||
bfd= BLO_read_from_memfile(memfile, &bre);
|
||||
if (bfd) {
|
||||
setup_app_data(bfd, "<memory>");
|
||||
} else {
|
||||
error("Loading failed: %s", BLO_bre_as_string(bre));
|
||||
}
|
||||
|
||||
if (!G.background)
|
||||
waitcursor(0);
|
||||
|
||||
return (bfd?1:0);
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,7 @@
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_oops_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
@ -323,6 +324,19 @@ void unlink_object(Object *ob)
|
||||
if(v3d->localvd->persp>1) v3d->localvd->persp= 1;
|
||||
}
|
||||
}
|
||||
else if(sl->spacetype==SPACE_IPO) {
|
||||
SpaceIpo *sipo= (SpaceIpo *)sl;
|
||||
if(sipo->from == (ID *)ob) sipo->from= NULL;
|
||||
}
|
||||
else if(sl->spacetype==SPACE_OOPS) {
|
||||
SpaceOops *so= (SpaceOops *)sl;
|
||||
Oops *oops;
|
||||
oops= so->oops.first;
|
||||
while(oops) {
|
||||
if(oops->id==(ID *)ob) oops->id= NULL;
|
||||
oops= oops->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sa= sa->next;
|
||||
|
@ -43,6 +43,7 @@ struct Main;
|
||||
struct UserDef;
|
||||
struct bScreen;
|
||||
struct Scene;
|
||||
struct MemFile;
|
||||
|
||||
typedef struct BlendHandle BlendHandle;
|
||||
|
||||
@ -113,7 +114,7 @@ BlendFileData* BLO_read_from_file (char *file, BlendReadError *error_r);
|
||||
* code indicating the cause of the failure.
|
||||
* @return The data of the file.
|
||||
*/
|
||||
BlendFileData* BLO_read_from_memory (void *mem, int memsize, BlendReadError *error_r);
|
||||
BlendFileData* BLO_read_from_memory(void *mem, int memsize, BlendReadError *error_r);
|
||||
|
||||
|
||||
/**
|
||||
@ -124,6 +125,9 @@ BlendFileData* BLO_read_from_memory (void *mem, int memsize, BlendReadError *err
|
||||
* @return A static human readable string representation
|
||||
* of @a error.
|
||||
*/
|
||||
|
||||
BlendFileData *BLO_read_from_memfile(struct MemFile *memfile, BlendReadError *error_r);
|
||||
|
||||
char*
|
||||
BLO_bre_as_string(
|
||||
BlendReadError error);
|
||||
|
58
source/blender/blenloader/BLO_undofile.h
Normal file
58
source/blender/blenloader/BLO_undofile.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* $Id:
|
||||
*
|
||||
* ***** BEGIN GPL/BL DUAL 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. The Blender
|
||||
* Foundation also sells licenses for use in proprietary software under
|
||||
* the Blender License. See http://www.blender.org/BL/ for information
|
||||
* about this.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2004 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
* external writefile function prototypes
|
||||
*/
|
||||
|
||||
#ifndef BLO_UNDOFILE_H
|
||||
#define BLO_UNDOFILE_H
|
||||
|
||||
typedef struct {
|
||||
void *next, *prev;
|
||||
|
||||
char *buf;
|
||||
unsigned int ident, size;
|
||||
|
||||
} MemFileChunk;
|
||||
|
||||
typedef struct MemFile {
|
||||
ListBase chunks;
|
||||
unsigned int size;
|
||||
} MemFile;
|
||||
|
||||
/* actually only used writefile.c */
|
||||
extern void add_memfilechunk(MemFile *compare, MemFile *current, char *buf, unsigned int size);
|
||||
|
||||
/* exports */
|
||||
extern void BLO_free_memfile(MemFile *memfile);
|
||||
extern void BLO_merge_memfile(MemFile *first, MemFile *second);
|
||||
|
||||
#endif
|
||||
|
@ -34,8 +34,11 @@
|
||||
#ifndef BLO_WRITEFILE_H
|
||||
#define BLO_WRITEFILE_H
|
||||
|
||||
int BLO_write_file(char *dir, int write_flags, char **error_r);
|
||||
void BLO_write_runtime(char *file, char *exename);
|
||||
struct MemFile;
|
||||
|
||||
extern int BLO_write_file(char *dir, int write_flags, char **error_r);
|
||||
extern int BLO_write_file_mem(struct MemFile *compare, struct MemFile *current, int write_flags, char **error_r);
|
||||
extern void BLO_write_runtime(char *file, char *exename);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -61,6 +61,8 @@
|
||||
#include "BKE_library.h" // for free_main
|
||||
|
||||
#include "BLO_readfile.h"
|
||||
#include "BLO_undofile.h"
|
||||
|
||||
#include "readfile.h"
|
||||
|
||||
#include "BLO_readblenfile.h"
|
||||
@ -113,7 +115,8 @@ static IDType idtypes[]= {
|
||||
};
|
||||
static int nidtypes= sizeof(idtypes)/sizeof(idtypes[0]);
|
||||
|
||||
static IDType *idtype_from_name(char *str) {
|
||||
static IDType *idtype_from_name(char *str)
|
||||
{
|
||||
int i= nidtypes;
|
||||
|
||||
while (i--)
|
||||
@ -122,7 +125,8 @@ static IDType *idtype_from_name(char *str) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
static IDType *idtype_from_code(int code) {
|
||||
static IDType *idtype_from_code(int code)
|
||||
{
|
||||
int i= nidtypes;
|
||||
|
||||
while (i--)
|
||||
@ -132,7 +136,8 @@ static IDType *idtype_from_code(int code) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int bheadcode_is_idcode(int code) {
|
||||
static int bheadcode_is_idcode(int code)
|
||||
{
|
||||
return idtype_from_code(code)?1:0;
|
||||
}
|
||||
|
||||
@ -141,13 +146,15 @@ static int idcode_is_linkable(int code) {
|
||||
return idt?(idt->flags&IDTYPE_FLAGS_ISLINKABLE):0;
|
||||
}
|
||||
|
||||
char *BLO_idcode_to_name(int code) {
|
||||
char *BLO_idcode_to_name(int code)
|
||||
{
|
||||
IDType *idt= idtype_from_code(code);
|
||||
|
||||
return idt?idt->name:NULL;
|
||||
}
|
||||
|
||||
int BLO_idcode_from_name(char *name) {
|
||||
int BLO_idcode_from_name(char *name)
|
||||
{
|
||||
IDType *idt= idtype_from_name(name);
|
||||
|
||||
return idt?idt->code:0;
|
||||
@ -155,11 +162,13 @@ int BLO_idcode_from_name(char *name) {
|
||||
|
||||
/* Access routines used by filesel. */
|
||||
|
||||
BlendHandle *BLO_blendhandle_from_file(char *file) {
|
||||
BlendHandle *BLO_blendhandle_from_file(char *file)
|
||||
{
|
||||
return (BlendHandle*) blo_openblenderfile(file);
|
||||
}
|
||||
|
||||
void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp) {
|
||||
void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp)
|
||||
{
|
||||
FileData *fd= (FileData*) bh;
|
||||
BHead *bhead;
|
||||
|
||||
@ -188,7 +197,8 @@ void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp) {
|
||||
fprintf(fp, "]\n");
|
||||
}
|
||||
|
||||
LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype) {
|
||||
LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype)
|
||||
{
|
||||
FileData *fd= (FileData*) bh;
|
||||
LinkNode *names= NULL;
|
||||
BHead *bhead;
|
||||
@ -205,7 +215,8 @@ LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype)
|
||||
return names;
|
||||
}
|
||||
|
||||
LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh) {
|
||||
LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh)
|
||||
{
|
||||
FileData *fd= (FileData*) bh;
|
||||
GHash *gathered= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
|
||||
LinkNode *names= NULL;
|
||||
@ -239,7 +250,8 @@ void BLO_blendhandle_close(BlendHandle *bh) {
|
||||
|
||||
/**********/
|
||||
|
||||
BlendFileData *BLO_read_from_file(char *file, BlendReadError *error_r) {
|
||||
BlendFileData *BLO_read_from_file(char *file, BlendReadError *error_r)
|
||||
{
|
||||
BlendFileData *bfd = NULL;
|
||||
FileData *fd;
|
||||
|
||||
@ -256,7 +268,8 @@ BlendFileData *BLO_read_from_file(char *file, BlendReadError *error_r) {
|
||||
return bfd;
|
||||
}
|
||||
|
||||
BlendFileData *BLO_read_from_memory(void *mem, int memsize, BlendReadError *error_r) {
|
||||
BlendFileData *BLO_read_from_memory(void *mem, int memsize, BlendReadError *error_r)
|
||||
{
|
||||
BlendFileData *bfd = NULL;
|
||||
FileData *fd;
|
||||
|
||||
@ -273,7 +286,26 @@ BlendFileData *BLO_read_from_memory(void *mem, int memsize, BlendReadError *erro
|
||||
return bfd;
|
||||
}
|
||||
|
||||
void BLO_blendfiledata_free(BlendFileData *bfd) {
|
||||
BlendFileData *BLO_read_from_memfile(MemFile *memfile, BlendReadError *error_r)
|
||||
{
|
||||
BlendFileData *bfd = NULL;
|
||||
FileData *fd;
|
||||
|
||||
fd = blo_openblendermemfile(memfile);
|
||||
if (fd) {
|
||||
bfd= blo_read_file_internal(fd, error_r);
|
||||
if (bfd) {
|
||||
bfd->type= BLENFILETYPE_BLEND;
|
||||
strcpy(bfd->main->name, "");
|
||||
}
|
||||
blo_freefiledata(fd);
|
||||
}
|
||||
|
||||
return bfd;
|
||||
}
|
||||
|
||||
void BLO_blendfiledata_free(BlendFileData *bfd)
|
||||
{
|
||||
if (bfd->main) {
|
||||
free_main(bfd->main);
|
||||
}
|
||||
@ -285,7 +317,8 @@ void BLO_blendfiledata_free(BlendFileData *bfd) {
|
||||
MEM_freeN(bfd);
|
||||
}
|
||||
|
||||
char *BLO_bre_as_string(BlendReadError error) {
|
||||
char *BLO_bre_as_string(BlendReadError error)
|
||||
{
|
||||
switch (error) {
|
||||
case BRE_NONE:
|
||||
return "No error";
|
||||
|
@ -121,6 +121,7 @@
|
||||
#include "BIF_butspace.h" // for do_versions, patching event codes
|
||||
|
||||
#include "BLO_readfile.h"
|
||||
#include "BLO_undofile.h"
|
||||
#include "readfile.h"
|
||||
|
||||
#include "genfile.h"
|
||||
@ -767,6 +768,54 @@ static int fd_read_from_memory(FileData *filedata, void *buffer, int size)
|
||||
return (readsize);
|
||||
}
|
||||
|
||||
static int fd_read_from_memfile(FileData *filedata, void *buffer, int size)
|
||||
{
|
||||
static unsigned int seek= 1<<30; /* the current position */
|
||||
static unsigned int offset= 0; /* size of previous chunks */
|
||||
static MemFileChunk *chunk=NULL;
|
||||
|
||||
if(size==0) return 0;
|
||||
|
||||
if(seek != filedata->seek) {
|
||||
chunk= filedata->memfile->chunks.first;
|
||||
seek= 0;
|
||||
|
||||
while(chunk) {
|
||||
if(seek + chunk->size > filedata->seek) break;
|
||||
seek+= chunk->size;
|
||||
chunk= chunk->next;
|
||||
}
|
||||
offset= seek;
|
||||
seek= filedata->seek;
|
||||
}
|
||||
|
||||
if(chunk) {
|
||||
/* first check if it's on the end if current chunk */
|
||||
if( seek-offset == chunk->size) {
|
||||
offset+= chunk->size;
|
||||
chunk= chunk->next;
|
||||
}
|
||||
|
||||
/* debug, should never happen */
|
||||
if(chunk==NULL) {
|
||||
printf("illegal read, chunk zero\n");
|
||||
return 0;
|
||||
}
|
||||
else if( (seek-offset)+size > chunk->size) {
|
||||
size= chunk->size - (seek-offset);
|
||||
printf("chunk too large, clipped to %d\n", size);
|
||||
}
|
||||
|
||||
memcpy(buffer, chunk->buf + (seek-offset), size);
|
||||
filedata->seek += size;
|
||||
seek+= size;
|
||||
|
||||
return (size);
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FileData *filedata_new(void)
|
||||
{
|
||||
extern char DNAstr[]; /* DNA.c */
|
||||
@ -850,6 +899,34 @@ FileData *blo_openblendermemory(void *mem, int memsize)
|
||||
}
|
||||
}
|
||||
|
||||
FileData *blo_openblendermemfile(MemFile *memfile)
|
||||
{
|
||||
if (!memfile) {
|
||||
return NULL;
|
||||
} else {
|
||||
FileData *fd= filedata_new();
|
||||
fd->memfile= memfile;
|
||||
|
||||
fd->read= fd_read_from_memfile;
|
||||
fd->flags|= FD_FLAGS_NOT_MY_BUFFER;
|
||||
|
||||
decode_blender_header(fd);
|
||||
|
||||
if (fd->flags & FD_FLAGS_FILE_OK) {
|
||||
if (!read_file_dna(fd)) {
|
||||
blo_freefiledata(fd);
|
||||
fd= NULL;
|
||||
}
|
||||
} else {
|
||||
blo_freefiledata(fd);
|
||||
fd= NULL;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void blo_freefiledata(FileData *fd)
|
||||
{
|
||||
if (fd) {
|
||||
@ -2437,6 +2514,8 @@ static void direct_link_scene(FileData *fd, Scene *sce)
|
||||
|
||||
/* ************ READ SCREEN ***************** */
|
||||
|
||||
/* note: file read without screens option G_FILE_NO_UI;
|
||||
check lib pointers in call below */
|
||||
static void lib_link_screen(FileData *fd, Main *main)
|
||||
{
|
||||
bScreen *sc;
|
||||
@ -2478,8 +2557,8 @@ static void lib_link_screen(FileData *fd, Main *main)
|
||||
}
|
||||
else if(sl->spacetype==SPACE_BUTS) {
|
||||
SpaceButs *sbuts= (SpaceButs *)sl;
|
||||
sbuts->rect= 0;
|
||||
sbuts->lockpoin= 0;
|
||||
sbuts->rect= NULL;
|
||||
sbuts->lockpoin= NULL;
|
||||
if(main->versionfile<132) set_rects_butspace(sbuts);
|
||||
}
|
||||
else if(sl->spacetype==SPACE_FILE) {
|
||||
@ -2540,6 +2619,130 @@ static void lib_link_screen(FileData *fd, Main *main)
|
||||
}
|
||||
}
|
||||
|
||||
static void *restore_pointer_by_name(Main *mainp, ID *id)
|
||||
{
|
||||
ListBase *lb;
|
||||
ID *idn=NULL;
|
||||
|
||||
if(id) {
|
||||
lb= wich_libbase(mainp, GS(id->name));
|
||||
idn= lb->first;
|
||||
while(idn) {
|
||||
if( strcmp(idn->name, id->name)==0) {
|
||||
if(idn->us==0) idn->us++;
|
||||
break;
|
||||
}
|
||||
idn= idn->next;
|
||||
}
|
||||
}
|
||||
return idn;
|
||||
}
|
||||
|
||||
/* called from kernel/blender.c */
|
||||
void lib_link_screen_restore(Main *newmain, char mode, Scene *curscene)
|
||||
{
|
||||
bScreen *sc;
|
||||
ScrArea *sa;
|
||||
|
||||
sc= newmain->screen.first;
|
||||
while(sc) {
|
||||
|
||||
if(mode=='u') sc->scene= restore_pointer_by_name(newmain, (ID *)sc->scene);
|
||||
if(sc->scene==NULL || mode=='n') sc->scene= curscene;
|
||||
|
||||
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(mode=='u') v3d->camera= restore_pointer_by_name(newmain, (ID *)v3d->camera);
|
||||
if(v3d->camera==NULL || mode=='n') v3d->camera= sc->scene->camera;
|
||||
|
||||
if(v3d->scenelock) v3d->lay= sc->scene->lay;
|
||||
|
||||
if(v3d->bgpic) {
|
||||
v3d->bgpic->ima= restore_pointer_by_name(newmain, (ID *)v3d->bgpic->ima);
|
||||
v3d->bgpic->tex= restore_pointer_by_name(newmain, (ID *)v3d->bgpic->tex);
|
||||
if(v3d->bgpic->rect) freeN(v3d->bgpic->rect);
|
||||
v3d->bgpic->rect= NULL;
|
||||
}
|
||||
if(v3d->localvd) {
|
||||
if(mode=='u') v3d->localvd->camera= restore_pointer_by_name(newmain, (ID *)v3d->localvd->camera);
|
||||
if(v3d->localvd->camera==NULL || mode=='n') v3d->localvd->camera= sc->scene->camera;
|
||||
}
|
||||
}
|
||||
else if(sl->spacetype==SPACE_IPO) {
|
||||
SpaceIpo *sipo= (SpaceIpo *)sl;
|
||||
sipo->from= restore_pointer_by_name(newmain, (ID *)sipo->from);
|
||||
// not free sipo->ipokey, creates dependency with src/
|
||||
sipo->ipo= restore_pointer_by_name(newmain, (ID *)sipo->ipo);
|
||||
if(sipo->editipo) MEM_freeN(sipo->editipo);
|
||||
sipo->editipo= NULL;
|
||||
}
|
||||
else if(sl->spacetype==SPACE_BUTS) {
|
||||
SpaceButs *sbuts= (SpaceButs *)sl;
|
||||
sbuts->lockpoin= NULL;
|
||||
if(sbuts->rect) MEM_freeN(sbuts->rect);
|
||||
sbuts->rect= NULL;
|
||||
}
|
||||
else if(sl->spacetype==SPACE_FILE) {
|
||||
SpaceFile *sfile= (SpaceFile *)sl;
|
||||
|
||||
}
|
||||
else if(sl->spacetype==SPACE_IMASEL) {
|
||||
check_imasel_copy((SpaceImaSel *)sl);
|
||||
}
|
||||
else if(sl->spacetype==SPACE_ACTION) {
|
||||
SpaceAction *saction= (SpaceAction *)sl;
|
||||
saction->action = restore_pointer_by_name(newmain, (ID *)saction->action);
|
||||
}
|
||||
else if(sl->spacetype==SPACE_IMAGE) {
|
||||
SpaceImage *sima= (SpaceImage *)sl;
|
||||
|
||||
sima->image= restore_pointer_by_name(newmain, (ID *)sima->image);
|
||||
}
|
||||
else if(sl->spacetype==SPACE_NLA){
|
||||
/* SpaceNla *snla= (SpaceNla *)sl; */
|
||||
}
|
||||
else if(sl->spacetype==SPACE_TEXT) {
|
||||
SpaceText *st= (SpaceText *)sl;
|
||||
|
||||
st->text= restore_pointer_by_name(newmain, (ID *)st->text);
|
||||
}
|
||||
else if(sl->spacetype==SPACE_SCRIPT) {
|
||||
SpaceScript *sc= (SpaceScript *)sl;
|
||||
|
||||
sc->script = NULL;
|
||||
}
|
||||
else if(sl->spacetype==SPACE_OOPS) {
|
||||
SpaceOops *so= (SpaceOops *)sl;
|
||||
Oops *oops;
|
||||
|
||||
oops= so->oops.first;
|
||||
while(oops) {
|
||||
oops->id= restore_pointer_by_name(newmain, (ID *)oops->id);
|
||||
oops= oops->next;
|
||||
}
|
||||
|
||||
so->lockpoin= NULL;
|
||||
}
|
||||
else if(sl->spacetype==SPACE_SOUND) {
|
||||
SpaceSound *ssound= (SpaceSound *)sl;
|
||||
|
||||
ssound->sound= restore_pointer_by_name(newmain, (ID *)ssound->sound);
|
||||
}
|
||||
}
|
||||
sa= sa->next;
|
||||
}
|
||||
|
||||
sc= sc->id.next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void direct_link_screen(FileData *fd, bScreen *sc)
|
||||
{
|
||||
ScrArea *sa;
|
||||
@ -2881,12 +3084,17 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
|
||||
|
||||
static void link_global(FileData *fd, BlendFileData *bfd, FileGlobal *fg)
|
||||
{
|
||||
// this is nonsense... will get rid of it once (ton)
|
||||
// this is nonsense... make it struct once (ton)
|
||||
bfd->winpos= fg->winpos;
|
||||
bfd->fileflags= fg->fileflags;
|
||||
bfd->displaymode= fg->displaymode;
|
||||
bfd->globalf= fg->globalf;
|
||||
bfd->curscreen= newlibadr(fd, 0, fg->curscreen);
|
||||
bfd->curscene= newlibadr(fd, 0, fg->curscene);
|
||||
// this happens in files older than 2.35
|
||||
if(bfd->curscene==NULL) {
|
||||
if(bfd->curscreen) bfd->curscene= bfd->curscreen->scene;
|
||||
}
|
||||
}
|
||||
|
||||
static void vcol_to_fcol(Mesh *me)
|
||||
@ -4344,30 +4552,10 @@ BlendFileData *blo_read_file_internal(FileData *fd, BlendReadError *error_r)
|
||||
lib_link_all(fd, bfd->main);
|
||||
link_global(fd, bfd, fg); /* as last */
|
||||
|
||||
if (!bfd->curscreen)
|
||||
bfd->curscreen= bfd->main->screen.first;
|
||||
|
||||
if (bfd->curscreen) {
|
||||
bfd->curscene= bfd->curscreen->scene;
|
||||
if (!bfd->curscene) {
|
||||
bfd->curscene= bfd->main->scene.first;
|
||||
bfd->curscreen->scene= bfd->curscene;
|
||||
}
|
||||
}
|
||||
/* removed here: check for existance of curscreen/scene, moved to kernel setup_app */
|
||||
|
||||
MEM_freeN(fg);
|
||||
|
||||
/* require all files to have an active scene
|
||||
* and screen. (implicitly: require all files
|
||||
* to have at least one scene and one screen).
|
||||
*/
|
||||
if (!bfd->curscreen || !bfd->curscene) {
|
||||
*error_r= (!bfd->curscreen)?BRE_NO_SCREEN:BRE_NO_SCENE;
|
||||
|
||||
BLO_blendfiledata_free(bfd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bfd;
|
||||
}
|
||||
|
||||
@ -5202,7 +5390,8 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
|
||||
|
||||
/* reading runtime */
|
||||
|
||||
BlendFileData *blo_read_blendafterruntime(int file, int actualsize, BlendReadError *error_r) {
|
||||
BlendFileData *blo_read_blendafterruntime(int file, int actualsize, BlendReadError *error_r)
|
||||
{
|
||||
BlendFileData *bfd = NULL;
|
||||
FileData *fd = filedata_new();
|
||||
fd->filedes = file;
|
||||
|
@ -34,6 +34,7 @@
|
||||
#define READFILE_H
|
||||
|
||||
struct OldNewMap;
|
||||
struct MemFile;
|
||||
|
||||
typedef struct FileData {
|
||||
// linked list of BHeadN's
|
||||
@ -45,7 +46,9 @@ typedef struct FileData {
|
||||
int (*read)(struct FileData *filedata, void *buffer, int size);
|
||||
|
||||
// variables needed for reading from memory / stream
|
||||
char * buffer;
|
||||
char *buffer;
|
||||
// variables needed for reading from memfile (undo)
|
||||
struct MemFile *memfile;
|
||||
|
||||
// variables needed for reading from file
|
||||
int filedes;
|
||||
@ -93,39 +96,18 @@ typedef struct BHeadN {
|
||||
void blo_join_main(ListBase *mainlist);
|
||||
void blo_split_main(ListBase *mainlist);
|
||||
|
||||
BlendFileData*
|
||||
blo_read_file_internal(
|
||||
FileData *fd,
|
||||
BlendReadError *error_r);
|
||||
BlendFileData *blo_read_file_internal( FileData *fd, BlendReadError *error_r);
|
||||
|
||||
FileData *blo_openblenderfile( char *name);
|
||||
FileData *blo_openblendermemory( void *buffer, int buffersize);
|
||||
FileData *blo_openblendermemfile(struct MemFile *memfile);
|
||||
|
||||
void blo_freefiledata( FileData *fd);
|
||||
|
||||
|
||||
FileData*
|
||||
blo_openblenderfile(
|
||||
char *name);
|
||||
|
||||
FileData*
|
||||
blo_openblendermemory(
|
||||
void *buffer,
|
||||
int buffersize);
|
||||
|
||||
void
|
||||
blo_freefiledata(
|
||||
FileData *fd);
|
||||
|
||||
|
||||
BHead*
|
||||
blo_firstbhead(
|
||||
FileData *fd);
|
||||
|
||||
BHead*
|
||||
blo_nextbhead(
|
||||
FileData *fd,
|
||||
BHead *thisblock);
|
||||
|
||||
BHead*
|
||||
blo_prevbhead(
|
||||
FileData *fd,
|
||||
BHead *thisblock);
|
||||
BHead *blo_firstbhead(FileData *fd);
|
||||
BHead *blo_nextbhead(FileData *fd, BHead *thisblock);
|
||||
BHead *blo_prevbhead(FileData *fd, BHead *thisblock);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -158,17 +158,22 @@ Important to know is that 'streaming' has been added to files, for Blender Publi
|
||||
|
||||
#include "BLO_writefile.h"
|
||||
#include "BLO_readfile.h"
|
||||
#include "BLO_undofile.h"
|
||||
|
||||
#include "readfile.h"
|
||||
#include "genfile.h"
|
||||
|
||||
|
||||
/* ********* my write, buffered writing with minimum 50k chunks ************ */
|
||||
|
||||
typedef struct {
|
||||
struct SDNA *sdna;
|
||||
|
||||
int file;
|
||||
unsigned char *buf;
|
||||
|
||||
int tot, count, error;
|
||||
MemFile *compare, *current;
|
||||
|
||||
int tot, count, error, memsize;
|
||||
} WriteData;
|
||||
|
||||
static WriteData *writedata_new(int file)
|
||||
@ -193,8 +198,16 @@ static WriteData *writedata_new(int file)
|
||||
static void writedata_do_write(WriteData *wd, void *mem, int memlen)
|
||||
{
|
||||
if (wd->error) return;
|
||||
if (write(wd->file, mem, memlen) != memlen)
|
||||
wd->error= 1;
|
||||
|
||||
/* memory based save */
|
||||
if(wd->current) {
|
||||
add_memfilechunk(NULL, wd->current, mem, memlen);
|
||||
}
|
||||
else {
|
||||
if (write(wd->file, mem, memlen) != memlen)
|
||||
wd->error= 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void writedata_free(WriteData *wd)
|
||||
@ -215,16 +228,23 @@ int mywfile;
|
||||
* @param len Length of new chunk of data
|
||||
* @warning Talks to other functions with global parameters
|
||||
*/
|
||||
static void
|
||||
mywrite(
|
||||
WriteData *wd,
|
||||
void *adr,
|
||||
int len)
|
||||
|
||||
#define MYWRITE_FLUSH NULL
|
||||
|
||||
static void mywrite( WriteData *wd, void *adr, int len)
|
||||
{
|
||||
if (wd->error) return;
|
||||
|
||||
wd->tot+= len;
|
||||
if(adr==MYWRITE_FLUSH) {
|
||||
if(wd->count) {
|
||||
writedata_do_write(wd, wd->buf, wd->count);
|
||||
wd->count= 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
wd->tot+= len;
|
||||
|
||||
if(len>50000) {
|
||||
if(wd->count) {
|
||||
writedata_do_write(wd, wd->buf, wd->count);
|
||||
@ -239,6 +259,7 @@ mywrite(
|
||||
}
|
||||
memcpy(&wd->buf[wd->count], adr, len);
|
||||
wd->count+= len;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -247,13 +268,15 @@ mywrite(
|
||||
* @param write_flags Write parameters
|
||||
* @warning Talks to other functions with global parameters
|
||||
*/
|
||||
static WriteData *
|
||||
bgnwrite(
|
||||
int file,
|
||||
int write_flags)
|
||||
static WriteData *bgnwrite(int file, MemFile *compare, MemFile *current, int write_flags)
|
||||
{
|
||||
WriteData *wd= writedata_new(file);
|
||||
|
||||
wd->compare= compare;
|
||||
wd->current= current;
|
||||
/* this inits comparing */
|
||||
add_memfilechunk(compare, NULL, NULL, 0);
|
||||
|
||||
return wd;
|
||||
}
|
||||
|
||||
@ -263,9 +286,7 @@ bgnwrite(
|
||||
* @return unknown global variable otherwise
|
||||
* @warning Talks to other functions with global parameters
|
||||
*/
|
||||
static int
|
||||
endwrite(
|
||||
WriteData *wd)
|
||||
static int endwrite(WriteData *wd)
|
||||
{
|
||||
int err;
|
||||
|
||||
@ -273,10 +294,10 @@ endwrite(
|
||||
writedata_do_write(wd, wd->buf, wd->count);
|
||||
wd->count= 0;
|
||||
}
|
||||
|
||||
|
||||
err= wd->error;
|
||||
writedata_free(wd);
|
||||
|
||||
if(wd->current) printf("undo size %d\n", wd->current->size);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -654,6 +675,9 @@ static void write_objects(WriteData *wd, ListBase *idbase)
|
||||
}
|
||||
ob= ob->id.next;
|
||||
}
|
||||
|
||||
/* flush helps the compression for undo-save */
|
||||
mywrite(wd, MYWRITE_FLUSH, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -709,6 +733,9 @@ static void write_ipos(WriteData *wd, ListBase *idbase)
|
||||
|
||||
ipo= ipo->id.next;
|
||||
}
|
||||
|
||||
/* flush helps the compression for undo-save */
|
||||
mywrite(wd, MYWRITE_FLUSH, 0);
|
||||
}
|
||||
|
||||
static void write_keys(WriteData *wd, ListBase *idbase)
|
||||
@ -733,6 +760,8 @@ static void write_keys(WriteData *wd, ListBase *idbase)
|
||||
|
||||
key= key->id.next;
|
||||
}
|
||||
/* flush helps the compression for undo-save */
|
||||
mywrite(wd, MYWRITE_FLUSH, 0);
|
||||
}
|
||||
|
||||
static void write_cameras(WriteData *wd, ListBase *idbase)
|
||||
@ -816,6 +845,9 @@ static void write_curves(WriteData *wd, ListBase *idbase)
|
||||
}
|
||||
cu= cu->id.next;
|
||||
}
|
||||
|
||||
/* flush helps the compression for undo-save */
|
||||
mywrite(wd, MYWRITE_FLUSH, 0);
|
||||
}
|
||||
|
||||
static void write_dverts(WriteData *wd, int count, MDeformVert *dvlist)
|
||||
@ -880,6 +912,8 @@ static void write_images(WriteData *wd, ListBase *idbase)
|
||||
}
|
||||
ima= ima->id.next;
|
||||
}
|
||||
/* flush helps the compression for undo-save */
|
||||
mywrite(wd, MYWRITE_FLUSH, 0);
|
||||
}
|
||||
|
||||
static void write_textures(WriteData *wd, ListBase *idbase)
|
||||
@ -899,6 +933,9 @@ static void write_textures(WriteData *wd, ListBase *idbase)
|
||||
}
|
||||
tex= tex->id.next;
|
||||
}
|
||||
|
||||
/* flush helps the compression for undo-save */
|
||||
mywrite(wd, MYWRITE_FLUSH, 0);
|
||||
}
|
||||
|
||||
static void write_materials(WriteData *wd, ListBase *idbase)
|
||||
@ -1088,6 +1125,8 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
|
||||
|
||||
sce= sce->id.next;
|
||||
}
|
||||
/* flush helps the compression for undo-save */
|
||||
mywrite(wd, MYWRITE_FLUSH, 0);
|
||||
}
|
||||
|
||||
static void write_screens(WriteData *wd, ListBase *scrbase)
|
||||
@ -1282,6 +1321,9 @@ static void write_armatures(WriteData *wd, ListBase *idbase)
|
||||
}
|
||||
arm=arm->id.next;
|
||||
}
|
||||
|
||||
/* flush helps the compression for undo-save */
|
||||
mywrite(wd, MYWRITE_FLUSH, 0);
|
||||
}
|
||||
|
||||
static void write_actions(WriteData *wd, ListBase *idbase)
|
||||
@ -1331,6 +1373,9 @@ static void write_texts(WriteData *wd, ListBase *idbase)
|
||||
}
|
||||
text= text->id.next;
|
||||
}
|
||||
|
||||
/* flush helps the compression for undo-save */
|
||||
mywrite(wd, MYWRITE_FLUSH, 0);
|
||||
}
|
||||
|
||||
static void write_sounds(WriteData *wd, ListBase *idbase)
|
||||
@ -1377,6 +1422,9 @@ static void write_sounds(WriteData *wd, ListBase *idbase)
|
||||
}
|
||||
sound= sound->id.next;
|
||||
}
|
||||
|
||||
/* flush helps the compression for undo-save */
|
||||
mywrite(wd, MYWRITE_FLUSH, 0);
|
||||
}
|
||||
|
||||
static void write_groups(WriteData *wd, ListBase *idbase)
|
||||
@ -1423,6 +1471,7 @@ static void write_global(WriteData *wd)
|
||||
FileGlobal fg;
|
||||
|
||||
fg.curscreen= G.curscreen;
|
||||
fg.curscene= G.scene;
|
||||
fg.displaymode= R.displaymode;
|
||||
fg.winpos= R.winpos;
|
||||
fg.fileflags= G.fileflags;
|
||||
@ -1431,8 +1480,10 @@ static void write_global(WriteData *wd)
|
||||
writestruct(wd, GLOB, "FileGlobal", 1, &fg);
|
||||
}
|
||||
|
||||
static int write_file_handle(int handle, int write_user_block, int write_flags)
|
||||
/* if *mem there's filesave to memory */
|
||||
static int write_file_handle(int handle, MemFile *compare, MemFile *current, int write_user_block, int write_flags)
|
||||
{
|
||||
BHead bhead;
|
||||
ListBase mainlist;
|
||||
char buf[13];
|
||||
WriteData *wd;
|
||||
@ -1443,21 +1494,18 @@ static int write_file_handle(int handle, int write_user_block, int write_flags)
|
||||
|
||||
blo_split_main(&mainlist);
|
||||
|
||||
wd= bgnwrite(handle, write_flags);
|
||||
|
||||
wd= bgnwrite(handle, compare, current, write_flags);
|
||||
|
||||
sprintf(buf, "BLENDER%c%c%.3d", (sizeof(void*)==8)?'-':'_', (G.order==B_ENDIAN)?'V':'v', G.version);
|
||||
mywrite(wd, buf, 12);
|
||||
|
||||
write_renderinfo(wd);
|
||||
|
||||
write_screens (wd, &G.main->screen);
|
||||
|
||||
if(current==NULL)
|
||||
write_screens (wd, &G.main->screen); // no UI save
|
||||
write_scenes (wd, &G.main->scene);
|
||||
write_objects (wd, &G.main->object);
|
||||
write_meshs (wd, &G.main->mesh);
|
||||
write_curves (wd, &G.main->curve);
|
||||
write_mballs (wd, &G.main->mball);
|
||||
write_materials(wd, &G.main->mat);
|
||||
write_textures (wd, &G.main->tex);
|
||||
write_images (wd, &G.main->image);
|
||||
write_cameras (wd, &G.main->camera);
|
||||
write_lamps (wd, &G.main->lamp);
|
||||
@ -1472,6 +1520,10 @@ static int write_file_handle(int handle, int write_user_block, int write_flags)
|
||||
write_groups (wd, &G.main->group);
|
||||
write_armatures(wd, &G.main->armature);
|
||||
write_actions (wd, &G.main->action);
|
||||
write_objects (wd, &G.main->object);
|
||||
write_materials(wd, &G.main->mat);
|
||||
write_textures (wd, &G.main->tex);
|
||||
write_meshs (wd, &G.main->mesh);
|
||||
write_libraries(wd, G.main->next);
|
||||
|
||||
write_global(wd);
|
||||
@ -1482,11 +1534,10 @@ static int write_file_handle(int handle, int write_user_block, int write_flags)
|
||||
/* dna as last, because (to be implemented) test for which structs are written */
|
||||
writedata(wd, DNA1, wd->sdna->datalen, wd->sdna->data);
|
||||
|
||||
data= ENDB;
|
||||
mywrite(wd, &data, 4);
|
||||
|
||||
data= 0;
|
||||
mywrite(wd, &data, 4);
|
||||
/* end of file */
|
||||
memset(&bhead, 0, sizeof(BHead));
|
||||
bhead.code= ENDB;
|
||||
mywrite(wd, &bhead, sizeof(BHead));
|
||||
|
||||
blo_join_main(&mainlist);
|
||||
G.main= mainlist.first;
|
||||
@ -1494,6 +1545,7 @@ static int write_file_handle(int handle, int write_user_block, int write_flags)
|
||||
return endwrite(wd);
|
||||
}
|
||||
|
||||
/* return: success (1) */
|
||||
int BLO_write_file(char *dir, int write_flags, char **error_r)
|
||||
{
|
||||
char userfilename[FILE_MAXDIR+FILE_MAXFILE];
|
||||
@ -1515,7 +1567,7 @@ int BLO_write_file(char *dir, int write_flags, char **error_r)
|
||||
|
||||
write_user_block= BLI_streq(dir, userfilename);
|
||||
|
||||
fout= write_file_handle(file, write_user_block, write_flags);
|
||||
fout= write_file_handle(file, NULL,NULL, write_user_block, write_flags);
|
||||
close(file);
|
||||
|
||||
if(!fout) {
|
||||
@ -1533,6 +1585,18 @@ int BLO_write_file(char *dir, int write_flags, char **error_r)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* return: success (1) */
|
||||
int BLO_write_file_mem(MemFile *compare, MemFile *current, int write_flags, char **error_r)
|
||||
{
|
||||
int err;
|
||||
|
||||
err= write_file_handle(0, compare, current, 0, write_flags);
|
||||
|
||||
if(err==0) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Runtime writing */
|
||||
|
||||
#ifdef WIN32
|
||||
@ -1632,7 +1696,7 @@ void BLO_write_runtime(char *file, char *exename) {
|
||||
outfd= open(gamename, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0777);
|
||||
if (outfd != -1) {
|
||||
|
||||
write_file_handle(outfd, 0, G.fileflags);
|
||||
write_file_handle(outfd, NULL,NULL, 0, G.fileflags);
|
||||
|
||||
if (write(outfd, " ", 1) != 1) {
|
||||
cause= "Unable to write to output file";
|
||||
@ -1712,7 +1776,7 @@ void BLO_write_runtime(char *file, char *exename) {
|
||||
|
||||
datastart= lseek(outfd, 0, SEEK_CUR);
|
||||
|
||||
write_file_handle(outfd, 0, G.fileflags);
|
||||
write_file_handle(outfd, NULL,NULL, 0, G.fileflags);
|
||||
|
||||
if (!handle_write_msb_int(outfd, datastart) || (write(outfd, "BRUNTIME", 8)!=8)) {
|
||||
cause= "Unable to write to output file";
|
||||
|
@ -40,6 +40,7 @@
|
||||
*/
|
||||
typedef struct FileGlobal {
|
||||
void *curscreen;
|
||||
void *curscene;
|
||||
short displaymode, winpos;
|
||||
int fileflags;
|
||||
int globalf;
|
||||
|
@ -554,11 +554,14 @@ void markdirty_all()
|
||||
ScrArea *sa;
|
||||
|
||||
for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
|
||||
scrarea_queue_winredraw(sa);
|
||||
sa->win_swap &= ~WIN_FRONT_OK;
|
||||
|
||||
scrarea_queue_headredraw(sa);
|
||||
sa->head_swap &= ~WIN_FRONT_OK;
|
||||
if(sa->win) {
|
||||
scrarea_queue_winredraw(sa);
|
||||
sa->win_swap &= ~WIN_FRONT_OK;
|
||||
}
|
||||
if(sa->headwin) {
|
||||
scrarea_queue_headredraw(sa);
|
||||
sa->head_swap &= ~WIN_FRONT_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1870,6 +1873,7 @@ void setscreen(bScreen *sc)
|
||||
sa= sa->next;
|
||||
}
|
||||
}
|
||||
else if(G.curscreen) markdirty_all(); /* at least redraw */
|
||||
|
||||
if (G.curscreen != sc) {
|
||||
mywinset(sc->mainwin);
|
||||
@ -1916,7 +1920,7 @@ void setscreen(bScreen *sc)
|
||||
|
||||
sa->cursor= CURSOR_STD;
|
||||
}
|
||||
|
||||
|
||||
G.scene= sc->scene;
|
||||
countall();
|
||||
|
||||
|
@ -883,12 +883,16 @@ static void do_info_filemenu(void *arg, int event)
|
||||
case 13:
|
||||
exit_usiblender();
|
||||
break;
|
||||
case 14:
|
||||
G.fileflags ^= G_FILE_NO_UI;
|
||||
break;
|
||||
case 31: /* save default settings */
|
||||
BIF_write_homefile();
|
||||
break;
|
||||
}
|
||||
allqueue(REDRAWINFO, 0);
|
||||
}
|
||||
|
||||
static uiBlock *info_filemenu(void *arg_unused)
|
||||
{
|
||||
uiBlock *block;
|
||||
@ -904,6 +908,14 @@ static uiBlock *info_filemenu(void *arg_unused)
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
if(G.fileflags & G_FILE_NO_UI) {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Load UI", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, "");
|
||||
} else {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Load UI", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, "");
|
||||
}
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save|Ctrl W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save As...|F2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
|
||||
|
||||
@ -1290,7 +1302,7 @@ static uiBlock *info_gamemenu(void *arg_unused)
|
||||
if(G.fileflags & (1 << G_FILE_ENABLE_ALL_FRAMES_BIT)) {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Enable All Frames", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_ENABLE_ALL_FRAMES_BIT, "");
|
||||
} else {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Enable All Frames", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_ENABLE_ALL_FRAMES_BIT, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Enable All Frames", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_ENABLE_ALL_FRAMES_BIT, "");
|
||||
}
|
||||
|
||||
if(G.fileflags & (1 << G_FILE_SHOW_FRAMERATE_BIT)) {
|
||||
|
@ -3091,7 +3091,7 @@ static int ui_do_block(uiBlock *block, uiEvent *uevent)
|
||||
if(inside || uevent->event!=LEFTMOUSE) {
|
||||
butevent= ui_do_button(block, but, uevent);
|
||||
|
||||
if(but->type!=BLOCK) BIF_write_undo(but->str);
|
||||
if(but->type!=BLOCK && but->type!=MENU) BIF_write_undo(but->str);
|
||||
|
||||
if(butevent) addqueue(block->winq, UI_BUT_EVENT, (short)butevent);
|
||||
|
||||
|
@ -105,6 +105,7 @@ Oops *find_oops(ID *id)
|
||||
return oops;
|
||||
}
|
||||
|
||||
/* never even called! (ton) */
|
||||
int test_oops(Oops *oops)
|
||||
{
|
||||
/* test if own ID block still exists */
|
||||
|
@ -888,7 +888,7 @@ int blenderqread(unsigned short event, short val)
|
||||
}
|
||||
else if(G.qual==(LR_ALTKEY|LR_CTRLKEY)) {
|
||||
int a;
|
||||
int event= pupmenu("10 Timer%t|draw|draw+swap|displist");
|
||||
int event= pupmenu("10 Timer%t|draw|draw+swap|displist|undo");
|
||||
if(event>0) {
|
||||
double stime= PIL_check_seconds_timer();
|
||||
char tmpstr[128];
|
||||
@ -907,6 +907,10 @@ int blenderqread(unsigned short event, short val)
|
||||
makeDispList(OBACT);
|
||||
}
|
||||
}
|
||||
else if(event==4) {
|
||||
extern void BIF_write_undo(char *name);
|
||||
BIF_write_undo("10 timer");
|
||||
}
|
||||
}
|
||||
|
||||
time= (PIL_check_seconds_timer()-stime)*1000;
|
||||
@ -914,6 +918,7 @@ int blenderqread(unsigned short event, short val)
|
||||
if(event==1) sprintf(tmpstr, "draw %%t|%d ms", time);
|
||||
if(event==2) sprintf(tmpstr, "d+sw %%t|%d ms", time);
|
||||
if(event==3) sprintf(tmpstr, "displist %%t|%d ms", time);
|
||||
if(event==4) sprintf(tmpstr, "undo %%t|%d ms", time);
|
||||
|
||||
waitcursor(0);
|
||||
pupmenu(tmpstr);
|
||||
|
@ -122,15 +122,16 @@
|
||||
|
||||
#include "PIL_time.h"
|
||||
|
||||
// temporal, will go to include file
|
||||
void BIF_reset_undo(void);
|
||||
void BIF_write_undo(char *);
|
||||
|
||||
|
||||
/***/
|
||||
|
||||
void BIF_read_file(char *name)
|
||||
{
|
||||
extern short winqueue_break; /* editscreen.c */
|
||||
void BIF_reset_undo(void);
|
||||
void BIF_write_undo(char *);
|
||||
|
||||
BIF_reset_undo();
|
||||
|
||||
//here?
|
||||
//sound_end_all_sounds();
|
||||
@ -149,6 +150,7 @@ void BIF_read_file(char *name)
|
||||
|
||||
winqueue_break= 1; /* leave queues everywhere */
|
||||
|
||||
BIF_reset_undo();
|
||||
BIF_write_undo("original"); /* save current state */
|
||||
}
|
||||
|
||||
@ -232,6 +234,8 @@ int BIF_read_homefile(void)
|
||||
space_set_commmandline_options();
|
||||
|
||||
if (U.undosteps==0) U.undosteps=32;
|
||||
BIF_reset_undo();
|
||||
BIF_write_undo("original"); /* save current state */
|
||||
|
||||
reset_autosave();
|
||||
|
||||
@ -464,124 +468,6 @@ static void delete_autosave(void)
|
||||
}
|
||||
}
|
||||
|
||||
/***/
|
||||
|
||||
#define MAXUNDONAME 64
|
||||
typedef struct UndoElem {
|
||||
struct UndoElem *next, *prev;
|
||||
char str[FILE_MAXDIR+FILE_MAXFILE];
|
||||
char name[MAXUNDONAME];
|
||||
} UndoElem;
|
||||
|
||||
#define MAXUNDO 32
|
||||
static ListBase undobase={NULL, NULL};
|
||||
static UndoElem *curundo= NULL;
|
||||
|
||||
static void get_undosave_location(char buf[FILE_MAXDIR+FILE_MAXFILE], int num)
|
||||
{
|
||||
char numstr[32];
|
||||
|
||||
sprintf(numstr, "%d.blend", num);
|
||||
BLI_make_file_string("/", buf, U.tempdir, numstr);
|
||||
|
||||
}
|
||||
|
||||
static int read_undosave(char *tstr)
|
||||
{
|
||||
char scestr[FILE_MAXDIR+FILE_MAXFILE];
|
||||
int success;
|
||||
|
||||
strcpy(scestr, G.sce); /* temporal store */
|
||||
|
||||
success= BKE_read_file(tstr, NULL);
|
||||
strcpy(G.sce, scestr);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/* name can be a dynamic string */
|
||||
void BIF_write_undo(char *name)
|
||||
{
|
||||
static int counter= 0;
|
||||
int nr;
|
||||
char *err, tstr[FILE_MAXDIR+FILE_MAXFILE];
|
||||
UndoElem *uel;
|
||||
|
||||
if( (U.uiflag & USER_GLOBALUNDO==0)) return;
|
||||
|
||||
/* calculate current filename */
|
||||
counter++;
|
||||
counter= counter % MAXUNDO;
|
||||
get_undosave_location(tstr, counter);
|
||||
|
||||
if(BLO_write_file(tstr, G.fileflags, &err)) {
|
||||
|
||||
/* remove all undos after (also when curundo==NULL) */
|
||||
while(undobase.last != curundo) {
|
||||
uel= undobase.last;
|
||||
BLI_remlink(&undobase, uel);
|
||||
MEM_freeN(uel);
|
||||
}
|
||||
|
||||
/* make new */
|
||||
curundo= uel= MEM_mallocN(sizeof(UndoElem), "undo file");
|
||||
strcpy(uel->str, tstr);
|
||||
strncpy(uel->name, name, MAXUNDONAME-1);
|
||||
BLI_addtail(&undobase, uel);
|
||||
|
||||
/* and limit amount to the maximum */
|
||||
nr= 0;
|
||||
uel= undobase.last;
|
||||
while(uel) {
|
||||
nr++;
|
||||
if(nr==MAXUNDO) break;
|
||||
uel= uel->prev;
|
||||
}
|
||||
if(uel) {
|
||||
while(undobase.first!=uel) {
|
||||
UndoElem *first= undobase.first;
|
||||
BLI_remlink(&undobase, first);
|
||||
MEM_freeN(first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* 1= an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation */
|
||||
void BIF_undo_step(int step)
|
||||
{
|
||||
|
||||
if(step==1) {
|
||||
/* curundo should never be NULL, after restart or load file it should call undo_save */
|
||||
if(curundo==NULL || curundo->prev==NULL) error("No undo available");
|
||||
else {
|
||||
printf("undo %s\n", curundo->name);
|
||||
curundo= curundo->prev;
|
||||
read_undosave(curundo->str);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
/* curundo has to remain current situation! */
|
||||
|
||||
if(curundo==NULL || curundo->next==NULL) error("No redo available");
|
||||
else {
|
||||
read_undosave(curundo->next->str);
|
||||
curundo= curundo->next;
|
||||
printf("redo %s\n", curundo->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BIF_reset_undo(void)
|
||||
{
|
||||
|
||||
BLI_freelistN(&undobase);
|
||||
curundo= NULL;
|
||||
}
|
||||
|
||||
|
||||
/***/
|
||||
|
||||
static void initbuttons(void)
|
||||
|
Loading…
Reference in New Issue
Block a user