Merge remote-tracking branch 'aesylwinn/editor_camera'

openmw-39
Marc Zinnschlag 9 years ago
commit 60509875e8

@ -86,11 +86,12 @@ opencs_units (view/widget
opencs_units (view/render opencs_units (view/render
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
previewwidget editmode instancemode instanceselectionmode instancemovemode previewwidget editmode instancemode instanceselectionmode instancemovemode
orbitcameramode
) )
opencs_units_noqt (view/render opencs_units_noqt (view/render
lighting lightingday lightingnight lighting lightingday lightingnight lightingbright object cell terrainstorage tagbase
lightingbright object cell terrainstorage tagbase cellarrow cellmarker cellborder cellarrow cellmarker cellborder cameracontroller
) )
opencs_hdrs_noqt (view/render opencs_hdrs_noqt (view/render

@ -15,10 +15,16 @@
CSMPrefs::DoubleSetting::DoubleSetting (Category *parent, Settings::Manager *values, CSMPrefs::DoubleSetting::DoubleSetting (Category *parent, Settings::Manager *values,
QMutex *mutex, const std::string& key, const std::string& label, double default_) QMutex *mutex, const std::string& key, const std::string& label, double default_)
: Setting (parent, values, mutex, key, label), : Setting (parent, values, mutex, key, label),
mMin (0), mMax (std::numeric_limits<double>::max()), mPrecision(2), mMin (0), mMax (std::numeric_limits<double>::max()),
mDefault (default_) mDefault (default_)
{} {}
CSMPrefs::DoubleSetting& CSMPrefs::DoubleSetting::setPrecision(int precision)
{
mPrecision = precision;
return *this;
}
CSMPrefs::DoubleSetting& CSMPrefs::DoubleSetting::setRange (double min, double max) CSMPrefs::DoubleSetting& CSMPrefs::DoubleSetting::setRange (double min, double max)
{ {
mMin = min; mMin = min;
@ -49,6 +55,7 @@ std::pair<QWidget *, QWidget *> CSMPrefs::DoubleSetting::makeWidgets (QWidget *p
QLabel *label = new QLabel (QString::fromUtf8 (getLabel().c_str()), parent); QLabel *label = new QLabel (QString::fromUtf8 (getLabel().c_str()), parent);
QDoubleSpinBox *widget = new QDoubleSpinBox (parent); QDoubleSpinBox *widget = new QDoubleSpinBox (parent);
widget->setDecimals(mPrecision);
widget->setRange (mMin, mMax); widget->setRange (mMin, mMax);
widget->setValue (mDefault); widget->setValue (mDefault);

@ -9,6 +9,7 @@ namespace CSMPrefs
{ {
Q_OBJECT Q_OBJECT
int mPrecision;
double mMin; double mMin;
double mMax; double mMax;
std::string mTooltip; std::string mTooltip;
@ -20,6 +21,8 @@ namespace CSMPrefs
QMutex *mutex, const std::string& key, const std::string& label, QMutex *mutex, const std::string& key, const std::string& label,
double default_); double default_);
DoubleSetting& setPrecision (int precision);
// defaults to [0, std::numeric_limits<double>::max()] // defaults to [0, std::numeric_limits<double>::max()]
DoubleSetting& setRange (double min, double max); DoubleSetting& setRange (double min, double max);

@ -172,6 +172,17 @@ void CSMPrefs::State::declare()
inputButtons.add (left).add (cLeft).add (right).add (cRight).add (middle).add (cMiddle); inputButtons.add (left).add (cLeft).add (right).add (cRight).add (middle).add (cMiddle);
declareEnum ("p-navi", "Primary Camera Navigation Button", left).addValues (inputButtons); declareEnum ("p-navi", "Primary Camera Navigation Button", left).addValues (inputButtons);
declareEnum ("s-navi", "Secondary Camera Navigation Button", cLeft).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 ("p-edit", "Primary Editing Button", right).addValues (inputButtons);
declareEnum ("s-edit", "Secondary Editing Button", cRight).addValues (inputButtons); declareEnum ("s-edit", "Secondary Editing Button", cRight).addValues (inputButtons);
declareEnum ("p-select", "Primary Selection Button", middle).addValues (inputButtons); declareEnum ("p-select", "Primary Selection Button", middle).addValues (inputButtons);

@ -0,0 +1,628 @@
#include "cameracontroller.hpp"
#include <cmath>
#include <QKeyEvent>
#include <osg/BoundingBox>
#include <osg/Camera>
#include <osg/ComputeBoundsVisitor>
#include <osg/Drawable>
#include <osg/Group>
#include <osg/Matrixd>
#include <osg/Quat>
#include <osgUtil/LineSegmentIntersector>
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<osgUtil::LineSegmentIntersector> 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);
}
}

@ -0,0 +1,152 @@
#ifndef OPENCS_VIEW_CAMERACONTROLLER_H
#define OPENCS_VIEW_CAMERACONTROLLER_H
#include <string>
#include <osg/ref_ptr>
#include <osg/Vec3d>
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

@ -0,0 +1,37 @@
#include "orbitcameramode.hpp"
#include <QMenu>
#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();
}
}

@ -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

@ -6,8 +6,6 @@
#include <QMouseEvent> #include <QMouseEvent>
#include <QApplication> #include <QApplication>
#include <osgGA/TrackballManipulator>
#include <components/esm/loadland.hpp> #include <components/esm/loadland.hpp>
#include "../../model/world/tablemimedata.hpp" #include "../../model/world/tablemimedata.hpp"
@ -23,7 +21,6 @@
bool CSVRender::PagedWorldspaceWidget::adjustCells() bool CSVRender::PagedWorldspaceWidget::adjustCells()
{ {
bool modified = false; bool modified = false;
bool wasEmpty = mCells.empty();
const CSMWorld::IdCollection<CSMWorld::Cell>& cells = mDocument.getData().getCells(); const CSMWorld::IdCollection<CSMWorld::Cell>& 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; return modified;
} }

@ -1,7 +1,5 @@
#include "previewwidget.hpp" #include "previewwidget.hpp"
#include <osgGA/TrackballManipulator>
#include "../../model/world/data.hpp" #include "../../model/world/data.hpp"
#include "../../model/world/idtable.hpp" #include "../../model/world/idtable.hpp"
@ -9,7 +7,7 @@ CSVRender::PreviewWidget::PreviewWidget (CSMWorld::Data& data,
const std::string& id, bool referenceable, QWidget *parent) const std::string& id, bool referenceable, QWidget *parent)
: SceneWidget (data.getResourceSystem(), parent), mData (data), mObject(data, mRootNode, id, referenceable) : SceneWidget (data.getResourceSystem(), parent), mData (data), mObject(data, mRootNode, id, referenceable)
{ {
mView->setCameraManipulator(new osgGA::TrackballManipulator); selectNavigationMode("orbit");
QAbstractItemModel *referenceables = QAbstractItemModel *referenceables =
mData.getTableModel (CSMWorld::UniversalId::Type_Referenceables); mData.getTableModel (CSMWorld::UniversalId::Type_Referenceables);

@ -18,8 +18,11 @@
#include "../widget/scenetoolmode.hpp" #include "../widget/scenetoolmode.hpp"
#include "../../model/prefs/state.hpp"
#include "lighting.hpp" #include "lighting.hpp"
#include "mask.hpp" #include "mask.hpp"
#include "cameracontroller.hpp"
namespace CSVRender namespace CSVRender
{ {
@ -57,9 +60,6 @@ RenderWidget::RenderWidget(QWidget *parent, Qt::WindowFlags f)
layout->addWidget(window->getGLWidget()); layout->addWidget(window->getGLWidget());
setLayout(layout); setLayout(layout);
// Pass events through this widget first
window->getGLWidget()->installEventFilter(this);
mView->getCamera()->setGraphicsContext(window); mView->getCamera()->setGraphicsContext(window);
mView->getCamera()->setClearColor( osg::Vec4(0.2, 0.2, 0.6, 1.0) ); 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) ); 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); 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<QMouseEvent*>(event));
if (event->type() == QEvent::MouseButtonRelease)
mouseReleaseEvent(static_cast<QMouseEvent*>(event));
if (event->type() == QEvent::MouseMove)
mouseMoveEvent(static_cast<QMouseEvent*>(event));
if (event->type() == QEvent::KeyPress)
keyPressEvent(static_cast<QKeyEvent*>(event));
if (event->type() == QEvent::KeyRelease)
keyReleaseEvent(static_cast<QKeyEvent*>(event));
if (event->type() == QEvent::Wheel)
wheelEvent(static_cast<QWheelEvent *>(event));
// Always pass the event on to GLWidget, i.e. to OSG event queue
return QObject::eventFilter(obj, event);
}
osg::Camera *RenderWidget::getCamera() osg::Camera *RenderWidget::getCamera()
{ {
return mView->getCamera(); return mView->getCamera();
@ -159,19 +139,33 @@ CompositeViewer &CompositeViewer::get()
void CompositeViewer::update() void CompositeViewer::update()
{ {
mSimulationTime += mFrameTimer.time_s(); double dt = mFrameTimer.time_s();
mFrameTimer.setStartTick(); mFrameTimer.setStartTick();
emit simulationUpdated(dt);
mSimulationTime += dt;
frame(mSimulationTime); frame(mSimulationTime);
} }
// --------------------------------------------------- // ---------------------------------------------------
SceneWidget::SceneWidget(boost::shared_ptr<Resource::ResourceSystem> resourceSystem, QWidget *parent, Qt::WindowFlags f) SceneWidget::SceneWidget(boost::shared_ptr<Resource::ResourceSystem> resourceSystem, QWidget *parent, Qt::WindowFlags f,
bool retrieveInput)
: RenderWidget(parent, f) : RenderWidget(parent, f)
, mResourceSystem(resourceSystem) , mResourceSystem(resourceSystem)
, mLighting(NULL) , mLighting(NULL)
, mHasDefaultAmbient(false) , 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 // we handle lighting manually
mView->setLightingMode(osgViewer::View::NO_LIGHT); mView->setLightingMode(osgViewer::View::NO_LIGHT);
@ -182,6 +176,18 @@ SceneWidget::SceneWidget(boost::shared_ptr<Resource::ResourceSystem> resourceSys
/// \todo make shortcut configurable /// \todo make shortcut configurable
QShortcut *focusToolbar = new QShortcut (Qt::Key_T, this, 0, 0, Qt::WidgetWithChildrenShortcut); QShortcut *focusToolbar = new QShortcut (Qt::Key_T, this, 0, 0, Qt::WidgetWithChildrenShortcut);
connect (focusToolbar, SIGNAL (activated()), this, SIGNAL (focusToolbarRequest())); 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() SceneWidget::~SceneWidget()
@ -261,4 +267,181 @@ void SceneWidget::setDefaultAmbient (const osg::Vec4f& colour)
setAmbient(mLighting->getAmbientColour(&mDefaultAmbient)); 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<Qt::MouseButton, bool> phyiscal (
event->button(), event->modifiers() & Qt::ControlModifier);
std::map<std::pair<Qt::MouseButton, bool>, std::string>::const_iterator iter =
mButtonMapping.find (phyiscal);
if (iter!=mButtonMapping.end())
return iter->second;
return "";
}
} }

@ -1,6 +1,9 @@
#ifndef OPENCS_VIEW_SCENEWIDGET_H #ifndef OPENCS_VIEW_SCENEWIDGET_H
#define OPENCS_VIEW_SCENEWIDGET_H #define OPENCS_VIEW_SCENEWIDGET_H
#include <map>
#include <memory>
#include <QWidget> #include <QWidget>
#include <QTimer> #include <QTimer>
@ -30,93 +33,135 @@ namespace CSVWidget
class SceneToolbar; class SceneToolbar;
} }
namespace CSMPrefs
{
class Setting;
}
namespace CSVRender namespace CSVRender
{ {
class CameraController;
class FreeCameraController;
class OrbitCameraController;
class Lighting; class Lighting;
class RenderWidget : public QWidget class RenderWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public:
RenderWidget(QWidget* parent = 0, Qt::WindowFlags f = 0);
virtual ~RenderWidget();
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<osgViewer::View> mView; osg::ref_ptr<osgViewer::View> mView;
osg::Group* mRootNode; osg::Group* mRootNode;
QTimer mTimer; QTimer mTimer;
}; };
// Extension of RenderWidget to support lighting mode selection & toolbar // Extension of RenderWidget to support lighting mode selection & toolbar
class SceneWidget : public RenderWidget class SceneWidget : public RenderWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
SceneWidget(boost::shared_ptr<Resource::ResourceSystem> resourceSystem, QWidget* parent = 0, Qt::WindowFlags f = 0); SceneWidget(boost::shared_ptr<Resource::ResourceSystem> resourceSystem, QWidget* parent = 0,
virtual ~SceneWidget(); 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); virtual void mousePressEvent (QMouseEvent *event);
///< \attention The created tool is not added to the toolbar (via addTool). Doing that virtual void mouseReleaseEvent (QMouseEvent *event);
/// is the responsibility of the calling function. 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); /// \return Is \a key a button mapping setting? (ignored otherwise)
///< \note The actual ambient colour may differ based on lighting settings. virtual bool storeMappingSetting (const CSMPrefs::Setting *setting);
protected: std::string mapButton (QMouseEvent *event);
void setLighting (Lighting *lighting);
///< \attention The ownership of \a lighting is not transferred to *this.
void setAmbient(const osg::Vec4f& ambient); boost::shared_ptr<Resource::ResourceSystem> mResourceSystem;
boost::shared_ptr<Resource::ResourceSystem> mResourceSystem; Lighting* mLighting;
Lighting* mLighting; osg::Vec4f mDefaultAmbient;
bool mHasDefaultAmbient;
LightingDay mLightingDay;
LightingNight mLightingNight;
LightingBright mLightingBright;
osg::Vec4f mDefaultAmbient; int mPrevMouseX, mPrevMouseY;
bool mHasDefaultAmbient; std::string mMouseMode;
LightingDay mLightingDay; std::auto_ptr<FreeCameraController> mFreeCamControl;
LightingNight mLightingNight; std::auto_ptr<OrbitCameraController> mOrbitCamControl;
LightingBright mLightingBright; CameraController* mCurrentCamControl;
private slots: std::map<std::pair<Qt::MouseButton, bool>, 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: signals:
void focusToolbarRequest(); void focusToolbarRequest();
}; };
// There are rendering glitches when using multiple Viewer instances, work around using CompositeViewer with multiple views // There are rendering glitches when using multiple Viewer instances, work around using CompositeViewer with multiple views
class CompositeViewer : public QObject, public osgViewer::CompositeViewer class CompositeViewer : public QObject, public osgViewer::CompositeViewer
{ {
Q_OBJECT Q_OBJECT
public: public:
CompositeViewer(); CompositeViewer();
static CompositeViewer& get(); static CompositeViewer& get();
QTimer mTimer; QTimer mTimer;
private: private:
osg::Timer mFrameTimer; osg::Timer mFrameTimer;
double mSimulationTime; double mSimulationTime;
public slots: public slots:
void update(); void update();
signals:
void simulationUpdated(double dt);
}; };
} }

@ -2,8 +2,6 @@
#include <sstream> #include <sstream>
#include <osgGA/TrackballManipulator>
#include <QEvent> #include <QEvent>
#include <components/sceneutil/util.hpp> #include <components/sceneutil/util.hpp>
@ -50,8 +48,6 @@ CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string&
update(); update();
mCell.reset (new Cell (document.getData(), mRootNode, mCellId)); mCell.reset (new Cell (document.getData(), mRootNode, mCellId));
mView->setCameraManipulator(new osgGA::TrackballManipulator);
} }
void CSVRender::UnpagedWorldspaceWidget::cellDataChanged (const QModelIndex& topLeft, void CSVRender::UnpagedWorldspaceWidget::cellDataChanged (const QModelIndex& topLeft,

@ -12,9 +12,6 @@
#include <QApplication> #include <QApplication>
#include <QToolTip> #include <QToolTip>
#include <osgGA/TrackballManipulator>
#include <osgGA/FirstPersonManipulator>
#include <osgUtil/LineSegmentIntersector> #include <osgUtil/LineSegmentIntersector>
#include "../../model/world/universalid.hpp" #include "../../model/world/universalid.hpp"
@ -22,6 +19,8 @@
#include "../../model/prefs/state.hpp" #include "../../model/prefs/state.hpp"
#include "../render/orbitcameramode.hpp"
#include "../widget/scenetoolmode.hpp" #include "../widget/scenetoolmode.hpp"
#include "../widget/scenetooltoggle2.hpp" #include "../widget/scenetooltoggle2.hpp"
#include "../widget/scenetoolrun.hpp" #include "../widget/scenetoolrun.hpp"
@ -30,9 +29,10 @@
#include "mask.hpp" #include "mask.hpp"
#include "editmode.hpp" #include "editmode.hpp"
#include "instancemode.hpp" #include "instancemode.hpp"
#include "cameracontroller.hpp"
CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent) 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), mInteractionMask (0), mEditMode (0), mLocked (false), mDragging (false), mDragX(0), mDragY(0), mDragFactor(0),
mDragWheelFactor(0), mDragShiftFactor(0), mDragWheelFactor(0), mDragShiftFactor(0),
mToolTipPos (-1, -1), mShowToolTips(false), mToolTipDelay(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)), connect (debugProfiles, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
this, SLOT (debugProfileAboutToBeRemoved (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); mToolTipDelayTimer.setSingleShot (true);
connect (&mToolTipDelayTimer, SIGNAL (timeout()), this, SLOT (showToolTip())); connect (&mToolTipDelayTimer, SIGNAL (timeout()), this, SLOT (showToolTip()));
CSMPrefs::get()["3D Scene Input"].update();
CSMPrefs::get()["Tooltips"].update();
} }
CSVRender::WorldspaceWidget::~WorldspaceWidget () CSVRender::WorldspaceWidget::~WorldspaceWidget ()
@ -82,9 +80,6 @@ CSVRender::WorldspaceWidget::~WorldspaceWidget ()
void CSVRender::WorldspaceWidget::settingChanged (const CSMPrefs::Setting *setting) void CSVRender::WorldspaceWidget::settingChanged (const CSMPrefs::Setting *setting)
{ {
if (storeMappingSetting (setting))
return;
if (*setting=="3D Scene Input/drag-factor") if (*setting=="3D Scene Input/drag-factor")
mDragFactor = setting->toDouble(); mDragFactor = setting->toDouble();
else if (*setting=="3D Scene Input/drag-wheel-factor") else if (*setting=="3D Scene Input/drag-wheel-factor")
@ -95,23 +90,29 @@ void CSVRender::WorldspaceWidget::settingChanged (const CSMPrefs::Setting *setti
mToolTipDelay = setting->toInt(); mToolTipDelay = setting->toInt();
else if (*setting=="Tooltips/scene") else if (*setting=="Tooltips/scene")
mShowToolTips = setting->isTrue(); 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::useViewHint (const std::string& hint) {}
void CSVRender::WorldspaceWidget::selectDefaultNavigationMode() void CSVRender::WorldspaceWidget::selectDefaultNavigationMode()
{ {
mView->setCameraManipulator(new osgGA::FirstPersonManipulator); selectNavigationMode("1st");
}
void CSVRender::WorldspaceWidget::centerOrbitCameraOnSelection()
{
std::vector<osg::ref_ptr<TagBase> > selection = getSelection(~0);
for (std::vector<osg::ref_ptr<TagBase> >::iterator it = selection.begin(); it!=selection.end(); ++it)
{
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag*> (it->get()))
{
mOrbitCamControl->setCenter(objectTag->mObject->getPosition().asVec3());
}
}
} }
CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector ( CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector (
@ -138,15 +139,17 @@ CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector (
"<li>Roll camera with Q and E keys</li>" "<li>Roll camera with Q and E keys</li>"
"<li>Hold shift to speed up movement</li>" "<li>Hold shift to speed up movement</li>"
"</ul>"); "</ul>");
tool->addButton (":scenetoolbar/orbiting-camera", "orbit", tool->addButton(
"Orbiting Camera" new CSVRender::OrbitCameraMode(this, QIcon(":scenetoolbar/orbiting-camera"),
"<ul><li>Always facing the centre point</li>" "Orbiting Camera"
"<li>Rotate around the centre point via WASD or by moving the mouse while holding the left button</li>" "<ul><li>Always facing the centre point</li>"
"<li>Mouse wheel moves camera away or towards centre point but can not pass through it</li>" "<li>Rotate around the centre point via WASD or by moving the mouse while holding the left button</li>"
"<li>Roll camera with Q and E keys</li>" "<li>Mouse wheel moves camera away or towards centre point but can not pass through it</li>"
"<li>Strafing (also vertically) by holding the left mouse button and control (includes relocation of the centre point)</li>" "<li>Roll camera with Q and E keys</li>"
"<li>Hold shift to speed up movement</li>" "<li>Strafing (also vertically) by holding the left mouse button and control (includes relocation of the centre point)</li>"
"</ul>"); "<li>Hold shift to speed up movement</li>"
"</ul>", tool),
"orbit");
connect (tool, SIGNAL (modeChanged (const std::string&)), connect (tool, SIGNAL (modeChanged (const std::string&)),
this, SLOT (selectNavigationMode (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) bool CSVRender::WorldspaceWidget::storeMappingSetting (const CSMPrefs::Setting *setting)
{ {
if (setting->getParent()->getKey()!="3D Scene Input")
return false;
static const char * const sMappingSettings[] = static const char * const sMappingSettings[] =
{ {
"p-navi", "s-navi",
"p-edit", "s-edit", "p-edit", "s-edit",
"p-select", "s-select", "p-select", "s-select",
0 0
}; };
for (int i=0; sMappingSettings[i]; ++i) if (setting->getParent()->getKey()=="3D Scene Input")
if (setting->getKey()==sMappingSettings[i]) {
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")) if (value.endsWith ("Left Mouse-Button"))
button = Qt::LeftButton; button = Qt::LeftButton;
else if (value.endsWith ("Right Mouse-Button")) else if (value.endsWith ("Right Mouse-Button"))
button = Qt::RightButton; button = Qt::RightButton;
else if (value.endsWith ("Middle Mouse-Button")) else if (value.endsWith ("Middle Mouse-Button"))
button = Qt::MiddleButton; button = Qt::MiddleButton;
else else
return false; return false;
bool ctrl = value.startsWith ("Ctrl-"); bool ctrl = value.startsWith ("Ctrl-");
mButtonMapping[std::make_pair (button, ctrl)] = sMappingSettings[i]; mButtonMapping[std::make_pair (button, ctrl)] = sMappingSettings[i];
return true; return true;
}
} }
}
return false; return SceneWidget::storeMappingSetting(setting);
} }
osg::ref_ptr<CSVRender::TagBase> CSVRender::WorldspaceWidget::mousePick (const QPoint& localPos) osg::ref_ptr<CSVRender::TagBase> CSVRender::WorldspaceWidget::mousePick (const QPoint& localPos)
@ -496,20 +500,6 @@ osg::ref_ptr<CSVRender::TagBase> CSVRender::WorldspaceWidget::mousePick (const Q
return osg::ref_ptr<CSVRender::TagBase>(); return osg::ref_ptr<CSVRender::TagBase>();
} }
std::string CSVRender::WorldspaceWidget::mapButton (QMouseEvent *event)
{
std::pair<Qt::MouseButton, bool> phyiscal (
event->button(), event->modifiers() & Qt::ControlModifier);
std::map<std::pair<Qt::MouseButton, bool>, std::string>::const_iterator iter =
mButtonMapping.find (phyiscal);
if (iter!=mButtonMapping.end())
return iter->second;
return "";
}
void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event) void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event)
{ {
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData()); const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
@ -615,50 +605,7 @@ void CSVRender::WorldspaceWidget::updateOverlay()
void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event)
{ {
if (!mDragging) 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<TagBase> tag = mousePick (event->pos());
EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*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
{ {
int diffX = event->x() - mDragX; int diffX = event->x() - mDragX;
int diffY = (height() - event->y()) - mDragY; int diffY = (height() - event->y()) - mDragY;
@ -675,59 +622,84 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event)
editMode.drag (diffX, diffY, factor); editMode.drag (diffX, diffY, factor);
} }
else if (mDragMode=="p-edit" || mDragMode=="s-edit" || mDragMode=="p-select" || mDragMode=="s-select")
{
osg::ref_ptr<TagBase> tag = mousePick (event->pos());
EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*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) void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event)
{ {
std::string button = mapButton (event); std::string button = mapButton (event);
if (!mDragging) if (button=="p-edit" || button=="s-edit" ||
mDragMode = button; button=="p-select" || button=="s-select")
{
if (!mDragging)
mDragMode = button;
}
else
SceneWidget::mousePressEvent(event);
} }
void CSVRender::WorldspaceWidget::mouseReleaseEvent (QMouseEvent *event) void CSVRender::WorldspaceWidget::mouseReleaseEvent (QMouseEvent *event)
{ {
std::string button = mapButton (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") if (mDragging)
{
}
else if (mDragMode=="p-edit" || mDragMode=="s-edit" ||
mDragMode=="p-select" || mDragMode=="s-select")
{ {
EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent()); EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent());
editMode.dragCompleted(); editMode.dragCompleted();
mDragging = false; mDragging = false;
} }
} else
else
{
if (button=="p-navi" || button=="s-navi")
{
}
else if (button=="p-edit" || button=="s-edit" ||
button=="p-select" || button=="s-select")
{ {
osg::ref_ptr<TagBase> tag = mousePick (event->pos()); osg::ref_ptr<TagBase> tag = mousePick (event->pos());
handleMouseClick (tag, button, event->modifiers() & Qt::ShiftModifier); handleMouseClick (tag, button, event->modifiers() & Qt::ShiftModifier);
} }
} }
else
mDragMode.clear(); SceneWidget::mouseReleaseEvent(event);
}
void CSVRender::WorldspaceWidget::mouseDoubleClickEvent (QMouseEvent *event)
{
if(event->button() == Qt::RightButton)
{
//mMouse->mouseDoubleClickEvent(event);
}
} }
void CSVRender::WorldspaceWidget::wheelEvent (QWheelEvent *event) void CSVRender::WorldspaceWidget::wheelEvent (QWheelEvent *event)
@ -743,6 +715,8 @@ void CSVRender::WorldspaceWidget::wheelEvent (QWheelEvent *event)
editMode.dragWheel (event->delta(), factor); editMode.dragWheel (event->delta(), factor);
} }
else
SceneWidget::wheelEvent(event);
} }
void CSVRender::WorldspaceWidget::keyPressEvent (QKeyEvent *event) void CSVRender::WorldspaceWidget::keyPressEvent (QKeyEvent *event)
@ -752,7 +726,7 @@ void CSVRender::WorldspaceWidget::keyPressEvent (QKeyEvent *event)
abortDrag(); abortDrag();
} }
else else
RenderWidget::keyPressEvent(event); SceneWidget::keyPressEvent(event);
} }
void CSVRender::WorldspaceWidget::handleMouseClick (osg::ref_ptr<TagBase> tag, const std::string& button, bool shift) void CSVRender::WorldspaceWidget::handleMouseClick (osg::ref_ptr<TagBase> tag, const std::string& button, bool shift)

@ -1,8 +1,6 @@
#ifndef OPENCS_VIEW_WORLDSPACEWIDGET_H #ifndef OPENCS_VIEW_WORLDSPACEWIDGET_H
#define OPENCS_VIEW_WORLDSPACEWIDGET_H #define OPENCS_VIEW_WORLDSPACEWIDGET_H
#include <map>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <QTimer> #include <QTimer>
@ -45,7 +43,6 @@ namespace CSVRender
CSVWidget::SceneToolRun *mRun; CSVWidget::SceneToolRun *mRun;
CSMDoc::Document& mDocument; CSMDoc::Document& mDocument;
unsigned int mInteractionMask; unsigned int mInteractionMask;
std::map<std::pair<Qt::MouseButton, bool>, std::string> mButtonMapping;
CSVWidget::SceneToolMode *mEditMode; CSVWidget::SceneToolMode *mEditMode;
bool mLocked; bool mLocked;
std::string mDragMode; std::string mDragMode;
@ -100,6 +97,8 @@ namespace CSVRender
void selectDefaultNavigationMode(); void selectDefaultNavigationMode();
void centerOrbitCameraOnSelection();
static DropType getDropType(const std::vector<CSMWorld::UniversalId>& data); static DropType getDropType(const std::vector<CSMWorld::UniversalId>& data);
virtual dropRequirments getDropRequirements(DropType type) const; virtual dropRequirments getDropRequirements(DropType type) const;
@ -189,13 +188,17 @@ namespace CSVRender
virtual void mouseMoveEvent (QMouseEvent *event); virtual void mouseMoveEvent (QMouseEvent *event);
virtual void mousePressEvent (QMouseEvent *event); virtual void mousePressEvent (QMouseEvent *event);
virtual void mouseReleaseEvent (QMouseEvent *event); virtual void mouseReleaseEvent (QMouseEvent *event);
virtual void mouseDoubleClickEvent (QMouseEvent *event);
virtual void wheelEvent (QWheelEvent *event); virtual void wheelEvent (QWheelEvent *event);
virtual void keyPressEvent (QKeyEvent *event); virtual void keyPressEvent (QKeyEvent *event);
virtual void handleMouseClick (osg::ref_ptr<TagBase> tag, const std::string& button, virtual void handleMouseClick (osg::ref_ptr<TagBase> tag, const std::string& button,
bool shift); 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(); EditMode *getEditMode();
private: private:
@ -206,21 +209,12 @@ namespace CSVRender
void dragMoveEvent(QDragMoveEvent *event); void dragMoveEvent(QDragMoveEvent *event);
/// \return Is \a key a button mapping setting? (ignored otherwise)
bool storeMappingSetting (const CSMPrefs::Setting *setting);
osg::ref_ptr<TagBase> mousePick (const QPoint& localPos); osg::ref_ptr<TagBase> mousePick (const QPoint& localPos);
std::string mapButton (QMouseEvent *event);
virtual std::string getStartupInstruction() = 0; virtual std::string getStartupInstruction() = 0;
private slots: private slots:
void settingChanged (const CSMPrefs::Setting *setting);
void selectNavigationMode (const std::string& mode);
virtual void referenceableDataChanged (const QModelIndex& topLeft, virtual void referenceableDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight) = 0; const QModelIndex& bottomRight) = 0;

@ -56,32 +56,15 @@ class GLWidget : public QGLWidget
public: public:
GLWidget( 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, bool forwardKeyEvents = false ); 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, bool forwardKeyEvents = false ); GLWidget( const QGLFormat& format, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0);
virtual ~GLWidget(); virtual ~GLWidget();
inline void setGraphicsWindow( GraphicsWindowQt* gw ) { _gw = gw; } inline void setGraphicsWindow( GraphicsWindowQt* gw ) { _gw = gw; }
inline GraphicsWindowQt* getGraphicsWindow() { return _gw; } inline GraphicsWindowQt* getGraphicsWindow() { return _gw; }
inline const GraphicsWindowQt* getGraphicsWindow() const { 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: protected:
int getNumDeferredEvents() int getNumDeferredEvents()
@ -114,9 +97,6 @@ protected:
QQueue<QEvent::Type> _deferredEventQueue; QQueue<QEvent::Type> _deferredEventQueue;
QSet<QEvent::Type> _eventCompressor; QSet<QEvent::Type> _eventCompressor;
bool _touchEventsEnabled;
bool _forwardKeyEvents;
qreal _devicePixelRatio; qreal _devicePixelRatio;
virtual void resizeEvent( QResizeEvent* event ); virtual void resizeEvent( QResizeEvent* event );
@ -164,9 +144,6 @@ public:
virtual std::string getWindowName(); virtual std::string getWindowName();
virtual void useCursor( bool cursorOn ); virtual void useCursor( bool cursorOn );
virtual void setCursor( MouseCursor cursor ); 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 valid() const;
virtual bool realizeImplementation(); virtual bool realizeImplementation();

@ -26,98 +26,6 @@
using namespace osgQt; 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<unsigned int, int> KeyMap;
KeyMap mKeyMap;
};
static QtKeyboardMap s_QtKeyboardMap;
/// The object responsible for the scene re-rendering. /// The object responsible for the scene re-rendering.
class HeartBeat : public QObject { class HeartBeat : public QObject {
public: public:
@ -126,7 +34,7 @@ public:
osg::observer_ptr< osgViewer::ViewerBase > _viewer; osg::observer_ptr< osgViewer::ViewerBase > _viewer;
virtual ~HeartBeat(); virtual ~HeartBeat();
void init( osgViewer::ViewerBase *viewer ); void init( osgViewer::ViewerBase *viewer );
void stopTimer(); void stopTimer();
void timerEvent( QTimerEvent *event ); void timerEvent( QTimerEvent *event );
@ -146,31 +54,20 @@ QPointer<HeartBeat> HeartBeat::heartBeat;
#define GETDEVICEPIXELRATIO() devicePixelRatio() #define GETDEVICEPIXELRATIO() devicePixelRatio()
#endif #endif
GLWidget::GLWidget( QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f, bool forwardKeyEvents ) GLWidget::GLWidget( QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
: QGLWidget(parent, shareWidget, f), : QGLWidget(parent, shareWidget, f), _gw( NULL )
_gw( NULL ),
_touchEventsEnabled( false ),
_forwardKeyEvents( forwardKeyEvents )
{ {
_devicePixelRatio = GETDEVICEPIXELRATIO(); _devicePixelRatio = GETDEVICEPIXELRATIO();
} }
GLWidget::GLWidget( QGLContext* context, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f, GLWidget::GLWidget( QGLContext* context, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
bool forwardKeyEvents ) : QGLWidget(context, parent, shareWidget, f), _gw( NULL )
: QGLWidget(context, parent, shareWidget, f),
_gw( NULL ),
_touchEventsEnabled( false ),
_forwardKeyEvents( forwardKeyEvents )
{ {
_devicePixelRatio = GETDEVICEPIXELRATIO(); _devicePixelRatio = GETDEVICEPIXELRATIO();
} }
GLWidget::GLWidget( const QGLFormat& format, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f, GLWidget::GLWidget( const QGLFormat& format, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
bool forwardKeyEvents ) : QGLWidget(format, parent, shareWidget, f), _gw( NULL )
: QGLWidget(format, parent, shareWidget, f),
_gw( NULL ),
_touchEventsEnabled( false ),
_forwardKeyEvents( forwardKeyEvents )
{ {
_devicePixelRatio = GETDEVICEPIXELRATIO(); _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() void GLWidget::processDeferredEvents()
{ {
QQueue<QEvent::Type> deferredEventQueueCopy; QQueue<QEvent::Type> deferredEventQueueCopy;
@ -224,10 +102,6 @@ void GLWidget::processDeferredEvents()
bool GLWidget::event( QEvent* event ) bool GLWidget::event( QEvent* event )
{ {
#ifdef USE_GESTURES
if ( event->type()==QEvent::Gesture )
return gestureEvent(static_cast<QGestureEvent*>(event));
#endif
// QEvent::Hide // QEvent::Hide
// //
@ -274,16 +148,6 @@ bool GLWidget::event( QEvent* event )
return QGLWidget::event( 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 ) void GLWidget::resizeEvent( QResizeEvent* event )
{ {
const QSize& size = event->size(); const QSize& size = event->size();
@ -309,178 +173,6 @@ void GLWidget::glDraw()
_gw->requestRedraw(); _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<QPinchGesture *>(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<osgGA::GUIEventAdapter> 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 ) GraphicsWindowQt::GraphicsWindowQt( osg::GraphicsContext::Traits* traits, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f )
: _realized(false) : _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; osg::ref_ptr< osgViewer::ViewerBase > viewer;
if( !_viewer.lock( viewer ) ) if( !_viewer.lock( viewer ) )

Loading…
Cancel
Save