This example builds on the symbol facade and driver from the previous examples in this tutorial series, and shows additional steps that are necessary for rotating created symbols using an item on the symbol's context menu.
In order to make applying rotations to selected symbols easier, the DtExampleSymbolDriver was updated to maintain a list of currently selected symbols at all times. The DtRotateSymbolItem then uses this list to determine if any symbols are selected, and uses the list to apply the rotation to the selected symbols.
DtSelectionManager& selMgr =
DtSelectionManager::instance( myAgentManager.de() );
const DtSelectionManager::IdSet& curSel = selMgr.currentSelections();
DtSelectionManager::IdSet::const_iterator selItr = curSel.begin();
DtSelectionManager::IdSet::const_iterator selEnd = curSel.end();
myCurrentlySelectedSymbols.clear();
DtSymbolFacade* symbol;
for ( ; selItr != selEnd; ++selItr )
{
if ( symbol = findSymbol(*selItr) )
{
myCurrentlySelectedSymbols.insert( symbol );
}
}
To signal that a symbol should be rotated and by how much, a menu item was created to prompt the user for the angle to rotate the symbol to and to apply the rotation to the currently selected symbols. In order to get the angle value from the user, a basic dialog (DtRotateSymbolDialog) was created.
void DtRotateSymbolItem::on_triggered()
{
DtRotateSymbolDialog rotateDialog( myDe );
int retCode = rotateDialog.exec();
if ( retCode == QDialog::Rejected )
{
return;
}
DtExampleSymbolDriver* symbolDriver = (DtExampleSymbolDriver*)
myDe.driverManager().findDriver( "DtExampleSymbolDriver" );
DtExampleSymbolDriver::SymbolList selectedSymbols =
symbolDriver->selectedSymbols();
DtExampleSymbolDriver::SymbolList::iterator i = selectedSymbols.begin();
DtExampleSymbolDriver::SymbolList::iterator e = selectedSymbols.end();
float angle = rotateDialog.selectedRotationAmount();
for ( ; i != e; ++i )
{
(*i)->setRotation( angle );
}
The menu item also checks to make sure at least one symbol is selected on displaying the context menu, since the rotation only applies to symbols.
void DtRotateSymbolItem::on_aboutToShow()
{
DtExampleSymbolDriver* symbolDriver = (DtExampleSymbolDriver*)
myDe.driverManager().findDriver( "DtExampleSymbolDriver" );
myAction->setEnabled( ! symbolDriver->selectedSymbols().empty() );
}
In order for the above DtRotateSymbolItem to work, the setRotation method must be implemented in the DtSymbolFacade.
void DtSymbolFacade::setRotation( float angleInDegrees )
{
myWidgetLabelAgent->setRotation( DtDeg2Rad(angleInDegrees) );
}
[<< exampleSymbolFacade2] [Home] [Top of Page] [exampleSymbolFacade4 >>]
DtSymbolDriverToolbar3.h
#pragma once
namespace makVrv
{
class DtDe;
}
namespace makVrv
{
namespace exampleSymbolFacade3
{
{
public:
virtual ~DtSymbolDriverToolbar();
};
{
public:
virtual ~DtAddSymbolItem();
virtual void on_triggered();
protected:
};
{
public:
virtual ~DtRotateSymbolItem();
virtual void on_aboutToShow();
virtual void on_triggered();
protected:
};
{
public:
DtSymbolFacadeExampleMenu(DtDe& de);
virtual ~DtSymbolFacadeExampleMenu();
};
}
}
DtSymbolDriverToolbar3.cxx
#include <QtGui/QToolBar>
#include <QtGui/QAction>
#include <QtGui/QMenu>
#include <matrix/vlVector.h>
#include <time.h>
#include <math.h>
namespace makVrv
{
namespace exampleSymbolFacade3
{
: DtToolbar( de, "DtSymbolDriverToolbar" )
{
}
DtSymbolDriverToolbar::~DtSymbolDriverToolbar()
{
}
{
bar->setWindowTitle( QObject::tr("Symbol Driver Toolbar") );
bar->setObjectName( QObject::tr("Symbol Driver Toolbar") );
return bar;
}
DtAddSymbolItem::DtAddSymbolItem( DtDe& de )
: DtMenuItem( "DtAddSymbolItem" )
, myDe( de )
{
srand( time(NULL ) );
}
DtAddSymbolItem::~DtAddSymbolItem()
{
}
{
act->setText( DtMenuItem::tr("&Add new symbol...") );
act->setToolTip( DtMenuItem::tr("Create a new symbol...") );
act->setIcon( QIcon(QObject::tr("../data/Icons/UtilityAdd.svg")) );
return act;
}
void DtAddSymbolItem::on_triggered()
{
static int numSymbolsCreated = 0;
DtString symbolName( "Symbol #" );
symbolName += DtString(numSymbolsCreated);
double rand_x = 4000.0*((double)rand())/RAND_MAX;
double rand_y = 4000.0*((double)rand())/RAND_MAX;
double rand_z = 4000.0*((double)rand())/RAND_MAX;
DtVector
location( rand_x, rand_y, rand_z );
DtExampleSymbolDriver* symbolDriver = (DtExampleSymbolDriver*)
myDe.driverManager().findDriver( "DtExampleSymbolDriver" );
symbolDriver->createSymbol( symbolName.string(),
location );
++numSymbolsCreated;
}
DtRotateSymbolItem::DtRotateSymbolItem( DtDe& de )
: DtMenuItem( "DtRotateSymbolItem" )
, myAction( 0 )
, myDe( de )
{
}
DtRotateSymbolItem::~DtRotateSymbolItem()
{
}
{
myAction->setText( DtMenuItem::tr("&Rotate symbol...") );
myAction->setToolTip( DtMenuItem::tr("Rotate symbol...") );
myAction->setIcon( QIcon(QObject::tr("../data/Icons/SetRestore.svg")) );
return myAction;
}
void DtRotateSymbolItem::on_aboutToShow()
{
DtExampleSymbolDriver* symbolDriver = (DtExampleSymbolDriver*)
myDe.driverManager().findDriver( "DtExampleSymbolDriver" );
myAction->setEnabled( ! symbolDriver->selectedSymbols().empty() );
}
void DtRotateSymbolItem::on_triggered()
{
DtRotateSymbolDialog rotateDialog( myDe );
int retCode = rotateDialog.exec();
if ( retCode == QDialog::Rejected )
{
return;
}
DtExampleSymbolDriver* symbolDriver = (DtExampleSymbolDriver*)
myDe.driverManager().findDriver( "DtExampleSymbolDriver" );
DtExampleSymbolDriver::SymbolList selectedSymbols =
symbolDriver->selectedSymbols();
DtExampleSymbolDriver::SymbolList::iterator i = selectedSymbols.begin();
DtExampleSymbolDriver::SymbolList::iterator e = selectedSymbols.end();
float angle = rotateDialog.selectedRotationAmount();
for ( ; i != e; ++i )
{
(*i)->setRotation( angle );
}
}
DtSymbolFacadeExampleMenu::DtSymbolFacadeExampleMenu(DtDe& de)
: DtMenu(de, "DtSymbolFacadeExampleMenu")
{
}
DtSymbolFacadeExampleMenu::~DtSymbolFacadeExampleMenu()
{
}
QMenu* DtSymbolFacadeExampleMenu::createMenu( DtDe& de,
QWidget* parent )
{
QMenu* menu =
new QMenu(QObject::tr(
"Example"), parent);
return menu;
}
}
}
DtRotateSymbolDialog3.h
#pragma once
#include <QtGui/QDialog>
class QDoubleSpinBox;
namespace makVrv
{
namespace exampleSymbolFacade3
{
{ Q_OBJECT;
public:
Qt::WindowFlags f = 0 );
virtual ~DtRotateSymbolDialog();
float selectedRotationAmount() const;
private:
DtRotateSymbolDialog( const DtRotateSymbolDialog& orig );
DtRotateSymbolDialog& operator = ( const DtRotateSymbolDialog& orig );
protected:
void setupGui();
protected:
QDoubleSpinBox* myRotationSpinner;
};
}
}
DtRotateSymbolDialog3.cxx
#include <QtGui/QDoubleSpinBox>
#include <QtGui/QVBoxLayout>
#include <QtGui/QHBoxLayout>
#include <QtGui/QPushButton>
#include <QtGui/QLabel>
namespace makVrv
{
namespace exampleSymbolFacade3
{
QWidget* parent , Qt::WindowFlags f )
, myRotationSpinner( 0 )
{
setupGui();
setWindowTitle(tr("Rotate Symbol"));
}
DtRotateSymbolDialog::~DtRotateSymbolDialog()
{
}
void DtRotateSymbolDialog::setupGui()
{
QVBoxLayout* dialogLayout = new QVBoxLayout();
QHBoxLayout* fieldLayout = new QHBoxLayout();
{
fieldLabel->setText( "Rotation (deg):" );
fieldLayout->addWidget( fieldLabel );
myRotationSpinner = new QDoubleSpinBox();
myRotationSpinner->setMinimum( 0 );
myRotationSpinner->setDecimals( 1 );
myRotationSpinner->setMaximum( 360 );
fieldLayout->addWidget( myRotationSpinner );
}
dialogLayout->addLayout( fieldLayout );
QHBoxLayout* okCancelLayout = new QHBoxLayout();
{
okCancelLayout->addStretch( 1 );
okButton->setText( "OK" );
okButton->setDefault( true );
okCancelLayout->addWidget( okButton );
connect( okButton, SIGNAL(clicked()), this, SLOT(accept()) );
cancelButton->setText( "Cancel" );
cancelButton->setDefault( false );
okCancelLayout->addWidget( cancelButton );
connect( cancelButton, SIGNAL(clicked()), this, SLOT(reject()) );
okCancelLayout->addStretch( 1 );
}
dialogLayout->addLayout( okCancelLayout );
setLayout( dialogLayout );
}
float DtRotateSymbolDialog::selectedRotationAmount() const
{
return myRotationSpinner->value();
}
}
}
DtSymbolFacade3.h
#pragma once
#include <boost/signal.hpp>
class DtVector;
namespace makVrv
{
class DtSceneObjectAgent;
class DtWidgetLabelAgent;
class DtAgentManagerInterface;
class DtProjectedWidgetModelAgent;
}
namespace makVrv
{
namespace exampleSymbolFacade3
{
{
public:
virtual ~DtSymbolFacade();
virtual void setPosition( const DtVector& pos );
virtual void setRotation( float angleInDegrees );
protected:
void initialize();
protected:
};
}
}
DtSymbolFacade3.cxx
#include <vlutil/vlUtil.h>
#include <matrix/vlMath.h>
namespace makVrv
{
namespace exampleSymbolFacade3
{
DtAgentManagerInterface& sceneInterface,
DtElementID id )
: myElementId( id )
, mySceneObjectAgent( DtSceneObjectAgent::create(sceneInterface) )
, myProjectedWidgetModelAgent( DtProjectedWidgetModelAgent::create(sceneInterface) )
, myWidgetLabelAgent( DtWidgetLabelAgent::create(sceneInterface) )
{
initialize();
}
DtSymbolFacade::~DtSymbolFacade()
{
myProjectedWidgetModelAgent->removeWidget( myWidgetLabelAgent );
DtDELETE( myWidgetLabelAgent );
mySceneObjectAgent->removeModel( myProjectedWidgetModelAgent );
DtDELETE( myProjectedWidgetModelAgent );
DtDELETE( mySceneObjectAgent );
}
void DtSymbolFacade::initialize()
{
if ( ! mySceneObjectAgent ) DtTHROW_NEW( DtCorruptedState, "Unable to create scene object agent." );
if ( ! myProjectedWidgetModelAgent ) DtTHROW_NEW( DtCorruptedState, "Unable to create projected widget model agent." );
if ( ! myWidgetLabelAgent ) DtTHROW_NEW( DtCorruptedState, "Unable to create widget label agent." );
mySceneObjectAgent->setModelSet( 5 );
mySceneObjectAgent->setElementID( myElementId );
mySceneObjectAgent->addModel( myProjectedWidgetModelAgent, DtStateVisualizer::EntityVisualizerType );
myWidgetLabelAgent->setOverlay( DtOverlayManager::ModelSet_2D_Icons_Overlay );
myWidgetLabelAgent->setBackgroundImage( "$(DATA_DIR)/images/ArrowCircle.png" );
myWidgetLabelAgent->setColor( 0.8f, 0.8f, 0.8f, 1.0f );
myWidgetLabelAgent->setSize( 32, 32 );
myProjectedWidgetModelAgent->addWidget( myWidgetLabelAgent );
myWidgetLabelAgent->setEventsEnabled( true );
}
{
return myElementId;
}
DtWidgetLabelAgent& DtSymbolFacade::widgetLabelAgent()
{
return *myWidgetLabelAgent;
}
void DtSymbolFacade::setPosition( const DtVector& pos )
{
mySceneObjectAgent->setPosition( 0, pos );
}
void DtSymbolFacade::setRotation( float angleInDegrees )
{
myWidgetLabelAgent->setRotation( DtDeg2Rad(angleInDegrees) );
}
DtElementEntry::ElementType DtSymbolFacade::elementType()
{
return DtElementEntry::Entity;
}
}
}
DtExampleSymbolDriver3.h
#pragma once
#include <boost/unordered_set.hpp>
class DtVector;
namespace makVrv
{
namespace exampleSymbolFacade3
{
class DtSymbolFacade;
{
public:
typedef boost::unordered_set<DtSymbolFacade*> SymbolList;
public:
virtual ~DtExampleSymbolDriver();
virtual bool onStart();
virtual bool onStop();
virtual bool onTick();
virtual DtSymbolFacade* createSymbol(
const std::string& name,
const DtVector& pos );
virtual SymbolList selectedSymbols() const;
protected:
virtual void positionSymbol( DtSymbolFacade* symbol, const DtVector& pos );
virtual void slot_currentSelectionChanged(
protected:
typedef boost::unordered_map<makVrv::DtElementID,DtSymbolFacade*> SymbolFacadeMap;
SymbolFacadeMap mySymbolFacades;
SymbolList myCurrentlySelectedSymbols;
};
}
}
DtExampleSymbolDriver3.cxx
#include <matrix/vlVector.h>
namespace makVrv
{
namespace exampleSymbolFacade3
{
: makVrv::DtDriver( am, "DtExampleSymbolDriver" )
{
}
DtExampleSymbolDriver::~DtExampleSymbolDriver()
{
DtExampleSymbolDriver::onStop();
}
const std::string& DtExampleSymbolDriver::className()
const
{
}
bool DtExampleSymbolDriver::onStart()
{
DtScene& sceneDriver = myAgentManager.de().scene();
std::string maklandPath = myAgentManager.de().dePathConfiguration().userPath();
maklandPath += "/terrains/MaklandNoSpeedtrees.mtf";
sceneDriver.loadTerrain( maklandPath );
DtSelectionManager& selectionManager =
DtSelectionManager::instance( myAgentManager.de() );
selectionManager.signal_currentSelectionChanged.connect( boost::bind(
&DtExampleSymbolDriver::slot_currentSelectionChanged,
this, _1, _2, _3, _4 ) );
return true;
}
bool DtExampleSymbolDriver::onStop()
{
DtSelectionManager& selectionManager =
DtSelectionManager::instance( myAgentManager.de() );
selectionManager.signal_currentSelectionChanged.disconnect(
boost::bind( &DtExampleSymbolDriver::slot_currentSelectionChanged,
this, _1, _2, _3, _4 ) );
SymbolFacadeMap::iterator i = mySymbolFacades.begin();
SymbolFacadeMap::iterator e = mySymbolFacades.end();
for ( ; i != e; ++i )
{
delete i->second;
}
mySymbolFacades.clear();
return true;
}
bool DtExampleSymbolDriver::onTick()
{
return true;
}
DtSymbolFacade* DtExampleSymbolDriver::createSymbol(
{
DtElementID elementId = myAgentManager.createNewUniqueId();
DtSymbolFacade* symbol = new DtSymbolFacade( myAgentManager, elementId );
symbol->widgetLabelAgent().setColor( 0.8f, 0.8f, 0.8f, 1.0f );
symbol->widgetLabelAgent().setSize( 32, 32 );
mySymbolFacades.insert( std::make_pair(elementId,symbol) );
reportElementCreated( elementId, 0, DtSymbolFacade::elementType() );
positionSymbol( symbol, pos );
return symbol;
}
DtSymbolFacade* DtExampleSymbolDriver::findSymbol(
DtElementID symbolId )
{
SymbolFacadeMap::iterator itr = mySymbolFacades.find( symbolId );
if ( itr != mySymbolFacades.end() )
return itr->second;
return NULL;
}
DtExampleSymbolDriver::SymbolList
DtExampleSymbolDriver::selectedSymbols() const
{
return myCurrentlySelectedSymbols;
}
void DtExampleSymbolDriver::positionSymbol(
DtSymbolFacade* symbol, const DtVector& pos )
{
DtCoordinateConverter* coordConverter =
myAgentManager.de().sharedState().coordinateSystem().converter();
coordConverter->setupTopoFrame( pos );
DtVector position;
coordConverter->enuToCig_coordTrans( pos, position );
symbol->setPosition( position );
}
void DtExampleSymbolDriver::slot_currentSelectionChanged(
const DtSelectionManager::IdSet& selected,
const DtSelectionManager::IdSet& deselected,
DtSelectionManager::SelectionType newType,
DtSelectionManager::SelectionType oldType )
{
DtSelectionManager::IdSet::const_iterator i, e;
e = selected.end();
i = selected.begin();
for ( ; i != e; ++i )
{
SymbolFacadeMap::iterator itr = mySymbolFacades.find( *i );
if ( itr != mySymbolFacades.end() )
{
DtWidgetLabelAgent& label = itr->second->widgetLabelAgent();
label.setColor( 1.0f, 1.0f, 1.0f, 1.0f );
label.setSize( 36, 36 );
}
}
e = deselected.end();
i = deselected.begin();
for ( ; i != e; ++i )
{
SymbolFacadeMap::iterator itr = mySymbolFacades.find( *i );
if ( itr != mySymbolFacades.end() )
{
DtWidgetLabelAgent& label = itr->second->widgetLabelAgent();
label.setColor( 0.8f, 0.8f, 0.8f, 1.0f );
label.setSize( 32, 32 );
}
}
DtSelectionManager& selMgr =
DtSelectionManager::instance( myAgentManager.de() );
const DtSelectionManager::IdSet& curSel = selMgr.currentSelections();
DtSelectionManager::IdSet::const_iterator selItr = curSel.begin();
DtSelectionManager::IdSet::const_iterator selEnd = curSel.end();
myCurrentlySelectedSymbols.clear();
DtSymbolFacade* symbol;
for ( ; selItr != selEnd; ++selItr )
{
if ( symbol = findSymbol(*selItr) )
{
myCurrentlySelectedSymbols.insert( symbol );
}
}
}
void DtExampleSymbolDriver::slot_displayEngineAdded( const DtDeRecord& igRecord )
{
stop();
}
}
}
exampleSymbolFacade3.cxx
using namespace makVrv;
using namespace makVrv::exampleSymbolFacade3;
{
return true;
}
{
if ( igApp )
{
}
{
}
}
{
}
exampleSymbolFacade3.h
#pragma once
#ifdef _WIN32
# ifdef EXAMPLESYMBOLFACADE3_EXPORTS
# define DT_DLL_EXAMPLESYMBOLFACADE3 __declspec ( dllexport )
# else
# define DT_DLL_EXAMPLESYMBOLFACADE3 __declspec ( dllimport )
# endif
#else
# define DT_DLL_EXAMPLESYMBOLFACADE3
#endif
#define DT_DE_PLUGIN_EXPORT_MACRO DT_DLL_EXAMPLESYMBOLFACADE3