diff --git a/examples/osgviewerCocoa/Info.plist b/examples/osgviewerCocoa/Info.plist index e90fc6f1b..4ce899f38 100644 --- a/examples/osgviewerCocoa/Info.plist +++ b/examples/osgviewerCocoa/Info.plist @@ -2,27 +2,27 @@ - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - - CFBundleIdentifier - org.openscenegraph.osgsimpleviewerCocoa - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 1.0 - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication + CFBundleDevelopmentRegion + English + CFBundleExecutable + osgviewerCocoa + CFBundleIconFile + + CFBundleIdentifier + org.openscenegraph.osgviewerCocoa + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + osgviewerCocoa + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication diff --git a/examples/osgviewerCocoa/ViewerCocoa.h b/examples/osgviewerCocoa/ViewerCocoa.h index a0022f224..6d058f945 100644 --- a/examples/osgviewerCocoa/ViewerCocoa.h +++ b/examples/osgviewerCocoa/ViewerCocoa.h @@ -53,37 +53,37 @@ namespace osgViewer { - // Just a forward declaration so I don't need the #include in the header. - class Viewer; - class GraphicsWindowEmbedded; + // Just a forward declaration so I don't need the #include in the header. + class Viewer; + class GraphicsWindowEmbedded; } // Subclass NSOpenGLView. We could subclass NSView instead, but NSOpenGLView is easy. @interface ViewerCocoa : NSOpenGLView { - // Note: In Objective-C++, if you use objects instead of pointers as - // member instance variables, you MUST turn on "Call C++ Default Ctors/Dtors in Objective-C". - // -fobjc-call-cxx-cdtors - // This option makes sure constructors and destructors are run. - // This option is only available for gcc 4.0+ (Mac OS X 10.4+) + // Note: In Objective-C++, if you use objects instead of pointers as + // member instance variables, you MUST turn on "Call C++ Default Ctors/Dtors in Objective-C". + // -fobjc-call-cxx-cdtors + // This option makes sure constructors and destructors are run. + // This option is only available for gcc 4.0+ (Mac OS X 10.4+) - // Is SimpleViewer supposed use ref_ptr? (Doesn't look like it to me.) - // If so, remember ref_ptr is an object on the stack and the cdtors option must be activated. - // We could also make simpleViewer an object instead of a pointer, but again, turn on the option. - osgViewer::Viewer* theViewer; - osgViewer::GraphicsWindowEmbedded* graphicsWindow; - + // Is SimpleViewer supposed use ref_ptr? (Doesn't look like it to me.) + // If so, remember ref_ptr is an object on the stack and the cdtors option must be activated. + // We could also make simpleViewer an object instead of a pointer, but again, turn on the option. + osgViewer::Viewer* theViewer; + osgViewer::GraphicsWindowEmbedded* graphicsWindow; + - // This timer is used to trigger animation callbacks since everything is event driven. - NSTimer* animationTimer; + // This timer is used to trigger animation callbacks since everything is event driven. + NSTimer* animationTimer; - // Flags to help track whether ctrl-clicking or option-clicking is being used - BOOL isUsingCtrlClick; - BOOL isUsingOptionClick; - - // Flag to track whether the OpenGL multithreading engine is enabled or not - BOOL isUsingMultithreadedOpenGLEngine; - + // Flags to help track whether ctrl-clicking or option-clicking is being used + BOOL isUsingCtrlClick; + BOOL isUsingOptionClick; + + // Flag to track whether the OpenGL multithreading engine is enabled or not + BOOL isUsingMultithreadedOpenGLEngine; + } // My custom static method to create a basic pixel format diff --git a/examples/osgviewerCocoa/ViewerCocoa.mm b/examples/osgviewerCocoa/ViewerCocoa.mm index 41bf7b474..872559ec4 100644 --- a/examples/osgviewerCocoa/ViewerCocoa.mm +++ b/examples/osgviewerCocoa/ViewerCocoa.mm @@ -136,28 +136,28 @@ static NSOpenGLContext* s_sharedOpenGLContext = NULL; // Taken/Adapted from one of the Apple OpenGL developer examples static void Internal_SetAlpha(NSBitmapImageRep *imageRep, unsigned char alpha_value) { - register unsigned char * sp = [imageRep bitmapData]; - register int bytesPerRow = [imageRep bytesPerRow]; - register int height = [imageRep pixelsHigh]; - register int width = [imageRep pixelsWide]; + register unsigned char * sp = [imageRep bitmapData]; + register int bytesPerRow = [imageRep bytesPerRow]; + register int height = [imageRep pixelsHigh]; + register int width = [imageRep pixelsWide]; - for(int i=0; i 0) - { - unsigned char* sp_char = (unsigned char *) the_pixel; -// register unsigned char * the_red = sp_char; -// register unsigned char * the_green = (sp_char+1); -// register unsigned char * the_blue = (sp_char+2); - register unsigned char * the_alpha = (sp_char+3); - - *the_alpha = alpha_value; - *the_pixel++; - } - sp += bytesPerRow; - } + for(int i=0; i 0) + { + unsigned char* sp_char = (unsigned char *) the_pixel; +// register unsigned char * the_red = sp_char; +// register unsigned char * the_green = (sp_char+1); +// register unsigned char * the_blue = (sp_char+2); + register unsigned char * the_alpha = (sp_char+3); + + *the_alpha = alpha_value; + *the_pixel++; + } + sp += bytesPerRow; + } } @@ -166,14 +166,14 @@ static void Internal_SetAlpha(NSBitmapImageRep *imageRep, unsigned char alpha_va // My simple pixel format definition + (NSOpenGLPixelFormat*) basicPixelFormat { - NSOpenGLPixelFormatAttribute pixel_attributes[] = - { - NSOpenGLPFAWindow, - NSOpenGLPFADoubleBuffer, // double buffered - NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)32, // depth buffer size in bits -// NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute)24, // Not sure if this helps -// NSOpenGLPFAAlphaSize, (NSOpenGLPixelFormatAttribute)8, // Not sure if this helps - (NSOpenGLPixelFormatAttribute)nil + NSOpenGLPixelFormatAttribute pixel_attributes[] = + { + NSOpenGLPFAWindow, + NSOpenGLPFADoubleBuffer, // double buffered + NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)32, // depth buffer size in bits +// NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute)24, // Not sure if this helps +// NSOpenGLPFAAlphaSize, (NSOpenGLPixelFormatAttribute)8, // Not sure if this helps + (NSOpenGLPixelFormatAttribute)nil }; return [[[NSOpenGLPixelFormat alloc] initWithAttributes:pixel_attributes] autorelease]; } @@ -190,12 +190,12 @@ static void Internal_SetAlpha(NSBitmapImageRep *imageRep, unsigned char alpha_va */ - (id) initWithFrame:(NSRect)frame_rect pixelFormat:(NSOpenGLPixelFormat*)pixel_format { - self = [super initWithFrame:frame_rect pixelFormat:pixel_format]; - if(self) - { - [self commonInit]; - } - return self; + self = [super initWithFrame:frame_rect pixelFormat:pixel_format]; + if(self) + { + [self commonInit]; + } + return self; } /* Going through the IB palette, this initializer is calling instead of the designated initializer @@ -208,14 +208,14 @@ static void Internal_SetAlpha(NSBitmapImageRep *imageRep, unsigned char alpha_va */ - (id) initWithCoder:(NSCoder*)the_coder { - self = [super initWithCoder:the_coder]; - if(self) - { - NSOpenGLPixelFormat* pixel_format = [ViewerCocoa basicPixelFormat]; - [self setPixelFormat:pixel_format]; - [self commonInit]; - } - return self; + self = [super initWithCoder:the_coder]; + if(self) + { + NSOpenGLPixelFormat* pixel_format = [ViewerCocoa basicPixelFormat]; + [self setPixelFormat:pixel_format]; + [self commonInit]; + } + return self; } /* Some generic code expecting regular NSView's may call this initializer instead of the specialized NSOpenGLView designated initializer. @@ -223,32 +223,32 @@ static void Internal_SetAlpha(NSBitmapImageRep *imageRep, unsigned char alpha_va */ - (id) initWithFrame:(NSRect)frame_rect { - self = [super initWithFrame:frame_rect pixelFormat:[ViewerCocoa basicPixelFormat]]; - if(self) - { - [self commonInit]; - } - return self; + self = [super initWithFrame:frame_rect pixelFormat:[ViewerCocoa basicPixelFormat]]; + if(self) + { + [self commonInit]; + } + return self; } // My custom methods to centralize common init stuff - (void) commonInit { - isUsingCtrlClick = NO; - isUsingOptionClick = NO; - isUsingMultithreadedOpenGLEngine = NO; + isUsingCtrlClick = NO; + isUsingOptionClick = NO; + isUsingMultithreadedOpenGLEngine = NO; - [self initSharedOpenGLContext]; + [self initSharedOpenGLContext]; - [self initOSGViewer]; - [self initAnimationTimer]; - - // Register for Drag and Drop - [self registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSURLPboardType, nil]]; - + [self initOSGViewer]; + [self initAnimationTimer]; + + // Register for Drag and Drop + [self registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSURLPboardType, nil]]; + // Add minification observer so we can set the Dock picture since OpenGL views don't do this automatically for us. - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(prepareForMiniaturization:) name:NSWindowWillMiniaturizeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(prepareForMiniaturization:) name:NSWindowWillMiniaturizeNotification object:nil]; } @@ -259,22 +259,22 @@ static void Internal_SetAlpha(NSBitmapImageRep *imageRep, unsigned char alpha_va { #ifdef VIEWER_USE_SHARED_CONTEXTS - NSOpenGLContext* this_views_opengl_context = nil; - - // create a context the first time through - if(s_sharedOpenGLContext == NULL) - { - s_sharedOpenGLContext = [[NSOpenGLContext alloc] + NSOpenGLContext* this_views_opengl_context = nil; + + // create a context the first time through + if(s_sharedOpenGLContext == NULL) + { + s_sharedOpenGLContext = [[NSOpenGLContext alloc] initWithFormat:[ViewerCocoa basicPixelFormat] - shareContext:nil]; - - } - - this_views_opengl_context = [[NSOpenGLContext alloc] + shareContext:nil]; + + } + + this_views_opengl_context = [[NSOpenGLContext alloc] initWithFormat:[ViewerCocoa basicPixelFormat] - shareContext:s_sharedOpenGLContext]; - [self setOpenGLContext:this_views_opengl_context]; -// [this_views_opengl_context makeCurrentContext]; + shareContext:s_sharedOpenGLContext]; + [self setOpenGLContext:this_views_opengl_context]; +// [this_views_opengl_context makeCurrentContext]; #endif // VIEWER_USE_SHARED_CONTEXTS } @@ -284,75 +284,75 @@ static void Internal_SetAlpha(NSBitmapImageRep *imageRep, unsigned char alpha_va { -// osg::setNotifyLevel( osg::DEBUG_FP ); - theViewer = new osgViewer::Viewer; - graphicsWindow = theViewer->setUpViewerAsEmbeddedInWindow(0,0,740,650); // numbers from Nib - // Builts in Stats handler - theViewer->addEventHandler(new osgViewer::StatsHandler); +// osg::setNotifyLevel( osg::DEBUG_FP ); + theViewer = new osgViewer::Viewer; + graphicsWindow = theViewer->setUpViewerAsEmbeddedInWindow(0,0,740,650); // numbers from Nib + // Builts in Stats handler + theViewer->addEventHandler(new osgViewer::StatsHandler); #ifdef VIEWER_USE_SHARED_CONTEXTS - // Workaround: osgViewer::Viewer automatically increments its context ID values. - // Since we're using a shared context, we want all Viewer's to use the same context ID. - // There is no API to avoid this behavior, so we need to undo what Viewer's constructor did. + // Workaround: osgViewer::Viewer automatically increments its context ID values. + // Since we're using a shared context, we want all Viewer's to use the same context ID. + // There is no API to avoid this behavior, so we need to undo what Viewer's constructor did. graphicsWindow->getState()->setContextID(0); - osg::DisplaySettings::instance()->setMaxNumberOfGraphicsContexts(1); + osg::DisplaySettings::instance()->setMaxNumberOfGraphicsContexts(1); #endif // VIEWER_USE_SHARED_CONTEXTS - // Cocoa follows the same coordinate convention as OpenGL. osgViewer's default is inverted. - theViewer->getEventQueue()->getCurrentEventState()->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS); - // Use a trackball manipulator...matches nicely with the Mighty Mouse Scrollball. - theViewer->setCameraManipulator(new osgGA::TrackballManipulator); - + // Cocoa follows the same coordinate convention as OpenGL. osgViewer's default is inverted. + theViewer->getEventQueue()->getCurrentEventState()->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS); + // Use a trackball manipulator...matches nicely with the Mighty Mouse Scrollball. + theViewer->setCameraManipulator(new osgGA::TrackballManipulator); + } - (void) initAnimationTimer { - // Cocoa is event driven, so by default, there is nothing to trigger redraws for animation. - // The easiest way to animate is to set a repeating NSTimer which triggers a redraw. - SEL the_selector; - NSMethodSignature* a_signature; - NSInvocation* an_invocation; - // animationCallback is my animation callback method - the_selector = @selector( animationCallback ); - a_signature = [ViewerCocoa instanceMethodSignatureForSelector:the_selector]; - an_invocation = [NSInvocation invocationWithMethodSignature:a_signature] ; - [an_invocation setSelector:the_selector]; - [an_invocation setTarget:self]; - - animationTimer = [NSTimer - scheduledTimerWithTimeInterval:1.0/60.0 // fps - invocation:an_invocation - repeats:YES]; - [animationTimer retain]; - - // For single threaded apps like this one, - // Cocoa seems to block timers or events sometimes. This can be seen - // when I'm animating (via a timer) and you open an popup box or move a slider. - // Apparently, sheets and dialogs can also block (try printing). - // To work around this, Cocoa provides different run-loop modes. I need to - // specify the modes to avoid the blockage. - // NSDefaultRunLoopMode seems to be the default. I don't think I need to explicitly - // set this one, but just in case, I will set it anyway. - [[NSRunLoop currentRunLoop] addTimer:animationTimer forMode:NSDefaultRunLoopMode]; - // This seems to be the one for preventing blocking on other events (popup box, slider, etc) - [[NSRunLoop currentRunLoop] addTimer:animationTimer forMode:NSEventTrackingRunLoopMode]; - // This seems to be the one for dialogs. - [[NSRunLoop currentRunLoop] addTimer:animationTimer forMode:NSModalPanelRunLoopMode]; + // Cocoa is event driven, so by default, there is nothing to trigger redraws for animation. + // The easiest way to animate is to set a repeating NSTimer which triggers a redraw. + SEL the_selector; + NSMethodSignature* a_signature; + NSInvocation* an_invocation; + // animationCallback is my animation callback method + the_selector = @selector( animationCallback ); + a_signature = [ViewerCocoa instanceMethodSignatureForSelector:the_selector]; + an_invocation = [NSInvocation invocationWithMethodSignature:a_signature] ; + [an_invocation setSelector:the_selector]; + [an_invocation setTarget:self]; + + animationTimer = [NSTimer + scheduledTimerWithTimeInterval:1.0/60.0 // fps + invocation:an_invocation + repeats:YES]; + [animationTimer retain]; + + // For single threaded apps like this one, + // Cocoa seems to block timers or events sometimes. This can be seen + // when I'm animating (via a timer) and you open an popup box or move a slider. + // Apparently, sheets and dialogs can also block (try printing). + // To work around this, Cocoa provides different run-loop modes. I need to + // specify the modes to avoid the blockage. + // NSDefaultRunLoopMode seems to be the default. I don't think I need to explicitly + // set this one, but just in case, I will set it anyway. + [[NSRunLoop currentRunLoop] addTimer:animationTimer forMode:NSDefaultRunLoopMode]; + // This seems to be the one for preventing blocking on other events (popup box, slider, etc) + [[NSRunLoop currentRunLoop] addTimer:animationTimer forMode:NSEventTrackingRunLoopMode]; + // This seems to be the one for dialogs. + [[NSRunLoop currentRunLoop] addTimer:animationTimer forMode:NSModalPanelRunLoopMode]; } - (void) dealloc { - [animationTimer invalidate]; - [animationTimer release]; - delete theViewer; - theViewer = NULL; - [super dealloc]; + [animationTimer invalidate]; + [animationTimer release]; + delete theViewer; + theViewer = NULL; + [super dealloc]; } - (void) finalize { - delete theViewer; - theViewer = NULL; - [super finalize]; + delete theViewer; + theViewer = NULL; + [super finalize]; } /* NSOpenGLView defines this method to be called (only once) after the OpenGL @@ -364,89 +364,89 @@ static void Internal_SetAlpha(NSBitmapImageRep *imageRep, unsigned char alpha_va */ - (void) prepareOpenGL { - [super prepareOpenGL]; - - // The NSOpenGLCPSwapInterval seems to be vsync. If 1, buffers are swapped with vertical refresh. - // If 0, flushBuffer will execute as soon as possible. - long swap_interval = 1 ; + [super prepareOpenGL]; + + // The NSOpenGLCPSwapInterval seems to be vsync. If 1, buffers are swapped with vertical refresh. + // If 0, flushBuffer will execute as soon as possible. + long swap_interval = 1 ; [[self openGLContext] setValues:&swap_interval forParameter:NSOpenGLCPSwapInterval]; - // Try new multithreaded OpenGL engine? - // See Technical Note TN2085 Enabling multi-threaded execution of the OpenGL framework - // http://developer.apple.com/technotes/tn2006/tn2085.html - // For this simple viewer, you are probably not going to see a speed boost, but possibly a speed hit, - // since we probably don't have much data to dispatch, - // but it is enabled anyway for demonstration purposes. - uint64_t num_cpus = 0; - size_t num_cpus_length = sizeof(num_cpus); - // Multithreaded engine only benefits with muliple CPUs, so do CPU count check - // I've been told that Apple has started doing this check behind the scenes in some version of Tiger. - if(sysctlbyname("hw.activecpu", &num_cpus, &num_cpus_length, NULL, 0) == 0) - { -// NSLog(@"Num CPUs=%d", num_cpus); - if(num_cpus >= 2) - { - // Cleared to enable multi-threaded engine - // kCGLCEMPEngine may not be defined before certain versions of Tiger/Xcode, - // so use the numeric value 313 instead to keep things compiling. - CGLError error_val = CGLEnable((CGLContextObj)[[self openGLContext] CGLContextObj], static_cast(313)); - if(error_val != 0) - { - // The likelihood of failure seems quite high on older hardware, at least for now. - // NSLog(@"Failed to enable Multithreaded OpenGL Engine: %s", CGLErrorString(error_val)); - isUsingMultithreadedOpenGLEngine = NO; - } - else - { - // NSLog(@"Success! Multithreaded OpenGL Engine activated!"); - isUsingMultithreadedOpenGLEngine = YES; - } - } - else - { - isUsingMultithreadedOpenGLEngine = NO; - } - } + // Try new multithreaded OpenGL engine? + // See Technical Note TN2085 Enabling multi-threaded execution of the OpenGL framework + // http://developer.apple.com/technotes/tn2006/tn2085.html + // For this simple viewer, you are probably not going to see a speed boost, but possibly a speed hit, + // since we probably don't have much data to dispatch, + // but it is enabled anyway for demonstration purposes. + uint64_t num_cpus = 0; + size_t num_cpus_length = sizeof(num_cpus); + // Multithreaded engine only benefits with muliple CPUs, so do CPU count check + // I've been told that Apple has started doing this check behind the scenes in some version of Tiger. + if(sysctlbyname("hw.activecpu", &num_cpus, &num_cpus_length, NULL, 0) == 0) + { +// NSLog(@"Num CPUs=%d", num_cpus); + if(num_cpus >= 2) + { + // Cleared to enable multi-threaded engine + // kCGLCEMPEngine may not be defined before certain versions of Tiger/Xcode, + // so use the numeric value 313 instead to keep things compiling. + CGLError error_val = CGLEnable((CGLContextObj)[[self openGLContext] CGLContextObj], static_cast(313)); + if(error_val != 0) + { + // The likelihood of failure seems quite high on older hardware, at least for now. + // NSLog(@"Failed to enable Multithreaded OpenGL Engine: %s", CGLErrorString(error_val)); + isUsingMultithreadedOpenGLEngine = NO; + } + else + { + // NSLog(@"Success! Multithreaded OpenGL Engine activated!"); + isUsingMultithreadedOpenGLEngine = YES; + } + } + else + { + isUsingMultithreadedOpenGLEngine = NO; + } + } - // This is also might be a good place to setup OpenGL state that OSG doesn't control. - glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + // This is also might be a good place to setup OpenGL state that OSG doesn't control. + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); /* - GLint maxbuffers[1]; - glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, maxbuffers); - NSLog(@"GL_MAX_COLOR_ATTACHMENTS=%d", maxbuffers[0]); + GLint maxbuffers[1]; + glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, maxbuffers); + NSLog(@"GL_MAX_COLOR_ATTACHMENTS=%d", maxbuffers[0]); */ - // We need to tell the osgViewer what the viewport size is - [self resizeViewport]; + // We need to tell the osgViewer what the viewport size is + [self resizeViewport]; - // This is optional: - // This is to setup some default text in the OpenGL view so the - // user knows that they should drag and drop a model into the view. - osg::ref_ptr default_text = new osgText::Text; + // This is optional: + // This is to setup some default text in the OpenGL view so the + // user knows that they should drag and drop a model into the view. + osg::ref_ptr default_text = new osgText::Text; default_text->setAlignment(osgText::Text::CENTER_CENTER); default_text->setBackdropType(osgText::Text::OUTLINE); -// default_text->setBackdropImplementation(osgText::Text::POLYGON_OFFSET); - default_text->setColor(osg::Vec4(1.0, 1.0, 0.0, 1.0)); - default_text->setBackdropColor(osg::Vec4(0.0, 0.0, 0.0, 1.0)); +// default_text->setBackdropImplementation(osgText::Text::POLYGON_OFFSET); + default_text->setColor(osg::Vec4(1.0, 1.0, 0.0, 1.0)); + default_text->setBackdropColor(osg::Vec4(0.0, 0.0, 0.0, 1.0)); default_text->setAxisAlignment(osgText::Text::XZ_PLANE); - - // We should use a (Cocoa) localizable string instead of a hard coded string. -// default_text->setText("Drag-and-Drop\nyour .osg model here!"); - // The first string is the key name (you need a Localizable.strings file for your Nib). The second string is just a comment. - NSString* localized_string = NSLocalizedString(@"DragAndDropHere", @"Drag-and-Drop\nyour .osg model here!"); - default_text->setText([localized_string UTF8String]); - - osg::ref_ptr the_geode = new osg::Geode; - the_geode->addDrawable(default_text.get()); + + // We should use a (Cocoa) localizable string instead of a hard coded string. +// default_text->setText("Drag-and-Drop\nyour .osg model here!"); + // The first string is the key name (you need a Localizable.strings file for your Nib). The second string is just a comment. + NSString* localized_string = NSLocalizedString(@"DragAndDropHere", @"Drag-and-Drop\nyour .osg model here!"); + default_text->setText([localized_string UTF8String]); + + osg::ref_ptr the_geode = new osg::Geode; + the_geode->addDrawable(default_text.get()); - theViewer->setSceneData(the_geode.get()); + theViewer->setSceneData(the_geode.get()); } /* disableScreenUpdatesUntilFlush was introduced in Tiger. It will prevent @@ -466,8 +466,8 @@ A -respondsToSelector: check has been used to provide compatibility with previou { NSWindow* the_window = [self window]; if([the_window respondsToSelector:@selector(disableScreenUpdatesUntilFlush)]) - { - [the_window disableScreenUpdatesUntilFlush]; + { + [the_window disableScreenUpdatesUntilFlush]; } [super renewGState]; } @@ -481,21 +481,21 @@ A -respondsToSelector: check has been used to provide compatibility with previou */ - (void) prepareForMiniaturization:(NSNotification*)notification { - [[self openGLContext] makeCurrentContext]; - NSBitmapImageRep* ns_image_rep = [self renderOpenGLSceneToFramebuffer]; - if([self lockFocusIfCanDraw]) - { - [ns_image_rep draw]; - [self unlockFocus]; - [[self window] flushWindow]; - } + [[self openGLContext] makeCurrentContext]; + NSBitmapImageRep* ns_image_rep = [self renderOpenGLSceneToFramebuffer]; + if([self lockFocusIfCanDraw]) + { + [ns_image_rep draw]; + [self unlockFocus]; + [[self window] flushWindow]; + } } /* Allow people to easily query if the multithreaded OpenGL engine is activated. */ - (BOOL) isUsingMultithreadedOpenGLEngine { - return isUsingMultithreadedOpenGLEngine; + return isUsingMultithreadedOpenGLEngine; } @@ -511,274 +511,274 @@ A -respondsToSelector: check has been used to provide compatibility with previou - (void) mouseDown:(NSEvent*)the_event { - // Because many Mac users have only a 1-button mouse, we should provide ways - // to access the button 2 and 3 actions of osgViewer. - // I will use the Ctrl modifer to represent right-clicking - // and Option modifier to represent middle clicking. - if([the_event modifierFlags] & NSControlKeyMask) - { - [self setIsUsingCtrlClick:YES]; - [self doRightMouseButtonDown:the_event]; - } - else if([the_event modifierFlags] & NSAlternateKeyMask) - { - [self setIsUsingOptionClick:YES]; - [self doMiddleMouseButtonDown:the_event]; - } - else if([the_event modifierFlags] & NSCommandKeyMask) - { - [self startDragAndDropAsSource:the_event]; - } - else - { - [self doLeftMouseButtonDown:the_event]; - } + // Because many Mac users have only a 1-button mouse, we should provide ways + // to access the button 2 and 3 actions of osgViewer. + // I will use the Ctrl modifer to represent right-clicking + // and Option modifier to represent middle clicking. + if([the_event modifierFlags] & NSControlKeyMask) + { + [self setIsUsingCtrlClick:YES]; + [self doRightMouseButtonDown:the_event]; + } + else if([the_event modifierFlags] & NSAlternateKeyMask) + { + [self setIsUsingOptionClick:YES]; + [self doMiddleMouseButtonDown:the_event]; + } + else if([the_event modifierFlags] & NSCommandKeyMask) + { + [self startDragAndDropAsSource:the_event]; + } + else + { + [self doLeftMouseButtonDown:the_event]; + } } - (void) mouseDragged:(NSEvent*)the_event { - // We must convert the mouse event locations from the window coordinate system to the - // local view coordinate system. - NSPoint the_point = [the_event locationInWindow]; + // We must convert the mouse event locations from the window coordinate system to the + // local view coordinate system. + NSPoint the_point = [the_event locationInWindow]; NSPoint converted_point = [self convertPoint:the_point fromView:nil]; - - theViewer->getEventQueue()->mouseMotion(converted_point.x, converted_point.y); - [self setNeedsDisplay:YES]; + + theViewer->getEventQueue()->mouseMotion(converted_point.x, converted_point.y); + [self setNeedsDisplay:YES]; } - (void) mouseUp:(NSEvent*)the_event { - // Because many Mac users have only a 1-button mouse, we should provide ways - // to access the button 2 and 3 actions of osgViewer. - // I will use the Ctrl modifer to represent right-clicking - // and Option modifier to represent middle clicking. - if([self isUsingCtrlClick] == YES) - { - [self setIsUsingCtrlClick:NO]; - [self doRightMouseButtonUp:the_event]; - } - else if([self isUsingOptionClick] == YES) - { - [self setIsUsingOptionClick:NO]; - [self doMiddleMouseButtonUp:the_event]; - } - else - { - [self doLeftMouseButtonUp:the_event]; - } + // Because many Mac users have only a 1-button mouse, we should provide ways + // to access the button 2 and 3 actions of osgViewer. + // I will use the Ctrl modifer to represent right-clicking + // and Option modifier to represent middle clicking. + if([self isUsingCtrlClick] == YES) + { + [self setIsUsingCtrlClick:NO]; + [self doRightMouseButtonUp:the_event]; + } + else if([self isUsingOptionClick] == YES) + { + [self setIsUsingOptionClick:NO]; + [self doMiddleMouseButtonUp:the_event]; + } + else + { + [self doLeftMouseButtonUp:the_event]; + } } - (void) rightMouseDown:(NSEvent*)the_event { - [self doRightMouseButtonDown:the_event]; + [self doRightMouseButtonDown:the_event]; } - (void) rightMouseDragged:(NSEvent*)the_event { - // We must convert the mouse event locations from the window coordinate system to the - // local view coordinate system. - NSPoint the_point = [the_event locationInWindow]; + // We must convert the mouse event locations from the window coordinate system to the + // local view coordinate system. + NSPoint the_point = [the_event locationInWindow]; NSPoint converted_point = [self convertPoint:the_point fromView:nil]; - - theViewer->getEventQueue()->mouseMotion(converted_point.x, converted_point.y); - [self setNeedsDisplay:YES]; + + theViewer->getEventQueue()->mouseMotion(converted_point.x, converted_point.y); + [self setNeedsDisplay:YES]; } - (void) rightMouseUp:(NSEvent*)the_event { - [self doRightMouseButtonUp:the_event]; + [self doRightMouseButtonUp:the_event]; } // "otherMouse" seems to capture middle button and any other buttons beyond (4th, etc). - (void) otherMouseDown:(NSEvent*)the_event { - // Button 0 is left - // Button 1 is right - // Button 2 is middle - // Button 3 keeps going - // osgViewer expects 1 for left, 3 for right, 2 for middle - // osgViewer has a reversed number mapping for right and middle compared to Cocoa - if([the_event buttonNumber] == 2) - { - [self doMiddleMouseButtonDown:the_event]; - } - else // buttonNumber should be 3,4,5,etc; must map to 4,5,6,etc in osgViewer - { - [self doExtraMouseButtonDown:the_event buttonNumber:[the_event buttonNumber]]; - } + // Button 0 is left + // Button 1 is right + // Button 2 is middle + // Button 3 keeps going + // osgViewer expects 1 for left, 3 for right, 2 for middle + // osgViewer has a reversed number mapping for right and middle compared to Cocoa + if([the_event buttonNumber] == 2) + { + [self doMiddleMouseButtonDown:the_event]; + } + else // buttonNumber should be 3,4,5,etc; must map to 4,5,6,etc in osgViewer + { + [self doExtraMouseButtonDown:the_event buttonNumber:[the_event buttonNumber]]; + } } - (void) otherMouseDragged:(NSEvent*)the_event { - // We must convert the mouse event locations from the window coordinate system to the - // local view coordinate system. - NSPoint the_point = [the_event locationInWindow]; + // We must convert the mouse event locations from the window coordinate system to the + // local view coordinate system. + NSPoint the_point = [the_event locationInWindow]; NSPoint converted_point = [self convertPoint:the_point fromView:nil]; - - theViewer->getEventQueue()->mouseMotion(converted_point.x, converted_point.y); - [self setNeedsDisplay:YES]; + + theViewer->getEventQueue()->mouseMotion(converted_point.x, converted_point.y); + [self setNeedsDisplay:YES]; } // "otherMouse" seems to capture middle button and any other buttons beyond (4th, etc). - (void) otherMouseUp:(NSEvent*)the_event { - // Button 0 is left - // Button 1 is right - // Button 2 is middle - // Button 3 keeps going - // osgViewer expects 1 for left, 3 for right, 2 for middle - // osgViewer has a reversed number mapping for right and middle compared to Cocoa - if([the_event buttonNumber] == 2) - { - [self doMiddleMouseButtonUp:the_event]; - } - else // buttonNumber should be 3,4,5,etc; must map to 4,5,6,etc in osgViewer - { - // I don't think osgViewer does anything for these additional buttons, - // but just in case, pass them along. But as a Cocoa programmer, you might - // think about things you can do natively here instead of passing the buck. - } [self doExtraMouseButtonUp:the_event buttonNumber:[the_event buttonNumber]]; + // Button 0 is left + // Button 1 is right + // Button 2 is middle + // Button 3 keeps going + // osgViewer expects 1 for left, 3 for right, 2 for middle + // osgViewer has a reversed number mapping for right and middle compared to Cocoa + if([the_event buttonNumber] == 2) + { + [self doMiddleMouseButtonUp:the_event]; + } + else // buttonNumber should be 3,4,5,etc; must map to 4,5,6,etc in osgViewer + { + // I don't think osgViewer does anything for these additional buttons, + // but just in case, pass them along. But as a Cocoa programmer, you might + // think about things you can do natively here instead of passing the buck. + } [self doExtraMouseButtonUp:the_event buttonNumber:[the_event buttonNumber]]; } - (void) setIsUsingCtrlClick:(BOOL)is_using_ctrl_click { - isUsingCtrlClick = is_using_ctrl_click; + isUsingCtrlClick = is_using_ctrl_click; } - (BOOL) isUsingCtrlClick { - return isUsingCtrlClick; + return isUsingCtrlClick; } - (void) setIsUsingOptionClick:(BOOL)is_using_option_click { - isUsingOptionClick = is_using_option_click; + isUsingOptionClick = is_using_option_click; } - (BOOL) isUsingOptionClick { - return isUsingOptionClick; + return isUsingOptionClick; } - (void) doLeftMouseButtonDown:(NSEvent*)the_event { - // We must convert the mouse event locations from the window coordinate system to the - // local view coordinate system. - NSPoint the_point = [the_event locationInWindow]; + // We must convert the mouse event locations from the window coordinate system to the + // local view coordinate system. + NSPoint the_point = [the_event locationInWindow]; NSPoint converted_point = [self convertPoint:the_point fromView:nil]; - if([the_event clickCount] == 1) - { - theViewer->getEventQueue()->mouseButtonPress(converted_point.x, converted_point.y, 1); - } - else - { - theViewer->getEventQueue()->mouseDoubleButtonPress(converted_point.x, converted_point.y, 1); - - - // Let's toggle fullscreen for show - [self toggleFullScreen:nil]; + if([the_event clickCount] == 1) + { + theViewer->getEventQueue()->mouseButtonPress(converted_point.x, converted_point.y, 1); + } + else + { + theViewer->getEventQueue()->mouseDoubleButtonPress(converted_point.x, converted_point.y, 1); + + + // Let's toggle fullscreen for show + [self toggleFullScreen:nil]; - } - [self setNeedsDisplay:YES]; + } + [self setNeedsDisplay:YES]; } - (void) doLeftMouseButtonUp:(NSEvent*)the_event { - // We must convert the mouse event locations from the window coordinate system to the - // local view coordinate system. - NSPoint the_point = [the_event locationInWindow]; + // We must convert the mouse event locations from the window coordinate system to the + // local view coordinate system. + NSPoint the_point = [the_event locationInWindow]; NSPoint converted_point = [self convertPoint:the_point fromView:nil]; - - theViewer->getEventQueue()->mouseButtonRelease(converted_point.x, converted_point.y, 1); - [self setNeedsDisplay:YES]; + + theViewer->getEventQueue()->mouseButtonRelease(converted_point.x, converted_point.y, 1); + [self setNeedsDisplay:YES]; } - (void) doRightMouseButtonDown:(NSEvent*)the_event { - // We must convert the mouse event locations from the window coordinate system to the - // local view coordinate system. - NSPoint the_point = [the_event locationInWindow]; + // We must convert the mouse event locations from the window coordinate system to the + // local view coordinate system. + NSPoint the_point = [the_event locationInWindow]; NSPoint converted_point = [self convertPoint:the_point fromView:nil]; - if([the_event clickCount] == 1) - { - theViewer->getEventQueue()->mouseButtonPress(converted_point.x, converted_point.y, 3); - } - else - { - theViewer->getEventQueue()->mouseDoubleButtonPress(converted_point.x, converted_point.y, 3); - } - [self setNeedsDisplay:YES]; + if([the_event clickCount] == 1) + { + theViewer->getEventQueue()->mouseButtonPress(converted_point.x, converted_point.y, 3); + } + else + { + theViewer->getEventQueue()->mouseDoubleButtonPress(converted_point.x, converted_point.y, 3); + } + [self setNeedsDisplay:YES]; } - (void) doRightMouseButtonUp:(NSEvent*)the_event { - // We must convert the mouse event locations from the window coordinate system to the - // local view coordinate system. - NSPoint the_point = [the_event locationInWindow]; + // We must convert the mouse event locations from the window coordinate system to the + // local view coordinate system. + NSPoint the_point = [the_event locationInWindow]; NSPoint converted_point = [self convertPoint:the_point fromView:nil]; - - theViewer->getEventQueue()->mouseButtonRelease(converted_point.x, converted_point.y, 3); - [self setNeedsDisplay:YES]; + + theViewer->getEventQueue()->mouseButtonRelease(converted_point.x, converted_point.y, 3); + [self setNeedsDisplay:YES]; } - (void) doMiddleMouseButtonDown:(NSEvent*)the_event { - // We must convert the mouse event locations from the window coordinate system to the - // local view coordinate system. - NSPoint the_point = [the_event locationInWindow]; + // We must convert the mouse event locations from the window coordinate system to the + // local view coordinate system. + NSPoint the_point = [the_event locationInWindow]; NSPoint converted_point = [self convertPoint:the_point fromView:nil]; - - if([the_event clickCount] == 1) - { - theViewer->getEventQueue()->mouseButtonPress(converted_point.x, converted_point.y, 2); - } - else - { - theViewer->getEventQueue()->mouseDoubleButtonPress(converted_point.x, converted_point.y, 2); - } - [self setNeedsDisplay:YES]; + + if([the_event clickCount] == 1) + { + theViewer->getEventQueue()->mouseButtonPress(converted_point.x, converted_point.y, 2); + } + else + { + theViewer->getEventQueue()->mouseDoubleButtonPress(converted_point.x, converted_point.y, 2); + } + [self setNeedsDisplay:YES]; } - (void) doExtraMouseButtonDown:(NSEvent*)the_event buttonNumber:(int)button_number { - // We must convert the mouse event locations from the window coordinate system to the - // local view coordinate system. - NSPoint the_point = [the_event locationInWindow]; + // We must convert the mouse event locations from the window coordinate system to the + // local view coordinate system. + NSPoint the_point = [the_event locationInWindow]; NSPoint converted_point = [self convertPoint:the_point fromView:nil]; - if([the_event clickCount] == 1) - { - theViewer->getEventQueue()->mouseButtonPress(converted_point.x, converted_point.y, button_number+1); - } - else - { - theViewer->getEventQueue()->mouseDoubleButtonPress(converted_point.x, converted_point.y, button_number+1); - } - [self setNeedsDisplay:YES]; + if([the_event clickCount] == 1) + { + theViewer->getEventQueue()->mouseButtonPress(converted_point.x, converted_point.y, button_number+1); + } + else + { + theViewer->getEventQueue()->mouseDoubleButtonPress(converted_point.x, converted_point.y, button_number+1); + } + [self setNeedsDisplay:YES]; } - (void) doMiddleMouseButtonUp:(NSEvent*)the_event { - // We must convert the mouse event locations from the window coordinate system to the - // local view coordinate system. NSPoint the_point = [the_event locationInWindow]; - NSPoint the_point = [the_event locationInWindow]; - NSPoint converted_point = [self convertPoint:the_point fromView:nil]; - theViewer->getEventQueue()->mouseButtonRelease(converted_point.x, converted_point.y, 2); - [self setNeedsDisplay:YES]; + // We must convert the mouse event locations from the window coordinate system to the + // local view coordinate system. NSPoint the_point = [the_event locationInWindow]; + NSPoint the_point = [the_event locationInWindow]; + NSPoint converted_point = [self convertPoint:the_point fromView:nil]; + theViewer->getEventQueue()->mouseButtonRelease(converted_point.x, converted_point.y, 2); + [self setNeedsDisplay:YES]; } - (void) doExtraMouseButtonUp:(NSEvent*)the_event buttonNumber:(int)button_number { - // We must convert the mouse event locations from the window coordinate system to the - // local view coordinate system. NSPoint the_point = [the_event locationInWindow]; - NSPoint the_point = [the_event locationInWindow]; - NSPoint converted_point = [self convertPoint:the_point fromView:nil]; - theViewer->getEventQueue()->mouseButtonRelease(converted_point.x, converted_point.y, button_number+1); - - [self setNeedsDisplay:YES]; + // We must convert the mouse event locations from the window coordinate system to the + // local view coordinate system. NSPoint the_point = [the_event locationInWindow]; + NSPoint the_point = [the_event locationInWindow]; + NSPoint converted_point = [self convertPoint:the_point fromView:nil]; + theViewer->getEventQueue()->mouseButtonRelease(converted_point.x, converted_point.y, button_number+1); + + [self setNeedsDisplay:YES]; } // This is a job for Mighty Mouse! @@ -791,19 +791,19 @@ A -respondsToSelector: check has been used to provide compatibility with previou // You should also be able to use 'two-finger scrolling' on newer laptops. - (void) scrollWheel:(NSEvent*)the_event { - // Unfortunately, it turns out mouseScroll2D doesn't actually do anything. - // The camera manipulators don't seem to implement any code that utilize the scroll values. - // This this call does nothing. -// theViewer->getEventQueue()->mouseScroll2D([the_event deltaX], [the_event deltaY]); + // Unfortunately, it turns out mouseScroll2D doesn't actually do anything. + // The camera manipulators don't seem to implement any code that utilize the scroll values. + // This this call does nothing. +// theViewer->getEventQueue()->mouseScroll2D([the_event deltaX], [the_event deltaY]); - // With the absense of a useful mouseScroll2D API, we can manually simulate the desired effect. - NSPoint the_point = [the_event locationInWindow]; - NSPoint converted_point = [self convertPoint:the_point fromView:nil]; - theViewer->getEventQueue()->mouseButtonPress(converted_point.x, converted_point.y, 1); - theViewer->getEventQueue()->mouseMotion(converted_point.x + -[the_event deltaX], converted_point.y + [the_event deltaY]); - theViewer->getEventQueue()->mouseButtonRelease(converted_point.x + -[the_event deltaX], converted_point.y + [the_event deltaY], 1); + // With the absense of a useful mouseScroll2D API, we can manually simulate the desired effect. + NSPoint the_point = [the_event locationInWindow]; + NSPoint converted_point = [self convertPoint:the_point fromView:nil]; + theViewer->getEventQueue()->mouseButtonPress(converted_point.x, converted_point.y, 1); + theViewer->getEventQueue()->mouseMotion(converted_point.x + -[the_event deltaX], converted_point.y + [the_event deltaY]); + theViewer->getEventQueue()->mouseButtonRelease(converted_point.x + -[the_event deltaX], converted_point.y + [the_event deltaY], 1); - [self setNeedsDisplay:YES]; + [self setNeedsDisplay:YES]; } //////////////////////////////////////////////////////////////////////// @@ -816,30 +816,30 @@ A -respondsToSelector: check has been used to provide compatibility with previou // Needed to accept keyboard events - (BOOL) acceptsFirstResponder { - return YES; + return YES; } - (void) keyDown:(NSEvent*)the_event { - // Do you want characters or charactersIgnoringModifiers? - NSString* event_characters = [the_event characters]; -// NSString* event_characters = [the_event charactersIgnoringModifiers]; + // Do you want characters or charactersIgnoringModifiers? + NSString* event_characters = [the_event characters]; +// NSString* event_characters = [the_event charactersIgnoringModifiers]; - unichar unicode_character = [event_characters characterAtIndex:0]; -// NSLog(@"unicode_character: %d", unicode_character); - theViewer->getEventQueue()->keyPress(static_cast(unicode_character)); + unichar unicode_character = [event_characters characterAtIndex:0]; +// NSLog(@"unicode_character: %d", unicode_character); + theViewer->getEventQueue()->keyPress(static_cast(unicode_character)); - [self setNeedsDisplay:YES]; + [self setNeedsDisplay:YES]; } - (void) keyUp:(NSEvent*)the_event { - // Do you want characters or charactersIgnoringModifiers? - NSString* event_characters = [the_event characters]; -// NSString* event_characters = [the_event charactersIgnoringModifiers]; - unichar unicode_character = [event_characters characterAtIndex:0]; - theViewer->getEventQueue()->keyRelease(static_cast(unicode_character)); - [self setNeedsDisplay:YES]; + // Do you want characters or charactersIgnoringModifiers? + NSString* event_characters = [the_event characters]; +// NSString* event_characters = [the_event charactersIgnoringModifiers]; + unichar unicode_character = [event_characters characterAtIndex:0]; + theViewer->getEventQueue()->keyRelease(static_cast(unicode_character)); + [self setNeedsDisplay:YES]; } //////////////////////////////////////////////////////////////////////// @@ -853,34 +853,34 @@ A -respondsToSelector: check has been used to provide compatibility with previou // This method is periodically called by my timer. - (void) animationCallback { - // Simply notify Cocoa that a drawRect needs to take place. - // Potential optimization is to query the OSG stuff to find out if a redraw is actually necessary. - [self setNeedsDisplay:YES]; + // Simply notify Cocoa that a drawRect needs to take place. + // Potential optimization is to query the OSG stuff to find out if a redraw is actually necessary. + [self setNeedsDisplay:YES]; } // This is an optional optimization. This states you don't have a transparent view/window. // Obviously don't use this or set it to NO if you intend for your view to be see-through. - (BOOL) isOpaque { - return YES; + return YES; } // Resolution Independent UI is coming... (Tiger's Quartz Debug already has the tool.) // We must think in 'point sizes', not pixel sizes, so a conversion is needed for OpenGL. - (void) resizeViewport { - NSSize size_in_points = [self bounds].size; - // This coordinate system conversion seems to make things work with Quartz Debug. - NSSize size_in_window_coordinates = [self convertSize:size_in_points toView:nil]; - theViewer->getEventQueue()->windowResize(0, 0, size_in_window_coordinates.width, size_in_window_coordinates.height); - graphicsWindow->resized(0, 0, size_in_window_coordinates.width, size_in_window_coordinates.height); + NSSize size_in_points = [self bounds].size; + // This coordinate system conversion seems to make things work with Quartz Debug. + NSSize size_in_window_coordinates = [self convertSize:size_in_points toView:nil]; + theViewer->getEventQueue()->windowResize(0, 0, size_in_window_coordinates.width, size_in_window_coordinates.height); + graphicsWindow->resized(0, 0, size_in_window_coordinates.width, size_in_window_coordinates.height); } // For window resize - (void) reshape { - [super reshape]; - [self resizeViewport]; + [super reshape]; + [self resizeViewport]; } // This is the code that actually draws. @@ -889,37 +889,37 @@ A -respondsToSelector: check has been used to provide compatibility with previou // (e.g. No sense drawing when the application is hidden.) - (void) drawRect:(NSRect)the_rect { - if([[NSGraphicsContext currentContext] isDrawingToScreen]) - { - [[self openGLContext] makeCurrentContext]; - theViewer->frame(); - [[self openGLContext] flushBuffer]; - } - else // This is usually the print case - { - [[self openGLContext] makeCurrentContext]; + if([[NSGraphicsContext currentContext] isDrawingToScreen]) + { + [[self openGLContext] makeCurrentContext]; + theViewer->frame(); + [[self openGLContext] flushBuffer]; + } + else // This is usually the print case + { + [[self openGLContext] makeCurrentContext]; - // FIXME: We should be computing a size that fits best to the paper target - NSSize size_in_points = [self bounds].size; - NSSize size_in_window_coordinates = [self convertSize:size_in_points toView:nil]; - NSBitmapImageRep * bitmap_image_rep = [self renderOpenGLSceneToFramebufferAsFormat:GL_RGB viewWidth:size_in_window_coordinates.width viewHeight:size_in_window_coordinates.height]; - - NSImage* ns_image = [self imageFromBitmapImageRep:bitmap_image_rep]; + // FIXME: We should be computing a size that fits best to the paper target + NSSize size_in_points = [self bounds].size; + NSSize size_in_window_coordinates = [self convertSize:size_in_points toView:nil]; + NSBitmapImageRep * bitmap_image_rep = [self renderOpenGLSceneToFramebufferAsFormat:GL_RGB viewWidth:size_in_window_coordinates.width viewHeight:size_in_window_coordinates.height]; + + NSImage* ns_image = [self imageFromBitmapImageRep:bitmap_image_rep]; - if(ns_image) - { - NSSize image_size = [ns_image size]; - [ns_image drawAtPoint:NSMakePoint(0.0, 0.0) - fromRect: NSMakeRect(0.0, 0.0, image_size.width, image_size.height) -// operation: NSCompositeSourceOver - operation: NSCompositeCopy - fraction: 1.0]; - } - else - { - NSLog(@"Image not valid"); - } - } + if(ns_image) + { + NSSize image_size = [ns_image size]; + [ns_image drawAtPoint:NSMakePoint(0.0, 0.0) + fromRect: NSMakeRect(0.0, 0.0, image_size.width, image_size.height) +// operation: NSCompositeSourceOver + operation: NSCompositeCopy + fraction: 1.0]; + } + else + { + NSLog(@"Image not valid"); + } + } } @@ -931,19 +931,19 @@ A -respondsToSelector: check has been used to provide compatibility with previou // Convenience version. Will use the current view's bounds and produce an RGB image with the current clear color. - (NSBitmapImageRep*) renderOpenGLSceneToFramebuffer { - NSSize size_in_points = [self bounds].size; - NSSize size_in_window_coordinates = [self convertSize:size_in_points toView:nil]; - const osg::Vec4& clear_color = theViewer->getCamera()->getClearColor(); + NSSize size_in_points = [self bounds].size; + NSSize size_in_window_coordinates = [self convertSize:size_in_points toView:nil]; + const osg::Vec4& clear_color = theViewer->getCamera()->getClearColor(); - return [self renderOpenGLSceneToFramebufferAsFormat:GL_RGB viewWidth:size_in_window_coordinates.width viewHeight:size_in_window_coordinates.height clearColorRed:clear_color[0] clearColorGreen:clear_color[1] clearColorBlue:clear_color[2] clearColorAlpha:clear_color[3]]; + return [self renderOpenGLSceneToFramebufferAsFormat:GL_RGB viewWidth:size_in_window_coordinates.width viewHeight:size_in_window_coordinates.height clearColorRed:clear_color[0] clearColorGreen:clear_color[1] clearColorBlue:clear_color[2] clearColorAlpha:clear_color[3]]; } // Convenience version. Allows you to specify the view and height and format, but uses the current the current clear color. - (NSBitmapImageRep*) renderOpenGLSceneToFramebufferAsFormat:(int)gl_format viewWidth:(float)view_width viewHeight:(float)view_height { - const osg::Vec4& clear_color = theViewer->getCamera()->getClearColor(); + const osg::Vec4& clear_color = theViewer->getCamera()->getClearColor(); - return [self renderOpenGLSceneToFramebufferAsFormat:gl_format viewWidth:view_width viewHeight:view_height clearColorRed:clear_color[0] clearColorGreen:clear_color[1] clearColorBlue:clear_color[2] clearColorAlpha:clear_color[3]]; + return [self renderOpenGLSceneToFramebufferAsFormat:gl_format viewWidth:view_width viewHeight:view_height clearColorRed:clear_color[0] clearColorGreen:clear_color[1] clearColorBlue:clear_color[2] clearColorAlpha:clear_color[3]]; } // Renders to an offscreen buffer and returns a copy of the data to an NSBitmapImageRep. @@ -951,198 +951,198 @@ A -respondsToSelector: check has been used to provide compatibility with previou // gl_format is only GL_RGB or GLRGBA. - (NSBitmapImageRep*) renderOpenGLSceneToFramebufferAsFormat:(int)gl_format viewWidth:(float)view_width viewHeight:(float)view_height clearColorRed:(float)clear_red clearColorGreen:(float)clear_green clearColorBlue:(float)clear_blue clearColorAlpha:(float)clear_alpha { - // Round values and bring to closest integer. - int viewport_width = (int)(view_width + 0.5f); - int viewport_height = (int)(view_height + 0.5f); - - NSBitmapImageRep* ns_image_rep; - osg::ref_ptr osg_image = new osg::Image; - - if(GL_RGBA == gl_format) - { - // Introduced in 10.4, but gives much better looking results if you utilize transparency - if([NSBitmapImageRep instancesRespondToSelector:@selector(initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:)]) - { - ns_image_rep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL - pixelsWide:viewport_width - pixelsHigh:viewport_height - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSCalibratedRGBColorSpace - bitmapFormat:NSAlphaNonpremultipliedBitmapFormat // 10.4+, gives much better looking results if you utilize transparency - bytesPerRow:osg::Image::computeRowWidthInBytes(viewport_width, GL_RGBA, GL_UNSIGNED_BYTE, 1) - bitsPerPixel:32] - autorelease]; - } - else // fallback for 10.0 to 10.3 - { - ns_image_rep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL - pixelsWide:viewport_width - pixelsHigh:viewport_height - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSCalibratedRGBColorSpace - // bitmapFormat:NSAlphaNonpremultipliedBitmapFormat // 10.4+, gives much better looking results if you utilize transparency - bytesPerRow:osg::Image::computeRowWidthInBytes(viewport_width, GL_RGBA, GL_UNSIGNED_BYTE, 1) - bitsPerPixel:32] - autorelease]; - } - // This is an optimization. Instead of creating data in both an osg::Image and NSBitmapImageRep, - // Allocate just the memory in the NSBitmapImageRep and give the osg::Image a reference to the data. - // I let NSBitmapImageRep control the memory because I think it will be easier to deal with - // memory management in the cases where it must interact with other Cocoa mechanisms like Drag-and-drop - // where the memory persistence is less obvious. Make sure that you don't expect to use the osg::Image - // outside the scope of this function because there is no telling when the data will be removed out - // from under it by Cocoa since osg::Image will not retain. - osg_image->setImage([ns_image_rep pixelsWide], [ns_image_rep pixelsHigh], 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, [ns_image_rep bitmapData], osg::Image::NO_DELETE, 1); - } - else if(GL_RGB == gl_format) - { - ns_image_rep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL - pixelsWide:viewport_width - pixelsHigh:viewport_height - bitsPerSample:8 - samplesPerPixel:3 - hasAlpha:NO - isPlanar:NO - colorSpaceName:NSCalibratedRGBColorSpace - // bitmapFormat:(NSBitmapFormat)0 // 10.4+ - bytesPerRow:osg::Image::computeRowWidthInBytes(viewport_width, GL_RGB, GL_UNSIGNED_BYTE, 1) - bitsPerPixel:24] - autorelease]; + // Round values and bring to closest integer. + int viewport_width = (int)(view_width + 0.5f); + int viewport_height = (int)(view_height + 0.5f); + + NSBitmapImageRep* ns_image_rep; + osg::ref_ptr osg_image = new osg::Image; + + if(GL_RGBA == gl_format) + { + // Introduced in 10.4, but gives much better looking results if you utilize transparency + if([NSBitmapImageRep instancesRespondToSelector:@selector(initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:)]) + { + ns_image_rep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL + pixelsWide:viewport_width + pixelsHigh:viewport_height + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSCalibratedRGBColorSpace + bitmapFormat:NSAlphaNonpremultipliedBitmapFormat // 10.4+, gives much better looking results if you utilize transparency + bytesPerRow:osg::Image::computeRowWidthInBytes(viewport_width, GL_RGBA, GL_UNSIGNED_BYTE, 1) + bitsPerPixel:32] + autorelease]; + } + else // fallback for 10.0 to 10.3 + { + ns_image_rep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL + pixelsWide:viewport_width + pixelsHigh:viewport_height + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSCalibratedRGBColorSpace + // bitmapFormat:NSAlphaNonpremultipliedBitmapFormat // 10.4+, gives much better looking results if you utilize transparency + bytesPerRow:osg::Image::computeRowWidthInBytes(viewport_width, GL_RGBA, GL_UNSIGNED_BYTE, 1) + bitsPerPixel:32] + autorelease]; + } + // This is an optimization. Instead of creating data in both an osg::Image and NSBitmapImageRep, + // Allocate just the memory in the NSBitmapImageRep and give the osg::Image a reference to the data. + // I let NSBitmapImageRep control the memory because I think it will be easier to deal with + // memory management in the cases where it must interact with other Cocoa mechanisms like Drag-and-drop + // where the memory persistence is less obvious. Make sure that you don't expect to use the osg::Image + // outside the scope of this function because there is no telling when the data will be removed out + // from under it by Cocoa since osg::Image will not retain. + osg_image->setImage([ns_image_rep pixelsWide], [ns_image_rep pixelsHigh], 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, [ns_image_rep bitmapData], osg::Image::NO_DELETE, 1); + } + else if(GL_RGB == gl_format) + { + ns_image_rep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL + pixelsWide:viewport_width + pixelsHigh:viewport_height + bitsPerSample:8 + samplesPerPixel:3 + hasAlpha:NO + isPlanar:NO + colorSpaceName:NSCalibratedRGBColorSpace + // bitmapFormat:(NSBitmapFormat)0 // 10.4+ + bytesPerRow:osg::Image::computeRowWidthInBytes(viewport_width, GL_RGB, GL_UNSIGNED_BYTE, 1) + bitsPerPixel:24] + autorelease]; - // This is an optimization. Instead of creating data in both an osg::Image and NSBitmapImageRep, - // Allocate just the memory in the NSBitmapImageRep and give the osg::Image a reference to the data. - // I let NSBitmapImageRep control the memory because I think it will be easier to deal with - // memory management in the cases where it must interact with other Cocoa mechanisms like Drag-and-drop - // where the memory persistence is less obvious. Make sure that you don't expect to use the osg::Image - // outside the scope of this function because there is no telling when the data will be removed out - // from under it by Cocoa since osg::Image will not retain. - osg_image->setImage([ns_image_rep pixelsWide], [ns_image_rep pixelsHigh], 1, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, [ns_image_rep bitmapData], osg::Image::NO_DELETE, 1); - } - else - { - NSLog(@"Sorry, unsupported format in renderOpenGLSceneToFramebufferAsFormat"); - return nil; - } + // This is an optimization. Instead of creating data in both an osg::Image and NSBitmapImageRep, + // Allocate just the memory in the NSBitmapImageRep and give the osg::Image a reference to the data. + // I let NSBitmapImageRep control the memory because I think it will be easier to deal with + // memory management in the cases where it must interact with other Cocoa mechanisms like Drag-and-drop + // where the memory persistence is less obvious. Make sure that you don't expect to use the osg::Image + // outside the scope of this function because there is no telling when the data will be removed out + // from under it by Cocoa since osg::Image will not retain. + osg_image->setImage([ns_image_rep pixelsWide], [ns_image_rep pixelsHigh], 1, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, [ns_image_rep bitmapData], osg::Image::NO_DELETE, 1); + } + else + { + NSLog(@"Sorry, unsupported format in renderOpenGLSceneToFramebufferAsFormat"); + return nil; + } - // Can't find a way to query Viewer for the current values, so recompute current view size. - NSSize original_size_in_points = [self bounds].size; - NSSize original_size_in_window_coordinates = [self convertSize:original_size_in_points toView:nil]; -// theViewer->getEventQueue()->windowResize(0, 0, original_size_in_window_coordinates.width, original_size_in_window_coordinates.height); + // Can't find a way to query Viewer for the current values, so recompute current view size. + NSSize original_size_in_points = [self bounds].size; + NSSize original_size_in_window_coordinates = [self convertSize:original_size_in_points toView:nil]; +// theViewer->getEventQueue()->windowResize(0, 0, original_size_in_window_coordinates.width, original_size_in_window_coordinates.height); - theViewer->getEventQueue()->windowResize(0, 0, viewport_width, viewport_height); - graphicsWindow->resized(0, 0, viewport_width, viewport_height); + theViewer->getEventQueue()->windowResize(0, 0, viewport_width, viewport_height); + graphicsWindow->resized(0, 0, viewport_width, viewport_height); - /* - * I want to use a Framebuffer Object because it seems to be the OpenGL sanctioned way of rendering offscreen. - * Also, I want to try to decouple the image capture from the onscreen rendering. This is potentially useful - * for two reasons: - * 1) You may want to customize the image dimensions to best fit the situation (consider printing to a page to fit) - * 2) You may want to customize the scene for the target (consider special output for a printer, or removed data for a thumbnail) - * Unfortunately, I have hit two problems. - * 1) osg::Camera (which seems to be the way to access Framebuffer Objects in OSG) doesn't seem to capture if it is the root node. - * The workaround is to copy the camera attributes into another camera, and then add a second camera node into the scene. - * I'm hoping OSG will simplify this in the future. - * 2) I may have encountered a bug. Under some circumstances, the offscreen renderbuffer seems to get drawn into the onscreen view - * when using a DragImage for drag-and-drop. I reproduced a non-OSG example, but learned I missed two important FBO calls which trigger gl errors. - * So I'm wondering if OSG made the same mistake. - * But the problem doesn't seem critical. It just looks bad. - */ - //NSLog(@"Before camera glGetError: %s", gluErrorString(glGetError())); - osg::Camera* root_camera = theViewer->getCamera(); + /* + * I want to use a Framebuffer Object because it seems to be the OpenGL sanctioned way of rendering offscreen. + * Also, I want to try to decouple the image capture from the onscreen rendering. This is potentially useful + * for two reasons: + * 1) You may want to customize the image dimensions to best fit the situation (consider printing to a page to fit) + * 2) You may want to customize the scene for the target (consider special output for a printer, or removed data for a thumbnail) + * Unfortunately, I have hit two problems. + * 1) osg::Camera (which seems to be the way to access Framebuffer Objects in OSG) doesn't seem to capture if it is the root node. + * The workaround is to copy the camera attributes into another camera, and then add a second camera node into the scene. + * I'm hoping OSG will simplify this in the future. + * 2) I may have encountered a bug. Under some circumstances, the offscreen renderbuffer seems to get drawn into the onscreen view + * when using a DragImage for drag-and-drop. I reproduced a non-OSG example, but learned I missed two important FBO calls which trigger gl errors. + * So I'm wondering if OSG made the same mistake. + * But the problem doesn't seem critical. It just looks bad. + */ + //NSLog(@"Before camera glGetError: %s", gluErrorString(glGetError())); + osg::Camera* root_camera = theViewer->getCamera(); - // I originally tried the clone() method and the copy construction, but it didn't work right, - // so I manually copy the attributes. - osg::Camera* the_camera = new osg::Camera; + // I originally tried the clone() method and the copy construction, but it didn't work right, + // so I manually copy the attributes. + osg::Camera* the_camera = new osg::Camera; - the_camera->setClearMask(root_camera->getClearMask()); - the_camera->setProjectionMatrix(root_camera->getProjectionMatrix()); - the_camera->setViewMatrix(root_camera->getViewMatrix()); - the_camera->setViewport(root_camera->getViewport()); - the_camera->setClearColor( - osg::Vec4( - clear_red, - clear_green, - clear_blue, - clear_alpha - ) - ); + the_camera->setClearMask(root_camera->getClearMask()); + the_camera->setProjectionMatrix(root_camera->getProjectionMatrix()); + the_camera->setViewMatrix(root_camera->getViewMatrix()); + the_camera->setViewport(root_camera->getViewport()); + the_camera->setClearColor( + osg::Vec4( + clear_red, + clear_green, + clear_blue, + clear_alpha + ) + ); - // This must be ABSOLUTE_RF, and not a copy of the root camera because the transforms are additive. - the_camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); + // This must be ABSOLUTE_RF, and not a copy of the root camera because the transforms are additive. + the_camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); - // We need to insert the new (second) camera into the scene (below the root camera) and attach - // the scene data to the new camera. - osg::ref_ptr root_node = theViewer->getSceneData(); + // We need to insert the new (second) camera into the scene (below the root camera) and attach + // the scene data to the new camera. + osg::ref_ptr root_node = theViewer->getSceneData(); - the_camera->addChild(root_node.get()); - // Don't call (bypass) Viewer's setSceneData, but the underlying SceneView's setSceneData. - // Otherwise, the camera position gets reset to the home position. - theViewer->setSceneData(the_camera); + the_camera->addChild(root_node.get()); + // Don't call (bypass) Viewer's setSceneData, but the underlying SceneView's setSceneData. + // Otherwise, the camera position gets reset to the home position. + theViewer->setSceneData(the_camera); - // set the camera to render before the main camera. - the_camera->setRenderOrder(osg::Camera::PRE_RENDER); + // set the camera to render before the main camera. + the_camera->setRenderOrder(osg::Camera::PRE_RENDER); - // tell the camera to use OpenGL frame buffer object where supported. - the_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); + // tell the camera to use OpenGL frame buffer object where supported. + the_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); - // attach the image so its copied on each frame. - the_camera->attach(osg::Camera::COLOR_BUFFER, osg_image.get()); + // attach the image so its copied on each frame. + the_camera->attach(osg::Camera::COLOR_BUFFER, osg_image.get()); - //NSLog(@"Before frame(), glGetError: %s", gluErrorString(glGetError())); + //NSLog(@"Before frame(), glGetError: %s", gluErrorString(glGetError())); - // Render the scene - theViewer->frame(); + // Render the scene + theViewer->frame(); - // Not sure if I really need this (seems to work without it), and if so, not sure if I need flush or finish - glFlush(); -// glFinish(); + // Not sure if I really need this (seems to work without it), and if so, not sure if I need flush or finish + glFlush(); +// glFinish(); - //NSLog(@"After flush(), glGetError: %s", gluErrorString(glGetError())); + //NSLog(@"After flush(), glGetError: %s", gluErrorString(glGetError())); - // The image is upside-down to Cocoa, so invert it. - osg_image.get()->flipVertical(); + // The image is upside-down to Cocoa, so invert it. + osg_image.get()->flipVertical(); - // Clean up everything I changed -// the_camera->detach(osg::Camera::COLOR_BUFFER); -// the_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER); - // Don't call (bypass) Viewer's setSceneData, but the underlying SceneView's setSceneData. - // Otherwise, the camera position gets reset to the home position. - theViewer->setSceneData(root_node.get()); - theViewer->getEventQueue()->windowResize(0, 0, original_size_in_window_coordinates.width, original_size_in_window_coordinates.height); - graphicsWindow->resized(0, 0, original_size_in_window_coordinates.width, original_size_in_window_coordinates.height); + // Clean up everything I changed +// the_camera->detach(osg::Camera::COLOR_BUFFER); +// the_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER); + // Don't call (bypass) Viewer's setSceneData, but the underlying SceneView's setSceneData. + // Otherwise, the camera position gets reset to the home position. + theViewer->setSceneData(root_node.get()); + theViewer->getEventQueue()->windowResize(0, 0, original_size_in_window_coordinates.width, original_size_in_window_coordinates.height); + graphicsWindow->resized(0, 0, original_size_in_window_coordinates.width, original_size_in_window_coordinates.height); - // Ugh. Because of the bug I mentioned, I'm losing the picture in the display when I print. - [self setNeedsDisplay:YES]; - //NSLog(@"at return, glGetError: %s", gluErrorString(glGetError())); + // Ugh. Because of the bug I mentioned, I'm losing the picture in the display when I print. + [self setNeedsDisplay:YES]; + //NSLog(@"at return, glGetError: %s", gluErrorString(glGetError())); - return ns_image_rep; + return ns_image_rep; } // Convenience method - (NSImage*)imageFromBitmapImageRep:(NSBitmapImageRep*)bitmap_image_rep { - if(nil == bitmap_image_rep) - { - return nil; - } - NSImage* image = [[[NSImage alloc] initWithSize:[bitmap_image_rep size]] autorelease]; - [image addRepresentation:bitmap_image_rep]; - // This doesn't seem to work as I want it to. The image only gets flipped when rendered in a regular view. - // It doesn't flip for the printer view. I must actually invert the pixels. -// [image setFlipped:YES]; - return image; + if(nil == bitmap_image_rep) + { + return nil; + } + NSImage* image = [[[NSImage alloc] initWithSize:[bitmap_image_rep size]] autorelease]; + [image addRepresentation:bitmap_image_rep]; + // This doesn't seem to work as I want it to. The image only gets flipped when rendered in a regular view. + // It doesn't flip for the printer view. I must actually invert the pixels. +// [image setFlipped:YES]; + return image; } @@ -1157,20 +1157,20 @@ A -respondsToSelector: check has been used to provide compatibility with previou //////////////////////////////////////////////////////////////////////// - (unsigned int) draggingEntered:(id )the_sender { - if([the_sender draggingSource] != self) - { - NSPasteboard* paste_board = [the_sender draggingPasteboard]; - // I respond to filename types or URL types - NSArray* supported_types = [NSArray arrayWithObjects:NSFilenamesPboardType, NSURLPboardType, nil]; - // If any of the supported types are being dragged in, activate the copy operation - NSString* first_type = [paste_board availableTypeFromArray:supported_types]; - if(first_type != nil) - { - return NSDragOperationCopy; - } - } - // Means we don't support this type - return NSDragOperationNone; + if([the_sender draggingSource] != self) + { + NSPasteboard* paste_board = [the_sender draggingPasteboard]; + // I respond to filename types or URL types + NSArray* supported_types = [NSArray arrayWithObjects:NSFilenamesPboardType, NSURLPboardType, nil]; + // If any of the supported types are being dragged in, activate the copy operation + NSString* first_type = [paste_board availableTypeFromArray:supported_types]; + if(first_type != nil) + { + return NSDragOperationCopy; + } + } + // Means we don't support this type + return NSDragOperationNone; } // We're not using this method, but here it is as an example. @@ -1180,55 +1180,55 @@ A -respondsToSelector: check has been used to provide compatibility with previou - (BOOL) prepareForDragOperation:(id )the_sender { - return YES; + return YES; } - (BOOL) performDragOperation:(id )the_sender { - NSPasteboard* paste_board = [the_sender draggingPasteboard]; + NSPasteboard* paste_board = [the_sender draggingPasteboard]; if([[paste_board types] containsObject:NSFilenamesPboardType]) - { + { NSArray* file_names = [paste_board propertyListForType:NSFilenamesPboardType]; // int number_of_files = [file_names count]; - // Exercise for the reader: Try loading all files in the array - NSString* single_file = [file_names objectAtIndex:0]; - osg::ref_ptr loaded_model = osgDB::readNodeFile([single_file fileSystemRepresentation]); - if(!loaded_model) - { - NSLog(@"File: %@ failed to load", single_file); - return NO; - } - theViewer->setSceneData(loaded_model.get()); - return YES; + // Exercise for the reader: Try loading all files in the array + NSString* single_file = [file_names objectAtIndex:0]; + osg::ref_ptr loaded_model = osgDB::readNodeFile([single_file fileSystemRepresentation]); + if(!loaded_model) + { + NSLog(@"File: %@ failed to load", single_file); + return NO; + } + theViewer->setSceneData(loaded_model.get()); + return YES; + } + else if([[paste_board types] containsObject:NSURLPboardType]) + { + NSURL* file_url = [NSURL URLFromPasteboard:paste_board]; + // See if the URL is valid file path + if(![file_url isFileURL]) + { + NSLog(@"URL: %@ needs to be a file for readNodeFile()", file_url); + return NO; + } + NSString* file_path = [file_url path]; + osg::ref_ptr loaded_model = osgDB::readNodeFile([file_path fileSystemRepresentation]); + if(!loaded_model) + { + NSLog(@"URL: %@ failed to load, %@", file_url, file_path); + return NO; + } + theViewer->setSceneData(loaded_model.get()); + return YES; } - else if([[paste_board types] containsObject:NSURLPboardType]) - { - NSURL* file_url = [NSURL URLFromPasteboard:paste_board]; - // See if the URL is valid file path - if(![file_url isFileURL]) - { - NSLog(@"URL: %@ needs to be a file for readNodeFile()", file_url); - return NO; - } - NSString* file_path = [file_url path]; - osg::ref_ptr loaded_model = osgDB::readNodeFile([file_path fileSystemRepresentation]); - if(!loaded_model) - { - NSLog(@"URL: %@ failed to load, %@", file_url, file_path); - return NO; - } - theViewer->setSceneData(loaded_model.get()); - return YES; - } return NO; } // This method isn't really needed (I could move setNeedsDisplay up), but is here as an example - (void) concludeDragOperation:(id )the_sender { - [self setNeedsDisplay:YES]; + [self setNeedsDisplay:YES]; } //////////////////////////////////////////////////////////////////////// @@ -1245,7 +1245,7 @@ A -respondsToSelector: check has been used to provide compatibility with previou NSData* image_data = [self contentsAsDataOfType:type]; if(image_data) - { + { NSPasteboard* general_pboard = [NSPasteboard generalPasteboard]; [general_pboard declareTypes:[NSArray arrayWithObjects:type, nil] owner: nil]; [general_pboard setData:image_data forType:type]; @@ -1254,94 +1254,94 @@ A -respondsToSelector: check has been used to provide compatibility with previou - (NSData*) dataWithTIFFOfContentView { - [[self openGLContext] makeCurrentContext]; - NSBitmapImageRep * image = [self renderOpenGLSceneToFramebuffer]; - NSData* data = nil; + [[self openGLContext] makeCurrentContext]; + NSBitmapImageRep * image = [self renderOpenGLSceneToFramebuffer]; + NSData* data = nil; - if(image != nil) - { - data = [image TIFFRepresentation]; - } - return data; + if(image != nil) + { + data = [image TIFFRepresentation]; + } + return data; } /* Returns a data object containing the current contents of the receiving window */ - (NSData*) contentsAsDataOfType:(NSString *)pboardType { - NSData * data = nil; - if ([pboardType isEqualToString: NSTIFFPboardType] == YES) - { - data = [self dataWithTIFFOfContentView]; - } + NSData * data = nil; + if ([pboardType isEqualToString: NSTIFFPboardType] == YES) + { + data = [self dataWithTIFFOfContentView]; + } return data; } - (void) startDragAndDropAsSource:(NSEvent*)the_event { - NSPasteboard* drag_paste_board; - NSImage* the_image; - NSSize the_size; - NSPoint the_point; + NSPasteboard* drag_paste_board; + NSImage* the_image; + NSSize the_size; + NSPoint the_point; - NSSize size_in_points = [self bounds].size; - NSSize size_in_window_coordinates = [self convertSize:size_in_points toView:nil]; + NSSize size_in_points = [self bounds].size; + NSSize size_in_window_coordinates = [self convertSize:size_in_points toView:nil]; - // Create the image that will be dragged - NSString * type = NSTIFFPboardType; + // Create the image that will be dragged + NSString * type = NSTIFFPboardType; - [[self openGLContext] makeCurrentContext]; + [[self openGLContext] makeCurrentContext]; - // I want two images. One to be rendered for the target, and one as the drag-image. - // I want the drag-image to be translucent. - // I think this is where render GL_COLOR_ATTACHMENTn (COLOR_BUFFERn?) would be handy. - // But my hardware only returns 1 for glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, maxbuffers); - // So I won't bother and will just render twice. - NSBitmapImageRep* bitmap_image_rep = [self renderOpenGLSceneToFramebufferAsFormat:GL_RGB viewWidth:size_in_window_coordinates.width viewHeight:size_in_window_coordinates.height]; - NSBitmapImageRep* bitmap_image_rep_transparent_copy = [self renderOpenGLSceneToFramebufferAsFormat:GL_RGBA viewWidth:size_in_window_coordinates.width viewHeight:size_in_window_coordinates.height]; -// NSBitmapImageRep* bitmap_image_rep = [self renderOpenGLSceneToFramebufferAsFormat:GL_RGBA viewWidth:size_in_window_coordinates.width viewHeight:size_in_window_coordinates.height clearColorRed:1.0f clearColorGreen:1.0f clearColorBlue:0.0f clearColorAlpha:0.4f]; + // I want two images. One to be rendered for the target, and one as the drag-image. + // I want the drag-image to be translucent. + // I think this is where render GL_COLOR_ATTACHMENTn (COLOR_BUFFERn?) would be handy. + // But my hardware only returns 1 for glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, maxbuffers); + // So I won't bother and will just render twice. + NSBitmapImageRep* bitmap_image_rep = [self renderOpenGLSceneToFramebufferAsFormat:GL_RGB viewWidth:size_in_window_coordinates.width viewHeight:size_in_window_coordinates.height]; + NSBitmapImageRep* bitmap_image_rep_transparent_copy = [self renderOpenGLSceneToFramebufferAsFormat:GL_RGBA viewWidth:size_in_window_coordinates.width viewHeight:size_in_window_coordinates.height]; +// NSBitmapImageRep* bitmap_image_rep = [self renderOpenGLSceneToFramebufferAsFormat:GL_RGBA viewWidth:size_in_window_coordinates.width viewHeight:size_in_window_coordinates.height clearColorRed:1.0f clearColorGreen:1.0f clearColorBlue:0.0f clearColorAlpha:0.4f]; //NSBitmapImageRep* bitmap_image_rep_transparent_copy = bitmap_image_rep; - // 0x32 is an arbitrary number. Basically, I want something between 0 and 0xFF. - Internal_SetAlpha(bitmap_image_rep_transparent_copy, 0x32); + // 0x32 is an arbitrary number. Basically, I want something between 0 and 0xFF. + Internal_SetAlpha(bitmap_image_rep_transparent_copy, 0x32); - NSData* image_data = [bitmap_image_rep TIFFRepresentation]; + NSData* image_data = [bitmap_image_rep TIFFRepresentation]; if(image_data) - { - - drag_paste_board = [NSPasteboard pasteboardWithName:NSDragPboard]; - // is owner:self or nil? (Hillegass says self) + { + + drag_paste_board = [NSPasteboard pasteboardWithName:NSDragPboard]; + // is owner:self or nil? (Hillegass says self) [drag_paste_board declareTypes: [NSArray arrayWithObjects: type, nil] owner: self]; [drag_paste_board setData:image_data forType: type]; - - // create an image from the data - the_image = [[NSImage alloc] initWithData:[bitmap_image_rep_transparent_copy TIFFRepresentation]]; - - the_point = [self convertPoint:[the_event locationInWindow] fromView:nil]; - the_size = [the_image size]; - - // shift the point to the center of the image - the_point.x = the_point.x - the_size.width/2.0; - the_point.y = the_point.y - the_size.height/2.0; + + // create an image from the data + the_image = [[NSImage alloc] initWithData:[bitmap_image_rep_transparent_copy TIFFRepresentation]]; + + the_point = [self convertPoint:[the_event locationInWindow] fromView:nil]; + the_size = [the_image size]; + + // shift the point to the center of the image + the_point.x = the_point.x - the_size.width/2.0; + the_point.y = the_point.y - the_size.height/2.0; - // start drag - [self dragImage:the_image - at:the_point - offset:NSMakeSize(0,0) - event:the_event - pasteboard:drag_paste_board - source:self - slideBack:YES]; - - [the_image release]; - } - else - { - NSLog(@"Error, failed to create image data"); - } - + // start drag + [self dragImage:the_image + at:the_point + offset:NSMakeSize(0,0) + event:the_event + pasteboard:drag_paste_board + source:self + slideBack:YES]; + + [the_image release]; + } + else + { + NSLog(@"Error, failed to create image data"); + } + } ////////////////////////////////////////////////////////////////////////////////////// @@ -1360,18 +1360,18 @@ A -respondsToSelector: check has been used to provide compatibility with previou // Connect a button to this to stop and reset the position. - (IBAction) resetPosition:(id)the_sender { - // osgGA::MatrixManipulator* camera_manipulator = theViewer->getCameraManipulator(); - // This only resets the position - // camera_manipulator->home(0.0); - - // There is no external API from SimpleViewer that I can see that will stop movement. - // So fake the 'spacebar' to stop things and reset. - // (Changed in Viewer?) - // printf("I'am here"); - - // Reset to start position - theViewer->home(); - [self setNeedsDisplay:YES]; + // osgGA::MatrixManipulator* camera_manipulator = theViewer->getCameraManipulator(); + // This only resets the position + // camera_manipulator->home(0.0); + + // There is no external API from SimpleViewer that I can see that will stop movement. + // So fake the 'spacebar' to stop things and reset. + // (Changed in Viewer?) + // printf("I'am here"); + + // Reset to start position + theViewer->home(); + [self setNeedsDisplay:YES]; } // Connect a NSColorWell to this to change color. @@ -1380,38 +1380,38 @@ A -respondsToSelector: check has been used to provide compatibility with previou // aspect it wouldn't do much good. - (IBAction) takeBackgroundColorFrom:(id)the_sender { - NSColor* the_color = [the_sender color]; + NSColor* the_color = [the_sender color]; - theViewer->getCamera()->setClearColor( - osg::Vec4( - [the_color redComponent], - [the_color greenComponent], - [the_color blueComponent], - [the_color alphaComponent] - ) - ); - [self setNeedsDisplay:YES]; + theViewer->getCamera()->setClearColor( + osg::Vec4( + [the_color redComponent], + [the_color greenComponent], + [the_color blueComponent], + [the_color alphaComponent] + ) + ); + [self setNeedsDisplay:YES]; } - (IBAction) toggleFullScreen:(id)the_sender { - // I'm lazy and rather use the new 10.5 Cocoa Fullscreen API. - // For now, no legacy support for fullscreen. - // One of the cool things about Obj-C is dynamic/late binding. - // We can compile and run this code on versions prior to 10.5. - // At run-time, we check to see if these methods actually exist - // and if they do, we message them. If not, we avoid them. - if([self respondsToSelector:@selector(isInFullScreenMode)]) - { - if([self isInFullScreenMode]) - { - [self exitFullScreenModeWithOptions:nil]; - } - else - { - [self enterFullScreenMode:[NSScreen mainScreen] withOptions:nil]; - } - } + // I'm lazy and rather use the new 10.5 Cocoa Fullscreen API. + // For now, no legacy support for fullscreen. + // One of the cool things about Obj-C is dynamic/late binding. + // We can compile and run this code on versions prior to 10.5. + // At run-time, we check to see if these methods actually exist + // and if they do, we message them. If not, we avoid them. + if([self respondsToSelector:@selector(isInFullScreenMode)]) + { + if([self isInFullScreenMode]) + { + [self exitFullScreenModeWithOptions:nil]; + } + else + { + [self enterFullScreenMode:[NSScreen mainScreen] withOptions:nil]; + } + } } ////////////////////////////////////////////////////////////////////////