]> git.mxchange.org Git - flightgear.git/commitdiff
Expose character-aspect-ratio and do some clean up
authorThomas Geymayer <tomgey@gmail.com>
Sun, 20 May 2012 17:14:00 +0000 (19:14 +0200)
committerThomas Geymayer <tomgey@gmail.com>
Thu, 31 May 2012 20:04:19 +0000 (22:04 +0200)
 - 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

14 files changed:
docs-mini/README.canvas
src/Canvas/CMakeLists.txt
src/Canvas/canvas.cxx
src/Canvas/canvas.hxx
src/Canvas/canvas_mgr.cxx
src/Canvas/canvas_mgr.hxx
src/Canvas/elements/element.cxx
src/Canvas/elements/element.hxx
src/Canvas/elements/group.cxx
src/Canvas/elements/group.hxx
src/Canvas/elements/text.cxx
src/Canvas/elements/text.hxx
src/Canvas/property_helper.cxx [new file with mode: 0644]
src/Canvas/property_helper.hxx [new file with mode: 0644]

index 670f1d17d3c9ab593ae14ee386eb958f37466886..8cc0b3004d84c5950c6c0caa2e814997cdf8aac8 100644 (file)
@@ -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>
index 1dde0d26b57a085f52004ffd4047a6a8722ee966..5de9945c0e10ae187b29b2aadc88546efb1ba925 100644 (file)
@@ -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}")
index 31e82653a75cf11f5c90c82f0093bec0f8ab304e..e82c08123a55310c580ccda953f8dca44c48da9e 100644 (file)
@@ -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);
+}
index 1769b8ed43ba035a518e79f97d4ffd665d67d6c4..9094825d453ed1d7391762003eb39754826492c8 100644 (file)
@@ -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;
+
+    FGODGauge _texture;
 
-    bool _sampling_dirty;
+    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_ */
index eab30b5818d7165a4f90224f416c088bf55a2e63..72db55fd0dea11c6f4d6fff7f3818e14a6909baa 100644 (file)
@@ -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);
-}
index b3b5bac0e5328b1e7fd62f313c6f54b804a81a7a..893b50e887e7fc77c094671034e27518611bbfef 100644 (file)
@@ -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_ */
index 119f109e60ebf948d9268bacc70518dff6416a2d..87ce8e6097dd575146265f745c539c38258590b8 100644 (file)
 // 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
index b17a0297750af0ab28d705cf4b83a85d6db3f17b..3c9730e66f4d65106381b4b40e16498e600ce4fe 100644 (file)
@@ -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,
index 44b7166b71cdffbeeffb850bf32760a544cd9697..94e0836a6e8ee0378b9b641768e1060e9038d09b 100644 (file)
@@ -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
index ccfea07be3ee0589d900007f00fea7ed2127624e..d13bb255cea1e9de1a0c92e7f9c084210305c805 100644 (file)
 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);
index af27cda07753a17ddb2ed84593057e05a8e8e6aa..6f7a961d5a49be5e2eccc38e9216d3a245fb064b 100644 (file)
 // 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;
   }
 
   //----------------------------------------------------------------------------
index 38d508b006594477f765ddb11f58b836be60401f..38c7f13350d6a401502db15dc8f9ccf79a2c3cb4 100644 (file)
@@ -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);
diff --git a/src/Canvas/property_helper.cxx b/src/Canvas/property_helper.cxx
new file mode 100644 (file)
index 0000000..7bf6540
--- /dev/null
@@ -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]) );
+  }
+}
diff --git a/src/Canvas/property_helper.hxx b/src/Canvas/property_helper.hxx
new file mode 100644 (file)
index 0000000..c62134c
--- /dev/null
@@ -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_ */