1 
2 /*
3 A* -------------------------------------------------------------------
4 B* This file contains source code for the PyMOL computer program
5 C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific.
6 D* -------------------------------------------------------------------
7 E* It is unlawful to modify or remove this copyright notice.
8 F* -------------------------------------------------------------------
9 G* Please see the accompanying LICENSE file for further information.
10 H* -------------------------------------------------------------------
11 I* Additional authors of this source file include:
12 -*
13 -*
14 -*
15 Z* -------------------------------------------------------------------
16 */
17 #include"os_python.h"
18 #include"os_predef.h"
19 #include"os_std.h"
20 #include"os_gl.h"
21 
22 #include "main.h"
23 #include "Base.h"
24 #include "Control.h"
25 #include "Scene.h"
26 #include "Executive.h"
27 #include "Setting.h"
28 #include "P.h"
29 #include "Seq.h"
30 #include"Movie.h"
31 #include "Text.h"
32 #include "Util.h"
33 #include "Ortho.h"
34 #include "CGO.h"
35 
36 #define cControlBoxSize DIP2PIXEL(17)
37 #define cControlLeftMargin DIP2PIXEL(8)
38 #define cControlTopMargin DIP2PIXEL(2)
39 #define cControlSpacing DIP2PIXEL(2)
40 #define cControlInnerMargin  DIP2PIXEL(4)
41 #define cControlSpread DIP2PIXEL(6)
42 #define cControlSize DIP2PIXEL(160)
43 
44 #define cControlButtons 7
45 
46 #define cControlMinWidth 5
47 
48 #define SDOF_QUEUE_MASK 0x1F
49 
50 
51 struct CControl : public Block {
52   bool DragFlag {};
53   int LastPos {};
54   int ExtraSpace {};
55   float ButtonColor[3] { 0.5f, 0.5f, 0.5f };
56   float ActiveColor[3] { 0.65f, 0.65f, 0.65f };
57   int Pressed { -1 };
58   int Active { -1 };
59   int SaveWidth { 0 };
60   double LastClickTime {};
61   int SkipRelease {};
62   int NButton { 9 };
63 
64   /* not saved */
65 
66   int sdofActive {};
67   double sdofLastIterTime {};
68   int sdofMode {};
69   float sdofTrans[3] {};
70   float sdofRot[3] {};
71   unsigned int sdofWroteTo {}, sdofReadFrom {};       /* queue synchronization fields */
72   float sdofBuffer[(SDOF_QUEUE_MASK + 1) * 6] {};
73 
CControlCControl74   CControl(PyMOLGlobals * G) : Block(G) {};
75 
76   int click(int button, int x, int y, int mod) override;
77   void draw(CGO* ortho) override;
78   int drag(int x, int y, int mod) override;
79   int release(int button, int x, int y, int mod) override;
80   void reshape(int width, int height) override;
81 };
82 
ControlSdofButton(PyMOLGlobals * G,int button)83 int ControlSdofButton(PyMOLGlobals * G, int button)
84 {
85   CControl *I = G->Control;
86   if(I) {
87     if(button == 1) {           /* LEFT */
88       if(I->sdofMode != SDOF_DRAG_MODE) {
89         I->sdofMode = SDOF_DRAG_MODE;
90         OrthoAddOutput(G, " SDOF: Drag mode.\n");
91       } else {
92         I->sdofMode = SDOF_NORMAL_MODE;
93         OrthoAddOutput(G, " SDOF: Normal mode.\n");
94       }
95     } else if(button == 2) {    /* RIGHT */
96       if(I->sdofMode != SDOF_CLIP_MODE) {
97         I->sdofMode = SDOF_CLIP_MODE;
98         OrthoAddOutput(G, " SDOF: Clip mode.\n");
99       } else {
100         I->sdofMode = SDOF_NORMAL_MODE;
101         OrthoAddOutput(G, " SDOF: Normal mode.\n");
102       }
103     }
104     OrthoDirty(G);
105   }
106   return 1;
107 }
108 
ControlSdofUpdate(PyMOLGlobals * G,float tx,float ty,float tz,float rx,float ry,float rz)109 int ControlSdofUpdate(PyMOLGlobals * G, float tx, float ty, float tz, float rx, float ry,
110                       float rz)
111 {
112   /* may be called asynchronously anytime after CControl has been initialized */
113 
114   CControl *I = G->Control;
115   if(I) {
116     float tol = 0.0001;
117     bool active =
118       fabs(tx) >= tol || fabs(ty) >= tol || fabs(tz) >= tol ||
119       fabs(rx) >= tol || fabs(ry) >= tol || fabs(rz) >= tol;
120 
121     if(active) {
122       int slot = (I->sdofWroteTo + 1) & SDOF_QUEUE_MASK;
123       float *buffer = I->sdofBuffer + (6 * slot);
124 
125       buffer[0] = tx;
126       buffer[1] = ty;
127       buffer[2] = tz;
128       buffer[3] = rx;
129       buffer[4] = ry;
130       buffer[5] = rz;
131 
132       I->sdofWroteTo = slot;
133 
134       {
135         if(!I->sdofActive) {
136           I->sdofLastIterTime = UtilGetSeconds(G);
137         }
138       }
139       /*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); */
140     }
141     I->sdofActive = active;
142   }
143   return 1;
144 }
145 
ControlSdofIterate(PyMOLGlobals * G)146 int ControlSdofIterate(PyMOLGlobals * G)
147 {
148   CControl *I = G->Control;
149   if(I->sdofWroteTo != I->sdofReadFrom && I->sdofActive) {
150 
151     int slot = I->sdofWroteTo;
152 
153     /* new data available */
154 
155     float *buffer = I->sdofBuffer + (6 * slot);
156 
157     I->sdofTrans[0] = buffer[0];
158     I->sdofTrans[1] = buffer[1];
159     I->sdofTrans[2] = buffer[2];
160     I->sdofRot[0] = buffer[3];
161     I->sdofRot[1] = buffer[4];
162     I->sdofRot[2] = buffer[5];
163 
164     I->sdofReadFrom = slot;
165 
166     double now = UtilGetSeconds(G);
167     double delta = now - I->sdofLastIterTime;
168     I->sdofLastIterTime = now;
169 
170     {
171       /* suppress small amounts of combined motion using a truncated switching function */
172 
173       float len_rot = length3f(I->sdofRot);
174       float len_trans = length3f(I->sdofTrans);
175       float *dom, *sub;
176       if(len_rot > len_trans) {
177         dom = &len_rot;
178         sub = &len_trans;
179       } else {
180         dom = &len_trans;
181         sub = &len_rot;
182       }
183 
184       {
185         float expo = 2.0F;
186         float trnc = 0.05F;
187         float sub_fxn = (*sub) / (*dom);
188         if(sub_fxn < trnc) {
189           sub_fxn = 0.0F;
190         } else if(sub_fxn < 0.5F) {
191           sub_fxn = (sub_fxn - trnc) / (0.5F - trnc);
192           sub_fxn = (float) pow(sub_fxn, expo);
193         } else {
194           sub_fxn = 1.0F - (float) pow(1.0F - sub_fxn, expo);
195         }
196         *dom = 1.0F;
197         *sub = sub_fxn;
198         scale3f(I->sdofTrans, len_trans, I->sdofTrans);
199         scale3f(I->sdofRot, len_rot, I->sdofRot);
200       }
201     }
202     /* translate */
203     SceneTranslateScaled(G,
204                          delta * I->sdofTrans[0],
205                          -delta * I->sdofTrans[1], -delta * I->sdofTrans[2], I->sdofMode);
206 
207     /* rotate */
208     SceneRotateScaled(G,
209                       2.0F * delta * I->sdofRot[0],
210                       -2.0F * delta * I->sdofRot[1],
211                       -2.0F * delta * I->sdofRot[2], I->sdofMode);
212 
213     SceneDirty(G);
214   }
215   return 1;
216 }
217 
ControlRocking(PyMOLGlobals * G)218 int ControlRocking(PyMOLGlobals * G)
219 {
220   if(G->Interrupt) {
221     SettingSetGlobal_b(G, cSetting_rock, false);
222   }
223   return SettingGetGlobal_b(G, cSetting_rock);
224 }
225 
reshape(int width,int height)226 void CControl::reshape(int width, int height)
227 {
228   PyMOLGlobals *G = m_G;
229   CControl *I = G->Control;
230   Block::reshape(width, height);
231   /* this is a pragmatic workaround for mac X11 where the nub gets
232      hidden by the window expansion tab */
233 
234   if((rect.right - rect.left) < 20) {
235     rect.top = rect.top + 10;
236   }
237 
238   I->ExtraSpace = ((rect.right - rect.left) - cControlSize);
239   if(I->ExtraSpace < 0)
240     I->ExtraSpace = 0;
241 }
242 
which_button(CControl * I,int x,int y)243 static int which_button(CControl * I, int x, int y)
244 {
245   int result = -1;
246   x -= I->rect.left + cControlLeftMargin;
247   y -= I->rect.top - cControlTopMargin;
248   if(x >= 0)
249     if((y <= 0) && (y > (-cControlBoxSize))) {
250       int control_width =
251         I->rect.right - (I->rect.left + cControlLeftMargin);
252       result = (I->NButton * x) / control_width;
253     }
254   return result;
255 }
256 
drag(int x,int y,int mod)257 int CControl::drag(int x, int y, int mod)
258 {
259   int delta;
260   int gui_width;
261   PyMOLGlobals *G = m_G;
262   CControl *I = G->Control;
263   if(!I->SkipRelease) {
264     delta = x - I->LastPos;
265     delta /= DIP2PIXEL(1);
266     if(I->DragFlag) {
267       if(delta) {
268         gui_width = SettingGetGlobal_i(G, cSetting_internal_gui_width) - delta;
269         if(gui_width < cControlMinWidth)
270           gui_width = cControlMinWidth;
271         delta = SettingGetGlobal_i(G, cSetting_internal_gui_width) - gui_width;
272         I->LastPos = x;
273         I->SaveWidth = 0;
274         SettingSetGlobal_i(G, cSetting_internal_gui_width, gui_width);
275         OrthoReshape(G, -1, -1, false);
276       }
277     } else {
278       I->Active = which_button(I, x, y);
279       if(I->Active != I->Pressed)
280         I->Active = -1;
281       OrthoInvalidateDoDraw(G);
282       OrthoDirty(G);
283     }
284   }
285   return (1);
286 }
287 
release(int button,int x,int y,int mod)288 int CControl::release(int button, int x, int y, int mod)
289 {
290   PyMOLGlobals *G = m_G;
291   CControl *I = G->Control;
292 
293   int sel = 0;
294 
295   I->LastPos = x;
296   sel = which_button(I, x, y);
297   if(!I->SkipRelease) {
298     switch (sel) {
299     case 0:
300       SceneSetFrame(G, 4, 0);
301       PLog(G, "cmd.rewind()", cPLog_pym);
302       break;
303     case 1:
304       SceneSetFrame(G, 5, -1);
305       PLog(G, "cmd.back()", cPLog_pym);
306       break;
307     case 2:
308       MoviePlay(G, cMovieStop);
309       if(SettingGetGlobal_b(G, cSetting_sculpting))
310         SettingSetGlobal_b(G, cSetting_sculpting, 0);
311       if(SettingGetGlobal_b(G, cSetting_rock))
312         SettingSetGlobal_b(G, cSetting_rock, false);
313       OrthoDirty(G);
314       PLog(G, "cmd.mstop()", cPLog_pym);
315       break;
316     case 3:
317       if(!MoviePlaying(G)) {
318         if(mod & cOrthoCTRL) {
319           PLog(G, "cmd.rewind()", cPLog_pym);
320           PLog(G, "cmd.mplay()", cPLog_pym);
321           SceneSetFrame(G, 4, 0);
322           MoviePlay(G, cMoviePlay);
323         } else {
324           PLog(G, "cmd.mplay()", cPLog_pym);
325           MoviePlay(G, cMoviePlay);
326         }
327       } else {
328         MoviePlay(G, cMovieStop);
329         OrthoDirty(G);
330         PLog(G, "cmd.mstop()", cPLog_pym);
331       }
332       break;
333     case 4:
334       SceneSetFrame(G, 5, 1);
335       PLog(G, "cmd.forward()", cPLog_pym);
336       break;
337     case 5:
338       if(mod & cOrthoCTRL) {
339         SceneSetFrame(G, 3, 0);
340         PLog(G, "cmd.middle()", cPLog_pym);
341       } else {
342         SceneSetFrame(G, 6, 0);
343         PLog(G, "cmd.ending()", cPLog_pym);
344       }
345       break;
346     case 6:
347       if(SettingGetGlobal_b(G, cSetting_seq_view)) {
348         SettingSetGlobal_b(G, cSetting_seq_view, 0);
349         SeqChanged(G);
350         PLog(G, "cmd.set('seq_view',0)", cPLog_pym);
351       } else {
352         SettingSetGlobal_b(G, cSetting_seq_view, 1);
353         SeqChanged(G);
354         PLog(G, "cmd.set('seq_view',1)", cPLog_pym);
355       }
356       OrthoDirty(G);
357       break;
358     case 7:
359       SettingSetGlobal_b(G, cSetting_rock, !SettingGetGlobal_b(G, cSetting_rock));
360       if(SettingGetGlobal_b(G, cSetting_rock)) {
361         SceneRestartSweepTimer(G);
362         PLog(G, "cmd.rock(1)", cPLog_pym);
363       } else
364         PLog(G, "cmd.rock(0)", cPLog_pym);
365       SceneRestartFrameTimer(G);
366       OrthoDirty(G);
367       break;
368     case 8:
369       PLog(G, "cmd.full_screen()", cPLog_pym);
370 #ifdef _PYMOL_NOPY
371       ExecutiveFullScreen(G, -1);
372 #else
373       PParse(G, "full_screen");
374 #endif
375       break;
376     }
377     OrthoDirty(G);
378     OrthoUngrab(G);
379     I->LastClickTime = UtilGetSeconds(G);
380     I->DragFlag = false;
381     I->Active = -1;
382     I->Pressed = -1;
383   }
384   return (1);
385 }
386 
ControlGetBlock(PyMOLGlobals * G)387 Block *ControlGetBlock(PyMOLGlobals * G)
388 {
389   CControl *I = G->Control;
390   {
391     return (I);
392   }
393 }
394 
395 
396 /*========================================================================*/
ControlIdling(PyMOLGlobals * G)397 int ControlIdling(PyMOLGlobals * G)
398 {
399   CControl *I = G->Control;
400   return (I->sdofActive ||
401           MoviePlaying(G) ||
402           SettingGetGlobal_b(G, cSetting_rock) || SettingGetGlobal_b(G, cSetting_sculpting));
403 }
404 
405 
406 /*========================================================================*/
ControlFree(PyMOLGlobals * G)407 void ControlFree(PyMOLGlobals * G)
408 {
409 
410   DeleteP(G->Control);
411 }
412 
413 
414 /*========================================================================*/
ControlRock(PyMOLGlobals * G,int mode)415 pymol::Result<bool> ControlRock(PyMOLGlobals * G, int mode)
416 {
417   switch (mode) {
418   case -2:
419     break;
420   case -1:
421     SettingSetGlobal_b(G, cSetting_rock, !SettingGetGlobal_b(G, cSetting_rock));
422     if(SettingGetGlobal_b(G, cSetting_rock)) {
423       SceneRestartSweepTimer(G);
424     }
425     break;
426   case 0:
427     SettingSetGlobal_b(G, cSetting_rock, false);
428     break;
429   case 1:
430     SettingSetGlobal_b(G, cSetting_rock, true);
431     SceneRestartSweepTimer(G);
432     break;
433   }
434   if(mode != -2) {
435     SceneRestartFrameTimer(G);
436     OrthoDirty(G);
437   }
438   return SettingGetGlobal_b(G, cSetting_rock);
439 }
440 
441 
442 /*========================================================================*/
click(int button,int x,int y,int mod)443 int CControl::click(int button, int x, int y, int mod)
444 {
445   PyMOLGlobals *G = m_G;
446   CControl *I = G->Control;
447   I->SkipRelease = false;
448   if(x < (I->rect.left + cControlLeftMargin)) {
449     y -= I->rect.top - cControlTopMargin;
450     if((y <= 0) && (y > (-cControlBoxSize))) {
451       double now = UtilGetSeconds(m_G);
452       if((now - I->LastClickTime) < 0.35) {
453         if(I->SaveWidth) {
454           SettingSetGlobal_i(G, cSetting_internal_gui_width, I->SaveWidth);
455           OrthoReshape(G, -1, -1, false);
456           I->SaveWidth = 0;
457         } else {
458           I->SaveWidth = SettingGetGlobal_i(G, cSetting_internal_gui_width);
459           SettingSetGlobal_i(G, cSetting_internal_gui_width, cControlMinWidth);
460           OrthoReshape(G, -1, -1, false);
461         }
462         I->SkipRelease = true;
463       } else {
464         I->LastPos = x;
465         OrthoGrab(G, this);
466         I->DragFlag = true;
467         I->LastClickTime = UtilGetSeconds(G);
468       }
469     }
470   } else {
471     I->Pressed = which_button(I, x, y);
472     I->Active = I->Pressed;
473     if(I->Pressed)
474       OrthoGrab(G, this);
475     OrthoDirty(G);
476   }
477   return (1);
478 }
479 
draw_button(int x2,int y2,int w,int h,float * light,float * dark,float * inside ORTHOCGOARG)480 static void draw_button(int x2, int y2, int w, int h, float *light, float *dark,
481                         float *inside ORTHOCGOARG)
482 {
483   if (orthoCGO){
484     CGOColorv(orthoCGO, light);
485     CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
486     CGOVertex(orthoCGO, x2, y2, 0.f);
487     CGOVertex(orthoCGO, x2, y2 + h, 0.f);
488     CGOVertex(orthoCGO, x2 + w, y2, 0.f);
489     CGOVertex(orthoCGO, x2 + w, y2 + h, 0.f);
490     CGOEnd(orthoCGO);
491 
492     CGOColorv(orthoCGO, dark);
493     CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
494     CGOVertex(orthoCGO, x2 + 1, y2, 0.f);
495     CGOVertex(orthoCGO, x2 + 1, y2 + h - 1, 0.f);
496     CGOVertex(orthoCGO, x2 + w, y2, 0.f);
497     CGOVertex(orthoCGO, x2 + w, y2 + h - 1, 0.f);
498     CGOEnd(orthoCGO);
499 
500     CGOColorv(orthoCGO, inside);
501     CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
502     CGOVertex(orthoCGO, x2 + 1, y2 + 1, 0.f);
503     CGOVertex(orthoCGO, x2 + 1, y2 + h - 1, 0.f);
504     CGOVertex(orthoCGO, x2 + w - 1, y2 + 1, 0.f);
505     CGOVertex(orthoCGO, x2 + w - 1, y2 + h - 1, 0.f);
506     CGOEnd(orthoCGO);
507   } else {
508     glColor3fv(light);
509     glBegin(GL_POLYGON);
510     glVertex2i(x2, y2);
511     glVertex2i(x2, y2 + h);
512     glVertex2i(x2 + w, y2 + h);
513     glVertex2i(x2 + w, y2);
514     glEnd();
515 
516     glColor3fv(dark);
517     glBegin(GL_POLYGON);
518     glVertex2i(x2 + 1, y2);
519     glVertex2i(x2 + 1, y2 + h - 1);
520     glVertex2i(x2 + w, y2 + h - 1);
521     glVertex2i(x2 + w, y2);
522     glEnd();
523 
524     glColor3fv(inside);
525     glBegin(GL_POLYGON);
526     glVertex2i(x2 + 1, y2 + 1);
527     glVertex2i(x2 + 1, y2 + h - 1);
528     glVertex2i(x2 + w - 1, y2 + h - 1);
529     glVertex2i(x2 + w - 1, y2 + 1);
530     glEnd();
531   }
532 }
533 
534 
535 /*========================================================================*/
draw(CGO * orthoCGO)536 void CControl::draw(CGO* orthoCGO)
537 {
538   PyMOLGlobals *G = m_G;
539   CControl *I = this; // TODO: Remove I during Control refactor
540   int x, y;
541   int nButton = I->NButton;
542   int but_num;
543   float lightEdge[3] = { 0.65F, 0.65F, 0.65F };
544   float darkEdge[3] = { 0.3F, 0.3F, 0.3F };
545   float pushed[3] = { 0.8F, 0.8F, 0.8F };
546 
547   if(G->HaveGUI && G->ValidContext) {
548 
549     int control_width = rect.right - (rect.left + cControlLeftMargin);
550 
551     if (orthoCGO)
552       CGOColorv(orthoCGO, BackColor);
553 #ifndef PURE_OPENGL_ES_2
554     else
555       glColor3fv(BackColor);
556 #endif
557     fill(orthoCGO);
558     if (orthoCGO)
559       CGOColorv(orthoCGO, TextColor);
560 #ifndef PURE_OPENGL_ES_2
561     else
562       glColor3fv(TextColor);
563 #endif
564     {
565       int top, left, bottom, right;
566 
567       left = rect.left + 1;
568       bottom = rect.bottom + 1;
569       top = rect.top - (cControlTopMargin - 1);
570       right = left + DIP2PIXEL(5);
571 
572       /* This draws the separator on the left side of the movie control buttons */
573       if (orthoCGO){
574 	CGOColor(orthoCGO, 0.8F, 0.8F, 0.8F);
575 	CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
576 	CGOVertex(orthoCGO, right, top, 0.f);
577 	CGOVertex(orthoCGO, right, bottom, 0.f);
578 	CGOVertex(orthoCGO, left, top, 0.f);
579 	CGOVertex(orthoCGO, left, bottom, 0.f);
580 	CGOEnd(orthoCGO);
581 
582 	CGOColor(orthoCGO, 0.3F, 0.3F, 0.3F);
583 	CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
584 	CGOVertex(orthoCGO, right, top - 1, 0.f);
585 	CGOVertex(orthoCGO, right, bottom, 0.f);
586 	CGOVertex(orthoCGO, left + 1, top - 1, 0.f);
587 	CGOVertex(orthoCGO, left + 1, bottom, 0.f);
588 	CGOEnd(orthoCGO);
589 
590 	CGOColorv(orthoCGO, I->ButtonColor);
591 
592 	CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
593 	CGOVertex(orthoCGO, right - 1, top - 1, 0.f);
594 	CGOVertex(orthoCGO, right - 1, bottom + 1, 0.f);
595 	CGOVertex(orthoCGO, left + 1, top - 1, 0.f);
596 	CGOVertex(orthoCGO, left + 1, bottom + 1, 0.f);
597 	CGOEnd(orthoCGO);
598       } else {
599 	glColor3f(0.8F, 0.8F, 0.8F);
600 	glBegin(GL_POLYGON);
601 	glVertex2i(right, top);
602 	glVertex2i(right, bottom);
603 	glVertex2i(left, bottom);
604 	glVertex2i(left, top);
605 	glEnd();
606 
607 	glColor3f(0.3F, 0.3F, 0.3F);
608 	glBegin(GL_POLYGON);
609 	glVertex2i(right, top - 1);
610 	glVertex2i(right, bottom);
611 	glVertex2i(left + 1, bottom);
612 	glVertex2i(left + 1, top - 1);
613 	glEnd();
614 
615 	glColor3fv(I->ButtonColor);
616 
617 	glBegin(GL_POLYGON);
618 	glVertex2i(right - 1, top - 1);
619 	glVertex2i(right - 1, bottom + 1);
620 	glVertex2i(left + 1, bottom + 1);
621 	glVertex2i(left + 1, top - 1);
622 	glEnd();
623       }
624 
625     y = rect.top - cControlTopMargin;
626 
627     for(but_num = 0; but_num < nButton; but_num++) {
628       int but_width;
629       int but_left;
630       int but_bottom;
631       int but_height;
632 
633       but_left =
634         rect.left + cControlLeftMargin + (but_num * control_width) / nButton;
635       but_width =
636         (((but_num + 1) * control_width / nButton) -
637          ((but_num) * control_width / nButton)) - 1;
638 
639       but_bottom = y - (cControlBoxSize - 1);
640       but_height = cControlBoxSize;
641 
642       if(but_num == I->Active) {
643         draw_button(but_left, but_bottom,
644                     but_width, but_height, lightEdge, darkEdge, pushed ORTHOCGOARGVAR);
645       } else if(((but_num == 6) && (SettingGetGlobal_b(G, cSetting_seq_view))) ||
646                 ((but_num == 3) && (MoviePlaying(G))) ||
647                 ((but_num == 7) && (SettingGetGlobal_b(G, cSetting_rock)))){
648         draw_button(but_left, but_bottom,
649                     but_width, but_height, lightEdge, darkEdge, I->ActiveColor ORTHOCGOARGVAR);
650       } else {
651         draw_button(but_left, but_bottom,
652                     but_width, but_height, lightEdge, darkEdge, I->ButtonColor ORTHOCGOARGVAR);
653       }
654 
655       if(control_width > 100) {
656         x = but_left + (but_width - cControlBoxSize) / 2;
657 
658 	if (orthoCGO)
659 	  CGOColorv(orthoCGO, TextColor);
660 #ifndef PURE_OPENGL_ES_2
661 	else
662 	  glColor3fv(TextColor);
663 #endif
664         switch (but_num) {
665         case 0:
666 	  if (orthoCGO){
667 	    CGOBegin(orthoCGO, GL_TRIANGLES);
668 	    CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
669 		      y - cControlInnerMargin, 0.f);
670 	    CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
671 		       y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
672 	    CGOVertex(orthoCGO, x + cControlInnerMargin, y - (cControlBoxSize / 2), 0.f);
673 	    CGOEnd(orthoCGO);
674 
675 
676 	    CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
677 	    CGOVertex(orthoCGO, x + cControlInnerMargin, y - cControlInnerMargin, 0.f);
678 	    CGOVertex(orthoCGO, x + cControlInnerMargin-1.f, y - cControlInnerMargin, 0.f);
679 	    CGOVertex(orthoCGO, x + cControlInnerMargin, y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
680 	    CGOVertex(orthoCGO, x + cControlInnerMargin-1.f, y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
681 	    CGOEnd(orthoCGO);
682 	  } else {
683 	    glBegin(GL_TRIANGLES);
684 	    glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
685 		       y - cControlInnerMargin);
686 	    glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
687 		       y - (cControlBoxSize - 1) + cControlInnerMargin);
688 	    glVertex2i(x + cControlInnerMargin, y - (cControlBoxSize / 2));
689 	    glEnd();
690 	    glBegin(GL_LINES);
691 	    glVertex2i(x + cControlInnerMargin, y - cControlInnerMargin);
692 	    glVertex2i(x + cControlInnerMargin,
693 		       y - (cControlBoxSize - 1) + cControlInnerMargin);
694 	    glEnd();
695 	  }
696           break;
697         case 1:
698 	  if (orthoCGO){
699 	    CGOBegin(orthoCGO, GL_TRIANGLES);
700 	    CGOVertex(orthoCGO, x + cControlBoxSize / 2 + 2, y - (cControlBoxSize / 2), 0.f);
701 	    CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
702 		      y - cControlInnerMargin, 0.f);
703 	    CGOVertex(orthoCGO, x + cControlInnerMargin, y - (cControlBoxSize / 2), 0.f);
704 	    CGOVertex(orthoCGO, x + cControlInnerMargin, y - (cControlBoxSize / 2), 0.f);
705 	    CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
706 		      y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
707 	    CGOVertex(orthoCGO, x + cControlBoxSize / 2 + 2, y - (cControlBoxSize / 2), 0.f);
708 	    CGOEnd(orthoCGO);
709 	  } else {
710 	    glBegin(GL_POLYGON);
711 	    glVertex2i(x + cControlBoxSize / 2 + 2, y - (cControlBoxSize / 2));
712 	    glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
713 		       y - cControlInnerMargin);
714 	    glVertex2i(x + cControlInnerMargin, y - (cControlBoxSize / 2));
715 	    glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
716 		       y - (cControlBoxSize - 1) + cControlInnerMargin);
717 	    glEnd();
718 	  }
719           break;
720         case 2:
721 	  if (orthoCGO){
722 	    CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
723 	    CGOVertex(orthoCGO, x + cControlInnerMargin, y - cControlInnerMargin, 0.f);
724 	    CGOVertex(orthoCGO, x + cControlInnerMargin,
725 		       y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
726 	    CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
727 		       y - cControlInnerMargin, 0.f);
728 	    CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
729 		       y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
730 	    CGOEnd(orthoCGO);
731 	  } else {
732 	    glBegin(GL_POLYGON);
733 	    glVertex2i(x + cControlInnerMargin, y - cControlInnerMargin);
734 	    glVertex2i(x + cControlInnerMargin,
735 		       y - (cControlBoxSize - 1) + cControlInnerMargin);
736 	    glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
737 		       y - (cControlBoxSize - 1) + cControlInnerMargin);
738 	    glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
739 		       y - cControlInnerMargin);
740 	    glEnd();
741 	  }
742           break;
743         case 3:
744 	  if (orthoCGO){
745 	    CGOBegin(orthoCGO, GL_TRIANGLES);
746 	    CGOVertex(orthoCGO, x + cControlInnerMargin, y - cControlInnerMargin + 1, 0.f);
747 	    CGOVertex(orthoCGO, x + cControlInnerMargin,
748 		      y - (cControlBoxSize - 1) + cControlInnerMargin - 1, 0.f);
749 	    CGOVertex(orthoCGO, x + (cControlBoxSize) - cControlInnerMargin,
750 		      y - (cControlBoxSize / 2), 0.f);
751 	    CGOEnd(orthoCGO);
752 	  } else {
753 	    glBegin(GL_TRIANGLES);
754 	    glVertex2i(x + cControlInnerMargin, y - cControlInnerMargin + 1);
755 	    glVertex2i(x + cControlInnerMargin,
756 		       y - (cControlBoxSize - 1) + cControlInnerMargin - 1);
757 	    glVertex2i(x + (cControlBoxSize) - cControlInnerMargin,
758 		       y - (cControlBoxSize / 2));
759 	    glEnd();
760 	  }
761           break;
762         case 4:
763 	  if (orthoCGO){
764 	    CGOBegin(orthoCGO, GL_TRIANGLES);
765 	    CGOVertex(orthoCGO, x + cControlBoxSize / 2 - 2, y - (cControlBoxSize / 2), 0.f);
766 	    CGOVertex(orthoCGO, x + cControlInnerMargin, y - cControlInnerMargin, 0.f);
767 	    CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
768 		       y - (cControlBoxSize / 2), 0.f);
769 	    CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
770 		       y - (cControlBoxSize / 2), 0.f);
771 	    CGOVertex(orthoCGO, x + cControlInnerMargin,
772 		       y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
773 	    CGOVertex(orthoCGO, x + cControlBoxSize / 2 - 2, y - (cControlBoxSize / 2), 0.f);
774 	    CGOEnd(orthoCGO);
775 	  } else {
776 	    glBegin(GL_POLYGON);
777 	    glVertex2i(x + cControlBoxSize / 2 - 2, y - (cControlBoxSize / 2));
778 	    glVertex2i(x + cControlInnerMargin, y - cControlInnerMargin);
779 	    glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
780 		       y - (cControlBoxSize / 2));
781 	    glVertex2i(x + cControlInnerMargin,
782 		       y - (cControlBoxSize - 1) + cControlInnerMargin);
783 	    glEnd();
784 	  }
785           break;
786         case 5:
787 	  if (orthoCGO){
788 	    CGOBegin(orthoCGO, GL_TRIANGLES);
789 	    CGOVertex(orthoCGO, x + cControlInnerMargin, y - cControlInnerMargin, 0.f);
790 	    CGOVertex(orthoCGO, x + cControlInnerMargin,
791 		      y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
792 	    CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin,
793 		      y - (cControlBoxSize / 2), 0.f);
794 	    CGOEnd(orthoCGO);
795 
796 	    CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
797 	    CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin, y - cControlInnerMargin, 0.f);
798 	    CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin - 1.f, y - cControlInnerMargin, 0.f);
799 	    CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin, y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
800 	    CGOVertex(orthoCGO, x + (cControlBoxSize - 1) - cControlInnerMargin - 1.f, y - (cControlBoxSize - 1) + cControlInnerMargin, 0.f);
801 	    CGOEnd(orthoCGO);
802 	  } else {
803 	    glBegin(GL_TRIANGLES);
804 	    glVertex2i(x + cControlInnerMargin, y - cControlInnerMargin);
805 	    glVertex2i(x + cControlInnerMargin,
806 		       y - (cControlBoxSize - 1) + cControlInnerMargin);
807 	    glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
808 		       y - (cControlBoxSize / 2));
809 	    glEnd();
810 	    glBegin(GL_LINES);
811 	    glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
812 		       y - cControlInnerMargin);
813 	    glVertex2i(x + (cControlBoxSize - 1) - cControlInnerMargin,
814 		       y - (cControlBoxSize - 1) + cControlInnerMargin);
815 	    glEnd();
816 	  }
817           break;
818         case 6:
819 	  TextSetColor(G, TextColor);
820           TextDrawStrAt(G, "S", x + cControlInnerMargin,
821                         y - cControlBoxSize + cControlInnerMargin + 1 ORTHOCGOARGVAR);
822           break;
823         case 7:
824 	  if (orthoCGO){
825 	    CGOBegin(orthoCGO, GL_TRIANGLES);
826 	    CGOVertex(orthoCGO, x + (cControlBoxSize / 2) + cControlSpread, y - cControlInnerMargin, 0.f);
827 	    CGOVertex(orthoCGO, x + (cControlBoxSize / 2),
828 		      y - (cControlBoxSize) + cControlInnerMargin, 0.f);
829 	    CGOVertex(orthoCGO, x + (cControlBoxSize / 2) - cControlSpread, y - cControlInnerMargin, 0.f);
830 	    CGOEnd(orthoCGO);
831 	  } else {
832 	    glBegin(GL_POLYGON);
833 	    glVertex2i(x + (cControlBoxSize / 2) + cControlSpread, y - cControlInnerMargin);
834 	    glVertex2i(x + (cControlBoxSize / 2),
835 		       y - (cControlBoxSize) + cControlInnerMargin);
836 	    glVertex2i(x + (cControlBoxSize / 2) - cControlSpread, y - cControlInnerMargin);
837 	    glEnd();
838 	  }
839           break;
840         case 8:
841 	  TextSetColor(G, TextColor);
842           TextDrawStrAt(G, "F", x + cControlInnerMargin,
843                         y - cControlBoxSize + cControlInnerMargin + 1 ORTHOCGOARGVAR);
844           break;
845         }
846       }
847     }
848     }
849   }
850 }
851 
852 
853 /*========================================================================*/
ControlInit(PyMOLGlobals * G)854 int ControlInit(PyMOLGlobals * G)
855 {
856   CControl *I = NULL;
857   if((I = (G->Control = new CControl(G)))) {
858     I->active = true;
859     I->TextColor[0] = 1.0;
860     I->TextColor[1] = 0.75;
861     I->TextColor[2] = 0.75;
862     OrthoAttach(G, I, cOrthoTool);
863     I->LastClickTime = UtilGetSeconds(G);
864     return 1;
865   } else
866     return 0;
867 }
868