From fbadaf55eee36f0be5efb5728defde27065aeaaa Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 31 Oct 2014 21:50:57 +1100 Subject: [PATCH] Multiple SceneManagers per physics engine now working. --- apps/opencs/view/doc/subview.cpp | 5 +- apps/opencs/view/doc/subview.hpp | 4 ++ apps/opencs/view/doc/view.cpp | 12 ++++ apps/opencs/view/doc/view.hpp | 2 + apps/opencs/view/render/scenewidget.cpp | 8 ++- apps/opencs/view/render/scenewidget.hpp | 2 + apps/opencs/view/render/worldspacewidget.cpp | 19 ++--- apps/opencs/view/render/worldspacewidget.hpp | 3 + apps/opencs/view/world/physicssystem.cpp | 76 +++++++++++++++++--- apps/opencs/view/world/physicssystem.hpp | 13 +++- apps/opencs/view/world/scenesubview.cpp | 16 +++-- apps/opencs/view/world/scenesubview.hpp | 2 + 12 files changed, 136 insertions(+), 26 deletions(-) diff --git a/apps/opencs/view/doc/subview.cpp b/apps/opencs/view/doc/subview.cpp index a9dce25be..bce14a642 100644 --- a/apps/opencs/view/doc/subview.cpp +++ b/apps/opencs/view/doc/subview.cpp @@ -42,4 +42,7 @@ std::string CSVDoc::SubView::getTitle() const void CSVDoc::SubView::closeRequest() { emit closeRequest (this); -} \ No newline at end of file +} + +void CSVDoc::SubView::updateScene() +{} diff --git a/apps/opencs/view/doc/subview.hpp b/apps/opencs/view/doc/subview.hpp index a8aa3cda1..9acb7a5ae 100644 --- a/apps/opencs/view/doc/subview.hpp +++ b/apps/opencs/view/doc/subview.hpp @@ -52,6 +52,8 @@ namespace CSVDoc virtual void updateUserSetting (const QString& name, const QStringList& value); + virtual void updateScene(); + private: void closeEvent (QCloseEvent *event); @@ -66,6 +68,8 @@ namespace CSVDoc void updateSubViewIndicies (SubView *view = 0); + void refreshSubViews(); + protected slots: void closeRequest(); diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 8a6665cf2..932dab3aa 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -16,6 +16,7 @@ #include "../../model/world/idtable.hpp" #include "../world/subviews.hpp" +#include "../doc/subview.hpp" #include "../tools/subviews.hpp" @@ -300,6 +301,15 @@ void CSVDoc::View::setupUi() setupDebugMenu(); } +void CSVDoc::View::refreshSubViews() +{ + QList::iterator iter = mSubViews.begin(); + for(; iter != mSubViews.end(); ++iter) + { + (*iter)->updateScene(); + } +} + void CSVDoc::View::updateTitle() { std::ostringstream stream; @@ -527,6 +537,8 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin connect (view, SIGNAL (updateSubViewIndicies (SubView *)), this, SLOT (updateSubViewIndicies (SubView *))); + connect (view, SIGNAL (refreshSubViews()), this, SLOT (refreshSubViews())); + view->show(); } diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 55ea5ee51..c6bb206d6 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -139,6 +139,8 @@ namespace CSVDoc // called when subviews are added or removed void updateSubViewIndicies (SubView *view = 0); + void refreshSubViews(); + private slots: void newView(); diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index ee6630eac..40bca30b1 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -66,7 +66,7 @@ namespace CSVRender mOverlaySystem = OverlaySystem::instance().get(); mSceneMgr->addRenderQueueListener(mOverlaySystem); - CSVWorld::PhysicsSystem::instance()->addSceneManager(mSceneMgr); + CSVWorld::PhysicsSystem::instance()->addSceneManager(mSceneMgr, this); QTimer *timer = new QTimer (this); @@ -414,6 +414,12 @@ namespace CSVRender } } + void SceneWidget::updateScene() + { + flagAsModified(); + update(); + } + void SceneWidget::updateOverlay() { } diff --git a/apps/opencs/view/render/scenewidget.hpp b/apps/opencs/view/render/scenewidget.hpp index 5f023a7ad..a3b8cd4b0 100644 --- a/apps/opencs/view/render/scenewidget.hpp +++ b/apps/opencs/view/render/scenewidget.hpp @@ -47,6 +47,8 @@ namespace CSVRender virtual void setVisibilityMask (unsigned int mask); + virtual void updateScene(); + protected: void setNavigation (Navigation *navigation); diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 655a2e026..a94ad9dfd 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -665,15 +665,16 @@ void CSVRender::WorldspaceWidget::mouseReleaseEvent (QMouseEvent *event) Ogre::Vector3 pos = mOrigObjPos+planeResult.second-mOrigMousePos; placeObject(mGrabbedSceneNode, pos); //mCurrentObj = mGrabbedSceneNode; // FIXME - mCurrentObj = ""; + mCurrentObj = ""; // whether the object is selected // reset states - mCurrentMousePos = Ogre::Vector3(); - mOrigMousePos = Ogre::Vector3(); - mOrigObjPos = Ogre::Vector3(); - mGrabbedSceneNode = ""; - mOldPos = QPoint(0, 0); - mZOffset = 0.0f; + mCurrentMousePos = Ogre::Vector3(); // mouse pos to use in wheel event + mOrigMousePos = Ogre::Vector3(); // starting pos of mouse in world space + mOrigObjPos = Ogre::Vector3(); // starting pos of object in world space + mGrabbedSceneNode = ""; // id of the object + mZOffset = 0.0f; // used for z-axis movement + mOldPos = QPoint(0, 0); // to calculate relative movement of mouse + // on screen // FIXME: update document // FIXME: highlight current object? @@ -903,7 +904,6 @@ std::pair CSVRender::WorldspaceWidget::mousePositionOnPlane void CSVRender::WorldspaceWidget::placeObject(const std::string sceneNode, const Ogre::Vector3 &pos) { getSceneManager()->getSceneNode(sceneNode)->setPosition(pos); - flagAsModified(); // update physics std::string refId = CSVWorld::PhysicsSystem::instance()->sceneNodeToRefId(sceneNode); @@ -918,6 +918,9 @@ void CSVRender::WorldspaceWidget::placeObject(const std::string sceneNode, const std::string mesh = CSVWorld::PhysicsSystem::instance()->sceneNodeToMesh(sceneNode); CSVWorld::PhysicsSystem::instance()->removeObject(sceneNode); CSVWorld::PhysicsSystem::instance()->addObject(mesh, sceneNode, refId, cellref.mScale, pos, xr*yr*zr); + + // update all SceneWidgets and their SceneManagers + emit signalAsModified(); } bool CSVRender::WorldspaceWidget::isDebug() diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 48f5e98d4..e69fbe08e 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -168,7 +168,10 @@ namespace CSVRender signals: void closeRequest(); + void dataDropped(const std::vector& data); + + void signalAsModified(); }; } diff --git a/apps/opencs/view/world/physicssystem.cpp b/apps/opencs/view/world/physicssystem.cpp index 02775801c..bcf9aeff2 100644 --- a/apps/opencs/view/world/physicssystem.cpp +++ b/apps/opencs/view/world/physicssystem.cpp @@ -15,7 +15,7 @@ namespace CSVWorld { PhysicsSystem *PhysicsSystem::mPhysicsSystemInstance = 0; - PhysicsSystem::PhysicsSystem() : mSceneMgr(0) + PhysicsSystem::PhysicsSystem() { assert(!mPhysicsSystemInstance); mPhysicsSystemInstance = this; @@ -28,6 +28,7 @@ namespace CSVWorld PhysicsSystem::~PhysicsSystem() { delete mEngine; + // FIXME: update maps when SceneManagers are destroyed } PhysicsSystem *PhysicsSystem::instance() @@ -39,7 +40,7 @@ namespace CSVWorld // FIXME: looks up the scene manager based on the scene node name (highly inefficient) // NOTE: referenceId is assumed to be unique per document // NOTE: searching is done here rather than after rayTest, so slower to load but - // faster to find (not verified w/ perf test) + // faster to find (not verified w/ perf test) void PhysicsSystem::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) @@ -58,21 +59,67 @@ namespace CSVWorld } } - if(foundSceneManager) + if(!foundSceneManager) + return; // FIXME: this should be an exception + + // update physics, only one physics model per referenceId + if(mEngine->getRigidBody(referenceId, true) == NULL) { + mEngine->createAndAdjustRigidBody(mesh, referenceId, scale, position, rotation, 0, // scaledBoxTranslation 0, // boxRotation true, // raycasting placeable); + + // update other scene managers if they have the referenceId (may have moved) + iter = mSceneManagers.begin(); + for(; iter != mSceneManagers.end(); ++iter) + { + std::string name = refIdToSceneNode(referenceId, *iter); + if(name != sceneNodeName && (*iter)->hasSceneNode(name)) + { + // FIXME: rotation or scale not updated + (*iter)->getSceneNode(name)->setPosition(position); + } + } } } void PhysicsSystem::removeObject(const std::string &sceneNodeName) { - mEngine->removeRigidBody(sceneNodeName); - mEngine->deleteRigidBody(sceneNodeName); + std::string referenceId = sceneNodeToRefId(sceneNodeName); + if(referenceId != "") + { + mEngine->removeRigidBody(referenceId); + mEngine->deleteRigidBody(referenceId); + + Ogre::SceneManager *sceneManager = NULL; + std::list::const_iterator iter = mSceneManagers.begin(); + for(; iter != mSceneManagers.end(); ++iter) + { + if((*iter)->hasSceneNode(sceneNodeName)) + { + sceneManager = *iter; + break; + } + } + + if(!sceneManager) + return; // FIXME: maybe this should be an exception + + std::map >::iterator itRef = + mRefIdToSceneNode.begin(); + for(; itRef != mRefIdToSceneNode.end(); ++itRef) + { + if((*itRef).second.find(sceneManager) != (*itRef).second.end()) + { + (*itRef).second.erase(sceneManager); + return; + } + } + } } void PhysicsSystem::moveObject(const std::string &sceneNodeName, @@ -135,7 +182,15 @@ namespace CSVWorld if(result.first == "") return std::make_pair("", Ogre::Vector3(0,0,0)); else - return std::make_pair(refIdToSceneNode(result.first, sceneMgr), ray.getPoint(farClipDist*result.second)); + { + std::string name = refIdToSceneNode(result.first, sceneMgr); + if(name == "") + name = result.first; + else + name = refIdToSceneNode(result.first, sceneMgr); + + return std::make_pair(name, ray.getPoint(farClipDist*result.second)); + } } std::string PhysicsSystem::refIdToSceneNode(std::string referenceId, Ogre::SceneManager *sceneMgr) @@ -153,15 +208,20 @@ namespace CSVWorld return mSceneNodeToMesh[sceneNodeName]; } - void PhysicsSystem::addSceneManager(Ogre::SceneManager *sceneMgr) + void PhysicsSystem::addSceneManager(Ogre::SceneManager *sceneMgr, CSVRender::SceneWidget * scene) { mSceneManagers.push_back(sceneMgr); } + std::list PhysicsSystem::sceneWidgets() + { + return mSceneWidgets; + } + void PhysicsSystem::toggleDebugRendering(Ogre::SceneManager *sceneMgr) { // FIXME: should check if sceneMgr is in the list - if(!mSceneMgr) + if(!sceneMgr) return; // FIXME: maybe this should be an exception mEngine->setSceneManager(sceneMgr); diff --git a/apps/opencs/view/world/physicssystem.hpp b/apps/opencs/view/world/physicssystem.hpp index 616bd13e6..d62c5089b 100644 --- a/apps/opencs/view/world/physicssystem.hpp +++ b/apps/opencs/view/world/physicssystem.hpp @@ -21,6 +21,11 @@ namespace OEngine } } +namespace CSVRender +{ + class SceneWidget; +} + namespace CSVWorld { class PhysicsSystem @@ -30,10 +35,9 @@ namespace CSVWorld std::map > mRefIdToSceneNode; std::map mSceneNodeToMesh; std::list mSceneManagers; // FIXME: change to list per OEngine + std::list mSceneWidgets; // FIXME: change to list per OEngine OEngine::Physic::PhysicEngine* mEngine; - Ogre::SceneManager *mSceneMgr; - public: PhysicsSystem(); @@ -41,7 +45,7 @@ namespace CSVWorld static PhysicsSystem *instance(); - void addSceneManager(Ogre::SceneManager *sceneMgr); + void addSceneManager(Ogre::SceneManager *sceneMgr, CSVRender::SceneWidget * scene); void addObject(const std::string &mesh, const std::string &sceneNodeName, const std::string &referenceId, float scale, @@ -65,8 +69,11 @@ namespace CSVWorld float mouseY, Ogre::SceneManager *sceneMgr, Ogre::Camera *camera); std::string sceneNodeToRefId(std::string sceneNodeName); + std::string sceneNodeToMesh(std::string sceneNodeName); + std::list sceneWidgets(); + private: void updateSelectionHighlight(std::string sceneNode, const Ogre::Vector3 &position); diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index ce68da362..b02c14f12 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -38,7 +38,7 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D mLayout->setContentsMargins (QMargins (0, 0, 0, 0)); - CSVRender::WorldspaceWidget* wordspaceWidget = NULL; + CSVRender::WorldspaceWidget* worldspaceWidget = NULL; widgetType whatWidget; if (id.getId()=="sys::default") @@ -47,7 +47,7 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D CSVRender::PagedWorldspaceWidget *newWidget = new CSVRender::PagedWorldspaceWidget (this, document); - wordspaceWidget = newWidget; + worldspaceWidget = newWidget; makeConnections(newWidget); } @@ -57,12 +57,14 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D CSVRender::UnpagedWorldspaceWidget *newWidget = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this); - wordspaceWidget = newWidget; + worldspaceWidget = newWidget; makeConnections(newWidget); } - replaceToolbarAndWorldspace(wordspaceWidget, makeToolbar(wordspaceWidget, whatWidget)); + connect (worldspaceWidget, SIGNAL (signalAsModified()), this, SIGNAL (refreshSubViews())); + + replaceToolbarAndWorldspace(worldspaceWidget, makeToolbar(worldspaceWidget, whatWidget)); layout->insertLayout (0, mLayout, 1); @@ -137,7 +139,6 @@ void CSVWorld::SceneSubView::setEditLock (bool locked) void CSVWorld::SceneSubView::updateEditorSetting(const QString &settingName, const QString &settingValue) { - } void CSVWorld::SceneSubView::setStatusBar (bool show) @@ -150,6 +151,11 @@ void CSVWorld::SceneSubView::useHint (const std::string& hint) mScene->useViewHint (hint); } +void CSVWorld::SceneSubView::updateScene() +{ + if(mScene) mScene->updateScene(); +} + std::string CSVWorld::SceneSubView::getTitle() const { return mTitle; diff --git a/apps/opencs/view/world/scenesubview.hpp b/apps/opencs/view/world/scenesubview.hpp index fc45347d0..0bf19ee69 100644 --- a/apps/opencs/view/world/scenesubview.hpp +++ b/apps/opencs/view/world/scenesubview.hpp @@ -60,6 +60,8 @@ namespace CSVWorld virtual std::string getTitle() const; + virtual void updateScene(); + private: void makeConnections(CSVRender::PagedWorldspaceWidget* widget);