OpenWalnut  1.4.0
WGETextureHud.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <iostream>
26 #include <string>
27 
28 #include <boost/bind.hpp>
29 #include <boost/function.hpp>
30 
31 #include <osg/Camera>
32 #include <osg/Geode>
33 #include <osg/Geometry>
34 #include <osg/MatrixTransform>
35 #include <osg/Node>
36 #include <osg/TexEnv>
37 
38 #include "../common/WPathHelper.h"
39 
40 #include "WGETextureHud.h"
41 
43  osg::Projection(),
44  m_group( new WGEGroupNode() ),
45  m_maxElementWidth( 256 ),
46  m_renderBin( 10000 ),
47  m_viewport( new osg::Viewport() ),
48  m_coupleTexViewport( false )
49 {
50  getOrCreateStateSet()->setRenderBinDetails( m_renderBin, "RenderBin" );
51  m_group->addUpdateCallback( new SafeUpdateCallback( this ) );
52  addChild( m_group );
53 }
54 
56 {
57  // cleanup
58 }
59 
60 void WGETextureHud::SafeUpdateCallback::operator()( osg::Node* node, osg::NodeVisitor* nv )
61 {
62  // set the new size of the widget (how can we get this data?)
63  unsigned int screenWidth = m_hud->m_viewport->width();
64  unsigned int screenHeight = m_hud->m_viewport->height();
65  m_hud->setMatrix( osg::Matrix::ortho2D( 0, screenWidth, 0, screenHeight ) );
66 
67  // border around each element
68  unsigned int border = 5;
69 
70  // update all those
71  osg::Group* group = static_cast< osg::Group* >( node );
72 
73  unsigned int nextX = border;
74  unsigned int nextY = border;
75 
76  // iterate all children
77  for( size_t i = 0; i < group->getNumChildren(); ++i )
78  {
79  // all children are WGETextureHudEntries.
80  WGETextureHudEntry* tex = static_cast< WGETextureHudEntry* >( group->getChild( i ) );
81  tex->setMaxTextWidth( m_hud->getMaxElementWidth() ); // as this might change each frame, we set it here
82 
83  // scale the height of the quad (texture) to have proper aspect ratio
84  float height = static_cast< float >( m_hud->getMaxElementWidth() * tex->getRealHeight() ) / static_cast< float >( tex->getRealWidth() );
85 
86  // scale texture if needed
88  {
89  osg::ref_ptr< osg::TexMat > texMat = tex->getTextureMatrix();
90  texMat->setMatrix( osg::Matrixd::scale( static_cast< float >( screenWidth ) / static_cast< float >( tex->getRealWidth() ),
91  static_cast< float >( screenHeight )/ static_cast< float >( tex->getRealHeight() ), 1.0 ) );
92 
93  // this also changes the aspect ratio in the texture:
94  height = static_cast< float >( m_hud->getMaxElementWidth() * screenHeight ) / static_cast< float >( screenWidth );
95  }
96 
97  // scale them to their final size
98  osg::Matrixd scale = osg::Matrixd::scale( m_hud->getMaxElementWidth(), height, 1.0 );
99 
100  // need to add a "line-break"?
101  if( nextY + height + border > screenHeight )
102  {
103  nextX += m_hud->getMaxElementWidth() + border;
104  nextY = border;
105  }
106 
107  // transform them to the right place
108  osg::Matrixd translate = osg::Matrixd::translate( static_cast< double >( nextX ), static_cast< double >( nextY ), 0.0 );
109  tex->setMatrix( scale * translate );
110 
111  // calculate the y position of the next texture
112  nextY += height + border;
113  }
114 
115  // update all the others
116  traverse( node, nv );
117 }
118 
119 void WGETextureHud::addTexture( osg::ref_ptr< WGETextureHudEntry > texture )
120 {
121  m_group->insert( texture );
122 }
123 
124 void WGETextureHud::removeTexture( osg::ref_ptr< WGETextureHudEntry > texture )
125 {
126  m_group->remove( texture );
127 }
128 
129 /**
130  * This method compares a specified texture with the specified node. If the node is an WGETextureHudEntry instance, the containied textures
131  * get compared.
132  *
133  * \param tex the texture to compare to
134  * \param node the node
135  *
136  * \return true if node->m_texture == tex.
137  */
138 bool hudEntryPredicate( osg::ref_ptr< osg::Texture > tex, osg::ref_ptr< osg::Node > const& node )
139 {
140  // is the node an WGETextureHudEntry?
141  WGETextureHud::WGETextureHudEntry const* e = dynamic_cast< WGETextureHud::WGETextureHudEntry const* >( node.get() );
142  if( !e )
143  {
144  return false;
145  }
146 
147  // check if textures are equal
148  return e->getTexture() == tex;
149 }
150 
151 void WGETextureHud::removeTexture( osg::ref_ptr< osg::Texture > texture )
152 {
154  boost::function< bool ( osg::ref_ptr< osg::Node > const& ) > > TexCheck; // NOLINT - if the
155  // space after bool is removed (as the stylechecker want) it interprets it as old-style cast and complains about it. This is valid syntax for
156  // boost::function.
157 
158  m_group->remove_if(
159  boost::shared_ptr< WGEGroupNode::NodePredicate >(
160  new TexCheck( boost::bind( &hudEntryPredicate, texture, _1 ) )
161  )
162  );
163 }
164 
165 void WGETextureHud::setViewport( osg::Viewport* viewport )
166 {
167  m_viewport = viewport;
168 }
169 
171 {
172  m_coupleTexViewport = couple;
173 }
174 
175 WGETextureHud::WGETextureHudEntry::WGETextureHudEntry( osg::ref_ptr< osg::Texture2D > texture, std::string name, bool transparency ):
176  osg::MatrixTransform(),
177  m_texture( texture ),
178  m_name( name ),
179  m_maxTextWidth( 256 )
180 {
181  setMatrix( osg::Matrixd::identity() );
182  setReferenceFrame( osg::Transform::ABSOLUTE_RF );
183 
184  //////////////////////////////////////////////////
185  // Texture Quad
186 
187  osg::Geode* geode = new osg::Geode();
188 
189  // Set up geometry for the HUD and add it to the HUD
190  osg::ref_ptr< osg::Geometry > HUDBackgroundGeometry = new osg::Geometry();
191 
192  osg::ref_ptr< osg::Vec3Array > HUDBackgroundVertices = new osg::Vec3Array;
193  HUDBackgroundVertices->push_back( osg::Vec3( 0, 0, -1 ) );
194  HUDBackgroundVertices->push_back( osg::Vec3( 1, 0, -1 ) );
195  HUDBackgroundVertices->push_back( osg::Vec3( 1, 1, -1 ) );
196  HUDBackgroundVertices->push_back( osg::Vec3( 0, 1, -1 ) );
197 
198  osg::ref_ptr< osg::Vec3Array > HUDBackgroundTex = new osg::Vec3Array;
199  HUDBackgroundTex->push_back( osg::Vec3( 0, 0, 0 ) );
200  HUDBackgroundTex->push_back( osg::Vec3( 1, 0, 0 ) );
201  HUDBackgroundTex->push_back( osg::Vec3( 1, 1, 0 ) );
202  HUDBackgroundTex->push_back( osg::Vec3( 0, 1, 0 ) );
203 
204  osg::ref_ptr< osg::DrawElementsUInt > HUDBackgroundIndices = new osg::DrawElementsUInt( osg::PrimitiveSet::POLYGON, 0 );
205  HUDBackgroundIndices->push_back( 0 );
206  HUDBackgroundIndices->push_back( 1 );
207  HUDBackgroundIndices->push_back( 2 );
208  HUDBackgroundIndices->push_back( 3 );
209 
210  osg::ref_ptr< osg::Vec4Array > HUDcolors = new osg::Vec4Array;
211  HUDcolors->push_back( osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) );
212 
213  osg::ref_ptr< osg::Vec3Array > HUDnormals = new osg::Vec3Array;
214  HUDnormals->push_back( osg::Vec3( 0.0f, 0.0f, 1.0f ) );
215  HUDBackgroundGeometry->setNormalArray( HUDnormals );
216  HUDBackgroundGeometry->setNormalBinding( osg::Geometry::BIND_OVERALL );
217  HUDBackgroundGeometry->addPrimitiveSet( HUDBackgroundIndices );
218  HUDBackgroundGeometry->setVertexArray( HUDBackgroundVertices );
219  HUDBackgroundGeometry->setColorArray( HUDcolors );
220  HUDBackgroundGeometry->setColorBinding( osg::Geometry::BIND_OVERALL );
221  HUDBackgroundGeometry->setTexCoordArray( 0, HUDBackgroundTex );
222 
223  geode->addDrawable( HUDBackgroundGeometry );
224 
225  // Create and set up a state set using the texture from above
226  osg::StateSet* state = geode->getOrCreateStateSet();
227  state->setTextureAttributeAndModes( 0, texture, osg::StateAttribute::ON );
228  state->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
229  state->setMode( GL_LIGHTING, osg::StateAttribute::PROTECTED );
230  state->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
231 
232  // enable texture coordinate manipulation via texture matrices
233  m_texMat = new osg::TexMat;
234  m_texMat->setMatrix( osg::Matrixd::identity() );
235  state->setTextureAttributeAndModes( 0, m_texMat, osg::StateAttribute::ON );
236 
237  // This disables colorblending of the texture with the underlying quad
238  // osg::TexEnv* decalState = new osg::TexEnv();
239  // decalState->setMode( osg::TexEnv::DECAL );
240  // state->setTextureAttribute( 0, decalState, osg::StateAttribute::ON );
241 
242  // en/disable blending
243  if( !transparency )
244  {
245  state->setMode( GL_BLEND, osg::StateAttribute::PROTECTED );
246  state->setMode( GL_BLEND, osg::StateAttribute::OFF );
247  }
248  else
249  {
250  state->setMode( GL_BLEND, osg::StateAttribute::PROTECTED );
251  state->setMode( GL_BLEND, osg::StateAttribute::ON );
252  state->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
253  }
254 
255  // add the geode
256  addChild( geode );
257 
258  //////////////////////////////////////////////////
259  // Text
260  osg::ref_ptr< osg::Geode > textGeode = new osg::Geode();
261  state = textGeode->getOrCreateStateSet();
262  state->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
263  addChild( textGeode );
264  m_label = new osgText::Text();
265  m_label->setFont( WPathHelper::getAllFonts().Default.string() );
266  m_label->setBackdropType( osgText::Text::OUTLINE );
267  m_label->setCharacterSize( 15 );
268  m_label->setText( m_name );
269  m_label->setAxisAlignment( osgText::Text::SCREEN );
270  m_label->setPosition( osg::Vec3( 0.02, 0.925, -1.0 ) );
271  m_label->setColor( osg::Vec4( 1.0, 1.0, 1.0, 1.0 ) );
272  textGeode->addDrawable( m_label );
273 }
274 
276 {
277  // cleanup
278 }
279 
281 {
282  m_maxTextWidth = width;
283  m_label->setMaximumWidth( width - 20 ); // 20? Ensure some space at the right side
284 }
285 
287 {
288  return m_texture->getTextureWidth();
289 }
290 
292 {
293  return m_texture->getTextureHeight();
294 }
295 
296 osg::ref_ptr< osg::TexMat > WGETextureHud::WGETextureHudEntry::getTextureMatrix() const
297 {
298  return m_texMat;
299 }
300 
302 {
303  return m_name;
304 }
305 
307 {
308  return m_maxElementWidth;
309 }
310 
311 void WGETextureHud::setMaxElementWidth( unsigned int width )
312 {
313  m_maxElementWidth = width;
314 }
315 
316 osg::ref_ptr< osg::Texture2D > WGETextureHud::WGETextureHudEntry::getTexture() const
317 {
318  return m_texture;
319 }
320 
322 {
323  return m_renderBin;
324 }
325