diff options
Diffstat (limited to 'indra/llwindow/llopenglview-objc.mm')
-rw-r--r-- | indra/llwindow/llopenglview-objc.mm | 352 |
1 files changed, 352 insertions, 0 deletions
diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm new file mode 100644 index 0000000000..a96c4cf82c --- /dev/null +++ b/indra/llwindow/llopenglview-objc.mm @@ -0,0 +1,352 @@ +// +// LLOpenGLView.m +// SecondLife +// +// Created by Geenz on 10/2/12. +// +// + +#import "llopenglview-objc.h" + +@implementation LLOpenGLView + +- (void)viewDidMoveToWindow +{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(windowResized:) name:NSWindowDidResizeNotification + object:[self window]]; +} + +- (void)windowResized:(NSNotification *)notification; +{ + NSSize size = [[self window] frame].size; + + mResizeCallback(size.width, size.height); +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + +- (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync +{ + + [self initWithFrame:frame]; + + // Initialize with a default "safe" pixel format that will work with versions dating back to OS X 10.6. + // Any specialized pixel formats, i.e. a core profile pixel format, should be initialized through rebuildContextWithFormat. + // 10.7 and 10.8 don't really care if we're defining a profile or not. If we don't explicitly request a core or legacy profile, it'll always assume a legacy profile (for compatibility reasons). + NSOpenGLPixelFormatAttribute attrs[] = { + NSOpenGLPFANoRecovery, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAClosestPolicy, + NSOpenGLPFAAccelerated, + NSOpenGLPFASampleBuffers, (samples > 0 ? 1 : 0), + NSOpenGLPFASamples, samples, + NSOpenGLPFAStencilSize, 8, + NSOpenGLPFADepthSize, 24, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFAColorSize, 24, + 0 + }; + + NSOpenGLPixelFormat *pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs] autorelease]; + + if (pixelFormat == nil) + { + NSLog(@"Failed to create pixel format!", nil); + return nil; + } + + NSOpenGLContext *glContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil]; + + if (glContext == nil) + { + NSLog(@"Failed to create OpenGL context!", nil); + return nil; + } + + [self setPixelFormat:pixelFormat]; + + [self setOpenGLContext:glContext]; + + [glContext setView:self]; + + [glContext makeCurrentContext]; + + if (vsync) + { + [glContext setValues:(const GLint*)1 forParameter:NSOpenGLCPSwapInterval]; + } else { + [glContext setValues:(const GLint*)0 forParameter:NSOpenGLCPSwapInterval]; + } + + return self; +} + +- (BOOL) rebuildContext +{ + return [self rebuildContextWithFormat:[self pixelFormat]]; +} + +- (BOOL) rebuildContextWithFormat:(NSOpenGLPixelFormat *)format +{ + NSOpenGLContext *ctx = [self openGLContext]; + + [ctx clearDrawable]; + [ctx initWithFormat:format shareContext:nil]; + + if (ctx == nil) + { + NSLog(@"Failed to create OpenGL context!", nil); + return false; + } + + [self setOpenGLContext:ctx]; + [ctx setView:self]; + [ctx makeCurrentContext]; + return true; +} + +- (CGLContextObj)getCGLContextObj +{ + NSOpenGLContext *ctx = [self openGLContext]; + return (CGLContextObj)[ctx CGLContextObj]; +} + +- (CGLPixelFormatObj*)getCGLPixelFormatObj +{ + NSOpenGLPixelFormat *fmt = [self pixelFormat]; + return (CGLPixelFormatObj*)[fmt CGLPixelFormatObj]; +} + +- (void) registerResizeCallback:(ResizeCallback)callback +{ + mResizeCallback = callback; +} + +// Various events can be intercepted by our view, thus not reaching our window. +// Intercept these events, and pass them to the window as needed. - Geenz + +- (void) mouseDragged:(NSEvent *)theEvent +{ + [super mouseDragged:theEvent]; +} + +- (void) scrollWheel:(NSEvent *)theEvent +{ + [super scrollWheel:theEvent]; +} + +- (void) mouseDown:(NSEvent *)theEvent +{ + [super mouseDown:theEvent]; +} + +- (void) mouseUp:(NSEvent *)theEvent +{ + [super mouseUp:theEvent]; +} + +- (void) rightMouseDown:(NSEvent *)theEvent +{ + [super rightMouseDown:theEvent]; +} + +- (void) rightMouseUp:(NSEvent *)theEvent +{ + [super rightMouseUp:theEvent]; +} + +- (void) keyUp:(NSEvent *)theEvent +{ + [super keyUp:theEvent]; +} + +- (void) keyDown:(NSEvent *)theEvent +{ + [super keyDown:theEvent]; +} + +- (void) mouseMoved:(NSEvent *)theEvent +{ + [super mouseMoved:theEvent]; +} + +- (void) flagsChanged:(NSEvent *)theEvent +{ + [super flagsChanged:theEvent]; +} + +@end + +// We use a custom NSWindow for our event handling. +// Why not an NSWindowController you may ask? +// Answer: this is easier. + +@implementation LLNSWindow + +- (id) init +{ + return self; +} + +- (void) keyDown:(NSEvent *)theEvent { + mKeyDownCallback([theEvent keyCode], [theEvent modifierFlags]); + + NSString *chars = [theEvent charactersIgnoringModifiers]; + for (uint i = 0; i < [chars length]; i++) + { + mUnicodeCallback([chars characterAtIndex:i], [theEvent modifierFlags]); + } + + // The viewer expects return to be submitted separately as a unicode character. + if ([theEvent keyCode] == 3 || [theEvent keyCode] == 13) + { + mUnicodeCallback([theEvent keyCode], [theEvent modifierFlags]); + } +} + +- (void) keyUp:(NSEvent *)theEvent { + mKeyUpCallback([theEvent keyCode], [theEvent modifierFlags]); +} + +- (void)flagsChanged:(NSEvent *)theEvent { + mModifiers = [theEvent modifierFlags]; +} + +- (void) mouseDown:(NSEvent *)theEvent +{ + if ([theEvent clickCount] == 2) + { + mMouseDoubleClickCallback(mMousePos, [theEvent modifierFlags]); + } else if ([theEvent clickCount] == 1) { + mMouseDownCallback(mMousePos, [theEvent modifierFlags]); + } +} + +- (void) mouseUp:(NSEvent *)theEvent +{ + mMouseUpCallback(mMousePos, [theEvent modifierFlags]); +} + +- (void) rightMouseDown:(NSEvent *)theEvent +{ + mRightMouseDownCallback(mMousePos, [theEvent modifierFlags]); +} + +- (void) rightMouseUp:(NSEvent *)theEvent +{ + mRightMouseUpCallback(mMousePos, [theEvent modifierFlags]); +} + +- (void)mouseMoved:(NSEvent *)theEvent { + float mouseDeltas[2] = { + [theEvent deltaX], + [theEvent deltaZ] + }; + + mDeltaUpdateCallback(mouseDeltas, 0); + + NSPoint mPoint = [theEvent locationInWindow]; + mMousePos[0] = mPoint.x; + mMousePos[1] = mPoint.y; + mMouseMovedCallback(mMousePos, 0); +} + +// NSWindow doesn't trigger mouseMoved when the mouse is being clicked and dragged. +// Use mouseDragged for situations like this to trigger our movement callback instead. + +- (void) mouseDragged:(NSEvent *)theEvent +{ + float mouseDeltas[2] = { + [theEvent deltaX], + [theEvent deltaZ] + }; + + mDeltaUpdateCallback(mouseDeltas, 0); + + NSPoint mPoint = [theEvent locationInWindow]; + mMousePos[0] = mPoint.x; + mMousePos[1] = mPoint.y; + mMouseMovedCallback(mMousePos, 0); +} + +- (void) scrollWheel:(NSEvent *)theEvent +{ + mScrollWhellCallback(-[theEvent deltaY]); +} + +- (void) mouseExited:(NSEvent *)theEvent +{ + mMouseExitCallback(); +} + +- (void) registerKeyDownCallback:(KeyCallback)callback +{ + mKeyDownCallback = callback; +} + +- (void) registerKeyUpCallback:(KeyCallback)callback +{ + mKeyUpCallback = callback; +} + +- (void) registerUnicodeCallback:(UnicodeCallback)callback +{ + mUnicodeCallback = callback; +} + +- (void) registerModifierCallback:(ModifierCallback)callback +{ + mModifierCallback = callback; +} + +- (void) registerMouseDownCallback:(MouseCallback)callback +{ + mMouseDownCallback = callback; +} + +- (void) registerMouseUpCallback:(MouseCallback)callback +{ + mMouseUpCallback = callback; +} + +- (void) registerRightMouseDownCallback:(MouseCallback)callback +{ + mRightMouseDownCallback = callback; +} + +- (void) registerRightMouseUpCallback:(MouseCallback)callback +{ + mRightMouseUpCallback = callback; +} + +- (void) registerDoubleClickCallback:(MouseCallback)callback +{ + mMouseDoubleClickCallback = callback; +} + +- (void) registerMouseMovedCallback:(MouseCallback)callback +{ + mMouseMovedCallback = callback; +} + +- (void) registerScrollCallback:(ScrollWheelCallback)callback +{ + mScrollWhellCallback = callback; +} + +- (void) registerMouseExitCallback:(VoidCallback)callback +{ + mMouseExitCallback = callback; +} + +- (void) registerDeltaUpdateCallback:(MouseCallback)callback +{ + mDeltaUpdateCallback = callback; +} + +@end
\ No newline at end of file |