mirror of
https://github.com/dhewm/dhewm3.git
synced 2024-11-29 23:51:49 +00:00
b054261a0e
The problem was that the editors called ChoosePixelFormat() instead of wglChoosePixelFormatARB() - and the normal ChoosePixelFormat() has no attribute for MSAA, so if MSAA is enabled (by SDL2 which calls the wgl variant), ChoosePixelFormat() will return an incomaptible format and the editors don't get a working OpenGL context. So I wrote a wrapper around ChoosePixelFormat() that calls the wgl variant if available, and all the necessary plumbing around that. While at it, removed the unused qwgl*PixelFormat function pointers and supressed the "inconsistent dll linkage" warnings for the gl stubs
552 lines
13 KiB
C++
552 lines
13 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
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 "tools/edit_gui_common.h"
|
|
|
|
|
|
#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" ); DG: change from SteelStorm2
|
|
ospath = fileSystem->RelativePathToOSPath ( tempfile, "fs_savepath" );
|
|
|
|
// 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 = Win_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*) GetWindowLongPtr ( hwnd, GWLP_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;
|
|
SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG_PTR)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 = Win_ChoosePixelFormat(hDC);
|
|
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
|
|
qglMatrixMode(GL_PROJECTION);
|
|
qglLoadIdentity();
|
|
qglOrtho(0,mWindowWidth, mWindowHeight, 0, -1, 1);
|
|
qglMatrixMode(GL_MODELVIEW);
|
|
qglLoadIdentity();
|
|
|
|
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 );
|
|
}
|
|
}
|