mirror of
https://github.com/dhewm/dhewm3.git
synced 2025-03-03 16:12:12 +00:00
In short, it uses a idGLDrawableMaterial widget that calls renderSystem->BeginFrame(w, h); (with w and h being small for the texture preview window) and BeginFrame() sets glConfig.vidWidth and vidHeight to w/h and that never got reset to the original value (window width/height). This breaks everything because for some reason renderSystem->GetSCreenWidth()/Height() return glConfig.vidWidth/Height so it will just continue to render everything at that resolution (in a small rectangle on the lower left corner of the window). This bug has already existed in Doom3 1.3.1 (but was less noticable because apparently when switching away from Doom3 and back to the window it reset vidWidth/Height to the window resolution) I only implemented a workaround (restore glConfig.vid* after rendering the texture preview), it's possible that the same issue exists in other (probably editor-) code - but a "proper fix" might also break code (and I'm not super-familiar with the editor code or even just using them)
953 lines
22 KiB
C++
953 lines
22 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 "qe3.h"
|
|
#include "Radiant.h"
|
|
#include "GLWidget.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// idGLWidget
|
|
class idMiniDrawVert {
|
|
public:
|
|
idVec3 xyz;
|
|
idVec2 st;
|
|
idMiniDrawVert(float x, float y, float z, float s, float t) : xyz(x,y,z), st(s, t) {
|
|
};
|
|
};
|
|
|
|
static idMiniDrawVert cubeData[] = {
|
|
idMiniDrawVert(-1.0, -1.0, +1.0, 0.0, 0.0),
|
|
idMiniDrawVert(+1.0, -1.0, +1.0, 1.0, 0.0),
|
|
idMiniDrawVert(+1.0, +1.0, +1.0, 1.0, 1.0),
|
|
idMiniDrawVert(-1.0, +1.0, +1.0, 0.0, 1.0),
|
|
|
|
idMiniDrawVert(-1.0, -1.0, -1.0, 1.0, 0.0),
|
|
idMiniDrawVert(-1.0, +1.0, +1.0, 1.0, 1.0),
|
|
idMiniDrawVert(+1.0, +1.0, -1.0, 0.0, 1.0),
|
|
idMiniDrawVert(+1.0, -1.0, -1.0, 0.0, 0.0),
|
|
|
|
idMiniDrawVert(-1.0, +1.0, -1.0, 0.0, 1.0),
|
|
idMiniDrawVert(-1.0, +1.0, +1.0, 0.0, 0.0),
|
|
idMiniDrawVert(+1.0, +1.0, +1.0, 1.0, 0.0),
|
|
idMiniDrawVert(+1.0, +1.0, -1.0, 1.0, 1.0),
|
|
|
|
idMiniDrawVert(-1.0, -1.0, -1.0, 1.0, 1.0),
|
|
idMiniDrawVert(+1.0, -1.0, -1.0, 0.0, 1.0),
|
|
idMiniDrawVert(+1.0, -1.0, +1.0, 0.0, 0.0),
|
|
idMiniDrawVert(-1.0, -1.0, +1.0, 1.0, 0.0),
|
|
|
|
idMiniDrawVert(+1.0, -1.0, -1.0, 1.0, 0.0),
|
|
idMiniDrawVert(+1.0, +1.0, -1.0, 1.0, 1.0),
|
|
idMiniDrawVert(+1.0, +1.0, +1.0, 0.0, 1.0),
|
|
idMiniDrawVert(+1.0, -1.0, +1.0, 0.0, 0.0),
|
|
|
|
idMiniDrawVert(-1.0, -1.0, -1.0, 0.0, 0.0),
|
|
idMiniDrawVert(-1.0, -1.0, +1.0, 1.0, 0.0),
|
|
idMiniDrawVert(-1.0, +1.0, +1.0, 1.0, 1.0),
|
|
idMiniDrawVert(-1.0, +1.0, -1.0, 0.0, 1.0)
|
|
};
|
|
|
|
static int cubeSides = sizeof(cubeData) / sizeof(idMiniDrawVert);
|
|
static int numQuads = cubeSides / 4;
|
|
|
|
void glTexturedBox(idVec3 &point, float size, const idMaterial *mat) {
|
|
qglTranslatef(point.x, point.y, point.z);
|
|
for (int i = 0; i < numQuads; i++) {
|
|
qglBegin(GL_QUADS);
|
|
for (int j = 0; j < 4; j++) {
|
|
idVec3 v = cubeData[i * 4 + j].xyz;
|
|
v *= size;
|
|
qglTexCoord2fv(cubeData[i * 4 + j].st.ToFloatPtr());
|
|
qglVertex3fv(v.ToFloatPtr());
|
|
}
|
|
qglEnd();
|
|
}
|
|
}
|
|
|
|
idGLWidget::idGLWidget()
|
|
{
|
|
initialized = false;
|
|
drawable = NULL;
|
|
}
|
|
|
|
idGLWidget::~idGLWidget()
|
|
{
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(idGLWidget, CWnd)
|
|
//{{AFX_MSG_MAP(idGLWidget)
|
|
ON_WM_PAINT()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_MBUTTONDOWN()
|
|
ON_WM_MBUTTONUP()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_MOUSEWHEEL()
|
|
ON_WM_RBUTTONDOWN()
|
|
ON_WM_RBUTTONUP()
|
|
ON_WM_TIMER()
|
|
ON_WM_ERASEBKGND()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// idGLWidget message handlers
|
|
|
|
BOOL idGLWidget::PreCreateWindow(CREATESTRUCT& cs)
|
|
{
|
|
// TODO: Add your specialized code here and/or call the base class
|
|
|
|
return CWnd::PreCreateWindow(cs);
|
|
}
|
|
|
|
BOOL idGLWidget::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
|
|
{
|
|
if (CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext) == -1) {
|
|
return FALSE;
|
|
}
|
|
|
|
CDC *dc = GetDC();
|
|
QEW_SetupPixelFormat(dc->m_hDC, false);
|
|
ReleaseDC(dc);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
void idGLWidget::OnPaint()
|
|
{
|
|
|
|
if (!initialized) {
|
|
CDC *dc = GetDC();
|
|
QEW_SetupPixelFormat(dc->m_hDC, false);
|
|
ReleaseDC(dc);
|
|
initialized = true;
|
|
}
|
|
CPaintDC dc(this); // device context for painting
|
|
|
|
CRect rect;
|
|
GetClientRect(rect);
|
|
|
|
if (!qwglMakeCurrent(dc.m_hDC, win32.hGLRC)) {
|
|
}
|
|
|
|
qglViewport(0, 0, rect.Width(), rect.Height());
|
|
qglScissor(0, 0, rect.Width(), rect.Height());
|
|
qglMatrixMode(GL_PROJECTION);
|
|
qglLoadIdentity();
|
|
qglClearColor (0.4f, 0.4f, 0.4f, 0.7f);
|
|
qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
|
qglDisable(GL_DEPTH_TEST);
|
|
qglDisable(GL_BLEND);
|
|
qglOrtho(0, rect.Width(), 0, rect.Height(), -256, 256);
|
|
|
|
if (drawable) {
|
|
drawable->draw(1, 1, rect.Width()-1, rect.Height()-1);
|
|
} else {
|
|
qglViewport(0, 0, rect.Width(), rect.Height());
|
|
qglScissor(0, 0, rect.Width(), rect.Height());
|
|
qglMatrixMode(GL_PROJECTION);
|
|
qglLoadIdentity();
|
|
qglClearColor (0.4f, 0.4f, 0.4f, 0.7f);
|
|
qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
}
|
|
|
|
qwglSwapBuffers(dc);
|
|
qglFlush();
|
|
qwglMakeCurrent(win32.hDC, win32.hGLRC);
|
|
|
|
}
|
|
|
|
extern bool Sys_KeyDown(int key);
|
|
|
|
void idGLDrawable::buttonDown(int _button, float x, float y) {
|
|
pressX = x;
|
|
pressY = y;
|
|
button = _button;
|
|
if (button == MK_RBUTTON) {
|
|
handleMove = true;
|
|
}
|
|
}
|
|
|
|
void idGLDrawable::buttonUp(int button, float x, float y) {
|
|
handleMove = false;
|
|
}
|
|
|
|
extern float fDiff(float f1, float f2);
|
|
void idGLDrawable::mouseMove(float x, float y) {
|
|
if (handleMove) {
|
|
Update();
|
|
if (Sys_KeyDown(VK_MENU)) {
|
|
// scale
|
|
float *px = &x;
|
|
float *px2 = &pressX;
|
|
|
|
if (fDiff(y, pressY) > fDiff(x, pressX)) {
|
|
px = &y;
|
|
px2 = &pressY;
|
|
}
|
|
|
|
if (*px > *px2) {
|
|
// zoom in
|
|
scale += 0.1f;
|
|
if ( scale > 10.0f ) {
|
|
scale = 10.0f;
|
|
}
|
|
} else if (*px < *px2) {
|
|
// zoom out
|
|
scale -= 0.1f;
|
|
if ( scale <= 0.001f ) {
|
|
scale = 0.001f;
|
|
}
|
|
}
|
|
|
|
*px2 = *px;
|
|
::SetCursorPos(pressX, pressY);
|
|
|
|
} else if (Sys_KeyDown(VK_SHIFT)) {
|
|
// rotate
|
|
} else {
|
|
// origin
|
|
if (x != pressX) {
|
|
xOffset += (x - pressX);
|
|
pressX = x;
|
|
}
|
|
if (y != pressY) {
|
|
yOffset -= (y - pressY);
|
|
pressY = y;
|
|
}
|
|
//::SetCursorPos(pressX, pressY);
|
|
}
|
|
}
|
|
}
|
|
|
|
void idGLDrawable::draw(int x, int y, int w, int h) {
|
|
GL_State( GLS_DEFAULT );
|
|
qglViewport(x, y, w, h);
|
|
qglScissor(x, y, w, h);
|
|
qglMatrixMode(GL_PROJECTION);
|
|
qglClearColor( 0.1f, 0.1f, 0.1f, 0.0f );
|
|
qglClear(GL_COLOR_BUFFER_BIT);
|
|
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
qglLineWidth(0.5);
|
|
qglColor3f(1, 1, 1);
|
|
globalImages->BindNull();
|
|
qglBegin(GL_LINE_LOOP);
|
|
qglColor3f(1, 0, 0);
|
|
qglVertex2f(x + 3, y + 3);
|
|
qglColor3f(0, 1, 0);
|
|
qglVertex2f(x + 3, h - 3);
|
|
qglColor3f(0, 0, 1);
|
|
qglVertex2f(w - 3, h - 3);
|
|
qglColor3f(1, 1, 1);
|
|
qglVertex2f(w - 3, y + 3);
|
|
qglEnd();
|
|
|
|
}
|
|
|
|
static int viewAngle = -98;
|
|
void idGLDrawableMaterial::buttonDown(int button, float x, float y) {
|
|
idGLDrawable::buttonDown(button, x, y);
|
|
//viewAngle += (button == MK_LBUTTON) ? 15 : -15;
|
|
}
|
|
|
|
|
|
void idGLDrawableMaterial::mouseMove(float x, float y) {
|
|
if (handleMove) {
|
|
Update();
|
|
bool doScale = Sys_KeyDown(VK_MENU);
|
|
bool doLight = Sys_KeyDown(VK_SHIFT);
|
|
if (doScale || doLight) {
|
|
// scale
|
|
float *px = &x;
|
|
float *px2 = &pressX;
|
|
|
|
if (fDiff(y, pressY) > fDiff(x, pressX)) {
|
|
px = &y;
|
|
px2 = &pressY;
|
|
}
|
|
|
|
if (*px > *px2) {
|
|
// zoom in
|
|
if (doScale) {
|
|
scale += 0.1f;
|
|
if ( scale > 10.0f ) {
|
|
scale = 10.0f;
|
|
}
|
|
} else {
|
|
light += 0.05f;
|
|
if ( light > 2.0f ) {
|
|
light = 2.0f;
|
|
}
|
|
}
|
|
} else if (*px < *px2) {
|
|
// zoom out
|
|
if (doScale) {
|
|
scale -= 0.1f;
|
|
if ( scale <= 0.001f ) {
|
|
scale = 0.001f;
|
|
}
|
|
} else {
|
|
light -= 0.05f;
|
|
if ( light < 0.0f ) {
|
|
light = 0.0f;
|
|
}
|
|
}
|
|
}
|
|
*px2 = *px;
|
|
::SetCursorPos(pressX, pressY);
|
|
} else {
|
|
// origin
|
|
if (x != pressX) {
|
|
xOffset += (x - pressX);
|
|
pressX = x;
|
|
}
|
|
if (y != pressY) {
|
|
yOffset -= (y - pressY);
|
|
pressY = y;
|
|
}
|
|
//::SetCursorPos(pressX, pressY);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void idGLDrawableMaterial::draw(int x, int y, int w, int h) {
|
|
const idMaterial *mat = material;
|
|
if (mat) {
|
|
qglViewport(x, y, w, h);
|
|
qglScissor(x, y, w, h);
|
|
qglMatrixMode(GL_PROJECTION);
|
|
qglClearColor( 0.1f, 0.1f, 0.1f, 0.0f );
|
|
qglClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
if (worldDirty) {
|
|
InitWorld();
|
|
renderLight_t parms;
|
|
idDict spawnArgs;
|
|
spawnArgs.Set("classname", "light");
|
|
spawnArgs.Set("name", "light_1");
|
|
spawnArgs.Set("origin", "0 0 0");
|
|
idStr str;
|
|
sprintf(str, "%f %f %f", light, light, light);
|
|
spawnArgs.Set("_color", str);
|
|
gameEdit->ParseSpawnArgsToRenderLight( &spawnArgs, &parms );
|
|
lightDef = world->AddLightDef( &parms );
|
|
|
|
idImage *img = (mat->GetNumStages() > 0) ? mat->GetStage(0)->texture.image : mat->GetEditorImage();
|
|
|
|
if (img == NULL) {
|
|
common->Warning("Unable to load image for preview for %s", mat->GetName());
|
|
return;
|
|
}
|
|
|
|
int width = img->uploadWidth;
|
|
int height = img->uploadHeight;
|
|
|
|
width *= scale;
|
|
height *= scale;
|
|
|
|
srfTriangles_t *tris = worldModel->AllocSurfaceTriangles( 4, 6 );
|
|
tris->numVerts = 4;
|
|
tris->numIndexes = 6;
|
|
|
|
tris->indexes[0] = 0;
|
|
tris->indexes[1] = 1;
|
|
tris->indexes[2] = 2;
|
|
tris->indexes[3] = 3;
|
|
tris->indexes[4] = 1;
|
|
tris->indexes[5] = 0;
|
|
|
|
tris->verts[0].xyz.x = 64;
|
|
tris->verts[0].xyz.y = -xOffset + 0 - width / 2;
|
|
tris->verts[0].xyz.z = yOffset + 0 - height / 2;
|
|
tris->verts[0].st.x = 1;
|
|
tris->verts[0].st.y = 1;
|
|
|
|
tris->verts[1].xyz.x = 64;
|
|
tris->verts[1].xyz.y = -xOffset + width / 2;
|
|
tris->verts[1].xyz.z = yOffset + height / 2;
|
|
tris->verts[1].st.x = 0;
|
|
tris->verts[1].st.y = 0;
|
|
|
|
tris->verts[2].xyz.x = 64;
|
|
tris->verts[2].xyz.y = -xOffset + 0 - width / 2;
|
|
tris->verts[2].xyz.z = yOffset + height / 2;
|
|
tris->verts[2].st.x = 1;
|
|
tris->verts[2].st.y = 0;
|
|
|
|
tris->verts[3].xyz.x = 64;
|
|
tris->verts[3].xyz.y = -xOffset + width / 2;
|
|
tris->verts[3].xyz.z = yOffset + 0 - height / 2;
|
|
tris->verts[3].st.x = 0;
|
|
tris->verts[3].st.y = 1;
|
|
|
|
tris->verts[0].normal = tris->verts[1].xyz.Cross(tris->verts[3].xyz);
|
|
tris->verts[1].normal = tris->verts[2].normal = tris->verts[3].normal = tris->verts[0].normal;
|
|
AddTris(tris, mat);
|
|
|
|
worldModel->FinishSurfaces();
|
|
|
|
renderEntity_t worldEntity;
|
|
|
|
memset( &worldEntity, 0, sizeof( worldEntity ) );
|
|
if ( mat->HasGui() ) {
|
|
worldEntity.gui[ 0 ] = mat->GlobalGui();
|
|
}
|
|
worldEntity.hModel = worldModel;
|
|
worldEntity.axis = mat3_default;
|
|
worldEntity.shaderParms[0] = 1;
|
|
worldEntity.shaderParms[1] = 1;
|
|
worldEntity.shaderParms[2] = 1;
|
|
worldEntity.shaderParms[3] = 1;
|
|
modelDef = world->AddEntityDef( &worldEntity );
|
|
|
|
worldDirty = false;
|
|
}
|
|
|
|
renderView_t refdef;
|
|
|
|
// DG: renderSystem->BeginFrame() changes glConfig.vidWidth and vidHeight to w and h
|
|
// that is never reset automatically and for some reason glConfig.vidWith/height is even
|
|
// used for renderSystem->GetScreenWidth()/Height() so idSessionLocal::UpdateScreen()
|
|
// which calls renderSystem->BeginFrame( renderSystem->GetScreenWidth(), renderSystem->GetScreenHeight() );
|
|
// won't reset those values to something sane either, causing the game to be rendered in a tiny rectangle
|
|
// at the lower left corner of the screen once we're done picking a material here..
|
|
// I don't dare to fix this in renderSystem, as other code might rely on this behavior..
|
|
// (OTOH I wouldn't be surprised if other callers of renderSystem->BeginFrame() cause the same issue)
|
|
// Anyway, my workaround is to remember glConfig.vidWith/Height and set them to the original
|
|
// values once we're done rendering here..
|
|
int oldWidth = glConfig.vidWidth;
|
|
int oldHeight = glConfig.vidHeight;
|
|
// render it
|
|
renderSystem->BeginFrame(w, h);
|
|
memset( &refdef, 0, sizeof( refdef ) );
|
|
refdef.vieworg.Set(viewAngle, 0, 0);
|
|
|
|
refdef.viewaxis = idAngles(0,0,0).ToMat3();
|
|
refdef.shaderParms[0] = 1;
|
|
refdef.shaderParms[1] = 1;
|
|
refdef.shaderParms[2] = 1;
|
|
refdef.shaderParms[3] = 1;
|
|
|
|
refdef.width = SCREEN_WIDTH;
|
|
refdef.height = SCREEN_HEIGHT;
|
|
refdef.fov_x = 90;
|
|
refdef.fov_y = 2 * atan((float)h / w) * idMath::M_RAD2DEG;
|
|
|
|
refdef.time = eventLoop->Milliseconds();
|
|
|
|
world->RenderScene( &refdef );
|
|
int frontEnd, backEnd;
|
|
renderSystem->EndFrame( &frontEnd, &backEnd );
|
|
|
|
qglMatrixMode( GL_MODELVIEW );
|
|
qglLoadIdentity();
|
|
// DG: reset glConfig.vidWidth/Height
|
|
glConfig.vidWidth = oldWidth;
|
|
glConfig.vidHeight = oldHeight;
|
|
}
|
|
|
|
}
|
|
|
|
void idGLDrawableMaterial::setMedia(const char *name) {
|
|
idImage *img = NULL;
|
|
if (name && *name) {
|
|
material = declManager->FindMaterial(name);
|
|
if (material) {
|
|
const shaderStage_t *stage = (material->GetNumStages() > 0) ? material->GetStage(0) : NULL;
|
|
if (stage) {
|
|
img = stage->texture.image;
|
|
} else {
|
|
img = material->GetEditorImage();
|
|
}
|
|
}
|
|
} else {
|
|
material = NULL;
|
|
}
|
|
// set scale to get a good fit
|
|
|
|
if (material && img) {
|
|
|
|
float size = (img->uploadWidth > img->uploadHeight) ? img->uploadWidth : img->uploadHeight;
|
|
// use 128 as base scale of 1.0
|
|
scale = 128.0 / size;
|
|
} else {
|
|
scale = 1.0;
|
|
}
|
|
xOffset = 0.0;
|
|
yOffset = 0.0;
|
|
worldDirty = true;
|
|
}
|
|
|
|
idGLDrawableModel::idGLDrawableModel(const char *name) {
|
|
worldModel = renderModelManager->FindModel( name );
|
|
light = 1.0;
|
|
worldDirty = true;
|
|
}
|
|
|
|
idGLDrawableModel::idGLDrawableModel() {
|
|
worldModel = renderModelManager->DefaultModel();
|
|
light = 1.0;
|
|
}
|
|
|
|
void idGLDrawableModel::setMedia(const char *name) {
|
|
worldModel = renderModelManager->FindModel(name);
|
|
worldDirty = true;
|
|
xOffset = 0.0;
|
|
yOffset = 0.0;
|
|
zOffset = -128;
|
|
rotation.Set( 0.0f, 0.0f, 0.0f, 1.0f );
|
|
radius = 2.6f;
|
|
lastPress.Zero();
|
|
}
|
|
|
|
void idGLDrawableModel::SetSkin( const char *skin ) {
|
|
skinStr = skin;
|
|
}
|
|
|
|
|
|
void idGLDrawableModel::buttonDown(int _button, float x, float y) {
|
|
pressX = x;
|
|
pressY = y;
|
|
|
|
lastPress.y = -( float )( 2 * x - rect.z ) / rect.z;
|
|
lastPress.x = -( float )( 2 * y - rect.w ) / rect.w;
|
|
lastPress.z = 0.0f;
|
|
button = _button;
|
|
if (button == MK_RBUTTON || button == MK_LBUTTON) {
|
|
handleMove = true;
|
|
}
|
|
}
|
|
|
|
void idGLDrawableModel::mouseMove(float x, float y) {
|
|
if (handleMove) {
|
|
Update();
|
|
if (button == MK_LBUTTON) {
|
|
float cury = ( float )( 2 * x - rect.z ) / rect.z;
|
|
float curx = ( float )( 2 * y - rect.w ) / rect.w;
|
|
idVec3 to( -curx, -cury, 0.0f );
|
|
to.ProjectSelfOntoSphere( radius );
|
|
lastPress.ProjectSelfOntoSphere( radius );
|
|
idVec3 axis;
|
|
axis.Cross( to, lastPress );
|
|
float len = ( lastPress - to ).Length() / ( 2.0f * radius );
|
|
len = idMath::ClampFloat( -1.0f, 1.0f, len );
|
|
float phi = 2.0f * asin ( len ) ;
|
|
|
|
axis.Normalize();
|
|
axis *= sin( phi / 2.0f );
|
|
idQuat rot( axis.z, axis.y, axis.x, cos( phi / 2.0f ) );
|
|
rot.Normalize();
|
|
|
|
rotation *= rot;
|
|
rotation.Normalize();
|
|
|
|
lastPress = to;
|
|
lastPress.z = 0.0f;
|
|
} else {
|
|
bool doScale = Sys_KeyDown(VK_MENU);
|
|
bool doLight = Sys_KeyDown(VK_SHIFT);
|
|
if (doLight) {
|
|
// scale
|
|
float *px = &x;
|
|
float *px2 = &pressX;
|
|
|
|
if (fDiff(y, pressY) > fDiff(x, pressX)) {
|
|
px = &y;
|
|
px2 = &pressY;
|
|
}
|
|
|
|
if (*px > *px2) {
|
|
light += 0.05f;
|
|
if ( light > 2.0f ) {
|
|
light = 2.0f;
|
|
}
|
|
} else if (*px < *px2) {
|
|
light -= 0.05f;
|
|
if ( light < 0.0f ) {
|
|
light = 0.0f;
|
|
}
|
|
}
|
|
*px2 = *px;
|
|
::SetCursorPos(pressX, pressY);
|
|
} else {
|
|
// origin
|
|
if (x != pressX) {
|
|
if (doScale) {
|
|
zOffset += (x - pressX);
|
|
} else {
|
|
xOffset += (x - pressX);
|
|
}
|
|
pressX = x;
|
|
}
|
|
if (y != pressY) {
|
|
if (doScale) {
|
|
zOffset -= (y - pressY);
|
|
} else {
|
|
yOffset -= (y - pressY);
|
|
}
|
|
pressY = y;
|
|
}
|
|
//::SetCursorPos(pressX, pressY);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void idGLDrawableModel::draw(int x, int y, int w, int h) {
|
|
if ( !worldModel ) {
|
|
return;
|
|
}
|
|
if ( worldModel->IsDynamicModel() != DM_STATIC ) {
|
|
//return;
|
|
}
|
|
|
|
rect.Set( x, y, w, h );
|
|
|
|
qglViewport(x, y, w, h);
|
|
qglScissor(x, y, w, h);
|
|
qglMatrixMode(GL_PROJECTION);
|
|
qglClearColor( 0.1f, 0.1f, 0.1f, 0.0f );
|
|
qglClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
if (worldDirty) {
|
|
//InitWorld();
|
|
world->InitFromMap( NULL );
|
|
renderLight_t parms;
|
|
idDict spawnArgs;
|
|
spawnArgs.Set("classname", "light");
|
|
spawnArgs.Set("name", "light_1");
|
|
spawnArgs.Set("origin", "-128 0 0");
|
|
idStr str;
|
|
sprintf(str, "%f %f %f", light, light, light);
|
|
spawnArgs.Set("_color", str);
|
|
gameEdit->ParseSpawnArgsToRenderLight( &spawnArgs, &parms );
|
|
lightDef = world->AddLightDef( &parms );
|
|
|
|
renderEntity_t worldEntity;
|
|
memset( &worldEntity, 0, sizeof( worldEntity ) );
|
|
spawnArgs.Clear();
|
|
spawnArgs.Set("classname", "func_static");
|
|
spawnArgs.Set("name", spawnArgs.GetString("model"));
|
|
spawnArgs.Set("origin", "0 0 0");
|
|
if ( skinStr.Length() ) {
|
|
spawnArgs.Set( "skin", skinStr );
|
|
}
|
|
gameEdit->ParseSpawnArgsToRenderEntity(&spawnArgs, &worldEntity);
|
|
worldEntity.hModel = worldModel;
|
|
|
|
worldEntity.axis = rotation.ToMat3();
|
|
|
|
worldEntity.shaderParms[0] = 1;
|
|
worldEntity.shaderParms[1] = 1;
|
|
worldEntity.shaderParms[2] = 1;
|
|
worldEntity.shaderParms[3] = 1;
|
|
modelDef = world->AddEntityDef( &worldEntity );
|
|
|
|
worldDirty = false;
|
|
}
|
|
|
|
renderView_t refdef;
|
|
// render it
|
|
renderSystem->BeginFrame(w, h);
|
|
memset( &refdef, 0, sizeof( refdef ) );
|
|
refdef.vieworg.Set(zOffset, xOffset, -yOffset);
|
|
|
|
refdef.viewaxis = idAngles(0,0,0).ToMat3();
|
|
refdef.shaderParms[0] = 1;
|
|
refdef.shaderParms[1] = 1;
|
|
refdef.shaderParms[2] = 1;
|
|
refdef.shaderParms[3] = 1;
|
|
|
|
refdef.width = SCREEN_WIDTH;
|
|
refdef.height = SCREEN_HEIGHT;
|
|
refdef.fov_x = 90;
|
|
refdef.fov_y = 2 * atan((float)h / w) * idMath::M_RAD2DEG;
|
|
|
|
refdef.time = eventLoop->Milliseconds();
|
|
|
|
world->RenderScene( &refdef );
|
|
int frontEnd, backEnd;
|
|
renderSystem->EndFrame( &frontEnd, &backEnd );
|
|
|
|
qglMatrixMode( GL_MODELVIEW );
|
|
qglLoadIdentity();
|
|
}
|
|
|
|
|
|
|
|
void idGLWidget::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
SetCapture();
|
|
if (drawable) {
|
|
if ( drawable->ScreenCoords() ) {
|
|
ClientToScreen(&point);
|
|
}
|
|
drawable->buttonDown(MK_LBUTTON, point.x, point.y);
|
|
}
|
|
}
|
|
|
|
void idGLWidget::OnLButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
if (drawable) {
|
|
if ( drawable->ScreenCoords() ) {
|
|
ClientToScreen(&point);
|
|
}
|
|
drawable->buttonUp(MK_LBUTTON, point.x, point.y);
|
|
}
|
|
ReleaseCapture();
|
|
}
|
|
|
|
void idGLWidget::OnMButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
SetCapture();
|
|
if (drawable) {
|
|
if ( drawable->ScreenCoords() ) {
|
|
ClientToScreen(&point);
|
|
}
|
|
drawable->buttonDown(MK_MBUTTON, point.x, point.y);
|
|
}
|
|
}
|
|
|
|
void idGLWidget::OnMButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
if (drawable) {
|
|
if ( drawable->ScreenCoords() ) {
|
|
ClientToScreen(&point);
|
|
}
|
|
drawable->buttonUp(MK_MBUTTON, point.x, point.y);
|
|
}
|
|
ReleaseCapture();
|
|
}
|
|
|
|
void idGLWidget::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
if (drawable) {
|
|
if ( drawable->ScreenCoords() ) {
|
|
ClientToScreen(&point);
|
|
}
|
|
drawable->mouseMove(point.x, point.y);
|
|
RedrawWindow();
|
|
}
|
|
}
|
|
|
|
BOOL idGLWidget::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
|
|
{
|
|
if (drawable) {
|
|
float f = drawable->getScale();
|
|
if ( zDelta > 0.0f ) {
|
|
f += 0.1f;
|
|
} else {
|
|
f -= 0.1f;
|
|
}
|
|
if ( f <= 0.0f ) {
|
|
f = 0.1f;
|
|
}
|
|
if ( f > 5.0f ) {
|
|
f = 5.0f;
|
|
}
|
|
drawable->setScale(f);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void idGLWidget::OnRButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
SetCapture();
|
|
if (drawable) {
|
|
if ( drawable->ScreenCoords() ) {
|
|
ClientToScreen(&point);
|
|
}
|
|
drawable->buttonDown(MK_RBUTTON, point.x, point.y);
|
|
}
|
|
}
|
|
|
|
void idGLWidget::OnRButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
if (drawable) {
|
|
if ( drawable->ScreenCoords() ) {
|
|
ClientToScreen(&point);
|
|
}
|
|
drawable->buttonUp(MK_RBUTTON, point.x, point.y);
|
|
}
|
|
ReleaseCapture();
|
|
}
|
|
|
|
void idGLWidget::setDrawable(idGLDrawable *d) {
|
|
drawable = d;
|
|
if (d->getRealTime()) {
|
|
SetTimer(1, d->getRealTime(), NULL);
|
|
}
|
|
}
|
|
|
|
|
|
void idGLWidget::OnTimer(UINT nIDEvent) {
|
|
if (drawable && drawable->getRealTime()) {
|
|
Invalidate(FALSE);
|
|
} else {
|
|
KillTimer(1);
|
|
}
|
|
}
|
|
|
|
|
|
idGLDrawable::idGLDrawable() {
|
|
scale = 1.0;
|
|
xOffset = 0.0;
|
|
yOffset = 0.0;
|
|
handleMove = false;
|
|
realTime = 0;
|
|
|
|
}
|
|
|
|
void idGLDrawableConsole::draw(int x, int y, int w, int h) {
|
|
qglPushAttrib( GL_ALL_ATTRIB_BITS );
|
|
qglClearColor( 0.1f, 0.1f, 0.1f, 0.0f );
|
|
qglScissor( 0, 0, w, h );
|
|
qglClear( GL_COLOR_BUFFER_BIT );
|
|
renderSystem->BeginFrame( w, h );
|
|
|
|
console->Draw( true );
|
|
|
|
renderSystem->EndFrame( NULL, NULL );
|
|
qglPopAttrib();
|
|
}
|
|
|
|
void idGLConsoleWidget::init() {
|
|
setDrawable(&console);
|
|
}
|
|
|
|
void idGLConsoleWidget::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
sysEvent_t ev;
|
|
|
|
memset( &ev, 0, sizeof( ev ) );
|
|
ev.evType = SE_KEY;
|
|
ev.evValue2 = 1;
|
|
ev.evValue = nChar;
|
|
|
|
::console->ProcessEvent( &ev, true );
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(idGLConsoleWidget, idGLWidget)
|
|
//{{AFX_MSG_MAP(idGLConsoleWidget)
|
|
ON_WM_PAINT()
|
|
ON_WM_KEYDOWN()
|
|
ON_WM_KEYUP()
|
|
ON_WM_CHAR()
|
|
ON_WM_LBUTTONDOWN()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
|
|
void idGLConsoleWidget::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
sysEvent_t ev;
|
|
|
|
memset( &ev, 0, sizeof( ev ) );
|
|
ev.evType = SE_KEY;
|
|
ev.evValue2 = 0;
|
|
ev.evValue = nChar;
|
|
|
|
::console->ProcessEvent( &ev, true );
|
|
}
|
|
|
|
void idGLConsoleWidget::OnPaint() {
|
|
idGLWidget::OnPaint();
|
|
}
|
|
|
|
void idGLConsoleWidget::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
sysEvent_t ev;
|
|
|
|
memset( &ev, 0, sizeof( ev ) );
|
|
ev.evType = SE_CHAR;
|
|
ev.evValue = nChar;
|
|
|
|
::console->ProcessEvent( &ev, true );
|
|
}
|
|
|
|
void idGLConsoleWidget::OnLButtonDown(UINT nFlags, CPoint point) {
|
|
SetFocus();
|
|
}
|
|
|
|
BOOL idGLWidget::OnEraseBkgnd(CDC* pDC)
|
|
{
|
|
return FALSE;
|
|
|
|
//return CWnd::OnEraseBkgnd(pDC);
|
|
}
|
|
|
|
|
|
idGLDrawableWorld::idGLDrawableWorld() {
|
|
world = NULL;
|
|
worldModel = NULL;
|
|
InitWorld();
|
|
}
|
|
|
|
idGLDrawableWorld::~idGLDrawableWorld() {
|
|
delete world;
|
|
}
|
|
|
|
void idGLDrawableWorld::AddTris(srfTriangles_t *tris, const idMaterial *mat) {
|
|
modelSurface_t surf;
|
|
surf.geometry = tris;
|
|
surf.shader = mat;
|
|
worldModel->AddSurface( surf );
|
|
}
|
|
|
|
void idGLDrawableWorld::draw(int x, int y, int w, int h) {
|
|
|
|
}
|
|
|
|
void idGLDrawableWorld::InitWorld() {
|
|
if ( world == NULL ) {
|
|
world = renderSystem->AllocRenderWorld();
|
|
}
|
|
if ( worldModel == NULL ) {
|
|
worldModel = renderModelManager->AllocModel();
|
|
}
|
|
world->InitFromMap( NULL );
|
|
worldModel->InitEmpty( va( "GLWorldModel_%i", Sys_Milliseconds() ) );
|
|
}
|