diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index d95317aaf..266a9c250 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -113,7 +113,7 @@ opencs_units (view/prefs opencs_units (model/prefs state setting intsetting doublesetting boolsetting enumsetting coloursetting shortcut - shortcutmanager shortcutsetting + shortcuteventhandler shortcutmanager shortcutsetting ) opencs_units_noqt (model/prefs diff --git a/apps/opencs/model/prefs/shortcut.cpp b/apps/opencs/model/prefs/shortcut.cpp index f691cede9..b8820ae8b 100644 --- a/apps/opencs/model/prefs/shortcut.cpp +++ b/apps/opencs/model/prefs/shortcut.cpp @@ -14,6 +14,8 @@ namespace CSMPrefs , mName(name) , mCurrentPos(0) , mLastPos(0) + , mActive(false) + , mEnabled(true) { State::get().getShortcutManager().addShortcut(this); setSequence(State::get().getShortcutManager().getSequence(name)); @@ -24,116 +26,64 @@ namespace CSMPrefs State::get().getShortcutManager().removeShortcut(this); } - const std::string& Shortcut::getName() const + bool Shortcut::isActive() const { - return mName; + return mActive; } - const QKeySequence& Shortcut::getSequence() const + bool Shortcut::isEnabled() const { - return mSequence; + return mEnabled; } - void Shortcut::setSequence(const QKeySequence& sequence) + const std::string& Shortcut::getName() const { - mSequence = sequence; - mCurrentPos = 0; - mLastPos = sequence.count() - 1; + return mName; } - void Shortcut::keyPressEvent(QKeyEvent* event) + const QKeySequence& Shortcut::getSequence() const { - int withMod = event->key() | event->modifiers(); - int noMod = event->key(); - - if (withMod == mSequence[mCurrentPos] || (mCurrentPos > 0 && noMod == mSequence[mCurrentPos])) - { - if (mCurrentPos == mLastPos) - { - activated(true); - } - else - ++mCurrentPos; - } + return mSequence; } - void Shortcut::keyReleaseEvent(QKeyEvent* event) + int Shortcut::getPosition() const { - const int KeyMask = 0x01FFFFFF; - - if ((mSequence[mCurrentPos] & KeyMask) == event->key()) - { - if (mCurrentPos == mLastPos) - { - activated(false); - mCurrentPos = 0; // Resets to start, maybe shouldn't? - } - else if (mCurrentPos > 0) - { - --mCurrentPos; - } - } + return mCurrentPos; } - void Shortcut::mousePressEvent(QMouseEvent* event) + int Shortcut::getLastPosition() const { - int withMod = event->button() | (int)event->modifiers(); - int noMod = event->button(); - - if (withMod == mSequence[mCurrentPos] || (mCurrentPos > 0 && noMod == mSequence[mCurrentPos])) - { - if (mCurrentPos == mLastPos) - activated(true); - else - ++mCurrentPos; - } + return mLastPos; } - void Shortcut::mouseReleaseEvent(QMouseEvent* event) + void Shortcut::setPosition(int pos) { - const int MouseMask = 0x0000001F; - - if ((mSequence[mCurrentPos] & MouseMask) == event->button()) - { - if (mCurrentPos == mLastPos) - { - activated(false); - mCurrentPos = 0; - } - else if (mCurrentPos > 0) - { - --mCurrentPos; - } - } + mCurrentPos = pos; } - QShortcutWrapper::QShortcutWrapper(const std::string& name, QShortcut* shortcut) - : QObject(shortcut) - , mName(name) - , mShortcut(shortcut) + void Shortcut::setSequence(const QKeySequence& sequence) { - State::get().getShortcutManager().addShortcut(this); - setSequence(State::get().getShortcutManager().getSequence(name)); + mSequence = sequence; + mCurrentPos = 0; + mLastPos = sequence.count() - 1; } - QShortcutWrapper::~QShortcutWrapper() + void Shortcut::activate(bool state) { - State::get().getShortcutManager().removeShortcut(this); - } + mActive = state; + emit activated(state); - const std::string& QShortcutWrapper::getName() const - { - return mName; + if (state) + emit activated(); } - const QKeySequence& QShortcutWrapper::getSequence() const + void Shortcut::enable(bool state) { - return mSequence; + mEnabled = state; } - void QShortcutWrapper::setSequence(const QKeySequence& sequence) + QString Shortcut::toString() const { - mSequence = sequence; - mShortcut->setKey(sequence); + return QString(State::get().getShortcutManager().sequenceToString(mSequence).data()); } } diff --git a/apps/opencs/model/prefs/shortcut.hpp b/apps/opencs/model/prefs/shortcut.hpp index b121c0610..25bb13556 100644 --- a/apps/opencs/model/prefs/shortcut.hpp +++ b/apps/opencs/model/prefs/shortcut.hpp @@ -1,8 +1,11 @@ #ifndef CSM_PREFS_SHORTCUT_H #define CSM_PREFS_SHORTCUT_H +#include + #include #include +#include class QKeyEvent; class QMouseEvent; @@ -20,10 +23,24 @@ namespace CSMPrefs Shortcut(const std::string& name, QObject* parent); ~Shortcut(); + bool isActive() const; + bool isEnabled() const; + const std::string& getName() const; const QKeySequence& getSequence() const; + /// The position in the sequence + int getPosition() const; + /// The position in the sequence + int getLastPosition() const; void setSequence(const QKeySequence& sequence); + /// The position in the sequence + void setPosition(int pos); + + void activate(bool state); + void enable(bool state); + + QString toString() const; private: @@ -32,39 +49,16 @@ namespace CSMPrefs int mCurrentPos; int mLastPos; - public slots: - - void keyPressEvent(QKeyEvent* event); - void keyReleaseEvent(QKeyEvent* event); - void mousePressEvent(QMouseEvent* event); - void mouseReleaseEvent(QMouseEvent* event); + bool mActive; + bool mEnabled; signals: - /// Triggered when the shortcut is activated or deactived; can be determined from \p active - void activated(bool active); - }; - - /// Wraps a QShortcut object so that the sequence can be modified by the settings - class QShortcutWrapper : public QObject - { - Q_OBJECT - - public: + /// Triggered when the shortcut is activated or deactived; can be determined from \p state + void activated(bool state); - QShortcutWrapper(const std::string& name, QShortcut* shortcut); - ~QShortcutWrapper(); - - const std::string& getName() const; - const QKeySequence& getSequence() const; - - void setSequence(const QKeySequence& sequence); - - private: - - std::string mName; - QKeySequence mSequence; - QShortcut* mShortcut; + /// Trigger when activated; convenience signal. + void activated(); }; } diff --git a/apps/opencs/model/prefs/shortcuteventhandler.cpp b/apps/opencs/model/prefs/shortcuteventhandler.cpp new file mode 100644 index 000000000..49b13ff99 --- /dev/null +++ b/apps/opencs/model/prefs/shortcuteventhandler.cpp @@ -0,0 +1,171 @@ +#include "shortcuteventhandler.hpp" + +#include +#include + +#include +#include +#include +#include + +#include "shortcut.hpp" + +namespace CSMPrefs +{ + ShortcutEventHandler::ShortcutEventHandler(QObject* parent) + : QObject(parent) + { + } + + void ShortcutEventHandler::addShortcut(Shortcut* shortcut) + { + mShortcuts.push_back(shortcut); + } + + void ShortcutEventHandler::removeShortcut(Shortcut* shortcut) + { + std::remove(mShortcuts.begin(), mShortcuts.end(), shortcut); + } + + bool ShortcutEventHandler::eventFilter(QObject* watched, QEvent* event) + { + if (event->type() == QEvent::KeyPress) + { + QKeyEvent* keyEvent = static_cast(event); + unsigned int mod = (unsigned int) keyEvent->modifiers(); + unsigned int key = (unsigned int) keyEvent->key(); + + if (!keyEvent->isAutoRepeat()) + return activate(mod, key); + } + else if (event->type() == QEvent::KeyRelease) + { + QKeyEvent* keyEvent = static_cast(event); + unsigned int key = (unsigned int) keyEvent->key(); + + if (!keyEvent->isAutoRepeat()) + return deactivate(key); + } + else if (event->type() == QEvent::MouseButtonPress) + { + QMouseEvent* mouseEvent = static_cast(event); + unsigned int mod = (unsigned int) mouseEvent->modifiers(); + unsigned int button = (unsigned int) mouseEvent->button(); + + return activate(mod, button); + } + else if (event->type() == QEvent::MouseButtonRelease) + { + QMouseEvent* mouseEvent = static_cast(event); + unsigned int button = (unsigned int) mouseEvent->button(); + + return deactivate(button); + } + else if (event->type() == QEvent::FocusOut) + { + // Deactivate in case events are missed + for (std::vector::iterator it = mShortcuts.begin(); it != mShortcuts.end(); ++it) + { + Shortcut* shortcut = *it; + + if (shortcut->isActive()) + shortcut->activate(false); + } + } + + return false; + } + + bool ShortcutEventHandler::activate(unsigned int mod, unsigned int button) + { + std::vector > potentials; + bool used = false; + + // Find potential activations + for (std::vector::iterator it = mShortcuts.begin(); it != mShortcuts.end(); ++it) + { + Shortcut* shortcut = *it; + int pos = shortcut->getPosition(); + int lastPos = shortcut->getLastPosition(); + MatchResult result = match(mod, button, shortcut->getSequence()[pos]); + + if (!shortcut->isEnabled()) + continue; + + if (result == Matches_WithMod || result == Matches_NoMod) + { + if (pos < lastPos && (result == Matches_WithMod || pos > 0)) + { + shortcut->setPosition(pos+1); + used = true; + } + else if (pos == lastPos) + { + potentials.push_back(std::make_pair(result, shortcut)); + } + } + } + + // Only activate the best match; in exact conflicts, this will favor the first shortcut added. + if (!potentials.empty()) + { + std::sort(potentials.begin(), potentials.end(), ShortcutEventHandler::sort); + potentials.front().second->activate(true); + used = true; + } + + return used; + } + + bool ShortcutEventHandler::deactivate(unsigned int button) + { + const int KeyMask = 0x01FFFFFF; + + bool used = false; + + for (std::vector::iterator it = mShortcuts.begin(); it != mShortcuts.end(); ++it) + { + Shortcut* shortcut = *it; + int pos = shortcut->getPosition(); + MatchResult result = match(0, button, shortcut->getSequence()[pos] & KeyMask); + + if (result != Matches_Not) + { + if (shortcut->isActive()) + shortcut->activate(false); + + shortcut->setPosition(0); + + used = true; + } + } + + return used; + } + + ShortcutEventHandler::MatchResult ShortcutEventHandler::match(unsigned int mod, unsigned int button, + unsigned int value) + { + if ((mod | button) == value) + { + return Matches_WithMod; + } + else if (button == value) + { + return Matches_NoMod; + } + else + { + return Matches_Not; + } + } + + bool ShortcutEventHandler::sort(const std::pair& left, + const std::pair& right) + { + if (left.first == Matches_WithMod && left.first != right.first) + return true; + else + return left.second->getPosition() >= right.second->getPosition(); + } +} diff --git a/apps/opencs/model/prefs/shortcuteventhandler.hpp b/apps/opencs/model/prefs/shortcuteventhandler.hpp new file mode 100644 index 000000000..c1ce48f7e --- /dev/null +++ b/apps/opencs/model/prefs/shortcuteventhandler.hpp @@ -0,0 +1,54 @@ +#ifndef CSM_PREFS_SHORTCUT_EVENT_HANDLER_H +#define CSM_PREFS_SHORTCUT_EVENT_HANDLER_H + +#include + +#include + +class QEvent; +class QWidget; + +namespace CSMPrefs +{ + class Shortcut; + + /// Users of this class should install it as an event handler + class ShortcutEventHandler : public QObject + { + Q_OBJECT + + public: + + ShortcutEventHandler(QObject* parent=0); + + void addShortcut(Shortcut* shortcut); + void removeShortcut(Shortcut* shortcut); + + protected: + + bool eventFilter(QObject* watched, QEvent* event); + + private: + + enum MatchResult + { + Matches_WithMod, + Matches_NoMod, + Matches_Not + }; + + bool activate(unsigned int mod, unsigned int button); + + bool deactivate(unsigned int button); + + MatchResult match(unsigned int mod, unsigned int button, unsigned int value); + + // Prefers Matches_WithMod and a larger number of buttons + static bool sort(const std::pair& left, + const std::pair& right); + + std::vector mShortcuts; + }; +} + +#endif diff --git a/apps/opencs/model/prefs/shortcutmanager.cpp b/apps/opencs/model/prefs/shortcutmanager.cpp index 740179b25..a4b9b1818 100644 --- a/apps/opencs/model/prefs/shortcutmanager.cpp +++ b/apps/opencs/model/prefs/shortcutmanager.cpp @@ -16,11 +16,6 @@ namespace CSMPrefs mShortcuts.insert(std::make_pair(shortcut->getName(), shortcut)); } - void ShortcutManager::addShortcut(QShortcutWrapper* wrapper) - { - mShortcutWrappers.insert(std::make_pair(wrapper->getName(), wrapper)); - } - void ShortcutManager::removeShortcut(Shortcut* shortcut) { std::pair range = mShortcuts.equal_range(shortcut->getName()); @@ -38,24 +33,6 @@ namespace CSMPrefs } } - void ShortcutManager::removeShortcut(QShortcutWrapper* wrapper) - { - std::pair range = mShortcutWrappers.equal_range( - wrapper->getName()); - - for (ShortcutWrapperMap::iterator it = range.first; it != range.second;) - { - if (it->second == wrapper) - { - mShortcutWrappers.erase(it++); - } - else - { - ++it; - } - } - } - QKeySequence ShortcutManager::getSequence(const std::string& name) const { QKeySequence sequence; @@ -85,17 +62,11 @@ namespace CSMPrefs // Change active shortcuts std::pair rangeS = mShortcuts.equal_range(name); - std::pair rangeW = mShortcutWrappers.equal_range(name); for (ShortcutMap::iterator it = rangeS.first; it != rangeS.second; ++it) { it->second->setSequence(sequence); } - - for (ShortcutWrapperMap::iterator it = rangeW.first; it != rangeW.second; ++it) - { - it->second->setSequence(sequence); - } } std::string ShortcutManager::sequenceToString(const QKeySequence& seq) diff --git a/apps/opencs/model/prefs/shortcutmanager.hpp b/apps/opencs/model/prefs/shortcutmanager.hpp index f2534347a..2510ec77e 100644 --- a/apps/opencs/model/prefs/shortcutmanager.hpp +++ b/apps/opencs/model/prefs/shortcutmanager.hpp @@ -9,7 +9,6 @@ namespace CSMPrefs { class Shortcut; - class QShortcutWrapper; /// Class used to track and update shortcuts/sequences class ShortcutManager : public QObject @@ -20,13 +19,9 @@ namespace CSMPrefs /// The shortcut class will do this automatically void addShortcut(Shortcut* shortcut); - /// The wrapper class will do this automatically - void addShortcut(QShortcutWrapper* wrapper); /// The shortcut class will do this automatically void removeShortcut(Shortcut* shortcut); - /// The wrapper class will do this automatically - void removeShortcut(QShortcutWrapper* wrapper); QKeySequence getSequence(const std::string& name) const; void setSequence(const std::string& name, const QKeySequence& sequence); @@ -38,12 +33,9 @@ namespace CSMPrefs // Need a multimap in case multiple shortcuts share the same name typedef std::multimap ShortcutMap; - typedef std::multimap ShortcutWrapperMap; - typedef std::map SequenceMap; ShortcutMap mShortcuts; - ShortcutWrapperMap mShortcutWrappers; SequenceMap mSequences; }; } diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index f2a0b31e1..abb5c7f18 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -236,6 +236,15 @@ void CSMPrefs::State::declare() declareShortcut ("free-roll-left", "Free camera roll left", QKeySequence(Qt::Key_Q)); declareShortcut ("free-roll-right", "Free camera roll right", QKeySequence(Qt::Key_E)); declareShortcut ("free-speed-mode", "Free camera speed mode toggle", QKeySequence(Qt::Key_F)); + declareSeparator (); + declareShortcut ("orbit-up", "Orbit camera up", QKeySequence(Qt::Key_W)); + declareShortcut ("orbit-down", "Orbit camera down", QKeySequence(Qt::Key_S)); + declareShortcut ("orbit-left", "Orbit camera left", QKeySequence(Qt::Key_A)); + declareShortcut ("orbit-right", "Orbit camera right", QKeySequence(Qt::Key_D)); + declareShortcut ("orbit-roll-left", "Orbit camera roll left", QKeySequence(Qt::Key_Q)); + declareShortcut ("orbit-roll-right", "Orbit camera roll right", QKeySequence(Qt::Key_E)); + declareShortcut ("orbit-speed-mode", "Orbit camera speed mode toggle", QKeySequence(Qt::Key_F)); + declareShortcut ("orbit-center-selection", "Centers the camera on the selected item", QKeySequence(Qt::Key_C)); } void CSMPrefs::State::declareCategory (const std::string& key) diff --git a/apps/opencs/view/render/cameracontroller.cpp b/apps/opencs/view/render/cameracontroller.cpp index ec78db011..73d8aef52 100644 --- a/apps/opencs/view/render/cameracontroller.cpp +++ b/apps/opencs/view/render/cameracontroller.cpp @@ -15,6 +15,7 @@ #include #include "../../model/prefs/shortcut.hpp" +#include "../../model/prefs/shortcuteventhandler.hpp" #include "scenewidget.hpp" @@ -81,7 +82,25 @@ namespace CSVRender mActive = (mCamera != NULL); if (mActive) + { onActivate(); + + QList shortcuts = findChildren(); + + for (QList::iterator it = shortcuts.begin(); it != shortcuts.end(); ++it) + { + (*it)->enable(true); + } + } + else + { + QList shortcuts = findChildren(); + + for (QList::iterator it = shortcuts.begin(); it != shortcuts.end(); ++it) + { + (*it)->enable(false); + } + } } void CameraController::setCameraSensitivity(double value) @@ -144,7 +163,7 @@ namespace CSVRender Free Camera Controller */ - FreeCameraController::FreeCameraController(SceneWidget* scene) + FreeCameraController::FreeCameraController(CSMPrefs::ShortcutEventHandler* handler) : mLockUpright(false) , mModified(false) , mFast(false) @@ -160,31 +179,38 @@ namespace CSVRender , mSpeedMult(8) { CSMPrefs::Shortcut* forwardShortcut = new CSMPrefs::Shortcut("free-forward", this); - scene->addShortcut(forwardShortcut); + forwardShortcut->enable(false); + handler->addShortcut(forwardShortcut); connect(forwardShortcut, SIGNAL(activated(bool)), this, SLOT(forward(bool))); CSMPrefs::Shortcut* leftShortcut = new CSMPrefs::Shortcut("free-left", this); - scene->addShortcut(leftShortcut); + leftShortcut->enable(false); + handler->addShortcut(leftShortcut); connect(leftShortcut, SIGNAL(activated(bool)), this, SLOT(left(bool))); CSMPrefs::Shortcut* backShortcut = new CSMPrefs::Shortcut("free-backward", this); - scene->addShortcut(backShortcut); + backShortcut->enable(false); + handler->addShortcut(backShortcut); connect(backShortcut, SIGNAL(activated(bool)), this, SLOT(backward(bool))); CSMPrefs::Shortcut* rightShortcut = new CSMPrefs::Shortcut("free-right", this); - scene->addShortcut(rightShortcut); + rightShortcut->enable(false); + handler->addShortcut(rightShortcut); connect(rightShortcut, SIGNAL(activated(bool)), this, SLOT(right(bool))); CSMPrefs::Shortcut* rollLeftShortcut = new CSMPrefs::Shortcut("free-roll-left", this); - scene->addShortcut(rollLeftShortcut); + rollLeftShortcut->enable(false); + handler->addShortcut(rollLeftShortcut); connect(rollLeftShortcut, SIGNAL(activated(bool)), this, SLOT(rollLeft(bool))); CSMPrefs::Shortcut* rollRightShortcut = new CSMPrefs::Shortcut("free-roll-right", this); - scene->addShortcut(rollRightShortcut); + rollRightShortcut->enable(false); + handler->addShortcut(rollRightShortcut); connect(rollRightShortcut, SIGNAL(activated(bool)), this, SLOT(rollRight(bool))); CSMPrefs::Shortcut* speedModeShortcut = new CSMPrefs::Shortcut("free-speed-mode", this); - scene->addShortcut(speedModeShortcut); + speedModeShortcut->enable(false); + handler->addShortcut(speedModeShortcut); connect(speedModeShortcut, SIGNAL(activated(bool)), this, SLOT(swapSpeedMode(bool))); } @@ -230,14 +256,6 @@ namespace CSVRender mLockUpright = false; } - bool FreeCameraController::handleKeyEvent(QKeyEvent* event, bool pressed) - { - if (!isActive()) - return false; - - return true; - } - bool FreeCameraController::handleMouseMoveEvent(std::string mode, int x, int y) { if (!isActive()) @@ -412,7 +430,7 @@ namespace CSVRender Orbit Camera Controller */ - OrbitCameraController::OrbitCameraController(SceneWidget* widget) + OrbitCameraController::OrbitCameraController(CSMPrefs::ShortcutEventHandler* handler) : mInitialized(false) , mFast(false) , mLeft(false) @@ -427,6 +445,40 @@ namespace CSVRender , mOrbitSpeed(osg::PI / 4) , mOrbitSpeedMult(4) { + CSMPrefs::Shortcut* upShortcut = new CSMPrefs::Shortcut("orbit-up", this); + upShortcut->enable(false); + handler->addShortcut(upShortcut); + connect(upShortcut, SIGNAL(activated(bool)), this, SLOT(up(bool))); + + CSMPrefs::Shortcut* leftShortcut = new CSMPrefs::Shortcut("orbit-left", this); + leftShortcut->enable(false); + handler->addShortcut(leftShortcut); + connect(leftShortcut, SIGNAL(activated(bool)), this, SLOT(left(bool))); + + CSMPrefs::Shortcut* downShortcut = new CSMPrefs::Shortcut("orbit-down", this); + downShortcut->enable(false); + handler->addShortcut(downShortcut); + connect(downShortcut, SIGNAL(activated(bool)), this, SLOT(down(bool))); + + CSMPrefs::Shortcut* rightShortcut = new CSMPrefs::Shortcut("orbit-right", this); + rightShortcut->enable(false); + handler->addShortcut(rightShortcut); + connect(rightShortcut, SIGNAL(activated(bool)), this, SLOT(right(bool))); + + CSMPrefs::Shortcut* rollLeftShortcut = new CSMPrefs::Shortcut("orbit-roll-left", this); + rollLeftShortcut->enable(false); + handler->addShortcut(rollLeftShortcut); + connect(rollLeftShortcut, SIGNAL(activated(bool)), this, SLOT(rollLeft(bool))); + + CSMPrefs::Shortcut* rollRightShortcut = new CSMPrefs::Shortcut("orbit-roll-right", this); + rollRightShortcut->enable(false); + handler->addShortcut(rollRightShortcut); + connect(rollRightShortcut, SIGNAL(activated(bool)), this, SLOT(rollRight(bool))); + + CSMPrefs::Shortcut* speedModeShortcut = new CSMPrefs::Shortcut("orbit-speed-mode", this); + speedModeShortcut->enable(false); + handler->addShortcut(speedModeShortcut); + connect(speedModeShortcut, SIGNAL(activated(bool)), this, SLOT(swapSpeedMode(bool))); } osg::Vec3d OrbitCameraController::getCenter() const @@ -477,50 +529,6 @@ namespace CSVRender mPickingMask = value; } - bool OrbitCameraController::handleKeyEvent(QKeyEvent* event, bool pressed) - { - if (!isActive()) - return false; - - if (!mInitialized) - initialize(); - - if (event->key() == Qt::Key_Q) - { - mRollLeft = pressed; - } - else if (event->key() == Qt::Key_E) - { - mRollRight = pressed; - } - else if (event->key() == Qt::Key_A) - { - mLeft = pressed; - } - else if (event->key() == Qt::Key_D) - { - mRight = pressed; - } - else if (event->key() == Qt::Key_W) - { - mUp = pressed; - } - else if (event->key() == Qt::Key_S) - { - mDown = pressed; - } - else if (event->key() == Qt::Key_Shift) - { - mFast = pressed; - } - else - { - return false; - } - - return true; - } - bool OrbitCameraController::handleMouseMoveEvent(std::string mode, int x, int y) { if (!isActive()) @@ -687,4 +695,46 @@ namespace CSVRender getCamera()->setViewMatrixAsLookAt(mCenter + offset, mCenter, up); } + + void OrbitCameraController::up(bool active) + { + if (isActive()) + mUp = active; + } + + void OrbitCameraController::left(bool active) + { + if (isActive()) + mLeft = active; + } + + void OrbitCameraController::down(bool active) + { + if (isActive()) + mDown = active; + } + + void OrbitCameraController::right(bool active) + { + if (isActive()) + mRight = active; + } + + void OrbitCameraController::rollLeft(bool active) + { + if (isActive()) + mRollLeft = active; + } + + void OrbitCameraController::rollRight(bool active) + { + if (isActive()) + mRollRight = active; + } + + void OrbitCameraController::swapSpeedMode(bool active) + { + if (isActive() && active) + mFast = !mFast; + } } diff --git a/apps/opencs/view/render/cameracontroller.hpp b/apps/opencs/view/render/cameracontroller.hpp index 2131e1f02..297a58f58 100644 --- a/apps/opencs/view/render/cameracontroller.hpp +++ b/apps/opencs/view/render/cameracontroller.hpp @@ -16,6 +16,11 @@ namespace osg class Group; } +namespace CSMPrefs +{ + class ShortcutEventHandler; +} + namespace CSVRender { class SceneWidget; @@ -52,7 +57,6 @@ namespace CSVRender // moves the camera to an intelligent position void setup(osg::Group* root, unsigned int mask, const osg::Vec3d& up); - virtual bool handleKeyEvent(QKeyEvent* event, bool pressed) = 0; virtual bool handleMouseMoveEvent(std::string mode, int x, int y) = 0; virtual void update(double dt) = 0; @@ -79,7 +83,7 @@ namespace CSVRender public: - FreeCameraController(SceneWidget* widget); + FreeCameraController(CSMPrefs::ShortcutEventHandler* handler); double getLinearSpeed() const; double getRotationalSpeed() const; @@ -92,7 +96,6 @@ namespace CSVRender void fixUpAxis(const osg::Vec3d& up); void unfixUpAxis(); - bool handleKeyEvent(QKeyEvent* event, bool pressed); bool handleMouseMoveEvent(std::string mode, int x, int y); void update(double dt); @@ -133,7 +136,7 @@ namespace CSVRender public: - OrbitCameraController(SceneWidget* widget); + OrbitCameraController(CSMPrefs::ShortcutEventHandler* handler); osg::Vec3d getCenter() const; double getOrbitSpeed() const; @@ -145,7 +148,6 @@ namespace CSVRender void setOrbitSpeedMultiplier(double value); void setPickingMask(unsigned int value); - bool handleKeyEvent(QKeyEvent* event, bool pressed); bool handleMouseMoveEvent(std::string mode, int x, int y); void update(double dt); @@ -172,6 +174,16 @@ namespace CSVRender double mOrbitSpeed; double mOrbitSpeedMult; + + private slots: + + void up(bool active); + void left(bool active); + void down(bool active); + void right(bool active); + void rollLeft(bool active); + void rollRight(bool active); + void swapSpeedMode(bool active); }; } diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index 48fe4abdc..bb1ca4008 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -20,6 +20,7 @@ #include "../../model/prefs/state.hpp" #include "../../model/prefs/shortcut.hpp" +#include "../../model/prefs/shortcuteventhandler.hpp" #include "lighting.hpp" #include "mask.hpp" @@ -159,13 +160,13 @@ SceneWidget::SceneWidget(boost::shared_ptr resourceSys , mHasDefaultAmbient(false) , mPrevMouseX(0) , mPrevMouseY(0) - , mFreeCamControl(0) - , mOrbitCamControl(0) - , mCurrentCamControl(0) , mCamPositionSet(false) { - mFreeCamControl.reset(new FreeCameraController(this)); - mOrbitCamControl.reset(new OrbitCameraController(this)); + mShortcutHandler = new CSMPrefs::ShortcutEventHandler(this); + installEventFilter(mShortcutHandler); + + mFreeCamControl.reset(new FreeCameraController(mShortcutHandler)); + mOrbitCamControl.reset(new OrbitCameraController(mShortcutHandler)); mCurrentCamControl = mFreeCamControl.get(); mOrbitCamControl->setPickingMask(Mask_Reference | Mask_Terrain); @@ -201,6 +202,8 @@ SceneWidget::SceneWidget(boost::shared_ptr resourceSys SceneWidget::~SceneWidget() { + removeEventFilter(mShortcutHandler); + // Since we're holding on to the scene templates past the existance of this graphics context, we'll need to manually release the created objects mResourceSystem->getSceneManager()->releaseGLObjects(mView->getCamera()->getGraphicsContext()->getState()); } @@ -276,57 +279,17 @@ void SceneWidget::setDefaultAmbient (const osg::Vec4f& colour) setAmbient(mLighting->getAmbientColour(&mDefaultAmbient)); } -bool SceneWidget::event(QEvent *event) -{ - if (event->type() == QEvent::KeyPress) - { - QKeyEvent* keyEvent = static_cast(event); - SceneWidget::keyPressEvent(keyEvent); - } - else if (event->type() == QEvent::KeyRelease) - { - QKeyEvent* keyEvent = static_cast(event); - SceneWidget::keyReleaseEvent(keyEvent); - } - else if (event->type() == QEvent::MouseButtonPress) - { - QMouseEvent* keyEvent = static_cast(event); - SceneWidget::mousePressEvent(keyEvent); - } - else if (event->type() == QEvent::MouseButtonRelease) - { - QMouseEvent* keyEvent = static_cast(event); - SceneWidget::mouseReleaseEvent(keyEvent); - } - else - { - return RenderWidget::event(event); - } - - return true; -} - void SceneWidget::mousePressEvent (QMouseEvent *event) { mMouseMode = mapButton(event); mPrevMouseX = event->x(); mPrevMouseY = event->y(); - - for (std::vector::iterator it = mShortcuts.begin(); it != mShortcuts.end(); ++it) - { - (*it)->mousePressEvent(event); - } } void SceneWidget::mouseReleaseEvent (QMouseEvent *event) { mMouseMode = ""; - - for (std::vector::iterator it = mShortcuts.begin(); it != mShortcuts.end(); ++it) - { - (*it)->mouseReleaseEvent(event); - } } void SceneWidget::mouseMoveEvent (QMouseEvent *event) @@ -347,26 +310,6 @@ void SceneWidget::wheelEvent(QWheelEvent *event) mCurrentCamControl->handleMouseMoveEvent("t-navi", event->delta(), 0); } -void SceneWidget::keyPressEvent (QKeyEvent *event) -{ - mCurrentCamControl->handleKeyEvent(event, true); - - for (std::vector::iterator it = mShortcuts.begin(); it != mShortcuts.end(); ++it) - { - (*it)->keyPressEvent(event); - } -} - -void SceneWidget::keyReleaseEvent (QKeyEvent *event) -{ - mCurrentCamControl->handleKeyEvent(event, false); - - for (std::vector::iterator it = mShortcuts.begin(); it != mShortcuts.end(); ++it) - { - (*it)->keyReleaseEvent(event); - } -} - void SceneWidget::update(double dt) { if (mCamPositionSet) @@ -508,9 +451,4 @@ std::string SceneWidget::mapButton (QMouseEvent *event) return ""; } -void SceneWidget::addShortcut(CSMPrefs::Shortcut* shortcut) -{ - mShortcuts.push_back(shortcut); -} - } diff --git a/apps/opencs/view/render/scenewidget.hpp b/apps/opencs/view/render/scenewidget.hpp index 0744cc645..07f5f03cf 100644 --- a/apps/opencs/view/render/scenewidget.hpp +++ b/apps/opencs/view/render/scenewidget.hpp @@ -7,14 +7,15 @@ #include #include +#include +#include + #include #include "lightingday.hpp" #include "lightingnight.hpp" #include "lightingbright.hpp" -#include -#include namespace Resource { @@ -37,6 +38,7 @@ namespace CSMPrefs { class Setting; class Shortcut; + class ShortcutEventHandler; } namespace CSVRender @@ -85,21 +87,16 @@ namespace CSVRender void setDefaultAmbient (const osg::Vec4f& colour); ///< \note The actual ambient colour may differ based on lighting settings. - void addShortcut(CSMPrefs::Shortcut* shortcut); - protected: void setLighting (Lighting *lighting); ///< \attention The ownership of \a lighting is not transferred to *this. void setAmbient(const osg::Vec4f& ambient); - virtual bool event(QEvent *event); virtual void mousePressEvent (QMouseEvent *event); virtual void mouseReleaseEvent (QMouseEvent *event); virtual void mouseMoveEvent (QMouseEvent *event); virtual void wheelEvent (QWheelEvent *event); - virtual void keyPressEvent (QKeyEvent *event); - virtual void keyReleaseEvent (QKeyEvent *event); virtual void focusOutEvent (QFocusEvent *event); /// \return Is \a key a button mapping setting? (ignored otherwise) @@ -124,7 +121,7 @@ namespace CSVRender CameraController* mCurrentCamControl; std::map, std::string> mButtonMapping; - std::vector mShortcuts; + CSMPrefs::ShortcutEventHandler *mShortcutHandler; private: bool mCamPositionSet;