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

Mouse.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: Mouse.C,v $
00013 * $Author: johns $ $Locker: $ $State: Exp $
00014 * $Revision: 1.150 $ $Date: 2019年01月17日 21:21:00 $
00015 *
00016 ***************************************************************************
00017 * DESCRIPTION:
00018 *
00019 * The Mouse UI object, which maintains the current state of the 
00020 * mouse, including what it is currently used for, and how much it has moved
00021 * from one measurement to the next. This also deals with any pop-up or
00022 * pull-down menus available by using the mouse, as well as picking objects.
00023 *
00024 * A three-button mouse is assumed here, with the following usage:
00025 * 1) Buttons 1 and 2 : manipulation and picking.
00026 * 2) Button 3 (right): pop-up menu
00027 *
00028 * This is the general base class definition; specific versions for each
00029 * windowing/graphics system must be supplied.
00030 *
00031 ***************************************************************************/
00032 
00033 #include "Mouse.h"
00034 #include "DisplayDevice.h"
00035 #include "TextEvent.h"
00036 #include "CommandQueue.h"
00037 #include "Inform.h"
00038 #include "PickList.h"
00039 #include "VMDApp.h"
00040 
00041 #include "VideoStream.h" // for video streaming event generation
00042 
00043 // constructor
00044 Mouse::Mouse(VMDApp *vmdapp) : UIObject(vmdapp) {
00045 
00046 #ifndef VMDGUI
00047 // tell the graphics display to queue events... 
00048 // only if there is no GUI available
00049 app->display->queue_events(); // enable GUI events from graphics window
00050 #endif
00051 
00052 // Initial detail level state would be set here
00053 
00054 // set the default translation and rotation increments
00055 rocking_enabled = 1;
00056 transInc = 0.002f;
00057 rotInc = 1.0f/15.0f;
00058 scaleInc = 0.0002f;
00059 RotVelScale = 0.4f;
00060 currX = currY = oldX = oldY = 0;
00061 stop_rotation();
00062 moveObj = 0;
00063 moveMode = ROTATION;
00064 pickInProgress = B_NONE;
00065 buttonDown = B_NONE;
00066 
00067 #ifdef VMDVRJUGGLER
00068 // needed for VR Juggler patches
00069 if (app && app->display)
00070 app->display->set_cursor(DisplayDevice::NORMAL_CURSOR); // set normal cursor
00071 #else
00072 app->display->set_cursor(DisplayDevice::NORMAL_CURSOR); // set normal cursor
00073 #endif
00074 
00075 reset();
00076 }
00077 
00078 
00079 // destructor
00080 Mouse::~Mouse(void) {
00081 move_mode(ROTATION);
00082 }
00083 
00084 const char* Mouse::get_mode_str(MoveMode mm) {
00085 const char* modestr;
00086 
00087 switch (mm) {
00088 default:
00089 case ROTATION: 
00090 modestr = "rotate"; break; // default mouse cursor
00091 case TRANSLATION: modestr = "translate"; break;
00092 case SCALING: modestr = "scale"; break;
00093 case LIGHT: modestr = "light"; break;
00094 case USERPOINT: modestr = "userpoint"; break;
00095 // All the picking modes follow:
00096 case PICK: modestr = "pick"; break;
00097 case QUERY: modestr = "query"; break;
00098 case CENTER: modestr = "center"; break;
00099 case LABELATOM: modestr = "labelatom"; break;
00100 case LABELBOND: modestr = "labelbond"; break;
00101 case LABELANGLE: modestr = "labelangle"; break;
00102 case LABELDIHEDRAL: modestr = "labeldihedral"; break;
00103 case MOVEATOM: modestr = "moveatom"; break;
00104 case MOVERES: modestr = "moveres"; break;
00105 case MOVEFRAG: modestr = "movefrag"; break;
00106 case MOVEMOL: modestr = "movemol"; break;
00107 case FORCEATOM: modestr = "forceatom"; break;
00108 case FORCERES: modestr = "forceres"; break;
00109 case FORCEFRAG: modestr = "forcefrag"; break;
00110 case MOVEREP: modestr = "moverep"; break;
00111 case ADDBOND: modestr = "addbond"; break;
00112 }
00113 
00114 return modestr;
00115 }
00116 
00118 
00119 // stop rotation of object
00120 void Mouse::stop_rotation(void) {
00121 xRotVel = yRotVel = zRotVel = 0.0; // null out rotation rate
00122 }
00123 
00124 // set the mouse move mode to the given state; return success
00125 int Mouse::move_mode(MoveMode mm, int mobj) {
00126 const char *modestr;
00127 
00128 // we cannot change the mouse mode if an active pick is going on
00129 if (pickInProgress)
00130 return FALSE; // report failure
00131 
00132 // stop rotating no matter what mode we've changed to
00133 stop_rotation();
00134 
00135 // disable light highlight if previous mode was light mode
00136 if (moveMode == LIGHT) {
00137 app->light_highlight(moveObj, FALSE); // turn off old light
00138 }
00139 
00140 // special actions based on the new mode
00141 if (mm == LIGHT) {
00142 moveObj = mobj;
00143 app->light_highlight(moveObj, TRUE); // turn on new light number mobj
00144 }
00145 
00146 // change the mouse mode now
00147 moveMode = mm; 
00148 
00149 // Tell the text interpreter the new mouse mode
00150 // Set the variable "vmd_mouse_mode" to the correct string
00151 // and set the variable "vmd_mouse_submode" to the mobj number
00152 modestr = get_mode_str(moveMode);
00153 runcommand(new MouseModeEvent(modestr, mobj)); // and set the variables
00154 
00155 // set the cursor style to match the mouse mode
00156 switch (moveMode) {
00157 case ROTATION:
00158 case LIGHT:
00159 case USERPOINT:
00160 app->display->set_cursor(DisplayDevice::NORMAL_CURSOR);
00161 break;
00162 
00163 case TRANSLATION:
00164 app->display->set_cursor(DisplayDevice::TRANS_CURSOR);
00165 break;
00166 
00167 case SCALING:
00168 app->display->set_cursor(DisplayDevice::SCALE_CURSOR);
00169 break;
00170 
00171 // all the remaining are picking modes
00172 default:
00173 app->display->set_cursor(DisplayDevice::PICK_CURSOR);
00174 break;
00175 }
00176 
00177 return TRUE; // report success
00178 }
00179 
00180 
00181 
00182 // do action when the mouse is moved
00183 // arg: which buttons are currently being pressed
00184 // return: whether the mouse moved any
00185 int Mouse::mouse_moved() {
00186 int dx, dy, mymouseMoved;
00187 int b1Down, b2Down;
00188 
00189 b1Down = buttonDown == B_LEFT;
00190 
00191 // in order to better support old machines, the built-in mouse
00192 // modes of VMD treat the middle and right mouse buttons identically
00193 b2Down = (buttonDown == B_MIDDLE || buttonDown == B_RIGHT);
00194 
00195 if (b1Down || b2Down) {
00196 xRotVel = yRotVel = zRotVel = 0.0; // null out rotation rate
00197 }
00198 
00199 // get current mouse position
00200 currX = app->display->x();
00201 currY = app->display->y();
00202 
00203 // and calculate distance mouse has moved
00204 dx = 5 * (currX - oldX);
00205 dy = -5 * (currY - oldY); // negate Y coordinates
00206 
00207 mymouseMoved = (dx != 0 || dy != 0);
00208 if (!mymouseMoved)
00209 return FALSE; // early-exit if nothing happened
00210 
00211 // report the mouse location to TCL
00212 if (make_callbacks && !b1Down && !b2Down) {
00213 float r[2], oldr[2];
00214 r[0] = (float) currX; 
00215 r[1] = (float) currY;
00216 oldr[0] = (float) oldX; 
00217 oldr[1] = (float) oldY;
00218 int tag;
00219 
00220 app->display->rel_screen_pos(r[0], r[1]);
00221 app->display->rel_screen_pos(oldr[0], oldr[1]);
00222 if ((r[0] >= 0.0 && r[0] <= 1.0 && r[1] >= 0.0 && r[1] <= 1.0)) {
00223 // must be in the screen to do a pick!
00224 app->pickList->pick_check(2, r, tag, NULL, 0.01f, (char *)"mouse");
00225 } else if (oldr[0] >= 0.0 && oldr[0] <= 1.0 && oldr[1] >= 0.0 &&
00226 oldr[1] <= 1.0) {
00227 // but if we just moved out, inform TCL.
00228 app->commandQueue->runcommand(new PickAtomCallbackEvent(-1,-1,"mouse"));
00229 }
00230 }
00231 
00232 
00233 // save mouse coordinates for future reference
00234 oldX = currX;
00235 oldY = currY;
00236 
00237 if (!b1Down && !b2Down) return FALSE;
00238 
00239 // check if we are picking something; if so, generate pick-move command
00240 if (pickInProgress) {
00241 float mx = (float) currX;
00242 float my = (float) currY;
00243 app->display->rel_screen_pos(mx, my);
00244 if (mx >= 0.0 && mx <= 1.0 && my >= 0.0 && my <= 1.0) {
00245 float p[2];
00246 p[0] = mx;
00247 p[1] = my;
00248 app->pickList->pick_move(p);
00249 }
00250 return TRUE; // report that the mouse has moved
00251 }
00252 
00253 // Otherwise, if a button is pressed, check how far the mouse moved,
00254 // and transform the view accordingly.
00255 
00256 #if defined(VMDXPLOR)
00257 // Mouse handling for VMD-XPLOR builds
00258 DisplayDevice* dispDev = app->display;
00259 // check for button 1 action
00260 if (b1Down) {
00261 if (dispDev->shift_state()==0 &&
00262 (moveMode == ROTATION || moveMode == LIGHT || moveMode >= PICK)) {
00263 #else
00264 // Mouse handling for normal VMD builds
00265 // check for button 1 action
00266 if (b1Down) {
00267 if (moveMode == ROTATION || moveMode == LIGHT || moveMode >= PICK) {
00268 #endif
00269 xRotVel = rotInc * (float)dy;
00270 yRotVel = rotInc * (float)dx;
00271 if (moveMode == ROTATION || moveMode >= PICK) {
00272 // rotate the scene
00273 if (xRotVel != 0.0) {
00274 app->scene_rotate_by(xRotVel, 'x');
00275 xRotVel *= RotVelScale;
00276 }
00277 if (yRotVel != 0.0) {
00278 app->scene_rotate_by(yRotVel, 'y');
00279 yRotVel *= RotVelScale;
00280 }
00281 } else {
00282 // rotate a particular light
00283 if (xRotVel != 0.0) {
00284 app->light_rotate(moveObj, xRotVel, 'x');
00285 xRotVel *= RotVelScale;
00286 }
00287 if (yRotVel != 0.0) {
00288 app->light_rotate(moveObj, yRotVel, 'y');
00289 yRotVel *= RotVelScale;
00290 }
00291 }
00292 
00293 #if defined(VMDXPLOR)
00294 // Mouse handling for VMD-XPLOR builds
00295 } else if ((dispDev->shift_state() & DisplayDevice::SHIFT ||
00296 moveMode == TRANSLATION) && mymouseMoved) {
00297 app->scene_translate_by(transInc*(float)dx, -transInc*(float)dy, 0.0);
00298 } else if ((dispDev->shift_state() & DisplayDevice::CONTROL ||
00299 moveMode == SCALING) && dx != 0) {
00300 #else
00301 // Mouse handling for normal VMD builds
00302 } else if (moveMode == TRANSLATION && mymouseMoved) {
00303 app->scene_translate_by(transInc*(float)dx, -transInc*(float)dy, 0.0);
00304 } else if (moveMode == SCALING && dx != 0) {
00305 #endif
00306 float scf = scaling + scaleInc * (float)dx;
00307 if(scf < 0.0)
00308 scf = 0.0;
00309 app->scene_scale_by(scf);
00310 }
00311 }
00312 
00313 // check for button 2 action
00314 if (b2Down) {
00315 #if defined(VMDXPLOR)
00316 // Mouse handling for VMD-XPLOR builds
00317 if (dispDev->shift_state()==0 &&
00318 (moveMode == ROTATION || moveMode == LIGHT || moveMode >= PICK)) {
00319 #else
00320 // Mouse handling for normal VMD builds
00321 if (moveMode == ROTATION || moveMode == LIGHT || moveMode >= PICK) {
00322 #endif
00323 zRotVel = rotInc * (float)dx;
00324 if (moveMode == ROTATION || moveMode >= PICK) {
00325 if (zRotVel != 0.0) {
00326 app->scene_rotate_by(zRotVel, 'z');
00327 zRotVel *= RotVelScale;
00328 }
00329 } else {
00330 if (zRotVel != 0.0) {
00331 app->light_rotate(moveObj, zRotVel, 'z');
00332 zRotVel *= RotVelScale;
00333 }
00334 }
00335 #if defined(VMDXPLOR)
00336 // Mouse handling for VMD-XPLOR builds
00337 } else if ((dispDev->shift_state() & DisplayDevice::SHIFT ||
00338 moveMode == TRANSLATION) && dx != 0) {
00339 app->scene_translate_by(0.0, 0.0, transInc * (float)dx);
00340 } else if ((dispDev->shift_state() & DisplayDevice::CONTROL ||
00341 moveMode == SCALING) && dx != 0) {
00342 #else
00343 // Mouse handling for normal VMD builds
00344 } else if(moveMode == TRANSLATION && dx != 0) {
00345 app->scene_translate_by(0.0, 0.0, transInc * (float)dx);
00346 } else if(moveMode == SCALING && dx != 0) {
00347 #endif
00348 float scf = scaling + 10.0f * scaleInc * (float)dx;
00349 if(scf < 0.0)
00350 scf = 0.0;
00351 app->scene_scale_by(scf);
00352 }
00353 }
00354 
00355 return TRUE; // report that the mouse has moved
00356 }
00357 
00358 
00359 
00360 // mouse mode for special navigation/flying plugins,
00361 // reports the mouse location and button state to TCL callbacks
00362 int Mouse::mouse_userpoint() {
00363 float mpos[2];
00364 
00365 xRotVel = yRotVel = zRotVel = 0.0; // null out rotation rate
00366 
00367 // get current mouse position
00368 currX = app->display->x();
00369 currY = app->display->y();
00370 
00371 mpos[0] = (float) currX;
00372 mpos[1] = (float) currY;
00373 
00374 app->display->rel_screen_pos(mpos[0], mpos[1]);
00375 
00376 // inform TCL
00377 app->commandQueue->runcommand(new MousePositionEvent(mpos[0], mpos[1], buttonDown));
00378 
00379 // save mouse coordinates for future reference
00380 oldX = currX;
00381 oldY = currY;
00382 
00383 // Nothing happened for VMD to worry about for changing detail levels etc,
00384 // the user's Tcl callback will have to deal with this.
00385 return FALSE;
00386 }
00387 
00388 
00389 
00391 
00392 // reset the mouse to original settings
00393 void Mouse::reset(void) {
00394 scaling = 1.0;
00395 stop_rotation();
00396 currX = oldX = app->display->x();
00397 currY = oldY = app->display->y();
00398 }
00399 
00400 void Mouse::handle_winevent(long dev, long val) {
00401 switch(dev) {
00402 case DisplayDevice::WIN_WHEELUP:
00403 app->scene_scale_by(1.200f); // mouse wheel up scales up
00404 break;
00405 
00406 case DisplayDevice::WIN_WHEELDOWN:
00407 app->scene_scale_by(0.833f); // mouse wheel down scales down
00408 break;
00409 
00410 case DisplayDevice::WIN_LEFT:
00411 case DisplayDevice::WIN_MIDDLE:
00412 case DisplayDevice::WIN_RIGHT:
00413 if (val == 1 && buttonDown == B_NONE) {
00414 // start of a fresh button down event.
00415 xRotVel = yRotVel = zRotVel = 0.0; // null out rotation rate
00416 
00417 oldX = currX = app->display->x(); // save current mouse coords
00418 oldY = currY = app->display->y();
00419 
00420 if (dev == DisplayDevice::WIN_LEFT)
00421 buttonDown = B_LEFT;
00422 else if (dev == DisplayDevice::WIN_MIDDLE)
00423 buttonDown = B_MIDDLE; 
00424 else
00425 buttonDown = B_RIGHT;
00426 
00427 // check for a picked item if we are in a picking mode
00428 if ( moveMode >= PICK && ! pickInProgress) {
00429 pickInProgress = buttonDown;
00430 float mx = (float) currX;
00431 float my = (float) currY;
00432 app->display->rel_screen_pos(mx, my);
00433 
00434 // if picking an object fails, assume we are rotating the object
00435 float p[2];
00436 p[0] = mx;
00437 p[1] = my;
00438 if (app->pickList->pick_start(pickInProgress, 2, p) < 0)
00439 pickInProgress = B_NONE;
00440 }
00441 } else if (val == 0 && buttonDown != B_NONE) {
00442 // we're done moving the mouse while the button is down
00443 if (pickInProgress) {
00444 pickInProgress = B_NONE;
00445 app->pickList->pick_end(); // must finish the picking process
00446 }
00447 
00448 // Would return to previous detail level here
00449 buttonDown = B_NONE;
00450 }
00451 break;
00452 
00453 case DisplayDevice::WIN_KBD:
00454 case DisplayDevice::WIN_KBD_ESCAPE:
00455 case DisplayDevice::WIN_KBD_UP:
00456 case DisplayDevice::WIN_KBD_DOWN:
00457 case DisplayDevice::WIN_KBD_LEFT: 
00458 case DisplayDevice::WIN_KBD_RIGHT: 
00459 case DisplayDevice::WIN_KBD_PAGE_UP:
00460 case DisplayDevice::WIN_KBD_PAGE_DOWN:
00461 case DisplayDevice::WIN_KBD_HOME:
00462 case DisplayDevice::WIN_KBD_END:
00463 case DisplayDevice::WIN_KBD_INSERT:
00464 case DisplayDevice::WIN_KBD_DELETE:
00465 case DisplayDevice::WIN_KBD_F1:
00466 case DisplayDevice::WIN_KBD_F2:
00467 case DisplayDevice::WIN_KBD_F3:
00468 case DisplayDevice::WIN_KBD_F4:
00469 case DisplayDevice::WIN_KBD_F5:
00470 case DisplayDevice::WIN_KBD_F6:
00471 case DisplayDevice::WIN_KBD_F7:
00472 case DisplayDevice::WIN_KBD_F8:
00473 case DisplayDevice::WIN_KBD_F9:
00474 case DisplayDevice::WIN_KBD_F10:
00475 case DisplayDevice::WIN_KBD_F11:
00476 case DisplayDevice::WIN_KBD_F12:
00477 // if we are a video streaming client, graphics window 
00478 // keyboard events are sent to the server and are not
00479 // interpreted locally
00480 if (app->uivs && app->uivs->cli_connected()) {
00481 app->uivs->cli_send_keyboard(dev, (char) val, app->display->shift_state());
00482 } else {
00483 runcommand(new UserKeyEvent((DisplayDevice::EventCodes) dev, (char) val, app->display->shift_state()));
00484 }
00485 break;
00486 
00487 default:
00488 ; // ignore other events and just return
00489 } // switch
00490 }
00491 
00492 void Mouse::set_rocking(int on) {
00493 rocking_enabled = on;
00494 if (!on) {
00495 xRotVel = yRotVel = zRotVel = 0; // null out rotation rate
00496 }
00497 }
00498 
00499 // check for and queue events. Return TRUE if an event was generated.
00500 int Mouse::check_event(void) {
00501 int retval = FALSE;
00502 long dev=0, val=0; // we check for events ourselves
00503 
00504 if ((retval = app->display->read_event(dev, val)))
00505 handle_winevent(dev, val);
00506 
00507 if (moveMode == USERPOINT) {
00508 mouse_userpoint(); // user-defined mouse behavior
00509 } else if (make_callbacks || buttonDown != B_NONE) {
00510 if (mouse_moved()) {
00511 // Change to alternate detail level here...
00512 } 
00513 }
00514 
00515 // don't perform auto-rotation a remote video stream client at present
00516 if (rocking_enabled && !(app->uivs && app->uivs->cli_connected())) {
00517 // apply ang velocity, if necessary
00518 if (xRotVel != 0.0 || yRotVel != 0.0 || zRotVel != 0.0) {
00519 if (moveMode != LIGHT) { // (possibly) rotate app->scene
00520 if (xRotVel != 0.0)
00521 app->scene_rotate_by(xRotVel, 'x');
00522 if (yRotVel != 0.0)
00523 app->scene_rotate_by(yRotVel, 'y');
00524 if (zRotVel != 0.0)
00525 app->scene_rotate_by(zRotVel, 'z');
00526 } else { // (possibly) rotate particular light
00527 if (xRotVel != 0.0)
00528 app->light_rotate(moveObj, xRotVel, 'x');
00529 if (yRotVel != 0.0)
00530 app->light_rotate(moveObj, yRotVel, 'y');
00531 if (zRotVel != 0.0)
00532 app->light_rotate(moveObj, zRotVel, 'z');
00533 }
00534 }
00535 }
00536 return retval;
00537 }
00538 
00539 
00540 

Generated on Tue Nov 18 02:47:26 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

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