1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | - (void)drawRect:(NSRect)dirtyRect { CGContextRef gctx = [[NSGraphicsContext currentContext] graphicsPort]; CGRect myBoundingBox; myBoundingBox = CGRectMake(0, 0, GlobalBackbuffer.BitmapWidth, GlobalBackbuffer.BitmapHeight); CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); int bitmapBytesPerRow = GlobalBackbuffer.BitmapWidth * 4; _backBuffer = CGBitmapContextCreate(GlobalBackbuffer.BitmapMemory, GlobalBackbuffer.BitmapWidth, GlobalBackbuffer.BitmapHeight, 8, bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast); CGColorSpaceRelease(colorSpace); CGImageRef backImage = CGBitmapContextCreateImage(_backBuffer); CGContextDrawImage(gctx, myBoundingBox, backImage); CGContextRelease(_backBuffer); CGImageRelease(backImage); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | void ProcessEvents() { @autoreleasepool { NSEvent *ev; int speed = 255/1; do { ev = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES]; if (!ev) { //break; } switch ([ev type]) { case NSKeyUp: case NSKeyDown: { int hotkeyMask = NSCommandKeyMask | NSAlternateKeyMask | NSControlKeyMask | NSAlphaShiftKeyMask; if ([ev modifierFlags] & hotkeyMask) { // Handle events like cmd+q etc [NSApp sendEvent:ev]; break; } // Handle normal keyboard events in place. int isDown = ([ev type] == NSKeyDown); switch ([ev keyCode]) { case 13: { // W } break; default: { } break; } } break; default: { // Handle events like app focus/unfocus etc [NSApp sendEvent:ev]; } break; } } while (ev); } } |
adge
Is there another place where I can put the drawing code? Like doing it in a more Windows way without sending a message to view that then calls draw rect? Like an update function that gets called after animation is done without the use of delegates?
However I read that drawRect ist the only place where you can actually draw stuff. Sounds stupid to me but its the same on windows with the paint message right?
Another thing, would it make sense to use Metal for the bitmap blit? It seems to be faster then OpenGL and since the rendering is done by software until much later in the project, Metal could increase performance a bit I guess?
adge
Next problem, how is input handled by cocoa? The IOKit seems extremely complicated.
Maybe I will just implement the keyboard stuff first. Controllers seem extremely complicated.
Could you recommend resources for implementin keyboard/gamepad input?
I tried to understand this stuff from Jeff Buck's osx layer but daaaamn there is a lot of stuff going on.
EDIT: I implemented input through casual event handling. However I've seen people using IOKit for the Keyboard as well. Are there any advantages for using the IOKit?
adge
I’m wondering if there is a way to handle delegate methods like applicationDidFinishLaunching in the main event loop. Like it is done in Windows. This way you could organize the code a lot better and you wouldn’t have to use all these Delegates.
So is there a way to check if ev is type of NSNotification and equals for example applicationDidFinischLaunching?
Flyingsand
In your example though, I would cache the bitmap context when the view is created so you don't keep creating it every frame. :)
Flyingsand
The only way I can think of doing this is to still observe or implement the -applicationDidFinishLaunching: method, but in there, create an NSEvent yourself (and you can fill in its userData field with whatever you need) and then add it to the event queue by calling -postEvent:atStart: on the application instance. You should then receive the event in your process loop.
adgeFlyingsand
In your example though, I would cache the bitmap context when the view is created so you don't keep creating it every frame. :)
What do you mean by "caching"? Storing it in a variable that stays around? Like a static variable in the function? I thought I had to recreate the BitmapContext every time I change the bitmap itself because well, it's changing!
See thats the problem if you never really learned programming in a professional way and learned all by yourself, you do know nothing. Especially because the OS Framework documents are somewhat wacky, lacking and hard to understand. And there are not really books that teach you the Frameworks. There are 100 books that show you how the damn syntax works but thats it. Nobody tells you what a function actually does except you ask for it in a forum.
adgeFlyingsand
The only way I can think of doing this is to still observe or implement the -applicationDidFinishLaunching: method, but in there, create an NSEvent yourself (and you can fill in its userData field with whatever you need) and then add it to the event queue by calling -postEvent:atStart: on the application instance. You should then receive the event in your process loop.
Yeah thats exactly what I thought about to. But well, this seems like a roundabout which will slowdown things more I guess.
adge
Do I have to release the CGBitmapContext then in drawRect? Or just release it when the application closes?
adge
Another thing I just came across. Is there any guide on how to create build.sh scripts for the compilation of your code? I wanted to abandon Xcode but I cant seem to find any resources how to write them properly.
adge
Do I have to release it at all? Since the bitmap stays around the whole time the application is running. And when the application gets terminated everything is freed anyway right?
I guess its just good practice but strictly speaking there is no reason for freeing memory that is allocated the whole lifecycle of an application.
1 | clang code/main.m -fno-objc-arc -fmodules -mmacosx-version-min=10.6 -o main |
adge
Thank you very much for your answers. I hope you don't bother answering all my questions. There are probably more to come.
adge
I have ARC disabled. But it doesn't seem I'm leaking anything. Memory usage stays at around 40MB. Used @autorelease for all the window stuff.
Could it happen that if you didn't release all the memory an application uses when it shuts down, that the memory is still occupied, even when the application isn't running anymore?
adge
By the way why does my application not print to the terminal with printf()? I created a build.sh and to compile my application I just type sh build.sh. The script contains the following line:
1 clang code/main.m -fno-objc-arc -fmodules -mmacosx-version-min=10.6 -o main
I found this somewhere online. I really have no clue how this is done properly. I've searched a lot but it doesn't seem there is anyone who is not using Xcode.
1 2 3 | clang++ -std=c++11 -stdlib=libc++ -DDEBUG=1 -O0 -g -Wall -I../ -o filter main.cpp filter.cpp mv filter build/ mv filter.dSYM build/ |
1 | clang -g -Wall -framework Cocoa -o main code/main.m |
1 2 3 4 5 6 7 | backbuffer = CGBitmapContextCreate(GlobalBackbuffer.Memory, GlobalBackbuffer.Width, GlobalBackbuffer.Height, 8, bitmapBytesPerRow, colorSpace, kCGImageAlphaNoneSkipFirst| kCGBitmapByteOrder32Little); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | internal void RenderWeirdGradient(osx_offscreen_buffer *Buffer, int BlueOffset, int GreenOffset) { int Pitch = Buffer->Width * Buffer->BytesPerPixel; uint8 *Row = (uint8 *)Buffer->Memory; for(int Y = 0; Y < Buffer->Height; ++Y) { uint32 *Pixel = (uint32 *)Row; for(int X = 0; X < Buffer->Width; ++X) { uint8 Red = 0; uint8 Green = (Y + GreenOffset); uint8 Blue = (X + BlueOffset); *Pixel++ = Red | Green << 8 | Blue << 16 ; } Row += Pitch; } } |
1 | *Pixel++ = Red | Green << 8 | Blue << 16 ; |
1 | *Pixel++ = Red | Green | Blue | xx |