//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see .
//
//---------------------------------------------------------------------------
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "core/common/WLogger.h"
#include "WGE2DManipulator.h"
#include "WGEGroupNode.h"
#include "WGENoOpManipulator.h"
#include "WGEZoomTrackballManipulator.h"
#include "WGraphicsEngine.h"
#include "WPickHandler.h"
#include "WMouseLocationHandler.h"
#include "exceptions/WGEInitFailed.h"
#include "core/common/WConditionOneShot.h"
#include "core/common/WThreadedRunner.h"
#include "WGEViewer.h"
WGEViewer::WGEViewer( std::string name, osg::ref_ptr wdata, int x, int y, int width, int height,
WGECamera::ProjectionMode projectionMode ):
WGEGraphicsWindow( wdata, x, y, width, height ),
boost::enable_shared_from_this< WGEViewer >(),
m_name( name ),
m_scene( new WGEGroupNode ),
m_rendered( WBoolFlag::SPtr( new WBoolFlag( new WConditionOneShot(), false ) ) ),
m_screenCapture( new WGEScreenCapture() ),
m_inAnimationMode( false ),
m_effectHorizon( new WGEViewerEffectHorizon() ),
m_effectVignette( new WGEViewerEffectVignette() ),
m_effectImageOverlay( new WGEViewerEffectImageOverlay() ),
m_paused( false )
{
try
{
m_View = osg::ref_ptr( new osgViewer::Viewer );
osg::ref_ptr< WGECamera > cam( new WGECamera( width, height, projectionMode ) );
m_View->setCamera( cam );
m_queryCallback = new QueryCallback( cam, m_rendered );
m_View->getCamera()->setInitialDrawCallback( m_queryCallback );
m_View->getCamera()->setFinalDrawCallback( m_screenCapture );
m_View->getCamera()->setGraphicsContext( m_GraphicsWindow.get() );
m_mouseLocationHandler = new WMouseLocationHandler( name );
m_View->addEventHandler( m_mouseLocationHandler );
switch( projectionMode )
{
case( WGECamera::ORTHOGRAPHIC ):
m_pickHandler = new WPickHandler( name );
m_View->addEventHandler( m_pickHandler );
if( name != std::string( "Main View" ) )
break;
/* FALLTHRU */
case( WGECamera::PERSPECTIVE ):
// camera manipulator
m_View->setCameraManipulator( new WGEZoomTrackballManipulator() );
m_View->setLightingMode( osg::View::HEADLIGHT ); // this is the default anyway
break;
case( WGECamera::TWO_D ):
// no manipulators nor gui handlers
break;
case( WGECamera::TWO_D_UNIT ):
// use no-op handler by default
m_View->setCameraManipulator( new WGENoOpManipulator() );
break;
default:
throw WGEInitFailed( std::string( "Unknown projection mode" ) );
}
// add the stats handler
m_View->addEventHandler( new osgViewer::StatsHandler );
// Properties of the view. Collects props of the effects and similar
m_properties = boost::shared_ptr< WProperties >( new WProperties( "Viewer Properties", "The view's properties" ) );
m_bgColor = m_properties->addProperty( "Background Color", "Default background color if not overwritten by a camera effect.",
defaultColor::WHITE,
boost::bind( &WGEViewer::updateBgColor, this ) );
m_throwing = m_properties->addProperty( "Throwing", "If checked, you can grab the scene and throw it. It will keep the rotation impulse.",
false,
boost::bind( &WGEViewer::updateThrowing, this ) );
WPropGroup effects = m_properties->addPropertyGroup( "Camera Effects", "Several effects that to not depend on any scene content." );
effects->addProperty( m_effectHorizon->getProperties() );
effects->addProperty( m_effectVignette->getProperties() );
effects->addProperty( m_effectImageOverlay->getProperties() );
// scene node
m_View->setSceneData( m_scene );
// add effects to it:
m_scene->insert( m_effectVignette );
m_scene->insert( m_effectImageOverlay );
m_scene->insert( m_effectHorizon );
// apply the above default
updateThrowing();
updateBgColor();
}
catch( ... )
{
throw WGEInitFailed( std::string( "Initialization of WGEViewer failed" ) );
}
}
WGEViewer::~WGEViewer()
{
// cleanup
close();
}
osg::ref_ptr WGEViewer::getView()
{
return m_View;
}
void WGEViewer::setCameraManipulator( osg::ref_ptr manipulator )
{
if( !m_inAnimationMode )
{
m_View->setCameraManipulator( manipulator );
}
}
osg::ref_ptr WGEViewer::getCameraManipulator()
{
return m_View->getCameraManipulator();
}
void WGEViewer::setCamera( osg::ref_ptr camera )
{
m_View->setCamera( camera );
// redraw request?? No since it redraws permanently and uses the new settings
}
osg::ref_ptr WGEViewer::getCamera()
{
return dynamic_cast< WGECamera* >( m_View->getCamera() );
}
void WGEViewer::setScene( osg::ref_ptr< WGEGroupNode > node )
{
m_sceneMainNode = node;
m_effectImageOverlay->setReferenceViewer( shared_from_this() );
m_scene->clear();
m_scene->insert( m_sceneMainNode );
// add effects to scene node. We cleared it earlier.
m_scene->insert( m_effectVignette );
m_scene->insert( m_effectImageOverlay );
m_scene->insert( m_effectHorizon );
}
osg::ref_ptr< WGEGroupNode > WGEViewer::getScene()
{
return m_sceneMainNode;
}
void WGEViewer::updateThrowing()
{
WGEZoomTrackballManipulator* manipulator = dynamic_cast< WGEZoomTrackballManipulator* >( getCameraManipulator().get() );
if( manipulator )
{
manipulator->setThrow( m_throwing->get() );
}
}
void WGEViewer::updateBgColor()
{
m_View->getCamera()->setClearColor( m_bgColor->get() );
}
void WGEViewer::setBgColor( const WColor& bgColor )
{
m_bgColor->set( bgColor );
}
WColor WGEViewer::getBgColor() const
{
return m_bgColor->get();
}
void WGEViewer::paint()
{
m_View->frame();
}
void WGEViewer::resize( int width, int height )
{
m_View->getEventQueue()->windowResize( 0, 0, width, height );
WGEGraphicsWindow::resize( width, height );
// also update the camera
m_View->getCamera()->setViewport( 0, 0, width, height );
WGECamera* camera = dynamic_cast< WGECamera* >( m_View->getCamera() );
if( camera )
{
camera->resize();
}
}
void WGEViewer::close()
{
// delete/unset all the objects we sponsored a "shared_from_this" pointer to ensure the viewer gets deleted after close
m_effectImageOverlay->setReferenceViewer( WGEViewer::SPtr() );
// forward close event
WGEGraphicsWindow::close();
}
std::string WGEViewer::getName() const
{
return m_name;
}
osg::ref_ptr< WPickHandler > WGEViewer::getPickHandler()
{
return m_pickHandler;
}
osg::ref_ptr< WMouseLocationHandler > WGEViewer::getMouseLocationHandler()
{
return m_mouseLocationHandler;
}
void WGEViewer::reset()
{
m_View->home();
}
WGEScreenCapture::RefPtr WGEViewer::getScreenCapture() const
{
return m_screenCapture;
}
std::string WGEViewer::getOpenGLVendor() const
{
return m_queryCallback->getVendor();
}
WBoolFlag::SPtr WGEViewer::isFrameRendered() const
{
return m_rendered;
}
WGEViewer::QueryCallback::QueryCallback( osg::ref_ptr camera, WBoolFlag::SPtr run ):
m_vendor( "" ),
m_run( run ),
m_camera( camera )
{
// init
}
WGEViewer::QueryCallback::~QueryCallback()
{
// cleanup
}
void WGEViewer::QueryCallback::operator()( osg::RenderInfo& /* renderInfo */ ) const
{
const GLubyte* vendor = glGetString( GL_VENDOR );
m_vendor = reinterpret_cast< const char* >( vendor );
// job done. De-register.
m_camera->setInitialDrawCallback( NULL );
m_run->set( true );
}
std::string WGEViewer::QueryCallback::getVendor() const
{
return m_vendor;
}
WGEAnimationManipulator::RefPtr WGEViewer::animationMode( bool on )
{
if( m_inAnimationMode && !on ) // turn off mode
{
m_inAnimationMode = false;
// restore old manipulator
m_View->setCameraManipulator( m_animationModeManipulatorBackup );
return NULL;
}
else if( !m_inAnimationMode && on ) // turn on
{
m_inAnimationMode = true;
// backup
m_animationModeManipulatorBackup = getCameraManipulator();
// create animation manipulator
WGEAnimationManipulator::RefPtr anim = new WGEAnimationManipulator();
m_View->setCameraManipulator( anim );
return anim;
}
else if( m_inAnimationMode ) // already on
{
return dynamic_cast< WGEAnimationManipulator* >( getCameraManipulator().get() );
}
// else: do nothing
return NULL;
}
bool WGEViewer::isAnimationMode() const
{
return m_inAnimationMode;
}
WGEViewerEffectHorizon::SPtr WGEViewer::getBackground()
{
return m_effectHorizon;
}
WGEViewerEffectImageOverlay::SPtr WGEViewer::getImageOverlay()
{
return m_effectImageOverlay;
}
WGEViewerEffectVignette::SPtr WGEViewer::getVignette()
{
return m_effectVignette;
}
WGEViewerEffectHorizon::ConstSPtr WGEViewer::getBackground() const
{
return m_effectHorizon;
}
WGEViewerEffectImageOverlay::ConstSPtr WGEViewer::getImageOverlay() const
{
return m_effectImageOverlay;
}
WGEViewerEffectVignette::ConstSPtr WGEViewer::getVignette() const
{
return m_effectVignette;
}
WProperties::SPtr WGEViewer::getProperties() const
{
return m_properties;
}
void WGEViewer::setEffectsActiveDefault( bool activeByDefault )
{
getBackground()->setEnabledByDefault( activeByDefault );
getImageOverlay()->setEnabledByDefault( activeByDefault );
getVignette()->setEnabledByDefault( activeByDefault );
}
void WGEViewer::setPaused( bool pause )
{
m_paused = pause;
}
bool WGEViewer::getPaused() const
{
return m_paused;
}
void WGEViewer::handleVisibilityChange( bool visible )
{
getView()->getScene()->getSceneData()->setNodeMask( visible * 0xFFFFFFFF );
}
void WGEViewer::requestContinuousUpdate( bool continuous )
{
getView()->requestContinuousUpdate( continuous );
}