Canvas: First version of new Canvas GUI system.
- Refactor CanvasMgr into PropertyBasedMgr to be also used for the Canvas GUI system. - Get rid of tied properties in the Canvas system. - Add new placement type 'window' for placing canvases onto windows - Pass mouse events to Window class (only if cursor is over window) - Refactor canvas placement clean up
This commit is contained in:
parent
5f08e10c0a
commit
8a6a234653
25 changed files with 1477 additions and 464 deletions
|
@ -8,7 +8,12 @@ set(SOURCES
|
|||
elements/map.cxx
|
||||
elements/path.cxx
|
||||
elements/text.cxx
|
||||
gui_mgr.cxx
|
||||
placement.cxx
|
||||
property_based_element.cxx
|
||||
property_based_mgr.cxx
|
||||
property_helper.cxx
|
||||
window.cxx
|
||||
)
|
||||
|
||||
set(HEADERS
|
||||
|
@ -19,7 +24,12 @@ set(HEADERS
|
|||
elements/map.hxx
|
||||
elements/path.hxx
|
||||
elements/text.hxx
|
||||
gui_mgr.hxx
|
||||
placement.hxx
|
||||
property_based_element.hxx
|
||||
property_based_mgr.hxx
|
||||
property_helper.hxx
|
||||
window.hxx
|
||||
)
|
||||
|
||||
flightgear_component(Canvas "${SOURCES}" "${HEADERS}")
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "canvas.hxx"
|
||||
#include "elements/group.hxx"
|
||||
#include "mouse_event.hxx"
|
||||
|
||||
#include <Canvas/property_helper.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
|
@ -31,172 +32,95 @@
|
|||
#include <osgText/Text>
|
||||
#include <osgViewer/Viewer>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <iostream>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Callback used to disable/enable rendering to the texture if it is not
|
||||
* visible
|
||||
*/
|
||||
class CameraCullCallback:
|
||||
public osg::NodeCallback
|
||||
//----------------------------------------------------------------------------
|
||||
Canvas::CameraCullCallback::CameraCullCallback():
|
||||
_render( true ),
|
||||
_render_frame( 0 )
|
||||
{
|
||||
public:
|
||||
|
||||
CameraCullCallback():
|
||||
_render( true ),
|
||||
_render_frame( 0 )
|
||||
{}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable rendering for the next frame
|
||||
*/
|
||||
void enableRendering()
|
||||
{
|
||||
_render = true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool _render;
|
||||
unsigned int _render_frame;
|
||||
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
if( !_render && nv->getTraversalNumber() != _render_frame )
|
||||
return;
|
||||
|
||||
traverse(node, nv);
|
||||
|
||||
_render = false;
|
||||
_render_frame = nv->getTraversalNumber();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This callback is installed on every placement of the canvas in the scene to
|
||||
* only render the canvas if at least one placement is visible
|
||||
*/
|
||||
class PlacementCullCallback:
|
||||
public osg::NodeCallback
|
||||
//----------------------------------------------------------------------------
|
||||
void Canvas::CameraCullCallback::enableRendering()
|
||||
{
|
||||
public:
|
||||
_render = true;
|
||||
}
|
||||
|
||||
PlacementCullCallback(Canvas* canvas, CameraCullCallback* camera_cull):
|
||||
_canvas( canvas ),
|
||||
_camera_cull( camera_cull )
|
||||
{}
|
||||
//----------------------------------------------------------------------------
|
||||
void Canvas::CameraCullCallback::operator()( osg::Node* node,
|
||||
osg::NodeVisitor* nv )
|
||||
{
|
||||
if( !_render && nv->getTraversalNumber() != _render_frame )
|
||||
return;
|
||||
|
||||
private:
|
||||
traverse(node, nv);
|
||||
|
||||
Canvas *_canvas;
|
||||
CameraCullCallback *_camera_cull;
|
||||
_render = false;
|
||||
_render_frame = nv->getTraversalNumber();
|
||||
}
|
||||
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
if( nv->getTraversalMask() & simgear::MODEL_BIT )
|
||||
_camera_cull->enableRendering();
|
||||
//----------------------------------------------------------------------------
|
||||
Canvas::CullCallback::CullCallback(CameraCullCallback* camera_cull):
|
||||
_camera_cull( camera_cull )
|
||||
{
|
||||
|
||||
traverse(node, nv);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Canvas::CullCallback::operator()( osg::Node* node,
|
||||
osg::NodeVisitor* nv )
|
||||
{
|
||||
if( nv->getTraversalMask() & simgear::MODEL_BIT )
|
||||
_camera_cull->enableRendering();
|
||||
|
||||
traverse(node, nv);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Canvas::Canvas():
|
||||
Canvas::Canvas(SGPropertyNode* node):
|
||||
PropertyBasedElement(node),
|
||||
_size_x(-1),
|
||||
_size_y(-1),
|
||||
_view_width(-1),
|
||||
_view_height(-1),
|
||||
_status(0),
|
||||
_status(node, "status"),
|
||||
_status_msg(node, "status-msg"),
|
||||
_mouse_x(node, "mouse/x"),
|
||||
_mouse_y(node, "mouse/y"),
|
||||
_mouse_dx(node, "mouse/dx"),
|
||||
_mouse_dy(node, "mouse/dy"),
|
||||
_mouse_button(node, "mouse/button"),
|
||||
_mouse_state(node, "mouse/state"),
|
||||
_mouse_mod(node, "mouse/mod"),
|
||||
_mouse_scroll(node, "mouse/scroll"),
|
||||
_mouse_event(node, "mouse/event"),
|
||||
_sampling_dirty(false),
|
||||
_color_dirty(true),
|
||||
_node(0),
|
||||
_root_group( new canvas::Group(node) ),
|
||||
_render_always(false)
|
||||
{
|
||||
_status = 0;
|
||||
setStatusFlags(MISSING_SIZE_X | MISSING_SIZE_Y);
|
||||
|
||||
_camera_callback = new CameraCullCallback;
|
||||
_cull_callback = new PlacementCullCallback(this, _camera_callback);
|
||||
_cull_callback = new CullCallback(_camera_callback);
|
||||
|
||||
canvas::linkColorNodes
|
||||
(
|
||||
"color-background",
|
||||
_node,
|
||||
_color_background,
|
||||
osg::Vec4f(0,0,0,1)
|
||||
);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Canvas::~Canvas()
|
||||
{
|
||||
clearPlacements();
|
||||
|
||||
unbind();
|
||||
_node = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int Canvas::getStatus() const
|
||||
{
|
||||
return _status;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Canvas::reset(SGPropertyNode* node)
|
||||
{
|
||||
if( node )
|
||||
SG_LOG
|
||||
(
|
||||
SG_GL,
|
||||
SG_INFO,
|
||||
"Canvas::reset() texture[" << node->getIndex() << "]"
|
||||
);
|
||||
|
||||
unbind();
|
||||
|
||||
_node = node;
|
||||
setStatusFlags(MISSING_SIZE_X | MISSING_SIZE_Y);
|
||||
|
||||
if( _node )
|
||||
{
|
||||
_root_group.reset( new canvas::Group(_node) );
|
||||
_node->tie
|
||||
(
|
||||
"size[0]",
|
||||
SGRawValueMethods<Canvas, int>( *this, &Canvas::getSizeX,
|
||||
&Canvas::setSizeX )
|
||||
);
|
||||
_node->tie
|
||||
(
|
||||
"size[1]",
|
||||
SGRawValueMethods<Canvas, int>( *this, &Canvas::getSizeY,
|
||||
&Canvas::setSizeY )
|
||||
);
|
||||
_node->tie
|
||||
(
|
||||
"view[0]",
|
||||
SGRawValueMethods<Canvas, int>( *this, &Canvas::getViewWidth,
|
||||
&Canvas::setViewWidth )
|
||||
);
|
||||
_node->tie
|
||||
(
|
||||
"view[1]",
|
||||
SGRawValueMethods<Canvas, int>( *this, &Canvas::getViewHeight,
|
||||
&Canvas::setViewHeight )
|
||||
);
|
||||
_node->tie
|
||||
(
|
||||
"status",
|
||||
SGRawValueMethods<Canvas, int>(*this, &Canvas::getStatus)
|
||||
);
|
||||
_node->tie
|
||||
(
|
||||
"status-msg",
|
||||
SGRawValueMethods<Canvas, const char*>(*this, &Canvas::getStatusMsg)
|
||||
);
|
||||
_node->addChangeListener(this);
|
||||
|
||||
canvas::linkColorNodes
|
||||
(
|
||||
"color-background",
|
||||
_node,
|
||||
_color_background,
|
||||
osg::Vec4f(0,0,0,1)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -257,15 +181,29 @@ void Canvas::update(double delta_time_sec)
|
|||
// New placement
|
||||
_placements.resize(node->getIndex() + 1);
|
||||
else
|
||||
// Remove maybe already existing placements
|
||||
clearPlacements(node->getIndex());
|
||||
// Remove possibly existing placements
|
||||
_placements[ node->getIndex() ].clear();
|
||||
|
||||
// add new placements
|
||||
_placements[node->getIndex()] = _texture.set_texture(
|
||||
node,
|
||||
_texture.getTexture(),
|
||||
_cull_callback
|
||||
);
|
||||
// Get new placements
|
||||
PlacementFactoryMap::const_iterator placement_factory =
|
||||
_placement_factories.find( node->getStringValue("type", "object") );
|
||||
if( placement_factory != _placement_factories.end() )
|
||||
{
|
||||
canvas::Placements& placements =
|
||||
_placements[ node->getIndex() ] =
|
||||
placement_factory->second
|
||||
(
|
||||
node,
|
||||
boost::shared_static_cast<Canvas>(_self.lock())
|
||||
);
|
||||
node->setStringValue
|
||||
(
|
||||
"status-msg",
|
||||
placements.empty() ? "No match" : "Ok"
|
||||
);
|
||||
}
|
||||
else
|
||||
node->setStringValue("status-msg", "Unknown placement type");
|
||||
}
|
||||
|
||||
if( _render_always )
|
||||
|
@ -290,12 +228,6 @@ void Canvas::setSizeX(int sx)
|
|||
setStatusFlags(CREATE_FAILED, false);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int Canvas::getSizeX() const
|
||||
{
|
||||
return _size_x;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Canvas::setSizeY(int sy)
|
||||
{
|
||||
|
@ -314,12 +246,6 @@ void Canvas::setSizeY(int sy)
|
|||
setStatusFlags(CREATE_FAILED, false);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int Canvas::getSizeY() const
|
||||
{
|
||||
return _size_y;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Canvas::setViewWidth(int w)
|
||||
{
|
||||
|
@ -330,12 +256,6 @@ void Canvas::setViewWidth(int w)
|
|||
_texture.setViewSize(_view_width, _view_height);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int Canvas::getViewWidth() const
|
||||
{
|
||||
return _view_width;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Canvas::setViewHeight(int h)
|
||||
{
|
||||
|
@ -347,15 +267,19 @@ void Canvas::setViewHeight(int h)
|
|||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int Canvas::getViewHeight() const
|
||||
bool Canvas::handleMouseEvent(const canvas::MouseEvent& event)
|
||||
{
|
||||
return _view_height;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
const char* Canvas::getStatusMsg() const
|
||||
{
|
||||
return _status_msg.c_str();
|
||||
_mouse_x = event.x;
|
||||
_mouse_y = event.y;
|
||||
_mouse_dx = event.dx;
|
||||
_mouse_dy = event.dy;
|
||||
_mouse_button = event.button;
|
||||
_mouse_state = event.state;
|
||||
_mouse_mod = event.mod;
|
||||
_mouse_scroll = event.scroll;
|
||||
// Always set event type last because all listeners are attached to it
|
||||
_mouse_event = event.type;
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -380,7 +304,7 @@ void Canvas::childRemoved( SGPropertyNode * parent,
|
|||
return;
|
||||
|
||||
if( child->getNameString() == "placement" )
|
||||
clearPlacements(child->getIndex());
|
||||
_placements[ child->getIndex() ].clear();
|
||||
else
|
||||
static_cast<canvas::Element*>(_root_group.get())
|
||||
->childRemoved(parent, child);
|
||||
|
@ -389,6 +313,9 @@ void Canvas::childRemoved( SGPropertyNode * parent,
|
|||
//----------------------------------------------------------------------------
|
||||
void Canvas::valueChanged(SGPropertyNode* node)
|
||||
{
|
||||
if( boost::starts_with(node->getNameString(), "status") )
|
||||
return;
|
||||
|
||||
if( node->getParent()->getParent() == _node )
|
||||
{
|
||||
if( !_color_background.empty()
|
||||
|
@ -416,11 +343,31 @@ void Canvas::valueChanged(SGPropertyNode* node)
|
|||
_sampling_dirty = true;
|
||||
else if( node->getNameString() == "render-always" )
|
||||
_render_always = node->getBoolValue();
|
||||
else if( node->getNameString() == "size" )
|
||||
{
|
||||
if( node->getIndex() == 0 )
|
||||
setSizeX( node->getIntValue() );
|
||||
else if( node->getIndex() == 1 )
|
||||
setSizeY( node->getIntValue() );
|
||||
}
|
||||
else if( node->getNameString() == "view" )
|
||||
{
|
||||
if( node->getIndex() == 0 )
|
||||
setViewWidth( node->getIntValue() );
|
||||
else if( node->getIndex() == 1 )
|
||||
setViewHeight( node->getIntValue() );
|
||||
}
|
||||
}
|
||||
|
||||
_root_group->valueChanged(node);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
osg::Texture2D* Canvas::getTexture() const
|
||||
{
|
||||
return _texture.getTexture();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
GLuint Canvas::getTexId() const
|
||||
{
|
||||
|
@ -449,13 +396,41 @@ GLuint Canvas::getTexId() const
|
|||
return tobj->_id;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Canvas::CameraCullCallbackPtr Canvas::getCameraCullCallback() const
|
||||
{
|
||||
return _camera_callback;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Canvas::CullCallbackPtr Canvas::getCullCallback() const
|
||||
{
|
||||
return _cull_callback;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Canvas::addPlacementFactory( const std::string& type,
|
||||
canvas::PlacementFactory factory )
|
||||
{
|
||||
if( _placement_factories.find(type) != _placement_factories.end() )
|
||||
SG_LOG
|
||||
(
|
||||
SG_GENERAL,
|
||||
SG_WARN,
|
||||
"Canvas::addPlacementFactory: replace existing factor for type " << type
|
||||
);
|
||||
|
||||
_placement_factories[type] = factory;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Canvas::setStatusFlags(unsigned int flags, bool set)
|
||||
{
|
||||
if( set )
|
||||
_status |= flags;
|
||||
_status = _status | flags;
|
||||
else
|
||||
_status &= ~flags;
|
||||
_status = _status & ~flags;
|
||||
// TODO maybe extend simgear::PropertyObject to allow |=, &= etc.
|
||||
|
||||
if( (_status & MISSING_SIZE_X) && (_status & MISSING_SIZE_Y) )
|
||||
_status_msg = "Missing size";
|
||||
|
@ -472,47 +447,4 @@ void Canvas::setStatusFlags(unsigned int flags, bool set)
|
|||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Canvas::clearPlacements(int index)
|
||||
{
|
||||
Placements& placements = _placements.at(index);
|
||||
while( !placements.empty() )
|
||||
{
|
||||
osg::ref_ptr<osg::Group> group = placements.back();
|
||||
placements.pop_back();
|
||||
|
||||
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 Canvas::clearPlacements()
|
||||
{
|
||||
for(size_t i = 0; i < _placements.size(); ++i)
|
||||
clearPlacements(i);
|
||||
_placements.clear();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Canvas::unbind()
|
||||
{
|
||||
if( !_node )
|
||||
return;
|
||||
|
||||
_node->untie("size[0]");
|
||||
_node->untie("size[1]");
|
||||
_node->untie("view[0]");
|
||||
_node->untie("view[1]");
|
||||
_node->untie("status");
|
||||
_node->untie("status-msg");
|
||||
_node->removeChangeListener(this);
|
||||
}
|
||||
Canvas::PlacementFactoryMap Canvas::_placement_factories;
|
||||
|
|
|
@ -19,21 +19,20 @@
|
|||
#ifndef CANVAS_HXX_
|
||||
#define CANVAS_HXX_
|
||||
|
||||
#include "placement.hxx"
|
||||
#include "property_based_element.hxx"
|
||||
|
||||
#include <Canvas/canvas_fwd.hpp>
|
||||
#include <Instrumentation/od_gauge.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
#include <simgear/props/propertyObject.hxx>
|
||||
#include <osg/NodeCallback>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace canvas
|
||||
{
|
||||
class Group;
|
||||
}
|
||||
|
||||
class CameraCullCallback;
|
||||
class Canvas:
|
||||
public SGPropertyChangeListener
|
||||
public PropertyBasedElement
|
||||
{
|
||||
public:
|
||||
|
||||
|
@ -45,26 +44,58 @@ class Canvas:
|
|||
CREATE_FAILED = 0x0004
|
||||
};
|
||||
|
||||
Canvas();
|
||||
/**
|
||||
* Callback used to disable/enable rendering to the texture if it is not
|
||||
* visible
|
||||
*/
|
||||
class CameraCullCallback:
|
||||
public osg::NodeCallback
|
||||
{
|
||||
public:
|
||||
CameraCullCallback();
|
||||
|
||||
/**
|
||||
* Enable rendering for the next frame
|
||||
*/
|
||||
void enableRendering();
|
||||
|
||||
private:
|
||||
bool _render;
|
||||
unsigned int _render_frame;
|
||||
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
||||
};
|
||||
typedef osg::ref_ptr<CameraCullCallback> CameraCullCallbackPtr;
|
||||
|
||||
/**
|
||||
* This callback is installed on every placement of the canvas in the
|
||||
* scene to only render the canvas if at least one placement is visible
|
||||
*/
|
||||
class CullCallback:
|
||||
public osg::NodeCallback
|
||||
{
|
||||
public:
|
||||
CullCallback(CameraCullCallback* camera_cull);
|
||||
|
||||
private:
|
||||
CameraCullCallback *_camera_cull;
|
||||
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
||||
};
|
||||
typedef osg::ref_ptr<CullCallback> CullCallbackPtr;
|
||||
|
||||
Canvas(SGPropertyNode* node);
|
||||
virtual ~Canvas();
|
||||
|
||||
void reset(SGPropertyNode* node);
|
||||
void update(double delta_time_sec);
|
||||
|
||||
void setSizeX(int sx);
|
||||
int getSizeX() const;
|
||||
|
||||
void setSizeY(int sy);
|
||||
int getSizeY() const;
|
||||
|
||||
void setViewWidth(int w);
|
||||
int getViewWidth() const;
|
||||
|
||||
void setViewHeight(int h);
|
||||
int getViewHeight() const;
|
||||
|
||||
int getStatus() const;
|
||||
const char* getStatusMsg() const;
|
||||
bool handleMouseEvent(const canvas::MouseEvent& event);
|
||||
|
||||
virtual void childAdded( SGPropertyNode * parent,
|
||||
SGPropertyNode * child );
|
||||
|
@ -72,8 +103,15 @@ class Canvas:
|
|||
SGPropertyNode * child );
|
||||
virtual void valueChanged (SGPropertyNode * node);
|
||||
|
||||
osg::Texture2D* getTexture() const;
|
||||
GLuint getTexId() const;
|
||||
|
||||
CameraCullCallbackPtr getCameraCullCallback() const;
|
||||
CullCallbackPtr getCullCallback() const;
|
||||
|
||||
static void addPlacementFactory( const std::string& type,
|
||||
canvas::PlacementFactory factory );
|
||||
|
||||
private:
|
||||
|
||||
Canvas(const Canvas&); // = delete;
|
||||
|
@ -84,8 +122,16 @@ class Canvas:
|
|||
_view_width,
|
||||
_view_height;
|
||||
|
||||
int _status;
|
||||
std::string _status_msg;
|
||||
simgear::PropertyObject<int> _status;
|
||||
simgear::PropertyObject<std::string> _status_msg;
|
||||
|
||||
simgear::PropertyObject<int> _mouse_x, _mouse_y,
|
||||
_mouse_dx, _mouse_dy,
|
||||
_mouse_button,
|
||||
_mouse_state,
|
||||
_mouse_mod,
|
||||
_mouse_scroll,
|
||||
_mouse_event;
|
||||
|
||||
bool _sampling_dirty,
|
||||
_color_dirty;
|
||||
|
@ -93,22 +139,19 @@ class Canvas:
|
|||
FGODGauge _texture;
|
||||
std::auto_ptr<canvas::Group> _root_group;
|
||||
|
||||
SGPropertyNode_ptr _node;
|
||||
std::vector<SGPropertyNode_ptr> _color_background;
|
||||
|
||||
osg::ref_ptr<CameraCullCallback> _camera_callback;
|
||||
osg::ref_ptr<osg::NodeCallback> _cull_callback;
|
||||
|
||||
CameraCullCallbackPtr _camera_callback;
|
||||
CullCallbackPtr _cull_callback;
|
||||
bool _render_always; //<! Used to disable automatic lazy rendering (culling)
|
||||
|
||||
std::vector<SGPropertyNode*> _dirty_placements;
|
||||
std::vector<Placements> _placements;
|
||||
std::vector<canvas::Placements> _placements;
|
||||
|
||||
typedef std::map<std::string, canvas::PlacementFactory> PlacementFactoryMap;
|
||||
static PlacementFactoryMap _placement_factories;
|
||||
|
||||
void setStatusFlags(unsigned int flags, bool set = true);
|
||||
void clearPlacements(int index);
|
||||
void clearPlacements();
|
||||
|
||||
void unbind();
|
||||
};
|
||||
|
||||
#endif /* CANVAS_HXX_ */
|
||||
|
|
53
src/Canvas/canvas_fwd.hpp
Normal file
53
src/Canvas/canvas_fwd.hpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
// Canvas forward declarations
|
||||
//
|
||||
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#ifndef CANVAS_FWD_HPP_
|
||||
#define CANVAS_FWD_HPP_
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/weak_ptr.hpp>
|
||||
#include <vector>
|
||||
|
||||
class SGPropertyNode;
|
||||
|
||||
class Canvas;
|
||||
typedef boost::shared_ptr<Canvas> CanvasPtr;
|
||||
typedef boost::weak_ptr<Canvas> CanvasWeakPtr;
|
||||
|
||||
class PropertyBasedElement;
|
||||
typedef boost::shared_ptr<PropertyBasedElement> PropertyBasedElementPtr;
|
||||
typedef boost::weak_ptr<PropertyBasedElement> PropertyBasedElementWeakPtr;
|
||||
|
||||
namespace canvas
|
||||
{
|
||||
class Group;
|
||||
class MouseEvent;
|
||||
|
||||
class Placement;
|
||||
typedef boost::shared_ptr<Placement> PlacementPtr;
|
||||
typedef std::vector<PlacementPtr> Placements;
|
||||
typedef boost::function<Placements( const SGPropertyNode*,
|
||||
CanvasPtr )> PlacementFactory;
|
||||
|
||||
class Window;
|
||||
typedef boost::shared_ptr<Window> WindowPtr;
|
||||
typedef boost::weak_ptr<Window> WindowWeakPtr;
|
||||
}
|
||||
|
||||
#endif /* CANVAS_FWD_HPP_ */
|
|
@ -19,131 +19,38 @@
|
|||
#include "canvas_mgr.hxx"
|
||||
#include "canvas.hxx"
|
||||
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <osg/Camera>
|
||||
#include <osg/Texture2D>
|
||||
typedef boost::shared_ptr<Canvas> CanvasPtr;
|
||||
CanvasPtr canvasFactory(SGPropertyNode* node)
|
||||
{
|
||||
return CanvasPtr(new Canvas(node));
|
||||
}
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
CanvasMgr::CanvasMgr():
|
||||
_props( fgGetNode("/canvas", true) )
|
||||
PropertyBasedMgr("/canvas", "texture", &canvasFactory)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
CanvasMgr::~CanvasMgr()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void CanvasMgr::init()
|
||||
{
|
||||
_props->addChangeListener(this);
|
||||
triggerChangeRecursive(_props);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void CanvasMgr::reinit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void CanvasMgr::shutdown()
|
||||
{
|
||||
_props->removeChangeListener(this);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void CanvasMgr::bind()
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void CanvasMgr::unbind()
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void CanvasMgr::update(double delta_time_sec)
|
||||
{
|
||||
for( size_t i = 0; i < _canvases.size(); ++i )
|
||||
if( _canvases[i] )
|
||||
_canvases[i]->update(delta_time_sec);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void CanvasMgr::childAdded( SGPropertyNode * parent,
|
||||
SGPropertyNode * child )
|
||||
{
|
||||
if( parent != _props )
|
||||
return;
|
||||
|
||||
if( child->getNameString() == "texture" )
|
||||
textureAdded(child);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void CanvasMgr::childRemoved( SGPropertyNode * parent,
|
||||
SGPropertyNode * child )
|
||||
{
|
||||
if( parent != _props )
|
||||
return;
|
||||
|
||||
if( child->getNameString() == "texture" )
|
||||
{
|
||||
size_t index = child->getIndex();
|
||||
|
||||
if( index >= _canvases.size() )
|
||||
SG_LOG(SG_GL, SG_WARN, "can't removed unknown texture[" << index << "]!");
|
||||
else
|
||||
// remove the canvas...
|
||||
_canvases[index].reset();
|
||||
}
|
||||
Canvas::addPlacementFactory
|
||||
(
|
||||
"object",
|
||||
boost::bind
|
||||
(
|
||||
&FGODGauge::set_texture,
|
||||
_1,
|
||||
boost::bind(&Canvas::getTexture, _2),
|
||||
boost::bind(&Canvas::getCullCallback, _2)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned int CanvasMgr::getCanvasTexId(size_t index) const
|
||||
{
|
||||
if( index >= _canvases.size()
|
||||
|| !_canvases[index] )
|
||||
if( index >= _elements.size()
|
||||
|| !_elements[index] )
|
||||
return 0;
|
||||
|
||||
return _canvases[index]->getTexId();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void CanvasMgr::textureAdded(SGPropertyNode* node)
|
||||
{
|
||||
size_t index = node->getIndex();
|
||||
|
||||
if( index >= _canvases.size() )
|
||||
{
|
||||
if( index > _canvases.size() )
|
||||
SG_LOG(SG_GL, SG_WARN, "Skipping unused texture slot(s)!");
|
||||
|
||||
_canvases.resize(index + 1);
|
||||
}
|
||||
else if( _canvases[index] )
|
||||
SG_LOG(SG_GL, SG_WARN, "texture[" << index << "] already exists!");
|
||||
|
||||
_canvases[index].reset( new Canvas() );
|
||||
_canvases[index]->reset(node);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void CanvasMgr::triggerChangeRecursive(SGPropertyNode* node)
|
||||
{
|
||||
node->getParent()->fireChildAdded(node);
|
||||
|
||||
if( node->nChildren() == 0 && node->getType() != simgear::props::NONE )
|
||||
return node->fireValueChanged();
|
||||
|
||||
for( int i = 0; i < node->nChildren(); ++i )
|
||||
triggerChangeRecursive( node->getChild(i) );
|
||||
return static_cast<Canvas*>(_elements[index].get())->getTexId();
|
||||
}
|
||||
|
|
|
@ -19,36 +19,13 @@
|
|||
#ifndef CANVAS_MGR_H_
|
||||
#define CANVAS_MGR_H_
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <vector>
|
||||
|
||||
class Canvas;
|
||||
typedef boost::shared_ptr<Canvas> CanvasPtr;
|
||||
#include "property_based_mgr.hxx"
|
||||
|
||||
class CanvasMgr:
|
||||
public SGSubsystem,
|
||||
public SGPropertyChangeListener
|
||||
public PropertyBasedMgr
|
||||
{
|
||||
public:
|
||||
CanvasMgr();
|
||||
virtual ~CanvasMgr();
|
||||
|
||||
virtual void init();
|
||||
virtual void reinit();
|
||||
virtual void shutdown();
|
||||
|
||||
virtual void bind();
|
||||
virtual void unbind();
|
||||
|
||||
virtual void update(double delta_time_sec);
|
||||
|
||||
virtual void childAdded( SGPropertyNode * parent,
|
||||
SGPropertyNode * child );
|
||||
virtual void childRemoved( SGPropertyNode * parent,
|
||||
SGPropertyNode * child );
|
||||
|
||||
/**
|
||||
* Get OpenGL texture name for given canvas
|
||||
|
@ -57,23 +34,6 @@ class CanvasMgr:
|
|||
* @return OpenGL texture name
|
||||
*/
|
||||
unsigned int getCanvasTexId(size_t index) const;
|
||||
|
||||
private:
|
||||
|
||||
/** Root node for everything concerning the canvas system */
|
||||
SGPropertyNode_ptr _props;
|
||||
|
||||
/** The actual canvases */
|
||||
std::vector<CanvasPtr> _canvases;
|
||||
|
||||
void textureAdded(SGPropertyNode* node);
|
||||
|
||||
/**
|
||||
* Trigger a childAdded and valueChanged event for every child of node
|
||||
* (Unlimited depth) and node itself.
|
||||
*/
|
||||
void triggerChangeRecursive(SGPropertyNode* node);
|
||||
|
||||
};
|
||||
|
||||
#endif /* CANVAS_MGR_H_ */
|
||||
|
|
|
@ -126,54 +126,12 @@ namespace canvas
|
|||
|
||||
_font_size = getChildDefault<float>(_node, "character-size", 32);
|
||||
_font_aspect = getChildDefault<float>(_node, "character-aspect-ratio", 1);
|
||||
|
||||
_node->tie
|
||||
(
|
||||
"alignment",
|
||||
SGRawValueMethods<Text, const char*>
|
||||
(
|
||||
*this,
|
||||
&Text::getAlignment,
|
||||
&Text::setAlignment
|
||||
)
|
||||
);
|
||||
_node->tie
|
||||
(
|
||||
"padding",
|
||||
SGRawValueMethods<osgText::Text, float>
|
||||
(
|
||||
*_text.get(),
|
||||
&osgText::Text::getBoundingBoxMargin,
|
||||
&osgText::Text::setBoundingBoxMargin
|
||||
)
|
||||
);
|
||||
typedef SGRawValueMethods<osgText::Text, int> TextIntMethods;
|
||||
_node->tie
|
||||
(
|
||||
"draw-mode",
|
||||
// TEXT = 1 default
|
||||
// BOUNDINGBOX = 2
|
||||
// FILLEDBOUNDINGBOX = 4
|
||||
// ALIGNMENT = 8
|
||||
TextIntMethods
|
||||
(
|
||||
*_text.get(),
|
||||
(TextIntMethods::getter_t)&osgText::Text::getDrawMode,
|
||||
(TextIntMethods::setter_t)&osgText::Text::setDrawMode
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Text::~Text()
|
||||
{
|
||||
if( _node )
|
||||
{
|
||||
_node->untie("alignment");
|
||||
_node->untie("padding");
|
||||
_node->untie("draw-mode");
|
||||
}
|
||||
_node = 0;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -210,10 +168,20 @@ namespace canvas
|
|||
#include "text-alignment.hxx"
|
||||
#undef ENUM_MAPPING
|
||||
else
|
||||
{
|
||||
if( !align_string.empty() )
|
||||
SG_LOG
|
||||
(
|
||||
SG_GENERAL,
|
||||
SG_WARN,
|
||||
"canvas::Text: unknown alignment '" << align_string << "'"
|
||||
);
|
||||
_text->setAlignment(osgText::Text::LEFT_BASE_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
#if 0
|
||||
const char* Text::getAlignment() const
|
||||
{
|
||||
switch( _text->getAlignment() )
|
||||
|
@ -227,7 +195,7 @@ namespace canvas
|
|||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
//----------------------------------------------------------------------------
|
||||
void Text::childChanged(SGPropertyNode* child)
|
||||
{
|
||||
|
@ -247,10 +215,20 @@ namespace canvas
|
|||
osgText::String( child->getStringValue(),
|
||||
osgText::String::ENCODING_UTF8 )
|
||||
);
|
||||
else if( name == "padding" )
|
||||
_text->setBoundingBoxMargin( child->getFloatValue() );
|
||||
else if( name == "draw-mode" )
|
||||
// TEXT = 1 default
|
||||
// BOUNDINGBOX = 2
|
||||
// FILLEDBOUNDINGBOX = 4
|
||||
// ALIGNMENT = 8
|
||||
_text->setDrawMode( child->getIntValue() );
|
||||
else if( name == "max-width" )
|
||||
_text->setMaximumWidth( child->getFloatValue() );
|
||||
else if( name == "font" )
|
||||
setFont( child->getStringValue() );
|
||||
else if( name == "alignment" )
|
||||
setAlignment( child->getStringValue() );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
|
@ -33,14 +33,12 @@ namespace canvas
|
|||
{
|
||||
public:
|
||||
Text(SGPropertyNode_ptr node);
|
||||
virtual ~Text();
|
||||
~Text();
|
||||
|
||||
virtual void update(double dt);
|
||||
|
||||
void setFont(const char* name);
|
||||
|
||||
void setAlignment(const char* align);
|
||||
const char* getAlignment() const;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
297
src/Canvas/gui_mgr.cxx
Normal file
297
src/Canvas/gui_mgr.cxx
Normal file
|
@ -0,0 +1,297 @@
|
|||
// Canvas gui/dialog manager
|
||||
//
|
||||
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#include "gui_mgr.hxx"
|
||||
#include "mouse_event.hxx"
|
||||
#include <Canvas/window.hxx>
|
||||
#include <Canvas/canvas.hxx>
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
#include <Viewer/CameraGroup.hxx>
|
||||
#include <Viewer/renderer.hxx>
|
||||
|
||||
#include <osgViewer/Viewer>
|
||||
#include <osgGA/GUIEventHandler>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
/**
|
||||
* Event handler
|
||||
*/
|
||||
class GUIEventHandler:
|
||||
public osgGA::GUIEventHandler
|
||||
{
|
||||
public:
|
||||
GUIEventHandler(GUIMgr* gui_mgr):
|
||||
_gui_mgr( gui_mgr )
|
||||
{}
|
||||
|
||||
bool handle( const osgGA::GUIEventAdapter& ea,
|
||||
osgGA::GUIActionAdapter& aa,
|
||||
osg::Object*,
|
||||
osg::NodeVisitor* )
|
||||
{
|
||||
return _gui_mgr->handleEvent(ea);
|
||||
}
|
||||
|
||||
protected:
|
||||
GUIMgr *_gui_mgr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Track a canvas placement on a window
|
||||
*/
|
||||
class WindowPlacement:
|
||||
public canvas::Placement
|
||||
{
|
||||
public:
|
||||
WindowPlacement( canvas::WindowPtr window,
|
||||
CanvasPtr canvas ):
|
||||
_window(window),
|
||||
_canvas(canvas)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Remove placement from window
|
||||
*/
|
||||
virtual ~WindowPlacement()
|
||||
{
|
||||
canvas::WindowPtr window = _window.lock();
|
||||
CanvasPtr canvas = _canvas.lock();
|
||||
|
||||
if( window && canvas && canvas == window->getCanvas().lock() )
|
||||
window->setCanvas( CanvasPtr() );
|
||||
}
|
||||
|
||||
private:
|
||||
canvas::WindowWeakPtr _window;
|
||||
CanvasWeakPtr _canvas;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
typedef boost::shared_ptr<canvas::Window> WindowPtr;
|
||||
WindowPtr windowFactory(SGPropertyNode* node)
|
||||
{
|
||||
return WindowPtr(new canvas::Window(node));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
GUIMgr::GUIMgr():
|
||||
PropertyBasedMgr("/sim/gui/canvas", "window", &windowFactory),
|
||||
_event_handler( new GUIEventHandler(this) ),
|
||||
_transform( new osg::MatrixTransform ),
|
||||
_geode_windows( new osg::Geode ),
|
||||
_width(_props, "size[0]"),
|
||||
_height(_props, "size[1]"),
|
||||
_last_push(-1)
|
||||
{
|
||||
_width = _height = -1;
|
||||
|
||||
osg::Camera* camera =
|
||||
flightgear::getGUICamera( flightgear::CameraGroup::getDefault() );
|
||||
assert(camera);
|
||||
|
||||
osg::Viewport* vp = camera->getViewport();
|
||||
handleResize(vp->x(), vp->y(), vp->width(), vp->height());
|
||||
|
||||
_transform->addChild(_geode_windows);
|
||||
camera->addChild(_transform);
|
||||
|
||||
Canvas::addPlacementFactory
|
||||
(
|
||||
"window",
|
||||
boost::bind(&GUIMgr::addPlacement, this, _1, _2)
|
||||
);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GUIMgr::init()
|
||||
{
|
||||
PropertyBasedMgr::init();
|
||||
|
||||
globals->get_renderer()
|
||||
->getViewer()
|
||||
->addEventHandler( _event_handler );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GUIMgr::shutdown()
|
||||
{
|
||||
PropertyBasedMgr::shutdown();
|
||||
|
||||
globals->get_renderer()
|
||||
->getViewer()
|
||||
->removeEventHandler( _event_handler );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GUIMgr::elementCreated(PropertyBasedElementPtr element)
|
||||
{
|
||||
_geode_windows->addDrawable
|
||||
(
|
||||
static_cast<canvas::Window*>(element.get())->getDrawable()
|
||||
);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool GUIMgr::handleEvent(const osgGA::GUIEventAdapter& ea)
|
||||
{
|
||||
switch( ea.getEventType() )
|
||||
{
|
||||
case osgGA::GUIEventAdapter::PUSH:
|
||||
case osgGA::GUIEventAdapter::RELEASE:
|
||||
// case osgGA::GUIEventAdapter::DOUBLECLICK:
|
||||
// // DOUBLECLICK doesn't seem to be triggered...
|
||||
case osgGA::GUIEventAdapter::DRAG:
|
||||
case osgGA::GUIEventAdapter::MOVE:
|
||||
case osgGA::GUIEventAdapter::SCROLL:
|
||||
return handleMouse(ea);
|
||||
// case osgGA::GUIEventAdapter::MOVE:
|
||||
// std::cout << "MOVE" << std::endl;
|
||||
// break;
|
||||
case osgGA::GUIEventAdapter::RESIZE:
|
||||
handleResize( ea.getWindowX(),
|
||||
ea.getWindowY(),
|
||||
ea.getWindowWidth(),
|
||||
ea.getWindowHeight() );
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
canvas::WindowPtr GUIMgr::getWindow(size_t i)
|
||||
{
|
||||
return boost::shared_static_cast<canvas::Window>(_elements[i]);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
canvas::Placements GUIMgr::addPlacement( const SGPropertyNode* node,
|
||||
CanvasPtr canvas )
|
||||
{
|
||||
int placement_index = node->getIntValue("index", -1);
|
||||
|
||||
canvas::Placements placements;
|
||||
for( size_t i = 0; i < _elements.size(); ++i )
|
||||
{
|
||||
if( placement_index > 0 && static_cast<int>(i) != placement_index )
|
||||
continue;
|
||||
|
||||
canvas::WindowPtr window = getWindow(i);
|
||||
if( !window )
|
||||
continue;
|
||||
|
||||
window->setCanvas(canvas);
|
||||
placements.push_back(
|
||||
canvas::PlacementPtr(new WindowPlacement(window, canvas))
|
||||
);
|
||||
}
|
||||
return placements;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
|
||||
{
|
||||
canvas::MouseEvent event( ea.getEventType() );
|
||||
|
||||
event.x = 0.5 * (ea.getXnormalized() + 1) * _width + 0.5;
|
||||
event.y = 0.5 * (ea.getYnormalized() + 1) * _height + 0.5;
|
||||
if( ea.getMouseYOrientation()
|
||||
!= osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS )
|
||||
event.y = _height - event.y;
|
||||
|
||||
event.button = ea.getButton();
|
||||
event.state = ea.getButtonMask();
|
||||
event.mod = ea.getModKeyMask();
|
||||
event.scroll = ea.getScrollingMotion();
|
||||
|
||||
int window_at_cursor = -1;
|
||||
for( size_t i = 0; i < _elements.size(); ++i )
|
||||
{
|
||||
if( _elements[i]
|
||||
&& getWindow(i)->getRegion().contains(event.x, event.y) )
|
||||
{
|
||||
window_at_cursor = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int target_window = window_at_cursor;
|
||||
switch( ea.getEventType() )
|
||||
{
|
||||
case osgGA::GUIEventAdapter::PUSH:
|
||||
_last_push = window_at_cursor;
|
||||
break;
|
||||
case osgGA::GUIEventAdapter::SCROLL:
|
||||
case osgGA::GUIEventAdapter::MOVE:
|
||||
break;
|
||||
|
||||
case osgGA::GUIEventAdapter::RELEASE:
|
||||
if( _last_push < 0 )
|
||||
return false;
|
||||
|
||||
target_window = _last_push;
|
||||
_last_push = -1;
|
||||
break;
|
||||
|
||||
case osgGA::GUIEventAdapter::DRAG:
|
||||
target_window = _last_push;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if( target_window >= 0 )
|
||||
{
|
||||
canvas::WindowPtr window = getWindow(target_window);
|
||||
|
||||
event.dx = event.x - _last_x;
|
||||
event.dy = event.y - _last_y;
|
||||
|
||||
_last_x = event.x;
|
||||
_last_y = event.y;
|
||||
|
||||
// Let the event position be always relative to the top left window corner
|
||||
event.x -= window->getRegion().x();
|
||||
event.y -= window->getRegion().y();
|
||||
|
||||
return window->handleMouseEvent(event);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GUIMgr::handleResize(int x, int y, int width, int height)
|
||||
{
|
||||
if( _width == width && _height == height )
|
||||
return;
|
||||
|
||||
_width = width;
|
||||
_height = height;
|
||||
|
||||
// Origin should be at top left corner, therefore we need to mirror the y-axis
|
||||
_transform->setMatrix(osg::Matrix(
|
||||
1, 0, 0, 0,
|
||||
0, -1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, _height, 0, 1
|
||||
));
|
||||
}
|
71
src/Canvas/gui_mgr.hxx
Normal file
71
src/Canvas/gui_mgr.hxx
Normal file
|
@ -0,0 +1,71 @@
|
|||
// Canvas gui/dialog manager
|
||||
//
|
||||
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#ifndef CANVAS_GUI_MGR_HXX_
|
||||
#define CANVAS_GUI_MGR_HXX_
|
||||
|
||||
#include "property_based_mgr.hxx"
|
||||
#include <Canvas/canvas_fwd.hpp>
|
||||
#include <Canvas/placement.hxx>
|
||||
|
||||
#include <simgear/props/propertyObject.hxx>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Geode>
|
||||
#include <osg/MatrixTransform>
|
||||
|
||||
namespace osgGA
|
||||
{
|
||||
class GUIEventAdapter;
|
||||
}
|
||||
|
||||
class GUIEventHandler;
|
||||
class GUIMgr:
|
||||
public PropertyBasedMgr
|
||||
{
|
||||
public:
|
||||
GUIMgr();
|
||||
|
||||
virtual void init();
|
||||
virtual void shutdown();
|
||||
|
||||
virtual void elementCreated(PropertyBasedElementPtr element);
|
||||
|
||||
bool handleEvent(const osgGA::GUIEventAdapter& ea);
|
||||
|
||||
protected:
|
||||
osg::ref_ptr<GUIEventHandler> _event_handler;
|
||||
osg::ref_ptr<osg::MatrixTransform> _transform;
|
||||
osg::ref_ptr<osg::Geode> _geode_windows;
|
||||
|
||||
simgear::PropertyObject<int> _width,
|
||||
_height;
|
||||
|
||||
int _last_push,
|
||||
_last_x,
|
||||
_last_y;
|
||||
|
||||
canvas::WindowPtr getWindow(size_t i);
|
||||
canvas::Placements addPlacement( const SGPropertyNode*,
|
||||
CanvasPtr canvas );
|
||||
|
||||
bool handleMouse(const osgGA::GUIEventAdapter& ea);
|
||||
void handleResize(int x, int y, int width, int height);
|
||||
};
|
||||
|
||||
#endif /* CANVAS_GUI_MGR_HXX_ */
|
52
src/Canvas/mouse_event.hxx
Normal file
52
src/Canvas/mouse_event.hxx
Normal file
|
@ -0,0 +1,52 @@
|
|||
// Mouse event
|
||||
//
|
||||
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#ifndef CANVAS_MOUSE_EVENT_HXX_
|
||||
#define CANVAS_MOUSE_EVENT_HXX_
|
||||
|
||||
#include <osgGA/GUIEventAdapter>
|
||||
|
||||
namespace canvas
|
||||
{
|
||||
|
||||
struct MouseEvent
|
||||
{
|
||||
typedef osgGA::GUIEventAdapter::EventType EventType;
|
||||
typedef osgGA::GUIEventAdapter::ScrollingMotion Scroll;
|
||||
|
||||
MouseEvent(EventType type):
|
||||
type(type),
|
||||
x(-1), y(-1),
|
||||
dx(0), dy(0),
|
||||
button(-1),
|
||||
state(-1),
|
||||
mod(-1)
|
||||
{}
|
||||
|
||||
EventType type;
|
||||
int x, y,
|
||||
dx, dy,
|
||||
button, //<! Button for this event
|
||||
state, //<! Current button state
|
||||
mod; //<! Keyboard modifier state
|
||||
Scroll scroll;
|
||||
};
|
||||
|
||||
} // namespace canvas
|
||||
|
||||
#endif /* CANVAS_MOUSE_EVENT_HXX_ */
|
36
src/Canvas/placement.cxx
Normal file
36
src/Canvas/placement.cxx
Normal file
|
@ -0,0 +1,36 @@
|
|||
// Base class for canvas placements
|
||||
//
|
||||
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#include "placement.hxx"
|
||||
|
||||
namespace canvas
|
||||
{
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Placement::Placement()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Placement::~Placement()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
} // namespace canvas
|
38
src/Canvas/placement.hxx
Normal file
38
src/Canvas/placement.hxx
Normal file
|
@ -0,0 +1,38 @@
|
|||
// Base class for canvas placements
|
||||
//
|
||||
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#ifndef CANVAS_PLACEMENT_HXX_
|
||||
#define CANVAS_PLACEMENT_HXX_
|
||||
|
||||
namespace canvas
|
||||
{
|
||||
|
||||
class Placement
|
||||
{
|
||||
public:
|
||||
Placement();
|
||||
virtual ~Placement() = 0;
|
||||
|
||||
private:
|
||||
Placement(const Placement&) /* = delete */;
|
||||
Placement& operator=(const Placement&) /* = delete */;
|
||||
};
|
||||
|
||||
} // namespace canvas
|
||||
|
||||
#endif /* CANVAS_PLACEMENT_HXX_ */
|
32
src/Canvas/property_based_element.cxx
Normal file
32
src/Canvas/property_based_element.cxx
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Base class for elements of property controlled subsystems
|
||||
//
|
||||
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#include "property_based_element.hxx"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
PropertyBasedElement::PropertyBasedElement(SGPropertyNode* node):
|
||||
_node(node)
|
||||
{
|
||||
_node->addChangeListener(this);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
PropertyBasedElement::~PropertyBasedElement()
|
||||
{
|
||||
_node->removeChangeListener(this);
|
||||
}
|
46
src/Canvas/property_based_element.hxx
Normal file
46
src/Canvas/property_based_element.hxx
Normal file
|
@ -0,0 +1,46 @@
|
|||
// Base class for elements of property controlled subsystems
|
||||
//
|
||||
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#ifndef PROPERTY_BASED_ELEMENT_HXX_
|
||||
#define PROPERTY_BASED_ELEMENT_HXX_
|
||||
|
||||
#include <Canvas/canvas_fwd.hpp>
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
/**
|
||||
* Base class for a property controlled element
|
||||
*/
|
||||
class PropertyBasedElement:
|
||||
public SGPropertyChangeListener
|
||||
{
|
||||
public:
|
||||
PropertyBasedElement(SGPropertyNode* node);
|
||||
virtual ~PropertyBasedElement();
|
||||
|
||||
virtual void update(double delta_time_sec) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
friend class PropertyBasedMgr;
|
||||
|
||||
SGPropertyNode_ptr _node;
|
||||
PropertyBasedElementWeakPtr _self;
|
||||
};
|
||||
|
||||
|
||||
#endif /* PROPERTY_BASED_ELEMENT_HXX_ */
|
118
src/Canvas/property_based_mgr.cxx
Normal file
118
src/Canvas/property_based_mgr.cxx
Normal file
|
@ -0,0 +1,118 @@
|
|||
// Base class for all property controlled subsystems
|
||||
//
|
||||
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#include "property_based_mgr.hxx"
|
||||
#include "property_helper.hxx"
|
||||
#include <Main/fg_props.hxx>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void PropertyBasedMgr::init()
|
||||
{
|
||||
_props->addChangeListener(this);
|
||||
canvas::triggerChangeRecursive(_props);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void PropertyBasedMgr::shutdown()
|
||||
{
|
||||
_props->removeChangeListener(this);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void PropertyBasedMgr::update(double delta_time_sec)
|
||||
{
|
||||
for( size_t i = 0; i < _elements.size(); ++i )
|
||||
if( _elements[i] )
|
||||
_elements[i]->update(delta_time_sec);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void PropertyBasedMgr::childAdded( SGPropertyNode * parent,
|
||||
SGPropertyNode * child )
|
||||
{
|
||||
if( parent != _props || child->getNameString() != _name_elements )
|
||||
return;
|
||||
|
||||
size_t index = child->getIndex();
|
||||
|
||||
if( index >= _elements.size() )
|
||||
{
|
||||
if( index > _elements.size() )
|
||||
SG_LOG
|
||||
(
|
||||
SG_GENERAL,
|
||||
SG_WARN,
|
||||
"Skipping unused " << _name_elements << " slot(s)!"
|
||||
);
|
||||
|
||||
_elements.resize(index + 1);
|
||||
}
|
||||
else if( _elements[index] )
|
||||
SG_LOG
|
||||
(
|
||||
SG_GENERAL,
|
||||
SG_WARN,
|
||||
_name_elements << "[" << index << "] already exists!"
|
||||
);
|
||||
|
||||
PropertyBasedElementPtr el = _element_factory(child);
|
||||
el->_self = el;
|
||||
_elements[index] = el;
|
||||
elementCreated( el );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void PropertyBasedMgr::childRemoved( SGPropertyNode * parent,
|
||||
SGPropertyNode * child )
|
||||
{
|
||||
if( parent != _props || child->getNameString() != _name_elements )
|
||||
return;
|
||||
|
||||
size_t index = child->getIndex();
|
||||
|
||||
if( index >= _elements.size() )
|
||||
SG_LOG
|
||||
(
|
||||
SG_GENERAL,
|
||||
SG_WARN,
|
||||
"can't removed unknown " << _name_elements << "[" << index << "]!"
|
||||
);
|
||||
else
|
||||
// remove the element...
|
||||
_elements[index].reset();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
PropertyBasedMgr::PropertyBasedMgr( const std::string& path_root,
|
||||
const std::string& name_elements,
|
||||
ElementFactory element_factory ):
|
||||
_props( fgGetNode(path_root, true) ),
|
||||
_name_elements( name_elements ),
|
||||
_element_factory( element_factory )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
PropertyBasedMgr::~PropertyBasedMgr()
|
||||
{
|
||||
|
||||
}
|
75
src/Canvas/property_based_mgr.hxx
Normal file
75
src/Canvas/property_based_mgr.hxx
Normal file
|
@ -0,0 +1,75 @@
|
|||
// Base class for all property controlled subsystems
|
||||
//
|
||||
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#ifndef PROPERTY_BASED_MGR_HXX_
|
||||
#define PROPERTY_BASED_MGR_HXX_
|
||||
|
||||
#include "property_based_element.hxx"
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <vector>
|
||||
|
||||
class PropertyBasedMgr:
|
||||
public SGSubsystem,
|
||||
public SGPropertyChangeListener
|
||||
{
|
||||
public:
|
||||
virtual void init();
|
||||
virtual void shutdown();
|
||||
|
||||
virtual void update (double delta_time_sec);
|
||||
|
||||
virtual void childAdded( SGPropertyNode * parent,
|
||||
SGPropertyNode * child );
|
||||
virtual void childRemoved( SGPropertyNode * parent,
|
||||
SGPropertyNode * child );
|
||||
|
||||
virtual void elementCreated(PropertyBasedElementPtr element) {}
|
||||
|
||||
protected:
|
||||
|
||||
typedef boost::function<PropertyBasedElementPtr(SGPropertyNode*)>
|
||||
ElementFactory;
|
||||
|
||||
/** Branch in the property tree for this property managed subsystem */
|
||||
SGPropertyNode* _props;
|
||||
|
||||
/** Property name of managed elements */
|
||||
const std::string _name_elements;
|
||||
|
||||
/** The actually managed elements */
|
||||
std::vector<PropertyBasedElementPtr> _elements;
|
||||
|
||||
/** Function object which creates a new element */
|
||||
ElementFactory _element_factory;
|
||||
|
||||
/**
|
||||
* @param path_root Path to property branch used for controlling this
|
||||
* subsystem
|
||||
* @param name_elements The name of the nodes for the managed elements
|
||||
*/
|
||||
PropertyBasedMgr( const std::string& path_root,
|
||||
const std::string& name_elements,
|
||||
ElementFactory element_factory );
|
||||
virtual ~PropertyBasedMgr() = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif /* PROPERTY_BASED_MGR_HXX_ */
|
|
@ -44,4 +44,16 @@ namespace canvas
|
|||
for( size_t i = 0; i < num_channels; ++i )
|
||||
nodes.push_back( getChildDefault(color, channels[i], def[i]) );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void triggerChangeRecursive(SGPropertyNode* node)
|
||||
{
|
||||
node->getParent()->fireChildAdded(node);
|
||||
|
||||
if( node->nChildren() == 0 && node->getType() != simgear::props::NONE )
|
||||
return node->fireValueChanged();
|
||||
|
||||
for( int i = 0; i < node->nChildren(); ++i )
|
||||
triggerChangeRecursive( node->getChild(i) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,12 @@ namespace canvas
|
|||
std::vector<SGPropertyNode_ptr>& nodes,
|
||||
const osg::Vec4& def = osg::Vec4(0,0,0,1) );
|
||||
|
||||
/**
|
||||
* Trigger a childAdded and valueChanged event for every child of node
|
||||
* (Unlimited depth) and node itself.
|
||||
*/
|
||||
void triggerChangeRecursive(SGPropertyNode* node);
|
||||
|
||||
} // namespace canvas
|
||||
|
||||
#endif /* PROPERTY_HELPER_HXX_ */
|
||||
|
|
68
src/Canvas/rect.hxx
Normal file
68
src/Canvas/rect.hxx
Normal file
|
@ -0,0 +1,68 @@
|
|||
// Class representing a rectangular region
|
||||
//
|
||||
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#ifndef CANVAS_RECT_HXX_
|
||||
#define CANVAS_RECT_HXX_
|
||||
|
||||
#include <osg/Vec2>
|
||||
|
||||
namespace canvas
|
||||
{
|
||||
template<typename T>
|
||||
class Rect
|
||||
{
|
||||
public:
|
||||
Rect() {}
|
||||
|
||||
Rect(T x, T y, T w, T h):
|
||||
_x1(x),
|
||||
_x2(x + w),
|
||||
_y1(y),
|
||||
_y2(y + h)
|
||||
{}
|
||||
|
||||
void set(T x, T y, T w, T h)
|
||||
{
|
||||
_x1 = x;
|
||||
_x2 = x + w;
|
||||
_y1 = y;
|
||||
_y2 = y + h;
|
||||
}
|
||||
|
||||
T x() const { return _x1; }
|
||||
T y() const { return _y1; }
|
||||
T width() const { return _x2 - _x1; }
|
||||
T height() const { return _y2 - _y1; }
|
||||
|
||||
T l() const { return _x1; }
|
||||
T r() const { return _x2; }
|
||||
T t() const { return _y1; }
|
||||
T b() const { return _y2; }
|
||||
|
||||
bool contains(T x, T y) const
|
||||
{
|
||||
return _x1 <= x && x <= _x2
|
||||
&& _y1 <= y && y <= _y2;
|
||||
}
|
||||
|
||||
private:
|
||||
T _x1, _x2, _y1, _y2;
|
||||
};
|
||||
} // namespace canvas
|
||||
|
||||
#endif /* CANVAS_RECT_HXX_ */
|
177
src/Canvas/window.cxx
Normal file
177
src/Canvas/window.cxx
Normal file
|
@ -0,0 +1,177 @@
|
|||
// Window for placing a Canvas onto it (for dialogs, menus, etc.)
|
||||
//
|
||||
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#include "window.hxx"
|
||||
#include <Canvas/canvas.hxx>
|
||||
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Texture2D>
|
||||
#include <osgGA/GUIEventHandler>
|
||||
|
||||
/**
|
||||
* Callback to enable/disable rendering of canvas displayed inside windows
|
||||
*/
|
||||
class CullCallback:
|
||||
public osg::Drawable::CullCallback
|
||||
{
|
||||
public:
|
||||
CullCallback(Canvas::CameraCullCallback* camera_cull);
|
||||
|
||||
private:
|
||||
Canvas::CameraCullCallback *_camera_cull;
|
||||
|
||||
virtual bool cull( osg::NodeVisitor* nv,
|
||||
osg::Drawable* drawable,
|
||||
osg::RenderInfo* renderInfo ) const;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
CullCallback::CullCallback(Canvas::CameraCullCallback* camera_cull):
|
||||
_camera_cull( camera_cull )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool CullCallback::cull( osg::NodeVisitor* nv,
|
||||
osg::Drawable* drawable,
|
||||
osg::RenderInfo* renderInfo ) const
|
||||
{
|
||||
_camera_cull->enableRendering();
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace canvas
|
||||
{
|
||||
//----------------------------------------------------------------------------
|
||||
Window::Window(SGPropertyNode* node):
|
||||
PropertyBasedElement(node),
|
||||
_dirty(true),
|
||||
_geometry( new osg::Geometry ),
|
||||
_vertices( new osg::Vec3Array(4) ),
|
||||
_tex_coords( new osg::Vec2Array(4) ),
|
||||
_x(node, "x"),
|
||||
_y(node, "y"),
|
||||
_width(node, "size[0]"),
|
||||
_height(node, "size[1]")
|
||||
{
|
||||
_x = 50;
|
||||
_y = 100;
|
||||
_width = 400;
|
||||
_height = 300;
|
||||
|
||||
_geometry->setVertexArray(_vertices);
|
||||
_geometry->setTexCoordArray(0,_tex_coords);
|
||||
|
||||
osg::Vec4Array* colors = new osg::Vec4Array(1);
|
||||
(*colors)[0].set(1.0f,1.0f,1.0,1.0f);
|
||||
_geometry->setColorArray(colors);
|
||||
_geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
_geometry->addPrimitiveSet(
|
||||
new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4)
|
||||
);
|
||||
_geometry->setDataVariance(osg::Object::DYNAMIC);
|
||||
|
||||
osg::StateSet* stateSet = _geometry->getOrCreateStateSet();
|
||||
stateSet->setRenderBinDetails(1000, "RenderBin");
|
||||
|
||||
// speed optimization?
|
||||
stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
||||
stateSet->setAttribute(new osg::BlendFunc(
|
||||
osg::BlendFunc::SRC_ALPHA,
|
||||
osg::BlendFunc::ONE_MINUS_SRC_ALPHA)
|
||||
);
|
||||
stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
|
||||
stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
|
||||
stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Window::~Window()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Window::update(double delta_time_sec)
|
||||
{
|
||||
if( !_dirty )
|
||||
return;
|
||||
_dirty = false;
|
||||
|
||||
_region.set(_x, _y, _width, _height);
|
||||
|
||||
int z = 0; // TODO do we need to use z for depth ordering?
|
||||
|
||||
(*_vertices)[0].set(_region.l(), _region.t(), z);
|
||||
(*_vertices)[1].set(_region.r(), _region.t(), z);
|
||||
(*_vertices)[2].set(_region.r(), _region.b(), z);
|
||||
(*_vertices)[3].set(_region.l(), _region.b(), z);
|
||||
|
||||
float l = 0, t = 1, b = 0, r = 1;
|
||||
(*_tex_coords)[0].set(l,t);
|
||||
(*_tex_coords)[1].set(r,t);
|
||||
(*_tex_coords)[2].set(r,b);
|
||||
(*_tex_coords)[3].set(l,b);
|
||||
|
||||
_geometry->dirtyDisplayList();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Window::valueChanged (SGPropertyNode * node)
|
||||
{
|
||||
if( node->getParent() != _node )
|
||||
return;
|
||||
|
||||
const std::string& name = node->getNameString();
|
||||
if( name == "x" || name == "y" || name == "size" )
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Window::setCanvas(CanvasPtr canvas)
|
||||
{
|
||||
_canvas = canvas;
|
||||
_geometry->getOrCreateStateSet()
|
||||
->setTextureAttribute(0, canvas ? canvas->getTexture() : 0);
|
||||
_geometry->dirtyDisplayList();
|
||||
_geometry->setCullCallback(
|
||||
canvas ? new CullCallback(canvas->getCameraCullCallback()) : 0
|
||||
);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
CanvasWeakPtr Window::getCanvas() const
|
||||
{
|
||||
return _canvas;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool Window::handleMouseEvent(const MouseEvent& event)
|
||||
{
|
||||
if( !_canvas.expired() )
|
||||
return _canvas.lock()->handleMouseEvent(event);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace canvas
|
66
src/Canvas/window.hxx
Normal file
66
src/Canvas/window.hxx
Normal file
|
@ -0,0 +1,66 @@
|
|||
// Window for placing a Canvas onto it (for dialogs, menus, etc.)
|
||||
//
|
||||
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#ifndef CANVAS_WINDOW_HXX_
|
||||
#define CANVAS_WINDOW_HXX_
|
||||
|
||||
#include "mouse_event.hxx"
|
||||
#include "property_based_element.hxx"
|
||||
#include "rect.hxx"
|
||||
|
||||
#include <simgear/props/propertyObject.hxx>
|
||||
|
||||
#include <osg/Geometry>
|
||||
|
||||
namespace canvas
|
||||
{
|
||||
class Window:
|
||||
public PropertyBasedElement
|
||||
{
|
||||
public:
|
||||
Window(SGPropertyNode* node);
|
||||
virtual ~Window();
|
||||
|
||||
virtual void update(double delta_time_sec);
|
||||
virtual void valueChanged (SGPropertyNode * node);
|
||||
|
||||
osg::Drawable* getDrawable() { return _geometry; }
|
||||
const Rect<int>& getRegion() const { return _region; }
|
||||
|
||||
void setCanvas(CanvasPtr canvas);
|
||||
CanvasWeakPtr getCanvas() const;
|
||||
|
||||
bool handleMouseEvent(const MouseEvent& event);
|
||||
|
||||
protected:
|
||||
|
||||
bool _dirty;
|
||||
|
||||
osg::ref_ptr<osg::Geometry> _geometry;
|
||||
osg::ref_ptr<osg::Vec3Array> _vertices;
|
||||
osg::ref_ptr<osg::Vec2Array> _tex_coords;
|
||||
|
||||
simgear::PropertyObject<int> _x, _y,
|
||||
_width, _height;
|
||||
Rect<int> _region;
|
||||
|
||||
CanvasWeakPtr _canvas;
|
||||
};
|
||||
} // namespace canvas
|
||||
|
||||
#endif /* CANVAS_WINDOW_HXX_ */
|
|
@ -311,7 +311,7 @@ class ReplaceStaticTextureVisitor:
|
|||
* Get a list of groups which have been inserted into the scene graph to
|
||||
* replace the given texture
|
||||
*/
|
||||
Placements& getPlacements()
|
||||
canvas::Placements& getPlacements()
|
||||
{
|
||||
return _placements;
|
||||
}
|
||||
|
@ -386,7 +386,9 @@ class ReplaceStaticTextureVisitor:
|
|||
if( _cull_callback )
|
||||
group->setCullCallback(_cull_callback);
|
||||
|
||||
_placements.push_back(group);
|
||||
_placements.push_back(
|
||||
canvas::PlacementPtr(new ObjectPlacement(group))
|
||||
);
|
||||
|
||||
osg::StateSet* stateSet = group->getOrCreateStateSet();
|
||||
stateSet->setTextureAttribute( unit, _new_texture,
|
||||
|
@ -407,10 +409,38 @@ class ReplaceStaticTextureVisitor:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
class ObjectPlacement:
|
||||
public canvas::Placement
|
||||
{
|
||||
public:
|
||||
ObjectPlacement(osg::ref_ptr<osg::Group> group):
|
||||
_group(group)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Remove placement from the scene
|
||||
*/
|
||||
virtual ~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);
|
||||
}
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Group> _group;
|
||||
};
|
||||
|
||||
std::string _tex_name, ///<! Name of texture to be replaced
|
||||
_node_name, ///<! Only replace if node name matches
|
||||
_parent_name; ///<! Only replace if any parent node matches
|
||||
|
@ -418,11 +448,12 @@ class ReplaceStaticTextureVisitor:
|
|||
osg::Texture2D *_new_texture;
|
||||
osg::NodeCallback *_cull_callback;
|
||||
|
||||
Placements _placements;
|
||||
canvas::Placements _placements;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Placements FGODGauge::set_texture(const char* name, osg::Texture2D* new_texture)
|
||||
canvas::Placements FGODGauge::set_texture( const char* name,
|
||||
osg::Texture2D* new_texture )
|
||||
{
|
||||
osg::Group* root = globals->get_scenery()->get_aircraft_branch();
|
||||
ReplaceStaticTextureVisitor visitor(name, new_texture);
|
||||
|
@ -431,9 +462,9 @@ class ReplaceStaticTextureVisitor:
|
|||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Placements FGODGauge::set_texture( const SGPropertyNode* placement,
|
||||
osg::Texture2D* new_texture,
|
||||
osg::NodeCallback* cull_callback )
|
||||
canvas::Placements FGODGauge::set_texture( const SGPropertyNode* placement,
|
||||
osg::Texture2D* new_texture,
|
||||
osg::NodeCallback* cull_callback )
|
||||
{
|
||||
osg::Group* root = globals->get_scenery()->get_aircraft_branch();
|
||||
ReplaceStaticTextureVisitor visitor(placement, new_texture, cull_callback);
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
#ifndef _OD_GAUGE_HXX
|
||||
#define _OD_GAUGE_HXX
|
||||
|
||||
#include <Canvas/canvas_fwd.hpp>
|
||||
#include <Canvas/placement.hxx>
|
||||
|
||||
#include <osg/NodeCallback>
|
||||
#include <osg/Group>
|
||||
|
||||
|
@ -38,14 +41,13 @@ namespace osg {
|
|||
}
|
||||
|
||||
class SGPropertyNode;
|
||||
typedef std::vector<osg::ref_ptr<osg::Group> > Placements;
|
||||
|
||||
/**
|
||||
* Owner Drawn Gauge helper class.
|
||||
*/
|
||||
class FGODGauge
|
||||
{
|
||||
public:
|
||||
public:
|
||||
FGODGauge();
|
||||
virtual ~FGODGauge();
|
||||
|
||||
|
@ -109,7 +111,9 @@ public:
|
|||
* @param new_texture dynamic texture to replace the old one
|
||||
* @return A list of groups which override the given texture
|
||||
*/
|
||||
Placements set_texture(const char * name, osg::Texture2D* new_texture);
|
||||
static
|
||||
canvas::Placements set_texture( const char * name,
|
||||
osg::Texture2D* new_texture );
|
||||
|
||||
/**
|
||||
* Replace an opengl texture name inside the aircraft scene graph.
|
||||
|
@ -125,9 +129,10 @@ public:
|
|||
* object
|
||||
* @return A list of groups which override the given texture
|
||||
*/
|
||||
Placements set_texture( const SGPropertyNode* placement,
|
||||
osg::Texture2D* new_texture,
|
||||
osg::NodeCallback* cull_callback = 0 );
|
||||
static
|
||||
canvas::Placements set_texture( const SGPropertyNode* placement,
|
||||
osg::Texture2D* new_texture,
|
||||
osg::NodeCallback* cull_callback = 0 );
|
||||
|
||||
/**
|
||||
* Get the OSG camera for drawing this gauge.
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
#include <Cockpit/panel_io.hxx>
|
||||
|
||||
#include <Canvas/canvas_mgr.hxx>
|
||||
#include <Canvas/gui_mgr.hxx>
|
||||
#include <GUI/new_gui.hxx>
|
||||
#include <Input/input.hxx>
|
||||
#include <Instrumentation/instrument_mgr.hxx>
|
||||
|
@ -1164,6 +1165,7 @@ bool fgInitSubsystems() {
|
|||
// Initialize the canvas 2d drawing subsystem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
globals->add_subsystem("Canvas", new CanvasMgr, SGSubsystemMgr::DISPLAY);
|
||||
globals->add_subsystem("CanvasGUI", new GUIMgr, SGSubsystemMgr::DISPLAY);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialise the ATIS Manager
|
||||
|
|
Loading…
Add table
Reference in a new issue