layer5/PyMOL.cpp (2,912 lines of code) (raw):

/* A* ------------------------------------------------------------------- B* This file contains source code for the PyMOL computer program C* Copyright (c) Schrodinger, LLC. D* ------------------------------------------------------------------- E* It is unlawful to modify or remove this copyright notice. F* ------------------------------------------------------------------- G* Please see the accompanying LICENSE file for further information. H* ------------------------------------------------------------------- I* Additional authors of this source file include: -* -* -* Z* ------------------------------------------------------------------- */ #include"os_python.h" #include "os_std.h" #include "os_gl.h" #include <clocale> #include "MemoryDebug.h" #include "Base.h" #include "OVContext.h" #include "MemoryDebug.h" #include "Err.h" #include "Util.h" #include "Selector.h" #include "Color.h" #include "Ortho.h" #include "Scene.h" #include "PyMOLObject.h" #include "Executive.h" #include "Word.h" #include "RepMesh.h" #include "ObjectMolecule.h" #include "Control.h" #include "Sphere.h" #include "Setting.h" #include "Ray.h" #include "Util.h" #include "Movie.h" #include "P.h" #include "Editor.h" #include "SculptCache.h" #include "Isosurf.h" #include "Tetsurf.h" #include "PConv.h" #include "VFont.h" #include "Wizard.h" #include "Text.h" #include "Character.h" #include "Seq.h" #include "Seeker.h" #include "Texture.h" #include "TestPyMOL.h" #include "TypeFace.h" #include "PlugIOManager.h" #include "MovieScene.h" #include "Lex.h" #include "PyMOL.h" #include "PyMOLGlobals.h" #include "PyMOLOptions.h" #include "Feedback.h" #include "GraphicsUtil.h" #include "ShaderMgr.h" #include "Version.h" #ifndef _PYMOL_NOPY PyMOLGlobals *SingletonPyMOLGlobals = NULL; #endif /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ #ifndef _PYMOL_NOPY #ifdef _MACPYMOL_XCODE extern int *MacPyMOLReady; extern CPyMOLOptions *MacPyMOLOption; #endif #endif /* END PROPRIETARY CODE SEGMENT */ #ifdef _MACPYMOL_XCODE /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ #define PYMOL_API_LOCK if((I->PythonInitStage) && (!I->ModalDraw) && PLockAPIAsGlut(I->G,true)) { #define PYMOL_API_LOCK_MODAL if((I->PythonInitStage) && PLockAPIAsGlut(I->G,true)) { #define PYMOL_API_TRYLOCK PYMOL_API_LOCK #define PYMOL_API_UNLOCK PUnlockAPIAsGlut(I->G); } #define PYMOL_API_UNLOCK_NO_FLUSH PUnlockAPIAsGlutNoFlush(I->G); } /* END PROPRIETARY CODE SEGMENT */ #else #ifdef _PYMOL_LIB_HAS_PYTHON #define PYMOL_API_LOCK if(I->PythonInitStage && (!I->ModalDraw)) { PLockAPIAndUnblock(I->G); { #define PYMOL_API_LOCK_MODAL if(I->PythonInitStage) { PLockAPIAndUnblock(I->G); { #define PYMOL_API_TRYLOCK if(I->PythonInitStage && (!I->ModalDraw)) { if(PTryLockAPIAndUnblock(I->G)) { #define PYMOL_API_UNLOCK PBlockAndUnlockAPI(I->G); }} #define PYMOL_API_UNLOCK_NO_FLUSH PBlockAndUnlockAPI(I->G); }} #else #define PYMOL_API_LOCK if(!I->ModalDraw) { #define PYMOL_API_LOCK_MODAL { #define PYMOL_API_TRYLOCK if(!I->ModalDraw) { #define PYMOL_API_UNLOCK } #define PYMOL_API_UNLOCK_NO_FLUSH } #endif #endif #define IDLE_AND_READY 3 #ifdef __cplusplus extern "C" { #endif typedef struct _CPyMOL { PyMOLGlobals *G; int FakeDragFlag; int RedisplayFlag; int PassiveFlag; int SwapFlag; int BusyFlag; int InterruptFlag; int ReshapeFlag; int ClickReadyFlag; int DrawnFlag; ObjectNameType ClickedObject; int ClickedIndex, ClickedButton, ClickedModifiers, ClickedX, ClickedY, ClickedHavePos, ClickedPosState; float ClickedPos[3]; int ImageRequestedFlag, ImageReadyFlag; int DraggedFlag; int Reshape[PYMOL_RESHAPE_SIZE]; int Progress[PYMOL_PROGRESS_SIZE]; int ProgressChanged; int IdleAndReady; int ExpireCount; bool done_ConfigureShaders; PyMOLModalDrawFn *ModalDraw; PyMOLSwapBuffersFn *SwapFn; /* Python stuff */ #ifndef _PYMOL_NOPY int PythonInitStage; #endif /* dynamically mapped string constants */ OVLexicon *Lex; OVOneToOne *Rep; ov_word lex_everything, lex_sticks, lex_spheres, lex_surface; ov_word lex_labels, lex_nb_spheres, lex_cartoon, lex_ribbon; ov_word lex_lines, lex_mesh, lex_dots, lex_dashes, lex_nonbonded; ov_word lex_cell, lex_cgo, lex_callback, lex_extent, lex_slice; OVOneToOne *Clip; ov_word lex_near, lex_far, lex_move, lex_slab, lex_atoms; OVOneToOne *Reinit; ov_word lex_settings; OVOneToOne *SelectList; ov_word lex_index, lex_id, lex_rank; OVOneToOne *Setting; #ifdef _PYMOL_LIB OVOneToOne *MouseButtonCodeLexicon; ov_word lex_left, lex_middle, lex_right; ov_word lex_wheel; ov_word lex_double_left, lex_double_middle, lex_double_right; ov_word lex_single_left, lex_single_middle, lex_single_right; OVOneToOne *MouseButtonModCodeLexicon; ov_word lex_none, lex_shft, lex_ctrl, lex_ctsh; ov_word lex_alt, lex_alsh, lex_ctal, lex_ctas; OVOneToOne *MouseButtonActionCodeLexicon; ov_word lex_but_rota, lex_but_move, lex_but_movz, lex_but_clip, lex_but_rotz; ov_word lex_but_clpn, lex_but_clpf, lex_but_lb, lex_but_mb, lex_but_rb; ov_word lex_but_plus_lb, lex_but_plus_mb, lex_but_plus_rb, lex_but_pkat, lex_but_pkbd; ov_word lex_but_rotf, lex_but_torf, lex_but_movf, lex_but_orig, lex_but_plus_lbx; ov_word lex_but_minus_lbx, lex_but_lbbx, lex_but_none, lex_but_cent, lex_but_pktb; ov_word lex_but_slab, lex_but_movs, lex_but_pk1; ov_word lex_but_mova, lex_but_menu, lex_but_sele, lex_but_plus_minus; ov_word lex_but_plus_box, lex_but_minus_box, lex_but_mvsz, lex_but_dgrt, lex_but_dgmv; ov_word lex_but_dgmz, lex_but_roto, lex_but_movo, lex_but_mvoz, lex_but_mvfz; ov_word lex_but_mvaz, lex_but_drgm, lex_but_rotv, lex_but_movv, lex_but_mvvz; ov_word lex_but_drgo, lex_but_imsz, lex_but_imvz, lex_but_box, lex_but_irtz; OVOneToOne *MouseModeLexicon; #include "buttonmodes_lex_def.h" OVOneToOne *PaletteLexicon; #include "palettes_lex_def.h" #endif AtomPropertyInfo AtomPropertyInfos[NUM_ATOM_PROPERTIES]; OVOneToOne *AtomPropertyLexicon; ov_word lex_atom_prop_model, lex_atom_prop_index, lex_atom_prop_type, lex_atom_prop_name, lex_atom_prop_resn, lex_atom_prop_resi, lex_atom_prop_resv, lex_atom_prop_chain, lex_atom_prop_alt, lex_atom_prop_segi, lex_atom_prop_elem, lex_atom_prop_ss, lex_atom_prop_text_type, lex_atom_prop_custom, lex_atom_prop_label, lex_atom_prop_numeric_type, lex_atom_prop_q, lex_atom_prop_b, lex_atom_prop_vdw, lex_atom_prop_elec_radius, lex_atom_prop_partial_charge, lex_atom_prop_formal_charge, lex_atom_prop_stereo, lex_atom_prop_cartoon, lex_atom_prop_color, lex_atom_prop_ID, lex_atom_prop_rank, lex_atom_prop_flags, lex_atom_prop_geom, lex_atom_prop_valence, lex_atom_prop_x, lex_atom_prop_y, lex_atom_prop_z, lex_atom_prop_settings, lex_atom_prop_properties, lex_atom_prop_reps, lex_atom_prop_protons, lex_atom_prop_oneletter, lex_atom_prop_s, lex_atom_prop_p, lex_atom_prop_state; /* lex_atom_prop_, lex_atom_prop_, lex_atom_prop_, lex_atom_prop_, lex_atom_prop_, lex_atom_prop_,*/ } _CPyMOL; /* convenience functions -- inline */ #ifdef _PYMOL_INLINE #define CC_INLINE __inline__ #else #define CC_INLINE #endif CC_INLINE static PyMOLstatus get_status_ok(int ok) { if(ok) return PyMOLstatus_SUCCESS; else return PyMOLstatus_FAILURE; } CC_INLINE static PyMOLreturn_status return_status_ok(int ok) { PyMOLreturn_status result; result.status = get_status_ok(ok); return result; } CC_INLINE static PyMOLreturn_status return_status(int status) { PyMOLreturn_status result; result.status = status; return result; } #ifdef _PYMOL_LIB int initial_button_modes[cButModeInputCount]; #endif static OVstatus PyMOL_InitAPI(CPyMOL * I) { OVContext *C = I->G->Context; OVreturn_word result; I->Lex = OVLexicon_New(C->heap); if(!I->Lex) return_OVstatus_FAILURE; /* the following preprocessor macros may require GNU's cpp or VC++ we'll see... */ #define LEX(ARG) \ if(!OVreturn_IS_OK( (result= OVLexicon_GetFromCString(I->Lex,#ARG)))) \ return_OVstatus_FAILURE \ else \ I -> lex_ ## ARG = result.word; /* string constants that are accepted on input */ #define LEX_REP(NAME,CODE) LEX(NAME) \ if(!OVreturn_IS_OK( OVOneToOne_Set(I->Rep,I->lex_ ## NAME, CODE))) \ return_OVstatus_FAILURE; I->Rep = OVOneToOne_New(C->heap); if(!I->Rep) return_OVstatus_FAILURE; LEX_REP(everything, -1); LEX_REP(sticks, 0); LEX_REP(spheres, 1); LEX_REP(surface, 2); LEX_REP(labels, 3); LEX_REP(nb_spheres, 4); LEX_REP(cartoon, 5); LEX_REP(ribbon, 6); LEX_REP(lines, 7); LEX_REP(mesh, 8); LEX_REP(dots, 9); LEX_REP(dashes, 10); LEX_REP(nonbonded, 11); LEX_REP(cell, 12); LEX_REP(cgo, 13); LEX_REP(callback, 14); LEX_REP(extent, 15); LEX_REP(slice, 16); /* workaround for unexplained bug with nested macro on VC6 */ #define LEX_CLIP(NAME,CODE) {if(!OVreturn_IS_OK( (result= OVLexicon_GetFromCString(I->Lex,#NAME)))) \ return_OVstatus_FAILURE \ else \ I -> lex_ ## NAME = result.word;} \ if(!OVreturn_IS_OK( OVOneToOne_Set(I->Clip,I->lex_ ## NAME, CODE))) \ return_OVstatus_FAILURE; I->Clip = OVOneToOne_New(C->heap); if(!I->Clip) return_OVstatus_FAILURE; LEX_CLIP(near, 0); LEX_CLIP(far, 1); LEX_CLIP(move, 2); LEX_CLIP(slab, 3); LEX_CLIP(atoms, 4); #define LEX_REINIT(NAME,CODE) {if(!OVreturn_IS_OK( (result= OVLexicon_GetFromCString(I->Lex,#NAME)))) \ return_OVstatus_FAILURE \ else \ I -> lex_ ## NAME = result.word;} \ if(!OVreturn_IS_OK( OVOneToOne_Set(I->Reinit,I->lex_ ## NAME, CODE))) \ return_OVstatus_FAILURE; I->Reinit = OVOneToOne_New(C->heap); if(!I->Reinit) return_OVstatus_FAILURE; LEX_REINIT(everything, 0); LEX_REINIT(settings, 1); #define LEX_SELLIST(NAME,CODE) {if(!OVreturn_IS_OK( (result= OVLexicon_GetFromCString(I->Lex,#NAME)))) \ return_OVstatus_FAILURE \ else \ I -> lex_ ## NAME = result.word;} \ if(!OVreturn_IS_OK( OVOneToOne_Set(I->SelectList,I->lex_ ## NAME, CODE))) \ return_OVstatus_FAILURE; I->SelectList = OVOneToOne_New(C->heap); if(!I->SelectList) return_OVstatus_FAILURE; LEX_SELLIST(index, 0); LEX_SELLIST(id, 1); LEX_SELLIST(rank, 2); I->Setting = OVOneToOne_New(C->heap); if(!I->Setting) return_OVstatus_FAILURE; if(!CPyMOLInitSetting(I->Lex, I->Setting)) return_OVstatus_FAILURE; #ifdef _PYMOL_LIB I->MouseButtonCodeLexicon = OVOneToOne_New(C->heap); if(!I->MouseButtonCodeLexicon) return_OVstatus_FAILURE; #define LEX_MOUSECODE(NAME,CODE) LEX(NAME) \ if(!OVreturn_IS_OK( OVOneToOne_Set(I->MouseButtonCodeLexicon,I->lex_ ## NAME, CODE))) \ return_OVstatus_FAILURE; LEX_MOUSECODE(left, 0); LEX_MOUSECODE(middle, 1); LEX_MOUSECODE(right, 2); LEX_MOUSECODE(wheel, 3); LEX_MOUSECODE(double_left, 4); LEX_MOUSECODE(double_middle, 5); LEX_MOUSECODE(double_right, 6); LEX_MOUSECODE(single_left, 7); LEX_MOUSECODE(single_middle, 8); LEX_MOUSECODE(single_right, 9); I->MouseButtonModCodeLexicon = OVOneToOne_New(C->heap); if(!I->MouseButtonModCodeLexicon) return_OVstatus_FAILURE; #define LEX_BUTTONMODCODE(NAME,CODE) LEX(NAME) \ if(!OVreturn_IS_OK( OVOneToOne_Set(I->MouseButtonModCodeLexicon,I->lex_ ## NAME, CODE))) \ return_OVstatus_FAILURE; LEX_BUTTONMODCODE(none, 0); LEX_BUTTONMODCODE(shft, 1); LEX_BUTTONMODCODE(ctrl, 2); LEX_BUTTONMODCODE(ctsh, 3); LEX_BUTTONMODCODE(alt, 4); LEX_BUTTONMODCODE(alsh, 5); LEX_BUTTONMODCODE(ctal, 6); LEX_BUTTONMODCODE(ctas, 7); I->MouseButtonActionCodeLexicon = OVOneToOne_New(C->heap); if(!I->MouseButtonActionCodeLexicon) return_OVstatus_FAILURE; #define LEX_BUT(ARG) \ if(!OVreturn_IS_OK( (result= OVLexicon_GetFromCString(I->Lex,#ARG)))) \ return_OVstatus_FAILURE \ else \ I -> lex_but_ ## ARG = result.word; #define LEX_BUTTONACTIONCODE(NAME,CODE) LEX_BUT(NAME) \ if(!OVreturn_IS_OK( OVOneToOne_Set(I->MouseButtonActionCodeLexicon,I->lex_but_ ## NAME, CODE))) \ return_OVstatus_FAILURE; #define LEX_BUTTONACTIONCODEWITHSTRING(NAME,STRARG,CODE) \ if(!OVreturn_IS_OK( (result= OVLexicon_GetFromCString(I->Lex,STRARG)))) \ return_OVstatus_FAILURE \ else \ I -> lex_but_ ## NAME = result.word; \ if(!OVreturn_IS_OK( OVOneToOne_Set(I->MouseButtonActionCodeLexicon,I->lex_but_ ## NAME, CODE))) \ return_OVstatus_FAILURE; LEX_BUTTONACTIONCODE(rota, 0); LEX_BUTTONACTIONCODE(move, 1); LEX_BUTTONACTIONCODE(movz, 2); LEX_BUTTONACTIONCODE(clip, 3); LEX_BUTTONACTIONCODE(rotz, 4); LEX_BUTTONACTIONCODE(clpn, 5); LEX_BUTTONACTIONCODE(clpf, 6); LEX_BUTTONACTIONCODE(lb, 7); LEX_BUTTONACTIONCODE(mb, 8); LEX_BUTTONACTIONCODE(rb, 9); LEX_BUTTONACTIONCODEWITHSTRING(plus_lb, "+lb", 10); LEX_BUTTONACTIONCODEWITHSTRING(plus_mb, "+mb", 11); LEX_BUTTONACTIONCODEWITHSTRING(plus_rb, "+rb", 12); LEX_BUTTONACTIONCODE(pkat, 13); LEX_BUTTONACTIONCODE(pkbd, 14); LEX_BUTTONACTIONCODE(rotf, 15); LEX_BUTTONACTIONCODE(torf, 16); LEX_BUTTONACTIONCODE(movf, 17); LEX_BUTTONACTIONCODE(orig, 18); LEX_BUTTONACTIONCODEWITHSTRING(plus_lbx, "+lbx", 19); LEX_BUTTONACTIONCODEWITHSTRING(minus_lbx, "-lbx", 20); LEX_BUTTONACTIONCODE(lbbx, 21); LEX_BUTTONACTIONCODE(none, 22); LEX_BUTTONACTIONCODE(cent, 23); LEX_BUTTONACTIONCODE(pktb, 24); LEX_BUTTONACTIONCODE(slab, 25); LEX_BUTTONACTIONCODE(movs, 26); LEX_BUTTONACTIONCODE(pk1, 27); LEX_BUTTONACTIONCODE(mova, 28); LEX_BUTTONACTIONCODE(menu, 29); LEX_BUTTONACTIONCODE(sele, 30); LEX_BUTTONACTIONCODEWITHSTRING(plus_minus,"+/-", 31); LEX_BUTTONACTIONCODEWITHSTRING(plus_box, "+box", 32); LEX_BUTTONACTIONCODEWITHSTRING(minus_box, "-box", 33); LEX_BUTTONACTIONCODE(mvsz, 34); LEX_BUTTONACTIONCODE(dgrt, 36); LEX_BUTTONACTIONCODE(dgmv, 37); LEX_BUTTONACTIONCODE(dgmz, 38); LEX_BUTTONACTIONCODE(roto, 39); LEX_BUTTONACTIONCODE(movo, 40); LEX_BUTTONACTIONCODE(mvoz, 41); LEX_BUTTONACTIONCODE(mvfz, 42); LEX_BUTTONACTIONCODE(mvaz, 43); LEX_BUTTONACTIONCODE(drgm, 44); LEX_BUTTONACTIONCODE(rotv, 45); LEX_BUTTONACTIONCODE(movv, 46); LEX_BUTTONACTIONCODE(mvvz, 47); LEX_BUTTONACTIONCODE(drgo, 49); LEX_BUTTONACTIONCODE(imsz, 50); LEX_BUTTONACTIONCODE(imvz, 51); LEX_BUTTONACTIONCODE(box, 52); LEX_BUTTONACTIONCODE(irtz, 53); I->MouseModeLexicon = OVOneToOne_New(C->heap); if(!I->MouseModeLexicon) return_OVstatus_FAILURE; #define LEX_MOUSEMODECODE(NAME,CODE) LEX(NAME) \ if(!OVreturn_IS_OK( OVOneToOne_Set(I->MouseModeLexicon,I->lex_ ## NAME, CODE))) \ return_OVstatus_FAILURE; #include "buttonmodes_lex_init.h" { int a; /* These are set by default for the modes, basically, any single or double click is a simple click (i.e., cButModeSimpleClick), mouse button actions are initialized to a potential click, wheel actions are set to none. This is very similar to what is done in PyMOL_SetMouseButtonMode(), and it makes it easier to specify new modes without needing to set every mouse function */ for(a = cButModeLeftDouble /* 16 */; a <= cButModeRightCtrlAltShftSingle /* 63 */; a++) { /* all single and double clicks */ initial_button_modes[a] = cButModeSimpleClick; } for(a = cButModeLeftAlt /* 68 */; a <= cButModeRightCtrlAltShft /* 79 */; a++) { /* all button modes with Alt */ initial_button_modes[a] = cButModePotentialClick; } for(a = cButModeLeftNone /* 0 */; a <= cButModeRightCtSh /* 11 */; a++) { /* all button modes without Alt */ initial_button_modes[a] = cButModePotentialClick; } for(a = cButModeWheelNone /* 12 */; a <= cButModeWheelCtSh /* 15 */; a++) { initial_button_modes[a] = cButModeNone; } for(a = cButModeWheelAlt /* 64 */; a <= cButModeWheelCtrlAltShft /* 67 */; a++) { initial_button_modes[a] = cButModeNone; } } I->PaletteLexicon = OVOneToOne_New(C->heap); if(!I->PaletteLexicon) return_OVstatus_FAILURE; #define LEX_PALETTE(NAME,CODE) LEX(NAME) \ if(!OVreturn_IS_OK( OVOneToOne_Set(I->PaletteLexicon,I->lex_ ## NAME, CODE))) \ return_OVstatus_FAILURE; #include "palettes_lex_init.h" #endif I->AtomPropertyLexicon = OVOneToOne_New(C->heap); if(!I->AtomPropertyLexicon) return_OVstatus_FAILURE; #define LEX_ATM_PROP(ARG) \ if(!OVreturn_IS_OK( (result= OVLexicon_GetFromCString(I->Lex,#ARG)))) \ return_OVstatus_FAILURE \ else \ I -> lex_atom_prop_ ## ARG = result.word; #define LEX_ATOM_PROP(NAME,CODE,TYPE,OFFSET) LEX_ATM_PROP(NAME) \ if(!OVreturn_IS_OK( OVOneToOne_Set(I->AtomPropertyLexicon,I->lex_atom_prop_ ## NAME, CODE))) \ return_OVstatus_FAILURE; \ I->AtomPropertyInfos[CODE].id = CODE; \ I->AtomPropertyInfos[CODE].Ptype = TYPE; \ I->AtomPropertyInfos[CODE].offset = OFFSET; \ I->AtomPropertyInfos[CODE].maxlen = 0; #define LEX_ATOM_PROP_S(NAME,CODE,TYPE,OFFSET,MAXLEN) LEX_ATM_PROP(NAME) \ if(!OVreturn_IS_OK( OVOneToOne_Set(I->AtomPropertyLexicon,I->lex_atom_prop_ ## NAME, CODE))) \ return_OVstatus_FAILURE; \ I->AtomPropertyInfos[CODE].id = CODE; \ I->AtomPropertyInfos[CODE].Ptype = TYPE; \ I->AtomPropertyInfos[CODE].offset = OFFSET; \ I->AtomPropertyInfos[CODE].maxlen = MAXLEN; /*TEMP*/ LEX_ATOM_PROP(model, 0, cPType_model, 0); LEX_ATOM_PROP(index, 1, cPType_index, 0); LEX_ATOM_PROP(type, 2, cPType_char_as_type, 0); LEX_ATOM_PROP(name, 3, cPType_int_as_string, offsetof(AtomInfoType,name)); LEX_ATOM_PROP(resn, 4, cPType_int_as_string, offsetof(AtomInfoType,resn)); LEX_ATOM_PROP(resi, 5, 0, 0); LEX_ATOM_PROP(resv, 6, cPType_int, offsetof(AtomInfoType,resv)); LEX_ATOM_PROP(chain, 7, cPType_int_as_string, offsetof(AtomInfoType,chain)); LEX_ATOM_PROP_S(alt, 8, cPType_string, offsetof(AtomInfoType,alt), 1); LEX_ATOM_PROP(segi, 9, cPType_int_as_string, offsetof(AtomInfoType,segi)); LEX_ATOM_PROP_S(elem, 10, cPType_string, offsetof(AtomInfoType,elem), cElemNameLen); LEX_ATOM_PROP_S(ss, 11, cPType_string, offsetof(AtomInfoType,ssType), 1); LEX_ATOM_PROP(text_type, 12, cPType_int_as_string, offsetof(AtomInfoType,textType)); LEX_ATOM_PROP(custom, 13, cPType_int_as_string, offsetof(AtomInfoType,custom)); LEX_ATOM_PROP(label, 14, cPType_int_as_string, offsetof(AtomInfoType,label)); LEX_ATOM_PROP(numeric_type, 15, cPType_int_custom_type, offsetof(AtomInfoType,customType)); LEX_ATOM_PROP(q, 16, cPType_float, offsetof(AtomInfoType,q)); LEX_ATOM_PROP(b, 17, cPType_float, offsetof(AtomInfoType,b)); LEX_ATOM_PROP(vdw, 18, cPType_float, offsetof(AtomInfoType,vdw)); LEX_ATOM_PROP(elec_radius, 19, cPType_float, offsetof(AtomInfoType,elec_radius)); LEX_ATOM_PROP(partial_charge, 20, cPType_float, offsetof(AtomInfoType,partialCharge)); LEX_ATOM_PROP(formal_charge, 21, cPType_schar, offsetof(AtomInfoType,formalCharge)); LEX_ATOM_PROP(stereo, 22, 0, 0); LEX_ATOM_PROP(cartoon, 23, cPType_schar, offsetof(AtomInfoType,cartoon)); LEX_ATOM_PROP(color, 24, cPType_int, offsetof(AtomInfoType,color)); LEX_ATOM_PROP(ID, 25, cPType_int, offsetof(AtomInfoType,id)); LEX_ATOM_PROP(rank, 26, cPType_int, offsetof(AtomInfoType,rank)); LEX_ATOM_PROP(flags, 27, cPType_int, offsetof(AtomInfoType,flags)); LEX_ATOM_PROP(geom, 28, cPType_schar, offsetof(AtomInfoType,geom)); LEX_ATOM_PROP(valence, 29, cPType_schar, offsetof(AtomInfoType,valence)); LEX_ATOM_PROP(x, 30, cPType_xyz_float, 0); LEX_ATOM_PROP(y, 31, cPType_xyz_float, 1); LEX_ATOM_PROP(z, 32, cPType_xyz_float, 2); LEX_ATOM_PROP(settings, 33, cPType_settings, 0); LEX_ATOM_PROP(properties, 34, cPType_properties, 0); LEX_ATOM_PROP(s, 35, cPType_settings, 0); LEX_ATOM_PROP(p, 36, cPType_properties, 0); LEX_ATOM_PROP(state, 37, cPType_state, 0); LEX_ATOM_PROP(reps, 38, cPType_int, offsetof(AtomInfoType, visRep)); LEX_ATOM_PROP(protons, 39, cPType_schar, offsetof(AtomInfoType, protons)); LEX_ATOM_PROP(oneletter, 40, 0, 0); // LEX_ATOM_PROP(, ); return_OVstatus_SUCCESS; } int PyMOL_NewG3DStream(CPyMOL * I, int **array_ptr) { int *return_vla = ExecutiveGetG3d(I->G); int result = OVstatus_FAILURE; if(return_vla) { result = VLAGetSize(return_vla) * (sizeof(G3dPrimitive) / sizeof(int)); } if(array_ptr) *array_ptr = return_vla; return result; } int PyMOL_DelG3DStream(CPyMOL * I, int *array_ptr) { VLAFreeP(array_ptr); return OVstatus_SUCCESS; } static OVstatus PyMOL_PurgeAPI(CPyMOL * I) { OVOneToOne_DEL_AUTO_NULL(I->Setting); OVOneToOne_DEL_AUTO_NULL(I->Clip); OVOneToOne_DEL_AUTO_NULL(I->SelectList); OVOneToOne_DEL_AUTO_NULL(I->Reinit); OVOneToOne_DEL_AUTO_NULL(I->Rep); #ifdef _PYMOL_LIB OVOneToOne_DEL_AUTO_NULL(I->MouseButtonCodeLexicon); OVOneToOne_DEL_AUTO_NULL(I->MouseButtonModCodeLexicon); OVOneToOne_DEL_AUTO_NULL(I->MouseButtonActionCodeLexicon); OVOneToOne_DEL_AUTO_NULL(I->MouseModeLexicon); OVOneToOne_DEL_AUTO_NULL(I->PaletteLexicon); OVOneToOne_DEL_AUTO_NULL(I->CartoonLexicon); OVOneToOne_DEL_AUTO_NULL(I->FlagLexicon); OVOneToOne_DEL_AUTO_NULL(I->FlagActionLexicon); #endif OVOneToOne_DEL_AUTO_NULL(I->AtomPropertyLexicon); OVLexicon_DEL_AUTO_NULL(I->Lex); return_OVstatus_SUCCESS; } int PyMOL_FreeResultArray(CPyMOL * I, void *array) { if(array) { VLAFreeP(array); return PyMOLstatus_SUCCESS; } else { return PyMOLstatus_FAILURE; } } PyMOLreturn_status PyMOL_CmdDraw(CPyMOL * I, int width, int height, int antialias, int quiet) { PyMOLreturn_status result = { PyMOLstatus_FAILURE }; PYMOL_API_LOCK result.status = get_status_ok(ExecutiveDrawCmd(I->G, width, height, antialias, false, quiet)); I->ImageRequestedFlag = true; I->ImageReadyFlag = false; PYMOL_API_UNLOCK return result; } PyMOLreturn_status PyMOL_CmdCapture(CPyMOL * I, int quiet) { PyMOLreturn_status result = { PyMOLstatus_FAILURE }; PYMOL_API_LOCK result.status = get_status_ok(ExecutiveDrawCmd(I->G, -1, -1, 0, true, quiet)); I->ImageRequestedFlag = true; I->ImageReadyFlag = false; PYMOL_API_UNLOCK return result; } PyMOLreturn_status PyMOL_CmdRay(CPyMOL * I, int width, int height, int antialias, float angle, float shift, int renderer, int defer, int quiet) { PyMOLreturn_status result = { PyMOLstatus_FAILURE }; PYMOL_API_LOCK if(renderer < 0) renderer = SettingGetGlobal_i(I->G, cSetting_ray_default_renderer); SceneInvalidateCopy(I->G, true); result.status = get_status_ok(ExecutiveRay (I->G, width, height, renderer, angle, shift, quiet, defer, antialias)); if(defer) { I->ImageRequestedFlag = true; I->ImageReadyFlag = false; } else { I->ImageRequestedFlag = false; if(SceneHasImage(I->G)) { I->ImageReadyFlag = true; } else { I->ImageReadyFlag = false; } } PYMOL_API_UNLOCK return result; } PyMOLreturn_status PyMOL_CmdSetView(CPyMOL * I, float *view, int view_len, float animate, int quiet) { PyMOLreturn_status result = { PyMOLstatus_FAILURE }; SceneViewType tmp; PYMOL_API_LOCK if(view_len >= 18) { int a; UtilZeroMem(tmp, sizeof(tmp)); tmp[15] = 1.0F; for(a = 0; a < 3; a++) { tmp[a] = view[a]; tmp[a + 4] = view[a + 3]; tmp[a + 8] = view[a + 6]; tmp[a + 16] = view[a + 9]; tmp[a + 19] = view[a + 12]; tmp[a + 22] = view[a + 15]; } SceneSetView(I->G, tmp, quiet, animate, 0); /* TO DO -- add hand to the API */ result.status = get_status_ok(true); } else { result.status = get_status_ok(false); } PYMOL_API_UNLOCK return result; } PyMOLreturn_float_array PyMOL_CmdGetView(CPyMOL * I, int quiet) { PyMOLreturn_float_array result = { PyMOLstatus_FAILURE }; SceneViewType tmp; PYMOL_API_LOCK result.size = 18; result.array = VLAlloc(float, result.size); if(result.array) { int a; SceneGetView(I->G, tmp); for(a = 0; a < 3; a++) { result.array[a] = tmp[a]; result.array[a + 3] = tmp[a + 4]; result.array[a + 6] = tmp[a + 8]; result.array[a + 9] = tmp[a + 16]; result.array[a + 12] = tmp[a + 19]; result.array[a + 15] = tmp[a + 22]; } result.status = get_status_ok(true); } else { result.status = get_status_ok(false); } PYMOL_API_UNLOCK return result; } PyMOLreturn_float_array PyMOL_CmdAlign(CPyMOL * I, const char *source, const char *target, float cutoff, int cycles, float gap, float extend, int max_gap, const char *object, const char *matrix, int source_state, int target_state, int quiet, int max_skip, int transform, int reset) { PyMOLreturn_float_array result = { PyMOLstatus_FAILURE }; PYMOL_API_LOCK OrthoLineType s2 = "", s3 = ""; int ok = false; ExecutiveRMSInfo rms_info; result.size = 7; result.array = VLAlloc(float, result.size); if(!result.array) { ok = false; } else { ok = ((SelectorGetTmp(I->G, source, s2) >= 0) && (SelectorGetTmp(I->G, target, s3) >= 0)); if(ok) { const float _0 = 0.0F; /* GCC compiler bug workaround */ const float _m1 = -1.0F; ok = ExecutiveAlign(I->G, s2, s3, matrix, gap, extend, max_gap, max_skip, cutoff, cycles, quiet, object, source_state - 1, target_state - 1, &rms_info, transform, reset, _m1, _0, _0, _0, _0, _0, 0, _0); if(ok) { result.array[0] = rms_info.final_rms; result.array[1] = rms_info.final_n_atom; result.array[2] = rms_info.n_cycles_run; result.array[3] = rms_info.initial_rms; result.array[4] = rms_info.initial_n_atom; result.array[5] = rms_info.raw_alignment_score; result.array[6] = rms_info.n_residues_aligned; } } } SelectorFreeTmp(I->G, s2); SelectorFreeTmp(I->G, s3); if(!ok) { VLAFreeP(result.array); } result.status = get_status_ok(ok); PYMOL_API_UNLOCK return result; } PyMOLreturn_status PyMOL_CmdDelete(CPyMOL * I, const char *name, int quiet) { PYMOL_API_LOCK ExecutiveDelete(I->G, name); PyMOL_NeedRedisplay(I); /* this should really only get called if ExecutiveDelete deletes something */ PYMOL_API_UNLOCK return return_status_ok(true); /* TO DO: return a real result */ } PyMOLreturn_status PyMOL_CmdZoom(CPyMOL * I, const char *selection, float buffer, int state, int complete, float animate, int quiet) { int ok = false; PYMOL_API_LOCK ok = ExecutiveWindowZoom(I->G, selection, buffer, state - 1, complete, animate, quiet); PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdOrient(CPyMOL * I, const char *selection, float buffer, int state, int complete, float animate, int quiet) { int ok = true; PYMOL_API_LOCK double m[16]; OrthoLineType s1; SelectorGetTmp(I->G, selection, s1); if(ExecutiveGetMoment(I->G, s1, m, state)) ExecutiveOrient(I->G, s1, m, state - 1, animate, complete, buffer, quiet); /* TODO STATUS */ else ok = false; SelectorFreeTmp(I->G, s1); PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdCenter(CPyMOL * I, const char *selection, int state, int origin, float animate, int quiet) { int ok = false; PYMOL_API_LOCK ok = ExecutiveCenter(I->G, selection, state - 1, origin, animate, NULL, quiet); PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdOrigin(CPyMOL * I, const char *selection, int state, int quiet) { int ok = true; PYMOL_API_LOCK OrthoLineType s1; float v[3] = { 0.0F, 0.0F, 0.0F }; SelectorGetTmp2(I->G, selection, s1); ok = ExecutiveOrigin(I->G, s1, true, "", v, state - 1); /* TODO STATUS */ SelectorFreeTmp(I->G, s1); PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdOriginAt(CPyMOL * I, float x, float y, float z, int quiet) { int ok = true; PYMOL_API_LOCK float v[3]; v[0] = x; v[1] = y; v[2] = z; ok = ExecutiveOrigin(I->G, "", true, "", v, 0); /* TODO STATUS */ PYMOL_API_UNLOCK return return_status_ok(ok); } static OVreturn_word get_rep_id(CPyMOL * I, const char *representation) { OVreturn_word result; if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, representation)))) return result; return OVOneToOne_GetForward(I->Rep, result.word); } OVreturn_word get_setting_id(CPyMOL * I, const char *setting) { OVreturn_word result; if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, setting)))) return result; return OVOneToOne_GetForward(I->Setting, result.word); } static OVreturn_word get_clip_id(CPyMOL * I, const char *clip) { OVreturn_word result; if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, clip)))) return result; return OVOneToOne_GetForward(I->Clip, result.word); } static OVreturn_word get_reinit_id(CPyMOL * I, const char *reinit) { OVreturn_word result; if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, reinit)))) return result; return OVOneToOne_GetForward(I->Reinit, result.word); } static OVreturn_word get_select_list_mode(CPyMOL * I, const char *mode) { OVreturn_word result; if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, mode)))) return result; return OVOneToOne_GetForward(I->SelectList, result.word); } PyMOLreturn_status PyMOL_CmdClip(CPyMOL * I, const char *mode, float amount, const char *selection, int state, int quiet) { int ok = true; PYMOL_API_LOCK OrthoLineType s1; OVreturn_word clip_id; if(OVreturn_IS_OK((clip_id = get_clip_id(I, mode)))) { SelectorGetTmp2(I->G, selection, s1); SceneClip(I->G, clip_id.word, amount, s1, state - 1); SelectorFreeTmp(I->G, s1); } PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdLabel(CPyMOL * I, const char *selection, const char *text, int quiet) { int ok = true; PYMOL_API_LOCK OrthoLineType s1; SelectorGetTmp(I->G, selection, s1); ok = ExecutiveLabel(I->G, s1, text, quiet, cExecutiveLabelEvalAlt); SelectorFreeTmp(I->G, s1); PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdSelect(CPyMOL * I, const char *name, const char *selection, int quiet) { int ret = -1; PYMOL_API_LOCK ret = SelectorCreate(I->G, name, selection, NULL, quiet, NULL); PYMOL_API_UNLOCK return return_status_ok(ret >= 0); // if ret is negative it should fail } PyMOLreturn_status PyMOL_CmdSelectList(CPyMOL * I, const char *name, const char *object, int *list, int list_len, int state, const char *mode, int quiet) { PyMOLreturn_status result = { PyMOLstatus_FAILURE }; PYMOL_API_LOCK OVreturn_word mode_id; if(OVreturn_IS_OK((mode_id = get_select_list_mode(I, mode)))) { result.status = ExecutiveSelectList(I->G, name, object, list, list_len, state - 1, mode_id.word, quiet); } PYMOL_API_UNLOCK return result; } PyMOLreturn_status PyMOL_CmdShow(CPyMOL * I, const char *representation, const char *selection, int quiet) { int ok = true; PYMOL_API_LOCK OrthoLineType s1; OVreturn_word rep_id; if(OVreturn_IS_OK((rep_id = get_rep_id(I, representation)))) { SelectorGetTmp2(I->G, selection, s1); if (!s1[0]){ /* This doesn't catch patterns that don't match, but everything else */ ok = false; } else { ExecutiveSetRepVisib(I->G, s1, rep_id.word, true); PyMOL_NeedRedisplay(I); /* this should really only get called if ExecutiveSetRepVisib changes something */ SelectorFreeTmp(I->G, s1); } } else { ok = false; } PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdHide(CPyMOL * I, const char *representation, const char *selection, int quiet) { int ok = true; PYMOL_API_LOCK OrthoLineType s1; OVreturn_word rep_id; if(OVreturn_IS_OK((rep_id = get_rep_id(I, representation)))) { SelectorGetTmp2(I->G, selection, s1); if (!s1[0]){ /* This doesn't catch patterns that don't match, but everything else */ ok = false; } else { ExecutiveSetRepVisib(I->G, s1, rep_id.word, false); SelectorFreeTmp(I->G, s1); } } else { ok = false; } PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdEnable(CPyMOL * I, const char *name, int quiet) { int ok = false; PYMOL_API_LOCK if(name[0] == '(') { OrthoLineType s1; ok = (SelectorGetTmp2(I->G, name, s1) >= 0); if(ok) ok = ExecutiveSetOnOffBySele(I->G, s1, true); SelectorFreeTmp(I->G, s1); } ok = ExecutiveSetObjVisib(I->G, name, true, false); /* TO DO: parents */ PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdDisable(CPyMOL * I, const char *name, int quiet) { int ok = false; PYMOL_API_LOCK if(name[0] == '(') { OrthoLineType s1 = ""; ok = (SelectorGetTmp2(I->G, name, s1) >= 0); if(ok) ok = ExecutiveSetOnOffBySele(I->G, s1, false); SelectorFreeTmp(I->G, s1); } else { ok = ExecutiveSetObjVisib(I->G, name, false, false); } PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdSetBond(CPyMOL * I, const char *setting, const char *value, const char *selection1, const char *selection2, int state, int quiet, int side_effects) { int ok = true; PYMOL_API_LOCK { OVreturn_word setting_id; OrthoLineType s1 = ""; OrthoLineType s2 = ""; if(ok) ok = OVreturn_IS_OK((setting_id = get_setting_id(I, setting))); if(ok) ok = (SelectorGetTmp(I->G, selection1, s1) >= 0); if(ok) { if(selection2 && selection2[0]) { ok = (SelectorGetTmp(I->G, selection2, s2) >= 0); } else { ok = (SelectorGetTmp(I->G, selection1, s2) >= 0); } } if(ok) { ok = ExecutiveSetBondSettingFromString(I->G, setting_id.word, value, s1, s2, state - 1, quiet, side_effects); } SelectorFreeTmp(I->G, s1); SelectorFreeTmp(I->G, s2); } PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdUnsetBond(CPyMOL * I, const char *setting, const char *selection1, const char *selection2, int state, int quiet, int side_effects) { int ok = true; PYMOL_API_LOCK { OVreturn_word setting_id; OrthoLineType s1 = ""; OrthoLineType s2 = ""; if(ok) ok = OVreturn_IS_OK((setting_id = get_setting_id(I, setting))); if(ok) ok = (SelectorGetTmp(I->G, selection1, s1) >= 0); if(ok) { if(selection2 && selection2[0]) { ok = (SelectorGetTmp(I->G, selection2, s2) >= 0); } else { ok = (SelectorGetTmp(I->G, selection1, s2) >= 0); } } if(ok) { ok = ExecutiveUnsetBondSetting(I->G, setting_id.word, s1, s2, state - 1, quiet, side_effects); } SelectorFreeTmp(I->G, s1); SelectorFreeTmp(I->G, s2); } PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdSet(CPyMOL * I, const char *setting, const char *value, const char *selection, int state, int quiet, int side_effects) { int ok = true; PYMOL_API_LOCK { OVreturn_word setting_id; OrthoLineType s1 = ""; if(ok) ok = OVreturn_IS_OK((setting_id = get_setting_id(I, setting))); if(ok) ok = (SelectorGetTmp2(I->G, selection, s1) >= 0); if(ok) { ExecutiveSetSettingFromString(I->G, setting_id.word, value, s1, state - 1, quiet, side_effects); } SelectorFreeTmp(I->G, s1); } PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_value PyMOL_CmdGet(CPyMOL * I, const char *setting, const char *selection, int state, int quiet){ int ok = true; PyMOLreturn_value result = { PyMOLstatus_SUCCESS }; PYMOL_API_LOCK { OVreturn_word setting_id; OrthoLineType s1 = ""; if(ok) ok = OVreturn_IS_OK((setting_id = get_setting_id(I, setting))); if(ok) ok = (SelectorGetTmp2(I->G, selection, s1) >= 0); if(ok) { ExecutiveGetSettingFromString(I->G, &result, setting_id.word, s1, state - 1, quiet); } SelectorFreeTmp(I->G, s1); } PYMOL_API_UNLOCK return result; } PyMOLreturn_status PyMOL_CmdUnset(CPyMOL * I, const char *setting, const char *selection, int state, int quiet, int side_effects) { int ok = true; PYMOL_API_LOCK { OVreturn_word setting_id; OrthoLineType s1 = ""; if(ok) ok = OVreturn_IS_OK((setting_id = get_setting_id(I, setting))); if(ok) ok = (SelectorGetTmp2(I->G, selection, s1) >= 0); if(ok) { ExecutiveUnsetSetting(I->G, setting_id.word, s1, state - 1, quiet, side_effects); } SelectorFreeTmp(I->G, s1); } PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdColor(CPyMOL * I, const char *color, const char *selection, int flags, int quiet) { int ok = true; PYMOL_API_LOCK OrthoLineType s1 = ""; SelectorGetTmp2(I->G, selection, s1); ok = ExecutiveColor(I->G, s1, color, flags, quiet); SelectorFreeTmp(I->G, s1); PYMOL_API_UNLOCK return return_status_ok(ok); } /* -- JV */ PyMOLreturn_status PyMOL_CmdBackgroundColor(CPyMOL * I, const char *value) { int ok = true; PYMOL_API_LOCK int idx = ColorGetIndex(I->G, value); if(idx >= 0){ SettingSetGlobal_i(I->G, cSetting_bg_rgb, idx); } else { ErrMessage(I->G, "Color", "Bad color name."); } PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdReinitialize(CPyMOL * I, const char *what, const char *object_name) { int ok = true; OVreturn_word what_id; PYMOL_API_LOCK if(OVreturn_IS_OK((what_id = get_reinit_id(I, what)))) { ok = ExecutiveReinitialize(I->G, what_id.word, object_name); } PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_int PyMOL_CmdGetMovieLength(CPyMOL * I,int quiet) { int ok = true; PyMOLreturn_int result; result.status = PyMOLstatus_FAILURE; result.value = 0; PYMOL_API_LOCK if(ok) { result.value = MovieGetLength(I->G); result.status = get_status_ok(ok); }; PYMOL_API_UNLOCK return result; } PyMOLreturn_float PyMOL_CmdGetDistance(CPyMOL * I, const char *selection1, const char *selection2, int state, int quiet) { int ok = true; PyMOLreturn_float result; PYMOL_API_LOCK { ok = ExecutiveGetDistance(I->G, selection1, selection2, &result.value, state); result.status = get_status_ok(ok); } PYMOL_API_UNLOCK return result; } PyMOLreturn_float PyMOL_CmdDistance(CPyMOL * I, const char *name, const char *selection1, const char *selection2, int mode, float cutoff, int label, int reset, int zoom, int state, int quiet) { int ok = true; PyMOLreturn_float result; PYMOL_API_LOCK { ok = ExecutiveDist(I->G, &result.value, name, selection1, selection2, mode, cutoff, label, quiet, reset, state, zoom); result.status = get_status_ok(ok); } PYMOL_API_UNLOCK return result; } PyMOLreturn_float PyMOL_CmdGetAngle(CPyMOL * I, const char *selection1, const char *selection2, const char *selection3, int state, int quiet) { int ok = true; PyMOLreturn_float result; PYMOL_API_LOCK { ok = ExecutiveGetAngle(I->G, selection1, selection2, selection3, &result.value, state); result.status = get_status_ok(ok); } PYMOL_API_UNLOCK return result; } PyMOLreturn_float PyMOL_CmdAngle(CPyMOL * I, const char *name, const char *selection1, const char *selection2, const char *selection3, int mode, int label, int reset, int zoom, int state, int quiet) { int ok = true; PyMOLreturn_float result; PYMOL_API_LOCK { ok = ExecutiveAngle(I->G, &result.value, name, selection1, selection2, selection3, mode, label, reset, zoom, quiet, state); result.status = get_status_ok(ok); } PYMOL_API_UNLOCK return result; } PyMOLreturn_float PyMOL_CmdGetDihedral(CPyMOL * I, const char *selection1, const char *selection2, const char *selection3, const char *selection4, int state, int quiet) { int ok = true; PyMOLreturn_float result; PYMOL_API_LOCK { ok = ExecutiveGetDihe(I->G, selection1, selection2, selection3, selection4, &result.value, state); result.status = get_status_ok(ok); } PYMOL_API_UNLOCK return result; } PyMOLreturn_float PyMOL_CmdDihedral(CPyMOL * I, const char *name, const char *selection1, const char *selection2, const char *selection3, const char *selection4, int mode, int label, int reset, int zoom, int state, int quiet) { int ok = true; PyMOLreturn_float result; PYMOL_API_LOCK { ExecutiveDihedral(I->G, &result.value, name, selection1, selection2, selection3, selection4, mode, label, reset, zoom, quiet, state); result.status = get_status_ok(ok); } PYMOL_API_UNLOCK return result; } PyMOLreturn_status PyMOL_CmdIsodot(CPyMOL * I, const char *name, const char *map_name, float level, const char *selection, float buffer, int state, float carve, int source_state, int quiet) { int ok = true; OrthoLineType s1 = ""; PyMOLreturn_status result = { PyMOLstatus_FAILURE }; int box_mode = 0; PYMOL_API_LOCK if(selection && selection[0]) { if(ok) ok = (SelectorGetTmp(I->G, selection, s1) >= 0); if(ok) box_mode = 1; } if(ok) { ok = ExecutiveIsomeshEtc(I->G, name, map_name, level, s1, buffer, state - 1, carve, source_state - 1, quiet, 1, box_mode, level); result.status = get_status_ok(ok); } else { result.status = PyMOLstatus_FAILURE; } SelectorFreeTmp(I->G, s1); PYMOL_API_UNLOCK return result; } PyMOLreturn_status PyMOL_CmdIsomesh(CPyMOL * I, const char *name, const char *map_name, float level, const char *selection, float buffer, int state, float carve, int source_state, int quiet) { int ok = true; OrthoLineType s1 = ""; PyMOLreturn_status result = { PyMOLstatus_FAILURE }; int box_mode = 0; PYMOL_API_LOCK if(selection && selection[0]) { if(ok) ok = (SelectorGetTmp(I->G, selection, s1) >= 0); if(ok) box_mode = 1; } if(ok) { ok = ExecutiveIsomeshEtc(I->G, name, map_name, level, s1, buffer, state - 1, carve, source_state - 1, quiet, 0, box_mode, level); result.status = get_status_ok(ok); } else { result.status = PyMOLstatus_FAILURE; } SelectorFreeTmp(I->G, s1); PYMOL_API_UNLOCK return result; } PyMOLreturn_status PyMOL_CmdIsosurface(CPyMOL * I, const char *name, const char *map_name, float level, const char *selection, float buffer, int state, float carve, int source_state, int side, int mode, int quiet) { int ok = true; OrthoLineType s1 = ""; PyMOLreturn_status result = { PyMOLstatus_FAILURE }; int box_mode = 0; PYMOL_API_LOCK if(selection && selection[0]) { if(ok) ok = (SelectorGetTmp(I->G, selection, s1) >= 0); if(ok) box_mode = 1; } if(ok) { ok = ExecutiveIsosurfaceEtc(I->G, name, map_name, level, s1, buffer, state - 1, carve, source_state - 1, side, quiet, mode, box_mode); result.status = get_status_ok(ok); } else { result.status = PyMOLstatus_FAILURE; } SelectorFreeTmp(I->G, s1); PYMOL_API_UNLOCK return result; } PyMOLreturn_status PyMOL_CmdGradient(CPyMOL * I, const char *name, const char *map_name, float minimum, float maximum, const char *selection, float buffer, int state, float carve, int source_state, int quiet) { int ok = true; OrthoLineType s1 = ""; PyMOLreturn_status result = { PyMOLstatus_FAILURE }; int box_mode = 0; PYMOL_API_LOCK if(selection && selection[0]) { if(ok) ok = (SelectorGetTmp(I->G, selection, s1) >= 0); if(ok) box_mode = 1; } if(ok) { ok = ExecutiveIsomeshEtc(I->G, name, map_name, minimum, s1, buffer, state - 1, carve, source_state - 1, quiet, 3, box_mode, maximum); result.status = get_status_ok(ok); } else { result.status = PyMOLstatus_FAILURE; } SelectorFreeTmp(I->G, s1); PYMOL_API_UNLOCK return result; } PyMOLreturn_float PyMOL_CmdIsolevel(CPyMOL * I, const char *name, float level, int state, int query, int quiet) { int ok = true; OrthoLineType s1 = ""; PyMOLreturn_float result; PYMOL_API_LOCK if(ok) { ok = ExecutiveIsolevel(I->G, name, level, state - 1, query, &result.value, quiet); result.status = get_status_ok(ok); } else { result.status = PyMOLstatus_FAILURE; result.value = 0.0F; } SelectorFreeTmp(I->G, s1); PYMOL_API_UNLOCK return result; } static int word_count(const char *src) { /* only works for ascii */ int cnt = 0; while((*src) && ((*src) < 33)) /* skip leading whitespace */ src++; while(*src) { if((*src) > 32) { cnt++; while((*src) && ((*src) > 32)) src++; } while((*src) && ((*src) < 33)) src++; } return cnt; } static const char *next_word(const char *src, char *dst, int buf_size) { /* only works for ascii */ while((*src) && ((*src) < 33)) /* skip leading whitespace */ src++; while(*src) { if((*src) > 32) { while((*src) && ((*src) > 32) && (buf_size > 1)) { *(dst++) = *(src++); buf_size--; } break; } } dst[0] = 0; return src; } PyMOLreturn_status PyMOL_CmdRampNew(CPyMOL * I, const char *name, const char *map, float *range, int n_level, const char *color, int state, const char *selection, float beyond, float within, float sigma, int zero, int calc_mode, int quiet) { int ok = true; PyMOLreturn_status result = { PyMOLstatus_FAILURE }; OrthoLineType s1 = ""; float *color_vla = NULL; float *range_vla = NULL; PYMOL_API_LOCK if(selection && selection[0]) { if(ok) ok = (SelectorGetTmp(I->G, selection, s1) >= 0); } if(ok) { if(range && n_level) { range_vla = VLAlloc(float, n_level); UtilCopyMem(range_vla, range, sizeof(float) * n_level); } } if(ok && color) { int n_color = word_count(color); /* to do */ if(color && n_color) { color_vla = VLAlloc(float, n_color * 3); if(color_vla) { WordType colorName; int a; for(a = 0; a < n_color; a++) { color = next_word(color, colorName, sizeof(colorName)); { const float *src = ColorGetNamed(I->G, colorName); float *dst = color_vla + 3 * a; copy3f(src, dst); } } } } } if(ok) { ok = ExecutiveRampNew(I->G, name, map, range_vla, color_vla, state, s1, beyond, within, sigma, zero, calc_mode, quiet); result.status = get_status_ok(ok); } else { result.status = PyMOLstatus_FAILURE; } SelectorFreeTmp(I->G, s1); PYMOL_API_UNLOCK return result; } /* * Supported file formats and they internal codes */ struct { const char * name; cLoadType_t code_buffer; cLoadType_t code_filename; } const ContentTypeTable[] = { // molecules {"pdb", cLoadTypePDBStr, cLoadTypePDB}, {"vdb", cLoadTypeVDBStr, cLoadTypeUnknown}, {"cif", cLoadTypeCIFStr, cLoadTypeCIF}, {"mmtf", cLoadTypeMMTFStr, cLoadTypeMMTF}, {"mae", cLoadTypeMAEStr, cLoadTypeMAE}, {"sdf", cLoadTypeSDF2Str, cLoadTypeSDF2}, {"mol", cLoadTypeMOLStr, cLoadTypeMOL}, {"mol2", cLoadTypeMOL2Str, cLoadTypeMOL2}, {"xyz", cLoadTypeXYZStr, cLoadTypeXYZ}, {"pqr", cLoadTypeUnknown, cLoadTypePQR}, {"macromodel", cLoadTypeMMDStr, cLoadTypeMMD}, // maps {"ccp4", cLoadTypeCCP4Str, cLoadTypeUnknown}, {"xplor", cLoadTypeXPLORStr, cLoadTypeXPLORMap}, {"phi", cLoadTypePHIStr, cLoadTypePHIMap}, {"dx", cLoadTypeUnknown, cLoadTypeDXMap}, // special {"cgo", cLoadTypeCGO, cLoadTypeUnknown}, {NULL, cLoadTypeUnknown, cLoadTypeUnknown} }; /* * Proxy for "ExecutiveLoad" with string "content_format" (and "content_type") * argument. * * content: Either file name or file contents, depending on "content_type" * content_type: "filename", "string", "raw", or "cgo" * content_length: Length of "content", if it's not a file name or a * null-terminated string (pass -1). * content_format: The file format, e.g. "pdb", "sdf", "mol2", ... * object_name: New object name. Can be empty if "content_type" is * "filename". */ static PyMOLreturn_status Loader(CPyMOL * I, const char *content, const char *content_type, int content_length, const char *content_format, const char *object_name, int state, int discrete, int finish, int quiet, int multiplex, int zoom) { PyMOLGlobals * G = I->G; bool content_is_filename = false; int ok = true; WordType obj_name; // `content` can be a file name, or the file contents if (strcmp(content_type, "filename") == 0) { content_is_filename = true; } else if (strcmp(content_type, "string") == 0) { if (content_length < 0) content_length = strlen(content); } else if ( strcmp(content_type, "raw") != 0 && strcmp(content_type, "cgo") != 0) { PRINTFB(G, FB_Executive, FB_Errors) " Error: Unknown content type '%s'\n", content_type ENDFB(G); ok = false; } if(ok) { { /* if object_name is blank and content is a filename, then compute the object_name from the file prefix */ if((!object_name[0]) && content_is_filename) { const char *start, *stop; stop = start = content + strlen(content) - 1; while(start > content) { /* known path separators */ if((start[-1] == ':') || (start[-1] == '\'') || (start[-1] == '/')) break; start--; } while(stop > start) { if(*stop == '.') break; stop--; } if(stop == start) stop = content + strlen(content); if((stop - start) >= sizeof(WordType)) stop = start + sizeof(WordType) - 1; { char *q; const char *p = start; q = obj_name; while(p < stop) { *(q++) = *(p++); } *q = 0; object_name = obj_name; } } } { cLoadType_t pymol_content_type = cLoadTypeUnknown; for (auto it = ContentTypeTable; it->name; ++it) { if (strcmp(it->name, content_format) == 0) { pymol_content_type = content_is_filename ? it->code_filename : it->code_buffer; break; } } if (pymol_content_type == cLoadTypeUnknown) { PRINTFB(G, FB_Executive, FB_Errors) " Error: Unknown content format '%s' with type '%s'\n", content_format, content_type ENDFB(G); ok = false; } if(ok) { ok = ExecutiveLoad(I->G, content, content_length, pymol_content_type, object_name, state - 1, zoom, discrete, finish, multiplex, quiet, NULL, 0, NULL); } } } if (ok) PyMOL_NeedRedisplay(I); return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdLoad(CPyMOL * I, const char *content, const char *content_type, const char *content_format, const char *object_name, int state, int discrete, int finish, int quiet, int multiplex, int zoom) { PyMOLreturn_status status = { PyMOLstatus_FAILURE }; PYMOL_API_LOCK status = Loader(I, content, content_type, -1, content_format, object_name, state, discrete, finish, quiet, multiplex, zoom); PYMOL_API_UNLOCK return status; } PyMOLreturn_status PyMOL_CmdLoadRaw(CPyMOL * I, const char *content, int content_length, const char *content_format, const char *object_name, int state, int discrete, int finish, int quiet, int multiplex, int zoom) { PyMOLreturn_status status = { PyMOLstatus_FAILURE }; PYMOL_API_LOCK status = Loader(I, content, "raw", content_length, content_format, object_name, state, discrete, finish, quiet, multiplex, zoom); PYMOL_API_UNLOCK return status; } PyMOLreturn_status PyMOL_CmdLoadCGO(CPyMOL * I, const float *content, int content_length, const char *object_name, int state, int quiet, int zoom) { PyMOLreturn_status status = { PyMOLstatus_FAILURE }; PYMOL_API_LOCK status = Loader(I, (char *) content, "cgo", content_length, "cgo", object_name, state, 0, 1, quiet, 0, zoom); PYMOL_API_UNLOCK return status; } PyMOLreturn_status PyMOL_CmdCreate(CPyMOL * I, const char *name, const char *selection, int source_state, int target_state, int discrete, int zoom, int quiet, int singletons, const char *extract, int copy_properties) { int ok = true; PYMOL_API_LOCK ok = ExecutiveSeleToObject(I->G, name, selection, source_state, target_state, discrete, zoom, quiet, singletons, copy_properties); PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdPseudoatom(CPyMOL * I, const char *object_name, const char *selection, const char *name, const char *resn, const char *resi, const char *chain, const char *segi, const char *elem, float vdw, int hetatm, float b, float q, const char *color, const char *label, int use_xyz, float x, float y, float z, int state, int mode, int quiet) { int ok = true; PYMOL_API_LOCK if(ok) { OrthoLineType s1; int color_index = ColorGetIndex(I->G, color); ok = (SelectorGetTmp2(I->G, selection, s1)) >= 0; if(ok) { float pos_tmp[3], *pos = pos_tmp; if(use_xyz) { pos[0] = x; pos[1] = y; pos[2] = z; } else { pos = NULL; } ok = ExecutivePseudoatom(I->G, object_name, s1, name, resn, resi, chain, segi, elem, vdw, hetatm, b, q, label, pos, color_index, state - 1, mode, quiet); } SelectorFreeTmp(I->G, s1); } PYMOL_API_UNLOCK return return_status_ok(ok); } PyMOLreturn_status PyMOL_CmdTurn(CPyMOL * I, char axis, float angle){ PyMOLreturn_status result = { PyMOLstatus_SUCCESS }; PYMOL_API_LOCK PyMOLGlobals * G = I->G; switch (axis){ case 'x': SceneRotate(G, angle, 1.0, 0.0, 0.0); break; case 'y': SceneRotate(G, angle, 0.0, 1.0, 0.0); break; case 'z': SceneRotate(G, angle, 0.0, 0.0, 1.0); break; default: result.status = PyMOLstatus_FAILURE; break; } PYMOL_API_UNLOCK return result; } PyMOLreturn_status PyMOL_CmdMPlay(CPyMOL * I, int cmd){ PyMOLreturn_status result = { PyMOLstatus_SUCCESS }; PYMOL_API_LOCK PyMOLGlobals * G = I->G; MoviePlay(G, cmd); PYMOL_API_UNLOCK return result; } PyMOLreturn_status PyMOL_CmdSetFeedbackMask(CPyMOL * I, int action, int module, int mask){ PyMOLreturn_status result = { PyMOLstatus_SUCCESS }; PYMOL_API_LOCK PyMOLGlobals * G = I->G; switch (action){ case 0: FeedbackSetMask(G, module, (uchar) mask); break; case 1: FeedbackEnable(G, module, (uchar) mask); break; case 2: FeedbackDisable(G, module, (uchar) mask); break; case 3: FeedbackPush(G); break; case 4: FeedbackPop(G); break; } PYMOL_API_UNLOCK return result; } static const CPyMOLOptions Defaults = { true, /* pmgui */ #ifndef _PYMOL_NOPY true, /* internal_gui */ #else false, #endif #ifndef _PYMOL_NOPY true, /* show_splash */ #else false, #endif #ifndef _PYMOL_NOPY 1, /* internal_feedback */ #else 0, #endif true, /* security */ false, /* game mode */ 0, /* force_stereo */ 640, /* winX */ 480, /* winY */ false, /* blue_line */ 0, /* winPX */ 175, /* winPY */ true, /* external_gui */ true, /* siginthand */ false, /* reuse helper */ false, /* auto reinitialize */ false, /* keep thread alive */ false, /* quiet */ false, /* incentive product */ "", /* after_load_script */ 0, /* multisample */ 1, /* window_visible */ 0, /* read_stdin */ 0, /* presentation */ 0, /* defer builds mode */ 0, /* full screen mode */ -1, /* sphere mode */ 0, /* stereo capable */ 0, /* stereo mode */ -1, /* zoom mode */ 0, /* launch_status */ 0, /* no quit */ 0, /* gldebug */ }; CPyMOLOptions *PyMOLOptions_New(void) { CPyMOLOptions *result = NULL; result = Calloc(CPyMOLOptions, 1); if(result) *result = Defaults; return result; } #ifndef _PYMOL_NOPY void init_cmd(void); static void init_python(int argc, char *argv[]) { Py_Initialize(); if(argv) { #if PY_MAJOR_VERSION < 3 PySys_SetArgv(argc, argv); #endif } /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ #ifdef _MACPYMOL_XCODE /* there appears to be a bug or a race collection in the garbage collector of the Python version that ships with Mac OS -- better to potentially leak a little RAM than crash unexpectedly in a _PyObject_GC_Del call. BTW: PyMOL doesn't itself need the GC, but end-user code might. */ PyRun_SimpleString("import gc"); PyRun_SimpleString("gc.disable()"); #endif /* END PROPRIETARY CODE SEGMENT */ PyEval_InitThreads(); PyRun_SimpleString("import sys"); PyRun_SimpleString("import os"); PyRun_SimpleString("sys.path.insert(0,os.environ['PYMOL_PATH']+'/modules')"); /* initialize our embedded C modules */ init_cmd(); PyRun_SimpleString("import pymol"); /* parse arguments */ PyRun_SimpleString("pymol.invocation.parse_args(sys.argv)"); } /* WARNING: the routine below only works with the global singleton model -- not Python-enabled PyMOL instances */ CPyMOLOptions *PyMOLOptions_NewWithPython(int argc, char *argv[]) { CPyMOLOptions *result = PyMOLOptions_New(); /* use Python to parse options based on the command line */ init_python(argc, argv); PGetOptions(result); return result; } #endif void PyMOLOptions_Free(CPyMOLOptions * options) { FreeP(options); } void PyMOL_ResetProgress(CPyMOL * I) { I->ProgressChanged = true; UtilZeroMem(I->Progress, sizeof(int) * 6); } void PyMOL_SetProgress(CPyMOL * I, int offset, int current, int range) { switch (offset) { case PYMOL_PROGRESS_SLOW: case PYMOL_PROGRESS_MED: case PYMOL_PROGRESS_FAST: if(current != I->Progress[offset]) { I->Progress[offset] = current; I->ProgressChanged = true; } if(range != I->Progress[offset + 1]) { I->Progress[offset + 1] = range; I->ProgressChanged = true; } } } int PyMOL_GetProgress(CPyMOL * I, int *progress, int reset) { int a; int result = I->ProgressChanged; for(a = 0; a < PYMOL_PROGRESS_SIZE; a++) { progress[a] = I->Progress[a]; } if(reset) I->ProgressChanged = false; return result; } int PyMOL_GetProgressChanged(CPyMOL * I, int reset) { int result = I->ProgressChanged; if(reset) I->ProgressChanged = false; return result; } static CPyMOL *_PyMOL_New(void) { CPyMOL *result = NULL; /* allocate global container */ if((result = Calloc(CPyMOL, 1))) { /* all values initialized to zero */ if((result->G = Calloc(PyMOLGlobals, 1))) { result->G->PyMOL = result; /* store the instance pointer */ result->BusyFlag = false; result->InterruptFlag = false; PyMOL_ResetProgress(result); #ifndef _PYMOL_NOPY /* for the time being, the first PyMOL object created becomes the singleton object -- this is failsafe behavior designed to carry us through the transition to fully objectified PyMOL (PS note race in assignment covered by pymol2.pymol2_lock) */ if(!SingletonPyMOLGlobals) { SingletonPyMOLGlobals = result->G; } #endif /* continue initialization */ } else { FreeP(result); } } return result; } static void _PyMOL_Config(CPyMOL * I) { #ifndef _PYMOL_NO_MAIN // also assign in PyMOL_DrawWithoutLock I->G->HaveGUI = I->G->Option->pmgui; #endif I->G->Security = I->G->Option->security; } CPyMOL *PyMOL_New(void) { CPyMOL *result = _PyMOL_New(); if(result && result->G) { result->G->Option = Calloc(CPyMOLOptions, 1); if(result->G->Option) (*result->G->Option) = Defaults; _PyMOL_Config(result); } return result; } CPyMOL *PyMOL_NewWithOptions(const CPyMOLOptions * option) { CPyMOL *result = _PyMOL_New(); if(result && result->G) { result->G->Option = Calloc(CPyMOLOptions, 1); if(result->G->Option) *(result->G->Option) = *option; _PyMOL_Config(result); } result->G->StereoCapable = option->stereo_capable; return result; } void PyMOL_Start(CPyMOL * I) { PyMOLGlobals *G = I->G; // It's possible to change this from Python, functions which rely on // C locale should reset it before doing printf, atof, etc. std::setlocale(LC_NUMERIC, "C"); G->Context = OVContext_New(); G->Lexicon = OVLexicon_New(G->Context->heap); if(OVreturn_IS_ERROR(PyMOL_InitAPI(I))) { printf("ERROR: PyMOL internal C API initialization failed.\n"); } // global lexicon "constants" #define LEX_CONSTANTS_IMPL #include "lex_constants.h" FeedbackInit(G, G->Option->quiet); WordInit(G); UtilInit(G); ColorInit(G); CGORendererInit(G); ShaderMgrInit(G); SettingInitGlobal(G, true, true, false); SettingSetGlobal_i(G, cSetting_internal_gui, G->Option->internal_gui); SettingSetGlobal_i(G, cSetting_internal_feedback, G->Option->internal_feedback); TextureInit(G); TypeInit(G); TextInit(G); CharacterInit(G); PlugIOManagerInit(G); SphereInit(G); OrthoInit(G, G->Option->show_splash); SceneInit(G); MovieScenesInit(G); WizardInit(G); /* must come after ortho & scene */ MovieInit(G); SelectorInit(G); SeqInit(G); SeekerInit(G); ButModeInit(G); ControlInit(G); AtomInfoInit(G); SculptCacheInit(G); VFontInit(G); ExecutiveInit(G); IsosurfInit(G); TetsurfInit(G); EditorInit(G); #ifdef TRACKER_UNIT_TEST TrackerUnitTest(G); #endif /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ #ifdef _MACPYMOL_XCODE SettingSetGlobal_b(G, cSetting_stereo_double_pump_mono, true); if(G->Option->stereo_capable) { SettingSetGlobal_i(G, cSetting_stereo_mode, cStereo_quadbuffer); } /* SettingSetGlobal_i(G,cSetting_show_progress, 0); */ #endif /* END PROPRIETARY CODE SEGMENT */ I->DrawnFlag = false; I->RedisplayFlag = true; G->Ready = true; } /* This function is necessary to be called from PyMOL_StartWithPython which is called before the PYMOL_API is instantiated, thus it is not necessary (and you can't) lock the API */ void PyMOL_ConfigureShadersGL_WithoutLock(CPyMOL * I){ I->done_ConfigureShaders = false; // ShaderMgr->Config() moved to PyMOL_DrawWithoutLock } /* This function is called from CMol and needs to lock the PYMOL_API */ void PyMOL_ConfigureShadersGL(CPyMOL * I){ PYMOL_API_LOCK PyMOL_ConfigureShadersGL_WithoutLock(I); PYMOL_API_UNLOCK } #ifndef _PYMOL_NOPY void PyMOL_StartWithPython(CPyMOL * I) { PyMOL_Start(I); /* now locate all the C to Python function hooks and objects we need */ #ifdef _MACPYMOL_XCODE PInit(I->G, true); #else PInit(I->G, false); #endif /* and begin the initialization sequence */ I->PythonInitStage = 1; /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ #ifdef _MACPYMOL_XCODE MacPyMOLOption = I->G->Option; MacPyMOLReady = &I->G->Ready; #endif /* END PROPRIETARY CODE SEGMENT */ } #endif void PyMOL_Stop(CPyMOL * I) { PyMOLGlobals *G = I->G; G->Terminating = true; TetsurfFree(G); IsosurfFree(G); WizardFree(G); SceneCleanupStereo(G); EditorFree(G); ExecutiveFree(G); VFontFree(G); SculptCacheFree(G); AtomInfoFree(G); ButModeFree(G); ControlFree(G); SeekerFree(G); SeqFree(G); SelectorFree(G); MovieFree(G); SceneFree(G); MovieScenesFree(G); OrthoFree(G); DeleteP(G->ShaderMgr); SettingFreeGlobal(G); CharacterFree(G); TextFree(G); TypeFree(G); TextureFree(G); SphereFree(G); PlugIOManagerFree(G); PFree(G); CGORendererFree(G); ColorFree(G); UtilFree(G); WordFree(G); FeedbackFree(G); PyMOL_PurgeAPI(I); /* printf("%d \n", OVLexicon_GetNActive(G->Lexicon)); */ OVLexicon_Del(G->Lexicon); OVContext_Del(G->Context); } void PyMOL_Free(CPyMOL * I) { #if !defined(_PYMOL_ACTIVEX) && !defined(_MACPYMOL_XCODE) PYMOL_API_LOCK #endif /* take PyMOL down gracefully */ PyMOLOptions_Free(I->G->Option); #ifndef _PYMOL_NOPY FreeP(I->G->P_inst); if(I->G == SingletonPyMOLGlobals) SingletonPyMOLGlobals = NULL; #endif FreeP(I->G); FreeP(I); return; #if !defined(_PYMOL_ACTIVEX) && !defined(_MACPYMOL_XCODE) PYMOL_API_UNLOCK; #endif } struct _PyMOLGlobals *PyMOL_GetGlobals(CPyMOL * I) { return I->G; } struct _PyMOLGlobals **PyMOL_GetGlobalsHandle(CPyMOL * I) { return &(I->G); } void PyMOL_LockAPIAndUnblock(CPyMOL * I) { PyMOLGlobals *G = I->G; (void)G; PLockAPIAndUnblock(G); } void PyMOL_BlockAndUnlockAPI(CPyMOL * I) { PyMOLGlobals *G = I->G; (void)G; PBlockAndUnlockAPI(G); } void PyMOL_AdaptToHardware(CPyMOL * I) { PYMOL_API_LOCK PyMOLGlobals * G = I->G; if(G->HaveGUI) { PyMOL_PushValidContext(I); { char *vendor = (char *) glGetString(GL_VENDOR); char *renderer = (char *) glGetString(GL_RENDERER); char *version = (char *) glGetString(GL_VERSION); if(vendor && version) { /* work around broken lighting under Windows GDI Generic */ if((strcmp(vendor, "Microsoft Corporation") == 0) && (strcmp(renderer, "GDI Generic") == 0)) { ExecutiveSetSettingFromString(I->G, cSetting_light_count, "1", "", 0, 1, 0); ExecutiveSetSettingFromString(I->G, cSetting_spec_direct, "0.7", "", 0, 1, 0); } } } PyMOL_PopValidContext(I); } PYMOL_API_UNLOCK} static void setup_gl_state(void) { /* get us into a well defined GL state */ /*glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); */ #ifndef PURE_OPENGL_ES_2 glDisable(GL_ALPHA_TEST); glDisable(GL_COLOR_LOGIC_OP); glDisable(GL_COLOR_MATERIAL); glDisable(GL_FOG); glDisable(GL_LIGHTING); glDisable(GL_LIGHT0); glDisable(GL_LIGHT1); glDisable(GL_LINE_SMOOTH); glDisable(GL_NORMALIZE); #endif glDisable(GL_BLEND); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glDisable(GL_DITHER); #ifndef PURE_OPENGL_ES_2 glDisable(GL_POLYGON_SMOOTH); #endif } void PyMOL_DrawWithoutLock(CPyMOL * I); void PyMOL_Draw(CPyMOL * I){ PYMOL_API_LOCK_MODAL PyMOL_DrawWithoutLock(I); PYMOL_API_UNLOCK } static void PyMOL_LaunchStatus_Feedback(PyMOLGlobals * G) { G->LaunchStatus |= G->Option->launch_status; if(G->StereoCapable) { OrthoAddOutput(G, " OpenGL quad-buffer stereo 3D detected and enabled.\n");; } else { if(G->LaunchStatus & cPyMOLGlobals_LaunchStatus_StereoFailed) { FeedbackAddColored(G, "Error: The requested stereo 3D visualization mode is not available.\n", FB_Errors); } } if(G->LaunchStatus & cPyMOLGlobals_LaunchStatus_MultisampleFailed) { FeedbackAddColored(G, "Error: The requested multisampling mode is not available.\n", FB_Errors); } } #ifndef PURE_OPENGL_ES_2 static void check_gl_stereo_capable(PyMOLGlobals * G) { // quad buffer stereo available? GLboolean state; glGetBooleanv(GL_STEREO, &state); G->StereoCapable = state || G->Option->force_stereo > 0; if (!state && G->Option->force_stereo > 0) { printf("Warning: forcing stereo despite GL_STEREO=0\n"); } // stereo request feedback if (state && G->Option->stereo_mode == cStereo_default) { SettingSetGlobal_i(G, cSetting_stereo_mode, cStereo_quadbuffer); } else if (!state && G->Option->stereo_mode == cStereo_quadbuffer) { G->LaunchStatus |= cPyMOLGlobals_LaunchStatus_StereoFailed; } // multisample request feedback if (G->Option->multisample) { GLint samplebuffers = 0; glGetIntegerv(GL_SAMPLE_BUFFERS, &samplebuffers); if (!samplebuffers) { G->LaunchStatus |= cPyMOLGlobals_LaunchStatus_MultisampleFailed; } } // GL_BACK if GL_DOUBLEBUFFER else GL_FRONT // With QOpenGLWidget -> framebuffer object GLint buf; glGetIntegerv(GL_DRAW_BUFFER0, &buf); if (!buf) { printf("Warning: GL_DRAW_BUFFER0=0 -> using GL_BACK\n"); buf = GL_BACK; } G->DRAW_BUFFER0 = buf; // double buffer check glGetBooleanv(GL_DOUBLEBUFFER, &state); if (!state && buf <= GL_BACK) { printf("Warning: GL_DOUBLEBUFFER=0\n"); } // default framebuffer glGetIntegerv(GL_FRAMEBUFFER_BINDING, &buf); G->ShaderMgr->default_framebuffer_id = buf; } #endif void PyMOL_DrawWithoutLock(CPyMOL * I) { if (!I->done_ConfigureShaders) { I->done_ConfigureShaders = true; I->G->HaveGUI = I->G->Option->pmgui; #ifndef PURE_OPENGL_ES_2 // stereo test with PyQt5 on Linux is broken (QTBUG-59636), so we // test for stereo here if (I->G->HaveGUI) { check_gl_stereo_capable(I->G); } #endif PyMOL_LaunchStatus_Feedback(I->G); I->G->ShaderMgr->Config(); // OpenGL debugging (glewInit must be called first) if (I->G->Option->gldebug) { #ifdef GL_DEBUG_OUTPUT if (!glDebugMessageCallback) { printf("glDebugMessageCallback not available\n"); } else { glDebugMessageCallback(gl_debug_proc, NULL); glEnable(GL_DEBUG_OUTPUT); } #else printf("GL_DEBUG_OUTPUT not available\n"); #endif } } PyMOLGlobals * G = I->G; if(I->ModalDraw) { if(G->HaveGUI) { PyMOL_PushValidContext(I); setup_gl_state(); } { PyMOLModalDrawFn *fn = I->ModalDraw; I->ModalDraw = NULL; /* always resets to NULL! */ fn(G); } if(G->HaveGUI) { PyMOL_PopValidContext(I); } } else { if(I->DraggedFlag) { if(ControlIdling(I->G)) { ExecutiveSculptIterateAll(I->G); } I->DraggedFlag = false; } if(G->HaveGUI) { PyMOL_PushValidContext(I); setup_gl_state(); /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ #ifdef _MACPYMOL_XCODE { /* on a mac, this can change if we've switched contexts... */ GLboolean state; glGetBooleanv(GL_STEREO, &state); G->StereoCapable = (int) state; } #endif /* END PROPRIETARY CODE SEGMENT */ if(!I->DrawnFlag) { SceneSetCardInfo(G, (char *) glGetString(GL_VENDOR), (char *) glGetString(GL_RENDERER), (char *) glGetString(GL_VERSION)); if(G->Option->show_splash && !G->Option->quiet) { PRINTFB(G, FB_OpenGL, FB_Results) " OpenGL graphics engine:\n" " GL_VENDOR: %s\n" " GL_RENDERER: %s\n" " GL_VERSION: %s\n", (char *) glGetString(GL_VENDOR), (char *) glGetString(GL_RENDERER), (char *) glGetString(GL_VERSION) ENDFB(G); if(Feedback(G, FB_OpenGL, FB_Blather)) { printf(" GL_EXTENSIONS: %s\n", (char *) glGetString(GL_EXTENSIONS)); } } I->DrawnFlag = true; } } else { I->DrawnFlag = true; } I->RedisplayFlag = false; OrthoBusyPrime(G); ExecutiveDrawNow(G); if(I->ImageRequestedFlag) { if(SceneHasImage(G)) { I->ImageReadyFlag = true; I->ImageRequestedFlag = false; { int w, h; SceneGetImageSize(I->G, &w, &h); } } else { I->ImageReadyFlag = false; } } else if(I->ImageReadyFlag) { if(!SceneHasImage(G)) I->ImageReadyFlag = false; } if(G->HaveGUI) PyMOL_PopValidContext(I); } } void PyMOL_Key(CPyMOL * I, unsigned char k, int x, int y, int modifiers) { PYMOL_API_LOCK PyMOLGlobals * G = I->G; if(!WizardDoKey(G, k, x, y, modifiers)) OrthoKey(G, k, x, y, modifiers); PyMOL_NeedRedisplay(G->PyMOL); PYMOL_API_UNLOCK} void PyMOL_Special(CPyMOL * I, int k, int x, int y, int modifiers) { PYMOL_API_LOCK PyMOLGlobals * G = I->G; int grabbed = false; char buffer[255]; (void)buffer; if(!grabbed) grabbed = WizardDoSpecial(G, (unsigned char) k, x, y, modifiers); switch (k) { case P_GLUT_KEY_UP: case P_GLUT_KEY_DOWN: grabbed = 1; OrthoSpecial(G, k, x, y, modifiers); break; case P_GLUT_KEY_LEFT: case P_GLUT_KEY_RIGHT: if(OrthoArrowsGrabbed(G)) { grabbed = 1; OrthoSpecial(G, k, x, y, modifiers); } break; } #ifndef _PYMOL_NOPY if(!grabbed) { sprintf(buffer, "_special %d,%d,%d,%d", k, x, y, modifiers); PLog(G, buffer, cPLog_pml); PParse(G, buffer); PFlush(G); } #endif PYMOL_API_UNLOCK} void PyMOL_Reshape(CPyMOL * I, int width, int height, int force) { PYMOL_API_LOCK PyMOLGlobals * G = I->G; G->Option->winX = width; G->Option->winY = height; OrthoReshape(G, width, height, force); PYMOL_API_UNLOCK} int PyMOL_Idle(CPyMOL * I) { int did_work = false; PYMOL_API_TRYLOCK PyMOLGlobals * G = I->G; I->DraggedFlag = false; if(I->IdleAndReady < IDLE_AND_READY) { if(I->DrawnFlag) I->IdleAndReady++; } if(I->FakeDragFlag == 1) { I->FakeDragFlag = false; OrthoFakeDrag(G); did_work = true; } if(ControlIdling(G)) { ExecutiveSculptIterateAll(G); ControlSdofIterate(G); did_work = true; } SceneIdle(G); if(SceneRovingCheckDirty(G)) { SceneRovingUpdate(G); did_work = true; } #ifndef _PYMOL_NOPY if(PFlush(G)) { did_work = true; } if(I->PythonInitStage > 0) { if(I->PythonInitStage < 2) { I->PythonInitStage++; } else { I->PythonInitStage = -1; PBlock(G); /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ #ifdef _MACPYMOL_XCODE /* restore working directory if asked to */ PRunStringModule(G, "if 'PYMOL_WD' in os.environ: os.chdir(os.environ['PYMOL_WD'])"); PXDecRef(PYOBJECT_CALLMETHOD(G->P_inst->obj, "launch_gui", "O", G->P_inst->obj)); #endif /* END PROPRIETARY CODE SEGMENT */ PXDecRef(PYOBJECT_CALLMETHOD (G->P_inst->obj, "adapt_to_hardware", "O", G->P_inst->obj)); if(PyErr_Occurred()) PyErr_Print(); PXDecRef(PYOBJECT_CALLMETHOD(G->P_inst->obj, "exec_deferred", "O", G->P_inst->obj)); if(PyErr_Occurred()) PyErr_Print(); PUnblock(G); PFlush(G); } } #endif /* reset the interrupt flag if we're not doing anything */ if(!(did_work || I->ModalDraw)) if(PyMOL_GetInterrupt(I, false)) PyMOL_SetInterrupt(I, false); PYMOL_API_UNLOCK_NO_FLUSH return (did_work || I->ModalDraw); } void PyMOL_ExpireIfIdle(CPyMOL * I) { PYMOL_API_LOCK PyMOLGlobals * G = I->G; int final_init_done = true; #ifndef _PYMOL_NOPY final_init_done = (I->PythonInitStage == -1); #endif if(!G->HaveGUI) { if(final_init_done) { if(!OrthoCommandWaiting(G)) { if((!G->Option->keep_thread_alive) && (!G->Option->read_stdin)) { I->ExpireCount++; if(I->ExpireCount == 10) { PParse(G, "_quit"); } } } } } PYMOL_API_UNLOCK; } void PyMOL_NeedFakeDrag(CPyMOL * I) { I->FakeDragFlag = true; } void PyMOL_NeedRedisplay(CPyMOL * I) { I->RedisplayFlag = true; } void PyMOL_NeedSwap(CPyMOL * I) { I->SwapFlag = true; } void PyMOL_NeedReshape(CPyMOL * I, int mode, int x, int y, int width, int height) { PyMOLGlobals *G = I->G; if(width < 0) { if (!G->HaveGUI) return; width = SceneGetBlock(G)->getWidth(); if(SettingGetGlobal_b(G, cSetting_internal_gui)) width += DIP2PIXEL(SettingGetGlobal_i( G, cSetting_internal_gui_width)); } /* if height is negative, force a reshape based on the current height */ if(height < 0) { int internal_feedback; height = SceneGetBlock(G)->getHeight(); internal_feedback = SettingGetGlobal_i(G, cSetting_internal_feedback); if(internal_feedback) height += (internal_feedback - 1) * cOrthoLineHeight + cOrthoBottomSceneMargin; if(SettingGetGlobal_b(G, cSetting_seq_view) && !SettingGetGlobal_b(G, cSetting_seq_view_overlay)) { height += SeqGetHeight(G); } height += MovieGetPanelHeight(G); } if(G->HaveGUI) { float sf = DIP2PIXEL(1); I->Reshape[1] = x / sf; I->Reshape[2] = y / sf; I->Reshape[3] = width / sf; I->Reshape[4] = height / sf; I->ReshapeFlag = true; I->Reshape[0] = mode; PyMOL_NeedRedisplay(I); } else { /* if no gui, then force immediate reshape */ PyMOLGlobals *G = I->G; G->Option->winX = width; G->Option->winY = height; OrthoReshape(G, width, height, true); } } int PyMOL_GetIdleAndReady(CPyMOL * I) { return (I->IdleAndReady == IDLE_AND_READY); } int PyMOL_GetReshape(CPyMOL * I) { return I->ReshapeFlag; } PyMOLreturn_int_array PyMOL_GetReshapeInfo(CPyMOL * I, int reset) { PyMOLreturn_int_array result = { PyMOLstatus_SUCCESS, PYMOL_RESHAPE_SIZE, NULL }; PYMOL_API_LOCK if(reset) I->ReshapeFlag = false; result.array = VLAlloc(int, PYMOL_RESHAPE_SIZE); if(!result.array) { result.status = PyMOLstatus_FAILURE; } else { int a; for(a = 0; a < PYMOL_RESHAPE_SIZE; a++) result.array[a] = I->Reshape[a]; } PYMOL_API_UNLOCK return result; } void PyMOL_SetPassive(CPyMOL * I, int onOff) { I->PassiveFlag = onOff; } void PyMOL_SetClickReady(CPyMOL * I, const char *name, int index, int button, int mod, int x, int y, const float *pos, int state) { if(name && name[0] && (index >= 0)) { I->ClickReadyFlag = true; strcpy(I->ClickedObject, name); I->ClickedIndex = index; I->ClickedButton = button; I->ClickedModifiers = mod; I->ClickedX = x; I->ClickedY = y; } else { I->ClickedObject[0] = 0; I->ClickReadyFlag = true; I->ClickedX = x; I->ClickedY = y; I->ClickedIndex = index; I->ClickedButton = button; I->ClickedModifiers = mod; } if(pos) { I->ClickedHavePos = true; copy3f(pos, I->ClickedPos); I->ClickedPosState = state; } else { I->ClickedHavePos = false; zero3f(I->ClickedPos); I->ClickedPosState = 0; } } int PyMOL_GetClickReady(CPyMOL * I, int reset) { int result = I->ClickReadyFlag; if(reset) { I->ClickReadyFlag = false; } return result; } char *PyMOL_GetClickString(CPyMOL * I, int reset) { char *result = NULL; PYMOL_API_LOCK int ready = I->ClickReadyFlag; if(reset) I->ClickReadyFlag = false; if(ready) { result = Alloc(char, OrthoLineLength + 1); if(result) { WordType butstr = "left", modstr = "", posstr = ""; result[0] = 0; switch (I->ClickedButton) { case P_GLUT_SINGLE_LEFT: strcpy(butstr, "single_left"); break; case P_GLUT_SINGLE_MIDDLE: strcpy(butstr, "single_middle"); break; case P_GLUT_SINGLE_RIGHT: strcpy(butstr, "single_right"); break; case P_GLUT_DOUBLE_LEFT: strcpy(butstr, "double_left"); break; case P_GLUT_DOUBLE_MIDDLE: strcpy(butstr, "double_middle"); break; case P_GLUT_DOUBLE_RIGHT: strcpy(butstr, "double_right"); break; } if(cOrthoCTRL & I->ClickedModifiers) { if(modstr[0]) strcat(modstr, " "); strcat(modstr, "ctrl"); } if(cOrthoALT & I->ClickedModifiers) { if(modstr[0]) strcat(modstr, " "); strcat(modstr, "alt"); } if(cOrthoSHIFT & I->ClickedModifiers) { if(modstr[0]) strcat(modstr, " "); strcat(modstr, "shift"); } if(I->ClickedHavePos) { sprintf(posstr,"px=%.7g\npy=%.7g\npz=%.7g\nstate=%d",I->ClickedPos[0],I->ClickedPos[1],I->ClickedPos[2],I->ClickedPosState); } if(!I->ClickedObject[0]) { sprintf(result, "type=none\nclick=%s\nmod_keys=%s\nx=%d\ny=%d\n%s", butstr, modstr, I->ClickedX, I->ClickedY,posstr); } else { ObjectMolecule *obj = ExecutiveFindObjectMoleculeByName(I->G, I->ClickedObject); if(obj && (I->ClickedIndex < obj->NAtom)) { AtomInfoType *ai = obj->AtomInfo + I->ClickedIndex; char inscode_str[2] = { ai->inscode, '\0' }; sprintf(result, "type=object:molecule\nobject=%s\nindex=%d\nrank=%d\nid=%d\nsegi=%s\nchain=%s\nresn=%s\nresi=%d%s\nname=%s\nalt=%s\nclick=%s\nmod_keys=%s\nx=%d\ny=%d\n%s", I->ClickedObject, I->ClickedIndex + 1, ai->rank, ai->id, LexStr(I->G, ai->segi), LexStr(I->G, ai->chain), LexStr(I->G, ai->resn), ai->resv, inscode_str, LexStr(I->G, ai->name), ai->alt, butstr, modstr, I->ClickedX, I->ClickedY, posstr); } } } } PYMOL_API_UNLOCK return (result); } int PyMOL_GetImageReady(CPyMOL * I, int reset) { int result = I->ImageReadyFlag; if(reset) { I->ImageReadyFlag = false; } return result; } PyMOLreturn_int_array PyMOL_GetImageInfo(CPyMOL * I) { PyMOLreturn_int_array result = { PyMOLstatus_SUCCESS, 2, NULL }; PYMOL_API_LOCK result.array = VLAlloc(int, 2); if(!result.array) { result.status = PyMOLstatus_FAILURE; } else { SceneGetImageSize(I->G, result.array, result.array + 1); } PYMOL_API_UNLOCK return result; } int PyMOL_GetImageData(CPyMOL * I, int width, int height, int row_bytes, void *buffer, int mode, int reset) { int ok = true; PYMOL_API_LOCK if(reset) I->ImageReadyFlag = false; ok = SceneCopyExternal(I->G, width, height, row_bytes, (unsigned char *) buffer, mode); PYMOL_API_UNLOCK return get_status_ok(ok); } PyMOLreturn_int_array PyMOL_GetImageDataReturned(CPyMOL * I, int width, int height, int row_bytes, int mode, int reset) { PyMOLreturn_int_array result = { PyMOLstatus_SUCCESS, 0, NULL }; int ok = true; int size; void *buffer; PYMOL_API_LOCK if(reset){ I->ImageReadyFlag = false; } size = width*height; buffer = VLAlloc(int, size); ((int*)buffer)[0] = ('A'<<24)|('B'<<16)|('G'<<8)|'R'; ok = SceneCopyExternal(I->G, width, height, row_bytes, (unsigned char *) buffer, mode); if(ok) { result.array = (int*) buffer; result.size = size; } else { result.status = PyMOLstatus_FAILURE; } PYMOL_API_UNLOCK return result; } int PyMOL_FreeResultString(CPyMOL * I, char *st) { PYMOL_API_LOCK FreeP(st); PYMOL_API_UNLOCK return get_status_ok((st != NULL)); } int PyMOL_GetRedisplay(CPyMOL * I, int reset) { int result = false; PYMOL_API_TRYLOCK PyMOLGlobals * G = I->G; result = I->RedisplayFlag; if(result) { if(SettingGet_b(G, NULL, NULL, cSetting_defer_updates)) { result = false; } else { if(reset) I->RedisplayFlag = false; } } PYMOL_API_UNLOCK_NO_FLUSH return (result || I->ModalDraw); /* always true when ModalDraw is set */ } int PyMOL_GetPassive(CPyMOL * I, int reset) { /* lock intentionally omitted */ int result = I->PassiveFlag; if(reset) I->PassiveFlag = false; return result; } int PyMOL_GetModalDraw(CPyMOL * I) { if(I) return (I->ModalDraw != NULL); return false; } void PyMOL_SetModalDraw(CPyMOL * I, PyMOLModalDrawFn * fn) { I->ModalDraw = fn; } int PyMOL_GetSwap(CPyMOL * I, int reset) { /* lock intentionally omitted */ int result = I->SwapFlag; if(reset) I->SwapFlag = false; return result; } int PyMOL_GetBusy(CPyMOL * I, int reset) { /* lock intentionally omitted */ int result = I->BusyFlag; if(reset) PyMOL_SetBusy(I, false); return result; } void PyMOL_SetBusy(CPyMOL * I, int value) { /* lock intentionally omitted */ if(!I->BusyFlag) /* if we weren't busy before, then reset the progress indicators */ PyMOL_ResetProgress(I); I->BusyFlag = value; } int PyMOL_GetInterrupt(CPyMOL * I, int reset) { /* lock intentionally omitted */ if(I) { int result = I->InterruptFlag; if(reset) PyMOL_SetInterrupt(I, false); return result; } else return false; } void PyMOL_SetInterrupt(CPyMOL * I, int value) { /* lock intentionally omitted */ if(I) { I->InterruptFlag = value; if(I->G) I->G->Interrupt = value; } } void PyMOL_Drag(CPyMOL * I, int x, int y, int modifiers) { PYMOL_API_LOCK OrthoDrag(I->G, x, y, modifiers); I->DraggedFlag = true; PYMOL_API_UNLOCK} /* * Mouse button and keyboard press handler * * button: mouse button or key code * state: * -2 = key press with GLUT_KEY_* special code * -1 = key press with ascii code * 0 = mouse down * 1 = mouse up * x, y: mouse pointer position * modifiers: SHIFT/CTRL/ALT bitmask */ void PyMOL_Button(CPyMOL * I, int button, int state, int x, int y, int modifiers) { PYMOL_API_LOCK if (state == -1) { PyMOL_Key(I, (unsigned char)button, x, y, modifiers); } else if (state == -2) { PyMOL_Special(I, button, x, y, modifiers); } else { OrthoButton(I->G, button, state, x, y, modifiers); } PYMOL_API_UNLOCK} void PyMOL_SetSwapBuffersFn(CPyMOL * I, PyMOLSwapBuffersFn * fn) { I->SwapFn = fn; } void PyMOL_SwapBuffers(CPyMOL * I) { if(I->SwapFn && I->G->ValidContext) { I->SwapFn(); I->SwapFlag = false; } else { I->SwapFlag = true; } } void PyMOL_RunTest(CPyMOL * I, int group, int test) { PYMOL_API_LOCK TestPyMOLRun(I->G, group, test); PYMOL_API_UNLOCK} void PyMOL_PushValidContext(CPyMOL * I) { if(I && I->G) I->G->ValidContext++; } void PyMOL_PopValidContext(CPyMOL * I) { if(I && I->G && (I->G->ValidContext > 0)) I->G->ValidContext--; } void PyMOL_SetStereoCapable(CPyMOL * I, int stereoCapable){ PYMOL_API_LOCK PyMOLGlobals * G = I->G; G->StereoCapable = stereoCapable; if (SettingGetGlobal_b(I->G, cSetting_stereo_mode)==0){ /* if users haven't set stereo_mode, then set it to default */ if (G->StereoCapable){ SettingSetGlobal_i(I->G, cSetting_stereo_mode, cStereo_quadbuffer); /* quadbuffer if we can */ } else { SettingSetGlobal_i(I->G, cSetting_stereo_mode, cStereo_crosseye); /* otherwise crosseye by default */ } } else if (G->StereoCapable && SettingGetGlobal_b(G, cSetting_stereo)){ SettingSetGlobal_i(I->G, cSetting_stereo_mode, SettingGetGlobal_b(I->G, cSetting_stereo_mode)); } SceneUpdateStereo(I->G); PYMOL_API_UNLOCK } void PyMOL_InitializeCMol(CPyMOL * I){ PYMOL_API_LOCK PyMOLGlobals * G = I->G; /* Set stereo_mode to 0, so that PyMOL_SetStereoCapable() can determine whether user has changed the stereo_mode. If users have not changed it, then set to quadbuffer if we can, or crosseye by default (see above) */ SettingSetGlobal_i(G, cSetting_stereo_mode, 0); PYMOL_API_UNLOCK } void PyMOL_SetDefaultMouse(CPyMOL * I) { PYMOL_API_LOCK PyMOLGlobals * G = I->G; ButModeSet(G, cButModeLeftNone, cButModeRotXYZ); ButModeSet(G, cButModeMiddleNone, cButModeTransXY); ButModeSet(G, cButModeRightNone, cButModeTransZ); ButModeSet(G, cButModeLeftShft, cButModePotentialClick); ButModeSet(G, cButModeMiddleShft, cButModePotentialClick); ButModeSet(G, cButModeRightShft, cButModeClipNF); ButModeSet(G, cButModeLeftCtrl, cButModePotentialClick); ButModeSet(G, cButModeMiddleCtrl, cButModePotentialClick); ButModeSet(G, cButModeRightCtrl, cButModePotentialClick); ButModeSet(G, cButModeLeftCtSh, cButModePotentialClick); ButModeSet(G, cButModeMiddleCtSh, cButModePotentialClick); ButModeSet(G, cButModeRightCtSh, cButModePotentialClick); ButModeSet(G, cButModeWheelNone, cButModeScaleSlab); ButModeSet(G, cButModeWheelShft, cButModeMoveSlab); ButModeSet(G, cButModeWheelCtrl, cButModeMoveSlabAndZoom); ButModeSet(G, cButModeWheelCtSh, cButModeTransZ); ButModeSet(G, cButModeMiddleCtSh, cButModeOrigAt); /* SET TWICE?!? */ ButModeSet(G, cButModeLeftSingle, cButModeSimpleClick); ButModeSet(G, cButModeMiddleSingle, cButModeCent); ButModeSet(G, cButModeRightSingle, cButModeSimpleClick); ButModeSet(G, cButModeLeftDouble, cButModeSimpleClick); ButModeSet(G, cButModeRightDouble, cButModeSimpleClick); { int a; for(a = cButModeLeftShftDouble; a <= cButModeRightCtrlAltShftSingle; a++) { ButModeSet(G, a, cButModeSimpleClick); } for(a = cButModeLeftAlt; a <= cButModeRightCtrlAltShft; a++) { ButModeSet(G, a, cButModePotentialClick); } } G->Feedback->Mask[FB_Scene] &= ~(FB_Results); /* suppress click messages */ PYMOL_API_UNLOCK} PyMOLreturn_status PyMOL_CmdRock(CPyMOL * I, int mode){ PyMOLreturn_status result = { PyMOLstatus_SUCCESS }; PYMOL_API_LOCK PyMOLGlobals * G = I->G; ControlRock(G, mode); PYMOL_API_UNLOCK return result; } PyMOLreturn_string_array PyMOL_CmdGetNames(CPyMOL * I, int mode, const char *s0, int enabled_only){ char *res; char *p; int c = 0; int numstrs = 0; long reslen, pl = 0; OrthoLineType str0 = ""; PyMOLreturn_string_array result = { PyMOLstatus_SUCCESS }; PYMOL_API_LOCK PyMOLGlobals * G = I->G; if (s0[0]){ ok_assert(1, SelectorGetTmp(G, s0, str0) >= 0); } res = ExecutiveGetNames(G, mode, enabled_only, str0); if(str0[0]) SelectorFreeTmp(G, str0); // count strings p = res; c = VLAGetSize(res); while(c--) { /* count strings */ if(!*(p++)) numstrs++; } if (numstrs){ reslen = VLAGetSize(res); result.array = VLAlloc(char*, numstrs); result.size = numstrs; numstrs = 0; for (pl=0; pl<reslen;){ result.array[numstrs] = &res[pl]; pl += strlen(res + pl) + 1; numstrs++; } } else { ok_except1: result.array = NULL; result.size = 0; } PYMOL_API_UNLOCK return (result); } PyMOLreturn_status PyMOL_CmdMapNew(CPyMOL * I, const char *name, int type, float grid_spacing, const char *selection, int state, int normalize, int zoom, int quiet){ int ok = true; PyMOLreturn_status result = { PyMOLstatus_FAILURE }; float grid[3]; float minCorner[3], maxCorner[3]; PYMOL_API_LOCK grid[0] = grid[1] = grid[2] = grid_spacing ; minCorner[0] = minCorner[1] = minCorner[2] = 0.; maxCorner[0] = maxCorner[1] = maxCorner[2] = 1.; ok = ExecutiveMapNew(I->G, name, type, grid, selection, -1., minCorner, maxCorner, state, 0, quiet, 0, normalize, 1., -1., 0.); result.status = get_status_ok(ok); PYMOL_API_UNLOCK return result; } #ifdef _PYMOL_LIB PyMOLreturn_status PyMOL_SetIsEnabledCallback(CPyMOL * I, void *CallbackObject, void (*enabledCallback)(void *, const char *, int )){ PyMOLreturn_status result = { PyMOLstatus_FAILURE }; PYMOL_API_LOCK I->G->CallbackObject = CallbackObject; I->G->enabledCallback = enabledCallback; result.status = PyMOLstatus_SUCCESS; PYMOL_API_UNLOCK return result; } PyMOLreturn_int_array PyMOL_GetRepsInSceneForObject(CPyMOL * I, const char *name){ PyMOLreturn_int_array result = { PyMOLstatus_SUCCESS, 0, NULL }; int *retarr = 0; PYMOL_API_LOCK retarr = ExecutiveGetRepsInSceneForObject(I->G, name); if(!retarr) { result.status = PyMOLstatus_FAILURE; } else { result.size = VLAGetSize(retarr); result.array = retarr; } PYMOL_API_UNLOCK return result; } PyMOLreturn_int_array PyMOL_GetRepsForObject(CPyMOL * I, const char *name){ PyMOLreturn_int_array result = { PyMOLstatus_SUCCESS, 0, NULL }; int *retarr = 0; PYMOL_API_LOCK retarr = ExecutiveGetRepsForObject(I->G, name); if(!retarr) { result.status = PyMOLstatus_FAILURE; } else { result.size = VLAGetSize(retarr); result.array = retarr; } PYMOL_API_UNLOCK return result; } static OVreturn_word get_button_code(CPyMOL * I, char *code); static OVreturn_word get_button_mod_code(CPyMOL * I, char *modcode); static OVreturn_word get_button_action_code(CPyMOL * I, char *actioncode); static OVreturn_word get_mouse_mode(CPyMOL * I, char *mousemode); PyMOLreturn_status PyMOL_SetButton(CPyMOL * I, const char *buttonarg, const char *modifierarg, const char *actionarg){ int ok = true; OVreturn_word button_num, but_mod_num, act_code; int but_code; PyMOLreturn_status result = { PyMOLstatus_FAILURE }; OrthoLineType button, modifier, action; PYMOL_API_LOCK UtilNCopyToLower(button, buttonarg, strlen(buttonarg)+1); UtilNCopyToLower(modifier, modifierarg, strlen(modifierarg)+1); UtilNCopyToLower(action, actionarg, strlen(actionarg)+1); ok = OVreturn_IS_OK(button_num = get_button_code(I, button)); if (ok) ok = OVreturn_IS_OK((but_mod_num = get_button_mod_code(I, modifier))); if (ok) ok = OVreturn_IS_OK((act_code = get_button_action_code(I, action))); if (ok){ /* This is directly from the button() function in controlling.py */ if (button_num.word < 3){ // normal button (L,M,R) if (but_mod_num.word < 4){ // none, shft, ctrl, ctsh but_code = button_num.word + 3*but_mod_num.word; } else { // alt, alsh, alct, alcs but_code = button_num.word + 68 + 3*(but_mod_num.word-4); } } else if (button_num.word < 4){ // wheel if (but_mod_num.word < 4){ // none, shft, ctrl, ctsh but_code = 12 + but_mod_num.word; } else { but_code = 64 + but_mod_num.word - 4; } } else { // single and double clicks but_code = (16 + button_num.word -4) + but_mod_num.word * 6; } ButModeSet(I->G, but_code, act_code.word); result.status = PyMOLstatus_SUCCESS; } PYMOL_API_UNLOCK return result; } #include "buttonmodes.h" PyMOLreturn_status PyMOL_SetMouseButtonMode(CPyMOL * I, const char *modename){ int ok = true, i, start; OVreturn_word mode; PyMOLreturn_status result = { PyMOLstatus_FAILURE }; PYMOL_API_LOCK { char *nmodename = (char*)malloc(strlen(modename)+1); UtilNCopyToLower((char*)nmodename, modename, strlen(modename)+1); ok = OVreturn_IS_OK(mode = get_mouse_mode(I, (char*)nmodename)); free(nmodename); } if (ok){ result.status = PyMOLstatus_SUCCESS; { int a; /* for Button modes, first initialize all buttons, so that previous functionality does not linger */ for(a = 0; a < cButModeInputCount; a++) { ButModeSet(I->G, a, initial_button_modes[a]); } } start = button_mode_start[mode.word]; for (i=0; i<n_button_mode[mode.word]; i++, start+=2){ ButModeSet(I->G, all_buttons[start], all_buttons[start+1]); } } PYMOL_API_UNLOCK return result; } static OVreturn_word get_button_code(CPyMOL * I, char *code) { OVreturn_word result; if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, code)))) return result; return OVOneToOne_GetForward(I->MouseButtonCodeLexicon, result.word); } static OVreturn_word get_button_mod_code(CPyMOL * I, char *modcode) { OVreturn_word result; if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, modcode)))) return result; return OVOneToOne_GetForward(I->MouseButtonModCodeLexicon, result.word); } static OVreturn_word get_button_action_code(CPyMOL * I, char *actioncode) { OVreturn_word result; if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, actioncode)))) return result; return OVOneToOne_GetForward(I->MouseButtonActionCodeLexicon, result.word); } static OVreturn_word get_mouse_mode(CPyMOL * I, char *mousemode) { OVreturn_word result; if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, mousemode)))) return result; return OVOneToOne_GetForward(I->MouseModeLexicon, result.word); } PyMOLreturn_status PyMOL_ZoomScene(CPyMOL * I, float scale){ PyMOLreturn_status result = { PyMOLstatus_FAILURE }; PYMOL_API_LOCK SceneZoom(I->G, scale); PyMOL_NeedRedisplay(I); result.status = PyMOLstatus_SUCCESS; PYMOL_API_UNLOCK return result; } PyMOLreturn_status PyMOL_TranslateScene(CPyMOL * I, float x, float y, float z){ PyMOLreturn_status result = { PyMOLstatus_FAILURE }; PYMOL_API_LOCK SceneTranslate(I->G, x, y, z); result.status = PyMOLstatus_SUCCESS; PYMOL_API_UNLOCK return result; } #include "palettes.h" static OVreturn_word get_palette(CPyMOL * I, char *palette) { OVreturn_word result; if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, palette)))) return result; return OVOneToOne_GetForward(I->PaletteLexicon, result.word); } PyMOLreturn_float_array PyMOL_Spectrum(CPyMOL * I, const char *expression, const char *pal, const char *selection, float minimum, float maximum, int byres, int quiet){ PyMOLreturn_float_array result = { PyMOLstatus_FAILURE }; PYMOL_API_LOCK int ok = true; int digits, first, last, array_pl, ret; float min_ret, max_ret; char prefix[2]; OVreturn_word pal_word; char *palette = (char*)malloc(strlen(pal)+1); UtilNCopyToLower((char*)palette, pal, strlen(pal)+1); if (ok) ok = OVreturn_IS_OK(pal_word = get_palette(I, (char*)palette)); free(palette); prefix[0] = palette_prefix[pal_word.word]; prefix[1] = 0; array_pl = pal_word.word * 3; digits = palette_data[array_pl++]; first = palette_data[array_pl++]; last = palette_data[array_pl++]; ret = ExecutiveSpectrum(I->G, selection, expression, minimum, maximum, first, last, prefix, digits, byres, quiet, &min_ret, &max_ret); if (ret){ result.size = 2; result.array = VLAlloc(float, 2); result.array[0] = min_ret; result.array[1] = max_ret; result.status = PyMOLstatus_SUCCESS; } else { result.status = PyMOLstatus_FAILURE; } PYMOL_API_UNLOCK return result; } #endif PyMOLreturn_value PyMOL_GetVersion(CPyMOL * I){ int ok = true; PyMOLreturn_value result; result.status = PyMOLstatus_FAILURE; PYMOL_API_LOCK if(ok) { result.type = PYMOL_RETURN_VALUE_IS_STRING; result.string = mstrdup(_PyMOL_VERSION); result.status = PyMOLstatus_SUCCESS; }; PYMOL_API_UNLOCK return result; } AtomPropertyInfo *PyMOL_GetAtomPropertyInfo(CPyMOL * I, const char *atompropname) { OVreturn_word result; if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, atompropname)))) return NULL; result = OVOneToOne_GetForward(I->AtomPropertyLexicon, result.word); if(!OVreturn_IS_OK(result)) return NULL; return &I->AtomPropertyInfos[result.word]; } #ifdef __cplusplus } #endif