我正在使用OpenGl框架制作一个绘图应用程序,并且我坚持使用UNDO / REDO选项。 我实现的代码是这样的:
-(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);
}
这段代码效率不高,而且它有很多错误。看看撤消之前和之后的图像。
之前:http://imageshack.us/photo/my-images/577/screenshot20110714at121.png/
之后:http://imageshack.us/photo/my-images/200/screenshot20110714at121.png/
所以我想在每次用户的Touch结束时将图像保存在缓冲区中并在UNDO上调用上一个图像。任何人都可以帮助我如何将图像存储在缓冲区中并在UNDO上检索回来?我试图找到它的示例代码,但找不到..
谢谢..
答案 0 :(得分:1)
确定。我发布了自己的问题答案,因为很多人似乎都提到了这个问题。
有一个名为 TouchPainter 的应用程序,其source code可用。它包含绘图,颜色混合,撤消/重做(惊人...... !!),保存/打开图纸..
注意:可能需要非常深入的 Objective C 和设计模式知识(我仍然不知道设计模式是什么。但我发现它所以我分享..)。整本应用程序的源代码在本书“Apress.Pro Objective-C iOS设计模式”中进行了解释。
我希望它对你有帮助.. :)祝你好运..
答案 1 :(得分:0)
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];
}
}
答案 2 :(得分:-1)
使用nsundomanager,这是撤消
的最佳方法