问题
I am making a paint application using OpenGl framework and I'm stuck at UNDO/REDO option.. The code I implemented is like this:
-(void)undo_called
{
artbrushAppDelegate *app=(artbrushAppDelegate *)[[UIApplication sharedApplication]delegate];
mbrushscale=app.brushscale;
brushimage=app.brush_image;
Erase=YES;
[self playRayundo];
}
-(void)playRayundo
{
artbrushAppDelegate *app=(artbrushAppDelegate *)[[UIApplication sharedApplication]delegate];
glColor4f(app.r1g,
app.b1g,
app.g1g,
0);
NSLog(@"%f",app.r1g);
if(undo != NULL)
{
for(int l = 0; l < [undo count]; l++)
{
//replays my writRay -1 because of location point
for(int p = 0; p < [[undo objectAtIndex:l]count]-1; p ++)
{
[self drawErase:[[[undo objectAtIndex:l]objectAtIndex:p]CGPointValue] toPoint:[[[undo objectAtIndex:l]objectAtIndex:p + 1]CGPointValue]];
}
}
}
Erase=NO;
glColor4f(app.rg,
app.bg,
app.gg,
kBrushOpacity);
}
-(void) drawErase:(CGPoint)start toPoint:(CGPoint)end
{
static GLfloat* eraseBuffer = NULL;
static NSUInteger eraseMax = 64;
NSUInteger vertexCount = 0,
count,
i;
[EAGLContext setCurrentContext:context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
// Convert locations from Points to Pixels
CGFloat scale = 1.0;//self.contentScaleFactor;
start.x *= scale;
start.y *= scale;
end.x *= scale;
end.y *= scale;
// Allocate vertex array buffer
if(eraseBuffer == NULL)
eraseBuffer = malloc(eraseMax * 2 * sizeof(GLfloat));
// Add points to the buffer so there are drawing points every X pixels
count = MAX(ceilf(sqrtf((end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y)) / kBrushPixelStep), 1);
for(i = 0; i < count; ++i)
{
if(vertexCount == eraseMax)
{
eraseMax = 2 * eraseMax;
eraseBuffer = realloc(eraseBuffer, eraseMax * 2 * sizeof(GLfloat));
}
eraseBuffer[2 * vertexCount + 0] = start.x + (end.x - start.x) * ((GLfloat)i / (GLfloat)count);
eraseBuffer[2 * vertexCount + 1] = start.y + (end.y - start.y) * ((GLfloat)i / (GLfloat)count);
vertexCount += 1;
}
[self ChangebrushPic:brushimage];
//the erase brush color is transparent.
glEnable(GL_POINT_SPRITE_OES);
glTexEnvf(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE);
glPointSize(64/mbrushscale);
// Render the vertex array
glVertexPointer(2, GL_FLOAT, 0, eraseBuffer);
glDrawArrays(GL_POINTS, 0, vertexCount);
// Display the buffer
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
// at last restore the mixed-mode
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
This code is not efficient and it has so many faults..Have a look at images before and After Undo.
Before: http://imageshack.us/photo/my-images/577/screenshot20110714at121.png/
After: http://imageshack.us/photo/my-images/200/screenshot20110714at121.png/
So i want to Save image in buffer every time user's Touch ends and call previous image on UNDO..Can anyone help me how to Store image in buffer and retrieve back on UNDO?? I tried to find its sample code but could not find..
Thanks..
回答1:
Ok. I am posting answer to my own Question as so many people seem to refer this question.
There is an application named TouchPainter and its source code is available. It contains drawing, color blending, Undo/Redo (Amazing..!!), Save/Open drawings..
Note : It may require very deep level knowledge of Objective C and design pattern (I still do not know what design pattern is. But I found it so I am sharing..). The whole application's source code is explained in this book "Apress.Pro Objective-C Design Patterns for iOS".
I hope it will be helpful to you.. :) Good luck..
回答2:
Hope this may be help u..
This code for UIBezierPath Drawing.
-(void)undoButtonClicked
{
if([pathArray count]>0){
UIBezierPath *_path = [pathArray lastObject];
[bufferArray addObject:_path];
[bufferColorArray addObject:[PathColorArray lastObject]];
[pathArray removeLastObject];
[PathColorArray removeLastObject];
[bufferDrawType addObject:[pathDrawType lastObject]];
[pathDrawType removeLastObject];
[bufferDrawOpacity addObject:[pathDrawOpacity lastObject]];
[pathDrawOpacity removeLastObject];
[bufferDrawLineWidth addObject:[pathDrawLineWidth lastObject]];
[pathDrawLineWidth removeLastObject];
[self setNeedsDisplay];
}
}
-(void)redoButtonClicked
{
if([bufferArray count]>0){
UIBezierPath *_path = [bufferArray lastObject];
[pathArray addObject:_path];
[bufferArray removeLastObject];
[PathColorArray addObject:[bufferColorArray lastObject]];
[bufferColorArray removeLastObject];
[pathDrawType addObject:[bufferDrawType lastObject]];
[bufferDrawType removeLastObject];
[pathDrawOpacity addObject:[bufferDrawOpacity lastObject]];
[bufferDrawOpacity removeLastObject];
[pathDrawLineWidth addObject:[bufferDrawLineWidth lastObject]];
[bufferDrawLineWidth removeLastObject];
[self setNeedsDisplay];
}
}
回答3:
use the nsundomanager, that is the best way to undo
来源:https://stackoverflow.com/questions/6689600/undo-drawing-in-paint-application