pivy icon indicating copy to clipboard operation
pivy copied to clipboard

SoCoordinateElement.getInstance() doesn't work in event handler context

Open tomkcook opened this issue 5 years ago • 7 comments

SoCoordinateElement.getInstance(state) is meant to retrieve the coordinate data from the top of the scenegraph stack. But this doesn't seem to work in an event handler context. I'm trying to do something along these lines:

class MyObj(SoSeparator):
    def __init__(self):
        self.events = coin.SoEventCallback()
        self += self.events
        self.events.addEventCallback(coin.SoKeyboardEvent.getClassTypeId(), self.key_cb)

    def key_cb(self, attr, key_event):
        state = key_event.getAction().getState()
        co_el = coin.SoCoordinateElement.getInstance(state)

...

coords = coin.SoCoordinate3()
coords.point.setValues(...)
scene += coords
scene += MyObj()

But this results in co_el == None in the event callback. Am I doing something wrong? Or is there some other way to get the coordinate data in this context?

tomkcook avatar Sep 17 '20 08:09 tomkcook

@tomkcook do you have any docs/examples for this class?

looooo avatar Sep 17 '20 09:09 looooo

@looooo for which class?

tomkcook avatar Sep 17 '20 09:09 tomkcook

SoCoordinateElement

looooo avatar Sep 17 '20 09:09 looooo

No. This is what's in the documentation for SoCoordinateElement:

The SoCoordinateElement class is yet to be documented.

FIXME: write doc.

The approach I'm taking comes from SoVertexShape.cpp, SoVertexShape::getVertexData(...).

tomkcook avatar Sep 17 '20 09:09 tomkcook

SoVertexShape::getVertexData(...):

 Convenience method that returns the current coordinate and normal
  element. This method is not part of the Open Inventor API.

Do you know what "current" refers to? Maybe someone from the coin-maintainers can help? @VolkerEnderlein

looooo avatar Sep 17 '20 10:09 looooo

"Current" here refers to the state of scenegraph traversal. This is used in objects such as SoIndexedPointSet which don't have their own vertex data but take the vertex data from the scenegraph state; they refer to the SoCoordinate3 object nearest above them in the scenegraph hierarchy for their coordinate data. The documentation for SoState has a reasonable explanation of how this works.

TBH I'm not sure if this is a bug or how it's expected to work, and if it is a bug, whether it's a bug in Pivy or in Coin3D. I happen to have come at it via Pivy so I filed a ticket here, but I'm happy to be redirected to Coin3D if that's where the problem is.

tomkcook avatar Sep 17 '20 11:09 tomkcook

In the C++ API of Coin3d a convenience macro SO_ENABLE is provided to register an element type to an action type. Since pivy (as far as I can see) lacks of this macro you must implement it yourself as a function:

def SO_ENABLE(action, element):
  action.enableElement(element.getClassTypeId(), element.getClassStackIndex())

An SoEventCallback node internally uses an SoHandleEventAction to transport an SoEvent. So, in order to allow to access the SoCoordinateElement from within your event handler you must add this line to your code

SO_ENABLE(coin.SoHandleEventAction, coin.SoCoordinateElement)

For more details have a look at The Inventor Toolmaker: http://www-evasion.imag.fr/Membres/Francois.Faure/doc/inventorToolmaker/sgi_html/ch02.html#id5444406

wwmayer avatar Sep 17 '20 11:09 wwmayer