Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

VMDApp.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2008 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 /***************************************************************************
00009  * RCS INFORMATION:
00010  *
00011  *      $RCSfile: VMDApp.C,v $
00012  *      $Author: johns $        $Locker:  $             $State: Exp $
00013  *      $Revision: 1.412 $      $Date: 2008/08/06 20:27:53 $
00014  *
00015  ***************************************************************************/
00016  
00017 #include <stdlib.h>
00018 #include <string.h>
00019 #include <signal.h>
00020 #include <sys/types.h>
00021 #include <sys/stat.h>
00022 #include <ctype.h> // for isalnum()
00023 
00024 #include "VMDDisplayList.h"
00025 #include "CoorPluginData.h"
00026 #include "PluginMgr.h"
00027 #include "MolFilePlugin.h"
00028 #include "Matrix4.h"
00029 #include "config.h"
00030 #include "Inform.h"
00031 #include "AtomSel.h"
00032 #include "VMDTitle.h"
00033 #include "DisplayDevice.h"
00034 #include "PickList.h"
00035 #include "PickModeList.h"
00036 #include "MaterialList.h"
00037 #include "Scene.h"
00038 #include "CommandQueue.h"
00039 #include "UIText.h"
00040 #include "Stage.h"
00041 #include "Axes.h"
00042 #include "DisplayRocker.h"
00043 #include "FPS.h"
00044 #include "MoleculeList.h"
00045 #include "Mouse.h"
00046 #include "Spaceball.h"
00047 #ifdef WIN32
00048 #include "Win32Joystick.h"
00049 #endif
00050 #include "GeometryList.h"
00051 #include "FileRenderer.h"
00052 #include "FileRenderList.h"
00053 #include "CmdAnimate.h"
00054 #include "CmdMol.h"
00055 #include "CmdMaterial.h"
00056 #include "CmdPlugin.h"
00057 #include "CmdRender.h"   // to log the render commands we execute
00058 #include "CmdTrans.h"
00059 #include "CmdDisplay.h"
00060 #include "CmdColor.h"
00061 #include "CmdLabel.h"
00062 #include "TextEvent.h"
00063 #include "CmdMenu.h"
00064 #include "P_UIVR.h"
00065 #include "P_CmdTool.h"
00066 #include "SymbolTable.h"
00067 #include "VMDCollab.h"
00068 #include "CUDAAccel.h"
00069 
00070 #if defined(VMDTHREADS) // System-specific threads code
00071 #include "VMDThreads.h"
00072 #endif
00073 
00074 #ifdef MACVMD
00075 #include "MacVMDDisplayDevice.h"
00076 #endif
00077 
00078 #ifdef VMDOPENGL        // OpenGL-specific files
00079 #if defined(VMDFLTKOPENGL)
00080 #include "FltkOpenGLDisplayDevice.h"
00081 #else
00082 #ifndef MACVMD
00083 #include "OpenGLDisplayDevice.h"
00084 #endif
00085 #endif
00086 
00087 #ifdef VMDCAVE          // CAVE-specific files
00088 #include "cave_ogl.h"
00089 #include "CaveDisplayDevice.h"
00090 #include "CaveRoutines.h"
00091 #include "CaveScene.h"
00092 #endif // VMDCAVE
00093 #endif // VMDOPENGL
00094 
00095 #include "VMDMenu.h"
00096 #ifdef VMDFLTK         // If using FORMS GUI include FORMS-specific objects
00097 #include "FL/forms.H"
00098 
00099 // New Fltk menus 
00100 #include "MainFltkMenu.h"
00101 #include "ColorFltkMenu.h"
00102 #include "MaterialFltkMenu.h"
00103 #include "DisplayFltkMenu.h"
00104 #include "FileChooserFltkMenu.h"
00105 #include "SaveTrajectoryFltkMenu.h"
00106 #include "GeometryFltkMenu.h"
00107 #include "GraphicsFltkMenu.h"
00108 #include "RenderFltkMenu.h"
00109 #include "ToolFltkMenu.h"
00110 
00111 #endif // VMDFLTK
00112 
00113 #ifdef VMDIMD
00114 #include "IMDMgr.h"
00115 #include "CmdIMD.h"
00116 #endif
00117 
00118 // FreeVR conflicts with the FLTK include files, so include it _after_ FLTK.
00119 #ifdef VMDFREEVR     // FreeVR-specific files
00120 #include "freevr.h"
00121 #include "FreeVRDisplayDevice.h"
00122 #include "FreeVRRoutines.h"
00123 #include "FreeVRScene.h"
00124 #endif
00125 
00126 #if defined(VMDTKCON)
00127 #include "vmdconsole.h"
00128 #endif
00129 
00130 #include "VMDApp.h"
00131 
00132 // default atom selection
00133 #define DEFAULT_ATOMSEL "all"
00134 
00135 // XXX static data item
00136 static unsigned long repserialnum;
00137 static unsigned long texserialnum;
00138 
00139 // static initialization
00140 JString VMDApp::text_message;
00141 
00142 VMDApp::VMDApp(int argc, char **argv) {
00143   // initialize ALL member variables
00144   argc_m = argc;
00145   argv_m = (const char **)argv;
00146   menulist = NULL;
00147   nextMolID = 0; 
00148   stride_firsttime = 1;
00149   eofexit = 0;
00150   mouse = NULL;
00151   spaceball = NULL;
00152 #ifdef WIN32
00153   win32joystick = NULL;
00154 #endif
00155   vmdTitle = NULL; 
00156   fileRenderList = NULL;
00157   pluginMgr = NULL;
00158   uiText = NULL;
00159   uivr = NULL;
00160 #ifdef VMDIMD
00161   imdMgr = NULL;
00162 #endif
00163   display = NULL;
00164   scene = NULL;
00165   pickList = NULL;
00166   pickModeList = NULL;
00167   materialList = NULL;
00168   stage = NULL;
00169   axes = NULL;
00170   fps = NULL;
00171   commandQueue = NULL;
00172   moleculeList = NULL;
00173   geometryList = NULL;
00174   atomSelParser = NULL;
00175   anim = NULL;
00176 
00177   UpdateDisplay = TRUE;
00178   exitFlag = TRUE;
00179   ResetViewPending = FALSE;
00180 
00181   background_processing_clear();
00182 
00183   highlighted_molid  = highlighted_rep = -1;
00184 }
00185 
00186 // initialization routine for the library globals
00187 int VMDApp::VMDinit(int argc, char **argv, const char *displaytype, 
00188                     int *displayLoc, int *displaySize) {
00189 
00190   // register CUDA GPU accelerator devices
00191   cuda = new CUDAAccel();
00192 
00193   // initialize the display
00194   int *dloc = (displayLoc[0]  > 0 ? displayLoc  : (int *) NULL);
00195 
00196   int dsiz[2] = { 512, 512 };
00197   if (displaySize && displaySize[0] > 0 && displaySize[1] > 0) {
00198     dsiz[0] = displaySize[0];
00199     dsiz[1] = displaySize[1];
00200   }
00201 
00202   // initialize static data items
00203   repserialnum = 0; // initialize the display list serial number
00204   texserialnum = 0; // initialize the texture list serial number
00205 
00206 #ifdef MACVMD
00207   display = new MacVMDDisplayDevice(this, dsiz);
00208 #endif
00209 
00210   // check for a standard monitor display
00211   if (!strcmp(displaytype, "WIN") || !strcmp(displaytype, "OPENGL")) {
00212 #if defined(VMDOPENGL)
00213 #if defined(VMDFLTKOPENGL)
00214     display = new FltkOpenGLDisplayDevice(argc, argv, this, dsiz, dloc);
00215 #else
00216     display = new OpenGLDisplayDevice;
00217     if (!display->init(argc, argv, this, dsiz, dloc)) {
00218       VMDexit("Unable to create OpenGL window.", 1, 7);
00219       return FALSE;
00220     } 
00221 #endif
00222 #endif
00223   }
00224 
00225 #ifdef VMDCAVE
00226   if (!strcmp(displaytype, "CAVE") || !strcmp(displaytype, "CAVEFORMS")) {
00227     // The CAVE scene is allocated from shared memory and can be 
00228     // accessed by all of the rendering processes by virtue of its
00229     // class-specific operator new.
00230     scene = new CaveScene(this);
00231     msgInfo << "Cave shared memory scene created." << sendmsg;
00232 
00233     // the CAVE display device is created in process-private memory
00234     display = new CaveDisplayDevice;
00235 
00236     // set up pointers for cave_renderer, needs to be done before forking.
00237     set_cave_pointers(scene, display);
00238 
00239     // XXX this may cure a problem with specular highlights in CAVElib
00240     // by default CAVElib messes with the OpenGL modelview matrix, this
00241     // option prevents it from doing so, which should allow specular 
00242     // highlights to look right on multiple walls, but it breaks depth cueing.
00243     // CAVESetOption(CAVE_PROJ_USEMODELVIEW, 0);
00244     CAVESetOption(CAVE_GL_SAMPLES, 8); // enable multisample antialiasing
00245     CAVEInit();                        // fork off the rendering processes
00246     CAVEDisplay(cave_renderer, 0);     // set the fctn ptr for the renderers
00247     display->renderer_process = 0;     // this proc is the master process
00248     vmd_set_cave_is_initialized();     // flag successfull CAVE init
00249     msgInfo << "CAVE Initialized" << sendmsg;
00250   }
00251 #endif
00252 
00253 #ifdef VMDFREEVR
00254   if (!strcmp(displaytype, "FREEVR") || !strcmp(displaytype, "FREEVRFORMS")) {
00255     // The FreeVR scene is allocated from shared memory and can be 
00256     // accessed by all of the rendering processes by virtue of its
00257     // class-specific operator new.
00258     scene = new FreeVRScene(this);
00259     msgInfo << "FreeVR shared memory scene created." << sendmsg;
00260 
00261     // the FreeVR display device is created in process-private memory
00262     display = new FreeVRDisplayDevice;
00263 
00264     // set up pointers for freevr_renderer, needs to be done before forking.
00265     set_freevr_pointers(scene, display);
00266 
00267     // set the function pointer for the per-screen renderers
00268     vrFunctionSetCallback(VRFUNC_ALL_DISPLAY, vrCallbackCreate(freevr_renderer, 1, &display));  
00269     vrStart();                         // fork off the rendering processes
00270     display->renderer_process = 0;     // this proc is the master process
00271     msgInfo << "FreeVR Initialized" << sendmsg;
00272   }
00273 #endif
00274 
00275   // make sure there is a scene object.  If none yet, create default one.
00276   if(!scene) {
00277     scene = new Scene;
00278   }
00279 
00280   // No real display, create a stub display that eats commands
00281   if(!display) {
00282     display = new DisplayDevice("Default Display");
00283     display->resize_window(dsiz[0], dsiz[1]);
00284   }
00285 
00286   // print any useful informational messages now that the display is setup
00287   if (display->get_num_processes() > 1) {
00288     msgInfo << "Started " << display->get_num_processes() 
00289             << " slave rendering processes." << sendmsg;
00290   }
00291 
00292   //
00293   // create other global objects for the program
00294   //
00295 
00296   rocker = new DisplayRocker(&(scene->root));
00297 
00298   // create commandQueue before all UIObjects!
00299   commandQueue = new CommandQueue(); 
00300 
00301   pluginMgr = new PluginMgr;
00302 
00303   atomSelParser = new SymbolTable;
00304   atomSelParser_init(atomSelParser);
00305 
00306   pickModeList = new PickModeList(this);
00307   pickList = new PickList(this);
00308 
00309   // create material list
00310   materialList = new MaterialList(&scene->root);
00311 
00312   // create other useful graphics objects
00313   axes = new Axes(display, &(scene->root));
00314   pickList->add_pickable(axes);
00315   
00316   fps = new FPS(display, &(scene->root));
00317   fps->off();
00318 
00319   // create the list of molecules (initially empty)
00320   moleculeList = new MoleculeList(this, scene);
00321 
00322   anim = new Animation(this);
00323   anim->On();
00324 
00325   // create the list of geometry monitors (initially empty)
00326   geometryList = new GeometryList(this, &(scene->root));
00327 
00328   menulist = new NameList<VMDMenu *>;
00329 
00330   uiText = new UIText(this); // text user interface
00331   uiText->On();
00332 
00333   mouse = new Mouse(this); // mouse user interface
00334   mouse->On();
00335 
00336   spaceball = new Spaceball(this); // Spaceball 6DOF input device
00337   spaceball->On();
00338 
00339 #ifdef WIN32
00340   win32joystick = new Win32Joystick(this); // Win32 Joystick devices
00341   win32joystick->On();
00342 #endif
00343 
00344 #ifdef VMDIMD
00345   imdMgr = new IMDMgr(this);
00346   imdMgr->On();
00347 #endif
00348 
00349   stage = new Stage(&(scene->root));
00350 
00351   vmdcollab = new VMDCollab(this);
00352   vmdcollab->On();
00353 
00354   // make the classes which can render scenes to different file formats
00355   fileRenderList = new FileRenderList(this);
00356 
00357   display->queue_events(); // begin accepting UI events in graphics window
00358 
00359   // Create the menus; XXX currently this must be done _before_ calling
00360   // uiText->read_init() because otherwise the new menus created by the 
00361   // plugins loaded by the iit script won't be added to the main menu.
00362   activate_menus();
00363   
00364   // XXX loading static plugins should be controlled by a startup option
00365   pluginMgr->load_static_plugins();
00366 
00367   // plugin_update must take place _after_ creation of uiText.
00368   plugin_update();
00369 
00370   VMDupdate(VMD_IGNORE_EVENTS); // flush cmd queue, prepare to enter event loop
00371 
00372   // Read the initialization code for the text interpreter.
00373   // We wait to do it now since that script might contain commands that use 
00374   // the event queue
00375   uiText->read_init();
00376 
00377   // If there's no text interpreter, show the main menu
00378 #ifndef VMDTCL
00379 #ifndef VMDPYTHON
00380   menu_show("main", 1);
00381 #endif
00382 #endif
00383   
00384   // successful initialization.  Turn off the exit flag return success
00385   exitFlag = FALSE;
00386   return TRUE;
00387 }
00388 
00389 int VMDApp::num_menus() { return menulist->num(); }
00390 
00391 int VMDApp::add_menu(VMDMenu *m) {
00392   if (menulist->typecode(m->get_name()) != -1) {
00393     msgErr << "Menu " << m->get_name() << " already exists." << sendmsg;
00394     return 0;  
00395   }
00396   menulist->add_name(m->get_name(), m);
00397   return 1;
00398 }
00399  
00400 int VMDApp::remove_menu(const char *name) {
00401   int id = menulist->typecode(name);
00402   if (id == -1) {
00403     msgErr << "Menu " << name << " does not exist." << sendmsg;
00404     return 0;  
00405   }
00406   NameList<VMDMenu *> *newmenulist = new NameList<VMDMenu *>;
00407   for (int i=0; i<menulist->num(); i++) {
00408     VMDMenu *menu = menulist->data(i);
00409     if (i == id) {
00410       delete menu;
00411     } else {
00412       newmenulist->add_name(menu->get_name(), menu);
00413     }
00414   }
00415   delete menulist;
00416   menulist = newmenulist;
00417   return 1;
00418 }
00419  
00420 void VMDApp::menu_add_extension(const char *shortname, const char *menu_path) {
00421   commandQueue->runcommand(new CmdMenuExtensionAdd(shortname,menu_path));
00422 }
00423 
00424 void VMDApp::menu_remove_extension(const char *shortname) {
00425   commandQueue->runcommand(new CmdMenuExtensionRemove(shortname));
00426 }
00427 
00428 const char *VMDApp::menu_name(int i) { return menulist->name(i); }
00429 
00430 int VMDApp::menu_status(const char *name) {
00431   int id = menulist->typecode(name);
00432   if (id == -1) return 0;
00433   return menulist->data(id)->active();
00434 }
00435 
00436 int VMDApp::menu_location(const char *name, int &x, int &y) {
00437   int id = menulist->typecode(name);
00438   if (id == -1) return 0;
00439   menulist->data(id)->where(x, y);
00440   return 1;
00441 }
00442 
00443 int VMDApp::menu_show(const char *name, int on) {
00444   int id = menulist->typecode(name);
00445   if (id == -1) return 0;
00446   VMDMenu *obj = menulist->data(name);
00447   if (on)
00448     obj->On();
00449   else
00450     obj->Off();
00451   commandQueue->runcommand(new CmdMenuShow(name, on));
00452   return 1;
00453 }
00454 
00455 int VMDApp::menu_move(const char *name, int x, int y) {
00456   int id = menulist->typecode(name);
00457   if (id == -1) return 0;
00458   menulist->data(id)->move(x, y);
00459   return 1;
00460 }
00461 
00462 
00463 int VMDApp::menu_select_mol(const char *name, int molno) {
00464   int id = menulist->typecode(name);
00465   if (id == -1) return 0;
00466   return menulist->data(id)->selectmol(molno);
00467 }
00468 
00469 
00470 // redraw the screen and update all things that need updating
00471 int VMDApp::VMDupdate(int check_for_events) {
00472   // clear background processing flag
00473   background_processing_clear();
00474 
00475   // see if there are any pending events; if so, get them
00476   if (check_for_events) {
00477     commandQueue->check_events();
00478 #ifdef VMDGUI
00479 #ifdef VMDFLTK
00480     // if we are using the FLTK library ...
00481     if(display->supports_gui()) {
00482 #if (defined(ARCH_MACOSX) || defined(ARCH_MACOSXX86) || defined(ARCH_MACOSXX86_64)) && defined(VMDTCL)
00483       // don't call wait(0) since this causes Tcl/Tk to mishandle events
00484       Fl::flush();
00485 #else
00486       Fl::wait(0);
00487 #endif
00488     }
00489 #endif
00490 #endif
00491   } 
00492   
00493   // check if the user has requested to exit the program.
00494   if (exitFlag) 
00495     return FALSE;
00496  
00497   commandQueue->execute_all(); // execute commands still in the queue
00498 
00499   int needupdate = 0;
00500 #if 1
00501   // Only prepare objects if display update is enabled
00502   // XXX avoid N^2 behavior when loading thousdands of molecules, 
00503   // don't prepare for drawing unless we have to.
00504   if (UpdateDisplay) {
00505     // If a resetview is pending, take care of it now before drawing
00506     if (ResetViewPending) 
00507       scene_resetview_newmoldata();
00508 
00509     needupdate = scene->prepare(); // prepare all objects for drawing
00510   } else {
00511     // XXX this has to be done currently to force trajectories to continue
00512     //     loading frames since they don't have their own UIObject yet.
00513     int molnum = moleculeList->num();
00514     int i;
00515     for (i=0; i<molnum; i++) {
00516       Molecule *mol = moleculeList->molecule(i);
00517       if (mol != NULL) {
00518         if (mol->get_new_frames()) {
00519           needupdate = 1; // need to update if any new frames were loaded
00520         }
00521       }
00522     }
00523   }
00524 #else
00525   // XXX this has to be done currently to force trajectories to continue
00526   //     loading frames since they don't have their own UIObject yet.
00527   needupdate = scene->prepare(); // prepare all objects for drawing
00528 #endif
00529 
00530   // turn off the spinning vmd when molecules are loaded
00531   if (vmdTitle && moleculeList->num() > 0) {
00532     delete vmdTitle;
00533     vmdTitle = NULL;
00534   }
00535   
00536   // Update the display (or sleep a tiny bit).
00537   if (UpdateDisplay && (needupdate || display->needRedraw())) {
00538     scene->draw(display);   // make the display redraw if necessary
00539     scene->draw_finished(); // perform any necessary post-drawing cleanup
00540   } else {
00541     // if not updating the display or doing background I/O, 
00542     // we sleep so we don't hog CPU.
00543     if (!needupdate && !background_processing())
00544       vmd_msleep(1); // sleep for 1 millisecond or more
00545   }
00546 
00547   // XXX A hack to decrease CPU utilization on machines that have
00548   //     problems keeping up with the 3-D draw rate at full speed.
00549   if (getenv("VMDMSECDELAYHACK") != NULL) {
00550     // Delay the whole program for a user-specified number of milliseconds.  
00551     vmd_msleep(atoi(getenv("VMDMSECDELAYHACK"))); 
00552   }
00553 
00554   return TRUE;
00555 }
00556 
00557 
00558 // exit the program normally; first delete all the necessary objects
00559 void VMDApp::VMDexit(const char *exitmsg, int exitcode, int pauseseconds) {
00560 #if defined(VMDTKCON)
00561   // switch to text mode and flush all pending messages to the screen.
00562   vmdcon_use_text();
00563   vmdcon_purge();
00564 #endif
00565 
00566   msgInfo << VERSION_MSG << sendmsg; 
00567   if(exitmsg && strlen(exitmsg)) {
00568     msgInfo << exitmsg << sendmsg;
00569   } else {
00570     msgInfo << "Exiting normally." << sendmsg;
00571   }
00572 
00573   vmd_sleep(pauseseconds);  // sleep for requested number of seconds
00574 
00575   // make the VMDupdate event loop return FALSE.
00576   exitFlag = 1;
00577 }
00578 
00579 VMDApp::~VMDApp() {
00580   int i;
00581 
00582   // delete all objects we created during initialization
00583   if (fileRenderList) delete fileRenderList;
00584   if (mouse)          delete mouse;
00585   if (spaceball)      delete spaceball;
00586 
00587 #ifdef WIN32
00588   if (win32joystick)  delete win32joystick;
00589 #endif
00590 
00591   if (uivr)           delete uivr;
00592   if (geometryList)   delete geometryList;
00593 
00594 #ifdef VMDIMD
00595   if (imdMgr)         delete imdMgr;
00596   imdMgr = NULL;      // prevent free mem reads at moleculeList deletion
00597 #endif
00598 
00599   if (vmdTitle)       delete vmdTitle;
00600   if (stage)          delete stage;
00601   if (axes)           delete axes;
00602   if (fps)            delete fps;
00603   if (pickModeList)   delete pickModeList;
00604   if (materialList)   delete materialList;
00605   if (pluginMgr)      delete pluginMgr;
00606   if (cuda)           delete cuda;
00607   delete vmdcollab;
00608 
00609   // delete all of the Forms;
00610   if (menulist) {
00611     for (i=0; i<menulist->num(); i++)
00612       delete menulist->data(i);
00613     delete menulist;
00614   }
00615 
00616 #ifdef VMDGUI
00617   // Close all GUI windows
00618 #ifdef VMDFLTK
00619   if (display->supports_gui()) {
00620     Fl::wait(0); // Give Fltk a chance to close the menu windows.  
00621   }
00622 #endif
00623 #endif
00624 
00625   // Tcl/Python interpreters can only be deleted after Tk forms are shutdown
00626   if (uiText)         delete uiText;
00627 
00628   // delete the list of user keys and descriptions 
00629   for (i=0; i<userKeys.num(); i++)
00630     delete [] userKeys.data(i);
00631 
00632   for (i=0; i<userKeyDesc.num(); i++)
00633     delete [] userKeyDesc.data(i);
00634 
00635   delete atomSelParser;
00636   delete anim;
00637 
00638   // delete commandQueue _after_ all UIObjects have been deleted; otherwise
00639   // they will try to unRegister with a deleted CommandQueue.
00640   delete commandQueue;
00641 
00642   // (these dependencies really suck) delete moleculelist after uiText
00643   // because text interfaces might use commands that require moleculeList to
00644   // be there.
00645   delete moleculeList;
00646 
00647   // picklist can't be deleted until the molecule is deleted, since
00648   // the DrawMolecule destructor needs it.
00649   delete pickList;
00650  
00651   delete display;
00652   delete scene;
00653 }
00654 
00655 unsigned long VMDApp::get_repserialnum(void) {
00656   // first serial number returned will be 1, never return 0.
00657   repserialnum++;
00658   return repserialnum;
00659 }
00660 
00661 unsigned long VMDApp::get_texserialnum(void) {
00662   // first serial number returned will be 1, never return 0.
00663   texserialnum++;
00664   return texserialnum;
00665 }
00666 
00667 void VMDApp::show_stride_message() {
00668   if (stride_firsttime) {
00669     stride_firsttime = 0;
00670     msgInfo <<
00671      "In any publication of scientific results based in part or\n"
00672      "completely on the use of the program STRIDE, please reference:\n"
00673      " Frishman,D & Argos,P. (1995) Knowledge-based secondary structure\n"
00674      " assignment. Proteins: structure, function and genetics, 23, 566-579." 
00675       << "\n" << sendmsg;
00676   }
00677 }
00678 
00679 // this is a nasty hack until we get around to returning values from scripts
00680 // properly.
00681 
00682 #ifdef VMDTK
00683 #include <tcl.h> 
00684 #endif
00685 
00686 char *VMDApp::vmd_choose_file(const char *title,
00687         const char *extension, 
00688         const char *extension_label, int do_save) {
00689   
00690  char *chooser = getenv("VMDFILECHOOSER");
00691  if (!chooser || !strupcmp(chooser, "TK")) {
00692     
00693 #ifdef VMDTK
00694   JString t = title;
00695   JString ext = extension;
00696   JString label = extension_label;
00697   char *cmd = new char[300 + t.length() +ext.length() + label.length()];
00698   // no default extension for for saves/loads , because otherwise it 
00699   // automatically adds the file extension whether you specify it or not, and 
00700   // when the extension is * it won't let you save/load a file without an 
00701   // extension!
00702   if (do_save) {
00703     sprintf(cmd, "tk_getSaveFile -title {%s} -filetypes {{{%s} {%s}} {{All files} {*}}}", (const char *)t, (const char *)extension_label, (const char *)extension);
00704   } else {
00705     sprintf(cmd, "tk_getOpenFile -title {%s} -filetypes {{{%s} {%s}} {{All files} {*}}}", (const char *)t, (const char *)extension_label, (const char *)extension);
00706   }
00707   Tcl_Interp *interp = uiText->get_tcl_interp();
00708   if (interp) {
00709     int retval = Tcl_Eval(interp, cmd);
00710     delete [] cmd;
00711     if (retval == TCL_OK) {
00712       const char *result = Tcl_GetStringResult(interp);
00713       if (result == NULL || strlen(result) == 0) {
00714         return NULL;
00715       } else {
00716         return stringdup(result);
00717       }
00718     }
00719   }
00720   // fall through to next level on failure
00721 #endif
00722 
00723  } 
00724 
00725 #ifdef VMDFLTK
00726   return stringdup(fl_file_chooser(title, extension, NULL));
00727 #endif
00728 
00729   char *result = new char[256];
00730   fgets(result, 256, stdin);
00731   return result;
00732 }
00733  
00734 // file renderer API
00735 int VMDApp::filerender_num() {
00736   return fileRenderList->num();
00737 }
00738 const char *VMDApp::filerender_name(int n) {
00739   return fileRenderList->name(n); 
00740 }
00741 int VMDApp::filerender_valid(const char *method) {
00742   return (fileRenderList->find(method) != NULL);
00743 }
00744 int VMDApp::filerender_has_antialiasing(const char *method) {
00745   return (fileRenderList->has_antialiasing(method));
00746 }
00747 int VMDApp::filerender_aalevel(const char *method, int aalevel) {
00748   return fileRenderList->aalevel(method, aalevel);
00749 }
00750 int VMDApp::filerender_imagesize(const char *method, int *w, int *h) {
00751   if (!w || !h) return FALSE;
00752   return fileRenderList->imagesize(method, w, h); 
00753 }
00754 int VMDApp::filerender_has_imagesize(const char *method) {
00755   return fileRenderList->has_imagesize(method);
00756 }
00757 int VMDApp::filerender_aspectratio(const char *method, float *aspect) {
00758   if (!aspect) return FALSE;
00759   return fileRenderList->aspectratio(method, aspect);
00760 }
00761 int VMDApp::filerender_numformats(const char *method) {
00762   return fileRenderList->numformats(method);
00763 }
00764 const char *VMDApp::filerender_get_format(const char *method, int i) {
00765   return fileRenderList->format(method, i);
00766 }
00767 const char *VMDApp::filerender_cur_format(const char *method) {
00768   return fileRenderList->format(method);
00769 }
00770 int VMDApp::filerender_set_format(const char *m, const char *fmt) {
00771   return fileRenderList->set_format(m, fmt);
00772 }
00773 
00774 int VMDApp::filerender_render(const char *m, const char *f, const char *e) {
00775   int retval = fileRenderList->render(f, m, e);
00776   if (retval) {
00777     commandQueue->runcommand(new CmdRender(f, m, e));
00778   }
00779   return retval;
00780 }
00781 const char *VMDApp::filerender_option(const char *m, const char *o) {
00782   FileRenderer *ren = fileRenderList->find(m);
00783   if (!ren) {
00784     return NULL;
00785   }
00786   if (o) {
00787     ren->set_exec_string(o);
00788     commandQueue->runcommand(new CmdRenderOption(m, o));
00789   }
00790   return ren->saved_exec_string();
00791 }
00792 
00793 // XXX The Scene doesn't return error codes, so I don't know if the commands
00794 // worked or not.  I do what error checking I can here and hope that it works.
00795 int VMDApp::scene_rotate_by(float angle, char ax, float incr) {
00796   if (ax < 'x' || ax > 'z') return FALSE;  // failed
00797   rocker->stop_rocking();
00798   if (incr) {
00799     int nsteps = (int)(fabs(angle / incr) + 0.5);
00800     incr = (float) (angle < 0.0f ? -fabs(incr) : fabs(incr));
00801     rocker->start_rocking(incr, ax, nsteps, TRUE);
00802     commandQueue->runcommand(new CmdRotate(angle, ax, CmdRotate::BY, incr)); 
00803    
00804   } else {
00805     scene->root.add_rot(angle, ax);
00806     commandQueue->runcommand(new CmdRotate(angle, ax, CmdRotate::BY));
00807   }
00808   return TRUE;
00809 }
00810 int VMDApp::scene_rotate_to(float angle, char ax) {
00811   if (ax < 'x' || ax > 'z') return FALSE;  // failed
00812   rocker->stop_rocking();
00813   scene->root.set_rot(angle, ax);
00814   commandQueue->runcommand(new CmdRotate(angle, ax, CmdRotate::TO));
00815   return TRUE;
00816 }
00817 int VMDApp::scene_rotate_by(const float *m) {
00818   Matrix4 mat(m);
00819   scene->root.add_rot(mat);
00820   commandQueue->runcommand(new CmdRotMat(mat, CmdRotMat::BY));
00821   return TRUE;
00822 }
00823 int VMDApp::scene_rotate_to(const float *m) {
00824   Matrix4 mat(m);
00825   scene->root.set_rot(mat);
00826   commandQueue->runcommand(new CmdRotMat(mat, CmdRotMat::TO));
00827   return TRUE;
00828 }
00829 int VMDApp::scene_translate_by(float x, float y, float z) {
00830   scene->root.add_glob_trans(x, y, z);
00831   commandQueue->runcommand(new CmdTranslate(x,y,z,CmdTranslate::BY));
00832   return TRUE;
00833 }
00834 int VMDApp::scene_translate_to(float x, float y, float z) {
00835   scene->root.set_glob_trans(x, y, z);
00836   commandQueue->runcommand(new CmdTranslate(x,y,z,CmdTranslate::TO));
00837   return TRUE;
00838 }
00839 int VMDApp::scene_scale_by(float s) {
00840   if (s <= 0) return FALSE; 
00841   scene->root.mult_scale(s);
00842   commandQueue->runcommand(new CmdScale(s, CmdScale::BY));
00843   return TRUE;
00844 }
00845 int VMDApp::scene_scale_to(float s) {
00846   if (s <= 0) return FALSE; 
00847   scene->root.set_scale(s);
00848   commandQueue->runcommand(new CmdScale(s, CmdScale::TO));
00849   return TRUE;
00850 }
00851 void VMDApp::scene_resetview_newmoldata() {
00852 #if 1
00853   // XXX avoid N^2 behavior when loading thousands of molecules
00854   // we should only be resetting the view when necessary
00855   if (UpdateDisplay) {
00856     int nodisrupt = 0;
00857 
00858     if (getenv("VMDNODISRUPTHACK"))
00859       nodisrupt=1;
00860 
00861     if (nodisrupt && (moleculeList->num() > 1)) {
00862       moleculeList->center_top_molecule(); // new/top mol inherits current view
00863     } else {
00864       scene_resetview(); // reset all molecules to the newly loaded structure
00865     }
00866     ResetViewPending = FALSE;
00867   } else {
00868     ResetViewPending = TRUE;
00869   }
00870 #else
00871   scene_resetview(); // reset all molecules to the newly loaded structure
00872 #endif
00873 }
00874 void VMDApp::scene_resetview() {
00875   scene->root.reset_transformation();
00876   // center the view based on the displayed representations
00877   moleculeList->center_from_top_molecule_reps();
00878   moleculeList->center_all_molecules();
00879   commandQueue->runcommand(new CmdResetView);
00880 }
00881 int VMDApp::scene_rock(char ax, float step, int nsteps) {
00882   if (ax < 'x' || ax > 'z') return FALSE;  // failed
00883   rocker->start_rocking(step, ax, nsteps);
00884   commandQueue->runcommand(new CmdRockOn(step, ax, nsteps));
00885   return TRUE;
00886 }
00887 int VMDApp::scene_rockoff() {
00888   rocker->stop_rocking();
00889   commandQueue->runcommand(new CmdRockOff);
00890   return TRUE;
00891 } 
00892 int VMDApp::scene_stoprotation() {
00893   rocker->stop_rocking();
00894   mouse->stop_rotation();
00895   return TRUE;
00896 }
00897 
00898 int VMDApp::animation_num_dirs() {
00899   return Animation::ANIM_TOTAL_DIRS;
00900 }
00901 
00902 const char *VMDApp::animation_dir_name(int i) {
00903   if (i < 0 || i >= Animation::ANIM_TOTAL_DIRS) return NULL;
00904   return animationDirName[i]; 
00905 }
00906    
00907 int VMDApp::animation_set_dir(int d) {
00908   Animation::AnimDir dir = (Animation::AnimDir)d;
00909   anim->anim_dir(dir);
00910   commandQueue->runcommand(new CmdAnimDir(dir));
00911   return 1;
00912 }
00913 
00914 int VMDApp::animation_num_styles() {
00915   return Animation::ANIM_TOTAL_STYLES;
00916 }
00917 
00918 const char *VMDApp::animation_style_name(int i) {
00919   if (i < 0 || i >= Animation::ANIM_TOTAL_STYLES) return NULL;
00920   return animationStyleName[i];
00921 }
00922 
00923 int VMDApp::animation_set_style(int s) {
00924   Animation::AnimStyle style = (Animation::AnimStyle)s;
00925   anim->anim_style(style);
00926   commandQueue->runcommand(new CmdAnimStyle(style));
00927   return 1;
00928 }
00929 
00930 int VMDApp::animation_set_frame(int frame) {
00931     anim->goto_frame(frame);
00932     anim->anim_dir(Animation::ANIM_PAUSE);
00933     commandQueue->runcommand(new CmdAnimJump(frame));
00934     return 1;
00935 }
00936 
00937 int VMDApp::animation_set_stride(int stride) {
00938     anim->skip(stride);
00939     commandQueue->runcommand(new CmdAnimSkip(stride));
00940     return 1;
00941 }
00942 
00943 int VMDApp::animation_set_speed(float speed) {
00944     anim->speed(speed);
00945     commandQueue->runcommand(new CmdAnimSpeed(speed));
00946     return 1;
00947 }
00948 
00949 const char *VMDApp::filerender_default_option(const char *m) {
00950   FileRenderer *ren = fileRenderList->find(m);
00951   if (!ren) {
00952     return NULL;
00953   }
00954   return ren->default_exec_string();
00955 }
00956 const char *VMDApp::filerender_default_filename(const char *m) {
00957   FileRenderer *ren = fileRenderList->find(m);
00958   if (!ren) {
00959     return NULL;
00960   }
00961   return ren->default_filename();
00962 }
00963  
00964 
00965 // plugin stuff 
00966 
00967 vmdplugin_t *VMDApp::get_plugin(const char *type, const char *name) {
00968   if (!pluginMgr) return NULL;
00969   if (!type || !name) return NULL;
00970   PluginList p;
00971   vmdplugin_t *plugin = NULL;
00972   if (pluginMgr->plugins(p, type, name)) {
00973     plugin = p[0];
00974 
00975     // loop over plugins and select the highest version number for a 
00976     // given plugin type/name combo.
00977     for (int i=1; i<p.num(); i++) {
00978       vmdplugin_t *curplugin = p[i];
00979       if (curplugin->majorv > plugin->majorv || 
00980           (curplugin->majorv == plugin->majorv && curplugin->minorv > plugin->minorv))
00981         plugin = curplugin;
00982     }
00983   } 
00984   return plugin;
00985 }
00986 
00987 int VMDApp::list_plugins(PluginList &p, const char *type) {
00988   if (!pluginMgr) return 0;
00989   return pluginMgr->plugins(p, type);
00990 }
00991 
00992 int VMDApp::plugin_dlopen(const char *filename) {
00993   if (!pluginMgr) {
00994     msgErr << "scan_plugins: no plugin manager available" << sendmsg;
00995     return -1;
00996   }
00997   if (!filename) return -1;
00998   return pluginMgr->load_sharedlibrary_plugins(filename);
00999 }
01000 
01001 void VMDApp::plugin_update() {
01002   commandQueue->runcommand(new CmdPluginUpdate);
01003 }
01004 
01005 void VMDApp::display_update_on(int ison) {
01006   UpdateDisplay = ison;
01007 }
01008 
01009 int VMDApp::display_update_status() {
01010   return (UpdateDisplay != 0);
01011 }
01012 
01013 void VMDApp::display_update() {
01014   int prevUpdateFlag = UpdateDisplay;
01015   UpdateDisplay = 1;
01016   VMDupdate(VMD_IGNORE_EVENTS);
01017   UpdateDisplay = prevUpdateFlag;
01018 }
01019 
01020 void VMDApp::display_update_ui() {
01021   VMDupdate(VMD_CHECK_EVENTS);
01022 }
01023 
01024 int VMDApp::num_color_categories() {
01025   return scene->num_categories();
01026 }
01027 const char *VMDApp::color_category(int n) {
01028   return scene->category_name(n);
01029 }
01030 
01031 int VMDApp::color_add_item(const char *cat, const char *name, const char *defcolor) {
01032   int init_color = scene->color_index(defcolor);
01033   if (init_color < 0) {
01034     msgErr << "Cannot add color item: invalid color name '" << defcolor << "'" << sendmsg;
01035     return FALSE;
01036   }
01037   int ind = scene->category_index(cat);
01038   if (ind < 0) {
01039     ind = scene->add_color_category(cat);
01040   }
01041   if (scene->add_color_item(ind, name, init_color) < 0) {
01042     return FALSE;
01043   }
01044   commandQueue->runcommand(new CmdColorItem(cat, name, defcolor));
01045   return TRUE;
01046 }
01047 
01048 int VMDApp::num_color_category_items(const char *category) {
01049   int colCatIndex = scene->category_index(category);
01050   if (colCatIndex < 0) return 0;
01051   return scene->num_category_items(colCatIndex);
01052 }
01053 const char *VMDApp::color_category_item(const char *category, int n) {
01054   int colCatIndex = scene->category_index(category);
01055   if (colCatIndex < 0) return 0;
01056   return scene->category_item_name(colCatIndex, n); // XXX check valid n
01057 }
01058 int VMDApp::num_colors() {
01059   return MAXCOLORS;
01060 }
01061 int VMDApp::num_regular_colors() {
01062   return REGCLRS;
01063 }
01064 const char *VMDApp::color_name(int n) {
01065   return scene->color_name(n);
01066 }
01067 int VMDApp::color_index(const char *color) {
01068   if (!color) return -1;
01069   // If it's a number in the valid range, return the number; otherwise return
01070   // -1.
01071   int i;
01072   if (sscanf(color, "%d", &i)) {
01073     if (i >= 0 && i < MAXCOLORS)
01074       return i;
01075     else
01076       return -1;
01077   }
01078   // look up the color by name.
01079   return scene->color_index(color);
01080 } 
01081 int VMDApp::color_value(const char *colorname, float *r, float *g, float *b) {
01082   int colIndex = color_index(colorname);
01083   if (colIndex < 0) return 0;
01084   const float *col = scene->color_value(colIndex);
01085   *r = col[0];
01086   *g = col[1];
01087   *b = col[2];
01088   return 1;
01089 }
01090 int VMDApp::color_default_value(const char *colorname, float *r, float *g, float *b) {
01091   int colIndex = color_index(colorname);
01092   if (colIndex < 0) return 0;
01093   const float *col = scene->color_default_value(colIndex);
01094   *r = col[0];
01095   *g = col[1];
01096   *b = col[2];
01097   return 1;
01098 }
01099 const char *VMDApp::color_mapping(const char *category, const char *item) {
01100   
01101   int colCatIndex = scene->category_index(category);
01102   if (colCatIndex < 0) return 0;
01103 
01104   int colNameIndex = scene->category_item_index(colCatIndex, item);
01105   if (colNameIndex < 0) return 0;
01106   
01107   int ind = scene->category_item_value(colCatIndex, colNameIndex);
01108   return scene->color_name(ind);
01109 }
01110 
01111 const char *VMDApp::color_get_restype(const char *resname) {
01112   int id = moleculeList->resTypes.typecode(resname);
01113   if (id < 0) return NULL;
01114   return moleculeList->resTypes.data(id);
01115 }
01116 
01117 int VMDApp::color_set_restype(const char *resname, const char *restype) {
01118   int cat = moleculeList->colorCatIndex[MLCAT_RESTYPES];
01119   int ind = scene->category_item_index(cat, restype);
01120   if (ind < 0) return FALSE;  // nonexistent restype category
01121 
01122   // Use the string stored in Scene rather than the one passed to this
01123   // function, since then we don't have to worry about copying it and
01124   // freeing it later.
01125   const char *stable_restype_name = scene->category_item_name(cat, ind);
01126 
01127   // if the resname doesn't have an entry yet, create one.
01128   int resname_id = moleculeList->resTypes.add_name(resname, restype);
01129   moleculeList->resTypes.set_data(resname_id, stable_restype_name);
01130   scene->root.color_changed(cat);
01131   return TRUE;
01132 }
01133 
01134 int VMDApp::colorscale_info(float *mid, float *min, float *max) {
01135   scene->colorscale_value(mid, min, max);
01136   return 1;
01137 }
01138 int VMDApp::num_colorscale_methods() {
01139   return scene->num_colorscale_methods();
01140 }
01141 int VMDApp::colorscale_method_current() {
01142   return scene->colorscale_method();
01143 }
01144 const char *VMDApp::colorscale_method_name(int n) {
01145   if (n < 0 || n >= scene->num_colorscale_methods()) return NULL;
01146   return scene->colorscale_method_name(n);
01147 }
01148 int VMDApp::colorscale_method_index(const char *method) {
01149   for (int i=0; i<scene->num_colorscale_methods(); i++) {
01150     if (!strupncmp(method, scene->colorscale_method_name(i),CMDLEN)) {
01151       return i;
01152     }
01153   }
01154   return -1;
01155 }  
01156 
01157 int VMDApp::get_colorscale_colors(int whichScale, 
01158       float min[3], float mid[3], float max[3]) {
01159   return scene->get_colorscale_colors(whichScale, min, mid, max);
01160 }
01161 
01162 int VMDApp::set_colorscale_colors(int whichScale, 
01163       const float min[3], const float mid[3], const float max[3]) {
01164   if (scene->set_colorscale_colors(whichScale, min, mid, max)) {
01165     commandQueue->runcommand(new CmdColorScaleColors(
01166           scene->colorscale_method_name(whichScale), mid, min, max));
01167     return TRUE;
01168   }
01169   return FALSE;
01170 }
01171 
01172 int VMDApp::color_changename(const char *category, const char *colorname, 
01173                      const char *color) {
01174 
01175   if (!category || !colorname || !color) return 0;
01176 
01177   int colCatIndex = scene->category_index(category);
01178   if (colCatIndex < 0) return 0;
01179   
01180   int colNameIndex = scene->category_item_index(colCatIndex, colorname);
01181   if (colNameIndex < 0) return 0;
01182 
01183   int newIndex = color_index(color);
01184   if (newIndex < 0) return 0;
01185  
01186   // all systems go...
01187   scene->set_category_item(colCatIndex, colNameIndex, newIndex);
01188   
01189   // tell the rest of the world
01190   commandQueue->runcommand(new CmdColorName(category, colorname, color));
01191   return 1;
01192 }
01193 
01194 int VMDApp::color_get_from_name(const char *category, const char *colorname, 
01195                      const char **color) {
01196 
01197   if (!category || !colorname) return 0;
01198 
01199   int colCatIndex = scene->category_index(category);
01200   if (colCatIndex < 0) return 0;
01201   
01202   int colNameIndex = scene->category_item_index(colCatIndex, colorname);
01203   if (colNameIndex < 0) return 0;
01204  
01205   // all systems go...
01206   int colIndex = scene->get_category_item(colCatIndex, colNameIndex);
01207   if (colIndex < 0) return 0;
01208   
01209   *color = color_name(colIndex);
01210       
01211   return 1;
01212 }
01213 
01214 
01215 int VMDApp::color_changevalue(const char *color, float r, float g, float b) {
01216   int ind = color_index(color);
01217   if (ind < 0) return 0;
01218   float rgb[3] = {r, g, b};
01219   scene->set_color_value(ind, rgb);
01220   commandQueue->runcommand(new CmdColorChange(color, r, g, b));
01221   return 1;
01222 }
01223   
01224 int VMDApp::colorscale_setvalues(float mid, float min, float max) {
01225   scene->set_colorscale_value(min, mid, max);
01226   commandQueue->runcommand(new CmdColorScaleSettings(mid, min, max));
01227   return 1;
01228 }
01229 
01230 int VMDApp::colorscale_setmethod(int method) {
01231   if (method < 0 || method >= scene->num_colorscale_methods()) return 0;
01232   scene->set_colorscale_method(method);
01233   commandQueue->runcommand(new CmdColorScaleMethod(
01234         scene->colorscale_method_name(method)));
01235   return 1;
01236 }
01237   
01238   
01239 int VMDApp::logfile_read(const char *path) {
01240   uiText->read_from_file(path);
01241   return 1;
01242 }
01243 
01244 int VMDApp::save_state() {
01245   char *file = vmd_choose_file(
01246     "Enter filename to save current VMD state:",  // Title
01247     "*.vmd",                                      // extension
01248     "VMD files",                                  // label
01249     1                                             // do_save
01250   );
01251   if (!file)
01252     return 1;
01253   int retval = uiText->save_state(file);
01254   delete [] file;
01255   return retval;
01256 }
01257  
01258 int VMDApp::num_molecules() {
01259   return moleculeList->num();
01260 }
01261 
01262 int VMDApp::molecule_new(const char *name) {
01263   Molecule *newmol = new Molecule(name, this, &(scene->root));
01264   moleculeList->add_molecule(newmol);
01265   int molid = newmol->id();
01266   commandQueue->runcommand(new