Fri, 24 May 2013 20:38:55 +0300
Added method for zooming to fit, fixed zoom being inappropriate when parts are first loaded
src/gldraw.cpp | file | annotate | diff | comparison | revisions | |
src/gldraw.h | file | annotate | diff | comparison | revisions | |
src/gui.cpp | file | annotate | diff | comparison | revisions | |
src/gui.h | file | annotate | diff | comparison | revisions | |
src/gui_actions.cpp | file | annotate | diff | comparison | revisions |
--- a/src/gldraw.cpp Fri May 24 19:44:53 2013 +0300 +++ b/src/gldraw.cpp Fri May 24 20:38:55 2013 +0300 @@ -92,7 +92,6 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= GLRenderer::GLRenderer (QWidget* parent) : QGLWidget (parent) { - resetAngles (); m_picking = m_rangepick = false; m_camera = (GL::Camera) gl_camera.value; m_drawToolTip = false; @@ -100,6 +99,7 @@ m_rectdraw = false; setFile (null); setDrawOnly (false); + resetAngles (); m_toolTipTimer = new QTimer (this); m_toolTipTimer->setSingleShot (true); @@ -170,12 +170,7 @@ m_rotX = 30.0f; m_rotY = 325.f; m_panX = m_panY = m_rotZ = 0.0f; - - // Set the default zoom based on the bounding box - if (g_BBox.empty () == false) - setZoom (g_BBox.size () * 6); - else - setZoom (30.0f); + zoomToFit (); } // ============================================================================= @@ -360,6 +355,7 @@ glLoadIdentity (); glOrtho (-m_virtWidth, m_virtWidth, -m_virtHeight, m_virtHeight, -100.0f, 100.0f); glTranslatef (m_panX, m_panY, 0.0f); + glRotatef (90.0f, g_staticCameras[m_camera].glrotate[0], g_staticCameras[m_camera].glrotate[1], g_staticCameras[m_camera].glrotate[2]); @@ -976,11 +972,7 @@ void GLRenderer::wheelEvent (QWheelEvent* ev) { makeCurrent (); - if (zoom () > 15) - setZoom (zoom () * (ev->delta () < 0 ? 1.2f : 0.833f)); - else - setZoom (zoom () + ((double) ev->delta () / -100.0f)); - + zoomNotch (ev->delta () > 0); setZoom (clamp<double> (zoom (), 0.01f, 10000.0f)); update (); @@ -1401,4 +1393,88 @@ void deleteCameraIcons () { for (CameraIcon& info : g_CameraIcons) delete info.img; +} + +void GLRenderer::zoomNotch (bool inward) { + if (zoom () > 15) + setZoom (zoom () * (inward ? 0.833f : 1.2f)); + else + setZoom (zoom () + (inward ? -1.2f : 1.2f)); +} + +void GLRenderer::zoomToFit () { + if (file () == null) { + setZoom (30.0f); + return; + } + + bool lastfilled = false; + bool firstrun = true; + const uint32 white = 0xFFFFFFFF; + bool inward = true; + ulong run = 0; + const ushort w = m_width, h = m_height; + + glClearColor (1.0, 1.0, 1.0, 1.0); + glDisable (GL_DITHER); + + // Use the pick list while drawing the scene, this way we can tell whether borders + // are background or not. + m_picking = true; + + for (;;) { + if (zoom () > 10000.0f || zoom () < 0.0f) { + // Obviously, there's nothing to draw if we get here. + // Default to 30.0f and break out. + setZoom (30.0f); + break; + } + + zoomNotch (inward); + + uchar* cap = new uchar[4 * w * h]; + drawGLScene (); + glReadPixels (0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, cap); + uint32* imgdata = reinterpret_cast<uint32*> (cap); + bool filled = false; + + // Check the top and bottom rows + for (ushort i = 0; i < w && !filled; ++i) + if (imgdata[i] != white || imgdata[((h - 1) * w) + i] != white) + filled = true; + + // Left and right edges + for (ushort i = 0; i < h && !filled; ++i) + if (imgdata[i * w] != white || imgdata[(i * w) + (w - 1)] != white) + filled = true; + + if (firstrun) { + // If this is the first run, we don't know enough to determine + // whether the zoom was to fit, so we mark in our knowledge so + // far and start over. + inward = !filled; + firstrun = false; + } else { + // If this run filled the screen and the last one did not, the + // last run had ideal zoom - zoom a bit back and we should reach it. + if (filled && !lastfilled) { + zoomNotch (false); + break; + } + + // If this run did not fill the screen and the last one did, we've + // now reached ideal zoom so we're done here. + if (!filled && lastfilled) + break; + + inward = !filled; + } + + delete[] cap; + lastfilled = filled; + ++run; + } + + setBackground (); + m_picking = false; } \ No newline at end of file
--- a/src/gldraw.h Fri May 24 19:44:53 2013 +0300 +++ b/src/gldraw.h Fri May 24 20:38:55 2013 +0300 @@ -88,6 +88,8 @@ void setCamera (const Camera cam); void setDepthValue (double depth); void setupOverlay (); + void zoomNotch (bool inward); + void zoomToFit (); static void deleteLists (LDObject* obj);
--- a/src/gui.cpp Fri May 24 19:44:53 2013 +0300 +++ b/src/gui.cpp Fri May 24 20:38:55 2013 +0300 @@ -1131,4 +1131,9 @@ assert (g_metacursor < MAX_ACTIONS); g_actionMeta[g_metacursor++] = meta; +} + +QImage imageFromScreencap (uchar* data, ushort w, ushort h) { + // GL and Qt formats have R and B swapped. Also, GL flips Y - correct it as well. + return QImage (data, w, h, QImage::Format_ARGB32).rgbSwapped ().mirrored (); } \ No newline at end of file
--- a/src/gui.h Fri May 24 19:44:53 2013 +0300 +++ b/src/gui.h Fri May 24 20:38:55 2013 +0300 @@ -180,6 +180,7 @@ void makeColorSelector (QComboBox* box); QDialogButtonBox* makeButtonBox (QDialog& dlg); CheckBoxGroup* makeAxesBox (); +QImage imageFromScreencap (uchar* data, ushort w, ushort h); // ----------------------------------------------------------------------------- // Pointer to the instance of ForgeWindow.
--- a/src/gui_actions.cpp Fri May 24 19:44:53 2013 +0300 +++ b/src/gui_actions.cpp Fri May 24 20:38:55 2013 +0300 @@ -379,10 +379,8 @@ setlocale (LC_ALL, "C"); ushort w, h; - uchar* imagedata = g_win->R ()->screencap (w, h); - - // GL and Qt formats have R and B swapped. Also, GL flips Y - correct it as well. - QImage img = QImage (imagedata, w, h, QImage::Format_ARGB32).rgbSwapped ().mirrored (); + uchar* imgdata = g_win->R ()->screencap (w, h); + QImage img = imageFromScreencap (imgdata, w, h); str root = basename (g_curfile->name ()); if (~root >= 4 && root.substr (~root - 4, -1) == ".dat") @@ -395,7 +393,7 @@ if (~fname > 0 && !img.save (fname)) critical (fmt ("Couldn't open %s for writing to save screencap: %s", fname.c (), strerror (errno))); - delete[] imagedata; + delete[] imgdata; } // ========================================================================================================================================= @@ -470,9 +468,10 @@ rend->compileAllObjects (); rend->initGLData (); rend->drawGLScene (); - uchar* imagedata = rend->screencap (w, h); - QImage img = QImage (imagedata, w, h, QImage::Format_ARGB32).rgbSwapped ().mirrored (); + uchar* imgdata = rend->screencap (w, h); + QImage img = imageFromScreencap (imgdata, w, h); + if (img.isNull ()) { critical ("Failed to create the image!\n"); } else { @@ -484,6 +483,6 @@ dlg->exec (); } - delete[] imagedata; + delete[] imgdata; rend->deleteLater (); } \ No newline at end of file