Old feature request: undo system now restores images without reloading.
Was surprisingly easy to add, compiant with file reading and undo code. Currently only the Image->ibuf gets restored, and its opengl binding, so for realtime texture it works nicely. Also texture images are not freed inbetween undo steps Notes: - Painting textures will just keep the painted image, there's no undo yet for that - If this works satisfying, I'll extend it to compositing previews TEST IT WELL PLEASE! :)
This commit is contained in:
@@ -289,6 +289,7 @@ BlendFileData *BLO_read_from_memory(void *mem, int memsize, BlendReadError *erro
|
||||
return bfd;
|
||||
}
|
||||
|
||||
|
||||
BlendFileData *BLO_read_from_memfile(const char *filename, MemFile *memfile, BlendReadError *error_r)
|
||||
{
|
||||
BlendFileData *bfd = NULL;
|
||||
@@ -297,11 +298,19 @@ BlendFileData *BLO_read_from_memfile(const char *filename, MemFile *memfile, Ble
|
||||
fd = blo_openblendermemfile(memfile, error_r);
|
||||
if (fd) {
|
||||
strcpy(fd->filename, filename);
|
||||
|
||||
/* makes lookup of existing images in G.main */
|
||||
blo_make_image_pointer_map(fd);
|
||||
|
||||
bfd= blo_read_file_internal(fd, error_r);
|
||||
if (bfd) {
|
||||
bfd->type= BLENFILETYPE_BLEND;
|
||||
strcpy(bfd->main->name, "");
|
||||
}
|
||||
|
||||
/* ensures relinked images are not freed */
|
||||
blo_end_image_pointer_map(fd);
|
||||
|
||||
blo_freefiledata(fd);
|
||||
}
|
||||
|
||||
|
||||
@@ -983,6 +983,8 @@ void blo_freefiledata(FileData *fd)
|
||||
oldnewmap_free(fd->datamap);
|
||||
if (fd->globmap)
|
||||
oldnewmap_free(fd->globmap);
|
||||
if (fd->imamap)
|
||||
oldnewmap_free(fd->imamap);
|
||||
if (fd->libmap && !(fd->flags & FD_FLAGS_NOT_MY_LIBMAP))
|
||||
oldnewmap_free(fd->libmap);
|
||||
|
||||
@@ -1009,6 +1011,14 @@ static void *newglobadr(FileData *fd, void *adr) /* direct datablocks with glob
|
||||
return oldnewmap_lookup_and_inc(fd->globmap, adr);
|
||||
}
|
||||
|
||||
static void *newimaadr(FileData *fd, void *adr) /* used to restore image data after undo */
|
||||
{
|
||||
if(fd->imamap && adr)
|
||||
return oldnewmap_lookup_and_inc(fd->imamap, adr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void *newlibadr(FileData *fd, void *lib, void *adr) /* only lib data */
|
||||
{
|
||||
return oldnewmap_liblookup(fd->libmap, adr, lib);
|
||||
@@ -1056,6 +1066,42 @@ static void change_idid_adr(ListBase *mainlist, FileData *basefd, void *old, voi
|
||||
}
|
||||
}
|
||||
|
||||
/* assumed; G.main still exists */
|
||||
void blo_make_image_pointer_map(FileData *fd)
|
||||
{
|
||||
Image *ima= G.main->image.first;
|
||||
|
||||
fd->imamap= oldnewmap_new();
|
||||
|
||||
for(;ima; ima= ima->id.next) {
|
||||
if(ima->ibuf)
|
||||
oldnewmap_insert(fd->imamap, ima->ibuf, ima->ibuf, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* set G.main image ibufs to zero if it has been restored */
|
||||
void blo_end_image_pointer_map(FileData *fd)
|
||||
{
|
||||
OldNew *entry= fd->imamap->entries;
|
||||
Image *ima= G.main->image.first;
|
||||
int i;
|
||||
|
||||
/* used entries were restored, so we put them to zero */
|
||||
for (i=0; i<fd->imamap->nentries; i++, entry++) {
|
||||
if (entry->nr>0)
|
||||
entry->newp= NULL;
|
||||
}
|
||||
|
||||
for(;ima; ima= ima->id.next) {
|
||||
if(ima->ibuf) {
|
||||
ima->ibuf= newimaadr(fd, ima->ibuf);
|
||||
/* this mirrors direct_link_image */
|
||||
if(ima->ibuf==NULL)
|
||||
ima->bindcode= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ********** END OLD POINTERS ****************** */
|
||||
/* ********** READ FILE ****************** */
|
||||
|
||||
@@ -1977,11 +2023,15 @@ static void lib_link_image(FileData *fd, Main *main)
|
||||
|
||||
static void direct_link_image(FileData *fd, Image *ima)
|
||||
{
|
||||
ima->ibuf= NULL;
|
||||
ima->anim= NULL;
|
||||
/* for undo system, pointers could be restored */
|
||||
ima->ibuf= newimaadr(fd, ima->ibuf);
|
||||
/* if restored, we keep the binded opengl index */
|
||||
if(ima->ibuf==NULL)
|
||||
ima->bindcode= 0;
|
||||
|
||||
memset(ima->mipmap, 0, sizeof(ima->mipmap));
|
||||
ima->repbind= 0;
|
||||
ima->bindcode= 0;
|
||||
ima->anim= NULL;
|
||||
ima->repbind= NULL;
|
||||
|
||||
ima->packedfile = direct_link_packedfile(fd, ima->packedfile);
|
||||
ima->preview = direct_link_preview_image(fd, ima->preview);
|
||||
|
||||
@@ -73,6 +73,7 @@ typedef struct FileData {
|
||||
struct OldNewMap *datamap;
|
||||
struct OldNewMap *globmap;
|
||||
struct OldNewMap *libmap;
|
||||
struct OldNewMap *imamap;
|
||||
|
||||
ListBase mainlist;
|
||||
|
||||
@@ -108,8 +109,10 @@ FileData *blo_openblenderfile( char *name, BlendReadError *error_r);
|
||||
FileData *blo_openblendermemory( void *buffer, int buffersize, BlendReadError *error_r);
|
||||
FileData *blo_openblendermemfile(struct MemFile *memfile, BlendReadError *error_r);
|
||||
|
||||
void blo_freefiledata( FileData *fd);
|
||||
void blo_make_image_pointer_map(FileData *fd);
|
||||
void blo_end_image_pointer_map(FileData *fd);
|
||||
|
||||
void blo_freefiledata( FileData *fd);
|
||||
|
||||
BHead *blo_firstbhead(FileData *fd);
|
||||
BHead *blo_nextbhead(FileData *fd, BHead *thisblock);
|
||||
|
||||
@@ -474,7 +474,7 @@ void free_realtime_image(Image *ima)
|
||||
glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
|
||||
|
||||
MEM_freeN(ima->repbind);
|
||||
ima->repbind= 0;
|
||||
ima->repbind= NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user