diff -r cfe9ae5f1124 -r 7a776f6b0d2a src/gldraw.cpp --- a/src/gldraw.cpp Mon May 13 19:53:22 2013 +0300 +++ b/src/gldraw.cpp Tue May 14 00:52:20 2013 +0300 @@ -16,8 +16,13 @@ * along with this program. If not, see . */ -#include #include +#include +#include +#include +#include +#include +#include #include #include "common.h" #include "config.h" @@ -28,6 +33,8 @@ #include "gui.h" #include "misc.h" #include "history.h" +#include "radiobox.h" +#include "docs.h" static double g_objOffset[3]; @@ -44,6 +51,14 @@ { { 0, -1, 0 }, Z, Y, false, true }, }; +struct overlayMeta { + vertex v0, v1; + ushort ox, oy; + double lw, lh; + str fname; + QImage* img; +} g_overlays[6]; + cfg (str, gl_bgcolor, "#CCCCD9"); cfg (str, gl_maincolor, "#707078"); cfg (float, gl_maincolor_alpha, 1.0); @@ -112,6 +127,9 @@ info->cam = cam; } + for (int i = 0; i < 6; ++i) + g_overlays[i].img = null; + calcCameraIcons (); } @@ -467,6 +485,17 @@ m_hoverpos = g_origin; if (m_camera != Free) { + // Paint the overlay image if we have one + const overlayMeta& overlay = g_overlays[m_camera]; + if (overlay.img != null) { + QPoint v0 = coordconv3_2 (g_overlays[m_camera].v0), + v1 = coordconv3_2 (g_overlays[m_camera].v1); + + QRect targRect (v0.x (), v0.y (), abs (v1.x () - v0.x ()), abs (v1.y () - v0.y ())), + srcRect (0, 0, overlay.img->width (), overlay.img->height ()); + paint.drawImage (targRect, *overlay.img, srcRect); + } + // Calculate 3d position of the cursor m_hoverpos = coordconv2_3 (m_pos, true); @@ -1205,4 +1234,144 @@ void GLRenderer::deleteLists (LDObject* obj) { for (const GL::ListType listType : g_glListTypes) glDeleteLists (obj->glLists[listType], 1); +} + +// ============================================================================= +Axis GLRenderer::cameraAxis (bool y) { + const staticCameraMeta* cam = &g_staticCameras[m_camera]; + return (y) ? cam->axisY : cam->axisX; +} + +// ============================================================================= +OverlayDialog::OverlayDialog (QWidget* parent, Qt::WindowFlags f) : QDialog (parent, f) { + rb_camera = new RadioBox ("Camera", {}, 0, Qt::Horizontal, this); + + for (int i = 0; i < 6; ++i) { + if (i == 3) + rb_camera->rowBreak (); + + rb_camera->addButton (g_CameraNames[i]); + } + + GL::Camera cam = g_win->R ()->camera (); + if (cam != GL::Free) + rb_camera->setValue ((int) cam); + + QGroupBox* gb_image = new QGroupBox ("Image", this); + + QLabel* lb_fpath = new QLabel ("File:"); + le_fpath = new QLineEdit; + le_fpath->setFocus (); + + QLabel* lb_ofs = new QLabel ("Origin:"); + btn_fpath = new QPushButton; + btn_fpath->setIcon (getIcon ("folder")); + connect (btn_fpath, SIGNAL (clicked ()), this, SLOT (slot_fpath ())); + + sb_ofsx = new QSpinBox; + sb_ofsy = new QSpinBox; + sb_ofsx->setRange (0, 10000); + sb_ofsy->setRange (0, 10000); + + QLabel* lb_dimens = new QLabel ("Dimensions (LDU):"); + dsb_lwidth = new QDoubleSpinBox; + dsb_lheight = new QDoubleSpinBox; + dsb_lwidth->setRange (0.0f, 10000.0f); + dsb_lheight->setRange (0.0f, 10000.0f); + + QDialogButtonBox* bbx_buttons = makeButtonBox (*this); + bbx_buttons->addButton (QDialogButtonBox::Help); + connect (bbx_buttons, SIGNAL (helpRequested ()), this, SLOT (slot_help())); + + QHBoxLayout* fpathlayout = new QHBoxLayout; + fpathlayout->addWidget (lb_fpath); + fpathlayout->addWidget (le_fpath); + fpathlayout->addWidget (btn_fpath); + + QGridLayout* metalayout = new QGridLayout; + metalayout->addWidget (lb_ofs, 0, 0); + metalayout->addWidget (sb_ofsx, 0, 1); + metalayout->addWidget (sb_ofsy, 0, 2); + metalayout->addWidget (lb_dimens, 1, 0); + metalayout->addWidget (dsb_lwidth, 1, 1); + metalayout->addWidget (dsb_lheight, 1, 2); + + QVBoxLayout* imagelayout = new QVBoxLayout (gb_image); + imagelayout->addLayout (fpathlayout); + imagelayout->addLayout (metalayout); + + QVBoxLayout* layout = new QVBoxLayout (this); + layout->addWidget (rb_camera); + layout->addWidget (gb_image); + layout->addWidget (bbx_buttons); +} + +str OverlayDialog::fpath () const { return le_fpath->text (); } +ushort OverlayDialog::ofsx () const { return sb_ofsx->value (); } +ushort OverlayDialog::ofsy () const { return sb_ofsy->value (); } +double OverlayDialog::lwidth () const { return dsb_lwidth->value (); } +double OverlayDialog::lheight () const { return dsb_lheight->value (); } +GL::Camera OverlayDialog::camera () const { return (GL::Camera) rb_camera->value (); } + +void OverlayDialog::slot_fpath () const { + le_fpath->setText (QFileDialog::getOpenFileName (null, "Overlay image")); +} + +void OverlayDialog::slot_help () const { + showDocumentation (g_docs_overlays); +} + +void GLRenderer::setupOverlay () { + if (camera () == Free) + return; + + OverlayDialog dlg; + + if (!dlg.exec ()) + return; + + QImage* img = new QImage (dlg.fpath ().chars ()); + overlayMeta& info = g_overlays[camera ()]; + + if (img->isNull ()) { + critical ("Failed to load overlay image!"); + delete img; + return; + } + + delete info.img; // delete the old image + + info.fname = dlg.fpath (); + info.lw = dlg.lwidth (); + info.lh = dlg.lheight (); + info.ox = dlg.ofsx (); + info.oy = dlg.ofsy (); + info.img = img; + + const Axis x2d = cameraAxis (false), + y2d = cameraAxis (true); + + double negXFac = g_staticCameras[m_camera].negX ? -1 : 1, + negYFac = g_staticCameras[m_camera].negY ? -1 : 1; + + info.v0 = info.v1 = g_origin; + info.v0[x2d] = -(info.ox * info.lw * negXFac) / img->width (); + info.v0[y2d] = (info.oy * info.lh * negYFac) / img->height (); + info.v1[x2d] = info.v0[x2d] + info.lw; + info.v1[y2d] = info.v0[y2d] + info.lh; + + // Set alpha of all pixels to 0.5 + for (long i = 0; i < img->width (); ++i) + for (long j = 0; j < img->height (); ++j) { + uint32 pixel = img->pixel (i, j); + img->setPixel (i, j, 0x80000000 | (pixel & 0x00FFFFFF)); + } +} + +void GLRenderer::clearOverlay () { + if (camera () == Free) + return; + + overlayMeta& info = g_overlays[camera ()]; + delete info.img; } \ No newline at end of file