CelestiaOpenGLView.m
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:16k
源码类别:

OpenGL

开发平台:

Visual C++

  1. //
  2. //  CelestiaOpenGLView.m
  3. //  celestia
  4. //
  5. //  Created by Bob Ippolito on Tue May 28 2002.
  6. //  Copyright (C) 2007, Celestia Development Team
  7. //
  8. #import "CelestiaOpenGLView.h"
  9. #import "CelestiaAppCore.h"
  10. #import "MacInputWatcher.h"
  11. #import "TextWindowController.h"
  12. #import "Menu_Extensions.h"
  13. #import <OpenGL/gl.h>
  14. #import <OpenGL/glext.h>
  15. #import <OpenGL/CGLTypes.h>
  16. #ifndef ATI_FSAA_LEVEL
  17. #define ATI_FSAA_LEVEL  510
  18. #endif
  19. #define CEL_LEFT_BUTTON 1
  20. #define CEL_MIDDLE_BUTTON 2
  21. #define CEL_RIGHT_BUTTON 4
  22. @implementation CelestiaOpenGLView
  23. - (id) initWithCoder: (NSCoder *) coder
  24. {
  25.     NSOpenGLPixelFormatAttribute attrs[] = 
  26.     {
  27.         NSOpenGLPFADoubleBuffer,
  28.         NSOpenGLPFADepthSize,
  29.         (NSOpenGLPixelFormatAttribute)32,
  30.         nil
  31.     } ;
  32.     NSOpenGLPixelFormat* pixFmt ;
  33.     long swapInterval ;
  34.     self = [super initWithCoder: coder] ;
  35.     if (self)
  36.     {
  37.         pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: attrs];
  38.         if (pixFmt)
  39.         {
  40.             [self setPixelFormat: pixFmt] ;
  41.             [pixFmt release];
  42.             if (0 == CGLEnable([[self openGLContext] CGLContextObj], 313))
  43.             {
  44.                 NSLog(@"Multithreaded OpenGL enabled.");
  45.             }
  46.             else
  47.             {
  48.                 NSLog(@"Multithreaded OpenGL not supported on your system.");
  49.             }
  50.             swapInterval = 1 ;
  51.             [[self openGLContext]
  52.                 setValues: &swapInterval
  53.                 forParameter: NSOpenGLCPSwapInterval ] ;
  54.         }
  55.         else
  56.         {
  57.             [self release];
  58.             return nil;
  59.         }
  60.     }
  61.     return self;
  62. }
  63. - (void)dealloc
  64. {
  65.     [inputWatcher release];
  66.     [textWindow release];
  67.     [super dealloc];
  68. }
  69. - (void)setAASamples: (unsigned int)aaSamples
  70. {
  71.     if (aaSamples > 1)
  72.     {
  73.         const char *glRenderer = (const char *) glGetString(GL_RENDERER);
  74.         if (strstr(glRenderer, "ATI"))
  75.         {
  76.             [[self openGLContext] setValues: (const long *)&aaSamples
  77.                                forParameter: ATI_FSAA_LEVEL];
  78.         }
  79.         else
  80.         {
  81.             NSOpenGLPixelFormat *pixFmt;
  82.             NSOpenGLContext *context;
  83.             NSOpenGLPixelFormatAttribute fsaaAttrs[] =
  84.             {
  85.                 NSOpenGLPFADoubleBuffer,
  86.                 NSOpenGLPFADepthSize,
  87.                 (NSOpenGLPixelFormatAttribute)32,
  88.                 NSOpenGLPFASampleBuffers,
  89.                 (NSOpenGLPixelFormatAttribute)1,
  90.                 NSOpenGLPFASamples,
  91.                 (NSOpenGLPixelFormatAttribute)1,
  92.                 nil
  93.             };
  94.             fsaaAttrs[6] = aaSamples;
  95.             pixFmt =
  96.                 [[NSOpenGLPixelFormat alloc] initWithAttributes: fsaaAttrs];
  97.             if (pixFmt)
  98.             {
  99.                 context = [[NSOpenGLContext alloc] initWithFormat: pixFmt
  100.                                                      shareContext: nil];
  101.                 [pixFmt release];
  102.                 if (context)
  103.                 {
  104.                     // The following silently fails if not supported
  105.                     CGLEnable([context CGLContextObj], 313);
  106.                     long swapInterval = 1;
  107.                     [context setValues: &swapInterval
  108.                           forParameter: NSOpenGLCPSwapInterval];
  109.                     [self setOpenGLContext: context];
  110.                     [context setView: self];
  111.                     [context makeCurrentContext];
  112.                     [context release];
  113.                     glEnable(GL_MULTISAMPLE_ARB);
  114.                     // GL_NICEST enables Quincunx on supported NVIDIA cards,
  115.                     // but smears text.
  116. //                    glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
  117.                 }
  118.             }
  119.         }
  120.     }
  121. }
  122. - (BOOL) isFlipped {return YES;}
  123. - (void) viewDidMoveToWindow
  124. {    
  125.     [[self window] setAcceptsMouseMovedEvents: YES];
  126. }
  127. - (NSMenu *)menuForEvent:(NSEvent *)theEvent
  128. {
  129.     CelestiaSelection* selection;
  130.     NSString* selectionName;
  131.     NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: self];
  132.     NSPoint location2 = [self convertPoint: [theEvent locationInWindow] fromView: nil];
  133.     CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  134.     [appCore charEntered: 8 withModifiers:0];
  135.     [appCore mouseButtonDown:location modifiers:[appCore toCelestiaModifiers: 0 buttons:CEL_LEFT_BUTTON]];
  136.     [appCore mouseButtonUp:location2 modifiers:[appCore toCelestiaModifiers: 0 buttons:CEL_LEFT_BUTTON]];
  137.     int auxItemIndex     = -1;
  138.     int separatorIndex   = -1;
  139.     BOOL insertedAuxItem = NO;
  140.     [[self menu] removePlanetarySystemItem];
  141.     [[self menu] removeAltSurfaceItem];
  142.     [[self menu] removeRefMarkItems];
  143.     separatorIndex = [[self menu] numberOfItems] - 4;
  144.     if (separatorIndex < 0) separatorIndex = 0;
  145.     if ([[[self menu] itemAtIndex: separatorIndex] isSeparatorItem])
  146.         ++separatorIndex;
  147.     if ([[[self menu] itemAtIndex: separatorIndex] isSeparatorItem])
  148.         [[self menu] removeItemAtIndex: separatorIndex];
  149.     selection = [[appCore simulation] selection];
  150.     auxItemIndex   = [[self menu] numberOfItems] - 2;
  151.     if (auxItemIndex < 0) auxItemIndex = 0;
  152.     insertedAuxItem =
  153.         [[self menu] insertRefMarkItemsForSelection: selection
  154.                                             atIndex: auxItemIndex];
  155.     auxItemIndex   = [[self menu] numberOfItems] - 2;
  156.     if (auxItemIndex < 0) auxItemIndex = 0;
  157.     insertedAuxItem =
  158.         [[self menu] insertPlanetarySystemItemForSelection: selection
  159.                                                     target: controller
  160.                                                    atIndex: auxItemIndex]
  161.         || insertedAuxItem;
  162.     auxItemIndex   = [[self menu] numberOfItems] - 2;
  163.     if (auxItemIndex < 0) auxItemIndex = 0;
  164.     insertedAuxItem =
  165.         [[self menu] insertAltSurfaceItemForSelection: selection
  166.                                                target: controller
  167.                                               atIndex: auxItemIndex]
  168.         || insertedAuxItem;
  169.     if (insertedAuxItem)
  170.     {
  171.         separatorIndex = [[self menu] numberOfItems] - 2;
  172.         if (separatorIndex > 0)
  173.         {
  174.             [[self menu] insertItem: [NSMenuItem separatorItem]
  175.                             atIndex: separatorIndex];
  176.         }
  177.     }
  178.     if ([selection body])
  179.     {
  180.         selectionName = [[selection body] name];
  181.     }
  182.     else if ([selection star])
  183.     {
  184.         selectionName = [[selection star] name];
  185.     }
  186.     else
  187.     {
  188.         selectionName = [selection briefName];
  189.     }
  190. /*
  191.     selectionName = [[[appCore simulation] selection] briefName];
  192.     if ([selectionName isEqualToString: @""])
  193.     {
  194.         [appCore mouseButtonDown:location modifiers:[appCore toCelestiaModifiers: 0 buttons:CEL_LEFT_BUTTON]];
  195.         [appCore mouseButtonUp:location2 modifiers:[appCore toCelestiaModifiers: 0 buttons:CEL_LEFT_BUTTON]];
  196.         selection = [[appCore simulation] selection];
  197.         selectionName = [[[appCore simulation] selection] name];
  198.     }
  199. */
  200.     if ([selectionName isEqualToString: @""]) return nil;
  201.     [[[self menu] itemAtIndex: 0] setTitle: selectionName ];
  202.     [[[self menu] itemAtIndex: 0] setEnabled: YES ];
  203. //    [ [self menu] setAutoenablesItems: NO ];
  204.     return [self menu];
  205. }
  206. - (void) textEnterModeChanged
  207. {
  208.     CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  209.     if ([appCore textEnterMode] & 1)
  210.     {
  211.         if (textWindow == nil)
  212.             textWindow = [[TextWindowController alloc] init];
  213.         [textWindow makeActiveWithDelegate: inputWatcher];
  214.     }
  215.     else if (0 == ([appCore textEnterMode] & 1))
  216.     {
  217.         [[textWindow window] orderOut: nil];
  218.         [[self window] makeFirstResponder: self];
  219.     }
  220. }
  221. - (void) keyDown: (NSEvent*)theEvent
  222. {
  223.     CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  224.     if (inputWatcher == nil)
  225.         inputWatcher = [[MacInputWatcher alloc] initWithWatched: self];
  226.     NSString *eventChars = [theEvent characters];
  227.     if (!eventChars || [eventChars length] == 0)
  228.     {
  229.         eventChars = [theEvent charactersIgnoringModifiers];
  230.         if (!eventChars || [eventChars length] == 0)
  231.             return;
  232.     }
  233.     unichar key = [eventChars characterAtIndex: 0];
  234.     int modifiers = [appCore toCelestiaModifiers: [theEvent modifierFlags] buttons: 0];
  235.     if ( key == NSDeleteCharacter )
  236.         key = NSBackspaceCharacter; // delete = backspace
  237.     else if ( key == NSDeleteFunctionKey || key == NSClearLineFunctionKey )
  238.         key = NSDeleteCharacter; // del = delete
  239.     else if ( key == NSBackTabCharacter )
  240.         key = 127;
  241.     if ( (key<128) && ((key < '0') || (key>'9') || !([theEvent modifierFlags] & NSNumericPadKeyMask)) )
  242.         [ appCore charEntered: key
  243.                 withModifiers: modifiers];
  244.     [ appCore keyDown: [appCore toCelestiaKey: theEvent] 
  245.         withModifiers: modifiers  ];
  246. }
  247. - (void) keyUp: (NSEvent*)theEvent
  248. {
  249.     CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  250. //    if ( [[theEvent characters] characterAtIndex: 0] >= 128 )
  251. //        [ appCore keyUp: [appCore toCelestiaKey: theEvent] ];
  252.     [ appCore keyUp: [appCore toCelestiaKey: theEvent] 
  253.             withModifiers: [appCore toCelestiaModifiers: [theEvent modifierFlags] buttons: 0] ];
  254. //    NSLog(@"keyUp: %@",theEvent);
  255. }
  256. - (void) mouseDown: (NSEvent*)theEvent
  257. {
  258.     [ [self window] makeFirstResponder: self ];
  259.      NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
  260.     CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  261.     [appCore mouseButtonDown:location modifiers:[appCore toCelestiaModifiers:[theEvent modifierFlags] buttons:CEL_LEFT_BUTTON]];
  262. }
  263. - (void) mouseUp: (NSEvent*)theEvent
  264. {
  265.     if ( [theEvent modifierFlags] & NSAlternateKeyMask )
  266.     {
  267.         [self otherMouseUp: theEvent];
  268.         return;
  269.     }
  270.     NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
  271.     NSRect bounds = [self bounds];
  272.     if (!NSPointInRect(location, bounds))
  273.     {
  274.         // -ve coords can crash Celestia so clamp to view bounds
  275.         if (location.x < NSMinX(bounds)) location.x = NSMinX(bounds);
  276.         if (location.x > NSMaxX(bounds)) location.x = NSMaxX(bounds);
  277.         if (location.y < NSMinY(bounds)) location.y = NSMinY(bounds);
  278.         if (location.y > NSMaxY(bounds)) location.y = NSMaxY(bounds);
  279.     }
  280.     CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  281.     [appCore mouseButtonUp:location modifiers:[appCore toCelestiaModifiers:[theEvent modifierFlags] buttons:CEL_LEFT_BUTTON]];
  282. }
  283. - (void) mouseDragged: (NSEvent*) theEvent
  284. {
  285.     if ( [theEvent modifierFlags] & NSAlternateKeyMask )
  286.     {
  287.         [self rightMouseDragged: theEvent];
  288.         return;
  289.     }
  290.     CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  291.     [appCore mouseMove:NSMakePoint([theEvent deltaX], [theEvent deltaY]) modifiers:[appCore toCelestiaModifiers:[theEvent modifierFlags] buttons:CEL_LEFT_BUTTON]];
  292. }
  293. - (void) mouseMoved: (NSEvent*)theEvent
  294. {
  295.     CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  296.     NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
  297.     [appCore mouseMove: location];
  298. }
  299. - (void) rightMouseDown: (NSEvent*)theEvent
  300. {
  301.     NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
  302.     CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  303.     [appCore mouseButtonDown:location modifiers:[appCore toCelestiaModifiers:[theEvent modifierFlags] buttons:CEL_RIGHT_BUTTON]];
  304. }
  305. - (void) rightMouseUp: (NSEvent*)theEvent
  306. {
  307.     NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
  308.     CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  309.     [appCore mouseButtonUp:location modifiers:[appCore toCelestiaModifiers:[theEvent modifierFlags] buttons:CEL_RIGHT_BUTTON]];
  310.     if([theEvent clickCount] > 0)
  311.         [super rightMouseDown:theEvent];    //...Force context menu to appear only on clicks (not drags)
  312. }
  313. - (void) rightMouseDragged: (NSEvent*) theEvent
  314. {
  315.     CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  316.     [appCore mouseMove:NSMakePoint([theEvent deltaX], [theEvent deltaY]) modifiers:[appCore toCelestiaModifiers:[theEvent modifierFlags] buttons:CEL_RIGHT_BUTTON]];
  317. }
  318. - (void) otherMouseDown: (NSEvent *) theEvent
  319. {
  320.     NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
  321.     CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  322.     [appCore mouseButtonDown:location modifiers:[appCore toCelestiaModifiers:[theEvent modifierFlags] buttons:CEL_MIDDLE_BUTTON]];
  323. }
  324. - (void) otherMouseUp: (NSEvent *) theEvent
  325. {
  326.     NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
  327.     CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  328.     [appCore mouseButtonUp:location modifiers:[appCore toCelestiaModifiers:[theEvent modifierFlags] buttons:CEL_MIDDLE_BUTTON]];    
  329. }
  330. - (void) otherMouseDragged: (NSEvent *) theEvent
  331. {
  332.     CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  333.     [appCore mouseMove:NSMakePoint([theEvent deltaX], [theEvent deltaY]) modifiers:[appCore toCelestiaModifiers:[theEvent modifierFlags] buttons:CEL_MIDDLE_BUTTON]];
  334. }
  335. - (void) scrollWheel: (NSEvent*)theEvent
  336. {
  337.     CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  338.     [ appCore mouseWheel: [theEvent deltaY]
  339.        modifiers: [appCore toCelestiaModifiers: [theEvent modifierFlags] buttons: 0] ];
  340. }
  341. - (BOOL) acceptsFirstResponder: (NSEvent*)theEvent
  342. {
  343.     return YES;
  344. }
  345. - (BOOL) becomeFirstResponder
  346. {
  347.     return YES;
  348. }
  349. - (BOOL) resignFirstResponder
  350. {
  351.     return YES;
  352. }
  353. - (BOOL) acceptsFirstMouse: (NSEvent*)theEvent
  354. {
  355.     return YES;
  356. }
  357. - (void) drawRect: (NSRect) rect
  358. {
  359.     NSOpenGLContext *oglContext;
  360.     oglContext = [self openGLContext];
  361.     if (oglContext != nil) 
  362.     {
  363.         [controller display];
  364.         [oglContext flushBuffer];
  365.     }
  366. }
  367. - (void) update
  368. {
  369.     [controller setDirty];
  370.     [super update];
  371. }
  372. - (void) writeStringToPasteboard: (NSPasteboard *) pb
  373. {
  374.     NSString *value;
  375.     [pb declareTypes:
  376.         [NSArray arrayWithObject: NSStringPboardType] owner: self];
  377.     CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  378.     value = [appCore currentURL];
  379.     [ pb setString: value forType: NSStringPboardType ];
  380. }
  381. - (BOOL) readStringFromPasteboard: (NSPasteboard *) pb
  382. {
  383.     NSString *value = nil;
  384.     NSString *type = [pb availableTypeFromArray:
  385.         [NSArray arrayWithObjects: NSURLPboardType, NSFilenamesPboardType, NSStringPboardType, nil ]];
  386.     if ( type != nil )
  387.     {
  388.         CelestiaAppCore *appCore = [CelestiaAppCore sharedAppCore];
  389.         value = [ pb stringForType: NSStringPboardType ];
  390.         if (value != nil )
  391.         {
  392.             if ( [value rangeOfString:@"cel:" options: (NSCaseInsensitiveSearch|NSAnchoredSearch) ].location == 0 )
  393.                 [appCore goToUrl: value ];
  394.             else
  395.                 [appCore runScript: value ];
  396.         }
  397.         else
  398.         {
  399.             value = [[NSURL URLWithString: (NSString*) [((NSArray*)[ pb propertyListForType: type ]) objectAtIndex: 0 ]] path];
  400.             [controller runScript: value ];
  401.         
  402.             return NO;
  403.             if (value != nil)
  404.             {
  405.                 value = [ pb stringForType: NSFilenamesPboardType ];
  406.                 if (value != nil )
  407.                 {
  408.                     [controller runScript: value ];
  409.                 }
  410.             }
  411.         }
  412.         return YES;
  413.     }
  414.     return NO;
  415. }
  416. - (unsigned int) draggingEntered: (id <NSDraggingInfo>) sender
  417. {
  418.     NSPasteboard *pb = [sender draggingPasteboard];
  419.     NSString *type = [pb availableTypeFromArray:
  420.         [NSArray arrayWithObjects: NSStringPboardType, NSFilenamesPboardType, nil ]];
  421.     if ( type != nil )
  422.     {
  423.         return NSDragOperationCopy;
  424.     }
  425.     return NSDragOperationNone;
  426. }
  427. - (BOOL) prepareForDragOperation: (id <NSDraggingInfo>) sender
  428. {
  429.     return YES;
  430. }
  431. - (BOOL) performDragOperation: (id <NSDraggingInfo>) sender
  432. {
  433.     NSPasteboard *pb = [sender draggingPasteboard];
  434.     return [ self readStringFromPasteboard: pb ];
  435. }
  436. - (IBAction) paste: (id) sender
  437. {
  438.     NSPasteboard *pb = [NSPasteboard generalPasteboard];
  439.     [ self readStringFromPasteboard: pb ];
  440. }
  441. - (IBAction) copy: (id) sender
  442. {
  443.     NSPasteboard *pb = [NSPasteboard generalPasteboard];
  444.     [ self writeStringToPasteboard: pb ];
  445. }
  446. @end