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

PickList.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2019 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.49 $       $Date: 2019/01/17 21:21:01 $
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 
00090   // check if we have a valid Pickable index
00091   if (ind >= 0) {
00092     // cancel any active picking state if we're deleting the
00093     // pickable that's currently active
00094     if (picking() && (currPickable == p)) {
00095       // reset the status variables to null out the active pick
00096       currPickDim = currPickTag = (-1);
00097       currPickable = NULL;
00098     }
00099 
00100     pickableObjs.remove(ind);
00101   }
00102 }
00103 
00105 // routines to handle starting a pick, moving during a pick,
00106 // ending of a pick
00108 void PickList::pick_callback_clear(char *callback_client){
00109   app->commandQueue->runcommand(new PickAtomCallbackEvent(-1,-1,callback_client));
00110 }
00111 
00112 Pickable *PickList::pick_check(int dim, const float
00113                                *pos, int &tag, int *cell, float window_size,
00114                                char *callback_client){
00115   
00116 //  printf("doing a pickcheck\n");
00117   if(pos==NULL) {
00118     msgErr << "pick_check called with NULL pos" << sendmsg;
00119     return NULL;
00120   }
00121 
00122   Pickable *currObj, *retobj = NULL;
00123   float eyedist = (-1.0);
00124   int currtag, rettag = (-1);
00125   int i, np = num_pickable();
00126 
00127   if(!np)
00128     return NULL;
00129 
00130   // use left eye settings for picking; if not stereo, will just be normal
00131   app->display->left();
00132       
00133   // for all Pickable objects, check to see if they have a picked object
00134   for(i=0; i < np; i++) {
00135     currObj = pickable(i);
00136     if(currObj->pickable_on()) {
00137       currtag = app->display->pick(dim, pos, currObj->pick_cmd_list(), eyedist,
00138                         cell, window_size);
00139       if(currtag != -1) {
00140         // a new object closer to the eye position was found.  Save it.
00141         retobj = currObj;
00142         rettag = currtag;
00143       }
00144     }
00145   }
00146   
00147   // clean up after setting stereo mode, but do not do buffer swap
00148   app->display->update(FALSE);
00149       
00150   // for now, only check left eye.  Can later see if checking right eye helps
00151   // as well.
00152   
00153   // finished; report results
00154   if(callback_client != NULL) {
00155     if(retobj) {
00156       int mol,atom;
00157       Molecule *m = app->moleculeList->check_pickable(retobj);
00158       if (m) {
00159         mol = m->id();
00160         atom = rettag;
00161         app->commandQueue->runcommand(new PickAtomCallbackEvent(mol,atom,callback_client));
00162       }
00163     }
00164     else { // we didn't find anyhing
00165       app->commandQueue->runcommand(new PickAtomCallbackEvent(-1,-1,callback_client));
00166     }
00167   }
00168 
00169   if(retobj) {
00170     tag = rettag;
00171     // send a normal pick event if this is not a check for callbacks
00172     if(callback_client==NULL) {
00173       PickEvent *event = new PickEvent(retobj, tag);
00174       print_atom_info(app, event);
00175       app->commandQueue->runcommand(event);
00176     }
00177   }
00178   return retobj;
00179 }
00180 
00181 
00182 // called when a pick is begun: display device, button, mode, dim, pos
00183 // returns 'tag' of closest object, or (-1) if nothing is picked.
00184 // When a pick is started, the internal flags for this object are set,
00185 // and no other item can be picked until pick_end is called.
00186 // For 2D version: x & y are 0 ... 1, represent 'relative, scaled' coords.
00187 // For 3D version: x,y,z are transformed position of pointer
00188 int PickList::pick_start(int b, int dim,
00189                          const float *pos) {
00190   Pickable *closePickable;
00191   int tag = (-1); 
00192   int cell[3];
00193   float window_size = 0.01f;
00194   if (dim == 3) window_size *= 5;
00195 
00196   // make sure we're not already picking something
00197   if(picking())
00198     return (-1);
00199 
00200   cell[0] = cell[1] = cell[2] = 0;
00201 
00202   // check if something has been actually picked
00203   if((closePickable = pick_check(dim, pos, tag, cell, window_size)) != NULL) {
00204     // set all variables to show that we're picking something
00205     currPickDim = dim;
00206     currPickTag = tag;
00207     currPickable = closePickable;
00208     
00209     // use left eye settings for picking; if not stereo, will just be normal
00210     app->display->left();
00211   
00212 //    printf("pick start got tag %d\n", tag);
00213     PickMode *pm = app->pickModeList->current_pick_mode(); 
00214     if (pm != NULL)
00215       closePickable->pick_start(pm, app->display, b, currPickTag, cell, dim, pos);
00216 
00217     // clean up after setting stereo mode, but do not do buffer swap
00218     app->display->update(FALSE);   
00219   }
00220   return tag;
00221 }
00222 
00223 
00224 // called when a pick moves: display device, button, mode, dim, pos
00225 // Returns TRUE if a pick is currently active, FALSE otherwise.
00226 // For 2D version: x & y are 0 ... 1, represent 'relative, scaled' coords.
00227 // For 3D version: x,y,z are transformed position of pointer
00228 int PickList::pick_move(const float *pos) {
00229 
00230   // make sure we're already picking something
00231   if(!picking() )
00232     return FALSE;
00233 
00234   // use left eye settings for picking; if not stereo, will just be normal
00235   app->display->left();
00236   
00237   currPickable->pick_move(app->pickModeList->current_pick_mode(), app->display, currPickTag,
00238                           currPickDim, pos);
00239   // clean up after setting stereo mode, but do not do buffer swap
00240   app->display->update(FALSE);
00241       
00242   return TRUE;
00243 }
00244 
00245 
00246 // called when a pick ends: display device, button, mode, dim, pos
00247 // Returns TRUE if a pick is currently active, FALSE otherwise.
00248 // For 2D version: x & y are 0 ... 1, represent 'relative, scaled' coords.
00249 // For 3D version: x,y,z are transformed position of pointer
00250 int PickList::pick_end() {
00251   // make sure we're already picking something
00252   if(!picking() )
00253     return FALSE;
00254 
00255   // use left eye settings for picking; if not stereo, will just be normal
00256   app->display->left();
00257 
00258   currPickable->pick_end(app->pickModeList->current_pick_mode(), app->display);
00259  
00260   // clean up after setting stereo mode, but do not do buffer swap
00261   app->display->update(FALSE);
00262       
00263   // reset all current status variables, and return
00264   currPickDim = currPickTag = (-1);
00265   currPickable = NULL;
00266   
00267   return TRUE;
00268 }
00269 
00270 
00271 // print atom info to the console
00272 static void print_atom_info(VMDApp *app, PickEvent *event) {
00273   Molecule *mol = app->moleculeList->check_pickable(event->pickable);
00274   if (!mol) return;
00275   int atomindex = event->tag;
00276   if (atomindex >= mol->nAtoms) return;
00277 
00278   MolAtom *a = mol->atom(atomindex);
00279 
00280   msgInfo << "picked atom: \n------------\n"
00281           << "molecule id: " << mol->id()
00282           << "\ntrajectory frame: " << app->molecule_frame(mol->id())
00283           << "\nname: " << mol->atomNames.name(a->nameindex)
00284           << "\ntype: " << mol->atomTypes.name(a->typeindex)
00285           << "\nindex: " << atomindex
00286           << "\nresidue: " << a->uniq_resid
00287           << "\nresname: " << mol->resNames.name(a->resnameindex)
00288           << "\nresid: " << a->resid
00289           << "\nchain: " << mol->chainNames.name(a->chainindex)
00290           << "\nsegname: " << mol->segNames.name(a->segnameindex)
00291           << "\nx: " << mol->current()->pos[3L*atomindex]
00292           << "\ny: " << mol->current()->pos[3L*atomindex+1]
00293           << "\nz: " << mol->current()->pos[3L*atomindex+2] << "\n"
00294           << sendmsg;
00295 }

Generated on Wed Apr 24 02:43:11 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002