//----------------------------------------------------------------------------- // V12 Engine // // Copyright (c) 2001 GarageGames.Com // Portions Copyright (c) 2001 by Sierra Online, Inc. //----------------------------------------------------------------------------- #include "platformMacCarb/platformMacCarb.h" #include "platformMacCarb/platformGL.h" #include "platform/platform.h" #include "platform/platformVideo.h" #include "platformMacCarb/maccarbOGLVideo.h" #include "platform/event.h" #include "console/console.h" #include "platformMacCarb/maccarbConsole.h" #include "platform/platformInput.h" //#include "platformMacCarb/maccarbInput.h" #include "platform/gameInterface.h" #include "math/mRandom.h" #include "core/fileStream.h" #include "game/resource.h" #include "platformMacCarb/maccarbFileio.h" //-------------------------------------- Mac System includes #if defined(TARG_MACCARB) && (TARG_MACCARB>=0x0120) #include #else #include #include #endif #include #if !__APPLE__ #include #endif //-------------------------------------- Resource Includes #include "dgl/gBitmap.h" #include "dgl/gFont.h" extern void createFontInit(); extern void createFontShutdown(); bool gWindowCreated = false; #pragma message("todo: better timing abstraction") #define GetTickCount() GetMilliseconds() MacCarbPlatState platState; MacCarbPlatState::MacCarbPlatState() { hDisplay = NULL; appWindow = NULL; drawable = NULL; quit = false; fmt = NULL; ctx = NULL; // start with something reasonable. desktopBitsPixel = 16; desktopWidth = 1024; desktopHeight = 768; volRefNum = 0; dirID = 0; dStrcpy(appWindowTitle, "V12 Window"); } static bool windowLocked = false; static U8 keyboardState[256]; static bool mouseButtonState[3]; static bool capsLockDown = false; static S32 modifierKeys = 0; static bool windowActive = true; static Point2I lastCursorPos(0,0); static Point2I windowSize; static bool sgDoubleByteEnabled = false; static const char *getKeyName(S32 vkCode); #define TICKS_IN_FRONT 0L #define TICKS_IN_BACK 60L static bool gBackgrounded = false; static long gSleepTicks = TICKS_IN_FRONT; //-------------------------------------- static const char *getMessageName(S32 msg) { switch(msg) { // case WM_KEYDOWN: // return "WM_KEYDOWN"; // case WM_KEYUP: // return "WM_KEYUP"; // case WM_SYSKEYUP: // return "WM_SYSKEYUP"; // case WM_SYSKEYDOWN: // return "WM_SYSKEYDOWN"; default: return "Unknown!!"; } } void Platform::AlertOK(const char *windowTitle, const char *message) { S16 hit; Str255 title, desc; str2p(windowTitle, title); str2p(message, desc); Input::deactivate(); StandardAlert(0, title, desc, NULL, &hit); } bool Platform::AlertOKCancel(const char *windowTitle, const char *message) { S16 hit; AlertStdAlertParamRec param; Str255 title, desc; str2p(windowTitle, title); str2p(message, desc); param.movable = false; param.helpButton = false; param.filterProc = NULL; param.defaultText = (StringPtr)kAlertDefaultOKText; param.cancelText = (StringPtr)kAlertDefaultCancelText; param.otherText = NULL; param.defaultButton = kAlertStdAlertOKButton; param.cancelButton = kAlertStdAlertCancelButton; param.position = kWindowDefaultPosition; StandardAlert(0, title, desc, ¶m, &hit); return (hit==kAlertStdAlertOKButton); } bool Platform::AlertRetry(const char *windowTitle, const char *message) { S16 hit; AlertStdAlertParamRec param; Str255 title, desc; Str255 retryStr; str2p(windowTitle, title); str2p(message, desc); str2p("Retry", retryStr); param.movable = false; param.helpButton = false; param.filterProc = NULL; param.defaultText = retryStr; param.cancelText = (StringPtr)kAlertDefaultCancelText; param.otherText = NULL; param.defaultButton = kAlertStdAlertOKButton; param.cancelButton = kAlertStdAlertCancelButton; param.position = kWindowDefaultPosition; StandardAlert(0, title, desc, ¶m, &hit); return (hit==kAlertStdAlertOKButton); } //-------------------------------------- static void InitInput() { dMemset( keyboardState, 0, 256 ); dMemset( mouseButtonState, 0, sizeof( mouseButtonState ) ); } /* extern Point MTemp : 0x828; // RawMouse and MTemp both contain the current absolute mouse position extern Point RawMouse : 0x82C; extern Rect CrsrPin : 0x834; extern Byte CrsrNew : 0x8CE; // CrsrNew is a flag that tells the system when the mouse has changed extern Byte CrsrCouple : 0x8CF; // CrsrCouple is what CrsrNew should be set to when the mouse has changed */ static Point& ClientToScreen( WindowPtr wnd, Point pt ) { static Point screen; screen = pt; GrafPtr savePort; GetPort( &savePort ); SetPortWindowPort(platState.appWindow); LocalToGlobal( &screen ); SetPort( savePort ); return screen; } void GetWindowRect( WindowPtr wnd, RectI *pRect ) { // note - I should probably add a check for title bar, and borders to simulate Windows completely. if ( pRect && wnd ) { GrafPtr port; Rect r; GetPort( &port ); SetPortWindowPort(wnd); GetWindowPortBounds(wnd, &r); SetPort( port ); pRect->point.x = r.left; pRect->point.y = r.top; pRect->extent.x = r.right - r.left; pRect->extent.y = r.bottom - r.top; } } static void GetMousePos(Point *pt) { GrafPtr savePort; GetPort( &savePort ); SetPortWindowPort( platState.appWindow ); GetMouse(pt); SetPort( savePort ); } /* static void SetCursorPos(const Point2I &pos) { Point pt; Rect deviceRect = (*platState.hDisplay)->gdRect; // window to screen space //RectI r; //GetWindowRect(platState.appWindow, &r); pt.h = pos.x; pt.v = pos.y; pt = ClientToScreen(platState.appWindow, pt); // display to desktop ? //pt.h = deviceRect.left + pos.x; //pt.v = deviceRect.top + pos.y; MTemp = RawMouse = pt; CrsrNew = CrsrCouple; } //-------------------------------------- static void setMouseClipping() { // ClipCursor(NULL); if(windowActive) { // ShowCursor(false); if(windowLocked) { // RECT r; // GetWindowRect(winState.appWindow, &r); // ClipCursor(&r); // RectI r; GetWindowRect(platState.appWindow, &r); //r.point += r.extent / 2; r.extent /= 2; //S32 centerX = (r.right + r.left) >> 1; //S32 centerY = (r.bottom + r.top) >> 1; SetCursorPos(r.extent); } } // else // ShowCursor(true); } */ //-------------------------------------- void Platform::enableKeyboardTranslation(void) { } //-------------------------------------- void Platform::disableKeyboardTranslation(void) { } //-------------------------------------- void Platform::setWindowLocked(bool locked) { windowLocked = locked; // setMouseClipping(); } //-------------------------------------- static bool HandleUpdate(WindowPtr w) { if (w && w == platState.appWindow) { BeginUpdate(w); Game->refreshWindow(); EndUpdate(w); return(true); } return(false); } //-------------------------------------- static void HandleActivate(WindowPtr w, bool winActive, bool appActive) { if (w && w==platState.appWindow) { if (appActive) { Video::reactivate(); /* ShowCursor(false); if ( Video::isFullScreen() ) hideTheTaskbar(); */ } else { Video::deactivate(); // restoreTheTaskbar(); } if (winActive) { Input::activate(); } else { #pragma message("need to release input state on deactivate") // if any input captured -- release all input states so we don't errantly keep them locked... Input::deactivate(); } HandleUpdate(w); } } //-------------------------------------- //static void processKeyMessage(UINT message, WPARAM wParam, LPARAM lParam) //{ // S32 nVirtkey = wParam; // S32 scanCode = (lParam >> 16) & 0xff; // bool extended = (lParam >> 24) & 1; // bool repeat = (lParam >> 30) & 1; // bool make = (message == WM_KEYDOWN || message == WM_SYSKEYDOWN); // // S32 newVirtKey = nVirtkey; // switch(nVirtkey) // { // case KEY_MENU: // if(extended) // newVirtKey = KEY_RMENU; // else // newVirtKey = KEY_LMENU; // break; // case KEY_CONTROL: // if(extended) // newVirtKey = KEY_RCONTROL; // else // newVirtKey = KEY_LCONTROL; // break; // case KEY_SHIFT: // if(scanCode == 54) // newVirtKey = KEY_RSHIFT; // else // newVirtKey = KEY_LSHIFT; // break; // } // // S32 modKey = modifierKeys; // // if(make) // { // switch (newVirtKey) // { // case KEY_LSHIFT: modifierKeys |= SI_LSHIFT; modKey = 0; break; // case KEY_RSHIFT: modifierKeys |= SI_RSHIFT; modKey = 0; break; // case KEY_LCONTROL: modifierKeys |= SI_LCTRL; modKey = 0; break; // case KEY_RCONTROL: modifierKeys |= SI_RCTRL; modKey = 0; break; // case KEY_LMENU: modifierKeys |= SI_LALT; modKey = 0; break; // case KEY_RMENU: modifierKeys |= SI_RALT; modKey = 0; break; // } // if(nVirtkey == VK_CAPITAL) // { // capsLockDown = !capsLockDown; // if(capsLockDown) // keyboardState[nVirtkey] |= 0x01; // else // keyboardState[nVirtkey] &= 0xFE; // } // keyboardState[nVirtkey] |= 0x80; // } // else // { // switch (newVirtKey) // { // case KEY_LSHIFT: modifierKeys &= ~SI_LSHIFT; modKey = 0; break; // case KEY_RSHIFT: modifierKeys &= ~SI_RSHIFT; modKey = 0; break; // case KEY_LCONTROL: modifierKeys &= ~SI_LCTRL; modKey = 0; break; // case KEY_RCONTROL: modifierKeys &= ~SI_RCTRL; modKey = 0; break; // case KEY_LMENU: modifierKeys &= ~SI_LALT; modKey = 0; break; // case KEY_RMENU: modifierKeys &= ~SI_RALT; modKey = 0; break; // } // keyboardState[nVirtkey] &= 0x7f; // } // // WORD ascii = 0; // S32 res = ToAscii(nVirtkey, (lParam >> 16) & 0xFF, keyboardState, &ascii, 0); // if(res < 1) // ascii = 0; // // InputEvent event; // // event.deviceInst = 0; // event.deviceType = KeyboardDeviceType; // event.objType = SI_KEY; // event.objInst = newVirtKey; // event.action = make ? (repeat ? SI_REPEAT : SI_MAKE ) : SI_BREAK; // event.modifier = modKey; // event.ascii = ascii; // event.fValue = make ? 1.0 : 0.0; // // // printf("%s - %s (%d) count: %d ext: %s char: %c\n", // // getMessageName(message), getKeyName(nVirtkey), scanCode, // // repeat, extended ? "True" : "False", ascii); // GamePostEvent(event); //} //-------------------------------------- static Point lastPos = {-11,-11}; // something unlikely... static void CheckCursorPos() { static bool reset = true; if (!windowActive || gBackgrounded) //!!!!TBD windowActive/Locked should go false if bg. { reset = true; return; } Point mousePos; GetMousePos(&mousePos); if (!windowLocked) { // since we're in Poll mode, we need to post a mousemove event for the cursor to be updated. MouseMoveEvent event; event.xPos = mousePos.h; // horizontal position of cursor event.yPos = mousePos.v; // vertical position of cursor event.modifier = modifierKeys; Game->postEvent(event); } else { if (reset) reset = false; else if (mousePos.h!=lastPos.h && mousePos.v!=lastPos.v) // mouse moved. { if(mousePos.h != lastPos.h) { InputEvent event; event.deviceInst = 0; event.deviceType = MouseDeviceType; event.objType = SI_XAXIS; event.objInst = 0; event.action = SI_MOVE; event.modifier = modifierKeys; event.ascii = 0; event.fValue = F32(mousePos.h - lastPos.h); Game->postEvent(event); // Con::printf( "EVENT: Mouse move (%.1f, 0.0).\n", event.fValue ); } if(mousePos.v != lastPos.v) { InputEvent event; event.deviceInst = 0; event.deviceType = MouseDeviceType; event.objType = SI_YAXIS; event.objInst = 0; event.action = SI_MOVE; event.modifier = modifierKeys; event.ascii = 0; event.fValue = F32(mousePos.v - lastPos.v); Game->postEvent(event); // Con::printf( "EVENT: Mouse move (0.0, %.1f).\n", event.fValue ); } } lastPos = mousePos; // copy over last position. } } //-------------------------------------- //static void mouseButtonEvent(S32 action, S32 objInst) //{ // action, objInst; // CheckCursorPos(); // if(!windowLocked) // { // if(action == SI_MAKE) // SetCapture(winState.appWindow); // else // ReleaseCapture(); // } // // InputEvent event; // // event.deviceInst = 0; // event.deviceType = MouseDeviceType; // event.objType = SI_BUTTON; // event.objInst = objInst; // event.action = action; // event.modifier = modifierKeys; // event.ascii = 0; // event.fValue = action == SI_MAKE ? 1.0 : 0.0; // // Game->postEvent(event); //} #define WINDOW_RESTRICT_EVENTS 0 static void ProcessKeyboard( EventRecord &msg ) { #if WINDOW_RESTRICT_EVENTS WindowPtr which; FindWindow( msg.where, &which ); if (which != platState.appWindow) return; #endif #if ALLOW_MENU_PROCESSING unsigned char c; c = (msg.message & charCodeMask); if ((msg.modifiers & cmdKey) != 0) { AdjustMenus(); HandleMenuKey(c, msg.modifiers); } #endif InputEvent event; event.deviceInst = 0; event.deviceType = KeyboardDeviceType; event.objType = SI_KEY; event.objInst = TranslateOSKeyCode( (msg.message & keyCodeMask) >> 8 ); event.ascii = msg.message & charCodeMask; switch(msg.what) { case keyDown: event.action = SI_MAKE; event.fValue = 1.0f; //Con::printf("keyDN ( %02x )", (msg.message & keyCodeMask) >> 8); break; case autoKey: event.action = SI_REPEAT; event.fValue = 1.0f; break; case keyUp: event.action = SI_BREAK; event.fValue = 0.0f; //Con::printf("keyUP ( %02x )", (msg.message & keyCodeMask) >> 8); break; } event.modifier = 0; if (msg.modifiers & shiftKey) event.modifier |= SI_LSHIFT; if (msg.modifiers & rightShiftKey) event.modifier |= SI_RSHIFT; if (msg.modifiers & cmdKey) event.modifier |= SI_LALT; if (msg.modifiers & optionKey) event.modifier |= SI_MAC_LOPT; if (msg.modifiers & rightOptionKey) event.modifier |= SI_MAC_ROPT; if (msg.modifiers & controlKey) event.modifier |= SI_LCTRL; if (msg.modifiers & rightControlKey) event.modifier |= SI_RCTRL; // handle command-Q exit if ((event.objInst == KEY_Q) && (msg.modifiers & cmdKey)) Platform::postQuitMessage(0); Game->postEvent(event); } static void ProcessMouse( EventRecord &msg ) { WindowPtr which; U16 where = FindWindow( msg.where, &which ); if (which != platState.appWindow) return; SelectWindow(platState.appWindow); // handle a little window maintence switch (where) { #if !TARGET_API_MAC_CARBON case inSysWindow: SystemClick ( &msg, platState.appWindow ); return; #endif case inDrag: { RgnHandle rgn = GetGrayRgn(); Rect r; GetRegionBounds(rgn, &r); SetPortWindowPort(platState.appWindow); DragWindow(platState.appWindow, msg.where, &r); if (platState.ctx) aglUpdateContext(platState.ctx); HandleUpdate(platState.appWindow); return; } case inContent: // will handle below. break; default: return; } InputEvent event; event.deviceInst = 0; event.deviceType = MouseDeviceType; event.objType = SI_BUTTON; event.objInst = KEY_BUTTON0; // always button 0 for now event.modifier = 0; event.ascii = 0; if (msg.what == mouseDown) { event.action = SI_MAKE; event.fValue = 1.0; } else { event.action = SI_BREAK; event.fValue = 1.0; } Game->postEvent(event); } //-------------------------------------- static bool ProcessMessages() { if (platState.quit) return false; SetEventMask(everyEvent); EventRecord msg; bool done = false; while(!done && WaitNextEvent(everyEvent, &msg, 0, NULL)) { bool handled = (gConsole && gConsole->handleEvent(&msg)); if (!handled) switch(msg.what) { case nullEvent: //AdjustCursor(msg.where, ((msg.modifiers&optionKey)!=0), cursorRgn); done = true; break; case keyDown: // case autoKey: case keyUp: ProcessKeyboard(msg); break; case mouseDown: case mouseUp: ProcessMouse(msg); break; case activateEvt: HandleActivate((WindowPtr)(msg.message), (msg.modifiers & activeFlag) != 0, !gBackgrounded); break; case updateEvt: HandleUpdate((WindowPtr)(msg.message)); break; case osEvt: { switch ((unsigned long)(msg.message >> 24)) // osEvt msg is in the high byte. { case mouseMovedMessage: // this is it moved from the region passed to WNE { // AdjustCursor(msg.where, ((msg.modifiers&optionKey)!=0), cursorRgn); break; } case suspendResumeMessage: { Cursor arrow; GetQDGlobalsArrow(&arrow); gBackgrounded = (msg.message & resumeFlag) == 0; HandleActivate(platState.appWindow, !gBackgrounded, !gBackgrounded); gSleepTicks = (gBackgrounded?TICKS_IN_BACK:TICKS_IN_FRONT); if (gBackgrounded) /* just suspended */ SetCursor(&arrow); else /* just resumed */ SetCursor(&arrow); break; }/* end case suspend/resume evt */ } break; } case kHighLevelEvent: { // the type of message is stored in the where Point... so cast it U32 hlWhat = *((U32*)(&msg.where)); if ( hlWhat == kAEQuitApplication ) { Platform::postQuitMessage(0); return false; } else AEProcessAppleEvent(&msg); break; } default: // Con::printf("%d %08x", msg.what, msg.what); break; } } return true; } //-------------------------------------- void Platform::process() { extern bool gMouseActive; if (!Input::isActive() || !gMouseActive) CheckCursorPos(); gConsole->process(); if(!ProcessMessages()) { // generate a quit event Event quitEvent; quitEvent.type = QuitEventType; Game->postEvent(quitEvent); } /* // if there's no window, we sleep 1, otherwise we sleep 0 if(!Game->isJournalReading()) Sleep(gWindowCreated ? 0 : 1); // give others some process time if necessary... HWND window = GetForegroundWindow(); if (window && gWindowCreated) { // check to see if we are in the foreground or not // if not Sleep for 100ms or until a Win32 message/input is recieved DWORD foregroundProcessId; GetWindowThreadProcessId(window, &foregroundProcessId); if (foregroundProcessId != winState.processId) MsgWaitForMultipleObjects(0, NULL, false, 100, QS_ALLINPUT); } */ Input::process(); } extern U32 calculateCRC(void * buffer, S32 len, U32 crcVal ); #if defined(DEBUG) || defined(INTERNAL_RELEASE) static U32 stubCRC = 0; #else static U32 stubCRC = 0xEA63F56C; #endif //-------------------------------------- /* static void InitWindowClass() { WNDCLASS wc; dMemset(&wc, 0, sizeof(wc)); wc.style = CS_OWNDC; wc.lpfnWndProc = WindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = winState.appInstance; wc.hIcon = LoadIcon(winState.appInstance, MAKEINTRESOURCE(IDI_ICON2)); wc.hCursor = LoadCursor (NULL,IDC_ARROW); wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName = windowClassName; RegisterClass( &wc ); // Curtain window class: wc.lpfnWndProc = DefWindowProc; wc.hCursor = NULL; wc.hbrBackground = (HBRUSH) GetStockObject(GRAY_BRUSH); wc.lpszClassName = "Curtain"; RegisterClass( &wc ); } */ //-------------------------------------- static void GetDesktopState() { platState.hDisplay = GetMainDevice(); platState.desktopBitsPixel = (*(*(platState.hDisplay))->gdPMap)->pixelSize; Rect r = (*(platState.hDisplay))->gdRect; platState.desktopWidth = r.right - r.left; platState.desktopHeight = r.bottom - r.top; } //-------------------------------------- WindowPtr CreateOpenGLWindow( U32 width, U32 height, bool fullScreen ) { int offset = 144; // some nice starting offset. // for now just get first screen device. //!!!!!tbd - this needs to be in sync with what setupgl picks!!!! platState.hDisplay = GetMainDevice(); // this rect should really be based off the device coords... !!!!!TBD Rect rect; SetRect( &rect, offset+48, offset, width+offset+48, height+offset); CWindowPtr w; w = NewCWindow(NULL, &rect, // bounding rect str2p(platState.appWindowTitle), // window title false, // is visible fullScreen?kWindowPlainDialogProc:kWindowDocumentProc, // window type (WindowPtr) -1L, // top most window false, // has a close box 0L); // reference constant if (w != NULL) ShowWindow(w); return(w); } //-------------------------------------- WindowPtr CreateCurtain( U32 width, U32 height ) { WindowPtr w=NULL; /* w = CreateWindow( "Curtain", "", ( WS_POPUP | WS_MAXIMIZE | WS_VISIBLE ), 0, 0, width, height, NULL, NULL, winState.appInstance, NULL ); */ return(w); } /* //-------------------------------------- void CreatePixelFormat( PIXELFORMATDESCRIPTOR *pPFD, S32 colorBits, S32 depthBits, S32 stencilBits, bool stereo ) { PIXELFORMATDESCRIPTOR src = { sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd 1, // version number PFD_DRAW_TO_WINDOW | // support window PFD_SUPPORT_OPENGL | // support OpenGL PFD_DOUBLEBUFFER, // double buffered PFD_TYPE_RGBA, // RGBA type colorBits, // color depth 0, 0, 0, 0, 0, 0, // color bits ignored 0, // no alpha buffer 0, // shift bit ignored 0, // no accumulation buffer 0, 0, 0, 0, // accum bits ignored depthBits, // z-buffer stencilBits, // stencil buffer 0, // no auxiliary buffer PFD_MAIN_PLANE, // main layer 0, // reserved 0, 0, 0 // layer masks ignored }; if ( stereo ) { //ri.Printf( PRINT_ALL, "...attempting to use stereo\n" ); src.dwFlags |= PFD_STEREO; //glConfig.stereoEnabled = true; } else { //glConfig.stereoEnabled = qfalse; } *pPFD = src; } //-------------------------------------- enum { MAX_PFDS = 256 }; S32 ChooseBestPixelFormat(HDC hDC, PIXELFORMATDESCRIPTOR *pPFD) { PIXELFORMATDESCRIPTOR pfds[MAX_PFDS+1]; S32 i; S32 bestMatch = 0; S32 maxPFD = qwglDescribePixelFormat(hDC, 1, sizeof(PIXELFORMATDESCRIPTOR), &pfds[0]); if(maxPFD > MAX_PFDS) maxPFD = MAX_PFDS; bool accelerated = false; for(i = 1; i <= maxPFD; i++) { qwglDescribePixelFormat(hDC, i, sizeof(PIXELFORMATDESCRIPTOR), &pfds[i]); // make sure this has hardware acceleration: if ( ( pfds[i].dwFlags & PFD_GENERIC_FORMAT ) != 0 ) continue; // verify pixel type if ( pfds[i].iPixelType != PFD_TYPE_RGBA ) continue; // verify proper flags if ( ( ( pfds[i].dwFlags & pPFD->dwFlags ) & pPFD->dwFlags ) != pPFD->dwFlags ) continue; accelerated = !(pfds[i].dwFlags & PFD_GENERIC_FORMAT); // // selection criteria (in order of priority): // // PFD_STEREO // colorBits // depthBits // stencilBits // if ( bestMatch ) { // check stereo if ( ( pfds[i].dwFlags & PFD_STEREO ) && ( !( pfds[bestMatch].dwFlags & PFD_STEREO ) ) && ( pPFD->dwFlags & PFD_STEREO ) ) { bestMatch = i; continue; } if ( !( pfds[i].dwFlags & PFD_STEREO ) && ( pfds[bestMatch].dwFlags & PFD_STEREO ) && ( pPFD->dwFlags & PFD_STEREO ) ) { bestMatch = i; continue; } // check color if ( pfds[bestMatch].cColorBits != pPFD->cColorBits ) { // prefer perfect match if ( pfds[i].cColorBits == pPFD->cColorBits ) { bestMatch = i; continue; } // otherwise if this PFD has more bits than our best, use it else if ( pfds[i].cColorBits > pfds[bestMatch].cColorBits ) { bestMatch = i; continue; } } // check depth if ( pfds[bestMatch].cDepthBits != pPFD->cDepthBits ) { // prefer perfect match if ( pfds[i].cDepthBits == pPFD->cDepthBits ) { bestMatch = i; continue; } // otherwise if this PFD has more bits than our best, use it else if ( pfds[i].cDepthBits > pfds[bestMatch].cDepthBits ) { bestMatch = i; continue; } } // check stencil if ( pfds[bestMatch].cStencilBits != pPFD->cStencilBits ) { // prefer perfect match if ( pfds[i].cStencilBits == pPFD->cStencilBits ) { bestMatch = i; continue; } // otherwise if this PFD has more bits than our best, use it else if ( ( pfds[i].cStencilBits > pfds[bestMatch].cStencilBits ) && ( pPFD->cStencilBits > 0 ) ) { bestMatch = i; continue; } } } else { bestMatch = i; } } if ( !bestMatch ) return 0; else if ( pfds[bestMatch].dwFlags & PFD_GENERIC_ACCELERATED ) { // MCD } else { // ICD } *pPFD = pfds[bestMatch]; return bestMatch; } */ //-------------------------------------- const Point2I &Platform::getWindowSize() { return windowSize; } //-------------------------------------- void Platform::setWindowSize( U32 newWidth, U32 newHeight ) { windowSize.set( newWidth, newHeight ); } //-------------------------------------- // !!!!!TBD!!!!! what should this do on the Mac. void Platform::minimizeWindow() { } //-------------------------------------- static void InitWindow(const Point2I &initialSize) { windowSize = initialSize; } //-------------------------------------- static void InitOpenGL() { // Just for kicks. Seems a relatively central place to put this... #if !__APPLE__ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); #endif DisplayDevice::init(); // Get the video settings from the prefs: const char* resString = Con::getVariable( "$pref::Video::resolution" ); char* tempBuf = new char[dStrlen( resString ) + 1]; dStrcpy( tempBuf, resString ); char* temp = dStrtok( tempBuf, " x\0" ); U32 width = ( temp ? dAtoi( temp ) : 800 ); temp = dStrtok( NULL, " x\0" ); U32 height = ( temp ? dAtoi( temp ) : 600 ); temp = dStrtok( NULL, "\0" ); U32 bpp = ( temp ? dAtoi( temp ) : 16 ); delete [] tempBuf; bool fullScreen = Con::getBoolVariable( "$pref::Video::fullScreen" ); if ( !Video::setDevice( Con::getVariable( "$pref::Video::displayDevice" ), width, height, bpp, fullScreen ) ) { // Next, try the default OpenGL device: if ( !Video::setDevice( "OpenGL", width, height, bpp, fullScreen ) ) { AssertFatal( false, "Could not find a compatible display device!" ); return; } } } //-------------------------------------- ConsoleFunction( getDesktopResolution, const char*, 1, 1, "getDesktopResolution()" ) { argc; argv; char buffer[256]; dSprintf( buffer, sizeof( buffer ), "%d %d %d", platState.desktopWidth, platState.desktopHeight, platState.desktopBitsPixel ); char* returnString = Con::getReturnBuffer( dStrlen( buffer ) + 1 ); dStrcpy( returnString, buffer ); return( returnString ); } //-------------------------------------- void Platform::init() { // Set the platform variable for the scripts Con::setVariable( "$platform", "maccarb" ); MacConsole::create(); if ( !MacConsole::isEnabled() ) Input::init(); InitInput(); // in case Input setup falls through. GetDesktopState(); // installRedBookDevices(); // not sure why this is here on mac. Video::init(); Video::installDevice( OpenGLDevice::create() ); sgDoubleByteEnabled = true; // !!!!! this right? // sgQueueEvents = true; } //-------------------------------------- void Platform::shutdown() { // sgQueueEvents = false; // if(gMutexHandle) // CloseHandle(gMutexHandle); setWindowLocked( false ); Video::destroy(); Input::destroy(); MacConsole::destroy(); } //-------------------------------------- static U32 lastTimeTick; //-------------------------------------- static S32 run(S32 argc, const char **argv) { createFontInit(); windowSize.set(0,0); lastTimeTick = GetTickCount(); // TribesGame *tmpgame = new TribesGame; int ret = Game->main(argc, argv); createFontShutdown(); return ret; } void Platform::initWindow(const Point2I &initialSize, const char *name) { Con::printf( "Video Init:" ); Video::init(); if ( Video::installDevice( OpenGLDevice::create() ) ) Con::printf( " Accelerated OpenGL display device detected." ); else Con::printf( " Accelerated OpenGL display device not detected." ); Con::printf( "" ); dSprintf(platState.appWindowTitle, sizeof(platState.appWindowTitle), name); InitWindow(initialSize); InitOpenGL(); gWindowCreated = true; } //-------------------------------------- S32 main(S32 argc, const char **argv) { // mac does not support command line arguments // it may be possible to get the comment field from the file // see DesktopManager and DTGetComment #if !TARGET_API_MAC_CARBON InitGraf(&qd.thePort); // init QuickDraw -- 'qd' is a Mac Global InitFonts(); // init the Font Manager InitWindows(); // init the Window Manager InitMenus(); TEInit(); InitDialogs( NULL ); #endif InitCursor(); FlushEvents( everyEvent, 0 ); SetEventMask(everyEvent); // save away home directory info into platState. macGetHomeDirectory(); return run(argc, argv); } //-------------------------------------- void TimeManager::process() { U32 curTime = GetTickCount(); TimeEvent event; event.elapsedTime = curTime - lastTimeTick; if(event.elapsedTime > 5) { lastTimeTick = curTime; Game->postEvent(event); } } /* GLimp_Init GLW_LoadOpenGL QGL_Init(driver); GLW_StartDriverAndSetMode GLW_SetMode ChangeDisplaySettings GLW_CreateWindow GLW_InitDriver GLW_CreatePFD GLW_MakeContext GLW_ChoosePFD DescribePixelFormat SetPixelFormat GLW_InitExtensions WG_CheckHardwareGamma */ //-------------------------------------- #pragma message("todo: implement random") F32 Platform::getRandom() { //return rand() / F32(RAND_MAX); return 0.5; } //-------------------------------------- // Web browser function: //-------------------------------------- bool Platform::openWebBrowser( const char* webAddress ) {//!!!!!!! TBD return(false); }