server/canvas.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "canvas.h"
00019
00020 #include "channel.h"
00021 #include "compound.h"
00022 #include "config.h"
00023 #include "layout.h"
00024 #include "log.h"
00025 #include "nameFinder.h"
00026 #include "node.h"
00027 #include "paths.h"
00028 #include "pipe.h"
00029 #include "segment.h"
00030 #include "window.h"
00031
00032 #include <eq/net/dataIStream.h>
00033 #include <eq/net/dataOStream.h>
00034
00035
00036 using namespace eq::base;
00037
00038 namespace eq
00039 {
00040 namespace server
00041 {
00042
00043 Canvas::Canvas()
00044 : _config( 0 )
00045 , _activeLayout( 0 )
00046 {}
00047
00048 Canvas::Canvas( const Canvas& from, Config* config )
00049 : eq::Frustum( from )
00050 , _config( 0 )
00051 , _activeLayout( from._activeLayout )
00052 {
00053 EQASSERT( config );
00054
00055 for( SegmentVector::const_iterator i = from._segments.begin();
00056 i != from._segments.end(); ++i )
00057 {
00058 addSegment( new Segment( **i, config ));
00059 }
00060
00061 for( LayoutVector::const_iterator i = from._layouts.begin();
00062 i != from._layouts.end(); ++i )
00063 {
00064 const Layout* layout = *i;
00065 if( layout )
00066 {
00067 const LayoutPath path( layout->getPath( ));
00068 addLayout( config->getLayout( path ));
00069 }
00070 else
00071 addLayout( 0 );
00072 }
00073
00074 config->addCanvas( this );
00075 EQASSERT( _config );
00076 }
00077
00078 Canvas::~Canvas()
00079 {
00080 for( SegmentVector::const_iterator i = _segments.begin();
00081 i != _segments.end(); ++i )
00082 {
00083 Segment* segment = *i;
00084 segment->_canvas = 0;
00085 delete segment;
00086 }
00087 _segments.clear();
00088 _layouts.clear();
00089
00090 if( _config )
00091 _config->removeCanvas( this );
00092
00093 _config = 0;
00094 _activeLayout = 0;
00095 }
00096
00097 void Canvas::getInstanceData( net::DataOStream& os )
00098 {
00099
00100
00101
00102
00103 const uint64_t dirty = eq::Canvas::DIRTY_CUSTOM - 1;
00104 os << dirty;
00105 serialize( os, dirty );
00106 }
00107
00108 void Canvas::serialize( net::DataOStream& os, const uint64_t dirtyBits )
00109 {
00110 Frustum::serialize( os, dirtyBits );
00111
00112 if( dirtyBits & eq::Canvas::DIRTY_LAYOUT )
00113 os << _activeLayout;
00114
00115 if( dirtyBits & eq::Canvas::DIRTY_CHILDREN )
00116 {
00117 for( SegmentVector::const_iterator i = _segments.begin();
00118 i != _segments.end(); ++i )
00119 {
00120 Segment* segment = *i;
00121 EQASSERT( segment->getID() != EQ_ID_INVALID );
00122 os << segment->getID();
00123 }
00124 os << EQ_ID_INVALID;
00125
00126 for( LayoutVector::const_iterator i = _layouts.begin();
00127 i != _layouts.end(); ++i )
00128 {
00129 Layout* layout = *i;
00130 if( layout )
00131 {
00132 EQASSERT( layout->getID() != EQ_ID_INVALID );
00133 os << layout->getID();
00134 }
00135 else
00136 os << EQ_ID_NONE;
00137 }
00138 os << EQ_ID_INVALID;
00139 }
00140 }
00141
00142 void Canvas::deserialize( net::DataIStream& is, const uint64_t dirtyBits )
00143 {
00144 Frustum::deserialize( is, dirtyBits );
00145
00146 if( dirtyBits & eq::Canvas::DIRTY_LAYOUT )
00147 {
00148 uint32_t index;
00149 is >> index;
00150 _useLayout( index );
00151 }
00152 }
00153
00154 Segment* Canvas::getSegment( const SegmentPath& path )
00155 {
00156 EQASSERTINFO( _segments.size() > path.segmentIndex,
00157 _segments.size() << " <= " << path.segmentIndex );
00158
00159 if( _segments.size() <= path.segmentIndex )
00160 return 0;
00161
00162 return _segments[ path.segmentIndex ];
00163 }
00164
00165 CanvasPath Canvas::getPath() const
00166 {
00167 EQASSERT( _config );
00168
00169 const CanvasVector& canvases = _config->getCanvases();
00170 CanvasVector::const_iterator i = std::find( canvases.begin(),
00171 canvases.end(), this );
00172 EQASSERT( i != canvases.end( ));
00173
00174 CanvasPath path;
00175 path.canvasIndex = std::distance( canvases.begin(), i );
00176 return path;
00177 }
00178
00179 void Canvas::addSegment( Segment* segment )
00180 {
00181 EQASSERT( segment );
00182 EQASSERT( std::find( _segments.begin(), _segments.end(), segment ) ==
00183 _segments.end( ));
00184
00185
00186 if( segment->getCurrentType() == TYPE_NONE )
00187 {
00188 if( getCurrentType() != TYPE_NONE )
00189 {
00190 eq::Wall wall( getWall( ));
00191 const Viewport& viewport( segment->getViewport( ));
00192 wall.apply( viewport );
00193
00194 switch( getCurrentType( ))
00195 {
00196 case Frustum::TYPE_WALL:
00197 segment->setWall( wall );
00198 EQLOG( LOG_VIEW ) << "Segment " << segment->getName()
00199 << segment->getWall() << std::endl;
00200 break;
00201
00202 case Frustum::TYPE_PROJECTION:
00203 {
00204 Projection projection( getProjection( ));
00205 projection = wall;
00206 segment->setProjection( projection );
00207 break;
00208 }
00209 default:
00210 EQUNIMPLEMENTED;
00211 break;
00212 }
00213 }
00214 }
00215
00216 segment->_canvas = this;
00217 _segments.push_back( segment );
00218 }
00219
00220 Segment* Canvas::findSegment( const std::string& name )
00221 {
00222 SegmentFinder finder( name );
00223 accept( finder );
00224 return finder.getResult();
00225 }
00226
00227 void Canvas::addLayout( Layout* layout )
00228 {
00229 EQASSERT( std::find( _layouts.begin(), _layouts.end(), layout ) ==
00230 _layouts.end( ));
00231
00232
00233 _layouts.push_back( layout );
00234 }
00235
00236 void Canvas::_useLayout( const uint32_t index )
00237 {
00238 if( _config && _config->isRunning( ))
00239 _switchLayout( _activeLayout, index );
00240
00241 _activeLayout = index;
00242 }
00243
00244 void Canvas::init()
00245 {
00246 _switchLayout( EQ_ID_NONE, _activeLayout );
00247 }
00248
00249 void Canvas::exit()
00250 {
00251 _switchLayout( _activeLayout, EQ_ID_NONE );
00252 }
00253
00254 namespace
00255 {
00256 class ActivateVisitor : public ConfigVisitor
00257 {
00258 public:
00259 ActivateVisitor( const ChannelVector& channels ) : _channels( channels ) {}
00260 virtual ~ActivateVisitor() {}
00261
00262 virtual VisitorResult visit( Compound* compound )
00263 {
00264 Channel* channel = compound->getChannel();
00265 if( !channel )
00266 return TRAVERSE_CONTINUE;
00267
00268 for( ChannelVector::iterator i = _channels.begin();
00269 i != _channels.end(); ++i )
00270 {
00271 Channel* destChannel = *i;
00272 if( destChannel != channel )
00273 continue;
00274
00275 compound->activate();
00276 break;
00277 }
00278
00279 return TRAVERSE_PRUNE;
00280 }
00281
00282 private:
00283 ChannelVector _channels;
00284 };
00285
00286 class DeactivateVisitor : public ConfigVisitor
00287 {
00288 public:
00289 DeactivateVisitor( ChannelVector& channels )
00290 : _channels( channels ) {}
00291 virtual ~DeactivateVisitor() {}
00292
00293 virtual VisitorResult visit( Compound* compound )
00294 {
00295 Channel* channel = compound->getChannel();
00296 if( !channel )
00297 return TRAVERSE_CONTINUE;
00298
00299 for( ChannelVector::iterator i = _channels.begin();
00300 i != _channels.end(); ++i )
00301 {
00302 Channel* destChannel = *i;
00303 if( destChannel != channel )
00304 continue;
00305
00306 compound->deactivate();
00307 break;
00308 }
00309
00310 return TRAVERSE_PRUNE;
00311 }
00312
00313 private:
00314 ChannelVector& _channels;
00315 };
00316 }
00317
00318 void Canvas::_switchLayout( const uint32_t oldIndex, const uint32_t newIndex )
00319 {
00320 EQASSERT( _config );
00321 if( oldIndex == newIndex )
00322 return;
00323
00324 const size_t nLayouts = _layouts.size();
00325 const Layout* oldLayout = (oldIndex >= nLayouts) ? 0 :_layouts[oldIndex];
00326 const Layout* newLayout = (newIndex >= nLayouts) ? 0 :_layouts[newIndex];
00327
00328 for( SegmentVector::const_iterator i = _segments.begin();
00329 i != _segments.end(); ++i )
00330 {
00331 const Segment* segment = *i;
00332 const ChannelVector& destChannels = segment->getDestinationChannels();
00333
00334 if( newLayout )
00335 {
00336
00337 ChannelVector usedChannels;
00338 for( ChannelVector::const_iterator j = destChannels.begin();
00339 j != destChannels.end(); ++j )
00340 {
00341 Channel* channel = *j;
00342 const Layout* channelLayout = channel->getLayout();
00343 if( channelLayout == newLayout )
00344 usedChannels.push_back( channel );
00345 }
00346
00347 ActivateVisitor activator( usedChannels );
00348 _config->accept( activator );
00349 }
00350
00351 if( oldLayout )
00352 {
00353
00354 ChannelVector usedChannels;
00355
00356 for( ChannelVector::const_iterator j = destChannels.begin();
00357 j != destChannels.end(); ++j )
00358 {
00359 Channel* channel = *j;
00360 const Layout* channelLayout = channel->getLayout();
00361 if( channelLayout == oldLayout )
00362 usedChannels.push_back( channel );
00363 }
00364 DeactivateVisitor deactivator( usedChannels );
00365 _config->accept( deactivator );
00366 }
00367 }
00368 }
00369
00370 namespace
00371 {
00372 template< class C >
00373 VisitorResult _accept( C* canvas, CanvasVisitor& visitor )
00374 {
00375 VisitorResult result = visitor.visitPre( canvas );
00376 if( result != TRAVERSE_CONTINUE )
00377 return result;
00378
00379 const SegmentVector& segments = canvas->getSegments();
00380 for( SegmentVector::const_iterator i = segments.begin();
00381 i != segments.end(); ++i )
00382 {
00383 switch( (*i)->accept( visitor ))
00384 {
00385 case TRAVERSE_TERMINATE:
00386 return TRAVERSE_TERMINATE;
00387
00388 case TRAVERSE_PRUNE:
00389 result = TRAVERSE_PRUNE;
00390 break;
00391
00392 case TRAVERSE_CONTINUE:
00393 default:
00394 break;
00395 }
00396 }
00397
00398 switch( visitor.visitPost( canvas ))
00399 {
00400 case TRAVERSE_TERMINATE:
00401 return TRAVERSE_TERMINATE;
00402
00403 case TRAVERSE_PRUNE:
00404 return TRAVERSE_PRUNE;
00405
00406 case TRAVERSE_CONTINUE:
00407 default:
00408 break;
00409 }
00410
00411 return result;
00412 }
00413 }
00414
00415 VisitorResult Canvas::accept( CanvasVisitor& visitor )
00416 {
00417 return _accept( this, visitor );
00418 }
00419
00420 VisitorResult Canvas::accept( CanvasVisitor& visitor ) const
00421 {
00422 return _accept( this, visitor );
00423 }
00424
00425 void Canvas::unmap()
00426 {
00427 net::Session* session = getSession();
00428 EQASSERT( session );
00429 for( SegmentVector::const_iterator i = _segments.begin();
00430 i != _segments.end(); ++i )
00431 {
00432 Segment* segment = *i;
00433 EQASSERT( segment->getID() != EQ_ID_INVALID );
00434
00435 session->unmapObject( segment );
00436 }
00437
00438 EQASSERT( getID() != EQ_ID_INVALID );
00439 session->unmapObject( this );
00440 }
00441
00442 std::ostream& operator << ( std::ostream& os, const Canvas* canvas )
00443 {
00444 if( !canvas )
00445 return os;
00446
00447 os << disableFlush << disableHeader << "canvas" << std::endl;
00448 os << "{" << std::endl << indent;
00449
00450 const std::string& name = canvas->getName();
00451 if( !name.empty( ))
00452 os << "name \"" << name << "\"" << std::endl;
00453
00454 const LayoutVector& layouts = canvas->getLayouts();
00455 for( LayoutVector::const_iterator i = layouts.begin();
00456 i != layouts.end(); ++i )
00457 {
00458 Layout* layout = *i;
00459 if( layout )
00460 {
00461 const Config* config = layout->getConfig();
00462 const std::string& layoutName = layout->getName();
00463 if( layoutName.empty() ||
00464 config->findLayout( layoutName ) != layout )
00465 os << layout->getPath() << std::endl;
00466 else
00467 os << "layout \"" << layout->getName() << "\"" << std::endl;
00468 }
00469 else
00470 os << "layout OFF" << std::endl;
00471 }
00472
00473 os << static_cast< const eq::Frustum& >( *canvas );
00474
00475 const SegmentVector& segments = canvas->getSegments();
00476 for( SegmentVector::const_iterator i = segments.begin();
00477 i != segments.end(); ++i )
00478 {
00479 os << *i;
00480 }
00481 os << exdent << "}" << std::endl << enableHeader << enableFlush;
00482 return os;
00483 }
00484
00485 }
00486 }