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
+15 -16
View File
@@ -210,23 +210,22 @@ namespace canvas
// (eg. removed by another event handler) // (eg. removed by another event handler)
continue; continue;
// TODO provide functions to convert position and delta to local // TODO provide functions to convert delta to local coordinates on demand.
// coordinates on demand. Events shouldn't contain informations in // Maybe also provide a clone method for events as local coordinates
// local coordinates as they might differe between different elements // might differ between different elements receiving the same event.
// receiving the same event. if( mouse_event ) //&& event->type != Event::DRAG )
// if( mouse_event && event->type != Event::DRAG ) {
// { // TODO transform pos and delta for drag events. Maybe we should just
// // TODO transform pos and delta for drag events. Maybe we should just // store the global coordinates and convert to local coordinates
// // store the global coordinates and convert to local coordinates // on demand.
// // 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;
// }
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 ) if( event->propagation_stopped )
return true; return true;
+5
View File
@@ -49,6 +49,7 @@ namespace canvas
osg::Vec2f getScreenPos() const { return screen_pos; } osg::Vec2f getScreenPos() const { return screen_pos; }
osg::Vec2f getClientPos() const { return client_pos; } osg::Vec2f getClientPos() const { return client_pos; }
osg::Vec2f getLocalPos() const { return local_pos; }
osg::Vec2f getDelta() const { return delta; } osg::Vec2f getDelta() const { return delta; }
float getScreenX() const { return screen_pos.x(); } float getScreenX() const { return screen_pos.x(); }
@@ -57,6 +58,9 @@ namespace canvas
float getClientX() const { return client_pos.x(); } float getClientX() const { return client_pos.x(); }
float getClientY() const { return client_pos.y(); } 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 getDeltaX() const { return delta.x(); }
float getDeltaY() const { return delta.y(); } float getDeltaY() const { return delta.y(); }
@@ -64,6 +68,7 @@ namespace canvas
osg::Vec2f screen_pos, //<! Position in screen coordinates osg::Vec2f screen_pos, //<! Position in screen coordinates
client_pos, //<! Position in window/canvas coordinates client_pos, //<! Position in window/canvas coordinates
local_pos, //<! Position in local/element coordinates
delta; delta;
int button, //<! Button for this event int button, //<! Button for this event
state, //<! Current button state state, //<! Current button state
+4 -2
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()); ListenerMap::iterator listeners = _listener.find(event->getType());
if( listeners == _listener.end() ) if( listeners == _listener.end() )
return; return false;
BOOST_FOREACH(EventListenerPtr listener, listeners->second) BOOST_FOREACH(EventListenerPtr listener, listeners->second)
listener->call(event); listener->call(event);
return true;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
+1 -1
View File
@@ -90,7 +90,7 @@ namespace canvas
virtual bool ascend(EventVisitor& visitor); virtual bool ascend(EventVisitor& visitor);
virtual bool traverse(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, virtual bool hitBound( const osg::Vec2f& pos,
const osg::Vec2f& local_pos ) const; const osg::Vec2f& local_pos ) const;
+27 -12
View File
@@ -22,6 +22,7 @@
#include <simgear/canvas/CanvasMgr.hxx> #include <simgear/canvas/CanvasMgr.hxx>
#include <simgear/canvas/CanvasSystemAdapter.hxx> #include <simgear/canvas/CanvasSystemAdapter.hxx>
#include <simgear/canvas/MouseEvent.hxx> #include <simgear/canvas/MouseEvent.hxx>
#include <simgear/scene/util/OsgMath.hxx>
#include <simgear/scene/util/parse_color.hxx> #include <simgear/scene/util/parse_color.hxx>
#include <simgear/misc/sg_path.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(); CanvasPtr src_canvas = _src_canvas.lock();
if( !src_canvas ) 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) ); mouse_event->client_pos = mouse_event->local_pos
event->client_pos += osg::Vec2f(outset.l, outset.t); - toOsg(_region.getMin());
event->client_pos.x() *= src_canvas->getViewWidth()
/ (_region.width() + outset.l + outset.r); osg::Vec2f size(_region.width(), _region.height());
event->client_pos.y() *= src_canvas->getViewHeight() if( _outset.valid )
/ (_region.height() + outset.t + outset.b); {
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);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
+1 -1
View File
@@ -81,7 +81,7 @@ namespace canvas
const SGRect<float>& getRegion() const; const SGRect<float>& getRegion() const;
bool handleMouseEvent(MouseEventPtr event); bool handleEvent(EventPtr event);
protected: protected: