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 Tue Nov 18 02:47:54 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

AltStyle によって変換されたページ (->オリジナル) /