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

PickList.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 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: PickList.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.42 $       $Date: 2008/05/16 18:47:40 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *
00019  * The PickList object, which maintains a list of Pickable objects and
00020  * has the ability to find and deal with items picked by a pointer device.
00021  *
00022  * Only one picking operation may be in effect at a time.  A picking operation
00023  * consists of these steps:
00024  *      1. A pick is started by a pointer, by queueing a CmdPickStart command.
00025  *      2. pick_start is called, which determines if something is selected.
00026  *              If so, returns tag of item, and sets internal flags to
00027  *              indicate what is being picked, and how.
00028  *              The current PickMode and relevant picking parameters are
00029  *              passed to the picked object.
00030  *      3. pick_move is called whenever the pointer moves, by queueing the
00031  *              CmdPickMove command.  This continues until the picking is
00032  *              finished.  
00033  *      4. pick_end is called by queueing CmdPickEnd; this behaves similarly
00034  *              the pick_move.  When finished, the internal flags are reset
00035  *              to indicate that picking is finished, and a new one can begin.
00036  * NOTE: multiple concurrent picks could be implemented later by providing
00037  * an object which maintains separate sets of the internal flags and variables,
00038  * for each picking device.  This would also require another argument to the
00039  * pick_* routines, to indicate which picking device is being used.  Also,
00040  * PickMode and Pickable object involved in another picking operation would
00041  * have to be excluded from being informed of other picking operations.
00042  ***************************************************************************/
00043 
00044 #include "PickList.h"
00045 #include "DisplayDevice.h"
00046 #include "Pickable.h"
00047 #include "PickModeList.h"
00048 #include "PickMode.h"
00049 #include "ResizeArray.h"
00050 #include "NameList.h"
00051 #include "Inform.h"
00052 #include "VMDApp.h"
00053 #include "CommandQueue.h"
00054 #include "TextEvent.h"
00055 #include "Molecule.h"
00056 #include "MoleculeList.h"
00057 
00058 // forward declaration
00059 static void print_atom_info(VMDApp *app, PickEvent *event);
00060 
00062 PickList::PickList(VMDApp *vmdapp) : pickableObjs(32), app(vmdapp) {
00063 
00064   // reset all current picking flags
00065   currPickDim = currPickTag = (-1);
00066   currPickable = NULL;
00067   app->pickModeList->set_pick_mode(2);
00068   total_callback_clients = 0; // no clients yet!
00069 }
00070 
00072 
00073 // adds a Pickable to the current list, if it is not already in the list
00074 void PickList::add_pickable(Pickable *p) {
00075 
00076   // find if this is in the list already.
00077   int indx = pickableObjs.find(p);
00078   
00079   // if it is not, append it
00080   if(indx < 0) {
00081     pickableObjs.append(p);
00082   }
00083 }
00084 
00085 
00086 // remove the given pickable from the list; return TRUE if it was in the list
00087 void PickList::remove_pickable(Pickable *p) {
00088   int ind = pickableObjs.find(p);
00089   if (ind >= 0)
00090     pickableObjs.remove(ind);
00091 }
00092 
00094 // routines to handle starting a pick, moving during a pick,
00095 // ending of a pick
00097 void PickList::pick_callback_clear(char *callback_client){
00098   app->commandQueue->runcommand(new PickAtomCallbackEvent(-1,-1,callback_client));
00099 }
00100 
00101 Pickable *PickList::pick_check(int dim, const float
00102                                *pos, int &tag, int *cell, float window_size,
00103                                char *callback_client){
00104   
00105 //  printf("doing a pickcheck\n");
00106   if(pos==NULL) {
00107     msgErr << "pick_check called with NULL pos" << sendmsg;
00108     return NULL;
00109   }
00110 
00111   Pickable *currObj, *retobj = NULL;
00112   float eyedist = (-1.0);
00113   int currtag, rettag = (-1);
00114   int i, np = num_pickable();
00115 
00116   if(!np)
00117     return NULL;
00118 
00119   // use left eye settings for picking; if not stereo, will just be normal
00120   app->display->left();
00121       
00122   // for all Pickable objects, check to see if they have a picked object
00123   for(i=0; i < np; i++) {
00124     currObj = pickable(i);
00125     if(currObj->pickable_on()) {
00126       currtag = app->display->pick(dim, pos, currObj->pick_cmd_list(), eyedist,
00127                         cell, window_size);
00128       if(currtag != -1) {
00129         // a new object closer to the eye position was found.  Save it.
00130         retobj = currObj;
00131         rettag = currtag;
00132       }
00133     }
00134   }
00135   
00136   // clean up after setting stereo mode, but do not do buffer swap
00137   app->display->update(FALSE);
00138       
00139   // for now, only check left eye.  Can later see if checking right eye helps
00140   // as well.
00141   
00142   // finished; report results
00143   if(callback_client != NULL) {
00144     if(retobj) {
00145       int mol,atom;
00146       Molecule *m = app->moleculeList->check_pickable(retobj);
00147       if (m) {
00148         mol = m->id();
00149         atom = rettag;
00150         app->commandQueue->runcommand(new PickAtomCallbackEvent(mol,atom,callback_client));
00151       }
00152     }
00153     else { // we didn't find anyhing
00154       app->commandQueue->runcommand(new PickAtomCallbackEvent(-1,-1,callback_client));
00155     }
00156   }
00157 
00158   if(retobj) {
00159     tag = rettag;
00160     // send a normal pick event if this is not a check for callbacks
00161     if(callback_client==NULL) {
00162       PickEvent *event = new PickEvent(retobj, tag);
00163       print_atom_info(app, event);
00164       app->commandQueue->runcommand(event);
00165     }
00166   }
00167   return retobj;
00168 }
00169 
00170 
00171 // called when a pick is begun: display device, button, mode, dim, pos
00172 // returns 'tag' of closest object, or (-1) if nothing is picked.
00173 // When a pick is started, the internal flags for this object are set,
00174 // and no other item can be picked until pick_end is called.
00175 // For 2D version: x & y are 0 ... 1, represent 'relative, scaled' coords.
00176 // For 3D version: x,y,z are transformed position of pointer
00177 int PickList::pick_start(int b, int dim,
00178                          const float *pos) {
00179   Pickable *closePickable;
00180   int tag = (-1); 
00181   int cell[3];
00182   float window_size = 0.01f;
00183   if (dim == 3) window_size *= 5;
00184 
00185   // make sure we're not already picking something
00186   if(picking())
00187     return (-1);
00188 
00189   cell[0] = cell[1] = cell[2] = 0;
00190 
00191   // check if something has been actually picked
00192   if((closePickable = pick_check(dim, pos, tag, cell, window_size)) != NULL) {
00193     // set all variables to show that we're picking something
00194     currPickDim = dim;
00195     currPickTag = tag;
00196     currPickable = closePickable;
00197     
00198     // use left eye settings for picking; if not stereo, will just be normal
00199     app->display->left();
00200   
00201 //    printf("pick start got tag %d\n", tag);
00202     PickMode *pm = app->pickModeList->current_pick_mode(); 
00203     if (pm != NULL)
00204       closePickable->pick_start(pm, app->display, b, currPickTag, cell, dim, pos);
00205 
00206     // clean up after setting stereo mode, but do not do buffer swap
00207     app->display->update(FALSE);   
00208   }
00209   return tag;
00210 }
00211 
00212 
00213 // called when a pick moves: display device, button, mode, dim, pos
00214 // Returns TRUE if a pick is currently active, FALSE otherwise.
00215 // For 2D version: x & y are 0 ... 1, represent 'relative, scaled' coords.
00216 // For 3D version: x,y,z are transformed position of pointer
00217 int PickList::pick_move(const float *pos) {
00218 
00219   // make sure we're already picking something
00220   if(!picking() )
00221     return FALSE;
00222 
00223   // use left eye settings for picking; if not stereo, will just be normal
00224   app->display->left();
00225   
00226   currPickable->pick_move(app->pickModeList->current_pick_mode(), app->display, currPickTag,
00227                           currPickDim, pos);
00228   // clean up after setting stereo mode, but do not do buffer swap
00229   app->display->update(FALSE);
00230       
00231   return TRUE;
00232 }
00233 
00234 
00235 // called when a pick ends: display device, button, mode, dim, pos
00236 // Returns TRUE if a pick is currently active, FALSE otherwise.
00237 // For 2D version: x & y are 0 ... 1, represent 'relative, scaled' coords.
00238 // For 3D version: x,y,z are transformed position of pointer
00239 int PickList::pick_end() {
00240   // make sure we're already picking something
00241   if(!picking() )
00242     return FALSE;
00243 
00244   // use left eye settings for picking; if not stereo, will just be normal
00245   app->display->left();
00246      
00247   currPickable->pick_end(app->pickModeList->current_pick_mode(), app->display);
00248  
00249   // clean up after setting stereo mode, but do not do buffer swap
00250   app->display->update(FALSE);
00251       
00252   // reset all current status variables, and return
00253   currPickDim = currPickTag = (-1);
00254   currPickable = NULL;
00255   
00256   return TRUE;
00257 }
00258 
00259 
00260 // print atom info to the console
00261 static void print_atom_info(VMDApp *app, PickEvent *event) {
00262   Molecule *mol = app->moleculeList->check_pickable(event->pickable);
00263   if (!mol) return;
00264   int atomindex = event->tag;
00265   if (atomindex >= mol->nAtoms) return;
00266 
00267   MolAtom *a = mol->atom(atomindex);
00268 
00269   msgInfo << "picked atom: \n------------\n"
00270           << "molecule id: " << mol->id()
00271           << "\ntrajectory frame: " << app->molecule_frame(mol->id())
00272           << "\nname: " << mol->atomNames.name(a->nameindex)
00273           << "\ntype: " << mol->atomTypes.name(a->typeindex)
00274           << "\nindex: " << atomindex
00275           << "\nresidue: " << a->uniq_resid
00276           << "\nresname: " << mol->resNames.name(a->resnameindex)
00277           << "\nresid: " << a->resid
00278           << "\nchain: " << mol->chainNames.name(a->chainindex)
00279           << "\nsegname: " << mol->segNames.name(a->segnameindex)
00280           << "\nx: " << mol->current()->pos[3*atomindex]
00281           << "\ny: " << mol->current()->pos[3*atomindex+1]
00282           << "\nz: " << mol->current()->pos[3*atomindex+2] << "\n"
00283           << sendmsg;
00284 }

Generated on Sat Sep 6 01:27:05 2008 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002