Files
DoomRTX/neo/engine/tools/radiant/GLWidget.cpp
T
2026-05-15 10:32:24 -07:00

1076 lines
24 KiB
C++

/*
===========================================================================
IceTech GPL Source Code
Copyright (C) 2026 Justin Marshall
This file is part of the IceTech GPL Source Code (?IceTech Source Code?).
IceTech 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.
IceTech 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 IceTech Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the IceTech 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 IceTech 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 Justin Marshall, justinmarshall20@gmail.com
===========================================================================
*/
#include "precompiled.h"
#pragma hdrstop
#include "qe3.h"
#include "Radiant.h"
#include "GLWidget.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static bool GLWidget_IsValidSize(int w, int h) {
return (w > 0 && h > 0);
}
static void GLWidget_SetRawViewport(int x, int y, int w, int h) {
if (!GLWidget_IsValidSize(w, h)) {
return;
}
glViewport(x, y, w, h);
glEnable(GL_SCISSOR_TEST);
glScissor(x, y, w, h);
}
static void GLWidget_Set2DViewport(int x, int y, int w, int h) {
GLWidget_SetRawViewport(x, y, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, 0, h, -256, 256);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
static float GLWidget_CalcFovY(int w, int h) {
if (w <= 0 || h <= 0) {
return 90.0f;
}
return 2.0f * atan((float)h / (float)w) * idMath::M_RAD2DEG;
}
/////////////////////////////////////////////////////////////////////////////
// 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 const 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 const int cubeSides = sizeof(cubeData) / sizeof(cubeData[0]);
static const int numQuads = cubeSides / 4;
void glTexturedBox(idVec3& point, float size, const idMaterial* mat) {
// The material is expected to be bound by the caller. Keep this function
// free of glBegin/glEnd so stricter GL shims only have to handle draw calls.
(void)mat;
float xyz[cubeSides][3];
float st[cubeSides][2];
unsigned short indexes[numQuads * 6];
for (int i = 0; i < cubeSides; i++) {
const idMiniDrawVert& src = cubeData[i];
xyz[i][0] = point.x + src.xyz.x * size;
xyz[i][1] = point.y + src.xyz.y * size;
xyz[i][2] = point.z + src.xyz.z * size;
st[i][0] = src.st.x;
st[i][1] = src.st.y;
}
for (int i = 0; i < numQuads; i++) {
const unsigned short base = (unsigned short)(i * 4);
indexes[i * 6 + 0] = base + 0;
indexes[i * 6 + 1] = base + 1;
indexes[i * 6 + 2] = base + 2;
indexes[i * 6 + 3] = base + 0;
indexes[i * 6 + 4] = base + 2;
indexes[i * 6 + 5] = base + 3;
}
glDisableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &xyz[0][0]);
glTexCoordPointer(2, GL_FLOAT, 0, &st[0][0]);
glDrawElements(GL_TRIANGLES, numQuads * 6, GL_UNSIGNED_SHORT, indexes);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
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)) {
return FALSE;
}
CDC* dc = GetDC();
if (dc == NULL) {
return FALSE;
}
if (dc->m_hDC == NULL) {
ReleaseDC(dc);
return FALSE;
}
QEW_SetupPixelFormat(dc->m_hDC, false);
if ((hglrc = (HGLRC)wglCreateContext(dc->m_hDC)) == 0)
{
common->FatalError("idGLWidget failed");
}
ReleaseDC(dc);
initialized = true;
return TRUE;
}
void idGLWidget::OnPaint()
{
CPaintDC dc(this); // device context for painting
CRect rect;
GetClientRect(rect);
const int width = rect.Width();
const int height = rect.Height();
if (!GLWidget_IsValidSize(width, height)) {
return;
}
if (!initialized) {
QEW_SetupPixelFormat(dc.m_hDC, false);
if ((hglrc = (HGLRC)wglCreateContext(dc.m_hDC)) == 0)
{
common->FatalError("idGLWidget failed");
}
initialized = true;
}
idGraphicsDeviceContextHelper context(dc.m_hDC, hglrc);
GLWidget_Set2DViewport(0, 0, width, height);
glClearColor(0.4f, 0.4f, 0.4f, 0.7f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
if (drawable) {
drawable->draw(0, 0, width, height);
}
}
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) {
if (!GLWidget_IsValidSize(w, h)) {
return;
}
GL_State(GLS_DEFAULT);
GLWidget_Set2DViewport(x, y, w, h);
glClearColor(0.1f, 0.1f, 0.1f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glLineWidth(1.0f);
glColor3f(1, 1, 1);
if (globalImages) {
globalImages->BindNull();
}
const float verts[4][2] = {
{ 3.0f, 3.0f },
{ 3.0f, h - 3.0f },
{ w - 3.0f, h - 3.0f },
{ w - 3.0f, 3.0f }
};
const float colors[4][4] = {
{ 1.0f, 0.0f, 0.0f, 1.0f },
{ 0.0f, 1.0f, 0.0f, 1.0f },
{ 0.0f, 0.0f, 1.0f, 1.0f },
{ 1.0f, 1.0f, 1.0f, 1.0f }
};
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, &verts[0][0]);
glColorPointer(4, GL_FLOAT, 0, &colors[0][0]);
glDrawArrays(GL_LINE_LOOP, 0, 4);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
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;
}
}
worldDirty = true;
}
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;
}
}
worldDirty = true;
}
*px2 = *px;
::SetCursorPos(pressX, pressY);
}
else {
// origin
if (x != pressX) {
xOffset += (x - pressX);
pressX = x;
worldDirty = true;
}
if (y != pressY) {
yOffset -= (y - pressY);
pressY = y;
worldDirty = true;
}
//::SetCursorPos(pressX, pressY);
}
}
}
void idGLDrawableMaterial::draw(int x, int y, int w, int h) {
const idMaterial* mat = material;
if (!mat || !GLWidget_IsValidSize(w, h)) {
return;
}
GLWidget_SetRawViewport(x, y, w, h);
glClearColor(0.1f, 0.1f, 0.1f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (worldDirty) {
InitWorld();
if (world == NULL || worldModel == NULL) {
return;
}
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 = (int)(img->uploadWidth * scale);
int height = (int)(img->uploadHeight * scale);
if (width < 1) {
width = 1;
}
if (height < 1) {
height = 1;
}
srfTriangles_t* tris = worldModel->AllocSurfaceTriangles(4, 6);
tris->numVerts = 4;
tris->numIndexes = 6;
tris->indexes[0] = 0;
tris->indexes[1] = 3;
tris->indexes[2] = 1;
tris->indexes[3] = 0;
tris->indexes[4] = 1;
tris->indexes[5] = 2;
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;
idVec3 edge1 = tris->verts[3].xyz - tris->verts[0].xyz;
idVec3 edge2 = tris->verts[1].xyz - tris->verts[0].xyz;
tris->verts[0].normal = edge1.Cross(edge2);
tris->verts[0].normal.Normalize();
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;
// 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 = w;
refdef.height = h;
refdef.fov_x = 90;
refdef.fov_y = GLWidget_CalcFovY(w, h);
refdef.time = eventLoop->Milliseconds();
world->RenderScene(&refdef);
int frontEnd, backEnd;
renderSystem->EndFrame(&frontEnd, &backEnd, false);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
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 = (size > 0.0f) ? 128.0f / size : 1.0f;
}
else {
scale = 1.0;
}
xOffset = 0.0;
yOffset = 0.0;
worldDirty = true;
}
idGLDrawableModel::idGLDrawableModel(const char* name) {
worldModel = (name && *name) ? renderModelManager->FindModel(name) : renderModelManager->DefaultModel();
light = 1.0f;
worldDirty = true;
xOffset = 0.0f;
yOffset = 0.0f;
zOffset = -128.0f;
rotation.Set(0.0f, 0.0f, 0.0f, 1.0f);
radius = 2.6f;
lastPress.Zero();
}
idGLDrawableModel::idGLDrawableModel() {
worldModel = renderModelManager->DefaultModel();
light = 1.0f;
worldDirty = true;
xOffset = 0.0f;
yOffset = 0.0f;
zOffset = -128.0f;
rotation.Set(0.0f, 0.0f, 0.0f, 1.0f);
radius = 2.6f;
lastPress.Zero();
}
void idGLDrawableModel::setMedia(const char* name) {
worldModel = (name && *name) ? renderModelManager->FindModel(name) : renderModelManager->DefaultModel();
if (worldModel == NULL) {
worldModel = renderModelManager->DefaultModel();
}
worldDirty = true;
xOffset = 0.0f;
yOffset = 0.0f;
zOffset = -128.0f;
rotation.Set(0.0f, 0.0f, 0.0f, 1.0f);
radius = 2.6f;
lastPress.Zero();
}
void idGLDrawableModel::SetSkin(const char* skin) {
skinStr = skin ? skin : "";
worldDirty = true;
}
void idGLDrawableModel::buttonDown(int _button, float x, float y) {
pressX = x;
pressY = y;
const float rw = (rect.z != 0.0f) ? rect.z : 1.0f;
const float rh = (rect.w != 0.0f) ? rect.w : 1.0f;
lastPress.y = -(float)(2 * x - rw) / rw;
lastPress.x = -(float)(2 * y - rh) / rh;
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) {
const float rw = (rect.z != 0.0f) ? rect.z : 1.0f;
const float rh = (rect.w != 0.0f) ? rect.w : 1.0f;
float cury = (float)(2 * x - rw) / rw;
float curx = (float)(2 * y - rh) / rh;
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();
worldDirty = true;
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;
}
worldDirty = true;
}
else if (*px < *px2) {
light -= 0.05f;
if (light < 0.0f) {
light = 0.0f;
}
worldDirty = true;
}
*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 || !GLWidget_IsValidSize(w, h)) {
return;
}
if (worldModel->IsDynamicModel() != DM_STATIC) {
// Keep dynamic models renderable for previews; the renderer will choose
// the best static/dynamic representation available.
}
rect.Set(x, y, w, h);
GLWidget_SetRawViewport(x, y, w, h);
glClearColor(0.1f, 0.1f, 0.1f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (worldDirty) {
if (world == NULL) {
world = renderSystem->AllocRenderWorld(dxrWorldId_t::DXR_WIDGET_0);
}
if (world == NULL) {
return;
}
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", "preview_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 = w;
refdef.height = h;
refdef.fov_x = 90;
refdef.fov_y = GLWidget_CalcFovY(w, h);
refdef.time = eventLoop->Milliseconds();
world->RenderScene(&refdef);
int frontEnd, backEnd;
renderSystem->EndFrame(&frontEnd, &backEnd);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
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->Update();
drawable->setScale(f);
Invalidate(FALSE);
}
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 (m_hWnd != NULL) {
KillTimer(1);
if (d && d->getRealTime()) {
SetTimer(1, d->getRealTime(), NULL);
}
Invalidate(FALSE);
}
}
void idGLWidget::OnTimer(UINT_PTR 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) {
if (!GLWidget_IsValidSize(w, h)) {
return;
}
GL_State(GLS_DEFAULT);
GLWidget_SetRawViewport(x, y, w, h);
glClearColor(0.1f, 0.1f, 0.1f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderSystem->BeginFrame(w, h);
console->Draw(true);
renderSystem->EndFrame(NULL, NULL);
}
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 TRUE;
}
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(dxrWorldId_t::DXR_WIDGET_0);
}
if (worldModel == NULL) {
worldModel = renderModelManager->AllocModel();
}
if (world == NULL || worldModel == NULL) {
return;
}
world->InitFromMap(NULL);
worldModel->InitEmpty(va("GLWorldModel_%i", Sys_Milliseconds()));
}