From aae6a42261e9992df919d80708ffc8f60bdc6900 Mon Sep 17 00:00:00 2001 From: danij Date: Sat, 14 Dec 2013 12:39:56 +0000 Subject: [PATCH] Refactor|Renderer|Viewport: Represent viewport and viewwindow geometry as de::Rectanglei --- .../client/include/render/consoleeffect.h | 2 +- doomsday/client/include/render/viewports.h | 27 +-- .../client/include/ui/widgets/gamewidget.h | 2 +- doomsday/client/src/gl/gl_draw.cpp | 8 +- doomsday/client/src/gl/gl_main.cpp | 42 ++-- doomsday/client/src/render/consoleeffect.cpp | 7 +- doomsday/client/src/render/r_draw.cpp | 50 ++-- doomsday/client/src/render/viewports.cpp | 216 +++++++++--------- doomsday/client/src/ui/widgets/gamewidget.cpp | 4 +- 9 files changed, 175 insertions(+), 183 deletions(-) diff --git a/doomsday/client/include/render/consoleeffect.h b/doomsday/client/include/render/consoleeffect.h index 3132ac5356..3711e5c0a9 100644 --- a/doomsday/client/include/render/consoleeffect.h +++ b/doomsday/client/include/render/consoleeffect.h @@ -42,7 +42,7 @@ class ConsoleEffect /** * Determines the console's view rectangle in window coordinates. */ - de::Rectanglei viewRect() const; + de::Rectanglei const &viewRect() const; bool isInited() const; diff --git a/doomsday/client/include/render/viewports.h b/doomsday/client/include/render/viewports.h index 95d1f3397c..a62501e737 100644 --- a/doomsday/client/include/render/viewports.h +++ b/doomsday/client/include/render/viewports.h @@ -24,6 +24,7 @@ # error "viewports.h is for the client only" #endif +#include #include #include @@ -33,7 +34,7 @@ class Lumobj; struct viewport_t { int console; - RectRaw geometry; + de::Rectanglei geometry; }; struct viewer_t @@ -78,7 +79,7 @@ struct viewdata_t float viewCos, viewSin; - RectRaw window, windowTarget, windowOld; + de::Rectanglei window, windowTarget, windowOld; float windowInter; }; @@ -96,7 +97,7 @@ DENG_EXTERN_C boolean firstFrameAfterLoad; /** * Register console variables. */ -void Viewports_Register(void); +void Viewports_Register(); int R_FrameCount(); @@ -110,15 +111,15 @@ void R_RenderViewPorts(ui::ViewPortLayer layer); /** * Render a blank view for the specified player. */ -void R_RenderBlankView(void); +void R_RenderBlankView(); /** * Draw the border around the view window. */ -void R_RenderPlayerViewBorder(void); +void R_RenderPlayerViewBorder(); -/// @return Current viewport; otherwise @c NULL. -viewport_t const *R_CurrentViewPort(void); +/// @return Current viewport; otherwise @c 0. +viewport_t const *R_CurrentViewPort(); /** * Set the current GL viewport. @@ -129,22 +130,22 @@ viewdata_t const *R_ViewData(int consoleNum); void R_UpdateViewer(int consoleNum); -void R_ResetViewer(void); +void R_ResetViewer(); -int R_NextViewer(void); +int R_NextViewer(); -void R_ClearViewData(void); +void R_ClearViewData(); /** * To be called at the beginning of a render frame to perform necessary initialization. */ -void R_BeginFrame(void); +void R_BeginFrame(); /** * Update the sharp world data by rotating the stored values of plane * heights and sharp camera positions. */ -void R_NewSharpWorld(void); +void R_NewSharpWorld(); /** * Returns @c true iff the BSP leaf is marked as visible for the current frame. @@ -183,7 +184,7 @@ void R_ViewerClipLumobjBySight(Lumobj *lum, BspLeaf *bspLeaf); * Attempt to set up a view grid and calculate the viewports. Set 'numCols' and * 'numRows' to zero to just update the viewport coordinates. */ -boolean R_SetViewGrid(int numCols, int numRows); +bool R_SetViewGrid(int numCols, int numRows); void R_SetupDefaultViewWindow(int consoleNum); diff --git a/doomsday/client/include/ui/widgets/gamewidget.h b/doomsday/client/include/ui/widgets/gamewidget.h index 4fda5d4445..cd2c55d6d1 100644 --- a/doomsday/client/include/ui/widgets/gamewidget.h +++ b/doomsday/client/include/ui/widgets/gamewidget.h @@ -39,7 +39,7 @@ class GameWidget : public GuiWidget * * This is only intended to support old graphics code that doesn't use libgui. */ - void glApplyViewport(int x, int y, int width, int height); + void glApplyViewport(de::Rectanglei const &rect); void viewResized(); void update(); diff --git a/doomsday/client/src/gl/gl_draw.cpp b/doomsday/client/src/gl/gl_draw.cpp index 3fc7b2a8f7..83fcdb3b3a 100644 --- a/doomsday/client/src/gl/gl_draw.cpp +++ b/doomsday/client/src/gl/gl_draw.cpp @@ -332,10 +332,10 @@ void GL_DrawFilter(void) glColor4f(filterColor.x, filterColor.y, filterColor.z, filterColor.w); glBegin(GL_QUADS); - glVertex2f(vd->window.origin.x, vd->window.origin.y); - glVertex2f(vd->window.origin.x + vd->window.size.width, vd->window.origin.y); - glVertex2f(vd->window.origin.x + vd->window.size.width, vd->window.origin.y + vd->window.size.height); - glVertex2f(vd->window.origin.x, vd->window.origin.y + vd->window.size.height); + glVertex2f(vd->window.topLeft.x, vd->window.topLeft.y); + glVertex2f(vd->window.topRight().x, vd->window.topRight().y); + glVertex2f(vd->window.bottomRight.x, vd->window.bottomRight.y); + glVertex2f(vd->window.bottomLeft().x, vd->window.bottomLeft().y); glEnd(); } diff --git a/doomsday/client/src/gl/gl_main.cpp b/doomsday/client/src/gl/gl_main.cpp index 59d7d6a62d..e1d6fe6269 100644 --- a/doomsday/client/src/gl/gl_main.cpp +++ b/doomsday/client/src/gl/gl_main.cpp @@ -468,14 +468,15 @@ void GL_SwitchTo3DState(boolean push_state, viewport_t const *port, viewdata_t c glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); - memcpy(¤tView, port, sizeof(currentView)); + std::memcpy(¤tView, port, sizeof(currentView)); - viewpx = port->geometry.origin.x + viewData->window.origin.x; - viewpy = port->geometry.origin.y + viewData->window.origin.y; - viewpw = MIN_OF(port->geometry.size.width, viewData->window.size.width); - viewph = MIN_OF(port->geometry.size.height, viewData->window.size.height); + viewpx = port->geometry.topLeft.x + viewData->window.topLeft.x; + viewpy = port->geometry.topLeft.y + viewData->window.topLeft.y; + viewpw = de::min(port->geometry.width(), viewData->window.width()); + viewph = de::min(port->geometry.height(), viewData->window.height()); - ClientWindow::main().game().glApplyViewport(viewpx, viewpy, viewpw, viewph); + ClientWindow::main().game().glApplyViewport(Rectanglei::fromSize(Vector2i(viewpx, viewpy), + Vector2ui(viewpw, viewph))); // The 3D projection matrix. GL_ProjectionMatrix(); @@ -489,9 +490,9 @@ void GL_Restore2DState(int step, viewport_t const *port, viewdata_t const *viewD switch(step) { case 1: { // After Restore Step 1 normal player sprites are rendered. - int height = (float)(port->geometry.size.width * viewData->window.size.height / viewData->window.size.width) / port->geometry.size.height * SCREENHEIGHT; + int height = (float)(port->geometry.width() * viewData->window.height() / viewData->window.width()) / port->geometry.height() * SCREENHEIGHT; scalemode_t sm = R_ChooseScaleMode(SCREENWIDTH, SCREENHEIGHT, - port->geometry.size.width, port->geometry.size.height, + port->geometry.width(), port->geometry.height(), scalemode_t(weaponScaleMode)); glMatrixMode(GL_PROJECTION); @@ -509,19 +510,22 @@ void GL_Restore2DState(int step, viewport_t const *port, viewdata_t const *viewD * corrected coordinate space at 4:3, aligned vertically to * the bottom and centered horizontally in the window. */ - glOrtho(0, port->geometry.size.width, port->geometry.size.height, 0, -1, 1); - glTranslatef(port->geometry.size.width/2, port->geometry.size.height, 0); + glOrtho(0, port->geometry.width(), port->geometry.height(), 0, -1, 1); + glTranslatef(port->geometry.width()/2, port->geometry.height(), 0); - if(port->geometry.size.width >= port->geometry.size.height) - glScalef((float)port->geometry.size.height/SCREENHEIGHT, (float)port->geometry.size.height/SCREENHEIGHT, 1); + if(port->geometry.width() >= port->geometry.height()) + glScalef((float)port->geometry.height() / SCREENHEIGHT, + (float)port->geometry.height() / SCREENHEIGHT, 1); else - glScalef((float)port->geometry.size.width/SCREENWIDTH, (float)port->geometry.size.width/SCREENWIDTH, 1); + glScalef((float)port->geometry.width() / SCREENWIDTH, + (float)port->geometry.width() / SCREENWIDTH, 1); // Special case: viewport height is greater than width. - // Apply an additional scaling factor to prevent player sprites looking too small. - if(port->geometry.size.height > port->geometry.size.width) + // Apply an additional scaling factor to prevent player sprites + // looking too small. + if(port->geometry.height() > port->geometry.width()) { - float extraScale = (((float)port->geometry.size.height*2)/port->geometry.size.width) / 2; + float extraScale = (((float)port->geometry.height()*2)/port->geometry.width()) / 2; glScalef(extraScale, extraScale, 1); } @@ -538,11 +542,7 @@ void GL_Restore2DState(int step, viewport_t const *port, viewdata_t const *viewD break; } case 2: // After Restore Step 2 we're back in 2D rendering mode. - ClientWindow::main().game(). - glApplyViewport(currentView.geometry.origin.x, - currentView.geometry.origin.y, - currentView.geometry.size.width, - currentView.geometry.size.height); + ClientWindow::main().game().glApplyViewport(currentView.geometry); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); diff --git a/doomsday/client/src/render/consoleeffect.cpp b/doomsday/client/src/render/consoleeffect.cpp index db7a3b1787..bea12a9b08 100644 --- a/doomsday/client/src/render/consoleeffect.cpp +++ b/doomsday/client/src/render/consoleeffect.cpp @@ -44,13 +44,10 @@ int ConsoleEffect::console() const return d->console; } -Rectanglei ConsoleEffect::viewRect() const +Rectanglei const &ConsoleEffect::viewRect() const { viewdata_t const *vd = R_ViewData(d->console); - return Rectanglei(vd->window.origin.x, - vd->window.origin.y, - vd->window.size.width, - vd->window.size.height); + return vd->window; } bool ConsoleEffect::isInited() const diff --git a/doomsday/client/src/render/r_draw.cpp b/doomsday/client/src/render/r_draw.cpp index cf54d59a05..3e8445667c 100644 --- a/doomsday/client/src/render/r_draw.cpp +++ b/doomsday/client/src/render/r_draw.cpp @@ -217,21 +217,14 @@ static MaterialVariantSpec const &bgMaterialSpec() /// @todo Optimize: Do not search for resources (materials, textures) each frame. void R_DrawViewBorder() { - DENG_ASSERT(inited); + DENG2_ASSERT(inited); viewport_t const *port = R_CurrentViewPort(); viewdata_t const *vd = R_ViewData(displayPlayer); - DENG_ASSERT(port != 0 && vd != 0); + DENG2_ASSERT(port != 0 && vd != 0); - if(!vd->window.size.width || !vd->window.size.height) - { - return; - } - if(vd->window.size.width == port->geometry.size.width && - vd->window.size.height == port->geometry.size.height) - { - return; - } + if(vd->window.isNull()) return; + if(vd->window.size() >= port->geometry.size()) return; DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); @@ -243,15 +236,17 @@ void R_DrawViewBorder() // Scale from viewport space to fixed 320x200 space. int border; - if(port->geometry.size.width >= port->geometry.size.height) + if(port->geometry.width() >= port->geometry.height()) { - glScalef(float(SCREENHEIGHT) / port->geometry.size.height, float(SCREENHEIGHT) / port->geometry.size.height, 1); - border = float(borderSize) / SCREENHEIGHT * port->geometry.size.height; + glScalef(float(SCREENHEIGHT) / port->geometry.height(), + float(SCREENHEIGHT) / port->geometry.height(), 1); + border = float(borderSize) / SCREENHEIGHT * port->geometry.height(); } else { - glScalef(float(SCREENWIDTH) / port->geometry.size.width, float(SCREENWIDTH) / port->geometry.size.width, 1); - border = float(borderSize) / SCREENWIDTH * port->geometry.size.width; + glScalef(float(SCREENWIDTH) / port->geometry.width(), + float(SCREENWIDTH) / port->geometry.width(), 1); + border = float(borderSize) / SCREENWIDTH * port->geometry.width(); } glColor4f(1, 1, 1, 1); @@ -264,19 +259,20 @@ void R_DrawViewBorder() .prepare(bgMaterialSpec()); GL_BindTexture(&ms.texture(MTU_PRIMARY)); - GL_DrawCutRectf2Tiled(0, 0, port->geometry.size.width, port->geometry.size.height, ms.width(), ms.height(), 0, 0, - vd->window.origin.x - border, vd->window.origin.y - border, - vd->window.size.width + 2 * border, vd->window.size.height + 2 * border); + GL_DrawCutRectf2Tiled(0, 0, port->geometry.width(), port->geometry.height(), + ms.width(), ms.height(), 0, 0, + vd->window.topLeft.x - border, vd->window.topLeft.y - border, + vd->window.width() + 2 * border, vd->window.height() + 2 * border); } catch(MaterialManifest::MissingMaterialError const &) {} // Ignore this error. if(border) { - R_DrawPatchTiled(borderTexture(BG_TOP), vd->window.origin.x, vd->window.origin.y - border, vd->window.size.width, border, gl::Repeat, gl::ClampToEdge); - R_DrawPatchTiled(borderTexture(BG_BOTTOM), vd->window.origin.x, vd->window.origin.y + vd->window.size.height , vd->window.size.width, border, gl::Repeat, gl::ClampToEdge); - R_DrawPatchTiled(borderTexture(BG_LEFT), vd->window.origin.x - border, vd->window.origin.y, border, vd->window.size.height, gl::ClampToEdge, gl::Repeat); - R_DrawPatchTiled(borderTexture(BG_RIGHT), vd->window.origin.x + vd->window.size.width, vd->window.origin.y, border, vd->window.size.height, gl::ClampToEdge, gl::Repeat); + R_DrawPatchTiled(borderTexture(BG_TOP), vd->window.topLeft.x, vd->window.topLeft.y - border, vd->window.width(), border, gl::Repeat, gl::ClampToEdge); + R_DrawPatchTiled(borderTexture(BG_BOTTOM), vd->window.topLeft.x, vd->window.bottomRight.y, vd->window.width(), border, gl::Repeat, gl::ClampToEdge); + R_DrawPatchTiled(borderTexture(BG_LEFT), vd->window.topLeft.x - border, vd->window.topLeft.y, border, vd->window.height(), gl::ClampToEdge, gl::Repeat); + R_DrawPatchTiled(borderTexture(BG_RIGHT), vd->window.topRight().x, vd->window.topRight().y, border, vd->window.height(), gl::ClampToEdge, gl::Repeat); } glMatrixMode(GL_TEXTURE); @@ -284,10 +280,10 @@ void R_DrawViewBorder() if(border) { - R_DrawPatch(borderTexture(BG_TOPLEFT), vd->window.origin.x - border, vd->window.origin.y - border, border, border, false); - R_DrawPatch(borderTexture(BG_TOPRIGHT), vd->window.origin.x + vd->window.size.width, vd->window.origin.y - border, border, border, false); - R_DrawPatch(borderTexture(BG_BOTTOMRIGHT), vd->window.origin.x + vd->window.size.width, vd->window.origin.y + vd->window.size.height, border, border, false); - R_DrawPatch(borderTexture(BG_BOTTOMLEFT), vd->window.origin.x - border, vd->window.origin.y + vd->window.size.height, border, border, false); + R_DrawPatch(borderTexture(BG_TOPLEFT), vd->window.topLeft.x - border, vd->window.topLeft.y - border, border, border, false); + R_DrawPatch(borderTexture(BG_TOPRIGHT), vd->window.topRight().x, vd->window.topLeft.y - border, border, border, false); + R_DrawPatch(borderTexture(BG_BOTTOMRIGHT), vd->window.bottomRight.x, vd->window.bottomRight.y, border, border, false); + R_DrawPatch(borderTexture(BG_BOTTOMLEFT), vd->window.bottomLeft().x - border, vd->window.bottomRight.y, border, border, false); } glDisable(GL_TEXTURE_2D); diff --git a/doomsday/client/src/render/viewports.cpp b/doomsday/client/src/render/viewports.cpp index 506b7a3e29..a13dbbead1 100644 --- a/doomsday/client/src/render/viewports.cpp +++ b/doomsday/client/src/render/viewports.cpp @@ -130,38 +130,32 @@ void R_SetupDefaultViewWindow(int consoleNum) viewdata_t *vd = &viewDataOfConsole[consoleNum]; if(consoleNum < 0 || consoleNum >= DDMAXPLAYERS) return; - vd->window.origin.x = vd->windowOld.origin.x = vd->windowTarget.origin.x = 0; - vd->window.origin.y = vd->windowOld.origin.y = vd->windowTarget.origin.y = 0; - vd->window.size.width = vd->windowOld.size.width = vd->windowTarget.size.width = DENG_GAMEVIEW_WIDTH; - vd->window.size.height = vd->windowOld.size.height = vd->windowTarget.size.height = DENG_GAMEVIEW_HEIGHT; + vd->window = + vd->windowOld = + vd->windowTarget = Rectanglei::fromSize(Vector2i(0, 0), Vector2ui(DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT)); vd->windowInter = 1; } void R_ViewWindowTicker(int consoleNum, timespan_t ticLength) { -#define LERP(start, end, pos) (end * pos + start * (1 - pos)) - viewdata_t *vd = &viewDataOfConsole[consoleNum]; - if(consoleNum < 0 || consoleNum >= DDMAXPLAYERS) return; + if(consoleNum < 0 || consoleNum >= DDMAXPLAYERS) + { + return; + } vd->windowInter += float(.4 * ticLength * TICRATE); if(vd->windowInter >= 1) { - std::memcpy(&vd->window, &vd->windowTarget, sizeof(vd->window)); + vd->window = vd->windowTarget; } else { - float const x = LERP(vd->windowOld.origin.x, vd->windowTarget.origin.x, vd->windowInter); - float const y = LERP(vd->windowOld.origin.y, vd->windowTarget.origin.y, vd->windowInter); - float const w = LERP(vd->windowOld.size.width, vd->windowTarget.size.width, vd->windowInter); - float const h = LERP(vd->windowOld.size.height, vd->windowTarget.size.height, vd->windowInter); - vd->window.origin.x = ROUND(x); - vd->window.origin.y = ROUND(y); - vd->window.size.width = ROUND(w); - vd->window.size.height = ROUND(h); + vd->window.moveTopLeft(Vector2i(de::roundf(de::lerp(vd->windowOld.topLeft.x, vd->windowTarget.topLeft.x, vd->windowInter)), + de::roundf(de::lerp(vd->windowOld.topLeft.y, vd->windowTarget.topLeft.y, vd->windowInter)))); + vd->window.setSize(Vector2ui(de::roundf(de::lerp(vd->windowOld.width(), vd->windowTarget.width(), vd->windowInter)), + de::roundf(de::lerp(vd->windowOld.height(), vd->windowTarget.height(), vd->windowInter)))); } - -#undef LERP } #undef R_ViewWindowGeometry @@ -170,8 +164,11 @@ DENG_EXTERN_C int R_ViewWindowGeometry(int player, RectRaw *geometry) if(!geometry) return false; if(player < 0 || player >= DDMAXPLAYERS) return false; - viewdata_t const *vd = &viewDataOfConsole[player]; - std::memcpy(geometry, &vd->window, sizeof *geometry); + viewdata_t const &vd = viewDataOfConsole[player]; + geometry->origin.x = vd.window.topLeft.x; + geometry->origin.y = vd.window.topLeft.y; + geometry->size.width = vd.window.width(); + geometry->size.height = vd.window.height(); return true; } @@ -181,19 +178,21 @@ DENG_EXTERN_C int R_ViewWindowOrigin(int player, Point2Raw *origin) if(!origin) return false; if(player < 0 || player >= DDMAXPLAYERS) return false; - viewdata_t const *vd = &viewDataOfConsole[player]; - std::memcpy(origin, &vd->window.origin, sizeof *origin); + viewdata_t const &vd = viewDataOfConsole[player]; + origin->x = vd.window.topLeft.x; + origin->y = vd.window.topLeft.y; return true; } #undef R_ViewWindowSize -DENG_EXTERN_C int R_ViewWindowSize(int player, Size2Raw* size) +DENG_EXTERN_C int R_ViewWindowSize(int player, Size2Raw *size) { if(!size) return false; if(player < 0 || player >= DDMAXPLAYERS) return false; - viewdata_t const *vd = &viewDataOfConsole[player]; - std::memcpy(size, &vd->window.size, sizeof *size); + viewdata_t const &vd = viewDataOfConsole[player]; + size->width = vd.window.width(); + size->height = vd.window.height(); return true; } @@ -210,39 +209,41 @@ DENG_EXTERN_C void R_SetViewWindowGeometry(int player, RectRaw const *geometry, viewport_t const *vp = &viewportOfLocalPlayer[p]; viewdata_t *vd = &viewDataOfConsole[player]; - RectRaw newGeom; - - // Clamp to valid range. - newGeom.origin.x = de::clamp(0, geometry->origin.x, vp->geometry.size.width); - newGeom.origin.y = de::clamp(0, geometry->origin.y, vp->geometry.size.height); - newGeom.size.width = abs(geometry->size.width); - newGeom.size.height = abs(geometry->size.height); - if(newGeom.origin.x + newGeom.size.width > vp->geometry.size.width) - newGeom.size.width = vp->geometry.size.width - newGeom.origin.x; - if(newGeom.origin.y + newGeom.size.height > vp->geometry.size.height) - newGeom.size.height = vp->geometry.size.height - newGeom.origin.y; + + Rectanglei newGeom = Rectanglei::fromSize(Vector2i(de::clamp(0, geometry->origin.x, vp->geometry.width()), + de::clamp(0, geometry->origin.y, vp->geometry.height())), + Vector2ui(de::abs(geometry->size.width), + de::abs(geometry->size.height))); + + if((unsigned) newGeom.bottomRight.x > vp->geometry.width()) + { + newGeom.setWidth(vp->geometry.width() - newGeom.topLeft.x); + } + if((unsigned) newGeom.bottomRight.y > vp->geometry.height()) + { + newGeom.setHeight(vp->geometry.height() - newGeom.topLeft.y); + } // Already at this target? - if(vd->window.origin.x == newGeom.origin.x && - vd->window.origin.y == newGeom.origin.y && - vd->window.size.width == newGeom.size.width && - vd->window.size.height == newGeom.size.height) + if(vd->window == newGeom) + { return; + } // Record the new target. - std::memcpy(&vd->windowTarget, &newGeom, sizeof vd->windowTarget); + vd->windowTarget = newGeom; // Restart or advance the interpolation timer? // If dimensions have not yet been set - do not interpolate. - if(interpolate && !(vd->window.size.width == 0 && vd->window.size.height == 0)) + if(interpolate && vd->window.size() != Vector2ui(0, 0)) { + vd->windowOld = vd->window; vd->windowInter = 0; - std::memcpy(&vd->windowOld, &vd->window, sizeof(vd->windowOld)); } else { + vd->windowOld = vd->windowTarget; vd->windowInter = 1; // Update on next frame. - std::memcpy(&vd->windowOld, &vd->windowTarget, sizeof(vd->windowOld)); } } @@ -254,8 +255,11 @@ DENG_EXTERN_C int R_ViewPortGeometry(int player, RectRaw *geometry) int p = P_ConsoleToLocal(player); if(p == -1) return false; - viewport_t* vp = &viewportOfLocalPlayer[p]; - std::memcpy(geometry, &vp->geometry, sizeof *geometry); + viewport_t const &vp = viewportOfLocalPlayer[p]; + geometry->origin.x = vp.geometry.topLeft.x; + geometry->origin.y = vp.geometry.topLeft.y; + geometry->size.width = vp.geometry.width(); + geometry->size.height = vp.geometry.height(); return true; } @@ -267,8 +271,9 @@ DENG_EXTERN_C int R_ViewPortOrigin(int player, Point2Raw *origin) int p = P_ConsoleToLocal(player); if(p == -1) return false; - viewport_t *vp = &viewportOfLocalPlayer[p]; - std::memcpy(origin, &vp->geometry.origin, sizeof *origin); + viewport_t const &vp = viewportOfLocalPlayer[p]; + origin->x = vp.geometry.topLeft.x; + origin->y = vp.geometry.topLeft.y; return true; } @@ -280,8 +285,9 @@ DENG_EXTERN_C int R_ViewPortSize(int player, Size2Raw *size) int p = P_ConsoleToLocal(player); if(p == -1) return false; - viewport_t *vp = &viewportOfLocalPlayer[p]; - std::memcpy(size, &vp->geometry.size, sizeof *size); + viewport_t const &vp = viewportOfLocalPlayer[p]; + size->width = vp.geometry.width(); + size->height = vp.geometry.height(); return true; } @@ -303,47 +309,48 @@ void R_UpdateViewPortGeometry(viewport_t *port, int col, int row) { DENG2_ASSERT(port != 0); - RectRaw *rect = &port->geometry; - int const x = DENG_GAMEVIEW_X + col * DENG_GAMEVIEW_WIDTH / gridCols; - int const y = DENG_GAMEVIEW_Y + row * DENG_GAMEVIEW_HEIGHT / gridRows; - int const width = (col+1) * DENG_GAMEVIEW_WIDTH / gridCols - x; - int const height = (row+1) * DENG_GAMEVIEW_HEIGHT / gridRows - y; + Rectanglei newGeom = Rectanglei(Vector2i(DENG_GAMEVIEW_X + col * DENG_GAMEVIEW_WIDTH / gridCols, + DENG_GAMEVIEW_Y + row * DENG_GAMEVIEW_HEIGHT / gridRows), + Vector2i(DENG_GAMEVIEW_X + (col+1) * DENG_GAMEVIEW_WIDTH / gridCols, + DENG_GAMEVIEW_Y + (row+1) * DENG_GAMEVIEW_HEIGHT / gridRows)); ddhook_viewport_reshape_t p; - bool doReshape = false; - if(rect->origin.x == x && rect->origin.y == y && - rect->size.width == width && rect->size.height == height) - return; + if(port->geometry == newGeom) return; + bool doReshape = false; if(port->console != -1 && Plug_CheckForHook(HOOK_VIEWPORT_RESHAPE)) { - std::memcpy(&p.oldGeometry, rect, sizeof(p.oldGeometry)); + p.oldGeometry.origin.x = port->geometry.topLeft.x; + p.oldGeometry.origin.y = port->geometry.topLeft.y; + p.oldGeometry.size.width = port->geometry.width(); + p.oldGeometry.size.height = port->geometry.height(); doReshape = true; } - rect->origin.x = x; - rect->origin.y = y; - rect->size.width = width; - rect->size.height = height; + port->geometry = newGeom; if(doReshape) { - std::memcpy(&p.geometry, rect, sizeof(p.geometry)); + p.geometry.origin.x = port->geometry.topLeft.x; + p.geometry.origin.y = port->geometry.topLeft.y; + p.geometry.size.width = port->geometry.width(); + p.geometry.size.height = port->geometry.height(); + DD_CallHooks(HOOK_VIEWPORT_RESHAPE, port->console, (void*)&p); } } -boolean R_SetViewGrid(int numCols, int numRows) +bool R_SetViewGrid(int numCols, int numRows) { - int x, y, p, console; - // LensFx needs to reallocate resources only for the consoles in use. LensFx_GLRelease(); if(numCols > 0 && numRows > 0) { if(numCols * numRows > DDMAXPLAYERS) + { return false; + } if(numCols > DDMAXPLAYERS) numCols = DDMAXPLAYERS; @@ -354,27 +361,25 @@ boolean R_SetViewGrid(int numCols, int numRows) gridRows = numRows; } - p = 0; - for(y = 0; y < gridRows; ++y) + int p = 0; + for(int y = 0; y < gridRows; ++y) + for(int x = 0; x < gridCols; ++x) { - for(x = 0; x < gridCols; ++x) - { - // The console number is -1 if the viewport belongs to no one. - viewport_t *vp = viewportOfLocalPlayer + p; + // The console number is -1 if the viewport belongs to no one. + viewport_t *vp = viewportOfLocalPlayer + p; - console = P_LocalToConsole(p); - if(console != -1) - { - vp->console = clients[console].viewConsole; - } - else - { - vp->console = -1; - } - - R_UpdateViewPortGeometry(vp, x, y); - ++p; + int const console = P_LocalToConsole(p); + if(console != -1) + { + vp->console = clients[console].viewConsole; } + else + { + vp->console = -1; + } + + R_UpdateViewPortGeometry(vp, x, y); + ++p; } return true; @@ -691,19 +696,15 @@ void R_UseViewPort(viewport_t const *vp) if(!vp) { - currentViewport = NULL; - ClientWindow::main().game().glApplyViewport(DENG_GAMEVIEW_X, - DENG_GAMEVIEW_Y, - DENG_GAMEVIEW_WIDTH, - DENG_GAMEVIEW_HEIGHT); + currentViewport = 0; + ClientWindow::main().game().glApplyViewport( + Rectanglei::fromSize(Vector2i(DENG_GAMEVIEW_X, DENG_GAMEVIEW_Y), + Vector2ui(DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT))); } else { currentViewport = const_cast(vp); - ClientWindow::main().game().glApplyViewport(vp->geometry.origin.x, - vp->geometry.origin.y, - vp->geometry.size.width, - vp->geometry.size.height); + ClientWindow::main().game().glApplyViewport(vp->geometry); } } @@ -856,8 +857,7 @@ DENG_EXTERN_C void R_RenderPlayerView(int num) // Too early? Game has not configured the view window? viewdata_t *vd = &viewDataOfConsole[num]; - if(vd->window.size.width == 0) return; - if(vd->window.size.height == 0) return; + if(vd->window.isNull()) return; // Setup for rendering the frame. R_SetupFrame(player); @@ -1049,16 +1049,21 @@ void R_RenderViewPorts(ui::ViewPortLayer layer) /** * Use an orthographic projection in real pixel dimensions. */ - glOrtho(0, vp->geometry.size.width, vp->geometry.size.height, 0, -1, 1); + glOrtho(0, vp->geometry.width(), vp->geometry.height(), 0, -1, 1); viewdata_t const *vd = &viewDataOfConsole[vp->console]; + RectRaw vpGeometry(vp->geometry.topLeft.x, vp->geometry.topLeft.y, + vp->geometry.width(), vp->geometry.height()); + + RectRaw vdWindow(vd->window.topLeft.x, vd->window.topLeft.y, + vd->window.width(), vd->window.height()); switch(layer) { case ui::Player3DViewLayer: R_UpdateViewer(vp->console); LensFx_BeginFrame(vp->console); - gx.DrawViewPort(p, &vp->geometry, &vd->window, displayPlayer, 0/*layer #0*/); + gx.DrawViewPort(p, &vpGeometry, &vdWindow, displayPlayer, 0/*layer #0*/); LensFx_EndFrame(); break; @@ -1067,7 +1072,7 @@ void R_RenderViewPorts(ui::ViewPortLayer layer) break; case ui::HUDLayer: - gx.DrawViewPort(p, &vp->geometry, &vd->window, displayPlayer, 1/*layer #1*/); + gx.DrawViewPort(p, &vpGeometry, &vdWindow, displayPlayer, 1/*layer #1*/); break; } @@ -1296,14 +1301,7 @@ void R_ViewerClipLumobjBySight(Lumobj *lum, BspLeaf *bspLeaf) D_CMD(ViewGrid) { - DENG_UNUSED(src); - - if(argc != 3) - { - Con_Printf("Usage: %s (cols) (rows)\n", argv[0]); - return true; - } - + DENG2_UNUSED2(src, argc); // Recalculate viewports. - return R_SetViewGrid(strtol(argv[1], NULL, 0), strtol(argv[2], NULL, 0)); + return R_SetViewGrid(String(argv[1]).toInt(), String(argv[2]).toInt()); } diff --git a/doomsday/client/src/ui/widgets/gamewidget.cpp b/doomsday/client/src/ui/widgets/gamewidget.cpp index 5533830c18..5b21358a2c 100644 --- a/doomsday/client/src/ui/widgets/gamewidget.cpp +++ b/doomsday/client/src/ui/widgets/gamewidget.cpp @@ -118,10 +118,10 @@ GameWidget::GameWidget(String const &name) requestGeometry(false); } -void GameWidget::glApplyViewport(int x, int y, int width, int height) +void GameWidget::glApplyViewport(Rectanglei const &rect) { GLState::current() - .setNormalizedViewport(normalizedRect(Rectanglei(x, y, width, height))) + .setNormalizedViewport(normalizedRect(rect)) .apply(); }