layer3/Editor.cpp (2,041 lines of code) (raw):

/* A* ------------------------------------------------------------------- B* This file contains source code for the PyMOL computer program C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific. 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_predef.h" #include"os_std.h" #include"os_gl.h" #include"Err.h" #include"PConv.h" #include"MemoryDebug.h" #include"Vector.h" #include"Matrix.h" #include"ButMode.h" #include"Scene.h" #include"Editor.h" #include"Selector.h" #include"Ortho.h" #include"main.h" #include"Color.h" #include"Setting.h" #include"Util.h" #include"Executive.h" #include"P.h" #include"CGO.h" #include "Lex.h" struct _CEditor { ObjectMolecule *DihedObject; WordType DragSeleName; int Active; int ActiveState; int DragIndex; int DragSelection; int DragHaveAxis, DragHaveBase, DragBondFlag, DragSlowFlag; int PickMode; /* 1 = atom, 2 = bond, 3 = multiatom */ int NextPickSele; int BondMode; CObject *DragObject; int NFrag; float V0[3], V1[3], Axis[3], Center[3], DragBase[3]; float *PosVLA; int ShowFrags; int DihedralInvalid; int MouseInvalid; int FavorOrigin; float FavoredOrigin[3]; CGO *shaderCGO; }; int EditorGetScheme(PyMOLGlobals * G) { CEditor *I = G->Editor; int scheme = EDITOR_SCHEME_OBJ; if(EditorActive(G)) scheme = EDITOR_SCHEME_FRAG; else if(I->DragObject) { if(I->DragIndex >= 0) { scheme = EDITOR_SCHEME_OBJ; } else { scheme = EDITOR_SCHEME_DRAG; } } return scheme; } void EditorFavorOrigin(PyMOLGlobals * G, float *v1) { CEditor *I = G->Editor; if(v1) { I->FavorOrigin = true; copy3f(v1, I->FavoredOrigin); } else { I->FavorOrigin = false; } } static void EditorDrawDihedral(PyMOLGlobals * G) { if(EditorActive(G) && EditorIsBondMode(G) && SettingGetGlobal_b(G, cSetting_editor_auto_dihedral)) { ObjectMolecule *obj1, *obj2; int at1, at2, at0, at3; int sele1 = SelectorIndexByName(G, cEditorSele1); int sele2 = SelectorIndexByName(G, cEditorSele2); if((sele1 >= 0) && (sele2 >= 0)) { obj1 = SelectorGetFastSingleAtomObjectIndex(G, sele1, &at1); obj2 = SelectorGetFastSingleAtomObjectIndex(G, sele2, &at2); if(obj1 && (obj1 == obj2)) { CEditor *I = G->Editor; I->DihedObject = obj1; at0 = ObjectMoleculeGetTopNeighbor(G, obj1, at1, at2); at3 = ObjectMoleculeGetTopNeighbor(G, obj1, at2, at1); if((at0 >= 0) && (at3 >= 0)) { float result; /* find the highest priority atom attached to index1 */ SelectorCreateOrderedFromObjectIndices(G, cEditorDihe1, obj1, &at0, 1); SelectorCreateOrderedFromObjectIndices(G, cEditorDihe2, obj2, &at3, 1); ExecutiveDihedral(G, &result, cEditorDihedral, cEditorDihe1, cEditorSele1, cEditorSele2, cEditorDihe2, 0, true, true, false, true, -1); ExecutiveColor(G, cEditorDihedral, "white", 1, true); ExecutiveSetSettingFromString(G, cSetting_float_labels, "1", cEditorDihedral, 0, true, true); #ifndef _PYMOL_FREETYPE ExecutiveSetSettingFromString(G, cSetting_label_font_id, "4", cEditorDihedral, 0, true, true); #else ExecutiveSetSettingFromString(G, cSetting_label_font_id, "8", cEditorDihedral, 0, true, true); ExecutiveSetSettingFromString(G, cSetting_label_size, "20", cEditorDihedral, 0, true, true); #endif ExecutiveSetSettingFromString(G, cSetting_label_color, "brightorange", cEditorDihedral, 0, true, true); } } } } } void EditorDihedralInvalid(PyMOLGlobals * G, ObjectMolecule * obj) { CEditor *I = G->Editor; if(!obj) I->DihedralInvalid = true; else if(obj == I->DihedObject) I->DihedralInvalid = true; } void EditorMouseInvalid(PyMOLGlobals * G) { CEditor *I = G->Editor; I->MouseInvalid = true; } static void EditorConfigMouse(PyMOLGlobals * G) { int scheme = EditorGetScheme(G); const char *mouse_mode = SettingGetGlobal_s(G, cSetting_button_mode_name); if(mouse_mode && (!strcmp(mouse_mode, "3-Button Editing") || !strcmp(mouse_mode, "3-Button Motions"))) { /* WEAK! */ int button; button = cButModeMiddleShft; { int action = ButModeGet(G, button); if((action == cButModeMovFrag) || (action == cButModeMovObj) || (action == cButModeMovDrag)) { switch (scheme) { case EDITOR_SCHEME_OBJ: action = cButModeMovObj; break; case EDITOR_SCHEME_FRAG: action = cButModeMovFrag; break; case EDITOR_SCHEME_DRAG: action = cButModeMovDrag; break; } ButModeSet(G, button, action); } } button = cButModeLeftShft; { int action = ButModeGet(G, button); if((action == cButModeRotFrag) || (action == cButModeRotObj) || (action == cButModeRotDrag)) { switch (scheme) { case EDITOR_SCHEME_OBJ: action = cButModeRotObj; break; case EDITOR_SCHEME_FRAG: action = cButModeRotFrag; break; case EDITOR_SCHEME_DRAG: action = cButModeRotDrag; break; } ButModeSet(G, button, action); } } button = cButModeRightShft; { int action = ButModeGet(G, button); if((action == cButModeMovFragZ) || (action == cButModeMovObjZ) || (action == cButModeMovDragZ)) { switch (scheme) { case EDITOR_SCHEME_OBJ: action = cButModeMovObjZ; break; case EDITOR_SCHEME_FRAG: action = cButModeMovFragZ; break; case EDITOR_SCHEME_DRAG: action = cButModeMovDragZ; break; } ButModeSet(G, button, action); } } button = cButModeLeftCtrl; { int action = ButModeGet(G, button); if((action == cButModeMoveAtom) || (action == cButModeTorFrag)) { switch (scheme) { case EDITOR_SCHEME_OBJ: action = cButModeMoveAtom; break; case EDITOR_SCHEME_FRAG: action = cButModeTorFrag; break; case EDITOR_SCHEME_DRAG: action = cButModeMoveAtom; break; } ButModeSet(G, button, action); } } button = cButModeLeftDouble; { int action = ButModeGet(G, button); if((action == cButModeMoveAtom) || (action == cButModeTorFrag)) { switch (scheme) { case EDITOR_SCHEME_OBJ: action = cButModeMoveAtom; break; case EDITOR_SCHEME_FRAG: action = cButModeTorFrag; break; case EDITOR_SCHEME_DRAG: action = cButModeMoveAtom; break; } ButModeSet(G, button, action); } } button = cButModeLeftCtSh; { int action = ButModeGet(G, button); if((action == cButModeMoveAtom) || (action == cButModeMoveAtomZ)) { switch (scheme) { case EDITOR_SCHEME_OBJ: action = cButModeMoveAtomZ; break; case EDITOR_SCHEME_FRAG: action = cButModeMoveAtom; break; case EDITOR_SCHEME_DRAG: action = cButModeMoveAtomZ; break; } ButModeSet(G, button, action); } } } } void EditorUpdate(PyMOLGlobals * G) { CEditor *I = G->Editor; if(I->DihedralInvalid) { EditorDrawDihedral(G); I->DihedralInvalid = false; } if(I->MouseInvalid) { EditorConfigMouse(G); I->MouseInvalid = false; } } static int EditorGetEffectiveState(PyMOLGlobals * G, CObject * obj, int state) { if(obj && (obj->type == cObjectMolecule)) { ObjectMolecule *objMol = (ObjectMolecule*)(void*)obj; if(!objMol) objMol = SelectorGetFastSingleObjectMolecule(G, SelectorIndexByName(G, cEditorSele1)); if(!objMol) objMol = SelectorGetFastSingleObjectMolecule(G, SelectorIndexByName(G, cEditorSele2)); if(!objMol) objMol = SelectorGetFastSingleObjectMolecule(G, SelectorIndexByName(G, cEditorSele3)); if(!objMol) objMol = SelectorGetFastSingleObjectMolecule(G, SelectorIndexByName(G, cEditorSele4)); if(objMol) { if((objMol->NCSet == 1) && (state > 0)) if(SettingGet_i(G, NULL, objMol->Obj.Setting, cSetting_static_singletons)) return 0; } } return state; } int EditorGetNFrag(PyMOLGlobals * G) { CEditor *I = G->Editor; if(EditorActive(G)) { return I->NFrag; } return 0; } void EditorDefineExtraPks(PyMOLGlobals * G) { WordType name; WordType buffer; if(EditorGetSinglePicked(G, name)) { sprintf(buffer, "(byres %s)", name); SelectorCreate(G, cEditorRes, buffer, NULL, true, NULL); sprintf(buffer, "(bychain %s)", name); SelectorCreate(G, cEditorChain, buffer, NULL, true, NULL); sprintf(buffer, "(byobject %s)", name); SelectorCreate(G, cEditorObject, buffer, NULL, true, NULL); if(SettingGetGlobal_b(G, cSetting_auto_hide_selections)) ExecutiveHideSelections(G); EditorInvalidateShaderCGO(G); } } int EditorDeselectIfSelected(PyMOLGlobals * G, ObjectMolecule * obj, int index, int update) { CEditor *I = G->Editor; int result = false; int s, sele; if(obj) { if((index >= 0) && (index < obj->NAtom)) { s = obj->AtomInfo[index].selEntry; sele = SelectorIndexByName(G, cEditorSele1); if(SelectorIsMember(G, s, sele)) { ExecutiveDelete(G, cEditorSele1); result = true; } sele = SelectorIndexByName(G, cEditorSele2); if(SelectorIsMember(G, s, sele)) { ExecutiveDelete(G, cEditorSele2); result = true; } sele = SelectorIndexByName(G, cEditorSele3); if(SelectorIsMember(G, s, sele)) { ExecutiveDelete(G, cEditorSele3); result = true; } sele = SelectorIndexByName(G, cEditorSele4); if(SelectorIsMember(G, s, sele)) { ExecutiveDelete(G, cEditorSele4); result = true; } if(result && update) EditorActivate(G, I->ActiveState, I->BondMode); } } return result; } int EditorIsBondMode(PyMOLGlobals * G) { CEditor *I = G->Editor; return (I->BondMode); } PyObject *EditorAsPyList(PyMOLGlobals * G) { PyObject *result = NULL; CEditor *I = G->Editor; if(!EditorActive(G)) { result = PyList_New(0); /* not editing? return null list */ } else { result = PyList_New(3); PyList_SetItem(result, 0, PyString_FromString("")); PyList_SetItem(result, 1, PyInt_FromLong(I->ActiveState)); PyList_SetItem(result, 2, PyInt_FromLong(I->BondMode)); } return (PConvAutoNone(result)); } int EditorFromPyList(PyMOLGlobals * G, PyObject * list) { int ok = true; int active_flag = false; int active_state; WordType obj_name; int ll = 0; int bond_mode = true; if(ok) ok = (list != NULL); if(ok) ok = PyList_Check(list); if(ok) ll = PyList_Size(list); /* TO SUPPORT BACKWARDS COMPATIBILITY... Always check ll when adding new PyList_GetItem's */ if(ok) active_flag = (PyList_Size(list) != 0); if(!active_flag) { EditorInactivate(G); } else { if(ok) ok = PConvPyStrToStr(PyList_GetItem(list, 0), obj_name, sizeof(WordType)); if(ok) ok = PConvPyIntToInt(PyList_GetItem(list, 1), &active_state); if(ok && (ll > 2)) ok = PConvPyIntToInt(PyList_GetItem(list, 2), &bond_mode); /* newer session files */ if(ok) { EditorActivate(G, active_state, bond_mode); EditorDefineExtraPks(G); } else { EditorInactivate(G); } } if(!ok) { EditorInactivate(G); } return (ok); } int EditorActive(PyMOLGlobals * G) { CEditor *I = G->Editor; return (I->Active); } CObject *EditorDragObject(PyMOLGlobals * G) { CEditor *I = G->Editor; return I->DragObject; } int EditorGetSinglePicked(PyMOLGlobals * G, char *name) { int cnt = 0; int sele; if((sele = SelectorIndexByName(G, cEditorSele1)) >= 0) { cnt++; if(name) strcpy(name, cEditorSele1); } if((sele = SelectorIndexByName(G, cEditorSele2)) >= 0) { cnt++; if(name) strcpy(name, cEditorSele2); } if((sele = SelectorIndexByName(G, cEditorSele3)) >= 0) { cnt++; if(name) strcpy(name, cEditorSele3); } if((sele = SelectorIndexByName(G, cEditorSele4)) >= 0) { cnt++; if(name) strcpy(name, cEditorSele4); } return (cnt == 1); } void EditorGetNextMultiatom(PyMOLGlobals * G, char *name) { CEditor *I = G->Editor; int sele; sele = SelectorIndexByName(G, cEditorSele1); if(sele < 0) { strcpy(name, cEditorSele1); I->NextPickSele = 0; return; } sele = SelectorIndexByName(G, cEditorSele2); if(sele < 0) { strcpy(name, cEditorSele2); I->NextPickSele = 1; return; } sele = SelectorIndexByName(G, cEditorSele3); if(sele < 0) { strcpy(name, cEditorSele3); I->NextPickSele = 2; return; } sele = SelectorIndexByName(G, cEditorSele4); if(sele < 0) { strcpy(name, cEditorSele4); I->NextPickSele = 3; return; } strcpy(name, cEditorSele4); I->NextPickSele = 3; return; /* I->NextPickSele = (++I->NextPickSele)&0x3; switch(I->NextPickSele) { case 0: strcpy(name,cEditorSele1); break; case 1: strcpy(name,cEditorSele2); break; case 2: strcpy(name,cEditorSele3); break; case 3: strcpy(name,cEditorSele4); break; } return; */ } /*========================================================================*/ int EditorLogState(PyMOLGlobals * G, int pkresi) { CEditor *I = G->Editor; if(SettingGetGlobal_i(G, cSetting_logging)) { OrthoLineType buffer, buf1 = "None", buf2 = "None", buf3 = "None", buf4 = "None"; int pkbond = 1; if(!EditorActive(G)) { PLog(G, "edit", cPLog_pml); } else { int sele1, sele2, sele3, sele4; ObjectMolecule *obj1 = NULL, *obj2 = NULL, *obj3 = NULL, *obj4 = NULL; int index1, index2, index3, index4; sele1 = SelectorIndexByName(G, cEditorSele1); sele2 = SelectorIndexByName(G, cEditorSele2); sele3 = SelectorIndexByName(G, cEditorSele3); sele4 = SelectorIndexByName(G, cEditorSele4); obj1 = SelectorGetFastSingleAtomObjectIndex(G, sele1, &index1); obj2 = SelectorGetFastSingleAtomObjectIndex(G, sele2, &index2); obj3 = SelectorGetFastSingleAtomObjectIndex(G, sele3, &index3); obj4 = SelectorGetFastSingleAtomObjectIndex(G, sele4, &index4); if((sele1 >= 0) && (sele2 >= 0) && I->BondMode && obj1 && obj2) { /* bond mode */ ObjectMoleculeGetAtomSeleLog(obj1, index1, buf1, true); ObjectMoleculeGetAtomSeleLog(obj2, index2, buf2, true); } else { /* atom mode */ pkbond = 0; if(obj1) { ObjectMoleculeGetAtomSeleLog(obj1, index1, buf1, true); } if(obj2) { ObjectMoleculeGetAtomSeleLog(obj2, index2, buf2, true); } if(obj3) { ObjectMoleculeGetAtomSeleLog(obj3, index3, buf3, true); } if(obj4) { ObjectMoleculeGetAtomSeleLog(obj4, index4, buf4, true); } } sprintf(buffer, "cmd.edit(%s,%s,%s,%s,pkresi=%d,pkbond=%d)", buf1, buf2, buf3, buf4, pkresi ? 1 : 0, pkbond ? 1 : 0); PLog(G, buffer, cPLog_pym); } } return 1; } /*========================================================================*/ int EditorInvert(PyMOLGlobals * G, int quiet) { CEditor *I = G->Editor; int sele0, sele1, sele2; int i0, frg; int ia0 = -1; int ia1 = -1; float v[3], v0[3], v1[3]; float n0[3], n1[3]; float m[16]; int state; int vf, vf0, vf1; int ok = false; int found = false; WordType name; ObjectMolecule *obj0, *obj1, *obj2; if(!EditorActive(G)) { ErrMessage(G, "Editor", "Must pick an atom to invert."); } else { sele0 = SelectorIndexByName(G, cEditorSele1); sele1 = SelectorIndexByName(G, cEditorSele2); sele2 = SelectorIndexByName(G, cEditorSele3); obj0 = SelectorGetFastSingleAtomObjectIndex(G, sele0, &i0); obj1 = SelectorGetFastSingleAtomObjectIndex(G, sele1, &ia0); obj2 = SelectorGetFastSingleAtomObjectIndex(G, sele2, &ia1); if(sele0 < 0) { ErrMessage(G, "Editor", "Must pick atom to invert as pk1."); } else if(sele1 < 0) { ErrMessage(G, "Editor", "Must pick immobile atom in pk2."); } else if(sele2 < 0) { ErrMessage(G, "Editor", "Must pick immobile atom in pk3."); } else if(!(obj0 && (obj0 == obj1) && (obj0 = obj2))) { ErrMessage(G, "Editor", "Must pick three atoms in the same object."); } else { state = SceneGetState(G); ObjectMoleculeSaveUndo(obj0, state, false); vf = ObjectMoleculeGetAtomVertex(obj0, state, i0, v); vf0 = ObjectMoleculeGetAtomVertex(obj0, state, ia0, v0); vf1 = ObjectMoleculeGetAtomVertex(obj0, state, ia1, v1); if(vf & vf0 & vf1) { subtract3f(v, v0, n0); subtract3f(v, v1, n1); normalize3f(n0); normalize3f(n1); add3f(n0, n1, n0); normalize3f(n0); get_rotation_about3f3fTTTf((float) cPI, n0, v, m); for(frg = 1; frg <= I->NFrag; frg++) { sprintf(name, "%s%1d", cEditorFragPref, frg); sele2 = SelectorIndexByName(G, name); if(ObjectMoleculeDoesAtomNeighborSele(obj0, i0, sele2) && (!ObjectMoleculeDoesAtomNeighborSele(obj0, ia0, sele2)) && (!ObjectMoleculeDoesAtomNeighborSele(obj0, ia1, sele2))) { found = true; ok = ObjectMoleculeTransformSelection(obj0, state, sele2, m, false, NULL, false, false); } } if(found) { if(!quiet) { PRINTFB(G, FB_Editor, FB_Actions) " Editor: Inverted atom.\n" ENDFB(G); } } else { PRINTFB(G, FB_Editor, FB_Errors) " Editor-Error: No free fragments found for inversion.\n" ENDFB(G); } SceneInvalidate(G); I->DragIndex = -1; I->DragSelection = -1; I->DragObject = NULL; } } } return (ok); } /*========================================================================*/ int EditorTorsion(PyMOLGlobals * G, float angle) { CEditor *I = G->Editor; int sele0, sele1, sele2; int i0, i1; float v0[3], v1[3]; float d1[3], n0[3]; float theta; float m[16]; int state; int vf1, vf2; int ok = false; WordType sele; ObjectMolecule *obj0 = NULL, *obj1 = NULL, *obj2 = NULL; if(!EditorActive(G)) { ErrMessage(G, "Editor", "Must specify a bond first."); } else { sele0 = SelectorIndexByName(G, cEditorSele1); if(sele0 >= 0) { obj0 = SelectorGetFastSingleAtomObjectIndex(G, sele0, &i0); sele1 = SelectorIndexByName(G, cEditorSele2); obj1 = SelectorGetFastSingleAtomObjectIndex(G, sele1, &i1); strcpy(sele, cEditorFragPref); strcat(sele, "1"); sele2 = SelectorIndexByName(G, sele); obj2 = SelectorGetFastSingleObjectMolecule(G, sele2); if(!((sele0 >= 0) && (sele1 >= 0) && (sele2 >= 0) && (obj0 == obj1))) { ErrMessage(G, "Editor", "Must specify a bond first."); } else { if((i0 >= 0) && (i1 >= 0)) { state = SceneGetState(G); vf1 = ObjectMoleculeGetAtomVertex(obj0, state, i0, I->V0); vf2 = ObjectMoleculeGetAtomVertex(obj1, state, i1, I->V1); if(vf1 && vf2) { ObjectMoleculeSaveUndo(obj0, SceneGetState(G), false); subtract3f(I->V1, I->V0, I->Axis); average3f(I->V1, I->V0, I->Center); normalize3f(I->Axis); copy3f(I->V0, v1); copy3f(I->V1, v0); subtract3f(v1, v0, d1); copy3f(d1, n0); normalize3f(n0); theta = (float) (cPI * angle / 180.0); get_rotation_about3f3fTTTf(theta, n0, v1, m); ok = ObjectMoleculeTransformSelection(obj2, state, sele2, m, false, NULL, false, false); SceneInvalidate(G); I->DragIndex = -1; I->DragSelection = -1; I->DragObject = NULL; if(I->BondMode && SettingGetGlobal_b(G, cSetting_editor_auto_dihedral)) EditorDihedralInvalid(G, NULL); } } } } } return (ok); } /*========================================================================*/ int EditorSelect(PyMOLGlobals * G, const char *s0, const char *s1, const char *s2, const char *s3, int pkresi, int pkbond, int quiet) { int i0 = -1; int i1 = -1; int i2 = -1; int i3 = -1; int sele0 = -1, sele1 = -1, sele2 = -1, sele3 = -1; int result = false; int ok = true; ObjectMolecule *obj0 = NULL, *obj1 = NULL, *obj2 = NULL, *obj3 = NULL; if(s0) if(!*s0) s0 = NULL; if(s1) if(!*s1) s1 = NULL; if(s2) if(!*s2) s2 = NULL; if(s3) if(!*s3) s3 = NULL; if(s0) { sele0 = SelectorIndexByName(G, s0); obj0 = SelectorGetFastSingleAtomObjectIndex(G, sele0, &i0); ExecutiveDelete(G, cEditorSele1); } if(s1) { sele1 = SelectorIndexByName(G, s1); obj1 = SelectorGetFastSingleAtomObjectIndex(G, sele1, &i1); ExecutiveDelete(G, cEditorSele2); } if(s2) { sele2 = SelectorIndexByName(G, s2); obj2 = SelectorGetFastSingleAtomObjectIndex(G, sele2, &i2); ExecutiveDelete(G, cEditorSele3); } if(s3) { sele3 = SelectorIndexByName(G, s3); obj3 = SelectorGetFastSingleAtomObjectIndex(G, sele3, &i3); ExecutiveDelete(G, cEditorSele4); } if(!(obj0 || obj1 || obj2 || obj3)) ok = false; if(ok) { if(obj0) ObjectMoleculeVerifyChemistry(obj0, -1); if(obj1 && (obj1 != obj0)) ObjectMoleculeVerifyChemistry(obj1, -1); if(obj2 && (obj2 != obj0) && (obj2 != obj1)) ObjectMoleculeVerifyChemistry(obj2, -1); if(obj3 && (obj3 != obj0) && (obj3 != obj1) && (obj3 != obj2)) ObjectMoleculeVerifyChemistry(obj3, -1); if(i0 >= 0) SelectorCreate(G, cEditorSele1, s0, NULL, quiet, NULL); if(i1 >= 0) SelectorCreate(G, cEditorSele2, s1, NULL, quiet, NULL); if(i2 >= 0) SelectorCreate(G, cEditorSele3, s2, NULL, quiet, NULL); if(i3 >= 0) SelectorCreate(G, cEditorSele4, s3, NULL, quiet, NULL); EditorActivate(G, SceneGetState(G), pkbond); if(pkresi) EditorDefineExtraPks(G); SceneInvalidate(G); result = true; } else { EditorInactivate(G); if(s0 && s0[0]) { PRINTFB(G, FB_Editor, FB_Errors) "Editor-Error: Invalid input selection(s).\n" ENDFB(G); } } return (result); } /*========================================================================*/ int EditorIsAnActiveObject(PyMOLGlobals * G, ObjectMolecule * obj) { if(EditorActive(G)) { if(obj) { if(obj == SelectorGetFastSingleObjectMolecule(G, SelectorIndexByName(G, cEditorSele1))) return true; if(obj == SelectorGetFastSingleObjectMolecule(G, SelectorIndexByName(G, cEditorSele2))) return true; if(obj == SelectorGetFastSingleObjectMolecule(G, SelectorIndexByName(G, cEditorSele3))) return true; if(obj == SelectorGetFastSingleObjectMolecule(G, SelectorIndexByName(G, cEditorSele4))) return true; } } return false; } /*========================================================================*/ void EditorCycleValence(PyMOLGlobals * G, int quiet) { CEditor *I = G->Editor; int sele0, sele1; if(EditorActive(G)) { ObjectMolecule *obj0, *obj1; sele0 = SelectorIndexByName(G, cEditorSele1); if(sele0 >= 0) { sele1 = SelectorIndexByName(G, cEditorSele2); if(sele1 >= 0) { obj0 = SelectorGetFastSingleObjectMolecule(G, sele0); obj1 = SelectorGetFastSingleObjectMolecule(G, sele1); if((obj0 == obj1) && I->BondMode) { ObjectMoleculeVerifyChemistry(obj0, -1); ObjectMoleculeAdjustBonds(obj0, sele0, sele1, 0, 0); } } } } } /*========================================================================*/ void EditorAttach(PyMOLGlobals * G, const char *elem, int geom, int valence, const char *name, int quiet) { int i0; int sele0, sele1; AtomInfoType *ai; ObjectMolecule *obj0 = NULL, *obj1 = NULL; int ok = true; ai = (AtomInfoType *) VLAMalloc(1, sizeof(AtomInfoType), 1, true); if(EditorActive(G)) { sele0 = SelectorIndexByName(G, cEditorSele1); if(sele0 >= 0) { sele1 = SelectorIndexByName(G, cEditorSele2); obj0 = SelectorGetFastSingleObjectMolecule(G, sele0); obj1 = SelectorGetFastSingleObjectMolecule(G, sele1); if(obj0) { if(obj0->DiscreteFlag) { ErrMessage(G, "Remove", "Can't attach atoms onto discrete objects."); } else { ObjectMoleculeVerifyChemistry(obj0, -1); /* remember chemistry for later */ if(obj1) { if(obj0 == obj1) { /* bond mode - behave like replace */ EditorReplace(G, elem, geom, valence, name, quiet); } } else { /* atom mode */ i0 = ObjectMoleculeGetAtomIndex(obj0, sele0); /* slow */ if(i0 >= 0) { UtilNCopy(ai->elem, elem, sizeof(ElemName)); ai->geom = geom; ai->valence = valence; if(name[0]) LexAssign(G, ai->name, name); if (ok) ok &= ObjectMoleculeAttach(obj0, i0, std::move(ai)); /* will free ai */ } } } } } } VLAFreeP(ai); /* safety */ } /*========================================================================*/ void EditorRemove(PyMOLGlobals * G, int hydrogen, int quiet) { #define cEditorRemoveSele "_EditorRemove" if(EditorActive(G)) { OrthoLineType buf; CEditor *I = G->Editor; int sele0 = SelectorIndexByName(G, cEditorSele1); ObjectMolecule *obj0 = SelectorGetFastSingleObjectMolecule(G, sele0); ObjectMoleculeVerifyChemistry(obj0, -1); /* remember chemistry for later */ if((sele0 >= 0) && obj0) { int sele1 = SelectorIndexByName(G, cEditorSele2); ObjectMolecule *obj1 = SelectorGetFastSingleObjectMolecule(G, sele1); if((sele1 >= 0) && (obj0 == obj1) && I->BondMode) { /* bond mode */ ObjectMoleculeRemoveBonds(obj0, sele0, sele1); EditorInactivate(G); } else { int h_flag = false; if(SelectorIndexByName(G, cEditorSet) < 0) { int i0 = 0; /* only one atom picked */ if(hydrogen) { sprintf(buf, "((neighbor %s) and hydro)", cEditorSele1); h_flag = SelectorCreate(G, cEditorRemoveSele, buf, NULL, false, NULL); } if(SelectorGetFastSingleAtomObjectIndex(G, sele0, &i0)) { /* atom mode */ if(i0 >= 0) { ExecutiveRemoveAtoms(G, cEditorSele1, quiet); } } } else { /* multiple atoms picked */ if(hydrogen) { sprintf(buf, "((neighbor %s) and hydro)", cEditorSet); h_flag = SelectorCreate(G, cEditorRemoveSele, buf, NULL, false, NULL); } ExecutiveRemoveAtoms(G, cEditorSet, quiet); } EditorInactivate(G); if(h_flag) { ExecutiveRemoveAtoms(G, cEditorRemoveSele, quiet); SelectorDelete(G, cEditorRemoveSele); } } } } #undef cEditorRemoveSele } /*========================================================================*/ void EditorHFill(PyMOLGlobals * G, int quiet) { int sele0, sele1; int i0; OrthoLineType buffer, s1, s2; ObjectMolecule *obj0 = NULL, *obj1 = NULL; if(EditorActive(G)) { sele0 = SelectorIndexByName(G, cEditorSele1); obj0 = SelectorGetFastSingleObjectMolecule(G, sele0); ObjectMoleculeVerifyChemistry(obj0, -1); /* remember chemistry for later */ if(sele0 >= 0) { sele1 = SelectorIndexByName(G, cEditorSele2); if(sele0 >= 0) { if(sele1 >= 0){ sprintf(s2, "(%s) or (%s)", cEditorSele1, cEditorSele2); sprintf(buffer, "((neighbor (%s)) and hydro and not (%s))", s2, s2); } else { sprintf(s2, "(%s)", cEditorSele1); sprintf(buffer, "((neighbor %s) & hydro)", cEditorSele1); } SelectorGetTmp(G, buffer, s1); ExecutiveRemoveAtoms(G, s1, quiet); SelectorFreeTmp(G, s1); i0 = ObjectMoleculeGetAtomIndex(obj0, sele0); obj0->AtomInfo[i0].chemFlag = false; ExecutiveAddHydrogens(G, cEditorSele1, quiet); if(sele1 >= 0) { obj1 = SelectorGetFastSingleObjectMolecule(G, sele1); i0 = ObjectMoleculeGetAtomIndex(obj1, sele1); obj1->AtomInfo[i0].chemFlag = false; ExecutiveAddHydrogens(G, cEditorSele2, quiet); } } } } } /*========================================================================*/ void EditorHFix(PyMOLGlobals * G, const char *sele, int quiet) { int sele0, sele1; ObjectMolecule *obj0, *obj1; if((!sele) || (!sele[0])) { /* if selection is empty, then apply to picked atoms */ if(EditorActive(G)) { sele0 = SelectorIndexByName(G, cEditorSele1); if(sele0 >= 0) { obj0 = SelectorGetFastSingleObjectMolecule(G, sele0); ObjectMoleculeVerifyChemistry(obj0, -1); ExecutiveFixHydrogens(G, cEditorSele1, quiet); } sele1 = SelectorIndexByName(G, cEditorSele2); if(sele1 >= 0) { obj1 = SelectorGetFastSingleObjectMolecule(G, sele1); ObjectMoleculeVerifyChemistry(obj1, -1); ExecutiveFixHydrogens(G, cEditorSele2, quiet); } } } else { ExecutiveFixHydrogens(G, sele, quiet); } } /*========================================================================*/ void EditorReplace(PyMOLGlobals * G, const char *elem, int geom, int valence, const char *name, int quiet) { int i0; int sele0; AtomInfoType ai; ObjectMolecule *obj0 = NULL; int ok = true; UtilZeroMem(&ai, sizeof(AtomInfoType)); if(EditorActive(G)) { sele0 = SelectorIndexByName(G, cEditorSele1); obj0 = SelectorGetFastSingleObjectMolecule(G, sele0); if(obj0->DiscreteFlag) { ErrMessage(G, "Remove", "Can't attach atoms onto discrete objects."); } else { ObjectMoleculeVerifyChemistry(obj0, -1); /* remember chemistry for later */ if(sele0 >= 0) { i0 = ObjectMoleculeGetAtomIndex(obj0, sele0); /* slow */ if(i0 >= 0) { UtilNCopy(ai.elem, elem, sizeof(ElemName)); if(name[0]) LexAssign(G, ai.name, name); ai.geom = geom; ai.valence = valence; if (ok) ok &= ObjectMoleculePrepareAtom(obj0, i0, &ai); if (ok) ok &= ObjectMoleculePreposReplAtom(obj0, i0, &ai); ObjectMoleculeReplaceAtom(obj0, i0, std::move(ai)); ObjectMoleculeVerifyChemistry(obj0, -1); ObjectMoleculeFillOpenValences(obj0, i0); if (ok) ok &= ObjectMoleculeSort(obj0); ObjectMoleculeUpdateIDNumbers(obj0); EditorInactivate(G); } } } } } static void draw_bond(PyMOLGlobals * G, float *v0, float *v1, CGO *shaderCGO) { float v[3], v2[3], v3[3]; float d0[3], n0[3], n1[3], n2[3]; float x[50], y[50]; int nEdge; int c, a; float tube_size1 = 0.5F; float tube_size3 = 0.45F; nEdge = SettingGetGlobal_i(G, cSetting_stick_quality) * 2; if(nEdge > 50) nEdge = 50; if(nEdge < 3) nEdge = 3; subdivide(nEdge, x, y); subtract3f(v1, v0, d0); average3f(v1, v0, v2); average3f(v0, v2, v3); average3f(v2, v3, v2); copy3f(d0, n0); get_system1f3f(n0, n1, n2); if (shaderCGO){ CGOColorv(shaderCGO, ColorGet(G, 0)); CGOBegin(shaderCGO, GL_TRIANGLE_STRIP); for(a = 0; a <= nEdge; a++) { c = a % nEdge; v[0] = n1[0] * x[c] + n2[0] * y[c]; v[1] = n1[1] * x[c] + n2[1] * y[c]; v[2] = n1[2] * x[c] + n2[2] * y[c]; normalize3f(v); CGONormalv(shaderCGO, v); v[0] = v2[0] + n1[0] * tube_size1 * x[c] + n2[0] * tube_size1 * y[c]; v[1] = v2[1] + n1[1] * tube_size1 * x[c] + n2[1] * tube_size1 * y[c]; v[2] = v2[2] + n1[2] * tube_size1 * x[c] + n2[2] * tube_size1 * y[c]; CGOVertexv(shaderCGO, v); v[0] = v3[0] + n1[0] * tube_size1 * x[c] + n2[0] * tube_size1 * y[c]; v[1] = v3[1] + n1[1] * tube_size1 * x[c] + n2[1] * tube_size1 * y[c]; v[2] = v3[2] + n1[2] * tube_size1 * x[c] + n2[2] * tube_size1 * y[c]; CGOVertexv(shaderCGO, v); } CGOEnd(shaderCGO); CGOBegin(shaderCGO, GL_TRIANGLE_STRIP); CGONormalv(shaderCGO, n0); for(a = 0; a <= nEdge; a++) { c = a % nEdge; v[0] = v2[0] + n1[0] * tube_size3 * x[c] + n2[0] * tube_size3 * y[c]; v[1] = v2[1] + n1[1] * tube_size3 * x[c] + n2[1] * tube_size3 * y[c]; v[2] = v2[2] + n1[2] * tube_size3 * x[c] + n2[2] * tube_size3 * y[c]; CGOVertexv(shaderCGO, v); v[0] = v2[0] + n1[0] * tube_size1 * x[c] + n2[0] * tube_size1 * y[c]; v[1] = v2[1] + n1[1] * tube_size1 * x[c] + n2[1] * tube_size1 * y[c]; v[2] = v2[2] + n1[2] * tube_size1 * x[c] + n2[2] * tube_size1 * y[c]; CGOVertexv(shaderCGO, v); } CGOEnd(shaderCGO); CGOBegin(shaderCGO, GL_TRIANGLE_STRIP); scale3f(n0, -1.0F, v); CGONormalv(shaderCGO, v); for(a = 0; a <= nEdge; a++) { c = a % nEdge; v[0] = v3[0] + n1[0] * tube_size1 * x[c] + n2[0] * tube_size1 * y[c]; v[1] = v3[1] + n1[1] * tube_size1 * x[c] + n2[1] * tube_size1 * y[c]; v[2] = v3[2] + n1[2] * tube_size1 * x[c] + n2[2] * tube_size1 * y[c]; CGOVertexv(shaderCGO, v); v[0] = v3[0] + n1[0] * tube_size3 * x[c] + n2[0] * tube_size3 * y[c]; v[1] = v3[1] + n1[1] * tube_size3 * x[c] + n2[1] * tube_size3 * y[c]; v[2] = v3[2] + n1[2] * tube_size3 * x[c] + n2[2] * tube_size3 * y[c]; CGOVertexv(shaderCGO, v); } CGOEnd(shaderCGO); } else { #ifdef PURE_OPENGL_ES_2 /* TODO */ #else glColor3fv(ColorGet(G, 0)); glBegin(GL_TRIANGLE_STRIP); for(a = 0; a <= nEdge; a++) { c = a % nEdge; v[0] = n1[0] * x[c] + n2[0] * y[c]; v[1] = n1[1] * x[c] + n2[1] * y[c]; v[2] = n1[2] * x[c] + n2[2] * y[c]; normalize3f(v); glNormal3fv(v); v[0] = v2[0] + n1[0] * tube_size1 * x[c] + n2[0] * tube_size1 * y[c]; v[1] = v2[1] + n1[1] * tube_size1 * x[c] + n2[1] * tube_size1 * y[c]; v[2] = v2[2] + n1[2] * tube_size1 * x[c] + n2[2] * tube_size1 * y[c]; glVertex3fv(v); v[0] = v3[0] + n1[0] * tube_size1 * x[c] + n2[0] * tube_size1 * y[c]; v[1] = v3[1] + n1[1] * tube_size1 * x[c] + n2[1] * tube_size1 * y[c]; v[2] = v3[2] + n1[2] * tube_size1 * x[c] + n2[2] * tube_size1 * y[c]; glVertex3fv(v); } glEnd(); #endif #ifdef PURE_OPENGL_ES_2 /* TODO */ #else glBegin(GL_TRIANGLE_STRIP); glNormal3fv(n0); for(a = 0; a <= nEdge; a++) { c = a % nEdge; v[0] = v2[0] + n1[0] * tube_size3 * x[c] + n2[0] * tube_size3 * y[c]; v[1] = v2[1] + n1[1] * tube_size3 * x[c] + n2[1] * tube_size3 * y[c]; v[2] = v2[2] + n1[2] * tube_size3 * x[c] + n2[2] * tube_size3 * y[c]; glVertex3fv(v); v[0] = v2[0] + n1[0] * tube_size1 * x[c] + n2[0] * tube_size1 * y[c]; v[1] = v2[1] + n1[1] * tube_size1 * x[c] + n2[1] * tube_size1 * y[c]; v[2] = v2[2] + n1[2] * tube_size1 * x[c] + n2[2] * tube_size1 * y[c]; glVertex3fv(v); } glEnd(); #endif #ifdef PURE_OPENGL_ES_2 /* TODO */ #else glBegin(GL_TRIANGLE_STRIP); scale3f(n0, -1.0F, v); glNormal3fv(v); for(a = 0; a <= nEdge; a++) { c = a % nEdge; v[0] = v3[0] + n1[0] * tube_size1 * x[c] + n2[0] * tube_size1 * y[c]; v[1] = v3[1] + n1[1] * tube_size1 * x[c] + n2[1] * tube_size1 * y[c]; v[2] = v3[2] + n1[2] * tube_size1 * x[c] + n2[2] * tube_size1 * y[c]; glVertex3fv(v); v[0] = v3[0] + n1[0] * tube_size3 * x[c] + n2[0] * tube_size3 * y[c]; v[1] = v3[1] + n1[1] * tube_size3 * x[c] + n2[1] * tube_size3 * y[c]; v[2] = v3[2] + n1[2] * tube_size3 * x[c] + n2[2] * tube_size3 * y[c]; glVertex3fv(v); } glEnd(); #endif } } static void draw_globe(PyMOLGlobals * G, float *v2, int number, CGO *shaderCGO) { float v[3]; float n0[3], n1[3], n2[3]; float x[50], y[50]; int nEdge; int a, c; float radius = 0.5F; float width_base = 0.10F; float width = 0.0F; float offset = 0.0F; int cycle_counter; nEdge = SettingGetGlobal_i(G, cSetting_stick_quality) * 2; if(nEdge > 50) nEdge = 50; if(nEdge < 3) nEdge = 3; subdivide(nEdge, x, y); n0[0] = 1.0; n0[1] = 0.0; n0[2] = 0.0; get_system1f3f(n0, n1, n2); #ifndef PURE_OPENGL_ES_2 glColor3fv(ColorGet(G, 0)); #endif if (shaderCGO) CGOColorv(shaderCGO, ColorGet(G, 0)); cycle_counter = number; while(cycle_counter) { switch (number) { case 1: width = width_base; offset = 0.0F; break; case 2: switch (cycle_counter) { case 2: width = width_base / 2; offset = width_base; break; case 1: offset = -width_base; break; } break; case 3: switch (cycle_counter) { case 3: width = width_base / 2.8F; offset = 1.33F * width_base; break; case 2: offset = 0.0F; break; case 1: offset = -1.33F * width_base; break; } break; case 4: switch (cycle_counter) { case 4: width = width_base / 3.2F; offset = 2 * width_base; break; case 3: offset = 0.66F * width_base; break; case 2: offset = -0.66F * width_base; break; case 1: offset = -2 * width_base; break; } } if (shaderCGO){ CGOBegin(shaderCGO, GL_TRIANGLE_STRIP); for(a = 0; a <= nEdge; a++) { c = a % nEdge; v[0] = n1[0] * x[c] + n2[0] * y[c]; v[1] = n1[1] * x[c] + n2[1] * y[c]; v[2] = n1[2] * x[c] + n2[2] * y[c]; normalize3f(v); CGONormalv(shaderCGO, v); v[0] = v2[0] + n1[0] * radius * x[c] + n2[0] * radius * y[c] + n0[0] * (offset + width); v[1] = v2[1] + n1[1] * radius * x[c] + n2[1] * radius * y[c] + n0[1] * (offset + width); v[2] = v2[2] + n1[2] * radius * x[c] + n2[2] * radius * y[c] + n0[2] * (offset + width); CGOVertexv(shaderCGO, v); v[0] = v2[0] + n1[0] * radius * x[c] + n2[0] * radius * y[c] + n0[0] * (offset - width); v[1] = v2[1] + n1[1] * radius * x[c] + n2[1] * radius * y[c] + n0[1] * (offset - width); v[2] = v2[2] + n1[2] * radius * x[c] + n2[2] * radius * y[c] + n0[2] * (offset - width); CGOVertexv(shaderCGO, v); } CGOEnd(shaderCGO); CGOBegin(shaderCGO, GL_TRIANGLE_STRIP); for(a = 0; a <= nEdge; a++) { c = a % nEdge; v[0] = n2[0] * x[c] + n0[0] * y[c]; v[1] = n2[1] * x[c] + n0[1] * y[c]; v[2] = n2[2] * x[c] + n0[2] * y[c]; normalize3f(v); CGONormalv(shaderCGO, v); v[0] = v2[0] + n2[0] * radius * x[c] + n0[0] * radius * y[c] + n1[0] * (offset + width); v[1] = v2[1] + n2[1] * radius * x[c] + n0[1] * radius * y[c] + n1[1] * (offset + width); v[2] = v2[2] + n2[2] * radius * x[c] + n0[2] * radius * y[c] + n1[2] * (offset + width); CGOVertexv(shaderCGO, v); v[0] = v2[0] + n2[0] * radius * x[c] + n0[0] * radius * y[c] + n1[0] * (offset - width); v[1] = v2[1] + n2[1] * radius * x[c] + n0[1] * radius * y[c] + n1[1] * (offset - width); v[2] = v2[2] + n2[2] * radius * x[c] + n0[2] * radius * y[c] + n1[2] * (offset - width); CGOVertexv(shaderCGO, v); } CGOEnd(shaderCGO); CGOBegin(shaderCGO, GL_TRIANGLE_STRIP); for(a = 0; a <= nEdge; a++) { c = a % nEdge; v[0] = n0[0] * x[c] + n1[0] * y[c]; v[1] = n0[1] * x[c] + n1[1] * y[c]; v[2] = n0[2] * x[c] + n1[2] * y[c]; normalize3f(v); CGONormalv(shaderCGO, v); v[0] = v2[0] + n0[0] * radius * x[c] + n1[0] * radius * y[c] + n2[0] * (offset + width); v[1] = v2[1] + n0[1] * radius * x[c] + n1[1] * radius * y[c] + n2[1] * (offset + width); v[2] = v2[2] + n0[2] * radius * x[c] + n1[2] * radius * y[c] + n2[2] * (offset + width); CGOVertexv(shaderCGO, v); v[0] = v2[0] + n0[0] * radius * x[c] + n1[0] * radius * y[c] + n2[0] * (offset - width); v[1] = v2[1] + n0[1] * radius * x[c] + n1[1] * radius * y[c] + n2[1] * (offset - width); v[2] = v2[2] + n0[2] * radius * x[c] + n1[2] * radius * y[c] + n2[2] * (offset - width); CGOVertexv(shaderCGO, v); } CGOEnd(shaderCGO); } else { #ifdef PURE_OPENGL_ES_2 /* TODO */ #else glBegin(GL_TRIANGLE_STRIP); for(a = 0; a <= nEdge; a++) { c = a % nEdge; v[0] = n1[0] * x[c] + n2[0] * y[c]; v[1] = n1[1] * x[c] + n2[1] * y[c]; v[2] = n1[2] * x[c] + n2[2] * y[c]; normalize3f(v); glNormal3fv(v); v[0] = v2[0] + n1[0] * radius * x[c] + n2[0] * radius * y[c] + n0[0] * (offset + width); v[1] = v2[1] + n1[1] * radius * x[c] + n2[1] * radius * y[c] + n0[1] * (offset + width); v[2] = v2[2] + n1[2] * radius * x[c] + n2[2] * radius * y[c] + n0[2] * (offset + width); glVertex3fv(v); v[0] = v2[0] + n1[0] * radius * x[c] + n2[0] * radius * y[c] + n0[0] * (offset - width); v[1] = v2[1] + n1[1] * radius * x[c] + n2[1] * radius * y[c] + n0[1] * (offset - width); v[2] = v2[2] + n1[2] * radius * x[c] + n2[2] * radius * y[c] + n0[2] * (offset - width); glVertex3fv(v); } glEnd(); #endif #ifdef PURE_OPENGL_ES_2 /* TODO */ #else glBegin(GL_TRIANGLE_STRIP); for(a = 0; a <= nEdge; a++) { c = a % nEdge; v[0] = n2[0] * x[c] + n0[0] * y[c]; v[1] = n2[1] * x[c] + n0[1] * y[c]; v[2] = n2[2] * x[c] + n0[2] * y[c]; normalize3f(v); glNormal3fv(v); v[0] = v2[0] + n2[0] * radius * x[c] + n0[0] * radius * y[c] + n1[0] * (offset + width); v[1] = v2[1] + n2[1] * radius * x[c] + n0[1] * radius * y[c] + n1[1] * (offset + width); v[2] = v2[2] + n2[2] * radius * x[c] + n0[2] * radius * y[c] + n1[2] * (offset + width); glVertex3fv(v); v[0] = v2[0] + n2[0] * radius * x[c] + n0[0] * radius * y[c] + n1[0] * (offset - width); v[1] = v2[1] + n2[1] * radius * x[c] + n0[1] * radius * y[c] + n1[1] * (offset - width); v[2] = v2[2] + n2[2] * radius * x[c] + n0[2] * radius * y[c] + n1[2] * (offset - width); glVertex3fv(v); } glEnd(); #endif #ifdef PURE_OPENGL_ES_2 /* TODO */ #else glBegin(GL_TRIANGLE_STRIP); for(a = 0; a <= nEdge; a++) { c = a % nEdge; v[0] = n0[0] * x[c] + n1[0] * y[c]; v[1] = n0[1] * x[c] + n1[1] * y[c]; v[2] = n0[2] * x[c] + n1[2] * y[c]; normalize3f(v); glNormal3fv(v); v[0] = v2[0] + n0[0] * radius * x[c] + n1[0] * radius * y[c] + n2[0] * (offset + width); v[1] = v2[1] + n0[1] * radius * x[c] + n1[1] * radius * y[c] + n2[1] * (offset + width); v[2] = v2[2] + n0[2] * radius * x[c] + n1[2] * radius * y[c] + n2[2] * (offset + width); glVertex3fv(v); v[0] = v2[0] + n0[0] * radius * x[c] + n1[0] * radius * y[c] + n2[0] * (offset - width); v[1] = v2[1] + n0[1] * radius * x[c] + n1[1] * radius * y[c] + n2[1] * (offset - width); v[2] = v2[2] + n0[2] * radius * x[c] + n1[2] * radius * y[c] + n2[2] * (offset - width); glVertex3fv(v); } glEnd(); #endif } cycle_counter--; } } /* static void draw_string(float *v,char *l) { glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); if(*l) { glColor3f(1.0,0.0,0.5); glRasterPos4f(v[0],v[1],v[2],1.0); } while(*l) { p_g lutBi tmapChar acter(P_G LUT_BITMAP_8_BY_13,*(l++)); } glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); } */ /*========================================================================*/ void EditorRender(PyMOLGlobals * G, int state) { CEditor *I = G->Editor; int sele1, sele2, sele3, sele4; float v0[3], v1[3]; float vp[12], *vv; /* int v_cnt; */ ObjectMolecule *obj1 = NULL, *obj2 = NULL, *obj3 = NULL, *obj4 = NULL; int index1, index2, index3, index4; int st, frozen; CGO *shaderCGO = NULL; if(EditorActive(G)) { int use_shader = SettingGetGlobal_b(G, cSetting_use_shaders); if (use_shader){ if (!I->shaderCGO){ shaderCGO = CGONew(G); } else { CGORenderGL(I->shaderCGO, NULL, NULL, NULL, NULL, NULL); return; } } else { CGOFree(I->shaderCGO); } PRINTFD(G, FB_Editor) " EditorRender-Debug: rendering...\n" ENDFD; if(G->HaveGUI && G->ValidContext) { sele1 = SelectorIndexByName(G, cEditorSele1); sele2 = SelectorIndexByName(G, cEditorSele2); sele3 = SelectorIndexByName(G, cEditorSele3); sele4 = SelectorIndexByName(G, cEditorSele4); obj1 = SelectorGetFastSingleAtomObjectIndex(G, sele1, &index1); obj2 = SelectorGetFastSingleAtomObjectIndex(G, sele2, &index2); obj3 = SelectorGetFastSingleAtomObjectIndex(G, sele3, &index3); obj4 = SelectorGetFastSingleAtomObjectIndex(G, sele4, &index4); /* printf("%d %d %d %d\n",sele1,sele2,sele3,sele4); printf("%p %p %p %p\n",obj1,obj2,obj3,obj4); printf("%d %d %d %d\n",index1,index2,index3,index4); */ if((sele1 >= 0) && (sele2 >= 0) && I->BondMode && obj1 && obj2) { /* bond mode */ ObjectMoleculeGetAtomTxfVertex(obj1, state, index1, v0); ObjectMoleculeGetAtomTxfVertex(obj2, state, index2, v1); draw_bond(G, v0, v1, shaderCGO); } else { /* atom mode */ vv = vp; if(obj1) { /* if the user froze a state, use it instead of the global */ if((frozen = SettingGetIfDefined_i(obj1->Obj.G, obj1->Obj.Setting, cSetting_state, &st))) { state = st-1; } if(ObjectMoleculeGetAtomTxfVertex(obj1, state, index1, vv)) { draw_globe(G, vv, 1, shaderCGO); vv += 3; } } if(obj2) { if((frozen = SettingGetIfDefined_i(obj2->Obj.G, obj2->Obj.Setting, cSetting_state, &st))) { state = st-1; } if(ObjectMoleculeGetAtomTxfVertex(obj2, state, index2, vv)) { draw_globe(G, vv, 2, shaderCGO); vv += 3; } } if(obj3) { if((frozen = SettingGetIfDefined_i(obj3->Obj.G, obj3->Obj.Setting, cSetting_state, &st))) { state = st-1; } if(ObjectMoleculeGetAtomTxfVertex(obj3, state, index3, vv)) { draw_globe(G, vv, 3, shaderCGO); vv += 3; } } if(obj4) { if((frozen = SettingGetIfDefined_i(obj4->Obj.G, obj4->Obj.Setting, cSetting_state, &st))) { state = st-1; } if(ObjectMoleculeGetAtomTxfVertex(obj4, state, index4, vv)) { draw_globe(G, vv, 4, shaderCGO); vv += 3; } } } } if (shaderCGO){ CGO *convertcgo = NULL; int ok = true; CGOStop(shaderCGO); CHECKOK(ok, shaderCGO); convertcgo = CGOCombineBeginEnd(shaderCGO, 0); CHECKOK(ok, convertcgo); CGOFree(shaderCGO); if (ok){ CGO *tmpCGO = CGONew(G), *convertcgo2 = NULL; if (ok) ok &= CGOEnable(tmpCGO, GL_DEFAULT_SHADER); if (ok) ok &= CGODisable(tmpCGO, GL_TWO_SIDED_LIGHTING); convertcgo2 = CGOOptimizeToVBONotIndexedNoShader(convertcgo, 0); if (ok) ok &= CGOAppendNoStop(tmpCGO, convertcgo2); if (ok) ok &= CGODisable(tmpCGO, GL_DEFAULT_SHADER); if (ok) ok &= CGOStop(tmpCGO); CGOFreeWithoutVBOs(convertcgo2); I->shaderCGO = tmpCGO; I->shaderCGO->use_shader = true; } CGOFree(convertcgo); if (ok){ CGORenderGL(I->shaderCGO, NULL, NULL, NULL, NULL, NULL); } } } } /*========================================================================*/ void EditorInactivate(PyMOLGlobals * G) { CEditor *I = G->Editor; PRINTFD(G, FB_Editor) " EditorInactivate-Debug: callend.\n" ENDFD; I->DihedObject = NULL; I->DragObject = NULL; I->BondMode = false; I->ShowFrags = false; I->NFrag = 0; I->Active = false; SelectorDeletePrefixSet(G, cEditorFragPref); SelectorDeletePrefixSet(G, cEditorBasePref); ExecutiveDelete(G, cEditorSele1); ExecutiveDelete(G, cEditorSele2); ExecutiveDelete(G, cEditorSele3); ExecutiveDelete(G, cEditorSele4); ExecutiveDelete(G, cEditorSet); ExecutiveDelete(G, cEditorBond); ExecutiveDelete(G, cEditorRes); ExecutiveDelete(G, cEditorChain); ExecutiveDelete(G, cEditorObject); ExecutiveDelete(G, cEditorComp); ExecutiveDelete(G, cEditorLink); ExecutiveDelete(G, cEditorDihedral); ExecutiveDelete(G, cEditorDihe1); ExecutiveDelete(G, cEditorDihe2); ExecutiveDelete(G, cEditorMeasure); EditorMouseInvalid(G); EditorInvalidateShaderCGO(G); SceneInvalidate(G); } /*========================================================================*/ /* * Create a transient distance, angle, or dihedral measurement between * the pk1 - pk4 atoms. * * Assumes that the cEditorMeasure object does not exist yet. */ static void EditorAutoMeasure(PyMOLGlobals * G, int sele1, int sele2, int sele3, int sele4, int state) { if (sele1 < 0 || sele2 < 0) return; float _measure_value; if (sele3 < 0) { ExecutiveDist(G, &_measure_value, cEditorMeasure, cEditorSele1, cEditorSele2, 0, -1.f, true, true, false /* reset */, state, false); } else if (sele4 < 0) { ExecutiveAngle(G, &_measure_value, cEditorMeasure, cEditorSele1, cEditorSele2, cEditorSele3, 0, true, false /* reset */, false, true, state); } else { ExecutiveDihedral(G, &_measure_value, cEditorMeasure, cEditorSele1, cEditorSele2, cEditorSele3, cEditorSele4, 0, true, false /* reset */, false, true, state); } ExecutiveColor(G, cEditorMeasure, "gray", 0x1, true); } /*========================================================================*/ void EditorActivate(PyMOLGlobals * G, int state, int enable_bond) { int sele1, sele2, sele3, sele4; CEditor *I = G->Editor; sele1 = SelectorIndexByName(G, cEditorSele1); sele2 = SelectorIndexByName(G, cEditorSele2); sele3 = SelectorIndexByName(G, cEditorSele3); sele4 = SelectorIndexByName(G, cEditorSele4); if((sele1 >= 0) || (sele2 >= 0) || (sele3 >= 0) || (sele4 >= 0)) { I->Active = true; ExecutiveDelete(G, cEditorComp); ExecutiveDelete(G, cEditorRes); ExecutiveDelete(G, cEditorChain); ExecutiveDelete(G, cEditorObject); ExecutiveDelete(G, cEditorBond); ExecutiveDelete(G, cEditorDihedral); ExecutiveDelete(G, cEditorDihe1); ExecutiveDelete(G, cEditorDihe2); ExecutiveDelete(G, cEditorMeasure); I->BondMode = enable_bond; I->NFrag = SelectorSubdivide(G, cEditorFragPref, sele1, sele2, sele3, sele4, cEditorBasePref, cEditorComp, &I->BondMode); /* just returns 'state' */ state = EditorGetEffectiveState(G, NULL, state); I->ActiveState = state; if(0 && (I->NFrag > 1) && SettingGetGlobal_b(G, cSetting_editor_label_fragments)) { /* SelectorComputeFragPos(G,obj,I->ActiveState,I->NFrag,cEditorFragPref,&I->PosVLA); */ I->ShowFrags = true; } else { I->ShowFrags = false; } if(SettingGetGlobal_b(G, cSetting_auto_hide_selections)) ExecutiveHideSelections(G); if(I->BondMode && SettingGetGlobal_b(G, cSetting_editor_auto_dihedral)) EditorDihedralInvalid(G, NULL); if (!I->BondMode && SettingGetGlobal_b(G, cSetting_editor_auto_measure)) EditorAutoMeasure(G, sele1, sele2, sele3, sele4, state); } else { EditorInactivate(G); } EditorMouseInvalid(G); EditorInvalidateShaderCGO(G); } /*========================================================================*/ void EditorSetDrag(PyMOLGlobals * G, CObject * obj, int sele, int quiet, int state) { EditorInactivate(G); state = EditorGetEffectiveState(G, obj, state); if(obj->type == cObjectMolecule) { ObjectMolecule *objMol = (ObjectMolecule*)(void*)obj; if(ObjectMoleculeCheckFullStateSelection(objMol, sele, state)) { int matrix_mode = SettingGet_i(G, obj->Setting, NULL, cSetting_matrix_mode); if(matrix_mode>=1) { /* force / coerce object matrix drags? */ sele = -1; } } } EditorPrepareDrag(G, obj, sele, -1, state, 0); } void EditorReadyDrag(PyMOLGlobals * G, int state) { CEditor *I = G->Editor; if(I->DragObject && (I->DragIndex == -1)) { EditorPrepareDrag(G, I->DragObject, I->DragSelection, -1, state, 0); } } /*========================================================================*/ void EditorPrepareDrag(PyMOLGlobals * G, CObject * obj, int sele, int index, int state, int mode) { int frg; int sele0 = -1, sele1 = -1, sele2 = -1, sele3 = -1; int s; WordType name; int seleFlag = false; int i0, i1, i2, i3; CEditor *I = G->Editor; int log_trans = SettingGetGlobal_b(G, cSetting_log_conformations); int drag_sele = -1; ObjectMolecule *objMol = NULL; PRINTFD(G, FB_Editor) " EditorPrepareDrag-Debug: entered. obj %p index %d\n", (void *) obj, index ENDFD; if(obj->type == cObjectMolecule) objMol = (ObjectMolecule*)(void*)obj; state = EditorGetEffectiveState(G, obj, state); /* TODO: if user is drags label, then the editor must be deactivated */ if((!EditorActive(G))||(!objMol)) { /* non-anchored dragging of objects and now selections */ float mn[3], mx[3]; I->DragObject = obj; I->DragIndex = index; /* set to -1 when in "mouse drag" mode */ I->DragSelection = sele; I->DragHaveBase = false; if(sele >= 0) { char *sele_name = SelectorGetNameFromIndex(G, sele); if(sele_name) { strcpy(I->DragSeleName, sele_name); if(SettingGetGlobal_b(G, cSetting_editor_auto_origin)) { if(I->FavorOrigin) { I->DragHaveBase = true; copy3f(I->FavoredOrigin, I->DragBase); } else { if(ExecutiveGetExtent(G, sele_name, mn, mx, true, state, true)) { average3f(mn, mx, I->DragBase); I->DragHaveBase = true; } } } } else { I->DragSeleName[0] = 0; } } else { if(SettingGetGlobal_b(G, cSetting_editor_auto_origin)) { if(I->FavorOrigin) { I->DragHaveBase = true; copy3f(I->FavoredOrigin, I->DragBase); } else { if(ExecutiveGetExtent(G, obj->Name, mn, mx, true, state, true)) { average3f(mn, mx, I->DragBase); I->DragHaveBase = true; } } } } } else { /* anchored / fragment dragging */ for(frg = 1; frg <= I->NFrag; frg++) { sprintf(name, "%s%1d", cEditorFragPref, frg); drag_sele = SelectorIndexByName(G, name); if(drag_sele >= 0) { s = objMol->AtomInfo[index].selEntry; seleFlag = SelectorIsMember(G, s, drag_sele); } if(seleFlag) { strcpy(I->DragSeleName, name); break; } } if(seleFlag) { /* normal selection */ PRINTFB(G, FB_Editor, FB_Blather) " Editor: grabbing (%s).", name ENDFB(G); I->DragIndex = index; I->DragSelection = drag_sele; I->DragObject = obj; I->DragHaveAxis = false; I->DragHaveBase = false; I->DragBondFlag = false; I->DragSlowFlag = false; sprintf(name, "%s%1d", cEditorBasePref, frg); /* get relevant base vertex of bond */ sele1 = SelectorIndexByName(G, name); if(sele1 >= 0) { i1 = ObjectMoleculeGetAtomIndex(objMol, sele1); if(i1 >= 0) { ObjectMoleculeGetAtomTxfVertex(objMol, state, i1, I->DragBase); I->DragHaveBase = true; /*printf("base %s\n",name); */ } } /* get axis or base atom */ { int cnt = 0; if((sele0 = SelectorIndexByName(G, cEditorSele1)) >= 0) { if(SelectorIsAtomBondedToSele(G, objMol, sele0, drag_sele)) cnt++; else sele0 = -1; } if((sele1 = SelectorIndexByName(G, cEditorSele2)) >= 0) { if(SelectorIsAtomBondedToSele(G, objMol, sele1, drag_sele)) cnt++; else sele1 = -1; } if((sele2 = SelectorIndexByName(G, cEditorSele3)) >= 0) { if(SelectorIsAtomBondedToSele(G, objMol, sele2, drag_sele)) cnt++; else sele2 = -1; } if((sele3 = SelectorIndexByName(G, cEditorSele4)) >= 0) { if(SelectorIsAtomBondedToSele(G, objMol, sele3, drag_sele)) cnt++; else sele3 = -1; } i0 = ObjectMoleculeGetAtomIndex(objMol, sele0); i1 = ObjectMoleculeGetAtomIndex(objMol, sele1); i2 = ObjectMoleculeGetAtomIndex(objMol, sele2); i3 = ObjectMoleculeGetAtomIndex(objMol, sele3); if(cnt > 1) { /* bond/multiatom mode */ I->DragBondFlag = I->BondMode; zero3f(I->Center); if(i0 >= 0) { ObjectMoleculeGetAtomTxfVertex(objMol, state, i0, I->V0); } else if(i1 >= 0) { ObjectMoleculeGetAtomTxfVertex(objMol, state, i1, I->V0); } else if(i2 >= 0) { ObjectMoleculeGetAtomTxfVertex(objMol, state, i2, I->V0); } else if(i3 >= 0) { ObjectMoleculeGetAtomTxfVertex(objMol, state, i3, I->V0); } if(i0 >= 0) { ObjectMoleculeGetAtomTxfVertex(objMol, state, i0, I->V1); add3f(I->V1, I->Center, I->Center); } if(i1 >= 0) { ObjectMoleculeGetAtomTxfVertex(objMol, state, i1, I->V1); add3f(I->V1, I->Center, I->Center); } if(i2 >= 0) { ObjectMoleculeGetAtomTxfVertex(objMol, state, i2, I->V1); add3f(I->V1, I->Center, I->Center); } if(i3 >= 0) { ObjectMoleculeGetAtomTxfVertex(objMol, state, i3, I->V1); add3f(I->V1, I->Center, I->Center); } { float div = 1.0F / cnt; scale3f(I->Center, div, I->Center); } subtract3f(I->Center, I->V0, I->Axis); normalize3f(I->Axis); I->DragHaveAxis = true; if(SettingGetGlobal_b(G, cSetting_editor_auto_origin)) { if(I->FavorOrigin) { I->DragHaveBase = true; copy3f(I->FavoredOrigin, I->DragBase); } else { copy3f(I->Center, I->DragBase); I->DragHaveBase = true; } } } else { /* atom mode */ if(i0 >= 0) { ObjectMoleculeGetAtomTxfVertex(objMol, state, i0, I->V0); } else if(i1 >= 0) { ObjectMoleculeGetAtomTxfVertex(objMol, state, i1, I->V0); } else if(i2 >= 0) { ObjectMoleculeGetAtomTxfVertex(objMol, state, i2, I->V0); } else if(i3 >= 0) { ObjectMoleculeGetAtomTxfVertex(objMol, state, i3, I->V0); } if(I->DragHaveBase) { copy3f(I->DragBase, I->V1); subtract3f(I->V1, I->V0, I->Axis); average3f(I->V1, I->V0, I->Center); normalize3f(I->Axis); I->DragHaveAxis = true; if(mode == cButModeRotFrag) { copy3f(I->V0, I->DragBase); } } } } } else { /* clicked directly on an anchor atom */ sele0 = SelectorIndexByName(G, cEditorSele1); if(sele0 < 0) sele0 = SelectorIndexByName(G, cEditorSele2); if(sele0 < 0) sele0 = SelectorIndexByName(G, cEditorSele3); if(sele0 < 0) sele0 = SelectorIndexByName(G, cEditorSele4); if(sele0 >= 0) { s = objMol->AtomInfo[index].selEntry; seleFlag = SelectorIsMember(G, s, sele0); } PRINTFB(G, FB_Editor, FB_Actions) " Editor: grabbing all fragments." ENDFB(G); I->DragIndex = index; I->DragSelection = SelectorIndexByName(G, cEditorComp); strcpy(I->DragSeleName, cEditorComp); I->DragObject = obj; I->DragHaveAxis = false; I->DragHaveBase = false; I->DragBondFlag = false; I->DragSlowFlag = true; if(sele0 >= 0) { /* just provide a base vector, no valid axis exists */ i1 = ObjectMoleculeGetAtomIndex(objMol, sele0); if(i1 >= 0) { ObjectMoleculeGetAtomTxfVertex(objMol, state, i1, I->DragBase); I->DragHaveBase = true; I->DragBondFlag = true; } } } if(!seleFlag) { I->DragIndex = -1; I->DragSelection = -1; I->DragObject = NULL; } } if(I->DragObject) { I->ShowFrags = false; if(objMol) { ObjectMoleculeSaveUndo(objMol, state, log_trans); if(SettingGetGlobal_b(G, cSetting_auto_sculpt)) { SettingSetGlobal_b(G, cSetting_sculpting, 1); if(!objMol->Sculpt) ObjectMoleculeSculptImprint(objMol, state, -1, 0); } } } if(log_trans) PLogFlush(G); PRINTFD(G, FB_Editor) " EditorPrepDrag-Debug: leaving Index %d Sele %d Object %p\n Axis %d Base %d BondFlag %d SlowFlag %d seleFlag %d\n", I->DragIndex, I->DragSelection, (void *) I->DragObject, I->DragHaveAxis, I->DragHaveBase, I->DragBondFlag, I->DragSlowFlag, seleFlag ENDFD; } int EditorDraggingObjectMatrix(PyMOLGlobals *G) { CEditor *I = G->Editor; if(I->DragObject && (I->DragSelection < 0) && (I->DragIndex == -1)) { return true; } return false; } void EditorDrag(PyMOLGlobals * G, CObject * obj, int index, int mode, int state, float *pt, float *mov, float *z_dir) { CEditor *I = G->Editor; float v0[3], v1[3], v2[3], v3[3], v4[4], cp[3]; float d0[3], d1[3], d2[3], n0[3], n1[3], n2[3]; float opp, adj, theta; float m[16]; int log_trans = SettingGetGlobal_b(G, cSetting_log_conformations); PRINTFD(G, FB_Editor) " EditorDrag-Debug: entered. obj %p state %d index %d mode %d \nIndex %d Sele %d Object %p\n Axis %d Base %d BondFlag %d SlowFlag %d\n", (void *) obj, state, index, mode, I->DragIndex, I->DragSelection, (void *) I->DragObject, I->DragHaveAxis, I->DragHaveBase, I->DragBondFlag, I->DragSlowFlag ENDFD; if((index < 0) && (!obj)) obj = I->DragObject; if(obj) { ObjectMolecule *objMol = NULL; if(obj->type == cObjectMolecule) objMol = (ObjectMolecule*)(void*)obj; state = EditorGetEffectiveState(G, obj, state); if((index == I->DragIndex) && (obj == I->DragObject)) { if(!EditorActive(G)) { int matrix_mode = SettingGet_i(G, I->DragObject->Setting, NULL, cSetting_matrix_mode); if(matrix_mode<0) matrix_mode = EditorDraggingObjectMatrix(G) ? 1 : 0; /* always force use of matrix mode for non-molecular objects */ if((!objMol)&&(!matrix_mode)) matrix_mode = 1; /* non-achored actions */ switch (mode) { case cButModeRotDrag: if(I->DragHaveBase) { copy3f(I->DragBase, v3); } else { SceneOriginGet(G, v3); } get_rotation_about3f3fTTTf(pt[0], mov, v3, m); if(matrix_mode && (I->DragSelection < 0)) { switch (matrix_mode) { case 1: ObjectCombineTTT(obj, m, false, SettingGetGlobal_b(G,cSetting_movie_auto_store)); break; case 2: if(objMol) ObjectMoleculeTransformState44f(objMol, state, m, log_trans, false, true); break; } } else { if(objMol) ObjectMoleculeTransformSelection(objMol, state, I->DragSelection, m, log_trans, I->DragSeleName, false, true); } SceneInvalidate(G); break; case cButModeRotFrag: case cButModeRotObj: case cButModeRotView: if(I->DragHaveBase) { copy3f(I->DragBase, v3); } else { SceneOriginGet(G, v3); } subtract3f(pt, v3, n0); add3f(pt, mov, n1); subtract3f(n1, v3, n1); normalize3f(n0); normalize3f(n1); cross_product3f(n0, n1, cp); theta = (float) asin(length3f(cp)); normalize23f(cp, n2); get_rotation_about3f3fTTTf(theta, n2, v3, m); /* matrix m now contains a valid TTT rotation in global coordinate space that could be applied directly to the coordinates to effect the desired rotation */ if(mode == cButModeRotView) { /* modify the object's TTT */ ObjectCombineTTT(obj, m, false, SettingGetGlobal_b(G,cSetting_movie_auto_store)); } else { if(matrix_mode) { switch (matrix_mode) { case 1: ObjectCombineTTT(obj, m, false, SettingGetGlobal_b(G,cSetting_movie_auto_store)); break; case 2: if(objMol) ObjectMoleculeTransformState44f(objMol, state, m, log_trans, false, true); break; } } else { if(objMol) ObjectMoleculeTransformSelection(objMol, state, I->DragSelection, m, log_trans, I->DragSeleName, false, true); } } SceneInvalidate(G); break; case cButModeTorFrag: if(objMol) { ObjectMoleculeMoveAtom(objMol, state, index, mov, 1, log_trans); SceneInvalidate(G); } break; case cButModeMovView: case cButModeMovViewZ: ObjectTranslateTTT(obj, mov, SettingGetGlobal_b(G,cSetting_movie_auto_store)); break; case cButModeMovObj: case cButModeMovObjZ: case cButModeMovFrag: case cButModeMovFragZ: case cButModeMovDrag: case cButModeMovDragZ: if(matrix_mode && (I->DragSelection < 0)) { identity44f(m); m[3] = mov[0]; m[7] = mov[1]; m[11] = mov[2]; switch (matrix_mode) { case 1: ObjectCombineTTT(obj, m, false, SettingGetGlobal_b(G,cSetting_movie_auto_store)); break; case 2: if(objMol) ObjectMoleculeTransformState44f(objMol, state, m, log_trans, true, true); break; } } else { identity44f(m); copy3f(mov, m + 12); /* questionable... */ if(objMol) ObjectMoleculeTransformSelection(objMol, state, I->DragSelection, m, log_trans, I->DragSeleName, false, true); } SceneInvalidate(G); break; } } else { switch (mode) { case cButModeRotFrag: case cButModeRotObj: if(I->DragHaveBase) { copy3f(I->DragBase, v3); } else { copy3f(I->V0, v3); } if(I->DragSlowFlag) { SceneGetViewNormal(G, v4); scale3f(v4, -1.0F, v4); add3f(v3, v4, v4); subtract3f(pt, v4, n0); add3f(pt, mov, n1); subtract3f(n1, v4, n1); } else { subtract3f(pt, v3, n0); add3f(pt, mov, n1); subtract3f(n1, v3, n1); } normalize3f(n0); normalize3f(n1); cross_product3f(n0, n1, cp); theta = (float) asin(length3f(cp)); normalize23f(cp, n2); get_rotation_about3f3fTTTf(theta, n2, v3, m); if(objMol) { ObjectMoleculeTransformSelection(objMol, state, I->DragSelection, m, log_trans, I->DragSeleName, false, true); SceneInvalidate(G); } break; case cButModeTorFrag: case cButModePkTorBnd: if(I->DragHaveAxis) { subtract3f(pt, I->Center, d0); if(dot_product3f(d0, I->Axis) < 0.0) { copy3f(I->V0, v1); copy3f(I->V1, v0); } else { copy3f(I->V0, v0); copy3f(I->V1, v1); } subtract3f(v1, v0, d1); copy3f(d1, n0); normalize3f(n0); cross_product3f(n0, d0, n1); normalize3f(n1); project3f(d0, n0, v2); add3f(I->Center, v2, v2); /* v2 is the perpendicular point on the axis */ subtract3f(pt, v2, d2); opp = (float) length3f(mov); adj = (float) length3f(d2); if(adj > R_SMALL4) { theta = (float) atan(opp / adj); if(dot_product3f(n1, mov) < 0.0) theta = -theta; get_rotation_about3f3fTTTf(theta, n0, v1, m); if(objMol) ObjectMoleculeTransformSelection(objMol, state, I->DragSelection, m, log_trans, I->DragSeleName, false, true); } else { if(z_dir) { /* NULL-safety */ cross_product3f(I->Axis, z_dir, d0); theta = -dot_product3f(d0, mov); get_rotation_about3f3fTTTf(theta, n0, v1, m); if(objMol) ObjectMoleculeTransformSelection(objMol, state, I->DragSelection, m, log_trans, I->DragSeleName, false, true); } } if(I->BondMode && SettingGetGlobal_b(G, cSetting_editor_auto_dihedral)) EditorDihedralInvalid(G, NULL); } SceneInvalidate(G); break; case cButModeMovFrag: case cButModeMovFragZ: identity44f(m); copy3f(mov, m + 12); /* questionable */ if(objMol) ObjectMoleculeTransformSelection(objMol, state, I->DragSelection, m, log_trans, I->DragSeleName, false, true); SceneInvalidate(G); break; } } } ExecutiveInvalidateSelectionIndicatorsCGO(G); EditorInvalidateShaderCGO(G); } PRINTFD(G, FB_Editor) " EditorDrag-Debug: leaving...\n" ENDFD; } /*========================================================================*/ int EditorInit(PyMOLGlobals * G) { CEditor *I = NULL; if((I = (G->Editor = Calloc(CEditor, 1)))) { I->DihedObject = NULL; I->NFrag = 0; I->Active = false; I->DragObject = NULL; I->DragIndex = -1; I->DragSelection = -1; I->NextPickSele = 0; I->BondMode = false; I->PosVLA = VLAlloc(float, 30); I->DihedralInvalid = false; I->MouseInvalid = false; I->FavorOrigin = false; I->shaderCGO = NULL; return 1; } else return 0; } /*========================================================================*/ void EditorFree(PyMOLGlobals * G) { CEditor *I = G->Editor; VLAFreeP(I->PosVLA); FreeP(G->Editor); } void EditorInvalidateShaderCGO(PyMOLGlobals * G){ CEditor *I = G->Editor; CGOFree(I->shaderCGO); }