From 455d227f3c6eeb727b9aa805b7307ef01162c81a Mon Sep 17 00:00:00 2001 From: Aesylwinn Date: Fri, 22 Jul 2016 01:58:17 -0400 Subject: [PATCH] Changed shortcut design to allow a configurable second output. Also re-added shift for temporarily changing camera speed. --- apps/opencs/model/prefs/shortcut.cpp | 81 ++++++++++---- apps/opencs/model/prefs/shortcut.hpp | 52 +++++++-- .../model/prefs/shortcuteventhandler.cpp | 105 +++++++++++++++--- .../model/prefs/shortcuteventhandler.hpp | 4 +- apps/opencs/model/prefs/shortcutmanager.cpp | 102 +++++++++++++---- apps/opencs/model/prefs/shortcutmanager.hpp | 13 ++- apps/opencs/model/prefs/shortcutsetting.cpp | 6 +- apps/opencs/model/prefs/shortcutsetting.hpp | 10 +- apps/opencs/model/prefs/state.cpp | 12 +- apps/opencs/model/prefs/state.hpp | 3 +- apps/opencs/view/render/cameracontroller.cpp | 27 ++++- apps/opencs/view/render/cameracontroller.hpp | 8 +- 12 files changed, 335 insertions(+), 88 deletions(-) diff --git a/apps/opencs/model/prefs/shortcut.cpp b/apps/opencs/model/prefs/shortcut.cpp index b8820ae8b6..4aa6f0d846 100644 --- a/apps/opencs/model/prefs/shortcut.cpp +++ b/apps/opencs/model/prefs/shortcut.cpp @@ -11,14 +11,36 @@ namespace CSMPrefs { Shortcut::Shortcut(const std::string& name, QObject* parent) : QObject(parent) + , mEnabled(true) , mName(name) + , mSecondaryMode(SM_Ignore) + , mModifier(0) , mCurrentPos(0) , mLastPos(0) - , mActive(false) - , mEnabled(true) + , mActivationStatus(AS_Inactive) + , mModifierStatus(false) { State::get().getShortcutManager().addShortcut(this); - setSequence(State::get().getShortcutManager().getSequence(name)); + ShortcutManager::SequenceData data = State::get().getShortcutManager().getSequence(name); + setSequence(data.first); + setModifier(data.second); + } + + Shortcut::Shortcut(const std::string& name, SecondaryMode secMode, QObject* parent) + : QObject(parent) + , mEnabled(true) + , mName(name) + , mSecondaryMode(secMode) + , mModifier(0) + , mCurrentPos(0) + , mLastPos(0) + , mActivationStatus(AS_Inactive) + , mModifierStatus(false) + { + State::get().getShortcutManager().addShortcut(this); + ShortcutManager::SequenceData data = State::get().getShortcutManager().getSequence(name); + setSequence(data.first); + setModifier(data.second); } Shortcut::~Shortcut() @@ -26,11 +48,6 @@ namespace CSMPrefs State::get().getShortcutManager().removeShortcut(this); } - bool Shortcut::isActive() const - { - return mActive; - } - bool Shortcut::isEnabled() const { return mEnabled; @@ -41,11 +58,21 @@ namespace CSMPrefs return mName; } + Shortcut::SecondaryMode Shortcut::getSecondaryMode() const + { + return mSecondaryMode; + } + const QKeySequence& Shortcut::getSequence() const { return mSequence; } + int Shortcut::getModifier() const + { + return mModifier; + } + int Shortcut::getPosition() const { return mCurrentPos; @@ -56,9 +83,19 @@ namespace CSMPrefs return mLastPos; } - void Shortcut::setPosition(int pos) + Shortcut::ActivationStatus Shortcut::getActivationStatus() const { - mCurrentPos = pos; + return mActivationStatus; + } + + bool Shortcut::getModifierStatus() const + { + return mModifierStatus; + } + + void Shortcut::enable(bool state) + { + mEnabled = state; } void Shortcut::setSequence(const QKeySequence& sequence) @@ -68,22 +105,28 @@ namespace CSMPrefs mLastPos = sequence.count() - 1; } - void Shortcut::activate(bool state) + void Shortcut::setModifier(int modifier) { - mActive = state; - emit activated(state); - - if (state) - emit activated(); + mModifier = modifier; } - void Shortcut::enable(bool state) + void Shortcut::setPosition(int pos) { - mEnabled = state; + mCurrentPos = pos; + } + + void Shortcut::setActivationStatus(ActivationStatus status) + { + mActivationStatus = status; + } + + void Shortcut::setModifierStatus(bool status) + { + mModifierStatus = status; } QString Shortcut::toString() const { - return QString(State::get().getShortcutManager().sequenceToString(mSequence).data()); + return QString(State::get().getShortcutManager().sequenceToString(std::make_pair(mSequence, mModifier)).data()); } } diff --git a/apps/opencs/model/prefs/shortcut.hpp b/apps/opencs/model/prefs/shortcut.hpp index 25bb135566..491cd76679 100644 --- a/apps/opencs/model/prefs/shortcut.hpp +++ b/apps/opencs/model/prefs/shortcut.hpp @@ -20,45 +20,83 @@ namespace CSMPrefs public: + enum ActivationStatus + { + AS_Regular, + AS_Secondary, + AS_Inactive + }; + + enum SecondaryMode + { + SM_Replace, ///< The secondary signal replaces the regular signal when the modifier is active + SM_Detach, ///< The secondary signal is emitted independant of the regular signal, even if not active + SM_Ignore ///< The secondary signal will not ever be emitted + }; + Shortcut(const std::string& name, QObject* parent); + Shortcut(const std::string& name, SecondaryMode secMode, QObject* parent); + ~Shortcut(); - bool isActive() const; bool isEnabled() const; const std::string& getName() const; + SecondaryMode getSecondaryMode() const; + const QKeySequence& getSequence() const; + int getModifier() const; + /// The position in the sequence int getPosition() const; /// The position in the sequence int getLastPosition() const; + ActivationStatus getActivationStatus() const; + bool getModifierStatus() const; + + void enable(bool state); + void setSequence(const QKeySequence& sequence); + void setModifier(int modifier); + /// The position in the sequence void setPosition(int pos); - void activate(bool state); - void enable(bool state); + void setActivationStatus(ActivationStatus status); + void setModifierStatus(bool status); QString toString() const; private: + bool mEnabled; + std::string mName; + SecondaryMode mSecondaryMode; QKeySequence mSequence; + int mModifier; + int mCurrentPos; int mLastPos; - bool mActive; - bool mEnabled; + ActivationStatus mActivationStatus; + bool mModifierStatus; + signals: - /// Triggered when the shortcut is activated or deactived; can be determined from \p state + /// Triggered when the shortcut is activated or deactivated; can be determined from \p state void activated(bool state); - /// Trigger when activated; convenience signal. + /// Convenience signal. void activated(); + + /// Triggered depending on SecondaryMode + void secondary(bool state); + + /// Convenience signal. + void secondary(); }; } diff --git a/apps/opencs/model/prefs/shortcuteventhandler.cpp b/apps/opencs/model/prefs/shortcuteventhandler.cpp index 3119623ae2..0537c53a20 100644 --- a/apps/opencs/model/prefs/shortcuteventhandler.cpp +++ b/apps/opencs/model/prefs/shortcuteventhandler.cpp @@ -41,10 +41,11 @@ namespace CSMPrefs else if (event->type() == QEvent::KeyRelease) { QKeyEvent* keyEvent = static_cast(event); + unsigned int mod = (unsigned int) keyEvent->modifiers(); unsigned int key = (unsigned int) keyEvent->key(); if (!keyEvent->isAutoRepeat()) - return deactivate(key); + return deactivate(mod, key); } else if (event->type() == QEvent::MouseButtonPress) { @@ -57,9 +58,10 @@ namespace CSMPrefs else if (event->type() == QEvent::MouseButtonRelease) { QMouseEvent* mouseEvent = static_cast(event); + unsigned int mod = (unsigned int) mouseEvent->modifiers(); unsigned int button = (unsigned int) mouseEvent->button(); - return deactivate(button); + return deactivate(mod, button); } else if (event->type() == QEvent::FocusOut) { @@ -68,10 +70,18 @@ namespace CSMPrefs { Shortcut* shortcut = *it; - if (shortcut->isActive()) + shortcut->setPosition(0); + shortcut->setModifierStatus(false); + + if (shortcut->getActivationStatus() == Shortcut::AS_Regular) { - shortcut->activate(false); - shortcut->setPosition(0); + shortcut->setActivationStatus(Shortcut::AS_Inactive); + emit shortcut->activated(false); + } + else if (shortcut->getActivationStatus() == Shortcut::AS_Secondary) + { + shortcut->setActivationStatus(Shortcut::AS_Inactive); + emit shortcut->secondary(false); } } } @@ -88,39 +98,56 @@ namespace CSMPrefs 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; + int pos = shortcut->getPosition(); + int lastPos = shortcut->getLastPosition(); + MatchResult result = match(mod, button, shortcut->getSequence()[pos]); + 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)); } } + + if (checkModifier(mod, button, shortcut, true)) + used = true; } // 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); + Shortcut* shortcut = potentials.front().second; + + if (shortcut->getModifierStatus() && shortcut->getSecondaryMode() == Shortcut::SM_Replace) + { + shortcut->setActivationStatus(Shortcut::AS_Secondary); + emit shortcut->secondary(true); + emit shortcut->secondary(); + } + else + { + shortcut->setActivationStatus(Shortcut::AS_Regular); + emit shortcut->activated(true); + emit shortcut->activated(); + } + used = true; } return used; } - bool ShortcutEventHandler::deactivate(unsigned int button) + bool ShortcutEventHandler::deactivate(unsigned int mod, unsigned int button) { const int KeyMask = 0x01FFFFFF; @@ -129,16 +156,66 @@ namespace CSMPrefs for (std::vector::iterator it = mShortcuts.begin(); it != mShortcuts.end(); ++it) { Shortcut* shortcut = *it; + + if (checkModifier(mod, button, shortcut, false)) + used = true; + 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); + if (shortcut->getActivationStatus() == Shortcut::AS_Regular) + { + shortcut->setActivationStatus(Shortcut::AS_Inactive); + emit shortcut->activated(false); + used = true; + } + else if (shortcut->getActivationStatus() == Shortcut::AS_Secondary) + { + shortcut->setActivationStatus(Shortcut::AS_Inactive); + emit shortcut->secondary(false); + used = true; + } + } + } + + return used; + } + + bool ShortcutEventHandler::checkModifier(unsigned int mod, unsigned int button, Shortcut* shortcut, bool activate) + { + if (!shortcut->isEnabled() || !shortcut->getModifier() || shortcut->getSecondaryMode() == Shortcut::SM_Ignore) + return false; + + MatchResult result = match(mod, button, shortcut->getModifier()); + bool used = false; + + if (result != Matches_Not) + { + shortcut->setModifierStatus(activate); + + if (shortcut->getSecondaryMode() == Shortcut::SM_Detach) + { + if (activate) + { + emit shortcut->secondary(true); + emit shortcut->secondary(); + } + else + { + emit shortcut->secondary(false); + } + + used = true; + } + else if (!activate && shortcut->getActivationStatus() == Shortcut::AS_Secondary) + { + shortcut->setActivationStatus(Shortcut::AS_Inactive); + shortcut->setPosition(0); + emit shortcut->secondary(false); used = true; } } diff --git a/apps/opencs/model/prefs/shortcuteventhandler.hpp b/apps/opencs/model/prefs/shortcuteventhandler.hpp index c1ce48f7e4..d6a0d16ec6 100644 --- a/apps/opencs/model/prefs/shortcuteventhandler.hpp +++ b/apps/opencs/model/prefs/shortcuteventhandler.hpp @@ -39,7 +39,9 @@ namespace CSMPrefs bool activate(unsigned int mod, unsigned int button); - bool deactivate(unsigned int button); + bool deactivate(unsigned int mod, unsigned int button); + + bool checkModifier(unsigned int mod, unsigned int button, Shortcut* shortcut, bool activate); MatchResult match(unsigned int mod, unsigned int button, unsigned int value); diff --git a/apps/opencs/model/prefs/shortcutmanager.cpp b/apps/opencs/model/prefs/shortcutmanager.cpp index a4b9b18186..198804b3dd 100644 --- a/apps/opencs/model/prefs/shortcutmanager.cpp +++ b/apps/opencs/model/prefs/shortcutmanager.cpp @@ -33,31 +33,31 @@ namespace CSMPrefs } } - QKeySequence ShortcutManager::getSequence(const std::string& name) const + ShortcutManager::SequenceData ShortcutManager::getSequence(const std::string& name) const { - QKeySequence sequence; + SequenceData data; SequenceMap::const_iterator item = mSequences.find(name); if (item != mSequences.end()) { - sequence = item->second; + data = item->second; } - return sequence; + return data; } - void ShortcutManager::setSequence(const std::string& name, const QKeySequence& sequence) + void ShortcutManager::setSequence(const std::string& name, const SequenceData& data) { // Add to map/modify SequenceMap::iterator item = mSequences.find(name); if (item != mSequences.end()) { - item->second = sequence; + item->second = data; } else { - mSequences.insert(std::make_pair(name, sequence)); + mSequences.insert(std::make_pair(name, data)); } // Change active shortcuts @@ -65,11 +65,12 @@ namespace CSMPrefs for (ShortcutMap::iterator it = rangeS.first; it != rangeS.second; ++it) { - it->second->setSequence(sequence); + it->second->setSequence(data.first); + it->second->setModifier(data.second); } } - std::string ShortcutManager::sequenceToString(const QKeySequence& seq) + std::string ShortcutManager::sequenceToString(const SequenceData& data) { const int MouseMask = 0x0000001F; // Conflicts with key const int KeyMask = 0x01FFFFFF; @@ -80,27 +81,28 @@ namespace CSMPrefs std::string output; - for (int i = 0; i < seq.count(); ++i) + // KeySequence + for (unsigned int i = 0; i < data.first.count(); ++i) { - if (seq[i] & ModMask) + if (data.first[i] & ModMask) { // TODO separate out modifiers to allow more than 1 - output.append(staticQtMetaObject.enumerator(ModEnumIndex).valueToKey(seq[i] & ModMask)); + output.append(staticQtMetaObject.enumerator(ModEnumIndex).valueToKey(data.first[i] & ModMask)); output.append("+"); } - if (seq[i] & KeyMask & ~MouseMask) + if (data.first[i] & KeyMask & ~MouseMask) { // Is a key - output.append(staticQtMetaObject.enumerator(KeyEnumIndex).valueToKey(seq[i] & KeyMask)); + output.append(staticQtMetaObject.enumerator(KeyEnumIndex).valueToKey(data.first[i] & KeyMask)); output.append(","); } - else if (seq[i] & MouseMask) + else if (data.first[i] & MouseMask) { std::stringstream ss; std::string num; - unsigned int value = (unsigned int)(seq[i] & MouseMask); + unsigned int value = (unsigned int)(data.first[i] & MouseMask); // value will never be 0 int exponent = 1; // Offset by 1 @@ -123,18 +125,56 @@ namespace CSMPrefs output.resize(output.size() - 1); } + // Add modifier if needed + if (data.second & ModMask) + { + output.append(";"); + output.append(staticQtMetaObject.enumerator(ModEnumIndex).valueToKey(data.second & ModMask)); + } + else if (data.second & KeyMask & ~MouseMask) + { + output.append(";"); + output.append(staticQtMetaObject.enumerator(KeyEnumIndex).valueToKey(data.second & KeyMask)); + } + else if (data.second & MouseMask) + { + std::stringstream ss; + std::string num; + + unsigned int value = (unsigned int)(data.second & MouseMask); + + // value will never be 0 + int exponent = 1; // Offset by 1 + while (value >>= 1) + ++exponent; + + ss << exponent; + ss >> num; + + // Is a mouse button + output.append(";Mouse"); + output.append(num); + } + return output; } - QKeySequence ShortcutManager::stringToSequence(const std::string& input) + ShortcutManager::SequenceData ShortcutManager::stringToSequence(const std::string& input) { + // TODO clean and standardize + const int KeyEnumIndex = staticQtMetaObject.indexOfEnumerator("Key"); const int ModEnumIndex = staticQtMetaObject.indexOfEnumerator("KeyboardModifiers"); int keys[4] = { 0, 0, 0, 0 }; + int modifier = 0; + + size_t middle = input.find(';'); + std::string sequenceStr = input.substr(0, middle); + std::string modifierStr = input.substr((middle < input.size())? middle + 1 : input.size()); QRegExp splitRX("[, ]"); - QStringList keyStrs = QString(input.c_str()).split(splitRX, QString::SkipEmptyParts); + QStringList keyStrs = QString(sequenceStr.c_str()).split(splitRX, QString::SkipEmptyParts); for (int i = 0; i < keyStrs.size(); ++i) { @@ -162,9 +202,29 @@ namespace CSMPrefs } } - // TODO remove - std::cout << input << '.' << keys[0] << '.'<< keys[1] << '.'<< keys[2] << '.'<< keys[3] << std::endl; + if (!modifierStr.empty()) + { + if (modifierStr.find("Mouse") != std::string::npos) + { + QString num = QString::fromUtf8(modifierStr.substr(5).data()); + if (num > 0) + { + modifier = 1 << (num.toInt() - 1); // offset by 1 + } + } + else if (staticQtMetaObject.enumerator(ModEnumIndex).keyToValue(modifierStr.data()) != -1) + { + modifier = staticQtMetaObject.enumerator(ModEnumIndex).keyToValue(modifierStr.data()); + } + else if (staticQtMetaObject.enumerator(KeyEnumIndex).keyToValue(modifierStr.data()) != -1) + { + modifier = staticQtMetaObject.enumerator(KeyEnumIndex).keyToValue(modifierStr.data()); + } + } - return QKeySequence(keys[0], keys[1], keys[2], keys[3]); + // TODO remove + std::cout << input << '.' << keys[0] << '.'<< keys[1] << '.'<< keys[2] << '.'<< keys[3] << '.' << modifier << std::endl; + + return std::make_pair(QKeySequence(keys[0], keys[1], keys[2], keys[3]), modifier); } } diff --git a/apps/opencs/model/prefs/shortcutmanager.hpp b/apps/opencs/model/prefs/shortcutmanager.hpp index 2510ec77e7..60cdefe36b 100644 --- a/apps/opencs/model/prefs/shortcutmanager.hpp +++ b/apps/opencs/model/prefs/shortcutmanager.hpp @@ -17,23 +17,26 @@ namespace CSMPrefs public: + /// Key Sequence, Modifier (for secondary signal) + typedef std::pair SequenceData; + /// The shortcut class will do this automatically void addShortcut(Shortcut* shortcut); /// The shortcut class will do this automatically void removeShortcut(Shortcut* shortcut); - QKeySequence getSequence(const std::string& name) const; - void setSequence(const std::string& name, const QKeySequence& sequence); + SequenceData getSequence(const std::string& name) const; + void setSequence(const std::string& name, const SequenceData& sequence); - std::string sequenceToString(const QKeySequence& sequence); - QKeySequence stringToSequence(const std::string& str); + std::string sequenceToString(const SequenceData& sequence); + SequenceData stringToSequence(const std::string& str); private: // Need a multimap in case multiple shortcuts share the same name typedef std::multimap ShortcutMap; - typedef std::map SequenceMap; + typedef std::map SequenceMap; ShortcutMap mShortcuts; SequenceMap mSequences; diff --git a/apps/opencs/model/prefs/shortcutsetting.cpp b/apps/opencs/model/prefs/shortcutsetting.cpp index 5b20082410..fa2628e328 100644 --- a/apps/opencs/model/prefs/shortcutsetting.cpp +++ b/apps/opencs/model/prefs/shortcutsetting.cpp @@ -10,7 +10,7 @@ namespace CSMPrefs { ShortcutSetting::ShortcutSetting(Category* parent, Settings::Manager* values, QMutex* mutex, const std::string& key, - const std::string& label, const QKeySequence& default_) + const std::string& label, const SequenceData& default_) : Setting(parent, values, mutex, key, label) , mDefault(default_) { @@ -33,9 +33,9 @@ namespace CSMPrefs QMutexLocker lock(getMutex()); getValues().setString(getKey(), getParent()->getKey(), text.toUtf8().data()); - QKeySequence sequence = State::get().getShortcutManager().stringToSequence(text.toUtf8().data()); + SequenceData data = State::get().getShortcutManager().stringToSequence(text.toUtf8().data()); - State::get().getShortcutManager().setSequence(getKey(), sequence); + State::get().getShortcutManager().setSequence(getKey(), data); } getParent()->getState()->update(*this); diff --git a/apps/opencs/model/prefs/shortcutsetting.hpp b/apps/opencs/model/prefs/shortcutsetting.hpp index 893b01f932..e1979c8006 100644 --- a/apps/opencs/model/prefs/shortcutsetting.hpp +++ b/apps/opencs/model/prefs/shortcutsetting.hpp @@ -11,16 +11,20 @@ namespace CSMPrefs { Q_OBJECT - QKeySequence mDefault; - public: + typedef std::pair SequenceData; + ShortcutSetting(Category* parent, Settings::Manager* values, QMutex* mutex, const std::string& key, - const std::string& label, const QKeySequence& default_); + const std::string& label, const SequenceData& default_); // TODO replace with custom page virtual std::pair makeWidgets(QWidget* parent); + private: + + SequenceData mDefault; + private slots: void valueChanged(const QString& text); diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 4172093800..cfb06f21a7 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -229,7 +229,7 @@ void CSMPrefs::State::declare() addValues (insertOutsideVisibleCell); declareCategory ("Key Bindings"); - declareShortcut ("free-forward", "Free camera forward", QKeySequence(Qt::Key_W)); + declareShortcut ("free-forward", "Free camera forward", QKeySequence(Qt::Key_W), Qt::Key_Shift); declareShortcut ("free-backward", "Free camera backward", QKeySequence(Qt::Key_S)); declareShortcut ("free-left", "Free camera left", QKeySequence(Qt::Key_A)); declareShortcut ("free-right", "Free camera right", QKeySequence(Qt::Key_D)); @@ -238,7 +238,7 @@ void CSMPrefs::State::declare() 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-up", "Orbit camera up", QKeySequence(Qt::Key_W), Qt::Key_Shift); 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)); @@ -377,19 +377,19 @@ CSMPrefs::ColourSetting& CSMPrefs::State::declareColour (const std::string& key, } CSMPrefs::ShortcutSetting& CSMPrefs::State::declareShortcut (const std::string& key, const std::string& label, - const QKeySequence& default_) + const QKeySequence& default_, int modifier) { if (mCurrentCategory==mCategories.end()) throw std::logic_error ("no category for setting"); - std::string seqStr = getShortcutManager().sequenceToString(default_); + std::string seqStr = getShortcutManager().sequenceToString(std::make_pair(default_, modifier)); setDefault (key, seqStr); - QKeySequence seq = getShortcutManager().stringToSequence(mSettings.getString(key, + ShortcutManager::SequenceData data = getShortcutManager().stringToSequence(mSettings.getString(key, mCurrentCategory->second.getKey())); CSMPrefs::ShortcutSetting *setting = new CSMPrefs::ShortcutSetting (&mCurrentCategory->second, &mSettings, &mMutex, - key, label, seq); + key, label, data); mCurrentCategory->second.addSetting (setting); diff --git a/apps/opencs/model/prefs/state.hpp b/apps/opencs/model/prefs/state.hpp index 15f6e6d1b0..4ab713167d 100644 --- a/apps/opencs/model/prefs/state.hpp +++ b/apps/opencs/model/prefs/state.hpp @@ -74,7 +74,8 @@ namespace CSMPrefs ColourSetting& declareColour (const std::string& key, const std::string& label, QColor default_); - ShortcutSetting& declareShortcut (const std::string& key, const std::string& label, const QKeySequence& default_); + ShortcutSetting& declareShortcut (const std::string& key, const std::string& label, + const QKeySequence& default_, int modifier=0); void declareSeparator(); diff --git a/apps/opencs/view/render/cameracontroller.cpp b/apps/opencs/view/render/cameracontroller.cpp index 642991b360..df71a9b88d 100644 --- a/apps/opencs/view/render/cameracontroller.cpp +++ b/apps/opencs/view/render/cameracontroller.cpp @@ -169,6 +169,7 @@ namespace CSVRender , mLockUpright(false) , mModified(false) , mFast(false) + , mFastAlternate(false) , mLeft(false) , mRight(false) , mForward(false) @@ -190,10 +191,12 @@ namespace CSVRender handler->addShortcut(naviSecondaryShortcut); connect(naviSecondaryShortcut, SIGNAL(activated(bool)), this, SLOT(naviSecondary(bool))); - CSMPrefs::Shortcut* forwardShortcut = new CSMPrefs::Shortcut("free-forward", this); + CSMPrefs::Shortcut* forwardShortcut = new CSMPrefs::Shortcut("free-forward", CSMPrefs::Shortcut::SM_Detach, + this); forwardShortcut->enable(false); handler->addShortcut(forwardShortcut); connect(forwardShortcut, SIGNAL(activated(bool)), this, SLOT(forward(bool))); + connect(forwardShortcut, SIGNAL(secondary(bool)), this, SLOT(alternateFast(bool))); CSMPrefs::Shortcut* leftShortcut = new CSMPrefs::Shortcut("free-left", this); leftShortcut->enable(false); @@ -294,7 +297,7 @@ namespace CSVRender if (!isActive()) return; - translate(LocalForward * x * (mFast ? getWheelMovementMultiplier() : 1)); + translate(LocalForward * x * ((mFast ^ mFastAlternate) ? getWheelMovementMultiplier() : 1)); } void FreeCameraController::update(double dt) @@ -305,7 +308,7 @@ namespace CSVRender double linDist = mLinSpeed * dt; double rotDist = mRotSpeed * dt; - if (mFast) + if (mFast ^ mFastAlternate) linDist *= mSpeedMult; if (mLeft) @@ -423,6 +426,11 @@ namespace CSVRender mRollRight = active; } + void FreeCameraController::alternateFast(bool active) + { + mFastAlternate = active; + } + void FreeCameraController::swapSpeedMode() { mFast = !mFast; @@ -436,6 +444,7 @@ namespace CSVRender : CameraController(parent) , mInitialized(false) , mFast(false) + , mFastAlternate(false) , mLeft(false) , mRight(false) , mUp(false) @@ -458,10 +467,11 @@ namespace CSVRender handler->addShortcut(naviSecondaryShortcut); connect(naviSecondaryShortcut, SIGNAL(activated(bool)), this, SLOT(naviSecondary(bool))); - CSMPrefs::Shortcut* upShortcut = new CSMPrefs::Shortcut("orbit-up", this); + CSMPrefs::Shortcut* upShortcut = new CSMPrefs::Shortcut("orbit-up", CSMPrefs::Shortcut::SM_Detach, this); upShortcut->enable(false); handler->addShortcut(upShortcut); connect(upShortcut, SIGNAL(activated(bool)), this, SLOT(up(bool))); + connect(upShortcut, SIGNAL(secondary(bool)), this, SLOT(alternateFast(bool))); CSMPrefs::Shortcut* leftShortcut = new CSMPrefs::Shortcut("orbit-left", this); leftShortcut->enable(false); @@ -571,7 +581,7 @@ namespace CSVRender if (!isActive()) return; - zoom(-x * (mFast ? getWheelMovementMultiplier() : 1)); + zoom(-x * ((mFast ^ mFastAlternate) ? getWheelMovementMultiplier() : 1)); } void OrbitCameraController::update(double dt) @@ -584,7 +594,7 @@ namespace CSVRender double rotDist = mOrbitSpeed * dt; - if (mFast) + if (mFast ^ mFastAlternate) rotDist *= mOrbitSpeedMult; if (mLeft) @@ -737,6 +747,11 @@ namespace CSVRender mRollRight = active; } + void OrbitCameraController::alternateFast(bool active) + { + mFastAlternate = active; + } + void OrbitCameraController::swapSpeedMode() { mFast = !mFast; diff --git a/apps/opencs/view/render/cameracontroller.hpp b/apps/opencs/view/render/cameracontroller.hpp index 7cca048d8e..45ccfc14e2 100644 --- a/apps/opencs/view/render/cameracontroller.hpp +++ b/apps/opencs/view/render/cameracontroller.hpp @@ -111,7 +111,8 @@ namespace CSVRender bool mLockUpright, mModified; bool mNaviPrimary, mNaviSecondary; - bool mFast, mLeft, mRight, mForward, mBackward, mRollLeft, mRollRight; + bool mFast, mFastAlternate; + bool mLeft, mRight, mForward, mBackward, mRollLeft, mRollRight; osg::Vec3d mUp; double mLinSpeed; @@ -128,6 +129,7 @@ namespace CSVRender void right(bool active); void rollLeft(bool active); void rollRight(bool active); + void alternateFast(bool active); void swapSpeedMode(); }; @@ -168,7 +170,8 @@ namespace CSVRender bool mInitialized; bool mNaviPrimary, mNaviSecondary; - bool mFast, mLeft, mRight, mUp, mDown, mRollLeft, mRollRight; + bool mFast, mFastAlternate; + bool mLeft, mRight, mUp, mDown, mRollLeft, mRollRight; unsigned int mPickingMask; osg::Vec3d mCenter; double mDistance; @@ -186,6 +189,7 @@ namespace CSVRender void right(bool active); void rollLeft(bool active); void rollRight(bool active); + void alternateFast(bool active); void swapSpeedMode(); }; }