/* 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_gl.h" #include "os_predef.h" #include "os_std.h" #include "Base.h" #include "CGO.h" #include "Color.h" #include "GadgetSet.h" #include "MemoryDebug.h" #include "ObjectGadget.h" #include "ObjectGadgetRamp.h" #include "PConv.h" #include "Scene.h" #include "Setting.h" #include "VFont.h" #include "main.h" CGO* ObjectGadgetPyListFloatToCGO(PyObject* list); int ObjectGadgetGetVertex(const ObjectGadget* I, int index, int base, float* v) { GadgetSet* gs; int ok = false; if (I->CurGSet < I->NGSet) { gs = I->GSet[I->CurGSet]; if (gs) { ok = GadgetSetGetVertex(gs, index, base, v); } } return (ok); } int ObjectGadgetSetVertex(ObjectGadget* I, int index, int base, const float* v) { GadgetSet* gs; int ok = false; if (I->CurGSet < I->NGSet) { gs = I->GSet[I->CurGSet]; if (gs) { ok = GadgetSetSetVertex(gs, index, base, v); } } if (index) // if 0 - xyz doesn't change, 1 - mouse position when changing // colors I->Changed = true; return (ok); } /* in current state */ ObjectGadget* ObjectGadgetTest(PyMOLGlobals* G) { ObjectGadget* I = nullptr; GadgetSet* gs = nullptr; CGO* cgo = nullptr; int a; float coord[] = { 0.5F, 0.5F, 0.0F, 0.0F, 0.0F, 0.0F, 0.3F, 0.0F, 0.0F, 0.0F, -0.3F, 0.0F, 0.3F, -0.3F, 0.0F, 0.03F, -0.03F, 0.03F, 0.27F, -0.03F, 0.03F, 0.03F, -0.27F, 0.03F, 0.27F, -0.27F, 0.03F, 0.02F, -0.02F, 0.01F, 0.28F, -0.02F, 0.01F, 0.02F, -0.28F, 0.01F, 0.28F, -0.28F, 0.01F, }; float normal[] = { 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0, }; I = new ObjectGadget(G); gs = GadgetSetNew(G); gs->NCoord = 13; gs->Coord = VLAlloc(float, gs->NCoord * 3); for (a = 0; a < gs->NCoord * 3; a++) { gs->Coord[a] = coord[a]; } gs->NNormal = 5; gs->Normal = VLAlloc(float, gs->NNormal * 3); for (a = 0; a < gs->NNormal * 3; a++) { gs->Normal[a] = normal[a]; } cgo = CGONewSized(G, 100); CGOColor(cgo, 1.0, 1.0, 1.0); /* top */ CGOBegin(cgo, GL_TRIANGLE_STRIP); CGONormal(cgo, 2.0, 2.0, 0.0); CGOVertex(cgo, 1.0, 5.0, 0.0); CGOVertex(cgo, 1.0, 6.0, 0.0); CGONormal(cgo, 2.0, 1.0, 0.0); CGOVertex(cgo, 1.0, 1.0, 0.0); CGOVertex(cgo, 1.0, 2.0, 0.0); CGOEnd(cgo); /* bottom */ CGOBegin(cgo, GL_TRIANGLE_STRIP); CGONormal(cgo, 2.0, 4.0, 0.0); CGOVertex(cgo, 1.0, 3.0, 0.0); CGOVertex(cgo, 1.0, 4.0, 0.0); CGONormal(cgo, 2.0, 2.0, 0.0); CGOVertex(cgo, 1.0, 7.0, 0.0); CGOVertex(cgo, 1.0, 8.0, 0.0); CGOEnd(cgo); /* left */ CGOBegin(cgo, GL_TRIANGLE_STRIP); CGONormal(cgo, 2.0, 3.0, 0.0); CGOVertex(cgo, 1.0, 1.0, 0.0); CGOVertex(cgo, 1.0, 3.0, 0.0); CGONormal(cgo, 2.0, 2.0, 0.0); CGOVertex(cgo, 1.0, 5.0, 0.0); CGOVertex(cgo, 1.0, 7.0, 0.0); CGOEnd(cgo); /* right */ CGOBegin(cgo, GL_TRIANGLE_STRIP); CGONormal(cgo, 2.0, 2.0, 0.0); CGOVertex(cgo, 1.0, 6.0, 0.0); CGOVertex(cgo, 1.0, 8.0, 0.0); CGONormal(cgo, 2.0, 0.0, 0.0); CGOVertex(cgo, 1.0, 2.0, 0.0); CGOVertex(cgo, 1.0, 4.0, 0.0); CGOEnd(cgo); CGOColor(cgo, 1.0, 0.0, 0.0); /* center */ CGOBegin(cgo, GL_TRIANGLE_STRIP); CGONormal(cgo, 2.0, 2.0, 0.0); CGOVertex(cgo, 1.0, 5.0, 0.0); CGOVertex(cgo, 1.0, 7.0, 0.0); CGOVertex(cgo, 1.0, 6.0, 0.0); CGOVertex(cgo, 1.0, 8.0, 0.0); CGOEnd(cgo); CGOColor(cgo, 0.0, 1.0, 0.0); /* backr */ CGOBegin(cgo, GL_TRIANGLE_STRIP); CGONormal(cgo, 2.0, 2.0, 0.0); CGOVertex(cgo, 1.0, 9.0, 0.0); CGOVertex(cgo, 1.0, 10.0, 0.0); CGOVertex(cgo, 1.0, 11.0, 0.0); CGOVertex(cgo, 1.0, 12.0, 0.0); CGOEnd(cgo); CGOStop(cgo); gs->ShapeCGO = cgo; cgo = CGONewSized(G, 100); CGODotwidth(cgo, 5); CGOPickColor(cgo, 0, cPickableGadget); /* top */ CGOBegin(cgo, GL_TRIANGLE_STRIP); CGOVertex(cgo, 1.0, 1.0, 0.0); CGOVertex(cgo, 1.0, 2.0, 0.0); CGOVertex(cgo, 1.0, 5.0, 0.0); CGOVertex(cgo, 1.0, 6.0, 0.0); CGOEnd(cgo); /* bottom */ CGOBegin(cgo, GL_TRIANGLE_STRIP); CGOVertex(cgo, 1.0, 3.0, 0.0); CGOVertex(cgo, 1.0, 4.0, 0.0); CGOVertex(cgo, 1.0, 7.0, 0.0); CGOVertex(cgo, 1.0, 8.0, 0.0); CGOEnd(cgo); /* left */ CGOBegin(cgo, GL_TRIANGLE_STRIP); CGOVertex(cgo, 1.0, 1.0, 0.0); CGOVertex(cgo, 1.0, 3.0, 0.0); CGOVertex(cgo, 1.0, 5.0, 0.0); CGOVertex(cgo, 1.0, 7.0, 0.0); CGOEnd(cgo); /* right */ CGOBegin(cgo, GL_TRIANGLE_STRIP); CGOVertex(cgo, 1.0, 6.0, 0.0); CGOVertex(cgo, 1.0, 8.0, 0.0); CGOVertex(cgo, 1.0, 2.0, 0.0); CGOVertex(cgo, 1.0, 4.0, 0.0); CGOEnd(cgo); CGOEnd(cgo); CGOStop(cgo); gs->PickShapeCGO = cgo; gs->Obj = I; gs->State = 0; I->GSet[0] = gs; I->NGSet = 1; gs->update(); ObjectGadgetUpdateExtents(I); return (I); } void ObjectGadgetUpdateExtents(ObjectGadget* I) { float maxv[3] = {FLT_MAX, FLT_MAX, FLT_MAX}; float minv[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX}; int a; GadgetSet* ds; /* update extents */ copy3f(maxv, I->ExtentMin); copy3f(minv, I->ExtentMax); I->ExtentFlag = false; for (a = 0; a < I->NGSet; a++) { ds = I->GSet[a]; if (ds) { if (GadgetSetGetExtent(ds, I->ExtentMin, I->ExtentMax)) I->ExtentFlag = true; } } } static PyObject* ObjectGadgetGSetAsPyList(ObjectGadget* I, bool incl_cgos) { PyObject* result = nullptr; int a; result = PyList_New(I->NGSet); for (a = 0; a < I->NGSet; a++) { if (I->GSet[a]) { PyList_SetItem(result, a, GadgetSetAsPyList(I->GSet[a], incl_cgos)); } else { PyList_SetItem(result, a, PConvAutoNone(Py_None)); } } return (PConvAutoNone(result)); } static int ObjectGadgetGSetFromPyList( ObjectGadget* I, PyObject* list, int version) { int ok = true; int a; if (ok) ok = PyList_Check(list); if (ok) { VLACheck(I->GSet, GadgetSet*, I->NGSet); for (a = 0; a < I->NGSet; a++) { if (ok) { auto* val = PyList_GetItem(list, a); ok = GadgetSetFromPyList(I->G, val, &I->GSet[a], version); } if (ok && I->GSet[a]) { I->GSet[a]->Obj = I; I->GSet[a]->State = a; } } } return (ok); } int ObjectGadgetInitFromPyList( PyMOLGlobals* G, PyObject* list, ObjectGadget* I, int version) { int ok = true; if (ok) ok = (I != nullptr) && (list != nullptr); if (ok) ok = PyList_Check(list); /* TO SUPPORT BACKWARDS COMPATIBILITY... Always check ll when adding new PyList_GetItem's */ if (ok) { auto* val = PyList_GetItem(list, 0); ok = ObjectFromPyList(G, val, I); } if (ok) ok = PConvPyIntToInt(PyList_GetItem(list, 1), &I->GadgetType); if (ok) ok = PConvPyIntToInt(PyList_GetItem(list, 2), &I->NGSet); if (ok) ok = ObjectGadgetGSetFromPyList(I, PyList_GetItem(list, 3), version); if (ok) ok = PConvPyIntToInt(PyList_GetItem(list, 4), &I->CurGSet); /* ObjectGadgetInvalidateRep(I,cRepAll); */ if (ok) { ObjectGadgetUpdateExtents(I); } else { /* cleanup? */ } return (ok); } int ObjectGadgetNewFromPyList( PyMOLGlobals* G, PyObject* list, ObjectGadget** result, int version) { int ok = true; ObjectGadget* I = nullptr; int gadget_type = -1; PyObject* plain; (*result) = nullptr; if (ok) ok = (list != nullptr); if (ok) ok = PyList_Check(list); /* NOTE there is a serious screw-up here...ramp gadgets aren't saved right, but we've got to maintain backward compat...ugh */ if (ok) ok = ((plain = PyList_GetItem(list, 0)) != nullptr); if (ok) ok = PyList_Check(plain); if (ok) ok = PConvPyIntToInt(PyList_GetItem(plain, 1), &gadget_type); if (ok) switch (gadget_type) { /* call the right routine to restore the gadget! */ case cGadgetRamp: ok = ObjectGadgetRampNewFromPyList( G, list, (ObjectGadgetRamp**) result, version); break; case cGadgetPlain: I = new ObjectGadget(G); if (ok) ok = (I != nullptr); if (ok) ok = ObjectGadgetInitFromPyList(G, list, I, version); if (ok) (*result) = I; break; default: ok = false; break; } return (ok); } PyObject* ObjectGadgetPlainAsPyList(ObjectGadget* I, bool incl_cgos) { PyObject* result = nullptr; /* first, dump the atoms */ result = PyList_New(5); PyList_SetItem(result, 0, ObjectAsPyList(I)); PyList_SetItem(result, 1, PyInt_FromLong(I->GadgetType)); PyList_SetItem(result, 2, PyInt_FromLong(I->NGSet)); PyList_SetItem(result, 3, ObjectGadgetGSetAsPyList(I, incl_cgos)); PyList_SetItem(result, 4, PyInt_FromLong(I->CurGSet)); return (PConvAutoNone(result)); } PyObject* ObjectGadgetAsPyList(ObjectGadget* I) { PyObject* result = nullptr; /* first, dump the atoms */ switch (I->GadgetType) { case cGadgetRamp: result = ObjectGadgetRampAsPyList((ObjectGadgetRamp*) I); break; case cGadgetPlain: result = ObjectGadgetPlainAsPyList(I); break; } return (PConvAutoNone(result)); } ObjectGadget::~ObjectGadget() { auto I = this; for (int a = 0; a < I->NGSet; a++) if (I->GSet[a]) { delete I->GSet[a]; I->GSet[a] = nullptr; } } void ObjectGadgetUpdateStates(ObjectGadget* I) { int a; OrthoBusyPrime(I->G); for (a = 0; a < I->NGSet; a++) if (I->GSet[a]) { OrthoBusySlow(I->G, a, I->NGSet); /* printf(" ObjectGadget: updating state %d of \"%s\".\n" , a+1, * I->Name); */ I->GSet[a]->update(); } } /*========================================================================*/ void ObjectGadget::update() { auto I = this; if (I->Changed) { ObjectGadgetUpdateStates(I); ObjectGadgetUpdateExtents(I); I->Changed = false; } } /*========================================================================*/ int ObjectGadget::getNFrame() const { return NGSet; } /*========================================================================*/ void ObjectGadget::render(RenderInfo* info) { auto I = this; int state = info->state; const RenderPass pass = info->pass; if (pass == RenderPass::Transparent || info->ray || info->pick) { ObjectPrepareContext(I, info); for (StateIterator iter(I->G, I->Setting.get(), state, I->NGSet); iter.next();) { GadgetSet* gs = I->GSet[iter.state]; gs->render(info); } } } /*========================================================================*/ ObjectGadget::ObjectGadget(PyMOLGlobals* G) : pymol::CObject(G) { type = cObjectGadget; GSet = pymol::vla(10); /* auto-zero */ } pymol::RenderContext ObjectGadget::getRenderContext() const { return pymol::RenderContext::UnitWindow; }