CanvasEventTypes.hxx
CanvasEventVisitor.hxx
CanvasMgr.hxx
+ CanvasObjectPlacement.hxx
CanvasPlacement.hxx
CanvasSystemAdapter.hxx
MouseEvent.hxx
CanvasEventManager.cxx
CanvasEventVisitor.cxx
CanvasMgr.cxx
+ CanvasObjectPlacement.cxx
CanvasPlacement.cxx
ODGauge.cxx
VGInitOperation.cxx
--- /dev/null
+// Canvas placement for placing a canvas texture onto osg objects.
+//
+// It also provides a SGPickCallback for passing mouse events to the canvas and
+// manages emissive lighting of the placed canvas.
+//
+// Copyright (C) 2013 Thomas Geymayer <tomgey@gmail.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+
+#include "Canvas.hxx"
+#include "CanvasObjectPlacement.hxx"
+#include "MouseEvent.hxx"
+
+#include <simgear/props/props.hxx>
+#include <simgear/scene/util/SGPickCallback.hxx>
+
+#include <osgGA/GUIEventAdapter>
+
+namespace simgear
+{
+namespace canvas
+{
+
+ /**
+ * Handle picking events on object with a canvas placed onto
+ */
+ class ObjectPickCallback:
+ public SGPickCallback
+ {
+ public:
+
+ ObjectPickCallback(const CanvasWeakPtr& canvas):
+ _canvas(canvas)
+ {}
+
+ virtual bool needsUV() const { return true; }
+
+ virtual bool buttonPressed( int,
+ const osgGA::GUIEventAdapter& ea,
+ const Info& info )
+ {
+ MouseEventPtr event(new MouseEvent(ea));
+ updatePosFromUV(event, info.uv);
+
+ if( ea.getEventType() == osgGA::GUIEventAdapter::SCROLL )
+ {
+ event->type = Event::WHEEL;
+ event->delta.set(0,0);
+ switch( ea.getScrollingMotion() )
+ {
+ case osgGA::GUIEventAdapter::SCROLL_UP:
+ event->delta.y() = 1;
+ break;
+ case osgGA::GUIEventAdapter::SCROLL_DOWN:
+ event->delta.y() = -1;
+ break;
+ default:
+ return false;
+ }
+ }
+ else
+ {
+ event->type = Event::MOUSE_DOWN;
+ }
+
+ return handleEvent(event);
+ }
+
+ virtual void buttonReleased( int,
+ const osgGA::GUIEventAdapter& ea,
+ const Info* info )
+ {
+ if( ea.getEventType() != osgGA::GUIEventAdapter::RELEASE )
+ return;
+
+ MouseEventPtr event(new MouseEvent(ea));
+ event->type = Event::MOUSE_UP;
+ updatePosFromUV(event, info ? info->uv : SGVec2d(-1,-1));
+
+ handleEvent(event);
+ }
+
+ virtual void mouseMoved( const osgGA::GUIEventAdapter& ea,
+ const Info* info )
+ {
+ // drag (currently only with LMB)
+ if( ea.getEventType() != osgGA::GUIEventAdapter::DRAG )
+ return;
+
+ MouseEventPtr event(new MouseEvent(ea));
+ event->type = Event::DRAG;
+ updatePosFromUV(event, info ? info->uv : SGVec2d(-1,-1));
+
+ handleEvent(event);
+ }
+
+ virtual bool hover( const osg::Vec2d& windowPos,
+ const Info& info )
+ {
+ // TODO somehow get more info about event (time, modifiers, pressed
+ // buttons, ...)
+ MouseEventPtr event(new MouseEvent);
+ event->type = Event::MOUSE_MOVE;
+ event->screen_pos = windowPos;
+ updatePosFromUV(event, info.uv);
+
+ return handleEvent(event);
+ }
+
+ virtual void mouseLeave( const osg::Vec2d& windowPos )
+ {
+ MouseEventPtr event(new MouseEvent);
+ event->type = Event::MOUSE_LEAVE;
+ event->screen_pos = windowPos;
+
+ handleEvent(event);
+ }
+
+ protected:
+ CanvasWeakPtr _canvas;
+ osg::Vec2f _last_pos,
+ _last_delta;
+
+ void updatePosFromUV(const MouseEventPtr& event, const SGVec2d& uv)
+ {
+ CanvasPtr canvas = _canvas.lock();
+ if( !canvas )
+ return;
+
+ osg::Vec2d pos( uv.x() * canvas->getViewWidth(),
+ (1 - uv.y()) * canvas->getViewHeight() );
+
+ _last_delta = pos - _last_pos;
+ _last_pos = pos;
+
+ event->client_pos = pos;
+ event->delta = _last_delta;
+ }
+
+ bool handleEvent(const MouseEventPtr& event)
+ {
+ CanvasPtr canvas = _canvas.lock();
+ if( !canvas )
+ return false;
+
+ return canvas->handleMouseEvent(event);
+ }
+ };
+
+ //----------------------------------------------------------------------------
+ ObjectPlacement::ObjectPlacement( SGPropertyNode* node,
+ const GroupPtr& group,
+ const CanvasWeakPtr& canvas ):
+ Placement(node),
+ _group(group),
+ _canvas(canvas)
+ {
+ // TODO make more generic and extendable for more properties
+ if( node->hasValue("emission") )
+ setEmission( node->getFloatValue("emission") );
+ if( node->hasValue("capture-events") )
+ setCaptureEvents( node->getBoolValue("capture-events") );
+ }
+
+ //----------------------------------------------------------------------------
+ ObjectPlacement::~ObjectPlacement()
+ {
+ assert( _group->getNumChildren() == 1 );
+ osg::Node *child = _group->getChild(0);
+
+ if( _group->getNumParents() )
+ {
+ osg::Group *parent = _group->getParent(0);
+ parent->addChild(child);
+ parent->removeChild(_group);
+ }
+
+ _group->removeChild(child);
+ }
+
+ //----------------------------------------------------------------------------
+ void ObjectPlacement::setEmission(float emit)
+ {
+ emit = SGMiscf::clip(emit, 0, 1);
+
+ if( !_material )
+ {
+ _material = new osg::Material;
+ _material->setColorMode(osg::Material::OFF);
+ _material->setDataVariance(osg::Object::DYNAMIC);
+ _group->getOrCreateStateSet()
+ ->setAttribute(_material, ( osg::StateAttribute::ON
+ | osg::StateAttribute::OVERRIDE ) );
+ }
+
+ _material->setEmission(
+ osg::Material::FRONT_AND_BACK,
+ osg::Vec4(emit, emit, emit, emit)
+ );
+ }
+
+ //----------------------------------------------------------------------------
+ void ObjectPlacement::setCaptureEvents(bool enable)
+ {
+ if( !enable && _scene_user_data )
+ return;
+
+ if( enable && !_pick_cb )
+ _pick_cb = new ObjectPickCallback(_canvas);
+
+ _scene_user_data = SGSceneUserData::getOrCreateSceneUserData(_group);
+ _scene_user_data->setPickCallback(enable ? _pick_cb.get() : 0);
+ }
+
+ //----------------------------------------------------------------------------
+ bool ObjectPlacement::childChanged(SGPropertyNode* node)
+ {
+ if( node->getParent() != _node )
+ return false;
+
+ if( node->getNameString() == "emission" )
+ setEmission( node->getFloatValue() );
+ else if( node->getNameString() == "capture-events" )
+ setCaptureEvents( node->getBoolValue() );
+ else
+ return false;
+
+ return true;
+ }
+
+} // namespace canvas
+} // namespace simgear
--- /dev/null
+// Canvas placement for placing a canvas texture onto osg objects.
+//
+// It also provides a SGPickCallback for passing mouse events to the canvas and
+// manages emissive lighting of the placed canvas.
+//
+// Copyright (C) 2013 Thomas Geymayer <tomgey@gmail.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+
+#ifndef CANVAS_PICK_PLACEMENT_HXX_
+#define CANVAS_OBJECT_PLACEMENT_HXX_
+
+#include "CanvasPlacement.hxx"
+#include "canvas_fwd.hxx"
+
+#include <simgear/scene/util/SGSceneUserData.hxx>
+#include <osg/Material>
+
+namespace simgear
+{
+namespace canvas
+{
+
+ class ObjectPlacement:
+ public Placement
+ {
+ public:
+
+ typedef osg::ref_ptr<osg::Group> GroupPtr;
+ typedef osg::ref_ptr<osg::Material> MaterialPtr;
+
+ ObjectPlacement( SGPropertyNode* node,
+ const GroupPtr& group,
+ const CanvasWeakPtr& canvas );
+ virtual ~ObjectPlacement();
+
+ /**
+ * Set emissive lighting of the object the canvas is placed on.
+ */
+ void setEmission(float emit);
+
+ /**
+ * Set whether pick events should be captured.
+ */
+ void setCaptureEvents(bool enable);
+
+ virtual bool childChanged(SGPropertyNode* child);
+
+ protected:
+ typedef SGSharedPtr<SGPickCallback> PickCallbackPtr;
+ typedef osg::ref_ptr<SGSceneUserData> SGSceneUserDataPtr;
+
+ GroupPtr _group;
+ MaterialPtr _material;
+ CanvasWeakPtr _canvas;
+ PickCallbackPtr _pick_cb;
+ SGSceneUserDataPtr _scene_user_data;
+ };
+
+} // namespace canvas
+} // namespace simgear
+
+#endif /* CANVAS_PICK_PLACEMENT_HXX_ */
click_count(0)
{}
+ MouseEvent(const osgGA::GUIEventAdapter& ea):
+ button(ea.getButton()),
+ state(ea.getButtonMask()),
+ mod(ea.getModKeyMask()),
+ click_count(0)
+ {
+ time = ea.getTime();
+ }
+
osg::Vec2f getScreenPos() const { return screen_pos; }
osg::Vec2f getClientPos() const { return client_pos; }
osg::Vec2f getDelta() const { return delta; }
}
-osg::Vec2d eventToWindowCoords(const osgGA::GUIEventAdapter* ea)
+osg::Vec2d eventToWindowCoords(const osgGA::GUIEventAdapter& ea)
{
using namespace osg;
- const GraphicsContext* gc = ea->getGraphicsContext();
+ const GraphicsContext* gc = ea.getGraphicsContext();
const GraphicsContext::Traits* traits = gc->getTraits() ;
// Scale x, y to the dimensions of the window
- double x = (((ea->getX() - ea->getXmin()) / (ea->getXmax() - ea->getXmin()))
+ double x = (((ea.getX() - ea.getXmin()) / (ea.getXmax() - ea.getXmin()))
* (double)traits->width);
- double y = (((ea->getY() - ea->getYmin()) / (ea->getYmax() - ea->getYmin()))
+ double y = (((ea.getY() - ea.getYmin()) / (ea.getYmax() - ea.getYmin()))
* (double)traits->height);
- if (ea->getMouseYOrientation() == osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS)
+ if (ea.getMouseYOrientation() == osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS)
y = (double)traits->height - y;
return osg::Vec2d(x, y);
_hover = readBindingList(hoverNode->getChildren("binding"), modelRoot);
}
- virtual bool buttonPressed(int button, const osgGA::GUIEventAdapter* ea, const Info&)
+ virtual bool buttonPressed( int button,
+ const osgGA::GUIEventAdapter&,
+ const Info& )
{
if (_buttons.find(button) == _buttons.end()) {
return false;
_repeatTime = -_repeatInterval; // anti-bobble: delay start of repeat
return true;
}
- virtual void buttonReleased(int keyModState)
+ virtual void buttonReleased( int keyModState,
+ const osgGA::GUIEventAdapter&,
+ const Info* )
{
SG_UNUSED(keyModState);
fireBindingList(_bindingsUp);
}
}
- virtual bool hover(const osg::Vec2d& windowPos, const Info& info)
+ virtual bool hover( const osg::Vec2d& windowPos,
+ const Info& )
{
if (_hover.empty()) {
return false;
_squaredDown = dot(_toDown, _toDown);
}
- virtual bool buttonPressed(int button, const osgGA::GUIEventAdapter* ea, const Info& info)
+ virtual bool buttonPressed( int button,
+ const osgGA::GUIEventAdapter&,
+ const Info& info )
{
SGVec3d loc(info.local);
SG_LOG(SG_INPUT, SG_DEBUG, "VNC pressed " << button << ": " << loc);
return vv.wasSuccessful();
}
- virtual void buttonReleased(int keyModState)
+ virtual void buttonReleased( int keyModState,
+ const osgGA::GUIEventAdapter&,
+ const Info* )
{
SG_UNUSED(keyModState);
SG_LOG(SG_INPUT, SG_DEBUG, "VNC release");
}
}
- virtual bool buttonPressed(int button, const osgGA::GUIEventAdapter* ea, const Info&)
+ virtual bool buttonPressed( int button,
+ const osgGA::GUIEventAdapter& ea,
+ const Info& )
{
// the 'be nice to Mac / laptop' users option; alt-clicking spins the
// opposite direction. Should make this configurable
- if ((button == 0) && (ea->getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_ALT)) {
+ if ((button == 0) && (ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_ALT)) {
button = 1;
}
return true;
}
- virtual void buttonReleased(int keyModState)
+ virtual void buttonReleased( int keyModState,
+ const osgGA::GUIEventAdapter&,
+ const Info* )
{
// for *clicks*, we only fire on button release
if (!_hasDragged) {
return _dragDirection;
}
- virtual void mouseMoved(const osgGA::GUIEventAdapter* ea)
+ virtual void mouseMoved( const osgGA::GUIEventAdapter& ea,
+ const Info* )
{
_mousePos = eventToWindowCoords(ea);
osg::Vec2d deltaMouse = _mousePos - _lastFirePos;
if (fabs(delta) >= 1.0) {
// determine direction from sign of delta
Direction dir = (delta > 0.0) ? DIRECTION_INCREASE : DIRECTION_DECREASE;
- fire(ea->getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_SHIFT, dir);
+ fire(ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_SHIFT, dir);
_lastFirePos = _mousePos;
}
}
} // of repeat iteration
}
- virtual bool hover(const osg::Vec2d& windowPos, const Info& info)
+ virtual bool hover( const osg::Vec2d& windowPos,
+ const Info& )
{
if (_hover.empty()) {
return false;
{ }
virtual ~SGPickCallback() {}
- virtual bool buttonPressed(int button, const osgGA::GUIEventAdapter* event, const Info& info)
+
+ // TODO maybe better provide a single callback to handle all events
+ virtual bool buttonPressed( int button,
+ const osgGA::GUIEventAdapter& ea,
+ const Info& info )
{ return false; }
virtual void update(double dt, int keyModState)
{ }
-
- virtual void buttonReleased(int keyModState)
+
+ /**
+ * @param info Can be null if no info is available (eg. mouse not over 3d
+ * object anymore)
+ */
+ virtual void buttonReleased( int keyModState,
+ const osgGA::GUIEventAdapter& ea,
+ const Info* info )
+ { }
+
+ /**
+ * @param info Can be null if no info is available (eg. mouse not over 3d
+ * object anymore)
+ */
+ virtual void mouseMoved( const osgGA::GUIEventAdapter& ea,
+ const Info* info )
{ }
- virtual void mouseMoved(const osgGA::GUIEventAdapter* event)
+ /**
+ * The mouse is not hovering anymore over the element.
+ */
+ virtual void mouseLeave(const osg::Vec2d& windowPos)
{ }
- virtual bool hover(const osg::Vec2d& windowPos, const Info& info)
+ virtual bool hover( const osg::Vec2d& windowPos,
+ const Info& info )
{ return false; }
virtual Priority getPriority() const