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

Reply via email to