00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <math.h>
00028 #include "FltkOpenGLDisplayDevice.h"
00029 #include "Inform.h"
00030 #include "utilities.h"
00031 #include "config.h"
00032 #include "VMDApp.h"
00033 #include "FL/Fl.H"
00034 #include "FL/Fl_Gl_Window.H"
00035 #include "FL/forms.H"
00036
00039 class myglwindow : public Fl_Gl_Window {
00040 FltkOpenGLDisplayDevice *dispdev;
00041 VMDApp *app;
00042 int dragpending;
00043
00044 public:
00045 myglwindow(int wx, int wy, int width, int height, const char *nm,
00046 FltkOpenGLDisplayDevice *d, VMDApp *vmdapp)
00047 : Fl_Gl_Window(wx, wy, width, height, nm), dispdev(d), app(vmdapp), dragpending(0) {
00048
00049 size_range(1,1,0,0);
00050 }
00051
00052 int handle(int event) {
00053 #if 1
00054
00055 if (event == FL_PASTE) {
00056
00057
00058 if (dragpending) {
00059 int len = Fl::event_length();
00060
00061
00062 if (len > 0) {
00063 int numfiles, i;
00064 const char *lastc;
00065 int lasti;
00066 FileSpec spec;
00067 const char *ctext = Fl::event_text();
00068 char *filename = (char *) malloc((1 + len) * sizeof(char));
00069
00070 for (lasti=0,lastc=ctext,numfiles=0,i=0; i<len; i++) {
00071
00072 if (ctext[i] == '\n') {
00073 memcpy(filename, lastc, (i-lasti)*sizeof(char));
00074 filename[i-lasti] = '\0';
00075
00076
00077 app->molecule_load(-1, filename, NULL, &spec);
00078
00079 lasti=i+1;
00080 lastc=&ctext[lasti];
00081 numfiles++;
00082 }
00083
00084
00085 if (i == (len-1)) {
00086 memcpy(filename, lastc, (1+i-lasti)*sizeof(char));
00087 filename[1+i-lasti] = '\0';
00088
00089
00090 app->molecule_load(-1, filename, NULL, &spec);
00091 numfiles++;
00092 }
00093 }
00094
00095 free(filename);
00096 }
00097
00098 dragpending = 0;
00099 }
00100
00101 return 1;
00102 }
00103
00104
00105 if (event == FL_DND_ENTER || event == FL_DND_DRAG) {
00106 return 1;
00107 }
00108 if (event == FL_DND_RELEASE) {
00109 Fl::paste(*this);
00110 dragpending = 1;
00111 return 1;
00112 }
00113 #endif
00114
00115 switch (event) {
00116 case FL_MOUSEWHEEL:
00117 dispdev->lastevent = event;
00118 dispdev->lastzdelta = Fl::event_dy();
00119 break;
00120 case FL_PUSH:
00121 dispdev->lastevent = event;
00122 dispdev->lastbtn = Fl::event_button();
00123 if (dispdev->lastbtn == FL_LEFT_MOUSE && Fl::event_state(FL_META)) {
00124 dispdev->lastbtn = FL_MIDDLE_MOUSE;
00125 }
00126 break;
00127 case FL_DRAG:
00128 dispdev->lastevent = event;
00129 break;
00130 case FL_RELEASE:
00131 dispdev->lastevent = event;
00132 break;
00133 #if (FL_MAJOR_VERSION >= 1) && (FL_MINOR_VERSION >= 1)
00134 case FL_KEYDOWN:
00135 #else
00136
00137 case FL_KEYBOARD:
00138 #endif
00139 dispdev->lastevent = event;
00140 dispdev->lastkeycode = Fl::event_key();
00141 dispdev->lastbtn = *Fl::event_text();
00142 break;
00143 default:
00144 return Fl_Gl_Window::handle(event);
00145 }
00146 return 1;
00147 }
00148 void draw() {
00149 dispdev->reshape();
00150 dispdev->_needRedraw = 1;
00151 app->VMDupdate(VMD_IGNORE_EVENTS);
00152 }
00153
00154 void hide() {
00155 if (fl_show_question("Really Quit?", 0))
00156 app->VMDexit("",0,0);
00157 }
00158 };
00159
00160
00161
00162 static const char *glStereoNameStr[OPENGL_STEREO_MODES] =
00163 { "Off",
00164 "QuadBuffered",
00165 "DTI SideBySide",
00166 "Checkerboard",
00167 "ColumnInterleaved",
00168 "RowInterleaved",
00169 "Anaglyph",
00170 "SideBySide",
00171 "AboveBelow",
00172 "Left",
00173 "Right" };
00174
00175 static const char *glRenderNameStr[OPENGL_RENDER_MODES] =
00176 { "Normal",
00177 "GLSL",
00178 "Acrobat3D" };
00179
00180 static const char *glCacheNameStr[OPENGL_CACHE_MODES] =
00181 { "Off",
00182 "On" };
00183
00185
00186
00187 FltkOpenGLDisplayDevice::FltkOpenGLDisplayDevice(int argc, char **argv,
00188 VMDApp *vmdapp, int *size, int *loc)
00189 : OpenGLRenderer((char *) "VMD " VMDVERSION " OpenGL Display") {
00190
00191
00192 stereoNames = glStereoNameStr;
00193 stereoModes = OPENGL_STEREO_MODES;
00194
00195
00196 renderNames = glRenderNameStr;
00197 renderModes = OPENGL_RENDER_MODES;
00198
00199 cacheNames = glCacheNameStr;
00200 cacheModes = OPENGL_CACHE_MODES;
00201
00202
00203 int SX = 100, SY = 100, W, H;
00204
00205 W = size[0];
00206 H = size[1];
00207 if (loc) {
00208 SX = loc[0];
00209 SY = loc[1];
00210 }
00211 window = new myglwindow(SX, SY, W, H, name, this, vmdapp);
00212
00213 ext->hasstereo = FALSE;
00214 ext->stereodrawforced = FALSE;
00215 ext->hasmultisample = FALSE;
00216
00217 int rc=0;
00218
00219 #if (FL_MAJOR_VERSION >= 1) && (((FL_MINOR_VERSION >= 1) && (FL_PATCH_VERSION >= 7)) || ((FL_MINOR_VERSION >= 1) && (FL_PATCH_VERSION >= 7)))
00220
00221 if (getenv("VMDPREFERSTEREO") != NULL) {
00222
00223 rc = window->mode(FL_RGB8 | FL_DOUBLE | FL_STENCIL | FL_STEREO);
00224 ext->hasstereo = TRUE;
00225 #if defined(__APPLE__)
00226 ext->stereodrawforced = TRUE;
00227 #endif
00228
00229
00230 #if !defined(__APPLE__)
00231
00232 } else if (rc != 0) {
00233 rc = window->mode(FL_RGB8 | FL_DOUBLE | FL_STENCIL | FL_MULTISAMPLE);
00234 ext->hasmultisample = TRUE;
00235 #endif
00236 } else {
00237 rc = window->mode(FL_RGB8 | FL_DOUBLE | FL_STENCIL);
00238 }
00239 #else
00240
00241 rc = window->mode(FL_RGB8 | FL_DOUBLE | FL_STENCIL);
00242 #endif
00243
00244 window->show();
00245
00246 window->make_current();
00247
00248
00249 screenX = Fl::w();
00250 screenY = Fl::h();
00251
00252
00253 setup_initial_opengl_state();
00254
00255
00256
00257 if (ext->hasmultisample)
00258 aaAvailable = TRUE;
00259 else
00260 aaAvailable = FALSE;
00261
00262
00263 if (ext->hasmultisample) {
00264 aa_on();
00265
00266
00267 }
00268
00269 cueingAvailable = TRUE;
00270 cueing_on();
00271
00272 cullingAvailable = TRUE;
00273 culling_off();
00274
00275 set_sphere_mode(sphereMode);
00276 set_sphere_res(sphereRes);
00277 set_line_width(lineWidth);
00278 set_line_style(lineStyle);
00279
00280
00281 reshape();
00282 normal();
00283 clear();
00284 update();
00285 }
00286
00287
00288 FltkOpenGLDisplayDevice::~FltkOpenGLDisplayDevice(void) {
00289 free_opengl_ctx();
00290 delete window;
00291 }
00292
00294
00295
00296
00297
00298
00299
00300 int FltkOpenGLDisplayDevice::x(void) {
00301
00302 #if 1
00303 return Fl::event_x_root();
00304 #else
00305 int x, y;
00306 Fl::get_mouse(x, y);
00307 return x;
00308 #endif
00309 }
00310
00311
00312
00313 int FltkOpenGLDisplayDevice::y(void) {
00314
00315 #if 1
00316 return screenY - Fl::event_y_root();
00317 #else
00318 int x, y;
00319 Fl::get_mouse(x, y);
00320 return screenY - y;
00321 #endif
00322 }
00323
00324
00325 int FltkOpenGLDisplayDevice::shift_state(void) {
00326 Fl::check();
00327
00328 int retval = 0;
00329 int keymask = (int) Fl::event_state();
00330 if (keymask & FL_SHIFT)
00331 retval |= SHIFT;
00332 if (keymask & FL_CTRL)
00333 retval |= CONTROL;
00334 if (keymask & FL_ALT)
00335 retval |= ALT;
00336 return retval;
00337 }
00338
00339
00340 int FltkOpenGLDisplayDevice::spaceball(int *rx, int *ry, int *rz, int *tx, int *ty,
00341 int *tz, int *buttons) {
00342
00343 return 0;
00344 }
00345
00346
00347
00348
00349 void FltkOpenGLDisplayDevice::set_cursor(int n) {
00350 switch (n) {
00351 default:
00352 case DisplayDevice::NORMAL_CURSOR: window->cursor(FL_CURSOR_ARROW); break;
00353 case DisplayDevice::TRANS_CURSOR: window->cursor(FL_CURSOR_MOVE); break;
00354 case DisplayDevice::SCALE_CURSOR: window->cursor(FL_CURSOR_WE); break;
00355 case DisplayDevice::PICK_CURSOR: window->cursor(FL_CURSOR_CROSS); break;
00356 case DisplayDevice::WAIT_CURSOR: window->cursor(FL_CURSOR_WAIT); break;
00357 }
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367 int FltkOpenGLDisplayDevice::read_event(long &retdev, long &retval) {
00368 #if !defined(__APPLE__)
00369
00370
00371
00372
00373 Fl::check();
00374 #endif
00375
00376 switch (lastevent) {
00377 case FL_MOUSEWHEEL:
00378
00379
00380 if (lastzdelta < 0) {
00381 retdev = WIN_WHEELUP;
00382 } else {
00383 retdev = WIN_WHEELDOWN;
00384 }
00385 break;
00386 case FL_PUSH:
00387 case FL_DRAG:
00388 case FL_RELEASE:
00389 if (lastbtn == FL_LEFT_MOUSE) retdev = WIN_LEFT;
00390 else if (lastbtn == FL_MIDDLE_MOUSE) retdev = WIN_MIDDLE;
00391 else if (lastbtn == FL_RIGHT_MOUSE) retdev = WIN_RIGHT;
00392 else {
00393
00394 }
00395 retval = (lastevent == FL_PUSH || lastevent == FL_DRAG);
00396 break;
00397
00398 #if (FL_MAJOR_VERSION >= 1) && (FL_MINOR_VERSION >= 1)
00399 case FL_KEYDOWN:
00400 #else
00401
00402 case FL_KEYBOARD:
00403 #endif
00404
00405 if (lastkeycode >= FL_F && lastkeycode <= FL_F_Last) {
00406 retdev = (lastkeycode - FL_F) + ((int) WIN_KBD_F1);
00407 } else {
00408 switch(lastkeycode) {
00409 case FL_Escape: retdev = WIN_KBD_ESCAPE; break;
00410 case FL_Up: retdev = WIN_KBD_UP; break;
00411 case FL_Down: retdev = WIN_KBD_DOWN; break;
00412 case FL_Left: retdev = WIN_KBD_LEFT; break;
00413 case FL_Right: retdev = WIN_KBD_RIGHT; break;
00414 case FL_Page_Up: retdev = WIN_KBD_PAGE_UP; break;
00415 case FL_Page_Down: retdev = WIN_KBD_PAGE_UP; break;
00416 case FL_Home: retdev = WIN_KBD_HOME; break;
00417 case FL_End: retdev = WIN_KBD_END; break;
00418 case FL_Insert: retdev = WIN_KBD_INSERT; break;
00419 case FL_Delete: retdev = WIN_KBD_DELETE; break;
00420
00421 default:
00422 retdev = WIN_KBD;
00423 break;
00424 }
00425 }
00426 retval = lastbtn;
00427 break;
00428
00429 default:
00430 return 0;
00431 }
00432 lastevent = 0;
00433 return 1;
00434 }
00435
00436
00437
00438
00439
00440
00441 void FltkOpenGLDisplayDevice::reshape(void) {
00442
00443 xSize = window->w();
00444 ySize = window->h();
00445 xOrig = window->x();
00446 yOrig = screenY - window->y() - ySize;
00447
00448 switch (inStereo) {
00449 case OPENGL_STEREO_SIDE:
00450 set_screen_pos(0.5f * (float)xSize / (float)ySize);
00451 break;
00452
00453 case OPENGL_STEREO_ABOVEBELOW:
00454 set_screen_pos(2.0f * (float)xSize / (float)ySize);
00455 break;
00456
00457 case OPENGL_STEREO_STENCIL_CHECKERBOARD:
00458 case OPENGL_STEREO_STENCIL_COLUMNS:
00459 case OPENGL_STEREO_STENCIL_ROWS:
00460 enable_stencil_stereo(inStereo);
00461 set_screen_pos((float)xSize / (float)ySize);
00462 break;
00463
00464 default:
00465 set_screen_pos((float)xSize / (float)ySize);
00466 break;
00467 }
00468 }
00469
00470 unsigned char * FltkOpenGLDisplayDevice::readpixels(int &x, int &y) {
00471 unsigned char * img;
00472
00473 x = xSize;
00474 y = ySize;
00475
00476 if ((img = (unsigned char *) malloc(x * y * 3)) != NULL) {
00477 #if !defined(WIREGL)
00478 glPixelStorei(GL_PACK_ALIGNMENT, 1);
00479 glReadPixels(0, 0, x, y, GL_RGB, GL_UNSIGNED_BYTE, img);
00480 #endif
00481 } else {
00482 x = 0;
00483 y = 0;
00484 }
00485
00486 return img;
00487 }
00488
00489
00490
00491 void FltkOpenGLDisplayDevice::update(int do_update) {
00492 if(do_update)
00493 window->swap_buffers();
00494
00495 glDrawBuffer(GL_BACK);
00496 }
00497
00498 void FltkOpenGLDisplayDevice::do_resize_window(int w, int h) {
00499 window->size(w, h);
00500
00501 window->size_range(1,1,0,0);
00502 }
00503
00504 void FltkOpenGLDisplayDevice::do_reposition_window(int xpos, int ypos) {
00505 window->position(xpos, ypos);
00506
00507 window->size_range(1,1,0,0);
00508 }
00509
00510