Revision: 17460 http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17460 Author: campbellbarton Date: 2008-11-14 18:30:55 +0100 (Fri, 14 Nov 2008)
Log Message: ----------- tile based undo's now works while projection painting. TODO - float buffer support & for some reason painting on multiple images at once dosnt restore the tiles to the right image then undoing. Modified Paths: -------------- branches/projection-paint/source/blender/src/imagepaint.c Modified: branches/projection-paint/source/blender/src/imagepaint.c =================================================================== --- branches/projection-paint/source/blender/src/imagepaint.c 2008-11-14 17:05:25 UTC (rev 17459) +++ branches/projection-paint/source/blender/src/imagepaint.c 2008-11-14 17:30:55 UTC (rev 17460) @@ -244,6 +244,7 @@ typedef struct ProjectPixel { float projCo2D[2]; /* the floating point screen projection of this pixel */ + char origColor[4]; short x_px, y_px; void *pixel; short image_index; /* if anyone wants to paint onto more then 32000 images they can bite me */ @@ -301,6 +302,31 @@ tile->y*IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); } +static UndoTile *undo_init_tile(ID *id, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile) +{ + UndoTile *tile; + int allocsize; + + if (*tmpibuf==NULL) + *tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat|IB_rect, 0); + + tile= MEM_callocN(sizeof(UndoTile), "ImaUndoTile"); + tile->id= *id; + tile->x= x_tile; + tile->y= y_tile; + + allocsize= IMAPAINT_TILE_SIZE*IMAPAINT_TILE_SIZE*4; + allocsize *= (ibuf->rect_float)? sizeof(float): sizeof(char); + tile->rect= MEM_mapallocN(allocsize, "ImaUndoRect"); + + undo_copy_tile(tile, *tmpibuf, ibuf, 0); + curundo->undosize += allocsize; + + BLI_addtail(&curundo->tiles, tile); + + return tile; +} + static void undo_restore(UndoElem *undo) { Image *ima = NULL; @@ -1327,8 +1353,10 @@ if (ibuf->rect_float) { projPixel->pixel = (void *) ((( float * ) ibuf->rect_float) + (( x + y * ibuf->x ) * pixel_size)); + /* TODO float support for origColor */ } else { projPixel->pixel = (void *) ((( char * ) ibuf->rect) + (( x + y * ibuf->x ) * pixel_size)); + *((unsigned int *)projPixel->origColor) = *((unsigned int *)projPixel->pixel); } VECCOPY2D(projPixel->projCo2D, pixelScreenCo); @@ -2258,16 +2286,16 @@ ps->projectImBufs = BLI_memarena_alloc( ps->projectArena, sizeof(ImBuf *) * ps->projectImageTotal); *(ps->projectPartialRedraws) = BLI_memarena_alloc( ps->projectArena, sizeof(ImagePaintPartialRedraw) * ps->projectImageTotal * PROJ_BOUNDBOX_SQUARED); - for (a=1; a< ps->projectImageTotal; a++) { - ps->projectPartialRedraws[a] = *(ps->projectPartialRedraws) + (a * PROJ_BOUNDBOX_SQUARED); - } - // calloced - memset(ps->projectPartialRedraws, 0, sizeof(ImagePaintPartialRedraw) * ps->projectImageTotal); - for (node= image_LinkList, i=0; node; node= node->next, i++) { ps->projectImages[i] = node->link; ps->projectImages[i]->id.flag &= ~LIB_DOIT; ps->projectImBufs[i] = BKE_image_get_ibuf(ps->projectImages[i], NULL); + + ps->projectPartialRedraws[i] = *(ps->projectPartialRedraws) + (i * PROJ_BOUNDBOX_SQUARED); } + + // calloced - memset(ps->projectPartialRedraws, 0, sizeof(ImagePaintPartialRedraw) * ps->projectImageTotal); + /* we have built the array, discard the linked list */ BLI_linklist_free(image_LinkList, NULL); } @@ -2275,6 +2303,85 @@ static void project_paint_end( ProjectPaintState *ps ) { int a; + + /* build undo data from original pixel colors */ + if(U.uiflag & USER_GLOBALUNDO) { + ProjectPixel *projPixel; + ImBuf *ibuf, *tmpibuf = NULL; + LinkNode *pixel_node; + UndoTile *tile; + UndoTile ***image_undo_tiles = (UndoTile ***)BLI_memarena_alloc( ps->projectArena, sizeof(UndoTile ***) * ps->projectImageTotal); + int bucket_index = (ps->bucketsX * ps->bucketsY) - 1; /* we could get an X/Y but easier to loop through all possible buckets */ + int tile_index; + int x_round, y_round; + int x_tile, y_tile; + + /* context */ + int last_image_index = -1; + int last_tile_width; + ImBuf *last_ibuf; + Image *last_ima; + UndoTile **last_undo_grid = NULL; + + + for(a=0; a < ps->projectImageTotal; a++) { + ibuf = ps->projectImBufs[a]; + image_undo_tiles[a] = (UndoTile **)BLI_memarena_alloc( + ps->projectArena, + sizeof(UndoTile **) * IMAPAINT_TILE_NUMBER(ibuf->x) * IMAPAINT_TILE_NUMBER(ibuf->y) ); + } + + do { + if ((pixel_node = ps->projectBuckets[bucket_index])) { + + /* loop through all pixels */ + while (pixel_node) { + /* ok we have a pixel, was it modified? */ + projPixel = (ProjectPixel *)pixel_node->link; + + /* TODO - support float */ + if (*((unsigned int *)projPixel->origColor) != *((unsigned int *)projPixel->pixel)) { + + if (last_image_index != projPixel->image_index) { + /* set the context */ + last_image_index = projPixel->image_index; + last_ima = ps->projectImages[last_image_index]; + last_ibuf = ps->projectImBufs[last_image_index]; + last_tile_width = IMAPAINT_TILE_NUMBER(last_ibuf->x); + last_undo_grid = image_undo_tiles[last_image_index]; + } + + x_tile = projPixel->x_px >> IMAPAINT_TILE_BITS; + y_tile = projPixel->y_px >> IMAPAINT_TILE_BITS; + + x_round = x_tile * IMAPAINT_TILE_SIZE; + y_round = y_tile * IMAPAINT_TILE_SIZE; + + tile_index = x_tile + y_tile * last_tile_width; + + if (last_undo_grid[tile_index]==NULL) { + /* add the undo tile from the modified image, then write the original colors back into it */ + tile = last_undo_grid[tile_index] = undo_init_tile(&last_ima->id, ibuf, &tmpibuf, x_tile, y_tile); + } else { + tile = last_undo_grid[tile_index]; + } + + /* This is a BIT ODD, but overwrite the undo tiles image info with this pixels original color + * because allocating the tiles allong the way slows down painting */ + /* TODO float buffer */ + ((unsigned int *)tile->rect)[ (projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE ] = *((unsigned int *)projPixel->origColor); + } + + pixel_node = pixel_node->next; + } + } + } while(bucket_index--); + + if (tmpibuf) + IMB_freeImBuf(tmpibuf); + } + /* done calculating undo data */ + BLI_memarena_free(ps->projectArena); for (a=0; a<ps->thread_tot; a++) { @@ -2339,7 +2446,7 @@ { ImBuf *tmpibuf = NULL; UndoTile *tile; - int srcx= 0, srcy= 0, origx, allocsize; + int srcx= 0, srcy= 0, origx; IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h); @@ -2372,22 +2479,7 @@ break; if(!tile) { - if (tmpibuf==NULL) - tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat|IB_rect, 0); - - tile= MEM_callocN(sizeof(UndoTile), "ImaUndoTile"); - tile->id= ima->id; - tile->x= x; - tile->y= y; - - allocsize= IMAPAINT_TILE_SIZE*IMAPAINT_TILE_SIZE*4; - allocsize *= (ibuf->rect_float)? sizeof(float): sizeof(char); - tile->rect= MEM_mapallocN(allocsize, "ImaUndoRect"); - - undo_copy_tile(tile, tmpibuf, ibuf, 0); - curundo->undosize += allocsize; - - BLI_addtail(&curundo->tiles, tile); + undo_init_tile(&ima->id, ibuf, &tmpibuf, x, y); } } } _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org http://lists.blender.org/mailman/listinfo/bf-blender-cvs