mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-29 23:22:01 +00:00
635 lines
9.9 KiB
Mathematica
635 lines
9.9 KiB
Mathematica
|
/*
|
||
|
|
||
|
Copyright (C) 2001-2002 A Nourai
|
||
|
Copyright (C) 2006 Jacek Piszczek (Mac OSX port)
|
||
|
|
||
|
This program is free software; you can redistribute it and/or
|
||
|
modify it under the terms of the GNU General Public License
|
||
|
as published by the Free Software Foundation; either version 2
|
||
|
of the License, or (at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
|
||
|
See the included (GNU.txt) GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program; if not, write to the Free Software
|
||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
|
*/
|
||
|
|
||
|
#import <Cocoa/Cocoa.h>
|
||
|
#import <Quartz/Quartz.h>
|
||
|
#include "quakedef.h"
|
||
|
|
||
|
id _p;
|
||
|
extern float mouse_x,mouse_y;
|
||
|
int evcnt = 2;
|
||
|
|
||
|
// Jacek: some keys are bogus, my ibook kb lacks keys and apple's docs lack
|
||
|
// keyCode documentation
|
||
|
|
||
|
unsigned char keyconv[] =
|
||
|
{
|
||
|
'a', /* 0 */
|
||
|
's',
|
||
|
'd',
|
||
|
'f',
|
||
|
'h',
|
||
|
'g',
|
||
|
'z',
|
||
|
'x',
|
||
|
'c',
|
||
|
'v',
|
||
|
'0', /* 10 */
|
||
|
'b',
|
||
|
'q',
|
||
|
'w',
|
||
|
'e',
|
||
|
'r',
|
||
|
'y',
|
||
|
't',
|
||
|
'1',
|
||
|
'2',
|
||
|
'3', /* 20 */
|
||
|
'4',
|
||
|
'6',
|
||
|
'5',
|
||
|
'=',
|
||
|
'9',
|
||
|
'7',
|
||
|
'-',
|
||
|
'8',
|
||
|
'0',
|
||
|
']', /* 30 */
|
||
|
'o',
|
||
|
'u',
|
||
|
'[',
|
||
|
'i',
|
||
|
'p',
|
||
|
K_ENTER,
|
||
|
'l',
|
||
|
'j',
|
||
|
'\'',
|
||
|
'k', /* 40 */
|
||
|
';',
|
||
|
'\\',
|
||
|
',',
|
||
|
'/',
|
||
|
'n',
|
||
|
'm',
|
||
|
'.',
|
||
|
K_TAB,
|
||
|
K_SPACE,
|
||
|
'`', /* 50 */
|
||
|
K_BACKSPACE,
|
||
|
'v',
|
||
|
K_ESCAPE,
|
||
|
'n',
|
||
|
'm',
|
||
|
',',
|
||
|
'.',
|
||
|
'/',
|
||
|
0,
|
||
|
K_KP_DEL, /* 60 */
|
||
|
K_KP_HOME,
|
||
|
K_KP_UPARROW,
|
||
|
K_KP_PGUP,
|
||
|
' ',
|
||
|
K_KP_DEL,
|
||
|
K_TAB,
|
||
|
K_KP_STAR,
|
||
|
K_ENTER,
|
||
|
K_KP_PLUS,
|
||
|
K_DEL, /* 70 */
|
||
|
K_INS,
|
||
|
K_PGUP,
|
||
|
K_PGDN,
|
||
|
K_KP_MINUS,
|
||
|
K_KP_SLASH,
|
||
|
K_KP_ENTER,
|
||
|
0,
|
||
|
K_KP_MINUS,
|
||
|
0,
|
||
|
K_F1, /* 80 */
|
||
|
K_F2,
|
||
|
K_KP_INS,
|
||
|
K_KP_END,
|
||
|
K_KP_DOWNARROW,
|
||
|
K_KP_PGDN,
|
||
|
K_KP_LEFTARROW,
|
||
|
K_KP_5,
|
||
|
K_KP_RIGHTARROW,
|
||
|
K_KP_HOME,
|
||
|
0, /* 90 */
|
||
|
K_KP_UPARROW,
|
||
|
K_KP_PGUP,
|
||
|
0,
|
||
|
K_KP_PLUS,
|
||
|
0,
|
||
|
K_LSHIFT,
|
||
|
K_RSHIFT,
|
||
|
0,
|
||
|
K_RCTRL,
|
||
|
K_ALT, /* 100 */
|
||
|
K_ALT,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
K_PAUSE, /* 110 */
|
||
|
K_F12,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
K_HOME,
|
||
|
K_PGUP,
|
||
|
K_DEL,
|
||
|
0,
|
||
|
K_END,
|
||
|
0, /* 120 */
|
||
|
K_PGDN,
|
||
|
0,
|
||
|
K_LEFTARROW,
|
||
|
K_RIGHTARROW,
|
||
|
K_DOWNARROW,
|
||
|
K_UPARROW,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0, /* 130 */
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0, /* 140 */
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0, /* 150 */
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0, /* 160 */
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0, /* 170 */
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0, /* 180 */
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0, /* 190 */
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0, /* 200 */
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0, /* 210 */
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0, /* 220 */
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0, /* 230 */
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0, /* 240 */
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0, /* 250 */
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0
|
||
|
};
|
||
|
|
||
|
// validate the depth
|
||
|
int checkDepth(int d)
|
||
|
{
|
||
|
if (d == 24)
|
||
|
d = 32;
|
||
|
if (d != 15 && d != 16 && d != 32)
|
||
|
d = 32;
|
||
|
|
||
|
return d;
|
||
|
}
|
||
|
|
||
|
@interface FTEApplication : NSApplication
|
||
|
{
|
||
|
NSOpenGLContext *_openGLContext;
|
||
|
NSTimer *_timer;
|
||
|
double time, oldtime, newtime;
|
||
|
unsigned int oldmflags;
|
||
|
CFDictionaryRef olddmode;
|
||
|
}
|
||
|
- (void)initDisplayWidth:(int)width height:(int)height depth:(int)depth;
|
||
|
- (void)flushBuffer;
|
||
|
- (void)runLoop:(NSTimer *)timer;
|
||
|
@end
|
||
|
|
||
|
@implementation FTEApplication
|
||
|
|
||
|
- (id)init
|
||
|
{
|
||
|
if((self = [super init]))
|
||
|
[self setDelegate:self];
|
||
|
|
||
|
oldmflags = 0;
|
||
|
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
- (void)initDisplayWidth:(int)width height:(int)height depth:(int)depth;
|
||
|
{
|
||
|
long value = 1;
|
||
|
NSOpenGLPixelFormat* format;
|
||
|
NSOpenGLPixelFormatAttribute attributes[] = {
|
||
|
NSOpenGLPFAFullScreen,
|
||
|
NSOpenGLPFAScreenMask,
|
||
|
CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),
|
||
|
NSOpenGLPFANoRecovery,
|
||
|
NSOpenGLPFADoubleBuffer,
|
||
|
NSOpenGLPFAAccelerated,
|
||
|
NSOpenGLPFADepthSize, checkDepth(depth),
|
||
|
0};
|
||
|
|
||
|
olddmode = CGDisplayCurrentMode(kCGDirectMainDisplay);
|
||
|
|
||
|
// zeros mean we use the default screen! (but with 32bit depth)
|
||
|
if (!((width == 0) && (height == 0) && (depth == 0)))
|
||
|
{
|
||
|
depth = checkDepth(depth);
|
||
|
if (width == 0)
|
||
|
width = CGDisplayPixelsWide(kCGDirectMainDisplay);
|
||
|
if (height == 0)
|
||
|
height = CGDisplayPixelsHigh(kCGDirectMainDisplay);
|
||
|
CFDictionaryRef dmode = CGDisplayBestModeForParameters(
|
||
|
kCGDirectMainDisplay,
|
||
|
checkDepth(depth),
|
||
|
width,
|
||
|
height,
|
||
|
FALSE);
|
||
|
CGDisplaySwitchToMode(kCGDirectMainDisplay,dmode);
|
||
|
}
|
||
|
|
||
|
// get screen size
|
||
|
vid.width = CGDisplayPixelsWide(kCGDirectMainDisplay);
|
||
|
vid.height = CGDisplayPixelsHigh(kCGDirectMainDisplay);
|
||
|
|
||
|
// capture the display!
|
||
|
CGDisplayCapture(kCGDirectMainDisplay);
|
||
|
CGDisplayHideCursor(kCGDirectMainDisplay);
|
||
|
CGAssociateMouseAndMouseCursorPosition(false);
|
||
|
|
||
|
format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
|
||
|
_openGLContext = [[NSOpenGLContext alloc]
|
||
|
initWithFormat:format
|
||
|
shareContext:nil];
|
||
|
[format release];
|
||
|
if(_openGLContext == nil)
|
||
|
{
|
||
|
NSLog(@"Cannot create OpenGL context");
|
||
|
[NSApp terminate:nil];
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
[_openGLContext setFullScreen];
|
||
|
[_openGLContext setValues:&value forParameter:kCGLCPSwapInterval];
|
||
|
|
||
|
[_openGLContext makeCurrentContext];
|
||
|
|
||
|
_timer = [[NSTimer scheduledTimerWithTimeInterval:1.0/250.0
|
||
|
target:self
|
||
|
selector:@selector(runLoop:)
|
||
|
userInfo:nil
|
||
|
repeats:YES]
|
||
|
retain];
|
||
|
|
||
|
[[NSApp mainWindow] setAcceptsMouseMovedEvents:YES];
|
||
|
}
|
||
|
|
||
|
- (void)dealloc
|
||
|
{
|
||
|
CGAssociateMouseAndMouseCursorPosition(true);
|
||
|
CGDisplayRelease(kCGDirectMainDisplay);
|
||
|
CGDisplayRestoreColorSyncSettings();
|
||
|
CGDisplaySwitchToMode(kCGDirectMainDisplay,olddmode);
|
||
|
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay,
|
||
|
CGPointMake(vid.width/2,vid.height/2));
|
||
|
[_openGLContext release];
|
||
|
[_timer invalidate];
|
||
|
[_timer release];
|
||
|
|
||
|
[super dealloc];
|
||
|
}
|
||
|
|
||
|
- (void) sendEvent:(NSEvent*)event
|
||
|
{
|
||
|
if ([event type] == NSKeyDown)
|
||
|
{
|
||
|
Key_Event(keyconv[[event keyCode]],TRUE);
|
||
|
//printf("%d\n",[event keyCode]);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ([event type] == NSKeyUp)
|
||
|
{
|
||
|
Key_Event(keyconv[[event keyCode]],FALSE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ([event type] == NSFlagsChanged)
|
||
|
{
|
||
|
unsigned int mflags = [event modifierFlags];
|
||
|
|
||
|
if ((mflags & NSAlternateKeyMask) ^ (oldmflags & NSAlternateKeyMask))
|
||
|
{
|
||
|
Key_Event(K_ALT,(mflags & NSAlternateKeyMask) ? TRUE : FALSE);
|
||
|
}
|
||
|
|
||
|
if ((mflags & NSControlKeyMask) ^ (oldmflags & NSControlKeyMask))
|
||
|
{
|
||
|
Key_Event(K_LCTRL,(mflags & NSControlKeyMask) ? TRUE : FALSE);
|
||
|
}
|
||
|
|
||
|
if ((mflags & NSShiftKeyMask) ^ (oldmflags & NSShiftKeyMask))
|
||
|
{
|
||
|
Key_Event(K_LSHIFT,(mflags & NSShiftKeyMask) ? TRUE : FALSE);
|
||
|
}
|
||
|
|
||
|
if ((mflags & NSCommandKeyMask) ^ (oldmflags & NSCommandKeyMask))
|
||
|
{
|
||
|
Key_Event(K_LWIN,(mflags & NSCommandKeyMask) ? TRUE : FALSE);
|
||
|
}
|
||
|
|
||
|
if ((mflags & NSAlphaShiftKeyMask) ^ (oldmflags & NSAlphaShiftKeyMask))
|
||
|
{
|
||
|
Key_Event(K_CAPSLOCK,(mflags & NSAlphaShiftKeyMask) ? TRUE : FALSE);
|
||
|
}
|
||
|
|
||
|
oldmflags = mflags;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ([event type] == NSMouseMoved)
|
||
|
{
|
||
|
mouse_x += [event deltaX];
|
||
|
mouse_y += [event deltaY];
|
||
|
|
||
|
// lame hack to avoid mouse ptr moving to the top of the screen since
|
||
|
// a click there causes the mouse to appear and lock the event stream
|
||
|
// Apple sucks :(
|
||
|
// NOTE: it seems this is still needed for 10.3.x!
|
||
|
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay,
|
||
|
CGPointMake(vid.width - 1,vid.height - 1));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ([event type] == NSLeftMouseDragged)
|
||
|
{
|
||
|
mouse_x += [event deltaX];
|
||
|
mouse_y += [event deltaY];
|
||
|
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay,
|
||
|
CGPointMake(vid.width - 1,vid.height - 1));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ([event type] == NSRightMouseDragged)
|
||
|
{
|
||
|
mouse_x += [event deltaX];
|
||
|
mouse_y += [event deltaY];
|
||
|
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay,
|
||
|
CGPointMake(vid.width - 1,vid.height - 1));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ([event type] == NSOtherMouseDragged)
|
||
|
{
|
||
|
mouse_x += [event deltaX];
|
||
|
mouse_y += [event deltaY];
|
||
|
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay,
|
||
|
CGPointMake(vid.width - 1,vid.height - 1));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ([event type] == NSLeftMouseDown)
|
||
|
{
|
||
|
Key_Event(K_MOUSE1,TRUE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ([event type] == NSLeftMouseUp)
|
||
|
{
|
||
|
Key_Event(K_MOUSE1,FALSE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ([event type] == NSRightMouseDown)
|
||
|
{
|
||
|
Key_Event(K_MOUSE2,TRUE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ([event type] == NSRightMouseUp)
|
||
|
{
|
||
|
Key_Event(K_MOUSE2,FALSE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ([event type] == NSOtherMouseDown)
|
||
|
{
|
||
|
Key_Event(K_MOUSE3,TRUE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ([event type] == NSOtherMouseUp)
|
||
|
{
|
||
|
Key_Event(K_MOUSE3,FALSE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ([event type] == NSScrollWheel)
|
||
|
{
|
||
|
Key_Event(([event deltaY] > 0.0) ? K_MWHEELUP : K_MWHEELDOWN,TRUE);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)flushBuffer
|
||
|
{
|
||
|
// synchronise display
|
||
|
[_openGLContext flushBuffer];
|
||
|
}
|
||
|
|
||
|
// called on a timer event
|
||
|
- (void)runLoop:(NSTimer *)timer
|
||
|
{
|
||
|
newtime = Sys_DoubleTime ();
|
||
|
time = newtime - oldtime;
|
||
|
oldtime = newtime;
|
||
|
|
||
|
Host_Frame(time);
|
||
|
}
|
||
|
|
||
|
- (void)run
|
||
|
{
|
||
|
oldtime = Sys_DoubleTime ();
|
||
|
[super run];
|
||
|
}
|
||
|
|
||
|
@end
|
||
|
|
||
|
static FTEApplication *fteglapp;
|
||
|
|
||
|
BOOL initCocoa(rendererstate_t *info)
|
||
|
{
|
||
|
// init the application the hard way since we don't want to run it
|
||
|
// immediately
|
||
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||
|
fteglapp = [FTEApplication sharedApplication];
|
||
|
|
||
|
// store the var for later disposal
|
||
|
_p = pool;
|
||
|
|
||
|
// init the display
|
||
|
[fteglapp initDisplayWidth:info->width height:info->height depth:info->bpp];
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
qboolean glcocoaRunLoop(void)
|
||
|
{
|
||
|
if (!fteglapp)
|
||
|
return false;
|
||
|
// this will initialise the NSTimer and run the app
|
||
|
[NSApp run];
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void killCocoa(void)
|
||
|
{
|
||
|
// terminates FTEApplicaiton
|
||
|
[NSApp terminate:nil];
|
||
|
[_p release];
|
||
|
|
||
|
fteglapp = NULL;
|
||
|
}
|
||
|
|
||
|
void flushCocoa(void)
|
||
|
{
|
||
|
// synchronises display
|
||
|
[NSApp flushBuffer];
|
||
|
}
|
||
|
|
||
|
void cocoaGamma(unsigned short *r,unsigned short *g,unsigned short *b)
|
||
|
{
|
||
|
CGByteValue gammatable[3*256];
|
||
|
int i;
|
||
|
|
||
|
// convert the gamma values
|
||
|
for(i=0;i<256;i++)
|
||
|
{
|
||
|
gammatable[i] = r[i] >> 8;
|
||
|
gammatable[i+256] = g[i] >> 8;
|
||
|
gammatable[i+512] = b[i] >> 8;
|
||
|
}
|
||
|
|
||
|
//... and set them
|
||
|
CGSetDisplayTransferByByteTable(kCGDirectMainDisplay,256,
|
||
|
gammatable,
|
||
|
gammatable + 256,
|
||
|
gammatable + 512);
|
||
|
}
|