From faa84e0a3565221538db8f343d90e994476991d0 Mon Sep 17 00:00:00 2001 From: Aesylwinn Date: Tue, 19 Jul 2016 22:04:15 -0400 Subject: [PATCH] - Further extended usage of new shortcut class - Refactored camera classes to take advantage of Qt's reference counting - Removed some of the old implementation --- .../model/prefs/shortcuteventhandler.cpp | 3 + apps/opencs/model/prefs/state.cpp | 14 ++ apps/opencs/view/render/cameracontroller.cpp | 110 ++++++---- apps/opencs/view/render/cameracontroller.hpp | 16 +- .../view/render/pagedworldspacewidget.cpp | 13 +- .../view/render/pagedworldspacewidget.hpp | 2 +- apps/opencs/view/render/scenewidget.cpp | 101 ++------- apps/opencs/view/render/scenewidget.hpp | 28 ++- apps/opencs/view/render/worldspacewidget.cpp | 202 +++++++++--------- apps/opencs/view/render/worldspacewidget.hpp | 51 +++-- 10 files changed, 265 insertions(+), 275 deletions(-) diff --git a/apps/opencs/model/prefs/shortcuteventhandler.cpp b/apps/opencs/model/prefs/shortcuteventhandler.cpp index 49b13ff99..3119623ae 100644 --- a/apps/opencs/model/prefs/shortcuteventhandler.cpp +++ b/apps/opencs/model/prefs/shortcuteventhandler.cpp @@ -69,7 +69,10 @@ namespace CSMPrefs Shortcut* shortcut = *it; if (shortcut->isActive()) + { shortcut->activate(false); + shortcut->setPosition(0); + } } } diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index abb5c7f18..6e47c8598 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -236,6 +236,7 @@ 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)); @@ -245,6 +246,19 @@ void CSMPrefs::State::declare() 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)); + + declareSeparator (); + declareShortcut ("scene-navi-primary", "Camera rotation from mouse movement", QKeySequence(Qt::LeftButton)); + declareShortcut ("scene-navi-secondary", "Camera translation from mouse movement", + QKeySequence(Qt::ControlModifier | (int)Qt::LeftButton)); + declareShortcut ("scene-edit-primary", "Scene primary edit button", QKeySequence(Qt::RightButton)); + declareShortcut ("scene-edit-secondary", "Scene secondary edit button", + QKeySequence(Qt::ControlModifier | (int)Qt::RightButton)); + declareShortcut ("scene-select-primary", "Scene primary select button", QKeySequence(Qt::MiddleButton)); + declareShortcut ("scene-select-secondary", "Scene secondary select button", + QKeySequence(Qt::ControlModifier | (int)Qt::MiddleButton)); + declareShortcut ("scene-edit-abort", "Scene editor abort key", QKeySequence(Qt::Key_Escape)); + declareShortcut ("scene-focus-toolbar", "Change focus in scene editor", QKeySequence(Qt::Key_T)); } 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 73d8aef52..88ded40d6 100644 --- a/apps/opencs/view/render/cameracontroller.cpp +++ b/apps/opencs/view/render/cameracontroller.cpp @@ -32,8 +32,9 @@ namespace CSVRender const osg::Vec3d CameraController::LocalLeft = osg::Vec3d(1, 0, 0); const osg::Vec3d CameraController::LocalForward = osg::Vec3d(0, 0, 1); - CameraController::CameraController() - : mActive(false) + CameraController::CameraController(QObject* parent) + : QObject(parent) + , mActive(false) , mInverted(false) , mCameraSensitivity(1/650.f) , mSecondaryMoveMult(50) @@ -163,8 +164,9 @@ namespace CSVRender Free Camera Controller */ - FreeCameraController::FreeCameraController(CSMPrefs::ShortcutEventHandler* handler) - : mLockUpright(false) + FreeCameraController::FreeCameraController(CSMPrefs::ShortcutEventHandler* handler, QObject* parent) + : CameraController(parent) + , mLockUpright(false) , mModified(false) , mFast(false) , mLeft(false) @@ -178,6 +180,16 @@ namespace CSVRender , mRotSpeed(osg::PI / 2) , mSpeedMult(8) { + CSMPrefs::Shortcut* naviPrimaryShortcut = new CSMPrefs::Shortcut("scene-navi-primary", this); + naviPrimaryShortcut->enable(false); + handler->addShortcut(naviPrimaryShortcut); + connect(naviPrimaryShortcut, SIGNAL(activated(bool)), this, SLOT(naviPrimary(bool))); + + CSMPrefs::Shortcut* naviSecondaryShortcut = new CSMPrefs::Shortcut("scene-navi-secondary", this); + naviSecondaryShortcut->enable(false); + handler->addShortcut(naviSecondaryShortcut); + connect(naviSecondaryShortcut, SIGNAL(activated(bool)), this, SLOT(naviSecondary(bool))); + CSMPrefs::Shortcut* forwardShortcut = new CSMPrefs::Shortcut("free-forward", this); forwardShortcut->enable(false); handler->addShortcut(forwardShortcut); @@ -211,7 +223,7 @@ namespace CSVRender CSMPrefs::Shortcut* speedModeShortcut = new CSMPrefs::Shortcut("free-speed-mode", this); speedModeShortcut->enable(false); handler->addShortcut(speedModeShortcut); - connect(speedModeShortcut, SIGNAL(activated(bool)), this, SLOT(swapSpeedMode(bool))); + connect(speedModeShortcut, SIGNAL(activated()), this, SLOT(swapSpeedMode())); } double FreeCameraController::getLinearSpeed() const @@ -261,13 +273,13 @@ namespace CSVRender if (!isActive()) return false; - if (mode == "p-navi") + if (mNaviPrimary) { double scalar = getCameraSensitivity() * (getInverted() ? -1.0 : 1.0); yaw(x * scalar); pitch(y * scalar); } - else if (mode == "s-navi") + else if (mNaviSecondary) { osg::Vec3d movement; movement += LocalLeft * -x * getSecondaryMovementMultiplier(); @@ -384,54 +396,58 @@ namespace CSVRender getCamera()->setViewMatrixAsLookAt(eye, center, mUp); } + void FreeCameraController::naviPrimary(bool active) + { + mNaviPrimary = active; + } + + void FreeCameraController::naviSecondary(bool active) + { + mNaviSecondary = active; + } + void FreeCameraController::forward(bool active) { - if (isActive()) - mForward = active; + mForward = active; } void FreeCameraController::left(bool active) { - if (isActive()) - mLeft = active; + mLeft = active; } void FreeCameraController::backward(bool active) { - if (isActive()) - mBackward = active; + mBackward = active; } void FreeCameraController::right(bool active) { - if (isActive()) - mRight = active; + mRight = active; } void FreeCameraController::rollLeft(bool active) { - if (isActive()) - mRollLeft = active; + mRollLeft = active; } void FreeCameraController::rollRight(bool active) { - if (isActive()) - mRollRight = active; + mRollRight = active; } - void FreeCameraController::swapSpeedMode(bool active) + void FreeCameraController::swapSpeedMode() { - if (isActive() && active) - mFast = !mFast; + mFast = !mFast; } /* Orbit Camera Controller */ - OrbitCameraController::OrbitCameraController(CSMPrefs::ShortcutEventHandler* handler) - : mInitialized(false) + OrbitCameraController::OrbitCameraController(CSMPrefs::ShortcutEventHandler* handler, QObject* parent) + : CameraController(parent) + , mInitialized(false) , mFast(false) , mLeft(false) , mRight(false) @@ -445,6 +461,16 @@ namespace CSVRender , mOrbitSpeed(osg::PI / 4) , mOrbitSpeedMult(4) { + CSMPrefs::Shortcut* naviPrimaryShortcut = new CSMPrefs::Shortcut("scene-navi-primary", this); + naviPrimaryShortcut->enable(false); + handler->addShortcut(naviPrimaryShortcut); + connect(naviPrimaryShortcut, SIGNAL(activated(bool)), this, SLOT(naviPrimary(bool))); + + CSMPrefs::Shortcut* naviSecondaryShortcut = new CSMPrefs::Shortcut("scene-navi-secondary", this); + naviSecondaryShortcut->enable(false); + handler->addShortcut(naviSecondaryShortcut); + connect(naviSecondaryShortcut, SIGNAL(activated(bool)), this, SLOT(naviSecondary(bool))); + CSMPrefs::Shortcut* upShortcut = new CSMPrefs::Shortcut("orbit-up", this); upShortcut->enable(false); handler->addShortcut(upShortcut); @@ -478,7 +504,7 @@ namespace CSVRender 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))); + connect(speedModeShortcut, SIGNAL(activated()), this, SLOT(swapSpeedMode())); } osg::Vec3d OrbitCameraController::getCenter() const @@ -537,13 +563,13 @@ namespace CSVRender if (!mInitialized) initialize(); - if (mode == "p-navi") + if (mNaviPrimary) { double scalar = getCameraSensitivity() * (getInverted() ? -1.0 : 1.0); rotateHorizontal(x * scalar); rotateVertical(-y * scalar); } - else if (mode == "s-navi") + else if (mNaviSecondary) { osg::Vec3d movement; movement += LocalLeft * x * getSecondaryMovementMultiplier(); @@ -696,28 +722,34 @@ namespace CSVRender getCamera()->setViewMatrixAsLookAt(mCenter + offset, mCenter, up); } + void OrbitCameraController::naviPrimary(bool active) + { + mNaviPrimary = active; + } + + void OrbitCameraController::naviSecondary(bool active) + { + mNaviSecondary = active; + } + void OrbitCameraController::up(bool active) { - if (isActive()) - mUp = active; + mUp = active; } void OrbitCameraController::left(bool active) { - if (isActive()) - mLeft = active; + mLeft = active; } void OrbitCameraController::down(bool active) { - if (isActive()) - mDown = active; + mDown = active; } void OrbitCameraController::right(bool active) { - if (isActive()) - mRight = active; + mRight = active; } void OrbitCameraController::rollLeft(bool active) @@ -728,13 +760,11 @@ namespace CSVRender void OrbitCameraController::rollRight(bool active) { - if (isActive()) - mRollRight = active; + mRollRight = active; } - void OrbitCameraController::swapSpeedMode(bool active) + void OrbitCameraController::swapSpeedMode() { - if (isActive() && active) - mFast = !mFast; + mFast = !mFast; } } diff --git a/apps/opencs/view/render/cameracontroller.hpp b/apps/opencs/view/render/cameracontroller.hpp index 297a58f58..6a2773298 100644 --- a/apps/opencs/view/render/cameracontroller.hpp +++ b/apps/opencs/view/render/cameracontroller.hpp @@ -37,7 +37,7 @@ namespace CSVRender static const osg::Vec3d LocalLeft; static const osg::Vec3d LocalForward; - CameraController(); + CameraController(QObject* parent); virtual ~CameraController(); bool isActive() const; @@ -83,7 +83,7 @@ namespace CSVRender public: - FreeCameraController(CSMPrefs::ShortcutEventHandler* handler); + FreeCameraController(CSMPrefs::ShortcutEventHandler* handler, QObject* parent=0); double getLinearSpeed() const; double getRotationalSpeed() const; @@ -112,6 +112,7 @@ namespace CSVRender void stabilize(); bool mLockUpright, mModified; + bool mNaviPrimary, mNaviSecondary; bool mFast, mLeft, mRight, mForward, mBackward, mRollLeft, mRollRight; osg::Vec3d mUp; @@ -121,13 +122,15 @@ namespace CSVRender private slots: + void naviPrimary(bool active); + void naviSecondary(bool active); void forward(bool active); void left(bool active); void backward(bool active); void right(bool active); void rollLeft(bool active); void rollRight(bool active); - void swapSpeedMode(bool active); + void swapSpeedMode(); }; class OrbitCameraController : public CameraController @@ -136,7 +139,7 @@ namespace CSVRender public: - OrbitCameraController(CSMPrefs::ShortcutEventHandler* handler); + OrbitCameraController(CSMPrefs::ShortcutEventHandler* handler, QObject* parent=0); osg::Vec3d getCenter() const; double getOrbitSpeed() const; @@ -167,6 +170,7 @@ namespace CSVRender void zoom(double value); bool mInitialized; + bool mNaviPrimary, mNaviSecondary; bool mFast, mLeft, mRight, mUp, mDown, mRollLeft, mRollRight; unsigned int mPickingMask; osg::Vec3d mCenter; @@ -177,13 +181,15 @@ namespace CSVRender private slots: + void naviPrimary(bool active); + void naviSecondary(bool active); 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); + void swapSpeedMode(); }; } diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index a01df4392..54e359fb3 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -142,15 +142,14 @@ void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons ( "terrain-move"); } -void CSVRender::PagedWorldspaceWidget::handleMouseClick (const WorldspaceHitResult& hit, const std::string& button, +void CSVRender::PagedWorldspaceWidget::handleMouseClick (const WorldspaceHitResult& hit, InteractionType type, bool shift) { if (hit.tag && hit.tag->getMask()==Mask_CellArrow) { - if (button=="p-edit" || button=="s-edit") + if (type == InteractionType_PrimaryEdit || type == InteractionType_SecondaryEdit) { - if (CellArrowTag *cellArrowTag = - dynamic_cast (hit.tag.get())) + if (CellArrowTag *cellArrowTag = dynamic_cast (hit.tag.get())) { CellArrow *arrow = cellArrowTag->getCellArrow(); @@ -173,7 +172,7 @@ void CSVRender::PagedWorldspaceWidget::handleMouseClick (const WorldspaceHitResu if (shift) { - if (button=="p-edit") + if (type == InteractionType_PrimaryEdit) addCellSelection (x, y); else moveCellSelection (x, y); @@ -191,7 +190,7 @@ void CSVRender::PagedWorldspaceWidget::handleMouseClick (const WorldspaceHitResu modified = true; } - if (button=="s-edit") + if (type == InteractionType_SecondaryEdit) { if (mCells.find (coordinates)!=mCells.end()) { @@ -210,7 +209,7 @@ void CSVRender::PagedWorldspaceWidget::handleMouseClick (const WorldspaceHitResu } } - WorldspaceWidget::handleMouseClick (hit, button, shift); + WorldspaceWidget::handleMouseClick (hit, type, shift); } void CSVRender::PagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft, diff --git a/apps/opencs/view/render/pagedworldspacewidget.hpp b/apps/opencs/view/render/pagedworldspacewidget.hpp index 692000708..018d5dafb 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.hpp +++ b/apps/opencs/view/render/pagedworldspacewidget.hpp @@ -138,7 +138,7 @@ namespace CSVRender virtual void addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool); - virtual void handleMouseClick (const WorldspaceHitResult& hit, const std::string& button, bool shift); + virtual void handleMouseClick (const WorldspaceHitResult& hit, InteractionType type, bool shift); signals: diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index bb1ca4008..8a1f1ad35 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -77,7 +77,7 @@ RenderWidget::RenderWidget(QWidget *parent, Qt::WindowFlags f) mView->setSceneData(mRootNode); - // Press S to reveal profiling stats + // Add ability to signal osg to show its statistics for debugging purposes mView->addEventHandler(new osgViewer::StatsHandler); mView->getCamera()->setCullMask(~(Mask_UpdateVisitor)); @@ -165,12 +165,11 @@ SceneWidget::SceneWidget(boost::shared_ptr resourceSys mShortcutHandler = new CSMPrefs::ShortcutEventHandler(this); installEventFilter(mShortcutHandler); - mFreeCamControl.reset(new FreeCameraController(mShortcutHandler)); - mOrbitCamControl.reset(new OrbitCameraController(mShortcutHandler)); - mCurrentCamControl = mFreeCamControl.get(); + mFreeCamControl = new FreeCameraController(mShortcutHandler, this); + mOrbitCamControl = new OrbitCameraController(mShortcutHandler, this); + mCurrentCamControl = mFreeCamControl; mOrbitCamControl->setPickingMask(Mask_Reference | Mask_Terrain); - selectNavigationMode("free"); // we handle lighting manually mView->setLightingMode(osgViewer::View::NO_LIGHT); @@ -183,9 +182,9 @@ SceneWidget::SceneWidget(boost::shared_ptr resourceSys setMouseTracking(true); setFocusPolicy(Qt::ClickFocus); - /// \todo make shortcut configurable - //QShortcut *focusToolbar = new QShortcut (Qt::Key_T, this, 0, 0, Qt::WidgetWithChildrenShortcut); - //connect (focusToolbar, SIGNAL (activated()), this, SIGNAL (focusToolbarRequest())); + mFocusToolbarShortcut = new CSMPrefs::Shortcut("scene-focus-toolbar", this); + mShortcutHandler->addShortcut(mFocusToolbarShortcut); + connect(mFocusToolbarShortcut, SIGNAL(activated()), this, SIGNAL(focusToolbarRequest())); connect (&CSMPrefs::State::get(), SIGNAL (settingChanged (const CSMPrefs::Setting *)), this, SLOT (settingChanged (const CSMPrefs::Setting *))); @@ -279,32 +278,14 @@ void SceneWidget::setDefaultAmbient (const osg::Vec4f& colour) setAmbient(mLighting->getAmbientColour(&mDefaultAmbient)); } -void SceneWidget::mousePressEvent (QMouseEvent *event) -{ - mMouseMode = mapButton(event); - - mPrevMouseX = event->x(); - mPrevMouseY = event->y(); -} - -void SceneWidget::mouseReleaseEvent (QMouseEvent *event) -{ - mMouseMode = ""; -} - void SceneWidget::mouseMoveEvent (QMouseEvent *event) { - mCurrentCamControl->handleMouseMoveEvent(mMouseMode, event->x() - mPrevMouseX, event->y() - mPrevMouseY); + mCurrentCamControl->handleMouseMoveEvent("TODO", event->x() - mPrevMouseX, event->y() - mPrevMouseY); mPrevMouseX = event->x(); mPrevMouseY = event->y(); } -void SceneWidget::focusOutEvent (QFocusEvent *event) -{ - mCurrentCamControl->resetInput(); -} - void SceneWidget::wheelEvent(QWheelEvent *event) { mCurrentCamControl->handleMouseMoveEvent("t-navi", event->delta(), 0); @@ -371,10 +352,6 @@ void SceneWidget::settingChanged (const CSMPrefs::Setting *setting) { mOrbitCamControl->setOrbitSpeedMultiplier(setting->toDouble()); } - else - { - storeMappingSetting(setting); - } } void SceneWidget::selectNavigationMode (const std::string& mode) @@ -382,73 +359,23 @@ void SceneWidget::selectNavigationMode (const std::string& mode) if (mode=="1st") { mCurrentCamControl->setCamera(NULL); - mCurrentCamControl = mFreeCamControl.get(); - mCurrentCamControl->setCamera(getCamera()); + mCurrentCamControl = mFreeCamControl; + mFreeCamControl->setCamera(getCamera()); mFreeCamControl->fixUpAxis(CameraController::WorldUp); } else if (mode=="free") { mCurrentCamControl->setCamera(NULL); - mCurrentCamControl = mFreeCamControl.get(); - mCurrentCamControl->setCamera(getCamera()); + mCurrentCamControl = mFreeCamControl; + mFreeCamControl->setCamera(getCamera()); mFreeCamControl->unfixUpAxis(); } else if (mode=="orbit") { mCurrentCamControl->setCamera(NULL); - mCurrentCamControl = mOrbitCamControl.get(); - mCurrentCamControl->setCamera(getCamera()); + mCurrentCamControl = mOrbitCamControl; + mOrbitCamControl->setCamera(getCamera()); } } -bool SceneWidget::storeMappingSetting (const CSMPrefs::Setting *setting) -{ - if (setting->getParent()->getKey()!="3D Scene Input") - return false; - - static const char * const sMappingSettings[] = - { - "p-navi", "s-navi", - 0 - }; - - for (int i=0; sMappingSettings[i]; ++i) - if (setting->getKey()==sMappingSettings[i]) - { - QString value = QString::fromUtf8 (setting->toString().c_str()); - - Qt::MouseButton button = Qt::NoButton; - - if (value.endsWith ("Left Mouse-Button")) - button = Qt::LeftButton; - else if (value.endsWith ("Right Mouse-Button")) - button = Qt::RightButton; - else if (value.endsWith ("Middle Mouse-Button")) - button = Qt::MiddleButton; - else - return false; - - bool ctrl = value.startsWith ("Ctrl-"); - - mButtonMapping[std::make_pair (button, ctrl)] = sMappingSettings[i]; - return true; - } - - return false; -} - -std::string SceneWidget::mapButton (QMouseEvent *event) -{ - std::pair phyiscal ( - event->button(), event->modifiers() & Qt::ControlModifier); - - std::map, std::string>::const_iterator iter = - mButtonMapping.find (phyiscal); - - if (iter!=mButtonMapping.end()) - return iter->second; - - return ""; -} - } diff --git a/apps/opencs/view/render/scenewidget.hpp b/apps/opencs/view/render/scenewidget.hpp index 07f5f03cf..07d1dce75 100644 --- a/apps/opencs/view/render/scenewidget.hpp +++ b/apps/opencs/view/render/scenewidget.hpp @@ -56,6 +56,7 @@ namespace CSVRender RenderWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); virtual ~RenderWidget(); + /// Initiates a request to redraw the view void flagAsModified(); void setVisibilityMask(int mask); @@ -65,19 +66,21 @@ namespace CSVRender protected: osg::ref_ptr mView; - - osg::Group* mRootNode; + osg::ref_ptr mRootNode; QTimer mTimer; }; - // Extension of RenderWidget to support lighting mode selection & toolbar + /// Extension of RenderWidget to support lighting mode selection & toolbar class SceneWidget : public RenderWidget { Q_OBJECT + public: + SceneWidget(boost::shared_ptr resourceSystem, QWidget* parent = 0, Qt::WindowFlags f = 0, bool retrieveInput = true); + virtual ~SceneWidget(); CSVWidget::SceneToolMode *makeLightingSelector (CSVWidget::SceneToolbar *parent); @@ -88,21 +91,14 @@ namespace CSVRender ///< \note The actual ambient colour may differ based on lighting settings. protected: + void setLighting (Lighting *lighting); ///< \attention The ownership of \a lighting is not transferred to *this. void setAmbient(const osg::Vec4f& ambient); - virtual void mousePressEvent (QMouseEvent *event); - virtual void mouseReleaseEvent (QMouseEvent *event); virtual void mouseMoveEvent (QMouseEvent *event); virtual void wheelEvent (QWheelEvent *event); - virtual void focusOutEvent (QFocusEvent *event); - - /// \return Is \a key a button mapping setting? (ignored otherwise) - virtual bool storeMappingSetting (const CSMPrefs::Setting *setting); - - std::string mapButton (QMouseEvent *event); boost::shared_ptr mResourceSystem; @@ -115,13 +111,13 @@ namespace CSVRender LightingBright mLightingBright; int mPrevMouseX, mPrevMouseY; - std::string mMouseMode; - std::auto_ptr mFreeCamControl; - std::auto_ptr mOrbitCamControl; + + FreeCameraController* mFreeCamControl; + OrbitCameraController* mOrbitCamControl; CameraController* mCurrentCamControl; - std::map, std::string> mButtonMapping; CSMPrefs::ShortcutEventHandler *mShortcutHandler; + CSMPrefs::Shortcut* mFocusToolbarShortcut; private: bool mCamPositionSet; @@ -149,7 +145,9 @@ namespace CSVRender class CompositeViewer : public QObject, public osgViewer::CompositeViewer { Q_OBJECT + public: + CompositeViewer(); static CompositeViewer& get(); diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index e1706ca77..df0550730 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -16,6 +16,8 @@ #include "../../model/world/universalid.hpp" #include "../../model/world/idtable.hpp" +#include "../../model/prefs/shortcut.hpp" +#include "../../model/prefs/shortcuteventhandler.hpp" #include "../../model/prefs/state.hpp" #include "../render/orbitcameramode.hpp" @@ -31,10 +33,23 @@ #include "cameracontroller.hpp" CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent) -: SceneWidget (document.getData().getResourceSystem(), parent, 0, false), mSceneElements(0), mRun(0), mDocument(document), - mInteractionMask (0), mEditMode (0), mLocked (false), mDragging (false), mDragX(0), mDragY(0), mDragFactor(0), - mDragWheelFactor(0), mDragShiftFactor(0), - mToolTipPos (-1, -1), mShowToolTips(false), mToolTipDelay(0) + : SceneWidget (document.getData().getResourceSystem(), parent, 0, false) + , mSceneElements(0) + , mRun(0) + , mDocument(document) + , mInteractionMask (0) + , mEditMode (0) + , mLocked (false) + , mDragMode(InteractionType_None) + , mDragging (false) + , mDragX(0) + , mDragY(0) + , mDragFactor(0) + , mDragWheelFactor(0) + , mDragShiftFactor(0) + , mToolTipPos (-1, -1) + , mShowToolTips(false) + , mToolTipDelay(0) { setAcceptDrops(true); @@ -80,6 +95,27 @@ CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidg CSMPrefs::get()["3D Scene Input"].update(); CSMPrefs::get()["Tooltips"].update(); + + // Shortcuts + mPrimaryEditShortcut = new CSMPrefs::Shortcut("scene-edit-primary", this); + mShortcutHandler->addShortcut(mPrimaryEditShortcut); + connect(mPrimaryEditShortcut, SIGNAL(activated(bool)), this, SLOT(primaryEdit(bool))); + + mSecondaryEditShortcut = new CSMPrefs::Shortcut("scene-edit-secondary", this); + mShortcutHandler->addShortcut(mSecondaryEditShortcut); + connect(mSecondaryEditShortcut, SIGNAL(activated(bool)), this, SLOT(secondaryEdit(bool))); + + mPrimarySelectShortcut = new CSMPrefs::Shortcut("scene-select-primary", this); + mShortcutHandler->addShortcut(mPrimarySelectShortcut); + connect(mPrimarySelectShortcut, SIGNAL(activated(bool)), this, SLOT(primarySelect(bool))); + + mSecondarySelectShortcut = new CSMPrefs::Shortcut("scene-select-secondary", this); + mShortcutHandler->addShortcut(mSecondarySelectShortcut); + connect(mSecondarySelectShortcut, SIGNAL(activated(bool)), this, SLOT(secondarySelect(bool))); + + mAbortShortcut = new CSMPrefs::Shortcut("scene-edit-abort", this); + mShortcutHandler->addShortcut(mAbortShortcut); + connect(mSecondaryEditShortcut, SIGNAL(activated()), this, SLOT(abortDrag())); } CSVRender::WorldspaceWidget::~WorldspaceWidget () @@ -409,7 +445,7 @@ void CSVRender::WorldspaceWidget::abortDrag() editMode.dragAborted(); mDragging = false; - mDragMode.clear(); + mDragMode = InteractionType_None; } } @@ -453,45 +489,6 @@ void CSVRender::WorldspaceWidget::dragMoveEvent(QDragMoveEvent *event) } } -bool CSVRender::WorldspaceWidget::storeMappingSetting (const CSMPrefs::Setting *setting) -{ - static const char * const sMappingSettings[] = - { - "p-edit", "s-edit", - "p-select", "s-select", - 0 - }; - - if (setting->getParent()->getKey()=="3D Scene Input") - { - for (int i=0; sMappingSettings[i]; ++i) - { - if (setting->getKey()==sMappingSettings[i]) - { - QString value = QString::fromUtf8 (setting->toString().c_str()); - - Qt::MouseButton button = Qt::NoButton; - - if (value.endsWith ("Left Mouse-Button")) - button = Qt::LeftButton; - else if (value.endsWith ("Right Mouse-Button")) - button = Qt::RightButton; - else if (value.endsWith ("Middle Mouse-Button")) - button = Qt::MiddleButton; - else - return false; - - bool ctrl = value.startsWith ("Ctrl-"); - - mButtonMapping[std::make_pair (button, ctrl)] = sMappingSettings[i]; - return true; - } - } - } - - return SceneWidget::storeMappingSetting(setting); -} - void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event) { const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); @@ -567,7 +564,7 @@ void CSVRender::WorldspaceWidget::editModeChanged (const std::string& id) { dynamic_cast (*mEditMode->getCurrent()).setEditLock (mLocked); mDragging = false; - mDragMode.clear(); + mDragMode = InteractionType_None; } void CSVRender::WorldspaceWidget::showToolTip() @@ -615,17 +612,17 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) editMode.drag (event->pos(), diffX, diffY, factor); } - else if (mDragMode=="p-edit" || mDragMode=="s-edit" || mDragMode=="p-select" || mDragMode=="s-select") + else if (mDragMode != InteractionType_None) { EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); - if (mDragMode=="p-edit") + if (mDragMode == InteractionType_PrimaryEdit) mDragging = editMode.primaryEditStartDrag (event->pos()); - else if (mDragMode=="s-edit") + else if (mDragMode == InteractionType_SecondaryEdit) mDragging = editMode.secondaryEditStartDrag (event->pos()); - else if (mDragMode=="p-select") + else if (mDragMode == InteractionType_PrimarySelect) mDragging = editMode.primarySelectStartDrag (event->pos()); - else if (mDragMode=="s-select") + else if (mDragMode == InteractionType_SecondarySelect) mDragging = editMode.secondarySelectStartDrag (event->pos()); if (mDragging) @@ -656,46 +653,6 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) } } -void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event) -{ - std::string button = mapButton (event); - - if (button=="p-edit" || button=="s-edit" || - button=="p-select" || button=="s-select") - { - if (!mDragging) - mDragMode = button; - } - else - SceneWidget::mousePressEvent(event); -} - -void CSVRender::WorldspaceWidget::mouseReleaseEvent (QMouseEvent *event) -{ - std::string button = mapButton (event); - mDragMode.clear(); - - if (button=="p-edit" || button=="s-edit" || - button=="p-select" || button=="s-select") - { - if (mDragging) - { - EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); - - editMode.dragCompleted(event->pos()); - mDragging = false; - } - else - { - WorldspaceHitResult hit = mousePick(event->pos(), getInteractionMask()); - - handleMouseClick (hit, button, event->modifiers() & Qt::ShiftModifier); - } - } - else - SceneWidget::mouseReleaseEvent(event); -} - void CSVRender::WorldspaceWidget::wheelEvent (QWheelEvent *event) { if (mDragging) @@ -713,27 +670,17 @@ void CSVRender::WorldspaceWidget::wheelEvent (QWheelEvent *event) SceneWidget::wheelEvent(event); } -void CSVRender::WorldspaceWidget::keyPressEvent (QKeyEvent *event) -{ - if(event->key() == Qt::Key_Escape) - { - abortDrag(); - } - else - SceneWidget::keyPressEvent(event); -} - -void CSVRender::WorldspaceWidget::handleMouseClick (const WorldspaceHitResult& hit, const std::string& button, bool shift) +void CSVRender::WorldspaceWidget::handleMouseClick (const WorldspaceHitResult& hit, InteractionType type, bool shift) { EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); - if (button=="p-edit") + if (type == InteractionType_PrimaryEdit) editMode.primaryEditPressed (hit); - else if (button=="s-edit") + else if (type == InteractionType_SecondaryEdit) editMode.secondaryEditPressed (hit); - else if (button=="p-select") + else if (type == InteractionType_PrimarySelect) editMode.primarySelectPressed (hit); - else if (button=="s-select") + else if (type == InteractionType_SecondarySelect) editMode.secondarySelectPressed (hit); } @@ -741,3 +688,48 @@ CSVRender::EditMode *CSVRender::WorldspaceWidget::getEditMode() { return dynamic_cast (mEditMode->getCurrent()); } + +void CSVRender::WorldspaceWidget::primaryEdit(bool activate) +{ + handleInteraction(InteractionType_PrimaryEdit, activate); +} + +void CSVRender::WorldspaceWidget::secondaryEdit(bool activate) +{ + handleInteraction(InteractionType_SecondaryEdit, activate); +} + +void CSVRender::WorldspaceWidget::primarySelect(bool activate) +{ + handleInteraction(InteractionType_PrimarySelect, activate); +} + +void CSVRender::WorldspaceWidget::secondarySelect(bool activate) +{ + handleInteraction(InteractionType_SecondarySelect, activate); +} + +void CSVRender::WorldspaceWidget::handleInteraction(InteractionType type, bool activate) +{ + if (activate) + { + if (!mDragging) + mDragMode = type; + } + else + { + mDragMode = InteractionType_None; + + if (mDragging) + { + EditMode* editMode = getEditMode(); + editMode->dragCompleted(mapFromGlobal(QCursor::pos())); + mDragging = false; + } + else + { + WorldspaceHitResult hit = mousePick(mapFromGlobal(QCursor::pos()), getInteractionMask()); + handleMouseClick(hit, type, false); + } + } +} diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 92d31eb9e..36ee92773 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -15,6 +15,7 @@ namespace CSMPrefs { class Setting; + class Shortcut; } namespace CSMWorld @@ -55,7 +56,7 @@ namespace CSVRender unsigned int mInteractionMask; CSVWidget::SceneToolMode *mEditMode; bool mLocked; - std::string mDragMode; + int mDragMode; bool mDragging; int mDragX; int mDragY; @@ -67,6 +68,12 @@ namespace CSVRender bool mShowToolTips; int mToolTipDelay; + CSMPrefs::Shortcut* mPrimaryEditShortcut; + CSMPrefs::Shortcut* mSecondaryEditShortcut; + CSMPrefs::Shortcut* mPrimarySelectShortcut; + CSMPrefs::Shortcut* mSecondarySelectShortcut; + CSMPrefs::Shortcut* mAbortShortcut; + public: enum DropType @@ -85,6 +92,15 @@ namespace CSVRender ignored //either mixed cells, or not cells }; + enum InteractionType + { + InteractionType_PrimaryEdit, + InteractionType_PrimarySelect, + InteractionType_SecondaryEdit, + InteractionType_SecondarySelect, + InteractionType_None + }; + WorldspaceWidget (CSMDoc::Document& document, QWidget *parent = 0); ~WorldspaceWidget (); @@ -171,12 +187,6 @@ namespace CSVRender /// Erase all overrides and restore the visual representation to its true state. virtual void reset (unsigned int elementMask) = 0; - /// \note Drags will be automatically aborted when the aborting is triggered - /// (either explicitly or implicitly) from within this class. This function only - /// needs to be called, when the drag abort is triggered externally (e.g. from - /// an edit mode). - void abortDrag(); - protected: /// Visual elements in a scene @@ -197,16 +207,9 @@ namespace CSVRender virtual void updateOverlay(); virtual void mouseMoveEvent (QMouseEvent *event); - virtual void mousePressEvent (QMouseEvent *event); - virtual void mouseReleaseEvent (QMouseEvent *event); virtual void wheelEvent (QWheelEvent *event); - virtual void keyPressEvent (QKeyEvent *event); - virtual void handleMouseClick (const WorldspaceHitResult& hit, const std::string& button, - bool shift); - - /// \return Is \a key a button mapping setting? (ignored otherwise) - virtual bool storeMappingSetting (const CSMPrefs::Setting *setting); + virtual void handleMouseClick (const WorldspaceHitResult& hit, InteractionType type, bool shift); virtual void settingChanged (const CSMPrefs::Setting *setting); @@ -222,6 +225,16 @@ namespace CSVRender virtual std::string getStartupInstruction() = 0; + void handleInteraction(InteractionType type, bool activate); + + public slots: + + /// \note Drags will be automatically aborted when the aborting is triggered + /// (either explicitly or implicitly) from within this class. This function only + /// needs to be called, when the drag abort is triggered externally (e.g. from + /// an edit mode). + void abortDrag(); + private slots: virtual void referenceableDataChanged (const QModelIndex& topLeft, @@ -255,6 +268,14 @@ namespace CSVRender void showToolTip(); + void primaryEdit(bool activate); + + void secondaryEdit(bool activate); + + void primarySelect(bool activate); + + void secondarySelect(bool activate); + protected slots: void elementSelectionChanged();