From 36cd81815504cef195fe853b0b93046ac04c3c19 Mon Sep 17 00:00:00 2001 From: uramer Date: Thu, 28 Jan 2021 22:10:33 +0100 Subject: [PATCH] Fix separate drop, refactor for code reuse --- apps/opencs/view/render/instancemode.cpp | 116 ++++++++--------------- apps/opencs/view/render/instancemode.hpp | 21 ++-- 2 files changed, 54 insertions(+), 83 deletions(-) diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index 4f6759cdb..2489f4f57 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -802,39 +802,15 @@ void CSVRender::InstanceMode::deleteSelectedInstances(bool active) getWorldspaceWidget().clearSelection (Mask_Reference); } -void CSVRender::InstanceMode::dropInstance(DropMode dropMode, CSVRender::Object* object, float objectHeight) +void CSVRender::InstanceMode::dropInstance(CSVRender::Object* object, float dropHeight) { - osg::Vec3d point = object->getPosition().asVec3(); - - osg::Vec3d start = point; - start.z() += objectHeight; - osg::Vec3d end = point; - end.z() = std::numeric_limits::lowest(); - - osg::ref_ptr intersector (new osgUtil::LineSegmentIntersector( - osgUtil::Intersector::MODEL, start, end) ); - intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::NO_LIMIT); - osgUtil::IntersectionVisitor visitor(intersector); - - if (dropMode == TerrainSep) - visitor.setTraversalMask(Mask_Terrain); - if (dropMode == CollisionSep) - visitor.setTraversalMask(Mask_Terrain | Mask_Reference); - - mParentNode->accept(visitor); - - osgUtil::LineSegmentIntersector::Intersections::iterator it = intersector->getIntersections().begin(); - if (it != intersector->getIntersections().end()) - { - osgUtil::LineSegmentIntersector::Intersection intersection = *it; - ESM::Position position = object->getPosition(); - object->setEdited (Object::Override_Position); - position.pos[2] = intersection.getWorldIntersectPoint().z() + objectHeight; - object->setPosition(position.pos); - } + object->setEdited(Object::Override_Position); + ESM::Position position = object->getPosition(); + position.pos[2] -= dropHeight; + object->setPosition(position.pos); } -float CSVRender::InstanceMode::getDropHeight(DropMode dropMode, CSVRender::Object* object, float objectHeight) +float CSVRender::InstanceMode::calculateDropHeight(DropMode dropMode, CSVRender::Object* object, float objectHeight) { osg::Vec3d point = object->getPosition().asVec3(); @@ -848,9 +824,9 @@ float CSVRender::InstanceMode::getDropHeight(DropMode dropMode, CSVRender::Objec intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::NO_LIMIT); osgUtil::IntersectionVisitor visitor(intersector); - if (dropMode == Terrain) + if (dropMode & Terrain) visitor.setTraversalMask(Mask_Terrain); - if (dropMode == Collision) + if (dropMode & Collision) visitor.setTraversalMask(Mask_Terrain | Mask_Reference); mParentNode->accept(visitor); @@ -897,52 +873,44 @@ void CSVRender::InstanceMode::handleDropMethod(DropMode dropMode, QString comman CSMWorld::CommandMacro macro (undoStack, commandMsg); - DropObjectDataHandler dropObjectDataHandler(&getWorldspaceWidget()); + DropObjectHeightHandler dropObjectDataHandler(&getWorldspaceWidget()); - switch (dropMode) + if(dropMode & Separate) { - case Terrain: - case Collision: - { - float smallestDropHeight = std::numeric_limits::max(); - int counter = 0; - for(osg::ref_ptr tag: selection) - if (CSVRender::ObjectTag *objectTag = dynamic_cast (tag.get())) - { - float thisDrop = getDropHeight(dropMode, objectTag->mObject, dropObjectDataHandler.mObjectHeights[counter]); - if (thisDrop < smallestDropHeight) - smallestDropHeight = thisDrop; - counter++; - } - for(osg::ref_ptr tag: selection) - if (CSVRender::ObjectTag *objectTag = dynamic_cast (tag.get())) - { - objectTag->mObject->setEdited (Object::Override_Position); - ESM::Position position = objectTag->mObject->getPosition(); - position.pos[2] -= smallestDropHeight; - objectTag->mObject->setPosition(position.pos); - objectTag->mObject->apply (macro); - } - } - break; - - case TerrainSep: - case CollisionSep: - { - int counter = 0; - for(osg::ref_ptr tag: selection) - if (CSVRender::ObjectTag *objectTag = dynamic_cast (tag.get())) - { - dropInstance(dropMode, objectTag->mObject, dropObjectDataHandler.mObjectHeights[counter]); - objectTag->mObject->apply (macro); - counter++; - } - } - break; + int counter = 0; + for (osg::ref_ptr tag : selection) + if (CSVRender::ObjectTag* objectTag = dynamic_cast(tag.get())) + { + float objectHeight = dropObjectDataHandler.mObjectHeights[counter]; + float dropHeight = calculateDropHeight(dropMode, objectTag->mObject, objectHeight); + dropInstance(objectTag->mObject, dropHeight); + objectTag->mObject->apply(macro); + counter++; + } + } + else + { + float smallestDropHeight = std::numeric_limits::max(); + int counter = 0; + for (osg::ref_ptr tag : selection) + if (CSVRender::ObjectTag* objectTag = dynamic_cast(tag.get())) + { + float objectHeight = dropObjectDataHandler.mObjectHeights[counter]; + float thisDrop = calculateDropHeight(dropMode, objectTag->mObject, objectHeight); + if (thisDrop < smallestDropHeight) + smallestDropHeight = thisDrop; + counter++; + } + for (osg::ref_ptr tag : selection) + if (CSVRender::ObjectTag* objectTag = dynamic_cast(tag.get())) + { + dropInstance(objectTag->mObject, smallestDropHeight); + objectTag->mObject->apply(macro); + } } } -CSVRender::DropObjectDataHandler::DropObjectDataHandler(WorldspaceWidget* worldspacewidget) +CSVRender::DropObjectHeightHandler::DropObjectHeightHandler(WorldspaceWidget* worldspacewidget) : mWorldspaceWidget(worldspacewidget) { std::vector > selection = mWorldspaceWidget->getSelection (Mask_Reference); @@ -969,7 +937,7 @@ CSVRender::DropObjectDataHandler::DropObjectDataHandler(WorldspaceWidget* worlds } } -CSVRender::DropObjectDataHandler::~DropObjectDataHandler() +CSVRender::DropObjectHeightHandler::~DropObjectHeightHandler() { std::vector > selection = mWorldspaceWidget->getSelection (Mask_Reference); int counter = 0; diff --git a/apps/opencs/view/render/instancemode.hpp b/apps/opencs/view/render/instancemode.hpp index 0a4f2e478..d0a263ed8 100644 --- a/apps/opencs/view/render/instancemode.hpp +++ b/apps/opencs/view/render/instancemode.hpp @@ -28,10 +28,13 @@ namespace CSVRender enum DropMode { - Collision, - Terrain, - CollisionSep, - TerrainSep + Separate = 0x1, + + Collision = 0b10, + Terrain = 0b100, + + CollisionSep = Collision | Separate, + TerrainSep = Terrain | Separate, }; CSVWidget::SceneToolMode *mSubMode; @@ -53,8 +56,8 @@ namespace CSVRender osg::Vec3f getProjectionSpaceCoords(const osg::Vec3f& pos); osg::Vec3f getMousePlaneCoords(const QPoint& point, const osg::Vec3d& dragStart); void handleSelectDrag(const QPoint& pos); - void dropInstance(DropMode dropMode, CSVRender::Object* object, float objectHeight); - float getDropHeight(DropMode dropMode, CSVRender::Object* object, float objectHeight); + void dropInstance(CSVRender::Object* object, float objectHeight); + float calculateDropHeight(DropMode dropMode, CSVRender::Object* object, float objectHeight); public: @@ -116,11 +119,11 @@ namespace CSVRender }; /// \brief Helper class to handle object mask data in safe way - class DropObjectDataHandler + class DropObjectHeightHandler { public: - DropObjectDataHandler(WorldspaceWidget* worldspacewidget); - ~DropObjectDataHandler(); + DropObjectHeightHandler(WorldspaceWidget* worldspacewidget); + ~DropObjectHeightHandler(); std::vector mObjectHeights; private: