1 // Canvas placement for placing a canvas texture onto osg objects.
3 // It also provides a SGPickCallback for passing mouse events to the canvas and
4 // manages emissive lighting of the placed canvas.
6 // Copyright (C) 2013 Thomas Geymayer <tomgey@gmail.com>
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "CanvasObjectPlacement.hxx"
24 #include "MouseEvent.hxx"
26 #include <simgear/props/props.hxx>
27 #include <simgear/scene/util/SGPickCallback.hxx>
29 #include <osgGA/GUIEventAdapter>
37 * Handle picking events on object with a canvas placed onto
39 class ObjectPickCallback:
44 ObjectPickCallback(const CanvasWeakPtr& canvas):
48 virtual bool needsUV() const { return true; }
50 virtual bool buttonPressed( int,
51 const osgGA::GUIEventAdapter& ea,
54 MouseEventPtr event(new MouseEvent(ea));
55 updatePosFromUV(event, info.uv);
57 if( ea.getEventType() == osgGA::GUIEventAdapter::SCROLL )
59 event->type = Event::WHEEL;
60 event->delta.set(0,0);
61 switch( ea.getScrollingMotion() )
63 case osgGA::GUIEventAdapter::SCROLL_UP:
66 case osgGA::GUIEventAdapter::SCROLL_DOWN:
67 event->delta.y() = -1;
75 event->type = Event::MOUSE_DOWN;
78 return handleEvent(event);
81 virtual void buttonReleased( int,
82 const osgGA::GUIEventAdapter& ea,
85 if( ea.getEventType() != osgGA::GUIEventAdapter::RELEASE )
88 MouseEventPtr event(new MouseEvent(ea));
89 event->type = Event::MOUSE_UP;
90 updatePosFromUV(event, info ? info->uv : SGVec2d(-1,-1));
95 virtual void mouseMoved( const osgGA::GUIEventAdapter& ea,
98 // drag (currently only with LMB)
99 if( ea.getEventType() != osgGA::GUIEventAdapter::DRAG )
102 MouseEventPtr event(new MouseEvent(ea));
103 event->type = Event::DRAG;
104 updatePosFromUV(event, info ? info->uv : SGVec2d(-1,-1));
109 virtual bool hover( const osg::Vec2d& windowPos,
112 // TODO somehow get more info about event (time, modifiers, pressed
114 MouseEventPtr event(new MouseEvent);
115 event->type = Event::MOUSE_MOVE;
116 event->screen_pos = windowPos;
117 updatePosFromUV(event, info.uv);
119 return handleEvent(event);
122 virtual void mouseLeave( const osg::Vec2d& windowPos )
124 MouseEventPtr event(new MouseEvent);
125 event->type = Event::MOUSE_LEAVE;
126 event->screen_pos = windowPos;
132 CanvasWeakPtr _canvas;
133 osg::Vec2f _last_pos,
136 void updatePosFromUV(const MouseEventPtr& event, const SGVec2d& uv)
138 CanvasPtr canvas = _canvas.lock();
142 osg::Vec2d pos( uv.x() * canvas->getViewWidth(),
143 (1 - uv.y()) * canvas->getViewHeight() );
145 _last_delta = pos - _last_pos;
148 event->client_pos = pos;
149 event->delta = _last_delta;
152 bool handleEvent(const MouseEventPtr& event)
154 CanvasPtr canvas = _canvas.lock();
158 return canvas->handleMouseEvent(event);
162 //----------------------------------------------------------------------------
163 ObjectPlacement::ObjectPlacement( SGPropertyNode* node,
164 const GroupPtr& group,
165 const CanvasWeakPtr& canvas ):
170 // TODO make more generic and extendable for more properties
171 if( node->hasValue("emission") )
172 setEmission( node->getFloatValue("emission") );
173 if( node->hasValue("capture-events") )
174 setCaptureEvents( node->getBoolValue("capture-events") );
177 //----------------------------------------------------------------------------
178 ObjectPlacement::~ObjectPlacement()
180 assert( _group->getNumChildren() == 1 );
181 osg::Node *child = _group->getChild(0);
183 if( _group->getNumParents() )
185 osg::Group *parent = _group->getParent(0);
186 parent->addChild(child);
187 parent->removeChild(_group);
190 _group->removeChild(child);
193 //----------------------------------------------------------------------------
194 void ObjectPlacement::setEmission(float emit)
196 emit = SGMiscf::clip(emit, 0, 1);
200 _material = new osg::Material;
201 _material->setColorMode(osg::Material::OFF);
202 _material->setDataVariance(osg::Object::DYNAMIC);
203 _group->getOrCreateStateSet()
204 ->setAttribute(_material, ( osg::StateAttribute::ON
205 | osg::StateAttribute::OVERRIDE ) );
208 _material->setEmission(
209 osg::Material::FRONT_AND_BACK,
210 osg::Vec4(emit, emit, emit, emit)
214 //----------------------------------------------------------------------------
215 void ObjectPlacement::setCaptureEvents(bool enable)
217 if( !enable && _scene_user_data )
220 if( enable && !_pick_cb )
221 _pick_cb = new ObjectPickCallback(_canvas);
223 _scene_user_data = SGSceneUserData::getOrCreateSceneUserData(_group);
224 _scene_user_data->setPickCallback(enable ? _pick_cb.get() : 0);
227 //----------------------------------------------------------------------------
228 bool ObjectPlacement::childChanged(SGPropertyNode* node)
230 if( node->getParent() != _node )
233 if( node->getNameString() == "emission" )
234 setEmission( node->getFloatValue() );
235 else if( node->getNameString() == "capture-events" )
236 setCaptureEvents( node->getBoolValue() );
243 } // namespace canvas
244 } // namespace simgear