/* =========================================================================== Doom 3 GPL Source Code Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). Doom 3 Source Code 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 3 of the License, or (at your option) any later version. Doom 3 Source Code 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 GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Doom 3 Source Code. If not, see . In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ #include "../../idlib/precompiled.h" #pragma hdrstop #include "../../sys/win32/rc/guied_resource.h" #include "../../renderer/tr_local.h" #include "GEApp.h" #include "GEViewer.h" rvGEViewer::rvGEViewer ( ) { mInterface = NULL; mPaused = true; mTime = 0; } bool rvGEViewer::Create ( HWND parent ) { WNDCLASSEX wndClass; // Make sure the alpha slider window class is registered memset ( &wndClass, 0, sizeof(wndClass) ); wndClass.cbSize = sizeof(WNDCLASSEX); wndClass.lpszClassName = "GUIED_VIEWER"; wndClass.lpfnWndProc = rvGEViewer::WndProc; wndClass.hInstance = gApp.GetInstance ( ); wndClass.style = CS_OWNDC|CS_BYTEALIGNWINDOW|CS_VREDRAW|CS_HREDRAW; wndClass.hbrBackground = (HBRUSH) (COLOR_3DFACE + 1); RegisterClassEx ( &wndClass ); mWnd = CreateWindowEx ( WS_EX_TOOLWINDOW, "GUIED_VIEWER", "GUI Viewer", WS_SYSMENU|WS_THICKFRAME|WS_CAPTION|WS_POPUP|WS_OVERLAPPED|WS_BORDER|WS_CLIPSIBLINGS|WS_CHILD, CW_USEDEFAULT, CW_USEDEFAULT, SCREEN_WIDTH/2, SCREEN_HEIGHT/2, parent, NULL, gApp.GetInstance(), this ); gApp.GetOptions().GetWindowPlacement ( "viewer", mWnd ); ShowWindow ( mWnd, SW_SHOW ); UpdateWindow ( mWnd ); return true; } void rvGEViewer::Play ( void ) { if ( !mPaused ) { return; } mLastTime = eventLoop->Milliseconds(); mPaused = false; TBBUTTONINFO tbinfo; tbinfo.cbSize = sizeof(TBBUTTONINFO); tbinfo.dwMask = TBIF_COMMAND|TBIF_IMAGE; tbinfo.iImage = 1; tbinfo.idCommand = ID_GUIED_VIEWER_PAUSE; SendMessage ( mToolbar, TB_SETBUTTONINFO, ID_GUIED_VIEWER_PLAY, (LPARAM)&tbinfo ); } void rvGEViewer::Pause ( void ) { if ( mPaused ) { return; } mPaused = true; TBBUTTONINFO tbinfo; tbinfo.cbSize = sizeof(TBBUTTONINFO); tbinfo.dwMask = TBIF_COMMAND|TBIF_IMAGE; tbinfo.iImage = 0; tbinfo.idCommand = ID_GUIED_VIEWER_PLAY; SendMessage ( mToolbar, TB_SETBUTTONINFO, ID_GUIED_VIEWER_PAUSE, (LPARAM)&tbinfo ); } bool rvGEViewer::Destroy ( void ) { gApp.GetOptions().SetWindowPlacement ( "viewer", mWnd ); DestroyWindow ( mWnd ); return true; } bool rvGEViewer::OpenFile ( const char* filename ) { idStr tempfile; idStr ospath; delete mInterface; tempfile = filename; tempfile.StripPath (); tempfile.StripFileExtension ( ); tempfile = va("guis/temp.guied", tempfile.c_str() ); ospath = fileSystem->RelativePathToOSPath ( tempfile, "fs_basepath" ); // Make sure the gui directory exists idStr createDir = ospath; createDir.StripFilename ( ); CreateDirectory ( createDir, NULL ); SetFileAttributes ( ospath, FILE_ATTRIBUTE_NORMAL ); DeleteFile ( ospath ); CopyFile ( filename, ospath, FALSE ); SetFileAttributes ( ospath, FILE_ATTRIBUTE_NORMAL ); mInterface = reinterpret_cast< idUserInterfaceLocal* >( uiManager->FindGui( tempfile, true, true ) ); mInterface->SetStateString( "guied_item_0", "guied 1" ); mInterface->SetStateString( "guied_item_1", "guied 2" ); mInterface->SetStateString( "guied_item_2", "guied 3" ); mTime = 0; mInterface->Activate ( true, mTime ); DeleteFile ( ospath ); Play ( ); return true; } /* ======= MapKey Map from windows to Doom keynums ======= */ static int MapKey (int key) { int result; int modified; bool is_extended; modified = ( key >> 16 ) & 255; if ( modified > 127 ) return 0; if ( key & ( 1 << 24 ) ) { is_extended = true; } else { is_extended = false; } const unsigned char *scanToKey = Sys_GetScanTable(); result = scanToKey[modified]; // common->Printf( "Key: 0x%08x Modified: 0x%02x Extended: %s Result: 0x%02x\n", key, modified, (is_extended?"Y":"N"), result); if ( is_extended ) { switch ( result ) { case K_PAUSE: return K_KP_NUMLOCK; case 0x0D: return K_KP_ENTER; case 0x2F: return K_KP_SLASH; case 0xAF: return K_KP_PLUS; } } else { switch ( result ) { case K_HOME: return K_KP_HOME; case K_UPARROW: return K_KP_UPARROW; case K_PGUP: return K_KP_PGUP; case K_LEFTARROW: return K_KP_LEFTARROW; case K_RIGHTARROW: return K_KP_RIGHTARROW; case K_END: return K_KP_END; case K_DOWNARROW: return K_KP_DOWNARROW; case K_PGDN: return K_KP_PGDN; case K_INS: return K_KP_INS; case K_DEL: return K_KP_DEL; } } return result; } LRESULT CALLBACK rvGEViewer::WndProc ( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { rvGEViewer* viewer = (rvGEViewer*) GetWindowLong ( hwnd, GWL_USERDATA ); switch ( msg ) { case WM_COMMAND: switch ( LOWORD(wParam) ) { case ID_GUIED_VIEWER_PLAY: viewer->Play ( ); break; case ID_GUIED_VIEWER_PAUSE: viewer->Pause ( ); break; } break; case WM_SIZE: { RECT rToolbar; SendMessage ( viewer->mToolbar, TB_AUTOSIZE, 0, 0 ); GetWindowRect ( viewer->mToolbar, &rToolbar ); viewer->mToolbarHeight = rToolbar.bottom - rToolbar.top; break; } case WM_ACTIVATE: common->ActivateTool( LOWORD( wParam ) != WA_INACTIVE ); break; case WM_ERASEBKGND: return TRUE; case WM_PAINT: assert ( viewer ); viewer->HandlePaint ( wParam, lParam ); break; case WM_LBUTTONDOWN: if ( viewer->mInterface ) { sysEvent_t event; bool visuals; ZeroMemory ( &event, sizeof(event) ) ; event.evType = SE_KEY; event.evValue = K_MOUSE1; event.evValue2 = true; viewer->mInterface->HandleEvent ( &event, viewer->mTime, &visuals ); } break; case WM_LBUTTONUP: if ( viewer->mInterface ) { sysEvent_t event; bool visuals; ZeroMemory ( &event, sizeof(event) ) ; event.evType = SE_KEY; event.evValue = K_MOUSE1; event.evValue2 = false; viewer->mInterface->HandleEvent ( &event, viewer->mTime, &visuals ); } break; case WM_KEYDOWN: if ( viewer->mInterface ) { sysEvent_t event; bool visuals; ZeroMemory ( &event, sizeof(event) ) ; event.evType = SE_KEY; event.evValue = MapKey( lParam ); event.evValue2 = true; viewer->mInterface->HandleEvent ( &event, viewer->mTime, &visuals ); } break; case WM_SYSKEYUP: case WM_KEYUP: if ( viewer->mInterface ) { sysEvent_t event; bool visuals; ZeroMemory ( &event, sizeof(event) ) ; event.evType = SE_KEY; event.evValue = MapKey( lParam ); event.evValue2 = false; viewer->mInterface->HandleEvent ( &event, viewer->mTime, &visuals ); } break; case WM_CHAR: if ( wParam == VK_ESCAPE ) { SendMessage ( hwnd, WM_CLOSE, 0, 0 ); break; } if ( viewer->mInterface ) { sysEvent_t event; bool visuals; ZeroMemory ( &event, sizeof(event) ) ; event.evType = SE_CHAR; event.evValue = wParam; event.evValue2 = false; viewer->mInterface->HandleEvent ( &event, viewer->mTime, &visuals ); } break; case WM_MOUSEMOVE: if ( viewer->mInterface ) { float x = (float)(LOWORD(lParam)) / (float)viewer->mWindowWidth * SCREEN_WIDTH; float y = (float)(HIWORD(lParam)) / (float)(viewer->mWindowHeight - viewer->mToolbarHeight) * SCREEN_HEIGHT; sysEvent_t event; bool visuals; ZeroMemory ( &event, sizeof(event) ) ; event.evType = SE_MOUSE; event.evValue = (int)x - viewer->mInterface->CursorX(); event.evValue2 = (int)y - viewer->mInterface->CursorY(); viewer->mInterface->HandleEvent ( &event, viewer->mTime, &visuals ); } break; case WM_CLOSE: viewer->mInterface = NULL; gApp.CloseViewer ( ); return 0; case WM_CREATE: { CREATESTRUCT* cs = (CREATESTRUCT*) lParam; SetWindowLong ( hwnd, GWL_USERDATA, (LONG)cs->lpCreateParams ); viewer = (rvGEViewer*)cs->lpCreateParams; viewer->mWnd = hwnd; viewer->SetupPixelFormat ( ); viewer->mToolbar = CreateWindowEx ( 0, TOOLBARCLASSNAME, "", CCS_BOTTOM|WS_CHILD|WS_VISIBLE,0,0,0,0, hwnd, (HMENU)IDR_GUIED_VIEWERTOOLBAR, gApp.GetInstance(), NULL ); // Send the TB_BUTTONSTRUCTSIZE message, which is required for backward compatibility. SendMessage( viewer->mToolbar, TB_BUTTONSTRUCTSIZE, ( WPARAM )sizeof( TBBUTTON ), 0 ); SendMessage ( viewer->mToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(16,15) ); SendMessage ( viewer->mToolbar, TB_SETSTYLE, 0, SendMessage ( viewer->mToolbar, TB_GETSTYLE, 0, 0 ) | TBSTYLE_FLAT ); TBMETRICS tbmet; tbmet.cbSize = sizeof(TBMETRICS); SendMessage ( viewer->mToolbar, TB_GETMETRICS, 0, (LPARAM)&tbmet ); tbmet.cyPad = 0; tbmet.cyBarPad = 0; SendMessage ( viewer->mToolbar, TB_SETMETRICS, 0, (LPARAM)&tbmet ); // Add the bitmap containing button images to the toolbar. TBADDBITMAP tbab; tbab.hInst = win32.hInstance; tbab.nID = IDR_GUIED_VIEWERTOOLBAR; SendMessage( viewer->mToolbar, TB_ADDBITMAP, (WPARAM)4, (LPARAM) &tbab ); TBBUTTON tbb[4]; tbb[0].fsStyle = BTNS_SEP; tbb[0].fsState = 0; tbb[1].idCommand = ID_GUIED_VIEWER_START; tbb[1].iBitmap = 2; tbb[1].fsState = 0; tbb[1].fsStyle = BTNS_BUTTON; tbb[1].dwData = 0; tbb[1].iString = -1; tbb[2].idCommand = ID_GUIED_VIEWER_PAUSE; tbb[2].iBitmap = 1; tbb[2].fsState = TBSTATE_ENABLED; tbb[2].fsStyle = BTNS_BUTTON; tbb[2].dwData = 0; tbb[2].iString = -1; tbb[3].fsStyle = BTNS_SEP; tbb[3].fsState = 0; SendMessage( viewer->mToolbar, TB_ADDBUTTONS, (WPARAM)4, (LPARAM) &tbb ); break; } case WM_SETCURSOR: SetCursor ( NULL ); break; } return DefWindowProc ( hwnd, msg, wParam, lParam ); } LRESULT rvGEViewer::HandlePaint ( WPARAM wParam, LPARAM lParam ) { HDC dc; PAINTSTRUCT ps; dc = BeginPaint ( mWnd, &ps ); Render ( dc ); EndPaint ( mWnd, &ps ); return 1; } /* ================ rvGEViewer::SetupPixelFormat Setup the pixel format for the opengl context ================ */ bool rvGEViewer::SetupPixelFormat ( void ) { HDC hDC = GetDC ( mWnd ); bool result = true; int pixelFormat = ChoosePixelFormat(hDC, &win32.pfd); if (pixelFormat > 0) { if (SetPixelFormat(hDC, pixelFormat, &win32.pfd) == NULL) { result = false; } } else { result = false; } ReleaseDC ( mWnd, hDC ); return result; } void rvGEViewer::Render ( HDC dc ) { int frontEnd; int backEnd; // Switch GL contexts to our dc if (!qwglMakeCurrent( dc, win32.hGLRC )) { common->Printf("ERROR: wglMakeCurrent failed.. Error:%i\n", qglGetError()); common->Printf("Please restart Q3Radiant if the Map view is not working\n"); return; } if ( !mPaused ) { mTime += eventLoop->Milliseconds() - mLastTime; mLastTime = eventLoop->Milliseconds(); } RECT rClient; RECT rToolbar; GetClientRect ( mWnd, &rClient ); GetClientRect ( mToolbar, &rToolbar ); mWindowWidth = rClient.right - rClient.left; mWindowHeight = rClient.bottom - rClient.top; qglViewport(0, 0, mWindowWidth, mWindowHeight ); qglScissor(0, 0, mWindowWidth, mWindowHeight ); qglClearColor ( 0, 0, 0, 0 ); qglDisable(GL_DEPTH_TEST); qglDisable(GL_CULL_FACE); qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Render the workspace below glMatrixMode(GL_PROJECTION); glLoadIdentity(); qglOrtho(0,mWindowWidth, mWindowHeight, 0, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); if ( mInterface ) { viewDef_t viewDef; memset ( &viewDef, 0, sizeof(viewDef) ); tr.viewDef = &viewDef; viewDef.renderView.x = 0; viewDef.renderView.y = mToolbarHeight; viewDef.renderView.width = mWindowWidth; viewDef.renderView.height = mWindowHeight - mToolbarHeight; viewDef.scissor.x1 = 0; viewDef.scissor.y1 = 0; // (rToolbar.bottom-rToolbar.top); viewDef.scissor.x2 = mWindowWidth; viewDef.scissor.y2 = mWindowHeight; viewDef.isEditor = true; // Prepare the renderSystem view to draw the GUI in renderSystem->BeginFrame(mWindowWidth, mWindowHeight ); // Draw the gui mInterface->Redraw ( mTime ); // We are done using the renderSystem now renderSystem->EndFrame( &frontEnd, &backEnd ); } qglFinish ( ); qwglSwapBuffers(dc); } void rvGEViewer::RunFrame ( void ) { if ( !mPaused ) { HDC hDC = GetDC ( mWnd ); Render ( hDC ); ReleaseDC ( mWnd, hDC ); } }