]> git.mxchange.org Git - simgear.git/commitdiff
Canvas: fix transformation of clip rect.
authorThomas Geymayer <tomgey@gmail.com>
Thu, 5 Jun 2014 14:07:09 +0000 (16:07 +0200)
committerThomas Geymayer <tomgey@gmail.com>
Thu, 5 Jun 2014 14:07:09 +0000 (16:07 +0200)
simgear/canvas/elements/CanvasElement.cxx
simgear/canvas/elements/CanvasElement.hxx

index af378e28971b90617d34a4193636dd809c066df3..d67ba4f2df70071344c4df3d210a44c1da243f0d 100644 (file)
@@ -50,35 +50,50 @@ namespace canvas
   {
     public:
 
-      ReferenceFrame    _coord_reference;
-      osg::Matrix       _parent_inverse;
+      ReferenceFrame                _coord_reference;
+      osg::observer_ptr<osg::Node>  _node;
 
-      RelativeScissor():
-        _coord_reference(GLOBAL)
-      {}
-
-      bool contains(const osg::Vec2f& pos) const
+      RelativeScissor(osg::Node* node = NULL):
+        _coord_reference(GLOBAL),
+        _node(node)
       {
-        return _x <= pos.x() && pos.x() <= _x + _width
-            && _y <= pos.y() && pos.y() <= _y + _height;
+        _width = 0;
+        _height = 0;
       }
 
-      bool contains( const osg::Vec2f& global_pos,
-                     const osg::Vec2f& parent_pos,
-                     const osg::Vec2f& local_pos ) const
-      {
-        switch( _coord_reference )
-        {
-          case GLOBAL: return contains(global_pos);
-          case PARENT: return contains(parent_pos);
-          case LOCAL:  return contains(local_pos);
-        }
+      /** Copy constructor using CopyOp to manage deep vs shallow copy. */
+      RelativeScissor( const RelativeScissor& vp,
+                       const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY ):
+        Scissor(vp, copyop),
+        _coord_reference(vp._coord_reference),
+        _node(vp._node)
+      {}
 
-        return false;
+      META_StateAttribute(simgear, RelativeScissor, SCISSOR);
+
+      /** Return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. */
+      virtual int compare(const StateAttribute& sa) const
+      {
+        // check the types are equal and then create the rhs variable
+        // used by the COMPARE_StateAttribute_Parameter macros below.
+        COMPARE_StateAttribute_Types(RelativeScissor,sa)
+
+        // compare each parameter in turn against the rhs.
+        COMPARE_StateAttribute_Parameter(_x)
+        COMPARE_StateAttribute_Parameter(_y)
+        COMPARE_StateAttribute_Parameter(_width)
+        COMPARE_StateAttribute_Parameter(_height)
+        COMPARE_StateAttribute_Parameter(_coord_reference)
+        COMPARE_StateAttribute_Parameter(_node)
+
+        return 0; // passed all the above comparison macros, must be equal.
       }
 
       virtual void apply(osg::State& state) const
       {
+        if( _width <= 0 || _height <= 0 )
+          return;
+
         const osg::Viewport* vp = state.getCurrentViewport();
         float w2 = 0.5 * vp->width(),
               h2 = 0.5 * vp->height();
@@ -94,17 +109,28 @@ namespace canvas
 
         if( _coord_reference != GLOBAL )
         {
-          model_view.preMult(state.getModelViewMatrix());
+          osg::Node* ref_obj = _node.get();
 
           if( _coord_reference == PARENT )
-            model_view.preMult(_parent_inverse);
+          {
+            if( _node->getNumParents() < 1 )
+            {
+              SG_LOG(SG_GL, SG_WARN, "RelativeScissor: missing parent.");
+              return;
+            }
+
+            ref_obj = _node->getParent(0);
+          }
+
+          osg::MatrixList const& parent_matrices = ref_obj->getWorldMatrices();
+          assert( !parent_matrices.empty() );
+          model_view.preMult(parent_matrices.front());
         }
 
         const osg::Vec2 scale( model_view(0,0), model_view(1,1)),
                         offset(model_view(3,0), model_view(3,1));
 
         // TODO check/warn for rotation?
-
         GLint x = SGMiscf::roundToInt(scale.x() * _x + offset.x()),
               y = SGMiscf::roundToInt(scale.y() * _y + offset.y()),
               w = SGMiscf::roundToInt(std::fabs(scale.x()) * _width),
@@ -117,6 +143,26 @@ namespace canvas
 
         glScissor(x, y, w, h);
       }
+
+      bool contains(const osg::Vec2f& pos) const
+      {
+        return _x <= pos.x() && pos.x() <= _x + _width
+            && _y <= pos.y() && pos.y() <= _y + _height;
+      }
+
+      bool contains( const osg::Vec2f& global_pos,
+                     const osg::Vec2f& parent_pos,
+                     const osg::Vec2f& local_pos ) const
+      {
+        switch( _coord_reference )
+        {
+          case GLOBAL: return contains(global_pos);
+          case PARENT: return contains(parent_pos);
+          case LOCAL:  return contains(local_pos);
+        }
+
+        return false;
+      }
   };
 
   //----------------------------------------------------------------------------
@@ -179,15 +225,6 @@ namespace canvas
     // Trigger matrix update
     getMatrix();
 
-    // TODO limit bounding box to scissor
-    if( _attributes_dirty & SCISSOR_COORDS )
-    {
-      if( _scissor && _scissor->_coord_reference != GLOBAL )
-        _scissor->_parent_inverse = _transform->getInverseMatrix();
-
-      _attributes_dirty &= ~SCISSOR_COORDS;
-    }
-
     // Update bounding box on manual update (manual updates pass zero dt)
     if( dt == 0 && _drawable )
       _drawable->getBound();
@@ -524,28 +561,29 @@ namespace canvas
       return;
     }
 
-    _scissor = new RelativeScissor();
+    if( !_scissor )
+      _scissor = new RelativeScissor(_transform.get());
+
     // <top>, <right>, <bottom>, <left>
     _scissor->x() = SGMiscf::roundToInt(values[3]);
     _scissor->y() = SGMiscf::roundToInt(values[0]);
     _scissor->width() = SGMiscf::roundToInt(width);
     _scissor->height() = SGMiscf::roundToInt(height);
 
-    getOrCreateStateSet()->setAttributeAndModes(_scissor);
-
     SGPropertyNode* clip_frame = _node->getChild("clip-frame", 0);
     if( clip_frame )
       valueChanged(clip_frame);
+    else
+      _scissor->_coord_reference = GLOBAL;
+
+    getOrCreateStateSet()->setAttributeAndModes(_scissor);
   }
 
   //----------------------------------------------------------------------------
   void Element::setClipFrame(ReferenceFrame rf)
   {
     if( _scissor )
-    {
       _scissor->_coord_reference = rf;
-      _attributes_dirty |= SCISSOR_COORDS;
-    }
   }
 
   //----------------------------------------------------------------------------
@@ -647,7 +685,6 @@ namespace canvas
     }
     _transform->setMatrix(m);
     _attributes_dirty &= ~TRANSFORM;
-    _attributes_dirty |= SCISSOR_COORDS;
 
     return m;
   }
index 9e686739fcd05f068ee9888cc2cad12e63f22287..7ae7d22c436f52eef45f1c6fadc9ec8952fde01c 100644 (file)
@@ -211,8 +211,7 @@ namespace canvas
       {
         TRANSFORM       = 1,
         BLEND_FUNC      = TRANSFORM << 1,
-        SCISSOR_COORDS  = BLEND_FUNC << 1,
-        LAST_ATTRIBUTE  = SCISSOR_COORDS << 1
+        LAST_ATTRIBUTE  = BLEND_FUNC << 1
       };
 
       enum TransformType