diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index b9ccc00f9..70d807ea7 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -13,6 +14,8 @@ #include #include +#include + #include #include "textoverlay.hpp" #include "overlaymask.hpp" @@ -170,6 +173,146 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells() return modified; } +// mouse picking +// FIXME: need to virtualise mouse buttons +// +// State machine: +// +// [default] mousePressEvent->check if the mouse is pointing at an object +// if yes, go to [grab] else stay at [default] +// +// [grab] mouseReleaseEvent->if same button and new obj, go to [edit] +// mouseMoveEvent->if same button, create collision planes then go to [drag] +// other mouse events or buttons, go back to [default] (i.e. like 'cancel') +// +// [drag] mouseReleaseEvent->if same button, place the object at the new +// location, update the document then go to [edit] +// mouseMoveEvent->update position to the user based on ray to the collision +// planes and render the object at the new location, but do not update +// the document yet +// +// [edit] TODO, probably fine positional adjustments or rotations; clone/delete? +// +// +// press press (obj) +// [default] --------> [grab] <-------------------- [edit] +// ^ (obj) | | ------> [drag] -----> ^ +// | | | move ^ | release | +// | | | | | | +// | | | +-+ | +// | | | move | +// +----------------+ +--------------------------+ +// release release +// (same obj) (new obj) +// +// +void CSVRender::PagedWorldspaceWidget::mouseMoveEvent (QMouseEvent *event) +{ + if(event->buttons() & Qt::RightButton) + { + switch(mMouseState) + { + case Mouse_Grab: + { + // check if min elapsed time to stop false detection of drag + if(!mMouseEventTimer->isValid() || !mMouseEventTimer->hasExpired(100)) // ms + break; + else + { + mMouseEventTimer->invalidate(); + + mMouseState = Mouse_Drag; + //std::cout << "grab->drag" << std::endl; + } + + /* FALL_THROUGH */ + } + case Mouse_Drag: + { + // FIXME: don't update less than a quantum + //QPoint diff = mOldPos-event->pos(); + if(event->pos() != mOldPos) + { + mOldPos = event->pos(); + //std::cout << QString::number(event->pos().x()).toStdString() << ", " + //<< QString::number(event->pos().y()).toStdString() << std::endl; + + // ray test against the plane to provide feedback to the user the + // relative movement of the object on the x-y plane + std::pair planeResult = mousePositionOnPlane(event, *mPlane); + if(planeResult.first) + { + if(mObjSceneNode) + { + mObjSceneNode->setPosition(mOrigObjPos+planeResult.second-mOrigMousePos); + flagAsModified(); + } + } + } + break; + } + case Mouse_Edit: + case Mouse_Default: + { + break; // error event, ignore + } + /* NO_DEFAULT_CASE */ + } + } + SceneWidget::mouseMoveEvent(event); +} + +void CSVRender::PagedWorldspaceWidget::mousePressEvent (QMouseEvent *event) +{ + if(event->buttons() & Qt::RightButton) + { + switch(mMouseState) + { + case Mouse_Grab: + case Mouse_Drag: + { + break; // error event, ignore + } + case Mouse_Edit: + case Mouse_Default: + { + if(!getCamera()->getViewport()) + break; + + std::pair result = isObjectUnderCursor( + (float) event->x() / getCamera()->getViewport()->getActualWidth(), + (float) event->y() / getCamera()->getViewport()->getActualHeight()); + if(result.first != "") + { + mCurrentObj = result.first; // FIXME + // ray test agaist the plane to get a starting position of the + // mouse in relation to the object position + mPlane->redefine(Ogre::Vector3::UNIT_Z, result.second); + std::pair planeResult = mousePositionOnPlane(event, *mPlane); + if(planeResult.first) + mOrigMousePos = planeResult.second; + + std::string sceneNodeName = + CSVWorld::PhysicsSystem::instance()->referenceToSceneNode(result.first); + mObjSceneNode = getSceneManager()->getSceneNode(sceneNodeName); + mOrigObjPos = mObjSceneNode->getPosition(); + + + mMouseEventTimer->start(); + + mMouseState = Mouse_Grab; + //std::cout << "default/edit->grab" << std::endl; + } + break; + } + /* NO_DEFAULT_CASE */ + } + } + // FIXME: other button press - cancel grab and/or drag and place the object back in the original + // position + //SceneWidget::mousePressEvent(event); +} + void CSVRender::PagedWorldspaceWidget::mouseReleaseEvent (QMouseEvent *event) { if(event->button() == Qt::RightButton) @@ -184,8 +327,119 @@ void CSVRender::PagedWorldspaceWidget::mouseReleaseEvent (QMouseEvent *event) break; } } + + if(!getCamera()->getViewport()) + { + SceneWidget::mouseReleaseEvent(event); + return; + } + + // FIXME: skip this if overlay clicked above + // FIXME: stop/disable the timer + switch(mMouseState) + { + case Mouse_Grab: + { + std::pair result = isObjectUnderCursor( + (float) event->x() / getCamera()->getViewport()->getActualWidth(), + (float) event->y() / getCamera()->getViewport()->getActualHeight()); + if(result.first != "") + { + if(result.first == mCurrentObj) + { + mMouseState = Mouse_Default; + //std::cout << "grab->default" << std::endl; + mCurrentObj = ""; + } + else + { + mMouseState = Mouse_Edit; + //std::cout << "grab->edit" << std::endl; + mCurrentObj = result.first; + + + // print some debug info + std::cout << "ReferenceId: " << result.first << std::endl; + const CSMWorld::RefCollection& references = mDocument.getData().getReferences(); + int index = references.searchId(result.first); + if (index != -1) + { + int columnIndex = + references.findColumnIndex(CSMWorld::Columns::ColumnId_ReferenceableId); + std::cout << " index: " + QString::number(index).toStdString() + +", column index: " + QString::number(columnIndex).toStdString() + << std::endl; + } + } + // update highlighting the current object + std::string sceneNode = + CSVWorld::PhysicsSystem::instance()->referenceToSceneNode(result.first); + + uint32_t visibilityMask = getCamera()->getViewport()->getVisibilityMask(); + bool ignoreObjects = !(visibilityMask & (uint32_t)CSVRender::Element_Reference); + + if(!ignoreObjects && getSceneManager()->hasSceneNode(sceneNode)) + { + CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance(); + if(userSettings.setting("debug/mouse-picking", QString("false")) == "true" ? true : false) + updateSelectionHighlight(sceneNode, result.second); + } + flagAsModified(); + } + break; + } + case Mouse_Drag: + { + // final placement + std::pair planeResult = mousePositionOnPlane(event, *mPlane); + if(planeResult.first) + { + if(mObjSceneNode) + { + mObjSceneNode->setPosition(mOrigObjPos+planeResult.second-mOrigMousePos); + flagAsModified(); + + // update physics + const CSMWorld::CellRef& cellref = + mDocument.getData().getReferences().getRecord (mCurrentObj).get(); + Ogre::Quaternion xr (Ogre::Radian (-cellref.mPos.rot[0]), Ogre::Vector3::UNIT_X); + Ogre::Quaternion yr (Ogre::Radian (-cellref.mPos.rot[1]), Ogre::Vector3::UNIT_Y); + Ogre::Quaternion zr (Ogre::Radian (-cellref.mPos.rot[2]), Ogre::Vector3::UNIT_Z); + + // FIXME: adjustRigidBody() seems to lose objects, delete and recreate for now + //CSVWorld::PhysicsSystem::instance()->moveObject(mCurrentObj, + //mOrigObjPos+planeResult.second-mOrigMousePos, xr*yr*zr); + std::string sceneNodeName = + CSVWorld::PhysicsSystem::instance()->referenceToSceneNode(mCurrentObj); + std::string mesh = + CSVWorld::PhysicsSystem::instance()->sceneNodeToMesh(sceneNodeName); + CSVWorld::PhysicsSystem::instance()->removeObject(mCurrentObj); + CSVWorld::PhysicsSystem::instance()->addObject(mesh, + sceneNodeName, mCurrentObj, cellref.mScale, + mOrigObjPos+planeResult.second-mOrigMousePos, xr*yr*zr); + } + } + // FIXME: update document + // FIXME: highlight current object? + //std::cout << "final position" << std::endl; + + mMouseState = Mouse_Edit; + //std::cout << "drag->edit" << std::endl; + break; + } + case Mouse_Edit: + case Mouse_Default: + { + // probably terrain + debugMousePicking( + (float) event->x() / getCamera()->getViewport()->getActualWidth(), + (float) event->y() / getCamera()->getViewport()->getActualHeight()); + break; + } + /* NO_DEFAULT_CASE */ + } } - WorldspaceWidget::mouseReleaseEvent(event); + SceneWidget::mouseReleaseEvent(event); } void CSVRender::PagedWorldspaceWidget::mouseDoubleClickEvent (QMouseEvent *event) @@ -194,7 +448,14 @@ void CSVRender::PagedWorldspaceWidget::mouseDoubleClickEvent (QMouseEvent *event { std::cout << "double clicked" << std::endl; } - WorldspaceWidget::mouseDoubleClickEvent(event); + //SceneWidget::mouseDoubleClickEvent(event); +} + +void CSVRender::PagedWorldspaceWidget::wheelEvent (QWheelEvent *event) +{ + // FIXME: add wheel event to move the object along the y axis during Mouse_Drag or + // Mouse_Grab + SceneWidget::wheelEvent(event); } void CSVRender::PagedWorldspaceWidget::updateOverlay() @@ -298,7 +559,8 @@ std::string CSVRender::PagedWorldspaceWidget::getStartupInstruction() CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc::Document& document) : WorldspaceWidget (document, parent), mDocument (document), mWorldspace ("std::default"), - mControlElements(NULL), mDisplayCellCoord(true), mOverlayMask(NULL) + mControlElements(NULL), mDisplayCellCoord(true), mOverlayMask(NULL), + mCurrentObj(""), mMouseState(Mouse_Default), mOldPos(0,0), mMouseEventTimer(0), mPlane(0) { QAbstractItemModel *cells = document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells); @@ -309,6 +571,22 @@ CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc this, SLOT (cellRemoved (const QModelIndex&, int, int))); connect (cells, SIGNAL (rowsInserted (const QModelIndex&, int, int)), this, SLOT (cellAdded (const QModelIndex&, int, int))); + + initDebug(); + mMouseEventTimer = new QElapsedTimer(); + mMouseEventTimer->invalidate(); + + mPlane = new Ogre::Plane(Ogre::Vector3::UNIT_Z, 0); + Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createPlane("ground", + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + *mPlane, + 300000,300000, // FIXME: use far clip dist? + 1,1, // segments + true, // normals + 1, // numTexCoordSets + 1,1, // uTile, vTile + Ogre::Vector3::UNIT_Y // upVector + ); } CSVRender::PagedWorldspaceWidget::~PagedWorldspaceWidget() @@ -329,6 +607,28 @@ CSVRender::PagedWorldspaceWidget::~PagedWorldspaceWidget() removeRenderTargetListener(mOverlayMask); delete mOverlayMask; + + delete mMouseEventTimer; + + // For debugging only + std::map >::iterator iter = mSelectedEntities.begin(); + for(;iter != mSelectedEntities.end(); ++iter) + { + removeHitPoint(getSceneManager(), iter->first); + + if(getSceneManager()->hasSceneNode(iter->first)) + { + Ogre::SceneNode *scene = getSceneManager()->getSceneNode(iter->first); + + if(scene) + { + scene->removeAndDestroyAllChildren(); + getSceneManager()->destroySceneNode(iter->first); + } + } + } + + delete mPlane; } void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint) @@ -479,3 +779,179 @@ void CSVRender::PagedWorldspaceWidget::cellAdded (const QModelIndex& index, int if (adjustCells()) flagAsModified(); } + +std::pair CSVRender::PagedWorldspaceWidget::isObjectUnderCursor(float mouseX, float mouseY) +{ + std::pair result = CSVWorld::PhysicsSystem::instance()->castRay( + mouseX, mouseY, NULL, NULL, getCamera()); + if(result.first != "") + { + QString name = QString(result.first.c_str()); + if(!name.contains(QRegExp("^HeightField"))) + { + std::string sceneNode = + CSVWorld::PhysicsSystem::instance()->referenceToSceneNode(result.first); + + uint32_t visibilityMask = getCamera()->getViewport()->getVisibilityMask(); + bool ignoreObjects = !(visibilityMask & (uint32_t)CSVRender::Element_Reference); + + if(!ignoreObjects && getSceneManager()->hasSceneNode(sceneNode)) + { + return result; + } + } + } + else + std::cout << "error castRay returned empty " << result.first << std::endl; + + return std::make_pair("", Ogre::Vector3(0,0,0)); +} + +std::pair CSVRender::PagedWorldspaceWidget::mousePositionOnPlane(QMouseEvent *event, Ogre::Plane &plane) +{ + // using a really small value seems to mess up with the projections + float nearClipDistance = getCamera()->getNearClipDistance(); // save existing + getCamera()->setNearClipDistance(10.0f); // arbitrary number + Ogre::Ray mouseRay = getCamera()->getCameraToViewportRay( + (float) event->x() / getCamera()->getViewport()->getActualWidth(), + (float) event->y() / getCamera()->getViewport()->getActualHeight()); + getCamera()->setNearClipDistance(nearClipDistance); // restore + std::pair planeResult = mouseRay.intersects(plane); + + if(planeResult.first) + return std::make_pair(true, mouseRay.getPoint(planeResult.second)); + else + return std::make_pair(false, Ogre::Vector3()); // should only happen if the plane is too small +} + +void CSVRender::PagedWorldspaceWidget::debugMousePicking(float mouseX, float mouseY) +{ + CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance(); + bool debug = userSettings.setting ("debug/mouse-picking", QString("false")) == "true" ? true : false; + + std::pair result = CSVWorld::PhysicsSystem::instance()->castRay( + mouseX, mouseY, NULL, NULL, getCamera()); + if(debug && result.first != "") + { + // FIXME: is there a better way to distinguish terrain from objects? + QString name = QString(result.first.c_str()); + if(name.contains(QRegExp("^HeightField"))) + { + // terrain + std::cout << "terrain: " << result.first << std::endl; + std::cout << " hit pos "+ QString::number(result.second.x).toStdString() + + ", " + QString::number(result.second.y).toStdString() + + ", " + QString::number(result.second.z).toStdString() + << std::endl; + } + else + { + std::string sceneNode = + CSVWorld::PhysicsSystem::instance()->referenceToSceneNode(result.first); + + uint32_t visibilityMask = getCamera()->getViewport()->getVisibilityMask(); + bool ignoreObjects = !(visibilityMask & (uint32_t)CSVRender::Element_Reference); + + if(!ignoreObjects && getSceneManager()->hasSceneNode(sceneNode)) + { + if(userSettings.setting("debug/mouse-picking", QString("false")) == "true" ? true : false) + updateSelectionHighlight(sceneNode, result.second); + } + + std::cout << "ReferenceId: " << result.first << std::endl; + const CSMWorld::CellRef& cellref = mDocument.getData().getReferences().getRecord (result.first).get(); + //std::cout << "CellRef.mId: " << cellref.mId << std::endl; // Same as ReferenceId + std::cout << " CellRef.mCell: " << cellref.mCell << std::endl; + + const CSMWorld::RefCollection& references = mDocument.getData().getReferences(); + int index = references.searchId(result.first); + if (index != -1) + { + int columnIndex = + references.findColumnIndex(CSMWorld::Columns::ColumnId_ReferenceableId); + + std::cout << " index: " + QString::number(index).toStdString() + +", column index: " + QString::number(columnIndex).toStdString() << std::endl; + } + + std::map::iterator iter (mCells.begin()); + while (iter!=mCells.end()) + { + if(iter->first.getId("dummy") == cellref.mCell) + { + //std::cout << "Cell found" << std::endl; + break; + } + ++iter; + } + flagAsModified(); + } + } +} + +// FIXME: for debugging only +void CSVRender::PagedWorldspaceWidget::updateSelectionHighlight(std::string sceneNode, const Ogre::Vector3 &position) +{ + CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance(); + bool debugCursor = userSettings.setting( + "debug/mouse-position", QString("false")) == "true" ? true : false; + + //TODO: Try http://www.ogre3d.org/tikiwiki/Create+outline+around+a+character + Ogre::SceneNode *scene = getSceneManager()->getSceneNode(sceneNode); + std::map >::iterator iter = + mSelectedEntities.find(sceneNode); + if(iter != mSelectedEntities.end()) // currently selected + { + std::vector clonedEntities = mSelectedEntities[sceneNode]; + while(!clonedEntities.empty()) + { + if(getSceneManager()->hasEntity(clonedEntities.back())) + { + scene->detachObject(clonedEntities.back()); + getSceneManager()->destroyEntity(clonedEntities.back()); + } + clonedEntities.pop_back(); + } + mSelectedEntities.erase(iter); + + if(debugCursor) + removeHitPoint(getSceneManager(), sceneNode); + } + else + { + std::vector clonedEntities; + Ogre::SceneNode::ObjectIterator iter = scene->getAttachedObjectIterator(); + iter.begin(); + while(iter.hasMoreElements()) + { + Ogre::MovableObject * element = iter.getNext(); + if(!element) + break; + + if(element->getMovableType() != "Entity") + continue; + + Ogre::Entity * entity = dynamic_cast(element); + if(getSceneManager()->hasEntity(entity->getName()+"cover")) + { + // FIXME: this shouldn't really happen... but does :( + scene->detachObject(entity->getName()+"cover"); + getSceneManager()->destroyEntity(entity->getName()+"cover"); + } + Ogre::Entity * clone = entity->clone(entity->getName()+"cover"); + + Ogre::MaterialPtr mat = + Ogre::MaterialManager::getSingleton().getByName("TransMaterial"); + if(!mat.isNull()) + { + clone->setMaterial(mat); + scene->attachObject(clone); + clonedEntities.push_back(entity->getName()+"cover"); + } + } + mSelectedEntities[sceneNode] = clonedEntities; + + if(debugCursor) + showHitPoint(getSceneManager(), sceneNode, position); + } +} diff --git a/apps/opencs/view/render/pagedworldspacewidget.hpp b/apps/opencs/view/render/pagedworldspacewidget.hpp index 17b6d10c5..dc71e19db 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.hpp +++ b/apps/opencs/view/render/pagedworldspacewidget.hpp @@ -8,6 +8,8 @@ #include "worldspacewidget.hpp" #include "cell.hpp" +class QElapsedTimer; + namespace CSVRender { @@ -27,6 +29,21 @@ namespace CSVRender std::map mTextOverlays; OverlayMask *mOverlayMask; + enum MouseState { + Mouse_Grab, + Mouse_Drag, + Mouse_Edit, + Mouse_Default + }; + MouseState mMouseState; + QPoint mOldPos; + std::string mCurrentObj; + QElapsedTimer *mMouseEventTimer; + Ogre::Plane *mPlane; + Ogre::SceneNode *mObjSceneNode; + Ogre::Vector3 mOrigObjPos; + Ogre::Vector3 mOrigMousePos; + private: std::pair getCoordinatesFromId(const std::string& record) const; @@ -51,6 +68,11 @@ namespace CSVRender virtual std::string getStartupInstruction(); + std::pair isObjectUnderCursor(float mouseX, float mouseY); + std::pair mousePositionOnPlane(QMouseEvent *event, Ogre::Plane &plane); + void debugMousePicking(float mouseX, float mouseY); + void updateSelectionHighlight(std::string sceneNode, const Ogre::Vector3 &position); + public: PagedWorldspaceWidget (QWidget *parent, CSMDoc::Document& document); @@ -81,9 +103,11 @@ namespace CSVRender virtual void updateOverlay(); + 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); signals: diff --git a/apps/opencs/view/render/scenewidget.hpp b/apps/opencs/view/render/scenewidget.hpp index 1adbf3f17..5f023a7ad 100644 --- a/apps/opencs/view/render/scenewidget.hpp +++ b/apps/opencs/view/render/scenewidget.hpp @@ -71,6 +71,10 @@ namespace CSVRender virtual void mouseReleaseEvent (QMouseEvent *event); + virtual void mouseMoveEvent (QMouseEvent *event); + + void wheelEvent (QWheelEvent *event); + private: void paintEvent(QPaintEvent* e); void resizeEvent(QResizeEvent* e); @@ -82,12 +86,8 @@ namespace CSVRender void focusOutEvent (QFocusEvent *event); - void wheelEvent (QWheelEvent *event); - void leaveEvent (QEvent *event); - void mouseMoveEvent (QMouseEvent *event); - void updateOgreWindow(); void setLighting (Lighting *lighting); diff --git a/apps/opencs/view/world/physicssystem.cpp b/apps/opencs/view/world/physicssystem.cpp index 154cc6273..a422147a9 100644 --- a/apps/opencs/view/world/physicssystem.cpp +++ b/apps/opencs/view/world/physicssystem.cpp @@ -37,26 +37,35 @@ namespace CSVWorld } void PhysicsSystem::addObject(const std::string &mesh, - const std::string &name, const std::string &referenceId, float scale, + const std::string &sceneNodeName, const std::string &referenceId, float scale, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, bool placeable) { - mRefToSceneNode[referenceId] = name; + mRefToSceneNode[referenceId] = sceneNodeName; + mSceneNodeToMesh[sceneNodeName] = mesh; - mEngine->createAndAdjustRigidBody(mesh, referenceId, scale, position, rotation, - 0, // scaledBoxTranslation - 0, // boxRotation - true, // raycasting - placeable); + mEngine->createAndAdjustRigidBody(mesh, + referenceId, scale, position, rotation, + 0, // scaledBoxTranslation + 0, // boxRotation + true, // raycasting + placeable); } - void PhysicsSystem::removeObject(const std::string& name) + void PhysicsSystem::removeObject(const std::string &referenceId) { - mEngine->removeRigidBody(name); - mEngine->deleteRigidBody(name); + mEngine->removeRigidBody(referenceId); + mEngine->deleteRigidBody(referenceId); } - void PhysicsSystem::addHeightField(float* heights, int x, int y, float yoffset, - float triSize, float sqrtVerts) + void PhysicsSystem::moveObject(const std::string &referenceId, + const Ogre::Vector3 &position, const Ogre::Quaternion &rotation) + { + mEngine->adjustRigidBody(mEngine->getRigidBody(referenceId, true /*raycasting*/), + position, rotation); + } + + void PhysicsSystem::addHeightField(float* heights, + int x, int y, float yoffset, float triSize, float sqrtVerts) { mEngine->addHeightField(heights, x, y, yoffset, triSize, sqrtVerts); } @@ -66,8 +75,8 @@ namespace CSVWorld mEngine->removeHeightField(x, y); } - std::pair PhysicsSystem::castRay(float mouseX, float mouseY, - Ogre::Vector3* normal, std::string* hit, Ogre::Camera *camera) + std::pair PhysicsSystem::castRay(float mouseX, + float mouseY, Ogre::Vector3* normal, std::string* hit, Ogre::Camera *camera) { if(!mSceneMgr || !camera || !camera->getViewport()) return std::make_pair("", Ogre::Vector3(0,0,0)); // FIXME: this should be an exception @@ -102,9 +111,14 @@ namespace CSVWorld return std::make_pair(result.first, ray.getPoint(farClipDist*result.second)); } - std::string PhysicsSystem::referenceToSceneNode(std::string reference) + std::string PhysicsSystem::referenceToSceneNode(std::string referenceId) { - return mRefToSceneNode[reference]; + return mRefToSceneNode[referenceId]; + } + + std::string PhysicsSystem::sceneNodeToMesh(std::string sceneNodeName) + { + return mSceneNodeToMesh[sceneNodeName]; } void PhysicsSystem::setSceneManager(Ogre::SceneManager *sceneMgr) diff --git a/apps/opencs/view/world/physicssystem.hpp b/apps/opencs/view/world/physicssystem.hpp index c19486d17..983f1a2a7 100644 --- a/apps/opencs/view/world/physicssystem.hpp +++ b/apps/opencs/view/world/physicssystem.hpp @@ -27,6 +27,7 @@ namespace CSVWorld { static PhysicsSystem *mPhysicsSystemInstance; std::map mRefToSceneNode; + std::map mSceneNodeToMesh; OEngine::Physic::PhysicEngine* mEngine; Ogre::SceneManager *mSceneMgr; @@ -40,24 +41,28 @@ namespace CSVWorld void setSceneManager(Ogre::SceneManager *sceneMgr); - void addObject(const std::string &mesh, const std::string &name, - const std::string &referenceId, float scale, - const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, - bool placeable=false); + void addObject(const std::string &mesh, + const std::string &sceneNodeName, const std::string &referenceId, float scale, + const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, + bool placeable=false); - void removeObject(const std::string &name); + void removeObject(const std::string &referenceId); - void addHeightField(float* heights, int x, int y, float yoffset, - float triSize, float sqrtVerts); + void moveObject(const std::string &referenceId, + const Ogre::Vector3 &position, const Ogre::Quaternion &rotation); + + void addHeightField(float* heights, + int x, int y, float yoffset, float triSize, float sqrtVerts); void removeHeightField(int x, int y); void toggleDebugRendering(); - std::pair castRay(float mouseX, float mouseY, - Ogre::Vector3* normal, std::string* hit, Ogre::Camera *camera); + std::pair castRay(float mouseX, + float mouseY, Ogre::Vector3* normal, std::string* hit, Ogre::Camera *camera); - std::string referenceToSceneNode(std::string reference); + std::string referenceToSceneNode(std::string referenceId); + std::string sceneNodeToMesh(std::string sceneNodeName); private: