diff --git a/manifest.xml b/manifest.xml index c6cf22b..fdfc339 100644 --- a/manifest.xml +++ b/manifest.xml @@ -12,5 +12,6 @@ + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 921f563..c073992 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,7 +19,6 @@ rock_library(vizkit3d ${PROPERTY_BROWSER_RESOURCES} MOC Vizkit3DPlugin.cpp - PickHandler.cpp Vizkit3DWidget.cpp QVizkitMainWindow.cpp qtpropertybrowser/qteditorfactory.cpp @@ -44,7 +43,6 @@ rock_library(vizkit3d Vizkit3DPlugin.hpp Vizkit3DWidget.hpp QVizkitMainWindow.hpp - PickHandler.hpp ColorConversionHelper.hpp CoordinateFrame.hpp EnvPluginBase.hpp @@ -52,7 +50,8 @@ rock_library(vizkit3d ${HEADERS_EXTRA} LIBS ${Boost_THREAD_LIBRARY} ${Boost_SYSTEM_LIBRARY} DEPS_CMAKE OpenGL - DEPS_PKGCONFIG openscenegraph openscenegraph-osgQt ${DEPS_EXTRA}) + DEPS_PKGCONFIG openscenegraph openscenegraph-osgQt osgViz + PrimitivesFactory ManipulationClickHandler ${DEPS_EXTRA}) rock_library(vizkitwidgetloader MOC QVizkitWidgetLoader.cpp diff --git a/src/ConnexionPlugin.cpp b/src/ConnexionPlugin.cpp deleted file mode 100644 index c1b28b0..0000000 --- a/src/ConnexionPlugin.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "ConnexionPlugin.h" - -#include - -namespace vizkit3d{ - - -ConnexionPlugin::ConnexionPlugin(){ - //Different Values for this Plugin - scale[RX] = 5000.0; - scale[RY] = 5000.0; - scale[RZ] = 5000.0; - scale[TX] = 10.0; - scale[TY] = 10.0; - scale[TZ] = 10.0; - matrix.makeIdentity(); -} - -ConnexionPlugin::~ConnexionPlugin(){ -} - -bool ConnexionPlugin::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us){ - //Do Nothing, otherwise the screen would be resettet, but if needed in future here could be an addtional mouse handler registered - return false; -} - -bool ConnexionPlugin::init(osgGA::MatrixManipulator *manipulator){ - this->manipulator = manipulator; - if(!manipulator) - return false; - - if(!ConnexionHID::init()) return false; - - timer.setSingleShot(false); - timer.setInterval(20); - manipulator->setByMatrix(osg::Matrixd::identity()); - timer.start(); - connect(&timer,SIGNAL(timeout()), this, SLOT(handleMouse())); - return true; -} - -void ConnexionPlugin::handleMouse(){ - controldev::connexionValues motion; - - //Maybe in future the buttons could also be handelt, currently not used but already requested - controldev::connexionValues newValues; - - //Getting actual readings - getValue(motion, newValues); - - //Save processing power if mouse is not moved - if(motion.rx == 0.0 && motion.ry == 0.0 && motion.rz == 0.0 && motion.tx == 0.0 && motion.ty == 0.0 && motion.tz == 0.0) return; - - //Get current Camera matrix - osg::Matrixd m = manipulator->getMatrix(); - - //Create Quaternion from current Camera Orientation - osg::Quat q; - q.set(m); - Eigen::Quaterniond qu(q.w(),q.x(),q.y(),q.z()); - - //Create Quaternion from Rotation request - Eigen::Quaterniond q2 = - Eigen::AngleAxisd(motion.rx,Eigen::Vector3d::UnitX()) * - Eigen::AngleAxisd(motion.ry,Eigen::Vector3d::UnitY()) * - Eigen::AngleAxisd(-motion.rz,Eigen::Vector3d::UnitZ()); - - //Be sure that the rotation does not include an scake - qu.normalize(); - - //Create vector from Translation request - Eigen::Vector3d v(motion.tx,motion.ty,-motion.tz); - - //Rotation translation Request into current Camra frame - v = qu * v; - - //Apply Translation request to current Camera matrix - m *= osg::Matrix::translate(v[0],v[1],v[2]); - - //Apply Rotation Request to current Camera matrix (after translation!) - m = osg::Matrix::rotate(osg::Quat(q2.x(),q2.y(),q2.z(),q2.w())) * m; - - //Apply matrix to camera(-maipulator) - manipulator->setByMatrix(m); - - //LOG_DEBUG("Got called! %f,%f,%f, %f, %f, %f\n",v[0],v[1],v[2],rx,ry,rz); -} - -} diff --git a/src/ConnexionPlugin.h b/src/ConnexionPlugin.h deleted file mode 100644 index 6792427..0000000 --- a/src/ConnexionPlugin.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef _CONNEXIONPLUGIN_H_ -#define _CONNEXIONPLUGIN_H_ - -#include -#include -#include -#include - -namespace vizkit3d{ - - -class ConnexionPlugin : public QObject,public controldev::ConnexionHID, public osgGA::MatrixManipulator{ - Q_OBJECT -public: - - ConnexionPlugin(); - ~ConnexionPlugin(); - - /* Scan all devices in /dev/input/ to find the SpaceMouse. - * Returns the true if an SpaceMouse could be found. - */ - bool init(osgGA::MatrixManipulator *manipulator); - - /** - * Needed functions for osgGA::MatrixManipulator - */ - virtual osg::Matrixd getInverseMatrix() const { - return osg::Matrixd::inverse(matrix); - }; - - /** - * Needed functions for osgGA::MatrixManipulator - */ - virtual osg::Matrixd getMatrix() const { - return matrix; - } - - /** - * Needed functions for osgGA::MatrixManipulator - */ - virtual void setByInverseMatrix(const osg::Matrixd& matrix) { - this->matrix = osg::Matrixd::inverse(matrix); - }; - - /** - * Needed functions for osgGA::MatrixManipulator - */ - virtual void setByMatrix(const osg::Matrixd& matrix) { - this->matrix = matrix; - }; - - /** - * Needed functions for osgGA::MatrixManipulator - * Do Nothing, otherwise the screen would be resettet, but if needed in future here could be an addtional mouse handler registered - */ - virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us); - -protected: - osg::ref_ptr manipulator; - QTimer timer; - osg::Matrixd matrix; - -public slots: - /** - * In this method is the real handling for the mouse values - * this method need to called periodicly, this is normally done - * via an QT-Timer which is initialized in the init() function - */ - void handleMouse(); - -}; - -#endif - -}; diff --git a/src/NodeLink.cpp b/src/NodeLink.cpp index 2df7527..4485075 100644 --- a/src/NodeLink.cpp +++ b/src/NodeLink.cpp @@ -1,6 +1,9 @@ #include "NodeLink.hpp" +#include + #include +#include #include #include #include @@ -52,7 +55,7 @@ namespace vizkit ::osg::Node* NodeLink::create(::osg::Node *node1, ::osg::Node *node2, const ::osg::Vec4 &color) { assert(node1 && node2); - + osgviz::Object* object = new osgviz::NullClickObject(); //click events should not propagate through nodelinks ::osg::Geode* geode = new ::osg::Geode(); geode->setName(node2->getName()); ::osg::Geometry* geometry = new ::osg::Geometry(); @@ -89,6 +92,8 @@ namespace vizkit NodeCallback *callback = new NodeCallback(node1,node2); geode->setUpdateCallback(callback); - return (::osg::Node*)geode; + object->addChild(geode); + + return (::osg::Node*)object; } } diff --git a/src/PickHandler.cpp b/src/PickHandler.cpp deleted file mode 100644 index d3764c2..0000000 --- a/src/PickHandler.cpp +++ /dev/null @@ -1,344 +0,0 @@ -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "PickHandler.hpp" - -using namespace vizkit3d; - -PickHandler::PickHandler(): - _mx(0.0),_my(0.0), - _usePolytopeIntersector(false), - _useWindowCoordinates(false) {} - -PickHandler::~PickHandler() {} - -bool PickHandler::addFunction(int whatKey, functionType newFunction) -{ - if ( keyFuncMap.end() != keyFuncMap.find( whatKey )) - { - std::cout << "duplicate key '" << whatKey << "' ignored." << std::endl; - return false; - } - else - { - keyFuncMap[whatKey].keyFunction = newFunction; - return true; - } -} - -bool PickHandler::addFunction (int whatKey, keyStatusType keyPressStatus, functionType newFunction) -{ - if (keyPressStatus == KEY_DOWN) - { - return addFunction(whatKey,newFunction); - } - else - { - if ( keyUPFuncMap.end() != keyUPFuncMap.find( whatKey )) - { - std::cout << "duplicate key '" << whatKey << "' ignored." << std::endl; - return false; - } - else - { - keyUPFuncMap[whatKey].keyFunction = newFunction; - return true; - } - } // KEY_UP -} - -bool PickHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) -{ - osgViewer::View* viewer = dynamic_cast(&aa); - if (!viewer) return false; - - bool newKeyDownEvent = false; - - switch(ea.getEventType()) - { - case(osgGA::GUIEventAdapter::KEYDOWN): - { - if (ea.getKey()=='w') - { - this->wireFrameModeOn(viewer->getSceneData()); - } - else if (ea.getKey()=='n') - { - this->wireFrameModeOff(viewer->getSceneData()); - } - else - { - keyFunctionMap::iterator itr = keyFuncMap.find(ea.getKey()); - if (itr != keyFuncMap.end()) - { - if ( (*itr).second.keyState == KEY_UP ) - { - (*itr).second.keyState = KEY_DOWN; - newKeyDownEvent = true; - } - if (newKeyDownEvent) - { - (*itr).second.keyFunction(); - newKeyDownEvent = false; - } - return true; - } - } - return false; - } - case(osgGA::GUIEventAdapter::KEYUP): - { - if (ea.getKey()=='p') - { - _usePolytopeIntersector = !_usePolytopeIntersector; - if (_usePolytopeIntersector) - { - osg::notify(osg::NOTICE)<<"Using PolytopeIntersector"<getSceneData(); - if (!scene) return; - - osg::notify(osg::NOTICE)<getCamera()->getViewport(); - double mx = viewport->x() + (int)((double )viewport->width()*(ea.getXnormalized()*0.5+0.5)); - double my = viewport->y() + (int)((double )viewport->height()*(ea.getYnormalized()*0.5+0.5)); - - // half width, height. - double w = 5.0f; - double h = 5.0f; - picker = new osgUtil::PolytopeIntersector( osgUtil::Intersector::WINDOW, mx-w, my-h, mx+w, my+h ); - } else { - double mx = ea.getXnormalized(); - double my = ea.getYnormalized(); - double w = 0.05; - double h = 0.05; - picker = new osgUtil::PolytopeIntersector( osgUtil::Intersector::PROJECTION, mx-w, my-h, mx+w, my+h ); - } - osgUtil::IntersectionVisitor iv(picker); - - viewer->getCamera()->accept(iv); - - if (picker->containsIntersections()) - { - for(std::multiset::iterator it = picker->getIntersections().begin(); - it != picker->getIntersections().end(); it++) - { - const osgUtil::PolytopeIntersector::Intersection &intersection = *it; - - /* - osg::notify(osg::NOTICE)<<"Picked "<=1)?nodePath[nodePath.size()-1]:0; - - //osg::Matrixd l2w = osg::computeLocalToWorld( nodePath ); - //osg::Vec3 global = *intersection.matrix.get() * intersection.localIntersectionPoint; - osg::Vec3 global = intersection.localIntersectionPoint * *intersection.matrix.get(); - - QVector3D globalPoint( global.x(), global.y(), global.z()); - emit picked(globalPoint); - } - } - } - else - { - osgUtil::LineSegmentIntersector* picker; - if (!_useWindowCoordinates) - { - // use non dimensional coordinates - in projection/clip space - picker = new osgUtil::LineSegmentIntersector( osgUtil::Intersector::PROJECTION, ea.getXnormalized(),ea.getYnormalized() ); - } else { - // use window coordinates - // remap the mouse x,y into viewport coordinates. - osg::Viewport* viewport = viewer->getCamera()->getViewport(); - float mx = viewport->x() + (int)((float)viewport->width()*(ea.getXnormalized()*0.5f+0.5f)); - float my = viewport->y() + (int)((float)viewport->height()*(ea.getYnormalized()*0.5f+0.5f)); - picker = new osgUtil::LineSegmentIntersector( osgUtil::Intersector::WINDOW, mx, my ); - } - osgUtil::IntersectionVisitor iv(picker); - - viewer->getCamera()->accept(iv); - - if (picker->containsIntersections()) - { - osgUtil::LineSegmentIntersector::Intersection intersection = picker->getFirstIntersection(); - - osg::NodePath& nodePath = intersection.nodePath; - node = (nodePath.size()>=1)?nodePath[nodePath.size()-1]:0; - - // see if the object has a user object which is derived from pickcallback - PickedCallback *pc = dynamic_cast(node->getUserData()); - if( pc ) - pc->picked(); - - for(int i = nodePath.size()-1; i >= 0; i--) - { - osg::Node *node = nodePath[i]; - osg::Referenced *user_data = node->getUserData(); - if (!user_data) - continue; - PickedUserData *plugin_data = dynamic_cast(user_data); - if(!plugin_data) - continue; - - // Transform OSG viewport coordinates to QWidget coordinates (invert y axis) - float wy = (float)viewer->getCamera()->getViewport()->height() - _my; - float wx = _mx; - plugin_data->getPlugin()->click(wx, wy); - - osg::Vec3 global = intersection.localIntersectionPoint * *intersection.matrix.get(); - emit plugin_data->getPlugin()->picked(global.x(),global.y(),global.z()); - break; - } - // setTrackedNode(viewer, node); - } - } -} - -void PickHandler::setTrackedNode(osgViewer::View* viewer, osg::ref_ptr< osg::Node > node) -{ - osgGA::KeySwitchMatrixManipulator *keyswitchManipulator = - dynamic_cast(viewer->getCameraManipulator()); - - if( !keyswitchManipulator ) - return; - - osgGA::NodeTrackerManipulator *tracker = - dynamic_cast(keyswitchManipulator->getMatrixManipulatorWithIndex( 2 )); - if( tracker ) - { - tracker->setTrackerMode( osgGA::NodeTrackerManipulator::NODE_CENTER ); - tracker->setTrackNode( node ); - } -} - -void PickHandler::wireFrameModeOn(osg::Node *srcNode) -{ - //Quick sanity check , we need a node - if( srcNode == NULL ) - return; - - //Grab the state set of the node, this will a StateSet if one does not exist - osg::StateSet *state = srcNode->getOrCreateStateSet(); - - //We need to retrieve the Polygon mode of the state set, and create one if does not have one - osg::PolygonMode *polyModeObj; - - polyModeObj = dynamic_cast< osg::PolygonMode* >( state->getAttribute( osg::StateAttribute::POLYGONMODE )); - - if ( !polyModeObj ) - { - polyModeObj = new osg::PolygonMode; - state->setAttribute( polyModeObj ); - } - - //Now we can set the state to WIREFRAME - polyModeObj->setMode( osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE ); - -} - -void PickHandler::wireFrameModeOff(osg::Node *srcNode) -{ - //Quick sanity check , we need a node - if( srcNode == NULL ) - return; - - //Grab the state set of the node, this will a StateSet if one does not exist - osg::StateSet *state = srcNode->getOrCreateStateSet(); - - //We need to retrieve the Polygon mode of the state set, and create one if does not have one - osg::PolygonMode *polyModeObj; - - polyModeObj = dynamic_cast< osg::PolygonMode* >( state->getAttribute( osg::StateAttribute::POLYGONMODE )); - - if ( !polyModeObj ) - { - polyModeObj = new osg::PolygonMode; - state->setAttribute( polyModeObj ); - } - - //Now we can set the state to FILL - polyModeObj->setMode( osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::FILL ); -} - diff --git a/src/PickHandler.hpp b/src/PickHandler.hpp deleted file mode 100644 index 1835d1a..0000000 --- a/src/PickHandler.hpp +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef __VIZKIT_PICKHANDLER_HPP__ -#define __VIZKIT_PICKHANDLER_HPP__ - -#include -#include -#include -#include - -#include "Vizkit3DPlugin.hpp" - -namespace vizkit3d -{ -class PickedCallback : public osg::Referenced -{ - public: - virtual void picked() = 0; -}; - -class PickedUserData : public osg::Referenced -{ - public: - PickedUserData(VizPluginBase* plugin){ this->plugin = plugin; } - VizPluginBase* getPlugin() { return plugin; } - private: - VizPluginBase* plugin; -}; - -// class to handle events with a pick -class PickHandler : public QObject, public osgGA::GUIEventHandler -{ - Q_OBJECT - public: - typedef void (*functionType) (); - - enum keyStatusType - { - KEY_UP, KEY_DOWN - }; - - struct functionStatusType - { - functionStatusType() {keyState = KEY_UP; keyFunction = NULL;} - functionType keyFunction; - keyStatusType keyState; - }; - - - public: - PickHandler(); - ~PickHandler(); - - bool addFunction(int whatKey, functionType newFunction); - bool addFunction(int whatKey, keyStatusType keyPressStatus, functionType newFunction); - - bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa); - void pick(const osgGA::GUIEventAdapter& ea, osgViewer::View* viewer); - - signals: - void picked(const QVector3D& coord); - - protected: - void setTrackedNode(osgViewer::View* viewer, osg::ref_ptr< osg::Node > node); - - void wireFrameModeOn(osg::Node *srcNode); - void wireFrameModeOff(osg::Node *srcNode); - - float _mx,_my; - bool _usePolytopeIntersector; - bool _useWindowCoordinates; - - typedef std::map keyFunctionMap; - keyFunctionMap keyFuncMap; - keyFunctionMap keyUPFuncMap; -}; -} - -#endif diff --git a/src/QPropertyBrowserWidget.cpp b/src/QPropertyBrowserWidget.cpp index 7bfb176..3b739bc 100644 --- a/src/QPropertyBrowserWidget.cpp +++ b/src/QPropertyBrowserWidget.cpp @@ -199,24 +199,24 @@ void QPropertyBrowserWidget::removeProperties(QObject* obj) void QPropertyBrowserWidget::propertyChangedInGUI(QtProperty* property, const QVariant& val) { QHash::const_iterator i = propertyToObject.find(property); - if (i == propertyToObject.end()) return; - - //std::cout << "accessing from map: " << property->propertyName().toStdString() << " -> " << i.value() << std::endl; - + QtVariantProperty* prop = dynamic_cast(property); if(prop && prop->propertyType() == QtVariantPropertyManager::enumTypeId()) { // emulate string list by using enums QStringList list; - list << prop->attributeValue("enumNames").toStringList().at(val.toInt()); + const QStringList names = prop->attributeValue("enumNames").toStringList(); + if(names.size() > 0) + { + list << names.at(val.toInt()); + } i.value()->setProperty(property->propertyName().toStdString().c_str(), QVariant(list)); } else - { i.value()->setProperty(property->propertyName().toStdString().c_str(), val); - } + } /** diff --git a/src/QVizkitMainWindow.hpp b/src/QVizkitMainWindow.hpp index c3e258f..bc626b5 100644 --- a/src/QVizkitMainWindow.hpp +++ b/src/QVizkitMainWindow.hpp @@ -1,7 +1,11 @@ #ifndef QVIZKITMAINWINDOW_H #define QVIZKITMAINWINDOW_H -#include "Vizkit3DPlugin.hpp" -#include "Vizkit3DWidget.hpp" + +#ifndef Q_MOC_RUN + #include "Vizkit3DPlugin.hpp" + #include "Vizkit3DWidget.hpp" +#endif + #include #include diff --git a/src/TransformerGraph.cpp b/src/TransformerGraph.cpp index c215629..0cbb2d0 100644 --- a/src/TransformerGraph.cpp +++ b/src/TransformerGraph.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -37,7 +38,8 @@ osg::PositionAttitudeTransform *getTransform(osg::Node *node,bool raise=true) osg::PositionAttitudeTransform *createFrame(const std::string &name,bool root=false,float textSize=0.1) { - osg::PositionAttitudeTransform* node = new osg::PositionAttitudeTransform(); +// osg::PositionAttitudeTransform* node = new osg::PositionAttitudeTransform(); + osgviz::Object* node = new osgviz::Object(); node->setName(name.c_str()); // always add a group as first child which will used to hold custom nodes @@ -381,6 +383,31 @@ osg::Node *TransformerGraph::getFrame(osg::Node &transformer,osg::Node *node) return FindFrame::find(transformer,node); } +osgviz::Object *TransformerGraph::getFrameOsgVizObject(osg::Node &transformer,const std::string &frame) +{ + osg::Node *frameNode = TransformerGraph::getFrame(transformer, frame); + if(frameNode == NULL) + { + std::cerr << "Unknown frame: " << frame << std::endl; + return NULL; + } + + osg::PositionAttitudeTransform *transform = NULL; + try + { + transform = getTransform(frameNode); + } + catch(const std::runtime_error& ex) + { + std::cerr << ex.what() << std::endl; + return NULL; + } + + osgviz::Object *obj = dynamic_cast(transform); + if(obj == NULL) + std::cerr << "Frame is not an osgViz object" << std::endl; + return obj; +} osg::Group *TransformerGraph::getFrameGroup(osg::Node &transformer,const std::string &frame) { @@ -617,3 +644,11 @@ void TransformerGraph::detachNode(osg::Node &transformer,osg::Node &node) NodeRemover::remove(transformer,&node); } +void TransformerGraph::setWorldName(osg::Node &transformer, const std::string &name) +{ + transformer.setName(name); + osgText::Text* text = getFrameText(&transformer); + text->setText(name); +} + + diff --git a/src/TransformerGraph.hpp b/src/TransformerGraph.hpp index d7e67ac..3210192 100644 --- a/src/TransformerGraph.hpp +++ b/src/TransformerGraph.hpp @@ -8,6 +8,11 @@ #include #include +namespace osgviz +{ + class Object; +} + namespace vizkit3d { /** @@ -33,6 +38,8 @@ namespace vizkit3d * Returns the name of the wold (root) frame. */ static std::string getWorldName(const osg::Node &transformer); + + static void setWorldName(osg::Node &transformer, const std::string &name); /** * Sets the size of the frame annotations @@ -85,6 +92,17 @@ namespace vizkit3d * @param node The node */ static osg::Group *getFrameGroup(osg::Node &transformer,const std::string &frame=""); + + /** + * Returns the osgviz object for the given frame. Use this node if you + * want to attach event handlers etc. + * If no name is given it will return the top level osg viz object. + * + * Returns NULL and prints error message to stderr in case of error. + * + * @param transformer the osg node of the transformer graph + * @param frame Name of the frame*/ + static osgviz::Object *getFrameOsgVizObject(osg::Node &transformer,const std::string &frame=""); /** * Returns the name of the osg frame node for the given custom node. Returns an empty string if the given node diff --git a/src/Vizkit3DPlugin.cpp b/src/Vizkit3DPlugin.cpp index 94c1f7e..da1fb0d 100644 --- a/src/Vizkit3DPlugin.cpp +++ b/src/Vizkit3DPlugin.cpp @@ -1,13 +1,48 @@ #include #include #include +#include +#include +#include #include "Vizkit3DPlugin.hpp" #include "Vizkit3DWidget.hpp" -#include "PickHandler.hpp" -using namespace vizkit3d; +namespace vizkit3d{ + class ClickHandler : public osgviz::Clickable + { + VizPluginBase& plugin; + public: + ClickHandler(VizPluginBase& plugin) : plugin(plugin), enabled(true){}; + + virtual bool clicked(const int &buttonMask, const osg::Vec2d &cursor, + const osg::Vec3d &world, const osg::Vec3d &local, + Clickable* object, const int modifierMask, + osgviz::WindowInterface* window = NULL) + { + if (enabled){ + plugin.click((float)cursor.x(), (float)cursor.y(), buttonMask, modifierMask); + plugin.pick((float)world.x(), (float)world.y(), (float)world.z(), buttonMask, modifierMask); + return true; + } + return false; + } + + bool isEnabled(){ + return enabled; + } + + void enable(bool val = true){ + enabled = val; + } + + private: + bool enabled; + + }; +} +using namespace vizkit3d; /** this adapter is used to forward the update call to the plugin */ class VizPluginBase::CallbackAdapter : public osg::NodeCallback @@ -26,17 +61,15 @@ VizPluginBase::VizPluginBase(QObject *parent) : QObject(parent), oldNodes(NULL), isAttached(false), dirty( false ), plugin_enabled(true), keep_old_data(false),max_old_data(100) { - rootNode = new osg::Group(); + rootNode = new osgviz::Object(); + click_handler = std::shared_ptr(new ClickHandler(*this)); + rootNode->addClickableCallback(click_handler); nodeCallback = new CallbackAdapter(this); rootNode->setUpdateCallback(nodeCallback); vizNode = new osg::PositionAttitudeTransform(); rootNode->addChild(vizNode); oldNodes = new osg::Group(); rootNode->addChild(oldNodes); - - // reference counter we do not have to delete the data - // add picker callback - vizNode->setUserData(new PickedUserData(this)); } VizPluginBase::~VizPluginBase() @@ -67,7 +100,7 @@ osg::ref_ptr VizPluginBase::getRootNode() const return rootNode; } -void VizPluginBase::click(float x,float y) +void VizPluginBase::click(float x,float y, int buttonMask, int modifierMask) { QWidget *osg_widget = dynamic_cast(parent()); // widget displaying the osg scene. @@ -86,6 +119,7 @@ void VizPluginBase::click(float x,float y) QPoint container_coords = osg_widget->mapTo(container, QPoint(x,y)); //std::cout << "grandparent coords: (" << container_coords.x() << "," << container_coords.y() << ")" << std::endl; emit clicked(container_coords.x(), container_coords.y()); + emit clicked(container_coords.x(), container_coords.y(), buttonMask, modifierMask); break; } else @@ -94,9 +128,25 @@ void VizPluginBase::click(float x,float y) container = container->parentWidget(); } } +} +void VizPluginBase::pick(float x, float y, float z, int buttonMask, int modifierMask) +{ + emit picked(x, y, z); + emit picked(x, y, z, buttonMask, modifierMask); + + for(std::function f : pickCallbacks) + { + f(x, y, z); + } +} + +void VizPluginBase::addPickHandler(std::function f) +{ + pickCallbacks.push_back(f); } + void VizPluginBase::setPose(const QVector3D &position, const QQuaternion &orientation) { boost::mutex::scoped_lock lock(updateMutex); @@ -148,7 +198,7 @@ void VizPluginBase::updateCallback(osg::Node* node) { mainNode = createMainNode(); vizNode->addChild(mainNode); - isAttached = true; + isAttached = true; } if(isDirty()) @@ -157,7 +207,7 @@ void VizPluginBase::updateCallback(osg::Node* node) vizNode->setPosition(osg::Vec3d(position.x(), position.y(), position.z())); vizNode->setAttitude(osg::Quat(orientation.x(), orientation.y(), orientation.z(), orientation.scalar())); - updateMainNode(mainNode); + updateMainNode(mainNode); if(keep_old_data) { oldNodes->addChild(cloneCurrentViz()); @@ -165,11 +215,11 @@ void VizPluginBase::updateCallback(osg::Node* node) oldNodes->removeChild(0,oldNodes->getNumChildren() -max_old_data); } if(!isAttached) - { - vizNode->addChild(mainNode); - isAttached = true; - } - dirty = false; + { + vizNode->addChild(mainNode); + isAttached = true; + } + dirty = false; } } @@ -262,7 +312,7 @@ void VizPluginBase::setVisualizationFrameFromList(const QStringList &frames) if (frames.empty()) return; if (!getWidget()) - return; + return; getWidget()->setPluginDataFrameIntern(frames.front(),this); current_frame = frames.front(); } @@ -275,3 +325,12 @@ void VizPluginBase::setVisualizationFrame(const QString &frame) current_frame = frame; emit propertyChanged("frame"); } + +bool VizPluginBase::getEvaluatesClicks() const{ + return click_handler->isEnabled(); +} + +void VizPluginBase::setEvaluatesClicks (const bool &value){ + click_handler->enable(value); +} + diff --git a/src/Vizkit3DPlugin.hpp b/src/Vizkit3DPlugin.hpp index 839e541..54dc74c 100644 --- a/src/Vizkit3DPlugin.hpp +++ b/src/Vizkit3DPlugin.hpp @@ -9,9 +9,18 @@ #include #include +#include +#include + +namespace osgviz +{ + class Object; +} namespace vizkit3d { +class ClickHandler; + /** * Interface class for all ruby adapters of the visualization plugins * Ruby adapters are usefull to get incoming data via ruby. @@ -109,16 +118,17 @@ class Vizkit3DWidget; */ class VizPluginBase : public QObject { - friend class PickHandler; Q_OBJECT Q_PROPERTY(QString vizkit3d_plugin_name READ getPluginName) Q_PROPERTY(bool enabled READ isPluginEnabled WRITE setPluginEnabled) Q_PROPERTY(bool KeepOldData READ isKeepOldDataEnabled WRITE setKeepOldData) + Q_PROPERTY(bool evaluatesClicks READ getEvaluatesClicks WRITE setEvaluatesClicks) Q_PROPERTY(int MaxOldData READ getMaxOldData WRITE setMaxOldData) Q_PROPERTY(QStringList frame READ getVisualizationFrames WRITE setVisualizationFrameFromList) Q_PROPERTY(double scale READ getScale WRITE setScale) + public: VizPluginBase(QObject *parent=NULL); virtual ~VizPluginBase(); @@ -128,21 +138,22 @@ class VizPluginBase : public QObject * May be NULL if the plugin is e.g. built as a child of another plugin */ Vizkit3DWidget* getWidget() const; + + /** @return true if the plugins internal state has been updated */ + virtual bool isDirty() const; + /** mark the internal state as modified */ + void setDirty(); - /** @return true if the plugins internal state has been updated */ - virtual bool isDirty() const; - /** mark the internal state as modified */ - void setDirty(); - - /** @return a pointer to the internal Group that is used to maintain the - * plugin's nodes */ - osg::ref_ptr getVizNode() const; - osg::ref_ptr getRootNode() const; + /** @return a pointer to the internal Group that is used to maintain the + * plugin's nodes */ + osg::ref_ptr getVizNode() const; + osg::ref_ptr getRootNode() const; /** * @return a vector of QDockWidgets provided by this class. */ std::vector getDockWidgets(); + void addPickHandler(std::function f); public slots: /** @@ -155,14 +166,17 @@ class VizPluginBase : public QObject */ virtual void setPluginEnabled(bool enabled); - /** @return the name of the plugin */ - virtual const QString getPluginName() const; + /** @return the name of the plugin */ + virtual const QString getPluginName() const; virtual void setPluginName(const QString &name); /** * Emits signal 'clicked(float, float)' if the plugin has a Vizkit3DWidget as an ancestor. */ - virtual void click(float x,float y); + virtual void click(float x,float y, int buttonMask, int modifierMask); + + /**Emits signal picked() */ + virtual void pick(float x, float y, float z, int buttonMask, int modifierMask); /** * @return an instance of the ruby adapter collection. @@ -176,11 +190,11 @@ class VizPluginBase : public QObject void setKeepOldData(bool value); bool isKeepOldDataEnabled(); - /** - * Clears the visualization of the plugin - * */ - virtual void clearVisualization(); - + /** + * Clears the visualization of the plugin + * */ + virtual void clearVisualization(); + /** * deletes all copies of the osg graph which were genereted by keepCurrentViz */ @@ -189,7 +203,7 @@ class VizPluginBase : public QObject int getMaxOldData()const {return max_old_data;}; void setMaxOldData(int value); - void setPose(const QVector3D &position, const QQuaternion &orientation); + void setPose(const QVector3D &position, const QQuaternion &orientation); /** Returns the list of available visualization frames * @@ -219,6 +233,17 @@ class VizPluginBase : public QObject */ void setScale(double scale); + /** + * @return whether click events should be evaluated by this plugin or not + */ + bool getEvaluatesClicks() const; + + /** + * enable or disable click evaluation by this plugin + * @param value + */ + void setEvaluatesClicks (const bool &value); + signals: /** * must be emitted if a property of an inherited plugin changes @@ -240,22 +265,27 @@ class VizPluginBase : public QObject * That is the container widget of the OSG viewer and the property browser. */ void clicked(float x, float y); + void clicked(float x, float y, int buttonMask, int modifierMask); /** * Signals when this plugin has been clicked. x,y,z are in world coordinates. */ void picked(float x, float y,float z); + /** @param buttonMask Mouse button that has been pressed + * @param modifierMask Modifier key(s) that have been pressed + */ + void picked(float x, float y,float z, int buttonMask, int modifierMask); protected: - /** override this function to update the visualisation. - * @param node contains a point to the node which can be modified. - */ - virtual void updateMainNode(osg::Node* node) = 0; + /** override this function to update the visualisation. + * @param node contains a point to the node which can be modified. + */ + virtual void updateMainNode(osg::Node* node) = 0; - /** override this method to provide your own main node. - * @return node derived from osg::Group - */ - virtual osg::ref_ptr createMainNode(); + /** override this method to provide your own main node. + * @return node derived from osg::Group + */ + virtual osg::ref_ptr createMainNode(); /** override this method to provide your own QDockWidgets. * The QDockWidgets will automatically attached to the main window. @@ -267,22 +297,24 @@ class VizPluginBase : public QObject */ virtual osg::ref_ptr cloneCurrentViz(); - /** lock this mutex outside updateMainNode if you update the internal - * state of the visualization. - */ - boost::mutex updateMutex; + /** lock this mutex outside updateMainNode if you update the internal + * state of the visualization. + */ + boost::mutex updateMutex; std::vector dockWidgets; QString vizkit3d_plugin_name; VizPluginRubyAdapterCollection adapterCollection; private: - class CallbackAdapter; - osg::ref_ptr nodeCallback; - void updateCallback(osg::Node* node); + std::vector> pickCallbacks; + + class CallbackAdapter; + osg::ref_ptr nodeCallback; + void updateCallback(osg::Node* node); osg::ref_ptr mainNode; //node which is used by the child class - osg::ref_ptr rootNode; //node which is the osg root node of the pluign + osg::ref_ptr rootNode; //node which is the osg root node of the pluign osg::ref_ptr vizNode; //node which describes the transformation between rootNode and mainNode osg::ref_ptr oldNodes; //node which is the root node for all old visualization graphs of the plugin @@ -292,10 +324,11 @@ class VizPluginBase : public QObject //orientation of the viznode QQuaternion orientation; - bool isAttached; - bool dirty; + bool isAttached; + bool dirty; bool plugin_enabled; bool keep_old_data; + std::shared_ptr click_handler; unsigned int max_old_data; QString current_frame; }; @@ -328,11 +361,11 @@ class VizPluginAddType virtual ~VizPluginAddType() {} protected: - /** overide this method and set your internal state such that the next - * call to updateMainNode will reflect that update. - * @param data data to be updated - */ - virtual void updateDataIntern(const T &data) = 0; + /** overide this method and set your internal state such that the next + * call to updateMainNode will reflect that update. + * @param data data to be updated + */ + virtual void updateDataIntern(const T &data) = 0; }; /** @@ -350,21 +383,21 @@ class Vizkit3DPlugin : public VizPluginBase, virtual ~Vizkit3DPlugin() {} - /** updates the data to be visualised and marks the visualisation dirty - * @param data const ref to data that is visualised - */ + /** updates the data to be visualised and marks the visualisation dirty + * @param data const ref to data that is visualised + */ template - void updateData(const Type &data) { - boost::mutex::scoped_lock lockit(this->updateMutex); - this->setDirty(); - VizPluginAddType *type = dynamic_cast*>(this); - if(type) - type->updateDataIntern(data); - else - { - throw std::runtime_error("Wrong type given to visualizer"); - } - }; + void updateData(const Type &data) { + boost::mutex::scoped_lock lockit(this->updateMutex); + this->setDirty(); + VizPluginAddType *type = dynamic_cast*>(this); + if(type) + type->updateDataIntern(data); + else + { + throw std::runtime_error("Wrong type given to visualizer"); + } + }; }; /** @@ -409,8 +442,8 @@ class VizkitPluginFactory : public QObject void* ptr = data.value();\ dataType* pluginData = reinterpret_cast(ptr);\ vizPlugin->methodName(*pluginData);\ - if (pass_ownership) \ - delete pluginData; \ + if (pass_ownership) \ + delete pluginData; \ }\ public slots:\ QString getDataType() \ @@ -477,32 +510,32 @@ template class VizPluginAdapter : public Vizkit3DPlugin { protected: - virtual void operatorIntern( osg::Node* node, osg::NodeVisitor* nv ) = 0; + virtual void operatorIntern( osg::Node* node, osg::NodeVisitor* nv ) = 0; VizPluginAdapter() - : groupNode(new osg::Group()) + : groupNode(new osg::Group()) { } - osg::ref_ptr createMainNode() - { - return groupNode; - } + osg::ref_ptr createMainNode() + { + return groupNode; + } - void updateMainNode( osg::Node* node ) - { - // NULL for nodevisitor is ok here, since its not used anywhere - operatorIntern( node, NULL ); - } + void updateMainNode( osg::Node* node ) + { + // NULL for nodevisitor is ok here, since its not used anywhere + operatorIntern( node, NULL ); + } - void setMainNode( osg::Node* node ) - { - groupNode->addChild( node ); - } + void setMainNode( osg::Node* node ) + { + groupNode->addChild( node ); + } protected: - osg::ref_ptr groupNode; - osg::ref_ptr ownNode; + osg::ref_ptr groupNode; + osg::ref_ptr ownNode; }; } diff --git a/src/Vizkit3DWidget.cpp b/src/Vizkit3DWidget.cpp index d96caca..35af2fc 100644 --- a/src/Vizkit3DWidget.cpp +++ b/src/Vizkit3DWidget.cpp @@ -1,5 +1,3 @@ -#include -#include #include #include #include @@ -13,12 +11,12 @@ #include "Vizkit3DBase.hpp" #include "Vizkit3DWidget.hpp" #include "Vizkit3DPlugin.hpp" -#include "PickHandler.hpp" #include "QPropertyBrowserWidget.hpp" #include "AxesNode.hpp" #include "OsgVisitors.hpp" #include "TransformerGraph.hpp" #include "EnableGLDebugOperation.hpp" +#include #include #include @@ -27,6 +25,7 @@ #include #include +#include #include #include #include @@ -203,52 +202,86 @@ void Vizkit3DConfig::setCameraManipulator(QStringList const& manipulator) return getWidget()->setCameraManipulator(id); } -Vizkit3DWidget::Vizkit3DWidget( QWidget* parent,const QString &world_name,bool auto_update) - : QWidget(parent) - , env_plugin(NULL) +Vizkit3DWidget::Vizkit3DWidget(QWidget* parent,const QString &world_name,bool auto_update) + : QMainWindow(parent) + , env_plugin(NULL), clickHandler(new osgviz::ManipulationClickHandler), + movedHandler(*this), movingHandler(*this), selectedHandler(*this) { - //create layout - //objects will be owned by the parent widget (this) - QVBoxLayout* layout = new QVBoxLayout; - layout->setObjectName("main_layout"); - layout->setContentsMargins(2,2,2,2); - QSplitter* splitter = new QSplitter(Qt::Horizontal); - splitter->setObjectName("splitter"); + setEnabledManipulators(false); + clickHandler->objectMoved.connect(movedHandler); + clickHandler->objectMoving.connect(movingHandler); + selectedObjectConnection = clickHandler->objectSelected.connect(selectedHandler); + //currently only this is supported + current_manipulator = TERRAIN_MANIPULATOR; + + + last_manipulator = vizkit3d::DEFAULT_MANIPULATOR; + + graphicsWindowQt = createGraphicsWindow(0,0,800,600); + graphicsWindowQtgc = dynamic_cast(graphicsWindowQt.get()); + + + osgviz = osgviz::OsgViz::getInstance(); + + + osgviz::WindowConfig windowConfig; + windowConfig.width = 800; + windowConfig.height = 600; + windowConfig.title = "rock-display"; + + + int osgvizWindowID = osgviz->createWindow(windowConfig,graphicsWindowQtgc); + window = osgviz->getWindowManager()->getWindowByID(osgvizWindowID); - layout->addWidget(splitter); - this->setLayout(layout); // set threading model - setThreadingModel(osgViewer::CompositeViewer::SingleThreaded); + window->setThreadingModel(osgViewer::CompositeViewer::SingleThreaded); if (getenv("VIZKIT_GL_DEBUG") && (std::string(getenv("VIZKIT_GL_DEBUG")) == "1")) { osg::setNotifyLevel(osg::DEBUG_INFO); - setRealizeOperation(new EnableGLDebugOperation()); + window->setRealizeOperation(new EnableGLDebugOperation()); } // disable the default setting of viewer.done() by pressing Escape. - setKeyEventSetsDone(0); + window->setKeyEventSetsDone(0); // create root scene node root = createSceneGraph(world_name); + window->addChild(root); // create osg widget - QWidget* widget = addViewWidget(createGraphicsWindow(0,0,800,600), root); + QWidget* widget = graphicsWindowQt->getGLWidget(); widget->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); widget->setObjectName(QString("View Widget")); - splitter->addWidget(widget); + + setCentralWidget(widget); + // create propertyBrowserWidget - QPropertyBrowserWidget *propertyBrowserWidget = new QPropertyBrowserWidget( parent ); + propertyBrowserWidget = new QPropertyBrowserWidget( parent ); propertyBrowserWidget->setObjectName("PropertyBrowser"); propertyBrowserWidget->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); propertyBrowserWidget->resize(200,600); - splitter->addWidget(propertyBrowserWidget); + + propertyDocker = new QDockWidget("Properties"); + //prop browser should be closed + propertyDocker->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); + propertyDocker->setWidget(propertyBrowserWidget); + addDockWidget(Qt::RightDockWidgetArea, propertyDocker); + // add config object to the property browser Vizkit3DConfig *config = new Vizkit3DConfig(this); addProperties(config,NULL); + //setup camera + osg::Camera* camera = window->getView()->getCamera(); + camera->setClearColor(::osg::Vec4(0.2, 0.2, 0.6, 1.0) ); + //camera->setViewport( new ::osg::Viewport(0, 0, traits->width, traits->height) ); + //camera->setProjectionMatrixAsPerspective(30.0f, static_cast(traits->width)/static_cast(traits->height), 1.0f, 10000.0f ); + camera->setCullMask(~INVISIBLE_NODE_MASK); + camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); + //connect signals and slots connect(this, SIGNAL(addPlugins(QObject*,QObject*)), this, SLOT(addPluginIntern(QObject*,QObject*))); connect(this, SIGNAL(removePlugins(QObject*)), this, SLOT(removePluginIntern(QObject*))); @@ -261,7 +294,9 @@ Vizkit3DWidget::Vizkit3DWidget( QWidget* parent,const QString &world_name,bool a _timer.start(10); } -Vizkit3DWidget::~Vizkit3DWidget() {} +Vizkit3DWidget::~Vizkit3DWidget() { + osgviz->destroyWindow(0); +} //qt ruby is crashing if we use none pointer here QStringList* Vizkit3DWidget::getVisualizationFramesRuby() const @@ -329,7 +364,7 @@ void Vizkit3DWidget::disableGrabbing() captureHandler = NULL; } -QImage Vizkit3DWidget::grab() +QImage Vizkit3DWidget::grab(unsigned int viewIndex) { if (!captureHandler) { @@ -337,35 +372,11 @@ QImage Vizkit3DWidget::grab() return QImage(); } - dynamic_cast(*captureHandler).captureNextFrame(*this); - frame(); + dynamic_cast(*captureHandler).captureNextFrame(*window); + osgviz->update(); return static_cast(*captureOperation).image; }; -QWidget* Vizkit3DWidget::addViewWidget( osgQt::GraphicsWindowQt* gw, ::osg::Node* scene ) -{ - osgViewer::View* view = new osgViewer::View; - addView(view); - - ::osg::Camera* camera = view->getCamera(); - camera->setGraphicsContext( gw ); - - const ::osg::GraphicsContext::Traits* traits = gw->getTraits(); - - camera->setClearColor(::osg::Vec4(0.2, 0.2, 0.6, 1.0) ); - camera->setViewport( new ::osg::Viewport(0, 0, traits->width, traits->height) ); - camera->setProjectionMatrixAsPerspective(30.0f, static_cast(traits->width)/static_cast(traits->height), 1.0f, 10000.0f ); - camera->setCullMask(~INVISIBLE_NODE_MASK); - - view->setSceneData(scene); - view->addEventHandler( new osgViewer::StatsHandler ); - setCameraManipulator(TERRAIN_MANIPULATOR); - - // pickhandler is for selecting objects in the opengl view - PickHandler* pickHandler = new PickHandler(); - view->addEventHandler(pickHandler); - return gw->getGLWidget(); -} osgQt::GraphicsWindowQt* Vizkit3DWidget::createGraphicsWindow( int x, int y, int w, int h, const std::string& name, bool windowDecoration) { @@ -385,9 +396,10 @@ osgQt::GraphicsWindowQt* Vizkit3DWidget::createGraphicsWindow( int x, int y, int return new osgQt::GraphicsWindowQt(traits.get()); } -void Vizkit3DWidget::paintEvent( QPaintEvent* event ) +void Vizkit3DWidget::update() { - frame(); + QWidget::update(); + osgviz->update(); } QSize Vizkit3DWidget::sizeHint() const @@ -400,14 +412,14 @@ osg::Group* Vizkit3DWidget::getRootNode() const return root; } -void Vizkit3DWidget::setTrackedNode( VizPluginBase* plugin ) +void Vizkit3DWidget::setTrackedNode(VizPluginBase* plugin) { - return setTrackedNode(plugin->getRootNode(), QString("").arg(plugin->getPluginName())); + return setTrackedNode(plugin->getRootNode(), QString("").arg(plugin->getPluginName())); } -void Vizkit3DWidget::setTrackedNode( osg::Node* node, QString tracked_object_name ) +void Vizkit3DWidget::setTrackedNode(osg::Node* node,const QString& tracked_object_name) { - osgViewer::View *view = getView(0); + osgViewer::View *view = window->getView(0); assert(view); osgGA::NodeTrackerManipulator* manipulator = new osgGA::NodeTrackerManipulator; @@ -484,6 +496,16 @@ void Vizkit3DWidget::registerDataHandler(VizPluginBase* viz) plugins.insert(make_pair(viz, VizPluginInfo(viz, initial_parent))); } +void Vizkit3DWidget::registerClickHandler(const string& frame) +{ + osgviz::Object* obj = TransformerGraph::getFrameOsgVizObject(*getRootNode(), frame); + if(obj == NULL) + throw std::runtime_error("Cannot register click handler"); + + if(!obj->hasClickableCallback(clickHandler)) + obj->addClickableCallback(clickHandler); +} + void Vizkit3DWidget::deregisterDataHandler(VizPluginBase* viz) { PluginMap::iterator it = plugins.find(viz); @@ -571,11 +593,10 @@ void Vizkit3DWidget::setEnvironmentPluginEnabled(bool enabled) if (!env_plugin) return; - osgViewer::View *view = getView(0); if (enabled) - view->setSceneData(env_plugin->getRootNode()); + osgviz->setScene(env_plugin->getRootNode()); else - view->setSceneData(root); + osgviz->setScene(root); emit propertyChanged("environment"); } @@ -583,7 +604,7 @@ bool Vizkit3DWidget::isEnvironmentPluginEnabled() const { if (!env_plugin) return false; - return getView(0)->getSceneData() != root; + return osgviz->getChild() != root; } void Vizkit3DWidget::clearEnvironmentPlugin() @@ -619,27 +640,18 @@ void Vizkit3DWidget::setCameraUp(double x, double y, double z) void Vizkit3DWidget::collapsePropertyBrowser() { - QSplitter *splitter = findChild("splitter"); - if(!splitter) - return; - QList sizes; - sizes.push_front(0); - splitter->setSizes(sizes); + removeDockWidget(propertyDocker); + propertyBrowserWidget->close(); } -void Vizkit3DWidget::setSmallFeatureCullingPixelSize(float val) -{ - osgViewer::View *view = getView(0); - assert(view); - view->getCamera()->setSmallFeatureCullingPixelSize(val); -} + void Vizkit3DWidget::getCameraView(QVector3D& lookAtPos, QVector3D& eyePos, QVector3D& upVector) { osg::Vec3d eye, lookAt, up; - osgViewer::View *view = getView(0); + osgViewer::View *view = window->getView(0); assert(view); view->getCamera()->getViewMatrixAsLookAt(eye, lookAt, up); @@ -656,7 +668,7 @@ void Vizkit3DWidget::getCameraView(QVector3D& lookAtPos, QVector3D& eyePos, QVec void Vizkit3DWidget::changeCameraView(const osg::Vec3* lookAtPos, const osg::Vec3* eyePos, const osg::Vec3* upVector) { - osgViewer::View *view = getView(0); + osgViewer::View *view = window->getView(0); assert(view); osgGA::CameraManipulator* manipulator = dynamic_cast(view->getCameraManipulator()); @@ -692,7 +704,7 @@ void Vizkit3DWidget::changeCameraView(const osg::Vec3* lookAtPos, const osg::Vec QColor Vizkit3DWidget::getBackgroundColor()const { - const osgViewer::View *view = getView(0); + const osgViewer::View *view = window->getView(); assert(view); osg::Vec4 color = view->getCamera()->getClearColor(); return QColor(color.r()*255,color.g()*255,color.b()*255,color.a()*255); @@ -700,7 +712,7 @@ QColor Vizkit3DWidget::getBackgroundColor()const void Vizkit3DWidget::setBackgroundColor(QColor color) { - osgViewer::View *view = getView(0); + osgViewer::View *view = window->getView(); assert(view); view->getCamera()->setClearColor(::osg::Vec4(color.red()/255.0,color.green()/255.0,color.blue()/255.0,1.0)); } @@ -759,6 +771,13 @@ void Vizkit3DWidget::addPluginIntern(QObject* plugin,QObject *parent) connect(viz_plugin, SIGNAL(pluginActivityChanged(bool)), this, SLOT(pluginActivityChanged(bool))); connect(viz_plugin, SIGNAL(childrenChanged()), this, SLOT(pluginChildrenChanged())); connect(viz_plugin, SIGNAL(destroyed(QObject*)), this, SLOT(removePluginIntern(QObject*))); + + const std::vector dockWidgets = viz_plugin->getDockWidgets(); + for(QDockWidget* dockWidget : dockWidgets) + { + dockWidget->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); + addDockWidget(Qt::BottomDockWidgetArea, dockWidget); + } } // add sub plugins if object has some @@ -788,12 +807,18 @@ void Vizkit3DWidget::removePluginIntern(QObject* plugin) propertyBrowserWidget->removeProperties(viz_plugin); disconnect(viz_plugin, SIGNAL(pluginActivityChanged(bool)), this, SLOT(pluginActivityChanged(bool))); disconnect(viz_plugin, SIGNAL(childrenChanged()), this, SLOT(pluginChildrenChanged())); + + const std::vector dockWidgets = viz_plugin->getDockWidgets(); + for(QDockWidget* dockWidget : dockWidgets) + { + removeDockWidget(dockWidget); + } } } QWidget* Vizkit3DWidget::getPropertyWidget() const { - return findChild("PropertyBrowser"); + return propertyBrowserWidget; } void Vizkit3DWidget::setPluginDataFrame(const QString& frame, QObject* plugin) @@ -822,6 +847,7 @@ void Vizkit3DWidget::setPluginDataFrameIntern(const QString& frame, QObject* plu throw std::runtime_error("setPluginDataFrame called with something that is not a vizkit3d plugin"); TransformerGraph::addFrame(*getRootNode(),frame.toStdString()); + registerClickHandler(frame.toStdString()); osg::Group* node = TransformerGraph::getFrameGroup(*getRootNode(),frame.toStdString()); assert(node); PluginMap::iterator it = plugins.find(viz); @@ -854,8 +880,6 @@ void Vizkit3DWidget::setVisualizationFrame(const QString& frame) return; } - osgViewer::View *view = getView(0); - assert(view); // the following is not working if the directly track the transformation // therefore use a child osg::Node *node = TransformerGraph::getFrameGroup(*getRootNode(),frame.toStdString()); @@ -881,8 +905,14 @@ void Vizkit3DWidget::setTransformation(const QString &source_frame,const QString osg::Quat(quat.x(),quat.y(),quat.z(),quat.scalar()), osg::Vec3d(position.x(),position.y(),position.z())); + //if a new frame was added if(count != getVisualizationFrames().size()) { + //there is no way to determine which frame was new + //checking for duplicate handlers will be done elsewhere + registerClickHandler(source_frame.toStdString()); + registerClickHandler(target_frame.toStdString()); + emit propertyChanged("frame"); // first: VizPluginBase* // second: osg::ref_ptr @@ -903,6 +933,13 @@ void Vizkit3DWidget::setTransformation(const QString &source_frame,const QString TransformerGraph::makeRoot(*getRootNode(), root_frame.toStdString()); } +void Vizkit3DWidget::removeFrame(const QString& frame) +{ + const bool worked = TransformerGraph::removeFrame(*getRootNode(), frame.toStdString()); + if(!worked) + std::cerr << "WARN: Unable to remove frame " << frame.toStdString() << std::endl; +} + void Vizkit3DWidget::setRootFrame(QString frame) { TransformerGraph::makeRoot(*getRootNode(), frame.toStdString()); @@ -1068,25 +1105,25 @@ QStringList* Vizkit3DWidget::getAvailablePlugins() return plugins_str_list; } -QObject* Vizkit3DWidget::loadPlugin(QString lib_name,QString plugin_name) +QObject* Vizkit3DWidget::createPlugin(QString lib_name, QString plugin_name) { //check if the plugin name is encoded into the lib_name QStringList plugin_strings = lib_name.split("@"); if(plugin_strings.size() == 2) { - lib_name = plugin_strings.at(0); - plugin_name = plugin_strings.at(1); + plugin_name = plugin_strings.at(0); + lib_name = plugin_strings.at(1); } //if no lib_name is given try to find it from plugin_name if(lib_name.isEmpty() && !plugin_name.isEmpty()) lib_name = findPluginPath(plugin_name); - + //check if the lib name is a path QFileInfo file_info(lib_name); QString path; if(file_info.isFile()) - path = file_info.absolutePath(); + path = file_info.absoluteFilePath(); else path = findLibPath(lib_name); @@ -1115,6 +1152,13 @@ QObject* Vizkit3DWidget::loadPlugin(QString lib_name,QString plugin_name) lib->getAvailablePlugins()->join(", ").toStdString() << std::endl; return NULL; } + return plugin; +} + + +QObject* Vizkit3DWidget::loadPlugin(QString lib_name, QString plugin_name) +{ + QObject* plugin = createPlugin(lib_name, plugin_name); addPlugin(plugin); return plugin; } @@ -1134,7 +1178,7 @@ CAMERA_MANIPULATORS Vizkit3DWidget::getCameraManipulator() const void Vizkit3DWidget::setCameraManipulator(osg::ref_ptr manipulator, bool resetToDefaultHome) { - osgViewer::View *view = getView(0); + osgViewer::View *view = window->getView(0); assert(view); osg::Vec3d @@ -1204,3 +1248,130 @@ void Vizkit3DWidget::setCameraManipulator(CAMERA_MANIPULATORS manipulatorType, b } } +void Vizkit3DWidget::ObjectMovedHandler::operator()(const osgviz::Object* obj, + const osg::Matrix& motion) +{ + const std::string frame = obj->getName(); + if(TransformerGraph::hasFrame(*widget.getRootNode(), frame)) + { + const osg::Vec3d trans = motion.getTrans(); + const osg::Quat rot = motion.getRotate(); + const QVector3D qTrans(trans.x(), trans.y(), trans.z()); + const QQuaternion qRot(rot.w(), rot.x(), rot.y(), rot.z()); + emit widget.frameMoved(QString::fromStdString(frame), qTrans, qRot); + } + else + { + std::cerr << "Dragged object is not a frame: " << frame << std::endl; + } +} + +void Vizkit3DWidget::ObjectMovingHandler::operator()(const osgviz::Object* obj, + const osg::Matrix& motion) +{ + const std::string frame = obj->getName(); + if(TransformerGraph::hasFrame(*widget.getRootNode(), frame)) + { + const osg::Vec3d trans = motion.getTrans(); + const osg::Quat rot = motion.getRotate(); + const QVector3D qTrans(trans.x(), trans.y(), trans.z()); + const QQuaternion qRot(rot.w(), rot.x(), rot.y(), rot.z()); + emit widget.frameMoving(QString::fromStdString(frame), qTrans, qRot); + } + else + { + std::cerr << "Dragged object is not a frame: " << frame << std::endl; + } +} + +void Vizkit3DWidget::ObjectSelectedHandler::operator()(const osgviz::Object* obj) +{ + const std::string frame = obj->getName(); + if(TransformerGraph::hasFrame(*widget.getRootNode(), frame)) + { + emit widget.frameSelected(QString::fromStdString(frame)); + } + else + { + std::cerr << "Selected object that is not a frame: " << frame << std::endl; + } +} + +bool Vizkit3DWidget::ObjectSelectedHandler::operator==(const Vizkit3DWidget::ObjectSelectedHandler& other) const +{ + //to disconnect slots we need to be able to identify them, therefore they + //need to be comparable + return this == &other; +} + + +void Vizkit3DWidget::selectFrame(const QString& frame, const bool suppressSignal) +{ + if(TransformerGraph::hasFrame(*getRootNode(), frame.toStdString())) + { + osgviz::Object* obj = TransformerGraph::getFrameOsgVizObject(*getRootNode(), + frame.toStdString()); + if(obj != NULL) + { + if(suppressSignal) + { + boost::signals2::shared_connection_block block(selectedObjectConnection); + clickHandler->selectObject(obj); + } + else + { + clickHandler->selectObject(obj); + } + } + else + std::cerr << "Cannot select frame: " << frame.toStdString() << std::endl; + } + else + { + std::cerr << frame.toStdString() << " doesn't exist!" << std::endl; + } +} + +void Vizkit3DWidget::clear() +{ + //remove plugins, is while loop because removing invalidates iterators + while(plugins.size() > 0) + { + removePlugin(plugins.begin()->first); + } + + //remove frames + const std::vector frames = TransformerGraph::getFrameNames(*getRootNode()); + for(unsigned i = 0; i < frames.size(); ++i) + { + //removeFrame internally skips the world frame + TransformerGraph::removeFrame(*getRootNode(), frames[i]); + } +} + +void Vizkit3DWidget::setWorldName(const QString& name) +{ + const QString oldWorldName = getWorldName(); + TransformerGraph::setWorldName(*getRootNode(), name.toStdString()); + PluginMap::iterator it = plugins.begin(); + + //find all plugins that use the old world name as visualization frame + //and update them. Otherwise the old world name might be re-added when + //setting transformations + for(;it != plugins.end();++it) + { + if(it->first->getVisualizationFrame() == oldWorldName) + { + it->first->setVisualizationFrame(name); + } + } +} + +void Vizkit3DWidget::setEnabledManipulators(const bool value) +{ + clickHandler->setEnabled(value); +} + + + + diff --git a/src/Vizkit3DWidget.hpp b/src/Vizkit3DWidget.hpp index af14f64..cb971fd 100644 --- a/src/Vizkit3DWidget.hpp +++ b/src/Vizkit3DWidget.hpp @@ -6,6 +6,16 @@ #include #include #include +#include +#include + +#ifndef Q_MOC_RUN + #include + #include + #include + #include +#endif + // disable tons of waringins in osg // this is only valid for the rest of this @@ -18,9 +28,12 @@ #include #include + +namespace osgviz { class ManipulationClickHandler;} namespace osgQt { class GraphicsWindowQt;} namespace vizkit3d { + class QPropertyBrowserWidget; class EnvPluginBase; class Vizkit3DWidget; @@ -186,7 +199,7 @@ namespace vizkit3d QStringList getAvailableCameraManipulators() const; }; - class QDESIGNER_WIDGET_EXPORT Vizkit3DWidget : public QWidget, public osgViewer::CompositeViewer + class QDESIGNER_WIDGET_EXPORT Vizkit3DWidget : public QMainWindow { Q_OBJECT public: @@ -211,7 +224,7 @@ namespace vizkit3d * to be reported in getCameraManipulatorName (and therefore in * the property browser view) */ - void setTrackedNode(osg::Node* node, QString tracked_object_name); + void setTrackedNode(osg::Node* node, const QString& tracked_object_name); /** @overload sets the camera to track this plugins's root position * * The tracked object name is @@ -229,6 +242,7 @@ namespace vizkit3d void setCameraManipulator(osg::ref_ptr manipulator, bool resetToDefaultHome = false); public slots: + void update(); void addPlugin(QObject* plugin, QObject* parent = NULL); void removePlugin(QObject* plugin); @@ -269,14 +283,21 @@ namespace vizkit3d const QVector3D &position, const QQuaternion &orientation); void getTransformation(const QString &source_frame,const QString &target_frame, QVector3D &position, QQuaternion &orientation)const; QString getWorldName()const; + void setWorldName(const QString& name); + + /**Removes @p frame from the visualization */ + void removeFrame(const QString& frame); + + /**Select @p frame. This is the same as if the user clicked the frame. + * @param suppressSignal If true the frameSelected signal will not be + * emitted.*/ + void selectFrame(const QString& frame, const bool suppressSignal); void setCameraLookAt(double x, double y, double z); void setCameraEye(double x, double y, double z); void setCameraUp(double x, double y, double z); void getCameraView(QVector3D& eye, QVector3D& lookAt, QVector3D& up); - void setSmallFeatureCullingPixelSize(float val); - QColor getBackgroundColor()const; void setBackgroundColor(QColor color); @@ -308,10 +329,13 @@ namespace vizkit3d * You must call enableGrabbing() first. Will return an empty image * if you did not do so. */ - QImage grab(); + QImage grab(unsigned int viewIndex = 0); QString findPluginPath(QString plugin_name); QString findLibPath(QString lib_name); + + /**Creates the specified plugin but dos **not** add it to this widget */ + QObject* createPlugin(QString lib_name,QString plugin_name); QObject* loadPlugin(QString lib_name,QString plugin_name); QStringList* getAvailablePlugins(); @@ -357,14 +381,36 @@ namespace vizkit3d * remove the plugin itself */ void clearEnvironmentPlugin(); + + /*Removes all plugins and all frames except the world frame.*/ + void clear(); + + /**If set to true rotation and translation manipulators will be shown + * when a frame is clicked. Default: false*/ + void setEnabledManipulators(const bool value); signals: void addPlugins(QObject* plugin,QObject* parent); void removePlugins(QObject* plugin); void propertyChanged(QString propertyName); - - protected: - virtual void paintEvent( QPaintEvent* event ); + + /** This signal is emitted when the user wants to move a frame. + * The actual moving of the frame has to be done by the handler + * of this event. + * @p translation the translation relative to @p frame. + * @p rotation the rotation relative to @p frame.*/ + void frameMoved(const QString& frame, const QVector3D& translation, + const QQuaternion& rotation); + + /** This signal is emitted while the user is dragging or rotating a + * frame. This event is intendet to update gui elements. Do + * **not** update transformations while handling this event.*/ + void frameMoving(const QString& frame, const QVector3D& translation, + const QQuaternion& rotation); + + /** This signal is emitted when the user selects a frame in the + * 3d view.*/ + void frameSelected(const QString frame); private slots: void setPluginDataFrameIntern(const QString &frame, QObject *plugin); @@ -373,8 +419,12 @@ namespace vizkit3d void pluginActivityChanged(bool enabled); void pluginChildrenChanged(); void addProperties(QObject* plugin,QObject *parent=NULL); - + private: + + /**Register the click handler to the given frame */ + void registerClickHandler(const std::string& frame); + // Helper method for setPluginEnabled void enableEnvironmentPlugin(); // Helper method for setPluginEnabled @@ -389,9 +439,13 @@ namespace vizkit3d void disableDataHandler(VizPluginBase *viz); osg::Group *createSceneGraph(const QString &world_name); - QWidget* addViewWidget( osgQt::GraphicsWindowQt* gw, ::osg::Node* scene ); osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name="", bool windowDecoration=false ); + + osgviz::OsgViz* osgviz; + osgviz::Window* window; + + private: //holds the scene osg::ref_ptr root; @@ -436,6 +490,47 @@ namespace vizkit3d osg::ref_ptr captureHandler; osg::ref_ptr captureOperation; + osg::ref_ptr graphicsWindowQt; + osg::ref_ptr graphicsWindowQtgc; + + std::shared_ptr clickHandler; + + //TODO replace with lambda once c++11 is used + struct ObjectMovedHandler + { + ObjectMovedHandler(Vizkit3DWidget& widget) : widget(widget){} + /** @param obj The object that has been moved. + * @param motionMatrix Motion of the object relative to the + * current object position. */ + void operator()(const osgviz::Object* obj, + const osg::Matrix& motionMatrix); + Vizkit3DWidget& widget;//the widget that this handler belongs to + }movedHandler; + + struct ObjectMovingHandler + { + ObjectMovingHandler(Vizkit3DWidget& widget) : widget(widget){} + void operator()(const osgviz::Object* obj, + const osg::Matrix& motionMatrix); + Vizkit3DWidget& widget;//the widget that this handler belongs to + }movingHandler; + + struct ObjectSelectedHandler + { + ObjectSelectedHandler(Vizkit3DWidget& widget) : widget(widget){} + void operator()(const osgviz::Object* obj); + /**Does address comparision */ + bool operator==(const ObjectSelectedHandler& other) const; + Vizkit3DWidget& widget;//the widget that this handler belongs to + }selectedHandler; + + /**Connection between selectedHandler and it's signal. + * Used to temporarly block the slot*/ + boost::signals2::connection selectedObjectConnection; + + QPropertyBrowserWidget* propertyBrowserWidget; + QDockWidget* propertyDocker; + }; } #endif