Old feature request: undo system now restores images without reloading.
authorTon Roosendaal <ton@blender.org>
Fri, 10 Nov 2006 10:17:04 +0000 (10:17 +0000)
committerTon Roosendaal <ton@blender.org>
Fri, 10 Nov 2006 10:17:04 +0000 (10:17 +0000)
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! :)

source/blender/blenloader/intern/readblenentry.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/readfile.h
source/blender/src/drawmesh.c

index 4e3c674c2f591aea83c775c95a3d36e7a689f6d0..175494850250120951a16c3d04033c219b8e1c45 100644 (file)
@@ -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);                   
        }
 
index 594bfba0e923e175da4a2ab28b052e393db43ac8..969a0c71ebbf4fdfc178298ce50ec643de62ba2b 100644 (file)
@@ -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,12 +2023,16 @@ 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);
        ima->ok= 1;
index efdfa9f76bf9dd4953b5207f4b9a097995c63269..a0f42769762a76a6e326cac974fc79164e27bf62 100644 (file)
@@ -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);
index 83ffa6f44d8c73e4a0e32bccbafebdc3cab899c8..727a6ae744e0d625ddcb060e68bebdf5b23911c8 100644 (file)
@@ -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;
        }
 }