Expose character-aspect-ratio and do some clean up
- Fix stupid memory corruption bug - Fix bounding box calculations - Fix docs - Fix text size - Expose setting background color - Expose trigger for updating elements - Untie nodes if deleting according element - Allow deleting canvas, text and group elements - Allow creating groups as children of groups
This commit is contained in:
parent
17ec3278ed
commit
023021a879
14 changed files with 394 additions and 152 deletions
|
@ -2,7 +2,7 @@ Canvas - A 2D Drawing API
|
|||
=========================
|
||||
|
||||
Author: Thomas Geymayer <admin@tomprogs.at>
|
||||
Revision: 2012/05/04
|
||||
Revision: 2012/05/18
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
@ -22,11 +22,11 @@ Creating a canvas
|
|||
A new canvas can be instantiated by creating a node /canvas/texture[<INDEX>]
|
||||
with at least the following children:
|
||||
|
||||
<size-x type="int"> The width of the underlying texture
|
||||
<size-y type="int"> The height of the underlying texture
|
||||
<size n="0" type="int"> The width of the underlying texture
|
||||
<size n="1" type="int"> The height of the underlying texture
|
||||
|
||||
<view-width type="int"> The width of the canvas
|
||||
<view-height type="int"> The height of the canvas
|
||||
<view n="0" type="int"> The width of the canvas
|
||||
<view n="1" type="int"> The height of the canvas
|
||||
|
||||
The dimensions of the canvas are needed to be able to use textures with
|
||||
different resolutions but use the same units for rendering to the canvas.
|
||||
|
@ -60,6 +60,7 @@ only drawing Text is possible:
|
|||
<red type="float">
|
||||
<green type="float">
|
||||
<blue type="float">
|
||||
<alpha type="float">
|
||||
</NAME>
|
||||
|
||||
* Text:
|
||||
|
@ -71,7 +72,9 @@ only drawing Text is possible:
|
|||
2. aircraft-dir
|
||||
3. $FG_DATA/Fonts
|
||||
4. Default osg font paths
|
||||
<size type="float"> The font size (default: 32)
|
||||
<character-size type="float"> The font size (default: 32)
|
||||
<character-aspect-ratio type="float"> Ratio between character height and width
|
||||
(default: 1)
|
||||
<tf> A 3x3 transformation matrix specified by 6 values
|
||||
(child elements <a>, ..., <f>) See
|
||||
http://www.w3.org/TR/SVG/coords.html#TransformMatrixDefined
|
||||
|
@ -129,17 +132,24 @@ Example
|
|||
|
||||
<canvas>
|
||||
<texture>
|
||||
<size-x type="int">384</size-x>
|
||||
<size-y type="int">512</size-y>
|
||||
<view-width type="int">768</view-width>
|
||||
<view-height type="int">1024</view-height>
|
||||
<size n="0" type="int">384</size-x>
|
||||
<size n="1" type="int">512</size-y>
|
||||
<view n="0" type="int">768</view-width>
|
||||
<view n="1" type="int">1024</view-height>
|
||||
<mipmapping type="bool">false</mipmapping>
|
||||
<coverage-samples type="int">0</coverage-samples>
|
||||
<color-samples type="int">0</color-samples>
|
||||
<color-background>
|
||||
<red type="float">0</red>
|
||||
<green type="float">0.02</green>
|
||||
<blue type="float">0</blue>
|
||||
<alpha type="float">1</alpha>
|
||||
</color-background>
|
||||
<group>
|
||||
<text>
|
||||
<text type="string">TEST MESSAGE</text>
|
||||
<font type="string">helvetica_bold.txf</font>
|
||||
<character-size type="float">40</character-size>
|
||||
<tf>
|
||||
<!-- Translate (18|50) -->
|
||||
<tx>18</tx>
|
||||
|
|
|
@ -6,6 +6,7 @@ set(SOURCES
|
|||
elements/element.cxx
|
||||
elements/group.cxx
|
||||
elements/text.cxx
|
||||
property_helper.cxx
|
||||
)
|
||||
|
||||
set(HEADERS
|
||||
|
@ -14,6 +15,7 @@ set(HEADERS
|
|||
elements/element.hxx
|
||||
elements/group.hxx
|
||||
elements/text.hxx
|
||||
property_helper.hxx
|
||||
)
|
||||
|
||||
flightgear_component(Canvas "${SOURCES}" "${HEADERS}")
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "canvas.hxx"
|
||||
#include "elements/group.hxx"
|
||||
#include <Canvas/property_helper.hxx>
|
||||
|
||||
#include <osg/Camera>
|
||||
#include <osg/Geode>
|
||||
|
@ -25,9 +26,6 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
//#include <Main/globals.hxx>
|
||||
//#include <Viewer/renderer.hxx>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Callback used to disable/enable rendering to the texture if it is not
|
||||
|
@ -97,8 +95,9 @@ Canvas::Canvas():
|
|||
_view_width(-1),
|
||||
_view_height(-1),
|
||||
_status(0),
|
||||
_node(0),
|
||||
_sampling_dirty(false)
|
||||
_sampling_dirty(false),
|
||||
_color_dirty(true),
|
||||
_node(0)
|
||||
{
|
||||
setStatusFlags(MISSING_SIZE_X | MISSING_SIZE_Y);
|
||||
|
||||
|
@ -110,7 +109,10 @@ Canvas::Canvas():
|
|||
//------------------------------------------------------------------------------
|
||||
Canvas::~Canvas()
|
||||
{
|
||||
clearPlacements();
|
||||
|
||||
unbind();
|
||||
_node = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -122,23 +124,21 @@ int Canvas::getStatus() const
|
|||
//------------------------------------------------------------------------------
|
||||
void Canvas::reset(SGPropertyNode* node)
|
||||
{
|
||||
if( _node )
|
||||
{
|
||||
_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);
|
||||
_node = 0;
|
||||
}
|
||||
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 )
|
||||
if( _node )
|
||||
{
|
||||
_node = node;
|
||||
_node->tie
|
||||
(
|
||||
"size[0]",
|
||||
|
@ -174,6 +174,14 @@ void Canvas::reset(SGPropertyNode* node)
|
|||
SGRawValueMethods<Canvas, const char*>(*this, &Canvas::getStatusMsg)
|
||||
);
|
||||
_node->addChangeListener(this);
|
||||
|
||||
canvas::linkColorNodes
|
||||
(
|
||||
"color-background",
|
||||
_node,
|
||||
_color_background,
|
||||
osg::Vec4f(0,0,0,1)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,6 +225,17 @@ void Canvas::update(double delta_time_sec)
|
|||
);
|
||||
_sampling_dirty = false;
|
||||
}
|
||||
if( _color_dirty )
|
||||
{
|
||||
_texture.getCamera()->setClearColor
|
||||
(
|
||||
osg::Vec4( _color_background[0]->getFloatValue(),
|
||||
_color_background[1]->getFloatValue(),
|
||||
_color_background[2]->getFloatValue(),
|
||||
_color_background[3]->getFloatValue() )
|
||||
);
|
||||
_color_dirty = false;
|
||||
}
|
||||
|
||||
while( !_dirty_placements.empty() )
|
||||
{
|
||||
|
@ -345,8 +364,6 @@ void Canvas::childAdded( SGPropertyNode * parent,
|
|||
{
|
||||
_dirty_placements.push_back(child);
|
||||
}
|
||||
// else
|
||||
// std::cout << "Canvas::childAdded: " << child->getPath() << std::endl;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -358,24 +375,29 @@ void Canvas::childRemoved( SGPropertyNode * parent,
|
|||
|
||||
if( child->getNameString() == "placement" )
|
||||
clearPlacements(child->getIndex());
|
||||
else
|
||||
std::cout << "Canvas::childRemoved: " << child->getPath() << std::endl;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Canvas::valueChanged(SGPropertyNode * node)
|
||||
{
|
||||
if( node->getParent()->getParent() == _node
|
||||
&& node->getParent()->getNameString() == "placement" )
|
||||
if( node->getParent()->getParent() == _node )
|
||||
{
|
||||
// prevent double updates...
|
||||
for( size_t i = 0; i < _dirty_placements.size(); ++i )
|
||||
if( !_color_background.empty()
|
||||
&& _color_background[0]->getParent() == node->getParent() )
|
||||
{
|
||||
if( node->getParent() == _dirty_placements[i] )
|
||||
return;
|
||||
_color_dirty = true;
|
||||
}
|
||||
else if( node->getParent()->getNameString() == "placement" )
|
||||
{
|
||||
// prevent double updates...
|
||||
for( size_t i = 0; i < _dirty_placements.size(); ++i )
|
||||
{
|
||||
if( node->getParent() == _dirty_placements[i] )
|
||||
return;
|
||||
}
|
||||
|
||||
_dirty_placements.push_back(node->getParent());
|
||||
_dirty_placements.push_back(node->getParent());
|
||||
}
|
||||
}
|
||||
else if( node->getParent() == _node )
|
||||
{
|
||||
|
@ -428,3 +450,26 @@ void Canvas::clearPlacements(int index)
|
|||
parent->removeChild(group);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -73,6 +73,9 @@ class Canvas:
|
|||
|
||||
private:
|
||||
|
||||
Canvas(const Canvas&); // = delete;
|
||||
Canvas& operator=(const Canvas&); // = delete;
|
||||
|
||||
int _size_x,
|
||||
_size_y,
|
||||
_view_width,
|
||||
|
@ -81,10 +84,13 @@ class Canvas:
|
|||
int _status;
|
||||
std::string _status_msg;
|
||||
|
||||
FGODGauge _texture;
|
||||
SGPropertyNode *_node;
|
||||
bool _sampling_dirty,
|
||||
_color_dirty;
|
||||
|
||||
bool _sampling_dirty;
|
||||
FGODGauge _texture;
|
||||
|
||||
SGPropertyNode_ptr _node;
|
||||
std::vector<SGPropertyNode_ptr> _color_background;
|
||||
|
||||
osg::ref_ptr<osg::NodeCallback> _camera_callback;
|
||||
osg::ref_ptr<osg::NodeCallback> _cull_callback;
|
||||
|
@ -96,6 +102,9 @@ class Canvas:
|
|||
|
||||
void setStatusFlags(unsigned int flags, bool set = true);
|
||||
void clearPlacements(int index);
|
||||
void clearPlacements();
|
||||
|
||||
void unbind();
|
||||
};
|
||||
|
||||
#endif /* CANVAS_HXX_ */
|
||||
|
|
|
@ -73,7 +73,8 @@ void CanvasMgr::unbind()
|
|||
void CanvasMgr::update(double delta_time_sec)
|
||||
{
|
||||
for( size_t i = 0; i < _canvases.size(); ++i )
|
||||
_canvases[i].update(delta_time_sec);
|
||||
if( _canvases[i] )
|
||||
_canvases[i]->update(delta_time_sec);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -85,8 +86,6 @@ void CanvasMgr::childAdded( SGPropertyNode * parent,
|
|||
|
||||
if( child->getNameString() == "texture" )
|
||||
textureAdded(child);
|
||||
else
|
||||
std::cout << "CanvasMgr::childAdded: " << child->getPath() << std::endl;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -96,7 +95,16 @@ void CanvasMgr::childRemoved( SGPropertyNode * parent,
|
|||
if( parent != _props )
|
||||
return;
|
||||
|
||||
std::cout << "CanvasMgr::childRemoved: " << child->getPath() << std::endl;
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -108,17 +116,16 @@ void CanvasMgr::textureAdded(SGPropertyNode* node)
|
|||
{
|
||||
if( index > _canvases.size() )
|
||||
SG_LOG(SG_GL, SG_WARN, "Skipping unused texture slot(s)!");
|
||||
SG_LOG(SG_GL, SG_INFO, "Add new texture[" << index << "]");
|
||||
|
||||
_canvases.resize(index + 1);
|
||||
_canvases[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
SG_LOG(SG_GL, SG_WARN, "texture[" << index << "] already exists!");
|
||||
}
|
||||
|
||||
_canvases[index].reset(node);
|
||||
_canvases[index].reset( new Canvas() );
|
||||
_canvases[index]->reset(node);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -132,13 +139,3 @@ void CanvasMgr::triggerChangeRecursive(SGPropertyNode* node)
|
|||
for( int i = 0; i < node->nChildren(); ++i )
|
||||
triggerChangeRecursive( node->getChild(i) );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template<class T>
|
||||
T CanvasMgr::getParam(const SGPropertyNode* node, const char* prop)
|
||||
{
|
||||
const SGPropertyNode* child = node->getChild(prop);
|
||||
if( !child )
|
||||
throw std::runtime_error(std::string("Missing property ") + prop);
|
||||
return getValue<T>(child);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <vector>
|
||||
|
||||
class Canvas;
|
||||
typedef boost::shared_ptr<Canvas> CanvasPtr;
|
||||
|
||||
class CanvasMgr:
|
||||
public SGSubsystem,
|
||||
|
@ -55,7 +56,7 @@ class CanvasMgr:
|
|||
SGPropertyNode_ptr _props;
|
||||
|
||||
/** The actual canvases */
|
||||
std::vector<Canvas> _canvases;
|
||||
std::vector<CanvasPtr> _canvases;
|
||||
|
||||
void textureAdded(SGPropertyNode* node);
|
||||
|
||||
|
@ -65,12 +66,6 @@ class CanvasMgr:
|
|||
*/
|
||||
void triggerChangeRecursive(SGPropertyNode* node);
|
||||
|
||||
/**
|
||||
* Get the value of a property or throw an exception if it doesn't exist.
|
||||
*/
|
||||
template<class T>
|
||||
T getParam(const SGPropertyNode* node, const char* prop);
|
||||
|
||||
};
|
||||
|
||||
#endif /* CANVAS_MGR_H_ */
|
||||
|
|
|
@ -17,10 +17,13 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#include "element.hxx"
|
||||
#include <cassert>
|
||||
#include <Canvas/property_helper.hxx>
|
||||
|
||||
#include <osg/Drawable>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
namespace canvas
|
||||
{
|
||||
const std::string NAME_TRANSFORM = "tf";
|
||||
|
@ -33,12 +36,6 @@ namespace canvas
|
|||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
SGPropertyNode* Element::getPropertyNode()
|
||||
{
|
||||
return _node;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::update(double dt)
|
||||
{
|
||||
|
@ -97,7 +94,7 @@ namespace canvas
|
|||
colorChanged( osg::Vec4( _color[0]->getFloatValue(),
|
||||
_color[1]->getFloatValue(),
|
||||
_color[2]->getFloatValue(),
|
||||
1 ) );
|
||||
_color[3]->getFloatValue() ) );
|
||||
_attributes_dirty &= ~COLOR;
|
||||
}
|
||||
|
||||
|
@ -106,18 +103,19 @@ namespace canvas
|
|||
colorFillChanged( osg::Vec4( _color_fill[0]->getFloatValue(),
|
||||
_color_fill[1]->getFloatValue(),
|
||||
_color_fill[2]->getFloatValue(),
|
||||
1 ) );
|
||||
_color_fill[3]->getFloatValue() ) );
|
||||
_attributes_dirty &= ~COLOR_FILL;
|
||||
}
|
||||
|
||||
if( _drawable && (_attributes_dirty & BOUNDING_BOX) )
|
||||
if( !_bounding_box.empty() )
|
||||
{
|
||||
_bounding_box[0]->setFloatValue(_drawable->getBound()._min.x());
|
||||
_bounding_box[1]->setFloatValue(_drawable->getBound()._min.y());
|
||||
_bounding_box[2]->setFloatValue(_drawable->getBound()._max.x());
|
||||
_bounding_box[3]->setFloatValue(_drawable->getBound()._max.y());
|
||||
assert( _drawable );
|
||||
|
||||
_attributes_dirty &= ~BOUNDING_BOX;
|
||||
const osg::BoundingBox& bb = _drawable->getBound();
|
||||
_bounding_box[0]->setFloatValue(bb._min.x());
|
||||
_bounding_box[1]->setFloatValue(bb._min.y());
|
||||
_bounding_box[2]->setFloatValue(bb._max.x());
|
||||
_bounding_box[3]->setFloatValue(bb._max.y());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,29 +126,22 @@ namespace canvas
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Element::Element(SGPropertyNode* node, uint32_t attributes_used):
|
||||
_node( node ),
|
||||
_drawable( 0 ),
|
||||
Element::Element(SGPropertyNode_ptr node, uint32_t attributes_used):
|
||||
_attributes_used( attributes_used ),
|
||||
_attributes_dirty( 0 ),
|
||||
_attributes_dirty( attributes_used ),
|
||||
_transform_dirty( false ),
|
||||
_transform( new osg::MatrixTransform )
|
||||
_transform( new osg::MatrixTransform ),
|
||||
_node( node ),
|
||||
_drawable( 0 )
|
||||
{
|
||||
assert( _node );
|
||||
_node->addChangeListener(this);
|
||||
|
||||
if( _attributes_used & COLOR )
|
||||
linkColorNodes("color", _color, osg::Vec4f(0,1,0,1));
|
||||
linkColorNodes("color", _node, _color, osg::Vec4f(0,1,0,1));
|
||||
|
||||
if( _attributes_used & COLOR_FILL )
|
||||
linkColorNodes("color-fill", _color_fill);
|
||||
if( _attributes_used & BOUNDING_BOX )
|
||||
{
|
||||
SGPropertyNode* bb = _node->getChild("bounding-box", 0, true);
|
||||
_bounding_box[0] = bb->getChild("x-min", 0, true);
|
||||
_bounding_box[1] = bb->getChild("y-min", 0, true);
|
||||
_bounding_box[2] = bb->getChild("x-max", 0, true);
|
||||
_bounding_box[3] = bb->getChild("y-max", 0, true);
|
||||
}
|
||||
linkColorNodes("color-fill", _node, _color_fill);
|
||||
|
||||
SG_LOG
|
||||
(
|
||||
|
@ -161,22 +152,19 @@ namespace canvas
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::linkColorNodes( const char* name,
|
||||
SGPropertyNode** nodes,
|
||||
const osg::Vec4& def )
|
||||
void Element::setDrawable( osg::Drawable* drawable )
|
||||
{
|
||||
// Don't tie to allow the usage of aliases
|
||||
SGPropertyNode* color = _node->getChild(name, 0, true);
|
||||
_drawable = drawable;
|
||||
assert( _drawable );
|
||||
|
||||
static const char* color_names[] = {"red", "green", "blue"};
|
||||
for( size_t i = 0; i < sizeof(color_names)/sizeof(color_names[0]); ++i )
|
||||
if( _attributes_used & BOUNDING_BOX )
|
||||
{
|
||||
color->setFloatValue
|
||||
(
|
||||
color_names[i],
|
||||
color->getFloatValue(color_names[i], def[i])
|
||||
);
|
||||
nodes[i] = color->getChild(color_names[i]);
|
||||
SGPropertyNode* bb_node = _node->getChild("bounding-box", 0, true);
|
||||
_bounding_box.resize(4);
|
||||
_bounding_box[0] = bb_node->getChild("min-x", 0, true);
|
||||
_bounding_box[1] = bb_node->getChild("min-y", 0, true);
|
||||
_bounding_box[2] = bb_node->getChild("max-x", 0, true);
|
||||
_bounding_box[3] = bb_node->getChild("max-y", 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -254,13 +242,18 @@ namespace canvas
|
|||
{
|
||||
if( parent->getNameString() == NAME_TRANSFORM )
|
||||
_transform_dirty = true;
|
||||
else if( parent->getNameString() == NAME_COLOR )
|
||||
else if( !_color.empty() && _color[0]->getParent() == parent )
|
||||
_attributes_dirty |= COLOR;
|
||||
else if( parent->getNameString() == NAME_COLOR_FILL )
|
||||
else if( !_color_fill.empty() && _color_fill[0]->getParent() == parent )
|
||||
_attributes_dirty |= COLOR_FILL;
|
||||
}
|
||||
else
|
||||
childChanged(child);
|
||||
else if( parent == _node )
|
||||
{
|
||||
if( child->getNameString() == "update" )
|
||||
update(0);
|
||||
else
|
||||
childChanged(child);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace canvas
|
||||
|
|
|
@ -36,7 +36,6 @@ namespace canvas
|
|||
{
|
||||
public:
|
||||
virtual ~Element() = 0;
|
||||
SGPropertyNode* getPropertyNode();
|
||||
|
||||
/**
|
||||
* Called every frame to update internal state
|
||||
|
@ -53,7 +52,8 @@ namespace canvas
|
|||
{
|
||||
COLOR = 0x0001,
|
||||
COLOR_FILL = 0x0002,
|
||||
BOUNDING_BOX = 0x0004
|
||||
BOUNDING_BOX = 0x0004,
|
||||
LAST_ATTRIBUTE = BOUNDING_BOX
|
||||
};
|
||||
|
||||
enum TransformType
|
||||
|
@ -65,9 +65,6 @@ namespace canvas
|
|||
TT_SCALE
|
||||
};
|
||||
|
||||
SGPropertyNode *_node;
|
||||
osg::Drawable *_drawable;
|
||||
|
||||
uint32_t _attributes_used;
|
||||
uint32_t _attributes_dirty;
|
||||
|
||||
|
@ -75,11 +72,12 @@ namespace canvas
|
|||
osg::ref_ptr<osg::MatrixTransform> _transform;
|
||||
std::vector<TransformType> _transform_types;
|
||||
|
||||
SGPropertyNode *_bounding_box[4]; ///<! x-min, y-min, x-max, y-max
|
||||
SGPropertyNode *_color[3];
|
||||
SGPropertyNode *_color_fill[3];
|
||||
SGPropertyNode_ptr _node;
|
||||
std::vector<SGPropertyNode_ptr> _color,
|
||||
_color_fill;
|
||||
std::vector<SGPropertyNode_ptr> _bounding_box;
|
||||
|
||||
Element(SGPropertyNode* node, uint32_t attributes_used = 0);
|
||||
Element(SGPropertyNode_ptr node, uint32_t attributes_used = 0);
|
||||
|
||||
virtual void childAdded(SGPropertyNode * child) {}
|
||||
virtual void childRemoved(SGPropertyNode * child){}
|
||||
|
@ -88,11 +86,12 @@ namespace canvas
|
|||
virtual void colorChanged(const osg::Vec4& color) {}
|
||||
virtual void colorFillChanged(const osg::Vec4& color){}
|
||||
|
||||
void linkColorNodes( const char* name,
|
||||
SGPropertyNode** nodes,
|
||||
const osg::Vec4& def = osg::Vec4(1,1,0,1) );
|
||||
void setDrawable( osg::Drawable* drawable );
|
||||
|
||||
private:
|
||||
|
||||
osg::Drawable *_drawable;
|
||||
|
||||
Element(const Element&);// = delete
|
||||
|
||||
virtual void childAdded( SGPropertyNode * parent,
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace canvas
|
|||
{
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Group::Group(SGPropertyNode* node):
|
||||
Group::Group(SGPropertyNode_ptr node):
|
||||
Element(node)
|
||||
{
|
||||
|
||||
|
@ -39,7 +39,10 @@ namespace canvas
|
|||
void Group::update(double dt)
|
||||
{
|
||||
for( size_t i = 0; i < _children.size(); ++i )
|
||||
_children[i]->update(dt);
|
||||
{
|
||||
if( _children[i] )
|
||||
_children[i]->update(dt);
|
||||
}
|
||||
|
||||
Element::update(dt);
|
||||
}
|
||||
|
@ -47,19 +50,58 @@ namespace canvas
|
|||
//----------------------------------------------------------------------------
|
||||
void Group::childAdded(SGPropertyNode* child)
|
||||
{
|
||||
boost::shared_ptr<Element> element;
|
||||
|
||||
if( child->getNameString() == "text" )
|
||||
{
|
||||
_children.push_back( boost::shared_ptr<Element>(new Text(child)) );
|
||||
_transform->addChild( _children.back()->getMatrixTransform() );
|
||||
}
|
||||
element.reset( new Text(child) );
|
||||
else if( child->getNameString() == "group" )
|
||||
element.reset( new Group(child) );
|
||||
else
|
||||
std::cout << "New unknown child: " << child->getDisplayName() << std::endl;
|
||||
SG_LOG
|
||||
(
|
||||
SG_GL,
|
||||
SG_WARN,
|
||||
"canvas::Group unknown child: " << child->getDisplayName()
|
||||
);
|
||||
|
||||
if( !element )
|
||||
return;
|
||||
|
||||
// Add to osg scene graph...
|
||||
_transform->addChild( element->getMatrixTransform() );
|
||||
|
||||
// ...and build up canvas hierarchy
|
||||
size_t index = child->getIndex();
|
||||
|
||||
if( index >= _children.size() )
|
||||
_children.resize(index + 1);
|
||||
|
||||
_children[index] = element;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Group::childRemoved(SGPropertyNode* child)
|
||||
{
|
||||
if( child->getNameString() == "text"
|
||||
|| child->getNameString() == "group" )
|
||||
{
|
||||
size_t index = child->getIndex();
|
||||
|
||||
if( index >= _children.size() )
|
||||
SG_LOG
|
||||
(
|
||||
SG_GL,
|
||||
SG_WARN,
|
||||
"can't removed unknown child " << child->getDisplayName()
|
||||
);
|
||||
else
|
||||
{
|
||||
boost::shared_ptr<Element>& element = _children[index];
|
||||
if( element )
|
||||
_transform->removeChild(element->getMatrixTransform());
|
||||
element.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace canvas
|
||||
|
|
|
@ -26,17 +26,19 @@
|
|||
namespace canvas
|
||||
{
|
||||
|
||||
typedef boost::shared_ptr<Element> ElementPtr;
|
||||
|
||||
class Group:
|
||||
public Element
|
||||
{
|
||||
public:
|
||||
Group(SGPropertyNode* node);
|
||||
Group(SGPropertyNode_ptr node);
|
||||
virtual ~Group();
|
||||
|
||||
virtual void update(double dt);
|
||||
|
||||
protected:
|
||||
std::vector<boost::shared_ptr<Element> > _children;
|
||||
std::vector<ElementPtr> _children;
|
||||
|
||||
virtual void childAdded(SGPropertyNode * child);
|
||||
virtual void childRemoved(SGPropertyNode * child);
|
||||
|
|
|
@ -17,26 +17,30 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#include "text.hxx"
|
||||
#include <osgText/Text>
|
||||
#include <Canvas/property_helper.hxx>
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
|
||||
#include <osgText/Text>
|
||||
|
||||
namespace canvas
|
||||
{
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Text::Text(SGPropertyNode* node):
|
||||
Text::Text(SGPropertyNode_ptr node):
|
||||
Element(node, COLOR | COLOR_FILL | BOUNDING_BOX),
|
||||
_text( new osgText::Text )
|
||||
_text( new osgText::Text ),
|
||||
_font_size( 0 ),
|
||||
_font_aspect( 0 )
|
||||
{
|
||||
_drawable = _text;
|
||||
_text->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
|
||||
setDrawable(_text);
|
||||
_text->setCharacterSizeMode(osgText::Text::OBJECT_COORDS);
|
||||
_text->setAxisAlignment(osgText::Text::USER_DEFINED_ROTATION);
|
||||
_text->setRotation(osg::Quat(osg::PI, osg::X_AXIS));
|
||||
|
||||
// font size and property node
|
||||
float character_size = _node->getFloatValue("size", 32);
|
||||
_text->setCharacterSize( character_size );
|
||||
_node->setFloatValue("size", character_size);
|
||||
_font_size = getChildDefault<float>(_node, "character-size", 32);
|
||||
_font_aspect = getChildDefault<float>(_node, "character-aspect-ratio", 1);
|
||||
|
||||
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
|
||||
geode->addDrawable(_text);
|
||||
|
@ -82,7 +86,30 @@ namespace canvas
|
|||
//----------------------------------------------------------------------------
|
||||
Text::~Text()
|
||||
{
|
||||
if( _node )
|
||||
{
|
||||
_node->untie("alignment");
|
||||
_node->untie("padding");
|
||||
_node->untie("draw-mode");
|
||||
}
|
||||
_node = 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Text::update(double dt)
|
||||
{
|
||||
Element::update(dt);
|
||||
|
||||
if( _attributes_dirty & FONT_SIZE )
|
||||
{
|
||||
_text->setCharacterSize
|
||||
(
|
||||
_font_size->getFloatValue(),
|
||||
_font_aspect->getFloatValue()
|
||||
);
|
||||
|
||||
_attributes_dirty &= ~FONT_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -123,16 +150,12 @@ namespace canvas
|
|||
//----------------------------------------------------------------------------
|
||||
void Text::childChanged(SGPropertyNode* child)
|
||||
{
|
||||
if( child->getNameString() == "text" )
|
||||
_text->setText(child->getStringValue());
|
||||
else if( child->getNameString() == "size" )
|
||||
_text->setCharacterSize( child->getFloatValue() );
|
||||
if( _font_size == child || _font_aspect == child )
|
||||
_attributes_dirty |= FONT_SIZE;
|
||||
else if( child->getNameString() == "text" )
|
||||
_text->setText( child->getStringValue() );
|
||||
else if( child->getNameString() == "font" )
|
||||
setFont( child->getStringValue() );
|
||||
else
|
||||
return;
|
||||
|
||||
_attributes_dirty |= BOUNDING_BOX;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
|
@ -32,17 +32,28 @@ namespace canvas
|
|||
public Element
|
||||
{
|
||||
public:
|
||||
Text(SGPropertyNode* node);
|
||||
Text(SGPropertyNode_ptr node);
|
||||
virtual ~Text();
|
||||
|
||||
virtual void update(double dt);
|
||||
|
||||
void setFont(const char* name);
|
||||
|
||||
void setAlignment(const char* align);
|
||||
const char* getAlignment() const;
|
||||
|
||||
protected:
|
||||
|
||||
enum TextAttributes
|
||||
{
|
||||
FONT_SIZE = LAST_ATTRIBUTE << 1, // Font size and aspect ration
|
||||
};
|
||||
|
||||
osg::ref_ptr<osgText::Text> _text;
|
||||
|
||||
SGPropertyNode_ptr _font_size,
|
||||
_font_aspect;
|
||||
|
||||
virtual void childChanged(SGPropertyNode * child);
|
||||
virtual void colorChanged(const osg::Vec4& color);
|
||||
virtual void colorFillChanged(const osg::Vec4& color);
|
||||
|
|
47
src/Canvas/property_helper.cxx
Normal file
47
src/Canvas/property_helper.cxx
Normal file
|
@ -0,0 +1,47 @@
|
|||
// Some helper functions for accessing the property tree
|
||||
//
|
||||
// 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_helper.hxx"
|
||||
#include <cassert>
|
||||
|
||||
namespace canvas
|
||||
{
|
||||
//----------------------------------------------------------------------------
|
||||
void linkColorNodes( const char* name,
|
||||
SGPropertyNode* parent,
|
||||
std::vector<SGPropertyNode_ptr>& nodes,
|
||||
const osg::Vec4& def )
|
||||
{
|
||||
static const char* channels[] = {"red", "green", "blue", "alpha"};
|
||||
static const size_t num_channels = sizeof(channels)/sizeof(channels[0]);
|
||||
|
||||
assert(name);
|
||||
assert(parent);
|
||||
|
||||
// Don't tie to allow the usage of aliases
|
||||
SGPropertyNode_ptr color = parent->getChild(name, 0, true);
|
||||
|
||||
// We need to be carefull do not get any unitialized nodes or null pointers
|
||||
// because while creating the node a valueChanged event will be triggered.
|
||||
nodes.clear();
|
||||
nodes.reserve(num_channels);
|
||||
|
||||
for( size_t i = 0; i < num_channels; ++i )
|
||||
nodes.push_back( getChildDefault(color, channels[i], def[i]) );
|
||||
}
|
||||
}
|
67
src/Canvas/property_helper.hxx
Normal file
67
src/Canvas/property_helper.hxx
Normal file
|
@ -0,0 +1,67 @@
|
|||
// Some helper functions for accessing the property tree
|
||||
//
|
||||
// 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_HELPER_HXX_
|
||||
#define PROPERTY_HELPER_HXX_
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <osg/Vec4>
|
||||
|
||||
namespace canvas
|
||||
{
|
||||
|
||||
/**
|
||||
* Get property node with default value
|
||||
*/
|
||||
template<typename T>
|
||||
SGPropertyNode* getChildDefault( SGPropertyNode* parent,
|
||||
const char* name,
|
||||
T def_val )
|
||||
{
|
||||
SGPropertyNode* node = parent->getNode(name);
|
||||
if( node )
|
||||
// also set value for existing nodes to enforce type...
|
||||
def_val = getValue<T>(node);
|
||||
else
|
||||
node = parent->getChild(name, 0, true);
|
||||
|
||||
setValue(node, def_val);
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name Name of color node
|
||||
* @param parent Parent for color channel nodes
|
||||
* @param nodes Vector to push color nodes into
|
||||
* @param def Default color
|
||||
*
|
||||
* <name>
|
||||
* <red type="float">def[0] or existing value</red>
|
||||
* <green type="float">def[1] or existing value</green>
|
||||
* <blue type="float">def[2] or existing value</blue>
|
||||
* <alpha type="float">def[3] or existing value</alpha>
|
||||
* </name>
|
||||
*/
|
||||
void linkColorNodes( const char* name,
|
||||
SGPropertyNode* parent,
|
||||
std::vector<SGPropertyNode_ptr>& nodes,
|
||||
const osg::Vec4& def = osg::Vec4(0,0,0,0) );
|
||||
|
||||
} // namespace canvas
|
||||
|
||||
#endif /* PROPERTY_HELPER_HXX_ */
|
Loading…
Reference in a new issue