diff --git a/CMakeLists.txt b/CMakeLists.txt index 9cf2b11784299f00f84be061bd92347bb97fd01c..698385645ad3a54f3b951e2881699810696872f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,6 +90,7 @@ IF(NOT CLIENT_ONLY) ${CMAKE_SOURCE_DIR}/include/gepetto/gui/pick-handler.hh ${CMAKE_SOURCE_DIR}/include/gepetto/gui/shortcut-factory.hh ${CMAKE_SOURCE_DIR}/include/gepetto/gui/selection-handler.hh + ${CMAKE_SOURCE_DIR}/include/gepetto/gui/selection-event.hh ${CMAKE_SOURCE_DIR}/include/gepetto/gui/windows-manager.hh ) SET (${PROJECT_NAME}_HEADERS_NO_MOC diff --git a/include/gepetto/gui/bodytreewidget.hh b/include/gepetto/gui/bodytreewidget.hh index d6a7445621e11924353a11809ed06f0b4445c9b2..2c3dc6f22d0df7b4998fb6ad7369418048562476 100644 --- a/include/gepetto/gui/bodytreewidget.hh +++ b/include/gepetto/gui/bodytreewidget.hh @@ -59,6 +59,12 @@ namespace gepetto { return model_; } + /// Handle a selection event + /// + /// Does not re-emit a selection event when the body tree selection + /// is updated. + void handleSelectionEvent (const SelectionEvent* event); + public slots: /// \addtogroup available_in_python Python API /// \{ @@ -101,6 +107,9 @@ namespace gepetto { /// \param pos position of the item void customContextMenu (const QPoint& pos); + void currentChanged (const QModelIndex ¤t, + const QModelIndex &previous); + private: QTreeView* view_; QStandardItemModel* model_; diff --git a/include/gepetto/gui/fwd.hh b/include/gepetto/gui/fwd.hh index 6013b3abf2a8727a0a7aaf83ab265b0fabd438b7..2821edb6a7548ee6da713e55c26534bedf61ea18 100644 --- a/include/gepetto/gui/fwd.hh +++ b/include/gepetto/gui/fwd.hh @@ -13,6 +13,7 @@ namespace gepetto { class BodyTreeItem; class ShortcutFactory; class SelectionHandler; + class SelectionEvent; class ViewerCorbaServer; diff --git a/include/gepetto/gui/mainwindow.hh b/include/gepetto/gui/mainwindow.hh index b30b58a2b89ed3866561a8064b435c3497f59c21..4091fc7bd6b06cb63e53e20f73e1d39e1b112c55 100644 --- a/include/gepetto/gui/mainwindow.hh +++ b/include/gepetto/gui/mainwindow.hh @@ -62,6 +62,11 @@ namespace gepetto { /// Get WindowsManagerPtr_t osg () const; + SelectionHandler* selectionHandler() + { + return selectionHandler_; + } + /// Get the central widget. OSGWidget* centralWidget() const; diff --git a/include/gepetto/gui/osgwidget.hh b/include/gepetto/gui/osgwidget.hh index 6815254f969fbdf86ae9e196a361a916438cc4a8..83e750a08d861e6d6c6bc4af7f03514259711c7d 100644 --- a/include/gepetto/gui/osgwidget.hh +++ b/include/gepetto/gui/osgwidget.hh @@ -58,7 +58,7 @@ namespace gepetto { WindowsManager::WindowID windowID () const; signals: - void clicked (QString name, QVector3D positionInWorldFrame, QKeyEvent* event); + void clicked (SelectionEvent* event); public slots: /// Load an urdf file in the viewer. @@ -76,13 +76,13 @@ signals: void cameraManipulationMode (); void addFloor(); void attachToWindow (const std::string nodeName); + void emitClicked (SelectionEvent* event); protected: virtual void paintEvent( QPaintEvent* paintEvent ); private: - void emitClicked (QString name, QVector3D positionInWorldFrame, QKeyEvent* event); osgGA::EventQueue* getEventQueue() const; osg::ref_ptr<osgQt::GraphicsWindowQt> graphicsWindow_; diff --git a/include/gepetto/gui/pick-handler.hh b/include/gepetto/gui/pick-handler.hh index 5821a92d79e7070bf826257966d78164835ef6df..429f5635db0c19605a3bb741e3cb8c5ed03d2df0 100644 --- a/include/gepetto/gui/pick-handler.hh +++ b/include/gepetto/gui/pick-handler.hh @@ -24,14 +24,8 @@ namespace gepetto { virtual bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa ); - void select (graphics::NodePtr_t node); - void getUsage (osg::ApplicationUsage &usage); - private slots: - void bodyTreeCurrentChanged (const QModelIndex ¤t, - const QModelIndex &previous); - private: std::list <graphics::NodePtr_t> computeIntersection (osgGA::GUIActionAdapter& aa, const float& x, const float& y, @@ -42,7 +36,6 @@ namespace gepetto { QtOsgKeyboard mapper_; WindowsManagerPtr_t wsm_; OSGWidget* parent_; - graphics::NodePtr_t last_; bool pushed_; float lastX_, lastY_; }; diff --git a/include/gepetto/gui/qt-osg-keyboard.hh b/include/gepetto/gui/qt-osg-keyboard.hh index 29d5b99a17d364db24bbec4a073a972b16d8f5aa..73c6c323e0e900d2fcbafca9608f6bf6ff543935 100644 --- a/include/gepetto/gui/qt-osg-keyboard.hh +++ b/include/gepetto/gui/qt-osg-keyboard.hh @@ -72,7 +72,7 @@ namespace gepetto { mKeyMap[Qt::Key_Insert ] = osgGA::GUIEventAdapter::KEY_KP_Insert; //mKeyMap[Qt::Key_Delete ] = osgGA::GUIEventAdapter::KEY_KP_Delete; - modKeyMap[osgGA::GUIEventAdapter::MODKEY_CTRL ] = Qt::Key_Control; + modKeyMap[osgGA::GUIEventAdapter::MODKEY_CTRL ] = Qt::ControlModifier; } ~QtOsgKeyboard() @@ -81,7 +81,7 @@ namespace gepetto { int remapKey(QKeyEvent* event) { - KeyMap::iterator itr = mKeyMap.find(event->key()); + KeyMap::iterator itr = mKeyMap.find((Qt::Key)event->key()); if (itr == mKeyMap.end()) { return int(*(event->text().toLatin1().data())); @@ -104,19 +104,26 @@ namespace gepetto { QKeyEvent* remapModKey(int modMask) { if (modMask == 0) - return NULL; - for (ModKeyMap::iterator itr = modKeyMap.begin(); itr != modKeyMap.end(); ++itr) { - if (itr->first == modMask) - return new QKeyEvent(QEvent::KeyPress, itr->second, 0); - } + return NULL; + ModKeyMap::const_iterator it = modKeyMap.find(modMask); + if (it != modKeyMap.end()) + return new QKeyEvent(QEvent::KeyPress, it->second, 0); return NULL; } + Qt::KeyboardModifiers getQtModKey(int modMask) + { + ModKeyMap::const_iterator it = modKeyMap.find(modMask); + if (it != modKeyMap.end()) + return it->second; + return Qt::NoModifier; + } + private: - typedef std::map<unsigned int, int> KeyMap; + typedef std::map<Qt::Key, int> KeyMap; KeyMap mKeyMap; - typedef std::map<int, unsigned int> ModKeyMap; + typedef std::map<int, Qt::KeyboardModifiers> ModKeyMap; ModKeyMap modKeyMap; }; } diff --git a/include/gepetto/gui/selection-event.hh b/include/gepetto/gui/selection-event.hh new file mode 100644 index 0000000000000000000000000000000000000000..5dce391e50bb02553fb9161ff202876210479fe0 --- /dev/null +++ b/include/gepetto/gui/selection-event.hh @@ -0,0 +1,64 @@ +#ifndef GEPETTO_GUI_SELECTION_EVENT_HH +#define GEPETTO_GUI_SELECTION_EVENT_HH + +#include <QString> +#include <QVector3D> +#include <QObject> + +#include <gepetto/viewer/node.h> + +namespace gepetto { + namespace gui { + class SelectionEvent : public QObject { + Q_OBJECT + + public: + enum Type { + FromOsgWindow, + FromBodyTree + }; + + SelectionEvent (const Type& t, graphics::NodePtr_t node = graphics::NodePtr_t(), Qt::KeyboardModifiers modKey = Qt::NoModifier) + : type_ (t) + , node_ (node) + , modKey_ (modKey) + , hasIntersection_ (false) + { + if (node) + nodeName_ = QString::fromStdString(node->getID()); + } + + SelectionEvent (const Type& t, Qt::KeyboardModifiers modKey) + : type_ (t) + , modKey_ (modKey) + , hasIntersection_ (false) + {} + + void setupIntersection(const osgUtil::LineSegmentIntersector::Intersection& it); + + const graphics::NodePtr_t& node () const { return node_; } + + void modKey (const Qt::KeyboardModifiers& m) { modKey_ = m; } + + public slots: + Type type () const { return type_; } + QString nodeName() const { return nodeName_; } + Qt::KeyboardModifiers modKey () const { return modKey_; } + + bool hasIntersection () { return hasIntersection_; } + QVector3D normal(bool local) const { return (local ? localNormal_ : worldNormal_); } + QVector3D point (bool local) const { return (local ? localPoint_ : worldPoint_ ); } + + private: + Type type_; + QString nodeName_; + graphics::NodePtr_t node_; + Qt::KeyboardModifiers modKey_; + + bool hasIntersection_; + QVector3D localPoint_, localNormal_, worldPoint_, worldNormal_; + }; + } // namespace gui +} // namespace gepetto + +#endif // GEPETTO_GUI_SELECTION_EVENT_HH diff --git a/include/gepetto/gui/selection-handler.hh b/include/gepetto/gui/selection-handler.hh index 0f1b8d4cbfcc9ec003f0a3f78a87092837b9fb25..89f97c7a744f7ad4891ec3e41833ae2885d693f2 100644 --- a/include/gepetto/gui/selection-handler.hh +++ b/include/gepetto/gui/selection-handler.hh @@ -23,6 +23,8 @@ namespace gepetto { virtual void reset() { currentSelected_ = ""; } + QString currentBody () { return currentSelected_; } + signals: void selectedBodies(QStringList selectedBodies); @@ -30,11 +32,7 @@ namespace gepetto { /// Slot called when a body is selected. /// \param name body's name /// \param position click position - virtual void onSelect(QString name, QVector3D /*position*/, - QKeyEvent* /*event*/) - { - Q_UNUSED(name) emit selectedBodies(QStringList()); - } + virtual void onSelect(SelectionEvent* event) = 0; virtual QString getName() { return "None"; } @@ -52,7 +50,7 @@ namespace gepetto { ~UniqueSelection(); public slots: - virtual void onSelect(QString name, QVector3D position, QKeyEvent* event); + virtual void onSelect(SelectionEvent* event); virtual QString getName() { return "Unique"; } }; @@ -66,7 +64,7 @@ namespace gepetto { virtual void reset(); public slots: - virtual void onSelect(QString name, QVector3D position, QKeyEvent* event); + virtual void onSelect(SelectionEvent* event); virtual QString getName() { return "Multi"; } protected: @@ -82,6 +80,8 @@ namespace gepetto { void setParentOSG(OSGWidget* parent); + SelectionMode* mode (); + public slots: /// Add a mode to the list of available mode. /// \param mode mode to add diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 5b1aa5be0103e1737c260a2464575cc6f015b897..f29b79734c6cff8469acd74133015da1067cf1c3 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -38,6 +38,7 @@ SET (${PROJECT_NAME}_SOURCES dialog/pluginmanagerdialog.cc shortcut-factory.cc selection-handler.cc + selection-event.cc ) IF(GEPETTO_GUI_HAS_PYTHONQT) diff --git a/src/gui/bodytreewidget.cc b/src/gui/bodytreewidget.cc index 5774ce3b398620f583e4356cd5a80f168b0320d9..05ceefe73c3be542104375ccfe6dee52f3568d6b 100644 --- a/src/gui/bodytreewidget.cc +++ b/src/gui/bodytreewidget.cc @@ -5,6 +5,7 @@ #include <gepetto/gui/windows-manager.hh> #include <gepetto/gui/osgwidget.hh> #include <gepetto/gui/meta.hh> +#include <gepetto/gui/selection-event.hh> #include <QSignalMapper> #include <QColorDialog> @@ -73,6 +74,9 @@ namespace gepetto { view_->setSelectionMode(QAbstractItemView::ExtendedSelection); connect (view_, SIGNAL (customContextMenuRequested(QPoint)), SLOT(customContextMenu(QPoint))); + connect (view_->selectionModel(), + SIGNAL (currentChanged(QModelIndex,QModelIndex)), + SLOT (currentChanged(QModelIndex,QModelIndex))); toolBox_->removeItem(0); addSlider(toolBox_, "Transparency", this, SLOT(setTransparency(int))); @@ -115,6 +119,51 @@ namespace gepetto { return selectBodyByName (QString::fromStdString (bodyName)); } + void BodyTreeWidget::handleSelectionEvent (const SelectionEvent* event) + { + disconnect (view_->selectionModel(), + SIGNAL (currentChanged(QModelIndex,QModelIndex)), + this, SLOT (currentChanged(QModelIndex,QModelIndex))); + if (event->node()) { + QList<QStandardItem*> matches; + matches = model_->findItems(event->nodeName(), Qt::MatchFixedString + | Qt::MatchCaseSensitive + | Qt::MatchRecursive); + if (matches.empty()) + view_->clearSelection(); + else { + qDebug() << event->modKey(); + if (event->modKey() == Qt::ControlModifier) + view_->selectionModel()->setCurrentIndex + (matches.first()->index(), + QItemSelectionModel::Toggle); + else + view_->selectionModel()->select(matches.first()->index(), QItemSelectionModel::ClearAndSelect); + } + } else + view_->clearSelection(); + connect (view_->selectionModel(), + SIGNAL (currentChanged(QModelIndex,QModelIndex)), + SLOT (currentChanged(QModelIndex,QModelIndex))); + } + + void BodyTreeWidget::currentChanged (const QModelIndex ¤t, + const QModelIndex &/*previous*/) + { + // TODO + // if (!current.isValid()) { + // deselect + // } + BodyTreeItem *item = dynamic_cast <BodyTreeItem*> ( + qobject_cast <const QStandardItemModel*> + (view_->model())->itemFromIndex(current) + ); + if (item) { + SelectionEvent *event = new SelectionEvent(SelectionEvent::FromBodyTree, item->node(), QApplication::keyboardModifiers()); + MainWindow::instance()->centralWidget()->emitClicked(event); + } + } + QList<BodyTreeItem*> BodyTreeWidget::selectedBodies() const { QList<BodyTreeItem*> list; diff --git a/src/gui/mainwindow.cc b/src/gui/mainwindow.cc index 79944ed0bf5f87d437012d4fefc3524a4f5fd2cb..3b7fd438f1b1054c4f99ed0c5def51f64f46d4bf 100644 --- a/src/gui/mainwindow.cc +++ b/src/gui/mainwindow.cc @@ -71,8 +71,8 @@ namespace gepetto { connect(ui_->actionChange_shortcut, SIGNAL(triggered()), shortcutFactory_, SLOT(open())); selectionHandler_ = new SelectionHandler(osgViewerManagers_); - selectionHandler_->addMode(new UniqueSelection(osgViewerManagers_)); selectionHandler_->addMode(new MultiSelection(osgViewerManagers_)); + selectionHandler_->addMode(new UniqueSelection(osgViewerManagers_)); ui_->osgToolBar->addWidget(selectionHandler_); } diff --git a/src/gui/osgwidget.cc b/src/gui/osgwidget.cc index c24e3fd99fb6ec135e79fd755d509afa9e0763ee..c67eaf021e33f608d1f4ffd114ff3fc5d8d48413 100644 --- a/src/gui/osgwidget.cc +++ b/src/gui/osgwidget.cc @@ -37,6 +37,7 @@ #include <gepetto/gui/windows-manager.hh> #include <gepetto/gui/bodytreewidget.hh> +#include <gepetto/gui/selection-event.hh> namespace gepetto { namespace gui { @@ -145,11 +146,6 @@ namespace gepetto { render_.wsm_ = wsm_; render_.refreshRate = parent->settings_->refreshRate; render_.start (); - - parent->bodyTree()->connect(this, - SIGNAL (clicked(QString,QVector3D,QKeyEvent*)), SLOT (selectBodyByName(QString))); - parent->connect(this, SIGNAL (clicked(QString,QVector3D,QKeyEvent*)), - SLOT (requestSelectJointFromBodyName(QString))); } OSGWidget::~OSGWidget() @@ -184,9 +180,14 @@ namespace gepetto { // wsm_->lock().unlock(); } - void OSGWidget::emitClicked(QString name, QVector3D positionInWorldFrame, QKeyEvent* event) + void OSGWidget::emitClicked(SelectionEvent* event) { - emit clicked (name, positionInWorldFrame, event); + emit clicked (event); + if (event->type() != SelectionEvent::FromBodyTree) { + MainWindow* main = MainWindow::instance(); + main->bodyTree()->handleSelectionEvent(event); + main->requestSelectJointFromBodyName(event->nodeName()); + } } void OSGWidget::onHome() diff --git a/src/gui/pick-handler.cc b/src/gui/pick-handler.cc index 2a631bfd37f18ff006d9d294b8b405a500687754..0abc0ec5df46661b37c99576bfcd695d806723a4 100644 --- a/src/gui/pick-handler.cc +++ b/src/gui/pick-handler.cc @@ -12,11 +12,13 @@ #include <iostream> #include <boost/regex.hpp> +#include <gepetto/gui/selection-event.hh> #include <gepetto/gui/windows-manager.hh> #include <gepetto/gui/osgwidget.hh> #include <gepetto/gui/mainwindow.hh> #include <gepetto/gui/bodytreewidget.hh> #include <gepetto/gui/tree-item.hh> +#include <gepetto/gui/selection-handler.hh> namespace gepetto { namespace gui { @@ -24,16 +26,10 @@ namespace gepetto { : QObject (parent) , wsm_ (wsm) , parent_ (parent) - , last_ () , pushed_ (false) , lastX_ (0) , lastY_ (0) - { - MainWindow* main = MainWindow::instance (); - connect (main->bodyTree ()->view ()->selectionModel(), - SIGNAL (currentChanged(QModelIndex,QModelIndex)), - SLOT (bodyTreeCurrentChanged(QModelIndex,QModelIndex))); - } + {} PickHandler::~PickHandler() { @@ -80,14 +76,6 @@ namespace gepetto { return false; } - void PickHandler::select (graphics::NodePtr_t node) - { - if (last_ == node) return; - if (last_) last_->setHighlightState (0); - last_ = node; - if (last_) last_->setHighlightState (8); - } - void PickHandler::getUsage (osg::ApplicationUsage& usage) { usage.addKeyboardMouseBinding ("Right click", "Select node"); @@ -119,7 +107,7 @@ namespace gepetto { camera->accept( iv ); if( !intersector->containsIntersections() ) { - select (graphics::NodePtr_t()); + parent_->emitClicked(new SelectionEvent(SelectionEvent::FromOsgWindow, QApplication::keyboardModifiers())); return nodes; } @@ -132,30 +120,34 @@ namespace gepetto { if (n) { if (boost::regex_match (n->getID(), boost::regex ("^.*_[0-9]+$"))) continue; - osg::Vec3d p = it->getWorldIntersectPoint(); - QVector3D pWF (p[0],p[1],p[2]); - parent_->emitClicked(QString::fromStdString(n->getID ()), pWF, - mapper_.remapModKey(modKeyMask)); + SelectionEvent *event = new SelectionEvent(SelectionEvent::FromOsgWindow, + n, + mapper_.getQtModKey(modKeyMask)); + event->setupIntersection(*it); + parent_->emitClicked(event); return nodes; // nodes.push_back(n); // break; } } } - // emit parent_->selected (nodes.front()->getID ()); } - select (graphics::NodePtr_t()); + parent_->emitClicked(new SelectionEvent(SelectionEvent::FromOsgWindow, QApplication::keyboardModifiers())); return nodes; } void PickHandler::setCameraToSelected (osgGA::GUIActionAdapter &aa, bool zoom) { - if (!last_) return; + MainWindow* main = MainWindow::instance(); + graphics::NodePtr_t last = main->osg()->getNode( + main->selectionHandler()->mode()->currentBody().toStdString() + ); + if (!last) return; osgViewer::View* viewer = dynamic_cast<osgViewer::View*>( &aa ); if(!viewer) return; - const osg::BoundingSphere& bs = last_->asGroup()->getBound (); + const osg::BoundingSphere& bs = last->asGroup()->getBound (); osg::Vec3f eye, center, up; viewer->getCameraManipulator()->getInverseMatrix () .getLookAt (eye, center, up); @@ -167,23 +159,5 @@ namespace gepetto { osg::Matrixd::lookAt (eye, bs.center(), up) ); } - - void PickHandler::bodyTreeCurrentChanged (const QModelIndex ¤t, - const QModelIndex &/*previous*/) - { - if (!current.isValid()) { - select (graphics::NodePtr_t()); - return; - } - BodyTreeItem *item = dynamic_cast <BodyTreeItem*> ( - qobject_cast <const QStandardItemModel*> - (current.model())->itemFromIndex(current) - ); - if (item) { - wsm_->lock ().lock(); - select (item->node ()); - wsm_->lock ().unlock(); - } - } } } diff --git a/src/gui/pythonwidget.cc b/src/gui/pythonwidget.cc index dfe3a72a1744ef3e1becf9d8f21af57824d26b39..d3711d457dfe3f11eb268dc834e9b3962f8ce254 100644 --- a/src/gui/pythonwidget.cc +++ b/src/gui/pythonwidget.cc @@ -38,7 +38,11 @@ namespace gepetto { PythonQtObjectPtr sys = PythonQt::self()->importModule ("sys"); sys.evalScript ("argv = ['gepetto-gui']"); console_ = new PythonQtScriptingConsole(NULL, mainContext_); - PythonQt::self()->registerQObjectClassNames(QStringList() << "BodyTreeWidget" << "BodyTreeItem" << "WindowsManager"); + PythonQt::self()->registerQObjectClassNames(QStringList() + << "BodyTreeWidget" + << "BodyTreeItem" + << "SelectionEvent" + << "WindowsManager"); mainContext_.addObject("mainWindow", MainWindow::instance()); mainContext_.addObject("windowsManager", MainWindow::instance()->osg().get()); console_->QTextEdit::clear(); diff --git a/src/gui/selection-event.cc b/src/gui/selection-event.cc new file mode 100644 index 0000000000000000000000000000000000000000..0a32546106f99a64d995887ba9767a237ad4b03a --- /dev/null +++ b/src/gui/selection-event.cc @@ -0,0 +1,48 @@ +// Copyright (c) 2017, Joseph Mirabel +// Authors: Joseph Mirabel (joseph.mirabel@laas.fr) +// +// This file is part of gepetto-viewer-corba. +// gepetto-viewer-corba 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. +// +// gepetto-viewer-corba 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 +// General Lesser Public License for more details. You should have +// received a copy of the GNU Lesser General Public License along with +// gepetto-viewer-corba. If not, see <http://www.gnu.org/licenses/>. + +#include "gepetto/gui/selection-event.hh" + +#include <QDebug> + +#include <osgUtil/LineSegmentIntersector> + + +namespace gepetto { + namespace gui { + namespace { + void toQVector3(const osg::Vec3f& in, QVector3D& out) { + out.setX(in[0]); + out.setY(in[1]); + out.setZ(in[2]); + } + void toQVector3(const osg::Vec3d& in, QVector3D& out) { + out.setX(in[0]); + out.setY(in[1]); + out.setZ(in[2]); + } + } + + void SelectionEvent::setupIntersection(const osgUtil::LineSegmentIntersector::Intersection& it) + { + hasIntersection_ = true; + toQVector3(it.getLocalIntersectPoint(), localPoint_); + toQVector3(it.getWorldIntersectPoint(), worldPoint_); + toQVector3(it.getLocalIntersectNormal(), localNormal_); + toQVector3(it.getWorldIntersectNormal(), worldNormal_); + } + } +} diff --git a/src/gui/selection-handler.cc b/src/gui/selection-handler.cc index 7aaa8e555bbb57bae90e1367047c3a95ebec8f27..b7ec358871be2a6e6e8db7e9daa38593444feeaf 100644 --- a/src/gui/selection-handler.cc +++ b/src/gui/selection-handler.cc @@ -2,7 +2,9 @@ #include <QLabel> #include <QVector3D> #include <QAction> +#include <QDebug> +#include <gepetto/gui/selection-event.hh> #include <gepetto/gui/windows-manager.hh> #include "gepetto/gui/osgwidget.hh" #include "gepetto/gui/selection-handler.hh" @@ -28,6 +30,12 @@ namespace gepetto { changeMode(currentIndex()); } + SelectionMode* SelectionHandler::mode () + { + assert(index_ >= 0 && index_ < (int)modes_.size()); + return modes_[index_]; + } + void SelectionHandler::changeMode(int index) { if (osg_ != NULL) { @@ -36,14 +44,14 @@ namespace gepetto { } if (index_ != -1) { modes_[index_]->reset(); - disconnect(osg_, SIGNAL(clicked(QString, QVector3D, QKeyEvent*)), - modes_[index_], SLOT(onSelect(QString, QVector3D, QKeyEvent*))); + disconnect(osg_, SIGNAL(clicked(SelectionEvent*)), + modes_[index_], SLOT(onSelect(SelectionEvent*))); disconnect(modes_[index_], SIGNAL(selectedBodies(QStringList)), this, SLOT(getBodies(QStringList))); } index_ = index; - connect(osg_, SIGNAL(clicked(QString, QVector3D, QKeyEvent*)), - modes_[index], SLOT(onSelect(QString, QVector3D, QKeyEvent*))); + connect(osg_, SIGNAL(clicked(SelectionEvent*)), + modes_[index], SLOT(onSelect(SelectionEvent*))); connect(modes_[index], SIGNAL(selectedBodies(QStringList)), SLOT(getBodies(QStringList))); } @@ -69,14 +77,14 @@ namespace gepetto { { } - void UniqueSelection::onSelect(QString name, QVector3D /*position*/, - QKeyEvent* /*event*/) + void UniqueSelection::onSelect(SelectionEvent* event) { - if (currentSelected_ == name) return; + if (!event) return; + if (currentSelected_ == event->nodeName()) return; if (currentSelected_ != "") wsm_->setHighlight(currentSelected_.toStdString(), 0); - currentSelected_ = name; - wsm_->setHighlight(name.toStdString(), 8); - emit selectedBodies(QStringList() << name); + currentSelected_ = event->nodeName(); + wsm_->setHighlight(event->node()->getID(), 8); + emit selectedBodies(QStringList() << currentSelected_); } MultiSelection::MultiSelection(WindowsManagerPtr_t wsm) @@ -94,22 +102,36 @@ namespace gepetto { selectedBodies_ = QStringList(); } - void MultiSelection::onSelect(QString name, QVector3D /*position*/, - QKeyEvent* event) + void MultiSelection::onSelect(SelectionEvent* event) { - if (currentSelected_ == name) return; - if (!event || event->key() != Qt::Key_Control) { - foreach (QString n, selectedBodies_) { - wsm_->setHighlight(n.toStdString(), 0); - } - selectedBodies_.clear(); - } - else if (currentSelected_ != "") { - wsm_->setHighlight(currentSelected_.toStdString(), 7); + if (!event) return; + int i = selectedBodies_.indexOf(event->nodeName()); + if (event->modKey() != Qt::ControlModifier) { // CTRL not pressed + foreach (QString n, selectedBodies_) { + wsm_->setHighlight(n.toStdString(), 0); + } + selectedBodies_.clear(); + currentSelected_ = event->nodeName(); + if (event->node()) { + wsm_->setHighlight(event->node()->getID(), 8); + selectedBodies_ << currentSelected_; + } + } else { // CTRL pressed + if (!currentSelected_.isEmpty()) + wsm_->setHighlight(currentSelected_.toStdString(), 7); + if (i >= 0) { // Already selected. + wsm_->setHighlight(event->node()->getID(), 0); + currentSelected_ = ""; + selectedBodies_.removeAt(i); + } else { + currentSelected_ = event->nodeName(); + if (event->node()){ // Add to the list if not empty + wsm_->setHighlight(event->node()->getID(), 8); + selectedBodies_ << currentSelected_; + } + } } - currentSelected_ = name; - wsm_->setHighlight(name.toStdString(), 8); - selectedBodies_ << name; + qDebug() << selectedBodies_; emit selectedBodies(selectedBodies_); } }