diff --git a/src/meshlab_2.01/glarea.cpp b/src/meshlab_2.01/glarea.cpp new file mode 100644 index 000000000..14e17e071 --- /dev/null +++ b/src/meshlab_2.01/glarea.cpp @@ -0,0 +1,1024 @@ +/**************************************************************************** +* MeshLab o o * +* An extendible mesh processor o o * +* _ O _ * +* Copyright(C) 2005, 2006 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include "../common/interfaces.h" +#include "glarea.h" +//#include "layerDialog.h" +#include "mainwindow.h" + +#include +#include +#include + +using namespace std; +using namespace vcg; + +GLArea:: GLArea(QWidget *parent, MultiViewer_Container *mvcont, RichParameterSet *current, int id, MeshDocument *meshDoc) +: QGLWidget(parent) +{ + this->id =id; + this->meshDoc = meshDoc; + mvc = mvcont; + + this->updateCustomSettingValues(*current); + animMode=AnimNone; + iRenderer=0; //Shader support + iEdit=0; + currentEditor=0; + suspendedEditor=false; + lastModelEdited = 0; + cfps=0; + lastTime=0; + hasToPick=false; + hasToGetPickPos=false; + hasToUpdateTexture=false; + helpVisible=false; + takeSnapTile=false; + activeDefaultTrackball=true; + infoAreaVisible = true; + trackBallVisible = true; + currentShader = NULL; + lastFilterRef = NULL; + //lastEditRef = NULL; + setAttribute(Qt::WA_DeleteOnClose,true); + fov = 60; + clipRatioFar = 1; + clipRatioNear = 1; + nearPlane = .2f; + farPlane = 5.f; + pointSize = 2.0f; + //layerDialog = new LayerDialog(this); ** + //layerDialog->setAllowedAreas ( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); ** + connect(meshDoc, SIGNAL(currentMeshChanged(int)), this, SLOT(updateLayer())); + /*getting the meshlab MainWindow from parent, which is QWorkspace. + *note as soon as the GLArea is added as Window to the QWorkspace the parent of GLArea is a QWidget, + *which takes care about the window frame (its parent is the QWorkspace again). + */ + MainWindow* mainwindow = dynamic_cast(parent->parentWidget()); + //connecting the MainWindow Slots to GLArea signal (simple passthrough) + if(mainwindow != NULL){ + connect(this,SIGNAL(updateMainWindowMenus()),mainwindow,SLOT(updateMenus())); + connect(mainwindow,SIGNAL(dispatchCustomSettings(RichParameterSet&)),this,SLOT(updateCustomSettingValues(RichParameterSet&))); + }else{ + qDebug("The parent of the GLArea parent is not a pointer to the meshlab MainWindow."); + } + +} + +GLArea::~GLArea() +{ + // warn any iRender plugin that we're deleting glarea + if (iRenderer) + iRenderer->Finalize(currentShader, *meshDoc, this); + //delete this->layerDialog; +} + + +/* + This member returns the information of the Mesh in terms of VC,VQ,FC,FQ,WT + where: + VC = VertColor,VQ = VertQuality,FC = FaceColor,FQ = FaceQuality,WT = WedgTexCoord +*/ +QString GLArea::GetMeshInfoString() +{ + QString info; + if(mm()->hasDataMask(MeshModel::MM_VERTQUALITY) ) {info.append("VQ ");} + if(mm()->hasDataMask(MeshModel::MM_VERTCOLOR) ) {info.append("VC ");} + if(mm()->hasDataMask(MeshModel::MM_VERTRADIUS) ) {info.append("VR ");} + if(mm()->hasDataMask(MeshModel::MM_VERTTEXCOORD)) {info.append("VT ");} + if(mm()->hasDataMask(MeshModel::MM_VERTCURV) ) {info.append("VK ");} + if(mm()->hasDataMask(MeshModel::MM_VERTCURVDIR) ) {info.append("VD ");} + if(mm()->hasDataMask(MeshModel::MM_FACECOLOR) ) {info.append("FC ");} + if(mm()->hasDataMask(MeshModel::MM_FACEQUALITY) ) {info.append("FQ ");} + if(mm()->hasDataMask(MeshModel::MM_WEDGTEXCOORD)) {info.append("WT ");} + if(mm()->hasDataMask(MeshModel::MM_CAMERA) ) {info.append("MC ");} + + return info; +} + +QSize GLArea::minimumSizeHint() const {return QSize(400,300);} +QSize GLArea::sizeHint() const {return QSize(400,300);} + + +void GLArea::initializeGL() +{ + glShadeModel(GL_SMOOTH); + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + static float diffuseColor[]={1.0,1.0,1.0,1.0}; + glEnable(GL_LIGHT0); + glDisable(GL_LIGHT1); + glLightfv(GL_LIGHT1,GL_DIFFUSE,diffuseColor); + trackball.center=Point3f(0, 0, 0); + trackball.radius= 1; + + trackball_light.center=Point3f(0, 0, 0); + trackball_light.radius= 1; + GLenum err = glewInit(); + if (err != GLEW_OK ) { + assert(0); + } +} + +void GLArea::pasteTile() +{ + glPushAttrib(GL_ENABLE_BIT); + QImage tileBuffer=grabFrameBuffer(true).mirrored(false,true); + + if (snapBuffer.isNull()) + snapBuffer = QImage(tileBuffer.width() * ss.resolution, tileBuffer.height() * ss.resolution, tileBuffer.format()); + + uchar *snapPtr = snapBuffer.bits() + (tileBuffer.bytesPerLine() * tileCol) + ((totalCols * tileRow) * tileBuffer.numBytes()); + uchar *tilePtr = tileBuffer.bits(); + + for (int y=0; y < tileBuffer.height(); y++) + { + memcpy((void*) snapPtr, (void*) tilePtr, tileBuffer.bytesPerLine()); + snapPtr+=tileBuffer.bytesPerLine() * totalCols; + tilePtr+=tileBuffer.bytesPerLine(); + } + + tileCol++; + + if (tileCol >= totalCols) + { + tileCol=0; + tileRow++; + + if (tileRow >= totalRows) + { + QString outfile=QString("%1/%2%3.png") + .arg(ss.outdir) + .arg(ss.basename) + .arg(ss.counter++,2,10,QChar('0')); + bool ret = (snapBuffer.mirrored(false,true)).save(outfile,"PNG"); + if (ret) log.Logf(GLLogStream::SYSTEM, "Snapshot saved to %s",outfile.toLocal8Bit().constData()); + else log.Logf(GLLogStream::WARNING,"Error saving %s",outfile.toLocal8Bit().constData()); + + takeSnapTile=false; + snapBuffer=QImage(); + } + } + update(); + glPopAttrib(); +} + + + +void GLArea::drawGradient() + { + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(-1,1,-1,1,-1,1); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE_2D); + + glBegin(GL_TRIANGLE_STRIP); + glColor(glas.backgroundTopColor); glVertex2f(-1, 1); + glColor(glas.backgroundBotColor); glVertex2f(-1,-1); + glColor(glas.backgroundTopColor); glVertex2f( 1, 1); + glColor(glas.backgroundBotColor); glVertex2f( 1,-1); + glEnd(); + + glPopAttrib(); + glPopMatrix(); // restore modelview + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + } + +void GLArea::drawLight() +{ +// ============== LIGHT TRACKBALL ============== + // Apply the trackball for the light direction + glPushMatrix(); + trackball_light.GetView(); + trackball_light.Apply(!(isDefaultTrackBall())); + + static float lightPosF[]={0.0,0.0,1.0,0.0}; + glLightfv(GL_LIGHT0,GL_POSITION,lightPosF); + static float lightPosB[]={0.0,0.0,-1.0,0.0}; + glLightfv(GL_LIGHT1,GL_POSITION,lightPosB); + + if (!(isDefaultTrackBall())) + { + glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); + glColor3f(1,1,0); + glDisable(GL_LIGHTING); + const unsigned int lineNum=3; + glBegin(GL_LINES); + for(unsigned int i=0;i<=lineNum;++i) + for(unsigned int j=0;j<=lineNum;++j) { + glVertex3f(-1.0f+i*2.0/lineNum,-1.0f+j*2.0/lineNum,-2); + glVertex3f(-1.0f+i*2.0/lineNum,-1.0f+j*2.0/lineNum, 2); + } + glEnd(); + glPopAttrib(); + } + glPopMatrix(); + +} + +void GLArea::paintGL() +{ + QTime time; + time.start(); + initTexture(); + glClearColor(1.0,1.0,1.0,0.0); //vannini: alpha was 1.0 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + + setView(); // Set Modelview and Projection matrix + drawGradient(); // draws the background + drawLight(); + + glPushMatrix(); + + // Finally apply the Trackball for the model + trackball.GetView(); + trackball.Apply(false); + glPushMatrix(); + + //glScale(d); + // glTranslate(-FullBBox.Center()); + setLightModel(); + + // Set proper colorMode + if(rm.colorMode != GLW::CMNone) + { + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); + } + else glColor(Color4b::LightGray); + + if(rm.backFaceCull) glEnable(GL_CULL_FACE); + else glDisable(GL_CULL_FACE); + + if(!meshDoc->busy) + { + glPushAttrib(GL_ALL_ATTRIB_BITS); + + if (iRenderer) iRenderer->Render(currentShader, *meshDoc, rm, this); + else + { + + foreach(MeshModel * mp, meshDoc->meshList) + { + if(mp->visible) mp->Render(rm.drawMode,rm.colorMode,rm.textureMode); + } + } + if(iEdit) iEdit->Decorate(*mm(),this); + + // Draw the selection + if(rm.selectedFace) mm()->RenderSelectedFace(); + if(rm.selectedVert) mm()->RenderSelectedVert(); + QAction * p; + foreach(p , iDecoratorsList) + { + MeshDecorateInterface * decorInterface = qobject_cast(p->parent()); + decorInterface->Decorate(p,*mm(),this,qFont); + } + + glPopAttrib(); + } ///end if busy + + glPopMatrix(); // We restore the state to immediately after the trackball (and before the bbox scaling/translating) + + if(trackBallVisible && !takeSnapTile && !(iEdit && !suspendedEditor)) + trackball.DrawPostApply(); + + // The picking of the surface position has to be done in object space, + // so after trackball transformation (and before the matrix associated to each mesh); + if(hasToPick && hasToGetPickPos) + { + Point3f pp; + hasToPick=false; + if(Pick(pointToPick[0],pointToPick[1],pp)) + { + emit transmitSurfacePos(nameToGetPickPos, pp); + hasToGetPickPos=false; + } + } + glPopMatrix(); // We restore the state to immediately before the trackball + + // Double click move picked point to center + // It has to be done in the before trackball space (we MOVE the trackball itself...) + if(hasToPick && !hasToGetPickPos) + { + Point3f pp; + hasToPick=false; + if(Pick(pointToPick[0],pointToPick[1],pp)) + { + trackball.Translate(-pp); + trackball.Scale(1.25f); + QCursor::setPos(mapToGlobal(QPoint(width()/2+2,height()/2+2))); + } + } + + // ...and take a snapshot + if (takeSnapTile) pasteTile(); + + // Draw the log area background + // on the bottom of the glArea + if(infoAreaVisible) + { + displayInfo(); + updateFps(time.elapsed()); + } + + // Finally display HELP if requested + if (isHelpVisible()) displayHelp(); + + int error = glGetError(); + if(error) { + log.Logf(GLLogStream::WARNING,"There are gl errors"); + } +} + +void GLArea::displayInfo() +{ + // Enter in 2D screen Mode again + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(-1,1,-1,1,-1,1); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + + qFont.setStyleStrategy(QFont::NoAntialias); + qFont.setFamily("Helvetica"); + qFont.setPixelSize(12); + + glBlendFunc(GL_ONE,GL_SRC_ALPHA); + glas.logAreaColor[3]=128; + glColor(glas.logAreaColor); + int lineNum =4; + float lineSpacing = qFont.pixelSize()*1.5f; + float barHeight = -1 + 2.0*(lineSpacing*(lineNum+.25))/float(curSiz.height()); + + + glBegin(GL_QUADS); + glVertex2f(-1.f,barHeight); glVertex2f(-1.f,-1.f); + glVertex2f( 1.f,-1.f); glVertex2f( 1.f,barHeight); + glEnd(); + + // First the LOG + glColor4f(1,1,1,1); + + float middleCol=curSiz.width()*0.40; + float rightCol=curSiz.width()*0.85; + float startPos = curSiz.height()-(5+lineSpacing*(lineNum)); + + renderText(20,startPos+ 1*lineSpacing,tr("LOG MESSAGES"),qFont); + log.glDraw(this,-1,3,lineSpacing,qFont); + + if(meshDoc->size()==1) + { + renderText(middleCol,startPos+ 1*lineSpacing,tr("Vertices: %1").arg(mm()->cm.vn),qFont); + renderText(middleCol,startPos+ 2*lineSpacing,tr("Faces: %1").arg(mm()->cm.fn),qFont); + } + else + { + renderText(middleCol,startPos+ 1*lineSpacing,tr("<%1>").arg(mm()->shortName()),qFont); + renderText(middleCol,startPos+ 2*lineSpacing,tr("Vertices: %1 (%2)").arg(mm()->cm.vn).arg(meshDoc->vn()),qFont); + renderText(middleCol,startPos+ 3*lineSpacing,tr("Faces: %1 (%2)").arg(mm()->cm.fn).arg(meshDoc->fn()),qFont); + } + if(rm.selectedFace || rm.selectedVert || mm()->cm.sfn>0 || mm()->cm.svn>0 ) + renderText(middleCol,startPos+ 4*lineSpacing,tr("Selection: v:%1 f:%2").arg(mm()->cm.svn).arg(mm()->cm.sfn),qFont); + + renderText(rightCol,startPos+ 4*lineSpacing,GetMeshInfoString(),qFont); + + if(fov>5) renderText(rightCol,startPos+1*lineSpacing,QString("FOV: ")+QString::number((int)fov,10),qFont); + else renderText(rightCol,startPos+1*lineSpacing,QString("FOV: Ortho"),qFont); + if ((cfps>0) && (cfps<500)) + renderText(rightCol,startPos+2*lineSpacing,QString("FPS: %1").arg(cfps,7,'f',1),qFont); + if ((clipRatioNear!=1) || (clipRatioFar!=1)) + renderText(rightCol,startPos+3*lineSpacing,QString("Clipping: N:%1 F:%2").arg(clipRatioNear,7,'f',1).arg(clipRatioFar,7,'f',1),qFont); + + + // Closing 2D + glPopAttrib(); + glPopMatrix(); // restore modelview + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + +} + + +void GLArea::displayHelp() +{ + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(-1,1,-1,1,-1,1); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + + glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT ); + glDisable(GL_TEXTURE_2D); + glDisable(GL_LIGHTING); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glBegin(GL_TRIANGLE_STRIP); + glColor4f(.5f,.8f,1.f,.6f); glVertex2f(-1, 1); + glColor4f(.0f,.0f,.0f,.0f); glVertex2f(-1,-1); + glColor4f(.5f,.8f,1.f,.6f); glVertex2f(-.5f,1); + glColor4f(.0f,.0f,.0f,.0f); glVertex2f(-.5f,-1); + glEnd(); + + + float fontSpacingV = (curSiz.height()*.01f)+3; + float hPosition = curSiz.width()*.1f; + glColor(Color4b::White); + //qFont.setBold(true); + renderText(2+hPosition-(qFont.pointSize()*9),1.5*fontSpacingV,QString("MeshLab Quick Help"),qFont);qFont.setBold(false); + renderText(2,3*fontSpacingV,QString("Drag:"),qFont); renderText(hPosition,3*fontSpacingV,QString("Rotate"),qFont); + renderText(2,4.5*fontSpacingV,QString("Ctrl-Drag:"),qFont); renderText(hPosition,4.5*fontSpacingV,QString("Pan"),qFont); + renderText(2,6*fontSpacingV,QString("Shift-Drag:"),qFont); renderText(hPosition,6*fontSpacingV,QString("Zoom"),qFont); + renderText(2,7.5*fontSpacingV,QString("Alt-Drag:"),qFont); renderText(hPosition,7.5*fontSpacingV,QString("Z-Panning"),qFont); + renderText(2,9*fontSpacingV,QString("Ctrl-Shift-Drag:"),qFont); renderText(hPosition,9*fontSpacingV,QString("Rotate light"),qFont); + renderText(2,10.5*fontSpacingV,QString("Wheel:"),qFont); renderText(hPosition,10.5*fontSpacingV,QString("Zoom"),qFont); + renderText(2,12*fontSpacingV,QString("Shift-Wheel:"),qFont); renderText(hPosition,12*fontSpacingV,QString("Change perspective"),qFont); + renderText(2,13.5*fontSpacingV,QString("Ctrl-Wheel:"),qFont); renderText(hPosition,13.5*fontSpacingV,QString("Move far clipping plane"),qFont); + renderText(2,15*fontSpacingV,QString("Ctrl-Shift-Wheel:"),qFont); renderText(hPosition,15*fontSpacingV,QString("Move near clipping plane"),qFont); + renderText(2,16.5*fontSpacingV,QString("Double Click:"),qFont); renderText(hPosition,16.5*fontSpacingV,QString("Center on mouse"),qFont); + renderText(2,18*fontSpacingV,QString("Alt+enter:"),qFont); renderText(hPosition,18*fontSpacingV,QString("Enter/Exit fullscreen mode"),qFont); + glPopAttrib(); + // Closing 2D + glPopAttrib(); + glPopMatrix(); // restore modelview + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + +} + +void GLArea::saveSnapshot() +{ + totalCols=totalRows=ss.resolution; + tileRow=tileCol=0; + + takeSnapTile=true; + update(); +} + +void GLArea::updateLayer() +{ + //if we have an edit tool open, notify it that the current layer has changed + if(iEdit) + { + assert(lastModelEdited); //if there is an editor last model edited should always be set when start edit is called + iEdit->LayerChanged(*meshDoc, *lastModelEdited, this); + + //now update the last model edited + //TODO this is not the best design.... iEdit should maybe keep track of the model on its own + lastModelEdited = meshDoc->mm(); + } +} + +void GLArea::setCurrentEditAction(QAction *editAction) +{ + assert(editAction); + currentEditor = editAction; + + iEdit = actionToMeshEditMap.value(currentEditor); + assert(iEdit); + lastModelEdited = meshDoc->mm(); + if (!iEdit->StartEdit(*meshDoc, this)) + //iEdit->EndEdit(*(meshDoc.mm()), this); + endEdit(); + else + log.Logf(GLLogStream::SYSTEM,"Started Mode %s", qPrintable(currentEditor->text())); +} + + +void GLArea::closeEvent(QCloseEvent *event) +{ + bool close = true; + if(isWindowModified()) + { + QMessageBox::StandardButton ret=QMessageBox::question( + this, tr("MeshLab"), tr("File '%1' modified.\n\nClose without saving?").arg(getFileName()), + QMessageBox::Yes|QMessageBox::No, + QMessageBox::No); + if(ret==QMessageBox::No) + { + close = false; // don't close please! + event->ignore(); + return; + } + } + if(getCurrentEditAction()) endEdit(); + emit glareaClosed(); + event->accept(); +} + +void GLArea::keyReleaseEvent ( QKeyEvent * e ) +{ + e->ignore(); + if(iEdit && !suspendedEditor) iEdit->keyReleaseEvent(e,*mm(),this); + else{ + if(e->key()==Qt::Key_Control) + trackball.ButtonUp(QT2VCG(Qt::NoButton, Qt::ControlModifier ) ); + if(e->key()==Qt::Key_Shift) + trackball.ButtonUp(QT2VCG(Qt::NoButton, Qt::ShiftModifier ) ); + if(e->key()==Qt::Key_Alt) + trackball.ButtonUp(QT2VCG(Qt::NoButton, Qt::AltModifier ) ); + } +} + +void GLArea::keyPressEvent ( QKeyEvent * e ) +{ + e->ignore(); + if(iEdit && !suspendedEditor) iEdit->keyPressEvent(e,*mm(),this); + else{ + if(e->key()==Qt::Key_Control) + trackball.ButtonDown(QT2VCG(Qt::NoButton, Qt::ControlModifier ) ); + if(e->key()==Qt::Key_Shift) + trackball.ButtonDown(QT2VCG(Qt::NoButton, Qt::ShiftModifier ) ); + if(e->key()==Qt::Key_Alt) + trackball.ButtonDown(QT2VCG(Qt::NoButton, Qt::AltModifier ) ); + } +} + +void GLArea::mousePressEvent(QMouseEvent*e) +{ + e->accept(); + setFocus(); + + if( (iEdit && !suspendedEditor) && !(e->buttons() & Qt::MidButton) ) + iEdit->mousePressEvent(e,*mm(),this); + else { + if ((e->modifiers() & Qt::ShiftModifier) && (e->modifiers() & Qt::ControlModifier) && + (e->button()==Qt::LeftButton) ) + activeDefaultTrackball=false; + else activeDefaultTrackball=true; + + if (isDefaultTrackBall()) + { + if(QApplication::keyboardModifiers () & Qt::Key_Control) trackball.ButtonDown(QT2VCG(Qt::NoButton, Qt::ControlModifier ) ); + else trackball.ButtonUp (QT2VCG(Qt::NoButton, Qt::ControlModifier ) ); + if(QApplication::keyboardModifiers () & Qt::Key_Shift) trackball.ButtonDown(QT2VCG(Qt::NoButton, Qt::ShiftModifier ) ); + else trackball.ButtonUp (QT2VCG(Qt::NoButton, Qt::ShiftModifier ) ); + if(QApplication::keyboardModifiers () & Qt::Key_Alt) trackball.ButtonDown(QT2VCG(Qt::NoButton, Qt::AltModifier ) ); + else trackball.ButtonUp (QT2VCG(Qt::NoButton, Qt::AltModifier ) ); + + trackball.MouseDown(e->x(),height()-e->y(), QT2VCG(e->button(), e->modifiers() ) ); + } + else trackball_light.MouseDown(e->x(),height()-e->y(), QT2VCG(e->button(), Qt::NoModifier ) ); + } + emit currentViewerChanged(id); + emit updateMainWindowMenus(); + update(); + if(isCurrent()) + if(e->modifiers() & Qt::MetaModifier) + mvc->updatePressViewers(e); +} + +void GLArea::mousePressEvent2(QMouseEvent*e) +{ + e->accept(); + + if( (iEdit && !suspendedEditor) && !(e->buttons() & Qt::MidButton) ) + iEdit->mousePressEvent(e,*mm(),this); + else { + if ((e->modifiers() & Qt::ShiftModifier) && (e->modifiers() & Qt::ControlModifier) && + (e->button()==Qt::LeftButton) ) + activeDefaultTrackball=false; + else activeDefaultTrackball=true; + + if (isDefaultTrackBall()) + { + if(QApplication::keyboardModifiers () & Qt::Key_Control) trackball.ButtonDown(QT2VCG(Qt::NoButton, Qt::ControlModifier ) ); + else trackball.ButtonUp (QT2VCG(Qt::NoButton, Qt::ControlModifier ) ); + if(QApplication::keyboardModifiers () & Qt::Key_Shift) trackball.ButtonDown(QT2VCG(Qt::NoButton, Qt::ShiftModifier ) ); + else trackball.ButtonUp (QT2VCG(Qt::NoButton, Qt::ShiftModifier ) ); + if(QApplication::keyboardModifiers () & Qt::Key_Alt) trackball.ButtonDown(QT2VCG(Qt::NoButton, Qt::AltModifier ) ); + else trackball.ButtonUp (QT2VCG(Qt::NoButton, Qt::AltModifier ) ); + + trackball.MouseDown(e->x(),height()-e->y(), QT2VCG(e->button(), e->modifiers() ) ); + } + else trackball_light.MouseDown(e->x(),height()-e->y(), QT2VCG(e->button(), Qt::NoModifier ) ); + } + update(); +} + + +void GLArea::mouseMoveEvent(QMouseEvent*e) +{ + if( (iEdit && !suspendedEditor) && !(e->buttons() & Qt::MidButton) ) + iEdit->mouseMoveEvent(e,*mm(),this); + else { + if (isDefaultTrackBall()) + { + trackball.MouseMove(e->x(),height()-e->y()); + setCursorTrack(trackball.current_mode); + } + else trackball_light.MouseMove(e->x(),height()-e->y()); + update(); + } + if(isCurrent()) + if(e->modifiers() & Qt::MetaModifier) + mvc->updateMoveViewers(e); + +} +// When mouse is released we set the correct mouse cursor +void GLArea::mouseReleaseEvent(QMouseEvent*e) +{ + //clearFocus(); + activeDefaultTrackball=true; + if( (iEdit && !suspendedEditor) && (e->button() != Qt::MidButton) ) + iEdit->mouseReleaseEvent(e,*mm(),this); + else { + if (isDefaultTrackBall()) trackball.MouseUp(e->x(),height()-e->y(), QT2VCG(e->button(), e->modifiers() ) ); + else trackball_light.MouseUp(e->x(),height()-e->y(), QT2VCG(e->button(),e->modifiers()) ); + setCursorTrack(trackball.current_mode); + } + + update(); + if(isCurrent()) + mvc->updateReleaseViewers(e); +} + +//Processing of tablet events, interesting only for painting plugins +void GLArea::tabletEvent(QTabletEvent*e) +{ + if(iEdit && !suspendedEditor) iEdit->tabletEvent(e,*mm(),this); + else e->ignore(); +} + +void GLArea::wheelEvent(QWheelEvent*e) +{ + const int WHEEL_STEP = 120; + float notch = e->delta()/ float(WHEEL_STEP); + switch(e->modifiers()) + { + case Qt::ShiftModifier + Qt::ControlModifier : clipRatioFar *= powf(1.2f, notch); break; + case Qt::ControlModifier : clipRatioNear *= powf(1.2f, notch); break; + case Qt::AltModifier : pointSize = math::Clamp(pointSize*powf(1.2f, notch),0.01f,150.0f); + foreach(MeshModel * mp, meshDoc->meshList) + mp->glw.SetHintParamf(GLW::HNPPointSize,pointSize); + break; + case Qt::ShiftModifier : fov = math::Clamp(fov*powf(1.2f,notch),5.0f,90.0f); break; + default: + trackball.MouseWheel( e->delta()/ float(WHEEL_STEP)); + break; + } + updateGL(); +} + + +void GLArea::mouseDoubleClickEvent ( QMouseEvent * e ) +{ + hasToPick=true; + pointToPick=Point2i(e->x(),height()-e->y()); + updateGL(); +} + +void GLArea::setCursorTrack(vcg::TrackMode *tm) +{ + //static QMap curMap; + if(curMap.isEmpty()) + { + curMap[QString("")]=QCursor(Qt::ArrowCursor); + curMap["SphereMode"]=QCursor(QPixmap(":/images/cursors/plain_trackball.png"),1,1); + curMap["PanMode"]=QCursor(QPixmap(":/images/cursors/plain_pan.png"),1,1); + curMap["ScaleMode"]=QCursor(QPixmap(":/images/cursors/plain_zoom.png"),1,1); + } + if(tm) setCursor(curMap[tm->Name()]); + else setCursor(curMap[""]); + +} + +void GLArea::setDrawMode(vcg::GLW::DrawMode mode) +{ + rm.drawMode = mode; + updateGL(); +} + + +void GLArea::setColorMode(vcg::GLW::ColorMode mode) +{ + rm.colorMode = mode; + updateGL(); +} +void GLArea::updateTexture() +{ + hasToUpdateTexture = true; +} + +// Texture loading done during the first paint. +void GLArea::initTexture() +{ + if(hasToUpdateTexture) + { + foreach (MeshModel *mp,meshDoc->meshList) + mp->glw.TMId.clear(); + + qDebug("Beware: deleting the texutres could lead to problems for shared textures."); + hasToUpdateTexture = false; + } + + foreach (MeshModel *mp, meshDoc->meshList) + { + if(!mp->cm.textures.empty() && mp->glw.TMId.empty()){ + glEnable(GL_TEXTURE_2D); + GLint MaxTextureSize; + glGetIntegerv(GL_MAX_TEXTURE_SIZE,&MaxTextureSize); + + for(unsigned int i =0; i< mp->cm.textures.size();++i){ + QImage img, imgScaled, imgGL; + + bool res = img.load(mp->cm.textures[i].c_str()); + if(!res) + { + // Note that sometimes (in collada) the texture names could have been encoded with a url-like style (e.g. replacing spaces with '%20') so making some other attempt could be harmless + QString ConvertedName = QString(mp->cm.textures[i].c_str()).replace(QString("%20"), QString(" ")); + res = img.load(ConvertedName); + if(!res) qDebug("Failure of loading texture %s",mp->cm.textures[i].c_str()); + else qDebug("Warning, texture loading was successful only after replacing %%20 with spaces;\n Loaded texture %s instead of %s",qPrintable(ConvertedName),mp->cm.textures[i].c_str()); + } + // image has to be scaled to a 2^n size. We choose the first 2^N <= picture size. + int bestW=pow(2.0,floor(::log(double(img.width() ))/::log(2.0))); + int bestH=pow(2.0,floor(::log(double(img.height()))/::log(2.0))); + while(bestW>MaxTextureSize) bestW /=2; + while(bestH>MaxTextureSize) bestH /=2; + + log.Log(GLLogStream::SYSTEM,"Loading textures"); + log.Logf(GLLogStream::SYSTEM," Texture[ %3i ] = '%s' ( %6i x %6i ) -> ( %6i x %6i )", i,mp->cm.textures[i].c_str(), img.width(), img.height(),bestW,bestH); + imgScaled=img.scaled(bestW,bestH,Qt::IgnoreAspectRatio,Qt::SmoothTransformation); + imgGL=convertToGLFormat(imgScaled); + mp->glw.TMId.push_back(0); + glGenTextures( 1, (GLuint*)&(mp->glw.TMId.back()) ); + glBindTexture( GL_TEXTURE_2D, mp->glw.TMId.back() ); + glTexImage2D( GL_TEXTURE_2D, 0, 3, imgGL.width(), imgGL.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, imgGL.bits() ); + + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); + gluBuild2DMipmaps(GL_TEXTURE_2D, 3, imgGL.width(), imgGL.height(), GL_RGBA, GL_UNSIGNED_BYTE, imgGL.bits() ); + + if(glas.textureMagFilter == 0 ) glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + else glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + if(glas.textureMinFilter == 0 ) glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + else glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + qDebug(" will be loaded as GL texture id %i ( %i x %i )",mp->glw.TMId.back() ,imgGL.width(), imgGL.height()); + } + } + glDisable(GL_TEXTURE_2D); + } +} + +void GLArea::setTextureMode(vcg::GLW::TextureMode mode) +{ + rm.textureMode = mode; + updateGL(); +} + +void GLArea::setLight(bool state) +{ + rm.lighting = state; + updateGL(); +} + +void GLArea::setLightMode(bool state,LightingModel lmode) +{ + switch(lmode) + { + case LDOUBLE: rm.doubleSideLighting = state; break; + case LFANCY: rm.fancyLighting = state; break; + } + updateGL(); +} + +void GLArea::setBackFaceCulling(bool enabled) +{ + rm.backFaceCull = enabled; + updateGL(); +} + +void GLArea::setSelectFaceRendering(bool enabled) +{ + rm.selectedFace = enabled; + updateGL(); +} +void GLArea::setSelectVertRendering(bool enabled) +{ + rm.selectedVert = enabled; + updateGL(); +} + +void GLArea::setLightModel() +{ + if (rm.lighting) + { + glEnable(GL_LIGHTING); + + if (rm.doubleSideLighting) + glEnable(GL_LIGHT1); + else + glDisable(GL_LIGHT1); + + glLightfv(GL_LIGHT0, GL_AMBIENT, Color4f::Construct(glas.baseLightAmbientColor).V()); + glLightfv(GL_LIGHT0, GL_DIFFUSE, Color4f::Construct(glas.baseLightDiffuseColor).V()); + glLightfv(GL_LIGHT0, GL_SPECULAR,Color4f::Construct(glas.baseLightSpecularColor).V()); + + glLightfv(GL_LIGHT1, GL_AMBIENT, Color4f::Construct(glas.baseLightAmbientColor).V()); + glLightfv(GL_LIGHT1, GL_DIFFUSE, Color4f::Construct(glas.baseLightDiffuseColor).V()); + glLightfv(GL_LIGHT1, GL_SPECULAR,Color4f::Construct(glas.baseLightSpecularColor).V()); + if(rm.fancyLighting) + { + glLightfv(GL_LIGHT0, GL_DIFFUSE, Color4f::Construct(glas.fancyFLightDiffuseColor).V()); + glLightfv(GL_LIGHT1, GL_DIFFUSE, Color4f::Construct(glas.fancyBLightDiffuseColor).V()); + } + } + else glDisable(GL_LIGHTING); +} + +void GLArea::setSnapshotSetting(const SnapshotSetting & s) +{ + ss=s; +} + +void GLArea::setView() +{ + glViewport(0,0, this->width(),this->height()); + curSiz.setWidth(this->width()); + curSiz.setHeight(this->height()); + + GLfloat fAspect = (GLfloat)curSiz.width()/ curSiz.height(); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + // This parameter is the one that controls: + // HOW LARGE IS THE TRACKBALL ICON ON THE SCREEN. + float viewRatio = 1.75f; + float cameraDist = viewRatio / tanf(vcg::math::ToRad(fov*.5f)); + + nearPlane = cameraDist - 2.f*clipRatioNear; + farPlane = cameraDist + 10.f*clipRatioFar; + if(nearPlane<=cameraDist*.1f) nearPlane=cameraDist*.1f; + + if (!takeSnapTile) + { + if(fov==5) glOrtho( -viewRatio*fAspect, viewRatio*fAspect, -viewRatio, viewRatio, cameraDist - 2.f*clipRatioNear, cameraDist+2.f*clipRatioFar); + else gluPerspective(fov, fAspect, nearPlane, farPlane); + } + else setTiledView(fov, viewRatio, fAspect, nearPlane, farPlane, cameraDist); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(0, 0, cameraDist,0, 0, 0, 0, 1, 0); +} + +void GLArea::setTiledView(GLdouble fovY, float viewRatio, float fAspect, GLdouble zNear, GLdouble zFar, float cameraDist) +{ + if(fovY<=5) + { + GLdouble fLeft = -viewRatio*fAspect; + GLdouble fRight = viewRatio*fAspect; + GLdouble fBottom = -viewRatio; + GLdouble fTop = viewRatio; + + GLdouble tDimX = fabs(fRight-fLeft) / totalCols; + GLdouble tDimY = fabs(fTop-fBottom) / totalRows; + + + glOrtho(fLeft + tDimX * tileCol, fLeft + tDimX * (tileCol+1), /* left, right */ + fBottom + tDimY * tileRow, fBottom + tDimY * (tileRow+1), /* bottom, top */ + cameraDist - 2.f*clipRatioNear, cameraDist+2.f*clipRatioFar); + } + else + { + GLdouble fTop = zNear * tan(math::ToRad(fovY/2.0)); + GLdouble fRight = fTop * fAspect; + GLdouble fBottom = -fTop; + GLdouble fLeft = -fRight; + + // tile Dimension + GLdouble tDimX = fabs(fRight-fLeft) / totalCols; + GLdouble tDimY = fabs(fTop-fBottom) / totalRows; + + glFrustum(fLeft + tDimX * tileCol, fLeft + tDimX * (tileCol+1), + fBottom + tDimY * tileRow, fBottom + tDimY * (tileRow+1), zNear, zFar); + } +} + +void GLArea::updateFps(float deltaTime) +{ + static float fpsVector[10]; + static int j=0; + float averageFps=0; + if (deltaTime>0) { + fpsVector[j]=deltaTime; + j=(j+1) % 10; + } + for (int i=0;i<10;i++) averageFps+=fpsVector[i]; + cfps=1000.0f/(averageFps/10); + lastTime=deltaTime; +} + +void GLArea::resetTrackBall() +{ + trackball.Reset(); + float newScale= 3.0f/meshDoc->bbox().Diag(); + trackball.track.sca = newScale; + trackball.track.tra = -meshDoc->bbox().Center(); + updateGL(); +} + +void GLArea::hideEvent(QHideEvent * /*event*/) +{ + trackball.current_button=0; +} + +void GLArea::sendViewPos(QString name) +{ + #ifndef VCG_USE_EIGEN + Point3f pos= trackball.track.InverseMatrix() *Inverse(trackball.camera.model) *Point3f(0,0,0); + #else + Point3f pos= Eigen::Transform3f(trackball.track.InverseMatrix()) * Eigen::Transform3f(Inverse(trackball.camera.model)).translation(); + #endif + emit transmitViewPos(name, pos); +} + +void GLArea::sendSurfacePos(QString name) +{ + nameToGetPickPos = name; + hasToGetPickPos=true; +} + +void GLArea::sendViewDir(QString name) +{ + Point3f dir= getViewDir(); + emit transmitViewDir(name,dir); +} + +void GLArea::sendCameraPos(QString name) +{ + Point3f pos=meshDoc->mm()->cm.shot.GetViewPoint(); + emit transmitViewDir(name, pos); +} + + +Point3f GLArea::getViewDir() +{ + vcg::Matrix44f rotM; + trackball.track.rot.ToMatrix(rotM); + vcg::Invert(rotM); + return rotM*vcg::Point3f(0,0,1); +} + +void GLArea::updateCustomSettingValues( RichParameterSet& rps ) +{ + glas.updateGlobalParameterSet(rps); + this->update(); +} + +void GLArea::initGlobalParameterSet( RichParameterSet * defaultGlobalParamSet) +{ + GLAreaSetting::initGlobalParameterSet(defaultGlobalParamSet); +} + diff --git a/src/meshlab_2.01/glarea.h b/src/meshlab_2.01/glarea.h new file mode 100644 index 000000000..b7a4bd24b --- /dev/null +++ b/src/meshlab_2.01/glarea.h @@ -0,0 +1,316 @@ +/**************************************************************************** +* MeshLab o o * +* An extendible mesh processor o o * +* _ O _ * +* Copyright(C) 2005, 2006 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef GLAREA_H +#define GLAREA_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../common/interfaces.h" +#include "../common/filterscript.h" +//#include "layerDialog.h" ** +#include "glarea_setting.h" +#include "viewer.h" +#include "multiViewer_Container.h" + +#define SSHOT_BYTES_PER_PIXEL 4 + +enum LightingModel{LDOUBLE,LFANCY}; + + +class SnapshotSetting +{ +public: + QString outdir; + QString basename; + int counter; + int resolution; + + SnapshotSetting() + { + outdir="."; + basename="snapshot"; + counter=0; + resolution=1; + }; +}; + +class MeshModel; +class GLArea : public QGLWidget, public Viewer +{ + Q_OBJECT + +public: + GLArea(QWidget *parent, MultiViewer_Container *mvcont, RichParameterSet *current, int id, MeshDocument *meshDoc); + ~GLArea(); + static void initGlobalParameterSet( RichParameterSet * /*globalparam*/); +private: + + +public: + //LayerDialog *layerDialog; ** + // Layer Management stuff. + MeshDocument *meshDoc; + MeshModel *mm(){return meshDoc->mm();} + MultiViewer_Container *mvc; + + vcg::Trackball trackball; + vcg::Trackball trackball_light; + GLLogStream log; + FilterScript filterHistory; + GLAreaSetting glas; + QSize curSiz; + QSize minimumSizeHint() const; + QSize sizeHint() const; + + QAction *getLastAppliedFilter() {return lastFilterRef;} + void setLastAppliedFilter(QAction *qa) {lastFilterRef = qa;} + + QString getFileName() {return QString(mm()->shortName());} + + void setFileName(QString name) + { + mm()->setFileName(name); + setWindowTitle(QFileInfo(name).fileName()+tr("[*]")); + //layerDialog->setWindowTitle("Layer Dialog for "+QFileInfo(name).fileName()); + + ss.basename=QFileInfo(getFileName()).baseName().append("Snap"); + } + + RenderMode & getCurrentRenderMode() {return rm;} + + const SnapshotSetting& getSnapshotSetting() {/*ss.dx=vpWidth; ss.dy=vpHeight;*/ return ss;} + void updateFps(float deltaTime); + + void showTrackBall(bool b) {trackBallVisible = b; updateGL();} + bool isHelpVisible() {return helpVisible;} + bool isTrackBallVisible() {return trackBallVisible;} + bool isDefaultTrackBall() {return activeDefaultTrackball;} + + bool isCurrent() { return mvc->currentId == id;} + + void toggleHelpVisible() {helpVisible = !helpVisible; update();} + void setBackFaceCulling(bool enabled); + void setSnapshotSetting(const SnapshotSetting & s); + void setLight(bool state); + void setLightMode(bool state,LightingModel lmode); + void saveSnapshot(); + void setLightModel(); + void setView(); + void resetTrackBall(); + std::list iDecoratorsList; + + void setRenderer(MeshRenderInterface *rend, QAction *shader){ iRenderer = rend; currentShader = shader;} + MeshRenderInterface * getRenderer() { return iRenderer; } + + // Edit Mode management + // In the glArea we can have a active Editor that can toggled into a ''suspendeed'' state + // in which the mouse event are redirected back to the GLArea to drive the camera trackball + // The decorate function of the current active editor is still called. + // EndEdit is called only when you press again the same button or when you change editor. + +public slots: + void updateTexture(); // slot for forcing the texture reload. + + //slots for changing the draw rendering and texturing mode + void setDrawMode(vcg::GLW::DrawMode mode); + void setColorMode(vcg::GLW::ColorMode mode); + void setTextureMode(vcg::GLW::TextureMode mode); + void updateCustomSettingValues(RichParameterSet& rps); + + void endEdit(){ + if(iEdit && currentEditor) + { + iEdit->EndEdit(*mm(),this); + } + iEdit= 0; + currentEditor=0; + setCursorTrack(0); + update(); + emit updateMainWindowMenus(); + } + + void setSelectFaceRendering(bool enabled); + void setSelectVertRendering(bool enabled); + + void suspendEditToggle() + { + if(currentEditor==0) return; + static QCursor qc; + if(suspendedEditor) { + suspendedEditor=false; + setCursor(qc); + } else { + suspendedEditor=true; + qc=cursor(); + setCursorTrack(0); + } + } + +signals: + void updateMainWindowMenus(); //updates the menus of the meshlab MainWindow + void glareaClosed(); //someone has closed the glarea + + void currentViewerChanged(int currentId); // set this viewer as current + +public slots: + + // Called when we change layer, notifies the edit tool if one is open + void updateLayer(); + +public: + + //call when the editor changes + void setCurrentEditAction(QAction *editAction); + + //get the currently active edit action + QAction * getCurrentEditAction() { return currentEditor; } + + //get the currently active mesh editor + MeshEditInterface * getCurrentMeshEditor() { return iEdit; } + + //see if this glAarea has a MESHEditInterface for this action + bool editorExistsForAction(QAction *editAction){ return actionToMeshEditMap.contains(editAction); } + + //add a MeshEditInterface for the given action + void addMeshEditor(QAction *editAction, MeshEditInterface *editor){ actionToMeshEditMap.insert(editAction, editor); } + + void closeEvent(QCloseEvent *event); + float lastRenderingTime() { return lastTime;} + void drawGradient(); + void drawLight(); + float getFov() { return fov; } + +// the following pairs of slot/signal implements a very simple message passing mechanism. +// a widget that has a pointer to the glarea call the sendViewDir() slot and +// setup a connect to recive the transmitViewDir signal that actually contains the point3f. +// This mechanism is used to get the view direction/position and picking point on surface in the filter parameter dialog. +// See the Point3fWidget code. +signals : + void transmitViewDir(QString name, vcg::Point3f dir); + void transmitViewPos(QString name, vcg::Point3f dir); + void transmitSurfacePos(QString name,vcg::Point3f dir); + void transmitCameraPos(QString name,vcg::Point3f dir); +public slots: + void sendViewPos(QString name); + void sendSurfacePos(QString name); + void sendViewDir(QString name); + void sendCameraPos(QString name); + + +public: + vcg::Point3f getViewDir(); + bool infoAreaVisible; // Draws the lower info area ? + bool suspendedEditor; +protected: + + void initializeGL(); + void initTexture(); + void displayInfo(); + void displayHelp(); + + QString GetMeshInfoString(); + void paintGL(); + void keyReleaseEvent ( QKeyEvent * e ); + void keyPressEvent ( QKeyEvent * e ); + void mousePressEvent(QMouseEvent *event); + +public: + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent2(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + +protected: + void mouseDoubleClickEvent ( QMouseEvent * event ) ; + void wheelEvent(QWheelEvent*e); + void tabletEvent(QTabletEvent *e); + bool drawSelection; + + void hideEvent(QHideEvent * event); + +private: + QMap curMap; + void pasteTile(); + void setTiledView(GLdouble fovY, float viewRatio, float fAspect, GLdouble zNear, GLdouble zFar, float cameraDist); + + bool helpVisible; // Help on screen + bool trackBallVisible; // Draws the trackball ? + bool activeDefaultTrackball; // keep track on active trackball + bool hasToUpdateTexture; // has to reload textures at the next redraw + bool hasToPick; // has to pick during the next redraw. + bool hasToGetPickPos; // if we are waiting for a double click for getting a surface position that has to be sent back using signal/slots (for parameters) + QString nameToGetPickPos; // the name of the parameter that has asked for the point on the surface + + vcg::Point2i pointToPick; + + //shader support + MeshRenderInterface *iRenderer; + QAction *currentShader; + QAction *lastFilterRef; // reference to last filter applied + QFont qFont; //font settings + + // Editing support + MeshEditInterface *iEdit; + QAction *currentEditor; + QAction *suspendedEditRef; // reference to last Editing Mode Used + QMap actionToMeshEditMap; + + //the last model that start edit was called with + MeshModel *lastModelEdited; + +public: + RenderMode rm; + // view setting variables + float fov; + float clipRatioFar; + float clipRatioNear; + float nearPlane; + float farPlane; + float pointSize; +private: + float cfps; + float lastTime; + + SnapshotSetting ss; + QImage snapBuffer; + bool takeSnapTile; + + enum AnimMode { AnimNone, AnimSpin, AnimInterp}; + AnimMode animMode; + int tileCol, tileRow, totalCols, totalRows; + void setCursorTrack(vcg::TrackMode *tm); + + +}; + + +#endif diff --git a/src/meshlab_2.01/glarea_setting.cpp b/src/meshlab_2.01/glarea_setting.cpp new file mode 100644 index 000000000..db1cb65e5 --- /dev/null +++ b/src/meshlab_2.01/glarea_setting.cpp @@ -0,0 +1,41 @@ +#include "glarea.h" +#include "glarea_setting.h" + +void GLAreaSetting::initGlobalParameterSet( RichParameterSet * defaultGlobalParamSet) +{ + defaultGlobalParamSet->addParam(new RichColor(backgroundBotColorParam(),QColor(128,128,255),"MeshLab Bottom BackGround Color ","MeshLab GLarea's BackGround Color(bottom corner)")); + defaultGlobalParamSet->addParam(new RichColor(backgroundTopColorParam(),QColor( 0, 0, 0),"MeshLab Top BackGround Color","MeshLab GLarea's BackGround Color(top corner)")); + defaultGlobalParamSet->addParam(new RichColor(logAreaColorParam(), QColor(128,16,16),"MeshLab GLarea's Log Area Color","MeshLab GLarea's BackGround Color(bottom corner)")); + + + defaultGlobalParamSet->addParam(new RichColor(baseLightAmbientColorParam() ,QColor( 32, 32, 32),"MeshLab Base Light Ambient Color","MeshLab GLarea's BackGround Color(bottom corner)")); + defaultGlobalParamSet->addParam(new RichColor(baseLightDiffuseColorParam() ,QColor(204,204,204),"MeshLab Base Light Diffuse Color","MeshLab GLarea's BackGround Color(top corner)")); + defaultGlobalParamSet->addParam(new RichColor(baseLightSpecularColorParam() ,QColor(255,255,255),"MeshLab Base Light Specular Color","MeshLab GLarea's BackGround Color(bottom corner)")); + + defaultGlobalParamSet->addParam(new RichColor(fancyBLightDiffuseColorParam() ,QColor(255,204,204),"MeshLab Base Light Diffuse Color","MeshLab GLarea's BackGround Color(top corner)")); + defaultGlobalParamSet->addParam(new RichColor(fancyFLightDiffuseColorParam() ,QColor(204,204,255),"MeshLab Base Light Diffuse Color","MeshLab GLarea's BackGround Color(top corner)")); + + QStringList textureMinFilterModes = (QStringList() << "Nearest" << "MipMap"); + QStringList textureMagFilterModes = (QStringList() << "Nearest" << "Linear"); + defaultGlobalParamSet->addParam(new RichEnum(textureMinFilterParam() , 1,textureMinFilterModes,"MeshLab Texture Minification Filtering","MeshLab GLarea's BackGround Color(top corner)")); + defaultGlobalParamSet->addParam(new RichEnum(textureMagFilterParam() , 1,textureMagFilterModes,"MeshLab Texture Magnification Filtering","MeshLab GLarea's BackGround Color(top corner)")); +} + + +void GLAreaSetting::updateGlobalParameterSet( RichParameterSet& rps ) +{ + logAreaColor = rps.getColor4b(logAreaColorParam()); + backgroundBotColor = rps.getColor4b(backgroundBotColorParam()); + backgroundTopColor = rps.getColor4b(backgroundTopColorParam()); + + baseLightAmbientColor = rps.getColor4b(baseLightAmbientColorParam() ); + baseLightDiffuseColor = rps.getColor4b(baseLightDiffuseColorParam() ); + baseLightSpecularColor = rps.getColor4b(baseLightSpecularColorParam() ); + + fancyBLightDiffuseColor = rps.getColor4b(fancyBLightDiffuseColorParam()); + fancyFLightDiffuseColor = rps.getColor4b(fancyFLightDiffuseColorParam()); + + textureMinFilter = rps.getEnum(this->textureMinFilterParam()); + textureMagFilter = rps.getEnum(this->textureMagFilterParam()); + +} diff --git a/src/meshlab_2.01/glarea_setting.h b/src/meshlab_2.01/glarea_setting.h new file mode 100644 index 000000000..3136b5be6 --- /dev/null +++ b/src/meshlab_2.01/glarea_setting.h @@ -0,0 +1,39 @@ +#ifndef GLAREA_SETTING_H +#define GLAREA_SETTING_H + +class GLAreaSetting +{ +public: + + vcg::Color4b baseLightAmbientColor; + vcg::Color4b baseLightDiffuseColor; + vcg::Color4b baseLightSpecularColor; + inline static QString baseLightAmbientColorParam() {return "MeshLab::Appearance::baseLightAmbientColor";} + inline static QString baseLightDiffuseColorParam() {return "MeshLab::Appearance::baseLightDiffuseColor";} + inline static QString baseLightSpecularColorParam() {return "MeshLab::Appearance::baseLightSpecularColor";} + + vcg::Color4b fancyBLightDiffuseColor; + inline static QString fancyBLightDiffuseColorParam() {return "MeshLab::Appearance::fancyBLightDiffuseColor";} + + vcg::Color4b fancyFLightDiffuseColor; + inline static QString fancyFLightDiffuseColorParam() {return "MeshLab::Appearance::fancyFLightDiffuseColor";} + + + vcg::Color4b backgroundBotColor; + vcg::Color4b backgroundTopColor; + vcg::Color4b logAreaColor; + inline static QString backgroundBotColorParam() {return "MeshLab::Appearance::backgroundBotColor";} + inline static QString backgroundTopColorParam() {return "MeshLab::Appearance::backgroundTopColor";} + inline static QString logAreaColorParam() {return "MeshLab::Appearance::logAreaColor";} + + int textureMagFilter; + int textureMinFilter; + inline static QString textureMinFilterParam() {return "MeshLab::Appearance::textureMinFilter";} + inline static QString textureMagFilterParam() {return "MeshLab::Appearance::textureMagFilter";} + + void updateGlobalParameterSet( RichParameterSet& rps ); + static void initGlobalParameterSet( RichParameterSet * defaultGlobalParamSet); +}; + + +#endif // GLAREA_SETTING_H diff --git a/src/meshlab_2.01/images/100mesh.html b/src/meshlab_2.01/images/100mesh.html new file mode 100644 index 000000000..020faf537 --- /dev/null +++ b/src/meshlab_2.01/images/100mesh.html @@ -0,0 +1,25 @@ + + + + +
+
+ + Congratulations! +
+
+ You have successfully used MeshLab to open and process more than one hundred meshes!
+ We hope that this means that you have found MeshLab useful.

+ Please consider to send a short email to the developers of MeshLab, describing how MeshLab fitted your needs, + attach to the email some screenshots of your processed meshes and tell us your impression about MeshLab.
+
+ MeshLab is developed on public funding and assessment of its impact on the whole community is necessary, so, please, spend a couple of minutes writing down a mail to us.
+ Thanks for using MeshLab
+
+ Paolo Cignoni
+
+
+
+
+ + \ No newline at end of file diff --git a/src/meshlab_2.01/images/EasyIcons.png b/src/meshlab_2.01/images/EasyIcons.png new file mode 100644 index 000000000..b9262a7f3 Binary files /dev/null and b/src/meshlab_2.01/images/EasyIcons.png differ diff --git a/src/meshlab_2.01/images/EasyIconsTransp.png b/src/meshlab_2.01/images/EasyIconsTransp.png new file mode 100644 index 000000000..52c58aa43 Binary files /dev/null and b/src/meshlab_2.01/images/EasyIconsTransp.png differ diff --git a/src/meshlab_2.01/images/backlines.png b/src/meshlab_2.01/images/backlines.png new file mode 100644 index 000000000..69a39be9a Binary files /dev/null and b/src/meshlab_2.01/images/backlines.png differ diff --git a/src/meshlab_2.01/images/bbox.png b/src/meshlab_2.01/images/bbox.png new file mode 100644 index 000000000..7f2e0d9e4 Binary files /dev/null and b/src/meshlab_2.01/images/bbox.png differ diff --git a/src/meshlab_2.01/images/cursors/paint.png b/src/meshlab_2.01/images/cursors/paint.png new file mode 100644 index 000000000..9c5251183 Binary files /dev/null and b/src/meshlab_2.01/images/cursors/paint.png differ diff --git a/src/meshlab_2.01/images/cursors/plain.png b/src/meshlab_2.01/images/cursors/plain.png new file mode 100644 index 000000000..ae401137e Binary files /dev/null and b/src/meshlab_2.01/images/cursors/plain.png differ diff --git a/src/meshlab_2.01/images/cursors/plain_eye.png b/src/meshlab_2.01/images/cursors/plain_eye.png new file mode 100644 index 000000000..6f9a68ab1 Binary files /dev/null and b/src/meshlab_2.01/images/cursors/plain_eye.png differ diff --git a/src/meshlab_2.01/images/cursors/plain_pan.png b/src/meshlab_2.01/images/cursors/plain_pan.png new file mode 100644 index 000000000..bb39829ea Binary files /dev/null and b/src/meshlab_2.01/images/cursors/plain_pan.png differ diff --git a/src/meshlab_2.01/images/cursors/plain_trackball.png b/src/meshlab_2.01/images/cursors/plain_trackball.png new file mode 100644 index 000000000..80653343c Binary files /dev/null and b/src/meshlab_2.01/images/cursors/plain_trackball.png differ diff --git a/src/meshlab_2.01/images/cursors/plain_zoom.png b/src/meshlab_2.01/images/cursors/plain_zoom.png new file mode 100644 index 000000000..871833084 Binary files /dev/null and b/src/meshlab_2.01/images/cursors/plain_zoom.png differ diff --git a/src/meshlab_2.01/images/cursors/sel_rect.png b/src/meshlab_2.01/images/cursors/sel_rect.png new file mode 100644 index 000000000..a2a28a25f Binary files /dev/null and b/src/meshlab_2.01/images/cursors/sel_rect.png differ diff --git a/src/meshlab_2.01/images/cursors/sel_rect_minus.png b/src/meshlab_2.01/images/cursors/sel_rect_minus.png new file mode 100644 index 000000000..bbfb389b9 Binary files /dev/null and b/src/meshlab_2.01/images/cursors/sel_rect_minus.png differ diff --git a/src/meshlab_2.01/images/cursors/sel_rect_plus.png b/src/meshlab_2.01/images/cursors/sel_rect_plus.png new file mode 100644 index 000000000..26d6ccac4 Binary files /dev/null and b/src/meshlab_2.01/images/cursors/sel_rect_plus.png differ diff --git a/src/meshlab_2.01/images/eye.ico b/src/meshlab_2.01/images/eye.ico new file mode 100644 index 000000000..4d855589c Binary files /dev/null and b/src/meshlab_2.01/images/eye.ico differ diff --git a/src/meshlab_2.01/images/eye.svg b/src/meshlab_2.01/images/eye.svg new file mode 100644 index 000000000..47ab766b2 --- /dev/null +++ b/src/meshlab_2.01/images/eye.svg @@ -0,0 +1,1363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/meshlab_2.01/images/eye128.png b/src/meshlab_2.01/images/eye128.png new file mode 100644 index 000000000..1e71f12c6 Binary files /dev/null and b/src/meshlab_2.01/images/eye128.png differ diff --git a/src/meshlab_2.01/images/eye155.jpg b/src/meshlab_2.01/images/eye155.jpg new file mode 100644 index 000000000..f1560ac06 Binary files /dev/null and b/src/meshlab_2.01/images/eye155.jpg differ diff --git a/src/meshlab_2.01/images/eye16.png b/src/meshlab_2.01/images/eye16.png new file mode 100644 index 000000000..00507153a Binary files /dev/null and b/src/meshlab_2.01/images/eye16.png differ diff --git a/src/meshlab_2.01/images/eye48.png b/src/meshlab_2.01/images/eye48.png new file mode 100644 index 000000000..73f230b2f Binary files /dev/null and b/src/meshlab_2.01/images/eye48.png differ diff --git a/src/meshlab_2.01/images/eye512.jpg b/src/meshlab_2.01/images/eye512.jpg new file mode 100644 index 000000000..f75aa9e20 Binary files /dev/null and b/src/meshlab_2.01/images/eye512.jpg differ diff --git a/src/meshlab_2.01/images/eye512.png b/src/meshlab_2.01/images/eye512.png new file mode 100644 index 000000000..2f787916d Binary files /dev/null and b/src/meshlab_2.01/images/eye512.png differ diff --git a/src/meshlab_2.01/images/eye64.png b/src/meshlab_2.01/images/eye64.png new file mode 100644 index 000000000..b203b35db Binary files /dev/null and b/src/meshlab_2.01/images/eye64.png differ diff --git a/src/meshlab_2.01/images/eye_128_splash.png b/src/meshlab_2.01/images/eye_128_splash.png new file mode 100644 index 000000000..13c242cf7 Binary files /dev/null and b/src/meshlab_2.01/images/eye_128_splash.png differ diff --git a/src/meshlab_2.01/images/eye_256_splash.png b/src/meshlab_2.01/images/eye_256_splash.png new file mode 100644 index 000000000..15d27d4b5 Binary files /dev/null and b/src/meshlab_2.01/images/eye_256_splash.png differ diff --git a/src/meshlab_2.01/images/eye_512_splash.png b/src/meshlab_2.01/images/eye_512_splash.png new file mode 100644 index 000000000..0ea9ba14a Binary files /dev/null and b/src/meshlab_2.01/images/eye_512_splash.png differ diff --git a/src/meshlab_2.01/images/eye_cropped.png b/src/meshlab_2.01/images/eye_cropped.png new file mode 100644 index 000000000..86c32af84 Binary files /dev/null and b/src/meshlab_2.01/images/eye_cropped.png differ diff --git a/src/meshlab_2.01/images/eye_splash.svg b/src/meshlab_2.01/images/eye_splash.svg new file mode 100644 index 000000000..8c3448c3c --- /dev/null +++ b/src/meshlab_2.01/images/eye_splash.svg @@ -0,0 +1,1390 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/meshlab_2.01/images/eyedoc_256.png b/src/meshlab_2.01/images/eyedoc_256.png new file mode 100644 index 000000000..878b02757 Binary files /dev/null and b/src/meshlab_2.01/images/eyedoc_256.png differ diff --git a/src/meshlab_2.01/images/flat.png b/src/meshlab_2.01/images/flat.png new file mode 100644 index 000000000..d39b579b9 Binary files /dev/null and b/src/meshlab_2.01/images/flat.png differ diff --git a/src/meshlab_2.01/images/flatlines.png b/src/meshlab_2.01/images/flatlines.png new file mode 100644 index 000000000..5fe65c66c Binary files /dev/null and b/src/meshlab_2.01/images/flatlines.png differ diff --git a/src/meshlab_2.01/images/info.png b/src/meshlab_2.01/images/info.png new file mode 100644 index 000000000..cbe3e1e83 Binary files /dev/null and b/src/meshlab_2.01/images/info.png differ diff --git a/src/meshlab_2.01/images/layer_edit_locked.png b/src/meshlab_2.01/images/layer_edit_locked.png new file mode 100644 index 000000000..beb9a816b Binary files /dev/null and b/src/meshlab_2.01/images/layer_edit_locked.png differ diff --git a/src/meshlab_2.01/images/layer_edit_unlocked.png b/src/meshlab_2.01/images/layer_edit_unlocked.png new file mode 100644 index 000000000..c02fe2156 Binary files /dev/null and b/src/meshlab_2.01/images/layer_edit_unlocked.png differ diff --git a/src/meshlab_2.01/images/layer_eye_close.png b/src/meshlab_2.01/images/layer_eye_close.png new file mode 100644 index 000000000..9473dbfbb Binary files /dev/null and b/src/meshlab_2.01/images/layer_eye_close.png differ diff --git a/src/meshlab_2.01/images/layer_eye_open.png b/src/meshlab_2.01/images/layer_eye_open.png new file mode 100644 index 000000000..512cdd8a1 Binary files /dev/null and b/src/meshlab_2.01/images/layer_eye_open.png differ diff --git a/src/meshlab_2.01/images/layer_icons.svg b/src/meshlab_2.01/images/layer_icons.svg new file mode 100644 index 000000000..e4ee9aaed --- /dev/null +++ b/src/meshlab_2.01/images/layer_icons.svg @@ -0,0 +1,540 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/meshlab_2.01/images/layers.png b/src/meshlab_2.01/images/layers.png new file mode 100644 index 000000000..c81d9ce7d Binary files /dev/null and b/src/meshlab_2.01/images/layers.png differ diff --git a/src/meshlab_2.01/images/lightoff.png b/src/meshlab_2.01/images/lightoff.png new file mode 100644 index 000000000..d28795018 Binary files /dev/null and b/src/meshlab_2.01/images/lightoff.png differ diff --git a/src/meshlab_2.01/images/lighton.png b/src/meshlab_2.01/images/lighton.png new file mode 100644 index 000000000..fd9649097 Binary files /dev/null and b/src/meshlab_2.01/images/lighton.png differ diff --git a/src/meshlab_2.01/images/logo.png b/src/meshlab_2.01/images/logo.png new file mode 100644 index 000000000..bc5fba0ed Binary files /dev/null and b/src/meshlab_2.01/images/logo.png differ diff --git a/src/meshlab_2.01/images/logo_aimatshape.png b/src/meshlab_2.01/images/logo_aimatshape.png new file mode 100644 index 000000000..176b944c4 Binary files /dev/null and b/src/meshlab_2.01/images/logo_aimatshape.png differ diff --git a/src/meshlab_2.01/images/logo_epoch.png b/src/meshlab_2.01/images/logo_epoch.png new file mode 100644 index 000000000..0dbd8b288 Binary files /dev/null and b/src/meshlab_2.01/images/logo_epoch.png differ diff --git a/src/meshlab_2.01/images/logo_epoch_2.png b/src/meshlab_2.01/images/logo_epoch_2.png new file mode 100644 index 000000000..0dbd8b288 Binary files /dev/null and b/src/meshlab_2.01/images/logo_epoch_2.png differ diff --git a/src/meshlab_2.01/images/meshlab.icns b/src/meshlab_2.01/images/meshlab.icns new file mode 100644 index 000000000..395517331 Binary files /dev/null and b/src/meshlab_2.01/images/meshlab.icns differ diff --git a/src/meshlab_2.01/images/meshlab_icons.svg b/src/meshlab_2.01/images/meshlab_icons.svg new file mode 100644 index 000000000..b93dfe77e --- /dev/null +++ b/src/meshlab_2.01/images/meshlab_icons.svg @@ -0,0 +1,1176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/meshlab_2.01/images/meshlab_obj.icns b/src/meshlab_2.01/images/meshlab_obj.icns new file mode 100644 index 000000000..e87cdada3 Binary files /dev/null and b/src/meshlab_2.01/images/meshlab_obj.icns differ diff --git a/src/meshlab_2.01/images/meshlab_obj.svg b/src/meshlab_2.01/images/meshlab_obj.svg new file mode 100644 index 000000000..7dcc0fe3f --- /dev/null +++ b/src/meshlab_2.01/images/meshlab_obj.svg @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/src/meshlab_2.01/images/no_edit.png b/src/meshlab_2.01/images/no_edit.png new file mode 100644 index 000000000..fe7be2f97 Binary files /dev/null and b/src/meshlab_2.01/images/no_edit.png differ diff --git a/src/meshlab_2.01/images/old_icons.xar b/src/meshlab_2.01/images/old_icons.xar new file mode 100644 index 000000000..7a5d3fea6 Binary files /dev/null and b/src/meshlab_2.01/images/old_icons.xar differ diff --git a/src/meshlab_2.01/images/open.png b/src/meshlab_2.01/images/open.png new file mode 100644 index 000000000..3a9a03b64 Binary files /dev/null and b/src/meshlab_2.01/images/open.png differ diff --git a/src/meshlab_2.01/images/points.png b/src/meshlab_2.01/images/points.png new file mode 100644 index 000000000..6155c03e3 Binary files /dev/null and b/src/meshlab_2.01/images/points.png differ diff --git a/src/meshlab_2.01/images/reload.png b/src/meshlab_2.01/images/reload.png new file mode 100644 index 000000000..1d22f6dd7 Binary files /dev/null and b/src/meshlab_2.01/images/reload.png differ diff --git a/src/meshlab_2.01/images/save.png b/src/meshlab_2.01/images/save.png new file mode 100644 index 000000000..7a4ab5910 Binary files /dev/null and b/src/meshlab_2.01/images/save.png differ diff --git a/src/meshlab_2.01/images/selected.png b/src/meshlab_2.01/images/selected.png new file mode 100644 index 000000000..2d81d20c2 Binary files /dev/null and b/src/meshlab_2.01/images/selected.png differ diff --git a/src/meshlab_2.01/images/selected_face.png b/src/meshlab_2.01/images/selected_face.png new file mode 100644 index 000000000..f76161288 Binary files /dev/null and b/src/meshlab_2.01/images/selected_face.png differ diff --git a/src/meshlab_2.01/images/selected_vert.png b/src/meshlab_2.01/images/selected_vert.png new file mode 100644 index 000000000..db912598e Binary files /dev/null and b/src/meshlab_2.01/images/selected_vert.png differ diff --git a/src/meshlab_2.01/images/smooth.png b/src/meshlab_2.01/images/smooth.png new file mode 100644 index 000000000..21800bc98 Binary files /dev/null and b/src/meshlab_2.01/images/smooth.png differ diff --git a/src/meshlab_2.01/images/snapshot.png b/src/meshlab_2.01/images/snapshot.png new file mode 100644 index 000000000..9b5b9efe7 Binary files /dev/null and b/src/meshlab_2.01/images/snapshot.png differ diff --git a/src/meshlab_2.01/images/textures.png b/src/meshlab_2.01/images/textures.png new file mode 100644 index 000000000..a132cd3ea Binary files /dev/null and b/src/meshlab_2.01/images/textures.png differ diff --git a/src/meshlab_2.01/images/wire.png b/src/meshlab_2.01/images/wire.png new file mode 100644 index 000000000..bd2bb73ff Binary files /dev/null and b/src/meshlab_2.01/images/wire.png differ diff --git a/src/meshlab_2.01/layerDialog.cpp b/src/meshlab_2.01/layerDialog.cpp new file mode 100644 index 000000000..189b15a4d --- /dev/null +++ b/src/meshlab_2.01/layerDialog.cpp @@ -0,0 +1,197 @@ +/**************************************************************************** +* MeshLab o o * +* An extendible mesh processor o o * +* _ O _ * +* Copyright(C) 2005, 2006 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +/**************************************************************************** +History + +$Log: stdpardialog.cpp,v $ + +****************************************************************************/ + +#include +#include + +#include "ui_layerDialog.h" +#include "layerDialog.h" +#include "glarea.h" +#include "mainwindow.h" + +using namespace std; + +LayerDialog::LayerDialog(QWidget *parent ) : QDockWidget(parent) +{ + ui = new Ui::layerDialog(); + setWindowFlags( windowFlags() | Qt::WindowStaysOnTopHint | Qt::SubWindow); + setVisible(false); + LayerDialog::ui->setupUi(this); + //gla=qobject_cast(parent); + //mw=qobject_cast(gla->parentWidget()->parentWidget()); + mw=qobject_cast(parent->parentWidget()->parentWidget()); + + connect(ui->layerTableWidget, SIGNAL(cellClicked(int, int)), this, SLOT(toggleStatus(int,int)) ); + connect(ui->addButton, SIGNAL(clicked()), mw, SLOT(openIn()) ); + connect(ui->deleteButton, SIGNAL(clicked()), mw, SLOT(delCurrentMesh()) ); + + this->setContextMenuPolicy(Qt::CustomContextMenu); + ui->layerTableWidget->setContextMenuPolicy(Qt::CustomContextMenu); + + connect(ui->layerTableWidget, SIGNAL(customContextMenuRequested(const QPoint&)), + this, SLOT(showContextMenu(const QPoint&))); + connect(ui->menuButton, SIGNAL(clicked()), this, SLOT(showLayerMenu())); + //connect(gla->meshDoc, SIGNAL(currentMeshChanged(int)),this, SLOT(updateTable())); ** + //connect( ui->deleteButton, SIGNAL(cellClicked(int, int)) , this, SLOT(openIn(int,int)) ); +} +void LayerDialog::toggleStatus(int row, int col) +{ + switch(col) + { + case 0 : + //the user has chosen to switch the layer + mw->GLA()->meshDoc->setCurrentMesh(row); + break; + case 1 : + { + //the user has clicke on one of the eyes + QList &meshList=mw->GLA()->meshDoc->meshList; + // NICE TRICK. + // If the user has pressed ctrl when clicking on the eye icon, only that layer will remain visible + // Very useful for comparing meshes + + if(QApplication::keyboardModifiers() == Qt::ControlModifier) + foreach(MeshModel *mp, meshList) + { + mp->visible=false; + } + + if(meshList.at(row)->visible) meshList.at(row)->visible = false; + else meshList.at(row)->visible = true; + } + } + //make sure the right row is colored or that they right eye is drawn (open or closed) + updateTable(); + mw->GLA()->update(); +} + +void LayerDialog::showEvent ( QShowEvent * /* event*/ ) +{ + updateTable(); +} + +void LayerDialog::showLayerMenu() +{ + foreach (QWidget *widget, QApplication::topLevelWidgets()) { + MainWindow* mainwindow = dynamic_cast(widget); + if (mainwindow) + { + //mainwindow->layerMenu()->popup(ui->menuButton->mapToGlobal(QPoint(10,10)));** + return; + } + } +} + +void LayerDialog::showContextMenu(const QPoint& pos) +{ + // switch layer + int row = ui->layerTableWidget->rowAt(pos.y()); + if (row>=0) + mw->GLA()->meshDoc->setCurrentMesh(row); + + foreach (QWidget *widget, QApplication::topLevelWidgets()) { + MainWindow* mainwindow = dynamic_cast(widget); + if (mainwindow) + { + //mainwindow->layerMenu()->popup(ui->layerTableWidget->mapToGlobal(pos));** + return; + } + } +} + +void LayerDialog::updateLog(GLLogStream &log) +{ + QList< pair > &logStringList=log.S; + ui->logPlainTextEdit->clear(); + //ui->logPlainTextEdit->setFont(QFont("Courier",10)); + + pair logElem; + QString preWarn = " Warning: " ; + QString preSystem = " System: " ; + QString preFilter = " Filter: " ; + + QString post = ""; + + foreach(logElem, logStringList){ + QString logText = logElem.second; + if(logElem.first == GLLogStream::SYSTEM) logText = preSystem + logText + post; + if(logElem.first == GLLogStream::WARNING) logText = preWarn + logText + post; + if(logElem.first == GLLogStream::FILTER) logText = preFilter + logText + post; + ui->logPlainTextEdit->appendHtml(logText); + } +} + +void LayerDialog::updateTable() +{ + if(!isVisible()) return; + QList &meshList=mw->GLA()->meshDoc->meshList; + //qDebug("Items in list: %d", meshList.size()); + ui->layerTableWidget->clear(); + ui->layerTableWidget->setColumnCount(3); + ui->layerTableWidget->setRowCount(meshList.size()); + ui->layerTableWidget->horizontalHeader()->hide(); + ui->layerTableWidget->setColumnWidth(1,32); + ui->layerTableWidget->setColumnWidth(2,32); + ui->layerTableWidget->setShowGrid(false); + for(int i=0;ifileName.c_str()); + + item = new QTableWidgetItem(meshList.at(i)->shortName()); + if(meshList.at(i)==mw->GLA()->mm()) { + item->setBackground(QBrush(Qt::yellow)); + item->setForeground(QBrush(Qt::blue)); + } + ui->layerTableWidget->setItem(i,0,item ); + + if(meshList.at(i)->visible){ + item = new QTableWidgetItem(QIcon(":/images/layer_eye_open.png"),""); + } else { + item = new QTableWidgetItem(QIcon(":/images/layer_eye_close.png"),""); + } + item->setFlags(Qt::ItemIsEnabled); + ui->layerTableWidget->setItem(i,1,item ); + + item = new QTableWidgetItem(QIcon(":/images/layer_edit_unlocked.png"),QString()); + item->setFlags(Qt::ItemIsEnabled); + ui->layerTableWidget->setItem(i,2,item ); + + } + ui->layerTableWidget->resizeColumnsToContents(); + //ui->layerTableWidget->adjustSize(); + + //this->adjustSize(); + +} + +LayerDialog::~LayerDialog() +{ + delete ui; +} diff --git a/src/meshlab_2.01/layerDialog.h b/src/meshlab_2.01/layerDialog.h new file mode 100644 index 000000000..6d3cbb491 --- /dev/null +++ b/src/meshlab_2.01/layerDialog.h @@ -0,0 +1,66 @@ +/**************************************************************************** +* MeshLab o o * +* An extendible mesh processor o o * +* _ O _ * +* Copyright(C) 2005, 2006 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +/**************************************************************************** +History + +$Log: stdpardialog.cpp,v $ +****************************************************************************/ +#ifndef LAYER_DIALOG_H +#define LAYER_DIALOG_H +#include + +class GLArea; +class MainWindow; +class QTableWidget; +class GLLogStream; + +#include + +namespace Ui +{ + class layerDialog; +} + +class LayerDialog : public QDockWidget +{ + Q_OBJECT +public: + LayerDialog(QWidget *parent = 0); + ~LayerDialog(); + void updateLog(GLLogStream &Log); + +public slots: + void updateTable(); + void toggleStatus(int row, int column); + void showEvent ( QShowEvent * event ); + void showContextMenu(const QPoint& pos); + void showLayerMenu(); + +private: + Ui::layerDialog* ui; + //GLArea *gla; ** + MainWindow *mw; +}; + + +#endif diff --git a/src/meshlab_2.01/main.cpp b/src/meshlab_2.01/main.cpp new file mode 100644 index 000000000..59cabaf81 --- /dev/null +++ b/src/meshlab_2.01/main.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +/**************************************************************************** + History +$Log$ +Revision 1.8 2008/03/08 17:22:57 cignoni +added plugins path settings for macs + +Revision 1.7 2008/02/24 18:08:50 cignoni +added -h and --help standard options + +Revision 1.6 2007/03/27 12:20:09 cignoni +Revamped logging iterface, changed function names in automatic parameters, better selection handling + +Revision 1.5 2006/11/08 01:04:48 cignoni +First version with http communications + +Revision 1.4 2006/02/01 12:45:29 glvertex +- Solved openig bug when running by command line + +Revision 1.3 2005/12/01 02:24:50 davide_portelli +Mainwindow Splitted----->[ mainwindow_Init.cpp ]&&[ mainwindow_RunTime.cpp ] + +Revision 1.2 2005/11/21 12:12:54 cignoni +Added copyright info + +****************************************************************************/ + +#include +#include +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + +#if defined(Q_OS_MAC) + QDir dir(QApplication::applicationDirPath()); + dir.cdUp(); + dir.cd("plugins"); + QApplication::setLibraryPaths(QStringList(dir.absolutePath())); +#endif + QCoreApplication::setOrganizationName("VCG"); + QCoreApplication::setApplicationName("MeshLab"); + + if(argc>1) + { + QString helpOpt1="-h"; + QString helpOpt2="--help"; + if( (helpOpt1==argv[1]) || (helpOpt2==argv[1]) ) + { + printf("\n\n" + " MeshLab: an open source mesh processing system\n" + " Paolo Cignoni (and many many others) \n" + " Visual Computing Lab\n" + " ISTI - CNR \n\n" + "usage:\n\n" + " meshlab [meshfile] \n\n" + "Look at --- http://meshlab.sourceforge.net/wiki --- for a longer documentation\n\n" + ); + exit(-1); + } + } + + MainWindow window; + window.showMaximized(); + + // This filter is installed to intercept the open events sent directly by the Operative System. + FileOpenEater *filterObj=new FileOpenEater(); + filterObj->mainWindow=&window; + app.installEventFilter(filterObj); + app.processEvents(); + if(argc>1) + { + QString helpOpt1="-h"; + QString helpOpt2="--help"; + if( (helpOpt1==argv[1]) || (helpOpt2==argv[1]) ) + printf( + "usage:\n" + "meshlab \n" + "Look at http://meshlab.sourceforge.net/wiki\n" + "for a longer documentation\n" + ); + window.open(argv[1]); + } + else if(filterObj->noEvent) window.open(); + + return app.exec(); +} diff --git a/src/meshlab_2.01/mainwindow.h b/src/meshlab_2.01/mainwindow.h new file mode 100644 index 000000000..47ef96b87 --- /dev/null +++ b/src/meshlab_2.01/mainwindow.h @@ -0,0 +1,356 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +//None of this should happen if we are compiling c, not c++ +#ifdef __cplusplus +#include + +#include +#include +#include +#include +#include +#include "../common/pluginmanager.h" +#include "glarea.h" +#include "stdpardialog.h" +#include "multiViewer_Container.h" + +#define MAXRECENTFILES 4 + +class QAction; +class QActionGroup; +class QMenu; +class QScrollArea; +class QSignalMapper; +class QProgressDialog; +class QHttp; + + +class MainWindow : public QMainWindow, MainWindowInterface +{ + Q_OBJECT + +public: + // callback function to execute a filter + //void executeFilter(QAction *action, RichParameterSet &srcpar, bool isPreview); + + MainWindow(); + static bool QCallBack(const int pos, const char * str); + const QString appName() const {return tr("MeshLab v")+appVer(); } + const QString appVer() const {return tr("1.2.3b"); } + +signals: + void dispatchCustomSettings(RichParameterSet& rps); + +public slots: + + bool open(QString fileName=QString(), GLArea *gla=0); + bool openIn(QString fileName=QString()); + bool openProject(QString fileName=QString()); + void saveProject(); + void delCurrentMesh(); + void updateGL(); + void endEdit(); + void updateCustomSettings(); + +private slots: + + //////////// Slot Menu File ////////////////////// + void reload(); + void openRecentFile(); + bool saveAs(QString fileName = QString()); + bool save(); + //bool saveSnapshot(); + /////////////Slot Menu Edit //////////////////////// + //void applyEditMode(); + //void suspendEditMode(); + ///////////Slot Menu Filter //////////////////////// + //void startFilter(); + //void applyLastFilter(); + //void runFilterScript(); + //void showFilterScript(); + /////////// Slot Menu Render ///////////////////// + void renderBbox(); + void renderPoint(); + void renderWire(); + void renderFlat(); + void renderFlatLine(); + void renderHiddenLines(); + void renderSmooth(); + void renderTexture(); + void setLight(); + void setDoubleLighting(); + void setFancyLighting(); + void setColorMode(QAction *qa); + void applyRenderMode(); + //void applyColorMode(); + void toggleBackFaceCulling(); + void toggleSelectFaceRendering(); + void toggleSelectVertRendering(); + //void applyDecorateMode(); + ///////////Slot Menu View //////////////////////// + void fullScreen(); + void showToolbarFile(); + void showToolbarRender(); + void showInfoPane(); + void showTrackBall(); + void resetTrackBall(); + void showLayerDlg(); + ///////////Slot Menu Windows ///////////////////// + void updateWindowMenu(); + void updateMenus(); + void updateStdDialog(); + + ///////////Slot Menu Preferences ///////////////// + //void setCustomize(); + void setSplit(QAction *qa); + void setUnsplit(); + ///////////Slot Menu Help //////////////////////// + /*void about(); + void aboutPlugins();*/ + void helpOnline(); + void helpOnscreen(); + void submitBug(); + void checkForUpdates(bool verboseFlag=true); + + ///////////Slot General Purpose //////////////////////// + + void dropEvent ( QDropEvent * event ); + void dragEnterEvent(QDragEnterEvent *); + void connectionDone(bool status); + + ///////////Solt Wrapper for QMdiArea ////////////////// + void wrapSetActiveSubWindow(QWidget* window); +private: + void createStdPluginWnd(); // this one is + void initGlobalParameters(); + void createActions(); + void createMenus(); + /*void fillFilterMenu(); + void fillDecorateMenu();*/ + void fillRenderMenu(); + //void fillEditMenu(); + void createToolBars(); + void loadMeshLabSettings(); + void loadPlugins(); + void keyPressEvent(QKeyEvent *); + void updateRecentFileActions(); + void setCurrentFile(const QString &fileName); + void addToMenu(QList, QMenu *menu, const char *slot); + + + QHttp *httpReq; + QBuffer myLocalBuf; + int idHost; + int idGet; + bool VerboseCheckingFlag; + + MeshlabStdDialog *stddialog; + static QProgressBar *qb; + QMdiArea *mdiarea; + QSignalMapper *windowMapper; + QDir pluginsDir; + QStringList pluginFileNames; + + PluginManager PM; + + /* + Note this part should be detached from MainWindow just like the loading plugin part. + + For each running instance of meshlab, for the global params we have default (hardwired) values and current(saved,modified) values. + At the start up the initGlobalParameterSet function (of decorations and of glarea and of ... ) is called with the empty RichParameterSet defaultGlobalParams (to collect the default values) + At the start up the currentGlobalParams is filled with the values saved in the registry. + */ + + RichParameterSet currentGlobalParams; + RichParameterSet defaultGlobalParams; + + QByteArray toolbarState; //stato delle toolbar e dockwidgets + + QDir lastUsedDirectory; //This will hold the last directory that was used to load/save a file/project in + +public: + GLArea *GLA() const { + if(mdiarea->currentSubWindow()==0) return 0; + MultiViewer_Container *mvc = qobject_cast(mdiarea->currentSubWindow()); + if(!mvc) + mvc = qobject_cast(mdiarea->currentSubWindow()->widget()); + GLArea *glw = (GLArea*)(mvc->currentView());//qobject_castqobject_cast(mvc->currentView()); + if(glw) + return glw; + else return 0; + } + + const PluginManager& pluginManager() const { return PM; } + + //QMap filterMap; // a map to retrieve an action from a name. Used for playing filter scripts. + static QStatusBar *&globalStatusBar() + { + static QStatusBar *_qsb=0; + return _qsb; + } + //QMenu* layerMenu() { return filterMenuLayer; } + +private: + //////// ToolBars /////////////// + QToolBar *mainToolBar; + QToolBar *renderToolBar; + /*QToolBar *editToolBar; + QToolBar *filterToolBar;*/ + + ///////// Menus /////////////// + QMenu *fileMenu; + QMenu *fileMenuNew; + /*QMenu *filterMenu; + QMenu *filterMenuSelect; + QMenu *filterMenuClean; + QMenu *filterMenuRemeshing; + QMenu *filterMenuColorize; + QMenu *filterMenuSmoothing; + QMenu *filterMenuQuality; + QMenu *filterMenuNormal; + QMenu *filterMenuLayer; + QMenu *filterMenuRangeMap; + QMenu *filterMenuPointSet; + QMenu *filterMenuSampling; + QMenu *filterMenuTexture; + + QMenu *editMenu;*/ + + //Render Menu and SubMenu //// + QMenu *shadersMenu; + QMenu *renderMenu; + QMenu *renderModeMenu; + QMenu *lightingModeMenu; + QMenu *colorModeMenu; + QMenu *splitModeMenu; + + //View Menu and SubMenu ////// + QMenu *viewMenu; + QMenu *trackBallMenu; + QMenu *logMenu; + QMenu *toolBarMenu; + ////////////////////////////// + QMenu *windowsMenu; + QMenu *preferencesMenu; + QMenu *helpMenu; + + + //////////// Actions Menu File /////////////////////// + QAction *openAct; + QAction *openInAct,*openProjectAct; + QAction *closeAct; + QAction *reloadAct; + QAction *saveAct,*saveAsAct,*saveProjectAct; + QAction *saveSnapshotAct; + QAction *lastFilterAct; + QAction *runFilterScriptAct; + QAction *showFilterScriptAct; + QAction *recentFileActs[MAXRECENTFILES]; + QAction *separatorAct; + QAction *exitAct; + /////////// Actions Menu Edit ///////////////////// + QAction *suspendEditModeAct; + /////////// Actions Menu Render ///////////////////// + QActionGroup *renderModeGroupAct; + QAction *renderBboxAct; + QAction *renderModePointsAct; + QAction *renderModeWireAct; + QAction *renderModeHiddenLinesAct; + QAction *renderModeFlatLinesAct; + QAction *renderModeFlatAct; + QAction *renderModeSmoothAct; + QAction *renderModeTextureAct; + QAction *setDoubleLightingAct; + QAction *setFancyLightingAct; + QAction *setLightAct; + QAction *backFaceCullAct; + QAction *setSelectFaceRenderingAct; + QAction *setSelectVertRenderingAct; + + QActionGroup *colorModeGroupAct; + QAction *colorModeNoneAct; + QAction *colorModePerMeshAct; + QAction *colorModePerVertexAct; + QAction *colorModePerFaceAct; + ///////////Actions Menu View //////////////////////// + QAction *fullScreenAct; + QAction *showToolbarStandardAct; + QAction *showToolbarRenderAct; + QAction *showInfoPaneAct; + QAction *showTrackBallAct; + QAction *resetTrackBallAct; + QAction *showLayerDlgAct; + ///////////Actions Menu Windows ///////////////////// + QAction *windowsTileAct; + QAction *windowsCascadeAct; + QAction *windowsNextAct; + QAction *closeAllAct; + ///////////Actions Menu Preferences ///////////////// + QAction *setCustomizeAct; + QAction *setSplitHAct; + QAction *setSplitVAct; + QActionGroup *setSplitGroupAct; + QAction *setUnsplitAct; + + ///////////Actions Menu Help //////////////////////// + QAction *aboutAct; + QAction *aboutPluginsAct; + QAction *submitBugAct; + QAction *onlineHelpAct; + QAction *onscreenHelpAct; + QAction *checkUpdatesAct; + //////////////////////////////////////////////////// +}; + +class FileOpenEater : public QObject +{ +Q_OBJECT + +public: +FileOpenEater() {noEvent=true;} +MainWindow *mainWindow; +bool noEvent; + +protected: + +bool eventFilter(QObject *obj, QEvent *event) + { + if (event->type() == QEvent::FileOpen) { + noEvent=false; + QFileOpenEvent *fileEvent = static_cast(event); + mainWindow->open(fileEvent->file()); + // QMessageBox::information(0,"Meshlab",fileEvent->file()); + return true; + } else { + // standard event processing + return QObject::eventFilter(obj, event); + } + } + }; + +#endif +#endif diff --git a/src/meshlab_2.01/mainwindow_Init.cpp b/src/meshlab_2.01/mainwindow_Init.cpp new file mode 100644 index 000000000..57685be2a --- /dev/null +++ b/src/meshlab_2.01/mainwindow_Init.cpp @@ -0,0 +1,905 @@ +/**************************************************************************** +* MeshLab o o * +* An extendible mesh processor o o * +* _ O _ * +* Copyright(C) 2005, 2006 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + + +#include "../common/interfaces.h" + +#include +#include +#include +#include +#include +#include +#include +#include "mainwindow.h" +#include "glarea.h" +//#include "plugindialog.h" +//#include "customDialog.h" +//#include "saveSnapshotDialog.h" +//#include "ui_congratsDialog.h" + +QProgressBar *MainWindow::qb; + +MainWindow::MainWindow() +{ + //workspace = new QWorkspace(this); + mdiarea = new QMdiArea(this); + //setCentralWidget(workspace); + setCentralWidget(mdiarea); + windowMapper = new QSignalMapper(this); + // Permette di passare da una finestra all'altra e tenere aggiornato il workspace + connect(windowMapper, SIGNAL(mapped(QWidget*)),this, SLOT(wrapSetActiveSubWindow(QWidget *))); + // Quando si passa da una finestra all'altra aggiorna lo stato delle toolbar e dei menu + connect(mdiarea, SIGNAL(subWindowActivated(QMdiSubWindow *)),this, SLOT(updateMenus())); + connect(mdiarea, SIGNAL(subWindowActivated(QMdiSubWindow *)),this, SLOT(updateWindowMenu())); + connect(mdiarea, SIGNAL(subWindowActivated(QMdiSubWindow *)),this, SLOT(updateStdDialog())); + + httpReq=new QHttp(this); + //connect(httpReq, SIGNAL(requestFinished(int,bool)), this, SLOT(connectionFinished(int,bool))); + connect(httpReq, SIGNAL(done(bool)), this, SLOT(connectionDone(bool))); + + QIcon icon; + icon.addPixmap(QPixmap(":images/eye48.png")); + setWindowIcon(icon); + + PM.loadPlugins(defaultGlobalParams); + // Now load from the registry the settings and merge the hardwired values got from the PM.loadPlugins with the ones found in the registry. + loadMeshLabSettings(); + createActions(); + createToolBars(); + createMenus(); + stddialog = 0; + setAcceptDrops(true); + mdiarea->setAcceptDrops(true); + setWindowTitle(appName()); + setStatusBar(new QStatusBar(this)); + globalStatusBar()=statusBar(); + qb=new QProgressBar(this); + qb->setMaximum(100); + qb->setMinimum(0); + //qb->reset(); + statusBar()->addPermanentWidget(qb,0); + updateMenus(); + + //qb->setAutoClose(true); + //qb->setMinimumDuration(0); + //qb->reset(); +} + +void MainWindow::createActions() +{ + //////////////Action Menu File //////////////////////////////////////////////////////////////////////////// + openAct = new QAction(QIcon(":/images/open.png"),tr("&Open..."), this); + openAct->setShortcutContext(Qt::ApplicationShortcut); + openAct->setShortcut(Qt::CTRL+Qt::Key_O); + connect(openAct, SIGNAL(triggered()), this, SLOT(open())); + + openInAct = new QAction(QIcon(":/images/open.png"),tr("&Open as new layer..."), this); + connect(openInAct, SIGNAL(triggered()), this, SLOT(openIn())); + + openProjectAct = new QAction(QIcon(":/images/openPrj.png"),tr("&Open project..."), this); + connect(openProjectAct, SIGNAL(triggered()), this, SLOT(openProject())); + + closeAct = new QAction(tr("&Close"), this); + closeAct->setShortcutContext(Qt::ApplicationShortcut); + //closeAct->setShortcut(Qt::CTRL+Qt::Key_C); + connect(closeAct, SIGNAL(triggered()),mdiarea, SLOT(closeActiveSubWindow())); + + reloadAct = new QAction(QIcon(":/images/reload.png"),tr("&Reload"), this); + reloadAct->setShortcutContext(Qt::ApplicationShortcut); + reloadAct->setShortcut(Qt::CTRL+Qt::Key_R); + connect(reloadAct, SIGNAL(triggered()), this, SLOT(reload())); + + saveAct = new QAction(QIcon(":/images/save.png"),tr("&Save"), this); + saveAct->setShortcutContext(Qt::ApplicationShortcut); + saveAct->setShortcut(Qt::CTRL+Qt::Key_S); + connect(saveAct, SIGNAL(triggered()), this, SLOT(save())); + + + saveAsAct = new QAction(QIcon(":/images/save.png"),tr("Save As..."), this); + saveAsAct->setShortcutContext(Qt::ApplicationShortcut); + //saveAsAct->setShortcut(Qt::CTRL+Qt::Key_S); + connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); + + saveProjectAct = new QAction(QIcon(":/images/savePrj.png"),tr("&Save Project..."), this); + connect(saveProjectAct, SIGNAL(triggered()), this, SLOT(saveProject())); + + saveSnapshotAct = new QAction(QIcon(":/images/snapshot.png"),tr("Save snapsho&t"), this); + connect(saveSnapshotAct, SIGNAL(triggered()), this, SLOT(saveSnapshot())); + + for (int i = 0; i < MAXRECENTFILES; ++i) { + recentFileActs[i] = new QAction(this); + recentFileActs[i]->setVisible(false); + connect(recentFileActs[i], SIGNAL(triggered()),this, SLOT(openRecentFile())); + } + + exitAct = new QAction(tr("E&xit"), this); + exitAct->setShortcut(Qt::CTRL+Qt::Key_Q); + connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); + + //////////////Render Actions for Toolbar and Menu ///////////////////////////////////////////////////////// + renderModeGroupAct = new QActionGroup(this); + + renderBboxAct = new QAction(QIcon(":/images/bbox.png"),tr("&Bounding box"), renderModeGroupAct); + renderBboxAct->setCheckable(true); + connect(renderBboxAct, SIGNAL(triggered()), this, SLOT(renderBbox())); + + + renderModePointsAct = new QAction(QIcon(":/images/points.png"),tr("&Points"), renderModeGroupAct); + renderModePointsAct->setCheckable(true); + connect(renderModePointsAct, SIGNAL(triggered()), this, SLOT(renderPoint())); + + renderModeWireAct = new QAction(QIcon(":/images/wire.png"),tr("&Wireframe"), renderModeGroupAct); + renderModeWireAct->setCheckable(true); + connect(renderModeWireAct, SIGNAL(triggered()), this, SLOT(renderWire())); + + renderModeHiddenLinesAct = new QAction(QIcon(":/images/backlines.png"),tr("&Hidden Lines"),renderModeGroupAct); + renderModeHiddenLinesAct->setCheckable(true); + connect(renderModeHiddenLinesAct, SIGNAL(triggered()), this, SLOT(renderHiddenLines())); + + renderModeFlatLinesAct = new QAction(QIcon(":/images/flatlines.png"),tr("Flat &Lines"), renderModeGroupAct); + renderModeFlatLinesAct->setCheckable(true); + connect(renderModeFlatLinesAct, SIGNAL(triggered()), this, SLOT(renderFlatLine())); + + renderModeFlatAct = new QAction(QIcon(":/images/flat.png"),tr("&Flat"), renderModeGroupAct); + renderModeFlatAct->setCheckable(true); + connect(renderModeFlatAct, SIGNAL(triggered()), this, SLOT(renderFlat())); + + renderModeSmoothAct = new QAction(QIcon(":/images/smooth.png"),tr("&Smooth"), renderModeGroupAct); + renderModeSmoothAct->setCheckable(true); + connect(renderModeSmoothAct, SIGNAL(triggered()), this, SLOT(renderSmooth())); + + renderModeTextureAct = new QAction(QIcon(":/images/textures.png"),tr("&Texture"),this); + renderModeTextureAct->setCheckable(true); + connect(renderModeTextureAct, SIGNAL(triggered()), this, SLOT(renderTexture())); + + setLightAct = new QAction(QIcon(":/images/lighton.png"),tr("&Light on/off"),this); + setLightAct->setCheckable(true); + connect(setLightAct, SIGNAL(triggered()), this, SLOT(setLight())); + + setDoubleLightingAct= new QAction(tr("&Double side lighting"),this); + setDoubleLightingAct->setCheckable(true); + setDoubleLightingAct->setShortcutContext(Qt::ApplicationShortcut); + setDoubleLightingAct->setShortcut(Qt::CTRL+Qt::Key_D); + connect(setDoubleLightingAct, SIGNAL(triggered()), this, SLOT(setDoubleLighting())); + + setFancyLightingAct = new QAction(tr("&Fancy Lighting"),this); + setFancyLightingAct->setCheckable(true); + setFancyLightingAct->setShortcutContext(Qt::ApplicationShortcut); + setFancyLightingAct->setShortcut(Qt::CTRL+Qt::Key_F); + connect(setFancyLightingAct, SIGNAL(triggered()), this, SLOT(setFancyLighting())); + + backFaceCullAct = new QAction(tr("BackFace &Culling"),this); + backFaceCullAct->setCheckable(true); + backFaceCullAct->setShortcutContext(Qt::ApplicationShortcut); + backFaceCullAct->setShortcut(Qt::CTRL+Qt::Key_K); + connect(backFaceCullAct, SIGNAL(triggered()), this, SLOT(toggleBackFaceCulling())); + + setSelectFaceRenderingAct = new QAction(QIcon(":/images/selected_face.png"),tr("Selected Face Rendering"),this); + setSelectFaceRenderingAct->setCheckable(true); + setSelectFaceRenderingAct->setShortcutContext(Qt::ApplicationShortcut); + connect(setSelectFaceRenderingAct, SIGNAL(triggered()), this, SLOT(toggleSelectFaceRendering())); + + setSelectVertRenderingAct = new QAction(QIcon(":/images/selected_vert.png"),tr("Selected Vertex Rendering"),this); + setSelectVertRenderingAct->setCheckable(true); + setSelectVertRenderingAct->setShortcutContext(Qt::ApplicationShortcut); + connect(setSelectVertRenderingAct, SIGNAL(triggered()), this, SLOT(toggleSelectVertRendering())); + + //////////////Action Menu View //////////////////////////////////////////////////////////////////////////// + fullScreenAct = new QAction (tr("&FullScreen"), this); + fullScreenAct->setCheckable(true); + fullScreenAct->setShortcutContext(Qt::ApplicationShortcut); + fullScreenAct->setShortcut(Qt::ALT+Qt::Key_Return); + connect(fullScreenAct, SIGNAL(triggered()), this, SLOT(fullScreen())); + + showToolbarStandardAct = new QAction (tr("&Standard"), this); + showToolbarStandardAct->setCheckable(true); + showToolbarStandardAct->setChecked(true); + connect(showToolbarStandardAct, SIGNAL(triggered()), this, SLOT(showToolbarFile())); + + showToolbarRenderAct = new QAction (tr("&Render"), this); + showToolbarRenderAct->setCheckable(true); + showToolbarRenderAct->setChecked(true); + connect(showToolbarRenderAct, SIGNAL(triggered()), this, SLOT(showToolbarRender())); + + showInfoPaneAct= new QAction (tr("Show Info &Pane"), this); + showInfoPaneAct->setCheckable(true); + connect(showInfoPaneAct, SIGNAL(triggered()), this, SLOT(showInfoPane())); + + + showTrackBallAct = new QAction (tr("Show &Trackball"), this); + showTrackBallAct->setCheckable(true); + connect(showTrackBallAct, SIGNAL(triggered()), this, SLOT(showTrackBall())); + + resetTrackBallAct = new QAction (tr("Reset &Trackball"), this); + resetTrackBallAct->setShortcutContext(Qt::ApplicationShortcut); + resetTrackBallAct->setShortcut(Qt::CTRL+Qt::Key_H); + connect(resetTrackBallAct, SIGNAL(triggered()), this, SLOT(resetTrackBall())); + + showLayerDlgAct = new QAction (QIcon(":/images/layers.png"),tr("Show Layer Dialog"), this); + showLayerDlgAct->setCheckable(true); + showLayerDlgAct->setChecked(true); + connect(showLayerDlgAct, SIGNAL(triggered()), this, SLOT(showLayerDlg())); + + + //////////////Action Menu EDIT ///////////////////////////////////////////////////////////////////////// + suspendEditModeAct = new QAction (QIcon(":/images/no_edit.png"),tr("Not editing"), this); + suspendEditModeAct->setShortcut(Qt::Key_Escape); + suspendEditModeAct->setCheckable(true); + suspendEditModeAct->setChecked(true); + connect(suspendEditModeAct, SIGNAL(triggered()), this, SLOT(suspendEditMode())); + + //////////////Action Menu WINDOWS ///////////////////////////////////////////////////////////////////////// + windowsTileAct = new QAction(tr("&Tile"), this); + connect(windowsTileAct, SIGNAL(triggered()), mdiarea, SLOT(tileSubWindows())); + + windowsCascadeAct = new QAction(tr("&Cascade"), this); + connect(windowsCascadeAct, SIGNAL(triggered()), mdiarea, SLOT(cascadeSubWindows())); + + windowsNextAct = new QAction(tr("&Next"), this); + connect(windowsNextAct, SIGNAL(triggered()), mdiarea, SLOT(activateNextSubWindow())); + + closeAllAct = new QAction(tr("Close &All Windows"), this); + connect(closeAllAct, SIGNAL(triggered()),mdiarea, SLOT(closeAllSubWindows())); + + //////////////Action Menu Filters ///////////////////////////////////////////////////////////////////// + lastFilterAct = new QAction(tr("Apply filter"),this); + lastFilterAct->setShortcutContext(Qt::ApplicationShortcut); + lastFilterAct->setShortcut(Qt::CTRL+Qt::Key_L); + lastFilterAct->setEnabled(false); + connect(lastFilterAct, SIGNAL(triggered()), this, SLOT(applyLastFilter())); + + showFilterScriptAct = new QAction(tr("Show current filter script"),this); + showFilterScriptAct->setEnabled(true); + connect(showFilterScriptAct, SIGNAL(triggered()), this, SLOT(showFilterScript())); + + //////////////Action Menu Preferences ///////////////////////////////////////////////////////////////////// + + setCustomizeAct = new QAction(tr("&Options..."),this); + connect(setCustomizeAct, SIGNAL(triggered()), this, SLOT(setCustomize())); + + setSplitGroupAct = new QActionGroup(this); setSplitGroupAct->setExclusive(true); + + setSplitHAct = new QAction(tr("&Horizontally"),setSplitGroupAct); + + setSplitVAct = new QAction(tr("&Vertically"),setSplitGroupAct); + + connect(setSplitGroupAct, SIGNAL(triggered(QAction *)), this, SLOT(setSplit(QAction *))); + + setUnsplitAct = new QAction(tr("&Close current view"),this); + connect(setUnsplitAct, SIGNAL(triggered()), this, SLOT(setUnsplit())); + + //////////////Action Menu About /////////////////////////////////////////////////////////////////////////// + aboutAct = new QAction(tr("&About"), this); + connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); + + aboutPluginsAct = new QAction(tr("About &Plugins"), this); + connect(aboutPluginsAct, SIGNAL(triggered()), this, SLOT(aboutPlugins())); + + onlineHelpAct = new QAction(tr("Online &Documentation"), this); + connect(onlineHelpAct, SIGNAL(triggered()), this, SLOT(helpOnline())); + + submitBugAct = new QAction(tr("Submit Bug"), this); + connect(submitBugAct, SIGNAL(triggered()), this, SLOT(submitBug())); + + onscreenHelpAct = new QAction(tr("On screen quick help"), this); + connect(onscreenHelpAct, SIGNAL(triggered()), this, SLOT(helpOnscreen())); + + checkUpdatesAct = new QAction(tr("Check for updates"), this); + connect(checkUpdatesAct, SIGNAL(triggered()), this, SLOT(checkForUpdates())); +} + +void MainWindow::createToolBars() +{ + mainToolBar = addToolBar(tr("Standard")); + mainToolBar->setIconSize(QSize(32,32)); + mainToolBar->addAction(openAct); + mainToolBar->addAction(reloadAct); + mainToolBar->addAction(saveAct); + //mainToolBar->addAction(saveSnapshotAct); + mainToolBar->addAction(showLayerDlgAct); + + renderToolBar = addToolBar(tr("Render")); + //renderToolBar->setIconSize(QSize(32,32)); + renderToolBar->addActions(renderModeGroupAct->actions()); + renderToolBar->addAction(renderModeTextureAct); + renderToolBar->addAction(setLightAct); + renderToolBar->addAction(setSelectFaceRenderingAct); + renderToolBar->addAction(setSelectVertRenderingAct); + + /*editToolBar = addToolBar(tr("Edit")); + editToolBar->addAction(suspendEditModeAct); + editToolBar->addSeparator(); + + filterToolBar = addToolBar(tr("Action")); + + foreach(MeshEditInterfaceFactory *iEditFactory,PM.meshEditFactoryPlugins()) + { + foreach(QAction* editAction, iEditFactory->actions()) + { + if(!editAction->icon().isNull()) + { + editToolBar->addAction(editAction); + } else qDebug() << "action was null"; + } + }*/ +} + + +void MainWindow::createMenus() +{ + //////////////////// Menu File //////////////////////////////////////////////////////////////////////////// + fileMenu = menuBar()->addMenu(tr("&File")); + fileMenu->addAction(openAct); + fileMenu->addAction(openInAct); + fileMenu->addAction(openProjectAct); + fileMenu->addAction(closeAct); + fileMenu->addAction(reloadAct); + fileMenu->addAction(saveAct); + fileMenu->addAction(saveAsAct); + fileMenu->addAction(saveProjectAct); + + fileMenuNew = fileMenu->addMenu(tr("New")); + + /*fileMenu->addSeparator(); + fileMenu->addAction(saveSnapshotAct);*/ + separatorAct = fileMenu->addSeparator(); + + for (int i = 0; i < MAXRECENTFILES; ++i) fileMenu->addAction(recentFileActs[i]); + updateRecentFileActions(); + fileMenu->addSeparator(); + fileMenu->addAction(exitAct); + + //////////////////// Menu Edit ////////////////////////////////////////////////////////////////////////// + /*editMenu = menuBar()->addMenu(tr("&Edit")); + editMenu->addAction(suspendEditModeAct);*/ + + //////////////////// Menu Filter ////////////////////////////////////////////////////////////////////////// + /*filterMenu = menuBar()->addMenu(tr("Fi<ers")); + filterMenu->addAction(lastFilterAct); + filterMenu->addAction(showFilterScriptAct); + filterMenu->addSeparator(); + filterMenuSelect = filterMenu->addMenu(tr("Selection")); + filterMenuClean = filterMenu->addMenu(tr("Cleaning and Repairing")); + filterMenuRemeshing = filterMenu->addMenu(tr("Remeshing, simplification and reconstruction")); + filterMenuColorize = filterMenu->addMenu(tr("Color Creation and Processing")); + filterMenuSmoothing = filterMenu->addMenu(tr("Smoothing, Fairing and Deformation")); + filterMenuQuality = filterMenu->addMenu(tr("Quality Measure and computations")); + filterMenuNormal = filterMenu->addMenu(tr("Normals, Curvatures and Orientation")); + filterMenuLayer = filterMenu->addMenu(tr("Layer and Attribute Management")); + filterMenuRangeMap = filterMenu->addMenu(tr("Range Map")); + filterMenuPointSet = filterMenu->addMenu(tr("Point Set")); + filterMenuSampling = filterMenu->addMenu(tr("Sampling")); + filterMenuTexture = filterMenu->addMenu(tr("Texture"));*/ + + + //////////////////// Menu Render ////////////////////////////////////////////////////////////////////////// + renderMenu = menuBar()->addMenu(tr("&Render")); + + renderModeMenu=renderMenu->addMenu(tr("Render &Mode")); + renderModeMenu->addAction(backFaceCullAct); + renderModeMenu->addActions(renderModeGroupAct->actions()); + renderModeMenu->addAction(renderModeTextureAct); + renderModeMenu->addAction(setSelectFaceRenderingAct); + renderModeMenu->addAction(setSelectVertRenderingAct); + + lightingModeMenu=renderMenu->addMenu(tr("&Lighting")); + lightingModeMenu->addAction(setLightAct); + lightingModeMenu->addAction(setDoubleLightingAct); + lightingModeMenu->addAction(setFancyLightingAct); + + // Color SUBmenu + colorModeMenu = renderMenu->addMenu(tr("&Color")); + + colorModeGroupAct = new QActionGroup(this); colorModeGroupAct->setExclusive(true); + + colorModeNoneAct = new QAction(QString("&None"),colorModeGroupAct); + colorModeNoneAct->setCheckable(true); + colorModeNoneAct->setChecked(true); + + colorModePerMeshAct = new QAction(QString("Per &Mesh"),colorModeGroupAct); + colorModePerMeshAct->setCheckable(true); + + colorModePerVertexAct = new QAction(QString("Per &Vertex"),colorModeGroupAct); + colorModePerVertexAct->setCheckable(true); + + colorModePerFaceAct = new QAction(QString("Per &Face"),colorModeGroupAct); + colorModePerFaceAct->setCheckable(true); + + + colorModeMenu->addAction(colorModeNoneAct); + colorModeMenu->addAction(colorModePerMeshAct); + colorModeMenu->addAction(colorModePerVertexAct); + colorModeMenu->addAction(colorModePerFaceAct); + + connect(colorModeGroupAct, SIGNAL(triggered(QAction *)), this, SLOT(setColorMode(QAction *))); + + // Shaders SUBmenu + shadersMenu = renderMenu->addMenu(tr("&Shaders")); + + renderMenu->addSeparator(); + + //////////////////// Menu View //////////////////////////////////////////////////////////////////////////// + viewMenu = menuBar()->addMenu(tr("&View")); + viewMenu->addAction(fullScreenAct); + viewMenu->addAction(showLayerDlgAct); + + trackBallMenu = viewMenu->addMenu(tr("&Trackball")); + trackBallMenu->addAction(showTrackBallAct); + trackBallMenu->addAction(resetTrackBallAct); + + logMenu = viewMenu->addMenu(tr("&Info")); + logMenu->addAction(showInfoPaneAct); + + toolBarMenu = viewMenu->addMenu(tr("&ToolBars")); + toolBarMenu->addAction(showToolbarStandardAct); + toolBarMenu->addAction(showToolbarRenderAct); + connect(toolBarMenu,SIGNAL(aboutToShow()),this,SLOT(updateMenus())); + + //////////////////// Menu Windows ///////////////////////////////////////////////////////////////////////// + windowsMenu = menuBar()->addMenu(tr("&Windows")); + connect(windowsMenu, SIGNAL(aboutToShow()), this, SLOT(updateWindowMenu())); + menuBar()->addSeparator(); + + //////////////////// Menu Preferences ///////////////////////////////////////////////////////////////////// + preferencesMenu=menuBar()->addMenu(tr("&Tools")); + preferencesMenu->addAction(setCustomizeAct); + + // Split SUBmenu + splitModeMenu = preferencesMenu->addMenu(tr("&Split current view")); + + splitModeMenu->addAction(setSplitHAct); + splitModeMenu->addAction(setSplitVAct); + + //////// + + preferencesMenu->addAction(setUnsplitAct); + + //////////////////// Menu Help //////////////////////////////////////////////////////////////// + helpMenu = menuBar()->addMenu(tr("&Help")); + helpMenu->addAction(aboutAct); + helpMenu->addAction(aboutPluginsAct); + helpMenu->addAction(onlineHelpAct); + helpMenu->addAction(onscreenHelpAct); + helpMenu->addAction(submitBugAct); + helpMenu->addAction(checkUpdatesAct); + + /*fillFilterMenu(); + fillEditMenu();*/ + fillRenderMenu(); + //fillDecorateMenu(); +} + +//void MainWindow::fillFilterMenu() +//{ +// foreach(MeshFilterInterface *iFilter,PM.meshFilterPlugins()) +// { +// foreach(QAction *filterAction, iFilter->actions()) +// { +// filterAction->setToolTip(iFilter->filterInfo(filterAction)); +// connect(filterAction,SIGNAL(triggered()),this,SLOT(startFilter())); +// int filterClass = iFilter->getClass(filterAction); +// +// if( (filterClass & MeshFilterInterface::FaceColoring) || (filterClass & MeshFilterInterface::VertexColoring) ) filterMenuColorize->addAction(filterAction); +// if(filterClass & MeshFilterInterface::Selection) filterMenuSelect->addAction(filterAction); +// if(filterClass & MeshFilterInterface::Cleaning ) filterMenuClean->addAction(filterAction); +// if(filterClass & MeshFilterInterface::Remeshing ) filterMenuRemeshing->addAction(filterAction); +// if(filterClass & MeshFilterInterface::Smoothing ) filterMenuSmoothing->addAction(filterAction); +// if(filterClass & MeshFilterInterface::Normal ) filterMenuNormal->addAction(filterAction); +// if( (filterClass & MeshFilterInterface::Quality ) || (filterClass & MeshFilterInterface::Measure ) ) filterMenuQuality->addAction(filterAction); +// if(filterClass & MeshFilterInterface::Layer ) filterMenuLayer->addAction(filterAction); +// if(filterClass & MeshFilterInterface::MeshCreation ) fileMenuNew->addAction(filterAction); +// if(filterClass & MeshFilterInterface::RangeMap ) filterMenuRangeMap->addAction(filterAction); +// if(filterClass & MeshFilterInterface::PointSet ) filterMenuPointSet->addAction(filterAction); +// if(filterClass & MeshFilterInterface::Sampling ) filterMenuSampling->addAction(filterAction); +// if(filterClass & MeshFilterInterface::Texture) filterMenuTexture->addAction(filterAction); +// // MeshFilterInterface::Generic : +// if(filterClass == 0) filterMenu->addAction(filterAction); +// +// if(!filterAction->icon().isNull()) +// filterToolBar->addAction(filterAction); +// } +// } +//} +// +//void MainWindow::fillDecorateMenu() +//{ +// foreach(MeshDecorateInterface *iDecorate,PM.meshDecoratePlugins()) +// { +// foreach(QAction *decorateAction, iDecorate->actions()) +// { +// connect(decorateAction,SIGNAL(triggered()),this,SLOT(applyDecorateMode())); +// decorateAction->setToolTip(iDecorate->filterInfo(decorateAction)); +// renderMenu->addAction(decorateAction); +// } +// } +//} + +void MainWindow::fillRenderMenu() +{ + foreach(MeshRenderInterface *iRender,PM.meshRenderPlugins()) + { + addToMenu(iRender->actions(), shadersMenu, SLOT(applyRenderMode())); + } +} + +//void MainWindow::fillEditMenu() +//{ +// foreach(MeshEditInterfaceFactory *iEditFactory,PM.meshEditFactoryPlugins()) +// { +// foreach(QAction* editAction, iEditFactory->actions()) +// { +// editMenu->addAction(editAction); +// +// connect(editAction, SIGNAL(triggered()), this, SLOT(applyEditMode())); +// //editActionList.push_back(editAction); +// } +// } +//} + + +void MainWindow::loadPlugins() +{ + //PM.loadPlugins(); +// pluginsDir=QDir(getPluginDirPath()); +// // without adding the correct library path in the mac the loading of jpg (done via qt plugins) fails +// qApp->addLibraryPath(getPluginDirPath()); +// qApp->addLibraryPath(getBaseDirPath()); +// +// QStringList pluginfilters; +//#if defined(Q_OS_WIN) +// pluginfilters << "*.dll"; +//#elif defined(Q_OS_MAC) +// pluginfilters << "*.dylib"; +//#else +//#endif +// pluginsDir.setNameFilters(pluginfilters); +// +// qDebug( "Current Plugins Dir: %s ",qPrintable(pluginsDir.absolutePath())); +// foreach (QString fileName, pluginsDir.entryList(QDir::Files)) { +// QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); +// QObject *plugin = loader.instance(); +// +// if (plugin) { +// MeshFilterInterface *iFilter = qobject_cast(plugin); +// if (iFilter) +// { +// +// QAction *filterAction; +// +// foreach(filterAction, iFilter->actions()) +// { +// //qDebug("Processing action %s",qPrintable(filterAction->text()) ); +// //qDebug(" (%s)", qPrintable(iFilter->filterInfo(filterAction)) ); +// iFilter->initGlobalParameterSet(filterAction,defaultGlobalParams); +// filterMap[filterAction->text()]=filterAction; +// filterAction->setToolTip(iFilter->filterInfo(filterAction)); +// connect(filterAction,SIGNAL(triggered()),this,SLOT(startFilter())); +// int filterClass = iFilter->getClass(filterAction); +// +// if( (filterClass & MeshFilterInterface::FaceColoring) || +// (filterClass & MeshFilterInterface::VertexColoring) ) +// filterMenuColorize->addAction(filterAction); +// if(filterClass & MeshFilterInterface::Selection) +// filterMenuSelect->addAction(filterAction); +// if(filterClass & MeshFilterInterface::Cleaning ) +// filterMenuClean->addAction(filterAction); +// if(filterClass & MeshFilterInterface::Remeshing ) +// filterMenuRemeshing->addAction(filterAction); +// if(filterClass & MeshFilterInterface::Smoothing ) +// filterMenuSmoothing->addAction(filterAction); +// if(filterClass & MeshFilterInterface::Normal ) +// filterMenuNormal->addAction(filterAction); +// if( (filterClass & MeshFilterInterface::Quality ) || +// (filterClass & MeshFilterInterface::Measure ) ) +// filterMenuQuality->addAction(filterAction); +// if(filterClass & MeshFilterInterface::Layer ) +// filterMenuLayer->addAction(filterAction); +// if(filterClass & MeshFilterInterface::MeshCreation ) +// fileMenuNew->addAction(filterAction); +// if(filterClass & MeshFilterInterface::RangeMap ) +// filterMenuRangeMap->addAction(filterAction); +// if(filterClass & MeshFilterInterface::PointSet ) +// filterMenuPointSet->addAction(filterAction); +// if(filterClass & MeshFilterInterface::Sampling ) +// filterMenuSampling->addAction(filterAction); +// if (filterClass & MeshFilterInterface::Texture) +// filterMenuTexture->addAction(filterAction); +// if(filterClass == 0) // MeshFilterInterface::Generic : +// filterMenu->addAction(filterAction); +// +// if(!filterAction->icon().isNull()) +// filterToolBar->addAction(filterAction); +// } +// } +// MeshIOInterface *iIO = qobject_cast(plugin); +// if (iIO) +// meshIOPlugins.push_back(iIO); +// +// MeshDecorateInterface *iDecorator = qobject_cast(plugin); +// if (iDecorator){ +// QAction *decoratorAction; +// decoratorActionList+=iDecorator->actions(); +// foreach(decoratorAction, iDecorator->actions()) +// { +// iDecorator->initGlobalParameterSet(decoratorAction,&defaultGlobalParams); +// connect(decoratorAction,SIGNAL(triggered()),this,SLOT(applyDecorateMode())); +// decoratorAction->setToolTip(iDecorator->Info(decoratorAction)); +// renderMenu->addAction(decoratorAction); +// } +// } +// +// MeshRenderInterface *iRender = qobject_cast(plugin); +// if (iRender) +// addToMenu(iRender->actions(), shadersMenu, SLOT(applyRenderMode())); +///* +// MeshEditInterface *iEdit = qobject_cast(plugin); +// QAction *editAction; +// if (iEdit) +// foreach(editAction, iEdit->actions()) +// { +// editMenu->addAction(editAction); +// if(!editAction->icon().isNull()) +// editToolBar->addAction(editAction); +// connect(editAction,SIGNAL(triggered()),this,SLOT(applyEditMode())); +// editActionList.push_back(editAction); +// } +//*/ +// MeshEditInterfaceFactory *iEditFactory = qobject_cast(plugin); +// QAction *editAction = 0; +// if(iEditFactory) +// { +// //qDebug() << "Here with filename:" << fileName; +// +// foreach(editAction, iEditFactory->actions()) +// { +// editMenu->addAction(editAction); +// if(!editAction->icon().isNull()) +// { +// editToolBar->addAction(editAction); +// } else qDebug() << "action was null"; +// +// connect(editAction, SIGNAL(triggered()), this, SLOT(applyEditMode())); +// editActionList.push_back(editAction); +// } +// } +// +// pluginFileNames += fileName; +// } else +// { +// qDebug() << "error loading plugin with filename:" << fileName; +// qDebug() << loader.errorString(); +// } +// } +// filterMenu->setEnabled(!filterMenu->actions().isEmpty() && mdiarea->activeSubWindow()); +// +} + + +void MainWindow::loadMeshLabSettings() +{ + // I have already loaded the plugins so the default for the plugins are already in. + // we just miss the globals default of meshlab itself + GLArea::initGlobalParameterSet(& defaultGlobalParams); + + QSettings settings; + QStringList klist = settings.allKeys(); + + // 1) load saved values + for(int ii = 0;ii < klist.size();++ii) + { + QDomDocument doc; + doc.setContent(settings.value(klist.at(ii)).toString()); + + QString st = settings.value(klist.at(ii)).toString(); + QDomElement docElem = doc.firstChild().toElement(); + + RichParameter* rpar = NULL; + if(!docElem.isNull()) + { + bool ret = RichParameterFactory::create(docElem,&rpar); + if (!ret) + { + qDebug("Warning Ignored parameter '%s' = '%s'. Malformed.", qPrintable(docElem.attribute("name")),qPrintable(docElem.attribute("value"))); + continue; + } + if (!defaultGlobalParams.hasParameter(rpar->name)) + { + qDebug("Warning Ignored parameter %s. In the saved parameters there are ones that are not in the HardWired ones. " + "It happens if you are running MeshLab with only a subset of the plugins. ",qPrintable(rpar->name)); + } + else currentGlobalParams.addParam(rpar); + } + } + + // 2) eventually fill missing values with the hardwired defaults + for(int ii = 0;ii < defaultGlobalParams.paramList.size();++ii) + { + qDebug("Searching param[%i] %s of the default into the loaded settings. ",ii,qPrintable(defaultGlobalParams.paramList.at(ii)->name)); + if (!currentGlobalParams.hasParameter(defaultGlobalParams.paramList.at(ii)->name)) + { + qDebug("Warning! a default param was not found in the saved settings. This should happen only on the first run..."); + RichParameterCopyConstructor v; + defaultGlobalParams.paramList.at(ii)->accept(v); + currentGlobalParams.paramList.push_back(v.lastCreated); + + QDomDocument doc("MeshLabSettings"); + RichParameterXMLVisitor vxml(doc); + v.lastCreated->accept(vxml); + doc.appendChild(vxml.parElem); + QString docstring = doc.toString(); + QSettings setting; + setting.setValue(v.lastCreated->name,QVariant(docstring)); + } + } + + emit dispatchCustomSettings(currentGlobalParams); +} + +void MainWindow::addToMenu(QList actionList, QMenu *menu, const char *slot) +{ + foreach (QAction *a, actionList) + { + connect(a,SIGNAL(triggered()),this,slot); + menu->addAction(a); + } +} + +// this function update the app settings with the current recent file list +// and update the loaded mesh counter +void MainWindow::setCurrentFile(const QString &fileName) +{ + + QSettings settings; + QStringList files = settings.value("recentFileList").toStringList(); + files.removeAll(fileName); + files.prepend(fileName); + while (files.size() > MAXRECENTFILES) + files.removeLast(); + + settings.setValue("recentFileList", files); + + foreach (QWidget *widget, QApplication::topLevelWidgets()) { + MainWindow *mainWin = qobject_cast(widget); + if (mainWin) mainWin->updateRecentFileActions(); + } + + settings.setValue("totalKV", settings.value("totalKV",0).toInt() + (GLA()->mm()->cm.vn)/1000); + settings.setValue("loadedMeshCounter",settings.value("loadedMeshCounter",0).toInt() + 1); + + int loadedMeshCounter = settings.value("loadedMeshCounter",20).toInt(); + int connectionInterval = settings.value("connectionInterval",20).toInt(); + int lastComunicatedValue = settings.value("lastComunicatedValue",0).toInt(); + + if(loadedMeshCounter-lastComunicatedValue>connectionInterval && !myLocalBuf.isOpen()) + { +#if not defined(__DISABLE_AUTO_STATS__) + checkForUpdates(false); +#endif + int congratsMeshCounter = settings.value("congratsMeshCounter",0).toInt(); + if(loadedMeshCounter > congratsMeshCounter + 100 ) + { + QFile txtFile(":/images/100mesh.html"); + txtFile.open(QIODevice::ReadOnly | QIODevice::Text); + QString tttt=txtFile.readAll(); + // This preference values store when you did the last request for a mail + settings.setValue("congratsMeshCounter",loadedMeshCounter); + + /*QDialog *congratsDialog = new QDialog(); + Ui::CongratsDialog temp; + temp.setupUi(congratsDialog); + + temp.buttonBox->addButton("Send Mail", QDialogButtonBox::AcceptRole); + temp.congratsTextEdit->setHtml(tttt); + congratsDialog->exec(); + if(congratsDialog->result()==QDialog::Accepted) + QDesktopServices::openUrl(QUrl("mailto:p.cignoni@isti.cnr.it?subject=[MeshLab] Reporting Info on MeshLab Usage"));*/ + } + } +} + +void MainWindow::checkForUpdates(bool verboseFlag) +{ + VerboseCheckingFlag=verboseFlag; + QSettings settings; + int totalKV=settings.value("totalKV",0).toInt(); + int connectionInterval=settings.value("connectionInterval",20).toInt(); + settings.setValue("connectionInterval",connectionInterval); + int loadedMeshCounter=settings.value("loadedMeshCounter",0).toInt(); + int savedMeshCounter=settings.value("savedMeshCounter",0).toInt(); + QString UID=settings.value("UID",QString("")).toString(); + if(UID.isEmpty()) + { + UID=QUuid::createUuid ().toString(); + settings.setValue("UID",UID); + } + +#ifdef _DEBUG_PHP + QString BaseCommand("/~cignoni/meshlab_d.php"); +#else + QString BaseCommand("/~cignoni/meshlab.php"); +#endif + +#ifdef Q_WS_WIN + QString OS="Win"; +#elif defined( Q_WS_MAC) + QString OS="Mac"; +#else + QString OS="Lin"; +#endif + QString message=BaseCommand+QString("?code=%1&count=%2&scount=%3&totkv=%4&ver=%5&os=%6").arg(UID).arg(loadedMeshCounter).arg(savedMeshCounter).arg(totalKV).arg(appVer()).arg(OS); + idHost=httpReq->setHost("vcg.isti.cnr.it"); // id == 1 + bool ret=myLocalBuf.open(QBuffer::WriteOnly); + if(!ret) QMessageBox::information(this,"Meshlab",QString("Failed opening of internal buffer")); + idGet=httpReq->get(message,&myLocalBuf); // id == 2 + +} + +void MainWindow::connectionDone(bool /* status */) +{ + QString answer=myLocalBuf.data(); + if(answer.left(3)==QString("NEW")) + QMessageBox::information(this,"MeshLab Version Checking",answer.remove(0,3)); + else if (VerboseCheckingFlag) QMessageBox::information(this,"MeshLab Version Checking","Your MeshLab version is the most recent one."); + + myLocalBuf.close(); + QSettings settings; + int loadedMeshCounter=settings.value("loadedMeshCounter",0).toInt(); + settings.setValue("lastComunicatedValue",loadedMeshCounter); +} + + +void MainWindow::submitBug() +{ + QMessageBox mb(QMessageBox::NoIcon,tr("MeshLab"),tr("MeshLab"),QMessageBox::NoButton, this); + //mb.setWindowTitle(tr("MeshLab")); + QPushButton *submitBug = mb.addButton("Submit Bug",QMessageBox::AcceptRole); + mb.addButton(QMessageBox::Cancel); + mb.setText(tr("If Meshlab closed in unexpected way (e.g. it crashed badly) and" + "if you are able to repeat the bug, please consider to submit a report using the SourceForge tracking system.\n" + ) ); + mb.setInformativeText( tr( + "Hints for a good, useful bug report:\n" + "- Be verbose and descriptive\n" + "- Report meshlab version and OS\n" + "- Describe the sequence of actions that bring you to the crash.\n" + "- Consider submitting the mesh file causing a particular crash.\n" + ) ); + + mb.exec(); + + if (mb.clickedButton() == submitBug) + QDesktopServices::openUrl(QUrl("http://sourceforge.net/tracker/?func=add&group_id=149444&atid=774731")); + +} + +void MainWindow::wrapSetActiveSubWindow(QWidget* window){ + QMdiSubWindow* subwindow; + subwindow = dynamic_cast(window); + if(subwindow!= NULL){ + mdiarea->setActiveSubWindow(subwindow); + }else{ + qDebug("Type of window is not a QMdiSubWindow*"); + } +} + diff --git a/src/meshlab_2.01/mainwindow_RunTime.cpp b/src/meshlab_2.01/mainwindow_RunTime.cpp new file mode 100644 index 000000000..bfe1f1ff4 --- /dev/null +++ b/src/meshlab_2.01/mainwindow_RunTime.cpp @@ -0,0 +1,1230 @@ +/**************************************************************************** +* MeshLab o o * +* An extendible mesh processor o o * +* _ O _ * +* Copyright(C) 2005, 2006 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + + +#include +#include +#include +#include +#include + +#include "mainwindow.h" +#include "glarea.h" +//#include "plugindialog.h" +//#include "filterScriptDialog.h" +//#include "customDialog.h" +//#include "saveSnapshotDialog.h" +//#include "ui_aboutDialog.h" +//#include "savemaskexporter.h" +#include "stdpardialog.h" +#include "layerDialog.h" +//#include "alnParser.h" + +#include +#include +#include +#include + +using namespace std; +using namespace vcg; + +void MainWindow::updateRecentFileActions() +{ + QSettings settings; + QStringList files = settings.value("recentFileList").toStringList(); + int numRecentFiles = qMin(files.size(), (int)MAXRECENTFILES); + for (int i = 0; i < numRecentFiles; ++i) { + QString text = tr("&%1 %2").arg(i + 1).arg(QFileInfo(files[i]).fileName()); + recentFileActs[i]->setText(text); + recentFileActs[i]->setData(files[i]); + recentFileActs[i]->setVisible(true); + } + for (int j = numRecentFiles; j < MAXRECENTFILES; ++j) recentFileActs[j]->setVisible(false); + separatorAct->setVisible(numRecentFiles > 0); +} + +// creates the standard plugin window +void MainWindow::createStdPluginWnd() +{ + //checks if a MeshlabStdDialog is already open and closes it + if (stddialog!=0){ + stddialog->close(); + delete stddialog; + } + stddialog = new MeshlabStdDialog(this); + stddialog->setAllowedAreas ( Qt::RightDockWidgetArea); + addDockWidget(Qt::RightDockWidgetArea,stddialog); + //stddialog->setAttribute(Qt::WA_DeleteOnClose,true); + stddialog->setFloating(true); + stddialog->hide(); + connect(GLA(),SIGNAL(glareaClosed()),stddialog,SLOT(close())); +} + +// When we switch the current model (and we change the active window) +// we have to close the stddialog. +// this one is called when user switch current window. +void MainWindow::updateStdDialog() +{ + if(stddialog!=0){ + if(GLA()!=0){ + if(stddialog->curModel != GLA()->mm()){ + stddialog->curgla=0; // invalidate the curgla member that is no more valid. + stddialog->close(); + } + } + } +} + +void MainWindow::updateCustomSettings() +{ + emit dispatchCustomSettings(currentGlobalParams); +} + +void MainWindow::updateWindowMenu() +{ + windowsMenu->clear(); + windowsMenu->addAction(closeAllAct); + windowsMenu->addSeparator(); + windowsMenu->addAction(windowsTileAct); + windowsMenu->addAction(windowsCascadeAct); + windowsMenu->addAction(windowsNextAct); + windowsNextAct->setEnabled(mdiarea-> subWindowList().size()>1); + + QList windows = mdiarea->subWindowList(); + + if(windows.size() > 0) + windowsMenu->addSeparator(); + + int i=0; + foreach(QWidget *w,windows) + { + QString text = tr("&%1. %2").arg(i+1).arg(QFileInfo(w->windowTitle()).fileName()); + QAction *action = windowsMenu->addAction(text); + action->setCheckable(true); + action->setChecked(w == mdiarea->currentSubWindow()); + // Connect the signal to activate the selected window + connect(action, SIGNAL(triggered()), windowMapper, SLOT(map())); + windowMapper->setMapping(action, w); + ++i; + } +} + +void MainWindow::setColorMode(QAction *qa) +{ + if(qa->text() == tr("&None")) GLA()->setColorMode(GLW::CMNone); + if(qa->text() == tr("Per &Mesh")) GLA()->setColorMode(GLW::CMPerMesh); + if(qa->text() == tr("Per &Vertex")) GLA()->setColorMode(GLW::CMPerVert); + if(qa->text() == tr("Per &Face")) GLA()->setColorMode(GLW::CMPerFace); +} + +void MainWindow::updateMenus() +{ + bool active = (bool) !mdiarea->subWindowList().empty() && mdiarea->currentSubWindow(); + openInAct->setEnabled(active); + closeAct->setEnabled(active); + reloadAct->setEnabled(active); + saveAct->setEnabled(active); + saveAsAct->setEnabled(active); + //saveSnapshotAct->setEnabled(active); + //filterMenu->setEnabled(active && !filterMenu->actions().isEmpty()); + //editMenu->setEnabled(active && !editMenu->actions().isEmpty()); + renderMenu->setEnabled(active); + fullScreenAct->setEnabled(active); + trackBallMenu->setEnabled(active); + logMenu->setEnabled(active); + windowsMenu->setEnabled(active); + preferencesMenu->setEnabled(active); + + renderToolBar->setEnabled(active); + + showToolbarRenderAct->setChecked(renderToolBar->isVisible()); + showToolbarStandardAct->setChecked(mainToolBar->isVisible()); + if(active){ + const RenderMode &rm=GLA()->getCurrentRenderMode(); + switch (rm.drawMode) { + case GLW::DMBox: renderBboxAct->setChecked(true); break; + case GLW::DMPoints: renderModePointsAct->setChecked(true); break; + case GLW::DMWire: renderModeWireAct->setChecked(true); break; + case GLW::DMFlat: renderModeFlatAct->setChecked(true); break; + case GLW::DMSmooth: renderModeSmoothAct->setChecked(true); break; + case GLW::DMFlatWire: renderModeFlatLinesAct->setChecked(true); break; + case GLW::DMHidden: renderModeHiddenLinesAct->setChecked(true); break; + default: break; + } + colorModePerFaceAct->setEnabled(HasPerFaceColor(GLA()->mm()->cm)); + switch (rm.colorMode) + { + case GLW::CMNone: colorModeNoneAct->setChecked(true); break; + case GLW::CMPerMesh: colorModePerMeshAct->setChecked(true); break; + case GLW::CMPerVert: colorModePerVertexAct->setChecked(true); break; + case GLW::CMPerFace: colorModePerFaceAct->setChecked(true); break; + default: break; + } + + lastFilterAct->setEnabled(false); + if(GLA()->getLastAppliedFilter() != NULL) + { + lastFilterAct->setText(QString("Apply filter ") + GLA()->getLastAppliedFilter()->text()); + lastFilterAct->setEnabled(true); + } + else + { + lastFilterAct->setText(QString("Apply filter ")); + } + + + // Management of the editing toolbar + // when you enter in a editing mode you can toggle between editing + // and camera moving by esc; + // you exit from editing mode by pressing again the editing button + // When you are in a editing mode all the other editing are disabled. + + foreach (QAction *a,PM.editActionList) + { + a->setChecked(false); + a->setEnabled( GLA()->getCurrentEditAction() == NULL ); + } + + suspendEditModeAct->setChecked(GLA()->suspendedEditor); + suspendEditModeAct->setDisabled(GLA()->getCurrentEditAction() == NULL); + + if(GLA()->getCurrentEditAction()) + { + GLA()->getCurrentEditAction()->setChecked(! GLA()->suspendedEditor); + GLA()->getCurrentEditAction()->setEnabled(true); + } + + showInfoPaneAct->setChecked(GLA()->infoAreaVisible); + showTrackBallAct->setChecked(GLA()->isTrackBallVisible()); + backFaceCullAct->setChecked(GLA()->getCurrentRenderMode().backFaceCull); + renderModeTextureAct->setEnabled(GLA()->mm() && !GLA()->mm()->cm.textures.empty()); + renderModeTextureAct->setChecked(GLA()->getCurrentRenderMode().textureMode != GLW::TMNone); + + setLightAct->setIcon(rm.lighting ? QIcon(":/images/lighton.png") : QIcon(":/images/lightoff.png") ); + setLightAct->setChecked(rm.lighting); + + setFancyLightingAct->setChecked(rm.fancyLighting); + setDoubleLightingAct->setChecked(rm.doubleSideLighting); + setSelectFaceRenderingAct->setChecked(rm.selectedFace); + setSelectVertRenderingAct->setChecked(rm.selectedVert); + + // Check only the active decorations + foreach (QAction *a, PM.decoratorActionList){a->setChecked(false);a->setEnabled(true);} + foreach (QAction *a, GLA()->iDecoratorsList){a->setChecked(true);} + + //Viewer + MultiViewer_Container *mvc = qobject_cast(mdiarea->currentSubWindow()); + if(!mvc) + mvc = qobject_cast(mdiarea->currentSubWindow()->widget()); + + setUnsplitAct->setEnabled(mvc->viewerCounter()>1); + GLArea* current =(GLArea*) mvc->currentView(); + + int heigh= current->size().height(); + int width = current->size().width(); + int heighM= current->minimumSizeHint().height(); + int widthM = current->minimumSizeHint().width(); + setSplitHAct->setEnabled(current->size().height()/2 > current->minimumSizeHint().height()); + setSplitVAct->setEnabled(current->size().width()/2 > current->minimumSizeHint().width()); + + + } // if active + else + { + foreach (QAction *a,PM.editActionList) + { + a->setEnabled(false); + } + foreach (QAction *a,PM.decoratorActionList) + a->setEnabled(false); + + } + + + if(GLA()) + { + MultiViewer_Container *mvc = qobject_cast(mdiarea->currentSubWindow()); + if(!mvc) + mvc = qobject_cast(mdiarea->currentSubWindow()->widget()); + + showLayerDlgAct->setChecked(mvc->layerDialog->isVisible()); + if(mvc->layerDialog->isVisible()) + mvc->layerDialog->updateTable(); + mvc->layerDialog->updateLog(GLA()->log); + } +} + +void MainWindow::dragEnterEvent(QDragEnterEvent *event) +{ + //qDebug("dragEnterEvent: %s",event->format()); + event->accept(); +} + +void MainWindow::dropEvent ( QDropEvent * event ) +{ + //qDebug("dropEvent: %s",event->format()); + const QMimeData * data = event->mimeData(); + if (data->hasUrls()) + { + QList< QUrl > url_list = data->urls(); + for (int i=0, size=url_list.size(); imeshDoc->delMesh(GLA()->meshDoc->mm()); + //stddialog->hide(); + GLA()->updateGL(); + updateMenus(); +} + +void MainWindow::updateGL() +{ + GLA()->updateGL(); +} + +void MainWindow::endEdit() +{ + GLA()->endEdit(); +} +//void MainWindow::applyLastFilter() +//{ +// if(GLA()==0) return; +// GLA()->getLastAppliedFilter()->activate(QAction::Trigger); +//} +//void MainWindow::showFilterScript() +//{ +// FilterScriptDialog dialog(this); +// dialog.setScript(&(GLA()->filterHistory)); +// if (dialog.exec()==QDialog::Accepted) +// { +// runFilterScript(); +// return ; +// } +// +//} + +//void MainWindow::runFilterScript() +//{ +// FilterScript::iterator ii; +// for(ii= GLA()->filterHistory.actionList.begin();ii!= GLA()->filterHistory.actionList.end();++ii) +// { +// QAction *action = PM.actionFilterMap[ (*ii).first]; +// MeshFilterInterface *iFilter = qobject_cast(action->parent()); +// +// int req=iFilter->getRequirements(action); +// GLA()->mm()->updateDataMask(req); +// iFilter->setLog(&(GLA()->log)); +// +// MeshDocument &meshDocument=GLA()->meshDoc; +// RichParameterSet ¶meterSet = (*ii).second; +// +// for(int i = 0; i < parameterSet.paramList.size(); i++) +// { +// //get a modifieable reference +// RichParameter* parameter = parameterSet.paramList[i]; +// +// //if this is a mesh paramter and the index is valid +// if(parameter->val->isMesh()) +// { +// MeshDecoration* md = reinterpret_cast(parameter->pd); +// if( md->meshindex < meshDocument.size() && +// md->meshindex >= 0 ) +// { +// RichMesh* rmesh = new RichMesh(parameter->name,meshDocument.getMesh(md->meshindex),&meshDocument); +// parameterSet.paramList.replace(i,rmesh); +// } else +// { +// printf("Meshes loaded: %i, meshes asked for: %i \n", meshDocument.size(), md->meshindex ); +// printf("One of the filters in the script needs more meshes than you have loaded.\n"); +// exit(-1); +// } +// delete parameter; +// } +// } +// //iFilter->applyFilter( action, *(GLA()->mm()), (*ii).second, QCallBack ); +// +// //WARNING!!!!!!!!!!!! +// /* to be changed */ +// iFilter->applyFilter( action, meshDocument, (*ii).second, QCallBack ); +// +// if(iFilter->getClass(action) & MeshFilterInterface::FaceColoring ) { +// GLA()->setColorMode(vcg::GLW::CMPerFace); +// GLA()->mm()->updateDataMask(MeshModel::MM_FACECOLOR); +// } +// if(iFilter->getClass(action) & MeshFilterInterface::VertexColoring ){ +// GLA()->setColorMode(vcg::GLW::CMPerVert); +// GLA()->mm()->updateDataMask(MeshModel::MM_VERTCOLOR); +// } +// if(iFilter->postCondition(action) & MeshModel::MM_COLOR) +// { +// GLA()->setColorMode(vcg::GLW::CMPerMesh); +// GLA()->mm()->updateDataMask(MeshModel::MM_COLOR); +// } +// if(iFilter->getClass(action) & MeshFilterInterface::Selection ) +// { +// GLA()->setSelectFaceRendering(true); +// GLA()->setSelectVertRendering(true); +// } +// if(iFilter->getClass(action) & MeshFilterInterface::MeshCreation ) +// GLA()->resetTrackBall(); +// /* to be changed */ +// +// GLA()->log.Logf(GLLogStream::SYSTEM,"Re-Applied filter %s",qPrintable((*ii).first)); +// } +//} + + +// ///////////////////////////////////////////////// +// The Very Important Procedure of applying a filter +// ///////////////////////////////////////////////// +// It is splitted in two part +// - startFilter that setup the dialogs and asks for parameters +// - executeFilter callback invoked when the params have been set up. + + +//void MainWindow::startFilter() +//{ + //QAction *action = qobject_cast(sender()); + //MeshFilterInterface *iFilter = qobject_cast(action->parent()); + // iFilter->setLog(&(GLA()->log)); + //if(GLA() == NULL && iFilter->getClass(action) != MeshFilterInterface::MeshCreation) return; + + // // In order to avoid that a filter changes something assumed by the current editing tool, + //// before actually starting the filter we close the current editing tool (if any). + //if(GLA()) GLA()->endEdit(); + //updateMenus(); + + //QStringList missingStuff; + //if(iFilter->getClass(action) == MeshFilterInterface::MeshCreation) + //{ + // qDebug("MeshCreation"); + // GLArea *gla=new GLArea(mdiarea,¤tGlobalParams); + // addDockWidget(Qt::RightDockWidgetArea,gla->layerDialog); + // gla->meshDoc.addNewMesh("untitled.ply"); + // gla->setFileName("untitled.ply"); + // mdiarea->addSubWindow(gla); + // if(mdiarea->isVisible()) gla->showMaximized(); + //} + //else + // if (!iFilter->isFilterApplicable(action,(*GLA()->mm()),missingStuff)) + // { + // QString enstr = missingStuff.join(","); + // QMessageBox::warning(0, tr("PreConditions' Failure"), QString("Warning the filter '" + iFilter->filterName(action) + "' has not been applied.
" + // "Current mesh does not have " + enstr + ".")); + // return; + // } + + // // just to be sure... + // createStdPluginWnd(); + + // // (2) Ask for filter parameters and eventally directly invoke the filter + // // showAutoDialog return true if a dialog have been created (and therefore the execution is demanded to the apply event) + // // if no dialog is created the filter must be executed immediately + // if(! stddialog->showAutoDialog(iFilter, GLA()->mm(), &(GLA()->meshDoc), action, this,GLA()) ) + // { + // RichParameterSet dummyParSet; + // executeFilter(action, dummyParSet, false); + // } +//} + +/* + callback function that actually start the chosen filter. + it is called once the parameters have been filled. + It can be called + from the automatic dialog + from the user defined dialog +*/ +//void MainWindow::executeFilter(QAction *action, RichParameterSet ¶ms, bool isPreview) +//{ +// +// MeshFilterInterface *iFilter = qobject_cast< MeshFilterInterface *>(action->parent()); +// +// qb->show(); +// iFilter->setLog(&(GLA()->log)); +// +// // Ask for filter requirements (eg a filter can need topology, border flags etc) +// // and statisfy them +// qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); +// MainWindow::globalStatusBar()->showMessage("Starting Filter...",5000); +// int req=iFilter->getRequirements(action); +// GLA()->mm()->updateDataMask(req); +// qApp->restoreOverrideCursor(); +// +// // (3) save the current filter and its parameters in the history +// if(!isPreview) +// GLA()->filterHistory.actionList.append(qMakePair(action->text(),params)); +// +// // (4) Apply the Filter +// bool ret; +// qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); +// QTime tt; tt.start(); +// GLA()->meshDoc.busy=true; +// ret=iFilter->applyFilter(action, GLA()->meshDoc, params, QCallBack); +// GLA()->meshDoc.busy=false; +// qApp->restoreOverrideCursor(); +// +// // (5) Apply post filter actions (e.g. recompute non updated stuff if needed) +// +// if(ret) +// { +// GLA()->log.Logf(GLLogStream::SYSTEM,"Applied filter %s in %i msec",qPrintable(action->text()),tt.elapsed()); +// GLA()->setWindowModified(true); +// GLA()->setLastAppliedFilter(action); +// lastFilterAct->setText(QString("Apply filter ") + action->text()); +// lastFilterAct->setEnabled(true); +// } +// else // filter has failed. show the message error. +// { +// QMessageBox::warning(this, tr("Filter Failure"), QString("Failure of filter: '%1'\n\n").arg(action->text())+iFilter->errorMsg()); // text +// } +// // at the end for filters that change the color, or selection set the appropriate rendering mode +// if(iFilter->getClass(action) & MeshFilterInterface::FaceColoring ) { +// GLA()->setColorMode(vcg::GLW::CMPerFace); +// GLA()->mm()->updateDataMask(MeshModel::MM_FACECOLOR); +// } +// if(iFilter->getClass(action) & MeshFilterInterface::VertexColoring ){ +// GLA()->setColorMode(vcg::GLW::CMPerVert); +// GLA()->mm()->updateDataMask(MeshModel::MM_VERTCOLOR); +// } +// if(iFilter->postCondition(action) & MeshModel::MM_COLOR) +// { +// GLA()->setColorMode(vcg::GLW::CMPerMesh); +// GLA()->mm()->updateDataMask(MeshModel::MM_COLOR); +// } +// if(iFilter->getClass(action) & MeshFilterInterface::Selection ) +// { +// GLA()->setSelectVertRendering(true); +// GLA()->setSelectFaceRendering(true); +// } +// if(iFilter->getClass(action) & MeshFilterInterface::MeshCreation ) +// GLA()->resetTrackBall(); +// +// if(iFilter->getClass(action) & MeshFilterInterface::Texture ) +// GLA()->updateTexture(); +// +// qb->reset(); +// updateMenus(); +// GLA()->update(); +//} + +// Edit Mode Managment +// At any point there can be a single editing plugin active. +// When a plugin is active it intercept the mouse actions. +// Each active editing tools +// +// + + +//void MainWindow::suspendEditMode() +//{ +// // return if no window is open +// if(!GLA()) return; +// +// // return if no editing action is currently ongoing +// if(!GLA()->getCurrentEditAction()) return; +// +// GLA()->suspendEditToggle(); +// updateMenus(); +//} +//void MainWindow::applyEditMode() +//{ +// if(!GLA()) { //prevents crash without mesh +// QAction *action = qobject_cast(sender()); +// action->setChecked(false); +// return; +// } +// +// QAction *action = qobject_cast(sender()); +// +// if(GLA()->getCurrentEditAction()) //prevents multiple buttons pushed +// { +// if(action==GLA()->getCurrentEditAction()) // We have double pressed the same action and that means disable that actioon +// { +// if(GLA()->suspendedEditor) +// { +// suspendEditMode(); +// return; +// } +// GLA()->endEdit(); +// updateMenus(); +// return; +// } +// assert(0); // it should be impossible to start an action without having ended the previous one. +// return; +// } +// +// //if this GLArea does not have an instance of this action's MeshEdit tool then give it one +// if(!GLA()->editorExistsForAction(action)) +// { +// MeshEditInterfaceFactory *iEditFactory = qobject_cast(action->parent()); +// MeshEditInterface *iEdit = iEditFactory->getMeshEditInterface(action); +// GLA()->addMeshEditor(action, iEdit); +// } +// GLA()->setCurrentEditAction(action); +// +// updateMenus(); +//} + +void MainWindow::applyRenderMode() +{ + QAction *action = qobject_cast(sender()); // find the action which has sent the signal + + // Make the call to the plugin core + MeshRenderInterface *iRenderTemp = qobject_cast(action->parent()); + iRenderTemp->Init(action,*(GLA()->meshDoc),GLA()->getCurrentRenderMode(),GLA()); + + if(action->text() == tr("None")) + { + GLA()->log.Logf(GLLogStream::SYSTEM,"No Shader"); + GLA()->setRenderer(0,0); //vertex and fragment programs not supported + } else { + if(iRenderTemp->isSupported()) + { + GLA()->setRenderer(iRenderTemp,action); + GLA()->log.Logf(GLLogStream::SYSTEM,"%s",qPrintable(action->text())); // Prints out action name + } + else + { + GLA()->setRenderer(0,0); //vertex and fragment programs not supported + GLA()->log.Logf(GLLogStream::WARNING,"Shader not supported!"); + } + } +} + + +//void MainWindow::applyDecorateMode() +//{ +// QAction *action = qobject_cast(sender()); // find the action which has sent the signal +// +// MeshDecorateInterface *iDecorateTemp = qobject_cast(action->parent()); +// +// bool found=false; +// QAction * p; +// foreach(p,GLA()->iDecoratorsList) +// { +// if(p->text()==action->text()){ +// GLA()->iDecoratorsList.remove(p); +// GLA()->log.Logf(0,"Disabled Decorate mode %s",qPrintable(action->text())); +// found=true; +// } +// } +// +// if(!found){ +// //RichParameterSet * decoratorParams = new RichParameterSet(); +// //iDecorateTemp->initGlobalParameterSet(action,decoratorParams); +// bool ret = iDecorateTemp->StartDecorate(action,*GLA()->mm(), ¤tGlobalParams, GLA()); +// if(ret) { +// GLA()->iDecoratorsList.push_back(action); +// GLA()->log.Logf(GLLogStream::SYSTEM,"Enable Decorate mode %s",qPrintable(action->text())); +// } +// else GLA()->log.Logf(GLLogStream::SYSTEM,"Failed Decorate mode %s",qPrintable(action->text())); +// +// } +// GLA()->update(); +//} + +bool MainWindow::QCallBack(const int pos, const char * str) +{ + int static lastPos=-1; + if(pos==lastPos) return true; + lastPos=pos; + + static QTime currTime; + if(currTime.elapsed()< 100) return true; + currTime.start(); + MainWindow::globalStatusBar()->showMessage(str,5000); + qb->show(); + qb->setEnabled(true); + qb->setValue(pos); + MainWindow::globalStatusBar()->update(); + qApp->processEvents(); + return true; +} + +void MainWindow::setLight() +{ + GLA()->setLight(!GLA()->getCurrentRenderMode().lighting); + updateMenus(); +}; + +void MainWindow::setDoubleLighting() +{ + const RenderMode &rm = GLA()->getCurrentRenderMode(); + GLA()->setLightMode(!rm.doubleSideLighting,LDOUBLE); +} + +void MainWindow::setFancyLighting() +{ + const RenderMode &rm = GLA()->getCurrentRenderMode(); + GLA()->setLightMode(!rm.fancyLighting,LFANCY); +} + +void MainWindow::toggleBackFaceCulling() +{ + RenderMode &rm = GLA()->getCurrentRenderMode(); + GLA()->setBackFaceCulling(!rm.backFaceCull); +} + +void MainWindow::toggleSelectFaceRendering() +{ + RenderMode &rm = GLA()->getCurrentRenderMode(); + GLA()->setSelectFaceRendering(!rm.selectedFace); +} +void MainWindow::toggleSelectVertRendering() +{ + RenderMode &rm = GLA()->getCurrentRenderMode(); + GLA()->setSelectVertRendering(!rm.selectedVert); +} + +bool MainWindow::openIn(QString /* fileName */) +{ + if(mdiarea->currentSubWindow()==0) return false; + MultiViewer_Container *mvc = qobject_cast(mdiarea->currentSubWindow()); + if(!mvc) + mvc = qobject_cast(mdiarea->currentSubWindow()->widget()); + + bool wasLayerVisible=mvc->layerDialog->isVisible(); + mvc->layerDialog->setVisible(false); + bool ret= open(QString(),GLA()); + mvc->layerDialog->setVisible(wasLayerVisible); + return ret; +} + +void MainWindow::saveProject() +{ + + QString fileName = QFileDialog::getSaveFileName(this,tr("Save Project File"),lastUsedDirectory.path().append("/untitled.aln"), tr("*.aln")); + + qDebug("Saving aln file %s\n",qPrintable(fileName)); + if (fileName.isEmpty()) return; + else + { + //save path away so we can use it again + QString path = fileName; + path.truncate(path.lastIndexOf("/")); + lastUsedDirectory.setPath(path); + } + + MeshDocument &meshDoc=*(GLA()->meshDoc); + vector meshNameVector; + vector transfVector; + + foreach(MeshModel * mp, meshDoc.meshList) + { + meshNameVector.push_back(qPrintable(mp->shortName())); + transfVector.push_back(mp->cm.Tr); + } + /*bool ret= ALNParser::SaveALN(qPrintable(fileName),meshNameVector,transfVector); + + if(!ret) + QMessageBox::critical(this, tr("Meshlab Saving Error"), QString("Unable to save project file %1\n").arg(fileName));*/ + +} + +bool MainWindow::openProject(QString fileName) +{ + if (fileName.isEmpty()) + fileName = QFileDialog::getOpenFileName(this,tr("Open Project File"), lastUsedDirectory.path(), "*.aln"); + if (fileName.isEmpty()) return false; + else + { + //save path away so we can use it again + QString path = fileName; + path.truncate(path.lastIndexOf("/")); + lastUsedDirectory.setPath(path); + } + + /*vector rmv; + + int retVal=ALNParser::ParseALN(rmv,qPrintable(fileName)); + if(retVal != ALNParser::NoError) + { + QMessageBox::critical(this, tr("Meshlab Opening Error"), "Unable to open ALN file"); + return false; + }*/ + + // this change of dir is needed for subsequent textures/materials loading + QFileInfo fi(fileName); + QDir::setCurrent(fi.absoluteDir().absolutePath()); + + /*bool openRes=true; + vector::iterator ir; + for(ir=rmv.begin();ir!=rmv.end() && openRes;++ir) + { + if(ir==rmv.begin()) openRes = open((*ir).filename.c_str()); + else openRes = open((*ir).filename.c_str(),GLA()); + + if(openRes) GLA()->mm()->cm.Tr=(*ir).trasformation; + }*/ + if(this->GLA() == 0) return false; + this->GLA()->resetTrackBall(); + return true; +} + +bool MainWindow::open(QString fileName, GLArea *gla) +{ + // Opening files in a transparent form (IO plugins contribution is hidden to user) + QStringList filters; + + // HashTable storing all supported formats together with + // the (1-based) index of first plugin which is able to open it + QHash allKnownFormats; + + PM.LoadFormats(filters, allKnownFormats,PluginManager::IMPORT); + filters.push_back("ALN project ( *.aln)"); + filters.front().chop(1); + filters.front().append(" *.aln)"); + QStringList fileNameList; + if (fileName.isEmpty()) + fileNameList = QFileDialog::getOpenFileNames(this,tr("Open File"), lastUsedDirectory.path(), filters.join("\n")); + else fileNameList.push_back(fileName); + + if (fileNameList.isEmpty()) return false; + else + { + //save path away so we can use it again + QString path = fileNameList.first(); + path.truncate(path.lastIndexOf("/")); + lastUsedDirectory.setPath(path); + } + + foreach(fileName,fileNameList) + { + QFileInfo fi(fileName); + if(fi.suffix().toLower()=="aln") openProject(fileName); + else + { + if(!fi.exists()) { + QString errorMsgFormat = "Unable to open file:\n\"%1\"\n\nError details: file %1 does not exist."; + QMessageBox::critical(this, tr("Meshlab Opening Error"), errorMsgFormat.arg(fileName)); + return false; + } + if(!fi.isReadable()) { + QString errorMsgFormat = "Unable to open file:\n\"%1\"\n\nError details: file %1 is not readable."; + QMessageBox::critical(this, tr("Meshlab Opening Error"), errorMsgFormat.arg(fileName)); + return false; + } + + // this change of dir is needed for subsequent textures/materials loading + QDir::setCurrent(fi.absoluteDir().absolutePath()); + + QString extension = fi.suffix(); + + // retrieving corresponding IO plugin + MeshIOInterface *pCurrentIOPlugin = allKnownFormats[extension.toLower()]; + if (pCurrentIOPlugin == 0) + { + QString errorMsgFormat = "Error encountered while opening file:\n\"%1\"\n\nError details: The \"%2\" file extension does not correspond to any supported format."; + QMessageBox::critical(this, tr("Opening Error"), errorMsgFormat.arg(fileName, extension)); + return false; + } + //MeshIOInterface* pCurrentIOPlugin = meshIOPlugins[idx-1]; + bool newGla = false; + MultiViewer_Container *mvcont; + if(gla==0){ + mvcont = new MultiViewer_Container(mdiarea); + int id = mvcont->getNextViewerId(); + gla=new GLArea(mdiarea,mvcont, ¤tGlobalParams,id, &(mvcont->meshDoc)); //SAREBBE MEGLIO METTERE DA SUBITO CHE E'FIGLIO DI MVC MA DEVI MODIFICARE IL COSTRUTTORE DI GLAREA + mvcont->addView(gla, Qt::Horizontal); + addDockWidget(Qt::RightDockWidgetArea,mvcont->layerDialog); + mvcont->connectToLayerDialog(gla); + newGla =true; + pCurrentIOPlugin->setLog(&(gla->log)); + } + else + pCurrentIOPlugin->setLog(&(GLA()->log)); + + qb->show(); + RichParameterSet prePar; + pCurrentIOPlugin->initPreOpenParameter(extension, fileName,prePar); + if(!prePar.isEmpty()) + { + GenericParamDialog preOpenDialog(this, &prePar, tr("Pre-Open Options")); + preOpenDialog.exec(); + } + + int mask = 0; + MeshModel *mm= new MeshModel(); + if (!pCurrentIOPlugin->open(extension, fileName, *mm ,mask,prePar,QCallBack,this /*gla*/)) + { + QMessageBox::warning(this, tr("Opening Failure"), QString("While opening: '%1'\n\n").arg(fileName)+pCurrentIOPlugin->errorMsg()); // text + delete mm; + } + else{ + // After opening the mesh lets ask to the io plugin if this format + // requires some optional, or userdriven post-opening processing. + // and in that case ask for the required parameters and then + // ask to the plugin to perform that processing + RichParameterSet par; + pCurrentIOPlugin->initOpenParameter(extension, *mm, par); + if(!par.isEmpty()) + { + GenericParamDialog postOpenDialog(this, &par, tr("Post-Open Processing")); + postOpenDialog.exec(); + pCurrentIOPlugin->applyOpenParameter(extension, *mm, par); + } + + gla->meshDoc->busy=true; + gla->meshDoc->addNewMesh(qPrintable(fileName),mm); + + //gla->mm()->ioMask |= mask; // store mask into model structure + gla->setFileName(mm->shortName()); + if(newGla){ + //mdiarea->addSubWindow(gla);IO + mdiarea->addSubWindow(mvcont); + } + if(mdiarea->isVisible()) mvcont->showMaximized(); + setCurrentFile(fileName); + + if( mask & vcg::tri::io::Mask::IOM_FACECOLOR) + gla->setColorMode(GLW::CMPerFace); + if( mask & vcg::tri::io::Mask::IOM_VERTCOLOR) + { + gla->setColorMode(GLW::CMPerVert); + } + renderModeTextureAct->setChecked(false); + renderModeTextureAct->setEnabled(false); + if(!GLA()->mm()->cm.textures.empty()) + { + renderModeTextureAct->setChecked(true); + renderModeTextureAct->setEnabled(true); + GLA()->setTextureMode(GLW::TMPerWedgeMulti); + } + + // In case of polygonal meshes the normal should be updated accordingly + if( mask & vcg::tri::io::Mask::IOM_BITPOLYGONAL) + { + mm->updateDataMask(MeshModel::MM_POLYGONAL); // just to be sure. Hopefully it should be done in the plugin... + int degNum = tri::Clean::RemoveDegenerateFace(mm->cm); + if(degNum) GLA()->log.Logf(0,"Warning model contains %i degenerate faces. Removed them.",degNum); + mm->updateDataMask(MeshModel::MM_FACEFACETOPO); + vcg::tri::UpdateNormals::PerBitQuadFaceNormalized(mm->cm); + vcg::tri::UpdateNormals::PerVertexFromCurrentFaceNormal(mm->cm); + } // standard case + else { + if( mask & vcg::tri::io::Mask::IOM_VERTNORMAL) + vcg::tri::UpdateNormals::PerFace(mm->cm); + else + vcg::tri::UpdateNormals::PerVertexNormalizedPerFaceNormalized(mm->cm); + } + vcg::tri::UpdateBounding::Box(mm->cm); // updates bounding box + + if(gla->mm()->cm.fn==0){ + gla->setDrawMode(vcg::GLW::DMPoints); + if(!(mask & vcg::tri::io::Mask::IOM_VERTNORMAL)) gla->setLight(false); + else mm->updateDataMask(MeshModel::MM_VERTNORMAL); + } + else mm->updateDataMask(MeshModel::MM_VERTNORMAL); + + updateMenus(); + int delVertNum = vcg::tri::Clean::RemoveDegenerateVertex(mm->cm); + int delFaceNum = vcg::tri::Clean::RemoveDegenerateFace(mm->cm); + + if(delVertNum>0 || delFaceNum>0 ) + QMessageBox::warning(this, "MeshLab Warning", QString("Warning mesh contains %1 vertices with NAN coords and %2 degenerated faces.\nCorrected.").arg(delVertNum).arg(delFaceNum) ); + GLA()->meshDoc->busy=false; + if(newGla) GLA()->resetTrackBall(); + } + } + }// end foreach file of the input list + if(GLA()) GLA()->update(); + qb->reset(); + return true; +} + +void MainWindow::openRecentFile() +{ + QAction *action = qobject_cast(sender()); + if (action) open(action->data().toString()); +} + +void MainWindow::reload() +{ + // Discards changes and reloads current file + // save current file name + QString file = GLA()->getFileName(); + // close current window + mdiarea->closeActiveSubWindow(); + + // open a new window with old file + open(file); +} + +bool MainWindow::save() +{ + return saveAs(GLA()->mm()->fullName()); +} + + +bool MainWindow::saveAs(QString fileName) +{ + QStringList filters; + + QHash allKnownFormats; + + PM.LoadFormats( filters, allKnownFormats,PluginManager::EXPORT); + + if (fileName.isEmpty()) + fileName = QFileDialog::getSaveFileName(this,tr("Save File"),GLA()->mm()->shortName(), filters.join("\n")); + + bool ret = false; + + QStringList fs = fileName.split("."); + + if(!fileName.isEmpty() && fs.size() < 2) + { + QMessageBox::warning(new QWidget(),"Save Error","You must specify file extension!!"); + return ret; + } + + if (!fileName.isEmpty()) + { + //save path away so we can use it again + QString path = fileName; + path.truncate(path.lastIndexOf("/")); + lastUsedDirectory.setPath(path); + + QString extension = fileName; + extension.remove(0, fileName.lastIndexOf('.')+1); + + QStringListIterator itFilter(filters); + + MeshIOInterface *pCurrentIOPlugin = allKnownFormats[extension.toLower()]; + if (pCurrentIOPlugin == 0) + { + QMessageBox::warning(this, "Unknown type", "File extension not supported!"); + return false; + } + //MeshIOInterface* pCurrentIOPlugin = meshIOPlugins[idx-1]; + pCurrentIOPlugin->setLog(&(GLA()->log)); + + int capability=0,defaultBits=0; + pCurrentIOPlugin->GetExportMaskCapability(extension,capability,defaultBits); + + // optional saving parameters (like ascii/binary encoding) + RichParameterSet savePar; + + pCurrentIOPlugin->initSaveParameter(extension,*(this->GLA()->mm()),savePar); + + /*SaveMaskExporterDialog maskDialog(new QWidget(),this->GLA()->mm(),capability,defaultBits,&savePar,this->GLA()); + maskDialog.exec(); + int mask = maskDialog.GetNewMask(); + maskDialog.close(); + if(maskDialog.result() == QDialog::Rejected) + return false; + if(mask == -1) + return false;*/ + + qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); + qb->show(); + QTime tt; tt.start(); + //ret = pCurrentIOPlugin->save(extension, fileName, *this->GLA()->mm() ,mask,savePar,QCallBack,this); + qb->reset(); + GLA()->log.Logf(GLLogStream::SYSTEM,"Saved Mesh %s in %i msec",qPrintable(fileName),tt.elapsed()); + + qApp->restoreOverrideCursor(); + //GLA()->mm()->fileName = fileName.toStdString(); + GLA()->setFileName(fileName); + QSettings settings; + int savedMeshCounter=settings.value("savedMeshCounter",0).toInt(); + settings.setValue("savedMeshCounter",savedMeshCounter+1); + GLA()->setWindowModified(false); + + } + return ret; +} + +//bool MainWindow::saveSnapshot() +//{ +// +// SaveSnapshotDialog dialog(this); +// +// SnapshotSetting ss = GLA()->getSnapshotSetting(); +// dialog.setValues(ss); +// +// if (dialog.exec()==QDialog::Accepted) +// { +// ss=dialog.getValues(); +// GLA()->setSnapshotSetting(ss); +// GLA()->saveSnapshot(); +// return true; +// } +// +// return false; +//} +//void MainWindow::about() +//{ +// QDialog *about_dialog = new QDialog(); +// Ui::aboutDialog temp; +// temp.setupUi(about_dialog); +// temp.labelMLName->setText(appName()+" ("+__DATE__+")"); +// //about_dialog->setFixedSize(566,580); +// about_dialog->show(); +//} + +//void MainWindow::aboutPlugins() +//{ +// qDebug( "aboutPlugins(): Current Plugins Dir: %s ",qPrintable(pluginsDir.absolutePath())); +// PluginDialog dialog(pluginsDir.absolutePath(), pluginFileNames, this); +// dialog.exec(); +//} + +void MainWindow::helpOnscreen() +{ +if(GLA()) GLA()->toggleHelpVisible(); +} + +void MainWindow::helpOnline() +{ + checkForUpdates(false); + QDesktopServices::openUrl(QUrl("http://meshlab.sourceforge.net/wiki")); +} + + +void MainWindow::showToolbarFile(){ + mainToolBar->setVisible(!mainToolBar->isVisible()); +} + +void MainWindow::showToolbarRender(){ + renderToolBar->setVisible(!renderToolBar->isVisible()); +} + +void MainWindow::showInfoPane() {if(GLA() != 0) GLA()->infoAreaVisible =!GLA()->infoAreaVisible;} +void MainWindow::showTrackBall() {if(GLA() != 0) GLA()->showTrackBall(!GLA()->isTrackBallVisible());} +void MainWindow::resetTrackBall(){if(GLA() != 0) GLA()->resetTrackBall();} +void MainWindow::showLayerDlg() { + if(mdiarea->currentSubWindow()==0) return; + MultiViewer_Container *mvc = qobject_cast(mdiarea->currentSubWindow()); + if(!mvc) + mvc = qobject_cast(mdiarea->currentSubWindow()->widget()); + + if(GLA() != 0) + mvc->layerDialog->setVisible( !mvc->layerDialog->isVisible() );} + +//void MainWindow::setCustomize() +//{ +// CustomDialog dialog(currentGlobalParams,defaultGlobalParams, this); +// connect(&dialog,SIGNAL(applyCustomSetting()),this,SLOT(updateCustomSettings())); +// dialog.exec(); +//} + +void MainWindow::setSplit(QAction *qa) +{ + if(mdiarea->currentSubWindow()==0) return; + MultiViewer_Container *mvc = qobject_cast(mdiarea->currentSubWindow()); + if(!mvc) + mvc = qobject_cast(mdiarea->currentSubWindow()->widget()); + GLArea *glw = (GLArea*)(mvc->currentView()); + int id = mvc->getNextViewerId(); + GLArea *glwClone=new GLArea(mdiarea,mvc, ¤tGlobalParams,id, &(mvc->meshDoc)); + if(qa->text() == tr("&Horizontally")) + mvc->addView(glwClone, Qt::Vertical); + else + mvc->addView(glwClone, Qt::Horizontal); + + updateMenus(); + + glwClone->resetTrackBall(); + + glwClone->update(); + +} + +void MainWindow::setUnsplit() +{ + if(mdiarea->currentSubWindow()==0) return; + MultiViewer_Container *mvc = qobject_cast(mdiarea->currentSubWindow()); + if(!mvc) + mvc = qobject_cast(mdiarea->currentSubWindow()->widget()); + + assert(mvc->viewerCounter() >1); + + mvc->removeView(mvc->currentView()->getId()); + + updateMenus(); +} + +void MainWindow::renderBbox() { GLA()->setDrawMode(GLW::DMBox ); } +void MainWindow::renderPoint() { GLA()->setDrawMode(GLW::DMPoints ); } +void MainWindow::renderWire() { GLA()->setDrawMode(GLW::DMWire ); } +void MainWindow::renderFlat() { GLA()->setDrawMode(GLW::DMFlat ); } +void MainWindow::renderFlatLine() { GLA()->setDrawMode(GLW::DMFlatWire); } +void MainWindow::renderHiddenLines() { GLA()->setDrawMode(GLW::DMHidden ); } +void MainWindow::renderSmooth() { GLA()->setDrawMode(GLW::DMSmooth ); } +void MainWindow::renderTexture() +{ + QAction *a = qobject_cast(sender()); + GLA()->setTextureMode(!a->isChecked() ? GLW::TMNone : GLW::TMPerWedgeMulti); +} + + +void MainWindow::fullScreen(){ + if(!isFullScreen()) + { + toolbarState = saveState(); + menuBar()->hide(); + mainToolBar->hide(); + renderToolBar->hide(); + globalStatusBar()->hide(); + setWindowState(windowState()^Qt::WindowFullScreen); + bool found=true; + //Caso di piu' finestre aperte in tile: + if((mdiarea->subWindowList()).size()>1){ + foreach(QWidget *w,mdiarea->subWindowList()){if(w->isMaximized()) found=false;} + if (found)mdiarea->tileSubWindows(); + } + } + else + { + menuBar()->show(); + restoreState(toolbarState); + globalStatusBar()->show(); + + setWindowState(windowState()^ Qt::WindowFullScreen); + bool found=true; + //Caso di piu' finestre aperte in tile: + if((mdiarea->subWindowList()).size()>1){ + foreach(QWidget *w,mdiarea->subWindowList()){if(w->isMaximized()) found=false;} + if (found){mdiarea->tileSubWindows();} + } + fullScreenAct->setChecked(false); + } +} + +void MainWindow::keyPressEvent(QKeyEvent *e) +{ + if(e->key()==Qt::Key_Return && e->modifiers()==Qt::AltModifier) + { + fullScreen(); + e->accept(); + } + else e->ignore(); +} diff --git a/src/meshlab_2.01/meshlab.qrc b/src/meshlab_2.01/meshlab.qrc new file mode 100644 index 000000000..42d21341e --- /dev/null +++ b/src/meshlab_2.01/meshlab.qrc @@ -0,0 +1,38 @@ + + + images/backlines.png + images/bbox.png + images/cursors/plain.png + images/cursors/plain_pan.png + images/cursors/plain_trackball.png + images/cursors/plain_zoom.png + images/eye48.png + images/eye_256_splash.png + images/flat.png + images/flatlines.png + images/info.png + images/lightoff.png + images/lighton.png + images/logo.png + images/logo_aimatshape.png + images/logo_epoch.png + images/logo_epoch_2.png + images/no_edit.png + images/open.png + images/points.png + images/reload.png + images/save.png + images/smooth.png + images/snapshot.png + images/textures.png + images/wire.png + images/layers.png + images/layer_eye_open.png + images/layer_eye_close.png + images/layer_edit_locked.png + images/layer_edit_unlocked.png + images/100mesh.html + images/selected_face.png + images/selected_vert.png + + diff --git a/src/meshlab_2.01/meshlab.rc b/src/meshlab_2.01/meshlab.rc new file mode 100644 index 000000000..8011167df --- /dev/null +++ b/src/meshlab_2.01/meshlab.rc @@ -0,0 +1 @@ + IDI_ICON1 ICON DISCARDABLE "images/eye.ico" \ No newline at end of file diff --git a/src/meshlab_2.01/meshlab_2.0.pro b/src/meshlab_2.01/meshlab_2.0.pro new file mode 100644 index 000000000..20434a07d --- /dev/null +++ b/src/meshlab_2.01/meshlab_2.0.pro @@ -0,0 +1,121 @@ +VCGDIR = ../../../vcglib +GLEWDIR = ../external/glew-1.5.1 +#CONFIG += debug_and_release +DESTDIR = ../distrib +# uncomment to try Eigen +# DEFINES += VCG_USE_EIGEN +# CONFIG += warn_off +INCLUDEPATH *= ../.. \ + $$VCGDIR \ + $$GLEWDIR/include +DEPENDPATH += $$VCGDIR \ + $$VCGDIR/vcg \ + $$VCGDIR/wrap +HEADERS = ../common/interfaces.h \ + mainwindow.h \ + glarea.h \ + multiViewer_Container.h \ + viewer.h \ + glarea_setting.h \ + #plugindialog.h \ + #customDialog.h \ + #filterScriptDialog.h \ + #saveSnapshotDialog.h \ + #savemaskexporter.h \ + #changetexturename.h \ + layerDialog.h \ + stdpardialog.h \ + $$VCGDIR/wrap/gui/trackball.h \ + $$VCGDIR/wrap/gui/trackmode.h \ + $$VCGDIR/wrap/gl/trimesh.h +SOURCES = main.cpp \ + mainwindow_Init.cpp \ + mainwindow_RunTime.cpp \ + glarea.cpp \ + multiViewer_Container.cpp \ + #plugindialog.cpp \ + #customDialog.cpp \ + #filterScriptDialog.cpp \ + #saveSnapshotDialog.cpp \ + layerDialog.cpp \ + #savemaskexporter.cpp \ + #changetexturename.cpp \ + stdpardialog.cpp \ + $$VCGDIR/wrap/gui/trackball.cpp \ + $$VCGDIR/wrap/gui/trackmode.cpp \ + glarea_setting.cpp + +FORMS = ui/layerDialog.ui + # ui/savesnapshotDialog.ui \ + # ui/filterScriptDialog.ui \ + # ui/customDialog.ui \ + # ui/aboutDialog.ui \ + # ui/renametexture.ui \ + # ui/savemaskexporter.ui \ + # ui/congratsDialog.ui +RESOURCES = meshlab.qrc + +# to add windows icon +RC_FILE = meshlab.rc + +# ## the xml info list +# ## the next time the app open a new extension +QMAKE_INFO_PLIST = ../install/info.plist + +# to add MacOS icon +ICON = images/meshlab.icns + +# note that to add the file icons on the mac the following line does not work. +# You have to copy the file by hand into the meshlab.app/Contents/Resources directory. +# ICON += images/meshlab_obj.icns +QT += opengl +QT += xml +QT += network + +# the following line is needed to avoid mismatch between +# the awful min/max macros of windows and the limits max +win32:DEFINES += NOMINMAX + +# the following line is to hide the hundred of warnings about the deprecated +# old printf are all around the code +win32-msvc2005:DEFINES += _CRT_SECURE_NO_DEPRECATE +win32-msvc2008:DEFINES += _CRT_SECURE_NO_DEPRECATE +mac:QMAKE_CXX = g++-4.2 + +# Uncomment these if you want to experiment with newer gcc compilers +# (here using the one provided with macports) +# macx-g++:QMAKE_CXX=g++-mp-4.3 +# macx-g++:QMAKE_CXXFLAGS_RELEASE -= -Os +# macx-g++:QMAKE_CXXFLAGS_RELEASE += -O3 + +INCLUDEPATH += . \ + .. \ + ../../../vcglib \ + $$GLEWDIR/include +CONFIG += stl + +macx:LIBS += ../common/libcommon.dylib +macx:QMAKE_POST_LINK ="cp ../common/libcommon* ../distrib/meshlab.app/Contents/MacOS; install_name_tool -change libcommon.1.dylib @executable_path/libcommon.1.dylib ../distrib/meshlab.app/Contents/MacOS/meshlab" + + + + +win32-msvc2005:LIBS += -L../distrib -lcommon +win32-msvc2008:LIBS += -L../distrib -lcommon +win32-g++:LIBS += -L../distrib -lcommon + +#CONFIG(release,debug | release) { +# win32-msvc2005:release:LIBS += -L../common/release -lcommon +# win32-msvc2008:release:LIBS += -L../common/release -lcommon +# win32-g++:release:LIBS += -L../common/release -lcommon +#} + +unix:LIBS += -L../common -lcommon + +# uncomment in your local copy only in emergency cases. +# We should never be too permissive +# win32-g++:QMAKE_CXXFLAGS += -fpermissive + +# The following define is needed in gcc to remove the asserts +win32-g++:DEFINES += NDEBUG +CONFIG(debug, debug|release):win32-g++:release:DEFINES -= NDEBUG diff --git a/src/meshlab_2.01/multiViewer_Container.cpp b/src/meshlab_2.01/multiViewer_Container.cpp new file mode 100644 index 000000000..9686c8f04 --- /dev/null +++ b/src/meshlab_2.01/multiViewer_Container.cpp @@ -0,0 +1,310 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +#include "multiViewer_Container.h" +#include "glarea.h" + +using namespace vcg; + +MultiViewer_Container::MultiViewer_Container(QWidget *parent) +: QSplitter(parent) +{ + viewerList = QVector(); + + setChildrenCollapsible(false); + + idCounter=0; + + layerDialog = new LayerDialog(this); + layerDialog->setAllowedAreas (Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + + +} + +MultiViewer_Container::~MultiViewer_Container(){ + foreach(Viewer* viewer, viewerList) + delete viewer; + delete layerDialog; +} + +int MultiViewer_Container::getNextViewerId(){ + return idCounter++; +} + +void MultiViewer_Container::addView(Viewer* viewer,Qt::Orientation orient){//bool horiz){ + //The Viewers are organized like in a BSP tree. + // Every new viewer are added within an Horizontal splitter. Its orientation could change according to next insertions. + // HSplit + // / \ + // View1 VSplit + // / \ + // View2 HSplit + // / + // View3 + //In the GUI, when a viewer is splitted, the new one appears on its right (the space is split in two equal portions). + + viewerList.append(viewer); + int count = viewerCounter(); + + //CASE 1: only when the first viewer is opened. Here there is no current view. + if (count==1){ + addWidget((GLArea*) viewer); + } + + else{ + GLArea* current = (GLArea*)currentView(); + QSplitter* parentSplitter = qobject_cast(current->parent()); + //CASE 2: Simple insertion inside the parent splitter (right branch). + //Example: Add View3: + // + // HSplit HSplit + // / => / \ + // View1 View1 HSplit + // | + // View2 + if(parentSplitter->count()==1){ + + parentSplitter->setOrientation(orient); + + QSplitter* newSplitter = new QSplitter(Qt::Horizontal); + + parentSplitter->addWidget(newSplitter); + newSplitter->addWidget((GLArea*)viewer); + + //Setting the size of the widgets inside parent splitter. + QList *sizes = new QList(); + + if(parentSplitter->orientation()== Qt::Horizontal){ + sizes->append(parentSplitter->width()/2); + sizes->append(parentSplitter->width()/2); + } + else{ + sizes->append(parentSplitter->height()/2); + sizes->append(parentSplitter->height()/2); + } + + parentSplitter->setSizes(*sizes); + + parentSplitter->setHandleWidth(2); + + newSplitter->setChildrenCollapsible(false); + + } + //CASE 3: The parent splitter has two children. The insertion is on the left branch. + //Example: Add View3: + // + // HSplit HSplit + // / \ / \ + // View1 HSplit => VSplit HSplit + // | / \ | + // View2 View1 HSplit View2 + // | + // View3 + else{ + QSplitter* newSplitter; + newSplitter = new QSplitter(orient); + + QList sizes2 = parentSplitter->sizes(); + parentSplitter->insertWidget(0, newSplitter); + + QSplitter* newSplitter2 = new QSplitter(Qt::Horizontal); + newSplitter2->addWidget((GLArea*)viewer); + current->setParent(newSplitter); + newSplitter->addWidget(newSplitter2); + + //Setting the size of the widgets inside parent splitter + QList *sizes = new QList(); + if(newSplitter->orientation()== Qt::Horizontal){ + sizes->append(parentSplitter->width()/2); + sizes->append(parentSplitter->width()/2); + } + else{ + sizes->append(parentSplitter->height()/2); + sizes->append(parentSplitter->height()/2); + } + + parentSplitter->setSizes(sizes2); + newSplitter->setSizes(*sizes); + newSplitter->setHandleWidth(2); + + newSplitter->setChildrenCollapsible(false); + newSplitter2->setChildrenCollapsible(false); + } + } + + currentId = viewer->getId(); + //action for new viewer + connect((GLArea*) viewer, SIGNAL(currentViewerChanged(int)), this, SLOT(updateCurrent(int))); + + +} + +void MultiViewer_Container::removeView(int viewerId){ + for (int i=0; i< viewerList.count(); i++){ + Viewer* viewer = viewerList.at(i); + if (viewer->getId() == viewerId){ + viewerList.remove(i); + QSplitter* parentSplitter = qobject_cast(((GLArea*)viewer)->parent()); + delete viewer; + + //CASE 1: Simple deletion. + //Example: Cancel View2: + // + // HSplit HSplit + // / \ / + // View1 HSplit => View1 + // | + // View2 + + if(parentSplitter->count()==0) + delete parentSplitter; + + //CASE 2: Complex deletion, adjust the tree. + // Example: Cancel View1: + // + // HSplit HSplit + // / \ / \ + // VSplit HSplit => HSplit HSplit + // / \ | | | + // View1 HSplit View2 View3 View2 + // | + // View3 + + else if(parentSplitter->count()==1){ + QSplitter* parentParentSplitter = qobject_cast(parentSplitter->parent()); + if(parentParentSplitter){ + int index = parentParentSplitter->indexOf(parentSplitter); + parentParentSplitter->insertWidget(index,parentSplitter->widget(0)); + delete parentSplitter; + } + } + + currentId = viewerList.at(0)->getId(); //per default il current è il primo viewer della lista (sempre presente) + + updateLayout(); + } + } +} + +void MultiViewer_Container::connectToLayerDialog(Viewer* viewer){ + connect(((GLArea*) viewer)->meshDoc, SIGNAL(currentMeshChanged(int)),layerDialog, SLOT(updateTable())); +} + +void MultiViewer_Container::updateCurrent(int current){ + currentId=current; +} + +void MultiViewer_Container::updatePressViewers(QMouseEvent *e){ + foreach(Viewer* viewer, viewerList) + if(viewer->getId() != currentId){ + ((GLArea*) viewer)->mousePressEvent2(e); + } +} + +void MultiViewer_Container::updateMoveViewers(QMouseEvent *e){ + foreach(Viewer* viewer, viewerList) + if(viewer->getId() != currentId){ + ((GLArea*) viewer)->mouseMoveEvent(e); + } +} + +void MultiViewer_Container::updateReleaseViewers(QMouseEvent *e){ + foreach(Viewer* viewer, viewerList) + if(viewer->getId() != currentId){ + ((GLArea*) viewer)->mouseReleaseEvent(e); + } +} + + +void MultiViewer_Container::updateLayout(){ + foreach(Viewer* viewer, viewerList) + //splitter->removeWidget((GLArea*)viewer); + for (int i=0; i< viewerList.count(); i++){ + int row = i/2; + int column = i%2; + //splitter->addWidget((GLArea*)viewerList.at(i));//, row, column); + } +} + +Viewer* MultiViewer_Container::currentView(){ + foreach ( Viewer* viewer, viewerList) + if (viewer->getId() == currentId) + return viewer; +} + +int MultiViewer_Container::viewerCounter(){ + return viewerList.count(); +} + +//void MultiViewer_Container::resizeEvent ( QResizeEvent * event ) { +// /*if(data->imageList.size()!=0){ +// imageVis->adjustSize(); +// }*/ +//} +/// update all the visual widgets at one time (glw, imageVis, tree, imageMag) +void MultiViewer_Container::updateAll(){ + /*glw->update(); + imageVis->update(); + imageMag->update(); + tree->updatePoints();*/ +} +void MultiViewer_Container::keyPressEvent(QKeyEvent *keyEv){ + //keyEv->accept(); + // + //// if the Delete key is pressed, then remove the selected point + //if((data->selectedImagePoint.x()!=-1 || data->selectedMeshPoint!=-1) && keyEv->key() == Qt::Key_Delete){ + // + // if(data->selectedImagePoint.x()!=-1){ + // data->deleteImagePoint(data->selectedImagePoint); + // imageMag->update(); + // glw->update(); + // } + // else{ data->deleteMeshPoint(data->selectedMeshPoint); + // glw->update(); + // } + // + //}else + // // if any of WASD keys are pressed, then move the selected image point + // if(data->selectedImagePoint.x()!=-1 && (keyEv->key() == Qt::Key_A || keyEv->key() == Qt::Key_S || keyEv->key() == Qt::Key_D || keyEv->key() == Qt::Key_W)){ + // QPoint currentPoint = data->selectedImagePoint; + // + // switch(keyEv->key()){ + // case Qt::Key_A: + // currentPoint.setX(currentPoint.x()-1); + // data->setSelectedImagePoint(currentPoint); + // break; + // case Qt::Key_D: + // currentPoint.setX(currentPoint.x()+1); + // data->setSelectedImagePoint(currentPoint); + // break; + // case Qt::Key_W: + // currentPoint.setY(currentPoint.y()-1); + // data->setSelectedImagePoint(currentPoint); + // break; + // case Qt::Key_S: + // currentPoint.setY(currentPoint.y()+1); + // data->setSelectedImagePoint(currentPoint); + // break; + // } + // imageMag->update(); + //} +} \ No newline at end of file diff --git a/src/meshlab_2.01/multiViewer_Container.h b/src/meshlab_2.01/multiViewer_Container.h new file mode 100644 index 000000000..3e3997d3d --- /dev/null +++ b/src/meshlab_2.01/multiViewer_Container.h @@ -0,0 +1,87 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +#ifndef __MAULTIVIEWER_CONTAINER_H__ +#define __MAULTIVIEWER_CONTAINER_H__ + +#include "../../../vcglib/wrap/ply/plylib.h" +#include "../../../vcglib/wrap/io_trimesh/import_ply.h" +#include "../../../vcglib/wrap/io_trimesh/export_ply.h" + +#include +#include +#include + +#include "../common/meshmodel.h" +#include "viewer.h" +#include "layerDialog.h" + + +// Class list + +class RichParameterSet; + +class MultiViewer_Container : public QSplitter +{ + Q_OBJECT + +public: + MultiViewer_Container(QWidget *parent); + ~MultiViewer_Container(); + + /// load an image in the painter widget, the imageNumber is the index of imageList that has the image wanted (0-base index!) + void addView(Viewer* viewer, Qt::Orientation);//bool horiz); + void removeView(int); + /// update all the visual widgets at one time (glw, imageVis, tree, imageMag) + void updateAll(); + Viewer* currentView(); + int getNextViewerId(); + + int viewerCounter(); + void updateLayout(); + + void connectToLayerDialog(Viewer* viewer); + + void updatePressViewers(QMouseEvent *e); + void updateMoveViewers(QMouseEvent *e); + void updateReleaseViewers(QMouseEvent *e); + + LayerDialog *layerDialog; + MeshDocument meshDoc; + int currentId; + +public slots: + + // Called when we change viewer, set the current viewer + void updateCurrent(int current); + +private: + int idCounter; + QVector viewerList; /// widgets for the OpenGL contexts and images + + void keyPressEvent(QKeyEvent *keyEv); + // other stuff + //void resizeEvent ( QResizeEvent *); + +}; + +#endif // __MAULTIVIEWER_CONTAINER_H__ \ No newline at end of file diff --git a/src/meshlab_2.01/stdpardialog.cpp b/src/meshlab_2.01/stdpardialog.cpp new file mode 100644 index 000000000..f321d3a3b --- /dev/null +++ b/src/meshlab_2.01/stdpardialog.cpp @@ -0,0 +1,1443 @@ +/**************************************************************************** +* MeshLab o o * +* An extendible mesh processor o o * +* _ O _ * +* Copyright(C) 2005, 2008 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + + +#include "stdpardialog.h" +#include +using namespace vcg; +MeshlabStdDialog::MeshlabStdDialog(QWidget *p) +:QDockWidget(QString("Plugin"), p),curmask(MeshModel::MM_UNKNOWN) +{ + qf = NULL; + stdParFrame=NULL; + clearValues(); +} + +StdParFrame::StdParFrame(QWidget *p, QWidget *curr_gla) +//:QDialog(p) +:QFrame(p) +{ + gla=curr_gla; +} + + +/* manages the setup of the standard parameter window, when the execution of a plugin filter is requested */ +bool MeshlabStdDialog::showAutoDialog(MeshFilterInterface *mfi, MeshModel *mm, MeshDocument * mdp, QAction *action, MainWindowInterface *mwi, QWidget *gla) +{ + validcache = false; + curAction=action; + curmfi=mfi; + curmwi=mwi; + curParSet.clear(); + prevParSet.clear(); + curModel = mm; + curMeshDoc = mdp; + curgla=gla; + + mfi->initParameterSet(action, *mdp, curParSet); + curmask = mfi->postCondition(action); + if(curParSet.isEmpty() && !isDynamic()) return false; + + createFrame(); + loadFrameContent(mdp); + if(isDynamic()) + { + meshState.create(curmask, curModel); + connect(stdParFrame,SIGNAL(dynamicFloatChanged(int)), this, SLOT(applyDynamic())); + connect(stdParFrame,SIGNAL(parameterChanged()), this, SLOT(applyDynamic())); + } + connect(curMeshDoc, SIGNAL(currentMeshChanged(int)),this, SLOT(changeCurrentMesh(int))); + return true; + } + +void MeshlabStdDialog::changeCurrentMesh(int meshInd) +{ + if(isDynamic()) + { + meshState.apply(curModel); + curModel=curMeshDoc->meshList.at(meshInd); + meshState.create(curmask, curModel); + applyDynamic(); + } +} + +bool MeshlabStdDialog::isDynamic() +{ + return ((curmask != MeshModel::MM_UNKNOWN) && (curmask != MeshModel::MM_NONE) && !(curmask & MeshModel::MM_VERTNUMBER) && !(curmask & MeshModel::MM_FACENUMBER)); +} + + +void MeshlabStdDialog::clearValues() +{ + curAction = NULL; + curModel = NULL; + curmfi = NULL; + curmwi = NULL; +} + +void MeshlabStdDialog::createFrame() +{ + if(qf) delete qf; + + QFrame *newqf= new QFrame(this); + setWidget(newqf); + setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); + qf = newqf; +} + +// update the values of the widgets with the values in the paramlist; +void MeshlabStdDialog::resetValues() +{ + curParSet.clear(); + curmfi->initParameterSet(curAction, *curMeshDoc, curParSet); + + assert(qf); + assert(qf->isVisible()); + // assert(curParSet.paramList.count() == stdfieldwidgets.count()); + stdParFrame->resetValues(curParSet); +} + +void StdParFrame::resetValues(RichParameterSet &curParSet) +{ + QList &parList =curParSet.paramList; + assert(stdfieldwidgets.size() == parList.size()); + for(int i = 0; i < parList.count(); i++) + { + RichParameter* fpi= parList.at(i); + if (fpi != NULL) + stdfieldwidgets[i]->resetValue(); + } +} + + /* creates widgets for the standard parameters */ + +void MeshlabStdDialog::loadFrameContent(MeshDocument *mdPt) +{ + assert(qf); + qf->hide(); + QLabel *ql; + + QGridLayout *gridLayout = new QGridLayout(qf); + qf->setLayout(gridLayout); + + setWindowTitle(curmfi->filterName(curAction)); + ql = new QLabel(""+curmfi->filterInfo(curAction)+"",qf); + ql->setTextFormat(Qt::RichText); + ql->setWordWrap(true); + gridLayout->addWidget(ql,0,0,1,2,Qt::AlignTop); // this widgets spans over two columns. + + stdParFrame = new StdParFrame(this,curgla); + stdParFrame->loadFrameContent(curParSet,mdPt); + gridLayout->addWidget(stdParFrame,1,0,1,2); + + int buttonRow = 2; // the row where the line of buttons start + + QPushButton *helpButton = new QPushButton("Help", qf); + QPushButton *closeButton = new QPushButton("Close", qf); + QPushButton *applyButton = new QPushButton("Apply", qf); + QPushButton *defaultButton = new QPushButton("Default", qf); + +#ifdef Q_WS_MAC + // Hack needed on mac for correct sizes of button in the bottom of the dialog. + helpButton->setMinimumSize(100, 25); + closeButton->setMinimumSize(100,25); + applyButton->setMinimumSize(100,25); + defaultButton->setMinimumSize(100, 25); +#endif + + if(isDynamic()) + { + previewCB = new QCheckBox("Preview", qf); + previewCB->setCheckState(Qt::Unchecked); + gridLayout->addWidget(previewCB, buttonRow+0,0,Qt::AlignBottom); + connect(previewCB,SIGNAL(toggled(bool)),this,SLOT( togglePreview() )); + buttonRow++; + } + + gridLayout->addWidget(helpButton, buttonRow+0,1,Qt::AlignBottom); + gridLayout->addWidget(defaultButton,buttonRow+0,0,Qt::AlignBottom); + gridLayout->addWidget(closeButton, buttonRow+1,0,Qt::AlignBottom); + gridLayout->addWidget(applyButton, buttonRow+1,1,Qt::AlignBottom); + + + connect(helpButton,SIGNAL(clicked()),this,SLOT(toggleHelp())); + connect(applyButton,SIGNAL(clicked()),this,SLOT(applyClick())); + connect(closeButton,SIGNAL(clicked()),this,SLOT(closeClick())); + connect(defaultButton,SIGNAL(clicked()),this,SLOT(resetValues())); + + qf->showNormal(); + qf->adjustSize(); + + //set the minimum size so it will shrink down to the right size after the help is toggled + this->setMinimumSize(qf->sizeHint()); + this->showNormal(); + this->adjustSize(); +} + +//void StdParFrame::loadFrameContent(ParameterDeclarationSet &curParSet,MeshDocument *mdPt) +void StdParFrame::loadFrameContent(RichParameterSet &curParSet,MeshDocument */*mdPt*/) +{ + if(layout()) delete layout(); + QGridLayout * vLayout = new QGridLayout(this); + vLayout->setAlignment(Qt::AlignLeft); + setLayout(vLayout); + + //QLabel *ql; + + QList &parList =curParSet.paramList; + + QString descr; + RichWidgetInterfaceConstructor rwc(this); + for(int i = 0; i < parList.count(); i++) + { + RichParameter* fpi=parList.at(i); + fpi->accept(rwc); + //vLayout->addWidget(rwc.lastCreated,i,0,1,1,Qt::AlignTop); + stdfieldwidgets.push_back(rwc.lastCreated); + helpList.push_back(rwc.lastCreated->helpLab); + } // end for each parameter + showNormal(); + adjustSize(); +} + +void StdParFrame::loadFrameContent( RichParameter* par,MeshDocument */*mdPt*/ /*= 0*/ ) +{ + if(layout()) delete layout(); + QGridLayout * vLayout = new QGridLayout(this); + vLayout->setAlignment(Qt::AlignLeft); + setLayout(vLayout); + + QString descr; + RichWidgetInterfaceConstructor rwc(this); + + par->accept(rwc); + //vLayout->addWidget(rwc.lastCreated,i,0,1,1,Qt::AlignTop); + stdfieldwidgets.push_back(rwc.lastCreated); + helpList.push_back(rwc.lastCreated->helpLab); + + showNormal(); + adjustSize(); +} +void StdParFrame::toggleHelp() +{ + for(int i = 0; i < helpList.count(); i++) + helpList.at(i)->setVisible(!helpList.at(i)->isVisible()) ; + updateGeometry(); + adjustSize(); +} + +void MeshlabStdDialog::toggleHelp() +{ + stdParFrame->toggleHelp(); + qf->updateGeometry(); + qf->adjustSize(); + this->updateGeometry(); + this->adjustSize(); +} + +//void StdParFrame::readValues(ParameterDeclarationSet &curParSet) +void StdParFrame::readValues(RichParameterSet &curParSet) +{ + QList &parList =curParSet.paramList; + assert(parList.size() == stdfieldwidgets.size()); + QVector::iterator it = stdfieldwidgets.begin(); + for(int i = 0; i < parList.count(); i++) + { + QString sname = parList.at(i)->name; + curParSet.setValue(sname,(*it)->getWidgetValue()); + ++it; + } +} + +StdParFrame::~StdParFrame() +{ + +} + +/* click event for the apply button of the standard plugin window */ +// If the filter has some dynamic parameters +// - before applying the filter restore the original state of the mesh. +// - after applying the filter reget the state of the mesh. + +void MeshlabStdDialog::applyClick() +{ + QAction *q = curAction; + stdParFrame->readValues(curParSet); + + ////int mask = 0;//curParSet.getDynamicFloatMask(); + if(curmask) meshState.apply(curModel); + + //PreView Caching: if the apply parameters are the same to those used in the preview mode + //we don't need to reapply the filter to the mesh + bool isEqual = (curParSet == prevParSet); + if ((isEqual) && (validcache)) + meshCacheState.apply(curModel); + else + curmwi->executeFilter(q, curParSet, false); + + if(curmask) meshState.create(curmask, curModel); + if(this->curgla) this->curgla->update(); + +} + +void MeshlabStdDialog::applyDynamic() +{ + if(!previewCB->isChecked()) return; + QAction *q = curAction; + stdParFrame->readValues(curParSet); + //for cache mechanism + //needed to allocate the required memory space in prevParSet + //it called the operator=(RichParameterSet) function defined in RichParameterSet + prevParSet = curParSet; + stdParFrame->readValues(prevParSet); + // Restore the + meshState.apply(curModel); + curmwi->executeFilter(q, curParSet, true); + meshCacheState.create(curmask,curModel); + validcache = true; + + + if(this->curgla) + this->curgla->update(); +} + +void MeshlabStdDialog::togglePreview() +{ + if(previewCB->isChecked()) + { + applyDynamic(); + } + else + meshState.apply(curModel); + + curgla->update(); +} + +/* click event for the close button of the standard plugin window */ + +void MeshlabStdDialog::closeClick() +{ + //int mask = 0;//curParSet.getDynamicFloatMask(); + if(curmask) meshState.apply(curModel); + curmask = MeshModel::MM_UNKNOWN; + // Perform the update only if there is Valid GLarea. + if(this->curgla) this->curgla->update(); + close(); +} + + +// click event for the standard red crossed close button in the upper right widget's corner +void MeshlabStdDialog::closeEvent(QCloseEvent * /*event*/) +{ + closeClick(); +} + +MeshlabStdDialog::~MeshlabStdDialog() +{ + delete stdParFrame; + if(isDynamic()) + delete previewCB; +} + + +/******************************************/ +// AbsPercWidget Implementation +/******************************************/ + + +//QGridLayout(NULL) + AbsPercWidget::AbsPercWidget(QWidget *p, RichAbsPerc* rabs):MeshLabWidget(p,rabs) + + { + AbsPercDecoration* absd = reinterpret_cast(rp->pd); + m_min = absd->min; + m_max = absd->max; + + fieldDesc = new QLabel(rp->pd->fieldDesc + " (abs and %)",p); + fieldDesc->setToolTip(rp->pd->tooltip); + absSB = new QDoubleSpinBox(p); + percSB = new QDoubleSpinBox(p); + + absSB->setMinimum(m_min-(m_max-m_min)); + absSB->setMaximum(m_max*2); + absSB->setAlignment(Qt::AlignRight); + + int decimals= 7-ceil(log10(fabs(m_max-m_min)) ) ; + //qDebug("range is (%f %f) %f ",m_max,m_min,fabs(m_max-m_min)); + //qDebug("log range is %f ",log10(fabs(m_max-m_min))); + absSB->setDecimals(decimals); + absSB->setSingleStep((m_max-m_min)/100.0); + float initVal = rp->val->getAbsPerc(); + absSB->setValue(initVal); + + percSB->setMinimum(-200); + percSB->setMaximum(200); + percSB->setAlignment(Qt::AlignRight); + percSB->setSingleStep(0.5); + percSB->setValue((100*(initVal - m_min))/(m_max - m_min)); + percSB->setDecimals(3); + QLabel *absLab=new QLabel(" world unit"); + QLabel *percLab=new QLabel(" perc on"+QString("(%1 .. %2)").arg(m_min).arg(m_max)+""); + + int row = gridLay->rowCount() - 1; + gridLay->addWidget(fieldDesc,row,0,Qt::AlignHCenter); + + QGridLayout* lay = new QGridLayout(p); + lay->addWidget(absLab,0,0,Qt::AlignHCenter); + lay->addWidget(percLab,0,1,Qt::AlignHCenter); + + lay->addWidget(absSB,1,0,Qt::AlignTop); + lay->addWidget(percSB,1,1,Qt::AlignTop); + + gridLay->addLayout(lay,row,1,Qt::AlignTop); + + connect(absSB,SIGNAL(valueChanged(double)),this,SLOT(on_absSB_valueChanged(double))); + connect(percSB,SIGNAL(valueChanged(double)),this,SLOT(on_percSB_valueChanged(double))); + connect(this,SIGNAL(dialogParamChanged()),p,SLOT(parameterChanged())); + } + + AbsPercWidget::~AbsPercWidget() + { + delete absSB; + delete percSB; + delete fieldDesc; + } + + +void AbsPercWidget::on_absSB_valueChanged(double newv) +{ + percSB->setValue((100*(newv - m_min))/(m_max - m_min)); + emit dialogParamChanged(); +} + +void AbsPercWidget::on_percSB_valueChanged(double newv) +{ + absSB->setValue((m_max - m_min)*0.01*newv + m_min); + emit dialogParamChanged(); +} + +//float AbsPercWidget::getValue() +//{ +// return float(absSB->value()); +//} + +void AbsPercWidget::setValue(float val, float minV, float maxV) +{ + assert(absSB); + absSB->setValue (val); + m_min=minV; + m_max=maxV; +} + +void AbsPercWidget::collectWidgetValue() +{ + rp->val->set(AbsPercValue(float(absSB->value()))); +} + +void AbsPercWidget::resetWidgetValue() +{ + const AbsPercDecoration* absd = reinterpret_cast(&(rp->pd)); + setValue(rp->pd->defVal->getAbsPerc(),absd->min,absd->max); +} + +void AbsPercWidget::setWidgetValue( const Value& nv ) +{ + const AbsPercDecoration* absd = reinterpret_cast(&(rp->pd)); + setValue(nv.getAbsPerc(),absd->min,absd->max); +} + +/******************************************/ +// Point3fWidget Implementation +/******************************************/ + + +//QHBoxLayout(NULL) +Point3fWidget::Point3fWidget(QWidget *p, RichPoint3f* rpf, QWidget *gla_curr): MeshLabWidget(p,rpf) +{ + + paramName = rpf->name; + int row = gridLay->rowCount() - 1; + + descLab = new QLabel(rpf->pd->fieldDesc,p); + descLab->setToolTip(rpf->pd->fieldDesc); + gridLay->addWidget(descLab,row,0,Qt::AlignTop); + + QHBoxLayout* lay = new QHBoxLayout(p); + + for(int i =0;i<3;++i) + { + coordSB[i]= new QLineEdit(p); + QFont baseFont=coordSB[i]->font(); + if(baseFont.pixelSize() != -1) baseFont.setPixelSize(baseFont.pixelSize()*3/4); + else baseFont.setPointSize(baseFont.pointSize()*3/4); + coordSB[i]->setFont(baseFont); + //coordSB[i]->setMinimumWidth(coordSB[i]->sizeHint().width()/4); + coordSB[i]->setMinimumWidth(0); + coordSB[i]->setMaximumWidth(coordSB[i]->sizeHint().width()/2); + //coordSB[i]->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::Fixed); + coordSB[i]->setValidator(new QDoubleValidator(p)); + coordSB[i]->setAlignment(Qt::AlignRight); + //this->addWidget(coordSB[i],1,Qt::AlignHCenter); + lay->addWidget(coordSB[i]); + } + this->setValue(paramName,rp->val->getPoint3f()); + if(gla_curr) // if we have a connection to the current glarea we can setup the additional button for getting the current view direction. + { + getPoint3Button = new QPushButton("Get",p); + getPoint3Button->setMaximumWidth(getPoint3Button->sizeHint().width()/2); + + getPoint3Button->setFlat(true); + //getPoint3Button->setMinimumWidth(getPoint3Button->sizeHint().width()); + //this->addWidget(getPoint3Button,0,Qt::AlignHCenter); + lay->addWidget(getPoint3Button); + QStringList names; + names << "View Dir"; + names << "View Pos"; + names << "Surf. Pos"; + names << "Camera Pos"; + + getPoint3Combo = new QComboBox(p); + getPoint3Combo->addItems(names); + //getPoint3Combo->setMinimumWidth(getPoint3Combo->sizeHint().width()); + //this->addWidget(getPoint3Combo,0,Qt::AlignHCenter); + lay->addWidget(getPoint3Combo); + + connect(getPoint3Button,SIGNAL(clicked()),this,SLOT(getPoint())); + connect(getPoint3Combo,SIGNAL(currentIndexChanged(int)),this,SLOT(getPoint())); + connect(gla_curr,SIGNAL(transmitViewDir(QString,vcg::Point3f)),this,SLOT(setValue(QString,vcg::Point3f))); + connect(gla_curr,SIGNAL(transmitViewPos(QString,vcg::Point3f)),this,SLOT(setValue(QString,vcg::Point3f))); + connect(gla_curr,SIGNAL(transmitSurfacePos(QString,vcg::Point3f)),this,SLOT(setValue(QString,vcg::Point3f))); + connect(this,SIGNAL(askViewDir(QString)),gla_curr,SLOT(sendViewDir(QString))); + connect(this,SIGNAL(askViewPos(QString)),gla_curr,SLOT(sendViewPos(QString))); + connect(this,SIGNAL(askSurfacePos(QString)),gla_curr,SLOT(sendSurfacePos(QString))); + connect(this,SIGNAL(askCameraPos(QString)),gla_curr,SLOT(sendCameraPos(QString))); + } + gridLay->addLayout(lay,row,1,Qt::AlignTop); +} + +void Point3fWidget::getPoint() +{ +int index = getPoint3Combo->currentIndex(); +qDebug("Got signal %i",index); + switch(index) + { + case 0 : emit askViewDir(paramName); break; + case 1 : emit askViewPos(paramName); break; + case 2 : emit askSurfacePos(paramName); break; + case 3 : emit askCameraPos(paramName); break; + default : assert(0); + } +} + +Point3fWidget::~Point3fWidget() {} + +void Point3fWidget::setValue(QString name,Point3f newVal) +{ + if(name==paramName) + { + for(int i =0;i<3;++i) + coordSB[i]->setText(QString::number(newVal[i],'g',4)); + } +} + +vcg::Point3f Point3fWidget::getValue() +{ + return Point3f(coordSB[0]->text().toFloat(),coordSB[1]->text().toFloat(),coordSB[2]->text().toFloat()); +} + +void Point3fWidget::collectWidgetValue() +{ + rp->val->set(Point3fValue(vcg::Point3f(coordSB[0]->text().toFloat(),coordSB[1]->text().toFloat(),coordSB[2]->text().toFloat()))); +} + +void Point3fWidget::resetWidgetValue() +{ + for(unsigned int ii = 0; ii < 3;++ii) + coordSB[ii]->setText(QString::number(rp->pd->defVal->getPoint3f()[ii],'g',3)); +} + +void Point3fWidget::setWidgetValue( const Value& nv ) +{ + for(unsigned int ii = 0; ii < 3;++ii) + coordSB[ii]->setText(QString::number(nv.getPoint3f()[ii],'g',3)); +} + +ComboWidget::ComboWidget(QWidget *p, RichParameter* rpar) :MeshLabWidget(p,rpar) { +} + +void ComboWidget::Init(QWidget *p,int defaultEnum, QStringList values) +{ + enumLabel = new QLabel(p); + enumLabel->setText(rp->pd->fieldDesc); + enumCombo = new QComboBox(p); + enumCombo->addItems(values); + setIndex(defaultEnum); + int row = gridLay->rowCount() - 1; + gridLay->addWidget(enumLabel,row,0,Qt::AlignTop); + gridLay->addWidget(enumCombo,row,1,Qt::AlignTop); + connect(enumCombo,SIGNAL(activated(int)),this,SIGNAL(dialogParamChanged())); + connect(this,SIGNAL(dialogParamChanged()),p,SIGNAL(parameterChanged())); +} + +void ComboWidget::setIndex(int newEnum) +{ + enumCombo->setCurrentIndex(newEnum); +} + +int ComboWidget::getIndex() +{ + return enumCombo->currentIndex(); +} + +ComboWidget::~ComboWidget() +{ + delete enumCombo; + delete enumLabel; +} + +/******************************************/ +//EnumWidget Implementation +/******************************************/ + +EnumWidget::EnumWidget(QWidget *p, RichEnum* rpar) +:ComboWidget(p,rpar) +{ + //you MUST call it!!!! + Init(p,rpar->val->getEnum(),reinterpret_cast(rpar->pd)->enumvalues); + //assert(enumCombo != NULL); +} + +int EnumWidget::getSize() +{ + return enumCombo->count(); +} + + +void EnumWidget::collectWidgetValue() +{ + rp->val->set(EnumValue(enumCombo->currentIndex())); +} + +void EnumWidget::resetWidgetValue() +{ + //lned->setText(QString::number(rp->val->getFloat(),'g',3)); + enumCombo->setCurrentIndex(rp->pd->defVal->getEnum()); +} + +void EnumWidget::setWidgetValue( const Value& nv ) +{ + enumCombo->setCurrentIndex(nv.getEnum()); +} + +/******************************************/ +//MeshEnumWidget Implementation +/******************************************/ + + +MeshWidget::MeshWidget(QWidget *p, RichMesh* rpar) +:ComboWidget(p,rpar) +{ + md=reinterpret_cast(rp->pd)->meshdoc; + + QStringList meshNames; + + //make the default mesh Index be 0 + defaultMeshIndex = -1; + + for(int i=0;imeshList.size();++i) + { + QString shortName = md->meshList.at(i)->shortName(); + meshNames.push_back(shortName); + if(md->meshList.at(i) == rp->pd->defVal->getMesh()) defaultMeshIndex = i; + } + + //add a blank choice because there is no default available + if(defaultMeshIndex == -1) + { + meshNames.push_back(""); + defaultMeshIndex = meshNames.size()-1; //have the blank choice be shown + } + Init(p,defaultMeshIndex,meshNames); +} + +MeshModel * MeshWidget::getMesh() +{ + //test to make sure index is in bounds + int index = enumCombo->currentIndex(); + if(index < md->meshList.size() && index > -1) + return md->meshList.at(enumCombo->currentIndex()); + else return NULL; +} + +void MeshWidget::setMesh(MeshModel * newMesh) +{ + for(int i=0; i < md->meshList.size(); ++i) + { + if(md->meshList.at(i) == newMesh) setIndex(i); + } +} + +void MeshWidget::collectWidgetValue() +{ + rp->val->set(MeshValue(md->meshList.at(enumCombo->currentIndex()))); +} + +void MeshWidget::resetWidgetValue() +{ + enumCombo->setCurrentIndex(defaultMeshIndex); +} + +void MeshWidget::setWidgetValue( const Value& /*nv*/ ) +{ + //WARNING!!!!! I HAVE TO THINK CAREFULLY ABOUT THIS FUNCTION!!! + assert(0); + //enumCombo->setCurrentIndex(md->meshList(nv.getMesh()); +} + +/****************************************** + QVariantListWidget Implementation +******************************************/ + +/* +QVariantListWidget::QVariantListWidget(QWidget *parent, QList &values) +{ + tableWidget = new QTableWidget(parent); + tableWidget->setColumnCount(1); + tableWidget->setRowCount(values.size() ); + tableWidget->setMaximumSize(135, 180); + tableWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); + tableWidget->horizontalHeader()->setDisabled(true); + + setList(values); + + this->addWidget(tableWidget); +} + +QList QVariantListWidget::getList() +{ + QList values; + + for(int i = 0; i < tableWidget->rowCount(); i++) + { + QString rowValue = tableWidget->item(i,0)->text(); + + //if the row was not blank + if("" != rowValue) values.push_back(QVariant(rowValue)); + } + + return values; +} + + +void QVariantListWidget::setList(QList &values) +{ + tableWidget->clearContents(); + tableWidget->setRowCount(values.size() ); + for(int i = 0; i < values.size(); i++) + { + tableWidget->setItem(i, 0, new QTableWidgetItem(values.at(i).toString())); + } +} + +void QVariantListWidget::addRow() +{ + int count = tableWidget->rowCount(); + + //insert a new row at the end + tableWidget->insertRow(count); + + //fill row with something so that it can be removed if left blank... qt forces us to do this + tableWidget->setItem(count, 0, new QTableWidgetItem("")); +} + + +void QVariantListWidget::removeRow() +{ + QList items = tableWidget->selectedItems(); + + if(items.size() == 0){ + //remove the last row if none are selected + tableWidget->removeRow(tableWidget->rowCount()-1); + } else + { + //remove each selected row + for(int i = 0; i < items.size(); i++){ + tableWidget->removeRow(items.at(i)->row()); + } + } +} +*/ + +/****************************************** + GetFileNameButton Implementation +******************************************/ + +/* +GetFileNameWidget::GetFileNameWidget(QWidget *parent, + QString &defaultString, bool getOpenFileName, QString fileExtension) : QVBoxLayout(parent) +{ + _fileName = defaultString; + _fileExtension = fileExtension; + + _getOpenFileName = getOpenFileName; + + launchFileNameDialogButton = new QPushButton(QString("Get FileName"), parent); + fileNameLabel = new QLabel(_fileName, parent); + + addWidget(launchFileNameDialogButton); + addWidget(fileNameLabel); + + connect(launchFileNameDialogButton, SIGNAL(clicked()), this, SLOT(launchGetFileNameDialog())); + +} + +GetFileNameWidget::~GetFileNameWidget() +{ + delete launchFileNameDialogButton; +} + +QString GetFileNameWidget::getFileName() +{ + return _fileName; +} + +void GetFileNameWidget::launchGetFileNameDialog() +{ + QString temp; + if(_getOpenFileName){ + temp = QFileDialog::getOpenFileName(parentWidget(), tr("Select File"),".", "*"+_fileExtension); + } else + temp = QFileDialog::getSaveFileName(parentWidget(), tr("Select File"),".", "*"+_fileExtension); + + if(temp != ""){ + _fileName = temp; + fileNameLabel->setText(QFileInfo(_fileName).fileName()); + } +} + +void GetFileNameWidget::setFileName(QString newName){ + _fileName = newName; +} +*/ + +GenericParamDialog::GenericParamDialog(QWidget *p, RichParameterSet *_curParSet, QString title, MeshDocument *_meshDocument) + : QDialog(p) { + stdParFrame=NULL; + curParSet=_curParSet; + meshDocument = _meshDocument; + createFrame(); + if(!title.isEmpty()) + setWindowTitle(title); +} + + +// update the values of the widgets with the values in the paramlist; +void GenericParamDialog::resetValues() +{ + stdParFrame->resetValues(*curParSet); +} + +void GenericParamDialog::toggleHelp() +{ + stdParFrame->toggleHelp(); + this->updateGeometry(); + this->adjustSize(); +} + + +void GenericParamDialog::createFrame() +{ + QVBoxLayout *vboxLayout = new QVBoxLayout(this); + setLayout(vboxLayout); + + stdParFrame = new StdParFrame(this); + stdParFrame->loadFrameContent(*curParSet, meshDocument); + layout()->addWidget(stdParFrame); + + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + //add the reset button so we can get its signals + QPushButton *resetButton = buttonBox->addButton(QDialogButtonBox::Reset); + layout()->addWidget(buttonBox); + + connect(buttonBox, SIGNAL(accepted()), this, SLOT(getAccept())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + connect(buttonBox, SIGNAL(helpRequested()), this, SLOT(toggleHelp())); + connect(resetButton, SIGNAL(clicked()), this, SLOT(resetValues())); + + setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); + + //set the minimum size so it will shrink down to the right size after the help is toggled + this->setMinimumSize(stdParFrame->sizeHint()); + this->showNormal(); + this->adjustSize(); +} + + +void GenericParamDialog::getAccept() +{ + stdParFrame->readValues(*curParSet); + accept(); +} + +GenericParamDialog::~GenericParamDialog() +{ + delete stdParFrame; +} + +/******************************************/ +// DynamicFloatWidget Implementation +/******************************************/ + + +//QGridLayout(NULL) +DynamicFloatWidget::DynamicFloatWidget(QWidget *p, RichDynamicFloat* rdf):MeshLabWidget(p,rdf) +{ + minVal = reinterpret_cast(rdf->pd)->min; + maxVal = reinterpret_cast(rdf->pd)->max; + valueLE = new QLineEdit(p); + valueSlider = new QSlider(Qt::Horizontal,p); + valueSlider->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed); + fieldDesc = new QLabel(rp->pd->fieldDesc); + valueSlider->setMinimum(0); + valueSlider->setMaximum(100); + valueSlider->setValue(floatToInt(rp->val->getFloat())); + const DynamicFloatDecoration* dfd = reinterpret_cast(&(rp->pd)); + valueLE->setValidator(new QDoubleValidator (dfd->min,dfd->max, 5, valueLE)); + valueLE->setText(QString::number(rp->val->getFloat())); + + + int row = gridLay->rowCount() - 1; + gridLay->addWidget(fieldDesc,row,0,Qt::AlignTop); + + QHBoxLayout* lay = new QHBoxLayout(p); + lay->addWidget(valueLE,0,Qt::AlignHCenter); + //lay->addWidget(valueSlider,0,Qt::AlignJustify); + lay->addWidget(valueSlider,0,0); + gridLay->addLayout(lay,row,1,Qt::AlignTop); + + connect(valueLE,SIGNAL(textChanged(const QString &)),this,SLOT(setValue())); + connect(valueSlider,SIGNAL(valueChanged(int)),this,SLOT(setValue(int))); + connect(this,SIGNAL(dialogParamChanged()),p,SIGNAL(parameterChanged())); + +} + +DynamicFloatWidget::~DynamicFloatWidget() +{ +} + +float DynamicFloatWidget::getValue() +{ + return float(valueLE->text().toDouble()); + +} + +void DynamicFloatWidget::setValue(float newVal) +{ + if( QString::number(intToFloat(newVal)) != valueLE->text()) + valueLE->setText(QString::number(intToFloat(newVal))); +} + +void DynamicFloatWidget::setValue(int newVal) +{ + if(floatToInt(float(valueLE->text().toDouble())) != newVal) + { + valueLE->setText(QString::number(intToFloat(newVal))); + } +} + +void DynamicFloatWidget::setValue() +{ + float newValLE=float(valueLE->text().toDouble()); + valueSlider->setValue(floatToInt(newValLE)); + emit dialogParamChanged(); +} + +float DynamicFloatWidget::intToFloat(int val) +{ + return minVal+float(val)/100.0f*(maxVal-minVal); +} +int DynamicFloatWidget::floatToInt(float val) +{ + return int (100.0f*(val-minVal)/(maxVal-minVal)); +} + +void DynamicFloatWidget::collectWidgetValue() +{ + rp->val->set(DynamicFloatValue(valueLE->text().toFloat())); +} + +void DynamicFloatWidget::resetWidgetValue() +{ + valueLE->setText(QString::number(rp->pd->defVal->getFloat())); +} + +void DynamicFloatWidget::setWidgetValue( const Value& nv ) +{ + valueLE->setText(QString::number(nv.getFloat())); +} +/****************************/ +Value& MeshLabWidget::getWidgetValue() +{ + collectWidgetValue(); + return *(rp->val); +} + + +void MeshLabWidget::resetValue() +{ + rp->val->set(*rp->pd->defVal); + resetWidgetValue(); +} + +MeshLabWidget::MeshLabWidget( QWidget* p,RichParameter* rpar ) +:QWidget(p),rp(rpar) +{ + if (rp!= NULL) + { + helpLab = new QLabel(""+rpar->pd->tooltip +"",p); + helpLab->setTextFormat(Qt::RichText); + helpLab->setWordWrap(true); + helpLab->setVisible(false); + helpLab->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); + helpLab->setMinimumWidth(250); + helpLab->setMaximumWidth(QWIDGETSIZE_MAX); + gridLay = qobject_cast(p->layout()); + assert(gridLay != 0); + int row = gridLay->rowCount(); + gridLay->addWidget(helpLab,row,3,1,1,Qt::AlignTop); + } +} + +void MeshLabWidget::InitRichParameter(RichParameter* rpar) +{ + rp = rpar; +} + +MeshLabWidget::~MeshLabWidget() +{ + //delete rp; + delete helpLab; +} + +//connect(qcb,SIGNAL(stateChanged(int)),this,SIGNAL(parameterChanged())); +BoolWidget::BoolWidget( QWidget* p,RichBool* rb ) +:MeshLabWidget(p,rb) +{ + cb = new QCheckBox(rp->pd->fieldDesc,p); + cb->setToolTip(rp->pd->tooltip); + cb->setChecked(rp->val->getBool()); + + //gridlay->addWidget(this,i,0,1,1,Qt::AlignTop); + + int row = gridLay->rowCount() -1 ; + gridLay->addWidget(cb,row,0,1,2,Qt::AlignTop); + connect(cb,SIGNAL(stateChanged(int)),p,SIGNAL(parameterChanged())); + +} + +void BoolWidget::collectWidgetValue() +{ + rp->val->set(BoolValue(cb->isChecked())); +} + +void BoolWidget::resetWidgetValue() +{ + cb->setChecked(rp->pd->defVal->getBool()); +} + +BoolWidget::~BoolWidget() +{ + delete cb; +} + +void BoolWidget::setWidgetValue( const Value& nv ) +{ + cb->setChecked(nv.getBool()); +} + +//connect(qle,SIGNAL(editingFinished()),this,SIGNAL(parameterChanged())); +LineEditWidget::LineEditWidget( QWidget* p,RichParameter* rpar ) +:MeshLabWidget(p,rpar) +{ + lab = new QLabel(rp->pd->fieldDesc,this); + lned = new QLineEdit(this); + int row = gridLay->rowCount() -1; + + lab->setToolTip(rp->pd->tooltip); + gridLay->addWidget(lab,row,0,Qt::AlignTop); + gridLay->addWidget(lned,row,1,Qt::AlignTop); + connect(lned,SIGNAL(editingFinished()),p,SIGNAL(parameterChanged())); +} + +LineEditWidget::~LineEditWidget() +{ + delete lned; + delete lab; +} +IntWidget::IntWidget( QWidget* p,RichInt* rpar ) +:LineEditWidget(p,rpar) +{ + lned->setText(QString::number(rp->val->getInt())); +} + +void IntWidget::collectWidgetValue() +{ + rp->val->set(IntValue(lned->text().toInt())); +} + +void IntWidget::resetWidgetValue() +{ + lned->setText(QString::number(rp->pd->defVal->getInt())); +} + +void IntWidget::setWidgetValue( const Value& nv ) +{ + lned->setText(QString::number(nv.getInt())); +} +// +FloatWidget::FloatWidget( QWidget* p,RichFloat* rpar ) +:LineEditWidget(p,rpar) +{ + lned->setText(QString::number(rp->val->getFloat(),'g',3)); +} + +void FloatWidget::collectWidgetValue() +{ + rp->val->set(FloatValue(lned->text().toFloat())); +} + +void FloatWidget::resetWidgetValue() +{ + lned->setText(QString::number(rp->pd->defVal->getFloat(),'g',3)); +} + +void FloatWidget::setWidgetValue( const Value& nv ) +{ + lned->setText(QString::number(nv.getFloat(),'g',3)); +} + +StringWidget::StringWidget( QWidget* p,RichString* rpar ) +:LineEditWidget(p,rpar) +{ + lned->setText(rp->val->getString()); +} + +void StringWidget::collectWidgetValue() +{ + rp->val->set(StringValue(lned->text())); +} + +void StringWidget::resetWidgetValue() +{ + lned->setText(rp->pd->defVal->getString()); +} + +void StringWidget::setWidgetValue( const Value& nv ) +{ + lned->setText(nv.getString()); +} + +//Matrix44fWidget::Matrix44fWidget( QWidget* p,RichMatrix44f* rpar ) +//:MeshLabWidget(p,rb) +//{ +//} +// +//void Matrix44fWidget::collectWidgetValue() +//{ +//} +// +//void Matrix44fWidget::resetWidgetValue() +//{ +//} + + +/* +FloatListWidget::FloatListWidget( QWidget* p,RichMesh* rpar ) +:MeshLabWidget(p,rb) +{ +} + + +void FloatListWidget::collectWidgetValue() +{ +} + +void FloatListWidget::resetWidgetValue() +{ +} + +OpenFileWidget::OpenFileWidget( QWidget* p,RichMesh* rpar ) +:MeshLabWidget(p,rb) +{ +} + +void OpenFileWidget::collectWidgetValue() +{ +} + +void OpenFileWidget::resetWidgetValue() +{ +} +*/ + +SaveFileWidget::SaveFileWidget( QWidget* p,RichSaveFile* rpar ) +:MeshLabWidget(p,rpar) +{ +} + + +void SaveFileWidget::collectWidgetValue() +{ +} + +void SaveFileWidget::resetWidgetValue() +{ +} + +void SaveFileWidget::setWidgetValue( const Value& /*nv*/ ) +{ + +} +/* +ql = new QLabel(fpi.fieldDesc,this); +ql->setToolTip(fpi.fieldToolTip); + +qcbt = new QColorButton(this,QColor(fpi.fieldVal.toUInt())); +gridLayout->addWidget(ql,i,0,Qt::AlignTop); +gridLayout->addLayout(qcbt,i,1,Qt::AlignTop); + +stdfieldwidgets.push_back(qcbt); +connect(qcbt,SIGNAL(dialogParamChanged()),this,SIGNAL(parameterChanged())); +*/ + +/******************************************/ +// ColorWidget Implementation +/******************************************/ + + +ColorWidget::ColorWidget(QWidget *p, RichColor* newColor) +:MeshLabWidget(p,newColor),pickcol() +{ + + colorLabel = new QLabel(p); + descLabel = new QLabel(rp->pd->fieldDesc,p); + colorButton = new QPushButton(p); + colorButton->setAutoFillBackground(true); + colorButton->setFlat(true); + //const QColor cl = rp->pd->defVal->getColor(); + //resetWidgetValue(); + initWidgetValue(); + int row = gridLay->rowCount() - 1; + gridLay->addWidget(descLabel,row,0,Qt::AlignTop); + + QHBoxLayout* lay = new QHBoxLayout(p); + lay->addWidget(colorLabel); + lay->addWidget(colorButton); + + gridLay->addLayout(lay,row,1,Qt::AlignTop); + pickcol = rp->val->getColor(); + connect(colorButton,SIGNAL(clicked()),this,SLOT(pickColor())); + connect(this,SIGNAL(dialogParamChanged()),p,SIGNAL(parameterChanged())); +} + +void ColorWidget::updateColorInfo(const ColorValue& newColor) +{ + QColor col = newColor.getColor(); + colorLabel->setText("("+col.name()+")"); + QPalette palette(col); + colorButton->setPalette(palette); +} + +void ColorWidget::pickColor() +{ + pickcol =QColorDialog::getColor(pickcol); + if(pickcol.isValid()) + { + collectWidgetValue(); + updateColorInfo(ColorValue(pickcol)); + } + emit dialogParamChanged(); +} + +void ColorWidget::initWidgetValue() +{ + QColor cl = rp->val->getColor(); + pickcol = cl; + updateColorInfo(cl); +} + +void ColorWidget::resetWidgetValue() +{ + QColor cl = rp->pd->defVal->getColor(); + pickcol = cl; + updateColorInfo(cl); +} + +void ColorWidget::collectWidgetValue() +{ + rp->val->set(ColorValue(pickcol)); +} + +ColorWidget::~ColorWidget() +{ + delete colorButton; + delete colorLabel; + delete descLabel; +} + +void ColorWidget::setWidgetValue( const Value& nv ) +{ + QColor cl = nv.getColor(); + pickcol = cl; + updateColorInfo(cl); +} +/* +void GetFileNameWidget::launchGetFileNameDialog() +{ + +}*/ + +void RichParameterToQTableWidgetItemConstructor::visit( RichBool& pd ) +{ + if (pd.val->getBool()) + lastCreated = new QTableWidgetItem("true"/*,lst*/); + else + lastCreated = new QTableWidgetItem("false"/*,lst*/); + +} + +void RichParameterToQTableWidgetItemConstructor::visit( RichInt& pd ) +{ + lastCreated = new QTableWidgetItem(QString::number(pd.val->getInt())/*,lst*/); +} + +void RichParameterToQTableWidgetItemConstructor::visit( RichFloat& pd ) +{ + lastCreated = new QTableWidgetItem(QString::number(pd.val->getFloat())/*,lst*/); +} + +void RichParameterToQTableWidgetItemConstructor::visit( RichString& pd ) +{ + lastCreated = new QTableWidgetItem(pd.val->getString()/*,lst*/); +} + +void RichParameterToQTableWidgetItemConstructor::visit( RichPoint3f& pd ) +{ + vcg::Point3f pp = pd.val->getPoint3f(); + QString pst = "P3(" + QString::number(pp.X()) + "," + QString::number(pp.Y()) + "," + QString::number(pp.Z()) + ")"; + lastCreated = new QTableWidgetItem(pst/*,lst*/); +} + +void RichParameterToQTableWidgetItemConstructor::visit(RichOpenFile& pd) +{ + lastCreated = new QTableWidgetItem(pd.val->getFileName()/*,lst*/); +} + +void RichParameterToQTableWidgetItemConstructor::visit( RichColor& pd ) +{ + QPixmap pix(10,10); + pix.fill(pd.val->getColor()); + QIcon ic(pix); + lastCreated = new QTableWidgetItem(ic,""/*,lst*/); +} + +void RichParameterToQTableWidgetItemConstructor::visit( RichAbsPerc& pd ) +{ + lastCreated = new QTableWidgetItem(QString::number(pd.val->getAbsPerc())/*,lst*/); +} + +void RichParameterToQTableWidgetItemConstructor::visit( RichEnum& pd ) +{ + lastCreated = new QTableWidgetItem(QString::number(pd.val->getEnum())/*,lst*/); +} + +void RichParameterToQTableWidgetItemConstructor::visit( RichDynamicFloat& pd ) +{ + lastCreated = new QTableWidgetItem(QString::number(pd.val->getDynamicFloat())/*,lst*/); +} + + + +OpenFileWidget::OpenFileWidget( QWidget *p, RichOpenFile* rdf ) +:MeshLabWidget(p,rdf),fl() +{ + filename = new QLineEdit(p); + filename->setText(tr("")); + browse = new QPushButton(p); + descLab = new QLabel(rp->pd->fieldDesc,p); + browse->setText("..."); + //const QColor cl = rp->pd->defVal->getColor(); + //resetWidgetValue(); + int row = gridLay->rowCount() - 1; + gridLay->addWidget(descLab,row,0,Qt::AlignTop); + QHBoxLayout* lay = new QHBoxLayout(p); + lay->addWidget(filename,2); + lay->addWidget(browse); + + gridLay->addLayout(lay,row,1,Qt::AlignTop); + + connect(browse,SIGNAL(clicked()),this,SLOT(selectFile())); + connect(this,SIGNAL(dialogParamChanged()),p,SIGNAL(parameterChanged())); +} + +void OpenFileWidget::selectFile() +{ + OpenFileDecoration* dec = reinterpret_cast(rp->pd); + QString ext; + fl = QFileDialog::getOpenFileName(this,tr("Open"),dec->defVal->getFileName(),dec->exts.join(" ")); + collectWidgetValue(); + updateFileName(fl); + emit dialogParamChanged(); +} + +void OpenFileWidget::collectWidgetValue() +{ + rp->val->set(FileValue(fl)); +} + +void OpenFileWidget::resetWidgetValue() +{ + QString fle = rp->pd->defVal->getFileName(); + fl = fle; + updateFileName(fle); +} + + +void OpenFileWidget::setWidgetValue(const Value& nv) +{ + QString fle = nv.getFileName(); + fl = fle; + updateFileName(QString()); +} + +void OpenFileWidget::updateFileName( const FileValue& file ) +{ + filename->setText(file.getFileName()); +} + +OpenFileWidget::~OpenFileWidget() +{ + delete filename; + delete browse; + delete descLab; +} \ No newline at end of file diff --git a/src/meshlab_2.01/stdpardialog.h b/src/meshlab_2.01/stdpardialog.h new file mode 100644 index 000000000..c382c4d74 --- /dev/null +++ b/src/meshlab_2.01/stdpardialog.h @@ -0,0 +1,701 @@ +/**************************************************************************** +* MeshLab o o * +* An extendible mesh processor o o * +* _ O _ * +* Copyright(C) 2005, 2006 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +/**************************************************************************** +History + +$Log$ +Revision 1.16 2008/04/16 12:05:51 cignoni +option for title of the dialog + +Revision 1.15 2008/01/28 13:02:00 cignoni +added support for filters on collection of meshes (layer filters) + +Revision 1.14 2007/11/30 07:19:09 cignoni +moved generic dialog to the meshlab base + +Revision 1.13 2007/11/20 18:26:16 ponchio +Added enum support for auto dialogs, working. + +Revision 1.12 2007/11/19 17:09:20 ponchio +added enum value. [untested]. + +Revision 1.11 2007/11/19 15:51:50 cignoni +Added frame abstraction for reusing the std dialog mechanism + +Revision 1.10 2007/11/05 13:34:41 cignoni +added color and Help + +Revision 1.9 2007/10/02 07:59:44 cignoni +New filter interface. Hopefully more clean and easy to use. + +Revision 1.8 2007/03/26 08:25:10 zifnab1974 +added eol at the end of the files + +Revision 1.7 2007/02/27 23:58:36 cignoni +Changed apply/ok into apply/close + +Revision 1.6 2007/01/13 02:02:28 cignoni +Changed loadFrameContent to pass the QString not as a reference (to avoid a temp var referencing) + +Revision 1.5 2007/01/11 19:51:46 pirosu +fixed bug for QT 4.1.0/dotnet2003 +removed the request of the window title to the plugin. The action description is used instead. + +Revision 1.4 2007/01/11 10:40:09 cignoni +Renamed ambiguous min/max vars + +Revision 1.3 2006/12/27 21:41:41 pirosu +Added improvements for the standard plugin window: +split of the apply button in two buttons:ok and apply +added support for parameters with absolute and percentage values + +Revision 1.2 2006/12/13 21:54:35 pirosu +2 updates for the standard plugin window: 1) it recovers its last size when it is undocked and 2) it closes itself when a filter is applied (only if it is floating) + + +Revision 1.0 2006/12/13 17:37:02 pirosu +Added standard plugin window support + +****************************************************************************/ + +#ifndef MESHLAB_STDPARDIALOG_H +#define MESHLAB_STDPARDIALOG_H + +#include "../common/interfaces.h" +#include +#include +#include +#include +#include +#include + +class MeshLabWidget : public QWidget +{ + Q_OBJECT +public: + MeshLabWidget(QWidget* p,RichParameter* rpar); + + // this one is called by resetValue to reset the values inside the widgets. + virtual void resetWidgetValue() = 0; + // bring the values from the Qt widgets to the parameter (e.g. from the checkBox to the parameter). + virtual void collectWidgetValue() = 0; + virtual void setWidgetValue(const Value& nv) = 0; + virtual ~MeshLabWidget(); + + // called when the user press the 'default' button to reset the parameter values to its default. + // It just set the parameter value and then it calls the specialized resetWidgetValue() to update also the widget. + void resetValue(); + // update the parameter with the current widget values and return it. + Value& getWidgetValue(); + + RichParameter* rp; + QLabel* helpLab; +signals: + void parameterChanged(); +protected: + QGridLayout* gridLay; + void InitRichParameter(RichParameter* rpar); +}; + +class BoolWidget : public MeshLabWidget +{ + QCheckBox* cb; +public: + BoolWidget(QWidget* p,RichBool* rb); + ~BoolWidget(); + void collectWidgetValue(); + void resetWidgetValue(); + void setWidgetValue(const Value& nv); +}; + + +class LineEditWidget : public MeshLabWidget +{ +protected: + QLabel* lab; + QLineEdit* lned; +public: + + LineEditWidget(QWidget* p,RichParameter* rpar); + ~LineEditWidget(); + virtual void collectWidgetValue() = 0; + virtual void resetWidgetValue() = 0; + virtual void setWidgetValue(const Value& nv) = 0; +}; + + + +class IntWidget : public LineEditWidget +{ +public: + IntWidget(QWidget* p,RichInt* rpar); + ~IntWidget(){} + void collectWidgetValue(); + void resetWidgetValue(); + void setWidgetValue(const Value& nv); +}; + + + +class FloatWidget : public LineEditWidget +{ +public: + FloatWidget(QWidget* p,RichFloat* rpar); + ~FloatWidget(){} + void collectWidgetValue(); + void resetWidgetValue(); + void setWidgetValue(const Value& nv); +}; + + + +class StringWidget : public LineEditWidget +{ +public: + StringWidget(QWidget* p,RichString* rpar); + ~StringWidget(){} + void collectWidgetValue(); + void resetWidgetValue(); + void setWidgetValue(const Value& nv); +}; + +//class Matrix44fWidget : public MeshLabWidget +//{ +//public: +// Matrix44fWidget(QWidget* p,RichMatrix44f* rpar); +// +// void collectWidgetValue(); +// void resetWidgetValue(); +//}; + +/* +class FloatListWidget : public MeshLabWidget +{ +public: + FloatListWidget(QWidget* p,RichFloatList* rpar); + + void collectWidgetValue(); + void resetWidgetValue(); +}; +*/ + +/* +class OpenFileWidget : public MeshLabWidget +{ +public: + OpenFileWidget(QWidget* p,RichOpenFile* rpar); + + void collectWidgetValue(); + void resetWidgetValue(); +}; +*/ + + +class SaveFileWidget : public MeshLabWidget +{ +public: + SaveFileWidget(QWidget* p,RichSaveFile* rpar); + + void collectWidgetValue(); + void resetWidgetValue(); + void setWidgetValue(const Value& nv); +}; + + +/// Widget to enter a color. +// public QHBoxLayout, +class ColorWidget : public MeshLabWidget +{ + Q_OBJECT + + QPushButton* colorButton; + QLabel* colorLabel; + QLabel* descLabel; + QColor pickcol; + + public: + ColorWidget(QWidget *p, RichColor* newColor); + ~ColorWidget(); + + void collectWidgetValue(); + void resetWidgetValue(); + void setWidgetValue(const Value& nv); + void initWidgetValue(); + +private: + void updateColorInfo(const ColorValue& newColor); + + signals: + void dialogParamChanged(); + private slots: + void pickColor(); +}; + + + +/// Widget to enter a value as a percentage or as an absolute value. +/// You have to specify the default value and the range of the possible values. +/// The default value is expressed in ABSolute units (e.g. it should be in the min..max range. + + +//public QGridLayout +class AbsPercWidget : public MeshLabWidget +{ + Q_OBJECT + +public: + AbsPercWidget(QWidget *p,RichAbsPerc* rabs); + ~AbsPercWidget(); + + void collectWidgetValue(); + void resetWidgetValue(); + void setWidgetValue(const Value& nv); + +private: + void setValue(float val, float minV, float maxV); + +public slots: + + void on_absSB_valueChanged(double newv); + void on_percSB_valueChanged(double newv); +signals: + void dialogParamChanged(); + +protected: + QDoubleSpinBox *absSB; + QDoubleSpinBox *percSB; + QLabel* fieldDesc; + float m_min; + float m_max; +}; + + + +/// Widget to enter a Point3f, +/// if at the creation you provide a pointer to a GLArea (the mesh viewing window) +/// the widget exposes a button for getting the current view directiont + +//public QHBoxLayout, +class Point3fWidget : public MeshLabWidget +{ + Q_OBJECT + +public: + Point3fWidget(QWidget *p, RichPoint3f* rpf, QWidget *gla); + ~Point3fWidget(); + QString paramName; + vcg::Point3f getValue(); + + void collectWidgetValue(); + void resetWidgetValue(); + void setWidgetValue(const Value& nv); + + public slots: + void getPoint(); + void setValue(QString name, vcg::Point3f val); + signals: + void askViewDir(QString); + void askViewPos(QString); + void askSurfacePos(QString); + void askCameraPos(QString); + +protected: + QLineEdit * coordSB[3]; + QComboBox *getPoint3Combo; + QPushButton *getPoint3Button; + QLabel* descLab; +}; + + + +//public QGridLayout, +class DynamicFloatWidget : public MeshLabWidget +{ + Q_OBJECT + +public: + DynamicFloatWidget(QWidget *p, RichDynamicFloat* rdf); + ~DynamicFloatWidget(); + + float getValue(); + void setValue(float val, float minV, float maxV); + + void collectWidgetValue(); + void resetWidgetValue(); + void setWidgetValue(const Value& nv); + + public slots: + void setValue(int newv); + void setValue(); + void setValue(float newValue); + + signals: + //void valueChanged(int mask); + void dialogParamChanged(); + +protected: + QLineEdit *valueLE; + QSlider *valueSlider; + QLabel* fieldDesc; + float minVal; + float maxVal; + int mask; +private : + float intToFloat(int val); + int floatToInt(float val); +}; + + + +class ComboWidget : public MeshLabWidget +{ + Q_OBJECT +protected: + QComboBox *enumCombo; + QLabel *enumLabel; +public: + ComboWidget(QWidget *p, RichParameter* rpar); + ~ComboWidget(); + void Init(QWidget *p,int newEnum, QStringList values); + virtual void collectWidgetValue() = 0; + virtual void resetWidgetValue() = 0; + virtual void setWidgetValue(const Value& nv) = 0; + + int getIndex(); + void setIndex(int newEnum); + +signals: + void dialogParamChanged(); +}; + +/// Widget to select an entry from a list + +//public QHBoxLayout +class EnumWidget : public ComboWidget +{ + Q_OBJECT + +public: + EnumWidget(QWidget *p, RichEnum* rpar); + ~EnumWidget(){}; + + void collectWidgetValue(); + void resetWidgetValue(); + void setWidgetValue(const Value& nv); + + //returns the number of items in the list + int getSize(); +}; + + +/// Widget to select a Layer the current one +class MeshWidget : public ComboWidget +{ +private: + MeshDocument *md; + int defaultMeshIndex; +public: + MeshWidget(QWidget *p, RichMesh* defaultMesh); + ~MeshWidget(){}; + void collectWidgetValue(); + void resetWidgetValue(); + void setWidgetValue(const Value& nv); + + MeshModel * getMesh(); + void setMesh(MeshModel * newMesh); +}; + +class OpenFileWidget : public MeshLabWidget +{ + Q_OBJECT +public: + OpenFileWidget(QWidget *p, RichOpenFile* rdf); + ~OpenFileWidget(); + + void collectWidgetValue(); + void resetWidgetValue(); + void setWidgetValue(const Value& nv); + +protected: + QLineEdit* filename; + QPushButton* browse; + QString fl; + QLabel* descLab; + + +signals: + void dialogParamChanged(); + +private: + void updateFileName(const FileValue& file); +private slots: + void selectFile(); +}; +/* +class QVariantListWidget : public MeshLabWidget +{ + Q_OBJECT +public: + QVariantListWidget(QWidget *parent, QList &values); + + //get the values listed in this widget + QList getList(); + + //set the values this widget lists + void setList(QList &values); + + public slots: + //add a new row for input at the end + void addRow(); + + //remove the last row of the table widget + void removeRow(); + + void collectWidgetValue(); + void resetWidgetValue(); + +private: + QTableWidget *tableWidget; + +}; +*/ + + +/* +//public QVBoxLayout +class GetFileNameWidget : public MeshLabWidget +{ + Q_OBJECT +public: + GetFileNameWidget(QWidget *parent, QString &defaultString, bool getOpenFileName, QString fileExtension = QString("*.*")); + + ~GetFileNameWidget(); + + //set the values this widget lists + QString getFileName(); + + //set the name to be something else + void setFileName(QString newName); + + public slots: + //add a new row for input at the end + void launchGetFileNameDialog(); + + void collectWidgetValue(); + void resetWidgetValue(); +private: + + //open or save filename + bool _getOpenFileName; + + //label to display the current value of _filename + QLabel *fileNameLabel; + + //button to launch the get filename dialog + QPushButton *launchFileNameDialogButton; + + //the filename colected by the fileName dialog + QString _fileName; + + //the extension of the files to look for + QString _fileExtension; + +}; +*/ + +/*---------------------------------*/ + +/* +This class is used to automatically create a frame from a set of parameters. +it is used mostly for creating the main dialog of the filters, but it is used also +in the creation of the additional saving options, post and pre opening processing +and for general parameter setting in edit plugins (e.g. look at the aligment parameters) +*/ +class StdParFrame : public QFrame +{ + Q_OBJECT +public: + StdParFrame(QWidget *p, QWidget *gla=0); + + void loadFrameContent(RichParameterSet &curParSet,MeshDocument *mdPt = 0); + void loadFrameContent(RichParameter* par,MeshDocument *mdPt = 0); + + // The curParSet that is passed must be 'compatible' with the RichParameterSet that have been used to create the frame. + // This function updates the RichParameterSet used to create the frame AND fill also the passed + void readValues(RichParameterSet &curParSet); + void resetValues(RichParameterSet &curParSet); + + void toggleHelp(); + + QVector stdfieldwidgets; + QVector helpList; + + QWidget *gla; // used for having a link to the glarea that spawned the parameter asking. + ~StdParFrame(); +signals: + + void dynamicFloatChanged(int mask); + void parameterChanged(); +}; + + + +// This class provide a modal dialog box for asking a generic parameter set +// It can be used by anyone needing for some values in a structred form and having some integrated help +class GenericParamDialog: public QDialog +{ + Q_OBJECT +public: + GenericParamDialog(QWidget *p, RichParameterSet *_curParSet, QString title=QString(), MeshDocument *_meshDocument = 0); + ~GenericParamDialog(); + + RichParameterSet *curParSet; + StdParFrame *stdParFrame; + + void createFrame(); + + public slots: + void getAccept(); + void toggleHelp(); + + //reset the values on the gui back to the ones originally given to the dialog + void resetValues(); + +private: + MeshDocument *meshDocument; + +}; + + +// This is the dialog used to ask parameters for the MeshLab filters. +// This dialog is automatically configurated starting from the parameter asked by a given filter. +// It can handle dynamic parameters that modify only partially a given mesh. + +class MainWindow; +class MeshlabStdDialog : public QDockWidget +{ + Q_OBJECT + +public: + MeshlabStdDialog(QWidget *p); + ~MeshlabStdDialog(); + + void clearValues(); + void createFrame(); + void loadFrameContent(MeshDocument *mdPt=0); + + bool showAutoDialog(MeshFilterInterface *mfi, MeshModel *mm, MeshDocument * md, QAction *q, MainWindowInterface *mwi, QWidget *gla=0); + bool isDynamic(); + +private slots: + void applyClick(); + void closeClick(); + void resetValues(); + void toggleHelp(); + void togglePreview(); + void applyDynamic(); + void changeCurrentMesh(int meshInd); + +public: + QFrame *qf; + StdParFrame *stdParFrame; + QAction *curAction; + MeshModelState meshState; + MeshModelState meshCacheState; + QCheckBox *previewCB; + + void closeEvent ( QCloseEvent * event ); + + int curmask; + MeshModel *curModel; + MeshDocument * curMeshDoc; + MeshFilterInterface *curmfi; + MainWindowInterface *curmwi; + QWidget * curgla; + RichParameterSet curParSet; + RichParameterSet prevParSet; + bool validcache; +}; + + + +//QWidget* parent parameter says to the class who will destroy the MeshLabWidget object that it had created +//RichWidgetConstructor shouldn't destroy anything + +class RichWidgetInterfaceConstructor : public Visitor +{ +public: + RichWidgetInterfaceConstructor(QWidget* parent):lastCreated(NULL),par(parent){} + + void visit(RichBool& pd) {lastCreated = new BoolWidget(par,&pd);}; + void visit(RichInt& pd) {lastCreated = new IntWidget(par,&pd);}; + void visit(RichFloat& pd){lastCreated = new FloatWidget(par,&pd);}; + void visit(RichString& pd){lastCreated = new StringWidget(par,&pd);}; + void visit(RichMatrix44f& /*pd*/){assert(0);/*TO BE IMPLEMENTED*/ /*lastCreated = new Matrix44fWidget(par,&pd);*/}; + void visit(RichPoint3f& pd){lastCreated = new Point3fWidget(par,&pd,reinterpret_cast(par)->gla);}; + void visit(RichColor& pd){lastCreated = new ColorWidget(par,&pd);}; + void visit(RichAbsPerc& pd){lastCreated = new AbsPercWidget(par,&pd);}; + void visit(RichEnum& pd){lastCreated = new EnumWidget(par,&pd);}; + void visit(RichFloatList& /*pd*/){assert(0);/*TO BE IMPLEMENTED*/ /*lastCreated = new FloatListWidget(par,&pd);*/}; + void visit(RichDynamicFloat& pd){lastCreated = new DynamicFloatWidget(par,&pd);}; + void visit(RichOpenFile& pd){lastCreated = new OpenFileWidget(par,&pd);}; + void visit(RichSaveFile& /*pd*/){assert(0);/*TO BE IMPLEMENTED*/ /*lastCreated = new SaveFileWidget(par,&pd);*/}; + void visit(RichMesh& pd){lastCreated = new MeshWidget(par,&pd);}; + + ~RichWidgetInterfaceConstructor() {} + + void setParentWidget(QWidget* parent) {par = parent;} + MeshLabWidget* lastCreated; +private: + QWidget* par; + +}; + +class RichParameterToQTableWidgetItemConstructor : public Visitor +{ +public: + RichParameterToQTableWidgetItemConstructor(/*QListWidget* widlst*/):/*lst(widlst),*/lastCreated(NULL){} + + void visit(RichBool& pd); + void visit(RichInt& pd); + void visit(RichFloat& pd); + void visit(RichString& pd); + void visit(RichMatrix44f& /*pd*/){assert(0);}; + void visit(RichPoint3f& pd); + void visit(RichColor& pd); + void visit(RichAbsPerc& pd); + void visit(RichEnum& pd); + void visit(RichFloatList& /*pd*/){assert(0);}; + void visit(RichDynamicFloat& pd); + void visit(RichOpenFile& pd); + void visit(RichSaveFile& /*pd*/){assert(0);}; + void visit(RichMesh& /*pd*/){assert(0);}; + + /*QListWidget* lst;*/ + QTableWidgetItem* lastCreated; +}; + + + +#endif + diff --git a/src/meshlab_2.01/ui/layerDialog.ui b/src/meshlab_2.01/ui/layerDialog.ui new file mode 100644 index 000000000..f20ab7339 --- /dev/null +++ b/src/meshlab_2.01/ui/layerDialog.ui @@ -0,0 +1,69 @@ + + layerDialog + + + + 0 + 0 + 178 + 407 + + + + Layer Dialog + + + + + + + + + + + + Qt::Horizontal + + + + 28 + 23 + + + + + + + + ... + + + + + + + + + + + + + + + - + + + false + + + + + + + + + + + + + + diff --git a/src/meshlab_2.01/viewer.h b/src/meshlab_2.01/viewer.h new file mode 100644 index 000000000..2041f212d --- /dev/null +++ b/src/meshlab_2.01/viewer.h @@ -0,0 +1,44 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +#ifndef __VIEWER_H__ +#define __VIEWER_H__ + +#include "../../../vcglib/wrap/ply/plylib.h" +#include "../../../vcglib/wrap/io_trimesh/import_ply.h" +#include "../../../vcglib/wrap/io_trimesh/export_ply.h" + + +class Viewer +{ + +public: + + virtual ~Viewer(){}; + int getId() {return id;} + +protected: + int id; + +}; + +#endif // __VIEWER_H__ \ No newline at end of file