mirror of
https://github.com/schrodinger/pymol-open-source.git
synced 2026-06-04 20:04:21 +08:00
868 lines
26 KiB
C++
868 lines
26 KiB
C++
|
|
/*
|
|
A* -------------------------------------------------------------------
|
|
B* This file contains source code for the PyMOL computer program
|
|
C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific.
|
|
D* -------------------------------------------------------------------
|
|
E* It is unlawful to modify or remove this copyright notice.
|
|
F* -------------------------------------------------------------------
|
|
G* Please see the accompanying LICENSE file for further information.
|
|
H* -------------------------------------------------------------------
|
|
I* Additional authors of this source file include:
|
|
-*
|
|
-*
|
|
-*
|
|
Z* -------------------------------------------------------------------
|
|
*/
|
|
#include"os_python.h"
|
|
#include"os_predef.h"
|
|
#include"os_std.h"
|
|
#include"os_gl.h"
|
|
|
|
#include "main.h"
|
|
#include "Base.h"
|
|
#include "Control.h"
|
|
#include "Scene.h"
|
|
#include "Executive.h"
|
|
#include "Setting.h"
|
|
#include "P.h"
|
|
#include "Seq.h"
|
|
#include"Movie.h"
|
|
#include "Text.h"
|
|
#include "Util.h"
|
|
#include "Ortho.h"
|
|
#include "CGO.h"
|
|
|
|
#define cControlBoxSize DIP2PIXEL(17)
|
|
#define cControlLeftMargin DIP2PIXEL(8)
|
|
#define cControlTopMargin DIP2PIXEL(2)
|
|
#define cControlSpacing DIP2PIXEL(2)
|
|
#define cControlInnerMargin DIP2PIXEL(4)
|
|
#define cControlSpread DIP2PIXEL(6)
|
|
#define cControlSize DIP2PIXEL(160)
|
|
|
|
#define cControlButtons 7
|
|
|
|
#define cControlMinWidth 5
|
|
|
|
#define SDOF_QUEUE_MASK 0x1F
|
|
|
|
|
|
struct CControl : public Block {
|
|
bool DragFlag {};
|
|
int LastPos {};
|
|
int ExtraSpace {};
|
|
float ButtonColor[3] { 0.5f, 0.5f, 0.5f };
|
|
float ActiveColor[3] { 0.65f, 0.65f, 0.65f };
|
|
int Pressed { -1 };
|
|
int Active { -1 };
|
|
int SaveWidth { 0 };
|
|
double LastClickTime {};
|
|
int SkipRelease {};
|
|
int NButton { 9 };
|
|
|
|
/* not saved */
|
|
|
|
int sdofActive {};
|
|
double sdofLastIterTime {};
|
|
int sdofMode {};
|
|
float sdofTrans[3] {};
|
|
float sdofRot[3] {};
|
|
unsigned int sdofWroteTo {}, sdofReadFrom {}; /* queue synchronization fields */
|
|
float sdofBuffer[(SDOF_QUEUE_MASK + 1) * 6] {};
|
|
|
|
CControl(PyMOLGlobals * G) : Block(G) {};
|
|
|
|
int click(int button, int x, int y, int mod) override;
|
|
void draw(CGO* ortho) override;
|
|
int drag(int x, int y, int mod) override;
|
|
int release(int button, int x, int y, int mod) override;
|
|
void reshape(int width, int height) override;
|
|
};
|
|
|
|
int ControlSdofButton(PyMOLGlobals * G, int button)
|
|
{
|
|
CControl *I = G->Control;
|
|
if(I) {
|
|
if(button == 1) { /* LEFT */
|
|
if(I->sdofMode != SDOF_DRAG_MODE) {
|
|
I->sdofMode = SDOF_DRAG_MODE;
|
|
OrthoAddOutput(G, " SDOF: Drag mode.\n");
|
|
} else {
|
|
I->sdofMode = SDOF_NORMAL_MODE;
|
|
OrthoAddOutput(G, " SDOF: Normal mode.\n");
|
|
}
|
|
} else if(button == 2) { /* RIGHT */
|
|
if(I->sdofMode != SDOF_CLIP_MODE) {
|
|
I->sdofMode = SDOF_CLIP_MODE;
|
|
OrthoAddOutput(G, " SDOF: Clip mode.\n");
|
|
} else {
|
|
I->sdofMode = SDOF_NORMAL_MODE;
|
|
OrthoAddOutput(G, " SDOF: Normal mode.\n");
|
|
}
|
|
}
|
|
OrthoDirty(G);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int ControlSdofUpdate(PyMOLGlobals * G, float tx, float ty, float tz, float rx, float ry,
|
|
float rz)
|
|
{
|
|
/* may be called asynchronously anytime after CControl has been initialized */
|
|
|
|
CControl *I = G->Control;
|
|
if(I) {
|
|
float tol = 0.0001;
|
|
bool active =
|
|
fabs(tx) >= tol || fabs(ty) >= tol || fabs(tz) >= tol ||
|
|
fabs(rx) >= tol || fabs(ry) >= tol || fabs(rz) >= tol;
|
|
|
|
if(active) {
|
|
int slot = (I->sdofWroteTo + 1) & SDOF_QUEUE_MASK;
|
|
float *buffer = I->sdofBuffer + (6 * slot);
|
|
|
|
buffer[0] = tx;
|
|
buffer[1] = ty;
|
|
buffer[2] = tz;
|
|
buffer[3] = rx;
|
|
buffer[4] = ry;
|
|
buffer[5] = rz;
|
|
|
|
I->sdofWroteTo = slot;
|
|
|
|
{
|
|
if(!I->sdofActive) {
|
|
I->sdofLastIterTime = UtilGetSeconds(G);
|
|
}
|
|
}
|
|
/*printf("wrote %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f %d %d %d\n",tx,ty,tz,rx,ry,rz,I->sdofReadFrom,I->sdofWroteTo,slot); */
|
|
}
|
|
I->sdofActive = active;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int ControlSdofIterate(PyMOLGlobals * G)
|
|
{
|
|
CControl *I = G->Control;
|
|
if(I->sdofWroteTo != I->sdofReadFrom && I->sdofActive) {
|
|
|
|
int slot = I->sdofWroteTo;
|
|
|
|
/* new data available */
|
|
|
|
float *buffer = I->sdofBuffer + (6 * slot);
|
|
|
|
I->sdofTrans[0] = buffer[0];
|
|
I->sdofTrans[1] = buffer[1];
|
|
I->sdofTrans[2] = buffer[2];
|
|
I->sdofRot[0] = buffer[3];
|
|
I->sdofRot[1] = buffer[4];
|
|
I->sdofRot[2] = buffer[5];
|
|
|
|
I->sdofReadFrom = slot;
|
|
|
|
double now = UtilGetSeconds(G);
|
|
double delta = now - I->sdofLastIterTime;
|
|
I->sdofLastIterTime = now;
|
|
|
|
{
|
|
/* suppress small amounts of combined motion using a truncated switching function */
|
|
|
|
float len_rot = length3f(I->sdofRot);
|
|
float len_trans = length3f(I->sdofTrans);
|
|
float *dom, *sub;
|
|
if(len_rot > len_trans) {
|
|
dom = &len_rot;
|
|
sub = &len_trans;
|
|
} else {
|
|
dom = &len_trans;
|
|
sub = &len_rot;
|
|
}
|
|
|
|
{
|
|
float expo = 2.0F;
|
|
float trnc = 0.05F;
|
|
float sub_fxn = (*sub) / (*dom);
|
|
if(sub_fxn < trnc) {
|
|
sub_fxn = 0.0F;
|
|
} else if(sub_fxn < 0.5F) {
|
|
sub_fxn = (sub_fxn - trnc) / (0.5F - trnc);
|
|
sub_fxn = (float) pow(sub_fxn, expo);
|
|
} else {
|
|
sub_fxn = 1.0F - (float) pow(1.0F - sub_fxn, expo);
|
|
}
|
|
*dom = 1.0F;
|
|
*sub = sub_fxn;
|
|
scale3f(I->sdofTrans, len_trans, I->sdofTrans);
|
|
scale3f(I->sdofRot, len_rot, I->sdofRot);
|
|
}
|
|
}
|
|
/* translate */
|
|
SceneTranslateScaled(G,
|
|
delta * I->sdofTrans[0],
|
|
-delta * I->sdofTrans[1], -delta * I->sdofTrans[2], I->sdofMode);
|
|
|
|
/* rotate */
|
|
SceneRotateScaled(G,
|
|
2.0F * delta * I->sdofRot[0],
|
|
-2.0F * delta * I->sdofRot[1],
|
|
-2.0F * delta * I->sdofRot[2], I->sdofMode);
|
|
|
|
SceneDirty(G);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int ControlRocking(PyMOLGlobals * G)
|
|
{
|
|
if(G->Interrupt) {
|
|
SettingSetGlobal_b(G, cSetting_rock, false);
|
|
}
|
|
return SettingGetGlobal_b(G, cSetting_rock);
|
|
}
|
|
|
|
void CControl::reshape(int width, int height)
|
|
{
|
|
PyMOLGlobals *G = m_G;
|
|
CControl *I = G->Control;
|
|
Block::reshape(width, height);
|
|
/* this is a pragmatic workaround for mac X11 where the nub gets
|
|
hidden by the window expansion tab */
|
|
|
|
if((rect.right - rect.left) < 20) {
|
|
rect.top = rect.top + 10;
|
|
}
|
|
|
|
I->ExtraSpace = ((rect.right - rect.left) - cControlSize);
|
|
if(I->ExtraSpace < 0)
|
|
I->ExtraSpace = 0;
|
|
}
|
|
|
|
static int which_button(CControl * I, int x, int y)
|
|
{
|
|
int result = -1;
|
|
x -= I->rect.left + cControlLeftMargin;
|
|
y -= I->rect.top - cControlTopMargin;
|
|
if(x >= 0)
|
|
if((y <= 0) && (y > (-cControlBoxSize))) {
|
|
int control_width =
|
|
I->rect.right - (I->rect.left + cControlLeftMargin);
|
|
result = (I->NButton * x) / control_width;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int CControl::drag(int x, int y, int mod)
|
|
{
|
|
int delta;
|
|
int gui_width;
|
|
PyMOLGlobals *G = m_G;
|
|
CControl *I = G->Control;
|
|
if(!I->SkipRelease) {
|
|
delta = x - I->LastPos;
|
|
delta /= DIP2PIXEL(1);
|
|
if(I->DragFlag) {
|
|
if(delta) {
|
|
gui_width = SettingGetGlobal_i(G, cSetting_internal_gui_width) - delta;
|
|
if(gui_width < cControlMinWidth)
|
|
gui_width = cControlMinWidth;
|
|
delta = SettingGetGlobal_i(G, cSetting_internal_gui_width) - gui_width;
|
|
I->LastPos = x;
|
|
I->SaveWidth = 0;
|
|
SettingSetGlobal_i(G, cSetting_internal_gui_width, gui_width);
|
|
OrthoReshape(G, -1, -1, false);
|
|
}
|
|
} else {
|
|
I->Active = which_button(I, x, y);
|
|
if(I->Active != I->Pressed)
|
|
I->Active = -1;
|
|
OrthoInvalidateDoDraw(G);
|
|
OrthoDirty(G);
|
|
}
|
|
}
|
|
return (1);
|
|
}
|
|
|
|
int CControl::release(int button, int x, int y, int mod)
|
|
{
|
|
PyMOLGlobals *G = m_G;
|
|
CControl *I = G->Control;
|
|
|
|
int sel = 0;
|
|
|
|
I->LastPos = x;
|
|
sel = which_button(I, x, y);
|
|
if(!I->SkipRelease) {
|
|
switch (sel) {
|
|
case 0:
|
|
SceneSetFrame(G, 4, 0);
|
|
PLog(G, "cmd.rewind()", cPLog_pym);
|
|
break;
|
|
case 1:
|
|
SceneSetFrame(G, 5, -1);
|
|
PLog(G, "cmd.back()", cPLog_pym);
|
|
break;
|
|
case 2:
|
|
MoviePlay(G, cMovieStop);
|
|
if(SettingGetGlobal_b(G, cSetting_sculpting))
|
|
SettingSetGlobal_b(G, cSetting_sculpting, 0);
|
|
if(SettingGetGlobal_b(G, cSetting_rock))
|
|
SettingSetGlobal_b(G, cSetting_rock, false);
|
|
OrthoDirty(G);
|
|
PLog(G, "cmd.mstop()", cPLog_pym);
|
|
break;
|
|
case 3:
|
|
if(!MoviePlaying(G)) {
|
|
if(mod & cOrthoCTRL) {
|
|
PLog(G, "cmd.rewind()", cPLog_pym);
|
|
PLog(G, "cmd.mplay()", cPLog_pym);
|
|
SceneSetFrame(G, 4, 0);
|
|
MoviePlay(G, cMoviePlay);
|
|
} else {
|
|
PLog(G, "cmd.mplay()", cPLog_pym);
|
|
MoviePlay(G, cMoviePlay);
|
|
}
|
|
} else {
|
|
MoviePlay(G, cMovieStop);
|
|
OrthoDirty(G);
|
|
PLog(G, "cmd.mstop()", cPLog_pym);
|
|
}
|
|
break;
|
|
case 4:
|
|
SceneSetFrame(G, 5, 1);
|
|
PLog(G, "cmd.forward()", cPLog_pym);
|
|
break;
|
|
case 5:
|
|
if(mod & cOrthoCTRL) {
|
|
SceneSetFrame(G, 3, 0);
|
|
PLog(G, "cmd.middle()", cPLog_pym);
|
|
} else {
|
|
SceneSetFrame(G, 6, 0);
|
|
PLog(G, "cmd.ending()", cPLog_pym);
|
|
}
|
|
break;
|
|
case 6:
|
|
if(SettingGetGlobal_b(G, cSetting_seq_view)) {
|
|
SettingSetGlobal_b(G, cSetting_seq_view, 0);
|
|
SeqChanged(G);
|
|
PLog(G, "cmd.set('seq_view',0)", cPLog_pym);
|
|
} else {
|
|
SettingSetGlobal_b(G, cSetting_seq_view, 1);
|
|
SeqChanged(G);
|
|
PLog(G, "cmd.set('seq_view',1)", cPLog_pym);
|
|
}
|
|
OrthoDirty(G);
|
|
break;
|
|
case 7:
|
|
SettingSetGlobal_b(G, cSetting_rock, !SettingGetGlobal_b(G, cSetting_rock));
|
|
if(SettingGetGlobal_b(G, cSetting_rock)) {
|
|
SceneRestartSweepTimer(G);
|
|
PLog(G, "cmd.rock(1)", cPLog_pym);
|
|
} else
|
|
PLog(G, "cmd.rock(0)", cPLog_pym);
|
|
SceneRestartFrameTimer(G);
|
|
OrthoDirty(G);
|
|
break;
|
|
case 8:
|
|
PLog(G, "cmd.full_screen()", cPLog_pym);
|
|
#ifdef _PYMOL_NOPY
|
|
ExecutiveFullScreen(G, -1);
|
|
#else
|
|
PParse(G, "full_screen");
|
|
#endif
|
|
break;
|
|
}
|
|
OrthoDirty(G);
|
|
OrthoUngrab(G);
|
|
I->LastClickTime = UtilGetSeconds(G);
|
|
I->DragFlag = false;
|
|
I->Active = -1;
|
|
I->Pressed = -1;
|
|
}
|
|
return (1);
|
|
}
|
|
|
|
Block *ControlGetBlock(PyMOLGlobals * G)
|
|
{
|
|
CControl *I = G->Control;
|
|
{
|
|
return (I);
|
|
}
|
|
}
|
|
|
|
|
|
/*========================================================================*/
|
|
int ControlIdling(PyMOLGlobals * G)
|
|
{
|
|
CControl *I = G->Control;
|
|
return (I->sdofActive ||
|
|
MoviePlaying(G) ||
|
|
SettingGetGlobal_b(G, cSetting_rock) || SettingGetGlobal_b(G, cSetting_sculpting));
|
|
}
|
|
|
|
|
|
/*========================================================================*/
|
|
void ControlFree(PyMOLGlobals * G)
|
|
{
|
|
|
|
DeleteP(G->Control);
|
|
}
|
|
|
|
|
|
/*========================================================================*/
|
|
pymol::Result<bool> ControlRock(PyMOLGlobals * G, int mode)
|
|
{
|
|
switch (mode) {
|
|
case -2:
|
|
break;
|
|
case -1:
|
|
SettingSetGlobal_b(G, cSetting_rock, !SettingGetGlobal_b(G, cSetting_rock));
|
|
if(SettingGetGlobal_b(G, cSetting_rock)) {
|
|
SceneRestartSweepTimer(G);
|
|
}
|
|
break;
|
|
case 0:
|
|
SettingSetGlobal_b(G, cSetting_rock, false);
|
|
break;
|
|
case 1:
|
|
SettingSetGlobal_b(G, cSetting_rock, true);
|
|
SceneRestartSweepTimer(G);
|
|
break;
|
|
}
|
|
if(mode != -2) {
|
|
SceneRestartFrameTimer(G);
|
|
OrthoDirty(G);
|
|
}
|
|
return SettingGetGlobal_b(G, cSetting_rock);
|
|
}
|
|
|
|
|
|
/*========================================================================*/
|
|
int CControl::click(int button, int x, int y, int mod)
|
|
{
|
|
PyMOLGlobals *G = m_G;
|
|
CControl *I = G->Control;
|
|
I->SkipRelease = false;
|
|
if(x < (I->rect.left + cControlLeftMargin)) {
|
|
y -= I->rect.top - cControlTopMargin;
|
|
if((y <= 0) && (y > (-cControlBoxSize))) {
|
|
double now = UtilGetSeconds(m_G);
|
|
if((now - I->LastClickTime) < 0.35) {
|
|
if(I->SaveWidth) {
|
|
SettingSetGlobal_i(G, cSetting_internal_gui_width, I->SaveWidth);
|
|
OrthoReshape(G, -1, -1, false);
|
|
I->SaveWidth = 0;
|
|
} else {
|
|
I->SaveWidth = SettingGetGlobal_i(G, cSetting_internal_gui_width);
|
|
SettingSetGlobal_i(G, cSetting_internal_gui_width, cControlMinWidth);
|
|
OrthoReshape(G, -1, -1, false);
|
|
}
|
|
I->SkipRelease = true;
|
|
} else {
|
|
I->LastPos = x;
|
|
OrthoGrab(G, this);
|
|
I->DragFlag = true;
|
|
I->LastClickTime = UtilGetSeconds(G);
|
|
}
|
|
}
|
|
} else {
|
|
I->Pressed = which_button(I, x, y);
|
|
I->Active = I->Pressed;
|
|
if(I->Pressed)
|
|
OrthoGrab(G, this);
|
|
OrthoDirty(G);
|
|
}
|
|
return (1);
|
|
}
|
|
|
|
static void draw_button(int x2, int y2, int w, int h, float *light, float *dark,
|
|
float *inside , CGO *orthoCGO)
|
|
{
|
|
if (orthoCGO){
|
|
CGOColorv(orthoCGO, light);
|
|
CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
|
|
CGOVertex(orthoCGO, x2, y2, 0.f);
|
|
CGOVertex(orthoCGO, x2, y2 + h, 0.f);
|
|
CGOVertex(orthoCGO, x2 + w, y2, 0.f);
|
|
CGOVertex(orthoCGO, x2 + w, y2 + h, 0.f);
|
|
CGOEnd(orthoCGO);
|
|
|
|
CGOColorv(orthoCGO, dark);
|
|
CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
|
|
CGOVertex(orthoCGO, x2 + 1, y2, 0.f);
|
|
CGOVertex(orthoCGO, x2 + 1, y2 + h - 1, 0.f);
|
|
CGOVertex(orthoCGO, x2 + w, y2, 0.f);
|
|
CGOVertex(orthoCGO, x2 + w, y2 + h - 1, 0.f);
|
|
CGOEnd(orthoCGO);
|
|
|
|
CGOColorv(orthoCGO, inside);
|
|
CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
|
|
CGOVertex(orthoCGO, x2 + 1, y2 + 1, 0.f);
|
|
CGOVertex(orthoCGO, x2 + 1, y2 + h - 1, 0.f);
|
|
CGOVertex(orthoCGO, x2 + w - 1, y2 + 1, 0.f);
|
|
CGOVertex(orthoCGO, x2 + w - 1, y2 + h - 1, 0.f);
|
|
CGOEnd(orthoCGO);
|
|
} else {
|
|
glColor3fv(light);
|
|
glBegin(GL_POLYGON);
|
|
glVertex2i(x2, y2);
|
|
glVertex2i(x2, y2 + h);
|
|
glVertex2i(x2 + w, y2 + h);
|
|
glVertex2i(x2 + w, y2);
|
|
glEnd();
|
|
|
|
glColor3fv(dark);
|
|
glBegin(GL_POLYGON);
|
|
glVertex2i(x2 + 1, y2);
|
|
glVertex2i(x2 + 1, y2 + h - 1);
|
|
glVertex2i(x2 + w, y2 + h - 1);
|
|
glVertex2i(x2 + w, y2);
|
|
glEnd();
|
|
|
|
glColor3fv(inside);
|
|
glBegin(GL_POLYGON);
|
|
glVertex2i(x2 + 1, y2 + 1);
|
|
glVertex2i(x2 + 1, y2 + h - 1);
|
|
glVertex2i(x2 + w - 1, y2 + h - 1);
|
|
glVertex2i(x2 + w - 1, y2 + 1);
|
|
glEnd();
|
|
}
|
|
}
|
|
|
|
|
|
/*========================================================================*/
|
|
void CControl::draw(CGO* orthoCGO)
|
|
{
|
|
PyMOLGlobals *G = m_G;
|
|
CControl *I = this; // TODO: Remove I during Control refactor
|
|
int x, y;
|
|
int nButton = I->NButton;
|
|
int but_num;
|
|
float lightEdge[3] = { 0.65F, 0.65F, 0.65F };
|
|
float darkEdge[3] = { 0.3F, 0.3F, 0.3F };
|
|
float pushed[3] = { 0.8F, 0.8F, 0.8F };
|
|
|
|
if(G->HaveGUI && G->ValidContext) {
|
|
|
|
int control_width = rect.right - (rect.left + cControlLeftMargin);
|
|
|
|
if (orthoCGO)
|
|
CGOColorv(orthoCGO, BackColor);
|
|
#ifndef PURE_OPENGL_ES_2
|
|
else
|
|
glColor3fv(BackColor);
|
|
#endif
|
|
fill(orthoCGO);
|
|
if (orthoCGO)
|
|
CGOColorv(orthoCGO, TextColor);
|
|
#ifndef PURE_OPENGL_ES_2
|
|
else
|
|
glColor3fv(TextColor);
|
|
#endif
|
|
{
|
|
int top, left, bottom, right;
|
|
|
|
left = rect.left + 1;
|
|
bottom = rect.bottom + 1;
|
|
top = rect.top - (cControlTopMargin - 1);
|
|
right = left + DIP2PIXEL(5);
|
|
|
|
/* This draws the separator on the left side of the movie control buttons */
|
|
if (orthoCGO){
|
|
CGOColor(orthoCGO, 0.8F, 0.8F, 0.8F);
|
|
CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
|
|
CGOVertex(orthoCGO, right, top, 0.f);
|
|
CGOVertex(orthoCGO, right, bottom, 0.f);
|
|
CGOVertex(orthoCGO, left, top, 0.f);
|
|
CGOVertex(orthoCGO, left, bottom, 0.f);
|
|
CGOEnd(orthoCGO);
|
|
|
|
CGOColor(orthoCGO, 0.3F, 0.3F, 0.3F);
|
|
CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
|
|
CGOVertex(orthoCGO, right, top - 1, 0.f);
|
|
CGOVertex(orthoCGO, right, bottom, 0.f);
|
|
CGOVertex(orthoCGO, left + 1, top - 1, 0.f);
|
|
CGOVertex(orthoCGO, left + 1, bottom, 0.f);
|
|
CGOEnd(orthoCGO);
|
|
|
|
CGOColorv(orthoCGO, I->ButtonColor);
|
|
|
|
CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
|
|
CGOVertex(orthoCGO, right - 1, top - 1, 0.f);
|
|
CGOVertex(orthoCGO, right - 1, bottom + 1, 0.f);
|
|
CGOVertex(orthoCGO, left + 1, top - 1, 0.f);
|
|
CGOVertex(orthoCGO, left + 1, bottom + 1, 0.f);
|
|
CGOEnd(orthoCGO);
|
|
} else {
|
|
glColor3f(0.8F, 0.8F, 0.8F);
|
|
glBegin(GL_POLYGON);
|
|
glVertex2i(right, top);
|
|
glVertex2i(right, bottom);
|
|
glVertex2i(left, bottom);
|
|
glVertex2i(left, top);
|
|
glEnd();
|
|
|
|
glColor3f(0.3F, 0.3F, 0.3F);
|
|
glBegin(GL_POLYGON);
|
|
glVertex2i(right, top - 1);
|
|
glVertex2i(right, bottom);
|
|
glVertex2i(left + 1, bottom);
|
|
glVertex2i(left + 1, top - 1);
|
|
glEnd();
|
|
|
|
glColor3fv(I->ButtonColor);
|
|
|
|
glBegin(GL_POLYGON);
|
|
glVertex2i(right - 1, top - 1);
|
|
glVertex2i(right - 1, bottom + 1);
|
|
glVertex2i(left + 1, bottom + 1);
|
|
glVertex2i(left + 1, top - 1);
|
|
glEnd();
|
|
}
|
|
|
|
y = rect.top - cControlTopMargin;
|
|
|
|
for(but_num = 0; but_num < nButton; but_num++) {
|
|
int but_width;
|
|
int but_left;
|
|
int but_bottom;
|
|
int but_height;
|
|
|
|
but_left =
|
|
rect.left + cControlLeftMargin + (but_num * control_width) / nButton;
|
|
but_width =
|
|
(((but_num + 1) * control_width / nButton) -
|
|
((but_num) * control_width / nButton)) - 1;
|
|
|
|
but_bottom = y - (cControlBoxSize - 1);
|
|
but_height = cControlBoxSize;
|
|
|
|
if(but_num == I->Active) {
|
|
draw_button(but_left, but_bottom,
|
|
but_width, but_height, lightEdge, darkEdge, pushed, orthoCGO);
|
|
} else if(((but_num == 6) && (SettingGetGlobal_b(G, cSetting_seq_view))) ||
|
|
((but_num == 3) && (MoviePlaying(G))) ||
|
|
((but_num == 7) && (SettingGetGlobal_b(G, cSetting_rock)))){
|
|
draw_button(but_left, but_bottom,
|
|
but_width, but_height, lightEdge, darkEdge, I->ActiveColor, orthoCGO);
|
|
} else {
|
|
draw_button(but_left, but_bottom,
|
|
but_width, but_height, lightEdge, darkEdge, I->ButtonColor, orthoCGO);
|
|
}
|
|
|
|
if(control_width > 100) {
|
|
x = but_left + (but_width - cControlBoxSize) / 2;
|
|
|
|
if (orthoCGO)
|
|
CGOColorv(orthoCGO, TextColor);
|
|
#ifndef PURE_OPENGL_ES_2
|
|
else
|
|
glColor3fv(TextColor);
|
|
#endif
|
|
switch (but_num) {
|
|
case 0:
|
|
if (orthoCGO){
|
|
CGOBegin(orthoCGO, GL_TRIANGLES);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + cControlInnerMargin, y - (cControlBoxSize / 2), 0.f);
|
|
CGOEnd(orthoCGO);
|
|
|
|
|
|
CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
|
|
CGOVertex(orthoCGO, x + cControlInnerMargin, y - cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + cControlInnerMargin-1.f, y - cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + cControlInnerMargin, y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + cControlInnerMargin-1.f, y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
|
|
CGOEnd(orthoCGO);
|
|
} else {
|
|
glBegin(GL_TRIANGLES);
|
|
glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - cControlInnerMargin);
|
|
glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - (cControlBoxSize - 1) + cControlInnerMargin);
|
|
glVertex2i(x + cControlInnerMargin, y - (cControlBoxSize / 2));
|
|
glEnd();
|
|
glBegin(GL_LINES);
|
|
glVertex2i(x + cControlInnerMargin, y - cControlInnerMargin);
|
|
glVertex2i(x + cControlInnerMargin,
|
|
y - (cControlBoxSize - 1) + cControlInnerMargin);
|
|
glEnd();
|
|
}
|
|
break;
|
|
case 1:
|
|
if (orthoCGO){
|
|
CGOBegin(orthoCGO, GL_TRIANGLES);
|
|
CGOVertex(orthoCGO, x + cControlBoxSize / 2 + 2, y - (cControlBoxSize / 2), 0.f);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + cControlInnerMargin, y - (cControlBoxSize / 2), 0.f);
|
|
CGOVertex(orthoCGO, x + cControlInnerMargin, y - (cControlBoxSize / 2), 0.f);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + cControlBoxSize / 2 + 2, y - (cControlBoxSize / 2), 0.f);
|
|
CGOEnd(orthoCGO);
|
|
} else {
|
|
glBegin(GL_POLYGON);
|
|
glVertex2i(x + cControlBoxSize / 2 + 2, y - (cControlBoxSize / 2));
|
|
glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - cControlInnerMargin);
|
|
glVertex2i(x + cControlInnerMargin, y - (cControlBoxSize / 2));
|
|
glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - (cControlBoxSize - 1) + cControlInnerMargin);
|
|
glEnd();
|
|
}
|
|
break;
|
|
case 2:
|
|
if (orthoCGO){
|
|
CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
|
|
CGOVertex(orthoCGO, x + cControlInnerMargin, y - cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + cControlInnerMargin,
|
|
y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
|
|
CGOEnd(orthoCGO);
|
|
} else {
|
|
glBegin(GL_POLYGON);
|
|
glVertex2i(x + cControlInnerMargin, y - cControlInnerMargin);
|
|
glVertex2i(x + cControlInnerMargin,
|
|
y - (cControlBoxSize - 1) + cControlInnerMargin);
|
|
glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - (cControlBoxSize - 1) + cControlInnerMargin);
|
|
glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - cControlInnerMargin);
|
|
glEnd();
|
|
}
|
|
break;
|
|
case 3:
|
|
if (orthoCGO){
|
|
CGOBegin(orthoCGO, GL_TRIANGLES);
|
|
CGOVertex(orthoCGO, x + cControlInnerMargin, y - cControlInnerMargin + 1, 0.f);
|
|
CGOVertex(orthoCGO, x + cControlInnerMargin,
|
|
y - (cControlBoxSize - 1) + cControlInnerMargin - 1, 0.f);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize) - cControlInnerMargin,
|
|
y - (cControlBoxSize / 2), 0.f);
|
|
CGOEnd(orthoCGO);
|
|
} else {
|
|
glBegin(GL_TRIANGLES);
|
|
glVertex2i(x + cControlInnerMargin, y - cControlInnerMargin + 1);
|
|
glVertex2i(x + cControlInnerMargin,
|
|
y - (cControlBoxSize - 1) + cControlInnerMargin - 1);
|
|
glVertex2i(x + (cControlBoxSize) - cControlInnerMargin,
|
|
y - (cControlBoxSize / 2));
|
|
glEnd();
|
|
}
|
|
break;
|
|
case 4:
|
|
if (orthoCGO){
|
|
CGOBegin(orthoCGO, GL_TRIANGLES);
|
|
CGOVertex(orthoCGO, x + cControlBoxSize / 2 - 2, y - (cControlBoxSize / 2), 0.f);
|
|
CGOVertex(orthoCGO, x + cControlInnerMargin, y - cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - (cControlBoxSize / 2), 0.f);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - (cControlBoxSize / 2), 0.f);
|
|
CGOVertex(orthoCGO, x + cControlInnerMargin,
|
|
y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + cControlBoxSize / 2 - 2, y - (cControlBoxSize / 2), 0.f);
|
|
CGOEnd(orthoCGO);
|
|
} else {
|
|
glBegin(GL_POLYGON);
|
|
glVertex2i(x + cControlBoxSize / 2 - 2, y - (cControlBoxSize / 2));
|
|
glVertex2i(x + cControlInnerMargin, y - cControlInnerMargin);
|
|
glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - (cControlBoxSize / 2));
|
|
glVertex2i(x + cControlInnerMargin,
|
|
y - (cControlBoxSize - 1) + cControlInnerMargin);
|
|
glEnd();
|
|
}
|
|
break;
|
|
case 5:
|
|
if (orthoCGO){
|
|
CGOBegin(orthoCGO, GL_TRIANGLES);
|
|
CGOVertex(orthoCGO, x + cControlInnerMargin, y - cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + cControlInnerMargin,
|
|
y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - (cControlBoxSize / 2), 0.f);
|
|
CGOEnd(orthoCGO);
|
|
|
|
CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin, y - cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin - 1.f, y - cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin, y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin - 1.f, y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
|
|
CGOEnd(orthoCGO);
|
|
} else {
|
|
glBegin(GL_TRIANGLES);
|
|
glVertex2i(x + cControlInnerMargin, y - cControlInnerMargin);
|
|
glVertex2i(x + cControlInnerMargin,
|
|
y - (cControlBoxSize - 1) + cControlInnerMargin);
|
|
glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - (cControlBoxSize / 2));
|
|
glEnd();
|
|
glBegin(GL_LINES);
|
|
glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - cControlInnerMargin);
|
|
glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
|
|
y - (cControlBoxSize - 1) + cControlInnerMargin);
|
|
glEnd();
|
|
}
|
|
break;
|
|
case 6:
|
|
TextSetColor(G, TextColor);
|
|
TextDrawStrAt(G, "S", x + cControlInnerMargin,
|
|
y - cControlBoxSize + cControlInnerMargin + 1, orthoCGO);
|
|
break;
|
|
case 7:
|
|
if (orthoCGO){
|
|
CGOBegin(orthoCGO, GL_TRIANGLES);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize / 2) + cControlSpread, y - cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize / 2),
|
|
y - (cControlBoxSize) + cControlInnerMargin, 0.f);
|
|
CGOVertex(orthoCGO, x + (cControlBoxSize / 2) - cControlSpread, y - cControlInnerMargin, 0.f);
|
|
CGOEnd(orthoCGO);
|
|
} else {
|
|
glBegin(GL_POLYGON);
|
|
glVertex2i(x + (cControlBoxSize / 2) + cControlSpread, y - cControlInnerMargin);
|
|
glVertex2i(x + (cControlBoxSize / 2),
|
|
y - (cControlBoxSize) + cControlInnerMargin);
|
|
glVertex2i(x + (cControlBoxSize / 2) - cControlSpread, y - cControlInnerMargin);
|
|
glEnd();
|
|
}
|
|
break;
|
|
case 8:
|
|
TextSetColor(G, TextColor);
|
|
TextDrawStrAt(G, "F", x + cControlInnerMargin,
|
|
y - cControlBoxSize + cControlInnerMargin + 1, orthoCGO);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*========================================================================*/
|
|
int ControlInit(PyMOLGlobals * G)
|
|
{
|
|
CControl *I = nullptr;
|
|
if((I = (G->Control = new CControl(G)))) {
|
|
I->active = true;
|
|
I->TextColor[0] = 1.0;
|
|
I->TextColor[1] = 0.75;
|
|
I->TextColor[2] = 0.75;
|
|
OrthoAttach(G, I, cOrthoTool);
|
|
I->LastClickTime = UtilGetSeconds(G);
|
|
return 1;
|
|
} else
|
|
return 0;
|
|
}
|