Gui.cpp

Go to the documentation of this file.
00001 #include "Gui.h"
00002 #include "OpenGLCanvas.h"
00003 #include "ImageCanvas.h"
00004 #include "RenderThread.h"
00005 
00006 #include <milton.h>
00007 #include <QtGui>
00008 
00009 #include <fstream>
00010 #include <typeinfo>
00011 #include <iostream>
00012 using namespace std;
00013 
00014 void Gui::_init(const std::string &title) {
00015    QPalette plastique;
00016    QApplication::setStyle("plastique");
00017    
00018    QColor brightText, base, highlight, button, mid,
00019           text, windowText, buttonText, window, 
00020           highlightedText;
00021 
00022    highlightedText.setRgb(255,255,255);
00023    base.setRgb(255,255,255);
00024    highlight.setRgb(157, 187, 227);
00025    button.setRgb(240,240,240);
00026    mid.setRgb(75,75,75);
00027    brightText.setRgb(0,0,0);
00028    text.setRgb(0,0,0);
00029    windowText.setRgb(0,0,0);
00030    buttonText.setRgb(0,0,0);
00031    window.setRgb(255,255,255);
00032    
00033    plastique.setBrush(QPalette::HighlightedText, highlightedText);
00034    plastique.setBrush(QPalette::BrightText, brightText);
00035    plastique.setBrush(QPalette::Base, base);
00036    plastique.setBrush(QPalette::Highlight, highlight);
00037    plastique.setBrush(QPalette::Button, button);
00038    plastique.setBrush(QPalette::Mid, mid);
00039    plastique.setBrush(QPalette::Text, text);
00040    plastique.setBrush(QPalette::WindowText, windowText);
00041    plastique.setBrush(QPalette::ButtonText, buttonText);
00042    plastique.setBrush(QPalette::Window, window);
00043 
00044    QApplication::setPalette(plastique);
00045    
00046    setWindowTitle(QString(title.c_str()));
00047    setDockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks);
00048    
00049    QMenu *file = menuBar()->addMenu(QString("&File"));
00050    QMenu *options = menuBar()->addMenu(QString("&Options"));
00051    
00052    m_lastSaved = "/map/gfx0/users/tfischer/mlt/data/renders";
00053    
00054    /* FILE */
00055    file->addAction(QString("&Load Scene"), this, SLOT(loadPressed()));
00056    file->addAction(QString("&Save Render"), this, SLOT(savePressed()));
00057    file->addSeparator();
00058    
00059    file->addAction(QString("&Quit"), qApp, SLOT(quit()));   
00060    
00061    /* OPTIONS */
00062    options->addAction(QString("Render"), this, SLOT(renderPressed()));
00063    options->addSeparator();
00064    
00065    m_enableAccelPreview = options->addAction(QString("Preview Mesh kd-Trees"), this, SLOT(enableAccelPreviewChanged()));
00066    m_enableDefaultLighting = options->addAction(QString("Enable Default Lighting"), this, SLOT(enableDefaultLightingChanged()));
00067    
00068    options->addSeparator();
00069    
00070    m_enableAccelPreview->setCheckable(true);
00071    m_enableDefaultLighting->setCheckable(true);
00072    
00073    m_enableAccelPreview->setChecked(ResourceManager::getValue<bool>("enableAccelPreview", false));
00074    m_enableDefaultLighting->setChecked(ResourceManager::getValue<bool>("enableDefaultLighting", true));
00075    
00076    
00077    ASSERT(m_enableDefaultLighting->isChecked() == ResourceManager::getValue<bool>("enableDefaultLighting"));
00078    
00079    m_wire = options->addAction(QString("Wireframe"), this, SLOT(drawModeChanged()));
00080    QAction *action = options->addAction(QString("Solid"), this, SLOT(drawModeChanged()));
00081    m_wire->setCheckable(true);
00082    action->setCheckable(true);
00083    
00084    QActionGroup *actionGroup = new QActionGroup(this);
00085    actionGroup->setExclusive(true);
00086    actionGroup->addAction(m_wire);
00087    actionGroup->addAction(action);
00088    
00089    m_wire->setChecked(false);
00090    action->setChecked(true);
00091     
00092    layout()->setSizeConstraint(QLayout::SetFixedSize);
00093 }
00094 
00095 /*bool Gui::loadScene(const char *sceneFile, ParseData &data) {
00096    MiltonJSONSceneLoader loader;
00097    
00098    if (!loader.parse(sceneFile, data)) {
00099       cerr << "Parse error: " << data.error << endl;
00100       QMessageBox::warning(this, "Warning", 
00101                            QString("Error loading scenefile (%1): %2").arg(
00102                               sceneFile, QString(data.error.c_str())));
00103       return false;
00104    }
00105    
00106    return true;
00107 }*/
00108 
00109 void Gui::addCanvas(Canvas *canvas, const char* title) {
00110    // All dockwidgets must go into same area if you want them to be tabbed
00111    Qt::DockWidgetArea area = Qt::RightDockWidgetArea;
00112    
00113    setUpdatesEnabled(false);
00114    
00115    CanvasContainer *container = new CanvasContainer(canvas, title);
00116    addDockWidget(area, container);
00117    if (!m_canvases.isEmpty())
00118       tabifyDockWidget(m_canvases.top(), container);
00119    
00120    m_canvases.push(container);
00121    
00122    setUpdatesEnabled(true);
00123    
00124    // Notify canvas when mesh properties are modified
00125    
00126    if (canvas->supportsOpenGL()) {
00127       OpenGLCanvas *openGLCanvas = NULL;
00128       
00129       try {
00130          openGLCanvas = dynamic_cast<OpenGLCanvas*>(canvas);
00131       } catch(std::bad_cast &) { }
00132       
00133       if (openGLCanvas) {
00134          connect(this, SIGNAL(drawModeChanged(int)), openGLCanvas, 
00135                  SLOT(setDrawMode(int)));
00136       }
00137    } else {
00138       ImageCanvas *imageCanvas = NULL;
00139       
00140       try {
00141          imageCanvas = dynamic_cast<ImageCanvas*>(canvas);
00142       } catch(std::bad_cast &) { }
00143       
00144       if (imageCanvas) {
00145          connect(this, SIGNAL(render()), imageCanvas, SLOT(render()));
00146       }
00147    }
00148 }
00149 
00150 void Gui::addCanvas(Canvas* canvas) {
00151    addCanvas(canvas, "Canvas");
00152 }
00153 
00154 void Gui::drawModeChanged() {
00155    emit drawModeChanged(!((int)m_wire->isChecked()));
00156 }
00157 
00158 void Gui::loadPressed() {
00159    QMessageBox::warning(this, "Warning", 
00160                         QString("scene loading currently unsupported"));
00161    
00162    return;
00163    
00164 #if 0
00165    const QString &fileName = QFileDialog::getOpenFileName(
00166          this, 
00167          "Choose a scenefile to open",
00168          "/map/gfx0/users/mjacobs/cs197/src/gui/scenes");
00169    
00170    if (fileName.isEmpty())
00171       return;
00172    
00173    const char *sceneFile = fileName.toAscii().data();
00174    
00175    /* Set the busy cursor for the app */
00176    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
00177    
00178    ParseData data(true);
00179    
00180    loadScene(sceneFile, data);
00181    
00182    /* Set it back to the normal cursor */
00183    QApplication::restoreOverrideCursor();
00184 #endif
00185 }
00186 
00187 void Gui::savePressed() {
00188    const QString &fileName = QFileDialog::getSaveFileName(
00189       this,
00190       "Choose a filename to save to", 
00191       m_lastSaved.c_str(), 
00192       "Images (*.png *.jpg *.tiff)");
00193    
00194    if (fileName.isEmpty())
00195       return;
00196    
00197    // TODO: on Windows, use '\' as separator
00198    m_lastSaved = fileName.left(fileName.lastIndexOf('/')).toAscii().data();
00199    
00200    Canvas *active = _getActiveCanvas("Select the canvas you would like to save:");
00201    
00202    if (active) {
00203       bool success = active->save(fileName.toAscii().data());
00204       
00205       if (!success)
00206          QMessageBox::warning(this, "Error", QString("Could not save to file '%1'").arg(fileName));
00207    }
00208 }
00209 
00210 void Gui::renderPressed() {
00211    foreach(CanvasContainer *container, m_canvases) {
00212       if (container != NULL) {
00213          Canvas *canvas = container->getCanvas();
00214          ASSERT(canvas);
00215          
00216          if (!canvas->supportsOpenGL()) {
00217             ImageCanvas *imageCanvas = dynamic_cast<ImageCanvas*>(canvas);
00218             ASSERT(imageCanvas);
00219             
00220             Renderer *renderer = imageCanvas->getRenderer();
00221             
00222             if (renderer) {
00223                memset(imageCanvas->getData(), 0, 
00224                       imageCanvas->getWidth() * imageCanvas->getHeight() * 
00225                       sizeof(struct Rgba32));
00226                
00227                imageCanvas->update();
00228                
00229                // TODO: take care of memory leak here
00230                RenderThread *thread = new RenderThread(renderer);
00231                thread->start();
00232             }
00233          }
00234       }
00235    }
00236 }
00237 
00238 void Gui::enableAccelPreviewChanged() {
00239    bool enabled = m_enableAccelPreview->isChecked();
00240    ResourceManager::insert<bool>("enableAccelPreview", enabled);
00241    ASSERT(ResourceManager::getValue<bool>("enableAccelPreview") == enabled);
00242    
00243    _redrawAll();
00244 }
00245 
00246 void Gui::enableDefaultLightingChanged() {
00247    bool enabled = m_enableDefaultLighting->isChecked();
00248    ResourceManager::insert<bool>("enableDefaultLighting", enabled);
00249    ASSERT(ResourceManager::getValue<bool>("enableDefaultLighting") == enabled);
00250    
00251    _redrawAll();
00252 }
00253 
00254 void Gui::_redrawAll() {
00255    foreach(CanvasContainer *container, m_canvases) {
00256       if (container) {
00257          Canvas *canvas = container->getCanvas();
00258          
00259          if (canvas)
00260             canvas->redraw();
00261       }
00262    }
00263 }
00264 
00265 void Gui::selectComboBox(int index) {
00266    m_selectedCombo = index;
00267 }
00268 
00269 Canvas *Gui::_getActiveCanvas(const char *text) {
00270    Canvas *visible = NULL;
00271 
00272    QComboBox *available = new QComboBox(this);
00273    foreach(CanvasContainer *container, m_canvases) {
00274       if (container != NULL) {
00275          available->addItem(container->getTitle());
00276          visible = container->getCanvas();
00277       }
00278    }
00279    
00280    if (available->count() <= 1 && visible)
00281       return visible;
00282    
00283    connect(available, SIGNAL(currentIndexChanged(int)), this, SLOT(selectComboBox(int)));
00284 
00285    QDialog *d = new QDialog(this);
00286    d->setModal(true);
00287    QGridLayout *l = new QGridLayout(d);
00288    QLabel *label = new QLabel(QString(text), this);
00289    l->addWidget(label, 0, 0);
00290    l->addWidget(available, 1, 0);
00291    QPushButton *okay = new QPushButton(tr("Okay"), this);
00292    QPushButton *cancel = new QPushButton(tr("Cancel"), this);
00293 
00294    l->addWidget(okay, 2, 0);
00295    l->addWidget(cancel, 2, 1);
00296 
00297    d->setLayout(l);
00298 
00299    connect(okay, SIGNAL(released()), d, SLOT(accept()));
00300    connect(cancel, SIGNAL(released()), d, SLOT(reject()));
00301    
00302    m_selectedCombo = 0;
00303    int res = d->exec();
00304    
00305    if (res == QDialog::Rejected)
00306       return NULL;
00307    
00308    int i = 0;
00309    foreach(CanvasContainer *container, m_canvases) {
00310       if (container != NULL) {
00311          if (i++ == m_selectedCombo) {
00312             visible = container->getCanvas();
00313             break;
00314          }
00315       }
00316    }
00317 
00318    return visible;
00319 }
00320 
00321 
00322 // --------------------------
00323 // CanvasContainer
00324 // --------------------------
00325 
00326 CanvasContainer::CanvasContainer(Canvas* canvas, const char* title)
00327    : QDockWidget(tr(title)), m_canvas(canvas), 
00328      m_title(title ? title : "Canvas")
00329 {
00330    setupContainer();
00331 }
00332 
00333 CanvasContainer::~CanvasContainer() 
00334 { }
00335 
00336 void CanvasContainer::setupContainer() {
00337    QWidget *widget = m_canvas->getQWidget();
00338    assert(widget);
00339    
00340    setWidget(widget);
00341    
00342    if (layout())
00343       layout()->setSizeConstraint(QLayout::SetFixedSize);
00344    
00345    setFixedSize(sizeHint());
00346    setContentsMargins(0, 0, 0, 0);
00347 }
00348 
00349 void CanvasContainer::synchronizeSize(int, int) {
00350    bool floating = isFloating();
00351    setFloating(!floating);
00352    setFloating(floating);
00353    
00354    if (layout())
00355       layout()->setSizeConstraint(QLayout::SetFixedSize);
00356    
00357    setFixedSize(sizeHint());
00358    setContentsMargins(0, 0, 0, 0);
00359 }
00360 
00361 QSize CanvasContainer::sizeHint() const {
00362    return QSize(m_canvas->getWidth(), m_canvas->getHeight());
00363 }
00364 
00365 QSize CanvasContainer::minimumSize() const {
00366    return sizeHint();
00367 }
00368 
00369 QSize CanvasContainer::maximumSize() const {
00370    return sizeHint();
00371 }
00372 
00373 Canvas *CanvasContainer::getCanvas() const {
00374    return m_canvas;
00375 }
00376 
00377 char *CanvasContainer::getTitle() const {
00378    return m_title.toAscii().data();
00379 }
00380 

Generated on 28 Feb 2009 for Milton by doxygen 1.5.6