mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 06:53:53 +00:00
Changed shortcut design to allow a configurable second output. Also
re-added shift for temporarily changing camera speed.
This commit is contained in:
parent
1b5273f2b7
commit
455d227f3c
12 changed files with 335 additions and 88 deletions
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -41,10 +41,11 @@ namespace CSMPrefs
|
|||
else if (event->type() == QEvent::KeyRelease)
|
||||
{
|
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(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<QMouseEvent*>(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<Shortcut*>::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<Shortcut*>::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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,23 +17,26 @@ namespace CSMPrefs
|
|||
|
||||
public:
|
||||
|
||||
/// Key Sequence, Modifier (for secondary signal)
|
||||
typedef std::pair<QKeySequence, int> 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<std::string, Shortcut*> ShortcutMap;
|
||||
typedef std::map<std::string, QKeySequence> SequenceMap;
|
||||
typedef std::map<std::string, SequenceData> SequenceMap;
|
||||
|
||||
ShortcutMap mShortcuts;
|
||||
SequenceMap mSequences;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -11,16 +11,20 @@ namespace CSMPrefs
|
|||
{
|
||||
Q_OBJECT
|
||||
|
||||
QKeySequence mDefault;
|
||||
|
||||
public:
|
||||
|
||||
typedef std::pair<QKeySequence, int> 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<QWidget*, QWidget*> makeWidgets(QWidget* parent);
|
||||
|
||||
private:
|
||||
|
||||
SequenceData mDefault;
|
||||
|
||||
private slots:
|
||||
|
||||
void valueChanged(const QString& text);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue