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 
19 #include"os_predef.h"
20 #include"os_std.h"
21 #include"os_gl.h"
22 
23 #include"OOMac.h"
24 #include"ObjectGadget.h"
25 #include"ObjectGadgetRamp.h"
26 #include"GadgetSet.h"
27 #include"Base.h"
28 #include"MemoryDebug.h"
29 #include"CGO.h"
30 #include"Scene.h"
31 #include"Setting.h"
32 #include"PConv.h"
33 #include"main.h"
34 #include"Color.h"
35 #include"VFont.h"
36 
37 CGO *ObjectGadgetPyListFloatToCGO(PyObject * list);
38 
ObjectGadgetGetVertex(ObjectGadget * I,int index,int base,float * v)39 int ObjectGadgetGetVertex(ObjectGadget * I, int index, int base, float *v)
40 {
41   GadgetSet *gs;
42   int ok = false;
43   if(I->CurGSet < I->NGSet) {
44     gs = I->GSet[I->CurGSet];
45     if(gs) {
46       ok = GadgetSetGetVertex(gs, index, base, v);
47     }
48   }
49   return (ok);
50 }
51 
ObjectGadgetSetVertex(ObjectGadget * I,int index,int base,float * v)52 int ObjectGadgetSetVertex(ObjectGadget * I, int index, int base, float *v)
53 {
54   GadgetSet *gs;
55   int ok = false;
56   if(I->CurGSet < I->NGSet) {
57     gs = I->GSet[I->CurGSet];
58     if(gs) {
59       ok = GadgetSetSetVertex(gs, index, base, v);
60     }
61   }
62   if (index) // if 0 - xyz doesn't change, 1 - mouse position when changing colors
63     I->Changed = true;
64   return (ok);
65 }
66 
67 
68 /* in current state */
ObjectGadgetTest(PyMOLGlobals * G)69 ObjectGadget *ObjectGadgetTest(PyMOLGlobals * G)
70 {
71   ObjectGadget *I = NULL;
72   GadgetSet *gs = NULL;
73   CGO *cgo = NULL;
74   int a;
75 
76   float coord[] = {
77     0.5F, 0.5F, 0.0F,
78     0.0F, 0.0F, 0.0F,
79     0.3F, 0.0F, 0.0F,
80     0.0F, -0.3F, 0.0F,
81     0.3F, -0.3F, 0.0F,
82     0.03F, -0.03F, 0.03F,
83     0.27F, -0.03F, 0.03F,
84     0.03F, -0.27F, 0.03F,
85     0.27F, -0.27F, 0.03F,
86     0.02F, -0.02F, 0.01F,
87     0.28F, -0.02F, 0.01F,
88     0.02F, -0.28F, 0.01F,
89     0.28F, -0.28F, 0.01F,
90   };
91 
92   float normal[] = {
93     1.0, 0.0, 0.0,
94     0.0, 1.0, 0.0,
95     0.0, 0.0, 1.0,
96     -1.0, 0.0, 0.0,
97     0.0, -1.0, 0.0,
98   };
99 
100   I = new ObjectGadget(G);
101   gs = GadgetSetNew(G);
102 
103   gs->NCoord = 13;
104   gs->Coord = VLAlloc(float, gs->NCoord * 3);
105   for(a = 0; a < gs->NCoord * 3; a++) {
106     gs->Coord[a] = coord[a];
107   }
108 
109   gs->NNormal = 5;
110   gs->Normal = VLAlloc(float, gs->NNormal * 3);
111   for(a = 0; a < gs->NNormal * 3; a++) {
112     gs->Normal[a] = normal[a];
113   }
114 
115   cgo = CGONewSized(G, 100);
116   CGOColor(cgo, 1.0, 1.0, 1.0);
117 
118   /* top */
119   CGOBegin(cgo, GL_TRIANGLE_STRIP);
120   CGONormal(cgo, 2.0, 2.0, 0.0);
121   CGOVertex(cgo, 1.0, 5.0, 0.0);
122   CGOVertex(cgo, 1.0, 6.0, 0.0);
123 
124   CGONormal(cgo, 2.0, 1.0, 0.0);
125   CGOVertex(cgo, 1.0, 1.0, 0.0);
126   CGOVertex(cgo, 1.0, 2.0, 0.0);
127   CGOEnd(cgo);
128 
129   /* bottom */
130   CGOBegin(cgo, GL_TRIANGLE_STRIP);
131   CGONormal(cgo, 2.0, 4.0, 0.0);
132   CGOVertex(cgo, 1.0, 3.0, 0.0);
133   CGOVertex(cgo, 1.0, 4.0, 0.0);
134 
135   CGONormal(cgo, 2.0, 2.0, 0.0);
136   CGOVertex(cgo, 1.0, 7.0, 0.0);
137   CGOVertex(cgo, 1.0, 8.0, 0.0);
138   CGOEnd(cgo);
139 
140   /* left */
141   CGOBegin(cgo, GL_TRIANGLE_STRIP);
142   CGONormal(cgo, 2.0, 3.0, 0.0);
143   CGOVertex(cgo, 1.0, 1.0, 0.0);
144   CGOVertex(cgo, 1.0, 3.0, 0.0);
145 
146   CGONormal(cgo, 2.0, 2.0, 0.0);
147   CGOVertex(cgo, 1.0, 5.0, 0.0);
148   CGOVertex(cgo, 1.0, 7.0, 0.0);
149   CGOEnd(cgo);
150 
151   /* right */
152   CGOBegin(cgo, GL_TRIANGLE_STRIP);
153   CGONormal(cgo, 2.0, 2.0, 0.0);
154   CGOVertex(cgo, 1.0, 6.0, 0.0);
155   CGOVertex(cgo, 1.0, 8.0, 0.0);
156 
157   CGONormal(cgo, 2.0, 0.0, 0.0);
158   CGOVertex(cgo, 1.0, 2.0, 0.0);
159   CGOVertex(cgo, 1.0, 4.0, 0.0);
160   CGOEnd(cgo);
161 
162   CGOColor(cgo, 1.0, 0.0, 0.0);
163 
164   /* center */
165   CGOBegin(cgo, GL_TRIANGLE_STRIP);
166   CGONormal(cgo, 2.0, 2.0, 0.0);
167   CGOVertex(cgo, 1.0, 5.0, 0.0);
168   CGOVertex(cgo, 1.0, 7.0, 0.0);
169   CGOVertex(cgo, 1.0, 6.0, 0.0);
170   CGOVertex(cgo, 1.0, 8.0, 0.0);
171   CGOEnd(cgo);
172 
173   CGOColor(cgo, 0.0, 1.0, 0.0);
174   /* backr */
175   CGOBegin(cgo, GL_TRIANGLE_STRIP);
176   CGONormal(cgo, 2.0, 2.0, 0.0);
177   CGOVertex(cgo, 1.0, 9.0, 0.0);
178   CGOVertex(cgo, 1.0, 10.0, 0.0);
179   CGOVertex(cgo, 1.0, 11.0, 0.0);
180   CGOVertex(cgo, 1.0, 12.0, 0.0);
181   CGOEnd(cgo);
182   CGOStop(cgo);
183 
184   gs->ShapeCGO = cgo;
185 
186   cgo = CGONewSized(G, 100);
187   CGODotwidth(cgo, 5);
188 
189   CGOPickColor(cgo, 0, cPickableGadget);
190 
191   /* top */
192   CGOBegin(cgo, GL_TRIANGLE_STRIP);
193   CGOVertex(cgo, 1.0, 1.0, 0.0);
194   CGOVertex(cgo, 1.0, 2.0, 0.0);
195   CGOVertex(cgo, 1.0, 5.0, 0.0);
196   CGOVertex(cgo, 1.0, 6.0, 0.0);
197   CGOEnd(cgo);
198 
199   /* bottom */
200   CGOBegin(cgo, GL_TRIANGLE_STRIP);
201   CGOVertex(cgo, 1.0, 3.0, 0.0);
202   CGOVertex(cgo, 1.0, 4.0, 0.0);
203   CGOVertex(cgo, 1.0, 7.0, 0.0);
204   CGOVertex(cgo, 1.0, 8.0, 0.0);
205   CGOEnd(cgo);
206 
207   /* left */
208   CGOBegin(cgo, GL_TRIANGLE_STRIP);
209   CGOVertex(cgo, 1.0, 1.0, 0.0);
210   CGOVertex(cgo, 1.0, 3.0, 0.0);
211   CGOVertex(cgo, 1.0, 5.0, 0.0);
212   CGOVertex(cgo, 1.0, 7.0, 0.0);
213   CGOEnd(cgo);
214 
215   /* right */
216   CGOBegin(cgo, GL_TRIANGLE_STRIP);
217   CGOVertex(cgo, 1.0, 6.0, 0.0);
218   CGOVertex(cgo, 1.0, 8.0, 0.0);
219   CGOVertex(cgo, 1.0, 2.0, 0.0);
220   CGOVertex(cgo, 1.0, 4.0, 0.0);
221   CGOEnd(cgo);
222   CGOEnd(cgo);
223   CGOStop(cgo);
224   gs->PickShapeCGO = cgo;
225 
226   gs->Obj = I;
227   gs->State = 0;
228 
229   I->GSet[0] = gs;
230   I->NGSet = 1;
231   I->Context = 1;
232   gs->update();
233   ObjectGadgetUpdateExtents(I);
234   return (I);
235 
236 }
237 
ObjectGadgetUpdateExtents(ObjectGadget * I)238 void ObjectGadgetUpdateExtents(ObjectGadget * I)
239 {
240   float maxv[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
241   float minv[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
242   int a;
243   GadgetSet *ds;
244 
245   /* update extents */
246   copy3f(maxv, I->ExtentMin);
247   copy3f(minv, I->ExtentMax);
248   I->ExtentFlag = false;
249   for(a = 0; a < I->NGSet; a++) {
250     ds = I->GSet[a];
251     if(ds) {
252       if(GadgetSetGetExtent(ds, I->ExtentMin, I->ExtentMax))
253         I->ExtentFlag = true;
254     }
255   }
256 }
257 
ObjectGadgetGSetAsPyList(ObjectGadget * I,bool incl_cgos)258 static PyObject *ObjectGadgetGSetAsPyList(ObjectGadget * I, bool incl_cgos)
259 {
260   PyObject *result = NULL;
261   int a;
262   result = PyList_New(I->NGSet);
263   for(a = 0; a < I->NGSet; a++) {
264     if(I->GSet[a]) {
265       PyList_SetItem(result, a, GadgetSetAsPyList(I->GSet[a], incl_cgos));
266     } else {
267       PyList_SetItem(result, a, PConvAutoNone(Py_None));
268     }
269   }
270   return (PConvAutoNone(result));
271 
272 }
273 
ObjectGadgetGSetFromPyList(ObjectGadget * I,PyObject * list,int version)274 static int ObjectGadgetGSetFromPyList(ObjectGadget * I, PyObject * list, int version)
275 {
276 
277   int ok = true;
278   int a;
279   if(ok)
280     ok = PyList_Check(list);
281   if(ok) {
282     VLACheck(I->GSet, GadgetSet *, I->NGSet);
283     for(a = 0; a < I->NGSet; a++) {
284       if(ok){
285         auto *val = PyList_GetItem(list, a);
286         ok = GadgetSetFromPyList(I->G, val, &I->GSet[a], version);
287       }
288       if(ok && I->GSet[a]) {
289         I->GSet[a]->Obj = I;
290         I->GSet[a]->State = a;
291       }
292     }
293   }
294   return (ok);
295 }
296 
ObjectGadgetInitFromPyList(PyMOLGlobals * G,PyObject * list,ObjectGadget * I,int version)297 int ObjectGadgetInitFromPyList(PyMOLGlobals * G, PyObject * list, ObjectGadget * I,
298                                int version)
299 {
300   int ok = true;
301   if(ok)
302     ok = (I != NULL) && (list != NULL);
303   if(ok)
304     ok = PyList_Check(list);
305   /* TO SUPPORT BACKWARDS COMPATIBILITY...
306      Always check ll when adding new PyList_GetItem's */
307   if(ok){
308     auto *val = PyList_GetItem(list, 0);
309     ok = ObjectFromPyList(G, val, I);
310   }
311   if(ok)
312     ok = PConvPyIntToInt(PyList_GetItem(list, 1), &I->GadgetType);
313   if(ok)
314     ok = PConvPyIntToInt(PyList_GetItem(list, 2), &I->NGSet);
315   if(ok)
316     ok = ObjectGadgetGSetFromPyList(I, PyList_GetItem(list, 3), version);
317   if(ok)
318     ok = PConvPyIntToInt(PyList_GetItem(list, 4), &I->CurGSet);
319 
320   /*  ObjectGadgetInvalidateRep(I,cRepAll); */
321   if(ok) {
322     ObjectGadgetUpdateExtents(I);
323   } else {
324     /* cleanup? */
325   }
326   return (ok);
327 }
328 
ObjectGadgetNewFromPyList(PyMOLGlobals * G,PyObject * list,ObjectGadget ** result,int version)329 int ObjectGadgetNewFromPyList(PyMOLGlobals * G, PyObject * list, ObjectGadget ** result,
330                               int version)
331 {
332   int ok = true;
333   ObjectGadget *I = NULL;
334   int gadget_type = -1;
335   PyObject *plain;
336   (*result) = NULL;
337 
338   if(ok)
339     ok = (list != NULL);
340   if(ok)
341     ok = PyList_Check(list);
342 
343   /* NOTE there is a serious screw-up here...ramp gadgets aren't saved right, but
344      we've got to maintain backward compat...ugh */
345 
346   if(ok)
347     ok = ((plain = PyList_GetItem(list, 0)) != NULL);
348   if(ok)
349     ok = PyList_Check(plain);
350   if(ok)
351     ok = PConvPyIntToInt(PyList_GetItem(plain, 1), &gadget_type);
352   if(ok)
353     switch (gadget_type) {      /* call the right routine to restore the gadget! */
354     case cGadgetRamp:
355       ok = ObjectGadgetRampNewFromPyList(G, list, (ObjectGadgetRamp **) result, version);
356       break;
357     case cGadgetPlain:
358       I = new ObjectGadget(G);
359       if(ok)
360         ok = (I != NULL);
361       if(ok)
362         ok = ObjectGadgetInitFromPyList(G, list, I, version);
363       if(ok)
364         (*result) = I;
365       break;
366     default:
367       ok = false;
368       break;
369     }
370   return (ok);
371 }
372 
ObjectGadgetPlainAsPyList(ObjectGadget * I,bool incl_cgos)373 PyObject *ObjectGadgetPlainAsPyList(ObjectGadget * I, bool incl_cgos)
374 {
375   PyObject *result = NULL;
376 
377   /* first, dump the atoms */
378 
379   result = PyList_New(5);
380   PyList_SetItem(result, 0, ObjectAsPyList(I));
381   PyList_SetItem(result, 1, PyInt_FromLong(I->GadgetType));
382   PyList_SetItem(result, 2, PyInt_FromLong(I->NGSet));
383   PyList_SetItem(result, 3, ObjectGadgetGSetAsPyList(I, incl_cgos));
384   PyList_SetItem(result, 4, PyInt_FromLong(I->CurGSet));
385   return (PConvAutoNone(result));
386 }
387 
ObjectGadgetAsPyList(ObjectGadget * I)388 PyObject *ObjectGadgetAsPyList(ObjectGadget * I)
389 {
390   PyObject *result = NULL;
391 
392   /* first, dump the atoms */
393 
394   switch (I->GadgetType) {
395   case cGadgetRamp:
396     result = ObjectGadgetRampAsPyList((ObjectGadgetRamp *) I);
397     break;
398   case cGadgetPlain:
399     result = ObjectGadgetPlainAsPyList(I);
400     break;
401   }
402   return (PConvAutoNone(result));
403 }
404 
~ObjectGadget()405 ObjectGadget::~ObjectGadget()
406 {
407   auto I = this;
408   for(int a = 0; a < I->NGSet; a++)
409     if(I->GSet[a]) {
410       I->GSet[a]->fFree();
411       I->GSet[a] = NULL;
412     }
413 }
414 
ObjectGadgetUpdateStates(ObjectGadget * I)415 void ObjectGadgetUpdateStates(ObjectGadget * I)
416 {
417   int a;
418   OrthoBusyPrime(I->G);
419   for(a = 0; a < I->NGSet; a++)
420     if(I->GSet[a]) {
421       OrthoBusySlow(I->G, a, I->NGSet);
422       /*           printf(" ObjectGadget: updating state %d of \"%s\".\n" , a+1, I->Name); */
423       I->GSet[a]->update();
424     }
425 }
426 
427 
428 /*========================================================================*/
update()429 void ObjectGadget::update()
430 {
431   auto I = this;
432   if(I->Changed) {
433     ObjectGadgetUpdateStates(I);
434     ObjectGadgetUpdateExtents(I);
435     I->Changed = false;
436   }
437 }
438 
439 
440 /*========================================================================*/
441 
getNFrame() const442 int ObjectGadget::getNFrame() const
443 {
444   return NGSet;
445 }
446 
447 
448 /*========================================================================*/
render(RenderInfo * info)449 void ObjectGadget::render(RenderInfo * info)
450 {
451   auto I = this;
452   int state = info->state;
453   int pass = info->pass;
454   if(pass < 0 || info->ray || info->pick) {
455 
456     ObjectPrepareContext(I, info);
457     for(StateIterator iter(I->G, I->Setting, state, I->NGSet);
458         iter.next();) {
459       GadgetSet * gs = I->GSet[iter.state];
460       gs->render(info);
461     }
462   }
463 }
464 
465 
466 /*========================================================================*/
ObjectGadget(PyMOLGlobals * G)467 ObjectGadget::ObjectGadget(PyMOLGlobals * G) : CObject(G)
468 {
469   type = cObjectGadget;
470   GSet = pymol::vla<GadgetSet*>(10);        /* auto-zero */
471 }
472 
473 
474