1 // Canvas gui/dialog manager
3 // Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #include "gui_mgr.hxx"
20 #include <Canvas/window.hxx>
21 #include <Canvas/canvas.hxx>
23 #include <Main/globals.hxx>
24 #include <Viewer/CameraGroup.hxx>
25 #include <Viewer/renderer.hxx>
27 #include <osg/BlendFunc>
28 #include <osgViewer/Viewer>
29 #include <osgGA/GUIEventHandler>
31 #include <boost/bind.hpp>
36 class GUIEventHandler:
37 public osgGA::GUIEventHandler
40 GUIEventHandler(GUIMgr* gui_mgr):
44 bool handle( const osgGA::GUIEventAdapter& ea,
45 osgGA::GUIActionAdapter& aa,
49 return _gui_mgr->handleEvent(ea);
57 * Track a canvas placement on a window
59 class WindowPlacement:
60 public canvas::Placement
63 WindowPlacement( canvas::WindowPtr window,
70 * Remove placement from window
72 virtual ~WindowPlacement()
74 canvas::WindowPtr window = _window.lock();
75 CanvasPtr canvas = _canvas.lock();
77 if( window && canvas && canvas == window->getCanvas().lock() )
78 window->setCanvas( CanvasPtr() );
82 canvas::WindowWeakPtr _window;
83 CanvasWeakPtr _canvas;
86 //------------------------------------------------------------------------------
87 typedef boost::shared_ptr<canvas::Window> WindowPtr;
88 WindowPtr windowFactory(SGPropertyNode* node)
90 return WindowPtr(new canvas::Window(node));
93 //------------------------------------------------------------------------------
95 PropertyBasedMgr("/sim/gui/canvas", "window", &windowFactory),
96 _event_handler( new GUIEventHandler(this) ),
97 _transform( new osg::MatrixTransform ),
98 _width(_props, "size[0]"),
99 _height(_props, "size[1]"),
102 _width = _height = -1;
104 osg::Camera* camera =
105 flightgear::getGUICamera( flightgear::CameraGroup::getDefault() );
107 camera->addChild(_transform);
109 osg::Viewport* vp = camera->getViewport();
110 handleResize(vp->x(), vp->y(), vp->width(), vp->height());
112 Canvas::addPlacementFactory
115 boost::bind(&GUIMgr::addPlacement, this, _1, _2)
118 osg::StateSet* stateSet = _transform->getOrCreateStateSet();
119 stateSet->setDataVariance(osg::Object::STATIC);
120 stateSet->setRenderBinDetails(1000, "RenderBin");
122 // speed optimization?
123 stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
124 stateSet->setAttribute(new osg::BlendFunc(
125 osg::BlendFunc::SRC_ALPHA,
126 osg::BlendFunc::ONE_MINUS_SRC_ALPHA)
128 stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
129 stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
130 stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
131 stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
134 //------------------------------------------------------------------------------
137 PropertyBasedMgr::init();
139 globals->get_renderer()
141 ->addEventHandler( _event_handler );
144 //------------------------------------------------------------------------------
145 void GUIMgr::shutdown()
147 PropertyBasedMgr::shutdown();
149 globals->get_renderer()
151 ->removeEventHandler( _event_handler );
154 //------------------------------------------------------------------------------
155 void GUIMgr::elementCreated(PropertyBasedElementPtr element)
159 static_cast<canvas::Window*>(element.get())->getGroup()
163 //------------------------------------------------------------------------------
164 bool GUIMgr::handleEvent(const osgGA::GUIEventAdapter& ea)
166 switch( ea.getEventType() )
168 case osgGA::GUIEventAdapter::PUSH:
169 case osgGA::GUIEventAdapter::RELEASE:
170 // case osgGA::GUIEventAdapter::DOUBLECLICK:
171 // // DOUBLECLICK doesn't seem to be triggered...
172 case osgGA::GUIEventAdapter::DRAG:
173 case osgGA::GUIEventAdapter::MOVE:
174 case osgGA::GUIEventAdapter::SCROLL:
175 return handleMouse(ea);
176 // case osgGA::GUIEventAdapter::MOVE:
177 // std::cout << "MOVE" << std::endl;
179 case osgGA::GUIEventAdapter::RESIZE:
180 handleResize( ea.getWindowX(),
183 ea.getWindowHeight() );
190 //------------------------------------------------------------------------------
191 canvas::WindowPtr GUIMgr::getWindow(size_t i)
193 return boost::static_pointer_cast<canvas::Window>(_elements[i]);
196 //------------------------------------------------------------------------------
197 canvas::Placements GUIMgr::addPlacement( const SGPropertyNode* node,
200 int placement_index = node->getIntValue("index", -1);
202 canvas::Placements placements;
203 for( size_t i = 0; i < _elements.size(); ++i )
205 if( placement_index > 0 && static_cast<int>(i) != placement_index )
208 canvas::WindowPtr window = getWindow(i);
212 window->setCanvas(canvas);
213 placements.push_back(
214 canvas::PlacementPtr(new WindowPlacement(window, canvas))
220 //------------------------------------------------------------------------------
221 bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
223 canvas::MouseEvent event( ea.getEventType() );
225 event.x = 0.5 * (ea.getXnormalized() + 1) * _width + 0.5;
226 event.y = 0.5 * (ea.getYnormalized() + 1) * _height + 0.5;
227 if( ea.getMouseYOrientation()
228 != osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS )
229 event.y = _height - event.y;
231 event.button = ea.getButton();
232 event.state = ea.getButtonMask();
233 event.mod = ea.getModKeyMask();
234 event.scroll = ea.getScrollingMotion();
236 int window_at_cursor = -1;
237 for( size_t i = 0; i < _elements.size(); ++i )
240 && getWindow(i)->getRegion().contains(event.x, event.y) )
242 window_at_cursor = i;
247 int target_window = window_at_cursor;
248 switch( ea.getEventType() )
250 case osgGA::GUIEventAdapter::PUSH:
251 _last_push = window_at_cursor;
253 case osgGA::GUIEventAdapter::SCROLL:
254 case osgGA::GUIEventAdapter::MOVE:
257 case osgGA::GUIEventAdapter::RELEASE:
261 target_window = _last_push;
265 case osgGA::GUIEventAdapter::DRAG:
266 target_window = _last_push;
273 if( target_window >= 0 )
275 canvas::WindowPtr window = getWindow(target_window);
277 event.dx = event.x - _last_x;
278 event.dy = event.y - _last_y;
283 // Let the event position be always relative to the top left window corner
284 event.x -= window->getRegion().x();
285 event.y -= window->getRegion().y();
287 return window->handleMouseEvent(event);
293 //------------------------------------------------------------------------------
294 void GUIMgr::handleResize(int x, int y, int width, int height)
296 if( _width == width && _height == height )
302 // Origin should be at top left corner, therefore we need to mirror the y-axis
303 _transform->setMatrix(osg::Matrix(