dx(0), dy(0),
button(-1),
state(-1),
- mod(-1)
+ mod(-1),
+ scroll(osgGA::GUIEventAdapter::SCROLL_NONE)
{}
+ osg::Vec2f getPos() const { return osg::Vec2f(x, y); }
+ osg::Vec3f getPos3() const { return osg::Vec3f(x, y, 0); }
+
EventType type;
- int x, y,
- dx, dy,
- button, //<! Button for this event
+ float x, y,
+ dx, dy;
+ int button, //<! Button for this event
state, //<! Current button state
mod; //<! Keyboard modifier state
Scroll scroll;
_mouse_scroll = event.scroll;
// Always set event type last because all listeners are attached to it
_mouse_event = event.type;
- return true;
+
+ return _root_group->handleMouseEvent(event);
}
//------------------------------------------------------------------------------
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "element.hxx"
+#include <Canvas/MouseEvent.hxx>
#include <Canvas/property_helper.hxx>
#include <osg/Drawable>
}
}
+ //----------------------------------------------------------------------------
+ bool Element::handleMouseEvent(const canvas::MouseEvent& event)
+ {
+ // Transform event to local coordinates
+ const osg::Matrixd& m = _transform->getInverseMatrix();
+ canvas::MouseEvent local_event = event;
+ local_event.x = m(0, 0) * event.x + m(1, 0) * event.y + m(3, 0);
+ local_event.y = m(0, 1) * event.x + m(1, 1) * event.y + m(3, 1);
+
+ // Drawables have a bounding box...
+ if( _drawable )
+ {
+ if( !_drawable->getBound().contains(local_event.getPos3()) )
+ return false;
+ }
+ // ... for other elements, i.e. groups only a bounding sphere is available
+ else if( !_transform->getBound().contains(local_event.getPos3()) )
+ return false;
+
+ local_event.dx = m(0, 0) * event.dx + m(1, 0) * event.dy;
+ local_event.dy = m(0, 1) * event.dx + m(1, 1) * event.dy;
+
+ return handleLocalMouseEvent(local_event);
+ }
+
//----------------------------------------------------------------------------
osg::ref_ptr<osg::MatrixTransform> Element::getMatrixTransform()
{
);
}
+ //----------------------------------------------------------------------------
+ bool Element::handleLocalMouseEvent(const canvas::MouseEvent& event)
+ {
+ std::cout << _node->getPath()
+ << " local: pos=(" << event.x << "|" << event.y << ") "
+ << "d=(" << event.dx << "|" << event.dx << ")"
+ << std::endl;
+ return true;
+ }
+
//----------------------------------------------------------------------------
void Element::setDrawable( osg::Drawable* drawable )
{
namespace canvas
{
+ class MouseEvent;
class Element:
public SGPropertyChangeListener
{
*/
virtual void update(double dt);
+ virtual bool handleMouseEvent(const canvas::MouseEvent& event);
+
osg::ref_ptr<osg::MatrixTransform> getMatrixTransform();
virtual void childAdded( SGPropertyNode * parent,
Element(SGPropertyNode_ptr node, uint32_t attributes_used = 0);
+ virtual bool handleLocalMouseEvent(const canvas::MouseEvent& event);
+
virtual void childAdded(SGPropertyNode * child) {}
virtual void childRemoved(SGPropertyNode * child){}
virtual void childChanged(SGPropertyNode * child){}
#include "text.hxx"
#include "CanvasImage.hxx"
+#include <boost/foreach.hpp>
+
namespace canvas
{
//----------------------------------------------------------------------------
void Group::update(double dt)
{
- for( ChildMap::iterator child = _children.begin();
- child != _children.end();
- ++child )
- child->second->update(dt);
+ BOOST_FOREACH( ChildList::value_type child, _children )
+ child.second->update(dt);
Element::update(dt);
}
+ //----------------------------------------------------------------------------
+ bool Group::handleLocalMouseEvent(const canvas::MouseEvent& event)
+ {
+ // Iterate in reverse order as last child is displayed on top
+ BOOST_REVERSE_FOREACH( ChildList::value_type child, _children )
+ {
+ if( child.second->handleMouseEvent(event) )
+ return true;
+ }
+ return false;
+ }
+
//----------------------------------------------------------------------------
void Group::childAdded(SGPropertyNode* child)
{
boost::shared_ptr<Element> element;
+ // TODO create map of child factories and use also to check for element
+ // on deletion in ::childRemoved
if( child->getNameString() == "text" )
element.reset( new Text(child) );
else if( child->getNameString() == "group" )
element.reset( new Path(child) );
else if( child->getNameString() == "image" )
element.reset( new Image(child) );
-
+
if( !element )
return;
// Add to osg scene graph...
_transform->addChild( element->getMatrixTransform() );
- _children[ child ] = element;
+ _children.push_back( ChildList::value_type(child, element) );
}
+ //----------------------------------------------------------------------------
+ struct ChildFinder
+ {
+ public:
+ ChildFinder(SGPropertyNode *node):
+ _node(node)
+ {}
+
+ bool operator()(const Group::ChildList::value_type& el) const
+ {
+ return el.first == _node;
+ }
+
+ private:
+ SGPropertyNode *_node;
+ };
+
//----------------------------------------------------------------------------
void Group::childRemoved(SGPropertyNode* node)
{
if( node->getNameString() == "text"
|| node->getNameString() == "group"
|| node->getNameString() == "map"
- || node->getNameString() == "path" )
+ || node->getNameString() == "path"
+ || node->getNameString() == "image" )
{
- ChildMap::iterator child = _children.find(node);
+ ChildFinder pred(node);
+ ChildList::iterator child =
+ std::find_if(_children.begin(), _children.end(), pred);
if( child == _children.end() )
SG_LOG
#include "element.hxx"
#include <boost/shared_ptr.hpp>
-#include <map>
+#include <list>
namespace canvas
{
public Element
{
public:
+ typedef std::list< std::pair< const SGPropertyNode*,
+ ElementPtr
+ >
+ > ChildList;
+
Group(SGPropertyNode_ptr node);
virtual ~Group();
virtual void update(double dt);
protected:
- typedef std::map<const SGPropertyNode*, ElementPtr> ChildMap;
- ChildMap _children;
+
+ ChildList _children;
+
+ virtual bool handleLocalMouseEvent(const canvas::MouseEvent& event);
virtual void childAdded(SGPropertyNode * child);
virtual void childRemoved(SGPropertyNode * child);
{
public:
osg::Vec2 handleHit(float x, float y);
+
+ virtual osg::BoundingBox computeBound() const;
};
//----------------------------------------------------------------------------
);
}
+ //----------------------------------------------------------------------------
+ osg::BoundingBox Text::TextOSG::computeBound() const
+ {
+ osg::BoundingBox bb = osgText::Text::computeBound();
+ if( !bb.valid() )
+ return bb;
+
+ // TODO bounding box still doesn't seem always right (eg. with center
+ // horizontal alignment not completely accurate)
+ bb._min.y() += _offset.y();
+ bb._max.y() += _offset.y();
+
+ return bb;
+ }
+
//----------------------------------------------------------------------------
Text::Text(SGPropertyNode_ptr node):
Element(node, COLOR | COLOR_FILL | BOUNDING_BOX),