00001
00002
00004
00005 #include <qspinbox.h>
00006 #include <qfiledialog.h>
00007 #include <qstatusbar.h>
00008 #include <qmessagebox.h>
00009 #include <qtoolbar.h>
00010 #include <qmenubar.h>
00011 #include <qtoolbutton.h>
00012 #include <qpixmap.h>
00013 #include <qimage.h>
00014 #include <qlayout.h>
00015 #include <qlcdnumber.h>
00016 #include <qdockarea.h>
00017 #include <qgroupbox.h>
00018
00019
00020 #include <animal/event/keyEvent.h>
00021 #include <animal/event/mouseEvent.h>
00022 #include <animal/X3DTK/Qt/x3dTransformGUI/x3dTransformQt.h>
00023 #include <animal/X3DTK/Qt/world/qglviewerWorld.h>
00024 #include <iostream>
00025 using std::cout;
00026 using std::cerr;
00027 using std::endl;
00028
00029 #include "MainController.h"
00030
00031 animal::World * animal::Engine::theWorld = NULL;
00032
00033 static const char * recordButtonDown_xpm[] =
00034 {
00035 "16 16 4 1",
00036 "b c #f00000",
00037 "a c #f00606",
00038 "# c #f33434",
00039 ". c none",
00040 "................",
00041 "................",
00042 "......#aa#......",
00043 "....#bbbbbb#....",
00044 "...#bbbbbbbb#...",
00045 "...bbbbbbbbbb...",
00046 "..#bbbbbbbbbb#..",
00047 "..abbbbbbbbbba..",
00048 "..abbbbbbbbbba..",
00049 "..#bbbbbbbbbb#..",
00050 "...bbbbbbbbbb...",
00051 "...#bbbbbbbb#...",
00052 "....#bbbbbb#....",
00053 "......#aa#......",
00054 "................",
00055 "................"
00056 };
00057
00058 static const char * recordButton_xpm[] =
00059 {
00060 "16 16 4 1",
00061 "b c #0000f0",
00062 "a c #0606f0",
00063 "# c #3434f3",
00064 ". c none",
00065 "................",
00066 "................",
00067 "......#aa#......",
00068 "....#bbbbbb#....",
00069 "...#bbbbbbbb#...",
00070 "...bbbbbbbbbb...",
00071 "..#bbbbbbbbbb#..",
00072 "..abbbbbbbbbba..",
00073 "..abbbbbbbbbba..",
00074 "..#bbbbbbbbbb#..",
00075 "...bbbbbbbbbb...",
00076 "...#bbbbbbbb#...",
00077 "....#bbbbbb#....",
00078 "......#aa#......",
00079 "................",
00080 "................"
00081 };
00082
00084 MainController::MainController(X3DTK::MainScene * mainScene, bool use_docked_windows)
00085 : MainControllerDesigner(NULL, NULL, Qt::WDestructiveClose|Qt::WType_TopLevel)
00086 , mainScene(mainScene)
00087 ,x3dDirectory(std::string("."))
00088 {
00089
00090 viewer->setMainController(this);
00091 viewer->show();
00092
00093
00094 animal::Engine::setWorld(new X3DTK::Qt::QGLViewerWorld(viewer->camera()));
00095
00096
00097 mainScene->setMainController(this);
00098
00099
00100 x3dtreeqt->setMainController(this);
00101 x3dtreeqt->show();
00102 defineQWidgetCreationFunction(X3DTK::Qt::createTransformQWidget);
00103
00104
00105 animTimer = new QTimer(this);
00106 connect(animTimer, SIGNAL(timeout()), this, SLOT(doStep()));
00107
00108 connect( this, SIGNAL( animationFrequency( int ) ), update_rate_lCDNumber, SLOT( display(int) ) );
00109
00110
00111 go = false;
00112 realTime = false;
00113 animStep = 0.001*dt_SpinBox->value();
00114 displayStep = static_cast<int>(1000.0/delay_SpinBox->value());
00115
00116 if( use_docked_windows )
00117 {
00118
00119 w1 = new QDockWindow( rightDock(), "dock1");
00120 w1->setResizeEnabled(true);
00121 x3dtreeqt->reparent(w1,0,QPoint(0,0));
00122 x3dtreeqt->setMaximumWidth(10000);
00123 w1->setWidget(x3dtreeqt);
00124
00125 viewer->reparent(this,0,QPoint(0,0));
00126 setCentralWidget(viewer);
00127 viewer->setMaximumWidth(10000);
00128
00129 w2 = new QDockWindow( topDock(), "dock2");
00130 w2->setResizeEnabled(true);
00131 groupBoxAnimation->reparent(w2,0,QPoint(0,0));
00132 w2->setWidget(groupBoxAnimation);
00133 }
00134 }
00135
00137
00138
00139
00140
00141
00142
00143 void MainController::setViewer(X3DTK::Qt::Viewer * v)
00144 {
00145 if (viewer)
00146 {
00147 delete viewer;
00148 viewer = NULL;
00149 }
00150
00151 if (v)
00152 {
00153 viewer = v;
00154 viewer->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)7, 0, 0, viewer->sizePolicy().hasHeightForWidth() ) );
00155 viewer->setMinimumSize( QSize( 320, 240 ) );
00156 viewer->setMainController(this);
00157 MainControllerDesignerLayout->addWidget( viewer, 1, 0 );
00158 viewer->show();
00159 }
00160 }
00161 void MainController::addEngine(animal::Engine * E)
00162 {
00163 mainScene->addEngine(E);
00164 viewer->viewAll();
00165 }
00166
00167
00168
00169 void MainController::doStep()
00170 {
00171 static double cumulatedTime = 0;
00172 static int nbSteps = 0;
00173 const int period = 25;
00174
00175 double dt = 0.001 * clock.restart();
00176 cumulatedTime += dt;
00177 nbSteps++;
00178 if( nbSteps==period )
00179 {
00180 emit animationFrequency( static_cast<int>(period/cumulatedTime) );
00181
00182 nbSteps=0;
00183 cumulatedTime = 0;
00184 }
00185
00186
00187 if(!realTime)
00188 dt = animStep;
00189
00190 mainScene->move(dt);
00191 viewer->drawAfterAnimation();
00192 }
00193
00194
00195 void MainController::startStop()
00196 {
00197
00198 go = !go;
00199
00200 if (go)
00201 {
00202
00203 clock.restart();
00204
00205 animTimer->start(displayStep, FALSE);
00206 }
00207 else
00208 animTimer->stop();
00209 }
00210
00211 void MainController::reset()
00212 {
00213 mainScene->reset();
00214
00215 viewer->updateGL();
00216 }
00217
00218 void MainController::setAnimStep( int ms)
00219 {
00220
00221 animStep = 0.001*ms;
00222 }
00223
00224
00225 void MainController::setDisplayFreq( int hz)
00226 {
00227
00228 if( hz==0 )
00229 {
00230 displayStep = 0;
00231 animTimer->changeInterval( displayStep );
00232 }
00233 else
00234 {
00235 displayStep = static_cast<int>(1000.0/hz);
00236 animTimer->changeInterval( displayStep );
00237 }
00238 if( !go )
00239 animTimer->stop();
00240 }
00241
00242
00243 void MainController::setRealTime(bool b)
00244 {
00245
00246 if( realTime != b )
00247 {
00248 realTime = b;
00249 if( realTime )
00250 clock.restart();
00251 }
00252 }
00253
00254
00255 void MainController::activatedManipMode()
00256 {
00257 std::cerr<<"MainController::activatedManipMode "<<std::endl;
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 void MainController::fileOpen()
00269 {
00270 fileOpen("");
00271 }
00272
00273 void MainController::fileOpen(const char * filename)
00274 {
00275 if (filename=="")
00276 openFile = QFileDialog::getOpenFileName( x3dDirectory.data(),
00277 "X3D files (*.x3d)",
00278 this,
00279 "file open",
00280 "X3DAnimAL -- File Open" );
00281 else
00282 openFile = QString(filename);
00283
00284
00285 if (!QFile::exists(openFile))
00286 {
00287 statusBar()->message( "File not found: open abandoned" );
00288 return;
00289 }
00290
00291
00292 mainScene->load(openFile);
00293
00294 viewer->viewAll();
00295
00296 x3dtreeqt ->setSceneGraphRoot(mainScene->getX3DScene());
00297 }
00298
00299 void MainController::fileInsert( X3DTK::X3D::X3DNode * node)
00300 {
00301 QString filename = QFileDialog::getOpenFileName(
00302 QString::null, "X3D Files (*.x3d)", this,
00303 "file insert", "X3DAnimAL -- File Insert" );
00304 if ( filename.isEmpty() )
00305 statusBar()->message( "File Insert abandoned" );
00306 else
00307 {
00308
00309 mainScene->load(filename, node);
00310
00311 viewer->viewAll();
00312 }
00313 }
00314
00315 void MainController::fileSave()
00316 {
00317 QString filename = QFileDialog::getSaveFileName(
00318 QString::null, "X3D Files (*.x3d)", this,
00319 "file save", "X3DAnimAL -- File Save" );
00320 if ( filename.isEmpty() )
00321 statusBar()->message( "File Save abandoned" );
00322 else
00323 {
00324
00325 QFile file(filename);
00326 if (file.exists())
00327 {
00328 switch( QMessageBox::warning( this, "File Name",
00329 "The file "+filename+" already exists.\n"
00330 "OK to overwrite it.\n\n",
00331 "Yes",
00332 "No",
00333 "Cancel",0, 1) )
00334 {
00335 case 0:
00336 mainScene->save(filename);
00337 break;
00338 case 1:
00339 fileSave();
00340 break;
00341 case 2:
00342 statusBar()->message( "File Save abandoned" );
00343 break;
00344 }
00345 }
00346 else
00347 mainScene->save(filename);
00348 }
00349 }
00350
00351
00352 void MainController::fileReload()
00353 {
00354 if ( openFile.isEmpty() )
00355 statusBar()->message( "File Open abandoned" );
00356 else
00357 {
00358
00359 mainScene->load( openFile);
00360
00361 viewer->viewAll();
00362
00363 x3dtreeqt ->setSceneGraphRoot(mainScene->getX3DScene());
00364 }
00365 }
00366
00367
00368
00369
00370
00371 void MainController::toolBarSetShown(bool b)
00372 {
00373 toolBar->setShown(b);
00374 }
00375
00376 void MainController::menuBarSetShown(bool b)
00377 {
00378 menubar->setShown(b);
00379 statusBar()->setShown(b);
00380 }
00381
00382 void MainController::clickedRecordButton()
00383 {
00384 if (recordButton->isOn())
00385 {
00386 viewer->getViewerGUI()->move(this->x(),this->y());
00387 viewer->getViewerGUI()->hide();
00388 viewer->getViewerGUI()->show();
00389 recordButton->setOn(false);
00390 }
00391 else
00392 {
00393 toggleRecord(false);
00394 }
00395 }
00396
00397
00398
00399
00400 void MainController::display()
00401 {
00402 viewer->updateGL();
00403 }
00404 void MainController::computeBbox()
00405 {
00406 mainScene->computeBbox();
00407 }
00408 void MainController::viewAll()
00409 {
00410 viewer->viewAll();
00411 }
00412
00413
00414
00415 void MainController::toggleRecord(bool b)
00416 {
00417 if (b)
00418 {
00419 if (viewer->setSnapshot(true))
00420 {
00421 recordButton->setPixmap(QPixmap(recordButtonDown_xpm));
00422 recordButton->setOn(true);
00423 viewer->getViewerGUI()->hide();
00424 }
00425 else
00426 switch( QMessageBox::warning( this, "Files names of captured frames",
00427 "The files names of captured frames are not valid !\nThe pattern of these names depends on the video file name.\nIf the video file name is video.mpg,\nthe pattern is video####.ppm.",
00428 "New video file name",
00429 "Quit", 0, 0, 1 ) )
00430 {
00431 case 0:
00432 viewer->getViewerGUI()->chooseVideoName();
00433 break;
00434 case 1:
00435 statusBar()->message( "Capture abandoned" );
00436 break;
00437 }
00438 }
00439 else
00440 {
00441 viewer->setSnapshot(false);
00442 recordButton->setPixmap(QPixmap(recordButton_xpm));
00443 recordButton->setOn(false);
00444 viewer->getViewerGUI()->move(this->x(),this->y());
00445 viewer->getViewerGUI()->hide();
00446 viewer->getViewerGUI()->show();
00447 }
00448 }
00449
00450
00451
00452 void MainController::addNode(X3DTK::X3D::X3DNode * node)
00453 {
00454 x3dtreeqt->addNode(node);
00455 }
00456
00457
00458
00460 void MainController::removeX3DQtMap(X3DTK::X3DAbstractNode* EN)
00461 {
00462 if (x3dQtMap[EN])
00463 {
00464
00465 QWidget * q = x3dQtMap[EN];
00466
00467
00468 X3DTK::MFNode nodeToErase;
00469 for (X3DQtMap::iterator i=x3dQtMap.begin(); i!=x3dQtMap.end(); ++i )
00470 if ( (*i).second == q)
00471 {
00472 nodeToErase.push_back((*i).first);
00473 }
00474 for (X3DTK::MFNode::iterator i=nodeToErase.begin(); i!=nodeToErase.end(); ++i )
00475 x3dQtMap.erase(*i);
00476
00477
00478 if(q)
00479 delete q;
00480 }
00481
00482
00483
00484 if (dynamic_cast<X3DTK::X3D::FrameNode *>(EN))
00485 {
00486 X3DTK::MFNode list = EN->getParentList();
00487 X3DTK::X3DAbstractNode * parentNode =(*list.begin());
00488 removeX3DQtMap(parentNode);
00489 }
00490 }
00491
00493 QWidget * MainController::createQWidgetController(X3DTK::X3D::X3DNode * node)
00494 {
00495
00496 X3DTK::SFString string = node->getTypeName();
00497 for( X3DNodeQWidgetMap::iterator i=x3dNodeQWidgetMap.begin(); i!=x3dNodeQWidgetMap.end(); ++i )
00498 if((*i).first == string)
00499 {
00500
00501
00502 QString s1;
00503 X3DTK::SFString tmp = node->getName();
00504 if (tmp =="")
00505 s1 = QString(node->getType()->getName());
00506 else
00507 s1 = QString((node->getType()->getName()+" named "+tmp).data());
00508
00509
00510 QDialog * dialog = new QDialog(this, s1);
00511 dialog->setCaption(s1);
00512
00513
00514 QHBoxLayout * dialogLayout = new QHBoxLayout(dialog);
00515 dialogLayout->setAutoAdd(true);
00516
00517
00518 QScrollView * sv = new QScrollView(dialog);
00519 sv->setResizePolicy(QScrollView::AutoOneFit);
00520
00521
00522 QWidget * Q = ((*i).second)(node, sv->viewport());
00523 if (Q)
00524 {
00525
00526 QWidget::connect( Q, SIGNAL( changed() ), this, SLOT(computeBbox()));
00527 QWidget::connect( Q, SIGNAL( changed() ), this, SLOT(display()));
00528
00529 sv->addChild(Q);
00530
00531 x3dQtMap[node] = dialog;
00532 return x3dQtMap[node];
00533 }
00534 }
00535
00536
00537 std::cerr << std::endl;
00538 std::cerr << "Warning: a x3d node has no controller QWidget." << std::endl;
00539 std::cerr << " To create an associated controller QWidget to one x3d node," << std::endl;
00540 std::cerr << " see the documentation in $ANIMAL/doc/html/architecture.html#GUIController." << std::endl;
00541
00542 return NULL;
00543
00544 }
00545
00546
00547
00548 void MainController::keyPressEvent(QKeyEvent *e)
00549 {
00550 if (e->key()==Qt::Key_R)
00551 {
00552 viewer->getViewerGUI()->show();
00553 }
00554
00555 animal::KeyEvent * AKE
00556 = new animal::KeyEvent(e->type(), e->key(), e->state());
00557
00558 mainScene->keyPressEvent(AKE);
00559
00560 if (animTimer->isActive())
00561 doStep();
00562 }
00563
00564 void MainController::mouseDoubleClickEvent(QMouseEvent * e)
00565 {
00566 float orig[3], dir[3];
00567 viewer->camera()->convertClickToLine(e->x(), e->y(), orig, dir);
00568
00569 animal::MouseEvent * AME
00570 = new animal::MouseEvent( e->type(),
00571 e->x(),
00572 e->y(),
00573 e->button(),
00574 e->state(),
00575 animal::Vec3(orig[0], orig[1], orig[2]),
00576 animal::Vec3(dir[0], dir[1], dir[2]));
00577
00578 mainScene->mouseDoubleClickEvent(AME);
00579
00580 if (animTimer->isActive())
00581 doStep();
00582 }
00583
00584 void MainController::mouseMoveEvent(QMouseEvent * e)
00585 {
00586 float orig[3], dir[3];
00587 viewer->camera()->convertClickToLine(e->x(), e->y(), orig, dir);
00588
00589 animal::MouseEvent * AME
00590 = new animal::MouseEvent( e->type(),
00591 e->x(),
00592 e->y(),
00593 e->button(),
00594 e->state(),
00595 animal::Vec3(orig[0], orig[1], orig[2]),
00596 animal::Vec3(dir[0], dir[1], dir[2]));
00597 mainScene->mouseMoveEvent(AME);
00598
00599 if (animTimer->isActive())
00600 doStep();
00601 }
00602
00603 void MainController::mousePressEvent(QMouseEvent * e)
00604 {
00605 float orig[3], dir[3];
00606 viewer->camera()->convertClickToLine(e->x(), e->y(), orig, dir);
00607
00608 animal::MouseEvent * AME
00609 = new animal::MouseEvent( e->type(),
00610 e->x(),
00611 e->y(),
00612 e->button(),
00613 e->state(),
00614 animal::Vec3(orig[0], orig[1], orig[2]),
00615 animal::Vec3(dir[0], dir[1], dir[2]));
00616 mainScene->mousePressEvent(AME);
00617
00618 if (animTimer->isActive())
00619 doStep();
00620 }
00621
00622 void MainController::mouseReleaseEvent(QMouseEvent * e)
00623 {
00624 float orig[3], dir[3];
00625 viewer->camera()->convertClickToLine(e->x(), e->y(), orig, dir);
00626
00627 animal::MouseEvent * AME
00628 = new animal::MouseEvent( e->type(),
00629 e->x(),
00630 e->y(),
00631 e->button(),
00632 e->state(),
00633 animal::Vec3(orig[0], orig[1], orig[2]),
00634 animal::Vec3(dir[0], dir[1], dir[2]));
00635 mainScene->mouseReleaseEvent(AME);
00636
00637 if (animTimer->isActive())
00638 doStep();
00639 }
00640
00641
00642
00643 animal::ConstrainedItem* MainController::pickPoint( float origin[3], float direction[3],
00644 float threshold )
00645 {
00646 return mainScene->pickPoint(origin, direction, threshold );
00647 }
00648
00649
00650
00655 void MainController::setX3dDirectory(const std::string& d)
00656 {
00657 x3dDirectory = d;
00658 }
00659
00660
00664 std::string MainController::getX3dDirectory() const
00665 {
00666 return x3dDirectory;
00667 }