#include <simgear/canvas/Canvas.hxx>
#include <simgear/canvas/CanvasPlacement.hxx>
+#include <simgear/scene/util/OsgMath.hxx>
#include <osg/BlendFunc>
#include <osgViewer/Viewer>
#include <osgGA/GUIEventHandler>
#include <boost/bind.hpp>
+#include <boost/lexical_cast.hpp>
/**
* Event handler
{}
bool handle( const osgGA::GUIEventAdapter& ea,
- osgGA::GUIActionAdapter& aa,
+ osgGA::GUIActionAdapter&,
osg::Object*,
osg::NodeVisitor* )
{
canvas::WindowPtr window = _window.lock();
simgear::canvas::CanvasPtr canvas = _canvas.lock();
- if( window && canvas && canvas == window->getCanvas().lock() )
- window->setCanvas( simgear::canvas::CanvasPtr() );
+ if( window && canvas && canvas == window->getCanvasContent().lock() )
+ window->setCanvasContent( simgear::canvas::CanvasPtr() );
}
private:
simgear::canvas::CanvasWeakPtr _canvas;
};
-/**
- * Store pointer to window as user data
- */
-class WindowUserData:
- public osg::Referenced
-{
- public:
- canvas::WindowWeakPtr window;
- WindowUserData(canvas::WindowPtr window):
- window(window)
- {}
-};
-
-//------------------------------------------------------------------------------
-typedef boost::shared_ptr<canvas::Window> WindowPtr;
-WindowPtr windowFactory(SGPropertyNode* node)
-{
- return WindowPtr(new canvas::Window(node));
-}
-
//------------------------------------------------------------------------------
GUIMgr::GUIMgr():
- PropertyBasedMgr( fgGetNode("/sim/gui/canvas", true),
- "window",
- &windowFactory ),
+ Group(simgear::canvas::CanvasPtr(), fgGetNode("/sim/gui/canvas", true)),
_event_handler( new GUIEventHandler(this) ),
- _transform( new osg::MatrixTransform ),
- _width(_props, "size[0]"),
- _height(_props, "size[1]"),
+ _cb_mouse_mode( this,
+ &GUIMgr::handleMouseMode,
+ fgGetNode("/devices/status/mice/mouse[0]/mode") ),
+ _handle_events(true),
+ _width(_node, "size[0]"),
+ _height(_node, "size[1]"),
_resize(canvas::Window::NONE),
_last_cursor(MOUSE_CURSOR_NONE),
+ _last_x(-1),
+ _last_y(-1),
_last_scroll_time(0)
{
+ // We handle the property listener manually within ::init and ::shutdown.
+ removeListener();
+
_width = _height = -1;
+ // Do not change values on reinit
+ _width.node()->setAttribute(SGPropertyNode::PRESERVE, true);
+ _height.node()->setAttribute(SGPropertyNode::PRESERVE, true);
+
osg::Camera* camera =
flightgear::getGUICamera( flightgear::CameraGroup::getDefault() );
assert(camera);
- camera->addChild(_transform);
-
- osg::Viewport* vp = camera->getViewport();
- handleResize(vp->x(), vp->y(), vp->width(), vp->height());
+ camera->addChild( getMatrixTransform() );
simgear::canvas::Canvas::addPlacementFactory
(
stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
}
+//------------------------------------------------------------------------------
+canvas::WindowPtr GUIMgr::createWindow(const std::string& name)
+{
+ canvas::WindowPtr window = createChild<canvas::Window>(name);
+ if( name.empty() )
+ window->set<std::string>
+ (
+ "id",
+ boost::lexical_cast<std::string>(window->getProps()->getIndex())
+ );
+ return window;
+}
+
//------------------------------------------------------------------------------
void GUIMgr::init()
{
- PropertyBasedMgr::init();
+ handleResize
+ (
+ 0,
+ 0,
+ fgGetInt("/sim/startup/xsize"),
+ fgGetInt("/sim/startup/ysize")
+ );
globals->get_renderer()
->getViewer()
->getEventHandlers()
// GUI is on top of everything so lets install as first event handler
.push_front( _event_handler );
+
+ _node->addChangeListener(this);
+ _node->fireCreatedRecursive();
}
//------------------------------------------------------------------------------
void GUIMgr::shutdown()
{
- PropertyBasedMgr::shutdown();
+ _node->removeChangeListener(this);
globals->get_renderer()
->getViewer()
}
//------------------------------------------------------------------------------
-void GUIMgr::elementCreated(simgear::PropertyBasedElementPtr element)
+void GUIMgr::update(double dt)
{
- canvas::WindowPtr window =
- boost::static_pointer_cast<canvas::Window>(element);
-
- size_t layer_index = std::max(0, window->getProps()->getIntValue("layer", 1));
- osg::Group *layer = 0;
-
- if( layer_index < _transform->getNumChildren() )
- {
- layer = _transform->getChild(layer_index)->asGroup();
- assert(layer);
- }
- else
- {
- while( _transform->getNumChildren() <= layer_index )
- {
- layer = new osg::Group;
- _transform->addChild(layer);
- }
- }
- window->getGroup()->setUserData(new WindowUserData(window));
- layer->addChild(window->getGroup());
+ Group::update(dt);
}
//------------------------------------------------------------------------------
}
//------------------------------------------------------------------------------
-canvas::WindowPtr GUIMgr::getWindow(size_t i)
+GUIMgr::ElementFactory GUIMgr::getChildFactory(const std::string& type) const
{
- return boost::static_pointer_cast<canvas::Window>(_elements[i]);
+ if( type == "window" )
+ return &Element::create<canvas::Window>;
+
+ return Group::getChildFactory(type);
}
//------------------------------------------------------------------------------
GUIMgr::addPlacement( SGPropertyNode* node,
simgear::canvas::CanvasPtr canvas )
{
- int placement_index = node->getIntValue("index", -1);
+ const std::string& id = node->getStringValue("id");
simgear::canvas::Placements placements;
- for( size_t i = 0; i < _elements.size(); ++i )
+ canvas::WindowPtr window = getChild<canvas::Window>(id);
+ if( window )
{
- if( placement_index >= 0 && static_cast<int>(i) != placement_index )
- continue;
-
- canvas::WindowPtr window = getWindow(i);
- if( !window )
- continue;
-
- window->setCanvas(canvas);
+ window->setCanvasContent(canvas);
placements.push_back(
simgear::canvas::PlacementPtr(new WindowPlacement(node, window, canvas))
);
//------------------------------------------------------------------------------
bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
{
- if( !_transform->getNumChildren() )
+ if( !_transform->getNumChildren() || !_handle_events )
return false;
namespace sc = simgear::canvas;
- sc::MouseEventPtr event(new sc::MouseEvent);
- event->time = ea.getTime();
+ sc::MouseEventPtr event(new sc::MouseEvent(ea));
event->screen_pos.x() = 0.5 * (ea.getXnormalized() + 1) * _width + 0.5;
event->screen_pos.y() = 0.5 * (ea.getYnormalized() + 1) * _height + 0.5;
_last_x = event->getScreenX();
_last_y = event->getScreenY();
- event->client_pos = event->screen_pos;
- event->button = ea.getButton();
- event->state = ea.getButtonMask();
- event->mod = ea.getModKeyMask();
+ event->local_pos = event->client_pos = event->screen_pos;
if( !_resize_window.expired() )
{
canvas::WindowPtr window_at_cursor;
for( int i = _transform->getNumChildren() - 1; i >= 0; --i )
{
- osg::Group *layer = _transform->getChild(i)->asGroup();
- assert(layer);
- if( !layer->getNumChildren() )
+ osg::Group *element = _transform->getChild(i)->asGroup();
+
+ assert(element);
+ assert(element->getUserData());
+
+ canvas::WindowPtr window =
+ boost::static_pointer_cast<canvas::Window>
+ (
+ static_cast<sc::Element::OSGUserData*>(element->getUserData())->element
+ );
+
+ if( !window->isCapturingEvents() || !window->isVisible() )
continue;
- for( int j = layer->getNumChildren() - 1; j >= 0; --j )
+ float margin = window->isResizable() ? resize_margin_pos : 0;
+ if( window->getScreenRegion().contains( event->getScreenX(),
+ event->getScreenY(),
+ margin ) )
{
- assert(layer->getChild(j)->getUserData());
- canvas::WindowPtr window =
- static_cast<WindowUserData*>(layer->getChild(j)->getUserData())
- ->window.lock();
- float margin = window->isResizable() ? resize_margin_pos : 0;
- if( window->getRegion().contains( event->getScreenX(),
- event->getScreenY(),
- margin ) )
- {
- window_at_cursor = window;
- break;
- }
- }
-
- if( window_at_cursor )
+ window_at_cursor = window;
break;
+ }
}
if( window_at_cursor )
{
- const SGRect<float>& reg = window_at_cursor->getRegion();
+ const SGRect<float>& reg = window_at_cursor->getScreenRegion();
if( window_at_cursor->isResizable()
&& ( ea.getEventType() == osgGA::GUIEventAdapter::MOVE
if( ea.getEventType() == osgGA::GUIEventAdapter::PUSH )
{
_resize_window = window_at_cursor;
- window_at_cursor->doRaise();
+ window_at_cursor->raise();
window_at_cursor->handleResize( _resize | canvas::Window::INIT,
event->delta );
}
{
sc::MouseEventPtr move_event( new sc::MouseEvent(*event) );
move_event->type = sc::Event::MOUSE_LEAVE;
+ move_event->client_pos -= toOsg(last_mouse_over->getPosition());
+ move_event->local_pos = move_event->client_pos;
- // Let the event position be always relative to the top left window
- // corner
- move_event->client_pos.x() -= last_mouse_over->getRegion().x();
- move_event->client_pos.y() -= last_mouse_over->getRegion().y();
-
- last_mouse_over->handleMouseEvent(move_event);
+ last_mouse_over->handleEvent(move_event);
}
_last_mouse_over = window_at_cursor;
event->type = sc::Event::MOUSE_MOVE;
if( target_window )
{
- // Let the event position be always relative to the top left window corner
- event->client_pos.x() -= target_window->getRegion().x();
- event->client_pos.y() -= target_window->getRegion().y();
-
- return target_window->handleMouseEvent(event);
+ event->client_pos -= toOsg(target_window->getPosition());
+ event->local_pos = event->client_pos;
+ return target_window->handleEvent(event);
}
else
return false;
0, _height, 0, 1
));
}
+
+//------------------------------------------------------------------------------
+void GUIMgr::handleMouseMode(SGPropertyNode* node)
+{
+ // pass-through indicates events should pass through to the UI
+ _handle_events = fgGetNode("/input/mice/mouse[0]/mode", node->getIntValue())
+ ->getBoolValue("pass-through");
+}