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