Hi Robert,
please find attached a simple example that shows the issues I was trying to
explain:
- launch with no args to see the initial issue
- launch with "--crash" to get the crash i ran into when implementing the
callback deriving from osg::Callback
- launch with "--fix" to see the way I fixed it with the NodeCallback:
comments on the run() and operator() methods explain some concerns for this
solution
Hope this clarifies things :)
Ricky
On Mon, Aug 29, 2016 at 4:29 PM, Robert Osfield <[email protected]>
wrote:
> Hi Ricky,
>
> The changes to Drawable and the knock on effect to the callbacks is an
> awkward one - it would be easy if it we could just discard backwards
> compatibility, so it's a far from ideal code, but alas you can't
> rewrite history once it's happened.
>
> From your description I don't have a clear idea of what is being
> called twice and whether this is a problem. Could you create a small
> example that illustrates the problem, once I can see first hand I can
> review the behaviour and decide whether this is acceptable or is an
> bug.
>
> Thanks,
> Robert.
>
> On 29 August 2016 at 15:00, Riccardo Corsi <[email protected]>
> wrote:
> > Hi all,
> >
> > I report what I believe could be considered a bug, probably introduced
> after
> > the promotion of the Drawable class to a node, together with the new
> > callback system.
> >
> > I have a GUIEventHandler derived class installed on a Drawable.
> > After some digging I've realized that it's called twice for every event
> due
> > to the EventVisitor code here:
> > https://github.com/openscenegraph/OpenSceneGraph/
> blob/master/include/osgGA/EventVisitor#L86
> >
> > GUIEventHandler happens to derive both from NodeCallback and
> > DrawableEventCallback, resulting in it being called twice. I think this
> > might be considered as a bug if the intended behavior was to keep using
> the
> > old GUIEventHandler interface the way it was (when attached to the viewer
> > for instance, it is called only once as expected).
> >
> > Relate issue:
> > I've re-implemented my callback deriving from osg::Callback, but this
> > results in a crash as the osg::CallbackObject interface is used even if
> the
> > cast does not succeed (first if condition)
> > https://github.com/openscenegraph/OpenSceneGraph/
> blob/master/include/osgGA/EventVisitor#L93
> >
> > I fixed that by deriving from osg::NodeCallback, but I had to reimplement
> > the operator() method instead of run(), as the second is not called by
> the
> > visitor - that also it's a bit counter-intuitive with respect to the
> > osg::Callback class interface.
> >
> > Ricky
> >
> >
> >
> >
> >
> >
> >
> > _______________________________________________
> > osg-users mailing list
> > [email protected]
> > http://lists.openscenegraph.org/listinfo.cgi/osg-users-
> openscenegraph.org
> >
> _______________________________________________
> osg-users mailing list
> [email protected]
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
/* OpenSceneGraph example, osgcallback.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <osgViewer/Viewer>
#include <osg/Notify>
#include <osg/ShapeDrawable>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
class TwiceEventCallback : public osgGA::GUIEventHandler
{
public:
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv)
{
if (ea.getEventType() == osgGA::GUIEventAdapter::PUSH)
{
OSG_ALWAYS << "[Twice] Mouse PUSH on frame: " << nv->getFrameStamp()->getFrameNumber() << std::endl;
}
return false;
}
};
class CrashEventCallback : public osg::Callback
{
virtual bool run(osg::Object* object, osg::Object* data)
{
osgGA::EventVisitor* ev = data->asNodeVisitor()->asEventVisitor();
if (ev)
{
for (osgGA::EventQueue::Events::iterator itr = ev->getEvents().begin();
itr != ev->getEvents().end();
++itr)
{
osgGA::GUIEventAdapter* ea = (*itr)->asGUIEventAdapter();
if (ea->getEventType() == osgGA::GUIEventAdapter::PUSH)
{
OSG_ALWAYS << "[Crash] Mouse PUSH on frame: " << ev->getFrameStamp()->getFrameNumber() << std::endl;
}
}
}
return traverse(object, data);
}
};
class FixEventCallback : public osg::NodeCallback
{
// implementing this method does NOT work, never called by the event visitor
// this behaviour is not very intuitive
virtual bool run(osg::Object* object, osg::Object* data)
{
osgGA::EventVisitor* ev = data->asNodeVisitor()->asEventVisitor();
if (ev)
{
for (osgGA::EventQueue::Events::iterator itr = ev->getEvents().begin();
itr != ev->getEvents().end();
++itr)
{
osgGA::GUIEventAdapter* ea = (*itr)->asGUIEventAdapter();
if (ea->getEventType() == osgGA::GUIEventAdapter::PUSH)
{
OSG_ALWAYS << "[Fix run()] Mouse PUSH on frame: " << ev->getFrameStamp()->getFrameNumber() << std::endl;
}
}
}
return traverse(object, data);
}
// this one is ok and actually fixes, but method signature returns void
// so probably the event is not considered handled?? not sure...
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
osgGA::EventVisitor* ev = nv->asEventVisitor();
if (ev)
{
for (osgGA::EventQueue::Events::iterator itr = ev->getEvents().begin();
itr != ev->getEvents().end();
++itr)
{
osgGA::GUIEventAdapter* ea = (*itr)->asGUIEventAdapter();
if (ea->getEventType() == osgGA::GUIEventAdapter::PUSH)
{
OSG_ALWAYS << "[Fix operator()] Mouse PUSH on frame: " << ev->getFrameStamp()->getFrameNumber() << std::endl;
}
}
}
traverse(node, nv);
}
};
int main( int argc, char **argv )
{
// use an ArgumentParser object to manage the program arguments.
osg::ArgumentParser arguments(&argc,argv);
// initialize the viewer.
osgViewer::Viewer viewer(arguments);
osg::Drawable* sphere = new osg::ShapeDrawable(new osg::Sphere());
if (arguments.read("--crash"))
{
sphere->setEventCallback(new CrashEventCallback);
}
else if (arguments.read("--fix"))
{
sphere->setEventCallback(new FixEventCallback);
}
else
{
sphere->setEventCallback(new TwiceEventCallback);
}
// set the scene to render
viewer.setSceneData(sphere);
viewer.setCameraManipulator(new osgGA::TrackballManipulator);
viewer.realize();
viewer.run();
return 0;
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org