mirror of
https://github.com/schrodinger/pymol-open-source.git
synced 2026-06-04 20:04:21 +08:00
3257 lines
98 KiB
C++
3257 lines
98 KiB
C++
|
|
/*
|
|
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 "SelectorDef.h"
|
|
#include "ButMode.h"
|
|
#include "CGORenderer.h"
|
|
#include "GFXManager.h"
|
|
|
|
#ifdef _PYMOL_OPENVR
|
|
#include "OpenVRMode.h"
|
|
#endif
|
|
|
|
#include "Property.h"
|
|
|
|
#include "PyMOL.h"
|
|
#include "PyMOLGlobals.h"
|
|
#include "PyMOLOptions.h"
|
|
#include "Feedback.h"
|
|
#include "GraphicsUtil.h"
|
|
#include "pymol/zstring_view.h"
|
|
|
|
#include "ShaderMgr.h"
|
|
#include "Version.h"
|
|
|
|
#include <unordered_map>
|
|
|
|
#ifndef _PYMOL_NOPY
|
|
PyMOLGlobals *SingletonPyMOLGlobals = nullptr;
|
|
#endif
|
|
|
|
#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
|
|
#define IDLE_AND_READY 3
|
|
|
|
struct CPyMOL {
|
|
PyMOLGlobals *G = nullptr;
|
|
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{};
|
|
int ClickedBondIndex{};
|
|
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 = nullptr;
|
|
|
|
PyMOLSwapBuffersFn *SwapFn = nullptr;
|
|
|
|
|
|
/* Python stuff */
|
|
#ifndef _PYMOL_NOPY
|
|
int PythonInitStage{};
|
|
#endif
|
|
/* dynamically mapped string constants */
|
|
|
|
OVLexicon *Lex = nullptr;
|
|
std::unordered_map<int, int> 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{};
|
|
|
|
std::unordered_map<int, int> Reinit;
|
|
ov_word lex_settings;
|
|
|
|
std::unordered_map<int, int> SelectList;
|
|
ov_word lex_index{}, lex_id{}, lex_rank{};
|
|
|
|
std::unordered_map<int, int> Setting;
|
|
|
|
#ifdef _PYMOL_LIB
|
|
std::unordered_map<int, int> 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{};
|
|
|
|
std::unordered_map<int, int> MouseButtonModCodeLexicon;
|
|
ov_word lex_none{}, lex_shft{}, lex_ctrl{}, lex_ctsh{};
|
|
ov_word lex_alt{}, lex_alsh{}, lex_ctal{}, lex_ctas{};
|
|
|
|
std::unordered_map<int, int> 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{};
|
|
ov_word lex_but_clik{};
|
|
|
|
std::unordered_map<int, int> MouseModeLexicon;
|
|
#include "buttonmodes_lex_def.h"
|
|
|
|
std::unordered_map<int, int> PaletteLexicon;
|
|
#include "palettes_lex_def.h"
|
|
|
|
#endif
|
|
|
|
AtomPropertyInfo AtomPropertyInfos[NUM_ATOM_PROPERTIES]{};
|
|
std::unordered_map<int, int> 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_explicit_degree{},
|
|
lex_atom_prop_explicit_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_,*/
|
|
|
|
};
|
|
|
|
|
|
/* convenience functions -- inline */
|
|
|
|
inline PyMOLstatus get_status_ok(int ok)
|
|
{
|
|
if(ok)
|
|
return PyMOLstatus_SUCCESS;
|
|
else
|
|
return PyMOLstatus_FAILURE;
|
|
}
|
|
|
|
inline PyMOLreturn_status return_status_ok(int ok)
|
|
{
|
|
PyMOLreturn_status result;
|
|
result.status = get_status_ok(ok);
|
|
return result;
|
|
}
|
|
|
|
inline PyMOLreturn_status return_status(int status)
|
|
{
|
|
PyMOLreturn_status result;
|
|
result.status = status;
|
|
return result;
|
|
}
|
|
|
|
inline PyMOLreturn_float return_result(const pymol::Result<float>& res)
|
|
{
|
|
PyMOLreturn_float result = {PyMOLstatus_FAILURE};
|
|
if (res) {
|
|
result.status = PyMOLstatus_SUCCESS;
|
|
result.value = res.result();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static PyMOLreturn_string_array return_result(
|
|
const pymol::Result<std::vector<const char*>>& res)
|
|
{
|
|
PyMOLreturn_string_array result = {
|
|
PyMOLstatus_SUCCESS, 0, nullptr};
|
|
if (!res) {
|
|
result.status = PyMOLstatus_FAILURE;
|
|
} else if (!res.result().empty()) {
|
|
const auto& vec = res.result();
|
|
result.size = vec.size();
|
|
result.array = VLAlloc(char*, result.size);
|
|
|
|
// allocate space for concatenated string in first array element
|
|
size_t reslen = 0;
|
|
for (const char* s : vec) {
|
|
reslen += strlen(s) + 1;
|
|
}
|
|
result.array[0] = VLAlloc(char, reslen);
|
|
|
|
// copy elements
|
|
for (size_t pl = 0, i = 0; i != vec.size(); ++i) {
|
|
result.array[i] = result.array[0] + pl;
|
|
strcpy(result.array[i], vec[i]);
|
|
pl += strlen(vec[i]) + 1;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
pymol::Result<int> get_setting_id(CPyMOL * I, const char *setting)
|
|
{
|
|
OVreturn_word result;
|
|
if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, setting))))
|
|
return pymol::make_error(setting, " not found.");
|
|
auto it = I->Setting.find(result.word);
|
|
if (it == I->Setting.end()) {
|
|
return pymol::make_error(setting, " not found.");
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
static pymol::Result<int> get_rep_id(CPyMOL* I, const char* representation)
|
|
{
|
|
OVreturn_word result;
|
|
|
|
if (!OVreturn_IS_OK(
|
|
(result = OVLexicon_BorrowFromCString(I->Lex, representation))))
|
|
return pymol::make_error(representation, " not found.");
|
|
auto it = I->Rep.find(result.word);
|
|
if (it == I->Rep.end()) {
|
|
return pymol::make_error(representation, " not found.");
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
static pymol::Result<int> get_reinit_id(CPyMOL* I, const char* reinit)
|
|
{
|
|
OVreturn_word result;
|
|
if (!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, reinit))))
|
|
return pymol::make_error(reinit, " not found.");
|
|
auto it = I->Reinit.find(result.word);
|
|
if (it == I->Reinit.end()) {
|
|
return pymol::make_error(reinit, " not found.");
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
static pymol::Result<int> get_select_list_mode(CPyMOL* I, const char* mode)
|
|
{
|
|
OVreturn_word result;
|
|
if (!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, mode))))
|
|
return pymol::make_error(mode, " not found.\n");
|
|
auto it = I->SelectList.find(result.word);
|
|
if (it == I->SelectList.end()) {
|
|
return pymol::make_error(mode, " not found.\n");
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
#ifdef _PYMOL_LIB
|
|
|
|
static pymol::Result<int> get_button_code(CPyMOL* I, char* code)
|
|
{
|
|
OVreturn_word result;
|
|
if (!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, code))))
|
|
return pymol::make_error("Mouse button code ", code, " not found.");
|
|
auto it = I->MouseButtonCodeLexicon.find(result.word);
|
|
if (it == I->MouseButtonCodeLexicon.end()) {
|
|
return pymol::make_error("Mouse button code ", code, " not found.");
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
static pymol::Result<int> get_button_mod_code(CPyMOL* I, char* modcode)
|
|
{
|
|
OVreturn_word result;
|
|
if (!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, modcode))))
|
|
return pymol::make_error("Mouse button mod code ", modcode, " not found.");
|
|
auto it = I->MouseButtonModCodeLexicon.find(result.word);
|
|
if (it == I->MouseButtonModCodeLexicon.end()) {
|
|
return pymol::make_error("Mouse button mod code ", modcode, " not found.");
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
static pymol::Result<int> get_button_action_code(CPyMOL * I, char *actioncode)
|
|
{
|
|
OVreturn_word result;
|
|
if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, actioncode))))
|
|
return pymol::make_error("Mouse button action code ", actioncode, " not found.");
|
|
auto it = I->MouseButtonActionCodeLexicon.find(result.word);
|
|
if (it == I->MouseButtonActionCodeLexicon.end()) {
|
|
return pymol::make_error("Mouse button action code ", actioncode, " not found.");
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
static pymol::Result<int> get_mouse_mode(CPyMOL * I, char *mousemode)
|
|
{
|
|
OVreturn_word result;
|
|
if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, mousemode))))
|
|
return pymol::make_error("Mouse mode", mousemode, " not found.");
|
|
auto it = I->MouseModeLexicon.find(result.word);
|
|
if (it == I->MouseModeLexicon.end()) {
|
|
return pymol::make_error("Mouse mode", mousemode, " not found.");
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
#include "palettes.h"
|
|
|
|
static pymol::Result<int> get_palette(CPyMOL* I, char* palette)
|
|
{
|
|
OVreturn_word result;
|
|
if (!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, palette))))
|
|
return pymol::make_error("Palette ", palette, " not found.");
|
|
auto it = I->PaletteLexicon.find(result.word);
|
|
if (it == I->PaletteLexicon.end()) {
|
|
return pymol::make_error("Palette ", palette, " not found.");
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
static pymol::Result<int> get_cartoon(CPyMOL* I, char* cartoon)
|
|
{
|
|
OVreturn_word result;
|
|
if (!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, cartoon))))
|
|
return pymol::make_error("Cartoon ", cartoon, " not found.");
|
|
auto it = I->CartoonLexicon.find(result.word);
|
|
if (it == I->CartoonLexicon.end()) {
|
|
return pymol::make_error("Cartoon ", cartoon, " not found.");
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
static pymol::Result<int> get_flag(CPyMOL* I, char* flag)
|
|
{
|
|
OVreturn_word result;
|
|
if (!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, flag))))
|
|
return pymol::make_error("Flag ", flag, " not found.");
|
|
auto it = I->FlagLexicon.find(result.word);
|
|
if (it == I->FlagLexicon.end()) {
|
|
return pymol::make_error("Flag ", flag, " not found.");
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
static pymol::Result<int> get_flag_action(CPyMOL* I, char* flag)
|
|
{
|
|
OVreturn_word result;
|
|
if (!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, flag))))
|
|
return pymol::make_error("Flag Action ", flag, " not found.");
|
|
auto it = I->FlagActionLexicon.find(result.word);
|
|
if (it == I->FlagActionLexicon.end()) {
|
|
return pymol::make_error("Flag Action ", flag, " not found.");
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
#endif // _PYMOL_LIB
|
|
|
|
#if defined(__cplusplus) && !defined(_WEBGL)
|
|
extern "C" {
|
|
#endif
|
|
|
|
#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) \
|
|
I->Rep[I->lex_##NAME] = CODE;
|
|
|
|
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);
|
|
|
|
#define LEX_REINIT(NAME, CODE) \
|
|
{ \
|
|
if (!OVreturn_IS_OK((result = OVLexicon_GetFromCString(I->Lex, #NAME)))) \
|
|
return_OVstatus_FAILURE else I->lex_##NAME = result.word; \
|
|
} \
|
|
I->Reinit[I->lex_##NAME] = CODE;
|
|
|
|
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; \
|
|
} \
|
|
I->SelectList[I->lex_##NAME] = CODE;
|
|
|
|
LEX_SELLIST(index, 0);
|
|
LEX_SELLIST(id, 1);
|
|
LEX_SELLIST(rank, 2);
|
|
|
|
if(!CPyMOLInitSetting(I->Lex, I->Setting))
|
|
return_OVstatus_FAILURE;
|
|
|
|
#ifdef _PYMOL_LIB
|
|
|
|
#define LEX_MOUSECODE(NAME, CODE) \
|
|
LEX(NAME) \
|
|
I->MouseButtonCodeLexicon[I->lex_##NAME] = CODE;
|
|
|
|
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);
|
|
|
|
#define LEX_BUTTONMODCODE(NAME, CODE) \
|
|
LEX(NAME) \
|
|
I->MouseButtonModCodeLexicon[I->lex_##NAME] = CODE;
|
|
|
|
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);
|
|
|
|
#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) \
|
|
I->MouseButtonActionCodeLexicon[I->lex_but_##NAME] = CODE;
|
|
#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; \
|
|
I->MouseButtonActionCodeLexicon[I->lex_but_##NAME] = CODE;
|
|
|
|
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);
|
|
|
|
#define LEX_MOUSEMODECODE(NAME,CODE) LEX(NAME) \
|
|
I->MouseModeLexicon[I->lex_ ## NAME] = CODE;
|
|
|
|
#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;
|
|
}
|
|
}
|
|
|
|
#define LEX_PALETTE(NAME, CODE) \
|
|
LEX(NAME) \
|
|
I->PaletteLexicon[I->lex_##NAME] = CODE;
|
|
|
|
#include "palettes_lex_init.h"
|
|
|
|
#endif
|
|
|
|
#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) \
|
|
I->AtomPropertyLexicon[I->lex_atom_prop_##NAME] = CODE; \
|
|
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) \
|
|
I->AtomPropertyLexicon[I->lex_atom_prop_##NAME] = CODE; \
|
|
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_uint32, 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(explicit_degree, ATOM_PROP_EXPLICIT_DEGREE, 0, 0);
|
|
LEX_ATOM_PROP(explicit_valence, ATOM_PROP_EXPLICIT_VALENCE, 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)
|
|
{
|
|
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
|
|
SelectorTmp2 s1(I->G, selection);
|
|
auto result = ExecutiveWindowZoom(I->G, s1.getName(), buffer, state - 1,
|
|
complete, animate, quiet);
|
|
ok = static_cast<bool>(result);
|
|
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
|
|
auto res = ExecutiveOrient(
|
|
I->G, selection, state - 1, animate, complete, buffer, quiet);
|
|
ok = static_cast<bool>(res);
|
|
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
|
|
auto result = ExecutiveCenter(I->G, selection,
|
|
state - 1, origin, animate, nullptr, quiet);
|
|
ok = static_cast<bool>(result);
|
|
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
|
|
float v[3] = { 0.0F, 0.0F, 0.0F };
|
|
auto result = ExecutiveOrigin(I->G, selection, true, "", v, state - 1);
|
|
ok = static_cast<bool>(result);
|
|
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;
|
|
auto result = ExecutiveOrigin(I->G, "", true, "", v, 0);
|
|
ok = static_cast<bool>(ok);
|
|
PYMOL_API_UNLOCK return return_status_ok(ok);
|
|
}
|
|
|
|
PyMOLreturn_status PyMOL_CmdClip(CPyMOL * I,
|
|
const char *mode, float amount,
|
|
const char *selection,
|
|
int state, int quiet)
|
|
{
|
|
int ok = true;
|
|
PYMOL_API_LOCK
|
|
SelectorTmp2 s1(I->G, selection);
|
|
SceneClipFromMode(I->G, mode, amount, s1.getName(), state - 1);
|
|
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
|
|
auto result = ExecutiveLabel(I->G, selection, text, quiet, cExecutiveLabelEvalAlt);
|
|
ok = static_cast<bool>(result);
|
|
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
|
|
|
|
auto res = SelectorCreate(I->G, name, selection, nullptr, quiet, nullptr);
|
|
ret = res ? res.result() : -1;
|
|
|
|
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
|
|
|
|
if (auto mode_id = get_select_list_mode(I, mode)) {
|
|
auto res = ExecutiveSelectList(
|
|
I->G, name, object, list, list_len, state - 1, *mode_id, quiet);
|
|
result = return_status_ok(bool(res));
|
|
}
|
|
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;
|
|
if (auto 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, 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;
|
|
if (auto 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, 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] == '(') {
|
|
auto result1 = ExecutiveSetOnOffBySele(I->G, name, true);
|
|
ok = static_cast<bool>(result1);
|
|
} else {
|
|
auto result2 =
|
|
ExecutiveSetObjVisib(I->G, name, true, false); /* TO DO: parents */
|
|
ok = static_cast<bool>(result2);
|
|
}
|
|
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] == '(') {
|
|
auto result = ExecutiveSetOnOffBySele(I->G, name, false);
|
|
ok = static_cast<bool>(result);
|
|
} else {
|
|
auto result = ExecutiveSetObjVisib(I->G, name, false, false);
|
|
ok = static_cast<bool>(result);
|
|
}
|
|
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 {
|
|
OrthoLineType s1 = "";
|
|
OrthoLineType s2 = "";
|
|
auto setting_id = get_setting_id(I, setting);
|
|
if(ok) ok = static_cast<bool>(setting_id);
|
|
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, 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 {
|
|
OrthoLineType s1 = "";
|
|
OrthoLineType s2 = "";
|
|
auto setting_id = get_setting_id(I, setting);
|
|
if(ok) ok = static_cast<bool>(setting_id);
|
|
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,
|
|
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 {
|
|
OrthoLineType s1 = "";
|
|
auto setting_id = get_setting_id(I, setting);
|
|
if(ok) ok = static_cast<bool>(setting_id);
|
|
if(ok) ok = (SelectorGetTmp2(I->G, selection, s1) >= 0);
|
|
|
|
if(ok) {
|
|
ExecutiveSetSettingFromString(I->G, *setting_id, 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 {
|
|
OrthoLineType s1 = "";
|
|
auto setting_id = get_setting_id(I, setting);
|
|
if(ok) ok = static_cast<bool>(setting_id);
|
|
if(ok) ok = (SelectorGetTmp2(I->G, selection, s1) >= 0);
|
|
|
|
if(ok) {
|
|
ExecutiveGetSettingFromString(I->G, &result, *setting_id, 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 {
|
|
OrthoLineType s1 = "";
|
|
auto setting_id = get_setting_id(I, setting);
|
|
if(ok) ok = static_cast<bool>(setting_id);
|
|
if(ok) ok = (SelectorGetTmp2(I->G, selection, s1) >= 0);
|
|
if(ok) {
|
|
ExecutiveUnsetSetting(I->G, *setting_id, 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
|
|
auto result = ExecutiveColorFromSele(I->G, selection, color, flags, quiet);
|
|
ok = static_cast<bool>(result);
|
|
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);
|
|
SettingGenerateSideEffects(I->G, cSetting_bg_rgb, nullptr, -1, 0);
|
|
} 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;
|
|
PYMOL_API_LOCK
|
|
auto what_id = get_reinit_id(I, what);
|
|
ok = static_cast<bool>(what_id);
|
|
if (ok) {
|
|
auto res = ExecutiveReinitialize(I->G, *what_id, object_name);
|
|
ok = static_cast<bool>(res);
|
|
}
|
|
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)
|
|
{
|
|
PyMOLreturn_float result;
|
|
PYMOL_API_LOCK {
|
|
result = return_result(ExecutiveGetDistance(I->G,
|
|
selection1,
|
|
selection2,
|
|
state));
|
|
}
|
|
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)
|
|
{
|
|
PyMOLreturn_float result;
|
|
PYMOL_API_LOCK {
|
|
int defState1 = -4, defState2 = -4;
|
|
auto res = ExecutiveDistance(I->G, name,
|
|
selection1, selection2, mode, cutoff, label, quiet, reset, state, zoom, defState1, defState2);
|
|
result = return_result(res);
|
|
}
|
|
PYMOL_API_UNLOCK return result;
|
|
}
|
|
|
|
PyMOLreturn_float PyMOL_CmdGetAngle(CPyMOL * I,
|
|
const char *selection1,
|
|
const char *selection2,
|
|
const char *selection3, int state, int quiet)
|
|
{
|
|
PyMOLreturn_float result;
|
|
PYMOL_API_LOCK {
|
|
result = return_result(ExecutiveGetAngle(I->G,
|
|
selection1,
|
|
selection2,
|
|
selection3,
|
|
state));
|
|
}
|
|
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)
|
|
{
|
|
PyMOLreturn_float result;
|
|
PYMOL_API_LOCK {
|
|
int defState1 = -4, defState2 = -4, defState3 = -3;
|
|
auto res = ExecutiveAngle(I->G, name,
|
|
selection1, selection2, selection3, mode, label, reset, zoom, quiet,
|
|
state, defState1, defState2, defState3);
|
|
result = return_result(res);
|
|
}
|
|
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)
|
|
{
|
|
PyMOLreturn_float result;
|
|
PYMOL_API_LOCK {
|
|
result = return_result(ExecutiveGetDihe(I->G,
|
|
selection1,
|
|
selection2,
|
|
selection3,
|
|
selection4,
|
|
state));
|
|
}
|
|
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)
|
|
{
|
|
PyMOLreturn_float result;
|
|
PYMOL_API_LOCK {
|
|
auto res = ExecutiveDihedral(I->G,
|
|
name, selection1, selection2, selection3, selection4, mode, label,
|
|
reset, zoom, quiet, state);
|
|
result = return_result(res);
|
|
}
|
|
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)
|
|
{
|
|
PyMOLreturn_status result = { PyMOLstatus_FAILURE };
|
|
PYMOL_API_LOCK
|
|
auto res = ExecutiveIsomeshEtc(I->G, name, map_name, level, selection, buffer,
|
|
state - 1, carve, source_state - 1, quiet, 1, level);
|
|
result.status = get_status_ok(bool(res));
|
|
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)
|
|
{
|
|
PyMOLreturn_status result = { PyMOLstatus_FAILURE };
|
|
PYMOL_API_LOCK
|
|
auto res = ExecutiveIsomeshEtc(I->G, name, map_name, level, selection, buffer,
|
|
state - 1, carve, source_state - 1, quiet, 0, level);
|
|
result.status = get_status_ok(bool(res));
|
|
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)
|
|
{
|
|
PyMOLreturn_status result = { PyMOLstatus_FAILURE };
|
|
PYMOL_API_LOCK
|
|
auto res = ExecutiveIsosurfaceEtc(I->G, name, map_name, level, selection,
|
|
buffer, state - 1, carve, source_state - 1, side, quiet, mode);
|
|
result.status = get_status_ok(bool(res));
|
|
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)
|
|
{
|
|
PyMOLreturn_status result = { PyMOLstatus_FAILURE };
|
|
PYMOL_API_LOCK
|
|
auto res = ExecutiveIsomeshEtc(I->G, name, map_name, minimum, selection,
|
|
buffer, state - 1, carve, source_state - 1, quiet, 3, maximum);
|
|
result.status = get_status_ok(bool(res));
|
|
PYMOL_API_UNLOCK return result;
|
|
}
|
|
|
|
PyMOLreturn_float PyMOL_CmdIsolevel(CPyMOL * I, const char *name, float level, int state,
|
|
int query, int quiet)
|
|
{
|
|
PyMOLreturn_float result;
|
|
PYMOL_API_LOCK
|
|
if(query) {
|
|
auto res = ExecutiveGetIsolevel(I->G, name, state - 1);
|
|
result = return_result(res);
|
|
} else {
|
|
auto res = ExecutiveIsolevel(I->G, name, level, state - 1, quiet);
|
|
result.status = get_status_ok(static_cast<bool>(res));
|
|
result.value = level;
|
|
}
|
|
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 = nullptr;
|
|
float *range_vla = nullptr;
|
|
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) {
|
|
auto res =
|
|
ExecutiveRampNew(I->G, name, map, pymol::vla_take_ownership(range_vla),
|
|
pymol::vla_take_ownership(color_vla), state, s1, beyond, within,
|
|
sigma, zero, calc_mode, quiet);
|
|
ok = static_cast<bool>(res);
|
|
result.status = get_status_ok(ok);
|
|
} else {
|
|
result.status = PyMOLstatus_FAILURE;
|
|
}
|
|
SelectorFreeTmp(I->G, s1);
|
|
PYMOL_API_UNLOCK return result;
|
|
}
|
|
|
|
/**
|
|
* Supported file formats and their 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, cLoadTypeCCP4Map},
|
|
{"mrc", cLoadTypeMRCStr, cLoadTypeMRC},
|
|
{"map", cLoadTypeCCP4UnspecifiedStr, cLoadTypeCCP4Unspecified},
|
|
{"xplor", cLoadTypeXPLORStr, cLoadTypeXPLORMap},
|
|
{"phi", cLoadTypePHIStr, cLoadTypePHIMap},
|
|
{"dx", cLoadTypeDXStr, 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) {
|
|
auto result = ExecutiveLoad(I->G,
|
|
content_is_filename ? content : nullptr,
|
|
content_is_filename ? nullptr : content,
|
|
content_length,
|
|
pymol_content_type,
|
|
object_name,
|
|
state - 1, zoom, discrete, finish, multiplex, quiet, nullptr, 0, nullptr);
|
|
ok = static_cast<bool>(result);
|
|
}
|
|
}
|
|
}
|
|
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
|
|
auto result = ExecutiveSeleToObject(I->G,
|
|
name, selection, source_state, target_state, discrete, zoom, quiet,
|
|
singletons, copy_properties);
|
|
ok = static_cast<bool>(result);
|
|
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) {
|
|
int color_index = ColorGetIndex(I->G, color);
|
|
if(ok) {
|
|
float pos_tmp[3], *pos = pos_tmp;
|
|
if(use_xyz) {
|
|
pos[0] = x;
|
|
pos[1] = y;
|
|
pos[2] = z;
|
|
} else {
|
|
pos = nullptr;
|
|
}
|
|
auto pseudoatom_name = ExecutivePreparePseudoatomName(I->G, object_name);
|
|
auto res = ExecutivePseudoatom(I->G, pseudoatom_name, selection, name,
|
|
resn, resi, chain, segi, elem, vdw, hetatm, b, q, label, pos,
|
|
color_index, state - 1, mode, quiet);
|
|
ok = static_cast<bool>(res);
|
|
}
|
|
}
|
|
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:
|
|
G->Feedback->setMask(module, (uchar) mask);
|
|
break;
|
|
case 1:
|
|
G->Feedback->enable(module, (uchar) mask);
|
|
break;
|
|
case 2:
|
|
G->Feedback->disable(module, (uchar) mask);
|
|
break;
|
|
case 3:
|
|
G->Feedback->push();
|
|
break;
|
|
case 4:
|
|
G->Feedback->pop();
|
|
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 */
|
|
false, /* no openvr stub */
|
|
};
|
|
|
|
CPyMOLOptions *PyMOLOptions_New(void)
|
|
{
|
|
CPyMOLOptions *result = nullptr;
|
|
result = pymol::calloc<CPyMOLOptions>(1);
|
|
if(result)
|
|
*result = Defaults;
|
|
return result;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
CPyMOL *PyMOL_New(void)
|
|
{
|
|
assert(!Defaults.stereo_capable);
|
|
return PyMOL_NewWithOptions(&Defaults);
|
|
}
|
|
|
|
CPyMOL *PyMOL_NewWithOptions(const CPyMOLOptions * option)
|
|
{
|
|
auto result = new CPyMOL();
|
|
assert(result);
|
|
|
|
auto G = pymol::calloc<PyMOLGlobals>(1);
|
|
assert(G);
|
|
|
|
result->G = G;
|
|
G->PyMOL = result;
|
|
|
|
PyMOL_ResetProgress(result);
|
|
|
|
G->Option = pymol::calloc<CPyMOLOptions>(1);
|
|
assert(G->Option);
|
|
|
|
if (!option) {
|
|
assert(!Defaults.stereo_capable);
|
|
option = &Defaults;
|
|
}
|
|
|
|
*(G->Option) = *option;
|
|
|
|
G->Security = option->security;
|
|
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"
|
|
|
|
G->Feedback = new CFeedback(G, G->Option->quiet);
|
|
WordInit(G);
|
|
UtilInit(G);
|
|
ColorInit(G);
|
|
CGORendererInit(G);
|
|
ShaderMgrInit(G);
|
|
G->GFXMgr = new GFXManager(G->ShaderMgr);
|
|
SettingInitGlobal(G, true, true, false);
|
|
PropertyInit(G);
|
|
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);
|
|
// OpenVRInit() called in ExecutiveStereo
|
|
OrthoInit(G, G->Option->show_splash);
|
|
SceneInit(G);
|
|
MovieScenesInit(G);
|
|
WizardInit(G); /* must come after ortho & scene */
|
|
G->Movie = new CMovie(G);
|
|
G->SelectorMgr = new CSelectorManager();
|
|
G->Selector = new CSelector(G, G->SelectorMgr);
|
|
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
|
|
|
|
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 */
|
|
|
|
PInit(I->G, false);
|
|
|
|
/* and begin the initialization sequence */
|
|
|
|
I->PythonInitStage = 1;
|
|
}
|
|
|
|
#endif
|
|
|
|
void PyMOL_Stop(CPyMOL * I)
|
|
{
|
|
PyMOLGlobals *G = I->G;
|
|
G->Terminating = true;
|
|
TetsurfFree(G);
|
|
IsosurfFree(G);
|
|
WizardFree(G);
|
|
#ifdef SYM_TO_MAT_LIST_IN_C
|
|
SymmetryFree(G);
|
|
#endif
|
|
EditorFree(G);
|
|
ExecutiveFree(G);
|
|
VFontFree(G);
|
|
SculptCacheFree(G);
|
|
AtomInfoFree(G);
|
|
ButModeFree(G);
|
|
ControlFree(G);
|
|
SeekerFree(G);
|
|
SeqFree(G);
|
|
DeleteP(G->Selector);
|
|
DeleteP(G->SelectorMgr);
|
|
DeleteP(G->Movie);
|
|
SceneFree(G);
|
|
MovieScenesFree(G);
|
|
OrthoFree(G);
|
|
#ifdef _PYMOL_OPENVR
|
|
OpenVRFree(G);
|
|
#endif
|
|
DeleteP(G->GFXMgr);
|
|
DeleteP(G->ShaderMgr);
|
|
SettingFreeGlobal(G);
|
|
CharacterFree(G);
|
|
TextFree(G);
|
|
TypeFree(G);
|
|
TextureFree(G);
|
|
SphereFree(G);
|
|
PlugIOManagerFree(G);
|
|
PropertyFree(G);
|
|
PFree(G);
|
|
CGORendererFree(G);
|
|
ColorFree(G);
|
|
UtilFree(G);
|
|
WordFree(G);
|
|
DeleteP(G->Feedback);
|
|
|
|
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 = nullptr;
|
|
#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) {
|
|
G->Feedback->addColored(
|
|
"Error: The requested stereo 3D visualization mode is not available.\n",
|
|
FB_Errors);
|
|
}
|
|
}
|
|
|
|
if(G->LaunchStatus & cPyMOLGlobals_LaunchStatus_MultisampleFailed) {
|
|
G->Feedback->addColored(
|
|
"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->ShaderMgr->defaultBackbuffer.drawBuffer = 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->defaultBackbuffer.framebuffer = buf;
|
|
G->ShaderMgr->topLevelConfig = G->ShaderMgr->defaultBackbuffer;
|
|
}
|
|
#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, nullptr);
|
|
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 = nullptr; /* always resets to nullptr! */
|
|
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();
|
|
|
|
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;
|
|
} 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);
|
|
|
|
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, nullptr };
|
|
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, int bond)
|
|
{
|
|
I->ClickReadyFlag = true;
|
|
I->ClickedIndex = index;
|
|
I->ClickedBondIndex = bond;
|
|
I->ClickedButton = button;
|
|
I->ClickedModifiers = mod;
|
|
I->ClickedX = x;
|
|
I->ClickedY = y;
|
|
I->ClickedPosState = state;
|
|
|
|
strcpy(I->ClickedObject, name ? name : "");
|
|
|
|
if ((I->ClickedHavePos = bool(pos))) {
|
|
copy3f(pos, I->ClickedPos);
|
|
} else {
|
|
zero3f(I->ClickedPos);
|
|
}
|
|
}
|
|
|
|
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 = nullptr;
|
|
PYMOL_API_LOCK int ready = I->ClickReadyFlag;
|
|
if(reset)
|
|
I->ClickReadyFlag = false;
|
|
if(ready) {
|
|
size_t result_size = OrthoLineLength + 1;
|
|
result = pymol::malloc<char>(result_size);
|
|
if(result) {
|
|
const char* butstr = "left";
|
|
switch (I->ClickedButton) {
|
|
case P_GLUT_SINGLE_LEFT:
|
|
butstr = "single_left";
|
|
break;
|
|
case P_GLUT_SINGLE_MIDDLE:
|
|
butstr = "single_middle";
|
|
break;
|
|
case P_GLUT_SINGLE_RIGHT:
|
|
butstr = "single_right";
|
|
break;
|
|
case P_GLUT_DOUBLE_LEFT:
|
|
butstr = "double_left";
|
|
break;
|
|
case P_GLUT_DOUBLE_MIDDLE:
|
|
butstr = "double_middle";
|
|
break;
|
|
case P_GLUT_DOUBLE_RIGHT:
|
|
butstr = "double_right";
|
|
break;
|
|
}
|
|
|
|
WordType modstr = "";
|
|
if(cOrthoCTRL & I->ClickedModifiers) {
|
|
strcat(modstr, " ctrl");
|
|
}
|
|
if(cOrthoALT & I->ClickedModifiers) {
|
|
strcat(modstr, " alt");
|
|
}
|
|
if(cOrthoSHIFT & I->ClickedModifiers) {
|
|
strcat(modstr, " shift");
|
|
}
|
|
|
|
result[0] = 0;
|
|
if(!I->ClickedObject[0]) {
|
|
strcat(result, "type=none\n");
|
|
} else if (auto cobj =
|
|
ExecutiveFindObjectByName(I->G, I->ClickedObject)) {
|
|
switch (cobj->type) {
|
|
case cObjectMolecule:
|
|
strcat(result, "type=object:molecule\n");
|
|
break;
|
|
case cObjectCGO:
|
|
strcat(result, "type=object:cgo\n");
|
|
break;
|
|
default:
|
|
strcat(result, "type=object\n");
|
|
break;
|
|
}
|
|
|
|
snprintf(result + strlen(result), result_size - strlen(result),
|
|
"object=%s\n"
|
|
"index=%d\n"
|
|
"bond=%d\n",
|
|
I->ClickedObject, //
|
|
I->ClickedIndex + 1 /* 1-based */,
|
|
I->ClickedBondIndex /* 0-based or cPickable_t */);
|
|
|
|
auto obj = dynamic_cast<ObjectMolecule const*>(cobj);
|
|
if(obj && (I->ClickedIndex < obj->NAtom)) {
|
|
const AtomInfoType* ai = obj->AtomInfo + I->ClickedIndex;
|
|
char inscode_str[2] = { ai->inscode, '\0' };
|
|
snprintf(result + strlen(result), result_size - strlen(result),
|
|
"rank=%d\n"
|
|
"id=%d\n"
|
|
"segi=%s\n"
|
|
"chain=%s\n"
|
|
"resn=%s\n"
|
|
"resi=%d%s\n"
|
|
"name=%s\n"
|
|
"alt=%s\n",
|
|
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);
|
|
}
|
|
}
|
|
|
|
snprintf(result + strlen(result), result_size - strlen(result),
|
|
"click=%s\n"
|
|
"mod_keys=%s\n"
|
|
"x=%d\n"
|
|
"y=%d\n",
|
|
butstr, modstr + (modstr[0] == ' ' ? 1 : 0), I->ClickedX,
|
|
I->ClickedY);
|
|
|
|
if (I->ClickedHavePos) {
|
|
snprintf(result + strlen(result), result_size - strlen(result),
|
|
"px=%.7g\n"
|
|
"py=%.7g\n"
|
|
"pz=%.7g\n"
|
|
"state=%d\n",
|
|
I->ClickedPos[0], I->ClickedPos[1], I->ClickedPos[2],
|
|
I->ClickedPosState);
|
|
}
|
|
|
|
// strip trailing newline
|
|
assert(pymol::zstring_view(result).ends_with('\n'));
|
|
result[strlen(result) - 1] = '\0';
|
|
}
|
|
}
|
|
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, nullptr };
|
|
PYMOL_API_LOCK result.array = VLAlloc(int, 2);
|
|
if(!result.array) {
|
|
result.status = PyMOLstatus_FAILURE;
|
|
} else {
|
|
std::tie(result.array[0], result.array[1]) = SceneGetImageSize(I->G);
|
|
}
|
|
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, nullptr };
|
|
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 != nullptr));
|
|
}
|
|
|
|
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, nullptr, nullptr, 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 != nullptr);
|
|
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->currentMask(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){
|
|
PyMOLreturn_string_array result = { PyMOLstatus_FAILURE };
|
|
PYMOL_API_LOCK PyMOLGlobals * G = I->G;
|
|
result = return_result(ExecutiveGetNames(G, mode, enabled_only, s0));
|
|
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){
|
|
PyMOLreturn_status result = { PyMOLstatus_FAILURE };
|
|
float minCorner[3], maxCorner[3];
|
|
PYMOL_API_LOCK
|
|
|
|
minCorner[0] = minCorner[1] = minCorner[2] = 0.;
|
|
maxCorner[0] = maxCorner[1] = maxCorner[2] = 1.;
|
|
auto res = ExecutiveMapNew(I->G, name, type, grid_spacing,
|
|
selection, -1., minCorner, maxCorner, state, 0, quiet, 0, normalize, 1.,
|
|
-1., 0.);
|
|
result.status = get_status_ok(static_cast<bool>(res));
|
|
|
|
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, nullptr };
|
|
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, nullptr };
|
|
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;
|
|
}
|
|
|
|
PyMOLreturn_status PyMOL_SetButton(CPyMOL * I, const char *buttonarg, const char *modifierarg, const char *actionarg){
|
|
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);
|
|
auto button_num = get_button_code(I, button);
|
|
auto but_mod_num = get_button_mod_code(I, modifier);
|
|
auto act_code = get_button_action_code(I, action);
|
|
auto ok = static_cast<bool>(button_num) && static_cast<bool>(but_mod_num) &&
|
|
static_cast<bool>(act_code);
|
|
|
|
if (ok) {
|
|
int but_code;
|
|
/* This is directly from the button() function in controlling.py */
|
|
if (*button_num < 3) { // normal button (L,M,R)
|
|
if (*but_mod_num < 4) {
|
|
// none, shft, ctrl, ctsh
|
|
but_code = *button_num + 3 * *but_mod_num;
|
|
} else {
|
|
// alt, alsh, alct, alcs
|
|
but_code = *button_num + 68 + 3 * (*but_mod_num - 4);
|
|
}
|
|
} else if (*button_num < 4) { // wheel
|
|
if (*but_mod_num < 4) {
|
|
// none, shft, ctrl, ctsh
|
|
but_code = 12 + *but_mod_num;
|
|
} else {
|
|
but_code = 64 + *but_mod_num - 4;
|
|
}
|
|
} else {
|
|
// single and double clicks
|
|
but_code = (16 + *button_num - 4) + *but_mod_num * 6;
|
|
}
|
|
ButModeSet(I->G, but_code, *act_code);
|
|
result.status = PyMOLstatus_SUCCESS;
|
|
}
|
|
PYMOL_API_UNLOCK return result;
|
|
}
|
|
#include "buttonmodes.h"
|
|
|
|
PyMOLreturn_status PyMOL_SetMouseButtonMode(CPyMOL * I, const char *modename){
|
|
int ok = true, start;
|
|
pymol::Result<int> mode;
|
|
PyMOLreturn_status result = { PyMOLstatus_FAILURE };
|
|
|
|
PYMOL_API_LOCK
|
|
{
|
|
char *nmodename = (char*)malloc(strlen(modename)+1);
|
|
UtilNCopyToLower((char*)nmodename, modename, strlen(modename)+1);
|
|
mode = get_mouse_mode(I, (char*)nmodename);
|
|
ok = static_cast<bool>(mode);
|
|
free(nmodename);
|
|
}
|
|
if (ok){
|
|
result.status = PyMOLstatus_SUCCESS;
|
|
{
|
|
/* for Button modes, first initialize all buttons, so that
|
|
previous functionality does not linger */
|
|
for (int a = 0; a < cButModeInputCount; a++) {
|
|
ButModeSet(I->G, a, initial_button_modes[a]);
|
|
}
|
|
}
|
|
start = button_mode_start[*mode];
|
|
for (int i = 0; i < n_button_mode[*mode]; i++, start += 2) {
|
|
ButModeSet(I->G, all_buttons[start], all_buttons[start+1]);
|
|
}
|
|
}
|
|
PYMOL_API_UNLOCK return result;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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];
|
|
char *palette = (char*)malloc(strlen(pal)+1);
|
|
UtilNCopyToLower((char*)palette, pal, strlen(pal)+1);
|
|
|
|
auto pal_word = get_palette(I, (char*)palette);
|
|
free(palette);
|
|
if (ok)
|
|
ok = static_cast<bool>(pal_word);
|
|
|
|
result.status = PyMOLstatus_FAILURE;
|
|
if (ok) {
|
|
prefix[0] = palette_prefix[*pal_word];
|
|
prefix[1] = 0;
|
|
array_pl = *pal_word * 3;
|
|
digits = palette_data[array_pl++];
|
|
first = palette_data[array_pl++];
|
|
last = palette_data[array_pl++];
|
|
|
|
auto ret = ExecutiveSpectrum(I->G, selection, expression, minimum, maximum,
|
|
first, last, prefix, digits, byres, quiet);
|
|
|
|
if (ret) {
|
|
result.size = 2;
|
|
result.array = VLAlloc(float, 2);
|
|
result.array[0] = ret.result().first;
|
|
result.array[1] = ret.result().second;
|
|
result.status = PyMOLstatus_SUCCESS;
|
|
}
|
|
}
|
|
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 nullptr;
|
|
auto it = I->AtomPropertyLexicon.find(result.word);
|
|
if (it == I->AtomPropertyLexicon.end()) {
|
|
return nullptr;
|
|
}
|
|
return &I->AtomPropertyInfos[it->second];
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|