Canvas: Add local_pos to mouse event and fix transformation of event positions with multi-level nested canvases.

This commit is contained in:
Thomas Geymayer 2013-05-13 00:34:09 +02:00
parent d61b5827fd
commit 01104cc1d3
6 changed files with 53 additions and 32 deletions

View File

@ -210,23 +210,22 @@ namespace canvas
// (eg. removed by another event handler)
continue;
// TODO provide functions to convert position and delta to local
// coordinates on demand. Events shouldn't contain informations in
// local coordinates as they might differe between different elements
// receiving the same event.
// if( mouse_event && event->type != Event::DRAG )
// {
// // TODO transform pos and delta for drag events. Maybe we should just
// // store the global coordinates and convert to local coordinates
// // on demand.
//
// // Position and delta are specified in local coordinate system of
// // current element
// mouse_event->pos = it->local_pos;
// mouse_event->delta = it->local_delta;
// }
// TODO provide functions to convert delta to local coordinates on demand.
// Maybe also provide a clone method for events as local coordinates
// might differ between different elements receiving the same event.
if( mouse_event ) //&& event->type != Event::DRAG )
{
// TODO transform pos and delta for drag events. Maybe we should just
// store the global coordinates and convert to local coordinates
// on demand.
el->callListeners(event);
// Position and delta are specified in local coordinate system of
// current element
mouse_event->local_pos = it->local_pos;
//mouse_event->delta = it->local_delta;
}
el->handleEvent(event);
if( event->propagation_stopped )
return true;

View File

@ -49,6 +49,7 @@ namespace canvas
osg::Vec2f getScreenPos() const { return screen_pos; }
osg::Vec2f getClientPos() const { return client_pos; }
osg::Vec2f getLocalPos() const { return local_pos; }
osg::Vec2f getDelta() const { return delta; }
float getScreenX() const { return screen_pos.x(); }
@ -57,6 +58,9 @@ namespace canvas
float getClientX() const { return client_pos.x(); }
float getClientY() const { return client_pos.y(); }
float getLocalX() const { return local_pos.x(); }
float getLocalY() const { return local_pos.y(); }
float getDeltaX() const { return delta.x(); }
float getDeltaY() const { return delta.y(); }
@ -64,6 +68,7 @@ namespace canvas
osg::Vec2f screen_pos, //<! Position in screen coordinates
client_pos, //<! Position in window/canvas coordinates
local_pos, //<! Position in local/element coordinates
delta;
int button, //<! Button for this event
state, //<! Current button state

View File

@ -185,14 +185,16 @@ namespace canvas
}
//----------------------------------------------------------------------------
void Element::callListeners(const canvas::EventPtr& event)
bool Element::handleEvent(canvas::EventPtr event)
{
ListenerMap::iterator listeners = _listener.find(event->getType());
if( listeners == _listener.end() )
return;
return false;
BOOST_FOREACH(EventListenerPtr listener, listeners->second)
listener->call(event);
return true;
}
//----------------------------------------------------------------------------

View File

@ -90,7 +90,7 @@ namespace canvas
virtual bool ascend(EventVisitor& visitor);
virtual bool traverse(EventVisitor& visitor);
void callListeners(const canvas::EventPtr& event);
virtual bool handleEvent(canvas::EventPtr event);
virtual bool hitBound( const osg::Vec2f& pos,
const osg::Vec2f& local_pos ) const;

View File

@ -22,6 +22,7 @@
#include <simgear/canvas/CanvasMgr.hxx>
#include <simgear/canvas/CanvasSystemAdapter.hxx>
#include <simgear/canvas/MouseEvent.hxx>
#include <simgear/scene/util/OsgMath.hxx>
#include <simgear/scene/util/parse_color.hxx>
#include <simgear/misc/sg_path.hxx>
@ -411,26 +412,40 @@ namespace canvas
}
//----------------------------------------------------------------------------
bool Image::handleMouseEvent(MouseEventPtr event)
bool Image::handleEvent(EventPtr event)
{
bool handled = Element::handleEvent(event);
CanvasPtr src_canvas = _src_canvas.lock();
if( !src_canvas )
return false;
return handled;
if( _outset.valid )
MouseEventPtr mouse_event = boost::dynamic_pointer_cast<MouseEvent>(event);
if( mouse_event )
{
CSSOffsets outset = _outset.getAbsOffsets(getTextureDimensions());
mouse_event.reset( new MouseEvent(*mouse_event) );
event = mouse_event;
event.reset( new MouseEvent(*event) );
event->client_pos += osg::Vec2f(outset.l, outset.t);
event->client_pos.x() *= src_canvas->getViewWidth()
/ (_region.width() + outset.l + outset.r);
event->client_pos.y() *= src_canvas->getViewHeight()
/ (_region.height() + outset.t + outset.b);
mouse_event->client_pos = mouse_event->local_pos
- toOsg(_region.getMin());
osg::Vec2f size(_region.width(), _region.height());
if( _outset.valid )
{
CSSOffsets outset = _outset.getAbsOffsets(getTextureDimensions());
mouse_event->client_pos += osg::Vec2f(outset.l, outset.t);
size.x() += outset.l + outset.r;
size.y() += outset.t + outset.b;
}
// Scale event pos according to canvas view size vs. displayed/screen size
mouse_event->client_pos.x() *= src_canvas->getViewWidth() / size.x();
mouse_event->client_pos.y() *= src_canvas->getViewHeight()/ size.y();
mouse_event->local_pos = mouse_event->client_pos;
}
return src_canvas->handleMouseEvent(event);
return handled || src_canvas->handleMouseEvent(mouse_event);
}
//----------------------------------------------------------------------------

View File

@ -81,7 +81,7 @@ namespace canvas
const SGRect<float>& getRegion() const;
bool handleMouseEvent(MouseEventPtr event);
bool handleEvent(EventPtr event);
protected: