1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-19 20:53:50 +00:00

Fix separate drop, refactor for code reuse

This commit is contained in:
uramer 2021-01-28 22:10:33 +01:00
parent d984d13b1c
commit 36cd818155
2 changed files with 54 additions and 83 deletions

View file

@ -802,39 +802,15 @@ void CSVRender::InstanceMode::deleteSelectedInstances(bool active)
getWorldspaceWidget().clearSelection (Mask_Reference); 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(); object->setEdited(Object::Override_Position);
ESM::Position position = object->getPosition();
osg::Vec3d start = point; position.pos[2] -= dropHeight;
start.z() += objectHeight; object->setPosition(position.pos);
osg::Vec3d end = point;
end.z() = std::numeric_limits<float>::lowest();
osg::ref_ptr<osgUtil::LineSegmentIntersector> 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);
}
} }
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(); osg::Vec3d point = object->getPosition().asVec3();
@ -848,9 +824,9 @@ float CSVRender::InstanceMode::getDropHeight(DropMode dropMode, CSVRender::Objec
intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::NO_LIMIT); intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::NO_LIMIT);
osgUtil::IntersectionVisitor visitor(intersector); osgUtil::IntersectionVisitor visitor(intersector);
if (dropMode == Terrain) if (dropMode & Terrain)
visitor.setTraversalMask(Mask_Terrain); visitor.setTraversalMask(Mask_Terrain);
if (dropMode == Collision) if (dropMode & Collision)
visitor.setTraversalMask(Mask_Terrain | Mask_Reference); visitor.setTraversalMask(Mask_Terrain | Mask_Reference);
mParentNode->accept(visitor); mParentNode->accept(visitor);
@ -897,52 +873,44 @@ void CSVRender::InstanceMode::handleDropMethod(DropMode dropMode, QString comman
CSMWorld::CommandMacro macro (undoStack, commandMsg); CSMWorld::CommandMacro macro (undoStack, commandMsg);
DropObjectDataHandler dropObjectDataHandler(&getWorldspaceWidget()); DropObjectHeightHandler dropObjectDataHandler(&getWorldspaceWidget());
switch (dropMode) if(dropMode & Separate)
{ {
case Terrain: int counter = 0;
case Collision: for (osg::ref_ptr<TagBase> tag : selection)
{ if (CSVRender::ObjectTag* objectTag = dynamic_cast<CSVRender::ObjectTag*>(tag.get()))
float smallestDropHeight = std::numeric_limits<float>::max(); {
int counter = 0; float objectHeight = dropObjectDataHandler.mObjectHeights[counter];
for(osg::ref_ptr<TagBase> tag: selection) float dropHeight = calculateDropHeight(dropMode, objectTag->mObject, objectHeight);
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (tag.get())) dropInstance(objectTag->mObject, dropHeight);
{ objectTag->mObject->apply(macro);
float thisDrop = getDropHeight(dropMode, objectTag->mObject, dropObjectDataHandler.mObjectHeights[counter]); counter++;
if (thisDrop < smallestDropHeight) }
smallestDropHeight = thisDrop; }
counter++; else
} {
for(osg::ref_ptr<TagBase> tag: selection) float smallestDropHeight = std::numeric_limits<float>::max();
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (tag.get())) int counter = 0;
{ for (osg::ref_ptr<TagBase> tag : selection)
objectTag->mObject->setEdited (Object::Override_Position); if (CSVRender::ObjectTag* objectTag = dynamic_cast<CSVRender::ObjectTag*>(tag.get()))
ESM::Position position = objectTag->mObject->getPosition(); {
position.pos[2] -= smallestDropHeight; float objectHeight = dropObjectDataHandler.mObjectHeights[counter];
objectTag->mObject->setPosition(position.pos); float thisDrop = calculateDropHeight(dropMode, objectTag->mObject, objectHeight);
objectTag->mObject->apply (macro); if (thisDrop < smallestDropHeight)
} smallestDropHeight = thisDrop;
} counter++;
break; }
for (osg::ref_ptr<TagBase> tag : selection)
case TerrainSep: if (CSVRender::ObjectTag* objectTag = dynamic_cast<CSVRender::ObjectTag*>(tag.get()))
case CollisionSep: {
{ dropInstance(objectTag->mObject, smallestDropHeight);
int counter = 0; objectTag->mObject->apply(macro);
for(osg::ref_ptr<TagBase> tag: selection) }
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (tag.get()))
{
dropInstance(dropMode, objectTag->mObject, dropObjectDataHandler.mObjectHeights[counter]);
objectTag->mObject->apply (macro);
counter++;
}
}
break;
} }
} }
CSVRender::DropObjectDataHandler::DropObjectDataHandler(WorldspaceWidget* worldspacewidget) CSVRender::DropObjectHeightHandler::DropObjectHeightHandler(WorldspaceWidget* worldspacewidget)
: mWorldspaceWidget(worldspacewidget) : mWorldspaceWidget(worldspacewidget)
{ {
std::vector<osg::ref_ptr<TagBase> > selection = mWorldspaceWidget->getSelection (Mask_Reference); std::vector<osg::ref_ptr<TagBase> > selection = mWorldspaceWidget->getSelection (Mask_Reference);
@ -969,7 +937,7 @@ CSVRender::DropObjectDataHandler::DropObjectDataHandler(WorldspaceWidget* worlds
} }
} }
CSVRender::DropObjectDataHandler::~DropObjectDataHandler() CSVRender::DropObjectHeightHandler::~DropObjectHeightHandler()
{ {
std::vector<osg::ref_ptr<TagBase> > selection = mWorldspaceWidget->getSelection (Mask_Reference); std::vector<osg::ref_ptr<TagBase> > selection = mWorldspaceWidget->getSelection (Mask_Reference);
int counter = 0; int counter = 0;

View file

@ -28,10 +28,13 @@ namespace CSVRender
enum DropMode enum DropMode
{ {
Collision, Separate = 0x1,
Terrain,
CollisionSep, Collision = 0b10,
TerrainSep Terrain = 0b100,
CollisionSep = Collision | Separate,
TerrainSep = Terrain | Separate,
}; };
CSVWidget::SceneToolMode *mSubMode; CSVWidget::SceneToolMode *mSubMode;
@ -53,8 +56,8 @@ namespace CSVRender
osg::Vec3f getProjectionSpaceCoords(const osg::Vec3f& pos); osg::Vec3f getProjectionSpaceCoords(const osg::Vec3f& pos);
osg::Vec3f getMousePlaneCoords(const QPoint& point, const osg::Vec3d& dragStart); osg::Vec3f getMousePlaneCoords(const QPoint& point, const osg::Vec3d& dragStart);
void handleSelectDrag(const QPoint& pos); void handleSelectDrag(const QPoint& pos);
void dropInstance(DropMode dropMode, CSVRender::Object* object, float objectHeight); void dropInstance(CSVRender::Object* object, float objectHeight);
float getDropHeight(DropMode dropMode, CSVRender::Object* object, float objectHeight); float calculateDropHeight(DropMode dropMode, CSVRender::Object* object, float objectHeight);
public: public:
@ -116,11 +119,11 @@ namespace CSVRender
}; };
/// \brief Helper class to handle object mask data in safe way /// \brief Helper class to handle object mask data in safe way
class DropObjectDataHandler class DropObjectHeightHandler
{ {
public: public:
DropObjectDataHandler(WorldspaceWidget* worldspacewidget); DropObjectHeightHandler(WorldspaceWidget* worldspacewidget);
~DropObjectDataHandler(); ~DropObjectHeightHandler();
std::vector<float> mObjectHeights; std::vector<float> mObjectHeights;
private: private: