diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index b408503d1..dc22fd511 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -433,5 +433,5 @@ void CSVRender::Cell::reset (unsigned int elementMask) iter!=mObjects.end(); ++iter) iter->second->reset(); if (elementMask & Mask_Pathgrid) - mPathgrid->resetMove(); + mPathgrid->resetIndicators(); } diff --git a/apps/opencs/view/render/pathgrid.cpp b/apps/opencs/view/render/pathgrid.cpp index 5b2dd4f98..7c6c8eb9e 100644 --- a/apps/opencs/view/render/pathgrid.cpp +++ b/apps/opencs/view/render/pathgrid.cpp @@ -2,6 +2,7 @@ #include +#include #include #include #include @@ -61,6 +62,7 @@ namespace CSVRender , mParent(parent) , mPathgridGeometry(0) , mSelectedGeometry(0) + , mConnectionGeometry(0) , mTag(new PathgridTag(this)) { const float CoordScalar = ESM::Land::REAL_SIZE; @@ -189,12 +191,50 @@ namespace CSVRender createSelectedGeometry(); } - void Pathgrid::resetMove() + void Pathgrid::adjustConnectionIndicator(unsigned short node) + { + if (mConnectionIndicator) + { + const CSMWorld::Pathgrid* source = getPathgridSource(); + if (source) + { + const CSMWorld::Pathgrid::Point& pointA = source->mPoints[mConnectionNode]; + const CSMWorld::Pathgrid::Point& pointB = source->mPoints[node]; + + osg::Vec3f start = osg::Vec3f(pointA.mX, pointA.mY, pointA.mZ + SceneUtil::DiamondHalfHeight); + osg::Vec3f end = osg::Vec3f(pointB.mX, pointB.mY, pointB.mZ + SceneUtil::DiamondHalfHeight); + + createConnectionGeometry(start, end); + } + } + } + + void Pathgrid::adjustConnectionIndicator(const osg::Vec3d& pos) + { + if (mConnectionIndicator) + { + const CSMWorld::Pathgrid* source = getPathgridSource(); + if (source) + { + const CSMWorld::Pathgrid::Point& point = source->mPoints[mConnectionNode]; + + osg::Vec3f start = osg::Vec3f(point.mX, point.mY, point.mZ + SceneUtil::DiamondHalfHeight); + osg::Vec3f end = pos - mBaseNode->getPosition(); + createConnectionGeometry(start, end); + } + } + } + + void Pathgrid::resetIndicators() { mSelectedNode->setPosition(osg::Vec3f(0,0,0)); if (mConnectionIndicator) { mConnectionIndicator = false; + + mPathgridGeode->removeDrawable(mConnectionGeometry); + mConnectionGeometry = 0; + createSelectedGeometry(); } } @@ -379,8 +419,6 @@ namespace CSVRender void Pathgrid::removeGeometry() { mRemoveGeometry = true; - - } void Pathgrid::update() @@ -471,6 +509,31 @@ namespace CSVRender } } + void Pathgrid::createConnectionGeometry(const osg::Vec3f& start, const osg::Vec3f& end) + { + if (mConnectionGeometry) + mPathgridGeode->removeDrawable(mConnectionGeometry); + + mConnectionGeometry = new osg::Geometry(); + + osg::ref_ptr vertices = new osg::Vec3Array(2); + osg::ref_ptr colors = new osg::Vec4Array(1); + osg::ref_ptr indices = new osg::DrawElementsUShort(osg::PrimitiveSet::LINES, 2); + + (*vertices)[0] = start; + (*vertices)[1] = end; + (*colors)[0] = osg::Vec4f(0.4f, 1.f, 0.4f, 1.f); + indices->setElement(0, 0); + indices->setElement(1, 1); + + mConnectionGeometry->setVertexArray(vertices); + mConnectionGeometry->setColorArray(colors, osg::Array::BIND_OVERALL); + mConnectionGeometry->addPrimitiveSet(indices); + mConnectionGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + + mPathgridGeode->addDrawable(mConnectionGeometry); + } + const CSMWorld::Pathgrid* Pathgrid::getPathgridSource() { int index = mPathgridCollection.searchId(mId); diff --git a/apps/opencs/view/render/pathgrid.hpp b/apps/opencs/view/render/pathgrid.hpp index 7cab806d3..9f6cf2686 100644 --- a/apps/opencs/view/render/pathgrid.hpp +++ b/apps/opencs/view/render/pathgrid.hpp @@ -69,9 +69,11 @@ namespace CSVRender void clearSelected(); void moveSelected(const osg::Vec3d& offset); - void resetMove(); - void setupConnectionIndicator(unsigned short node); + void adjustConnectionIndicator(unsigned short node); + void adjustConnectionIndicator(const osg::Vec3d& pos); + + void resetIndicators(); void applyPoint(CSMWorld::CommandMacro& commands, const osg::Vec3d& worldPos); void applyPosition(CSMWorld::CommandMacro& commands); @@ -109,6 +111,7 @@ namespace CSVRender osg::ref_ptr mSelectedGeode; osg::ref_ptr mPathgridGeometry; osg::ref_ptr mSelectedGeometry; + osg::ref_ptr mConnectionGeometry; osg::ref_ptr mTag; @@ -118,6 +121,8 @@ namespace CSVRender void removePathgridGeometry(); void removeSelectedGeometry(); + void createConnectionGeometry(const osg::Vec3f& start, const osg::Vec3f& end); + const CSMWorld::Pathgrid* getPathgridSource(); int edgeExists(const CSMWorld::Pathgrid& source, unsigned short node1, unsigned short node2); diff --git a/apps/opencs/view/render/pathgridmode.cpp b/apps/opencs/view/render/pathgridmode.cpp index 0dd458346..423497a24 100644 --- a/apps/opencs/view/render/pathgridmode.cpp +++ b/apps/opencs/view/render/pathgridmode.cpp @@ -156,13 +156,13 @@ namespace CSVRender void PathgridMode::drag(const QPoint& pos, int diffX, int diffY, double speedFactor) { - std::vector > selection = getWorldspaceWidget().getSelection (Mask_Pathgrid); - - for (std::vector >::iterator it = selection.begin(); it != selection.end(); ++it) + if (mDragMode == DragMode_Move) { - if (PathgridTag* tag = dynamic_cast(it->get())) + std::vector > selection = getWorldspaceWidget().getSelection(Mask_Pathgrid); + + for (std::vector >::iterator it = selection.begin(); it != selection.end(); ++it) { - if (mDragMode == DragMode_Move) + if (PathgridTag* tag = dynamic_cast(it->get())) { osg::Vec3d eye, center, up, offset; getWorldspaceWidget().getCamera()->getViewMatrix().getLookAt (eye, center, up); @@ -171,10 +171,26 @@ namespace CSVRender tag->getPathgrid()->moveSelected(offset); } - else if (mDragMode == DragMode_Edge) + } + } + else if (mDragMode == DragMode_Edge) + { + WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask()); + + Cell* cell = getWorldspaceWidget().getCell(hit.worldPos); + if (cell) + { + PathgridTag* tag = 0; + if (hit.tag && (tag = dynamic_cast(hit.tag.get())) && tag->getPathgrid()->getId() == mEdgeId) + { + unsigned short node = SceneUtil::getPathgridNode(static_cast(hit.index0)); + cell->getPathgrid()->adjustConnectionIndicator(node); + } + else { - // TODO Add indicator, need raytrace + cell->getPathgrid()->adjustConnectionIndicator(hit.worldPos); } + } } } diff --git a/components/sceneutil/pathgridutil.cpp b/components/sceneutil/pathgridutil.cpp index 5078b1edb..48e398132 100644 --- a/components/sceneutil/pathgridutil.cpp +++ b/components/sceneutil/pathgridutil.cpp @@ -15,8 +15,6 @@ namespace SceneUtil const unsigned short DiamondTotalVertexCount = DiamondVertexCount + DiamondConnectorVertexCount; - const float DiamondHalfHeight = 40.f; - const float DiamondHalfWidth = 16.f; const float DiamondWireframeScalar = 1.1f; const osg::Vec3f DiamondPoints[DiamondVertexCount] = diff --git a/components/sceneutil/pathgridutil.hpp b/components/sceneutil/pathgridutil.hpp index 9a93ddf91..de0ff35ed 100644 --- a/components/sceneutil/pathgridutil.hpp +++ b/components/sceneutil/pathgridutil.hpp @@ -11,6 +11,9 @@ namespace ESM namespace SceneUtil { + const float DiamondHalfHeight = 40.f; + const float DiamondHalfWidth = 16.f; + osg::ref_ptr createPathgridGeometry(const ESM::Pathgrid& pathgrid); osg::ref_ptr createPathgridSelectedWireframe(const ESM::Pathgrid& pathgrid,