diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index d7ab59b53f..42ab8e62e5 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -791,8 +791,57 @@ void CSVRender::InstanceMode::handleDropMethod(DropMode dropMode, QString comman CSMWorld::CommandMacro macro (undoStack, commandMsg); - std::vector oldMasks; - std::vector objectHeights; + DropObjectDataHandler dropObjectDataHandler(&getWorldspaceWidget()); + + switch (dropMode) + { + 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 Terrain_sep: + case Collision_sep: + { + 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; + + default: + break; + } +} + +CSVRender::DropObjectDataHandler::DropObjectDataHandler(WorldspaceWidget* worldspacewidget) + : mWorldspaceWidget(worldspacewidget) +{ + std::vector > selection = mWorldspaceWidget->getSelection (SceneUtil::Mask_EditorReference); for(osg::ref_ptr tag: selection) { if (CSVRender::ObjectTag *objectTag = dynamic_cast (tag.get())) @@ -807,70 +856,24 @@ void CSVRender::InstanceMode::handleDropMethod(DropMode dropMode, QString comman float boundingBoxOffset = 0.0f; if (bounds.valid()) boundingBoxOffset = bounds.zMin(); - objectHeights.emplace_back(boundingBoxOffset); - oldMasks.emplace_back(objectNodeWithGUI->getNodeMask()); + mObjectHeights.emplace_back(boundingBoxOffset); + mOldMasks.emplace_back(objectNodeWithGUI->getNodeMask()); objectNodeWithGUI->setNodeMask(SceneUtil::Mask_Disabled); } } +} - try - { - switch (dropMode) - { - 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, objectHeights[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 Terrain_sep: - case Collision_sep: - { - int counter = 0; - for(osg::ref_ptr tag: selection) - if (CSVRender::ObjectTag *objectTag = dynamic_cast (tag.get())) - { - dropInstance(dropMode, objectTag->mObject, objectHeights[counter]); - objectTag->mObject->apply (macro); - counter++; - } - } - break; - default: - break; - } - } - catch (const std::exception& e) - { - Log(Debug::Error) << "Error in dropping instance: " << e.what(); - } - +CSVRender::DropObjectDataHandler::~DropObjectDataHandler() +{ + std::vector > selection = mWorldspaceWidget->getSelection (SceneUtil::Mask_EditorReference); int counter = 0; for(osg::ref_ptr tag: selection) { if (CSVRender::ObjectTag *objectTag = dynamic_cast (tag.get())) { osg::ref_ptr objectNodeWithGUI = objectTag->mObject->getRootNode(); - objectNodeWithGUI->setNodeMask(oldMasks[counter]); + objectNodeWithGUI->setNodeMask(mOldMasks[counter]); counter++; } } diff --git a/apps/opencs/view/render/instancemode.hpp b/apps/opencs/view/render/instancemode.hpp index de7004f4f0..b1d5de7fe3 100644 --- a/apps/opencs/view/render/instancemode.hpp +++ b/apps/opencs/view/render/instancemode.hpp @@ -114,6 +114,19 @@ namespace CSVRender void dropSelectedInstancesToTerrainSeparately(); void handleDropMethod(DropMode dropMode, QString commandMsg); }; + + /// \brief Helper class to handle object mask data in safe way + class DropObjectDataHandler + { + public: + DropObjectDataHandler(WorldspaceWidget* worldspacewidget); + ~DropObjectDataHandler(); + std::vector mObjectHeights; + + private: + WorldspaceWidget* mWorldspaceWidget; + std::vector mOldMasks; + }; } #endif