mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-25 10:09:42 +00:00
Better mouse cursor tracking for the third axis.
This commit is contained in:
parent
1f73fae6ef
commit
d7804974e8
2 changed files with 83 additions and 51 deletions
|
@ -57,9 +57,9 @@ namespace CSVRender
|
||||||
|
|
||||||
MouseState::MouseState(WorldspaceWidget *parent)
|
MouseState::MouseState(WorldspaceWidget *parent)
|
||||||
: mParent(parent), mPhysics(parent->getPhysics()), mSceneManager(parent->getSceneManager())
|
: mParent(parent), mPhysics(parent->getPhysics()), mSceneManager(parent->getSceneManager())
|
||||||
, mCurrentObj(""), mMouseState(Mouse_Default), mOldPos(0,0), mMouseEventTimer(0), mPlane(0)
|
, mCurrentObj(""), mMouseState(Mouse_Default), mOldCursorPos(0,0), mMouseEventTimer(0)
|
||||||
, mGrabbedSceneNode(""), mOrigObjPos(Ogre::Vector3()), mOrigMousePos(Ogre::Vector3())
|
, mGrabbedSceneNode(""), mOrigObjPos(Ogre::Vector3()), mOrigMousePos(Ogre::Vector3())
|
||||||
, mCurrentMousePos(Ogre::Vector3()), mOffset(0.0f)
|
, mOldMousePos(Ogre::Vector3()), mPlane(0)
|
||||||
, mColIndexPosX(0), mColIndexPosY(0), mColIndexPosZ(0), mIdTableModel(0)
|
, mColIndexPosX(0), mColIndexPosY(0), mColIndexPosZ(0), mIdTableModel(0)
|
||||||
{
|
{
|
||||||
const CSMWorld::RefCollection& references = mParent->mDocument.getData().getReferences();
|
const CSMWorld::RefCollection& references = mParent->mDocument.getData().getReferences();
|
||||||
|
@ -111,23 +111,24 @@ namespace CSVRender
|
||||||
}
|
}
|
||||||
case Mouse_Drag:
|
case Mouse_Drag:
|
||||||
{
|
{
|
||||||
if(event->pos() != mOldPos) // TODO: maybe don't update less than a quantum?
|
if(event->pos() != mOldCursorPos) // TODO: maybe don't update less than a quantum?
|
||||||
{
|
{
|
||||||
mOldPos = event->pos();
|
mOldCursorPos = event->pos();
|
||||||
|
|
||||||
// ray test against the plane to provide feedback to the user the
|
// ray test against the plane to provide feedback to the user the
|
||||||
// relative movement of the object on the x-y plane
|
// relative movement of the object on the movement plane
|
||||||
std::pair<bool, Ogre::Vector3> planeResult = mousePositionOnPlane(event->pos(), *mPlane);
|
std::pair<bool, Ogre::Vector3> planeResult = mousePosOnPlane(event->pos(), *mPlane);
|
||||||
if(planeResult.first)
|
if(planeResult.first)
|
||||||
{
|
{
|
||||||
if(mGrabbedSceneNode != "")
|
if(mGrabbedSceneNode != "")
|
||||||
{
|
{
|
||||||
std::pair<Ogre::Vector3, Ogre::Vector3> planeRes = planeAxis();
|
Ogre::Vector3 pos = mOrigObjPos + (planeResult.second-mOrigMousePos);
|
||||||
Ogre::Vector3 pos = mOrigObjPos + planeRes.first*mOffset;
|
|
||||||
mSceneManager->getSceneNode(mGrabbedSceneNode)->setPosition(pos+planeResult.second-mOrigMousePos);
|
mSceneManager->getSceneNode(mGrabbedSceneNode)->setPosition(pos);
|
||||||
mCurrentMousePos = planeResult.second;
|
mPhysics->moveSceneNodes(mGrabbedSceneNode, pos);
|
||||||
mPhysics->moveSceneNodes(mGrabbedSceneNode, pos+planeResult.second-mOrigMousePos);
|
|
||||||
updateSceneWidgets();
|
updateSceneWidgets();
|
||||||
|
|
||||||
|
mOldMousePos = planeResult.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,12 +166,11 @@ namespace CSVRender
|
||||||
// mouse in relation to the object position
|
// mouse in relation to the object position
|
||||||
std::pair<Ogre::Vector3, Ogre::Vector3> planeRes = planeAxis();
|
std::pair<Ogre::Vector3, Ogre::Vector3> planeRes = planeAxis();
|
||||||
mPlane->redefine(planeRes.first, result.second);
|
mPlane->redefine(planeRes.first, result.second);
|
||||||
std::pair<bool, Ogre::Vector3> planeResult = mousePositionOnPlane(event->pos(), *mPlane);
|
std::pair<bool, Ogre::Vector3> planeResult = mousePosOnPlane(event->pos(), *mPlane);
|
||||||
if(planeResult.first)
|
if(planeResult.first)
|
||||||
{
|
{
|
||||||
mOrigMousePos = planeResult.second;
|
mOrigMousePos = planeResult.second;
|
||||||
mCurrentMousePos = planeResult.second;
|
mOldMousePos = planeResult.second;
|
||||||
mOffset = 0.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mOrigObjPos = mSceneManager->getSceneNode(mGrabbedSceneNode)->getPosition();
|
mOrigObjPos = mSceneManager->getSceneNode(mGrabbedSceneNode)->getPosition();
|
||||||
|
@ -206,6 +206,7 @@ namespace CSVRender
|
||||||
mCurrentObj = result.first;
|
mCurrentObj = result.first;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
//#if 0
|
||||||
// print some debug info
|
// print some debug info
|
||||||
std::string referenceId = mPhysics->sceneNodeToRefId(result.first);
|
std::string referenceId = mPhysics->sceneNodeToRefId(result.first);
|
||||||
if(referenceId != "")
|
if(referenceId != "")
|
||||||
|
@ -215,17 +216,18 @@ namespace CSVRender
|
||||||
std::cout << " hit pos "+ QString::number(result.second.x).toStdString()
|
std::cout << " hit pos "+ QString::number(result.second.x).toStdString()
|
||||||
+ ", " + QString::number(result.second.y).toStdString()
|
+ ", " + QString::number(result.second.y).toStdString()
|
||||||
+ ", " + QString::number(result.second.z).toStdString() << std::endl;
|
+ ", " + QString::number(result.second.z).toStdString() << std::endl;
|
||||||
|
//#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Mouse_Drag:
|
case Mouse_Drag:
|
||||||
{
|
{
|
||||||
// final placement
|
// final placement
|
||||||
std::pair<bool, Ogre::Vector3> planeResult = mousePositionOnPlane(event->pos(), *mPlane);
|
std::pair<bool, Ogre::Vector3> planeResult = mousePosOnPlane(event->pos(), *mPlane);
|
||||||
if(planeResult.first && mGrabbedSceneNode != "")
|
if(planeResult.first && mGrabbedSceneNode != "")
|
||||||
{
|
{
|
||||||
std::pair<Ogre::Vector3, Ogre::Vector3> planeRes = planeAxis();
|
Ogre::Vector3 pos = mOrigObjPos + (planeResult.second-mOrigMousePos);
|
||||||
Ogre::Vector3 pos = mOrigObjPos+planeRes.first*mOffset+planeResult.second-mOrigMousePos;
|
|
||||||
// use the saved scene node name since the physics model has not moved yet
|
// use the saved scene node name since the physics model has not moved yet
|
||||||
std::string referenceId = mPhysics->sceneNodeToRefId(mGrabbedSceneNode);
|
std::string referenceId = mPhysics->sceneNodeToRefId(mGrabbedSceneNode);
|
||||||
|
|
||||||
|
@ -234,18 +236,19 @@ namespace CSVRender
|
||||||
// move pathgrid point, but don't save yet (need pathgrid
|
// move pathgrid point, but don't save yet (need pathgrid
|
||||||
// table feature & its data structure to be completed)
|
// table feature & its data structure to be completed)
|
||||||
// FIXME: need to signal PathgridPoint object of change
|
// FIXME: need to signal PathgridPoint object of change
|
||||||
// FIXME: shouldn't allow pathgrid points under the cursor
|
//std::pair<std::string, Ogre::Vector3> result =
|
||||||
std::pair<std::string, Ogre::Vector3> result =
|
//anyUnderCursor(event->x(), event->y());
|
||||||
anyUnderCursor(event->x(), event->y());
|
//std::string refId = mPhysics->sceneNodeToRefId(result.first);
|
||||||
if(result.first != "")
|
//if(result.first != "" && // don't allow pathgrid points under the cursor
|
||||||
|
//!QString(refId.c_str()).contains(QRegExp("^Pathgrid")))
|
||||||
{
|
{
|
||||||
// FIXME: rather than just updating at the end, should
|
// FIXME: rather than just updating at the end, should
|
||||||
// consider providing visual feedback of terrain height
|
// consider providing visual feedback of terrain height
|
||||||
// while dragging the pathgrid point (maybe check whether
|
// while dragging the pathgrid point (maybe check whether
|
||||||
// the object is a pathgrid point at the begging and set
|
// the object is a pathgrid point at the begging and set
|
||||||
// a flag?)
|
// a flag?)
|
||||||
placeObject(mGrabbedSceneNode, result.second);
|
placeObject(mGrabbedSceneNode, pos); // result.second
|
||||||
mParent->pathgridMoved(referenceId, result.second);
|
mParent->pathgridMoved(referenceId, pos); // result.second
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -267,12 +270,11 @@ namespace CSVRender
|
||||||
mMouseState = Mouse_Edit;
|
mMouseState = Mouse_Edit;
|
||||||
|
|
||||||
// reset states
|
// reset states
|
||||||
mCurrentMousePos = Ogre::Vector3(); // mouse pos to use in wheel event
|
mGrabbedSceneNode = ""; // id of the object
|
||||||
mOrigMousePos = Ogre::Vector3(); // starting pos of mouse in world space
|
mOrigMousePos = Ogre::Vector3(); // starting pos of mouse in world space
|
||||||
mOrigObjPos = Ogre::Vector3(); // starting pos of object in world space
|
mOrigObjPos = Ogre::Vector3(); // starting pos of object in world space
|
||||||
mGrabbedSceneNode = ""; // id of the object
|
mOldMousePos = Ogre::Vector3(); // mouse pos to use in wheel event
|
||||||
mOffset = 0.0f; // used for z-axis movement
|
mOldCursorPos = QPoint(0, 0); // to calculate relative movement of mouse
|
||||||
mOldPos = QPoint(0, 0); // to calculate relative movement of mouse
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -284,10 +286,12 @@ namespace CSVRender
|
||||||
if(result.first != "")
|
if(result.first != "")
|
||||||
{
|
{
|
||||||
// FIXME: terrain editing goes here
|
// FIXME: terrain editing goes here
|
||||||
|
//#if 0
|
||||||
std::cout << "result default/edit release: " << result.first << std::endl;
|
std::cout << "result default/edit release: " << result.first << std::endl;
|
||||||
std::cout << " hit pos "+ QString::number(result.second.x).toStdString()
|
std::cout << " hit pos "+ QString::number(result.second.x).toStdString()
|
||||||
+ ", " + QString::number(result.second.y).toStdString()
|
+ ", " + QString::number(result.second.y).toStdString()
|
||||||
+ ", " + QString::number(result.second.z).toStdString() << std::endl;
|
+ ", " + QString::number(result.second.z).toStdString() << std::endl;
|
||||||
|
//#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -298,9 +302,9 @@ namespace CSVRender
|
||||||
|
|
||||||
void MouseState::mouseDoubleClickEvent (QMouseEvent *event)
|
void MouseState::mouseDoubleClickEvent (QMouseEvent *event)
|
||||||
{
|
{
|
||||||
//event->ignore();
|
event->ignore();
|
||||||
mPhysics->toggleDebugRendering(mSceneManager);
|
//mPhysics->toggleDebugRendering(mSceneManager);
|
||||||
mParent->flagAsModified();
|
//mParent->flagAsModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MouseState::wheelEvent (QWheelEvent *event)
|
bool MouseState::wheelEvent (QWheelEvent *event)
|
||||||
|
@ -313,17 +317,47 @@ namespace CSVRender
|
||||||
/* FALL_THROUGH */
|
/* FALL_THROUGH */
|
||||||
case Mouse_Drag:
|
case Mouse_Drag:
|
||||||
{
|
{
|
||||||
// move the object along the z axis during Mouse_Drag or Mouse_Grab
|
// move the object along the axis normal to the plane during Mouse_Drag or Mouse_Grab
|
||||||
if (event->delta())
|
if (event->delta())
|
||||||
{
|
{
|
||||||
// seems positive is up and negative is down
|
// The mouse point is where the mouse points the object when dragging starts.
|
||||||
mOffset += (event->delta()/1); // FIXME: arbitrary number, make config option?
|
// The object position is usually a little away from the mount point.
|
||||||
|
|
||||||
|
// Get the new world position of mouse on the plane offset from the wheel
|
||||||
std::pair<Ogre::Vector3, Ogre::Vector3> planeRes = planeAxis();
|
std::pair<Ogre::Vector3, Ogre::Vector3> planeRes = planeAxis();
|
||||||
Ogre::Vector3 pos = mOrigObjPos + planeRes.first*mOffset;
|
Ogre::Vector3 mousePos = mOldMousePos + planeRes.first*(event->delta()/2);
|
||||||
mSceneManager->getSceneNode(mGrabbedSceneNode)->setPosition(pos+mCurrentMousePos-mOrigMousePos);
|
|
||||||
mPhysics->moveSceneNodes(mGrabbedSceneNode, pos+mCurrentMousePos-mOrigMousePos);
|
// Move the movement plane to the new mouse position. The plane is created on
|
||||||
|
// the mouse point (i.e. not the object position)
|
||||||
|
mPlane->redefine(planeRes.first, mousePos);
|
||||||
|
|
||||||
|
// Calculate the new screen position of the cursor
|
||||||
|
Ogre::Vector3 screenPos =
|
||||||
|
getCamera()->getProjectionMatrix() * getCamera()->getViewMatrix() * mousePos;
|
||||||
|
int screenX = (screenPos.x/2+0.5) * getViewport()->getActualWidth();
|
||||||
|
int screenY = (1-(screenPos.y/2+0.5)) * getViewport()->getActualHeight();
|
||||||
|
|
||||||
|
// Move the cursor to the new screen position
|
||||||
|
QCursor::setPos(mParent->mapToGlobal(QPoint(screenX, screenY)));
|
||||||
|
|
||||||
|
// Use the new position to check the world position of the mouse
|
||||||
|
std::pair<bool, Ogre::Vector3> planeResult =
|
||||||
|
mousePosOnPlane(QPoint(screenX, screenY), *mPlane);
|
||||||
|
{
|
||||||
|
if(planeResult.first)
|
||||||
|
mousePos = planeResult.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the final world position of the cursor
|
||||||
|
Ogre::Vector3 finalPos = mOrigObjPos + (mousePos-mOrigMousePos);
|
||||||
|
|
||||||
|
mSceneManager->getSceneNode(mGrabbedSceneNode)->setPosition(finalPos);
|
||||||
|
mPhysics->moveSceneNodes(mGrabbedSceneNode, finalPos);
|
||||||
updateSceneWidgets();
|
updateSceneWidgets();
|
||||||
|
|
||||||
|
// remember positions for next time
|
||||||
|
mOldMousePos = mousePos;
|
||||||
|
mOldCursorPos = QPoint(screenX, screenY);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -353,14 +387,13 @@ namespace CSVRender
|
||||||
|
|
||||||
// reset states
|
// reset states
|
||||||
mMouseState = Mouse_Default;
|
mMouseState = Mouse_Default;
|
||||||
mCurrentMousePos = Ogre::Vector3();
|
mOldMousePos = Ogre::Vector3();
|
||||||
mOrigMousePos = Ogre::Vector3();
|
mOrigMousePos = Ogre::Vector3();
|
||||||
mOrigObjPos = Ogre::Vector3();
|
mOrigObjPos = Ogre::Vector3();
|
||||||
mGrabbedSceneNode = "";
|
mGrabbedSceneNode = "";
|
||||||
mCurrentObj = "";
|
mCurrentObj = "";
|
||||||
mOldPos = QPoint(0, 0);
|
mOldCursorPos = QPoint(0, 0);
|
||||||
mMouseEventTimer->invalidate();
|
mMouseEventTimer->invalidate();
|
||||||
mOffset = 0.0f;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -420,7 +453,7 @@ namespace CSVRender
|
||||||
return std::make_pair("", Ogre::Vector3());
|
return std::make_pair("", Ogre::Vector3());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<bool, Ogre::Vector3> MouseState::mousePositionOnPlane(const QPoint &pos, const Ogre::Plane &plane)
|
std::pair<bool, Ogre::Vector3> MouseState::mousePosOnPlane(const QPoint &pos, const Ogre::Plane &plane)
|
||||||
{
|
{
|
||||||
// using a really small value seems to mess up with the projections
|
// using a really small value seems to mess up with the projections
|
||||||
float nearClipDistance = getCamera()->getNearClipDistance(); // save existing
|
float nearClipDistance = getCamera()->getNearClipDistance(); // save existing
|
||||||
|
|
|
@ -46,15 +46,14 @@ namespace CSVRender
|
||||||
CSVWorld::PhysicsSystem *mPhysics; // local copy
|
CSVWorld::PhysicsSystem *mPhysics; // local copy
|
||||||
Ogre::SceneManager *mSceneManager; // local copy
|
Ogre::SceneManager *mSceneManager; // local copy
|
||||||
|
|
||||||
QPoint mOldPos;
|
QPoint mOldCursorPos;
|
||||||
std::string mCurrentObj;
|
std::string mCurrentObj;
|
||||||
std::string mGrabbedSceneNode;
|
std::string mGrabbedSceneNode;
|
||||||
QElapsedTimer *mMouseEventTimer;
|
QElapsedTimer *mMouseEventTimer;
|
||||||
Ogre::Plane *mPlane;
|
Ogre::Plane *mPlane;
|
||||||
Ogre::Vector3 mOrigObjPos;
|
Ogre::Vector3 mOrigObjPos;
|
||||||
Ogre::Vector3 mOrigMousePos;
|
Ogre::Vector3 mOrigMousePos;
|
||||||
Ogre::Vector3 mCurrentMousePos;
|
Ogre::Vector3 mOldMousePos;
|
||||||
float mOffset;
|
|
||||||
|
|
||||||
CSMWorld::IdTable *mIdTableModel;
|
CSMWorld::IdTable *mIdTableModel;
|
||||||
int mColIndexPosX;
|
int mColIndexPosX;
|
||||||
|
@ -78,7 +77,7 @@ namespace CSVRender
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::pair<bool, Ogre::Vector3> mousePositionOnPlane(const QPoint &pos, const Ogre::Plane &plane);
|
std::pair<bool, Ogre::Vector3> mousePosOnPlane(const QPoint &pos, const Ogre::Plane &plane);
|
||||||
std::pair<std::string, Ogre::Vector3> terrainUnderCursor(const int mouseX, const int mouseY);
|
std::pair<std::string, Ogre::Vector3> terrainUnderCursor(const int mouseX, const int mouseY);
|
||||||
std::pair<std::string, Ogre::Vector3> objectUnderCursor(const int mouseX, const int mouseY);
|
std::pair<std::string, Ogre::Vector3> objectUnderCursor(const int mouseX, const int mouseY);
|
||||||
std::pair<Ogre::Vector3, Ogre::Vector3> planeAxis();
|
std::pair<Ogre::Vector3, Ogre::Vector3> planeAxis();
|
||||||
|
|
Loading…
Reference in a new issue