diff --git a/apps/opencs/view/render/editmode.cpp b/apps/opencs/view/render/editmode.cpp index 22de54218..5f0852c90 100644 --- a/apps/opencs/view/render/editmode.cpp +++ b/apps/opencs/view/render/editmode.cpp @@ -37,29 +37,29 @@ void CSVRender::EditMode::primarySelectPressed (const WorldspaceHitResult& hit) void CSVRender::EditMode::secondarySelectPressed (const WorldspaceHitResult& hit) {} -bool CSVRender::EditMode::primaryEditStartDrag (const WorldspaceHitResult& hit) +bool CSVRender::EditMode::primaryEditStartDrag (const QPoint& pos) { return false; } -bool CSVRender::EditMode::secondaryEditStartDrag (const WorldspaceHitResult& hit) +bool CSVRender::EditMode::secondaryEditStartDrag (const QPoint& pos) { return false; } -bool CSVRender::EditMode::primarySelectStartDrag (const WorldspaceHitResult& hit) +bool CSVRender::EditMode::primarySelectStartDrag (const QPoint& pos) { return false; } -bool CSVRender::EditMode::secondarySelectStartDrag (const WorldspaceHitResult& hit) +bool CSVRender::EditMode::secondarySelectStartDrag (const QPoint& pos) { return false; } -void CSVRender::EditMode::drag (int diffX, int diffY, double speedFactor) {} +void CSVRender::EditMode::drag (const QPoint& pos, int diffX, int diffY, double speedFactor) {} -void CSVRender::EditMode::dragCompleted(const WorldspaceHitResult& hit) {} +void CSVRender::EditMode::dragCompleted(const QPoint& pos) {} void CSVRender::EditMode::dragAborted() {} @@ -67,7 +67,7 @@ void CSVRender::EditMode::dragWheel (int diff, double speedFactor) {} void CSVRender::EditMode::dragEnterEvent (QDragEnterEvent *event) {} -void CSVRender::EditMode::dropEvent (QDropEvent* event) {} +void CSVRender::EditMode::dropEvent (QDropEvent *event) {} void CSVRender::EditMode::dragMoveEvent (QDragMoveEvent *event) {} diff --git a/apps/opencs/view/render/editmode.hpp b/apps/opencs/view/render/editmode.hpp index 37bbafdb1..f9b7027f9 100644 --- a/apps/opencs/view/render/editmode.hpp +++ b/apps/opencs/view/render/editmode.hpp @@ -8,6 +8,7 @@ class QDragEnterEvent; class QDropEvent; class QDragMoveEvent; +class QPoint; namespace CSVRender { @@ -53,28 +54,28 @@ namespace CSVRender /// Default-implementation: ignore and return false /// /// \return Drag accepted? - virtual bool primaryEditStartDrag (const WorldspaceHitResult& hit); + virtual bool primaryEditStartDrag (const QPoint& pos); /// Default-implementation: ignore and return false /// /// \return Drag accepted? - virtual bool secondaryEditStartDrag (const WorldspaceHitResult& hit); + virtual bool secondaryEditStartDrag (const QPoint& pos); /// Default-implementation: ignore and return false /// /// \return Drag accepted? - virtual bool primarySelectStartDrag (const WorldspaceHitResult& hit); + virtual bool primarySelectStartDrag (const QPoint& pos); /// Default-implementation: ignore and return false /// /// \return Drag accepted? - virtual bool secondarySelectStartDrag (const WorldspaceHitResult& hit); + virtual bool secondarySelectStartDrag (const QPoint& pos); /// Default-implementation: ignored - virtual void drag (int diffX, int diffY, double speedFactor); + virtual void drag (const QPoint& pos, int diffX, int diffY, double speedFactor); /// Default-implementation: ignored - virtual void dragCompleted(const WorldspaceHitResult& hit); + virtual void dragCompleted(const QPoint& pos); /// Default-implementation: ignored /// @@ -89,7 +90,7 @@ namespace CSVRender virtual void dragEnterEvent (QDragEnterEvent *event); /// Default-implementation: ignored - virtual void dropEvent (QDropEvent* event); + virtual void dropEvent (QDropEvent *event); /// Default-implementation: ignored virtual void dragMoveEvent (QDragMoveEvent *event); diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index 958d29337..df5ba7621 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -2,6 +2,7 @@ #include "instancemode.hpp" #include +#include #include "../../model/prefs/state.hpp" @@ -145,11 +146,12 @@ void CSVRender::InstanceMode::secondarySelectPressed (const WorldspaceHitResult& } } -bool CSVRender::InstanceMode::primaryEditStartDrag (const WorldspaceHitResult& hit) +bool CSVRender::InstanceMode::primaryEditStartDrag (const QPoint& pos) { if (mDragMode!=DragMode_None || mLocked) return false; + WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask()); if (hit.tag && CSMPrefs::get()["3D Scene Input"]["context-select"].isTrue()) { getWorldspaceWidget().clearSelection (Mask_Reference); @@ -189,7 +191,7 @@ bool CSVRender::InstanceMode::primaryEditStartDrag (const WorldspaceHitResult& h return true; } -bool CSVRender::InstanceMode::secondaryEditStartDrag (const WorldspaceHitResult& hit) +bool CSVRender::InstanceMode::secondaryEditStartDrag (const QPoint& pos) { if (mLocked) return false; @@ -197,7 +199,7 @@ bool CSVRender::InstanceMode::secondaryEditStartDrag (const WorldspaceHitResult& return false; } -void CSVRender::InstanceMode::drag (int diffX, int diffY, double speedFactor) +void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, double speedFactor) { osg::Vec3f eye; osg::Vec3f centre; @@ -244,7 +246,7 @@ void CSVRender::InstanceMode::drag (int diffX, int diffY, double speedFactor) } } -void CSVRender::InstanceMode::dragCompleted(const WorldspaceHitResult& hit) +void CSVRender::InstanceMode::dragCompleted(const QPoint& pos) { std::vector > selection = getWorldspaceWidget().getEdited (Mask_Reference); @@ -333,9 +335,9 @@ void CSVRender::InstanceMode::dropEvent (QDropEvent* event) if (!mime->fromDocument (document)) return; - osg::Vec3f insertPoint = getWorldspaceWidget().getIntersectionPoint (event->pos()); + WorldspaceHitResult hit = getWorldspaceWidget().mousePick (event->pos(), getWorldspaceWidget().getInteractionMask()); - std::string cellId = getWorldspaceWidget().getCellId (insertPoint); + std::string cellId = getWorldspaceWidget().getCellId (hit.worldPos); CSMWorld::IdTree& cellTable = dynamic_cast ( *document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells)); @@ -412,11 +414,11 @@ void CSVRender::InstanceMode::dropEvent (QDropEvent* event) createCommand->addValue (referencesTable.findColumnIndex ( CSMWorld::Columns::ColumnId_Cell), QString::fromUtf8 (cellId.c_str())); createCommand->addValue (referencesTable.findColumnIndex ( - CSMWorld::Columns::ColumnId_PositionXPos), insertPoint.x()); + CSMWorld::Columns::ColumnId_PositionXPos), hit.worldPos.x()); createCommand->addValue (referencesTable.findColumnIndex ( - CSMWorld::Columns::ColumnId_PositionYPos), insertPoint.y()); + CSMWorld::Columns::ColumnId_PositionYPos), hit.worldPos.y()); createCommand->addValue (referencesTable.findColumnIndex ( - CSMWorld::Columns::ColumnId_PositionZPos), insertPoint.z()); + CSMWorld::Columns::ColumnId_PositionZPos), hit.worldPos.z()); createCommand->addValue (referencesTable.findColumnIndex ( CSMWorld::Columns::ColumnId_ReferenceableId), QString::fromUtf8 (iter->getId().c_str())); diff --git a/apps/opencs/view/render/instancemode.hpp b/apps/opencs/view/render/instancemode.hpp index 39e3773ad..4f7937b51 100644 --- a/apps/opencs/view/render/instancemode.hpp +++ b/apps/opencs/view/render/instancemode.hpp @@ -49,13 +49,13 @@ namespace CSVRender virtual void secondarySelectPressed (const WorldspaceHitResult& hit); - virtual bool primaryEditStartDrag (const WorldspaceHitResult& hit); + virtual bool primaryEditStartDrag (const QPoint& pos); - virtual bool secondaryEditStartDrag (const WorldspaceHitResult& hit); + virtual bool secondaryEditStartDrag (const QPoint& pos); - virtual void drag (int diffX, int diffY, double speedFactor); + virtual void drag (const QPoint& pos, int diffX, int diffY, double speedFactor); - virtual void dragCompleted(const WorldspaceHitResult& hit); + virtual void dragCompleted(const QPoint& pos); /// \note dragAborted will not be called, if the drag is aborted via changing /// editing mode @@ -65,7 +65,7 @@ namespace CSVRender virtual void dragEnterEvent (QDragEnterEvent *event); - virtual void dropEvent (QDropEvent* event); + virtual void dropEvent (QDropEvent *event); virtual int getSubMode() const; diff --git a/apps/opencs/view/render/pathgridmode.cpp b/apps/opencs/view/render/pathgridmode.cpp index d50b42d35..3a2cc600a 100644 --- a/apps/opencs/view/render/pathgridmode.cpp +++ b/apps/opencs/view/render/pathgridmode.cpp @@ -1,6 +1,7 @@ #include "pathgridmode.hpp" #include +#include #include @@ -69,27 +70,8 @@ namespace CSVRender void PathgridMode::primaryEditPressed(const WorldspaceHitResult& hitResult) { - // Determine placement - osg::Vec3d position; - - if (hitResult.hit) - { - position = hitResult.worldPos; - } - else - { - const double DefaultDistance = 500.f; - - osg::Vec3d eye, center, up, offset; - getWorldspaceWidget().getCamera()->getViewMatrix().getLookAt (eye, center, up); - - osg::Vec3d direction = center - eye; - direction.normalize(); - position = eye + direction * DefaultDistance; - } - // Get pathgrid cell - Cell* cell = getWorldspaceWidget().getCell (position); + Cell* cell = getWorldspaceWidget().getCell (hitResult.worldPos); if (cell) { // Add node @@ -97,7 +79,7 @@ namespace CSVRender QString description = "Connect node to selected nodes"; CSMWorld::CommandMacro macro(undoStack, description); - cell->getPathgrid()->applyPoint(macro, position); + cell->getPathgrid()->applyPoint(macro, hitResult.worldPos); } } @@ -158,7 +140,7 @@ namespace CSVRender getWorldspaceWidget().clearSelection(Mask_Pathgrid); } - bool PathgridMode::primaryEditStartDrag(const WorldspaceHitResult& hit) + bool PathgridMode::primaryEditStartDrag(const QPoint& pos) { std::vector > selection = getWorldspaceWidget().getSelection (Mask_Pathgrid); @@ -170,8 +152,9 @@ namespace CSVRender return true; } - bool PathgridMode::secondaryEditStartDrag(const WorldspaceHitResult& hit) + bool PathgridMode::secondaryEditStartDrag(const QPoint& pos) { + WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask()); if (hit.tag) { if (PathgridTag* tag = dynamic_cast(hit.tag.get())) @@ -187,7 +170,7 @@ namespace CSVRender return true; } - void PathgridMode::drag(int diffX, int diffY, double speedFactor) + void PathgridMode::drag(const QPoint& pos, int diffX, int diffY, double speedFactor) { std::vector > selection = getWorldspaceWidget().getSelection (Mask_Pathgrid); @@ -212,7 +195,7 @@ namespace CSVRender } } - void PathgridMode::dragCompleted(const WorldspaceHitResult& hit) + void PathgridMode::dragCompleted(const QPoint& pos) { if (mDragMode == DragMode_Move) { @@ -231,6 +214,8 @@ namespace CSVRender } else if (mDragMode == DragMode_Edge) { + WorldspaceHitResult hit = getWorldspaceWidget().mousePick(pos, getWorldspaceWidget().getInteractionMask()); + if (hit.tag) { if (PathgridTag* tag = dynamic_cast(hit.tag.get())) diff --git a/apps/opencs/view/render/pathgridmode.hpp b/apps/opencs/view/render/pathgridmode.hpp index 6a070333d..b6933cb8e 100644 --- a/apps/opencs/view/render/pathgridmode.hpp +++ b/apps/opencs/view/render/pathgridmode.hpp @@ -27,13 +27,13 @@ namespace CSVRender virtual void secondarySelectPressed(const WorldspaceHitResult& hit); - virtual bool primaryEditStartDrag (const WorldspaceHitResult& hit); + virtual bool primaryEditStartDrag (const QPoint& pos); - virtual bool secondaryEditStartDrag (const WorldspaceHitResult& hit); + virtual bool secondaryEditStartDrag (const QPoint& pos); - virtual void drag (int diffX, int diffY, double speedFactor); + virtual void drag (const QPoint& pos, int diffX, int diffY, double speedFactor); - virtual void dragCompleted(const WorldspaceHitResult& hit); + virtual void dragCompleted(const QPoint& pos); /// \note dragAborted will not be called, if the drag is aborted via changing /// editing mode diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index ec40d880a..1859401dc 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -326,39 +326,64 @@ CSMDoc::Document& CSVRender::WorldspaceWidget::getDocument() return mDocument; } -osg::Vec3f CSVRender::WorldspaceWidget::getIntersectionPoint (const QPoint& localPos, - unsigned int interactionMask, bool ignoreHidden) const +CSVRender::WorldspaceHitResult CSVRender::WorldspaceWidget::mousePick (const QPoint& localPos, + unsigned int interactionMask) const { // (0,0) is considered the lower left corner of an OpenGL window int x = localPos.x(); int y = height() - localPos.y(); - osg::ref_ptr intersector ( - new osgUtil::LineSegmentIntersector (osgUtil::Intersector::WINDOW, x, y)); + // Get intersection + osg::ref_ptr intersector (new osgUtil::LineSegmentIntersector( + osgUtil::Intersector::WINDOW, x, y)); - intersector->setIntersectionLimit (osgUtil::LineSegmentIntersector::NO_LIMIT); - osgUtil::IntersectionVisitor visitor (intersector); + intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::NO_LIMIT); + osgUtil::IntersectionVisitor visitor(intersector); - unsigned int mask = interactionMask; + visitor.setTraversalMask(interactionMask); - if (ignoreHidden) - mask &= getVisibilityMask(); + mView->getCamera()->accept(visitor); - visitor.setTraversalMask (mask); - - mView->getCamera()->accept (visitor); - - for (osgUtil::LineSegmentIntersector::Intersections::iterator iter = intersector->getIntersections().begin(); - iter!=intersector->getIntersections().end(); ++iter) + // Get relevant data + for (osgUtil::LineSegmentIntersector::Intersections::iterator it = intersector->getIntersections().begin(); + it != intersector->getIntersections().end(); ++it) { - // reject back-facing polygons - osg::Vec3f normal = osg::Matrix::transform3x3 ( - iter->getWorldIntersectNormal(), mView->getCamera()->getViewMatrix()); + osgUtil::LineSegmentIntersector::Intersection intersection = *it; - if (normal.z()>=0) - return iter->getWorldIntersectPoint(); + // reject back-facing polygons + osg::Vec3f normal = intersection.getWorldIntersectNormal(); + normal = osg::Matrix::transform3x3(normal, mView->getCamera()->getViewMatrix()); + if (normal.z() < 0) + continue; + + for (std::vector::iterator it = intersection.nodePath.begin(); it != intersection.nodePath.end(); ++it) + { + osg::Node* node = *it; + if (osg::ref_ptr tag = dynamic_cast(node->getUserData())) + { + WorldspaceHitResult hit = { true, tag, 0, 0, 0, intersection.getWorldIntersectPoint() }; + if (intersection.indexList.size() >= 3) + { + hit.index0 = intersection.indexList[0]; + hit.index1 = intersection.indexList[1]; + hit.index2 = intersection.indexList[2]; + } + return hit; + } + } + + // Something untagged, probably terrain + WorldspaceHitResult hit = { true, 0, 0, 0, 0, intersection.getWorldIntersectPoint() }; + if (intersection.indexList.size() >= 3) + { + hit.index0 = intersection.indexList[0]; + hit.index1 = intersection.indexList[1]; + hit.index2 = intersection.indexList[2]; + } + return hit; } + // Default placement osg::Matrixd matrix; matrix.preMult (mView->getCamera()->getViewport()->computeWindowMatrix()); matrix.preMult (mView->getCamera()->getProjectionMatrix()); @@ -368,10 +393,12 @@ osg::Vec3f CSVRender::WorldspaceWidget::getIntersectionPoint (const QPoint& loca osg::Vec3d start = matrix.preMult (intersector->getStart()); osg::Vec3d end = matrix.preMult (intersector->getEnd()); - osg::Vec3d direction = end-start; + osg::Vec3d direction = end - start; direction.normalize(); + direction *= CSMPrefs::get()["Scene Drops"]["distance"].toInt(); - return start + direction * CSMPrefs::get()["Scene Drops"]["distance"].toInt(); + WorldspaceHitResult hit = { false, 0, 0, 0, 0, start + direction }; + return hit; } void CSVRender::WorldspaceWidget::abortDrag() @@ -465,63 +492,6 @@ bool CSVRender::WorldspaceWidget::storeMappingSetting (const CSMPrefs::Setting * return SceneWidget::storeMappingSetting(setting); } -CSVRender::WorldspaceHitResult CSVRender::WorldspaceWidget::mousePick (const QPoint& localPos) -{ - // (0,0) is considered the lower left corner of an OpenGL window - int x = localPos.x(); - int y = height() - localPos.y(); - - osg::ref_ptr intersector (new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, x, y)); - - intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::NO_LIMIT); - osgUtil::IntersectionVisitor visitor(intersector); - - visitor.setTraversalMask(getInteractionMask()); - - mView->getCamera()->accept(visitor); - - for (osgUtil::LineSegmentIntersector::Intersections::iterator it = intersector->getIntersections().begin(); - it != intersector->getIntersections().end(); ++it) - { - osgUtil::LineSegmentIntersector::Intersection intersection = *it; - - // reject back-facing polygons - osg::Vec3f normal = intersection.getWorldIntersectNormal(); - normal = osg::Matrix::transform3x3(normal, mView->getCamera()->getViewMatrix()); - if (normal.z() < 0) - continue; - - for (std::vector::iterator it = intersection.nodePath.begin(); it != intersection.nodePath.end(); ++it) - { - osg::Node* node = *it; - if (osg::ref_ptr tag = dynamic_cast(node->getUserData())) - { - WorldspaceHitResult hit = { true, tag, 0, 0, 0, intersection.getWorldIntersectPoint() }; - if (intersection.indexList.size() >= 3) - { - hit.index0 = intersection.indexList[0]; - hit.index1 = intersection.indexList[1]; - hit.index2 = intersection.indexList[2]; - } - return hit; - } - } - - // Something untagged, probably terrain - WorldspaceHitResult hit = { true, 0, 0, 0, 0, intersection.getWorldIntersectPoint() }; - if (intersection.indexList.size() >= 3) - { - hit.index0 = intersection.indexList[0]; - hit.index1 = intersection.indexList[1]; - hit.index2 = intersection.indexList[2]; - } - return hit; - } - - WorldspaceHitResult hit = { false, 0, 0, 0, 0, osg::Vec3d() }; - return hit; -} - void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event) { const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); @@ -606,7 +576,7 @@ void CSVRender::WorldspaceWidget::showToolTip() { QPoint pos = QCursor::pos(); - WorldspaceHitResult hit = mousePick (mapFromGlobal (pos)); + WorldspaceHitResult hit = mousePick (mapFromGlobal (pos), getInteractionMask()); if (hit.tag) { bool hideBasics = CSMPrefs::get()["Tooltips"]["scene-hide-basic"].isTrue(); @@ -643,22 +613,20 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); - editMode.drag (diffX, diffY, factor); + editMode.drag (event->pos(), diffX, diffY, factor); } else if (mDragMode=="p-edit" || mDragMode=="s-edit" || mDragMode=="p-select" || mDragMode=="s-select") { - WorldspaceHitResult hit = mousePick (event->pos()); - EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); if (mDragMode=="p-edit") - mDragging = editMode.primaryEditStartDrag (hit); + mDragging = editMode.primaryEditStartDrag (event->pos()); else if (mDragMode=="s-edit") - mDragging = editMode.secondaryEditStartDrag (hit); + mDragging = editMode.secondaryEditStartDrag (event->pos()); else if (mDragMode=="p-select") - mDragging = editMode.primarySelectStartDrag (hit); + mDragging = editMode.primarySelectStartDrag (event->pos()); else if (mDragMode=="s-select") - mDragging = editMode.secondarySelectStartDrag (hit); + mDragging = editMode.secondarySelectStartDrag (event->pos()); if (mDragging) { @@ -710,14 +678,13 @@ void CSVRender::WorldspaceWidget::mouseReleaseEvent (QMouseEvent *event) if (mDragging) { EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); - WorldspaceHitResult hit = mousePick (event->pos()); - editMode.dragCompleted(hit); + editMode.dragCompleted(event->pos()); mDragging = false; } else { - WorldspaceHitResult hit = mousePick (event->pos()); + WorldspaceHitResult hit = mousePick(event->pos(), getInteractionMask()); handleMouseClick (hit, button, event->modifiers() & Qt::ShiftModifier); } diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index e6cd7aab0..92d31eb9e 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -149,16 +149,11 @@ namespace CSVRender /// \param elementMask Elements to be affected by the select operation virtual void selectAllWithSameParentId (int elementMask) = 0; - /// Return the next intersection point with scene elements matched by + /// Return the next intersection with scene elements matched by /// \a interactionMask based on \a localPos and the camera vector. - /// If there is no such point, instead a point "in front" of \a localPos will be + /// If there is no such intersection, instead a point "in front" of \a localPos will be /// returned. - /// - /// \param ignoreHidden ignore elements specified in interactionMask that are - /// flagged as not visible. - osg::Vec3f getIntersectionPoint (const QPoint& localPos, - unsigned int interactionMask = Mask_Reference | Mask_Terrain, - bool ignoreHidden = false) const; + WorldspaceHitResult mousePick (const QPoint& localPos, unsigned int interactionMask) const; virtual std::string getCellId (const osg::Vec3f& point) const = 0; @@ -225,8 +220,6 @@ namespace CSVRender void dragMoveEvent(QDragMoveEvent *event); - WorldspaceHitResult mousePick (const QPoint& localPos); - virtual std::string getStartupInstruction() = 0; private slots: