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