PYMOL-1538 Picking support for ObjectCGO

No nice API available yet. Pick event can be captured like this:

>>> cmd.button("single_left", "none", "clik")
>>> cmd.set_key("F1", lambda: print(_cmd.get_click_string(cmd._COb)))

(press "F1" after a pick)

- Add pick colors to CGO demo (for testing/demo)
This commit is contained in:
Thomas Holder
2020-07-07 13:27:44 +02:00
parent 085f45b4f8
commit d020c80214
4 changed files with 51 additions and 11 deletions

View File

@@ -30,6 +30,7 @@ for a in range(0,63):
for y in range(0,30):
z[x][y]=(math.cos((aa)+x/2.0)+math.sin((aa)+(y/2.0)))
obj += [PICK_COLOR, 0, cPickableGadget]
obj.extend( [ COLOR, 0.3, 0.3, 1.0 ] )
for x in range(0,30):
@@ -46,14 +47,17 @@ for a in range(0,63):
# add into this a couple circulating spheres
obj += [PICK_COLOR, 1, cPickableGadget]
obj.extend( [ COLOR, 1.0, 0.2, 0.2 ] )
obj.extend( [ SPHERE, 5*math.cos(ab)+15.0, 5*math.sin(ab)+15.0, 6.0, 1.0 ] )
obj += [PICK_COLOR, 2, cPickableGadget]
obj.extend( [ COLOR, 1.0, 1.0, 0.2 ] )
obj.extend( [ SPHERE, 5*math.cos(aa)+15.0, 5*math.sin(aa)+15.0, 3.0, 2.0 ] )
# now add a colorful cylinder
obj += [PICK_COLOR, 3, cPickableGadget]
obj.extend( [ CYLINDER,
5.0, 15+math.sin(aa)*10, -5.0, # XYZ 1
25.0, 15+math.sin(aa)*10, -5.0, # XYZ 2

View File

@@ -339,6 +339,12 @@ static PyObject *CGOArrayAsPyList(const CGO * I)
++pc;
--sz;
break;
case CGO_PICK_COLOR:
assert(sz == 2);
flat.push_back(*reinterpret_cast<const int*>(pc++)); // atom index
flat.push_back(*reinterpret_cast<const int*>(pc++)); // bond index
sz -= 2;
break;
case CGO_DRAW_ARRAYS:
{
auto sp = reinterpret_cast<const cgo::draw::arrays*>(pc);
@@ -415,6 +421,12 @@ static int CGOArrayFromPyListInPlace(PyObject * list, CGO * I)
CGO_write_int(fdata, GET_INT(i++));
sz--;
break;
case CGO_PICK_COLOR:
ok_assert(1, i + 1 < l);
CGO_write_int(fdata, GET_INT(i++)); // atom index
CGO_write_int(fdata, GET_INT(i++)); // bond index
sz -= 2;
break;
case CGO_DRAW_ARRAYS:
{
// has abstract superclass, need to be constructed!
@@ -627,6 +639,11 @@ int CGOFromFloatArray(CGO * I, const float *src, int len)
iarg = (int) *(tf);
CGO_write_int(tf, iarg);
break;
case CGO_PICK_COLOR:
tf = save_pc + 1;
CGO_write_int(tf, int(save_pc[1])); // atom index
CGO_write_int(tf, int(save_pc[2])); // bond index
break;
}
save_pc = pc;
I->c += sz + 1;

View File

@@ -261,9 +261,13 @@ static void ObjectCGORenderState(PyMOLGlobals* G, RenderPass pass, CRay* ray,
CGOFree(cgo_copy);
}
}
} else if(G->HaveGUI && G->ValidContext && pass != RenderPass::Antialias) {
if(info->pick) { // no picking yet
} else {
} else if (G->HaveGUI && G->ValidContext) {
if (info->pick) {
PickContext context;
context.object = I;
context.state = sobj - I->State;
CGORenderGLPicking(sobj->renderCGO, info, &context, I->Setting, nullptr);
} else if (pass != RenderPass::Antialias) {
bool pass_is_opaque = pass == RenderPass::Opaque;
if(sobj && ((sobj->hasTransparency ^ pass_is_opaque) || (sobj->hasOpaque == pass_is_opaque))){
{
@@ -373,6 +377,7 @@ static void ObjectCGOGenerateCGO(PyMOLGlobals * G, ObjectCGO * I, ObjectCGOState
}
CGO* convertcgo = CGONew(G);
CGOPickColor(convertcgo, 0, cPickableGadget);
CGOColorv(convertcgo, colorWithA);
CGOAlpha(convertcgo, colorWithA[3]);
CGOAppend(convertcgo, inputCGO);
@@ -431,14 +436,18 @@ static void ObjectCGOGenerateCGO(PyMOLGlobals * G, ObjectCGO * I, ObjectCGOState
preOpt.reset(CGOCombineBeginEnd(preOpt.get(), 0));
}
preOpt.reset(CGOOptimizeToVBOIndexedWithColorEmbedTransparentInfo(
preOpt.get(), 0, colorWithA, false));
if (hasTransparency) {
preOpt.reset(CGOOptimizeToVBOIndexedWithColorEmbedTransparentInfo(
preOpt.get(), 0, colorWithA, false));
if (someLinesWithoutNormals){
// if some lines without normals, turn lighting off on lines
CGO* convertcgo = preOpt.release();
preOpt.reset(CGOTurnLightingOnLinesOff(convertcgo, use_shader));
CGOFreeWithoutVBOs(convertcgo);
if (someLinesWithoutNormals){
// if some lines without normals, turn lighting off on lines
CGO* convertcgo = preOpt.release();
preOpt.reset(CGOTurnLightingOnLinesOff(convertcgo, use_shader));
CGOFreeWithoutVBOs(convertcgo);
}
} else {
preOpt.reset(CGOOptimizeToVBONotIndexed(preOpt.get(), 0));
}
if (allCylinders){
@@ -493,7 +502,7 @@ void ObjectCGO::render(RenderInfo * info)
if(!I->State)
return;
if(pass != RenderPass::Antialias || info->ray) {
if(pass != RenderPass::Antialias || info->ray || info->pick) {
if((I->visRep & cRepCGOBit)) {
for(StateIterator iter(G, I->Setting, state, I->NState); iter.next();) {
sobj = I->State + iter.state;

View File

@@ -64,8 +64,18 @@ ALPHA = 25.0
QUADRIC = 26.0 # NOTE: Only works with ellipsoids and disks
CONE = 27.0
PICK_COLOR = 31.0 # 0x1F [PICK_COLOR, index, bond/cPickable_t]
LIGHTING = float(0x0B50)
# enum cPickable_t:
cPickableAtom = -1.0
cPickableLabel = -2.0
cPickableGadget = -3.0
cPickableNoPick = -4.0
cPickableThrough = -5.0
def molauto(name="mols", sele="(all)", marg="-nice", _self=cmd):
_self.save("molauto.pdb",sele)
print("molauto %s -nocentre molauto.pdb | molscript -r > molauto.r3d"%marg)