OpenWalnut  1.4.0
WGEBorderLayout.cpp
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #include <osgText/Text>
00026 #include <osg/LineWidth>
00027 #include <osg/Geometry>
00028 
00029 #include "../../WGraphicsEngine.h"
00030 #include "../../WGECamera.h"
00031 
00032 #include "WGEBorderLayout.h"
00033 
00034 WGEBorderLayout::WGEBorderLayout():
00035     WGEGroupNode(),
00036     m_geode( new osg::Geode() ),
00037     m_lineGeode( new osg::Geode() ),
00038     m_screen( new osg::Projection() )
00039 
00040 {
00041     // initialize members
00042     osg::ref_ptr< osg::MatrixTransform > matrix = new osg::MatrixTransform();
00043     setDataVariance( osg::Object::DYNAMIC );
00044     matrix->setMatrix( osg::Matrix::identity() );
00045     matrix->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
00046     matrix->addChild( m_geode );
00047     matrix->addChild( m_lineGeode );
00048     m_screen->addChild( matrix );
00049     insert( m_screen );
00050 
00051     m_geode->setDataVariance( osg::Object::DYNAMIC );
00052     m_lineGeode->setDataVariance( osg::Object::DYNAMIC );
00053     m_screen->setDataVariance( osg::Object::DYNAMIC );
00054 
00055     addUpdateCallback( new SafeUpdateCallback( this ) );
00056 
00057     // ensure it is drawn the last
00058     getOrCreateStateSet()->setRenderBinDetails( 11, "RenderBin" );
00059     getOrCreateStateSet()->setDataVariance( osg::Object::DYNAMIC );
00060     getOrCreateStateSet()->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
00061     getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
00062 }
00063 
00064 WGEBorderLayout::~WGEBorderLayout()
00065 {
00066     // cleanup
00067 }
00068 
00069 void WGEBorderLayout::addLayoutable( osg::ref_ptr< WGELabel > obj )
00070 {
00071     m_geode->addDrawable( obj );
00072 }
00073 
00074 void WGEBorderLayout::SafeUpdateCallback::operator()( osg::Node* node, osg::NodeVisitor* nv )
00075 {
00076     osg::ref_ptr<WGECamera> cam = WGraphicsEngine::getGraphicsEngine()->getViewer()->getCamera();
00077 
00078     // set up projection
00079     unsigned int  vwidth = cam->getViewport()->width();
00080     unsigned int  vheight = cam->getViewport()->height();
00081     m_layouter->m_screen->setMatrix( osg::Matrix::ortho2D( 0, vwidth, 0, vheight ) );
00082 
00083     // the geometry for the lead lines
00084     osg::ref_ptr< osg::Vec3Array > v = new osg::Vec3Array;
00085 
00086     for( unsigned int i = 0; i < m_layouter->m_geode->getNumDrawables(); ++i )
00087     {
00088         // each drawable is a WGELabel:
00089         osg::ref_ptr< WGELabel > t = static_cast< WGELabel* >( m_layouter->m_geode->getDrawable( i ) );
00090 
00091         // get anchor position in screen space for this item
00092         osg::Vec4 anchor = osg::Vec4( t->getAnchor(), 1.0 );
00093         osg::Matrixd projection = cam->getProjectionMatrix();
00094         osg::Matrixd view = cam->getViewMatrix();
00095         osg::Matrixd window = cam->getViewport()->computeWindowMatrix();
00096         osg::Vec4 anchorScreen = anchor * view * projection * window;
00097 
00098         // is the anchor on this or the other side of the screen?
00099         //int b = static_cast< int >( anchorScreen.y() / vheight * 10.0  ) % 10;
00100 
00101         // draw a line
00102         osg::Vec3 leadPos;
00103 
00104         if( anchorScreen.x() >= vwidth / 2 )
00105         {
00106             leadPos = osg::Vec3( vwidth - 10.0, anchorScreen.y(), 0.0 );
00107 
00108             t->setPosition( osg::Vec3( vwidth - 10.0, anchorScreen.y() + 5, 0.0 ) );
00109             t->setAlignment( osgText::Text::RIGHT_BOTTOM );
00110         }
00111         else
00112         {
00113             leadPos = osg::Vec3( 10.0, anchorScreen.y(), 0.0 );
00114 
00115             t->setPosition( osg::Vec3( 10.0, anchorScreen.y() + 5, 0.0 ) );
00116             t->setAlignment( osgText::Text::LEFT_BOTTOM );
00117         }
00118 
00119         v->push_back( leadPos );
00120         v->push_back( osg::Vec3( anchorScreen.x(), anchorScreen.y(), anchorScreen.z() ) );
00121     }
00122 
00123     // create geometry for the lines calculated above
00124     osg::ref_ptr< osg::Geometry > g = new osg::Geometry;
00125     g->setDataVariance( osg::Object::DYNAMIC );
00126     osg::ref_ptr< osg::DrawArrays > da = new osg::DrawArrays( osg::PrimitiveSet::LINES, 0, v->size() );
00127     g->setVertexArray( v );
00128     osg::ref_ptr< osg::Vec4Array > colors = new osg::Vec4Array;
00129     colors->push_back( osg::Vec4( 0.0f, 0.0f, 0.0f, 1.0f ) );
00130     g->setColorArray( colors );
00131     g->setColorBinding( osg::Geometry::BIND_OVERALL );
00132     g->addPrimitiveSet( da );
00133 
00134     osg::LineWidth* linewidth = new osg::LineWidth();
00135     linewidth->setWidth( 2.0f );
00136     g->getOrCreateStateSet()->setAttributeAndModes( linewidth, osg::StateAttribute::ON );
00137 
00138     // remove all previous drawables and insert new
00139     m_layouter->m_lineGeode->removeDrawables( 0, m_layouter->m_lineGeode->getNumDrawables() );
00140     m_layouter->m_lineGeode->addDrawable( g );
00141 
00142     traverse( node, nv );
00143 }
00144