]> git.mxchange.org Git - flightgear.git/commitdiff
Canvas: Image/Window unifying and allow using canvas inside canvas.
authorThomas Geymayer <thomas.geymayer@student.tugraz.at>
Thu, 9 Aug 2012 12:50:20 +0000 (14:50 +0200)
committerThomas Geymayer <thomas.geymayer@student.tugraz.at>
Thu, 9 Aug 2012 14:13:38 +0000 (16:13 +0200)
 - Refactor and unify common functionality of canvas::Window and
   canvas::Image
 - Make canvas::Image actually work
 - Allow using canvases inside canvas::Image
   * Use new canvas:// "protocol" to allow using canvases in
     place of images
 - Prepare for categorizing canvases:
   * Move canvases to /canvas/by-index
   * Later support linking to other nodes in subbranches of
     /canvas

14 files changed:
src/Canvas/canvas_fwd.hpp
src/Canvas/canvas_mgr.cxx
src/Canvas/canvas_mgr.hxx
src/Canvas/elements/CanvasImage.cxx
src/Canvas/elements/CanvasImage.hxx
src/Canvas/elements/element.cxx
src/Canvas/gui_mgr.cxx
src/Canvas/gui_mgr.hxx
src/Canvas/property_based_mgr.cxx
src/Canvas/property_based_mgr.hxx
src/Canvas/rect.hxx
src/Canvas/window.cxx
src/Canvas/window.hxx
src/GUI/CanvasWidget.cxx

index c56612fd99e73998e7a4c1af47d12214f778026a..56b40fcb25da8bc40bebb4c98f859d10cb2a48b2 100644 (file)
@@ -37,6 +37,7 @@ typedef boost::weak_ptr<PropertyBasedElement> PropertyBasedElementWeakPtr;
 namespace canvas
 {
   class Group;
+  class Image;
   class MouseEvent;
 
   class Placement;
index 21fcccf80f676ebc6b2dac5d492bc379898d4852..a175076237112b4583c097e2069a582a8ac682fc 100644 (file)
@@ -30,7 +30,7 @@ CanvasPtr canvasFactory(SGPropertyNode* node)
 
 //------------------------------------------------------------------------------
 CanvasMgr::CanvasMgr():
-  PropertyBasedMgr("/canvas", "texture", &canvasFactory)
+  PropertyBasedMgr("/canvas/by-index", "texture", &canvasFactory)
 {
   Canvas::addPlacementFactory
   (
@@ -46,11 +46,21 @@ CanvasMgr::CanvasMgr():
 }
 
 //------------------------------------------------------------------------------
-unsigned int CanvasMgr::getCanvasTexId(size_t index) const
+CanvasPtr CanvasMgr::getCanvas(size_t index) const
 {
   if(    index >= _elements.size()
       || !_elements[index] )
-    return 0;
+    return CanvasPtr();
+
+  return boost::static_pointer_cast<Canvas>(_elements[index]);
+}
 
-  return static_cast<Canvas*>(_elements[index].get())->getTexId();
+//------------------------------------------------------------------------------
+unsigned int CanvasMgr::getCanvasTexId(size_t index) const
+{
+  CanvasPtr canvas = getCanvas(index);
+  if( canvas )
+    return canvas->getTexId();
+  else
+    return 0;
 }
index 10cbe9a764a6bae20fd9463d215c36fe4447c822..568da3d61615b65825034cacdce86f7c534328b6 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef CANVAS_MGR_H_
 #define CANVAS_MGR_H_
 
+#include "canvas_fwd.hpp"
 #include "property_based_mgr.hxx"
 
 class CanvasMgr:
@@ -27,9 +28,20 @@ class CanvasMgr:
   public:
     CanvasMgr();
 
+    /**
+     * Get ::Canvas by index
+     *
+     * @param index Index of texture node in /canvas/by-index/
+     */
+    CanvasPtr getCanvas(size_t index) const;
+
     /**
      * Get OpenGL texture name for given canvas
      *
+     * @deprecated This was only meant to be used by the PUI CanvasWidget
+     *             implementation as PUI can't handle osg::Texture objects.
+     *             Use getCanvas(index)->getTexture() instead.
+     *
      * @param Index of canvas
      * @return OpenGL texture name
      */
index 5bbed177e9ca9a6fa2ab895655f06519ab1bb7db..3addb4901adaa6e40f9ccd0b0d5e1b6421f36780 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <osgDB/ReadFile>
 
+#include <Canvas/canvas.hxx>
+#include <Canvas/canvas_mgr.hxx>
 #include <Canvas/property_helper.hxx>
 #include <osg/Array>
 #include <osg/Geometry>
 #include <Main/globals.hxx>
 #include <Main/fg_props.hxx>
 
+#include <boost/algorithm/string/predicate.hpp>
+
+/**
+ * Callback to enable/disable rendering of canvas displayed inside windows or
+ * other canvases.
+ */
+class CullCallback:
+  public osg::Drawable::CullCallback
+{
+  public:
+    CullCallback(Canvas::CameraCullCallback* camera_cull);
+
+  private:
+    Canvas::CameraCullCallback *_camera_cull;
+
+    virtual bool cull( osg::NodeVisitor* nv,
+                       osg::Drawable* drawable,
+                       osg::RenderInfo* renderInfo ) const;
+};
+
+//------------------------------------------------------------------------------
+CullCallback::CullCallback(Canvas::CameraCullCallback* camera_cull):
+  _camera_cull( camera_cull )
+{
+
+}
+
+//------------------------------------------------------------------------------
+bool CullCallback::cull( osg::NodeVisitor* nv,
+                         osg::Drawable* drawable,
+                         osg::RenderInfo* renderInfo ) const
+{
+  _camera_cull->enableRendering();
+
+  // TODO check if window/image should be culled
+  return false;
+}
+
 namespace canvas
 {
   //----------------------------------------------------------------------------
   Image::Image(SGPropertyNode_ptr node):
-    Element(node, COLOR | COLOR_FILL | BOUNDING_BOX),
-    _texture(new osg::Texture2D)
+    Element(node, COLOR_FILL | BOUNDING_BOX),
+    _texture(new osg::Texture2D),
+    _node_src_rect( node->getNode("source", 0, true) ),
+    _src_rect(0,0,0,0),
+    _region(0,0,0,0)
   {
-    _source_rect = node->getChild("source");
-    
     _geom = new osg::Geometry;
     _geom->setUseDisplayList(false);
-  
+
     osg::StateSet *stateSet = _geom->getOrCreateStateSet();
     stateSet->setTextureAttributeAndModes(0, _texture.get());
     stateSet->setDataVariance(osg::Object::STATIC);
 
     // allocate arrays for the image
-    _vertices = new osg::Vec2Array;
+    _vertices = new osg::Vec3Array(4);
     _vertices->setDataVariance(osg::Object::STATIC);
-    _vertices->reserve(4);
     _geom->setVertexArray(_vertices);
-  
-    _texCoords = new osg::Vec2Array;
+
+    _texCoords = new osg::Vec2Array(4);
     _texCoords->setDataVariance(osg::Object::STATIC);
-    _texCoords->reserve(4);
     _geom->setTexCoordArray(0, _texCoords);
-  
-    _colors = new osg::Vec4Array;
+
+    _colors = new osg::Vec4Array(4);
     _colors->setDataVariance(osg::Object::STATIC);
     _geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
     _geom->setColorArray(_colors);
-  
+
     osg::DrawArrays* prim = new osg::DrawArrays(osg::PrimitiveSet::QUADS);
-    prim->set(osg::PrimitiveSet::QUADS, 0, 1);
+    prim->set(osg::PrimitiveSet::QUADS, 0, 4);
     prim->setDataVariance(osg::Object::STATIC);
     _geom->addPrimitiveSet(prim);
-  
+
     setDrawable(_geom);
   }
 
@@ -79,69 +118,184 @@ namespace canvas
   {
     Element::update(dt);
 
-    if( _attributes_dirty & SRC_RECT ) {
-      _attributes_dirty &= ~SRC_RECT;
-      int texWidth = _texture->getTextureWidth();
-      int texHeight = _texture->getTextureHeight();
-      
-      double x0 = _source_rect->getDoubleValue("left"),
-          x1 = _source_rect->getDoubleValue("right"),
-          y0 = _source_rect->getDoubleValue("top"),
-          y1 =  _source_rect->getDoubleValue("bottom"); 
-      double width = x1 - x0, height = y1 - y0;
-      
-      _vertices->clear();
-      _vertices->push_back(osg::Vec2(0, 0));
-      _vertices->push_back(osg::Vec2(width, 0));
-      _vertices->push_back(osg::Vec2(width, height));
-      _vertices->push_back(osg::Vec2(0, height));
+    if( _attributes_dirty & DEST_SIZE )
+    {
+      (*_vertices)[0].set(_region.l(), _region.t(), 0);
+      (*_vertices)[1].set(_region.r(), _region.t(), 0);
+      (*_vertices)[2].set(_region.r(), _region.b(), 0);
+      (*_vertices)[3].set(_region.l(), _region.b(), 0);
       _vertices->dirty();
-      
-      double u0 = x0 / texWidth,
-        u1 = x1 / texWidth,
-        v0 = y0 / texHeight,
-        v1 = y1 / texHeight;
-            
-      _texCoords->clear();
-      _texCoords->push_back(osg::Vec2(u0, v0));
-      _texCoords->push_back(osg::Vec2(u1, v0));
-      _texCoords->push_back(osg::Vec2(u1, v1));
-      _texCoords->push_back(osg::Vec2(u0, v1));
+
+      _attributes_dirty &= ~DEST_SIZE;
+      _geom->dirtyBound();
+    }
+
+    if( _attributes_dirty & SRC_RECT )
+    {
+      double u0 = _src_rect.l(),
+             u1 = _src_rect.r(),
+             v0 = _src_rect.b(),
+             v1 = _src_rect.t();
+
+      if( !_node_src_rect->getBoolValue("normalized", true) )
+      {
+        osg::Texture2D *texture = !_canvas.expired()
+                                ? _canvas.lock()->getTexture()
+                                : _texture.get();
+
+        int texWidth = texture->getTextureWidth();
+        int texHeight = texture->getTextureHeight();
+
+        u0 /= texWidth;
+        u1 /= texWidth;
+        v0 /= texHeight;
+        v1 /= texHeight;
+      }
+
+      (*_texCoords)[0].set(u0, v0);
+      (*_texCoords)[1].set(u1, v0);
+      (*_texCoords)[2].set(u1, v1);
+      (*_texCoords)[3].set(u0, v1);
       _texCoords->dirty();
+
+      _attributes_dirty &= ~SRC_RECT;
     }
   }
 
   //----------------------------------------------------------------------------
-  void Image::childChanged(SGPropertyNode* child)
+  void Image::setCanvas(CanvasPtr canvas)
   {
-    const std::string& name = child->getNameString();
-    
-    if (_source_rect == child) 
+    _canvas = canvas;
+    _geom->getOrCreateStateSet()
+         ->setTextureAttribute(0, canvas ? canvas->getTexture() : 0);
+    _geom->setCullCallback(
+      canvas ? new CullCallback(canvas->getCameraCullCallback()) : 0
+    );
+  }
+
+  //----------------------------------------------------------------------------
+  CanvasWeakPtr Image::getCanvas() const
+  {
+    return _canvas;
+  }
+
+  //----------------------------------------------------------------------------
+  void Image::setImage(osg::Image *img)
+  {
+    // remove canvas...
+    setCanvas( CanvasPtr() );
+
+    _texture->setImage(img);
+    _geom->getOrCreateStateSet()
+         ->setTextureAttributeAndModes(0, _texture);
+  }
+
+  //----------------------------------------------------------------------------
+  const Rect<float>& Image::getRegion() const
+  {
+    return _region;
+  }
+
+  //----------------------------------------------------------------------------
+  void Image::valueChanged(SGPropertyNode *node)
+  {
+    if( node->getParent() == _node_src_rect )
+    {
       _attributes_dirty |= SRC_RECT;
-    else if (name == "file") {
-        SGPath tpath = globals->resolve_ressource_path(child->getStringValue());
-        if (tpath.isNull() || !tpath.exists()) {
-            SG_LOG(SG_GL, SG_ALERT, "canvas::Image: No such image: " << child->getStringValue());
-        } else {
-            _texture->setImage(osgDB::readImageFile(tpath.c_str()));  
-            _attributes_dirty |= SRC_RECT;              
-        }
-    } 
+
+      if( node->getNameString() == "left" )
+        _src_rect.setLeft( node->getFloatValue() );
+      else if( node->getNameString() == "right" )
+        _src_rect.setRight( node->getFloatValue() );
+      else if( node->getNameString() == "top" )
+        _src_rect.setTop( node->getFloatValue() );
+      else if( node->getNameString() == "bottom" )
+        _src_rect.setBottom( node->getFloatValue() );
+    }
+    else
+      Element::valueChanged(node);
   }
 
   //----------------------------------------------------------------------------
-  void Image::colorChanged(const osg::Vec4& color)
+  void Image::childChanged(SGPropertyNode* child)
   {
-      _colors->clear();
-      for (int i=0; i<4; ++i) {
-          _colors->push_back(color);
+    const std::string& name = child->getNameString();
+
+    if( name == "x" )
+    {
+      _region.setX( child->getFloatValue() );
+      _attributes_dirty |= DEST_SIZE;
+    }
+    else if( name == "y" )
+    {
+      _region.setY( child->getFloatValue() );
+      _attributes_dirty |= DEST_SIZE;
+    }
+    else if( name == "size" )
+    {
+      if( child->getIndex() == 0 )
+        _region.setWidth( child->getFloatValue() );
+      else
+        _region.setHeight( child->getFloatValue() );
+
+      _attributes_dirty |= DEST_SIZE;
+    }
+    else if( name == "file" )
+    {
+      static const std::string CANVAS_PROTOCOL = "canvas://";
+      const std::string& path = child->getStringValue();
+
+      if( boost::starts_with(path, CANVAS_PROTOCOL) )
+      {
+        CanvasMgr* canvas_mgr =
+          dynamic_cast<CanvasMgr*>(globals->get_subsystem("Canvas"));
+        if( !canvas_mgr )
+        {
+          SG_LOG(SG_GL, SG_ALERT, "canvas::Image: Failed to get CanvasMgr");
+          return;
+        }
+
+        const SGPropertyNode* canvas_node =
+          canvas_mgr->getPropertyRoot()
+                    ->getParent()
+                    ->getNode( path.substr(CANVAS_PROTOCOL.size()) );
+        if( !canvas_node )
+        {
+          SG_LOG(SG_GL, SG_ALERT, "canvas::Image: No such canvas: " << path);
+          return;
+        }
+
+        // TODO add support for other means of addressing canvases (eg. by
+        // name)
+        CanvasPtr canvas = canvas_mgr->getCanvas( canvas_node->getIndex() );
+        if( !canvas )
+        {
+          SG_LOG(SG_GL, SG_ALERT, "canvas::Image: Invalid canvas: " << path);
+          return;
+        }
+
+        setCanvas(canvas);
       }
-      _colors->dirty();
+      else
+      {
+        SGPath tpath = globals->resolve_ressource_path(path);
+        if( tpath.isNull() || !tpath.exists() )
+        {
+          SG_LOG(SG_GL, SG_ALERT, "canvas::Image: No such image: " << path);
+          return;
+        }
+
+        setImage( osgDB::readImageFile(tpath.c_str()) );
+      }
+    }
   }
 
   //----------------------------------------------------------------------------
-  void Image::colorFillChanged(const osg::Vec4& /*color*/)
+  void Image::colorFillChanged(const osg::Vec4& color)
   {
+    for( int i = 0; i < 4; ++i )
+      (*_colors)[i] = color;
+    _colors->dirty();
   }
 
 } // namespace canvas
index c115277d05aa588678a09f99010273f19dcaf9f3..934df7a0a210c798ce014bcc9e19696f0d4fe0a3 100644 (file)
 #define CANVAS_IMAGE_HXX_
 
 #include "element.hxx"
-
-#include <boost/shared_ptr.hpp>
-
-#include <map>
-#include <vector>
+#include <Canvas/canvas_fwd.hpp>
+#include <Canvas/rect.hxx>
 
 #include <osg/Texture2D>
 
@@ -35,33 +32,58 @@ namespace canvas
     public Element
   {
     public:
+      /**
+       * @param node    Property node containing settings for this image:
+       *                  rect/[left/right/top/bottom]  Dimensions of source
+       *                                                rect
+       *                  size[0-1]                     Dimensions of rectangle
+       *                  [x,y]                         Position of rectangle
+       */
       Image(SGPropertyNode_ptr node);
       ~Image();
 
       virtual void update(double dt);
 
+      void setCanvas(CanvasPtr canvas);
+      CanvasWeakPtr getCanvas() const;
+
+      void setImage(osg::Image *img);
+
+      const Rect<float>& getRegion() const;
+
+      /**
+       * Callback for every changed child node
+       */
+      virtual void valueChanged(SGPropertyNode *node);
+
     protected:
 
-      enum TextAttributes
+      enum ImageAttributes
       {
         SRC_RECT       = LAST_ATTRIBUTE << 1, // Source image rectangle
+        DEST_SIZE      = SRC_RECT << 1        // Element size
       };
 
-      SGPropertyNode_ptr  _source_rect, 
-          _dest_rect;
-
+      /**
+       * Callback for changed direct child nodes
+       */
       virtual void childChanged(SGPropertyNode * child);
-      virtual void colorChanged(const osg::Vec4& color);
       virtual void colorFillChanged(const osg::Vec4& color);
 
       void handleHit(float x, float y);
 
       osg::ref_ptr<osg::Texture2D> _texture;
-      
+      // TODO optionally forward events to canvas
+      CanvasWeakPtr _canvas;
+
       osg::Geometry *_geom;
-      osg::Vec2Array *_vertices;
+      osg::Vec3Array *_vertices;
       osg::Vec2Array *_texCoords;
-      osg::Vec4Array* _colors;      
+      osg::Vec4Array* _colors;
+
+      SGPropertyNode *_node_src_rect;
+      Rect<float>     _src_rect,
+                      _region;
   };
 
 }  // namespace canvas
index b01b36966c473d89d35375358cb23973b87609b7..01fbf1a5de98f198c49f874c01d4f64a47723486 100644 (file)
@@ -226,10 +226,10 @@ namespace canvas
     _node->addChangeListener(this);
 
     if( _attributes_used & COLOR )
-      linkColorNodes("color", _node, _color, osg::Vec4f(0,1,0,1));
+      linkColorNodes("color", _node, _color, osg::Vec4f(0,0,0,1));
 
     if( _attributes_used & COLOR_FILL )
-      linkColorNodes("color-fill", _node, _color_fill, osg::Vec4f(1,0,1,1));
+      linkColorNodes("color-fill", _node, _color_fill, osg::Vec4f(1,1,1,1));
 
     SG_LOG
     (
index 34b356f0a22c2759608791d2b9e681ec1c2350b6..7d581e6c91ee1b96d21e1037604c39e4a421f055 100644 (file)
@@ -24,6 +24,7 @@
 #include <Viewer/CameraGroup.hxx>
 #include <Viewer/renderer.hxx>
 
+#include <osg/BlendFunc>
 #include <osgViewer/Viewer>
 #include <osgGA/GUIEventHandler>
 
@@ -94,7 +95,6 @@ GUIMgr::GUIMgr():
   PropertyBasedMgr("/sim/gui/canvas", "window", &windowFactory),
   _event_handler( new GUIEventHandler(this) ),
   _transform( new osg::MatrixTransform ),
-  _geode_windows( new osg::Geode ),
   _width(_props, "size[0]"),
   _height(_props, "size[1]"),
   _last_push(-1)
@@ -104,18 +104,31 @@ GUIMgr::GUIMgr():
   osg::Camera* camera =
     flightgear::getGUICamera( flightgear::CameraGroup::getDefault() );
   assert(camera);
+  camera->addChild(_transform);
 
   osg::Viewport* vp = camera->getViewport();
   handleResize(vp->x(), vp->y(), vp->width(), vp->height());
 
-  _transform->addChild(_geode_windows);
-  camera->addChild(_transform);
-
   Canvas::addPlacementFactory
   (
     "window",
     boost::bind(&GUIMgr::addPlacement, this, _1, _2)
   );
+
+  osg::StateSet* stateSet = _transform->getOrCreateStateSet();
+  stateSet->setDataVariance(osg::Object::STATIC);
+  stateSet->setRenderBinDetails(1000, "RenderBin");
+
+  // speed optimization?
+  stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
+  stateSet->setAttribute(new osg::BlendFunc(
+    osg::BlendFunc::SRC_ALPHA,
+    osg::BlendFunc::ONE_MINUS_SRC_ALPHA)
+  );
+  stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
+  stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+  stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
+  stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
 }
 
 //------------------------------------------------------------------------------
@@ -141,9 +154,9 @@ void GUIMgr::shutdown()
 //------------------------------------------------------------------------------
 void GUIMgr::elementCreated(PropertyBasedElementPtr element)
 {
-  _geode_windows->addDrawable
+  _transform->addChild
   (
-    static_cast<canvas::Window*>(element.get())->getDrawable()
+    static_cast<canvas::Window*>(element.get())->getGroup()
   );
 }
 
index 6b010a02054c42509bde069d84dc61f7d4f9c75a..76722ec7dc4b2709831faf80a6e9e98bdacc209a 100644 (file)
@@ -51,7 +51,6 @@ class GUIMgr:
   protected:
     osg::ref_ptr<GUIEventHandler>       _event_handler;
     osg::ref_ptr<osg::MatrixTransform>  _transform;
-    osg::ref_ptr<osg::Geode>            _geode_windows;
 
     simgear::PropertyObject<int>        _width,
                                         _height;
index 1d57228dfcf29a6fd584efdbd0d784f8afea0677..d02e7ed6fb535d32f06cb848239e0908a5d16ac0 100644 (file)
@@ -100,6 +100,12 @@ void PropertyBasedMgr::childRemoved( SGPropertyNode * parent,
     _elements[index].reset();
 }
 
+//------------------------------------------------------------------------------
+const SGPropertyNode* PropertyBasedMgr::getPropertyRoot() const
+{
+  return _props;
+}
+
 //------------------------------------------------------------------------------
 PropertyBasedMgr::PropertyBasedMgr( const std::string& path_root,
                                     const std::string& name_elements,
index 904b3c619ade21e557a847f960d57d44e655a1f1..e80f85cfd90be9587e0f926913f3dee3042546cc 100644 (file)
@@ -43,6 +43,8 @@ class PropertyBasedMgr:
 
     virtual void elementCreated(PropertyBasedElementPtr element) {}
 
+    virtual const SGPropertyNode* getPropertyRoot() const;
+
   protected:
 
     typedef boost::function<PropertyBasedElementPtr(SGPropertyNode*)>
index b3b42cc4e33d7e956b4a6733882834a0b045a0ec..f140cebf231d3567fdbe4613177b881fee8b6663 100644 (file)
@@ -49,11 +49,21 @@ namespace canvas
       T width() const { return _x2 - _x1; }
       T height() const { return _y2 - _y1; }
 
+      void setX(T x) { T w = width(); _x1 = x; _x2 = x + w; }
+      void setY(T y) { T h = height(); _y1 = y; _y2 = y + h; }
+      void setWidth(T w) { _x2 = _x1 + w; }
+      void setHeight(T h) { _y2 = _y1 + h; }
+
       T l() const { return _x1; }
       T r() const { return _x2; }
       T t() const { return _y1; }
       T b() const { return _y2; }
 
+      void setLeft(T l) { _x1 = l; }
+      void setRight(T r) { _x2 = r; }
+      void setTop(T t) { _y1 = t; }
+      void setBottom(T b) { _y2 = b; }
+
       bool contains(T x, T y) const
       {
         return _x1 <= x && x <= _x2
index 304f0168c4184918f183e1d9d3e2c34ca8fda32e..43c9a1654b764942c445792c64d619375831c43f 100644 (file)
 #include "window.hxx"
 #include <Canvas/canvas.hxx>
 
-#include <osg/BlendFunc>
-#include <osg/Geometry>
-#include <osg/Texture2D>
 #include <osgGA/GUIEventHandler>
 
 #include <boost/foreach.hpp>
 
-/**
- * Callback to enable/disable rendering of canvas displayed inside windows
- */
-class CullCallback:
-  public osg::Drawable::CullCallback
-{
-  public:
-    CullCallback(Canvas::CameraCullCallback* camera_cull);
-
-  private:
-    Canvas::CameraCullCallback *_camera_cull;
-
-    virtual bool cull( osg::NodeVisitor* nv,
-                       osg::Drawable* drawable,
-                       osg::RenderInfo* renderInfo ) const;
-};
-
-//------------------------------------------------------------------------------
-CullCallback::CullCallback(Canvas::CameraCullCallback* camera_cull):
-  _camera_cull( camera_cull )
-{
-
-}
-
-//------------------------------------------------------------------------------
-bool CullCallback::cull( osg::NodeVisitor* nv,
-                         osg::Drawable* drawable,
-                         osg::RenderInfo* renderInfo ) const
-{
-  _camera_cull->enableRendering();
-  return false;
-}
-
 namespace canvas
 {
   //----------------------------------------------------------------------------
   Window::Window(SGPropertyNode* node):
     PropertyBasedElement(node),
-    _dirty(true),
-    _geometry( new osg::Geometry ),
-    _vertices( new osg::Vec3Array(4) ),
-    _tex_coords( new osg::Vec2Array(4) ),
-    _x(node, "x"),
-    _y(node, "y"),
-    _width(node, "size[0]"),
-    _height(node, "size[1]")
+    _image(node)
   {
-    _x = 50;
-    _y = 100;
-    _width = 400;
-    _height = 300;
-
-    _geometry->setVertexArray(_vertices);
-    _geometry->setTexCoordArray(0,_tex_coords);
-
-    osg::Vec4Array* colors = new osg::Vec4Array(1);
-    (*colors)[0].set(1.0f,1.0f,1.0,1.0f);
-    _geometry->setColorArray(colors);
-    _geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
-
-    _geometry->addPrimitiveSet(
-      new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4)
-    );
-    _geometry->setDataVariance(osg::Object::DYNAMIC);
-
-    osg::StateSet* stateSet = _geometry->getOrCreateStateSet();
-    stateSet->setRenderBinDetails(1000, "RenderBin");
-
-    // speed optimization?
-    stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
-    stateSet->setAttribute(new osg::BlendFunc(
-      osg::BlendFunc::SRC_ALPHA,
-      osg::BlendFunc::ONE_MINUS_SRC_ALPHA)
-    );
-    stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
-    stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
-    stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
-    stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
-    stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
+    // TODO probably better remove default position and size
+    node->setFloatValue("x", 50);
+    node->setFloatValue("y", 100);
+    node->setFloatValue("size[0]", 400);
+    node->setFloatValue("size[1]", 300);
+
+    node->setFloatValue("source/right", 1);
+    node->setFloatValue("source/bottom", 1);
+    node->setBoolValue("source/normalized", true);
   }
 
   //----------------------------------------------------------------------------
   Window::~Window()
   {
-    BOOST_FOREACH(osg::Node* parent, _geometry->getParents())
+    BOOST_FOREACH(osg::Group* parent, getGroup()->getParents())
     {
-      osg::Geode* geode = dynamic_cast<osg::Geode*>(parent);
-      if( geode )
-        geode->removeDrawable(_geometry);
+      parent->removeChild(getGroup());
     }
   }
 
   //----------------------------------------------------------------------------
   void Window::update(double delta_time_sec)
   {
-    if( !_dirty )
-      return;
-    _dirty = false;
-
-    _region.set(_x, _y, _width, _height);
-
-    int z = 0; // TODO do we need to use z for depth ordering?
-
-    (*_vertices)[0].set(_region.l(), _region.t(), z);
-    (*_vertices)[1].set(_region.r(), _region.t(), z);
-    (*_vertices)[2].set(_region.r(), _region.b(), z);
-    (*_vertices)[3].set(_region.l(), _region.b(), z);
-
-    float l = 0, t = 1, b = 0, r = 1;
-    (*_tex_coords)[0].set(l,t);
-    (*_tex_coords)[1].set(r,t);
-    (*_tex_coords)[2].set(r,b);
-    (*_tex_coords)[3].set(l,b);
+    _image.update(delta_time_sec);
+  }
 
-    _geometry->dirtyDisplayList();
+  //----------------------------------------------------------------------------
+  void Window::valueChanged(SGPropertyNode * node)
+  {
+    _image.valueChanged(node);
   }
 
   //----------------------------------------------------------------------------
-  void Window::valueChanged (SGPropertyNode * node)
+  osg::Group* Window::getGroup()
   {
-    if( node->getParent() != _node )
-      return;
+    return _image.getMatrixTransform();
+  }
 
-    const std::string& name = node->getNameString();
-    if(    name == "x" || name == "y" || name == "size" )
-      _dirty = true;
+  //----------------------------------------------------------------------------
+  const Rect<float>& Window::getRegion() const
+  {
+    return _image.getRegion();
   }
 
   //----------------------------------------------------------------------------
   void Window::setCanvas(CanvasPtr canvas)
   {
-    _canvas = canvas;
-    _geometry->getOrCreateStateSet()
-             ->setTextureAttribute(0, canvas ? canvas->getTexture() : 0);
-    _geometry->dirtyDisplayList();
-    _geometry->setCullCallback(
-      canvas ? new CullCallback(canvas->getCameraCullCallback()) : 0
-    );
+    _image.setCanvas(canvas);
   }
 
   //----------------------------------------------------------------------------
   CanvasWeakPtr Window::getCanvas() const
   {
-    return _canvas;
+    return _image.getCanvas();
   }
 
   //----------------------------------------------------------------------------
   bool Window::handleMouseEvent(const MouseEvent& event)
   {
-    if( !_canvas.expired() )
-      return _canvas.lock()->handleMouseEvent(event);
+    if( !getCanvas().expired() )
+      return getCanvas().lock()->handleMouseEvent(event);
     else
       return false;
   }
index 647bea1ae9d6874ca230d5f1f4eac8a4052a3cbf..3a94f4c8e1dacf5b01a6d2e14c05c134f73809fd 100644 (file)
@@ -20,7 +20,7 @@
 #define CANVAS_WINDOW_HXX_
 
 #include "property_based_element.hxx"
-#include "rect.hxx"
+#include <Canvas/elements/CanvasImage.hxx>
 #include <Canvas/MouseEvent.hxx>
 
 #include <simgear/props/propertyObject.hxx>
@@ -40,8 +40,8 @@ namespace canvas
       virtual void update(double delta_time_sec);
       virtual void valueChanged (SGPropertyNode * node);
 
-      osg::Drawable* getDrawable() { return _geometry; }
-      const Rect<int>& getRegion() const { return _region; }
+      osg::Group* getGroup();
+      const Rect<float>& getRegion() const;
 
       void setCanvas(CanvasPtr canvas);
       CanvasWeakPtr getCanvas() const;
@@ -50,17 +50,7 @@ namespace canvas
 
     protected:
 
-      bool _dirty;
-
-      osg::ref_ptr<osg::Geometry>   _geometry;
-      osg::ref_ptr<osg::Vec3Array>  _vertices;
-      osg::ref_ptr<osg::Vec2Array>  _tex_coords;
-
-      simgear::PropertyObject<int>  _x, _y,
-                                    _width, _height;
-      Rect<int>                     _region;
-
-      CanvasWeakPtr _canvas;
+      Image _image;
   };
 } // namespace canvas
 
index fea0f150f0667209db5956a949c5fc7eb07ccdbd..1db2f9391853c1e434c721986994a9dbbfbd23c1 100644 (file)
@@ -32,7 +32,7 @@ CanvasWidget::CanvasWidget( int x, int y,
   }
 
   // Get the first unused canvas slot
-  SGPropertyNode* canvas_root = fgGetNode("/canvas", true);
+  SGPropertyNode* canvas_root = fgGetNode("/canvas/by-index", true);
   for(int index = 0;; ++index)
   {
     if( !canvas_root->getChild("texture", index) )