I've recently downloaded the GLPaint sample code and looked at a very interesting part in it. There is a recordedPaths NSMutableArray that has points in it that are then read and drawn by GLPaint.
It's declared here:
NSMutableArray *recordedPaths;
recordedPaths = [NSMutableArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Recording" ofType:@"data"]];
if([recordedPaths count])
[self performSelector:@selector(playback:) withObject:recordedPaths afterDelay:0.2];
This is the code for playback:
- (void) playback:(NSMutableArray*)recordedPaths {
NSData* data = [recordedPaths objectAtIndex:0];
CGPoint* point = (CGPoint*)[data bytes];
NSUInteger count = [data length] / sizeof(CGPoint),
i;
//Render the current path
for(i = 0; i < count - 1; ++i, ++point)
[self renderLineFromPoint:*point toPoint:*(point + 1)];
//Render the next path after a short delay
[recordedPaths removeObjectAtIndex:0];
if([recordedPaths count])
[self performSelector:@selector(playback:) withObject:recordedPaths afterDelay:0.01];
}
From this I understand that recordedPaths is a mutable array that his in it struct c arrays of CGPoint that are then read and rendered. I'd like to put in my own array and i've been having trouble with that.
I tried changing the recordedPaths declaration to this:
NSMutableArray *myArray = [[NSMutableArray alloc] init];
CGPoint* points;
CGPoint a = CGPointMake(50,50);
int i;
for (i=0; i<100; i++,points++) {
a = CGPointMake(i,i);
points = &a;
}
NSData *data = [NSData dataWithBytes:&points length:sizeof(*points)];
[myArray addObject:data];
This didn't work though... Any advice?
If you look at the Recording.data you will notice that each line is its own array. To capture the ink and play it back you need to have an array of arrays. For purposes of this demo - declare a mutable array - writRay
@synthesize writRay;
//init in code
writRay = [[NSMutableArray alloc]init];
Capture the ink
// Handles the continuation of a touch.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
CGRect bounds = [self bounds];
UITouch* touch = [[event touchesForView:self] anyObject];
// Convert touch point from UIView referential to OpenGL one (upside-down flip)
if (firstTouch) {
firstTouch = NO;
previousLocation = [touch previousLocationInView:self];
previousLocation.y = bounds.size.height - previousLocation.y;
/******************* create a new array for this stroke's points **************/
[writRay addObject:[[NSMutableArray alloc]init]];
/***** add 1st point *********/
[[writRay objectAtIndex:[writRay count] -1]addObject:[NSValue valueWithCGPoint:previousLocation]];
} else {
location = [touch locationInView:self];
location.y = bounds.size.height - location.y;
previousLocation = [touch previousLocationInView:self];
previousLocation.y = bounds.size.height - previousLocation.y;
/********* add additional points *********/
[[writRay objectAtIndex:[writRay count] -1]addObject:[NSValue valueWithCGPoint:previousLocation]];
}
// Render the stroke
[self renderLineFromPoint:previousLocation toPoint:location];
}
Playback the ink.
- (void)playRay{
if(writRay != NULL){
for(int l = 0; l < [writRay count]; l++){
//replays my writRay -1 because of location point
for(int p = 0; p < [[writRay objectAtIndex:l]count] -1; p ++){
[self renderLineFromPoint:[[[writRay objectAtIndex:l]objectAtIndex:p]CGPointValue] toPoint:[[[writRay objectAtIndex:l]objectAtIndex:p + 1]CGPointValue]];
}
}
}
}
For best effect shake the screen to clear and call playRay from changeBrushColor in the AppController.
CGPoint* points;
CGPoint a = CGPointMake(50,50);
int i;
for (i=0; i<100; i++,points++) {
a = CGPointMake(i,i);
points = &a;
}
NSData *data = [NSData dataWithBytes:&points length:sizeof(*points)];
Wrong code.
(1) You need an array of points. Simply declaring CGPoint* points;
won't create an array of points, just an uninitialized pointer of CGPoint. You need to allocate space for the array either with
CGPoint points[100];
or
CGPoint* points = malloc(sizeof(CGPoint)*100);
Remember to free
the points if you choose the malloc
way.
(2) To copy value to the content of the pointer you need to use
*points = a;
But I suggest you keep the pointer points
invariant in the loop, since you're going to reuse it later. Use the array syntax points[i]
.
(3)
sizeof(*points)
Since *points
is just one CGPoint, so the sizeof is always 8 bytes. You need to multiply the result by 100 to get the correct length.
(4)
[NSData dataWithBytes:&points ...
points
already is a pointer to the actual data. You don't need to take the address of it again. Just pass points
directly.
So the final code should look like
CGPoint* points = malloc(sizeof(CGPoint)*100); // make a cast if the compiler warns.
CGPoint a;
int i;
for (i=0; i<100; i++) {
a = CGPointMake(i,i);
points[i] = a;
}
NSData *data = [NSData dataWithBytes:points length:sizeof(*points)*100];
free(points);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With