Re: How to redraw a view in slow-motion
Re: How to redraw a view in slow-motion
- Subject: Re: How to redraw a view in slow-motion
- From: Ken Tozier <email@hidden>
- Date: Mon, 20 Jun 2011 04:43:05 -0400
Hi Matthias
I got frustrated with my own coding and thought I'd take another crack at your animation problem as a diversion...
Here's the result, enjoy
-Ken
#define DRAW_LINES_BLOCK_SIZE 100
#define DRAW_LINES_BLOCK_DELAY 1
- (void) setFrame:(NSRect) inRect
{
// I'm assuming you store you lines in an array
int lineCount = [lineArray count],
leftovers = lineCount % DRAW_LINES_BLOCK_SIZE,
blockCount = lineCount / DRAW_LINES_BLOCK_SIZE + ((leftovers == 0) ? 0 : 1);
maxBlockIndex = blockCount - 1,
i;
NSRange subrange = NSMakeRange(0, DRAW_LINES_BLOCK_SIZE);
NSInvocation *invocation;
NSValue *rangeWrapper;
// next variable needs to be defined in the interface
if (invocationStack != nil)
[invocationStack release];
// allocate new invocation stack
invocationStack = [[NSMutableArray alloc] initWithCapacity: blockCount];
// populate invocation stack
for (i = 0; i < blockCount; i++)
{
rangeWrapper = [NSValue valueWithRange: subrange];
invocation = [NSInvocation invocationWithMethodSignature: [self methodSignatureForSelector: @selector(drawBlockOfLines:)]];
[invocation setTarget: self];
[invocation setSelector: @selector(drawBlockOfLines:)];
[invocation setArgument: &rangeWrapper atIndex: 3];
[invocationStack addObject: invocation];
subrange.location += DRAW_LINES_BLOCK_SIZE;
if (i == maxBlockIndex)
subrange.length = leftovers;
}
[super setFrame: inRect];
// may need a [self setNeedsDisplay: YES] here, not sure...
}
// in your drawRect method
- (void) drawRect:(NSRect) inRect
{
// pop an invocation off the stack and run it
NSInvocation *invocation = [[invocationStack objectAtIndex: 0] retain];
[invocationStack removeObjectAtIndex: 0];
[invocation invoke];
[invocation release];
// schedule the next round of drawing
[NSTimer scheduledTimerWithTimeInterval: DRAW_LINES_BLOCK_DELAY target: self selector: @selector(drawRect:) userInfo: nil repeats: NO];
}
- (void) drawBlockOfLines:(NSValue *) inRange
{
NSRange range = [inRange rangeValue];
// do your drawing here
}
On Jun 20, 2011, at 3:49 AM, Matthias Arndt wrote:
> Hi Graham, hi Uli,
>
> guys, you're gems! Thanks for all the input. Currently it's too early to dive into some high sophisticated optimization, and with Graham's info I'm confident the view's back buffer will work for me.
>
> Am 20. Jun 2011 um 08:59 schrieb Graham Cox <email@hidden>:
>
>> The view is already doing this for you. Everything drawn in a view actually ends up in a bitmap - the window's back buffer. If you draw a subrange of your objects, the ones you've earlier drawn into the back buffer are still there. The only time you have to start over is when the view resizes, which is what the 'needsErase' flag is for in my example - the back buffer gets cleared effectively clearing your "cache". There's no reason to reinvent the drawing mechanism from scratch, it's just a duplication of effort.
>
> Hopefully I find some time these days to implement more details of the animation based on NSTimer-triggered redraws: Currently it's only quick & dirty, but seems to do the trick. I'll keep you posted.
>
> Thanks again, Mattes
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden