00001 #include "master.h"
00002
00007 #include <glutm/window.h>
00008 #include <glutm/winiv.h>
00009 #include <glutm/config.h>
00010
00011 #ifdef WIN32
00012 #pragma warning(disable : 4786) // Lengthy STL symbols
00013 #endif
00014
00015 #define GLUT_DISABLE_ATEXIT_HACK
00016 #include <glutm/glut.h>
00017
00018 #include <map>
00019 #include <list>
00020 #include <cassert>
00021 #include <algorithm>
00022 using namespace std;
00023
00024
00025
00026 #ifdef GLUTM_DEBUG
00027 #include <iostream>
00028 #include <iomanip>
00029 #define DEBUG_TITLE(x) setw(27) << setiosflags(ios::left) << (x) << ' '
00030 #endif
00031
00033
00034
00035
00036
00037 typedef list<GlutWindow *> GlutWindowList;
00038 typedef map<const int,GlutWindowList,less<const int> > GlutWindowDatabase;
00039
00040 GlutWindowDatabase _windows;
00041 GlutWindowList _toOpen;
00042 GlutWindowList _toClose;
00043
00045
00046 int GlutMaster::_idleCount = 0;
00047 bool GlutMaster::_glutInit = false;
00048
00049 GlutMaster::GlutMaster()
00050 {
00051 }
00052
00053 GlutMaster::~GlutMaster()
00054 {
00055 }
00056
00057
00058
00059
00060
00061 #if !defined(GLUTM_SAVER)
00062
00063 GlutWindow *
00064 GlutMaster::currentWindow()
00065 {
00066 assert(_glutInit);
00067
00068
00069 const int id = glutGetWindow();
00070
00071
00072 GlutWindowDatabase::const_iterator i = _windows.find(id);
00073
00074 if (i==_windows.end())
00075 return NULL;
00076 else
00077 {
00078 const GlutWindowList &list = i->second;
00079
00080
00081
00082 assert(list.size()>0);
00083 if (list.size()<=0)
00084 return NULL;
00085
00086
00087 return list.front();
00088 }
00089 }
00090
00091 void
00092 GlutMaster::openWindow(GlutWindow *glutWindow)
00093 {
00094 if (!glutWindow)
00095 return;
00096
00097
00098
00099 int &id = glutWindow->_windowID;
00100
00101
00102
00103 if (id==-1)
00104 {
00105 GlutMaster::init();
00106 glutInitDisplayMode(glutWindow->_displayMode);
00107
00108 if (glutWindow->_gameMode)
00109 {
00110
00111 id = glutEnterGameMode();
00112 }
00113 else
00114 {
00115
00116 glutInitWindowSize(glutWindow->_width,glutWindow->_height);
00117 glutInitWindowPosition(glutWindow->_x,glutWindow->_y);
00118 id = glutCreateWindow(glutWindow->_title.c_str());
00119 }
00120 }
00121
00122
00123
00124
00125
00126 assert(_glutInit);
00127
00128 GlutWindowDatabase::iterator i = _windows.find(id);
00129
00130
00131
00132
00133
00134 if (i==_windows.end())
00135 {
00136
00137
00138
00139 GlutWindowList list;
00140 list.push_back(glutWindow);
00141 _windows.insert(GlutWindowDatabase::value_type(id,list));
00142
00143
00144
00145
00146
00147 glutDisplayFunc (OnDisplay);
00148 glutIdleFunc (NULL);
00149 glutKeyboardFunc (OnKeyboard);
00150 glutKeyboardUpFunc (OnKeyboardUp);
00151 glutSpecialFunc (OnSpecial);
00152 glutSpecialUpFunc (OnSpecialUp);
00153 glutMotionFunc (OnMotion);
00154 glutMouseFunc (OnMouse);
00155 glutPassiveMotionFunc(OnPassiveMotion);
00156 glutEntryFunc (OnEntry);
00157 glutReshapeFunc (OnReshape);
00158 glutVisibilityFunc (OnVisibility);
00159 }
00160
00161
00162
00163
00164
00165
00166 else
00167 {
00168 GlutWindowList &list = i->second;
00169
00170
00171 assert(list.size()>0);
00172
00173
00174
00175 GlutWindow *previous = list.front();
00176
00177 if (glutWindow!=previous)
00178 {
00179
00180 glutSetWindow(id);
00181 previous->OnClose();
00182
00183
00184 list.remove(glutWindow);
00185 list.push_front(glutWindow);
00186 }
00187 }
00188
00189
00190
00191
00192
00193 _toOpen.push_back(glutWindow);
00194 glutTimerFunc(0,GlutMaster::CheckOnOpen,0);
00195 }
00196
00197 void
00198 GlutMaster::closeWindow(GlutWindow *glutWindow)
00199 {
00200
00201
00202
00203
00204
00205 _toClose.push_back(glutWindow);
00206 glutTimerFunc(0,GlutMaster::CheckOnClose,0);
00207 }
00208
00209 void
00210 GlutMaster::init(int argc,char *argv[])
00211 {
00212
00213
00214
00215
00216
00217 if (!_glutInit)
00218 {
00219 glutInit(&argc,argv);
00220
00221
00222
00223
00224 #ifdef GLUTM_OPEN_INVENTOR
00225 GlutWindowInventor::initOpenInventor();
00226 #endif
00227 }
00228
00229
00230
00231
00232 _glutInit = true;
00233 }
00234
00235 void
00236 GlutMaster::init()
00237 {
00238
00239 int argc = 1;
00240 char *argv = "";
00241 init(argc,&argv);
00242 }
00243
00244 void
00245 GlutMaster::mainLoop()
00246 {
00247
00248
00249
00250
00251 if (_windows.size())
00252 {
00253 init();
00254 glutMainLoop();
00255 }
00256 }
00257
00258 void
00259 GlutMaster::positionWindow(GlutWindow *window,int x,int y)
00260 {
00261 assert(window);
00262 if (!window)
00263 return;
00264
00265 const int id = window->_windowID;
00266
00267 if (id!=-1)
00268 {
00269 glutSetWindow(id);
00270 glutPositionWindow(x,y);
00271 window->_x = x;
00272 window->_y = y;
00273 }
00274 }
00275
00276
00277
00278 void
00279 GlutMaster::reshapeWindow(GlutWindow *window,int width,int height)
00280 {
00281 assert(window);
00282 if (!window)
00283 return;
00284
00285 const int id = window->_windowID;
00286
00287 if (id!=-1)
00288 {
00289 glutSetWindow(id);
00290 glutReshapeWindow(width,height);
00291 window->_width = width;
00292 window->_height = height;
00293 }
00294 }
00295
00296 void
00297 GlutMaster::setTick(GlutWindow *window,unsigned int msec)
00298 {
00299 assert(window);
00300 if (!window)
00301 return;
00302
00303 window->_tick = msec;
00304 const int id = window->_windowID;
00305
00306 #ifdef GLUTM_DEBUG
00307 cout << DEBUG_TITLE("GlutMaster::setTick");
00308 cout << window << ' ';
00309 cout << id << ' ';
00310 cout << msec << " msec" << endl;
00311 #endif
00312
00313 if (id!=-1 && msec!=0 && !window->_tickPending)
00314 {
00315 glutSetWindow(id);
00316 window->setTimer(msec,GlutWindow::_tickVal);
00317 window->_tickPending = true;
00318 }
00319 }
00320
00321 void
00322 GlutMaster::setTimer(GlutWindow *window,unsigned int msec,unsigned int val)
00323 {
00324 assert(window);
00325 if (!window)
00326 return;
00327
00328 const int id = window->_windowID;
00329
00330 #ifdef GLUTM_DEBUG
00331 cout << DEBUG_TITLE("GlutMaster::setTimer");
00332 cout << window << ' ';
00333 cout << id << ' ';
00334 cout << (val>>24) << ' ';
00335 cout << msec << " msec" << endl;
00336 #endif
00337
00338 if (id!=-1)
00339 glutTimerFunc(msec,GlutMaster::OnTimer,val);
00340 }
00341
00342 void
00343 GlutMaster::setIdle(GlutWindow *window,bool idle)
00344 {
00345 assert(window);
00346 if (!window)
00347 return;
00348
00349 if (!window->_idle && idle)
00350 {
00351
00352
00353 _idleCount++;
00354 if (_idleCount>0)
00355 glutIdleFunc(GlutMaster::OnIdle);
00356 }
00357 else
00358 if (window->_idle && !idle)
00359 {
00360
00361
00362 _idleCount--;
00363 if (_idleCount<1)
00364 glutIdleFunc(NULL);
00365 }
00366
00367 window->_idle = idle;
00368 }
00369
00370 void
00371 GlutMaster::setCursor(GlutWindow *window,int cursor)
00372 {
00373 assert(window);
00374 if (!window)
00375 return;
00376
00377 const int id = window->_windowID;
00378
00379 if (id!=-1)
00380 {
00381 glutSetWindow(id);
00382 glutSetCursor(cursor);
00383 }
00384 }
00385
00386 void
00387 GlutMaster::postRedisplay(GlutWindow *window)
00388 {
00389 assert(window);
00390 if (!window)
00391 return;
00392
00393 const int id = window->_windowID;
00394
00395 if (id!=-1)
00396 {
00397 glutSetWindow(id);
00398 glutPostRedisplay();
00399 }
00400 }
00401
00402 void
00403 GlutMaster::swapBuffers(GlutWindow *window)
00404 {
00405 assert(window);
00406 if (!window)
00407 return;
00408
00409 const int id = window->_windowID;
00410
00411 if (id!=-1)
00412 {
00413 glutSetWindow(id);
00414 glutSwapBuffers();
00415 }
00416 }
00417
00418 int
00419 GlutMaster::get(const GlutWindow *window,int info)
00420 {
00421 assert(window);
00422 if (!window)
00423 return 0;
00424
00425 const int id = window->_windowID;
00426
00427 assert(id!=-1);
00428
00429 if (id!=-1)
00430 {
00431 glutSetWindow(id);
00432 return glutGet(info);
00433 }
00434
00435 return 0;
00436 }
00437
00438 void
00439 GlutMaster::fullScreen(GlutWindow *window)
00440 {
00441 assert(window);
00442
00443 if (window)
00444 {
00445 const int id = window->_windowID;
00446
00447 assert(id!=-1);
00448
00449 if (id!=-1)
00450 {
00451 glutSetWindow(id);
00452 glutFullScreen();
00453 }
00454 }
00455 }
00456
00457 void
00458 GlutMaster::gameMode(GlutWindow *window)
00459 {
00460 }
00461
00462 void
00463 GlutMaster::updateModifiers(GlutWindow *window)
00464 {
00465 assert(window);
00466 if (window)
00467 {
00468 window->_shiftModifier = (glutGetModifiers()&GLUT_ACTIVE_SHIFT)!=0;
00469 window->_ctrlModifier = (glutGetModifiers()&GLUT_ACTIVE_CTRL) !=0;
00470 window->_altModifier = (glutGetModifiers()&GLUT_ACTIVE_ALT) !=0;
00471 }
00472 }
00473
00474
00475
00476
00477
00478 int GlutMaster::getScreenWidth() { return glutGet(GLUT_SCREEN_WIDTH); }
00479 int GlutMaster::getScreenHeight() { return glutGet(GLUT_SCREEN_HEIGHT); }
00480 int GlutMaster::getScreenWidthMm() { return glutGet(GLUT_SCREEN_WIDTH_MM); }
00481 int GlutMaster::getScreenHeightMm() { return glutGet(GLUT_SCREEN_HEIGHT_MM); }
00482 int GlutMaster::getElapsedTime() { return glutGet(GLUT_ELAPSED_TIME); }
00483
00485
00486 void
00487 GlutMaster::CheckShutdown(int val)
00488 {
00489 assert(_glutInit);
00490
00491 #ifdef GLUTM_DEBUG
00492 cout << DEBUG_TITLE("GlutMaster::CheckShutdown") << endl;
00493 #endif
00494
00495
00496
00497
00498 if (_windows.size()==0)
00499 exit(1);
00500 }
00501
00502 void
00503 GlutMaster::CheckOnOpen(int val)
00504 {
00505 assert(_glutInit);
00506
00507 #ifdef GLUTM_DEBUG
00508 cout << DEBUG_TITLE("GlutMaster::CheckOnOpen") << endl;
00509 #endif
00510
00511
00512
00513 while (_toOpen.size())
00514 {
00515 GlutWindow *window = _toOpen.front();
00516 const int id = window->_windowID;
00517
00518 #ifdef GLUTM_DEBUG
00519 cout << DEBUG_TITLE("GlutMaster::OnOpen") << window << endl;
00520 #endif
00521
00522 glutSetWindow(id);
00523 window->OnOpen();
00524 setTick(window,window->_tick);
00525 _toOpen.pop_front();
00526 }
00527 }
00528
00529 void
00530 GlutMaster::CheckOnClose(int val)
00531 {
00532 assert(_glutInit);
00533
00534 #ifdef GLUTM_DEBUG
00535 cout << DEBUG_TITLE("GlutMaster::CheckOnClose") << endl;
00536 #endif
00537
00538
00539
00540 while (_toClose.size())
00541 {
00542 GlutWindow *window = _toClose.front();
00543 const int id = window->_windowID;
00544 const bool gameMode = window->_gameMode;
00545
00546 #ifdef GLUTM_DEBUG
00547 cout << DEBUG_TITLE("GlutMaster::OnClose") << window << endl;
00548 #endif
00549
00550
00551
00552 glutSetWindow(id);
00553 window->OnClose();
00554 _toClose.pop_front();
00555
00556
00557
00558 GlutWindowDatabase::iterator i = _windows.find(id);
00559 assert(i!=_windows.end());
00560
00561
00562
00563 GlutWindowList &list = i->second;
00564 assert(find(list.begin(),list.end(),window)!=list.end());
00565
00566
00567
00568 delete window;
00569
00570
00571
00572
00573
00574 if (list.size()==1)
00575 {
00576 _windows.erase(i);
00577 if (gameMode)
00578 glutLeaveGameMode();
00579 else
00580 glutDestroyWindow(id);
00581 }
00582 else
00583 {
00584
00585
00586 if (list.front()==window)
00587 {
00588 list.pop_front();
00589 _toOpen.push_back(list.front());
00590 }
00591 else
00592 list.remove(window);
00593 }
00594
00595
00596
00597 _toOpen.remove(window);
00598
00599
00600
00601 glutTimerFunc(0,GlutMaster::CheckShutdown,0);
00602 }
00603 }
00604
00606
00607
00608
00609
00610
00611 void
00612 GlutMaster::OnDisplay()
00613 {
00614 GlutWindow *window = currentWindow();
00615
00616 assert(_glutInit);
00617 assert(window);
00618
00619 #ifdef GLUTM_DEBUG
00620 cout << DEBUG_TITLE("GlutMaster::OnDisplay") << window << endl;
00621 #endif
00622
00623 if (window)
00624 {
00625 window->OnPreDisplay();
00626 window->OnDisplay();
00627 window->OnPostDisplay();
00628 }
00629 }
00630
00631 void
00632 GlutMaster::OnIdle()
00633 {
00634 assert(_glutInit);
00635
00636 if (_idleCount!=0)
00637 {
00638
00639
00640
00641 for (GlutWindowDatabase::iterator i=_windows.begin(); i!=_windows.end(); i++)
00642 {
00643
00644 assert(i->second.size()>0);
00645
00646 GlutWindow *window = i->second.front();
00647
00648
00649 assert(window->_windowID==i->first);
00650
00651 if (window->getIdle())
00652 {
00653 glutSetWindow(i->first);
00654 window->OnIdle();
00655 }
00656 }
00657 }
00658 }
00659
00660 void
00661 GlutMaster::OnTimer(int val)
00662 {
00663 const unsigned int v = val;
00664
00666 const uint32 id = v&0x00ffffff;
00668 const byte m = v>>24;
00669
00670
00671
00672 GlutWindowDatabase::const_iterator i = _windows.find(id);
00673
00674 #ifdef GLUTM_DEBUG
00675 cout << DEBUG_TITLE("GlutMaster::OnTimer");
00676 cout << (i==_windows.end() ? NULL : i->second.front()) << ' ';
00677 cout << id << ' ';
00678 cout << uint32(m) << endl;
00679 #endif
00680
00681
00682
00683
00684
00685 if (i==_windows.end())
00686 return;
00687
00688 GlutWindow *window = i->second.front();
00689
00690 assert(window);
00691
00692
00693
00694 glutSetWindow(id);
00695 window->OnPreTimer(m);
00696 window->OnTimer(m);
00697 }
00698
00699 void
00700 GlutMaster::OnKeyboard(unsigned char key, int x, int y)
00701 {
00702 GlutWindow *window = currentWindow();
00703
00704 assert(_glutInit);
00705 assert(window);
00706
00707 #ifdef GLUTM_DEBUG
00708 cout << DEBUG_TITLE("GlutMaster::OnKeyboard");
00709 cout << window << ' ' << key << ' ' << x << ',' << y << endl;
00710 #endif
00711
00712 if (window)
00713 {
00714 updateModifiers(window);
00715 window->OnKeyboard(key, x, y);
00716 }
00717 }
00718
00719 void
00720 GlutMaster::OnKeyboardUp(unsigned char key, int x, int y)
00721 {
00722 GlutWindow *window = currentWindow();
00723
00724 assert(_glutInit);
00725 assert(window);
00726
00727 #ifdef GLUTM_DEBUG
00728 cout << DEBUG_TITLE("GlutMaster::OnKeyboardUp");
00729 cout << window << ' ' << key << ' ' << x << ',' << y << endl;
00730 #endif
00731
00732 if (window)
00733 {
00734 updateModifiers(window);
00735 window->OnKeyboardUp(key, x, y);
00736 }
00737
00738 }
00739
00740 void
00741 GlutMaster::OnSpecial(int key, int x, int y)
00742 {
00743 GlutWindow *window = currentWindow();
00744
00745 assert(_glutInit);
00746 assert(window);
00747
00748 #ifdef GLUTM_DEBUG
00749 cout << DEBUG_TITLE("GlutMaster::OnSpecial ");
00750 cout << window << ' ' << key << ' ' << x << ',' << y << endl;
00751 #endif
00752
00753 if (window)
00754 {
00755 updateModifiers(window);
00756 window->OnSpecial(key, x, y);
00757 }
00758 }
00759
00760 void
00761 GlutMaster::OnSpecialUp(int key, int x, int y)
00762 {
00763 GlutWindow *window = currentWindow();
00764
00765 assert(_glutInit);
00766 assert(window);
00767
00768 #ifdef GLUTM_DEBUG
00769 cout << DEBUG_TITLE("GlutMaster::OnSpecialUp");
00770 cout << window << ' ' << key << ' ' << x << ',' << y << endl;
00771 #endif
00772
00773 if (window)
00774 {
00775 updateModifiers(window);
00776 window->OnSpecialUp(key, x, y);
00777 }
00778 }
00779
00780 void
00781 GlutMaster::OnMenu(int value)
00782 {
00783 GlutWindow *window = currentWindow();
00784
00785 assert(_glutInit);
00786 assert(window);
00787
00788 #ifdef GLUTM_DEBUG
00789 cout << DEBUG_TITLE("GlutMaster::OnMenu");
00790 cout << window << ' ' << value << endl;
00791 #endif
00792
00793 if (window)
00794 window->OnMenu(value);
00795 }
00796
00797 void
00798 GlutMaster::OnMotion(int x, int y)
00799 {
00800 GlutWindow *window = currentWindow();
00801
00802 assert(_glutInit);
00803 assert(window);
00804
00805 #ifdef GLUTM_DEBUG
00806 cout << DEBUG_TITLE("GlutMaster::OnMotion");
00807 cout << window << ' ' << x << ',' << y << endl;
00808 #endif
00809
00810 if (window)
00811 {
00812
00813
00814
00815 if (window->_tick)
00816 {
00817 window->_mouseEvents = true;
00818 window->_mouseX = x;
00819 window->_mouseY = y;
00820 }
00821 else
00822 window->OnMotion(x, y);
00823 }
00824 }
00825
00826 void
00827 GlutMaster::OnMouse(int button, int state, int x, int y)
00828 {
00829 GlutWindow *window = currentWindow();
00830
00831 assert(_glutInit);
00832 assert(window);
00833
00834 #ifdef GLUTM_DEBUG
00835 cout << DEBUG_TITLE("GlutMaster::OnMouse");
00836 cout << window << ' ' << button << ' ' << state << ' ' << x << ',' << y << endl;
00837 #endif
00838
00839 if (window)
00840 {
00841 updateModifiers(window);
00842 window->OnMouse(button, state, x, y);
00843 }
00844 }
00845
00846 void
00847 GlutMaster::OnPassiveMotion(int x, int y)
00848 {
00849 GlutWindow *window = currentWindow();
00850
00851 assert(_glutInit);
00852 assert(window);
00853
00854 #ifdef GLUTM_DEBUG
00855 cout << DEBUG_TITLE("GlutMaster::OnPassiveMotion");
00856 cout << window << ' ' << x << ',' << y << endl;
00857 #endif
00858
00859 if (window)
00860 window->OnPassiveMotion(x, y);
00861 }
00862
00863 void
00864 GlutMaster::OnEntry(int state)
00865 {
00866 GlutWindow *window = currentWindow();
00867
00868 assert(_glutInit);
00869
00870 #ifdef GLUTM_DEBUG
00871 cout << DEBUG_TITLE("GlutMaster::OnEntry");
00872 cout << window << (state==GLUT_ENTERED ? " entered" : " left") << endl;
00873 #endif
00874
00875
00876
00877
00878
00879
00880
00881 if (window)
00882 window->OnEntry(state);
00883 }
00884
00885 void
00886 GlutMaster::OnReshape(int w, int h)
00887 {
00888 GlutWindow *window = currentWindow();
00889
00890 assert(_glutInit);
00891 assert(window);
00892
00893 #ifdef GLUTM_DEBUG
00894 cout << DEBUG_TITLE("GlutMaster::OnReshape");
00895 cout << window << ' ' << w << ',' << h << endl;
00896 #endif
00897
00898 if (window)
00899 window->OnReshape(w,h);
00900 }
00901
00902 void
00903 GlutMaster::OnVisibility(int visible)
00904 {
00905 GlutWindow *window = currentWindow();
00906
00907 assert(_glutInit);
00908 assert(window);
00909
00910 #ifdef GLUTM_DEBUG
00911 cout << DEBUG_TITLE("GlutMaster::OnVisibility");
00912 cout << window << ' ' << visible << endl;
00913 #endif
00914
00915 if (window)
00916 window->OnVisibility(visible);
00917 }
00918
00919 #endif