From 023021a879b3c7c1235b8a1fb936b2e20b7859b9 Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Sun, 20 May 2012 19:14:00 +0200 Subject: [PATCH] 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 --- docs-mini/README.canvas | 30 ++++++---- src/Canvas/CMakeLists.txt | 2 + src/Canvas/canvas.cxx | 103 +++++++++++++++++++++++--------- src/Canvas/canvas.hxx | 15 ++++- src/Canvas/canvas_mgr.cxx | 31 +++++----- src/Canvas/canvas_mgr.hxx | 9 +-- src/Canvas/elements/element.cxx | 87 +++++++++++++-------------- src/Canvas/elements/element.hxx | 23 ++++--- src/Canvas/elements/group.cxx | 56 ++++++++++++++--- src/Canvas/elements/group.hxx | 6 +- src/Canvas/elements/text.cxx | 57 ++++++++++++------ src/Canvas/elements/text.hxx | 13 +++- src/Canvas/property_helper.cxx | 47 +++++++++++++++ src/Canvas/property_helper.hxx | 67 +++++++++++++++++++++ 14 files changed, 394 insertions(+), 152 deletions(-) create mode 100644 src/Canvas/property_helper.cxx create mode 100644 src/Canvas/property_helper.hxx diff --git a/docs-mini/README.canvas b/docs-mini/README.canvas index 670f1d17d..8cc0b3004 100644 --- a/docs-mini/README.canvas +++ b/docs-mini/README.canvas @@ -2,7 +2,7 @@ Canvas - A 2D Drawing API ========================= Author: Thomas Geymayer -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[] with at least the following children: - The width of the underlying texture - The height of the underlying texture + The width of the underlying texture + The height of the underlying texture - The width of the canvas - The height of the canvas + The width of the canvas + 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: + * Text: @@ -71,7 +72,9 @@ only drawing Text is possible: 2. aircraft-dir 3. $FG_DATA/Fonts 4. Default osg font paths - The font size (default: 32) + The font size (default: 32) + Ratio between character height and width + (default: 1) A 3x3 transformation matrix specified by 6 values (child elements , ..., ) See http://www.w3.org/TR/SVG/coords.html#TransformMatrixDefined @@ -129,17 +132,24 @@ Example - 384 - 512 - 768 - 1024 + 384 + 512 + 768 + 1024 false 0 0 + + 0 + 0.02 + 0 + 1 + TEST MESSAGE helvetica_bold.txf + 40 18 diff --git a/src/Canvas/CMakeLists.txt b/src/Canvas/CMakeLists.txt index 1dde0d26b..5de9945c0 100644 --- a/src/Canvas/CMakeLists.txt +++ b/src/Canvas/CMakeLists.txt @@ -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}") diff --git a/src/Canvas/canvas.cxx b/src/Canvas/canvas.cxx index 31e82653a..e82c08123 100644 --- a/src/Canvas/canvas.cxx +++ b/src/Canvas/canvas.cxx @@ -18,6 +18,7 @@ #include "canvas.hxx" #include "elements/group.hxx" +#include #include #include @@ -25,9 +26,6 @@ #include -//#include
-//#include - //------------------------------------------------------------------------------ /** * 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(*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); +} diff --git a/src/Canvas/canvas.hxx b/src/Canvas/canvas.hxx index 1769b8ed4..9094825d4 100644 --- a/src/Canvas/canvas.hxx +++ b/src/Canvas/canvas.hxx @@ -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 _color_background; osg::ref_ptr _camera_callback; osg::ref_ptr _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_ */ diff --git a/src/Canvas/canvas_mgr.cxx b/src/Canvas/canvas_mgr.cxx index eab30b581..72db55fd0 100644 --- a/src/Canvas/canvas_mgr.cxx +++ b/src/Canvas/canvas_mgr.cxx @@ -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 -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(child); -} diff --git a/src/Canvas/canvas_mgr.hxx b/src/Canvas/canvas_mgr.hxx index b3b5bac0e..893b50e88 100644 --- a/src/Canvas/canvas_mgr.hxx +++ b/src/Canvas/canvas_mgr.hxx @@ -26,6 +26,7 @@ #include class Canvas; +typedef boost::shared_ptr CanvasPtr; class CanvasMgr: public SGSubsystem, @@ -55,7 +56,7 @@ class CanvasMgr: SGPropertyNode_ptr _props; /** The actual canvases */ - std::vector _canvases; + std::vector _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 - T getParam(const SGPropertyNode* node, const char* prop); - }; #endif /* CANVAS_MGR_H_ */ diff --git a/src/Canvas/elements/element.cxx b/src/Canvas/elements/element.cxx index 119f109e6..87ce8e609 100644 --- a/src/Canvas/elements/element.cxx +++ b/src/Canvas/elements/element.cxx @@ -17,10 +17,13 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "element.hxx" -#include +#include #include +#include +#include + 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 diff --git a/src/Canvas/elements/element.hxx b/src/Canvas/elements/element.hxx index b17a02977..3c9730e66 100644 --- a/src/Canvas/elements/element.hxx +++ b/src/Canvas/elements/element.hxx @@ -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 _transform; std::vector _transform_types; - SGPropertyNode *_bounding_box[4]; /// _color, + _color_fill; + std::vector _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, diff --git a/src/Canvas/elements/group.cxx b/src/Canvas/elements/group.cxx index 44b7166b7..94e0836a6 100644 --- a/src/Canvas/elements/group.cxx +++ b/src/Canvas/elements/group.cxx @@ -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; + if( child->getNameString() == "text" ) - { - _children.push_back( boost::shared_ptr(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 = _children[index]; + if( element ) + _transform->removeChild(element->getMatrixTransform()); + element.reset(); + } + } } } // namespace canvas diff --git a/src/Canvas/elements/group.hxx b/src/Canvas/elements/group.hxx index ccfea07be..d13bb255c 100644 --- a/src/Canvas/elements/group.hxx +++ b/src/Canvas/elements/group.hxx @@ -26,17 +26,19 @@ namespace canvas { + typedef boost::shared_ptr ElementPtr; + class Group: public Element { public: - Group(SGPropertyNode* node); + Group(SGPropertyNode_ptr node); virtual ~Group(); virtual void update(double dt); protected: - std::vector > _children; + std::vector _children; virtual void childAdded(SGPropertyNode * child); virtual void childRemoved(SGPropertyNode * child); diff --git a/src/Canvas/elements/text.cxx b/src/Canvas/elements/text.cxx index af27cda07..6f7a961d5 100644 --- a/src/Canvas/elements/text.cxx +++ b/src/Canvas/elements/text.cxx @@ -17,26 +17,30 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "text.hxx" -#include +#include #include
#include
+#include + 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(_node, "character-size", 32); + _font_aspect = getChildDefault(_node, "character-aspect-ratio", 1); osg::ref_ptr 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; } //---------------------------------------------------------------------------- diff --git a/src/Canvas/elements/text.hxx b/src/Canvas/elements/text.hxx index 38d508b00..38c7f1335 100644 --- a/src/Canvas/elements/text.hxx +++ b/src/Canvas/elements/text.hxx @@ -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 _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); diff --git a/src/Canvas/property_helper.cxx b/src/Canvas/property_helper.cxx new file mode 100644 index 000000000..7bf65404e --- /dev/null +++ b/src/Canvas/property_helper.cxx @@ -0,0 +1,47 @@ +// Some helper functions for accessing the property tree +// +// Copyright (C) 2012 Thomas Geymayer +// +// 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 + +namespace canvas +{ + //---------------------------------------------------------------------------- + void linkColorNodes( const char* name, + SGPropertyNode* parent, + std::vector& 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]) ); + } +} diff --git a/src/Canvas/property_helper.hxx b/src/Canvas/property_helper.hxx new file mode 100644 index 000000000..c62134ca1 --- /dev/null +++ b/src/Canvas/property_helper.hxx @@ -0,0 +1,67 @@ +// Some helper functions for accessing the property tree +// +// Copyright (C) 2012 Thomas Geymayer +// +// 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 +#include + +namespace canvas +{ + + /** + * Get property node with default value + */ + template + 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(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 + * + * + * def[0] or existing value + * def[1] or existing value + * def[2] or existing value + * def[3] or existing value + * + */ + void linkColorNodes( const char* name, + SGPropertyNode* parent, + std::vector& nodes, + const osg::Vec4& def = osg::Vec4(0,0,0,0) ); + +} // namespace canvas + +#endif /* PROPERTY_HELPER_HXX_ */