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

VMDApp.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 * RCS INFORMATION:
00010 *
00011 * $RCSfile: VMDApp.C,v $
00012 * $Author: johns $ $Locker: $ $State: Exp $
00013 * $Revision: 1.587 $ $Date: 2022年04月09日 21:15:13 $
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 "MobileInterface.h"
00047 #include "Spaceball.h"
00048 #ifdef WIN32
00049 #include "Win32Joystick.h"
00050 #endif
00051 #include "GeometryList.h"
00052 #include "FileRenderer.h"
00053 #include "FileRenderList.h"
00054 #include "CmdAnimate.h"
00055 #include "CmdMol.h"
00056 #include "CmdMaterial.h"
00057 #include "CmdPlugin.h"
00058 #include "CmdRender.h" // to log the render commands we execute
00059 #include "CmdTrans.h"
00060 #include "CmdDisplay.h"
00061 #include "CmdColor.h"
00062 #include "CmdLabel.h"
00063 #include "TextEvent.h"
00064 #include "CmdMenu.h"
00065 #include "P_UIVR.h"
00066 #include "P_CmdTool.h"
00067 #include "SymbolTable.h"
00068 #include "VMDCollab.h"
00069 #include "QMData.h"
00070 #include "Orbital.h"
00071 #include "QuickSurf.h"
00072 
00073 #include "CUDAAccel.h"
00074 #if defined(VMDOPENCL)
00075 #include "OpenCLUtils.h"
00076 #endif
00077 
00078 #if defined(VMDNVENC)
00079 #include "NVENCMgr.h" // GPU-accelerated H.26[45] video encode/decode
00080 #endif
00081 #include "VideoStream.h" // GPU-accelerated H.26[45] video streaming 
00082 
00083 #if defined(VMDTHREADS) // System-specific threads code
00084 #include "WKFThreads.h"
00085 #endif
00086 
00087 #ifdef MACVMD
00088 #include "MacVMDDisplayDevice.h"
00089 #endif
00090 
00091 #ifdef VMDOPENGL // OpenGL-specific files
00092 #if defined(VMDFLTKOPENGL)
00093 #include "FltkOpenGLDisplayDevice.h"
00094 #else
00095 #ifndef MACVMD
00096 #include "OpenGLDisplayDevice.h"
00097 #endif
00098 #endif
00099 
00100 #ifdef VMDCAVE // CAVE-specific files
00101 #include "cave_ogl.h"
00102 #include "CaveDisplayDevice.h"
00103 #include "CaveRoutines.h"
00104 #include "CaveScene.h"
00105 #endif // VMDCAVE
00106 #endif // VMDOPENGL
00107 
00108 // OpenGL Pbuffer off-screen rendering
00109 #if defined(VMDOPENGLPBUFFER) || defined(VMDEGLPBUFFER)
00110 #include "OpenGLPbufferDisplayDevice.h"
00111 #endif
00112 
00113 #include "VMDMenu.h"
00114 #ifdef VMDFLTK // If using FLTK GUI include FLTK objects
00115 #include "FL/forms.H"
00116 
00117 // New Fltk menus 
00118 #include "MainFltkMenu.h"
00119 #include "ColorFltkMenu.h"
00120 #include "MaterialFltkMenu.h"
00121 #include "DisplayFltkMenu.h"
00122 #include "FileChooserFltkMenu.h"
00123 #include "SaveTrajectoryFltkMenu.h"
00124 #include "GeometryFltkMenu.h"
00125 #include "GraphicsFltkMenu.h"
00126 #include "RenderFltkMenu.h"
00127 #include "ToolFltkMenu.h"
00128 
00129 #endif // VMDFLTK
00130 
00131 #ifdef VMDIMD
00132 #include "IMDMgr.h"
00133 #include "CmdIMD.h"
00134 #endif
00135 
00136 // FreeVR conflicts with the FLTK include files, so include it _after_ FLTK.
00137 #ifdef VMDFREEVR // FreeVR-specific files
00138 #include "freevr.h"
00139 #include "FreeVRDisplayDevice.h"
00140 #include "FreeVRRoutines.h"
00141 #include "FreeVRScene.h"
00142 #endif
00143 
00144 #if defined(VMDTKCON)
00145 #include "vmdconsole.h"
00146 #endif
00147 
00148 #ifdef VMDMPI
00149 #include "VMDMPI.h" 
00150 #endif
00151 
00152 #include "vmdfsinfo.h"
00153 #include "VMDApp.h"
00154 
00155 // default atom selection
00156 #define DEFAULT_ATOMSEL "all"
00157 
00158 // XXX static data item
00159 static unsigned long repserialnum;
00160 static unsigned long texserialnum;
00161 
00162 // static initialization
00163 JString VMDApp::text_message;
00164 
00165 #if defined(VMDXPLOR) 
00166 VMDApp* VMDApp::obj = 0; 
00167 #endif
00168 
00169 VMDApp::VMDApp(int argc, char **argv, int mpion) {
00170 #if defined(VMDXPLOR) 
00171 if (!obj) obj = this; 
00172 #endif
00173 
00174 // initialize ALL member variables
00175 argc_m = argc;
00176 argv_m = (const char **)argv;
00177 mpienabled = mpion; // flag to enable/disable MPI functionality at runtime...
00178 menulist = NULL;
00179 nextMolID = 0; 
00180 stride_firsttime = 1;
00181 eofexit = 0;
00182 mouse = NULL;
00183 mobile = NULL;
00184 spaceball = NULL;
00185 #ifdef WIN32
00186 win32joystick = NULL;
00187 #endif
00188 vmdTitle = NULL; 
00189 fileRenderList = NULL;
00190 pluginMgr = NULL;
00191 uiText = NULL;
00192 uivr = NULL;
00193 uivs = NULL;
00194 #ifdef VMDIMD
00195 imdMgr = NULL;
00196 #endif
00197 display = NULL;
00198 scene = NULL;
00199 pickList = NULL;
00200 pickModeList = NULL;
00201 materialList = NULL;
00202 stage = NULL;
00203 axes = NULL;
00204 fps = NULL;
00205 commandQueue = NULL;
00206 moleculeList = NULL;
00207 geometryList = NULL;
00208 atomSelParser = NULL;
00209 anim = NULL;
00210 vmdcollab = NULL;
00211 thrpool = NULL;
00212 cuda = NULL;
00213 nvenc = NULL;
00214 strcpy(nodename, "");
00215 noderank = 0; // init with MPI values later
00216 nodecount = 1; // init with MPI values later
00217 
00218 UpdateDisplay = TRUE;
00219 exitFlag = TRUE;
00220 ResetViewPending = FALSE;
00221 
00222 background_processing_clear();
00223 
00224 highlighted_molid = highlighted_rep = -1;
00225 }
00226 
00227 
00228 
00229 // Permanently bind worker threads to CPUs to achieve 
00230 // peak performance and reducing run-to-run jitter for
00231 // graphics related algorithms. This code simply performs
00232 // a one-to-one mapping of threads to CPUs at present, and
00233 // doesn't handle other cases with any greater logic yet.
00234 extern "C" void * affinitize_threads(void *voidparms) {
00235 int tid, numthreads;
00236 wkf_threadpool_worker_getid(voidparms, &tid, &numthreads);
00237 int physcpus = wkf_thread_numphysprocessors();
00238 int setthreadaffinity=1; // enable affinity assignment by default
00239 
00240 int verbose = (getenv("VMDCPUAFFINITYVERBOSE") != NULL);
00241 
00242 // XXX need to add some kind of check to skip trying to set affinity
00243 // if the OS, batch system, or other external CPU set management
00244 // system has already restricted or set of CPUs we can use
00245 
00246 #if defined(ARCH_SUMMIT)
00247 // XXX On the ORNL Summit system, the IBM LSF scheduler and 'jsrun'
00248 // handle pinning of threads to CPU sockets/cores, and the application
00249 // appears to have absolutely no control over this at present. 
00250 // To prevent runtime errors when we try to map out and set
00251 // the affinity of VMD CPU thread pool, we skip setting the affinity
00252 // and live with whatever the scheduler has assigned.
00253 // setthreadaffinity=0;
00254 if (tid == 0 && verbose) {
00255 printf("Host physcpus: %d numthreads: %d\n", physcpus, numthreads);
00256 }
00257 #endif
00258 
00259 if ((physcpus > 0) && setthreadaffinity) {
00260 int taffinity=0;
00261 
00262 #if defined(ARCH_SUMMIT) || defined(ARCH_OPENPOWER)
00263 // debug affinity behavior on P9 w/ IBM's jsrun tool
00264 int *affinitylist=NULL;
00265 int affinitycount=0;
00266 affinitylist = wkf_cpu_affinitylist(&affinitycount);
00267 
00268 if (tid == 0 && verbose) {
00269 printf("CPU affinity count: %d\n", affinitycount);
00270 int t;
00271 for (t=0; t<affinitycount; t++) {
00272 printf("thread[0] affinity[%d]: %d\n", t, affinitylist[t]);
00273 }
00274 }
00275 
00276 if (tid < affinitycount) {
00277 setthreadaffinity=1;
00278 taffinity=affinitylist[tid];
00279 
00280 if (verbose)
00281 printf("thread[%d] affinity binding: %d\n", tid, taffinity);
00282 } else {
00283 setthreadaffinity=0;
00284 if (verbose)
00285 printf("Skipping thread[%d] affinity binding\n", tid);
00286 }
00287 #elif defined(ARCH_SUMMIT) || defined(ARCH_OPENPOWER)
00288 // on POWER8 CPU SMT "cores" are numbered consecutively, so to spread out
00289 // threads across all physical cores, threads are assigned to distinct 
00290 // physical CPU cores by multiplying thread ID * SMT depth, modulo the 
00291 // total SMT core count.
00292 if (numthreads == physcpus) {
00293 taffinity=tid * 8 % physcpus;
00294 } else {
00295 #if !defined(VMDMPI)
00296 if (tid == 0) 
00297 msgWarn << "Thread affinity binding: physical cpus != numthreads" << sendmsg;
00298 #endif
00299 taffinity=tid * 8 % physcpus;
00300 }
00301 #else
00302 // On Intel/AMD hardware, physically distinct CPU cores are numbered 
00303 // consecutively, and additional SMT "cores" appear as additional multiples
00304 // of the physical CPU core count. It is therefore sufficient to 
00305 // use consecutive CPU indices to spread worker threads fully across CPUs
00306 // and SMT hardware threads
00307 if (numthreads == physcpus) {
00308 taffinity=tid; // set affinity of tid to same CPU id if numthreads == cpus
00309 } else {
00310 #if !defined(VMDMPI)
00311 if (tid == 0) 
00312 msgWarn << "Thread affinity binding: physical cpus != numthreads" << sendmsg;
00313 #endif
00314 
00315 taffinity=tid; // set affinity of tid to same CPU id if numthreads == cpus
00316 }
00317 #endif
00318 
00319 if (verbose)
00320 printf("Affinitizing thread[%d] to CPU[%d]...\n", tid, taffinity);
00321 
00322 wkf_thread_set_self_cpuaffinity(taffinity);
00323 }
00324 
00325 // mark CPU threads for display in profiling tools
00326 char threadname[1024];
00327 sprintf(threadname, "VMD CPU threadpool[%d]", tid);
00328 PROFILE_NAME_THREAD(threadname);
00329 
00330 return NULL;
00331 }
00332 
00333 
00334 
00335 // initialization routine for the library globals
00336 int VMDApp::VMDinit(int argc, char **argv, const char *displaytype, 
00337 int *displayLoc, int *displaySize) {
00338 cpucaps = NULL;
00339 #if defined(VMDTHREADS)
00340 cpucaps = (wkf_cpu_caps_t *) calloc(1, sizeof(wkf_cpu_caps_t));
00341 #endif
00342 
00343 // Tell the user what we think about the hardware we're running on.
00344 // If VMD is compiled for MPI, then we don't print any of the normal
00345 // standalone startup messages and instead we use the special MPI-specific
00346 // node scan startup messages only.
00347 #if defined(VMDMPI)
00348 if (mpienabled) {
00349 vmd_mpi_nodeinfo(&noderank, &nodecount);
00350 }
00351 #endif
00352 
00353 #if defined(VMDTHREADS)
00354 int vmdnumcpus = wkf_thread_numprocessors();
00355 if (!mpienabled) {
00356 msgInfo << "Multithreading available, " << vmdnumcpus
00357 << ((vmdnumcpus > 1) ? " CPUs" : " CPU") 
00358 #if defined(VMDCPUDISPATCH)
00359 << ", ISA dispatch enabled."
00360 #else
00361 << "."
00362 #endif
00363 << sendmsg;
00364 }
00365 
00366 if (!wkf_cpu_capability_flags((wkf_cpu_caps_t *) cpucaps) &&
00367 !mpienabled) {
00368 msgInfo << " CPU features: ";
00369 
00370 #if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64))
00371 if (cpucaps->flags & CPU_SSE2)
00372 msgInfo << "SSE2 ";
00373 if (cpucaps->flags & CPU_SSE4_1)
00374 msgInfo << "SSE4.1 ";
00375 if (cpucaps->flags & CPU_AVX)
00376 msgInfo << "AVX ";
00377 if (cpucaps->flags & CPU_AVX2)
00378 msgInfo << "AVX2 ";
00379 if (cpucaps->flags & CPU_FMA)
00380 msgInfo << "FMA ";
00381 if (cpucaps->flags & CPU_F16C)
00382 msgInfo << "F16 ";
00383 
00384 if ((cpucaps->flags & CPU_KNL) == CPU_KNL) {
00385 msgInfo << "KNL:AVX-512F+CD+ER+PF ";
00386 } else {
00387 if (cpucaps->flags & CPU_AVX512F)
00388 msgInfo << "AVX512F ";
00389 if (cpucaps->flags & CPU_AVX512CD)
00390 msgInfo << "AVX512CD ";
00391 if (cpucaps->flags & CPU_AVX512ER)
00392 msgInfo << "AVX512ER ";
00393 if (cpucaps->flags & CPU_AVX512PF)
00394 msgInfo << "AVX512PF ";
00395 }
00396 
00397 if (cpucaps->flags & CPU_HT)
00398 msgInfo << "HT ";
00399 
00400 if (cpucaps->flags & CPU_HYPERVISOR) {
00401 msgInfo << sendmsg;
00402 msgInfo << " Detected VM or hypervisor execution environment";
00403 }
00404 #endif
00405 
00406 #if (defined(ARCH_LINUXARM64) || defined(__ARM_ARCH_ISA_A64) || defined(__ARM_NEON))
00407 if (cpucaps->flags & CPU_ARM64_FP)
00408 msgInfo << "FP ";
00409 if (cpucaps->flags & CPU_ARM64_SVE)
00410 msgInfo << "SVE ";
00411 
00412 if (cpucaps->flags & CPU_ARM64_ASIMD)
00413 msgInfo << "ASIMD ";
00414 if (cpucaps->flags & CPU_ARM64_ASIMDHP)
00415 msgInfo << "ASIMDHP ";
00416 if (cpucaps->flags & CPU_ARM64_ASIMDRDM)
00417 msgInfo << "ASIMDRDM ";
00418 if (cpucaps->flags & CPU_ARM64_ASIMDDP)
00419 msgInfo << "ASIMDDP ";
00420 if (cpucaps->flags & CPU_ARM64_ASIMDFHM)
00421 msgInfo << "ASIMDFHM ";
00422 
00423 if (cpucaps->flags & CPU_ARM64_AES)
00424 msgInfo << "AES ";
00425 if (cpucaps->flags & CPU_ARM64_CRC32)
00426 msgInfo << "CRC32 ";
00427 if (cpucaps->flags & CPU_ARM64_SHA1)
00428 msgInfo << "SHA1 ";
00429 if (cpucaps->flags & CPU_ARM64_SHA2)
00430 msgInfo << "SHA2 ";
00431 if (cpucaps->flags & CPU_ARM64_SHA3)
00432 msgInfo << "SHA3 ";
00433 if (cpucaps->flags & CPU_ARM64_SHA512)
00434 msgInfo << "SHA512 ";
00435 
00436 #if defined(VMDCPUDISPATCH) && defined(__ARM_ARCH_ISA_A64) && !defined(ARCH_MACOSXARM64)
00437 if (cpucaps->flags & CPU_ARM64_SVE) {
00438 int vs32 = arm_sve_vecsize_32bits();
00439 int vs64 = arm_sve_vecsize_64bits();
00440 if (vs32 > 0 && vs64 > 0) {
00441 msgInfo << sendmsg;
00442 msgInfo << " ARM64 SVE vector lengths 32-bit: " 
00443 << vs32 << ", 64-bit: " << vs64;
00444 }
00445 }
00446 #endif
00447 #endif
00448 
00449 msgInfo << sendmsg;
00450 }
00451 #endif
00452 
00453 long vmdcorefree = vmd_get_avail_physmem_mb();
00454 if (!mpienabled && vmdcorefree >= 0) {
00455 long vmdcorepcnt = vmd_get_avail_physmem_percent();
00456 
00457 // on systems with large physical memory (tens of GB) we
00458 // report gigabytes of memory rather than megabytes
00459 if (vmdcorefree > 8000) {
00460 vmdcorefree += 512; // round up to nearest GB
00461 vmdcorefree /= 1024;
00462 msgInfo << "Free system memory: " << vmdcorefree
00463 << "GB (" << vmdcorepcnt << "%)" << sendmsg;
00464 } else {
00465 msgInfo << "Free system memory: " << vmdcorefree
00466 << "MB (" << vmdcorepcnt << "%)" << sendmsg;
00467 }
00468 }
00469 
00470 #if defined(VMDTHREADS)
00471 PROFILE_PUSH_RANGE("CPU thread pool init", 3);
00472 thrpool=wkf_threadpool_create(wkf_thread_numprocessors(), WKF_THREADPOOL_DEVLIST_CPUSONLY);
00473 
00474 // affinitize persistent threadpool to the available CPUs
00475 wkf_tasktile_t tile;
00476 memset(&tile, 0, sizeof(tile));
00477 wkf_threadpool_launch((wkf_threadpool_t *) thrpool, 
00478 affinitize_threads, NULL, 1);
00479 PROFILE_POP_RANGE();
00480 #endif
00481 
00482 #if defined(VMDCUDA)
00483 PROFILE_PUSH_RANGE("GPU device pool init", 0);
00484 
00485 // register all usable CUDA GPU accelerator devices
00486 cuda = new CUDAAccel();
00487 
00488 PROFILE_POP_RANGE();
00489 #endif
00490 
00491 #if defined(VMDMPI)
00492 if (mpienabled) {
00493 PROFILE_PUSH_RANGE("MPI init", 5);
00494 
00495 // initialize MPI node info and print output here
00496 vmd_mpi_nodescan(NULL, NULL, nodename, sizeof(nodename), 
00497 (cuda != NULL) ? cuda->num_devices() : 0);
00498 
00499 PROFILE_POP_RANGE();
00500 }
00501 #endif
00502 
00503 // only emit detailed GPU enumeration data if we're running on a single node
00504 if (nodecount == 1) {
00505 // CUDA and OpenCL GPU/multi-core acceleration
00506 #if defined(VMDCUDA)
00507 cuda->print_cuda_devices();
00508 #endif
00509 #if defined(VMDOPENCL)
00510 vmd_cl_print_platform_info();
00511 #endif
00512 }
00513 
00514 #if defined(VMDNVENC)
00515 // It may eventually be desirable to relocate NVENC initialization after
00516 // OpenGL or Vulkan initialization has completed so that we have access 
00517 // to window handles and OpenGL or Vulkan context info at the point 
00518 // where video streaming is setup. There don't presently appear to be
00519 // any APIs for graphics interop w/ NVENC. We may need to instead use 
00520 // the GRID IFR library to achieve zero-copy streaming for OpenGL / Vulkan.
00521 // Direct use of NVENC seems most appropriate for ray tracing however, since
00522 // it allows CUDA interop.
00523 
00524 PROFILE_PUSH_RANGE("NVENC init", 0);
00525 nvenc = new NVENCMgr;
00526 int nvencrc;
00527 if ((nvencrc = nvenc->init()) == NVENCMGR_SUCCESS) {
00528 nvencrc = nvenc->open_session();
00529 }
00530 if (nvencrc == NVENCMGR_SUCCESS) {
00531 msgInfo << "NVENC GPU-accelerated video streaming available."
00532 << sendmsg;
00533 } else {
00534 msgInfo << "NVENC GPU-accelerated video streaming is not available." 
00535 << sendmsg;
00536 }
00537 PROFILE_POP_RANGE();
00538 #endif
00539 
00540 
00541 PROFILE_PUSH_RANGE("UIObject init", 1);
00542 
00543 //
00544 // create commandQueue before all UIObjects!
00545 //
00546 commandQueue = new CommandQueue(); 
00547 
00548 
00549 // XXX This is currently only used for 64-bit MacOS X builds using Cocoa...
00550 // XXX Francois-Xavier Coudert has noted that this code path also corrected
00551 // startup crashes he had been having with 32-bit builds using MacOS X
00552 // 10.7.x using FLTK 1.3.0. It remains to be seen how stable the GUI is
00553 // for the 32-bit build when the Cocoa workaround is active. It has not
00554 // been very stable for 64-bit builds thus far.
00555 #if defined(ARCH_MACOSXARM64) || defined(ARCH_MACOSXX86_64)
00556 // Tcl/Tk _must_ be initialized before FLTK due to low-level implementation
00557 // details of Cocoa-based Tk and FLTK code required for 64-bit MacOS X.
00558 uiText = new UIText(this, (strcmp(displaytype, "TEXT") != 0), 0); // text user interface
00559 #endif
00560 
00561 PROFILE_POP_RANGE();
00562 PROFILE_PUSH_RANGE("DisplayDevice init", 0);
00563 
00564 // initialize the display
00565 int *dloc = (displayLoc[0] > 0 ? displayLoc : (int *) NULL);
00566 
00567 int dsiz[2] = { 512, 512 };
00568 if (displaySize && displaySize[0] > 0 && displaySize[1] > 0) {
00569 dsiz[0] = displaySize[0];
00570 dsiz[1] = displaySize[1];
00571 }
00572 
00573 // initialize static data items
00574 repserialnum = 0; // initialize the display list serial number
00575 texserialnum = 0; // initialize the texture list serial number
00576 
00577 #ifdef MACVMD
00578 display = new MacVMDDisplayDevice(this, dsiz);
00579 #endif
00580 
00581 // check for a standard windowed display
00582 if (!strcmp(displaytype, "WIN") || !strcmp(displaytype, "OPENGL")) {
00583 #if defined(VMDOPENGL)
00584 #if defined(VMDFLTKOPENGL)
00585 display = new FltkOpenGLDisplayDevice(argc, argv, this, dsiz, dloc);
00586 #else
00587 display = new OpenGLDisplayDevice;
00588 if (!display->init(argc, argv, this, dsiz, dloc)) {
00589 VMDexit("Unable to create OpenGL window.", 1, 7);
00590 return FALSE;
00591 } 
00592 #endif
00593 #endif
00594 }
00595 
00596 #if defined(VMDOPENGLPBUFFER) || defined(VMDEGLPBUFFER)
00597 // check for OpenGL Pbuffer off-screen rendering context
00598 if (!strcmp(displaytype, "OPENGLPBUFFER")) {
00599 display = new OpenGLPbufferDisplayDevice;
00600 if (!display->init(argc, argv, this, dsiz, dloc)) {
00601 VMDexit("Unable to create OpenGL Pbuffer context.", 1, 7);
00602 return FALSE;
00603 } 
00604 }
00605 #endif
00606 
00607 #ifdef VMDCAVE
00608 if (!strcmp(displaytype, "CAVE") || !strcmp(displaytype, "CAVEFORMS")) {
00609 // The CAVE scene is allocated from shared memory and can be 
00610 // accessed by all of the rendering processes by virtue of its
00611 // class-specific operator new.
00612 scene = new CaveScene(this);
00613 msgInfo << "Cave shared memory scene created." << sendmsg;
00614 
00615 // the CAVE display device is created in process-private memory
00616 display = new CaveDisplayDevice;
00617 
00618 // set up pointers for cave_renderer, needs to be done before forking.
00619 set_cave_pointers(scene, display);
00620 
00621 // XXX this may cure a problem with specular highlights in CAVElib
00622 // by default CAVElib messes with the OpenGL modelview matrix, this
00623 // option prevents it from doing so, which should allow specular 
00624 // highlights to look right on multiple walls, but it breaks depth cueing.
00625 // CAVESetOption(CAVE_PROJ_USEMODELVIEW, 0);
00626 CAVESetOption(CAVE_GL_SAMPLES, 8); // enable multisample antialiasing
00627 CAVEInit(); // fork off the rendering processes
00628 CAVEDisplay(cave_renderer, 0); // set the fctn ptr for the renderers
00629 display->renderer_process = 0; // this proc is the master process
00630 vmd_set_cave_is_initialized(); // flag successfull CAVE init
00631 
00632 if (!display->init(argc, argv, this, NULL, NULL)) {
00633 VMDexit("Unable to create CAVE display context.", 1, 7);
00634 return FALSE;
00635 }
00636 msgInfo << "CAVE Initialized" << sendmsg;
00637 }
00638 #endif
00639 
00640 #ifdef VMDFREEVR
00641 if (!strcmp(displaytype, "FREEVR") || !strcmp(displaytype, "FREEVRFORMS")) {
00642 // The FreeVR scene is allocated from shared memory and can be 
00643 // accessed by all of the rendering processes by virtue of its
00644 // class-specific operator new.
00645 scene = new FreeVRScene(this);
00646 msgInfo << "FreeVR shared memory scene created." << sendmsg;
00647 
00648 // the FreeVR display device is created in process-private memory
00649 display = new FreeVRDisplayDevice;
00650 
00651 // set up pointers for freevr_renderer, needs to be done before forking.
00652 set_freevr_pointers(scene, display);
00653 
00654 // set the function pointer for the per-screen renderers
00655 vrFunctionSetCallback(VRFUNC_ALL_DISPLAY, vrCallbackCreate(freevr_renderer, 1, &display)); 
00656 vrStart(); // fork off the rendering processes
00657 vrSystemSetName("VMD using FreeVR display form");
00658 vrSystemSetAuthors("John Stone, Justin Gullingsrud, Bill Sherman");
00659 vrSystemSetExtraInfo(VERSION_MSG);
00660 vrInputSet2switchDescription(0, "Terminate the FreeVR windows");
00661 vrInputSet2switchDescription(1, "Interface with the Graphics->Tools grab tool");
00662 vrInputSet2switchDescription(2, "Grab the world");
00663 vrInputSet2switchDescription(3, "Reset the world's position");
00664 vrInputSetValuatorDescription(0, "Rotate us in the world about the Y-axis");
00665 vrInputSetValuatorDescription(1, "Move us though the world in the direction we point");
00666 display->renderer_process = 0; // this proc is the master process
00667 
00668 if (!display->init(argc, argv, this, NULL, NULL)) {
00669 VMDexit("Unable to create FreeVR display context.", 1, 7);
00670 return FALSE;
00671 }
00672 msgInfo << "FreeVR Initialized" << sendmsg;
00673 }
00674 #endif
00675 
00676 // If no scene object has been created yet (e.g. CAVE/FreeVR), create one.
00677 if (!scene) {
00678 scene = new Scene;
00679 }
00680 
00681 // If a real display doesn't exist, create a stub display that eats commands
00682 if (!display) {
00683 display = new DisplayDevice("Default Display");
00684 if (!display->init(argc, argv, this, dsiz, dloc)) {
00685 VMDexit("Unable to create stub default display context.", 1, 7);
00686 return FALSE;
00687 }
00688 }
00689 
00690 // print any useful informational messages now that the display is setup
00691 if (display->get_num_processes() > 1) {
00692 msgInfo << "Started " << display->get_num_processes() 
00693 << " slave rendering processes." << sendmsg;
00694 }
00695 
00696 PROFILE_POP_RANGE();
00697 
00698 //
00699 // create other global objects for the program
00700 //
00701 PROFILE_PUSH_RANGE("Internal state init", 1);
00702 
00703 rocker = new DisplayRocker(&(scene->root));
00704 
00705 pluginMgr = new PluginMgr;
00706 
00707 atomSelParser = new SymbolTable(this);
00708 atomSelParser_init(atomSelParser);
00709 
00710 pickModeList = new PickModeList(this);
00711 pickList = new PickList(this);
00712 
00713 // create material list
00714 materialList = new MaterialList(&scene->root);
00715 
00716 // create other useful graphics objects
00717 axes = new Axes(display, &(scene->root));
00718 pickList->add_pickable(axes);
00719 
00720 fps = new FPS(display, &(scene->root));
00721 fps->off();
00722 
00723 // create the list of molecules (initially empty)
00724 moleculeList = new MoleculeList(this, scene);
00725 
00726 // create shared QuickSurf object used by all reps
00727 qsurf = new QuickSurf();
00728 
00729 anim = new Animation(this);
00730 anim->On();
00731 
00732 // create the list of geometry monitors (initially empty)
00733 geometryList = new GeometryList(this, &(scene->root));
00734 
00735 menulist = new NameList<VMDMenu *>;
00736 
00737 // If the text UI hasn't already been initialized then initialize it here.
00738 // Cocoa-based FLTK/Tk builds of VMD for 64-bit MacOS X must 
00739 // initialize Tcl/Tk first, so that FLTK works correctly.
00740 if (uiText == NULL)
00741 uiText = new UIText(this, display->supports_gui(), mpienabled); // text interface
00742 uiText->On();
00743 
00744 mouse = new Mouse(this); // mouse user interface
00745 mouse->On();
00746 
00747 mobile = new Mobile(this); // Smartphone/tablet network input device
00748 mobile->On();
00749 
00750 spaceball = new Spaceball(this); // Spaceball 6DOF input device
00751 spaceball->On();
00752 
00753 #ifdef WIN32
00754 win32joystick = new Win32Joystick(this); // Win32 Joystick devices
00755 win32joystick->On();
00756 #endif
00757 
00758 #ifdef VMDIMD
00759 imdMgr = new IMDMgr(this);
00760 imdMgr->On();
00761 #endif
00762 
00763 #if 1 || defined(VMDNVPIPE)
00764 // only create a video streaming object if we have back-end encoder support
00765 uivs = new VideoStream(this);
00766 uivs->On();
00767 #endif
00768 
00769 stage = new Stage(&(scene->root));
00770 pickList->add_pickable(stage);
00771 
00772 vmdcollab = new VMDCollab(this);
00773 vmdcollab->On();
00774 
00775 // make the classes which can render scenes to different file formats
00776 fileRenderList = new FileRenderList(this);
00777 
00778 display->queue_events(); // begin accepting UI events in graphics window
00779 
00780 // Create the menus; XXX currently this must be done _before_ calling
00781 // uiText->read_init() because otherwise the new menus created by the 
00782 // plugins loaded by the iit script won't be added to the main menu.
00783 activate_menus();
00784 
00785 PROFILE_POP_RANGE();
00786 PROFILE_PUSH_RANGE("Plugin shared obj init", 5);
00787 
00788 // XXX loading static plugins should be controlled by a startup option
00789 pluginMgr->load_static_plugins();
00790 
00791 // plugin_update must take place _after_ creation of uiText.
00792 plugin_update();
00793 
00794 PROFILE_POP_RANGE();
00795 PROFILE_PUSH_RANGE("Interp loop init", 3);
00796 
00797 VMDupdate(VMD_IGNORE_EVENTS); // flush cmd queue, prepare to enter event loop
00798 
00799 // Read the initialization code for the text interpreter.
00800 // We wait to do it now since that script might contain commands that use 
00801 // the event queue
00802 uiText->read_init();
00803 
00804 // If there's no text interpreter, show the main menu
00805 #ifndef VMDTCL
00806 #ifndef VMDPYTHON
00807 menu_show("main", 1);
00808 #endif
00809 #endif
00810 
00811 #if defined(VMDTCL)
00812 // XXX hacks for Swift/T
00813 if (mpienabled) {
00814 commandQueue->runcommand(
00815 new TclEvalEvent("parallel swift_clone_communicator"));
00816 }
00817 #endif
00818 
00819 PROFILE_POP_RANGE();
00820 
00821 // successful initialization. Turn off the exit flag return success
00822 exitFlag = FALSE;
00823 return TRUE;
00824 }
00825 
00826 int VMDApp::num_menus() { return menulist->num(); }
00827 
00828 int VMDApp::add_menu(VMDMenu *m) {
00829 if (menulist->typecode(m->get_name()) != -1) {
00830 msgErr << "Menu " << m->get_name() << " already exists." << sendmsg;
00831 return 0; 
00832 }
00833 menulist->add_name(m->get_name(), m);
00834 return 1;
00835 }
00836 
00837 int VMDApp::remove_menu(const char *name) {
00838 int id = menulist->typecode(name);
00839 if (id == -1) {
00840 msgErr << "Menu " << name << " does not exist." << sendmsg;
00841 return 0; 
00842 }
00843 NameList<VMDMenu *> *newmenulist = new NameList<VMDMenu *>;
00844 for (int i=0; i<menulist->num(); i++) {
00845 VMDMenu *menu = menulist->data(i);
00846 if (i == id) {
00847 delete menu;
00848 } else {
00849 newmenulist->add_name(menu->get_name(), menu);
00850 }
00851 }
00852 delete menulist;
00853 menulist = newmenulist;
00854 return 1;
00855 }
00856 
00857 void VMDApp::menu_add_extension(const char *shortname, const char *menu_path) {
00858 commandQueue->runcommand(new CmdMenuExtensionAdd(shortname,menu_path));
00859 }
00860 
00861 void VMDApp::menu_remove_extension(const char *shortname) {
00862 commandQueue->runcommand(new CmdMenuExtensionRemove(shortname));
00863 }
00864 
00865 const char *VMDApp::menu_name(int i) { 
00866 return menulist->name(i); 
00867 }
00868 
00869 int VMDApp::menu_id(const char *name) {
00870 return menulist->typecode(name);
00871 }
00872 
00873 int VMDApp::menu_status(const char *name) {
00874 int id = menulist->typecode(name);
00875 if (id == -1) return 0;
00876 return menulist->data(id)->active();
00877 }
00878 
00879 int VMDApp::menu_location(const char *name, int &x, int &y) {
00880 int id = menulist->typecode(name);
00881 if (id == -1) return 0;
00882 menulist->data(id)->where(x, y);
00883 return 1;
00884 }
00885 
00886 int VMDApp::menu_show(const char *name, int on) {
00887 int id = menulist->typecode(name);
00888 if (id == -1) return 0;
00889 VMDMenu *obj = menulist->data(name);
00890 if (on)
00891 obj->On();
00892 else
00893 obj->Off();
00894 commandQueue->runcommand(new CmdMenuShow(name, on));
00895 return 1;
00896 }
00897 
00898 int VMDApp::menu_move(const char *name, int x, int y) {
00899 int id = menulist->typecode(name);
00900 if (id == -1) return 0;
00901 menulist->data(id)->move(x, y);
00902 return 1;
00903 }
00904 
00905 
00906 int VMDApp::menu_select_mol(const char *name, int molno) {
00907 int id = menulist->typecode(name);
00908 if (id == -1) return 0;
00909 return menulist->data(id)->selectmol(molno);
00910 }
00911 
00912 
00913 // redraw the screen and update all things that need updating
00914 int VMDApp::VMDupdate(int check_for_events) {
00915 PROFILE_PUSH_RANGE("VMDApp::VMDupdate()", 5);
00916 
00917 // clear background processing flag
00918 background_processing_clear();
00919 
00920 // see if there are any pending events; if so, get them
00921 if (check_for_events) {
00922 commandQueue->check_events();
00923 #ifdef VMDGUI
00924 #ifdef VMDFLTK
00925 // if we are using the FLTK library ...
00926 if (display->supports_gui()) {
00927 #if defined(ARCH_MACOSX) && defined(VMDTCL)
00928 // don't call wait(0) since this causes Tcl/Tk to mishandle events
00929 Fl::flush();
00930 #elif (defined(ARCH_MACOSXARM64) || defined(ARCH_MACOSXX86) || defined(ARCH_MACOSXX86_64)) && defined(VMDTCL)
00931 // starting with more recent revs of FLTK and Tcl/Tk, we should no
00932 // longer need to drop events
00933 Fl::wait(0);
00934 #else
00935 Fl::wait(0);
00936 #endif
00937 }
00938 #endif
00939 #endif
00940 } 
00941 
00942 // check if the user has requested to exit the program.
00943 if (exitFlag) {
00944 PROFILE_POP_RANGE();
00945 return FALSE;
00946 }
00947 
00948 commandQueue->execute_all(); // execute commands still in the queue
00949 
00950 //
00951 // if video streaming is active and we're a client with an active
00952 // connection, all local rendering is disabled..
00953 //
00954 if (uivs == NULL || !uivs->cli_connected()) {
00955 int needupdate = 0;
00956 #if 1
00957 // Only prepare objects if display update is enabled
00958 // XXX avoid N^2 behavior when loading thousdands of molecules, 
00959 // don't prepare for drawing unless we have to.
00960 if (UpdateDisplay) {
00961 // If a resetview is pending, take care of it now before drawing
00962 if (ResetViewPending) 
00963 scene_resetview_newmoldata();
00964 
00965 needupdate = scene->prepare(); // prepare all objects for drawing
00966 } else {
00967 // XXX this has to be done currently to force trajectories to continue
00968 // loading frames since they don't have their own UIObject yet.
00969 int molnum = moleculeList->num();
00970 int i;
00971 for (i=0; i<molnum; i++) {
00972 Molecule *mol = moleculeList->molecule(i);
00973 if (mol != NULL) {
00974 if (mol->get_new_frames()) {
00975 needupdate = 1; // need to update if any new frames were loaded
00976 }
00977 }
00978 }
00979 }
00980 #else
00981 // XXX this has to be done currently to force trajectories to continue
00982 // loading frames since they don't have their own UIObject yet.
00983 needupdate = scene->prepare(); // prepare all objects for drawing
00984 #endif
00985 
00986 // turn off the spinning vmd when molecules are loaded
00987 if (vmdTitle && moleculeList->num() > 0) {
00988 delete vmdTitle;
00989 vmdTitle = NULL;
00990 }
00991 
00992 // Update the display (or sleep a tiny bit).
00993 if (UpdateDisplay && (needupdate || display->needRedraw())) {
00994 scene->draw(display); // make the display redraw if necessary
00995 scene->draw_finished(); // perform any necessary post-drawing cleanup
00996 
00997 // if video streaming is active, we tell the encoder a new frame is ready
00998 if (uivs != NULL && uivs->srv_connected()) {
00999 #if 0
01000 int xs, ys;
01001 unsigned char *img = display->readpixels_rgba4u(xs, ys);
01002 if (img != NULL) {
01003 uivs->srv_send_frame(img, xs * 4, xs, ys, 0);
01004 free(img);
01005 }
01006 #elif 0
01007 uivs->video_frame_pending();
01008 #endif
01009 }
01010 } else {
01011 // if not updating the display or doing background I/O, 
01012 // we sleep so we don't hog CPU.
01013 if (!needupdate && !background_processing())
01014 vmd_msleep(1); // sleep for 1 millisecond or more
01015 }
01016 } // no active video-streaming-client connection
01017 
01018 // XXX A hack to decrease CPU utilization on machines that have
01019 // problems keeping up with the 3-D draw rate at full speed.
01020 if (getenv("VMDMSECDELAYHACK") != NULL) {
01021 // Delay the whole program for a user-specified number of milliseconds. 
01022 vmd_msleep(atoi(getenv("VMDMSECDELAYHACK"))); 
01023 }
01024 
01025 PROFILE_POP_RANGE();
01026 return TRUE;
01027 }
01028 
01029 
01030 // exit the program normally; first delete all the necessary objects
01031 void VMDApp::VMDexit(const char *exitmsg, int exitcode, int pauseseconds) {
01032 
01033 #if defined(VMDTKCON)
01034 // switch to text mode and flush all pending messages to the screen.
01035 vmdcon_use_text((void *)uiText->get_tcl_interp());
01036 vmdcon_purge();
01037 #endif
01038 
01039 #if defined(VMDMPI)
01040 // If MPI parallel execution is in effect, help console output complete before
01041 // final shutdown.
01042 if (mpienabled) { 
01043 fflush(stdout);
01044 vmd_mpi_barrier(); // wait for peers before printing final messages
01045 if (noderank == 0)
01046 vmd_msleep(250); // give peer output time to percolate to the console...
01047 }
01048 #endif
01049 
01050 // only print exit status output on the first exit call
01051 if (exitFlag == 0 || (exitmsg != NULL && strlen(exitmsg))) {
01052 msgInfo << VERSION_MSG << sendmsg; 
01053 if (exitmsg && strlen(exitmsg)) {
01054 msgInfo << exitmsg << sendmsg;
01055 } else {
01056 msgInfo << "Exiting normally." << sendmsg;
01057 }
01058 }
01059 
01060 vmd_sleep(pauseseconds); // sleep for requested number of seconds
01061 
01062 // make the VMDupdate event loop return FALSE.
01063 exitFlag = 1;
01064 }
01065 
01066 VMDApp::~VMDApp() {
01067 int i;
01068 
01069 // delete shared QuickSurf object used by all reps.
01070 // destroy QuickSurf object prior to other GPU-related teardown
01071 if (qsurf) delete qsurf;
01072 
01073 // delete all objects we created during initialization
01074 if (fileRenderList) delete fileRenderList;
01075 if (mouse) delete mouse;
01076 if (mobile) delete mobile;
01077 if (spaceball) delete spaceball;
01078 
01079 #ifdef WIN32
01080 if (win32joystick) delete win32joystick;
01081 #endif
01082 
01083 if (uivr) delete uivr;
01084 
01085 if (uivs) delete uivs;
01086 uivs = NULL; // prevent free mem accesses in event loops
01087 
01088 if (geometryList) delete geometryList;
01089 
01090 #ifdef VMDIMD
01091 if (imdMgr) delete imdMgr;
01092 imdMgr = NULL; // prevent free mem reads at moleculeList deletion
01093 #endif
01094 
01095 if (vmdTitle) delete vmdTitle;
01096 if (stage) delete stage;
01097 if (axes) delete axes;
01098 if (fps) delete fps;
01099 if (pickModeList) delete pickModeList;
01100 if (materialList) delete materialList;
01101 if (pluginMgr) delete pluginMgr;
01102 if (cuda) delete cuda;
01103 delete vmdcollab;
01104 
01105 // delete all of the Forms;
01106 if (menulist) {
01107 for (i=0; i<menulist->num(); i++)
01108 delete menulist->data(i);
01109 delete menulist;
01110 }
01111 
01112 #ifdef VMDGUI
01113 // Close all GUI windows
01114 #ifdef VMDFLTK
01115 if (display->supports_gui()) {
01116 Fl::wait(0); // Give Fltk a chance to close the menu windows. 
01117 }
01118 #endif
01119 #endif
01120 
01121 // Tcl/Python interpreters can only be deleted after Tk forms are shutdown
01122 if (uiText) delete uiText;
01123 
01124 // delete the list of user keys and descriptions 
01125 for (i=0; i<userKeys.num(); i++)
01126 delete [] userKeys.data(i);
01127 
01128 for (i=0; i<userKeyDesc.num(); i++)
01129 delete [] userKeyDesc.data(i);
01130 
01131 delete atomSelParser;
01132 delete anim;
01133 
01134 // delete commandQueue _after_ all UIObjects have been deleted; otherwise
01135 // they will try to unRegister with a deleted CommandQueue.
01136 delete commandQueue;
01137 
01138 // (these dependencies really suck) delete moleculelist after uiText
01139 // because text interfaces might use commands that require moleculeList to
01140 // be there.
01141 delete moleculeList;
01142 
01143 // picklist can't be deleted until the molecule is deleted, since
01144 // the DrawMolecule destructor needs it.
01145 delete pickList;
01146 
01147 delete display;
01148 delete scene;
01149 
01150 #if defined(VMDTHREADS)
01151 if (thrpool) {
01152 wkf_threadpool_destroy((wkf_threadpool_t *) thrpool);
01153 thrpool=NULL;
01154 }
01155 #endif
01156 
01157 if (cpucaps) {
01158 free(cpucaps);
01159 }
01160 }
01161 
01162 unsigned long VMDApp::get_repserialnum(void) {
01163 // first serial number returned will be 1, never return 0.
01164 repserialnum++;
01165 return repserialnum;
01166 }
01167 
01168 unsigned long VMDApp::get_texserialnum(void) {
01169 // first serial number returned will be 1, never return 0.
01170 texserialnum++;
01171 return texserialnum;
01172 }
01173 
01174 void VMDApp::show_stride_message() {
01175 if (stride_firsttime) {
01176 stride_firsttime = 0;
01177 msgInfo <<
01178 "In any publication of scientific results based in part or\n"
01179 "completely on the use of the program STRIDE, please reference:\n"
01180 " Frishman,D & Argos,P. (1995) Knowledge-based secondary structure\n"
01181 " assignment. Proteins: structure, function and genetics, 23, 566-579." 
01182 << "\n" << sendmsg;
01183 }
01184 }
01185 
01186 // this is a nasty hack until we get around to returning values from scripts
01187 // properly.
01188 
01189 #ifdef VMDTK
01190 #include <tcl.h> 
01191 #endif
01192 
01193 char *VMDApp::vmd_choose_file(const char *title,
01194 const char *extension, 
01195 const char *extension_label, int do_save) {
01196 
01197 char *chooser = getenv("VMDFILECHOOSER");
01198 if (!chooser || !strupcmp(chooser, "TK")) {
01199 
01200 #ifdef VMDTK
01201 JString t = title;
01202 JString ext = extension;
01203 JString label = extension_label;
01204 char *cmd = new char[300 + t.length() +ext.length() + label.length()];
01205 // no default extension for for saves/loads , because otherwise it 
01206 // automatically adds the file extension whether you specify it or not, and 
01207 // when the extension is * it won't let you save/load a file without an 
01208 // extension!
01209 if (do_save) {
01210 sprintf(cmd, "tk_getSaveFile -title {%s} -filetypes {{{%s} {%s}} {{All files} {*}}}", (const char *)t, (const char *)extension_label, (const char *)extension);
01211 } else {
01212 sprintf(cmd, "tk_getOpenFile -title {%s} -filetypes {{{%s} {%s}} {{All files} {*}}}", (const char *)t, (const char *)extension_label, (const char *)extension);
01213 }
01214 Tcl_Interp *interp = uiText->get_tcl_interp();
01215 if (interp) {
01216 int retval = Tcl_Eval(interp, cmd);
01217 delete [] cmd;
01218 if (retval == TCL_OK) {
01219 const char *result = Tcl_GetStringResult(interp);
01220 if (result == NULL || strlen(result) == 0) {
01221 return NULL;
01222 } else {
01223 return stringdup(result);
01224 }
01225 }
01226 }
01227 // fall through to next level on failure
01228 #endif
01229 
01230 } 
01231 
01232 #ifdef VMDFLTK
01233 return stringdup(fl_file_chooser(title, extension, NULL));
01234 #endif
01235 
01236 char *result = new char[1024];
01237 if (fgets(result, 1024, stdin) == NULL)
01238 result[0] = '0円';
01239 
01240 return result;
01241 }
01242 
01243 // file renderer API
01244 int VMDApp::filerender_num() {
01245 return fileRenderList->num();
01246 }
01247 const char *VMDApp::filerender_name(int n) {
01248 return fileRenderList->name(n);
01249 }
01250 const char *VMDApp::filerender_prettyname(int n) {
01251 return fileRenderList->pretty_name(n);
01252 }
01253 int VMDApp::filerender_valid(const char *method) {
01254 return (fileRenderList->find(method) != NULL);
01255 }
01256 // Find short renderer name from the "pretty" GUI renderer name
01257 const char *VMDApp::filerender_shortname_from_prettyname(const char *pretty) {
01258 return fileRenderList->find_short_name_from_pretty_name(pretty);
01259 }
01260 int VMDApp::filerender_has_antialiasing(const char *method) {
01261 return (fileRenderList->has_antialiasing(method));
01262 }
01263 int VMDApp::filerender_aasamples(const char *method, int aasamples) {
01264 return fileRenderList->aasamples(method, aasamples);
01265 }
01266 int VMDApp::filerender_aosamples(const char *method, int aosamples) {
01267 return fileRenderList->aosamples(method, aosamples);
01268 }
01269 int VMDApp::filerender_imagesize(const char *method, int *w, int *h) {
01270 if (!w || !h) return FALSE;
01271 return fileRenderList->imagesize(method, w, h); 
01272 }
01273 int VMDApp::filerender_has_imagesize(const char *method) {
01274 return fileRenderList->has_imagesize(method);
01275 }
01276 int VMDApp::filerender_aspectratio(const char *method, float *aspect) {
01277 if (!aspect) return FALSE;
01278 return fileRenderList->aspectratio(method, aspect);
01279 }
01280 int VMDApp::filerender_numformats(const char *method) {
01281 return fileRenderList->numformats(method);
01282 }
01283 const char *VMDApp::filerender_get_format(const char *method, int i) {
01284 return fileRenderList->format(method, i);
01285 }
01286 const char *VMDApp::filerender_cur_format(const char *method) {
01287 return fileRenderList->format(method);
01288 }
01289 int VMDApp::filerender_set_format(const char *m, const char *fmt) {
01290 return fileRenderList->set_format(m, fmt);
01291 }
01292 
01293 int VMDApp::filerender_render(const char *m, const char *f, const char *e) {
01294 int retval = fileRenderList->render(f, m, e);
01295 if (retval) {
01296 commandQueue->runcommand(new CmdRender(f, m, e));
01297 }
01298 return retval;
01299 }
01300 const char *VMDApp::filerender_option(const char *m, const char *o) {
01301 FileRenderer *ren = fileRenderList->find(m);
01302 if (!ren) {
01303 return NULL;
01304 }
01305 if (o) {
01306 ren->set_exec_string(o);
01307 commandQueue->runcommand(new CmdRenderOption(m, o));
01308 }
01309 return ren->saved_exec_string();
01310 }
01311 
01312 // XXX The Scene doesn't return error codes, so I don't know if the commands
01313 // worked or not. I do what error checking I can here and hope that it works.
01314 int VMDApp::scene_rotate_by(float angle, char ax, float incr) {
01315 if (uivs && uivs->cli_connected()) {
01316 uivs->cli_send_rotate_by(angle, ax);
01317 return TRUE;
01318 }
01319 
01320 if (ax < 'x' || ax > 'z') return FALSE; // failed
01321 rocker->stop_rocking();
01322 if (incr) {
01323 int nsteps = (int)(fabs(angle / incr) + 0.5);
01324 incr = (float) (angle < 0.0f ? -fabs(incr) : fabs(incr));
01325 rocker->start_rocking(incr, ax, nsteps, TRUE);
01326 commandQueue->runcommand(new CmdRotate(angle, ax, CmdRotate::BY, incr)); 
01327 } else {
01328 scene->root.add_rot(angle, ax);
01329 commandQueue->runcommand(new CmdRotate(angle, ax, CmdRotate::BY));
01330 }
01331 return TRUE;
01332 }
01333 int VMDApp::scene_rotate_to(float angle, char ax) {
01334 if (ax < 'x' || ax > 'z') return FALSE; // failed
01335 rocker->stop_rocking();
01336 scene->root.set_rot(angle, ax);
01337 commandQueue->runcommand(new CmdRotate(angle, ax, CmdRotate::TO));
01338 return TRUE;
01339 }
01340 int VMDApp::scene_rotate_by(const float *m) {
01341 Matrix4 mat(m);
01342 scene->root.add_rot(mat);
01343 commandQueue->runcommand(new CmdRotMat(mat, CmdRotMat::BY));
01344 return TRUE;
01345 }
01346 int VMDApp::scene_rotate_to(const float *m) {
01347 Matrix4 mat(m);
01348 scene->root.set_rot(mat);
01349 commandQueue->runcommand(new CmdRotMat(mat, CmdRotMat::TO));
01350 return TRUE;
01351 }
01352 int VMDApp::scene_translate_by(float x, float y, float z) {
01353 if (uivs && uivs->cli_connected()) {
01354 uivs->cli_send_translate_by(x, y, z);
01355 return TRUE;
01356 }
01357 
01358 scene->root.add_glob_trans(x, y, z);
01359 commandQueue->runcommand(new CmdTranslate(x,y,z,CmdTranslate::BY));
01360 return TRUE;
01361 }
01362 int VMDApp::scene_translate_to(float x, float y, float z) {
01363 scene->root.set_glob_trans(x, y, z);
01364 commandQueue->runcommand(new CmdTranslate(x,y,z,CmdTranslate::TO));
01365 return TRUE;
01366 }
01367 int VMDApp::scene_scale_by(float s) {
01368 if (uivs && uivs->cli_connected()) {
01369 uivs->cli_send_scale_by(s);
01370 return TRUE;
01371 }
01372 
01373 if (s <= 0) return FALSE; 
01374 scene->root.mult_scale(s);
01375 commandQueue->runcommand(new CmdScale(s, CmdScale::BY));
01376 return TRUE;
01377 }
01378 int VMDApp::scene_scale_to(float s) {
01379 if (s <= 0) return FALSE; 
01380 scene->root.set_scale(s);
01381 commandQueue->runcommand(new CmdScale(s, CmdScale::TO));
01382 return TRUE;
01383 }
01384 void VMDApp::scene_resetview_newmoldata() {
01385 #if 1
01386 // XXX avoid N^2 behavior when loading thousands of molecules
01387 // we should only be resetting the view when necessary
01388 if (UpdateDisplay) {
01389 int nodisrupt = 0;
01390 
01391 if (getenv("VMDNODISRUPTHACK"))
01392 nodisrupt=1;
01393 
01394 if (nodisrupt && (moleculeList->num() > 1)) {
01395 moleculeList->center_top_molecule(); // new/top mol inherits current view
01396 } else {
01397 scene_resetview(); // reset all molecules to the newly loaded structure
01398 }
01399 ResetViewPending = FALSE;
01400 } else {
01401 ResetViewPending = TRUE;
01402 }
01403 #else
01404 scene_resetview(); // reset all molecules to the newly loaded structure
01405 #endif
01406 }
01407 void VMDApp::scene_resetview() {
01408 scene->root.reset_transformation();
01409 // center the view based on the displayed representations
01410 moleculeList->center_from_top_molecule_reps();
01411 moleculeList->center_all_molecules();
01412 commandQueue->runcommand(new CmdResetView);
01413 }
01414 int VMDApp::scene_rock(char ax, float step, int nsteps) {
01415 if (ax < 'x' || ax > 'z') return FALSE; // failed
01416 rocker->start_rocking(step, ax, nsteps);
01417 commandQueue->runcommand(new CmdRockOn(step, ax, nsteps));
01418 return TRUE;
01419 }
01420 int VMDApp::scene_rockoff() {
01421 rocker->stop_rocking();
01422 commandQueue->runcommand(new CmdRockOff);
01423 return TRUE;
01424 } 
01425 int VMDApp::scene_stoprotation() {
01426 rocker->stop_rocking();
01427 mouse->stop_rotation();
01428 return TRUE;
01429 }
01430 
01431 int VMDApp::animation_num_dirs() {
01432 return Animation::ANIM_TOTAL_DIRS;
01433 }
01434 
01435 const char *VMDApp::animation_dir_name(int i) {
01436 if (i < 0 || i >= Animation::ANIM_TOTAL_DIRS) return NULL;
01437 return animationDirName[i]; 
01438 }
01439 
01440 int VMDApp::animation_set_dir(int d) {
01441 Animation::AnimDir dir = (Animation::AnimDir)d;
01442 anim->anim_dir(dir);
01443 commandQueue->runcommand(new CmdAnimDir(dir));
01444 return 1;
01445 }
01446 
01447 int VMDApp::animation_num_styles() {
01448 return Animation::ANIM_TOTAL_STYLES;
01449 }
01450 
01451 const char *VMDApp::animation_style_name(int i) {
01452 if (i < 0 || i >= Animation::ANIM_TOTAL_STYLES) return NULL;
01453 return animationStyleName[i];
01454 }
01455 
01456 int VMDApp::animation_set_style(int s) {
01457 Animation::AnimStyle style = (Animation::AnimStyle)s;
01458 anim->anim_style(style);
01459 commandQueue->runcommand(new CmdAnimStyle(style));
01460 return 1;
01461 }
01462 
01463 int VMDApp::animation_set_frame(int frame) {
01464 anim->goto_frame(frame);
01465 anim->anim_dir(Animation::ANIM_PAUSE);
01466 commandQueue->runcommand(new CmdAnimJump(frame));
01467 return 1;
01468 }
01469 
01470 int VMDApp::animation_set_stride(int stride) {
01471 anim->skip(stride);
01472 commandQueue->runcommand(new CmdAnimSkip(stride));
01473 return 1;
01474 }
01475 
01476 int VMDApp::animation_set_speed(float speed) {
01477 anim->speed(speed);
01478 commandQueue->runcommand(new CmdAnimSpeed(speed));
01479 return 1;
01480 }
01481 
01482 const char *VMDApp::filerender_default_option(const char *m) {
01483 FileRenderer *ren = fileRenderList->find(m);
01484 if (!ren) {
01485 return NULL;
01486 }
01487 return ren->default_exec_string();
01488 }
01489 const char *VMDApp::filerender_default_filename(const char *m) {
01490 FileRenderer *ren = fileRenderList->find(m);
01491 if (!ren) {
01492 return NULL;
01493 }
01494 return ren->default_filename();
01495 }
01496 
01497 
01498 // plugin stuff 
01499 
01500 vmdplugin_t *VMDApp::get_plugin(const char *type, const char *name) {
01501 if (!pluginMgr) return NULL;
01502 if (!type || !name) return NULL;
01503 PluginList p;
01504 vmdplugin_t *plugin = NULL;
01505 if (pluginMgr->plugins(p, type, name)) {
01506 plugin = p[0];
01507 
01508 // loop over plugins and select the highest version number for a 
01509 // given plugin type/name combo.
01510 for (int i=1; i<p.num(); i++) {
01511 vmdplugin_t *curplugin = p[i];
01512 if (curplugin->majorv > plugin->majorv || 
01513 (curplugin->majorv == plugin->majorv && curplugin->minorv > plugin->minorv))
01514 plugin = curplugin;
01515 }
01516 } 
01517 return plugin;
01518 }
01519 
01520 int VMDApp::list_plugins(PluginList &p, const char *type) {
01521 if (!pluginMgr) return 0;
01522 return pluginMgr->plugins(p, type);
01523 }
01524 
01525 int VMDApp::plugin_dlopen(const char *filename) {
01526 if (!pluginMgr) {
01527 msgErr << "scan_plugins: no plugin manager available" << sendmsg;
01528 return -1;
01529 }
01530 if (!filename) return -1;
01531 return pluginMgr->load_sharedlibrary_plugins(filename);
01532 }
01533 
01534 void VMDApp::plugin_update() {
01535 commandQueue->runcommand(new CmdPluginUpdate);
01536 }
01537 
01538 void VMDApp::display_update_on(int ison) {
01539 UpdateDisplay = ison;
01540 }
01541 
01542 int VMDApp::display_update_status() {
01543 return (UpdateDisplay != 0);
01544 }
01545 
01546 void VMDApp::display_update() {
01547 int prevUpdateFlag = UpdateDisplay;
01548 UpdateDisplay = 1;
01549 VMDupdate(VMD_IGNORE_EVENTS);
01550 UpdateDisplay = prevUpdateFlag;
01551 }
01552 
01553 void VMDApp::display_update_ui() {
01554 VMDupdate(VMD_CHECK_EVENTS);
01555 }
01556 
01557 int VMDApp::num_color_categories() {
01558 return scene->num_categories();
01559 }
01560 const char *VMDApp::color_category(int n) {
01561 return scene->category_name(n);
01562 }
01563 
01564 int VMDApp::color_add_item(const char *cat, const char *name, const char *defcolor) {
01565 int init_color = scene->color_index(defcolor);
01566 if (init_color < 0) {
01567 msgErr << "Cannot add color item: invalid color name '" << defcolor << "'" << sendmsg;
01568 return FALSE;
01569 }
01570 int ind = scene->category_index(cat);
01571 if (ind < 0) {
01572 ind = scene->add_color_category(cat);
01573 }
01574 if (scene->add_color_item(ind, name, init_color) < 0) {
01575 return FALSE;
01576 }
01577 commandQueue->runcommand(new CmdColorItem(cat, name, defcolor));
01578 return TRUE;
01579 }
01580 
01581 int VMDApp::num_color_category_items(const char *category) {
01582 int colCatIndex = scene->category_index(category);
01583 if (colCatIndex < 0) return 0;
01584 return scene->num_category_items(colCatIndex);
01585 }
01586 const char *VMDApp::color_category_item(const char *category, int n) {
01587 int colCatIndex = scene->category_index(category);
01588 if (colCatIndex < 0) return 0;
01589 return scene->category_item_name(colCatIndex, n); // XXX check valid n
01590 }
01591 int VMDApp::num_colors() {
01592 return MAXCOLORS;
01593 }
01594 int VMDApp::num_regular_colors() {
01595 return REGCLRS;
01596 }
01597 const char *VMDApp::color_name(int n) {
01598 return scene->color_name(n);
01599 }
01600 int VMDApp::color_index(const char *color) {
01601 if (!color) return -1;
01602 // If it's a number in the valid range, return the number; otherwise return
01603 // -1.
01604 int i;
01605 if (sscanf(color, "%d", &i)) {
01606 if (i >= 0 && i < MAXCOLORS)
01607 return i;
01608 else
01609 return -1;
01610 }
01611 // look up the color by name.
01612 return scene->color_index(color);
01613 } 
01614 int VMDApp::color_value(const char *colorname, float *r, float *g, float *b) {
01615 int colIndex = color_index(colorname);
01616 if (colIndex < 0) return 0;
01617 const float *col = scene->color_value(colIndex);
01618 *r = col[0];
01619 *g = col[1];
01620 *b = col[2];
01621 return 1;
01622 }
01623 int VMDApp::color_default_value(const char *colorname, float *r, float *g, float *b) {
01624 int colIndex = color_index(colorname);
01625 if (colIndex < 0) return 0;
01626 const float *col = scene->color_default_value(colIndex);
01627 *r = col[0];
01628 *g = col[1];
01629 *b = col[2];
01630 return 1;
01631 }
01632 const char *VMDApp::color_mapping(const char *category, const char *item) {
01633 
01634 int colCatIndex = scene->category_index(category);
01635 if (colCatIndex < 0) return 0;
01636 
01637 int colNameIndex = scene->category_item_index(colCatIndex, item);
01638 if (colNameIndex < 0) return 0;
01639 
01640 int ind = scene->category_item_value(colCatIndex, colNameIndex);
01641 return scene->color_name(ind);
01642 }
01643 
01644 const char *VMDApp::color_get_restype(const char *resname) {
01645 int id = moleculeList->resTypes.typecode(resname);
01646 if (id < 0) return NULL;
01647 return moleculeList->resTypes.data(id);
01648 }
01649 
01650 int VMDApp::color_set_restype(const char *resname, const char *restype) {
01651 int cat = moleculeList->colorCatIndex[MLCAT_RESTYPES];
01652 int ind = scene->category_item_index(cat, restype);
01653 if (ind < 0) return FALSE; // nonexistent restype category
01654 
01655 // Use the string stored in Scene rather than the one passed to this
01656 // function, since then we don't have to worry about copying it and
01657 // freeing it later.
01658 const char *stable_restype_name = scene->category_item_name(cat, ind);
01659 
01660 // if the resname doesn't have an entry yet, create one.
01661 int resname_id = moleculeList->resTypes.add_name(resname, restype);
01662 moleculeList->resTypes.set_data(resname_id, stable_restype_name);
01663 scene->root.color_changed(cat);
01664 return TRUE;
01665 }
01666 
01667 int VMDApp::colorscale_params(float *mid, float *min, float *max, 
01668 int *rev, int *posterize) {
01669 scene->colorscale_params(mid, min, max, rev, posterize);
01670 return 1;
01671 }
01672 int VMDApp::num_colorscale_methods() {
01673 return scene->num_colorscale_methods();
01674 }
01675 int VMDApp::colorscale_method_current() {
01676 return scene->colorscale_method();
01677 }
01678 const char *VMDApp::colorscale_method_name(int n) {
01679 if (n < 0 || n >= scene->num_colorscale_methods()) return NULL;
01680 return scene->colorscale_method_name(n);
01681 }
01682 const char *VMDApp::colorscale_method_menuname(int n) {
01683 if (n < 0 || n >= scene->num_colorscale_methods()) return NULL;
01684 return scene->colorscale_method_menuname(n);
01685 }
01686 int VMDApp::colorscale_method_index(const char *method) {
01687 for (int i=0; i<scene->num_colorscale_methods(); i++) {
01688 if (!strupncmp(method, scene->colorscale_method_name(i),CMDLEN)) {
01689 return i;
01690 }
01691 }
01692 return -1;
01693 } 
01694 
01695 int VMDApp::get_colorscale_colors(int whichScale, 
01696 float min[3], float mid[3], float max[3]) {
01697 return scene->get_colorscale_colors(whichScale, min, mid, max);
01698 }
01699 
01700 int VMDApp::set_colorscale_colors(int whichScale, 
01701 const float min[3], const float mid[3], const float max[3]) {
01702 if (scene->set_colorscale_colors(whichScale, min, mid, max)) {
01703 commandQueue->runcommand(new CmdColorScaleColors(
01704 scene->colorscale_method_name(whichScale), mid, min, max));
01705 return TRUE;
01706 }
01707 return FALSE;
01708 }
01709 
01710 
01711 int VMDApp::color_change_name(const char *category, const char *colorname, 
01712 const char *color) {
01713 
01714 if (!category || !colorname || !color) return 0;
01715 
01716 int colCatIndex = scene->category_index(category);
01717 if (colCatIndex < 0) return 0;
01718 
01719 int colNameIndex = scene->category_item_index(colCatIndex, colorname);
01720 if (colNameIndex < 0) return 0;
01721 
01722 int newIndex = color_index(color);
01723 if (newIndex < 0) return 0;
01724 
01725 // all systems go...
01726 scene->set_category_item(colCatIndex, colNameIndex, newIndex);
01727 
01728 // tell the rest of the world
01729 commandQueue->runcommand(new CmdColorName(category, colorname, color));
01730 return 1;
01731 }
01732 
01733 
01734 int VMDApp::color_change_namelist(int numcols, char **category, 
01735 char **colorname, char **color) {
01736 if (numcols < 1 || !category || !colorname || !color) return 0;
01737 
01738 int i;
01739 for (i=0; i<numcols; i++) {
01740 int colCatIndex = scene->category_index(category[i]);
01741 if (colCatIndex < 0) return 0;
01742 
01743 int colNameIndex = scene->category_item_index(colCatIndex, colorname[i]);
01744 if (colNameIndex < 0) return 0;
01745 
01746 int newIndex = color_index(color[i]);
01747 if (newIndex < 0) return 0;
01748 
01749 // all systems go...
01750 scene->set_category_item(colCatIndex, colNameIndex, newIndex);
01751 }
01752 
01753 // XXX need a new command for this 
01754 // commandQueue->runcommand(new CmdColorName(category, colorname, color));
01755 return 1;
01756 }
01757 
01758 
01759 
01760 int VMDApp::color_get_from_name(const char *category, const char *colorname, 
01761 const char **color) {
01762 
01763 if (!category || !colorname) return 0;
01764 
01765 int colCatIndex = scene->category_index(category);
01766 if (colCatIndex < 0) return 0;
01767 
01768 int colNameIndex = scene->category_item_index(colCatIndex, colorname);
01769 if (colNameIndex < 0) return 0;
01770 
01771 // all systems go...
01772 int colIndex = scene->get_category_item(colCatIndex, colNameIndex);
01773 if (colIndex < 0) return 0;
01774 
01775 *color = color_name(colIndex);
01776 
01777 return 1;
01778 }
01779 
01780 
01781 int VMDApp::color_change_rgb(const char *color, float r, float g, float b) {
01782 int ind = color_index(color);
01783 if (ind < 0) return 0;
01784 float rgb[3] = {r, g, b};
01785 scene->set_color_value(ind, rgb);
01786 commandQueue->runcommand(new CmdColorChange(color, r, g, b));
01787 return 1;
01788 }
01789 
01790 
01791 int VMDApp::color_change_rgblist(int numcols, const char **colors, float *rgb3fv) {
01792 if (numcols < 1) return 0;
01793 
01794 int i;
01795 for (i=0; i<numcols; i++) {
01796 int ind = color_index(colors[i]);
01797 if (ind < 0) return 0;
01798 scene->set_color_value(ind, &rgb3fv[i*3]);
01799 }
01800 
01801 // XXX need a new command for this
01802 // commandQueue->runcommand(new CmdColorChange(color, r, g, b));
01803 return 1;
01804 }
01805 
01806 
01807 int VMDApp::colorscale_setparams(float mid, float min, float max, 
01808 int rev, int posterize) {
01809 scene->set_colorscale_params(min, mid, max, rev, posterize);
01810 commandQueue->runcommand(new CmdColorScaleSettings(mid, min, max, rev, posterize));
01811 return 1;
01812 }
01813 
01814 int VMDApp::colorscale_setmethod(int method) {
01815 if (method < 0 || method >= scene->num_colorscale_methods()) return 0;
01816 scene->set_colorscale_method(method);
01817 commandQueue->runcommand(new CmdColorScaleMethod(
01818 scene->colorscale_method_name(method)));
01819 return 1;
01820 }
01821 
01822 
01823 int VMDApp::logfile_read(const char *path) {
01824 uiText->read_from_file(path);
01825 return 1;
01826 }
01827 
01828 int VMDApp::save_state() {
01829 char *file = vmd_choose_file(
01830 "Enter filename to save current VMD state:", // Title
01831 "*.vmd", // extension
01832 "VMD files", // label
01833 1 // do_save
01834 );
01835 if (!file)
01836 return 1;
01837 int retval = uiText->save_state(file);
01838 delete [] file;
01839 return retval;
01840 }
01841 
01842 int VMDApp::num_molecules() {
01843 return moleculeList->num();
01844 }
01845 
01846 
01847 // This creates a blank molecule, for use by "mol new atoms" and the like...
01848 int VMDApp::molecule_new(const char *name, int natoms, int docallbacks) {
01849 PROFILE_PUSH_RANGE("VMDApp::molecule_new()", 5);
01850 
01851 // if we aren't given a name for the molecule, use a temp name
01852 Molecule *newmol = new Molecule((name == NULL) ? "molecule" : name,
01853 this, &(scene->root));
01854 moleculeList->add_molecule(newmol);
01855 int molid = newmol->id();
01856 
01857 // If we aren't given a name for the molecule, we auto-generate one
01858 // from the assigned molid.
01859 if (name == NULL) {
01860 char buf[30];
01861 sprintf(buf, "molecule%d", molid);
01862 #if 1
01863 // We rename the molecule for ourselves without calling molecule_rename()
01864 // in order to avoid triggering extra callbacks that cause expensive 
01865 // GUI redraws.
01866 newmol->rename(buf);
01867 
01868 // Add item to Molecule color category; default color should be the same as
01869 // the original molecule. 
01870 int ind = moleculeList->colorCatIndex[MLCAT_MOLECULES];
01871 scene->add_color_item(ind, buf, molid % VISCLRS);
01872 #else
01873 molecule_rename(molid, buf);
01874 #endif
01875 }
01876 
01877 if (natoms > 0) {
01878 int i;
01879 newmol->init_atoms(natoms);
01880 
01881 float *charge = newmol->charge();
01882 float defcharge = newmol->default_charge("X");
01883 for (i=0; i<natoms; i++)
01884 charge[i] = defcharge;
01885 
01886 float *mass = newmol->mass();
01887 float defmass = newmol->default_mass("X");
01888 for (i=0; i<natoms; i++)
01889 mass[i] = defmass;
01890 
01891 float *radius = newmol->radius();
01892 float defradius = newmol->default_radius("X");
01893 for (i=0; i<natoms; i++)
01894 radius[i] = defradius;
01895 
01896 float *beta = newmol->beta();
01897 float defbeta = newmol->default_beta();
01898 for (i=0; i<natoms; i++)
01899 beta[i] = defbeta;
01900 
01901 float *occupancy = newmol->occupancy();
01902 float defoccupancy = newmol->default_occup();
01903 for (i=0; i<natoms; i++)
01904 occupancy[i] = defoccupancy;
01905 
01906 // add all of the atoms in a single call, looping internally in add_atoms()
01907 if (0 > newmol->add_atoms(natoms, "X", "X", 0, "UNK", 0, "", "", " ", "")) {
01908 // if an error occured while adding an atom, we should delete
01909 // the offending molecule since the data is presumably inconsistent,
01910 // or at least not representative of what we tried to load
01911 msgErr << "VMDApp::molecule_new: molecule creation aborted" << sendmsg;
01912 return -1; // signal failure
01913 }
01914 }
01915 
01916 if (docallbacks) {
01917 commandQueue->runcommand(new CmdMolNew);
01918 commandQueue->runcommand(new MoleculeEvent(molid, MoleculeEvent::MOL_NEW));
01919 commandQueue->runcommand(new InitializeStructureEvent(molid, 1));
01920 }
01921 
01922 PROFILE_POP_RANGE();
01923 
01924 return molid; 
01925 } 
01926 
01927 
01928 int VMDApp::molecule_from_selection_list(const char *name, int mergemode,
01929 int numsels, AtomSel **sellist, 
01930 int docallbacks) {
01931 PROFILE_PUSH_RANGE("VMDApp::molecule_from_selection_lis()", 3);
01932 
01933 // sanity check on contents of atom selection list
01934 int natoms=0;
01935 int selidx, i=0, j=0;
01936 int havecoords=0, allhavecoords=0;
01937 for (selidx=0; selidx<numsels; selidx++) {
01938 natoms += sellist[selidx]->selected;
01939 if (sellist[selidx]->coordinates(moleculeList) != NULL)
01940 havecoords++;
01941 } 
01942 if (havecoords==numsels) {
01943 allhavecoords=1;
01944 }
01945 havecoords = (havecoords != 0);
01946 msgInfo << "Building new molecule with " << natoms 
01947 << " atoms from " << numsels << " selections." << sendmsg;
01948 if (allhavecoords) {
01949 msgInfo << "All atoms will be assigned atomic coordinates." << sendmsg;
01950 } else if (havecoords) {
01951 msgInfo << "Some atoms will be assigned atomic coordinates." << sendmsg;
01952 } else {
01953 msgInfo << "No atomic atomic coordinates assigned from selection list." << sendmsg;
01954 }
01955 
01956 // if we aren't given a name for the molecule, use a temp name
01957 Molecule *newmol = new Molecule((name == NULL) ? "molecule" : name,
01958 this, &(scene->root));
01959 moleculeList->add_molecule(newmol);
01960 int molid = newmol->id();
01961 
01962 // If we aren't given a name for the molecule, we auto-generate one
01963 // from the assigned molid.
01964 if (name == NULL) {
01965 char buf[30];
01966 sprintf(buf, "molecule%d", molid);
01967 #if 1
01968 // We rename the molecule for ourselves without calling molecule_rename()
01969 // in order to avoid triggering extra callbacks that cause expensive 
01970 // GUI redraws.
01971 newmol->rename(buf);
01972 
01973 // Add item to Molecule color category; default color should be the same as
01974 // the original molecule. 
01975 int ind = moleculeList->colorCatIndex[MLCAT_MOLECULES];
01976 scene->add_color_item(ind, buf, molid % VISCLRS);
01977 #else
01978 molecule_rename(molid, buf);
01979 #endif
01980 }
01981 
01982 // initialize molecule and copy data from selected atoms into the
01983 // final molecule structure 
01984 newmol->init_atoms(natoms);
01985 
01986 // add a timestep for atomic coordinates, if we have them
01987 Timestep *ts = NULL;
01988 if (havecoords) {
01989 ts = new Timestep(natoms);
01990 newmol->append_frame(ts);
01991 }
01992 
01993 float *charge = newmol->charge();
01994 float *mass = newmol->mass();
01995 float *radius = newmol->radius();
01996 float *beta = newmol->beta();
01997 float *occupancy = newmol->occupancy();
01998 
01999 int naidx=0;
02000 for (selidx=0; selidx<numsels; selidx++) {
02001 const AtomSel *s = sellist[selidx];
02002 Molecule *sm = moleculeList->mol_from_id(s->molid());
02003 
02004 #if 0
02005 printf("selected mol[%d]: '%s'\n" 
02006 " %d atoms, %d residues, %d frags, %d protein, %d nucleic,\n"
02007 " %d selected first: %d last: %d\n", 
02008 s->molid(), sm->molname(),
02009 sm->nAtoms, sm->nResidues, sm->nFragments, 
02010 sm->nProteinFragments, sm->nNucleicFragments,
02011 s->selected, s->firstsel, s->lastsel);
02012 #endif
02013 
02014 // build a mapping from original atom indices to new atom indices
02015 int *atomindexmap = (int *) calloc(1, sm->nAtoms*sizeof(int));
02016 
02017 // initialize the atom index map to an invalid atom index value, so that
02018 // we can use this to eliminate bonds to atoms that aren't selected.
02019 for (j=0; j<sm->nAtoms; j++)
02020 atomindexmap[j] = -1;
02021 
02022 const float *s_charge = sm->charge();
02023 const float *s_mass = sm->mass();
02024 const float *s_radius = sm->radius();
02025 const float *s_beta = sm->beta();
02026 const float *s_occupancy = sm->occupancy();
02027 
02028 const Timestep *s_ts = s->timestep(moleculeList);
02029 
02030 // copy PBC unit cell information from first selection, when possible
02031 if (selidx == 0 && ts != NULL && s_ts != NULL) {
02032 ts->a_length = s_ts->a_length;
02033 ts->b_length = s_ts->b_length;
02034 ts->c_length = s_ts->c_length;
02035 ts->alpha = s_ts->alpha;
02036 ts->beta = s_ts->beta;
02037 ts->gamma = s_ts->gamma;
02038 }
02039 
02040 int saidx=s->firstsel;
02041 while (saidx<=s->lastsel) {
02042 if (s->on[saidx]) {
02043 const MolAtom *satm = sm->atom(saidx);
02044 #if 0
02045 printf("Adding satom[%d, %p] as atom[%d] nameidx: %d '%s'\n", 
02046 saidx, satm, naidx, satm->nameindex,
02047 sm->atomNames.name(satm->nameindex));
02048 #endif
02049 
02050 newmol->add_atoms(1, 
02051 sm->atomNames.name(satm->nameindex), 
02052 sm->atomTypes.name(satm->typeindex),
02053 satm->atomicnumber,
02054 sm->resNames.name(satm->resnameindex),
02055 satm->resid,
02056 sm->chainNames.name(satm->chainindex),
02057 sm->segNames.name(satm->segnameindex),
02058 satm->insertionstr,
02059 sm->altlocNames.name(satm->altlocindex));
02060 
02061 // copy atomic coordinates and other per-atom data if possible
02062 if (ts != NULL && s_ts != NULL) {
02063 #if 0
02064 printf("Copying atomic coordinates for atom[%d] from orig[%d]...\n", naidx, saidx);
02065 #endif
02066 long naddr = naidx*3;
02067 long saddr = saidx*3;
02068 
02069 // copy atomic coordinates
02070 ts->pos[naddr ] = s_ts->pos[saddr ];
02071 ts->pos[naddr + 1] = s_ts->pos[saddr + 1];
02072 ts->pos[naddr + 2] = s_ts->pos[saddr + 2];
02073 
02074 // XXX copy velocities, user fields, etc
02075 }
02076 
02077 // copy contents of the other per-atom fields
02078 charge[naidx] = s_charge[saidx];
02079 mass[naidx] = s_mass[saidx];
02080 radius[naidx] = s_radius[saidx];
02081 beta[naidx] = s_beta[saidx];
02082 occupancy[naidx] = s_occupancy[saidx];
02083 
02084 // build index map for bond/angle/dihedral/cterms
02085 atomindexmap[saidx] = naidx;
02086 
02087 naidx++; // increment total count of atoms built in new mol
02088 }
02089 
02090 // copy dataset flags from parent molecule(s)
02091 newmol->datasetflags |= sm->datasetflags;
02092 
02093 saidx++; // increment selected molecule atom index
02094 }
02095 
02096 // copy bonds to atoms that are also included in the selection
02097 j=0;
02098 for (saidx=s->firstsel; saidx<=s->lastsel; saidx++) {
02099 if (s->on[saidx]) {
02100 int newidx = naidx - s->selected + j; // index of new atom
02101 const MolAtom *satm = sm->atom(saidx);
02102 #if 0
02103 printf("atom[%d] (orig[%d]): %d bonds\n", newidx, saidx, satm->bonds);
02104 #endif
02105 int k;
02106 for (k=0; k<satm->bonds; k++) {
02107 float bondorder = 1;
02108 int bondtype = -1;
02109 int bto = satm->bondTo[k];
02110 int btmap = atomindexmap[bto];
02111 if (btmap >= 0) {
02112 #if 0
02113 printf("+bond from[%d] to [%d]\n", newidx, btmap);
02114 #endif
02115 // we must ensure that we do not duplicate bonds, so we
02116 // only add bonds to atoms with a higher index than our own
02117 if (btmap > newidx)
02118 newmol->add_bond(newidx, btmap, bondorder, bondtype);
02119 } 
02120 #if 0
02121 else {
02122 printf("-bond from[%d] to [%d] (%d to %d)\n", newidx, btmap, saidx, bto);
02123 }
02124 #endif
02125 }
02126 j++;
02127 }
02128 }
02129 
02130 #if 0
02131 printf("processing angles...\n");
02132 #endif
02133 // copy angles/dihedrals/impropers that are included in the selection
02134 int numangles = sm->num_angles();
02135 int numdihedrals = sm->num_dihedrals();
02136 int numimpropers = sm->num_impropers();
02137 int numcterms = sm->num_cterms();
02138 
02139 for (i=0; i<numangles; i++) {
02140 long i3addr = i*3L;
02141 int idx0 = atomindexmap[sm->angles[i3addr ]];
02142 int idx1 = atomindexmap[sm->angles[i3addr + 1]];
02143 int idx2 = atomindexmap[sm->angles[i3addr + 2]];
02144 if ((idx0 >= 0) && (idx1 >= 0) && (idx2 >= 0)) {
02145 newmol->add_angle(idx0, idx1, idx2); 
02146 }
02147 }
02148 
02149 #if 0
02150 printf("processing dihedrals...\n");
02151 #endif
02152 for (i=0; i<numdihedrals; i++) {
02153 long i4addr = i*4L;
02154 int idx0 = atomindexmap[sm->dihedrals[i4addr ]];
02155 int idx1 = atomindexmap[sm->dihedrals[i4addr + 1]];
02156 int idx2 = atomindexmap[sm->dihedrals[i4addr + 2]];
02157 int idx3 = atomindexmap[sm->dihedrals[i4addr + 3]];
02158 if ((idx0 >= 0) && (idx1 >= 0) && (idx2 >= 0) && (idx3 >= 0)) {
02159 newmol->add_dihedral(idx0, idx1, idx2, idx3);
02160 }
02161 }
02162 
02163 #if 0
02164 printf("processing numimpropers...\n");
02165 #endif
02166 for (i=0; i<numimpropers; i++) {
02167 long i4addr = i*4L;
02168 int idx0 = atomindexmap[sm->impropers[i4addr ]];
02169 int idx1 = atomindexmap[sm->impropers[i4addr + 1]];
02170 int idx2 = atomindexmap[sm->impropers[i4addr + 2]];
02171 int idx3 = atomindexmap[sm->impropers[i4addr + 3]];
02172 if ((idx0 >= 0) && (idx1 >= 0) && (idx2 >= 0) && (idx3 >= 0)) {
02173 newmol->add_improper(idx0, idx1, idx2, idx3);
02174 }
02175 }
02176 
02177 #if 0
02178 printf("processing numcterms...\n");
02179 #endif
02180 for (i=0; i<numcterms; i++) {
02181 long i8addr = i*8L;
02182 int idx0 = atomindexmap[sm->cterms[i8addr ]];
02183 int idx1 = atomindexmap[sm->cterms[i8addr + 1]];
02184 int idx2 = atomindexmap[sm->cterms[i8addr + 2]];
02185 int idx3 = atomindexmap[sm->cterms[i8addr + 3]];
02186 int idx4 = atomindexmap[sm->cterms[i8addr + 4]];
02187 int idx5 = atomindexmap[sm->cterms[i8addr + 5]];
02188 int idx6 = atomindexmap[sm->cterms[i8addr + 6]];
02189 int idx7 = atomindexmap[sm->cterms[i8addr + 7]];
02190 
02191 if ((idx0 >= 0) && (idx1 >= 0) && (idx2 >= 0) && (idx3 >= 0) &&
02192 (idx4 >= 0) && (idx5 >= 0) && (idx6 >= 0) && (idx7 >= 0)) {
02193 newmol->add_cterm(idx0, idx1, idx2, idx3, 
02194 idx4, idx5, idx6, idx7);
02195 }
02196 }
02197 
02198 // XXX need to implement handling for 
02199 // angle types, dihedral types, and improper types (names)
02200 
02201 free(atomindexmap);
02202 }
02203 
02204 
02205 #if 0
02206 // add all of the atoms in a single call, looping internally in add_atoms()
02207 if (0 > newmol->add_atoms(natoms, "X", "X", 0, "UNK", 0, "", "", " ", "")) {
02208 // if an error occured while adding an atom, we should delete
02209 // the offending molecule since the data is presumably inconsistent,
02210 // or at least not representative of what we tried to load
02211 msgErr << "VMDApp::molecule_new: molecule creation aborted" << sendmsg;
02212 PROFILE_POP_RANGE();
02213 return -1; // signal failure
02214 }
02215 #endif
02216 
02217 // Cause VMD to analyze the newly-created atomic structure, so that
02218 // data such as the "residue" field get populated.
02219 newmol->analyze();
02220 
02221 if (docallbacks) {
02222 commandQueue->runcommand(new CmdMolNew);
02223 commandQueue->runcommand(new MoleculeEvent(molid, MoleculeEvent::MOL_NEW));
02224 commandQueue->runcommand(new InitializeStructureEvent(molid, 1));
02225 }
02226 
02227 PROFILE_POP_RANGE();
02228 
02229 return molid; 
02230 } 
02231 
02232 
02233 const char *VMDApp::guess_filetype(const char *filename) {
02234 const char *ext = strrchr(filename, '.');
02235 if (!ext) {
02236 // check for webpdb
02237 if (strlen(filename) == 4) {
02238 return "webpdb";
02239 }
02240 msgWarn << "Unable to ascertain filetype from filename '"
02241 << filename << "'; assuming pdb." << sendmsg;
02242 return "pdb";
02243 }
02244 ext++;
02245 char *s = strdup(ext);
02246 char *c = s;
02247 while (*c) { *c = tolower(*c); c++; }
02248 PluginList plugins;
02249 pluginMgr->plugins(plugins, "mol file reader", NULL);
02250 pluginMgr->plugins(plugins, "mol file converter", NULL);
02251 const char *bestname = NULL;
02252 int bestrank = 9999;
02253 for (int i=0; i<plugins.num(); i++) {
02254 // check against comma separated list of filename extensions, 
02255 // no spaces, as in: "pdb,ent,foo,bar,baz,ban"
02256 // Also keep track of the place in the list that the extension was
02257 // found - thus a plugin that lists the extension first can override
02258 // a plugin that comes earlier in the plugin list but lists the
02259 // extension later in its filename_extension string.
02260 MolFilePlugin p(plugins[i]);
02261 char *extbuf = strdup(p.extension());
02262 int extlen = strlen(extbuf);
02263 char *extcur = extbuf;
02264 char *extnext = NULL; 
02265 int currank = 1;
02266 while ((extcur - extbuf) < extlen) { 
02267 extnext = strchr(extcur, ','); // find next extension string
02268 if (extnext) {
02269 *extnext = '0円'; // NUL terminate this extension string
02270 extnext++; // step to beginning of next extension string
02271 } else {
02272 extnext = extbuf + extlen; // no more extensions, last time through
02273 }
02274 if (!strcmp(s, extcur)) {
02275 if (!bestname || currank < bestrank) {
02276 bestname = p.name();
02277 bestrank = currank;
02278 }
02279 }
02280 extcur = extnext;
02281 ++currank;
02282 }
02283 free(extbuf);
02284 }
02285 free(s);
02286 return bestname;
02287 }
02288 
02289 int VMDApp::molecule_load(int molid, const char *filename, 
02290 const char *filetype, const FileSpec *spec) {
02291 int original_molid = molid;
02292 
02293 // Call BaseMolecule::analyze() only once, when structure is first created.
02294 int first_structure = 0;
02295 
02296 // check for valid timestep parameters
02297 if (spec->last != -1 && spec->last < spec->first) {
02298 msgErr << "Invalid last frame: " << spec->last << sendmsg;
02299 return -1;
02300 }
02301 if (spec->stride < 1) {
02302 msgErr << "Invalid stride: " << spec->stride << sendmsg;
02303 return -1;
02304 }
02305 
02306 // if no filetype was given, try to obtain it from the filename.
02307 if (!filetype) {
02308 filetype = guess_filetype(filename);
02309 if (!filetype) {
02310 msgErr << "Could not determine filetype of file '" << filename 
02311 << "' from its name." << sendmsg;
02312 return -1;
02313 }
02314 }
02315 
02316 int waitfor = spec->waitfor;
02317 if (waitfor == 0 && molid == -1) {
02318 // It's not ok to load zero frames for a new molecule because coordinates
02319 // might be needed to determine bonds from atom distances.
02320 waitfor = 1;
02321 msgWarn << "Will load one coordinate frame for new molecule." << sendmsg;
02322 }
02323 
02324 // Prefer to use a direct reader plugin over a translator, if one
02325 // is available. If not, then attempt to use a translator.
02326 vmdplugin_t *p = get_plugin("mol file reader", filetype);
02327 if (!p) p = get_plugin("mol file converter", filetype);
02328 if (!p) {
02329 msgErr << "Cannot read file of type " << filetype << sendmsg;
02330 return -1;
02331 }
02332 MolFilePlugin *plugin = new MolFilePlugin(p);
02333 if (plugin->init_read(filename)) {
02334 msgErr << "Could not read file " << filename << sendmsg;
02335 delete plugin;
02336 return -1;
02337 }
02338 
02339 // Check if VMD has to use page-aligned memory allocations for
02340 // timestep data, to allow for fast kernel-bypass unbuffered I/O APIs
02341 // Note: we make this call after the plugin's open_read() API has been
02342 // called, but before the first call to read_structure(), to ensure
02343 // that the called plugin sees that we have queried the required memory
02344 // alignment page size for all per-timestep data. 
02345 int ts_page_align_sz = 1;
02346 if (plugin->can_read_pagealigned_timesteps()) {
02347 // Determine whether a given file on a local or remote filesystem. 
02348 // We don't engage kernel-bypass direct-I/O when reading from
02349 // remote filesystems, as it turns out that filesystem caching
02350 // mechanisms like the Linux 'cachefilesd' daemon interpret
02351 // Unix direct-I/O (e.g. O_DIRECT) calls to be NFS-cache-bypassing 
02352 // I/O operations, which is not what we want in that particular case.
02353 // We want local NFS caches to be utilized rather than hitting the 
02354 // network, so in the case of remote filesystems we now revert to
02355 // normal I/O. We only engage kernel-bypass I/O when the file of
02356 // interest resides on a local filesystem where there are no 
02357 // surprising side effects from direct-I/O. This is particularly
02358 // beneficial on the NVIDIA DGX-2 which incorporates a large 30+TB
02359 // RAID-0 NFS cache, as an example.
02360 int fslocality = vmd_fstype_locality(filename);
02361 
02362 if (fslocality == VMD_FS_IS_REMOTE) {
02363 msgInfo << "Kernel-bypass direct-I/O disabled for remote filesystem" 
02364 << sendmsg;
02365 }
02366 
02367 #if vmdplugin_ABIVERSION > 17
02368 // If we don't query the page alignment size, the molfile plugin
02369 // will have to assume that we can't support kernel-bypassing
02370 // block-based direct-I/O, and will revert to using normal I/O.
02371 if (fslocality != VMD_FS_IS_REMOTE) {
02372 ts_page_align_sz = plugin->read_timestep_pagealign_size();
02373 }
02374 #endif
02375 }
02376 
02377 // to avoid excessive error handling cleanup, we only push the 
02378 // profiler marker when we've made it through 80% of the error checks
02379 PROFILE_PUSH_RANGE("VMDApp::molecule_load()", 5);
02380 
02381 Molecule *newmol = NULL;
02382 if (molid == -1) {
02383 #if 1
02384 // don't trigger callbacks for MOL_NEW etc yet, as we will be triggering
02385 // more of them below, and we wish to prevent the GUIs from exhibiting
02386 // quadratic behavior -- they regen their molecule choosers from scratch
02387 // in any case where the count of molecules doesn't change (e.g. when
02388 // getting redundant molecule new events from the same load event)
02389 molid = molecule_new(filename, 0, 0);
02390 #else
02391 molid = molecule_new(filename, 0);
02392 #endif
02393 }
02394 newmol = moleculeList->mol_from_id(molid);
02395 if (!newmol) {
02396 msgErr << "Invalid molecule " << molid << sendmsg;
02397 delete plugin;
02398 PROFILE_POP_RANGE();
02399 return -1;
02400 }
02401 
02402 // We've committed to loading as much as we can from the file, so go ahead
02403 // and record it. This needs to be done before the InitializeStructure
02404 // event is triggered so that the list of filenames for the molecule is
02405 // complete and the filename can be used by Tcl/Python scripts that want
02406 // to process the filename when the InitializeStructure even occurs.
02407 char specstr[8192];
02408 sprintf(specstr, "first %d last %d step %d filebonds %d autobonds %d",
02409 spec->first, spec->last, spec->stride, 
02410 spec->filebonds, spec->autobonds);
02411 newmol->record_file(filename, filetype, specstr);
02412 
02413 //
02414 // Molecule file metadata
02415 // 
02416 if (plugin->can_read_metadata()) {
02417 if (plugin->read_metadata(newmol)) {
02418 msgErr << "Error reading metadata." << sendmsg;
02419 } 
02420 } else {
02421 // each file must have something, even if blank 
02422 newmol->record_database("", "");
02423 newmol->record_remarks("");
02424 }
02425 
02426 // 
02427 // Atomic structure and coordinate data
02428 //
02429 if (plugin->can_read_structure()) {
02430 if (!newmol->has_structure()) {
02431 // if the plugin can read structure data and there are a non-zero
02432 // number of atoms, we proceed with reading it, otherwise we bail out
02433 // of reading the structure, consider the outcome as having no structure,
02434 // and continue parsing for other data, e.g., file blocks containing
02435 // rawgraphics, density maps, or other contents independent of atomic
02436 // structure information. Handling of the zero-atoms case is
02437 // required for correct handling of some of the (nascent) 
02438 // PDB hybrid modeling structure files hosted at PDB-Dev that contain
02439 // no atomic structure and only graphics glyph objects.
02440 // In this case, it is not acceptable to get MOLFILE_NUMATOMS_UNKNOWN,
02441 // since we must have an atom count to initialize structure information.
02442 if (plugin->natoms() > 0) {
02443 msgInfo << "Using plugin " << filetype << " for structure file " 
02444 << filename << sendmsg;
02445 
02446 int rc = plugin->read_structure(newmol, spec->filebonds, spec->autobonds);
02447 
02448 // it's not an error to get no structure data from formats that
02449 // don't always contain it, so only report an error when we 
02450 // expected to get structure data and got an error instead.
02451 if (rc != MOLFILE_SUCCESS && rc != MOLFILE_NOSTRUCTUREDATA) {
02452 // tell the user something went wrong, but keep going and try to
02453 // read other information in the file. Perhaps it's better to
02454 // stop immediately and create no molecule if something goes wrong
02455 // at this stage?
02456 msgErr << "molecule_structure: Unable to read structure for molecule "
02457 << molid << sendmsg;
02458 if (rc == MOLFILE_ERROR) {
02459 msgErr << "molecule_structure: severe error indicated by plugin "
02460 << "aborting loading of molecule " << molid << sendmsg;
02461 delete plugin;
02462 PROFILE_POP_RANGE();
02463 return -1;
02464 }
02465 }
02466 
02467 // initialize structure if we loaded with no errors
02468 if (rc == MOLFILE_SUCCESS) {
02469 first_structure = 1;
02470 commandQueue->runcommand(new InitializeStructureEvent(molid, 1));
02471 }
02472 }
02473 } else {
02474 // the molecule already has structure information, so we only look for
02475 // extra/optional structure data.
02476 int rc = plugin->read_optional_structure(newmol, spec->filebonds);
02477 if (rc != MOLFILE_SUCCESS && rc != MOLFILE_NOSTRUCTUREDATA) {
02478 msgErr << 
02479 "Error reading optional structure information from coordinate file "
02480 << filename << sendmsg;
02481 msgErr << "Will ignore structure information in this file." << sendmsg;
02482 }
02483 }
02484 } else {
02485 // Can't read structure, but some plugins (e.g. dcd) can initialize the
02486 // atom number. Do this if possible
02487 // This implies natoms != MOLFILE_NUMATOMS_UNKNOWN
02488 if (plugin->natoms() > 0) {
02489 if (!newmol->init_atoms(plugin->natoms())) {
02490 msgErr << "Invalid number of atoms in file: " << plugin->natoms()
02491 << sendmsg;
02492 }
02493 }
02494 }
02495 
02496 
02497 //
02498 // Read QM metadata and the actual data in one swoop
02499 // for now. We might have to separate these later.
02500 // 
02501 if (plugin->can_read_qm()) {
02502 if (plugin->read_qm_data(newmol)) {
02503 msgErr << "Error reading metadata." << sendmsg;
02504 } 
02505 }
02506 
02507 
02508 //
02509 // Volumetric data
02510 // We proceed with attempting to volumetric density maps for any plugin
02511 // that advertises the possibility of their existence. This is done 
02512 // independently of the availability of any atomic structure information. 
02513 if (plugin->can_read_volumetric()) {
02514 if (plugin->read_volumetric(newmol, spec->nvolsets, spec->setids)) {
02515 msgErr << "Error reading volumetric data." << sendmsg;
02516 } else {
02517 scene_resetview_newmoldata(); // reset the view so we can see the dataset.
02518 commandQueue->runcommand(new CmdMolVolume(molid));
02519 }
02520 }
02521 
02522 
02523 // 
02524 // Raw graphics
02525 // We proceed with attempting to read graphics objects for any plugin
02526 // that advertises the possibility of their existence. This is done 
02527 // independently of the availability of any atomic structure information. 
02528 if (plugin->can_read_graphics()) {
02529 if (plugin->read_rawgraphics(newmol, scene)) {
02530 msgErr << "Reading raw graphics failed." << sendmsg;
02531 } else {
02532 scene_resetview_newmoldata(); // reset the view so we can see the dataset.
02533 }
02534 }
02535 
02536 //
02537 // Timesteps:
02538 // At present we only read timesteps if we have a non-zero atom count,
02539 // or the trajectory plugin returns MOLFILE_NUMATOMS_UNKNOWN, indicating
02540 // that it has to be paired with a struture file containing a known
02541 // atom count. This is needed by AMBER CRD files, among others.
02542 // It may become necessary to alter this logic if we later on have
02543 // trajectory file formats that mix in non-atomic information that is
02544 // present independent of any atomic coordinates.
02545 if ((plugin->can_read_timesteps() || plugin->can_read_qm_timestep()) &&
02546 ((plugin->natoms()==MOLFILE_NUMATOMS_UNKNOWN) || (plugin->natoms()>0))) {
02547 msgInfo << "Using plugin " << filetype << " for coordinates from file " 
02548 << filename << sendmsg;
02549 
02550 // Report use of direct block-based I/O when applicable
02551 if (ts_page_align_sz > 1)
02552 msgInfo << " Direct I/O block size: " << ts_page_align_sz << sendmsg;
02553 
02554 if (!newmol->nAtoms) {
02555 msgErr << "Some frames from file '" << filename << "' could not be loaded"
02556 << sendmsg;
02557 msgErr << "because the number of atoms could not be determined. Load a"
02558 << sendmsg;
02559 msgErr << "structure file first, then try loading this file again." << sendmsg;
02560 } else {
02561 // CoorPluginData also checks whether it has to use page-aligned 
02562 // memory allocations for incoming timestep data, to allow for 
02563 // fast kernel-bypass unbuffered I/O APIs, handling of padded and
02564 // aligned allocations is then taken care of in Timestep constructors
02565 CoorPluginData *data = new CoorPluginData(
02566 filename, newmol, plugin, 1, spec->first, spec->stride, spec->last);
02567 
02568 #if 0
02569 // Abort if there was a problem initializing coordinates, such as if
02570 // number of atoms doesn't match the topology. The plugin field is
02571 // used as a canary in the CoorPluginData constructor for this purpose.
02572 if (!data->is_valid()) {
02573 msgErr << "Problem loading coordinate data. Aborting loading of "
02574 << "molecule " << molid << sendmsg;
02575 delete data;
02576 delete plugin;
02577 PROFILE_POP_RANGE();
02578 return -1;
02579 }
02580 #endif
02581 
02582 newmol->add_coor_file(data);
02583 if (waitfor < 0) {
02584 // drain the I/O queue of all frames, even those that didn't necessarily
02585 // come from this file.
02586 while (newmol->next_frame());
02587 } else {
02588 // read waitfor frames.
02589 for (int i=0; i<waitfor; i++)
02590 if (!newmol->next_frame()) break;
02591 }
02592 }
02593 } else {
02594 // Delete the plugin unless timesteps were loaded, in which case the 
02595 // plugin will be deleted by the CoorPluginData object.
02596 delete plugin;
02597 plugin = NULL;
02598 }
02599 
02600 // Now go back and analyze structure, since we may have had to load
02601 // timesteps first.
02602 if (first_structure) {
02603 // build structure information for this molecule
02604 newmol->analyze(); 
02605 
02606 // Must add color names here because atom names and such aren't defined
02607 // until there's a molecular structure.
02608 moleculeList->add_color_names(moleculeList->mol_index_from_id(molid));
02609 
02610 // force all colors and reps to be recalculated, since this may be 
02611 // loaded into a molecule that didn't previously contain atomic data
02612 newmol->force_recalc(DrawMolItem::COL_REGEN | DrawMolItem::SEL_REGEN);
02613 
02614 // since atom color definitions are now established, create a new 
02615 // representation using the default parameters.
02616 moleculeList->set_color((char *)moleculeList->default_color());
02617 moleculeList->set_representation((char *)moleculeList->default_representation());
02618 moleculeList->set_selection(moleculeList->default_selection());
02619 moleculeList->set_material((char *)moleculeList->default_material());
02620 molecule_addrep(newmol->id());
02621 scene_resetview_newmoldata(); // reset the view so we can see the dataset.
02622 }
02623 
02624 // If the molecule doesn't have any reps yet and we have volume data,
02625 // add a new Isosurface rep.
02626 if (!newmol->components() && newmol->num_volume_data()) {
02627 molecule_set_style("Isosurface");
02628 molecule_addrep(newmol->id());
02629 }
02630 
02631 commandQueue->runcommand(new CmdMolLoad(original_molid, filename, filetype, 
02632 spec));
02633 
02634 PROFILE_POP_RANGE();
02635 return molid;
02636 }
02637 
02638 
02639 int VMDApp::molecule_savetrajectory(int molid, const char *fname, 
02640 const char *type, const FileSpec *spec) {
02641 Molecule *newmol = moleculeList->mol_from_id(molid);
02642 if (!newmol) {
02643 msgErr << "Invalid molecule id " << molid << sendmsg;
02644 return -1;
02645 }
02646 if (fname == NULL) {
02647 msgErr << "Invalid NULL filename string" << sendmsg;
02648 return -1;
02649 }
02650 
02651 int first = spec->first;
02652 int last = spec->last;
02653 int stride = spec->stride;
02654 int waitfor = spec->waitfor;
02655 int nframes = 0;
02656 int natoms = 0;
02657 const int *selection = spec->selection;
02658 CoorData *data = NULL;
02659 int savevoldata = (newmol->num_volume_data() > 0) && (spec->nvolsets != 0);
02660 
02661 // Determine number of atoms to write.
02662 natoms = newmol->nAtoms;
02663 if (selection) {
02664 natoms=0;
02665 // the selection cannot change as the trajectory is written out,
02666 // so this is a safe way to count selected atoms
02667 for (int i=0; i<newmol->nAtoms; i++)
02668 natoms += selection[i] ? 1 : 0;
02669 }
02670 
02671 // validate timesteps if we actually have atomic coordinates to write
02672 if (natoms > 0) {
02673 if (last == -1)
02674 last = newmol->numframes() - 1;
02675 
02676 if (last < first && last >= 0) {
02677 msgErr << "Invalid last frame: " << last << sendmsg;
02678 return -1;
02679 }
02680 
02681 if (stride == -1 || stride == 0)
02682 stride = 1; // save all frames 
02683 
02684 if (stride < 1) {
02685 msgErr << "Invalid stride: " << stride << sendmsg;
02686 return -1;
02687 }
02688 
02689 nframes = (last-first)/stride + 1;
02690 if (nframes < 1 && !savevoldata) {
02691 msgInfo << "Save Trajectory: 0 frames specified; no coordinates written."
02692 << sendmsg;
02693 return 0;
02694 }
02695 
02696 if (natoms < 1 && !savevoldata) {
02697 msgInfo << "Save Trajectory: 0 atoms in molecule or selection; no coordinates written."
02698 << sendmsg;
02699 return -1;
02700 }
02701 }
02702 
02703 // Prefer to use a direct reader plugin over a translator, if one
02704 // is available. If not, then attempt to use a translator.
02705 vmdplugin_t *p = get_plugin("mol file reader", type);
02706 if (!p) p = get_plugin("mol file converter", type);
02707 MolFilePlugin *plugin = NULL;
02708 if (p) {
02709 plugin = new MolFilePlugin(p);
02710 if (plugin->init_write(fname, natoms)) {
02711 msgErr << "Unable to open file " << fname << " of type " << type
02712 << " for writing frames." << sendmsg;
02713 delete plugin;
02714 return -1;
02715 }
02716 data = new CoorPluginData(fname, newmol, plugin, 0, first, stride, last,
02717 selection);
02718 } else {
02719 msgErr << "Unknown coordinate file type " << type << sendmsg;
02720 return -1;
02721 }
02722 if (data == NULL) {
02723 msgErr << "NULL data returned by plugin " << sendmsg;
02724 return -1;
02725 } 
02726 msgInfo << "Opened coordinate file " << fname << " for writing.";
02727 msgInfo << sendmsg;
02728 
02729 // to avoid excessive error handling cleanup, we only push the 
02730 // profiler marker when we've made it through 80% of the error checks
02731 PROFILE_PUSH_RANGE("VMDApp::molecule_savetrajectory()", 5);
02732 
02733 // XXX if writing volume sets was requested, do it here, since CoorPluginData 
02734 // doesn't know about that type of data. CoorPluginData should be using
02735 // a FileSpec struct.
02736 if (savevoldata) {
02737 if (plugin->can_write_volumetric()) {
02738 for (int i=0; i<spec->nvolsets; i++) {
02739 if (plugin->write_volumetric(newmol, spec->setids[i]) != 
02740 MOLFILE_SUCCESS) {
02741 msgErr << "Failed to write volume set " << spec->setids[i]
02742 << sendmsg;
02743 }
02744 }
02745 } else {
02746 msgErr << "Cannot write volsets to files of type " << type << sendmsg;
02747 }
02748 }
02749 
02750 // write waitfor frames before adding to the Molecule's queue.
02751 int numwritten = 0;
02752 if (waitfor < 0) {
02753 while (data->next(newmol) == CoorData::NOTDONE)
02754 numwritten++;
02755 
02756 // Don't add to the I/O queue, just complete the I/O transaction 
02757 // synchronously and trigger any necessary callbacks.
02758 // This prevents analysis scripts that don't return control to the
02759 // main loop from queueing up large amounts of I/Os that only needed
02760 // file closures and memory frees to be completed.
02761 newmol->close_coor_file(data);
02762 } else if (waitfor > 0) {
02763 for (int i=0; i<waitfor; i++) {
02764 if (data->next(newmol) == CoorData::DONE) break;
02765 numwritten++;
02766 }
02767 
02768 // Add the I/O to the asynchronous queue and let it continue 
02769 // with subsequent main loop event polling/updates.
02770 newmol->add_coor_file(data);
02771 }
02772 
02773 commandQueue->runcommand(new CmdAnimWriteFile(molid, fname, type,
02774 first, last, stride));
02775 
02776 PROFILE_POP_RANGE();
02777 
02778 return numwritten;
02779 }
02780 
02781 
02782 int VMDApp::molecule_deleteframes(int molid, int first, int last, 
02783 int stride) {
02784 Molecule *mol = moleculeList->mol_from_id(molid);
02785 if (!mol) {
02786 msgErr << "Invalid molecule id " << molid << sendmsg;
02787 return 0;
02788 }
02789 if (!mol->numframes()) return TRUE;
02790 
02791 if (last == -1)
02792 last = mol->numframes()-1;
02793 if (last < first) {
02794 msgErr << "Invalid last frame: " << last << sendmsg;
02795 return 0;
02796 }
02797 
02798 if (stride==-1) stride=0; //delete all frames in range
02799 if (stride < 0) {
02800 msgErr << "Invalid stride: " << stride << sendmsg;
02801 return 0;
02802 }
02803 
02804 // keep every stride frame btw first and last
02805 int indexshift = first; // as frames are deleted, indices are shifted
02806 for (int i=0; i<=last-first; i++) {
02807 if (!stride || i%stride) {
02808 mol->delete_frame(indexshift+i);
02809 indexshift--;
02810 }
02811 }
02812 
02813 commandQueue->runcommand(new CmdAnimDelete(molid, first, last, stride));
02814 return 1;
02815 }
02816 
02817 int VMDApp::molecule_index_from_id(int id) {
02818 if (id < 0) return -1;
02819 return moleculeList->mol_index_from_id(id);
02820 }
02821 int VMDApp::molecule_id(int i) {
02822 if (i < 0 || i >= num_molecules()) return -1;
02823 Molecule *m = moleculeList->molecule(i);
02824 if (m == NULL)
02825 return -1;
02826 return m->id();
02827 }
02828 int VMDApp::molecule_valid_id(int molid) {
02829 return (moleculeList->mol_from_id(molid) != NULL);
02830 }
02831 int VMDApp::molecule_cancel_io(int molid) {
02832 Molecule *m = moleculeList->mol_from_id(molid);
02833 if (!m) return 0;
02834 m->cancel();
02835 commandQueue->runcommand(new CmdMolCancel(molid));
02836 return 1;
02837 }
02838 
02839 int VMDApp::molecule_delete(int molid) {
02840 if (moleculeList->del_molecule(molid)) {
02841 commandQueue->runcommand(new CmdMolDelete(molid));
02842 commandQueue->runcommand(new InitializeStructureEvent(molid, 0));
02843 commandQueue->runcommand(new MoleculeEvent(molid, MoleculeEvent::MOL_DELETE));
02844 // XXX this has the side effect of altering the 'top' molecule.
02845 // At present the GUI is checking for MOL_DEL in addition to MOL_TOP,
02846 // but really it'd be nicer if we generated appropriate events for 
02847 // side effect cases like this.
02848 return 1;
02849 }
02850 return 0; 
02851 }
02852 
02853 int VMDApp::molecule_delete_all(void) {
02854 int i, nummols, rc;
02855 int *molidlist;
02856 
02857 rc = 0;
02858 nummols = num_molecules();
02859 molidlist = new int[nummols];
02860 
02861 // save molid translation list before we delete them all
02862 for (i=0; i<nummols; i++) {
02863 molidlist[i] = moleculeList->molecule(i)->id();
02864 }
02865 
02866 // delete all molecules and process molecule event callbacks
02867 if (moleculeList->del_all_molecules()) {
02868 for (i=0; i<nummols; i++) {
02869 int molid = molidlist[i];
02870 commandQueue->runcommand(new CmdMolDelete(molid));
02871 commandQueue->runcommand(new InitializeStructureEvent(molid, 0));
02872 commandQueue->runcommand(new MoleculeEvent(molid, MoleculeEvent::MOL_DELETE));
02873 }
02874 
02875 // XXX this has the side effect of altering the 'top' molecule.
02876 // At present the GUI is checking for MOL_DEL in addition to MOL_TOP,
02877 // but really it'd be nicer if we generated appropriate events for 
02878 // side effect cases like this.
02879 rc=1;
02880 }
02881 
02882 delete [] molidlist;
02883 
02884 return rc; 
02885 }
02886 
02887 int VMDApp::molecule_activate(int molid, int onoff) {
02888 int ind = moleculeList->mol_index_from_id(molid);
02889 if (ind < 0) return 0;
02890 if (onoff)
02891 moleculeList->activate(ind);
02892 else
02893 moleculeList->inactivate(ind);
02894 commandQueue->runcommand(new CmdMolActive(molid, onoff));
02895 return 1;
02896 }
02897 int VMDApp::molecule_is_active(int molid) {
02898 int ind = moleculeList->mol_index_from_id(molid);
02899 if (ind < 0) return 0;
02900 return moleculeList->active(ind);
02901 }
02902 int VMDApp::molecule_fix(int molid, int onoff) {
02903 int ind = moleculeList->mol_index_from_id(molid);
02904 if (ind < 0) return 0;
02905 if (onoff)
02906 moleculeList->fix(ind);
02907 else
02908 moleculeList->unfix(ind);
02909 commandQueue->runcommand(new CmdMolFix(molid, onoff));
02910 return 1;
02911 }
02912 int VMDApp::molecule_is_fixed(int molid) {
02913 int ind = moleculeList->mol_index_from_id(molid);
02914 if (ind < 0) return 0;
02915 return moleculeList->fixed(ind);
02916 }
02917 int VMDApp::molecule_display(int molid, int onoff) {
02918 int ind = moleculeList->mol_index_from_id(molid);
02919 if (ind < 0) return 0;
02920 if (onoff)
02921 moleculeList->show(ind);
02922 else
02923 moleculeList->hide(ind);
02924 commandQueue->runcommand(new CmdMolOn(molid, onoff));
02925 return 1;
02926 }
02927 int VMDApp::molecule_is_displayed(int molid) {
02928 int ind = moleculeList->mol_index_from_id(molid);
02929 if (ind < 0) return 0;
02930 return moleculeList->displayed(ind);
02931 }
02932 int VMDApp::molecule_make_top(int molid) {
02933 int ind = moleculeList->mol_index_from_id(molid);
02934 if (ind < 0) return 0;
02935 moleculeList->make_top(ind);
02936 commandQueue->runcommand(new CmdMolTop(molid));
02937 return 1;
02938 }
02939 int VMDApp::molecule_top() {
02940 Molecule *m = moleculeList->top();
02941 if (!m) return -1;
02942 return m->id();
02943 }
02944 int VMDApp::num_molreps(int molid) {
02945 Molecule *m = moleculeList->mol_from_id(molid);
02946 if (!m) return 0;
02947 return m->components();
02948 }
02949 const char *VMDApp::molrep_get_style(int molid, int repid) {
02950 if (repid < 0 || repid >= num_molreps(molid)) return NULL;
02951 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02952 if (item == NULL)
02953 return NULL;
02954 return item->atomRep->cmdStr;
02955 }
02956 int VMDApp::molrep_set_style(int molid, int repid, const char *style) {
02957 int ind = moleculeList->mol_index_from_id(molid);
02958 if (ind < 0) return 0;
02959 if (!moleculeList->change_repmethod(repid, ind, (char *)style)) return 0;
02960 commandQueue->runcommand(
02961 new CmdMolChangeRepItem(repid, molid, CmdMolChangeRepItem::REP, style));
02962 return 1;
02963 }
02964 const char *VMDApp::molrep_get_color(int molid, int repid) {
02965 if (repid < 0 || repid >= num_molreps(molid)) return NULL;
02966 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02967 if (item == NULL)
02968 return NULL;
02969 return item->atomColor->cmdStr;
02970 }
02971 int VMDApp::molrep_set_color(int molid, int repid, const char *color) {
02972 int ind = moleculeList->mol_index_from_id(molid);
02973 if (ind < 0) return 0;
02974 if (!moleculeList->change_repcolor(repid, ind, (char *)color)) return 0;
02975 commandQueue->runcommand(
02976 new CmdMolChangeRepItem(repid, molid, CmdMolChangeRepItem::COLOR, color));
02977 return 1;
02978 }
02979 const char *VMDApp::molrep_get_selection(int molid, int repid) {
02980 if (repid < 0 || repid >= num_molreps(molid)) return NULL;
02981 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02982 if (item == NULL)
02983 return NULL;
02984 return item->atomSel->cmdStr;
02985 }
02986 int VMDApp::molrep_set_selection(int molid, int repid, const char *selection) {
02987 int ind = moleculeList->mol_index_from_id(molid);
02988 if (ind < 0) return FALSE;
02989 if (!moleculeList->change_repsel(repid, ind, selection)) 
02990 return FALSE;
02991 commandQueue->runcommand(
02992 new CmdMolChangeRepItem(repid, molid, CmdMolChangeRepItem::SEL, selection));
02993 return TRUE;
02994 }
02995 int VMDApp::molrep_numselected(int molid, int repid) {
02996 if (repid >= num_molreps(molid)) return -1;
02997 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02998 if (item == NULL)
02999 return -1;
03000 return item->atomSel->selected;
03001 }
03002 const char *VMDApp::molrep_get_material(int molid, int repid) {
03003 if (repid >= num_molreps(molid)) return NULL;
03004 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03005 if (item == NULL)
03006 return NULL;
03007 return materialList->material_name(item->curr_material());
03008 }
03009 int VMDApp::molrep_set_material(int molid, int repid, const char *material) {
03010 int ind = moleculeList->mol_index_from_id(molid);
03011 if (ind < 0) return 0;
03012 if (!moleculeList->change_repmat(repid, ind, (char *)material)) return 0;
03013 commandQueue->runcommand(
03014 new CmdMolChangeRepItem(repid, molid, CmdMolChangeRepItem::MAT, material));
03015 return 1;
03016 }
03017 const char *VMDApp::molecule_get_style() {
03018 return moleculeList->representation();
03019 }
03020 int VMDApp::molecule_set_style(const char *style) {
03021 if (!moleculeList->set_representation((char *)style))
03022 return 0;
03023 commandQueue->runcommand(new CmdMolRep(style));
03024 return 1;
03025 }
03026 const char *VMDApp::molecule_get_color() {
03027 return moleculeList->color();
03028 }
03029 int VMDApp::molecule_set_color(const char *color) {
03030 if (!moleculeList->set_color((char *)color)) 
03031 return 0;
03032 commandQueue->runcommand(new CmdMolColor(color));
03033 return 1;
03034 }
03035 const char *VMDApp::molecule_get_selection() {
03036 return moleculeList->selection();
03037 }
03038 int VMDApp::molecule_set_selection(const char *selection) {
03039 if (!moleculeList->set_selection(selection))
03040 return FALSE;
03041 commandQueue->runcommand(new CmdMolSelect(selection));
03042 return TRUE;
03043 }
03044 const char *VMDApp::molecule_get_material() {
03045 return moleculeList->material();
03046 }
03047 int VMDApp::molecule_set_material(const char *material) {
03048 if (!moleculeList->set_material((char *)material))
03049 return 0;
03050 commandQueue->runcommand(new CmdMolMaterial(material));
03051 return 1;
03052 }
03053 int VMDApp::molecule_addrep(int molid) {
03054 int ind = moleculeList->mol_index_from_id(molid);
03055 if (ind < 0) return 0;
03056 if (!moleculeList->add_rep(ind)) return 0;
03057 commandQueue->runcommand(new CmdMolAddRep(molid));
03058 return 1;
03059 }
03060 int VMDApp::molecule_modrep(int molid, int repid) {
03061 int ind = moleculeList->mol_index_from_id(molid);
03062 if (ind < 0) return 0;
03063 if (!moleculeList->change_rep(repid, ind)) return 0;
03064 commandQueue->runcommand(new CmdMolChangeRep(molid, repid));
03065 return 1;
03066 } 
03067 int VMDApp::molrep_delete(int molid, int repid) {
03068 int ind = moleculeList->mol_index_from_id(molid);
03069 if (ind < 0) return 0;
03070 if (!moleculeList->del_rep(repid, ind)) return 0;
03071 commandQueue->runcommand(new CmdMolDeleteRep(repid, molid));
03072 return 1;
03073 }
03074 
03075 int VMDApp::molrep_get_selupdate(int molid, int repid) {
03076 if (repid >= num_molreps(molid)) return 0;
03077 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03078 if (item == NULL || item->atomSel == NULL)
03079 return 0;
03080 return item->atomSel->do_update; 
03081 } 
03082 int VMDApp::molrep_set_selupdate(int molid, int repid, int onoff) {
03083 if (repid >= num_molreps(molid)) return 0;
03084 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03085 if (item == NULL || item->atomSel == NULL)
03086 return 0;
03087 item->atomSel->do_update = onoff;
03088 commandQueue->runcommand(new CmdMolRepSelUpdate(repid, molid, onoff));
03089 return 1;
03090 } 
03091 
03092 int VMDApp::molrep_set_colorupdate(int molid, int repid, int onoff) {
03093 if (repid >= num_molreps(molid)) return 0;
03094 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03095 if (item == NULL || item->atomColor == NULL)
03096 return 0;
03097 item->atomColor->do_update = onoff;
03098 if (onoff) item->force_recalc(DrawMolItem::COL_REGEN);
03099 commandQueue->runcommand(new CmdMolRepColorUpdate(repid, molid, onoff));
03100 return 1;
03101 } 
03102 int VMDApp::molrep_get_colorupdate(int molid, int repid) {
03103 if (repid >= num_molreps(molid)) return 0;
03104 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03105 if (item == NULL || item->atomColor == NULL)
03106 return 0;
03107 return item->atomColor->do_update;
03108 }
03109 
03110 int VMDApp::molrep_set_smoothing(int molid, int repid, int n) {
03111 if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
03112 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03113 if (item->get_smoothing() == n) return TRUE;
03114 if (item->set_smoothing(n)) {
03115 item->force_recalc(DrawMolItem::MOL_REGEN);
03116 commandQueue->runcommand(new CmdMolSmoothRep(molid, repid, n));
03117 return TRUE;
03118 }
03119 return FALSE;
03120 }
03121 int VMDApp::molrep_get_smoothing(int molid, int repid) {
03122 if (repid < 0 || repid >= num_molreps(molid)) return -1;
03123 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03124 return item->get_smoothing();
03125 }
03126 
03127 int VMDApp::molrep_set_pbc(int molid, int repid, int pbc) {
03128 if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
03129 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03130 item->set_pbc(pbc);
03131 commandQueue->runcommand(new CmdMolShowPeriodic(molid, repid, pbc));
03132 return TRUE;
03133 }
03134 int VMDApp::molrep_get_pbc(int molid, int repid) {
03135 if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
03136 const DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03137 return item->get_pbc();
03138 }
03139 
03140 int VMDApp::molrep_set_pbc_images(int molid, int repid, int n) {
03141 if (n < 1) return FALSE;
03142 if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
03143 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03144 item->set_pbc_images(n);
03145 commandQueue->runcommand(new CmdMolNumPeriodic(molid, repid, n));
03146 return TRUE;
03147 }
03148 int VMDApp::molrep_get_pbc_images(int molid, int repid) {
03149 if (repid < 0 || repid >= num_molreps(molid)) return -1;
03150 const DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03151 return item->get_pbc_images();
03152 }
03153 
03154 
03155 int VMDApp::molecule_add_instance(int molid, Matrix4 & inst) {
03156 Molecule *m = moleculeList->mol_from_id(molid);
03157 if (!m) return 0;
03158 m->add_instance(inst);
03159 
03160 // commandQueue->runcommand(new CmdMolVolume(molid));
03161 return 1;
03162 }
03163 int VMDApp::molecule_num_instances(int molid) {
03164 Molecule *m = moleculeList->mol_from_id(molid);
03165 if (!m) return -1;
03166 return m->num_instances();
03167 }
03168 int VMDApp::molecule_delete_all_instances(int molid) {
03169 Molecule *m = moleculeList->mol_from_id(molid);
03170 if (!m) return -1;
03171 m->clear_instances();
03172 // commandQueue->runcommand(new CmdMolVolume(molid));
03173 return 1;
03174 }
03175 
03176 int VMDApp::molrep_set_instances(int molid, int repid, int inst) {
03177 if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
03178 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03179 item->set_instances(inst);
03180 commandQueue->runcommand(new CmdMolShowInstances(molid, repid, inst));
03181 return TRUE;
03182 }
03183 int VMDApp::molrep_get_instances(int molid, int repid) {
03184 if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
03185 const DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03186 return item->get_instances();
03187 }
03188 
03189 int VMDApp::molecule_set_dataset_flag(int molid, const char *dataflagstr,
03190 int setval) {
03191 int dataflag=BaseMolecule::NODATA;
03192 Molecule *m = moleculeList->mol_from_id(molid);
03193 if (!m) return 0;
03194 
03195 // which flag to set/clear
03196 if (!strcmp("insertion", dataflagstr)) {
03197 dataflag=BaseMolecule::INSERTION;
03198 } else if (!strcmp("occupancy", dataflagstr)) {
03199 dataflag=BaseMolecule::OCCUPANCY;
03200 } else if (!strcmp("beta", dataflagstr)) {
03201 dataflag=BaseMolecule::BFACTOR;
03202 } else if (!strcmp("mass", dataflagstr)) {
03203 dataflag=BaseMolecule::MASS;
03204 } else if (!strcmp("charge", dataflagstr)) {
03205 dataflag=BaseMolecule::CHARGE;
03206 } else if (!strcmp("radius", dataflagstr)) {
03207 dataflag=BaseMolecule::RADIUS;
03208 } else if (!strcmp("altloc", dataflagstr)) {
03209 dataflag=BaseMolecule::ALTLOC;
03210 } else if (!strcmp("atomicnumber", dataflagstr)) {
03211 dataflag=BaseMolecule::ATOMICNUMBER;
03212 } else if (!strcmp("bonds", dataflagstr)) {
03213 dataflag=BaseMolecule::BONDS;
03214 } else if (!strcmp("bondorders", dataflagstr)) {
03215 dataflag=BaseMolecule::BONDORDERS;
03216 } else if (!strcmp("bondtypes", dataflagstr)) {
03217 dataflag=BaseMolecule::BONDTYPES;
03218 } else if (!strcmp("angles", dataflagstr)) {
03219 dataflag=BaseMolecule::ANGLES;
03220 } else if (!strcmp("angletypes", dataflagstr)) {
03221 dataflag=BaseMolecule::ANGLETYPES;
03222 } else if (!strcmp("cterms", dataflagstr)) {
03223 dataflag=BaseMolecule::CTERMS;
03224 } else if (!strcmp("all", dataflagstr)) {
03225 dataflag=
03226 BaseMolecule::INSERTION |
03227 BaseMolecule::OCCUPANCY |
03228 BaseMolecule::BFACTOR |
03229 BaseMolecule::MASS |
03230 BaseMolecule::CHARGE |
03231 BaseMolecule::RADIUS |
03232 BaseMolecule::ALTLOC |
03233 BaseMolecule::ATOMICNUMBER |
03234 BaseMolecule::BONDS |
03235 BaseMolecule::BONDORDERS |
03236 BaseMolecule::BONDTYPES |
03237 BaseMolecule::ANGLES |
03238 BaseMolecule::ANGLETYPES |
03239 BaseMolecule::CTERMS;
03240 }
03241 
03242 // return an error if the flag string is unknown
03243 if (dataflag == BaseMolecule::NODATA)
03244 return 0;
03245 
03246 // set/unset the flag if we recognized it
03247 if (setval)
03248 m->set_dataset_flag(dataflag); 
03249 else
03250 m->unset_dataset_flag(dataflag); 
03251 
03252 return 1;
03253 }
03254 
03255 
03256 int VMDApp::molecule_reanalyze(int molid) {
03257 Molecule *m = moleculeList->mol_from_id(molid);
03258 if (!m) return 0;
03259 
03260 // (re)analyze the molecular structure, since bonds may have been changed
03261 m->analyze();
03262 
03263 // force all reps and selections to be recalculated
03264 m->force_recalc(DrawMolItem::COL_REGEN | 
03265 DrawMolItem::MOL_REGEN |
03266 DrawMolItem::SEL_REGEN);
03267 
03268 // regen secondary structure as well
03269 m->invalidate_ss();
03270 
03271 // log the command
03272 commandQueue->runcommand(new CmdMolReanalyze(molid));
03273 commandQueue->runcommand(new MoleculeEvent(molid, MoleculeEvent::MOL_REGEN));
03274 return TRUE;
03275 }
03276 int VMDApp::molecule_bondsrecalc(int molid) {
03277 Molecule *m = moleculeList->mol_from_id(molid);
03278 if (!m) return 0;
03279 if (m->recalc_bonds()) return 0;
03280 commandQueue->runcommand(new CmdMolBondsRecalc(molid));
03281 commandQueue->runcommand(new MoleculeEvent(molid, MoleculeEvent::MOL_REGEN));
03282 return 1;
03283 }
03284 int VMDApp::molecule_ssrecalc(int molid) {
03285 Molecule *m = moleculeList->mol_from_id(molid);
03286 if (!m) return FALSE;
03287 if (!m->recalc_ss()) return FALSE;
03288 commandQueue->runcommand(new CmdMolSSRecalc(molid));
03289 return TRUE;
03290 }
03291 int VMDApp::molecule_numatoms(int molid) {
03292 Molecule *m = moleculeList->mol_from_id(molid);
03293 if (!m) return -1;
03294 return m->nAtoms;
03295 }
03296 int VMDApp::molecule_numframes(int molid) {
03297 Molecule *m = moleculeList->mol_from_id(molid);
03298 if (!m) return -1;
03299 return m->numframes();
03300 } 
03301 int VMDApp::molecule_frame(int molid) {
03302 Molecule *m = moleculeList->mol_from_id(molid);
03303 if (!m) return -1;
03304 return m->frame();
03305 } 
03306 int VMDApp::molecule_dupframe(int molid, int frame) {
03307 Molecule *m = moleculeList->mol_from_id(molid);
03308 if (!m) {
03309 msgErr << "molecule_dupframe: invalid molecule" << sendmsg;
03310 return FALSE;
03311 }
03312 if (frame >= m->numframes()) {
03313 msgErr << "molecule_dupframe: frame out of range" << sendmsg;
03314 return FALSE;
03315 }
03316 if (frame == -1) {
03317 m->duplicate_frame(m->current());
03318 } else {
03319 m->duplicate_frame(m->get_frame(frame));
03320 }
03321 commandQueue->runcommand(new CmdAnimDup(frame, molid));
03322 return TRUE;
03323 }
03324 
03325 const char *VMDApp::molecule_name(int molid) {
03326 Molecule *m = moleculeList->mol_from_id(molid);
03327 if (!m) return NULL;
03328 return m->molname();
03329 } 
03330 int VMDApp::molecule_rename(int molid, const char *newname) {
03331 Molecule *m = moleculeList->mol_from_id(molid);
03332 if (!m) return 0;
03333 if (!newname) return 0;
03334 if (!m->rename(newname)) return 0;
03335 
03336 // Add item to Molecule color category; default color should be the same as
03337 // the original molecule. 
03338 int ind = moleculeList->colorCatIndex[MLCAT_MOLECULES];
03339 scene->add_color_item(ind, newname, m->id() % VISCLRS);
03340 
03341 commandQueue->runcommand(new CmdMolRename(molid, newname));
03342 commandQueue->runcommand(new MoleculeEvent(molid, MoleculeEvent::MOL_RENAME));
03343 return 1;
03344 }
03345 
03348 int VMDApp::molecule_orblocalize(int molid, int waveid) {
03349 Molecule *m = moleculeList->mol_from_id(molid);
03350 if (!m) return 0;
03351 
03352 float *expandedbasis = NULL;
03353 int *numprims = NULL;
03354 m->qm_data->expand_basis_array(expandedbasis, numprims);
03355 
03356 int i;
03357 for (i=0; i<m->numframes(); i++) {
03358 msgInfo << "Localizing orbitals for wavefunction " << waveid
03359 << " in frame " << i << sendmsg;
03360 m->qm_data->orblocalize(m->get_frame(i), waveid, expandedbasis, numprims);
03361 }
03362 
03363 delete [] expandedbasis;
03364 delete [] numprims;
03365 // XXX need to add commandQueue->runcommand()
03366 return 1;
03367 }
03368 
03369 int VMDApp::molecule_add_volumetric(int molid, const char *dataname, 
03370 const float origin[3], const float xaxis[3], const float yaxis[3],
03371 const float zaxis[3], int xsize, int ysize, int zsize, float *datablock) {
03372 PROFILE_PUSH_RANGE("VMDApp::molecule_add_volumetric()", 3);
03373 
03374 Molecule *m = moleculeList->mol_from_id(molid);
03375 if (!m) return 0;
03376 m->add_volume_data(dataname, origin, xaxis, yaxis, zaxis, xsize, ysize, 
03377 zsize, datablock);
03378 
03379 scene_resetview_newmoldata(); // reset the view so we can see the dataset.
03380 commandQueue->runcommand(new CmdMolVolume(molid));
03381 
03382 PROFILE_POP_RANGE();
03383 return 1;
03384 }
03385 
03386 int VMDApp::molecule_add_volumetric(int molid, const char *dataname, 
03387 const double origin[3], const double xaxis[3], const double yaxis[3],
03388 const double zaxis[3], int xsize, int ysize, int zsize, float *datablock) {
03389 PROFILE_PUSH_RANGE("VMDApp::molecule_add_volumetric()", 3);
03390 
03391 Molecule *m = moleculeList->mol_from_id(molid);
03392 if (!m) return 0;
03393 m->add_volume_data(dataname, origin, xaxis, yaxis, zaxis, xsize, ysize, 
03394 zsize, datablock);
03395 
03396 scene_resetview_newmoldata(); // reset the view so we can see the dataset.
03397 commandQueue->runcommand(new CmdMolVolume(molid));
03398 
03399 PROFILE_POP_RANGE();
03400 return 1;
03401 }
03402 
03403 void VMDApp::set_mouse_callbacks(int on) {
03404 mouse->set_callbacks(on);
03405 }
03406 
03407 void VMDApp::set_mouse_rocking(int on) {
03408 mouse->set_rocking(on);
03409 }
03410 
03411 int VMDApp::num_clipplanes() {
03412 return VMD_MAX_CLIP_PLANE;
03413 }
03414 int VMDApp::molrep_get_clipplane(int molid, int repid, int clipid,
03415 float *center, float *normal, float *color, int *mode) {
03416 Molecule *mol = moleculeList->mol_from_id(molid);
03417 if (!mol) return 0;
03418 Displayable *d = mol->component(repid);
03419 if (!d) return 0;
03420 const VMDClipPlane *c = d->clipplane(clipid);
03421 if (!c) return 0;
03422 memcpy(center, c->center, 3L*sizeof(float));
03423 memcpy(normal, c->normal, 3L*sizeof(float));
03424 memcpy(color, c->color, 3L*sizeof(float));
03425 *mode = c->mode;
03426 return 1;
03427 }
03428 int VMDApp::molrep_set_clipcenter(int molid, int repid, int clipid,
03429 const float *center) {
03430 Molecule *mol = moleculeList->mol_from_id(molid);
03431 if (!mol) return 0;
03432 Displayable *d = mol->component(repid);
03433 if (!d) return 0;
03434 return d->set_clip_center(clipid, center);
03435 }
03436 int VMDApp::molrep_set_clipnormal(int molid, int repid, int clipid,
03437 const float *normal) {
03438 Molecule *mol = moleculeList->mol_from_id(molid);
03439 if (!mol) return 0;
03440 Displayable *d = mol->component(repid);
03441 if (!d) return 0;
03442 return d->set_clip_normal(clipid, normal);
03443 }
03444 int VMDApp::molrep_set_clipcolor(int molid, int repid, int clipid,
03445 const float *color) {
03446 Molecule *mol = moleculeList->mol_from_id(molid);
03447 if (!mol) return 0;
03448 Displayable *d = mol->component(repid);
03449 if (!d) return 0;
03450 return d->set_clip_color(clipid, color);
03451 }
03452 int VMDApp::molrep_set_clipstatus(int molid, int repid, int clipid, int mode) {
03453 Molecule *mol = moleculeList->mol_from_id(molid);
03454 if (!mol) return 0;
03455 Displayable *d = mol->component(repid);
03456 if (!d) return 0;
03457 return d->set_clip_status(clipid, mode);
03458 }
03459 
03460 const char *VMDApp::molrep_get_name(int molid, int repid) {
03461 Molecule *mol = moleculeList->mol_from_id(molid); 
03462 if (!mol) return NULL;
03463 return mol->get_component_name(repid);
03464 }
03465 
03466 int VMDApp::molrep_get_by_name(int molid, const char *name) {
03467 Molecule *mol = moleculeList->mol_from_id(molid); 
03468 if (!mol) return -1;
03469 return mol->get_component_by_name(name);
03470 }
03471 
03472 int VMDApp::molrep_get_scaleminmax(int molid, int repid, float *min, float *max) {
03473 if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
03474 const DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03475 #if 0
03476 // XXX Axel's color data range auto scale patch to fix the "two clicks"
03477 // problem he discovered with some volumetric datasets. Needs closer
03478 // examination when I have a few minutes, but this will get him by for
03479 // the CPMD tutorial.
03480 Molecule *mol = moleculeList->mol_from_id(molid);
03481 item->atomColor->rescale_colorscale_minmax();
03482 item->atomColor->find(mol);
03483 #endif
03484 item->atomColor->get_colorscale_minmax(min, max);
03485 return TRUE;
03486 }
03487 int VMDApp::molrep_set_scaleminmax(int molid, int repid, float min, float max) {
03488 if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
03489 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03490 if (item->atomColor->set_colorscale_minmax(min, max)) {
03491 item->force_recalc(DrawMolItem::COL_REGEN);
03492 commandQueue->runcommand(new CmdMolScaleMinmax(molid, repid, min, max));
03493 return TRUE;
03494 }
03495 return FALSE;
03496 }
03497 int VMDApp::molrep_reset_scaleminmax(int molid, int repid) {
03498 if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
03499 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03500 item->atomColor->rescale_colorscale_minmax();
03501 item->force_recalc(DrawMolItem::COL_REGEN);
03502 commandQueue->runcommand(new CmdMolScaleMinmax(molid, repid, 0, 0, 1));
03503 return TRUE;
03504 }
03505 
03506 int VMDApp::molrep_set_drawframes(int molid, int repid, const char *framesel) {
03507 if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
03508 if (!framesel) {
03509 msgErr << "molrep_set_drawframes: Error, framesel is NULL!" << sendmsg;
03510 return FALSE;
03511 }
03512 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03513 item->set_drawframes(framesel);
03514 commandQueue->runcommand(new CmdMolDrawFrames(molid, repid, framesel));
03515 return TRUE;
03516 }
03517 
03518 const char *VMDApp::molrep_get_drawframes(int molid, int repid) {
03519 if (repid < 0 || repid >= num_molreps(molid)) return NULL;
03520 const DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03521 return item->get_drawframes();
03522 }
03523 
03524 int VMDApp::molrep_show(int molid, int repid, int onoff) {
03525 if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
03526 moleculeList->mol_from_id(molid)->show_rep(repid, onoff);
03527 commandQueue->runcommand(new CmdMolShowRep(molid, repid, onoff));
03528 return TRUE;
03529 }
03530 
03531 int VMDApp::molrep_is_shown(int molid, int repid) {
03532 if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
03533 DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
03534 return item->displayed();
03535 }
03536 
03537 
03538 //
03539 // IMD methods
03540 //
03541 int VMDApp::imd_connect(int molid, const char *host, int port) {
03542 #ifdef VMDIMD 
03543 Molecule *mol = moleculeList->mol_from_id(molid); 
03544 if (!mol) return 0;
03545 if (!imdMgr) return 0;
03546 if (imdMgr->connect(mol, host, port)) {
03547 // tell the world
03548 commandQueue->runcommand(new CmdIMDConnect(molid,host, port));
03549 return 1;
03550 }
03551 #endif
03552 return 0;
03553 }
03554 
03555 int VMDApp::imd_connected(int molid) {
03556 #ifdef VMDIMD
03557 if (!imdMgr) return 0;
03558 Molecule *mol = imdMgr->get_imdmol();
03559 if (mol) {
03560 return (mol->id() == molid);
03561 }
03562 #endif
03563 return 0;
03564 }
03565 
03566 int VMDApp::imd_sendforces(int num, const int *ind, const float *forces) {
03567 #ifdef VMDIMD
03568 if (!imdMgr) 
03569 return 0;
03570 
03571 return imdMgr->send_forces(num, ind, forces);
03572 #else
03573 return 0;
03574 #endif
03575 }
03576 
03577 int VMDApp::imd_disconnect(int molid) {
03578 #ifdef VMDIMD
03579 if (!imdMgr) return FALSE;
03580 Molecule *mol = imdMgr->get_imdmol();
03581 if (mol && mol->id() == molid) {
03582 imdMgr->detach();
03583 return TRUE;
03584 }
03585 #endif
03586 return FALSE;
03587 }
03588 
03589 
03590 //
03591 // VideoStream methods
03592 //
03593 int VMDApp::vs_connect(const char *host, int port) {
03594 #ifdef VMDNVPIPE
03595 if (!uivs) return 0;
03596 if (uivs->cli_connect(host, port)) {
03597 // tell the world
03598 // commandQueue->runcommand(new CmdVSConnect(host, port));
03599 msgInfo << "VMDApp: VideoStream connected" << sendmsg;
03600 return 1;
03601 }
03602 #endif
03603 return 0;
03604 }
03605 
03606 int VMDApp::vs_connected() {
03607 #ifdef VMDNVPIPE
03608 if (!uivs) return 0;
03609 // XXX check for connection here
03610 #endif
03611 return 0;
03612 }
03613 
03614 int VMDApp::vs_disconnect() {
03615 #ifdef VMDNVPIPE
03616 if (!uivs) return FALSE;
03617 if (uivs) {
03618 uivs->cli_disconnect();
03619 return TRUE;
03620 }
03621 #endif
03622 return FALSE;
03623 }
03624 
03625 
03626 
03627 //
03628 // Display methods
03629 //
03630 
03631 void VMDApp::display_set_screen_height(float ht) {
03632 if (!display) return;
03633 display->screen_height(ht);
03634 commandQueue->runcommand(new CmdDisplayScreenHeight(ht));
03635 }
03636 float VMDApp::display_get_screen_height() {
03637 if (!display) return 0.0f;
03638 return display->screen_height();
03639 }
03640 void VMDApp::display_set_screen_distance(float d) {
03641 if (!display) return;
03642 display->distance_to_screen(d);
03643 commandQueue->runcommand(new CmdDisplayScreenDistance(d));
03644 }
03645 float VMDApp::display_get_screen_distance() {
03646 if (!display) return 0.0f;
03647 return display->distance_to_screen();
03648 }
03649 void VMDApp::display_set_position(int x, int y) {
03650 if (display)
03651 display->reposition_window(x, y);
03652 }
03653 #if 0
03654 void VMDApp::display_get_position(int *x, int *y) {
03655 if (display) {
03656 display->window_position(x, y);
03657 }
03658 }
03659 #endif
03660 void VMDApp::display_set_size(int w, int h) {
03661 if (display) {
03662 display->resize_window(w, h);
03663 // do an update so that the new size of the window becomes immediately
03664 // available. 
03665 display_update_ui();
03666 }
03667 }
03668 void VMDApp::display_get_size(int *w, int *h) {
03669 if (display) {
03670 *w = display->xSize;
03671 *h = display->ySize;
03672 }
03673 }
03674 void VMDApp::display_titlescreen() {
03675 if (display && display->supports_gui()) {
03676 delete vmdTitle;
03677 vmdTitle = new VMDTitle(display, &(scene->root));
03678 }
03679 }
03680 
03681 int VMDApp::display_set_stereo(const char *mode) {
03682 if (!mode) 
03683 return FALSE;
03684 
03685 int i, j;
03686 for (i=0; i<display->num_stereo_modes(); i++) {
03687 if (!strcmp(mode, display->stereo_name(i))) {
03688 display->set_stereo_mode(i);
03689 commandQueue->runcommand(new CmdDisplayStereo(mode));
03690 return TRUE;
03691 }
03692 }
03693 
03694 // Backwards compatibility with old scripts...
03695 const char *OldStereoNames[] = { 
03696 "CrystalEyes", "CrystalEyesReversed", "CrossEyes" 
03697 };
03698 const char *NewStereoNames[] = {
03699 "QuadBuffered", "QuadBuffered", "SideBySide" 
03700 };
03701 for (j=0; j<3; j++) {
03702 if (!strcmp(mode, OldStereoNames[j])) {
03703 for (i=0; i<display->num_stereo_modes(); i++) {
03704 if (!strcmp(NewStereoNames[j], display->stereo_name(i))) {
03705 display->set_stereo_mode(i);
03706 commandQueue->runcommand(new CmdDisplayStereo(NewStereoNames[j]));
03707 
03708 // preserve the swapped eye behavior of the old stereo mode names
03709 if (!strcmp(mode, "CrystalEyesReversed") ||
03710 !strcmp(mode, "CrossEyes")) {
03711 display_set_stereo_swap(1); 
03712 } 
03713 return TRUE;
03714 }
03715 }
03716 }
03717 }
03718 
03719 msgErr << "Illegal stereo mode: " << mode << sendmsg;
03720 return FALSE;
03721 }
03722 
03723 int VMDApp::display_set_stereo_swap(int onoff) {
03724 if (!onoff) {
03725 display->set_stereo_swap(0);
03726 commandQueue->runcommand(new CmdDisplayStereoSwap(0));
03727 return TRUE;
03728 }
03729 
03730 display->set_stereo_swap(1);
03731 commandQueue->runcommand(new CmdDisplayStereoSwap(1));
03732 return TRUE;
03733 }
03734 
03735 int VMDApp::display_set_cachemode(const char *mode) {
03736 if (!mode) return FALSE;
03737 for (int i=0; i<display->num_cache_modes(); i++) {
03738 if (!strcmp(mode, display->cache_name(i))) {
03739 display->set_cache_mode(i);
03740 commandQueue->runcommand(new CmdDisplayCacheMode(mode));
03741 return TRUE;
03742 }
03743 }
03744 msgErr << "Illegal cache mode: " << mode << sendmsg;
03745 return FALSE;
03746 }
03747 
03748 int VMDApp::display_set_rendermode(const char *mode) {
03749 if (!mode) return FALSE;
03750 for (int i=0; i<display->num_render_modes(); i++) {
03751 if (!strcmp(mode, display->render_name(i))) {
03752 display->set_render_mode(i);
03753 commandQueue->runcommand(new CmdDisplayRenderMode(mode));
03754 return TRUE;
03755 }
03756 }
03757 msgErr << "Illegal rendering mode: " << mode << sendmsg;
03758 return FALSE;
03759 }
03760 
03761 int VMDApp::display_set_eyesep(float sep) {
03762 if (sep < 0) return FALSE;
03763 display->set_eyesep(sep);
03764 commandQueue->runcommand(new CmdDisplayEyesep(sep));
03765 return TRUE;
03766 }
03767 
03768 int VMDApp::display_set_focallen(float flen) {
03769 if (!display->set_eye_dist(flen)) return FALSE;
03770 commandQueue->runcommand(new CmdDisplayFocallen(flen));
03771 return TRUE;
03772 }
03773 
03774 int VMDApp::display_set_projection(const char *proj) {
03775 if (!display->set_projection(proj)) return FALSE;
03776 commandQueue->runcommand(new CmdDisplayProj(proj));
03777 return TRUE;
03778 }
03779 
03780 int VMDApp::display_projection_is_perspective(void) {
03781 if (display->projection() == DisplayDevice::ORTHOGRAPHIC)
03782 return FALSE;
03783 
03784 return TRUE;
03785 }
03786 
03787 int VMDApp::display_set_aa(int onoff) {
03788 if (!display->aa_available()) return FALSE;
03789 if (onoff) display->aa_on(); else display->aa_off();
03790 commandQueue->runcommand(new CmdDisplayAAOn(onoff));
03791 return TRUE;
03792 }
03793 
03794 int VMDApp::display_set_depthcue(int onoff) {
03795 if (!display->cueing_available()) return FALSE;
03796 if (onoff) display->cueing_on(); else display->cueing_off();
03797 commandQueue->runcommand(new CmdDisplayDepthcueOn(onoff));
03798 return TRUE;
03799 }
03800 
03801 int VMDApp::display_set_culling(int onoff) {
03802 if (!display->culling_available()) return FALSE;
03803 if (onoff) display->culling_on(); else display->culling_off();
03804 commandQueue->runcommand(new CmdDisplayCullingOn(onoff));
03805 return TRUE;
03806 }
03807 
03808 int VMDApp::display_set_fps(int onoff) {
03809 if (onoff) fps->on(); else fps->off();
03810 commandQueue->runcommand(new CmdDisplayFPSOn(onoff));
03811 return TRUE;
03812 }
03813 
03814 int VMDApp::display_set_background_mode(int mode) {
03815 scene->set_background_mode(mode);
03816 commandQueue->runcommand(new CmdDisplayBackgroundGradientOn(mode));
03817 return TRUE;
03818 }
03819 
03820 int VMDApp::display_set_nearclip(float amt, int isdelta) {
03821 if (isdelta) {
03822 display->addto_near_clip(amt); 
03823 commandQueue->runcommand(new CmdDisplayClipNearRel(amt));
03824 } else {
03825 // prevent illegal near clipping plane values from causing problems
03826 if (amt <= 0.0)
03827 amt = 0.001f;
03828 display->set_near_clip(amt);
03829 commandQueue->runcommand(new CmdDisplayClipNear(amt));
03830 }
03831 return TRUE;
03832 }
03833 
03834 int VMDApp::display_set_farclip(float amt, int isdelta) {
03835 if (isdelta) {
03836 display->addto_far_clip(amt); 
03837 commandQueue->runcommand(new CmdDisplayClipFarRel(amt));
03838 } else {
03839 display->set_far_clip(amt);
03840 commandQueue->runcommand(new CmdDisplayClipFar(amt));
03841 }
03842 return TRUE;
03843 }
03844 
03845 int VMDApp::stage_set_location (const char *pos) {
03846 if (!pos) return FALSE;
03847 for (int i=0; i<stage->locations(); i++) {
03848 if (!strupcmp(pos, stage->loc_description(i))) {
03849 stage->location(i);
03850 commandQueue->runcommand(new CmdDisplayStageLocation(pos));
03851 return TRUE;
03852 }
03853 }
03854 return FALSE;
03855 }
03856 
03857 int VMDApp::stage_set_numpanels(int num) {
03858 if (!stage->panels(num)) return FALSE;
03859 commandQueue->runcommand(new CmdDisplayStagePanels(num));
03860 return TRUE;
03861 }
03862 
03863 int VMDApp::stage_set_size(float sz) {
03864 if (!stage->size(sz)) return FALSE;
03865 commandQueue->runcommand(new CmdDisplayStageSize(sz));
03866 return TRUE;
03867 }
03868 
03869 int VMDApp::axes_set_location (const char *pos) {
03870 if (!pos) return FALSE;
03871 for (int i=0; i<axes->locations(); i++) {
03872 if (!strupcmp(pos, axes->loc_description(i))) {
03873 axes->location(i);
03874 commandQueue->runcommand(new CmdDisplayAxes(pos));
03875 return TRUE;
03876 }
03877 }
03878 return FALSE;
03879 }
03880 
03881 int VMDApp::light_on(int n, int onoff) {
03882 if (n<0 || n >= DISP_LIGHTS) return FALSE;
03883 scene->activate_light(n, onoff);
03884 commandQueue->runcommand(new CmdDisplayLightOn(n, onoff));
03885 return TRUE;
03886 }
03887 int VMDApp::light_highlight(int n, int onoff) {
03888 if (n<0 || n >= DISP_LIGHTS) return FALSE;
03889 scene->highlight_light(n, onoff);
03890 commandQueue->runcommand(new CmdDisplayLightHL(n, onoff));
03891 return TRUE;
03892 }
03893 
03894 int VMDApp::light_rotate(int n, float amt, char axis) {
03895 if (n<0 || n >= DISP_LIGHTS) return FALSE;
03896 scene->rotate_light(n, amt, axis);
03897 commandQueue->runcommand(new CmdDisplayLightRot(n, amt, axis));
03898 return TRUE;
03899 }
03900 
03901 int VMDApp::light_move(int n, const float *newpos) {
03902 if (n<0 || n >= DISP_LIGHTS) return FALSE;
03903 scene->move_light(n, newpos);
03904 commandQueue->runcommand(new CmdDisplayLightMove(n, newpos));
03905 return TRUE;
03906 }
03907 
03908 int VMDApp::depthcue_set_mode(const char *mode) {
03909 if (!display->set_cue_mode(mode)) return FALSE;
03910 commandQueue->runcommand(new CmdDisplayCueMode(mode));
03911 return TRUE;
03912 }
03913 
03914 int VMDApp::depthcue_set_start(float val) {
03915 if (!display->set_cue_start(val)) return FALSE;
03916 commandQueue->runcommand(new CmdDisplayCueStart(val));
03917 return TRUE;
03918 }
03919 
03920 int VMDApp::depthcue_set_end(float val) {
03921 if (!display->set_cue_end(val)) return FALSE;
03922 commandQueue->runcommand(new CmdDisplayCueEnd(val));
03923 return TRUE;
03924 }
03925 
03926 int VMDApp::depthcue_set_density(float val) {
03927 if (!display->set_cue_density(val)) return FALSE;
03928 commandQueue->runcommand(new CmdDisplayCueDensity(val));
03929 return TRUE;
03930 }
03931 
03932 int VMDApp::display_set_shadows(int onoff) {
03933 if (!display->set_shadow_mode(onoff)) return FALSE;
03934 commandQueue->runcommand(new CmdDisplayShadowOn(onoff));
03935 return TRUE;
03936 } 
03937 
03938 int VMDApp::display_set_ao(int onoff) {
03939 if (!display->set_ao_mode(onoff)) return FALSE;
03940 commandQueue->runcommand(new CmdDisplayAOOn(onoff));
03941 return TRUE;
03942 } 
03943 
03944 int VMDApp::display_set_ao_ambient(float val) {
03945 if (!display->set_ao_ambient(val)) return FALSE;
03946 commandQueue->runcommand(new CmdDisplayAOAmbient(val));
03947 return TRUE;
03948 }
03949 
03950 int VMDApp::display_set_ao_direct(float val) {
03951 if (!display->set_ao_direct(val)) return FALSE;
03952 commandQueue->runcommand(new CmdDisplayAODirect(val));
03953 return TRUE;
03954 }
03955 
03956 int VMDApp::display_set_dof(int onoff) {
03957 if (!display->set_dof_mode(onoff)) return FALSE;
03958 commandQueue->runcommand(new CmdDisplayDoFOn(onoff));
03959 return TRUE;
03960 } 
03961 
03962 int VMDApp::display_set_dof_fnumber(float f) {
03963 if (!display->set_dof_fnumber(f)) return FALSE;
03964 commandQueue->runcommand(new CmdDisplayDoFFNumber(f));
03965 return TRUE;
03966 }
03967 
03968 int VMDApp::display_set_dof_focal_dist(float d) {
03969 if (!display->set_dof_focal_dist(d)) return FALSE;
03970 commandQueue->runcommand(new CmdDisplayDoFFocalDist(d));
03971 return TRUE;
03972 }
03973 
03974 void VMDApp::deactivate_uitext_stdin() {
03975 if (uiText)
03976 uiText->Off();
03977 }
03978 
03979 int VMDApp::activate_menus() {
03980 // XXX This should control Tk menus as well; at present Tk menus are 
03981 // available whenever the display supports GUI's.
03982 
03983 #ifdef VMDGUI
03984 if(display->supports_gui()) {
03985 
03986 delete uivr;
03987 uivr = new UIVR(this);
03988 uivr->On();
03989 
03990 // if we are using the FLTK library ...
03991 #ifdef VMDFLTK
03992 VMDMenu *obj;
03993 obj = new MainFltkMenu(this);
03994 menulist->add_name(obj->get_name(), obj);
03995 obj = new ColorFltkMenu(this);
03996 menulist->add_name(obj->get_name(), obj);
03997 obj = new MaterialFltkMenu(this);
03998 menulist->add_name(obj->get_name(), obj);
03999 obj = new DisplayFltkMenu(this);
04000 menulist->add_name(obj->get_name(), obj);
04001 obj = new FileChooserFltkMenu(this);
04002 menulist->add_name(obj->get_name(), obj);
04003 obj = new GeometryFltkMenu(this);
04004 menulist->add_name(obj->get_name(), obj);
04005 obj = new GraphicsFltkMenu(this);
04006 menulist->add_name(obj->get_name(), obj);
04007 obj = new RenderFltkMenu(this);
04008 menulist->add_name(obj->get_name(), obj);
04009 obj = new SaveTrajectoryFltkMenu(this);
04010 menulist->add_name(obj->get_name(), obj);
04011 obj = new ToolFltkMenu(this);
04012 menulist->add_name(obj->get_name(), obj);
04013 #endif /*VMDFLTK*/
04014 }
04015 return TRUE;
04016 #endif /*VMDGUI*/
04017 
04018 // no menus available
04019 return FALSE;
04020 }
04021 
04022 int VMDApp::label_add(const char *category, int n, const int *molids, 
04023 const int *atomids, const int *cells, float k, int toggle) {
04024 if (!category || !molids || !atomids) return -1;
04025 int rc = geometryList->add_geometry(category, molids, atomids, cells, k, 
04026 toggle);
04027 if (rc >= 0) {
04028 if (!strcmp(category, "Springs"))
04029 commandQueue->runcommand(new CmdLabelAddspring(molids[0], atomids[0],
04030 atomids[1], k));
04031 else 
04032 commandQueue->runcommand(new CmdLabelAdd(category, n, (int *)molids, (int *)atomids));
04033 }
04034 return rc;
04035 }
04036 
04037 int VMDApp::label_show (const char *category, int n, int onoff) {
04038 if (!category) return FALSE;
04039 if (geometryList->show_geometry(category, n, onoff)) {
04040 commandQueue->runcommand(new CmdLabelShow(category, n, onoff));
04041 return TRUE;
04042 }
04043 return FALSE;
04044 }
04045 
04046 float VMDApp::label_get_text_size() const {
04047 return geometryList->getTextSize();
04048 }
04049 
04050 int VMDApp::label_set_text_size(float newsize) {
04051 if (geometryList->setTextSize(newsize)) {
04052 commandQueue->runcommand(new CmdLabelTextSize(newsize));
04053 return TRUE;
04054 }
04055 return FALSE;
04056 }
04057 
04058 float VMDApp::label_get_text_thickness() const {
04059 return geometryList->getTextThickness();
04060 }
04061 
04062 int VMDApp::label_set_text_thickness(float newthick) {
04063 if (geometryList->setTextThickness(newthick)) {
04064 commandQueue->runcommand(new CmdLabelTextThickness(newthick));
04065 return TRUE;
04066 }
04067 return FALSE;
04068 }
04069 
04070 int VMDApp::label_set_textoffset(const char *nm, int n, float x, float y) {
04071 float delta[2] = { x, y };
04072 if (geometryList->setTextOffset(nm, n, delta)) {
04073 commandQueue->runcommand(new CmdLabelTextOffset(nm, n, x, y));
04074 return TRUE;
04075 }
04076 return FALSE;
04077 }
04078 
04079 int VMDApp::label_set_textformat(const char *nm, int n, const char *format) {
04080 if (geometryList->setTextFormat(nm, n, format)) {
04081 commandQueue->runcommand(new CmdLabelTextFormat(nm, n, format));
04082 return TRUE;
04083 }
04084 return FALSE;
04085 }
04086 
04087 int VMDApp::label_delete(const char *category, int n) {
04088 if (!category) return FALSE;
04089 if (geometryList->del_geometry(category, n)) {
04090 commandQueue->runcommand(new CmdLabelDelete(category, n));
04091 return TRUE;
04092 }
04093 return FALSE;
04094 }
04095 
04096 int VMDApp::tool_create(const char *type, int argc, const char **argv) {
04097 if (!uivr) return FALSE;
04098 if (!uivr->add_tool_with_USL(type, argc, argv)) return FALSE;
04099 commandQueue->runcommand(new CmdToolCreate(type, argc, argv));
04100 return TRUE;
04101 }
04102 
04103 int VMDApp::tool_change_type(int toolnum, const char *type) {
04104 if (!uivr) return FALSE;
04105 if (!uivr->change_type(toolnum, type)) return FALSE;
04106 commandQueue->runcommand(new CmdToolChange(type, toolnum));
04107 return TRUE;
04108 }
04109 
04110 int VMDApp::tool_delete(int toolnum) {
04111 if (!uivr) return FALSE;
04112 if (!uivr->remove_tool(toolnum)) return FALSE;
04113 commandQueue->runcommand(new CmdToolDelete(toolnum));
04114 // XXXX fix this for multiple tools
04115 commandQueue->runcommand(new PickAtomCallbackEvent(-1,-1,"uivr"));
04116 return TRUE;
04117 }
04118 
04119 int VMDApp::tool_set_position_scale(int toolnum, float newval) {
04120 if (!uivr) return FALSE;
04121 if (uivr->set_position_scale(toolnum, newval)) {
04122 commandQueue->runcommand(new CmdToolScale(newval, toolnum));
04123 return TRUE;
04124 }
04125 return FALSE;
04126 }
04127 
04128 int VMDApp::tool_set_force_scale(int toolnum, float newval) {
04129 if (!uivr) return FALSE;
04130 if (uivr->set_force_scale(toolnum, newval)) {
04131 commandQueue->runcommand(new CmdToolScaleForce(newval, toolnum));
04132 return TRUE;
04133 }
04134 return FALSE;
04135 }
04136 
04137 int VMDApp::tool_set_spring_scale(int toolnum, float newval) {
04138 if (!uivr) return FALSE;
04139 if (uivr->set_spring_scale(toolnum, newval)) {
04140 commandQueue->runcommand(new CmdToolScaleSpring(newval, toolnum));
04141 return TRUE;
04142 }
04143 return FALSE;
04144 }
04145 
04146 const char *VMDApp::material_add(const char *name, const char *copy) {
04147 const char *newname = materialList->add_material(name, copy);
04148 if (newname) {
04149 commandQueue->runcommand(new CmdMaterialAdd(name, copy));
04150 }
04151 return newname;
04152 }
04153 
04154 int VMDApp::material_delete(const char *name) {
04155 char * strname = stringdup(name);
04156 int ind = materialList->material_index(strname);
04157 if (materialList->delete_material(ind)) {
04158 commandQueue->runcommand(new CmdMaterialDelete(strname));
04159 delete [] strname;
04160 return TRUE;
04161 }
04162 delete [] strname;
04163 return FALSE;
04164 }
04165 
04166 int VMDApp::material_rename(const char *prevname, const char *newname) {
04167 char * oldname = stringdup(prevname);
04168 int ind = materialList->material_index(oldname);
04169 if (ind < 0) {
04170 msgErr << "material rename: '" << oldname << "' does not exist." 
04171 << sendmsg;
04172 delete [] oldname;
04173 return FALSE;
04174 }
04175 int n = strlen(newname);
04176 if (!n) return FALSE;
04177 for (size_t i=0; i<strlen(newname); i++) {
04178 if (!isalnum(newname[i])) {
04179 msgErr << "material rename: new name contains non-alphanumeric character"
04180 << sendmsg;
04181 delete [] oldname;
04182 return FALSE;
04183 }
04184 }
04185 if (materialList->material_index(newname) >= 0) {
04186 msgErr << "material rename: '" << newname << "' already exists." 
04187 << sendmsg;
04188 delete [] oldname;
04189 return FALSE;
04190 }
04191 materialList->set_name(ind, newname);
04192 commandQueue->runcommand(new CmdMaterialRename(oldname, newname));
04193 delete [] oldname;
04194 return TRUE;
04195 }
04196 
04197 int VMDApp::material_change(const char *name, int property, float val) {
04198 int ind = materialList->material_index(name);
04199 if (ind < 0) return FALSE;
04200 switch (property) {
04201 case MAT_AMBIENT: materialList->set_ambient(ind, val); break;
04202 case MAT_SPECULAR: materialList->set_specular(ind, val); break;
04203 case MAT_DIFFUSE: materialList->set_diffuse(ind, val); break;
04204 case MAT_SHININESS: materialList->set_shininess(ind, val); break;
04205 case MAT_MIRROR: materialList->set_mirror(ind, val); break;
04206 case MAT_OPACITY: materialList->set_opacity(ind, val); break;
04207 case MAT_OUTLINE: materialList->set_outline(ind, val); break;
04208 case MAT_OUTLINEWIDTH: materialList->set_outlinewidth(ind, val); break;
04209 case MAT_TRANSMODE: materialList->set_transmode(ind, val); break;
04210 }
04211 commandQueue->runcommand(new CmdMaterialChange(name, property, val));
04212 return TRUE;
04213 }
04214 
04215 int VMDApp::material_restore_default(int ind) {
04216 if (materialList->restore_default(ind)) {
04217 commandQueue->runcommand(new CmdMaterialDefault(ind));
04218 return TRUE;
04219 }
04220 return FALSE;
04221 }
04222 
04223 int VMDApp::mouse_set_mode(int mm, int ms) {
04224 if (!mouse->move_mode((Mouse::MoveMode)mm, ms)) {
04225 msgErr << "Illegal mouse mode: " << mm << " " << ms << sendmsg;
04226 return FALSE;
04227 }
04228 
04229 // If mouse mode is a picking mode, set it here
04230 switch (mm) {
04231 case Mouse::PICK: pickModeList->set_pick_mode(PickModeList::PICK); break;
04232 case Mouse::QUERY: pickModeList->set_pick_mode(PickModeList::QUERY); break;
04233 case Mouse::CENTER: pickModeList->set_pick_mode(PickModeList::CENTER); break;
04234 case Mouse::LABELATOM: pickModeList->set_pick_mode(PickModeList::LABELATOM); break;
04235 case Mouse::LABELBOND: pickModeList->set_pick_mode(PickModeList::LABELBOND); break;
04236 case Mouse::LABELANGLE: pickModeList->set_pick_mode(PickModeList::LABELANGLE); break;
04237 case Mouse::LABELDIHEDRAL: pickModeList->set_pick_mode(PickModeList::LABELDIHEDRAL); break;
04238 case Mouse::MOVEATOM: pickModeList->set_pick_mode(PickModeList::MOVEATOM); break;
04239 case Mouse::MOVERES: pickModeList->set_pick_mode(PickModeList::MOVERES); break;
04240 case Mouse::MOVEFRAG: pickModeList->set_pick_mode(PickModeList::MOVEFRAG); break;
04241 case Mouse::MOVEMOL: pickModeList->set_pick_mode(PickModeList::MOVEMOL); break;
04242 case Mouse::FORCEATOM: pickModeList->set_pick_mode(PickModeList::FORCEATOM); break;
04243 case Mouse::FORCERES: pickModeList->set_pick_mode(PickModeList::FORCERES); break;
04244 case Mouse::FORCEFRAG: pickModeList->set_pick_mode(PickModeList::FORCEFRAG); break;
04245 case Mouse::MOVEREP: pickModeList->set_pick_mode(PickModeList::MOVEREP); break;
04246 case Mouse::ADDBOND: pickModeList->set_pick_mode(PickModeList::ADDBOND); break;
04247 default: break;
04248 }
04249 
04250 commandQueue->runcommand(new CmdMouseMode(mm, ms));
04251 return TRUE;
04252 }
04253 
04254 
04255 int VMDApp::mobile_set_mode(int mm) {
04256 if (!mobile->move_mode((Mobile::MoveMode) mm)) {
04257 msgErr << "Illegal mobile mode: " << mm << " " << sendmsg;
04258 return FALSE;
04259 }
04260 commandQueue->runcommand(new CmdMobileMode(mm));
04261 return TRUE;
04262 }
04263 
04264 int VMDApp::mobile_get_mode() {
04265 return mobile->get_move_mode();
04266 }
04267 
04268 void VMDApp::mobile_get_client_list(ResizeArray <JString*>* &nick, 
04269 ResizeArray <JString*>* &ip, ResizeArray <bool>* &active) 
04270 {
04271 mobile->get_client_list(nick, ip, active);
04272 }
04273 
04274 int VMDApp::mobile_network_port(int port) {
04275 mobile->network_port(port);
04276 // commandQueue->runcommand(new CmdMobileNetworkPort(port));
04277 return TRUE;
04278 }
04279 
04280 int VMDApp::mobile_get_network_port() {
04281 return mobile->get_port();
04282 }
04283 
04284 int VMDApp::mobile_get_APIsupported() {
04285 return mobile->get_APIsupported();
04286 }
04287 
04289 int VMDApp::mobile_set_activeClient(const char *nick, const char *ip) {
04290 return mobile->set_activeClient(nick, ip);
04291 }
04292 
04294 int VMDApp::mobile_sendMsg(const char *nick, const char *ip, 
04295 const char *msgType, const char *msg) {
04296 return mobile->sendMsgToClient(nick, ip, msgType, msg);
04297 }
04298 
04299 
04302 void VMDApp::mobile_get_tracker_status(float &tx, float &ty, float &tz,
04303 float &rx, float &ry, float &rz,
04304 int &buttons) {
04305 if (mobile != NULL) {
04306 mobile->get_tracker_status(tx, ty, tz, rx, ry, rz, buttons);
04307 } else {
04308 tx=ty=tz=rx=ry=rz=0.0f;
04309 buttons=0;
04310 }
04311 }
04312 
04313 
04314 int VMDApp::spaceball_set_mode(int mm) {
04315 if (!spaceball->move_mode((Spaceball::MoveMode) mm)) {
04316 msgErr << "Illegal spaceball mode: " << mm << " " << sendmsg;
04317 return FALSE;
04318 }
04319 commandQueue->runcommand(new CmdSpaceballMode(mm));
04320 return TRUE;
04321 }
04322 
04323 
04324 int VMDApp::spaceball_set_sensitivity(float s) {
04325 spaceball->set_sensitivity(s);
04326 // commandQueue->runcommand(new CmdSpaceballSensitivity(s));
04327 return TRUE;
04328 }
04329 
04330 
04331 int VMDApp::spaceball_set_null_region(int nr) {
04332 spaceball->set_null_region(nr);
04333 // commandQueue->runcommand(new CmdSpaceballNullRegion(s));
04334 return TRUE;
04335 }
04336 
04337 
04340 void VMDApp::spaceball_get_tracker_status(float &tx, float &ty, float &tz,
04341 float &rx, float &ry, float &rz,
04342 int &buttons) {
04343 if (spaceball != NULL) {
04344 spaceball->get_tracker_status(tx, ty, tz, rx, ry, rz, buttons);
04345 } else {
04346 tx=ty=tz=rx=ry=rz=0.0f;
04347 buttons=0;
04348 }
04349 }
04350 
04351 
04352 int VMDApp::textinterp_change(const char *name) {
04353 return uiText->change_interp(name);
04354 }
04355 
04356 //
04357 // MPI related routines
04358 //
04359 void VMDApp::par_barrier() {
04360 #if defined(VMDMPI)
04361 // perform a barrier if running in parallel
04362 if (mpienabled)
04363 vmd_mpi_barrier();
04364 #endif
04365 }
04366 

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

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