diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index ec4737d16..816b8d732 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -86,11 +86,12 @@ opencs_units (view/widget opencs_units (view/render scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget previewwidget editmode instancemode instanceselectionmode instancemovemode + orbitcameramode ) opencs_units_noqt (view/render - lighting lightingday lightingnight - lightingbright object cell terrainstorage tagbase cellarrow cellmarker cellborder + lighting lightingday lightingnight lightingbright object cell terrainstorage tagbase + cellarrow cellmarker cellborder cameracontroller ) opencs_hdrs_noqt (view/render diff --git a/apps/opencs/model/prefs/doublesetting.cpp b/apps/opencs/model/prefs/doublesetting.cpp index 7c247777d..531196174 100644 --- a/apps/opencs/model/prefs/doublesetting.cpp +++ b/apps/opencs/model/prefs/doublesetting.cpp @@ -15,10 +15,16 @@ CSMPrefs::DoubleSetting::DoubleSetting (Category *parent, Settings::Manager *values, QMutex *mutex, const std::string& key, const std::string& label, double default_) : Setting (parent, values, mutex, key, label), - mMin (0), mMax (std::numeric_limits::max()), + mPrecision(2), mMin (0), mMax (std::numeric_limits::max()), mDefault (default_) {} +CSMPrefs::DoubleSetting& CSMPrefs::DoubleSetting::setPrecision(int precision) +{ + mPrecision = precision; + return *this; +} + CSMPrefs::DoubleSetting& CSMPrefs::DoubleSetting::setRange (double min, double max) { mMin = min; @@ -49,6 +55,7 @@ std::pair CSMPrefs::DoubleSetting::makeWidgets (QWidget *p QLabel *label = new QLabel (QString::fromUtf8 (getLabel().c_str()), parent); QDoubleSpinBox *widget = new QDoubleSpinBox (parent); + widget->setDecimals(mPrecision); widget->setRange (mMin, mMax); widget->setValue (mDefault); diff --git a/apps/opencs/model/prefs/doublesetting.hpp b/apps/opencs/model/prefs/doublesetting.hpp index 3868f014e..8fd345f4d 100644 --- a/apps/opencs/model/prefs/doublesetting.hpp +++ b/apps/opencs/model/prefs/doublesetting.hpp @@ -9,6 +9,7 @@ namespace CSMPrefs { Q_OBJECT + int mPrecision; double mMin; double mMax; std::string mTooltip; @@ -20,6 +21,8 @@ namespace CSMPrefs QMutex *mutex, const std::string& key, const std::string& label, double default_); + DoubleSetting& setPrecision (int precision); + // defaults to [0, std::numeric_limits::max()] DoubleSetting& setRange (double min, double max); diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 772047961..70456ee1d 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -172,6 +172,17 @@ void CSMPrefs::State::declare() inputButtons.add (left).add (cLeft).add (right).add (cRight).add (middle).add (cMiddle); declareEnum ("p-navi", "Primary Camera Navigation Button", left).addValues (inputButtons); declareEnum ("s-navi", "Secondary Camera Navigation Button", cLeft).addValues (inputButtons); + declareDouble ("p-navi-free-sensitivity", "Free Camera Sensitivity", 1/650.).setPrecision(5).setRange(0.0, 1.0); + declareBool ("p-navi-free-invert", "Invert Free Camera Mouse Input", false); + declareDouble ("p-navi-orbit-sensitivity", "Orbit Camera Sensitivity", 1/650.).setPrecision(5).setRange(0.0, 1.0); + declareBool ("p-navi-orbit-invert", "Invert Orbit Camera Mouse Input", false); + declareDouble ("s-navi-sensitivity", "Secondary Camera Movement Sensitivity", 50.0).setRange(-1000.0, 1000.0); + declareDouble ("navi-wheel-factor", "Camera Zoom Sensitivity", 8).setRange(-100.0, 100.0); + declareDouble ("navi-free-lin-speed", "Free Camera Linear Speed", 1000.0).setRange(1.0, 10000.0); + declareDouble ("navi-free-rot-speed", "Free Camera Rotational Speed", 3.14 / 2).setRange(0.001, 6.28); + declareDouble ("navi-free-speed-mult", "Free Camera Speed Multiplier (from Modifier)", 8).setRange(0.001, 1000.0); + declareDouble ("navi-orbit-rot-speed", "Orbital Camera Rotational Speed", 3.14 / 4).setRange(0.001, 6.28); + declareDouble ("navi-orbit-speed-mult", "Orbital Camera Speed Multiplier (from Modifier)", 4).setRange(0.001, 1000.0); declareEnum ("p-edit", "Primary Editing Button", right).addValues (inputButtons); declareEnum ("s-edit", "Secondary Editing Button", cRight).addValues (inputButtons); declareEnum ("p-select", "Primary Selection Button", middle).addValues (inputButtons); diff --git a/apps/opencs/view/render/cameracontroller.cpp b/apps/opencs/view/render/cameracontroller.cpp new file mode 100644 index 000000000..68f0c76ef --- /dev/null +++ b/apps/opencs/view/render/cameracontroller.cpp @@ -0,0 +1,628 @@ +#include "cameracontroller.hpp" + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace CSVRender +{ + + /* + Camera Controller + */ + + const osg::Vec3d CameraController::WorldUp = osg::Vec3d(0, 0, 1); + + const osg::Vec3d CameraController::LocalUp = osg::Vec3d(0, 1, 0); + const osg::Vec3d CameraController::LocalLeft = osg::Vec3d(1, 0, 0); + const osg::Vec3d CameraController::LocalForward = osg::Vec3d(0, 0, 1); + + CameraController::CameraController() + : mActive(false) + , mInverted(false) + , mCameraSensitivity(1/650.f) + , mSecondaryMoveMult(50) + , mWheelMoveMult(8) + , mCamera(NULL) + { + } + + CameraController::~CameraController() + { + } + + bool CameraController::isActive() const + { + return mActive; + } + + osg::Camera* CameraController::getCamera() const + { + return mCamera; + } + + double CameraController::getCameraSensitivity() const + { + return mCameraSensitivity; + } + + bool CameraController::getInverted() const + { + return mInverted; + } + + double CameraController::getSecondaryMovementMultiplier() const + { + return mSecondaryMoveMult; + } + + double CameraController::getWheelMovementMultiplier() const + { + return mWheelMoveMult; + } + + void CameraController::setCamera(osg::Camera* camera) + { + mCamera = camera; + mActive = (mCamera != NULL); + + if (mActive) + onActivate(); + } + + void CameraController::setCameraSensitivity(double value) + { + mCameraSensitivity = value; + } + + void CameraController::setInverted(bool value) + { + mInverted = value; + } + + void CameraController::setSecondaryMovementMultiplier(double value) + { + mSecondaryMoveMult = value; + } + + void CameraController::setWheelMovementMultiplier(double value) + { + mWheelMoveMult = value; + } + + void CameraController::setup(osg::Group* root, unsigned int mask, const osg::Vec3d& up) + { + // Find World bounds + osg::ComputeBoundsVisitor boundsVisitor; + osg::BoundingBox& boundingBox = boundsVisitor.getBoundingBox(); + + boundsVisitor.setTraversalMask(mask); + root->accept(boundsVisitor); + + if (!boundingBox.valid()) + { + // Try again without any mask + boundsVisitor.reset(); + boundsVisitor.setTraversalMask(~0); + root->accept(boundsVisitor); + + // Last resort, set a default + if (!boundingBox.valid()) + { + boundingBox.set(-1, -1, -1, 1, 1, 1); + } + } + + // Calculate a good starting position + osg::Vec3d minBounds = boundingBox.corner(0) - boundingBox.center(); + osg::Vec3d maxBounds = boundingBox.corner(7) - boundingBox.center(); + + osg::Vec3d camOffset = up * maxBounds > 0 ? maxBounds : minBounds; + camOffset *= 2; + + osg::Vec3d eye = camOffset + boundingBox.center(); + osg::Vec3d center = boundingBox.center(); + + getCamera()->setViewMatrixAsLookAt(eye, center, up); + } + + /* + Free Camera Controller + */ + + FreeCameraController::FreeCameraController() + : mLockUpright(false) + , mModified(false) + , mFast(false) + , mLeft(false) + , mRight(false) + , mForward(false) + , mBackward(false) + , mRollLeft(false) + , mRollRight(false) + , mUp(LocalUp) + , mLinSpeed(1000) + , mRotSpeed(osg::PI / 2) + , mSpeedMult(8) + { + } + + double FreeCameraController::getLinearSpeed() const + { + return mLinSpeed; + } + + double FreeCameraController::getRotationalSpeed() const + { + return mRotSpeed; + } + + double FreeCameraController::getSpeedMultiplier() const + { + return mSpeedMult; + } + + void FreeCameraController::setLinearSpeed(double value) + { + mLinSpeed = value; + } + + void FreeCameraController::setRotationalSpeed(double value) + { + mRotSpeed = value; + } + + void FreeCameraController::setSpeedMultiplier(double value) + { + mSpeedMult = value; + } + + void FreeCameraController::fixUpAxis(const osg::Vec3d& up) + { + mLockUpright = true; + mUp = up; + mModified = true; + } + + void FreeCameraController::unfixUpAxis() + { + mLockUpright = false; + } + + bool FreeCameraController::handleKeyEvent(QKeyEvent* event, bool pressed) + { + if (!isActive()) + return false; + + if (event->key() == Qt::Key_Q) + { + mRollLeft = pressed; + } + else if (event->key() == Qt::Key_E) + { + mRollRight = pressed; + } + else if (event->key() == Qt::Key_A) + { + mLeft = pressed; + } + else if (event->key() == Qt::Key_D) + { + mRight = pressed; + } + else if (event->key() == Qt::Key_W) + { + mForward = pressed; + } + else if (event->key() == Qt::Key_S) + { + mBackward = pressed; + } + else if (event->key() == Qt::Key_Shift) + { + mFast = pressed; + } + else + { + return false; + } + + return true; + } + + bool FreeCameraController::handleMouseMoveEvent(std::string mode, int x, int y) + { + if (!isActive()) + return false; + + if (mode == "p-navi") + { + double scalar = getCameraSensitivity() * (getInverted() ? -1.0 : 1.0); + yaw(x * scalar); + pitch(y * scalar); + } + else if (mode == "s-navi") + { + osg::Vec3d movement; + movement += LocalLeft * -x * getSecondaryMovementMultiplier(); + movement += LocalUp * y * getSecondaryMovementMultiplier(); + + translate(movement); + } + else if (mode == "t-navi") + { + translate(LocalForward * x * (mFast ? getWheelMovementMultiplier() : 1)); + } + else + { + return false; + } + + return true; + } + + void FreeCameraController::update(double dt) + { + if (!isActive()) + return; + + double linDist = mLinSpeed * dt; + double rotDist = mRotSpeed * dt; + + if (mFast) + linDist *= mSpeedMult; + + if (mLeft) + translate(LocalLeft * linDist); + if (mRight) + translate(LocalLeft * -linDist); + if (mForward) + translate(LocalForward * linDist); + if (mBackward) + translate(LocalForward * -linDist); + + if (!mLockUpright) + { + if (mRollLeft) + roll(-rotDist); + if (mRollRight) + roll(rotDist); + } + else if(mModified) + { + stabilize(); + mModified = false; + } + + // Normalize the matrix to counter drift + getCamera()->getViewMatrix().orthoNormal(getCamera()->getViewMatrix()); + } + + void FreeCameraController::yaw(double value) + { + getCamera()->getViewMatrix() *= osg::Matrixd::rotate(value, LocalUp); + mModified = true; + } + + void FreeCameraController::pitch(double value) + { + const double Constraint = osg::PI / 2 - 0.1; + + if (mLockUpright) + { + osg::Vec3d eye, center, up; + getCamera()->getViewMatrixAsLookAt(eye, center, up); + + osg::Vec3d forward = center - eye; + osg::Vec3d left = up ^ forward; + + double pitchAngle = std::acos(up * mUp); + if ((mUp ^ up) * left < 0) + pitchAngle *= -1; + + if (std::abs(pitchAngle + value) > Constraint) + value = (pitchAngle > 0 ? 1 : -1) * Constraint - pitchAngle; + } + + getCamera()->getViewMatrix() *= osg::Matrixd::rotate(value, LocalLeft); + mModified = true; + } + + void FreeCameraController::roll(double value) + { + getCamera()->getViewMatrix() *= osg::Matrixd::rotate(value, LocalForward); + mModified = true; + } + + void FreeCameraController::translate(const osg::Vec3d& offset) + { + getCamera()->getViewMatrix() *= osg::Matrixd::translate(offset); + mModified = true; + } + + void FreeCameraController::stabilize() + { + osg::Vec3d eye, center, up; + getCamera()->getViewMatrixAsLookAt(eye, center, up); + getCamera()->setViewMatrixAsLookAt(eye, center, mUp); + } + + /* + Orbit Camera Controller + */ + + OrbitCameraController::OrbitCameraController() + : mInitialized(false) + , mFast(false) + , mLeft(false) + , mRight(false) + , mUp(false) + , mDown(false) + , mRollLeft(false) + , mRollRight(false) + , mPickingMask(~0) + , mCenter(0,0,0) + , mDistance(0) + , mOrbitSpeed(osg::PI / 4) + , mOrbitSpeedMult(4) + { + } + + osg::Vec3d OrbitCameraController::getCenter() const + { + return mCenter; + } + + double OrbitCameraController::getOrbitSpeed() const + { + return mOrbitSpeed; + } + + double OrbitCameraController::getOrbitSpeedMultiplier() const + { + return mOrbitSpeedMult; + } + + unsigned int OrbitCameraController::getPickingMask() const + { + return mPickingMask; + } + + void OrbitCameraController::setCenter(const osg::Vec3d& value) + { + osg::Vec3d eye, center, up; + getCamera()->getViewMatrixAsLookAt(eye, center, up); + + mCenter = value; + mDistance = (eye - mCenter).length(); + + getCamera()->setViewMatrixAsLookAt(eye, mCenter, up); + + mInitialized = true; + } + + void OrbitCameraController::setOrbitSpeed(double value) + { + mOrbitSpeed = value; + } + + void OrbitCameraController::setOrbitSpeedMultiplier(double value) + { + mOrbitSpeedMult = value; + } + + void OrbitCameraController::setPickingMask(unsigned int value) + { + mPickingMask = value; + } + + bool OrbitCameraController::handleKeyEvent(QKeyEvent* event, bool pressed) + { + if (!isActive()) + return false; + + if (!mInitialized) + initialize(); + + if (event->key() == Qt::Key_Q) + { + mRollLeft = pressed; + } + else if (event->key() == Qt::Key_E) + { + mRollRight = pressed; + } + else if (event->key() == Qt::Key_A) + { + mLeft = pressed; + } + else if (event->key() == Qt::Key_D) + { + mRight = pressed; + } + else if (event->key() == Qt::Key_W) + { + mUp = pressed; + } + else if (event->key() == Qt::Key_S) + { + mDown = pressed; + } + else if (event->key() == Qt::Key_Shift) + { + mFast = pressed; + } + else + { + return false; + } + + return true; + } + + bool OrbitCameraController::handleMouseMoveEvent(std::string mode, int x, int y) + { + if (!isActive()) + return false; + + if (!mInitialized) + initialize(); + + if (mode == "p-navi") + { + double scalar = getCameraSensitivity() * (getInverted() ? -1.0 : 1.0); + rotateHorizontal(x * scalar); + rotateVertical(-y * scalar); + } + else if (mode == "s-navi") + { + osg::Vec3d movement; + movement += LocalLeft * x * getSecondaryMovementMultiplier(); + movement += LocalUp * -y * getSecondaryMovementMultiplier(); + + translate(movement); + } + else if (mode == "t-navi") + { + zoom(-x * (mFast ? getWheelMovementMultiplier() : 1)); + } + else + { + return false; + } + + return true; + } + + void OrbitCameraController::update(double dt) + { + if (!isActive()) + return; + + if (!mInitialized) + initialize(); + + double rotDist = mOrbitSpeed * dt; + + if (mFast) + rotDist *= mOrbitSpeedMult; + + if (mLeft) + rotateHorizontal(-rotDist); + if (mRight) + rotateHorizontal(rotDist); + if (mUp) + rotateVertical(rotDist); + if (mDown) + rotateVertical(-rotDist); + + if (mRollLeft) + roll(-rotDist); + if (mRollRight) + roll(rotDist); + + // Normalize the matrix to counter drift + getCamera()->getViewMatrix().orthoNormal(getCamera()->getViewMatrix()); + } + + void OrbitCameraController::onActivate() + { + mInitialized = false; + } + + void OrbitCameraController::initialize() + { + static const int DefaultStartDistance = 10000.f; + + // Try to intelligently pick focus object + osg::ref_ptr intersector (new osgUtil::LineSegmentIntersector( + osgUtil::Intersector::PROJECTION, osg::Vec3d(0, 0, 0), LocalForward)); + + intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::LIMIT_NEAREST); + osgUtil::IntersectionVisitor visitor(intersector); + + visitor.setTraversalMask(mPickingMask); + + getCamera()->accept(visitor); + + osg::Vec3d eye, center, up; + getCamera()->getViewMatrixAsLookAt(eye, center, up, DefaultStartDistance); + + if (intersector->getIntersections().begin() != intersector->getIntersections().end()) + { + mCenter = intersector->getIntersections().begin()->getWorldIntersectPoint(); + mDistance = (eye - mCenter).length(); + } + else + { + mCenter = center; + mDistance = DefaultStartDistance; + } + + mInitialized = true; + } + + void OrbitCameraController::rotateHorizontal(double value) + { + osg::Vec3d eye, center, up; + getCamera()->getViewMatrixAsLookAt(eye, center, up); + + osg::Quat rotation = osg::Quat(value, up); + osg::Vec3d oldOffset = eye - mCenter; + osg::Vec3d newOffset = rotation * oldOffset; + + getCamera()->setViewMatrixAsLookAt(mCenter + newOffset, mCenter, up); + } + + void OrbitCameraController::rotateVertical(double value) + { + osg::Vec3d eye, center, up; + getCamera()->getViewMatrixAsLookAt(eye, center, up); + + osg::Vec3d forward = center - eye; + osg::Quat rotation = osg::Quat(value, up ^ forward); + osg::Vec3d oldOffset = eye - mCenter; + osg::Vec3d newOffset = rotation * oldOffset; + + getCamera()->setViewMatrixAsLookAt(mCenter + newOffset, mCenter, up); + } + + void OrbitCameraController::roll(double value) + { + getCamera()->getViewMatrix() *= osg::Matrixd::rotate(value, LocalForward); + } + + void OrbitCameraController::translate(const osg::Vec3d& offset) + { + osg::Vec3d eye, center, up; + getCamera()->getViewMatrixAsLookAt(eye, center, up); + + osg::Vec3d newOffset = getCamera()->getViewMatrix().getRotate().inverse() * offset; + mCenter += newOffset; + eye += newOffset; + + getCamera()->setViewMatrixAsLookAt(eye, mCenter, up); + } + + void OrbitCameraController::zoom(double value) + { + mDistance = std::max(10., mDistance + value); + + osg::Vec3d eye, center, up; + getCamera()->getViewMatrixAsLookAt(eye, center, up, 1.f); + + osg::Vec3d offset = (eye - center) * mDistance; + + getCamera()->setViewMatrixAsLookAt(mCenter + offset, mCenter, up); + } +} diff --git a/apps/opencs/view/render/cameracontroller.hpp b/apps/opencs/view/render/cameracontroller.hpp new file mode 100644 index 000000000..575bbb4ea --- /dev/null +++ b/apps/opencs/view/render/cameracontroller.hpp @@ -0,0 +1,152 @@ +#ifndef OPENCS_VIEW_CAMERACONTROLLER_H +#define OPENCS_VIEW_CAMERACONTROLLER_H + +#include + +#include +#include + +class QKeyEvent; + +namespace osg +{ + class Camera; + class Group; +} + +namespace CSVRender +{ + class CameraController + { + public: + + static const osg::Vec3d WorldUp; + + static const osg::Vec3d LocalUp; + static const osg::Vec3d LocalLeft; + static const osg::Vec3d LocalForward; + + CameraController(); + virtual ~CameraController(); + + bool isActive() const; + + osg::Camera* getCamera() const; + double getCameraSensitivity() const; + bool getInverted() const; + double getSecondaryMovementMultiplier() const; + double getWheelMovementMultiplier() const; + + void setCamera(osg::Camera*); + void setCameraSensitivity(double value); + void setInverted(bool value); + void setSecondaryMovementMultiplier(double value); + void setWheelMovementMultiplier(double value); + + // moves the camera to an intelligent position + void setup(osg::Group* root, unsigned int mask, const osg::Vec3d& up); + + virtual bool handleKeyEvent(QKeyEvent* event, bool pressed) = 0; + virtual bool handleMouseMoveEvent(std::string mode, int x, int y) = 0; + + virtual void update(double dt) = 0; + + protected: + + virtual void onActivate(){} + + private: + + bool mActive, mInverted; + double mCameraSensitivity; + double mSecondaryMoveMult; + double mWheelMoveMult; + + osg::Camera* mCamera; + }; + + class FreeCameraController : public CameraController + { + public: + + FreeCameraController(); + + double getLinearSpeed() const; + double getRotationalSpeed() const; + double getSpeedMultiplier() const; + + void setLinearSpeed(double value); + void setRotationalSpeed(double value); + void setSpeedMultiplier(double value); + + void fixUpAxis(const osg::Vec3d& up); + void unfixUpAxis(); + + bool handleKeyEvent(QKeyEvent* event, bool pressed); + bool handleMouseMoveEvent(std::string mode, int x, int y); + + void update(double dt); + + private: + + void yaw(double value); + void pitch(double value); + void roll(double value); + void translate(const osg::Vec3d& offset); + + void stabilize(); + + bool mLockUpright, mModified; + bool mFast, mLeft, mRight, mForward, mBackward, mRollLeft, mRollRight; + osg::Vec3d mUp; + + double mLinSpeed; + double mRotSpeed; + double mSpeedMult; + }; + + class OrbitCameraController : public CameraController + { + public: + + OrbitCameraController(); + + osg::Vec3d getCenter() const; + double getOrbitSpeed() const; + double getOrbitSpeedMultiplier() const; + unsigned int getPickingMask() const; + + void setCenter(const osg::Vec3d& center); + void setOrbitSpeed(double value); + void setOrbitSpeedMultiplier(double value); + void setPickingMask(unsigned int value); + + bool handleKeyEvent(QKeyEvent* event, bool pressed); + bool handleMouseMoveEvent(std::string mode, int x, int y); + + void update(double dt); + + private: + + void onActivate(); + + void initialize(); + + void rotateHorizontal(double value); + void rotateVertical(double value); + void roll(double value); + void translate(const osg::Vec3d& offset); + void zoom(double value); + + bool mInitialized; + bool mFast, mLeft, mRight, mUp, mDown, mRollLeft, mRollRight; + unsigned int mPickingMask; + osg::Vec3d mCenter; + double mDistance; + + double mOrbitSpeed; + double mOrbitSpeedMult; + }; +} + +#endif diff --git a/apps/opencs/view/render/orbitcameramode.cpp b/apps/opencs/view/render/orbitcameramode.cpp new file mode 100644 index 000000000..e6f3612c6 --- /dev/null +++ b/apps/opencs/view/render/orbitcameramode.cpp @@ -0,0 +1,37 @@ +#include "orbitcameramode.hpp" + +#include + +#include "worldspacewidget.hpp" + +namespace CSVRender +{ + OrbitCameraMode::OrbitCameraMode(WorldspaceWidget* worldspaceWidget, const QIcon& icon, const QString& tooltip, + QWidget* parent) + : ModeButton(icon, tooltip, parent) + , mWorldspaceWidget(worldspaceWidget) + , mCenterOnSelection(0) + { + } + + void OrbitCameraMode::activate(CSVWidget::SceneToolbar* toolbar) + { + mCenterOnSelection = new QAction("Center on selected object", this); + connect(mCenterOnSelection, SIGNAL(triggered()), this, SLOT(centerSelection())); + } + + bool OrbitCameraMode::createContextMenu(QMenu* menu) + { + if (menu) + { + menu->addAction(mCenterOnSelection); + } + + return true; + } + + void OrbitCameraMode::centerSelection() + { + mWorldspaceWidget->centerOrbitCameraOnSelection(); + } +} diff --git a/apps/opencs/view/render/orbitcameramode.hpp b/apps/opencs/view/render/orbitcameramode.hpp new file mode 100644 index 000000000..cd8387084 --- /dev/null +++ b/apps/opencs/view/render/orbitcameramode.hpp @@ -0,0 +1,33 @@ +#ifndef CSV_RENDER_ORBITCAMERAPICKMODE_H +#define CSV_RENDER_ORBITCAMERAPICKMODE_H + +#include "../widget/modebutton.hpp" + +namespace CSVRender +{ + class WorldspaceWidget; + + class OrbitCameraMode : public CSVWidget::ModeButton + { + Q_OBJECT + + public: + + OrbitCameraMode(WorldspaceWidget* worldspaceWidget, const QIcon& icon, const QString& tooltip = "", + QWidget* parent = 0); + + virtual void activate(CSVWidget::SceneToolbar* toolbar); + virtual bool createContextMenu(QMenu* menu); + + private: + + WorldspaceWidget* mWorldspaceWidget; + QAction* mCenterOnSelection; + + private slots: + + void centerSelection(); + }; +} + +#endif diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index d96f36692..8b20d22ba 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -6,8 +6,6 @@ #include #include -#include - #include #include "../../model/world/tablemimedata.hpp" @@ -23,7 +21,6 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells() { bool modified = false; - bool wasEmpty = mCells.empty(); const CSMWorld::IdCollection& cells = mDocument.getData().getCells(); @@ -114,11 +111,6 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells() } } - /// \todo do not overwrite manipulator object - /// \todo move code to useViewHint function - if (modified && wasEmpty) - mView->setCameraManipulator(new osgGA::TrackballManipulator); - return modified; } diff --git a/apps/opencs/view/render/previewwidget.cpp b/apps/opencs/view/render/previewwidget.cpp index a03b277d3..2f3510317 100644 --- a/apps/opencs/view/render/previewwidget.cpp +++ b/apps/opencs/view/render/previewwidget.cpp @@ -1,7 +1,5 @@ #include "previewwidget.hpp" -#include - #include "../../model/world/data.hpp" #include "../../model/world/idtable.hpp" @@ -9,7 +7,7 @@ CSVRender::PreviewWidget::PreviewWidget (CSMWorld::Data& data, const std::string& id, bool referenceable, QWidget *parent) : SceneWidget (data.getResourceSystem(), parent), mData (data), mObject(data, mRootNode, id, referenceable) { - mView->setCameraManipulator(new osgGA::TrackballManipulator); + selectNavigationMode("orbit"); QAbstractItemModel *referenceables = mData.getTableModel (CSMWorld::UniversalId::Type_Referenceables); diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index 55d9c8195..2ba396563 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -18,8 +18,11 @@ #include "../widget/scenetoolmode.hpp" +#include "../../model/prefs/state.hpp" + #include "lighting.hpp" #include "mask.hpp" +#include "cameracontroller.hpp" namespace CSVRender { @@ -57,9 +60,6 @@ RenderWidget::RenderWidget(QWidget *parent, Qt::WindowFlags f) layout->addWidget(window->getGLWidget()); setLayout(layout); - // Pass events through this widget first - window->getGLWidget()->installEventFilter(this); - mView->getCamera()->setGraphicsContext(window); mView->getCamera()->setClearColor( osg::Vec4(0.2, 0.2, 0.6, 1.0) ); mView->getCamera()->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) ); @@ -100,26 +100,6 @@ void RenderWidget::setVisibilityMask(int mask) mView->getCamera()->setCullMask(mask | Mask_ParticleSystem | Mask_Lighting); } -bool RenderWidget::eventFilter(QObject* obj, QEvent* event) -{ - // handle event in this widget, is there a better way to do this? - if (event->type() == QEvent::MouseButtonPress) - mousePressEvent(static_cast(event)); - if (event->type() == QEvent::MouseButtonRelease) - mouseReleaseEvent(static_cast(event)); - if (event->type() == QEvent::MouseMove) - mouseMoveEvent(static_cast(event)); - if (event->type() == QEvent::KeyPress) - keyPressEvent(static_cast(event)); - if (event->type() == QEvent::KeyRelease) - keyReleaseEvent(static_cast(event)); - if (event->type() == QEvent::Wheel) - wheelEvent(static_cast(event)); - - // Always pass the event on to GLWidget, i.e. to OSG event queue - return QObject::eventFilter(obj, event); -} - osg::Camera *RenderWidget::getCamera() { return mView->getCamera(); @@ -159,19 +139,33 @@ CompositeViewer &CompositeViewer::get() void CompositeViewer::update() { - mSimulationTime += mFrameTimer.time_s(); + double dt = mFrameTimer.time_s(); mFrameTimer.setStartTick(); + + emit simulationUpdated(dt); + + mSimulationTime += dt; frame(mSimulationTime); } // --------------------------------------------------- -SceneWidget::SceneWidget(boost::shared_ptr resourceSystem, QWidget *parent, Qt::WindowFlags f) +SceneWidget::SceneWidget(boost::shared_ptr resourceSystem, QWidget *parent, Qt::WindowFlags f, + bool retrieveInput) : RenderWidget(parent, f) , mResourceSystem(resourceSystem) , mLighting(NULL) , mHasDefaultAmbient(false) + , mPrevMouseX(0) + , mPrevMouseY(0) + , mFreeCamControl(new FreeCameraController()) + , mOrbitCamControl(new OrbitCameraController()) + , mCurrentCamControl(mFreeCamControl.get()) + , mCamPositionSet(false) { + mOrbitCamControl->setPickingMask(Mask_Reference | Mask_Terrain); + selectNavigationMode("free"); + // we handle lighting manually mView->setLightingMode(osgViewer::View::NO_LIGHT); @@ -182,6 +176,18 @@ SceneWidget::SceneWidget(boost::shared_ptr resourceSys /// \todo make shortcut configurable QShortcut *focusToolbar = new QShortcut (Qt::Key_T, this, 0, 0, Qt::WidgetWithChildrenShortcut); connect (focusToolbar, SIGNAL (activated()), this, SIGNAL (focusToolbarRequest())); + + connect (&CSMPrefs::State::get(), SIGNAL (settingChanged (const CSMPrefs::Setting *)), + this, SLOT (settingChanged (const CSMPrefs::Setting *))); + + // TODO update this outside of the constructor where virtual methods can be used + if (retrieveInput) + { + CSMPrefs::get()["3D Scene Input"].update(); + CSMPrefs::get()["Tooltips"].update(); + } + + connect (&CompositeViewer::get(), SIGNAL (simulationUpdated(double)), this, SLOT (update(double))); } SceneWidget::~SceneWidget() @@ -261,4 +267,181 @@ 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); + + mPrevMouseX = event->x(); + mPrevMouseY = event->y(); +} + +void SceneWidget::wheelEvent(QWheelEvent *event) +{ + mCurrentCamControl->handleMouseMoveEvent("t-navi", event->delta(), 0); +} + +void SceneWidget::keyPressEvent (QKeyEvent *event) +{ + mCurrentCamControl->handleKeyEvent(event, true); +} + +void SceneWidget::keyReleaseEvent (QKeyEvent *event) +{ + mCurrentCamControl->handleKeyEvent(event, false); +} + +void SceneWidget::update(double dt) +{ + if (mCamPositionSet) + { + mCurrentCamControl->update(dt); + } + else + { + mCurrentCamControl->setup(mRootNode, Mask_Reference | Mask_Terrain, CameraController::WorldUp); + mCamPositionSet = true; + } +} + +void SceneWidget::settingChanged (const CSMPrefs::Setting *setting) +{ + if (*setting=="3D Scene Input/p-navi-free-sensitivity") + { + mFreeCamControl->setCameraSensitivity(setting->toDouble()); + } + else if (*setting=="3D Scene Input/p-navi-orbit-sensitivity") + { + mOrbitCamControl->setCameraSensitivity(setting->toDouble()); + } + else if (*setting=="3D Scene Input/p-navi-free-invert") + { + mFreeCamControl->setInverted(setting->isTrue()); + } + else if (*setting=="3D Scene Input/p-navi-orbit-invert") + { + mOrbitCamControl->setInverted(setting->isTrue()); + } + else if (*setting=="3D Scene Input/s-navi-sensitivity") + { + mFreeCamControl->setSecondaryMovementMultiplier(setting->toDouble()); + mOrbitCamControl->setSecondaryMovementMultiplier(setting->toDouble()); + } + else if (*setting=="3D Scene Input/navi-wheel-factor") + { + mFreeCamControl->setWheelMovementMultiplier(setting->toDouble()); + mOrbitCamControl->setWheelMovementMultiplier(setting->toDouble()); + } + else if (*setting=="3D Scene Input/navi-free-lin-speed") + { + mFreeCamControl->setLinearSpeed(setting->toDouble()); + } + else if (*setting=="3D Scene Input/navi-free-rot-speed") + { + mFreeCamControl->setRotationalSpeed(setting->toDouble()); + } + else if (*setting=="3D Scene Input/navi-free-speed-mult") + { + mFreeCamControl->setSpeedMultiplier(setting->toDouble()); + } + else if (*setting=="3D Scene Input/navi-orbit-rot-speed") + { + mOrbitCamControl->setOrbitSpeed(setting->toDouble()); + } + else if (*setting=="3D Scene Input/navi-orbit-speed-mult") + { + mOrbitCamControl->setOrbitSpeedMultiplier(setting->toDouble()); + } + else + { + storeMappingSetting(setting); + } +} + +void SceneWidget::selectNavigationMode (const std::string& mode) +{ + if (mode=="1st") + { + mCurrentCamControl->setCamera(NULL); + mCurrentCamControl = mFreeCamControl.get(); + mCurrentCamControl->setCamera(getCamera()); + mFreeCamControl->fixUpAxis(CameraController::WorldUp); + } + else if (mode=="free") + { + mCurrentCamControl->setCamera(NULL); + mCurrentCamControl = mFreeCamControl.get(); + mCurrentCamControl->setCamera(getCamera()); + mFreeCamControl->unfixUpAxis(); + } + else if (mode=="orbit") + { + mCurrentCamControl->setCamera(NULL); + mCurrentCamControl = mOrbitCamControl.get(); + mCurrentCamControl->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 07a7d7600..dfda1f96c 100644 --- a/apps/opencs/view/render/scenewidget.hpp +++ b/apps/opencs/view/render/scenewidget.hpp @@ -1,6 +1,9 @@ #ifndef OPENCS_VIEW_SCENEWIDGET_H #define OPENCS_VIEW_SCENEWIDGET_H +#include +#include + #include #include @@ -30,93 +33,135 @@ namespace CSVWidget class SceneToolbar; } +namespace CSMPrefs +{ + class Setting; +} + namespace CSVRender { + class CameraController; + class FreeCameraController; + class OrbitCameraController; class Lighting; class RenderWidget : public QWidget { - Q_OBJECT - - public: - RenderWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); - virtual ~RenderWidget(); + Q_OBJECT - void flagAsModified(); + public: + RenderWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); + virtual ~RenderWidget(); - void setVisibilityMask(int mask); + void flagAsModified(); - bool eventFilter(QObject *, QEvent *); + void setVisibilityMask(int mask); - osg::Camera *getCamera(); + osg::Camera *getCamera(); - protected: + protected: - osg::ref_ptr mView; + osg::ref_ptr mView; - osg::Group* mRootNode; + osg::Group* mRootNode; - QTimer mTimer; + QTimer mTimer; }; // 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); - virtual ~SceneWidget(); + 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); + ///< \attention The created tool is not added to the toolbar (via addTool). Doing that + /// is the responsibility of the calling function. + + void setDefaultAmbient (const osg::Vec4f& colour); + ///< \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); - CSVWidget::SceneToolMode *makeLightingSelector (CSVWidget::SceneToolbar *parent); - ///< \attention The created tool is not added to the toolbar (via addTool). Doing that - /// is the responsibility of the calling function. + virtual void mousePressEvent (QMouseEvent *event); + virtual void mouseReleaseEvent (QMouseEvent *event); + virtual void mouseMoveEvent (QMouseEvent *event); + virtual void wheelEvent (QWheelEvent *event); + virtual void keyPressEvent (QKeyEvent *event); + virtual void keyReleaseEvent (QKeyEvent *event); - void setDefaultAmbient (const osg::Vec4f& colour); - ///< \note The actual ambient colour may differ based on lighting settings. + /// \return Is \a key a button mapping setting? (ignored otherwise) + virtual bool storeMappingSetting (const CSMPrefs::Setting *setting); - protected: - void setLighting (Lighting *lighting); - ///< \attention The ownership of \a lighting is not transferred to *this. + std::string mapButton (QMouseEvent *event); - void setAmbient(const osg::Vec4f& ambient); + boost::shared_ptr mResourceSystem; - boost::shared_ptr mResourceSystem; + Lighting* mLighting; - Lighting* mLighting; + osg::Vec4f mDefaultAmbient; + bool mHasDefaultAmbient; + LightingDay mLightingDay; + LightingNight mLightingNight; + LightingBright mLightingBright; - osg::Vec4f mDefaultAmbient; - bool mHasDefaultAmbient; - LightingDay mLightingDay; - LightingNight mLightingNight; - LightingBright mLightingBright; + int mPrevMouseX, mPrevMouseY; + std::string mMouseMode; + std::auto_ptr mFreeCamControl; + std::auto_ptr mOrbitCamControl; + CameraController* mCurrentCamControl; - private slots: + std::map, std::string> mButtonMapping; - void selectLightingMode (const std::string& mode); + private: + bool mCamPositionSet; + + public slots: + void update(double dt); + + protected slots: + + virtual void settingChanged (const CSMPrefs::Setting *setting); + + void selectNavigationMode (const std::string& mode); + + private slots: + + void selectLightingMode (const std::string& mode); signals: - void focusToolbarRequest(); + void focusToolbarRequest(); }; // There are rendering glitches when using multiple Viewer instances, work around using CompositeViewer with multiple views class CompositeViewer : public QObject, public osgViewer::CompositeViewer { - Q_OBJECT - public: - CompositeViewer(); + Q_OBJECT + public: + CompositeViewer(); - static CompositeViewer& get(); + static CompositeViewer& get(); - QTimer mTimer; + QTimer mTimer; - private: - osg::Timer mFrameTimer; - double mSimulationTime; + private: + osg::Timer mFrameTimer; + double mSimulationTime; - public slots: - void update(); + public slots: + void update(); + + signals: + void simulationUpdated(double dt); }; } diff --git a/apps/opencs/view/render/unpagedworldspacewidget.cpp b/apps/opencs/view/render/unpagedworldspacewidget.cpp index 16c28cf93..79ffd4fb0 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.cpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.cpp @@ -2,8 +2,6 @@ #include -#include - #include #include @@ -50,8 +48,6 @@ CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& update(); mCell.reset (new Cell (document.getData(), mRootNode, mCellId)); - - mView->setCameraManipulator(new osgGA::TrackballManipulator); } void CSVRender::UnpagedWorldspaceWidget::cellDataChanged (const QModelIndex& topLeft, diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index df5790473..927ce545f 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -12,9 +12,6 @@ #include #include -#include -#include - #include #include "../../model/world/universalid.hpp" @@ -22,6 +19,8 @@ #include "../../model/prefs/state.hpp" +#include "../render/orbitcameramode.hpp" + #include "../widget/scenetoolmode.hpp" #include "../widget/scenetooltoggle2.hpp" #include "../widget/scenetoolrun.hpp" @@ -30,9 +29,10 @@ #include "mask.hpp" #include "editmode.hpp" #include "instancemode.hpp" +#include "cameracontroller.hpp" CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent) -: SceneWidget (document.getData().getResourceSystem(), parent), mSceneElements(0), mRun(0), mDocument(document), +: 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) @@ -67,13 +67,11 @@ CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidg connect (debugProfiles, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)), this, SLOT (debugProfileAboutToBeRemoved (const QModelIndex&, int, int))); - connect (&CSMPrefs::State::get(), SIGNAL (settingChanged (const CSMPrefs::Setting *)), - this, SLOT (settingChanged (const CSMPrefs::Setting *))); - CSMPrefs::get()["3D Scene Input"].update(); - CSMPrefs::get()["Tooltips"].update(); - mToolTipDelayTimer.setSingleShot (true); connect (&mToolTipDelayTimer, SIGNAL (timeout()), this, SLOT (showToolTip())); + + CSMPrefs::get()["3D Scene Input"].update(); + CSMPrefs::get()["Tooltips"].update(); } CSVRender::WorldspaceWidget::~WorldspaceWidget () @@ -82,9 +80,6 @@ CSVRender::WorldspaceWidget::~WorldspaceWidget () void CSVRender::WorldspaceWidget::settingChanged (const CSMPrefs::Setting *setting) { - if (storeMappingSetting (setting)) - return; - if (*setting=="3D Scene Input/drag-factor") mDragFactor = setting->toDouble(); else if (*setting=="3D Scene Input/drag-wheel-factor") @@ -95,23 +90,29 @@ void CSVRender::WorldspaceWidget::settingChanged (const CSMPrefs::Setting *setti mToolTipDelay = setting->toInt(); else if (*setting=="Tooltips/scene") mShowToolTips = setting->isTrue(); + else + SceneWidget::settingChanged(setting); } -void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode) -{ - if (mode=="1st") - mView->setCameraManipulator(new osgGA::FirstPersonManipulator); - else if (mode=="free") - mView->setCameraManipulator(new osgGA::FirstPersonManipulator); - else if (mode=="orbit") - mView->setCameraManipulator(new osgGA::OrbitManipulator); -} void CSVRender::WorldspaceWidget::useViewHint (const std::string& hint) {} void CSVRender::WorldspaceWidget::selectDefaultNavigationMode() { - mView->setCameraManipulator(new osgGA::FirstPersonManipulator); + selectNavigationMode("1st"); +} + +void CSVRender::WorldspaceWidget::centerOrbitCameraOnSelection() +{ + std::vector > selection = getSelection(~0); + + for (std::vector >::iterator it = selection.begin(); it!=selection.end(); ++it) + { + if (CSVRender::ObjectTag *objectTag = dynamic_cast (it->get())) + { + mOrbitCamControl->setCenter(objectTag->mObject->getPosition().asVec3()); + } + } } CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector ( @@ -138,15 +139,17 @@ CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector ( "
  • Roll camera with Q and E keys
  • " "
  • Hold shift to speed up movement
  • " ""); - tool->addButton (":scenetoolbar/orbiting-camera", "orbit", - "Orbiting Camera" - "
    • Always facing the centre point
    • " - "
    • Rotate around the centre point via WASD or by moving the mouse while holding the left button
    • " - "
    • Mouse wheel moves camera away or towards centre point but can not pass through it
    • " - "
    • Roll camera with Q and E keys
    • " - "
    • Strafing (also vertically) by holding the left mouse button and control (includes relocation of the centre point)
    • " - "
    • Hold shift to speed up movement
    • " - "
    "); + tool->addButton( + new CSVRender::OrbitCameraMode(this, QIcon(":scenetoolbar/orbiting-camera"), + "Orbiting Camera" + "
    • Always facing the centre point
    • " + "
    • Rotate around the centre point via WASD or by moving the mouse while holding the left button
    • " + "
    • Mouse wheel moves camera away or towards centre point but can not pass through it
    • " + "
    • Roll camera with Q and E keys
    • " + "
    • Strafing (also vertically) by holding the left mouse button and control (includes relocation of the centre point)
    • " + "
    • Hold shift to speed up movement
    • " + "
    ", tool), + "orbit"); connect (tool, SIGNAL (modeChanged (const std::string&)), this, SLOT (selectNavigationMode (const std::string&))); @@ -418,40 +421,41 @@ void CSVRender::WorldspaceWidget::dragMoveEvent(QDragMoveEvent *event) bool CSVRender::WorldspaceWidget::storeMappingSetting (const CSMPrefs::Setting *setting) { - if (setting->getParent()->getKey()!="3D Scene Input") - return false; - static const char * const sMappingSettings[] = { - "p-navi", "s-navi", "p-edit", "s-edit", "p-select", "s-select", 0 }; - for (int i=0; sMappingSettings[i]; ++i) - if (setting->getKey()==sMappingSettings[i]) + if (setting->getParent()->getKey()=="3D Scene Input") + { + for (int i=0; sMappingSettings[i]; ++i) { - QString value = QString::fromUtf8 (setting->toString().c_str()); + if (setting->getKey()==sMappingSettings[i]) + { + QString value = QString::fromUtf8 (setting->toString().c_str()); - Qt::MouseButton button = Qt::NoButton; + 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; + 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-"); + bool ctrl = value.startsWith ("Ctrl-"); - mButtonMapping[std::make_pair (button, ctrl)] = sMappingSettings[i]; - return true; + mButtonMapping[std::make_pair (button, ctrl)] = sMappingSettings[i]; + return true; + } } + } - return false; + return SceneWidget::storeMappingSetting(setting); } osg::ref_ptr CSVRender::WorldspaceWidget::mousePick (const QPoint& localPos) @@ -496,20 +500,6 @@ osg::ref_ptr CSVRender::WorldspaceWidget::mousePick (const Q return osg::ref_ptr(); } -std::string CSVRender::WorldspaceWidget::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 ""; -} - void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event) { const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); @@ -615,50 +605,7 @@ void CSVRender::WorldspaceWidget::updateOverlay() void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) { - if (!mDragging) - { - if (mDragMode.empty()) - { - if (event->globalPos()!=mToolTipPos) - { - mToolTipPos = event->globalPos(); - - if (mShowToolTips) - mToolTipDelayTimer.start (mToolTipDelay); - } - } - else if (mDragMode=="p-navi" || mDragMode=="s-navi") - { - - } - else if (mDragMode=="p-edit" || mDragMode=="s-edit" || mDragMode=="p-select" || mDragMode=="s-select") - { - osg::ref_ptr tag = mousePick (event->pos()); - - EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); - - if (mDragMode=="p-edit") - mDragging = editMode.primaryEditStartDrag (tag); - else if (mDragMode=="s-edit") - mDragging = editMode.secondaryEditStartDrag (tag); - else if (mDragMode=="p-select") - mDragging = editMode.primarySelectStartDrag (tag); - else if (mDragMode=="s-select") - mDragging = editMode.secondarySelectStartDrag (tag); - - if (mDragging) - { -#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) - mDragX = event->localPos().x(); - mDragY = height() - event->localPos().y(); -#else - mDragX = event->posF().x(); - mDragY = height() - event->posF().y(); -#endif - } - } - } - else + if (mDragging) { int diffX = event->x() - mDragX; int diffY = (height() - event->y()) - mDragY; @@ -675,59 +622,84 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) editMode.drag (diffX, diffY, factor); } + else if (mDragMode=="p-edit" || mDragMode=="s-edit" || mDragMode=="p-select" || mDragMode=="s-select") + { + osg::ref_ptr tag = mousePick (event->pos()); + + EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); + + if (mDragMode=="p-edit") + mDragging = editMode.primaryEditStartDrag (tag); + else if (mDragMode=="s-edit") + mDragging = editMode.secondaryEditStartDrag (tag); + else if (mDragMode=="p-select") + mDragging = editMode.primarySelectStartDrag (tag); + else if (mDragMode=="s-select") + mDragging = editMode.secondarySelectStartDrag (tag); + + if (mDragging) + { +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + mDragX = event->localPos().x(); + mDragY = height() - event->localPos().y(); +#else + mDragX = event->posF().x(); + mDragY = height() - event->posF().y(); +#endif + } + } + else + { + if (event->globalPos()!=mToolTipPos) + { + mToolTipPos = event->globalPos(); + + if (mShowToolTips) + mToolTipDelayTimer.start (mToolTipDelay); + } + + SceneWidget::mouseMoveEvent(event); + } } void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event) { std::string button = mapButton (event); - if (!mDragging) - mDragMode = button; + 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 (mDragging) + if (button=="p-edit" || button=="s-edit" || + button=="p-select" || button=="s-select") { - if (mDragMode=="p-navi" || mDragMode=="s-navi") - { - - } - else if (mDragMode=="p-edit" || mDragMode=="s-edit" || - mDragMode=="p-select" || mDragMode=="s-select") + if (mDragging) { EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); editMode.dragCompleted(); mDragging = false; } - } - else - { - if (button=="p-navi" || button=="s-navi") - { - - } - else if (button=="p-edit" || button=="s-edit" || - button=="p-select" || button=="s-select") + else { osg::ref_ptr tag = mousePick (event->pos()); handleMouseClick (tag, button, event->modifiers() & Qt::ShiftModifier); } } - - mDragMode.clear(); -} - -void CSVRender::WorldspaceWidget::mouseDoubleClickEvent (QMouseEvent *event) -{ - if(event->button() == Qt::RightButton) - { - //mMouse->mouseDoubleClickEvent(event); - } + else + SceneWidget::mouseReleaseEvent(event); } void CSVRender::WorldspaceWidget::wheelEvent (QWheelEvent *event) @@ -743,6 +715,8 @@ void CSVRender::WorldspaceWidget::wheelEvent (QWheelEvent *event) editMode.dragWheel (event->delta(), factor); } + else + SceneWidget::wheelEvent(event); } void CSVRender::WorldspaceWidget::keyPressEvent (QKeyEvent *event) @@ -752,7 +726,7 @@ void CSVRender::WorldspaceWidget::keyPressEvent (QKeyEvent *event) abortDrag(); } else - RenderWidget::keyPressEvent(event); + SceneWidget::keyPressEvent(event); } void CSVRender::WorldspaceWidget::handleMouseClick (osg::ref_ptr tag, const std::string& button, bool shift) diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 4c9c0c31e..b18123944 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -1,8 +1,6 @@ #ifndef OPENCS_VIEW_WORLDSPACEWIDGET_H #define OPENCS_VIEW_WORLDSPACEWIDGET_H -#include - #include #include @@ -45,7 +43,6 @@ namespace CSVRender CSVWidget::SceneToolRun *mRun; CSMDoc::Document& mDocument; unsigned int mInteractionMask; - std::map, std::string> mButtonMapping; CSVWidget::SceneToolMode *mEditMode; bool mLocked; std::string mDragMode; @@ -100,6 +97,8 @@ namespace CSVRender void selectDefaultNavigationMode(); + void centerOrbitCameraOnSelection(); + static DropType getDropType(const std::vector& data); virtual dropRequirments getDropRequirements(DropType type) const; @@ -189,13 +188,17 @@ namespace CSVRender virtual void mouseMoveEvent (QMouseEvent *event); virtual void mousePressEvent (QMouseEvent *event); virtual void mouseReleaseEvent (QMouseEvent *event); - virtual void mouseDoubleClickEvent (QMouseEvent *event); virtual void wheelEvent (QWheelEvent *event); virtual void keyPressEvent (QKeyEvent *event); virtual void handleMouseClick (osg::ref_ptr tag, 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 settingChanged (const CSMPrefs::Setting *setting); + EditMode *getEditMode(); private: @@ -206,21 +209,12 @@ namespace CSVRender void dragMoveEvent(QDragMoveEvent *event); - /// \return Is \a key a button mapping setting? (ignored otherwise) - bool storeMappingSetting (const CSMPrefs::Setting *setting); - osg::ref_ptr mousePick (const QPoint& localPos); - std::string mapButton (QMouseEvent *event); - virtual std::string getStartupInstruction() = 0; private slots: - void settingChanged (const CSMPrefs::Setting *setting); - - void selectNavigationMode (const std::string& mode); - virtual void referenceableDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) = 0; diff --git a/extern/osgQt/GraphicsWindowQt b/extern/osgQt/GraphicsWindowQt index 54d069176..ad456ef44 100644 --- a/extern/osgQt/GraphicsWindowQt +++ b/extern/osgQt/GraphicsWindowQt @@ -56,32 +56,15 @@ class GLWidget : public QGLWidget public: - GLWidget( QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false ); - GLWidget( QGLContext* context, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false ); - GLWidget( const QGLFormat& format, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false ); + GLWidget( QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0); + GLWidget( QGLContext* context, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0); + GLWidget( const QGLFormat& format, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0); virtual ~GLWidget(); inline void setGraphicsWindow( GraphicsWindowQt* gw ) { _gw = gw; } inline GraphicsWindowQt* getGraphicsWindow() { return _gw; } inline const GraphicsWindowQt* getGraphicsWindow() const { return _gw; } - inline bool getForwardKeyEvents() const { return _forwardKeyEvents; } - virtual void setForwardKeyEvents( bool f ) { _forwardKeyEvents = f; } - - inline bool getTouchEventsEnabled() const { return _touchEventsEnabled; } - void setTouchEventsEnabled( bool e ); - - void setKeyboardModifiers( QInputEvent* event ); - - virtual void keyPressEvent( QKeyEvent* event ); - virtual void keyReleaseEvent( QKeyEvent* event ); - virtual void mousePressEvent( QMouseEvent* event ); - virtual void mouseReleaseEvent( QMouseEvent* event ); - virtual void mouseDoubleClickEvent( QMouseEvent* event ); - virtual void mouseMoveEvent( QMouseEvent* event ); - virtual void wheelEvent( QWheelEvent* event ); - virtual bool gestureEvent( QGestureEvent* event ); - protected: int getNumDeferredEvents() @@ -114,9 +97,6 @@ protected: QQueue _deferredEventQueue; QSet _eventCompressor; - bool _touchEventsEnabled; - - bool _forwardKeyEvents; qreal _devicePixelRatio; virtual void resizeEvent( QResizeEvent* event ); @@ -164,9 +144,6 @@ public: virtual std::string getWindowName(); virtual void useCursor( bool cursorOn ); virtual void setCursor( MouseCursor cursor ); - inline bool getTouchEventsEnabled() const { return _widget->getTouchEventsEnabled(); } - virtual void setTouchEventsEnabled( bool e ) { _widget->setTouchEventsEnabled(e); } - virtual bool valid() const; virtual bool realizeImplementation(); diff --git a/extern/osgQt/GraphicsWindowQt.cpp b/extern/osgQt/GraphicsWindowQt.cpp index 2001c8b31..46df7216c 100644 --- a/extern/osgQt/GraphicsWindowQt.cpp +++ b/extern/osgQt/GraphicsWindowQt.cpp @@ -26,98 +26,6 @@ using namespace osgQt; - -class QtKeyboardMap -{ - -public: - QtKeyboardMap() - { - mKeyMap[Qt::Key_Escape ] = osgGA::GUIEventAdapter::KEY_Escape; - mKeyMap[Qt::Key_Delete ] = osgGA::GUIEventAdapter::KEY_Delete; - mKeyMap[Qt::Key_Home ] = osgGA::GUIEventAdapter::KEY_Home; - mKeyMap[Qt::Key_Enter ] = osgGA::GUIEventAdapter::KEY_KP_Enter; - mKeyMap[Qt::Key_End ] = osgGA::GUIEventAdapter::KEY_End; - mKeyMap[Qt::Key_Return ] = osgGA::GUIEventAdapter::KEY_Return; - mKeyMap[Qt::Key_PageUp ] = osgGA::GUIEventAdapter::KEY_Page_Up; - mKeyMap[Qt::Key_PageDown ] = osgGA::GUIEventAdapter::KEY_Page_Down; - mKeyMap[Qt::Key_Left ] = osgGA::GUIEventAdapter::KEY_Left; - mKeyMap[Qt::Key_Right ] = osgGA::GUIEventAdapter::KEY_Right; - mKeyMap[Qt::Key_Up ] = osgGA::GUIEventAdapter::KEY_Up; - mKeyMap[Qt::Key_Down ] = osgGA::GUIEventAdapter::KEY_Down; - mKeyMap[Qt::Key_Backspace ] = osgGA::GUIEventAdapter::KEY_BackSpace; - mKeyMap[Qt::Key_Tab ] = osgGA::GUIEventAdapter::KEY_Tab; - mKeyMap[Qt::Key_Space ] = osgGA::GUIEventAdapter::KEY_Space; - mKeyMap[Qt::Key_Delete ] = osgGA::GUIEventAdapter::KEY_Delete; - mKeyMap[Qt::Key_Alt ] = osgGA::GUIEventAdapter::KEY_Alt_L; - mKeyMap[Qt::Key_Shift ] = osgGA::GUIEventAdapter::KEY_Shift_L; - mKeyMap[Qt::Key_Control ] = osgGA::GUIEventAdapter::KEY_Control_L; - mKeyMap[Qt::Key_Meta ] = osgGA::GUIEventAdapter::KEY_Meta_L; - - mKeyMap[Qt::Key_F1 ] = osgGA::GUIEventAdapter::KEY_F1; - mKeyMap[Qt::Key_F2 ] = osgGA::GUIEventAdapter::KEY_F2; - mKeyMap[Qt::Key_F3 ] = osgGA::GUIEventAdapter::KEY_F3; - mKeyMap[Qt::Key_F4 ] = osgGA::GUIEventAdapter::KEY_F4; - mKeyMap[Qt::Key_F5 ] = osgGA::GUIEventAdapter::KEY_F5; - mKeyMap[Qt::Key_F6 ] = osgGA::GUIEventAdapter::KEY_F6; - mKeyMap[Qt::Key_F7 ] = osgGA::GUIEventAdapter::KEY_F7; - mKeyMap[Qt::Key_F8 ] = osgGA::GUIEventAdapter::KEY_F8; - mKeyMap[Qt::Key_F9 ] = osgGA::GUIEventAdapter::KEY_F9; - mKeyMap[Qt::Key_F10 ] = osgGA::GUIEventAdapter::KEY_F10; - mKeyMap[Qt::Key_F11 ] = osgGA::GUIEventAdapter::KEY_F11; - mKeyMap[Qt::Key_F12 ] = osgGA::GUIEventAdapter::KEY_F12; - mKeyMap[Qt::Key_F13 ] = osgGA::GUIEventAdapter::KEY_F13; - mKeyMap[Qt::Key_F14 ] = osgGA::GUIEventAdapter::KEY_F14; - mKeyMap[Qt::Key_F15 ] = osgGA::GUIEventAdapter::KEY_F15; - mKeyMap[Qt::Key_F16 ] = osgGA::GUIEventAdapter::KEY_F16; - mKeyMap[Qt::Key_F17 ] = osgGA::GUIEventAdapter::KEY_F17; - mKeyMap[Qt::Key_F18 ] = osgGA::GUIEventAdapter::KEY_F18; - mKeyMap[Qt::Key_F19 ] = osgGA::GUIEventAdapter::KEY_F19; - mKeyMap[Qt::Key_F20 ] = osgGA::GUIEventAdapter::KEY_F20; - - mKeyMap[Qt::Key_hyphen ] = '-'; - mKeyMap[Qt::Key_Equal ] = '='; - - mKeyMap[Qt::Key_division ] = osgGA::GUIEventAdapter::KEY_KP_Divide; - mKeyMap[Qt::Key_multiply ] = osgGA::GUIEventAdapter::KEY_KP_Multiply; - mKeyMap[Qt::Key_Minus ] = '-'; - mKeyMap[Qt::Key_Plus ] = '+'; - //mKeyMap[Qt::Key_H ] = osgGA::GUIEventAdapter::KEY_KP_Home; - //mKeyMap[Qt::Key_ ] = osgGA::GUIEventAdapter::KEY_KP_Up; - //mKeyMap[92 ] = osgGA::GUIEventAdapter::KEY_KP_Page_Up; - //mKeyMap[86 ] = osgGA::GUIEventAdapter::KEY_KP_Left; - //mKeyMap[87 ] = osgGA::GUIEventAdapter::KEY_KP_Begin; - //mKeyMap[88 ] = osgGA::GUIEventAdapter::KEY_KP_Right; - //mKeyMap[83 ] = osgGA::GUIEventAdapter::KEY_KP_End; - //mKeyMap[84 ] = osgGA::GUIEventAdapter::KEY_KP_Down; - //mKeyMap[85 ] = osgGA::GUIEventAdapter::KEY_KP_Page_Down; - mKeyMap[Qt::Key_Insert ] = osgGA::GUIEventAdapter::KEY_KP_Insert; - //mKeyMap[Qt::Key_Delete ] = osgGA::GUIEventAdapter::KEY_KP_Delete; - } - - ~QtKeyboardMap() - { - } - - int remapKey(QKeyEvent* event) - { - KeyMap::iterator itr = mKeyMap.find(event->key()); - if (itr == mKeyMap.end()) - { - return int(*(event->text().toLatin1().data())); - } - else - return itr->second; - } - - private: - typedef std::map KeyMap; - KeyMap mKeyMap; -}; - -static QtKeyboardMap s_QtKeyboardMap; - - /// The object responsible for the scene re-rendering. class HeartBeat : public QObject { public: @@ -126,7 +34,7 @@ public: osg::observer_ptr< osgViewer::ViewerBase > _viewer; virtual ~HeartBeat(); - + void init( osgViewer::ViewerBase *viewer ); void stopTimer(); void timerEvent( QTimerEvent *event ); @@ -146,31 +54,20 @@ QPointer HeartBeat::heartBeat; #define GETDEVICEPIXELRATIO() devicePixelRatio() #endif -GLWidget::GLWidget( QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f, bool forwardKeyEvents ) -: QGLWidget(parent, shareWidget, f), -_gw( NULL ), -_touchEventsEnabled( false ), -_forwardKeyEvents( forwardKeyEvents ) +GLWidget::GLWidget( QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f) +: QGLWidget(parent, shareWidget, f), _gw( NULL ) { _devicePixelRatio = GETDEVICEPIXELRATIO(); } -GLWidget::GLWidget( QGLContext* context, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f, - bool forwardKeyEvents ) -: QGLWidget(context, parent, shareWidget, f), -_gw( NULL ), -_touchEventsEnabled( false ), -_forwardKeyEvents( forwardKeyEvents ) +GLWidget::GLWidget( QGLContext* context, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f) +: QGLWidget(context, parent, shareWidget, f), _gw( NULL ) { _devicePixelRatio = GETDEVICEPIXELRATIO(); } -GLWidget::GLWidget( const QGLFormat& format, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f, - bool forwardKeyEvents ) -: QGLWidget(format, parent, shareWidget, f), -_gw( NULL ), -_touchEventsEnabled( false ), -_forwardKeyEvents( forwardKeyEvents ) +GLWidget::GLWidget( const QGLFormat& format, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f) +: QGLWidget(format, parent, shareWidget, f), _gw( NULL ) { _devicePixelRatio = GETDEVICEPIXELRATIO(); } @@ -186,25 +83,6 @@ GLWidget::~GLWidget() } } -void GLWidget::setTouchEventsEnabled(bool e) -{ -#ifdef USE_GESTURES - if (e==_touchEventsEnabled) - return; - - _touchEventsEnabled = e; - - if (_touchEventsEnabled) - { - grabGesture(Qt::PinchGesture); - } - else - { - ungrabGesture(Qt::PinchGesture); - } -#endif -} - void GLWidget::processDeferredEvents() { QQueue deferredEventQueueCopy; @@ -224,10 +102,6 @@ void GLWidget::processDeferredEvents() bool GLWidget::event( QEvent* event ) { -#ifdef USE_GESTURES - if ( event->type()==QEvent::Gesture ) - return gestureEvent(static_cast(event)); -#endif // QEvent::Hide // @@ -274,16 +148,6 @@ bool GLWidget::event( QEvent* event ) return QGLWidget::event( event ); } -void GLWidget::setKeyboardModifiers( QInputEvent* event ) -{ - int modkey = event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier); - unsigned int mask = 0; - if ( modkey & Qt::ShiftModifier ) mask |= osgGA::GUIEventAdapter::MODKEY_SHIFT; - if ( modkey & Qt::ControlModifier ) mask |= osgGA::GUIEventAdapter::MODKEY_CTRL; - if ( modkey & Qt::AltModifier ) mask |= osgGA::GUIEventAdapter::MODKEY_ALT; - _gw->getEventQueue()->getCurrentEventState()->setModKeyMask( mask ); -} - void GLWidget::resizeEvent( QResizeEvent* event ) { const QSize& size = event->size(); @@ -309,178 +173,6 @@ void GLWidget::glDraw() _gw->requestRedraw(); } -void GLWidget::keyPressEvent( QKeyEvent* event ) -{ - setKeyboardModifiers( event ); - int value = s_QtKeyboardMap.remapKey( event ); - _gw->getEventQueue()->keyPress( value ); - - // this passes the event to the regular Qt key event processing, - // among others, it closes popup windows on ESC and forwards the event to the parent widgets - if( _forwardKeyEvents ) - inherited::keyPressEvent( event ); -} - -void GLWidget::keyReleaseEvent( QKeyEvent* event ) -{ - if( event->isAutoRepeat() ) - { - event->ignore(); - } - else - { - setKeyboardModifiers( event ); - int value = s_QtKeyboardMap.remapKey( event ); - _gw->getEventQueue()->keyRelease( value ); - } - - // this passes the event to the regular Qt key event processing, - // among others, it closes popup windows on ESC and forwards the event to the parent widgets - if( _forwardKeyEvents ) - inherited::keyReleaseEvent( event ); -} - -void GLWidget::mousePressEvent( QMouseEvent* event ) -{ - int button = 0; - switch ( event->button() ) - { - case Qt::LeftButton: button = 1; break; - case Qt::MidButton: button = 2; break; - case Qt::RightButton: button = 3; break; - case Qt::NoButton: button = 0; break; - default: button = 0; break; - } - setKeyboardModifiers( event ); - _gw->getEventQueue()->mouseButtonPress( event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button ); -} - -void GLWidget::mouseReleaseEvent( QMouseEvent* event ) -{ - int button = 0; - switch ( event->button() ) - { - case Qt::LeftButton: button = 1; break; - case Qt::MidButton: button = 2; break; - case Qt::RightButton: button = 3; break; - case Qt::NoButton: button = 0; break; - default: button = 0; break; - } - setKeyboardModifiers( event ); - _gw->getEventQueue()->mouseButtonRelease( event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button ); -} - -void GLWidget::mouseDoubleClickEvent( QMouseEvent* event ) -{ - int button = 0; - switch ( event->button() ) - { - case Qt::LeftButton: button = 1; break; - case Qt::MidButton: button = 2; break; - case Qt::RightButton: button = 3; break; - case Qt::NoButton: button = 0; break; - default: button = 0; break; - } - setKeyboardModifiers( event ); - _gw->getEventQueue()->mouseDoubleButtonPress( event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button ); -} - -void GLWidget::mouseMoveEvent( QMouseEvent* event ) -{ - setKeyboardModifiers( event ); - _gw->getEventQueue()->mouseMotion( event->x()*_devicePixelRatio, event->y()*_devicePixelRatio ); -} - -void GLWidget::wheelEvent( QWheelEvent* event ) -{ - setKeyboardModifiers( event ); - _gw->getEventQueue()->mouseScroll( - event->orientation() == Qt::Vertical ? - (event->delta()>0 ? osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN) : - (event->delta()>0 ? osgGA::GUIEventAdapter::SCROLL_LEFT : osgGA::GUIEventAdapter::SCROLL_RIGHT) ); -} - -#ifdef USE_GESTURES -static osgGA::GUIEventAdapter::TouchPhase translateQtGestureState( Qt::GestureState state ) -{ - osgGA::GUIEventAdapter::TouchPhase touchPhase; - switch ( state ) - { - case Qt::GestureStarted: - touchPhase = osgGA::GUIEventAdapter::TOUCH_BEGAN; - break; - case Qt::GestureUpdated: - touchPhase = osgGA::GUIEventAdapter::TOUCH_MOVED; - break; - case Qt::GestureFinished: - case Qt::GestureCanceled: - touchPhase = osgGA::GUIEventAdapter::TOUCH_ENDED; - break; - default: - touchPhase = osgGA::GUIEventAdapter::TOUCH_UNKNOWN; - }; - - return touchPhase; -} -#endif - - -bool GLWidget::gestureEvent( QGestureEvent* qevent ) -{ -#ifndef USE_GESTURES - return false; -#else - - bool accept = false; - - if ( QPinchGesture* pinch = static_cast(qevent->gesture(Qt::PinchGesture) ) ) - { - const QPointF qcenterf = pinch->centerPoint(); - const float angle = pinch->totalRotationAngle(); - const float scale = pinch->totalScaleFactor(); - - const QPoint pinchCenterQt = mapFromGlobal(qcenterf.toPoint()); - const osg::Vec2 pinchCenter( pinchCenterQt.x(), pinchCenterQt.y() ); - - //We don't have absolute positions of the two touches, only a scale and rotation - //Hence we create pseudo-coordinates which are reasonable, and centered around the - //real position - const float radius = (width()+height())/4; - const osg::Vec2 vector( scale*cos(angle)*radius, scale*sin(angle)*radius); - const osg::Vec2 p0 = pinchCenter+vector; - const osg::Vec2 p1 = pinchCenter-vector; - - osg::ref_ptr event = 0; - const osgGA::GUIEventAdapter::TouchPhase touchPhase = translateQtGestureState( pinch->state() ); - if ( touchPhase==osgGA::GUIEventAdapter::TOUCH_BEGAN ) - { - event = _gw->getEventQueue()->touchBegan(0 , touchPhase, p0[0], p0[1] ); - } - else if ( touchPhase==osgGA::GUIEventAdapter::TOUCH_MOVED ) - { - event = _gw->getEventQueue()->touchMoved( 0, touchPhase, p0[0], p0[1] ); - } - else - { - event = _gw->getEventQueue()->touchEnded( 0, touchPhase, p0[0], p0[1], 1 ); - } - - if ( event ) - { - event->addTouchPoint( 1, touchPhase, p1[0], p1[1] ); - accept = true; - } - } - - if ( accept ) - qevent->accept(); - - return accept; -#endif -} - - - GraphicsWindowQt::GraphicsWindowQt( osg::GraphicsContext::Traits* traits, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f ) : _realized(false) { @@ -1016,7 +708,7 @@ void HeartBeat::init( osgViewer::ViewerBase *viewer ) } -void HeartBeat::timerEvent( QTimerEvent */*event*/ ) +void HeartBeat::timerEvent( QTimerEvent * /*event*/ ) { osg::ref_ptr< osgViewer::ViewerBase > viewer; if( !_viewer.lock( viewer ) )