Simple way of using irregular shaped buttons - objective-c

I've finally got my main app release (Tap Play MMO - check it out ;-) ) and I'm now working on expanding it.
To do this I need to have a circle that has four seperate buttons in it, these buttons will essentially be quarters. I've come to the conclusion that the circlular image will need to be constructed of four images, one for each quarter, but due to the necessity of rectangular image shapes I'm going to end up with some overlap, although the overlap will be transparent.
What's the best way of getting this to work? I need something really simple really, I've looked at this
http://iphonedevelopment.blogspot.com/2010/03/irregularly-shaped-uibuttons.html
Before but not yet succeeded in getting it to work. Anyone able to offer some advice?
In case it makes any difference I'll be deploying to a iOS 3.X framework (will be 4.2 down the line when 4.2 comes out for iPad)

Skip the buttons and simply respond to touches in your view that contains the circle.
Create a CGPath for each area that you want to capture touches, when your UIview receives a touch, check for membership inside the paths.
[Edited answer to show skeleton implementation details -- TomH]
Here's how I would approach the problem: (I haven't tested this code and the syntax may not be quite right, but this is the general idea)
1) Using PS or your favorite image creation application, create one png of the quarter circles. Add it to your XCode project.
2) Add a UIView to the UI. Set the UIView's layer's contents to the png.
self.myView = [[UIView alloc] initWithRect:CGRectMake(10.0, 10.0, 100.0, 100,0)];
[myView.layer setContents:(id)[UIImage loadImageNamed:#"my.png"]];
3) Create CGPaths that describe the region in the UIView that you are interested in.
self.quadrantOnePath = CGPathCreateMutable();
CGPathMoveToPoint(self.quadrantOnePath, NULL, 50.0, 50.0);
CGPathAddLineToPoint(self.quadrantOnePath, NULL, 100.0, 50.0);
CGPathAddArc(self.quadrantOnePath, NULL, 50.0, 50.0, 50.0, 0.0, M_PI2, 1);
CGPathCloseSubpath(self.quadrantOnePath);
// create paths for the other 3 circle quadrants too!
4) Add a UIGestureRecognizer and listen/observe for taps in the view
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)];
[tapRecognizer setNumberOfTapsRequired:2]; // default is 1
5) When tapRecognizer invokes its target selector
- (void)handleGesture:(UIGestureRecognizer *) recognizer {
CGPoint touchPoint = [recognizer locationOfTouch:0 inView:self.myView];
bool processTouch = CGPathContainsPoint(self.quadrantOnePath, NULL, touchPoint, true);
if(processTouch) {
// call your method to process the touch
}
}
Don't forget to release everything when appropriate -- use CGPathRelease to release paths.
Another thought: If the graphic that you are using to represent your circle quadrants is simply a filled color (i.e. no fancy graphics, layer effects, etc.), you could also use the paths you created in the UIView's drawRect method to draw the quadrants too. This would address one of the failings of the approach above: there isn't a tight integration between the graphic and the paths used to check for the touches. That is, if you swap out the graphic for something different, change the size of the graphic, etc., your paths used to check for touches will be out of sync. Potentially a high maintenance piece of code.

I can't see, why overlapping is needed.
Just create 4 buttons and give each one a slice of your image.
edit after comment
see this great project. One example is exactly what you want to do.
It works by incorporating the alpha-value of a pixel in the overwritten
pointInside:withEvent: and a category on UIImage, that adds this method
- (UIColor *)colorAtPixel:(CGPoint)point {
// Cancel if point is outside image coordinates
if (!CGRectContainsPoint(CGRectMake(0.0f, 0.0f, self.size.width, self.size.height), point)) {
return nil;
}
// Create a 1x1 pixel byte array and bitmap context to draw the pixel into.
// Reference: http://stackoverflow.com/questions/1042830/retrieving-a-pixel-alpha-value-for-a-uiimage
NSInteger pointX = trunc(point.x);
NSInteger pointY = trunc(point.y);
CGImageRef cgImage = self.CGImage;
NSUInteger width = self.size.width;
NSUInteger height = self.size.height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
int bytesPerPixel = 4;
int bytesPerRow = bytesPerPixel * 1;
NSUInteger bitsPerComponent = 8;
unsigned char pixelData[4] = { 0, 0, 0, 0 };
CGContextRef context = CGBitmapContextCreate(pixelData,
1,
1,
bitsPerComponent,
bytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextSetBlendMode(context, kCGBlendModeCopy);
// Draw the pixel we are interested in onto the bitmap context
CGContextTranslateCTM(context, -pointX, pointY-(CGFloat)height);
CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), cgImage);
CGContextRelease(context);
// Convert color values [0..255] to floats [0.0..1.0]
CGFloat red = (CGFloat)pixelData[0] / 255.0f;
CGFloat green = (CGFloat)pixelData[1] / 255.0f;
CGFloat blue = (CGFloat)pixelData[2] / 255.0f;
CGFloat alpha = (CGFloat)pixelData[3] / 255.0f;
return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
}

Here's an awesome project that solves the problem of irregular shaped buttons so easily:
http://christinemorris.com/2011/06/ios-irregular-shaped-buttons/

Related

Draw text into CGBitmapContext

I have an app that renders into a UIView's CGContext in drawRect. I also export those renderings using a background renderer. It uses the same rendering logic to render (in faster than real time) into a CGBitmapContext (which I subsequently transform into an mp4 file).
I have noticed that the output video has a number of weird glitches. Such as the image being rotated, weird duplications of the rendered images, random noise, and the timing is also odd.
I'm looking for ways to debug this. For the timing issue, I thought I'd render a string that tells me which frame I'm currently viewing, only to find rendering text into CGContext's not very well documented. In fact, the documentations around much of core graphics is quite unforgiving to some one of my experience.
So specifically, I'd like to know how to render text into a context. If its Core Text, must it inter-operate some how with the core graphics context? And in general, I'd appreciate any tips and advice on doing bitmap rendering and debugging the results.
according another question:
How to convert Text to Image in Cocoa Objective-C
we can use the CTLineDraw to draw the text in a CGBitmapContext
sample code:
NSString* string = #"terry.wang";
CGFloat fontSize = 10.0f;
// Create an attributed string with string and font information
CTFontRef font = CTFontCreateWithName(CFSTR("Helvetica Light"), fontSize, nil);
NSDictionary* attributes = [NSDictionary dictionaryWithObjectsAndKeys:
(id)font, kCTFontAttributeName,
nil];
NSAttributedString* as = [[NSAttributedString alloc] initWithString:string attributes:attributes];
CFRelease(font);
// Figure out how big an image we need
CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)as);
CGFloat ascent, descent, leading;
double fWidth = CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
// On iOS 4.0 and Mac OS X v10.6 you can pass null for data
size_t width = (size_t)ceilf(fWidth);
size_t height = (size_t)ceilf(ascent + descent);
void* data = malloc(width*height*4);
// Create the context and fill it with white background
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast;
CGContextRef ctx = CGBitmapContextCreate(data, width, height, 8, width*4, space, bitmapInfo);
CGColorSpaceRelease(space);
CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0); // white background
CGContextFillRect(ctx, CGRectMake(0.0, 0.0, width, height));
// Draw the text
CGFloat x = 0.0;
CGFloat y = descent;
CGContextSetTextPosition(ctx, x, y);
CTLineDraw(line, ctx);
CFRelease(line);

Custom MKOverlayView/unmodified MKPolygonView is clipped at certain zoom levels

I'm having an issue with both a custom MKOverlayView and standard MKPolygonView being clipped at certain zoom levels when there are multiple overlays added to a map.
The overlay of Algeria at two double tap zoom level.
The overlay of Algeria at three double tap zoom level. Note the clipping.
A few observations:
This occurs regardless of whether or not I use a custom MKOverlayView or return an MKPolygonView with the same polygons.
If I only draw one overlay, this problem does not occur.
This does not occur for all overlays - only some.
As far as code goes: this adds the overlay to an NSMutableArray (borderOverlays), which is then accessed elsewhere to load the overlay for a specific country ID. minX/minY/maxX/maxY are latitude/longitude values; polygon is a path constructed from an ESRI shapefile.
CLLocationCoordinate2D mbrMin = CLLocationCoordinate2DMake(minY, minX);
CLLocationCoordinate2D mbrMax = CLLocationCoordinate2DMake(maxY, maxX);
MKMapPoint minPoint = MKMapPointForCoordinate(mbrMin);
MKMapPoint maxPoint = MKMapPointForCoordinate(mbrMax);
MKMapSize size = MKMapSizeMake(maxPoint.x - minPoint.x, maxPoint.y - minPoint.y);
MKMapRect rect = MKMapRectMake(minPoint.x, minPoint.y, size.width, size.height);
if ( spans180 ) {
rect = MKMapRectMake(minPoint.x, minPoint.y, MKMapSizeWorld.width * 2, size.height);
}
CustomMKOverlay* overlay = [[CustomMKOverlay alloc] initWithPolygon:polygon withBoundingMapRect:rect];
[borderOverlays addObject:overlay];
The overlay is added to the map via:
[mapView addOverlay:overlay];
viewForOverlay:
- (MKOverlayView *)mapView:(MKMapView*)aMapView viewForOverlay:(id<MKOverlay>)overlay
{
if ( [overlay isKindOfClass:[CustomMKOverlay class]] ) {
/* Note: the behaviour if this chunk is not commented is the exact same as below.
CustomMKOverlayView* overlayView = [[[CustomMKOverlayView alloc] initWithOverlay:overlay withMapView:aMapView] autorelease];
[borderViews addObject:overlayView];
return overlayView; */
MKPolygonView* view = [[[MKPolygonView alloc] initWithPolygon:((CustomMKOverlay*)overlay).polygon] autorelease];
view.fillColor = [((CustomMKOverlay*)overlay).colour colorWithAlphaComponent:0.5f];
view.lineWidth = 5.0f;
view.strokeColor = [UIColor blackColor];
[borderViews addObject:view];
return view;
}
}
When MKPolygonView is used, there is no drawing code (the example shown). For completion's sake, though, here's my custom drawing code, and the same issue occurs. The outlines normally draw - this is actually debugging drawing, which draws a rect around the boundingMapRect of the overlay and fills it without mucking around with the outlines.
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
{
CustomMKOverlay* overlay = (CustomMKOverlay*)self.overlay;
CGRect clipRect = [self rectForMapRect:overlay.boundingMapRect];
CGContextAddRect(context, clipRect);
CGContextClip(context);
UIColor* colour = [UIColor redColor];
colour = [colour colorWithAlphaComponent:0.5f];
CGContextSetFillColorWithColor(context, [colour CGColor]);
CGRect fillRect = [self rectForMapRect:overlay.boundingMapRect];
CGContextFillRect(context, fillRect);
}
Suffice to say, I'm a bit stumped at this point - it's almost as if the zoomed tiled that's being loaded draws over the overlay. I've poured over various examples regarding TileMap and HazardMap, but as I am not loading my own map tiles, they're not very helpful.
I'm probably missing something painfully obvious. Any help would be appreciated. I'm happy to provide more code/context if necessary.
It would appear that the culprit is:
CLLocationCoordinate2D mbrMin = CLLocationCoordinate2DMake(minY, minX);
CLLocationCoordinate2D mbrMax = CLLocationCoordinate2DMake(maxY, maxX);
Bounding rectangles for MKOverlays apparently need to be based on the northwest/southeast coordinates of the bounding region, and not southwest/northeast (which is the format the ESRI shapefile stores its bounding coordinates in). Changing the offending code to:
CLLocationCoordinate2D mbrMin = CLLocationCoordinate2DMake(maxY, minX);
CLLocationCoordinate2D mbrMax = CLLocationCoordinate2DMake(minY, maxX);
Appears to resolve all issues with zooming and strange outline anomalies. I hope this helps anyone who comes across this problem in the future (and I'd like to hear about it if it doesn't, since this solution works a treat for me).
Also: if anyone can point to any documentation that states this, I'd like to see it.

How do I avoid interpolation artifacts when drawing NSImage into a different size rect?

My end goal is to fill an arbitrarily sized rectangle with an NSImage. I want to:
Fill the entire rectangle
Preserve the aspect ratio of the image
Show as much as possible of the image while maintaining 1) and 2)
When not all the image can be shown, crop toward the center.
This demonstrates what I'm trying to do. The original image of the boat at the top is drawn into various sized rectangles below.
Okay, so far so good. I added a category to NSImage to do this.
#implementation NSImage (Fill)
/**
* Crops source to best fit the destination
*
* destRect is the rect in which we want to draw the image
* sourceRect is the rect of the image
*/
-(NSRect)scaleAspectFillRect:(NSRect)destRect fromRect:(NSRect)sourceRect
{
NSSize sourceSize = sourceRect.size;
NSSize destSize = destRect.size;
CGFloat sourceAspect = sourceSize.width / sourceSize.height;
CGFloat destAspect = destSize.width / destSize.height;
NSRect cropRect = NSZeroRect;
if (sourceAspect > destAspect) { // source is proportionally wider than dest
cropRect.size.height = sourceSize.height;
cropRect.size.width = cropRect.size.height * destAspect;
cropRect.origin.x = (sourceSize.width - cropRect.size.width) / 2;
} else { // dest is proportionally wider than source (or they are equal)
cropRect.size.width = sourceSize.width;
cropRect.size.height = cropRect.size.width / destAspect;
cropRect.origin.y = (sourceSize.height - cropRect.size.height) / 2;
}
return cropRect;
}
- (void)drawScaledAspectFilledInRect:(NSRect)rect
{
NSRect imageRect = NSMakeRect(0, 0, [self size].width, [self size].height);
NSRect sourceRect = [self scaleAspectFillRect:rect fromRect:imageRect];
[[NSGraphicsContext currentContext]
setImageInterpolation:NSImageInterpolationHigh];
[self drawInRect:rect
fromRect:sourceRect
operation:NSCompositeSourceOver
fraction:1.0 respectFlipped:YES hints:nil];
}
#end
When I want to draw the image into a certain rectangle I call:
[myImage drawScaledAspectFilledInRect:onScreenRect];
Works really well except for one problem. At certain sizes the image looks quite blurry:
My first thought was that I need to draw on integral pixels, so I used NSIntegralRect() before drawing. No luck.
As I thought about it I figured that it's probably a result of the interpolation. To draw from the larger image to the smaller draw rect NSImage has to interpolate. The blurry images are likely just a case where the values don't map very well and we end up with some undesirable artifacts that can't be avoided.
So, the question is this: How do I choose an optimal rect that avoids those artifacts? I can adjust either the draw rect or the crop rect before drawing to avoid this, but I don't know how or when to adjust them.

How to draw a NSImage like images in NSButtons (with a deepness)?

Is there any way to draw an NSImage like images in NSButtons or other cocoa interface elements?
Here are examples:
Apple uses pdf's with black icons:
If you simply want this effect to be applied when you use your own images in a button, use [myImage setTemplate:YES]. There is no built-in way to draw images with this effect outside of a button that has the style shown in your screenshots.
You can however replicate the effect using Core Graphics. If you look closely, the effect consists of a horizontal gradient, a white drop shadow and a dark inner shadow (the latter is the most difficult).
You could implement this as a category on NSImage:
//NSImage+EtchedDrawing.h:
#interface NSImage (EtchedImageDrawing)
- (void)drawEtchedInRect:(NSRect)rect;
#end
//NSImage+EtchedDrawing.m:
#implementation NSImage (EtchedImageDrawing)
- (void)drawEtchedInRect:(NSRect)rect
{
NSSize size = rect.size;
CGFloat dropShadowOffsetY = size.width <= 64.0 ? -1.0 : -2.0;
CGFloat innerShadowBlurRadius = size.width <= 32.0 ? 1.0 : 4.0;
CGContextRef c = [[NSGraphicsContext currentContext] graphicsPort];
//save the current graphics state
CGContextSaveGState(c);
//Create mask image:
NSRect maskRect = rect;
CGImageRef maskImage = [self CGImageForProposedRect:&maskRect context:[NSGraphicsContext currentContext] hints:nil];
//Draw image and white drop shadow:
CGContextSetShadowWithColor(c, CGSizeMake(0, dropShadowOffsetY), 0, CGColorGetConstantColor(kCGColorWhite));
[self drawInRect:maskRect fromRect:NSMakeRect(0, 0, self.size.width, self.size.height) operation:NSCompositeSourceOver fraction:1.0];
//Clip drawing to mask:
CGContextClipToMask(c, NSRectToCGRect(maskRect), maskImage);
//Draw gradient:
NSGradient *gradient = [[[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceWhite:0.5 alpha:1.0]
endingColor:[NSColor colorWithDeviceWhite:0.25 alpha:1.0]] autorelease];
[gradient drawInRect:maskRect angle:90.0];
CGContextSetShadowWithColor(c, CGSizeMake(0, -1), innerShadowBlurRadius, CGColorGetConstantColor(kCGColorBlack));
//Draw inner shadow with inverted mask:
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef maskContext = CGBitmapContextCreate(NULL, CGImageGetWidth(maskImage), CGImageGetHeight(maskImage), 8, CGImageGetWidth(maskImage) * 4, colorSpace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
CGContextSetBlendMode(maskContext, kCGBlendModeXOR);
CGContextDrawImage(maskContext, maskRect, maskImage);
CGContextSetRGBFillColor(maskContext, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(maskContext, maskRect);
CGImageRef invertedMaskImage = CGBitmapContextCreateImage(maskContext);
CGContextDrawImage(c, maskRect, invertedMaskImage);
CGImageRelease(invertedMaskImage);
CGContextRelease(maskContext);
//restore the graphics state
CGContextRestoreGState(c);
}
#end
Example usage in a view:
- (void)drawRect:(NSRect)dirtyRect
{
[[NSColor colorWithDeviceWhite:0.8 alpha:1.0] set];
NSRectFill(self.bounds);
NSImage *image = [NSImage imageNamed:#"MyIcon.pdf"];
[image drawEtchedInRect:self.bounds];
}
This would give you the following result (shown in different sizes):
You may need to experiment a bit with the gradient colors and offset/blur radius of the two shadows to get closer to the original effect.
If you don't mind calling a private API, you can let the operating system (CoreUI) do the shading for you. You need a few declarations:
typedef CFTypeRef CUIRendererRef;
extern void CUIDraw(CUIRendererRef renderer, CGRect frame, CGContextRef context, CFDictionaryRef object, CFDictionaryRef *result);
#interface NSWindow(CoreUIRendererPrivate)
+ (CUIRendererRef)coreUIRenderer;
#end
And for the actual drawing:
CGRect drawRect = CGRectMake(x, y, width, height);
CGImageRef cgimage = your_image;
CFDictionaryRef dict = (CFDictionaryRef) [NSDictionary dictionaryWithObjectsAndKeys:
#"backgroundTypeRaised", #"backgroundTypeKey",
[NSNumber numberWithBool:YES], #"imageIsGrayscaleKey",
cgimage, #"imageReferenceKey",
#"normal", #"state",
#"image", #"widget",
[NSNumber numberWithBool:YES], #"is.flipped",
nil];
CUIDraw ([NSWindow coreUIRenderer], drawRect, cg, dict, nil);
CGImageRelease (cgimage);
This will take the alpha channel of cgimage and apply the embossing effect as seen on toolbar buttons. You may or may not need the "is.flipped" line. Remove it if your result is upside-down.
There are a bunch of variations:
kCUIPresentationStateKey = kCUIPresentationStateInactive: The window is not active, the image will be lighter.
state = rollover: Only makes sense with the previous option. This means you are hovering over the image, the window is inactive, but the button is sensitive (click-through is enabled). It will become darker.
state = pressed: Occurs when the button is pressed. The icon gets slightly darker.
Bonus tip: To find out stuff like this, you can use the SIMBL plugin CUITrace. It prints out all the CoreUI invocations of a target app. This is a treasure trove if you have to draw your own native-looking UI.
Here's a much simpler solution: just create a cell and let it draw. No mucking around with private APIs or Core Graphics.
Code could look similar to the following:
NSButtonCell *buttonCell = [[NSButtonCell alloc] initImageCell:image];
buttonCell.bordered = YES;
buttonCell.bezelStyle = NSTexturedRoundedBezelStyle;
// additional configuration
[buttonCell drawInteriorWithFrame: someRect inView:self];
You can use different cells and configurations depending on the look you want to have (eg. NSImageCell with NSBackgroundStyleDark if you want the inverted look in a selected table view row)
And as a bonus, it will automatically look correct on all versions of OS X.
To get to draw correctly within any rect, the CGContextDrawImage and CGContextFillRect for the inner mask must have the origin of (0,0). then when you draw the image for the inner shadow you can then reuse the mask rect. So ends up looking like:
CGRect cgRect = CGRectMake( 0, 0, maskRect.size.width, maskRect.size.height );
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef maskContext = CGBitmapContextCreate( NULL, CGImageGetWidth( maskImage ), CGImageGetHeight( maskImage ), 8, CGImageGetWidth( maskImage ) * 4, colorSpace, kCGImageAlphaPremultipliedLast );
CGColorSpaceRelease( colorSpace );
CGContextSetBlendMode( maskContext , kCGBlendModeXOR );
CGContextDrawImage( maskContext, cgRect, maskImage );
CGContextSetRGBFillColor( maskContext, 1.0, 1.0, 1.0, 1.0 );
CGContextFillRect( maskContext, cgRect );
CGImageRef invertedMaskImage = CGBitmapContextCreateImage( maskContext );
CGContextDrawImage( context, maskRect, invertedMaskImage );
CGImageRelease( invertedMaskImage );
CGContextRelease( maskContext );
CGContextRestoreGState( context );
You also have to leave a 1px border around the outside of the image or the shadows won't work correctly.

Flipping OpenGL texture

When I load textures from images normally, they are upside down because of OpenGL's coordinate system. What would be the best way to flip them?
glScalef(1.0f, -1.0f, 1.0f);
mapping the y coordinates of the textures in reverse
vertically flipping the image files manually (in Photoshop)
flipping them programatically after loading them (I don't know how)
This is the method I'm using to load png textures, in my Utilities.m file (Objective-C):
+ (TextureImageRef)loadPngTexture:(NSString *)name {
CFURLRef textureURL = CFBundleCopyResourceURL(
CFBundleGetMainBundle(),
(CFStringRef)name,
CFSTR("png"),
CFSTR("Textures"));
NSAssert(textureURL, #"Texture name invalid");
CGImageSourceRef imageSource = CGImageSourceCreateWithURL(textureURL, NULL);
NSAssert(imageSource, #"Invalid Image Path.");
NSAssert((CGImageSourceGetCount(imageSource) > 0), #"No Image in Image Source.");
CFRelease(textureURL);
CGImageRef image = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL);
NSAssert(image, #"Image not created.");
CFRelease(imageSource);
GLuint width = CGImageGetWidth(image);
GLuint height = CGImageGetHeight(image);
void *data = malloc(width * height * 4);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
NSAssert(colorSpace, #"Colorspace not created.");
CGContextRef context = CGBitmapContextCreate(
data,
width,
height,
8,
width * 4,
colorSpace,
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
NSAssert(context, #"Context not created.");
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);
CGImageRelease(image);
CGContextRelease(context);
return TextureImageCreate(width, height, data);
}
Where TextureImage is a struct that has a height, width and void *data.
Right now I'm just playing around with OpenGL, but later I want to try making a simple 2d game. I'm using Cocoa for all the windowing and Objective-C as the language.
Also, another thing I was wondering about: If I made a simple game, with pixels mapped to units, would it be alright to set it up so that the origin is in the top-left corner (personal preference), or would I run in to problems with other things (e.g. text rendering)?
Thanks.
Any of those:
Flip texture during the texture load,
OR flip model texture coordinates during model load
OR set texture matrix to flip y (glMatrixMode(GL_TEXTURE)) during render.
Also, another thing I was wondering about: If I made a simple game, with pixels mapped to units, would it be alright to set it up so that the origin is in the top-left corner (personal preference), or would I run in to problems with other things (e.g. text rendering)?
Depends on how you are going to render text.
Jordan Lewis pointed out CGContextDrawImage draws image upside down when passed UIImage.CGImage. There I found a quick and easy solution: Before calling CGContextDrawImage,
CGContextTranslateCTM(context, 0, height);
CGContextScaleCTM(context, 1.0f, -1.0f);
Does the job perfectly well.