#include "pch.h" #include "shader.hpp" #include "shape.hpp" #include "texture.hpp" #include "image.hpp" #include "app.hpp" #include #include #include #include @interface View : NSOpenGLView { CVDisplayLinkRef dl; } @end @implementation View - (instancetype)initWithFrame:(NSRect)frameRect { NSOpenGLPixelFormatAttribute attrs[] = { NSOpenGLPFADoubleBuffer, NSOpenGLPFADepthSize, 24, // Must specify the 3.2 Core Profile to use OpenGL 3.2 NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core, // Multisample NSOpenGLPFAMultisample, NSOpenGLPFASamples, 2, NSOpenGLPFASampleBuffers, 1, 0 }; NSOpenGLPixelFormat *pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; NSOpenGLContext* context = [[NSOpenGLContext alloc] initWithFormat:pf shareContext:nil]; self = [super initWithFrame:frameRect pixelFormat:pf]; [self setPixelFormat:pf]; [self setOpenGLContext:context]; return self; } - (void)prepareOpenGL { NSLog(@"prepare"); // Synchronize buffer swaps with vertical refresh rate GLint swapInt = 1; [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; // Create a display link capable of being used with all active displays CVDisplayLinkCreateWithActiveCGDisplays(&dl); // Set the renderer output callback function CVDisplayLinkSetOutputCallback(dl, &MyDisplayLinkCallback, (__bridge void*)self); // Set the display link for the current renderer CGLContextObj cglContext = [[self openGLContext] CGLContextObj]; CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj]; CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(dl, cglContext, cglPixelFormat); // Activate the display link CVDisplayLinkStart(dl); CGLEnable([self.openGLContext CGLContextObj], kCGLCECrashOnRemovedFunctions); App::I.init(); } // This is the renderer output callback function static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) { CVReturn result = [(__bridge View*)displayLinkContext getFrameForTime:outputTime]; return result; } - (CVReturn)getFrameForTime:(const CVTimeStamp*)outputTime { static double _timeFreq = CVGetHostClockFrequency(); static double _prevTime = (double)outputTime->hostTime / _timeFreq; double hostTime = (double)outputTime->hostTime; double now = hostTime / _timeFreq; // this will not update unless 1/30th of a second has passed since the last update if ( now < _prevTime + (1.0 / 30.0) ) { // Add your drawing codes here [[self openGLContext] makeCurrentContext]; App::I.update(now - _prevTime); [[self openGLContext] flushBuffer]; // returning NO will cause the layer to NOT be redrawn return NO; } else { // change whatever you want to change here, as a function of time elapsed _prevTime = now; // return YES to have your layer redrawn return YES; } return kCVReturnSuccess; } - (void)dealloc { // Release the display link CVDisplayLinkRelease(dl); } - (void)drawRect:(NSRect)dirtyRect { NSLog(@"drawRect"); } @end @interface Window : NSWindow @end @implementation Window - (void)keyDown:(NSEvent *)theEvent { [[self windowController] keyDown:theEvent]; } @end @interface Controller : NSWindowController @end @implementation Controller - (void)keyDown:(NSEvent *)theEvent { unichar c = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]; if (c == 27) { [[NSApplication sharedApplication] terminate:nil]; } } @end @interface AppOSX : NSApplication { Window* window; Controller* controller; View* view; } @end @implementation AppOSX - (instancetype)init { self = [super init]; [self setActivationPolicy:NSApplicationActivationPolicyRegular]; // make it to the front [self setDelegate:self]; return self; } - (void)applicationDidFinishLaunching:(NSNotification *)notification { auto& app = App::I; app.create(); NSRect r = NSMakeRect(0, 0, app.width, app.height); view = [[View alloc] initWithFrame:r]; window = [[Window alloc] initWithContentRect:r styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask backing:NSBackingStoreBuffered defer:NO]; [window setTitle:@"hello engine"]; [window center]; [window makeKeyAndOrderFront:controller]; [window setContentView:view]; controller = [[Controller alloc] initWithWindow:window]; auto menubar = [NSMenu new]; auto appMenuItem = [NSMenuItem new]; [menubar addItem:appMenuItem]; [self setMainMenu:menubar]; auto appMenu = [NSMenu new]; auto appName = [[NSProcessInfo processInfo] processName]; auto quitTitle = [@"Quit " stringByAppendingString:appName]; auto quitMenuItem = [[NSMenuItem alloc] initWithTitle:quitTitle action:@selector(terminate:) keyEquivalent:@"q"]; [appMenu addItem:quitMenuItem]; [appMenuItem setSubmenu:appMenu]; NSLog(@"app launched"); } @end int main(int argc, const char * argv[]) { AppOSX* app = [AppOSX sharedApplication]; [app run]; return 0; }